From 8375cfa0a79f53cdcb3c9767260e1d1e48522143 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 5 Jan 2025 15:08:50 +0100 Subject: [PATCH 001/153] from retail --- WeakAuras/Animations.lua | 2 +- WeakAuras/AuraEnvironment.lua | 2 +- WeakAuras/AuraWarnings.lua | 2 +- WeakAuras/BuffTrigger.lua | 2 +- WeakAuras/BuffTrigger2.lua | 4 +- WeakAuras/Conditions.lua | 8 +-- WeakAuras/GenericTrigger.lua | 20 +++---- WeakAuras/History.lua | 2 +- WeakAuras/Init.lua | 57 ++++++++++++++++++- .../widgets/AceGUIWidget-DropDown.lua | 2 +- WeakAuras/Locales/deDE.lua | 2 +- WeakAuras/Locales/esES.lua | 2 +- WeakAuras/Locales/esMX.lua | 2 +- WeakAuras/Locales/frFR.lua | 2 +- WeakAuras/Locales/itIT.lua | 2 +- WeakAuras/Locales/koKR.lua | 2 +- WeakAuras/Locales/ptBR.lua | 2 +- WeakAuras/Locales/ruRU.lua | 2 +- WeakAuras/Locales/zhCN.lua | 2 +- WeakAuras/Locales/zhTW.lua | 2 +- WeakAuras/Modernize.lua | 13 ++++- WeakAuras/Profiling.lua | 20 ++++--- WeakAuras/Prototypes.lua | 41 +++++++------ WeakAuras/RegionTypes/AuraBar.lua | 12 ++-- WeakAuras/RegionTypes/DynamicGroup.lua | 8 +-- WeakAuras/RegionTypes/Group.lua | 6 +- WeakAuras/RegionTypes/Icon.lua | 12 ++-- WeakAuras/RegionTypes/Model.lua | 6 +- WeakAuras/RegionTypes/ProgressTexture.lua | 4 +- WeakAuras/RegionTypes/RegionPrototype.lua | 4 +- WeakAuras/RegionTypes/StopMotion.lua | 4 +- WeakAuras/RegionTypes/Text.lua | 6 +- WeakAuras/RegionTypes/Texture.lua | 4 +- WeakAuras/SubRegionTypes/Background.lua | 2 +- WeakAuras/SubRegionTypes/Border.lua | 4 +- WeakAuras/SubRegionTypes/Glow.lua | 4 +- WeakAuras/SubRegionTypes/Model.lua | 4 +- WeakAuras/SubRegionTypes/SubText.lua | 4 +- WeakAuras/SubRegionTypes/Tick.lua | 4 +- WeakAuras/Transmission.lua | 2 +- WeakAuras/Types.lua | 10 ++-- WeakAuras/WeakAuras.lua | 24 ++++---- .../AceGUIContainer-WeakAurasTreeGroup.lua | 2 +- .../AceGUIWidget-WeakAurasAnchorButtons.lua | 2 +- .../AceGUIWidget-WeakAurasDisplayButton.lua | 12 ++-- .../AceGUIWidget-WeakAurasExpand.lua | 2 +- .../AceGUIWidget-WeakAurasExpandAnchor.lua | 2 +- .../AceGUIWidget-WeakAurasExpandSmall.lua | 2 +- .../AceGUIWidget-WeakAurasIcon.lua | 2 +- .../AceGUIWidget-WeakAurasIconButton.lua | 4 +- .../AceGUIWidget-WeakAurasImportButton.lua | 6 +- .../AceGUIWidget-WeakAurasInputFocus.lua | 2 +- ...eGUIWidget-WeakAurasLoadedHeaderButton.lua | 8 +-- ...AceGUIWidget-WeakAurasMultiLineEditBox.lua | 2 +- ...get-WeakAurasMultiLineEditBoxWithEnter.lua | 2 +- .../AceGUIWidget-WeakAurasNewButton.lua | 4 +- .../AceGUIWidget-WeakAurasNewHeaderButton.lua | 4 +- ...UIWidget-WeakAurasPendingInstallButton.lua | 4 +- ...GUIWidget-WeakAurasPendingUpdateButton.lua | 4 +- .../AceGUIWidget-WeakAurasSnippetButton.lua | 2 +- .../AceGUIWidget-WeakAurasTextureButton.lua | 4 +- ...ceGUIWidget-WeakAurasTwoColumnDropDown.lua | 2 +- WeakAurasOptions/ActionOptions.lua | 2 +- WeakAurasOptions/AnimationOptions.lua | 2 +- WeakAurasOptions/AuthorOptions.lua | 6 +- WeakAurasOptions/BuffTrigger.lua | 2 +- WeakAurasOptions/BuffTrigger2.lua | 2 +- WeakAurasOptions/Cache.lua | 2 +- WeakAurasOptions/CommonOptions.lua | 2 +- WeakAurasOptions/ConditionOptions.lua | 2 +- WeakAurasOptions/DisplayOptions.lua | 2 +- WeakAurasOptions/ForAllIndentsAndPurposes.lua | 2 +- WeakAurasOptions/GenericTrigger.lua | 2 +- WeakAurasOptions/GroupOptions.lua | 2 +- WeakAurasOptions/InformationOptions.lua | 2 +- WeakAurasOptions/LoadOptions.lua | 2 +- WeakAurasOptions/Locales/deDE.lua | 4 +- WeakAurasOptions/Locales/enUS.lua | 2 +- WeakAurasOptions/Locales/esES.lua | 4 +- WeakAurasOptions/Locales/esMX.lua | 4 +- WeakAurasOptions/Locales/frFR.lua | 4 +- WeakAurasOptions/Locales/itIT.lua | 4 +- WeakAurasOptions/Locales/koKR.lua | 4 +- WeakAurasOptions/Locales/ptBR.lua | 4 +- WeakAurasOptions/Locales/ruRU.lua | 4 +- WeakAurasOptions/Locales/zhCN.lua | 4 +- WeakAurasOptions/Locales/zhTW.lua | 4 +- WeakAurasOptions/OptionsFrames/CodeReview.lua | 2 +- .../OptionsFrames/FrameChooser.lua | 6 +- WeakAurasOptions/OptionsFrames/IconPicker.lua | 2 +- .../OptionsFrames/ImportExport.lua | 2 +- .../OptionsFrames/ModelPicker.lua | 4 +- WeakAurasOptions/OptionsFrames/MoverSizer.lua | 32 +++++------ .../OptionsFrames/OptionsFrame.lua | 10 ++-- WeakAurasOptions/OptionsFrames/TextEditor.lua | 2 +- .../OptionsFrames/TexturePicker.lua | 2 +- WeakAurasOptions/OptionsFrames/Update.lua | 2 +- WeakAurasOptions/RegionOptions/AuraBar.lua | 8 +-- .../RegionOptions/DynamicGroup.lua | 6 +- WeakAurasOptions/RegionOptions/Group.lua | 6 +- WeakAurasOptions/RegionOptions/Icon.lua | 4 +- WeakAurasOptions/RegionOptions/Model.lua | 4 +- .../RegionOptions/ProgressTexture.lua | 6 +- WeakAurasOptions/RegionOptions/StopMotion.lua | 2 +- WeakAurasOptions/RegionOptions/Text.lua | 4 +- WeakAurasOptions/RegionOptions/Texture.lua | 4 +- .../SubRegionOptions/Background.lua | 2 +- WeakAurasOptions/SubRegionOptions/Border.lua | 2 +- WeakAurasOptions/SubRegionOptions/Glow.lua | 2 +- WeakAurasOptions/SubRegionOptions/Model.lua | 2 +- .../SubRegionOptions/SubRegionCommon.lua | 2 +- WeakAurasOptions/SubRegionOptions/SubText.lua | 2 +- WeakAurasOptions/SubRegionOptions/Tick.lua | 2 +- WeakAurasOptions/TriggerOptions.lua | 2 +- WeakAurasOptions/WeakAurasOptions.lua | 4 +- 115 files changed, 332 insertions(+), 261 deletions(-) diff --git a/WeakAuras/Animations.lua b/WeakAuras/Animations.lua index 871c59a..bbf9d71 100644 --- a/WeakAuras/Animations.lua +++ b/WeakAuras/Animations.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Animations diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index 4efb70e..20b4da4 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras diff --git a/WeakAuras/AuraWarnings.lua b/WeakAuras/AuraWarnings.lua index f58185c..e09ac86 100644 --- a/WeakAuras/AuraWarnings.lua +++ b/WeakAuras/AuraWarnings.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras diff --git a/WeakAuras/BuffTrigger.lua b/WeakAuras/BuffTrigger.lua index 9d0afc6..538217f 100644 --- a/WeakAuras/BuffTrigger.lua +++ b/WeakAuras/BuffTrigger.lua @@ -2,7 +2,7 @@ This used to contains the "aura" trigger for buffs and debuffs. Nowadays all functions do essentially nothing ]]-- -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 86730b6..4f3e8b7 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -50,7 +50,7 @@ Returns the tooltip text for additional properties. GetTriggerConditions(data, triggernum) Returns the potential conditions for a trigger ]]-- -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Lua APIs @@ -1708,7 +1708,7 @@ local function RecheckActiveForUnitType(unitType, unit, unitsToRemoveScan) end end -local frame = CreateFrame("FRAME") +local frame = CreateFrame("Frame") WeakAuras.frames["WeakAuras Buff2 Frame"] = frame local function EventHandler(frame, event, arg1, arg2, ...) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index 9b8b002..bfd96f2 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L @@ -843,7 +843,7 @@ function Private.RegisterForGlobalConditions(uid) end if (next(register) and not dynamicConditionsFrame) then - dynamicConditionsFrame = CreateFrame("FRAME"); + dynamicConditionsFrame = CreateFrame("Frame"); dynamicConditionsFrame:SetScript("OnEvent", handleDynamicConditions); dynamicConditionsFrame.units = {} WeakAuras.frames["Rerun Conditions Frame"] = dynamicConditionsFrame @@ -860,7 +860,7 @@ function Private.RegisterForGlobalConditions(uid) if unitEvent and unit then unit = unit:lower() if not dynamicConditionsFrame.units[unit] then - dynamicConditionsFrame.units[unit] = CreateFrame("FRAME"); + dynamicConditionsFrame.units[unit] = CreateFrame("Frame"); dynamicConditionsFrame.units[unit]:SetScript("OnEvent", handleDynamicConditionsPerUnit); end dynamicConditionsFrame.units[unit].unit = unit; @@ -909,7 +909,7 @@ function Private.UnloadAllConditions() dynamicConditions = {} if dynamicConditionsFrame then dynamicConditionsFrame:UnregisterAllEvents() - for unit, frame in pairs(dynamicConditionsFrame.units) do + for _, frame in pairs(dynamicConditionsFrame.units) do frame:UnregisterAllEvents() end dynamicConditionsFrame:SetScript("OnUpdate", nil) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index dec3a4f..8a26d98 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -49,7 +49,7 @@ Returns the a tooltip for the additional properties. GetTriggerConditions(data, triggernum) Returns potential conditions that this trigger provides. ]]-- -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Lua APIs @@ -1086,7 +1086,7 @@ end local genericTriggerRegisteredEvents = {}; local genericTriggerRegisteredUnitEvents = {}; -local frame = CreateFrame("FRAME"); +local frame = CreateFrame("Frame"); frame.unitFrames = {}; WeakAuras.frames["WeakAuras Generic Trigger Frame"] = frame; frame:RegisterEvent("PLAYER_ENTERING_WORLD"); @@ -1631,7 +1631,7 @@ do update_clients_num = update_clients_num + 1; end if not(update_frame) then - update_frame = CreateFrame("FRAME"); + update_frame = CreateFrame("Frame"); end if not(updating) then update_frame:SetScript("OnUpdate", function() @@ -1885,7 +1885,7 @@ do function WeakAuras.InitSwingTimer() if not(swingTimerFrame) then - swingTimerFrame = CreateFrame("frame"); + swingTimerFrame = CreateFrame("Frame"); swingTimerFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED"); swingTimerFrame:RegisterEvent("PLAYER_ENTER_COMBAT"); swingTimerFrame:RegisterEvent("UNIT_ATTACK_SPEED"); @@ -2084,7 +2084,7 @@ do local spellDetails = {} function WeakAuras.InitCooldownReady() - cdReadyFrame = CreateFrame("FRAME"); + cdReadyFrame = CreateFrame("Frame"); WeakAuras.frames["Cooldown Trigger Handler"] = cdReadyFrame cdReadyFrame:RegisterEvent("RUNE_POWER_UPDATE"); cdReadyFrame:RegisterEvent("RUNE_TYPE_UPDATE"); @@ -3350,7 +3350,7 @@ do WeakAuras.frames["Pet Use Handler"] = petFrame; function WeakAuras.WatchForPetDeath() if not(petFrame) then - petFrame = CreateFrame("frame"); + petFrame = CreateFrame("Frame"); petFrame:RegisterEvent("UNIT_PET") petFrame:SetScript("OnEvent", function(_, event, unit) if unit ~= "player" then return end @@ -3445,7 +3445,7 @@ do function WeakAuras.WatchForMounts() if not(mountedFrame) then - mountedFrame = CreateFrame("frame"); + mountedFrame = CreateFrame("Frame"); WeakAuras.frames["Mount Use Handler"] = mountedFrame; mountedFrame:RegisterEvent("COMPANION_UPDATE"); mountedFrame:SetScript("OnEvent", function() @@ -3472,7 +3472,7 @@ do function WeakAuras.WatchPlayerMoveSpeed() if not (playerMovingFrame) then - playerMovingFrame = CreateFrame("frame"); + playerMovingFrame = CreateFrame("Frame"); WeakAuras.frames["Player Moving Frame"] = playerMovingFrame; end playerMovingFrame.speed = GetUnitSpeed("player") @@ -3567,7 +3567,7 @@ end local itemCountWatchFrame; function WeakAuras.RegisterItemCountWatch() if not(itemCountWatchFrame) then - itemCountWatchFrame = CreateFrame("frame"); + itemCountWatchFrame = CreateFrame("Frame"); itemCountWatchFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED"); itemCountWatchFrame:SetScript("OnEvent", function(_, _, unit) if unit ~= "player" then return end @@ -3604,7 +3604,7 @@ do function WeakAuras.WatchQueuedAction() if not(queuedActionFrame) then - queuedActionFrame = CreateFrame("frame"); + queuedActionFrame = CreateFrame("Frame"); WeakAuras.frames["Queued Action Frame"] = queuedActionFrame for slotID = 1, 120 do local spellID = GetActionSpellID(slotID) diff --git a/WeakAuras/History.lua b/WeakAuras/History.lua index b216b24..38566a4 100644 --- a/WeakAuras/History.lua +++ b/WeakAuras/History.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index bbceab9..ea3c50c 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -33,13 +33,64 @@ WeakAuras.prettyPrint = function(...) print("|cff9900ffWeakAuras:|r ", ...) end +-- Force enable WeakAurasCompanion and Archive because some addon managers interfere with it +EnableAddOn("WeakAurasCompanion") +EnableAddOn("WeakAurasArchive") + +local libsAreOk = true +do + local StandAloneLibs = { + "Archivist", + "LibStub" + } + local LibStubLibs = { + "CallbackHandler-1.0", + "AceConfig-3.0", + "AceConsole-3.0", + "AceGUI-3.0", + "AceEvent-3.0", + "AceGUISharedMediaWidgets-1.0", + "AceTimer-3.0", + "AceSerializer-3.0", + "AceComm-3.0", + "LibSharedMedia-3.0", + "LibDataBroker-1.1", + "LibCompress", + "SpellRange-1.0", + "LibCustomGlow-1.0", + "LibDBIcon-1.0", + "LibGetFrame-1.0", + "LibSerialize", + } + for _, lib in ipairs(StandAloneLibs) do + if not lib then + libsAreOk = false + WeakAuras.prettyPrint("Missing library:", lib) + end + end + if LibStub then + for _, lib in ipairs(LibStubLibs) do + if not LibStub:GetLibrary(lib, true) then + libsAreOk = false + WeakAuras.prettyPrint("Missing library:", lib) + end + end + else + libsAreOk = false + end +end + +function WeakAuras.IsLibsOK() + return libsAreOk +end + if versionString ~= versionStringFromToc and versionStringFromToc ~= "Dev" then WeakAuras.prettyPrint("You need to restart your game client to complete the WeakAuras update!") end --- Force enable WeakAurasCompanion and Archive because some addon managers interfere with it -EnableAddOn("WeakAurasCompanion") -EnableAddOn("WeakAurasArchive") +if not WeakAuras.IsLibsOK() then + WeakAuras.prettyPrint("WeakAuras is missing necessary libraries. Please reinstall a proper package.") +end -- These function stubs are defined here to reduce the number of errors that occur if WeakAuras.lua fails to compile function WeakAuras.RegisterRegionType() diff --git a/WeakAuras/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua b/WeakAuras/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua index cb09a23..97651ad 100644 --- a/WeakAuras/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua +++ b/WeakAuras/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua @@ -713,7 +713,7 @@ do button:SetScript("OnLeave",Control_OnLeave) button:SetScript("OnClick",Dropdown_TogglePullout) - local button_cover = CreateFrame("BUTTON",nil,self.frame) + local button_cover = CreateFrame("Button",nil,self.frame) self.button_cover = button_cover button_cover.obj = self button_cover:SetPoint("TOPLEFT",self.frame,"BOTTOMLEFT",0,25) diff --git a/WeakAuras/Locales/deDE.lua b/WeakAuras/Locales/deDE.lua index bc44d09..f47562e 100644 --- a/WeakAuras/Locales/deDE.lua +++ b/WeakAuras/Locales/deDE.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "deDE") then +if GetLocale() ~= "deDE" then return end diff --git a/WeakAuras/Locales/esES.lua b/WeakAuras/Locales/esES.lua index 07a2afd..67638df 100644 --- a/WeakAuras/Locales/esES.lua +++ b/WeakAuras/Locales/esES.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "esES") then +if GetLocale() ~= "esES" then return end diff --git a/WeakAuras/Locales/esMX.lua b/WeakAuras/Locales/esMX.lua index 0612c6a..6a2de5a 100644 --- a/WeakAuras/Locales/esMX.lua +++ b/WeakAuras/Locales/esMX.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "esMX") then +if GetLocale() ~= "esMX" then return end diff --git a/WeakAuras/Locales/frFR.lua b/WeakAuras/Locales/frFR.lua index b81903b..e01b372 100644 --- a/WeakAuras/Locales/frFR.lua +++ b/WeakAuras/Locales/frFR.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "frFR") then +if GetLocale() ~= "frFR" then return end diff --git a/WeakAuras/Locales/itIT.lua b/WeakAuras/Locales/itIT.lua index ec6c3c6..b18b6f9 100644 --- a/WeakAuras/Locales/itIT.lua +++ b/WeakAuras/Locales/itIT.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "itIT") then +if GetLocale() ~= "itIT" then return end diff --git a/WeakAuras/Locales/koKR.lua b/WeakAuras/Locales/koKR.lua index 4a9579e..a98381d 100644 --- a/WeakAuras/Locales/koKR.lua +++ b/WeakAuras/Locales/koKR.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "koKR") then +if GetLocale() ~= "koKR" then return end diff --git a/WeakAuras/Locales/ptBR.lua b/WeakAuras/Locales/ptBR.lua index 91778eb..9ce7aad 100644 --- a/WeakAuras/Locales/ptBR.lua +++ b/WeakAuras/Locales/ptBR.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "ptBR") then +if GetLocale() ~= "ptBR" then return end diff --git a/WeakAuras/Locales/ruRU.lua b/WeakAuras/Locales/ruRU.lua index 3745be1..1e7204e 100644 --- a/WeakAuras/Locales/ruRU.lua +++ b/WeakAuras/Locales/ruRU.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "ruRU") then +if GetLocale() ~= "ruRU" then return end diff --git a/WeakAuras/Locales/zhCN.lua b/WeakAuras/Locales/zhCN.lua index d763389..75bd5da 100644 --- a/WeakAuras/Locales/zhCN.lua +++ b/WeakAuras/Locales/zhCN.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "zhCN") then +if GetLocale() ~= "zhCN" then return end diff --git a/WeakAuras/Locales/zhTW.lua b/WeakAuras/Locales/zhTW.lua index 56007af..e2cbafc 100644 --- a/WeakAuras/Locales/zhTW.lua +++ b/WeakAuras/Locales/zhTW.lua @@ -1,4 +1,4 @@ -if not(GetLocale() == "zhTW") then +if GetLocale() ~= "zhTW" then return end diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index c92d467..07fb46f 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L @@ -1160,6 +1160,17 @@ function Private.Modernize(data) end end + if (data.internalVersion < 51) then + for _, triggerData in ipairs(data.triggers) do + if triggerData.trigger.event == "Threat Situation" then + triggerData.trigger.unit = triggerData.trigger.threatUnit + triggerData.trigger.use_unit = triggerData.trigger.use_threatUnit + triggerData.trigger.threatUnit = nil + triggerData.trigger.use_threatUnit = nil + end + end + end + if (data.internalVersion < 52) then local function matchTarget(input) return input == "target" or input == "'target'" or input == "\"target\"" or input == "%t" or input == "'%t'" or input == "\"%t\"" diff --git a/WeakAuras/Profiling.lua b/WeakAuras/Profiling.lua index 7d7ba6a..1db3605 100644 --- a/WeakAuras/Profiling.lua +++ b/WeakAuras/Profiling.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras @@ -446,14 +446,10 @@ function WeakAuras.PrintProfile() PrintOneProfile(popup, "|cff9900ffTotal time:|r", profileData.systems.time) PrintOneProfile(popup, "|cff9900ffTime inside WA:|r", profileData.systems.wa) popup:AddText(string.format("|cff9900ffTime spent inside WA:|r %.2f%%", 100 * profileData.systems.wa.elapsed / profileData.systems.time.elapsed)) - popup:AddText("") - popup:AddText("|cff9900ffSystems:|r") - for i, k in ipairs(SortProfileMap(profileData.systems)) do - if (k ~= "time" and k ~= "wa") then - PrintOneProfile(popup, k, profileData.systems[k], profileData.systems.wa.elapsed) - end - end + popup:AddText("") + popup:AddText("Note: Not every aspect of each aura can be tracked.") + popup:AddText("You can ask on our discord https://discord.gg/weakauras for help interpreting this output.") popup:AddText("") popup:AddText("|cff9900ffAuras:|r") @@ -462,6 +458,14 @@ function WeakAuras.PrintProfile() for i, k in ipairs(SortProfileMap(profileData.auras)) do PrintOneProfile(popup, k, profileData.auras[k], total) end + + popup:AddText("") + popup:AddText("|cff9900ffSystems:|r") + for i, k in ipairs(SortProfileMap(profileData.systems)) do + if (k ~= "time" and k ~= "wa") then + PrintOneProfile(popup, k, profileData.systems[k], profileData.systems.wa.elapsed) + end + end popup:Show() end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 8477517..3fa8e8b 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Lua APIs @@ -133,7 +133,7 @@ Private.function_strings = { ]] }; -local hsvFrame = CreateFrame("Colorselect") +local hsvFrame = CreateFrame("ColorSelect") -- HSV transition, for a much prettier color transition in many cases -- see http://www.wowinterface.com/forums/showthread.php?t=48236 @@ -1084,7 +1084,7 @@ Private.load_prototype = { multiEntry = { operator = "or" }, - test = "IsEquippedItem(%s)", + test = "IsEquippedItem(GetItemInfo(%s))", events = { "UNIT_INVENTORY_CHANGED", "PLAYER_EQUIPMENT_CHANGED"} }, { @@ -1094,7 +1094,7 @@ Private.load_prototype = { multiEntry = { operator = "or" }, - test = "not IsEquippedItem(%s)", + test = "not IsEquippedItem(GetItemInfo(%s))", events = { "UNIT_INVENTORY_CHANGED", "PLAYER_EQUIPMENT_CHANGED"} }, } @@ -5440,7 +5440,7 @@ Private.event_prototypes = { local ret = [[ local inverse = %s; - local equipped = IsEquippedItem(%s); + local equipped = IsEquippedItem(GetItemInfo(%s)); ]]; return ret:format(trigger.use_inverse and "true" or "false", itemName); @@ -5555,18 +5555,20 @@ Private.event_prototypes = { ["Threat Situation"] = { type = "unit", events = function(trigger) + local unit = trigger.unit local result = {} - if trigger.threatUnit and trigger.threatUnit ~= "none" then - AddUnitEventForEvents(result, trigger.threatUnit, "UNIT_THREAT_LIST_UPDATE") + if unit and unit ~= "none" then + AddUnitEventForEvents(result, unit, "UNIT_THREAT_LIST_UPDATE") else AddUnitEventForEvents(result, "player", "UNIT_THREAT_SITUATION_UPDATE") end return result end, internal_events = function(trigger) + local unit = trigger.unit local result = {} - if trigger.threatUnit and trigger.threatUnit ~= "none" then - AddUnitChangeInternalEvents(trigger.threatUnit, result) + if unit and unit ~= "none" then + AddUnitChangeInternalEvents(unit, result) end return result end, @@ -5576,14 +5578,15 @@ Private.event_prototypes = { AddWatchedUnits(unit) end end, - force_events = "UNIT_THREAT_LIST_UPDATE", + force_events = unitHelperFunctions.UnitChangedForceEvents, name = L["Threat Situation"], init = function(trigger) + trigger.unit = trigger.unit or "target"; local ret = [[ - local unit = %s + unit = string.lower(unit) local ok = true local aggro, status, threatpct, rawthreatpct, threatvalue, threattotal - if unit then + if unit and unit ~= "none" then aggro, status, threatpct, rawthreatpct, threatvalue = WeakAuras.UnitDetailedThreatSituation('player', unit) threattotal = (threatvalue or 0) * 100 / (threatpct ~= 0 and threatpct or 1) else @@ -5592,18 +5595,20 @@ Private.event_prototypes = { threatpct, rawthreatpct, threatvalue, threattotal = 100, 100, 0, 100 end ]]; - return ret:format(trigger.threatUnit and trigger.threatUnit ~= "none" and "[["..trigger.threatUnit.."]]" or "nil"); + return ret; end, canHaveDuration = true, - statesParameter = "one", + statesParameter = "unit", args = { { - name = "threatUnit", + name = "unit", display = L["Unit"], required = true, type = "unit", + init = "arg", values = "threat_unit_types", test = "true", + store = true, default = "target" }, { @@ -5628,7 +5633,7 @@ Private.event_prototypes = { type = "number", store = true, conditionType = "number", - enable = function(trigger) return trigger.threatUnit ~= "none" end, + enable = function(trigger) return trigger.unit ~= "none" end, multiEntry = { operator = "and", limit = 2 @@ -5641,7 +5646,7 @@ Private.event_prototypes = { type = "number", store = true, conditionType = "number", - enable = function(trigger) return trigger.threatUnit ~= "none" end, + enable = function(trigger) return trigger.unit ~= "none" end, multiEntry = { operator = "and", limit = 2 @@ -5654,7 +5659,7 @@ Private.event_prototypes = { type = "number", store = true, conditionType = "number", - enable = function(trigger) return trigger.threatUnit ~= "none" end, + enable = function(trigger) return trigger.unit ~= "none" end, multiEntry = { operator = "and", limit = 2 diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 82f1a97..1fc87c9 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -1004,19 +1004,19 @@ end -- Called when first creating a new region/display local function create(parent) -- Create overall region (containing everything else) - local region = CreateFrame("FRAME", nil, parent); + local region = CreateFrame("Frame", nil, parent); region.regionType = "aurabar" region:SetMovable(true); region:SetResizable(true); region:SetMinResize(1, 1); -- Create statusbar (inherit prototype) - local bar = CreateFrame("FRAME", nil, region); + local bar = CreateFrame("Frame", nil, region); WeakAuras.Mixin(bar, SmoothStatusBarMixin); local fg = bar:CreateTexture(nil, "BORDER"); local bg = bar:CreateTexture(nil, "BACKGROUND"); bg:SetAllPoints(); - local fgFrame = CreateFrame("FRAME", nil, bar) + local fgFrame = CreateFrame("Frame", nil, bar) local spark = bar:CreateTexture(nil, "ARTWORK"); bar.fg = fg; bar.fgFrame = fgFrame @@ -1031,7 +1031,7 @@ local function create(parent) region.bar = bar; -- Create icon - local iconFrame = CreateFrame("FRAME", nil, region); + local iconFrame = CreateFrame("Frame", nil, region); region.iconFrame = iconFrame; local icon = iconFrame:CreateTexture(nil, "OVERLAY"); region.icon = icon; @@ -1187,7 +1187,7 @@ local function modify(parent, region, data) if tooltipType and data.useTooltip then -- Create and enable tooltip-hover frame if not region.tooltipFrame then - region.tooltipFrame = CreateFrame("frame", nil, region); + region.tooltipFrame = CreateFrame("Frame", nil, region); region.tooltipFrame:SetAllPoints(icon); region.tooltipFrame:SetScript("OnEnter", function() Private.ShowMouseoverTooltip(region, region.tooltipFrame); diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 7aed002..54ad403 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras @@ -79,7 +79,7 @@ local controlPointFunctions = { } local function createControlPoint(self) - local controlPoint = CreateFrame("FRAME", nil, self.parent) + local controlPoint = CreateFrame("Frame", nil, self.parent) WeakAuras.Mixin(controlPoint, controlPointFunctions) controlPoint:SetWidth(16) @@ -103,14 +103,14 @@ local function releaseControlPoint(self, controlPoint) end local function create(parent) - local region = CreateFrame("FRAME", nil, parent) + local region = CreateFrame("Frame", nil, parent) region.regionType = "dynamicgroup" region:SetSize(16, 16) region:SetMovable(true) region.sortedChildren = {} region.controlledChildren = {} region.updatedChildren = {} - local background = CreateFrame("frame", nil, region) + local background = CreateFrame("Frame", nil, region) region.background = background region.selfPoint = "TOPLEFT" region.controlPoints = CreateObjectPool(createControlPoint, releaseControlPoint) diff --git a/WeakAuras/RegionTypes/Group.lua b/WeakAuras/RegionTypes/Group.lua index 57f9312..1ed9f39 100644 --- a/WeakAuras/RegionTypes/Group.lua +++ b/WeakAuras/RegionTypes/Group.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -25,14 +25,14 @@ local default = { -- Called when first creating a new region/display local function create(parent) -- Main region - local region = CreateFrame("FRAME", nil, parent); + local region = CreateFrame("Frame", nil, parent); region.regionType = "group" region:SetMovable(true); region:SetWidth(2); region:SetHeight(2); -- Border region - local border = CreateFrame("frame", nil, region); + local border = CreateFrame("Frame", nil, region); region.border = border; WeakAuras.regionPrototype.create(region); diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index b89af10..b3306ce 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -143,7 +143,7 @@ local function AnchorSubRegion(self, subRegion, anchorType, selfPoint, anchorPoi local anchorRegion = self.icon if anchorPoint:sub(1, 6) == "INNER_" then if not self.inner then - self.inner = CreateFrame("FRAME", nil, self) + self.inner = CreateFrame("Frame", nil, self) self.inner:SetPoint("CENTER") self.UpdateInnerOuterSize() end @@ -151,7 +151,7 @@ local function AnchorSubRegion(self, subRegion, anchorType, selfPoint, anchorPoi anchorPoint = anchorPoint:sub(7) elseif anchorPoint:sub(1, 6) == "OUTER_" then if not self.outer then - self.outer = CreateFrame("FRAME", nil, self) + self.outer = CreateFrame("Frame", nil, self) self.outer:SetPoint("CENTER") self.UpdateInnerOuterSize() end @@ -243,7 +243,7 @@ end local function create(parent, data) local font = "GameFontHighlight"; - local region = CreateFrame("FRAME", nil, parent); + local region = CreateFrame("Frame", nil, parent); region.regionType = "icon" region:SetMovable(true); region:SetResizable(true); @@ -312,7 +312,7 @@ local function create(parent, data) end region.frameId = frameId; - local cooldown = CreateFrame("COOLDOWN", "WeakAurasCooldown"..frameId, region, "CooldownFrameTemplate"); + local cooldown = CreateFrame("Cooldown", "WeakAurasCooldown"..frameId, region, "CooldownFrameTemplate"); region.cooldown = cooldown; cooldown:SetAllPoints(icon); @@ -428,7 +428,7 @@ local function modify(parent, region, data) local tooltipType = Private.CanHaveTooltip(data); if(tooltipType and data.useTooltip) then if not region.tooltipFrame then - region.tooltipFrame = CreateFrame("frame", nil, region); + region.tooltipFrame = CreateFrame("Frame", nil, region); region.tooltipFrame:SetAllPoints(region); region.tooltipFrame:SetScript("OnEnter", function() Private.ShowMouseoverTooltip(region, region); diff --git a/WeakAuras/RegionTypes/Model.lua b/WeakAuras/RegionTypes/Model.lua index 6e6a5f9..73db987 100644 --- a/WeakAuras/RegionTypes/Model.lua +++ b/WeakAuras/RegionTypes/Model.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -69,14 +69,14 @@ local regionFunctions = { -- Called when first creating a new region/display local function create(parent) -- Main region - local region = CreateFrame("FRAME", nil, UIParent); + local region = CreateFrame("Frame", nil, UIParent); region.regionType = "model" region:SetMovable(true); region:SetResizable(true); region:SetMinResize(1, 1); -- Border region - local border = CreateFrame("frame", nil, region); + local border = CreateFrame("Frame", nil, region); region.border = border; WeakAuras.regionPrototype.create(region); diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 20fc4e1..cf188e4 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; @@ -424,7 +424,7 @@ WeakAuras.createSpinner = createSpinner; local function create(parent) local font = "GameFontHighlight"; - local region = CreateFrame("FRAME", nil, parent); + local region = CreateFrame("Frame", nil, parent); region.regionType = "progresstexture" region:SetMovable(true); region:SetResizable(true); diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index ed46aac..443d1c8 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras; @@ -624,7 +624,7 @@ end local regionsForFrameTick = {} -local frameForFrameTick = CreateFrame("FRAME"); +local frameForFrameTick = CreateFrame("Frame"); WeakAuras.frames["Frame Tick Frame"] = frameForFrameTick diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index 5863394..81a68f2 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local texture_types = WeakAuras.StopMotion.texture_types; @@ -90,7 +90,7 @@ local properties = { WeakAuras.regionPrototype.AddProperties(properties, default); local function create(parent) - local frame = CreateFrame("FRAME", nil, UIParent); + local frame = CreateFrame("Frame", nil, UIParent); frame.regionType = "stopmotion" frame:SetMovable(true); frame:SetResizable(true); diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index e676fea..33df1e4 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -54,7 +54,7 @@ local function GetProperties(data) end local function create(parent) - local region = CreateFrame("FRAME", nil, parent); + local region = CreateFrame("Frame", nil, parent); region.regionType = "text" region:SetMovable(true); @@ -98,7 +98,7 @@ local function modify(parent, region, data) local tooltipType = Private.CanHaveTooltip(data); if(tooltipType and data.useTooltip) then if not region.tooltipFrame then - region.tooltipFrame = CreateFrame("frame", nil, region); + region.tooltipFrame = CreateFrame("Frame", nil, region); region.tooltipFrame:SetAllPoints(region); region.tooltipFrame:SetScript("OnEnter", function() Private.ShowMouseoverTooltip(region, region); diff --git a/WeakAuras/RegionTypes/Texture.lua b/WeakAuras/RegionTypes/Texture.lua index 4bb3e38..cf5fbad 100644 --- a/WeakAuras/RegionTypes/Texture.lua +++ b/WeakAuras/RegionTypes/Texture.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; @@ -68,7 +68,7 @@ local properties = { WeakAuras.regionPrototype.AddProperties(properties, default); local function create(parent) - local region = CreateFrame("FRAME", nil, UIParent); + local region = CreateFrame("Frame", nil, UIParent); region.regionType = "texture" region:SetMovable(true); region:SetResizable(true); diff --git a/WeakAuras/SubRegionTypes/Background.lua b/WeakAuras/SubRegionTypes/Background.lua index 3320c40..97bf3a0 100644 --- a/WeakAuras/SubRegionTypes/Background.lua +++ b/WeakAuras/SubRegionTypes/Background.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; diff --git a/WeakAuras/SubRegionTypes/Border.lua b/WeakAuras/SubRegionTypes/Border.lua index 1275bf3..d1d3984 100644 --- a/WeakAuras/SubRegionTypes/Border.lua +++ b/WeakAuras/SubRegionTypes/Border.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -34,7 +34,7 @@ local properties = { local function create() - return CreateFrame("FRAME", nil, UIParent) + return CreateFrame("Frame", nil, UIParent) end local function onAcquire(subRegion) diff --git a/WeakAuras/SubRegionTypes/Glow.lua b/WeakAuras/SubRegionTypes/Glow.lua index 8c93d4b..922ea1f 100644 --- a/WeakAuras/SubRegionTypes/Glow.lua +++ b/WeakAuras/SubRegionTypes/Glow.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -297,7 +297,7 @@ local funcs = { } local function create() - local region = CreateFrame("FRAME", nil, UIParent) + local region = CreateFrame("Frame", nil, UIParent) for name, func in pairs(funcs) do region[name] = func diff --git a/WeakAuras/SubRegionTypes/Model.lua b/WeakAuras/SubRegionTypes/Model.lua index 21eb44e..77dc88a 100644 --- a/WeakAuras/SubRegionTypes/Model.lua +++ b/WeakAuras/SubRegionTypes/Model.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -155,7 +155,7 @@ local funcs = { } local function create() - local subRegion = CreateFrame("FRAME", nil, UIParent) + local subRegion = CreateFrame("Frame", nil, UIParent) --subRegion:SetClipsChildren(true) for k, v in pairs(funcs) do diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index f83e451..81e55a1 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -101,7 +101,7 @@ local properties = { } local function create() - local region = CreateFrame("FRAME", nil, UIParent); + local region = CreateFrame("Frame", nil, UIParent); local text = region:CreateFontString(nil, "OVERLAY"); region.text = text; diff --git a/WeakAuras/SubRegionTypes/Tick.lua b/WeakAuras/SubRegionTypes/Tick.lua index 8aaae83..772435e 100644 --- a/WeakAuras/SubRegionTypes/Tick.lua +++ b/WeakAuras/SubRegionTypes/Tick.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -107,7 +107,7 @@ local auraBarAnchorInverse = { } local function create() - local subRegion = CreateFrame("FRAME", nil, UIParent) + local subRegion = CreateFrame("Frame", nil, UIParent) subRegion.texture = subRegion:CreateTexture() subRegion.texture:SetDrawLayer("ARTWORK", 3) subRegion.texture:SetAllPoints(subRegion) diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 761689e..77210f7 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -18,7 +18,7 @@ Imports an aura from a table, which may or may not be encoded as a B64 string. If target is installed data, or is a uid which points to installed data, then the import will be an update to that aura ]]-- -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Lua APIs diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 810ce42..0c76851 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras; @@ -150,8 +150,8 @@ local simpleFormatters = { local fmt, time = SecondsToTimeAbbrev(value) -- Remove the space between the value and unit return fmt:gsub(" ", ""):format(time) - end - } + end, + }, } Private.format_types = { @@ -257,7 +257,7 @@ Private.format_types = { if value < threshold then return string.format(formatString, value) else - return mainFormater(value, state) + return mainFormater(value) end end end @@ -874,7 +874,7 @@ local function update_forms() end end end -local form_frame = CreateFrame("frame"); +local form_frame = CreateFrame("Frame"); form_frame:RegisterEvent("UPDATE_SHAPESHIFT_FORMS") form_frame:RegisterEvent("PLAYER_LOGIN") form_frame:SetScript("OnEvent", update_forms); diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index baafcc5..a386550 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -30,7 +30,7 @@ LibStub("AceTimer-3.0"):Embed(WeakAurasTimers) Private.watched_trigger_events = {} --- The worlds simplest callback system +-- The worlds simplest callback system. -- That supports 1:N, but no deregistration and breaks if registrating in a callback Private.callbacks = {} Private.callbacks.events = {} @@ -141,7 +141,7 @@ function SlashCmdList.WEAKAURAS(input) end end -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end function Private.ToggleMinimap() WeakAurasSaved.minimap.hide = not WeakAurasSaved.minimap.hide @@ -913,7 +913,7 @@ local function tooltip_draw() tooltip:Show(); end -local colorFrame = CreateFrame("frame"); +local colorFrame = CreateFrame("Frame"); WeakAuras.frames["LDB Icon Recoloring"] = colorFrame; local colorElapsed = 0; @@ -921,7 +921,7 @@ local colorDelay = 2; local r, g, b = 0.8, 0, 1; local r2, g2, b2 = random(2)-1, random(2)-1, random(2)-1; -local tooltip_update_frame = CreateFrame("FRAME"); +local tooltip_update_frame = CreateFrame("Frame"); WeakAuras.frames["LDB Tooltip Updater"] = tooltip_update_frame; -- function copied from LibDBIcon-1.0.lua @@ -1102,12 +1102,12 @@ function Private.Login(initialTime, takeNewSnapshots) end end -local WeakAurasFrame = CreateFrame("FRAME", "WeakAurasFrame", UIParent); +local WeakAurasFrame = CreateFrame("Frame", "WeakAurasFrame", UIParent); WeakAuras.frames["WeakAuras Main Frame"] = WeakAurasFrame; WeakAurasFrame:SetAllPoints(UIParent); WeakAurasFrame:SetFrameStrata("BACKGROUND"); -local loadedFrame = CreateFrame("FRAME"); +local loadedFrame = CreateFrame("Frame"); WeakAuras.frames["Addon Initialization Handler"] = loadedFrame; loadedFrame:RegisterEvent("ADDON_LOADED"); loadedFrame:RegisterEvent("PLAYER_LOGIN"); @@ -1446,7 +1446,7 @@ function Private.ScanForLoads(toCheck, event, arg1, ...) scanForLoadsImpl(toCheck, event, arg1, ...) end -local loadFrame = CreateFrame("FRAME"); +local loadFrame = CreateFrame("Frame"); WeakAuras.loadFrame = loadFrame; WeakAuras.frames["Display Load Handling"] = loadFrame; @@ -1473,7 +1473,7 @@ loadFrame:RegisterEvent("PLAYER_UNGHOST") loadFrame:RegisterEvent("PLAYER_FLAGS_CHANGED") loadFrame:RegisterEvent("PARTY_LEADER_CHANGED") -local unitLoadFrame = CreateFrame("FRAME"); +local unitLoadFrame = CreateFrame("Frame"); WeakAuras.unitLoadFrame = unitLoadFrame; WeakAuras.frames["Display Load Handling 2"] = unitLoadFrame; @@ -3564,7 +3564,7 @@ end local dynFrame = {}; do -- Internal data - dynFrame.frame = CreateFrame("frame"); + dynFrame.frame = CreateFrame("Frame"); dynFrame.update = {}; dynFrame.size = 0; @@ -4474,12 +4474,12 @@ local function ensureMouseFrame() if (mouseFrame) then return; end - mouseFrame = CreateFrame("FRAME", "WeakAurasAttachToMouseFrame", UIParent); + mouseFrame = CreateFrame("Frame", "WeakAurasAttachToMouseFrame", UIParent); mouseFrame.attachedVisibleFrames = {}; mouseFrame:SetWidth(1); mouseFrame:SetHeight(1); - local moverFrame = CreateFrame("FRAME", "WeakAurasMousePointerFrame", mouseFrame); + local moverFrame = CreateFrame("Frame", "WeakAurasMousePointerFrame", mouseFrame); mouseFrame.moverFrame = moverFrame; moverFrame:SetPoint("TOPLEFT", mouseFrame, "CENTER"); moverFrame:SetWidth(32); @@ -4794,7 +4794,7 @@ local function postponeAnchor(id) end end -local HiddenFrames = CreateFrame("FRAME", "WeakAurasHiddenFrames") +local HiddenFrames = CreateFrame("Frame", "WeakAurasHiddenFrames") HiddenFrames:Hide() WeakAuras.HiddenFrames = HiddenFrames diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasTreeGroup.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasTreeGroup.lua index 0ba0539..1fb5ff2 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasTreeGroup.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasTreeGroup.lua @@ -3,7 +3,7 @@ WeakAurasTreeGroup Container Container that uses a tree control to switch between groups. This file was forked from AceGUIContainer-TreeGroup.lua version 41 -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasTreeGroup", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasAnchorButtons.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasAnchorButtons.lua index ef21408..773881a 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasAnchorButtons.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasAnchorButtons.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasAnchorButtons", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index b99ed4e..57da6ef 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local tinsert, tconcat, tremove, wipe = table.insert, table.concat, table.remove, wipe @@ -1855,7 +1855,7 @@ local function Constructor() renamebox:Hide(); end); - local group = CreateFrame("BUTTON", nil, button); + local group = CreateFrame("Button", nil, button); button.group = group; group:SetWidth(16); group:SetHeight(16); @@ -1870,7 +1870,7 @@ local function Constructor() group:SetScript("OnEnter", function() Show_Tooltip(button, L["Group (verb)"], L["Put this display in a group"]) end); group:SetScript("OnLeave", Hide_Tooltip); - local ungroup = CreateFrame("BUTTON", nil, button); + local ungroup = CreateFrame("Button", nil, button); button.ungroup = ungroup; ungroup:SetWidth(11); ungroup:SetHeight(11); @@ -1885,7 +1885,7 @@ local function Constructor() ungroup:SetScript("OnLeave", Hide_Tooltip); ungroup:Hide(); - local upgroup = CreateFrame("BUTTON", nil, button); + local upgroup = CreateFrame("Button", nil, button); button.upgroup = upgroup; upgroup:SetWidth(11); upgroup:SetHeight(11); @@ -1902,7 +1902,7 @@ local function Constructor() upgroup:SetScript("OnLeave", Hide_Tooltip); upgroup:Hide(); - local downgroup = CreateFrame("BUTTON", nil, button); + local downgroup = CreateFrame("Button", nil, button); button.downgroup = downgroup; downgroup:SetWidth(11); downgroup:SetHeight(11); @@ -1918,7 +1918,7 @@ local function Constructor() downgroup:SetScript("OnLeave", Hide_Tooltip); downgroup:Hide(); - local expand = CreateFrame("BUTTON", nil, button); + local expand = CreateFrame("Button", nil, button); button.expand = expand; expand.expanded = true; expand.disabled = true; diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua index e1132d9..9d96e9a 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- Button Widget for our Expand button -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasExpand", 3 diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandAnchor.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandAnchor.lua index 8f2b5d9..a4bb427 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandAnchor.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandAnchor.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- Anchor for a Expandable section -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local Type, Version = "WeakAurasExpandAnchor", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua index 5593e51..d7a2ca8 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- Button Widget for our Expand button -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local Type, Version = "WeakAurasExpandSmall", 2 diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIcon.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIcon.lua index c6ebfbb..bd164aa 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIcon.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIcon.lua @@ -3,7 +3,7 @@ Icon Widget that allows for a tooltip, by preventing SetLabel from actually setting a label Graphical Button. -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasIcon", 1 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIconButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIconButton.lua index 3306deb..13a0724 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIconButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIconButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasIconButton", 21 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) @@ -62,7 +62,7 @@ Constructor -------------------------------------------------------------------------------]] local function Constructor() - local button = CreateFrame("BUTTON", nil, UIParent); + local button = CreateFrame("Button", nil, UIParent); button:SetHeight(52); button:SetWidth(52); diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasImportButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasImportButton.lua index fc47819..c372f97 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasImportButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasImportButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasImportButton", 20 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) @@ -124,7 +124,7 @@ Constructor local function Constructor() local name = "WeakAurasImportButton"..AceGUI:GetNextWidgetNum(Type); - local button = CreateFrame("BUTTON", name, UIParent, "OptionsListButtonTemplate"); + local button = CreateFrame("Button", name, UIParent, "OptionsListButtonTemplate"); button:SetHeight(18); button:SetWidth(380); button.dgroup = nil; @@ -136,7 +136,7 @@ local function Constructor() background:SetVertexColor(0.5, 0.5, 0.5, 0.25); background:SetAllPoints(button); - local expand = CreateFrame("BUTTON", nil, button); + local expand = CreateFrame("Button", nil, button); button.expand = expand; expand.expanded = true; expand.disabled = true; diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasInputFocus.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasInputFocus.lua index a510470..478c58e 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasInputFocus.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasInputFocus.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- Input Widget that allows to show an alternative text when it does not have focus -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasInputFocus", 1 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasLoadedHeaderButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasLoadedHeaderButton.lua index a99a6dc..3e0fadd 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasLoadedHeaderButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasLoadedHeaderButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasLoadedHeaderButton", 22 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) @@ -142,7 +142,7 @@ Constructor local function Constructor() local name = Type..AceGUI:GetNextWidgetNum(Type) - local button = CreateFrame("BUTTON", name, UIParent, "OptionsListButtonTemplate"); + local button = CreateFrame("Button", name, UIParent, "OptionsListButtonTemplate"); button:SetHeight(20); button:SetWidth(1000); button:SetDisabledFontObject("GameFontNormal"); @@ -154,7 +154,7 @@ local function Constructor() background:SetVertexColor(0.5, 0.5, 0.5, 0.6); background:SetAllPoints(button); - local expand = CreateFrame("BUTTON", nil, button); + local expand = CreateFrame("Button", nil, button); button.expand = expand; expand.expanded = true; expand.disabled = true; @@ -172,7 +172,7 @@ local function Constructor() expand:SetScript("OnEnter", function() Show_Tooltip(button, expand.title, expand.desc) end); expand:SetScript("OnLeave", Hide_Tooltip); - local view = CreateFrame("BUTTON", nil, button); + local view = CreateFrame("Button", nil, button); button.view = view; view:SetWidth(16); view:SetHeight(16); diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBox.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBox.lua index e179ab2..2a6a67b 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBox.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBox.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasMultiLineEditBox", 35 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBoxWithEnter.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBoxWithEnter.lua index eacbd81..3fd968c 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBoxWithEnter.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBoxWithEnter.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -- based on the AceGUI widget, overwrites the enter handling local Type, Version = "WeakAuras-MultiLineEditBoxWithEnter", 1 diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua index 1dfa80b..32099fb 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasNewButton", 24 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) @@ -90,7 +90,7 @@ Constructor local function Constructor() local name = "WeakAurasDisplayButton"..AceGUI:GetNextWidgetNum(Type); - local button = CreateFrame("BUTTON", name, UIParent, "OptionsListButtonTemplate"); + local button = CreateFrame("Button", name, UIParent, "OptionsListButtonTemplate"); button:SetHeight(40); button:SetWidth(380); button.dgroup = nil; diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewHeaderButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewHeaderButton.lua index d01b27b..6d489e5 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewHeaderButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewHeaderButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasNewHeaderButton", 20 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) @@ -56,7 +56,7 @@ Constructor local function Constructor() local name = Type..AceGUI:GetNextWidgetNum(Type) - local button = CreateFrame("BUTTON", name, UIParent, "OptionsListButtonTemplate"); + local button = CreateFrame("Button", name, UIParent, "OptionsListButtonTemplate"); button:SetHeight(20); button:SetWidth(1000); button:SetDisabledFontObject("GameFontNormal"); diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua index 72a800c..40b0555 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua @@ -160,7 +160,7 @@ Constructor local function Constructor() local name = "WeakAurasPendingInstallButton" .. AceGUI:GetNextWidgetNum(Type) - local button = CreateFrame("BUTTON", name, UIParent) + local button = CreateFrame("Button", name, UIParent) button:SetHeight(32) button:SetWidth(1000) button.data = {} @@ -191,7 +191,7 @@ local function Constructor() button.description = {} - local update = CreateFrame("BUTTON", nil, button) + local update = CreateFrame("Button", nil, button) button.update = update update.disabled = true update.func = function() diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua index 6e76883..e2e4ff5 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua @@ -289,7 +289,7 @@ Constructor local function Constructor() local name = "WeakAurasPendingUpdateButton" .. AceGUI:GetNextWidgetNum(Type) - local button = CreateFrame("BUTTON", name, UIParent) + local button = CreateFrame("Button", name, UIParent) button:SetHeight(32) button:SetWidth(1000) button.data = {} @@ -320,7 +320,7 @@ local function Constructor() button.description = {} - local update = CreateFrame("BUTTON", nil, button) + local update = CreateFrame("Button", nil, button) button.update = update update.disabled = true update.func = function() diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSnippetButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSnippetButton.lua index 6d8564c..21354e3 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSnippetButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSnippetButton.lua @@ -137,7 +137,7 @@ local function Constructor() button:SetHeight(24) button:SetWidth(170) - local deleteButton = CreateFrame("BUTTON", nil, button) + local deleteButton = CreateFrame("Button", nil, button) deleteButton:SetPoint("RIGHT", button, "RIGHT", -3, 0) deleteButton:SetSize(20, 20) local deleteTex = deleteButton:CreateTexture() diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua index 5db65ad..b321578 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasTextureButton", 25 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) @@ -87,7 +87,7 @@ Constructor local function Constructor() local name = "WeakAurasTextureButton"..AceGUI:GetNextWidgetNum(Type); - local button = CreateFrame("BUTTON", name, UIParent, "OptionsListButtonTemplate"); + local button = CreateFrame("Button", name, UIParent, "OptionsListButtonTemplate"); button:SetHeight(128); button:SetWidth(128); button:SetBackdrop({ diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua index 5f5c42f..5a99a04 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasTwoColumnDropdown", 3 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/ActionOptions.lua b/WeakAurasOptions/ActionOptions.lua index d71efb6..8779964 100644 --- a/WeakAurasOptions/ActionOptions.lua +++ b/WeakAurasOptions/ActionOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/AnimationOptions.lua b/WeakAurasOptions/AnimationOptions.lua index 89806d6..5d4796c 100644 --- a/WeakAurasOptions/AnimationOptions.lua +++ b/WeakAurasOptions/AnimationOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index 11d52fe..301c405 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -58,7 +58,7 @@ bigStep (optional) -> step size of the slider. Defaults to 0.05 step (optional) -> like bigStep, but applies to number input as well ]] -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local WeakAuras = WeakAuras @@ -2001,7 +2001,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) while i <= #values or i <= #childValues do if firstChild then values[i] = childValues[i][nameSource] or conflictBlue .. L["Entry %i"]:format(i) - elseif childValues[i] ~= values[i] then + elseif childValues[i][nameSource] ~= values[i] then values[i] = conflictBlue .. L["Entry %i"]:format(i) end i = i + 1 @@ -2418,7 +2418,7 @@ local function mergeOptions(mergedOptions, data, options, config, prepath, paren -- check if nextToMerge.nameSource was merged in the same spot as mergedOption.nameSource local subMergedOption = mergedOption.subOptions[mergedOption.nameSource] local optionData = subMergedOption.references[data.id] - if not optionData or optionData.optionIndex ~= nextToMerge.nameSource then + if not optionData or optionData.index ~= nextToMerge.nameSource then -- either an option was not merged at the name source's index, or the wrong option was. -- in both cases, the name source is conflicted. Fallback to "Entry #" as entry names mergedOption.nameSource = nil diff --git a/WeakAurasOptions/BuffTrigger.lua b/WeakAurasOptions/BuffTrigger.lua index 422e074..70215e9 100644 --- a/WeakAurasOptions/BuffTrigger.lua +++ b/WeakAurasOptions/BuffTrigger.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index 21a0e2f..e576353 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/Cache.lua b/WeakAurasOptions/Cache.lua index ef13e10..fbe94da 100644 --- a/WeakAurasOptions/Cache.lua +++ b/WeakAurasOptions/Cache.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index 15fa934..3196ba4 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index a54964d..596360b 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -44,7 +44,7 @@ -- - setter: The setter function, called both on activating and deactivating a property change --- - action: The action function, called on activating a condition -- - type: The type -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local WeakAuras = WeakAuras; diff --git a/WeakAurasOptions/DisplayOptions.lua b/WeakAurasOptions/DisplayOptions.lua index 8f36c26..19e0149 100644 --- a/WeakAurasOptions/DisplayOptions.lua +++ b/WeakAurasOptions/DisplayOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L local regionOptions = WeakAuras.regionOptions diff --git a/WeakAurasOptions/ForAllIndentsAndPurposes.lua b/WeakAurasOptions/ForAllIndentsAndPurposes.lua index cb2463a..0e6bc72 100644 --- a/WeakAurasOptions/ForAllIndentsAndPurposes.lua +++ b/WeakAurasOptions/ForAllIndentsAndPurposes.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -- For All Indents And Purposes local revision = 23 diff --git a/WeakAurasOptions/GenericTrigger.lua b/WeakAurasOptions/GenericTrigger.lua index 0731789..32b72d3 100644 --- a/WeakAurasOptions/GenericTrigger.lua +++ b/WeakAurasOptions/GenericTrigger.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/GroupOptions.lua b/WeakAurasOptions/GroupOptions.lua index 7289d45..d45c55c 100644 --- a/WeakAurasOptions/GroupOptions.lua +++ b/WeakAurasOptions/GroupOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index a3f7656..247332a 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/LoadOptions.lua b/WeakAurasOptions/LoadOptions.lua index 8f1941a..3d52dec 100644 --- a/WeakAurasOptions/LoadOptions.lua +++ b/WeakAurasOptions/LoadOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/Locales/deDE.lua b/WeakAurasOptions/Locales/deDE.lua index 1d67876..708bffb 100644 --- a/WeakAurasOptions/Locales/deDE.lua +++ b/WeakAurasOptions/Locales/deDE.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "deDE") then +if GetLocale() ~= "deDE" then return end diff --git a/WeakAurasOptions/Locales/enUS.lua b/WeakAurasOptions/Locales/enUS.lua index bdff1c8..8d00390 100644 --- a/WeakAurasOptions/Locales/enUS.lua +++ b/WeakAurasOptions/Locales/enUS.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local L = WeakAuras.L diff --git a/WeakAurasOptions/Locales/esES.lua b/WeakAurasOptions/Locales/esES.lua index 3009603..d468fd7 100644 --- a/WeakAurasOptions/Locales/esES.lua +++ b/WeakAurasOptions/Locales/esES.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "esES") then +if GetLocale() ~= "esES" then return end diff --git a/WeakAurasOptions/Locales/esMX.lua b/WeakAurasOptions/Locales/esMX.lua index a5feadb..805889c 100644 --- a/WeakAurasOptions/Locales/esMX.lua +++ b/WeakAurasOptions/Locales/esMX.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "esMX") then +if GetLocale() ~= "esMX" then return end diff --git a/WeakAurasOptions/Locales/frFR.lua b/WeakAurasOptions/Locales/frFR.lua index 74e499c..d5abaae 100644 --- a/WeakAurasOptions/Locales/frFR.lua +++ b/WeakAurasOptions/Locales/frFR.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "frFR") then +if GetLocale() ~= "frFR" then return end diff --git a/WeakAurasOptions/Locales/itIT.lua b/WeakAurasOptions/Locales/itIT.lua index 8d4d25b..8ed5bcb 100644 --- a/WeakAurasOptions/Locales/itIT.lua +++ b/WeakAurasOptions/Locales/itIT.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "itIT") then +if GetLocale() ~= "itIT" then return end diff --git a/WeakAurasOptions/Locales/koKR.lua b/WeakAurasOptions/Locales/koKR.lua index 1af8660..ab55e56 100644 --- a/WeakAurasOptions/Locales/koKR.lua +++ b/WeakAurasOptions/Locales/koKR.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "koKR") then +if GetLocale() ~= "koKR" then return end diff --git a/WeakAurasOptions/Locales/ptBR.lua b/WeakAurasOptions/Locales/ptBR.lua index dc28b7d..1221ac9 100644 --- a/WeakAurasOptions/Locales/ptBR.lua +++ b/WeakAurasOptions/Locales/ptBR.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "ptBR") then +if GetLocale() ~= "ptBR" then return end diff --git a/WeakAurasOptions/Locales/ruRU.lua b/WeakAurasOptions/Locales/ruRU.lua index 2a11e18..14dc68f 100644 --- a/WeakAurasOptions/Locales/ruRU.lua +++ b/WeakAurasOptions/Locales/ruRU.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "ruRU") then +if GetLocale() ~= "ruRU" then return end diff --git a/WeakAurasOptions/Locales/zhCN.lua b/WeakAurasOptions/Locales/zhCN.lua index dc6ddcf..f1ba902 100644 --- a/WeakAurasOptions/Locales/zhCN.lua +++ b/WeakAurasOptions/Locales/zhCN.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "zhCN") then +if GetLocale() ~= "zhCN" then return end diff --git a/WeakAurasOptions/Locales/zhTW.lua b/WeakAurasOptions/Locales/zhTW.lua index 3ad44fe..01eaedb 100644 --- a/WeakAurasOptions/Locales/zhTW.lua +++ b/WeakAurasOptions/Locales/zhTW.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end -if not(GetLocale() == "zhTW") then +if GetLocale() ~= "zhTW" then return end diff --git a/WeakAurasOptions/OptionsFrames/CodeReview.lua b/WeakAurasOptions/OptionsFrames/CodeReview.lua index d8a3a13..2f67f7e 100644 --- a/WeakAurasOptions/OptionsFrames/CodeReview.lua +++ b/WeakAurasOptions/OptionsFrames/CodeReview.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/FrameChooser.lua b/WeakAurasOptions/OptionsFrames/FrameChooser.lua index c83ebbf..2281812 100644 --- a/WeakAurasOptions/OptionsFrames/FrameChooser.lua +++ b/WeakAurasOptions/OptionsFrames/FrameChooser.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs @@ -21,8 +21,8 @@ local oldFocusName function OptionsPrivate.StartFrameChooser(data, path) local frame = WeakAuras.OptionsFrame(); if not(frameChooserFrame) then - frameChooserFrame = CreateFrame("frame"); - frameChooserBox = CreateFrame("frame", nil, frameChooserFrame); + frameChooserFrame = CreateFrame("Frame"); + frameChooserBox = CreateFrame("Frame", nil, frameChooserFrame); frameChooserBox:SetFrameStrata("TOOLTIP"); frameChooserBox:SetBackdrop({ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", diff --git a/WeakAurasOptions/OptionsFrames/IconPicker.lua b/WeakAurasOptions/OptionsFrames/IconPicker.lua index d7f7170..0d06f02 100644 --- a/WeakAurasOptions/OptionsFrames/IconPicker.lua +++ b/WeakAurasOptions/OptionsFrames/IconPicker.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/ImportExport.lua b/WeakAurasOptions/OptionsFrames/ImportExport.lua index 319923e..85b5fd1 100644 --- a/WeakAurasOptions/OptionsFrames/ImportExport.lua +++ b/WeakAurasOptions/OptionsFrames/ImportExport.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/ModelPicker.lua b/WeakAurasOptions/OptionsFrames/ModelPicker.lua index 066c744..0df16d8 100644 --- a/WeakAurasOptions/OptionsFrames/ModelPicker.lua +++ b/WeakAurasOptions/OptionsFrames/ModelPicker.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs @@ -57,7 +57,7 @@ local function ConstructModelPicker(frame) group.frame:Hide(); group:SetLayout("flow"); - local filterInput = CreateFrame("editbox", "WeakAurasModelFilterInput", group.frame, "WA_InputBoxTemplate") + local filterInput = CreateFrame("EditBox", "WeakAurasModelFilterInput", group.frame, "WA_InputBoxTemplate") filterInput:SetAutoFocus(false) filterInput:SetTextInsets(16, 20, 0, 0) diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index 25e4855..ff2f885 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs @@ -56,11 +56,11 @@ local function ConstructMover(frame) topAndBottom:SetClampedToScreen(true) topAndBottom:SetSize(25, 45) topAndBottom:SetPoint("LEFT", frame, "RIGHT", 1, 0) - local top = CreateFrame("BUTTON", nil, topAndBottom) + local top = CreateFrame("Button", nil, topAndBottom) top:SetSize(25, 25) top:SetPoint("TOP", topAndBottom) top:SetFrameStrata("BACKGROUND") - local bottom = CreateFrame("BUTTON", nil, topAndBottom) + local bottom = CreateFrame("Button", nil, topAndBottom) bottom:SetSize(25, 25) bottom:SetPoint("BOTTOM", topAndBottom) bottom:SetFrameStrata("BACKGROUND") @@ -69,11 +69,11 @@ local function ConstructMover(frame) leftAndRight:SetClampedToScreen(true) leftAndRight:SetSize(45, 25) leftAndRight:SetPoint("TOP", frame, "BOTTOM", 0, 1) - local left = CreateFrame("BUTTON", nil, leftAndRight) + local left = CreateFrame("Button", nil, leftAndRight) left:SetSize(25, 25) left:SetPoint("LEFT", leftAndRight) left:SetFrameStrata("BACKGROUND") - local right = CreateFrame("BUTTON", nil, leftAndRight) + local right = CreateFrame("Button", nil, leftAndRight) right:SetSize(25, 25) right:SetPoint("RIGHT", leftAndRight) right:SetFrameStrata("BACKGROUND") @@ -107,7 +107,7 @@ local function ConstructMover(frame) right:GetPushedTexture():SetRotation(-math.pi/2) right:SetScript("OnClick", function() moveOnePxl("right") end) - local arrow = CreateFrame("frame", nil, frame) + local arrow = CreateFrame("Frame", nil, frame) arrow:SetClampedToScreen(true) arrow:SetSize(196, 196) arrow:SetPoint("CENTER", frame, "CENTER") @@ -146,7 +146,7 @@ end local function ConstructSizer(frame) -- topright, bottomright, bottomleft, topleft - local topright = CreateFrame("FRAME", nil, frame) + local topright = CreateFrame("Frame", nil, frame) topright:EnableMouse() topright:SetWidth(16) topright:SetHeight(16) @@ -178,7 +178,7 @@ local function ConstructSizer(frame) texTR2:Hide() end - local bottomright = CreateFrame("FRAME", nil, frame) + local bottomright = CreateFrame("Frame", nil, frame) bottomright:EnableMouse() bottomright:SetWidth(16) bottomright:SetHeight(16) @@ -210,7 +210,7 @@ local function ConstructSizer(frame) texBR2:Hide() end - local bottomleft = CreateFrame("FRAME", nil, frame) + local bottomleft = CreateFrame("Frame", nil, frame) bottomleft:EnableMouse() bottomleft:SetSize(16, 16) bottomleft:SetHeight(16) @@ -242,7 +242,7 @@ local function ConstructSizer(frame) texBL2:Hide() end - local topleft = CreateFrame("FRAME", nil, frame) + local topleft = CreateFrame("Frame", nil, frame) topleft:EnableMouse() topleft:SetWidth(16) topleft:SetHeight(16) @@ -276,7 +276,7 @@ local function ConstructSizer(frame) -- top, right, bottom, left - local top = CreateFrame("FRAME", nil, frame) + local top = CreateFrame("Frame", nil, frame) top:EnableMouse() top:SetHeight(8) top:SetPoint("TOPRIGHT", topright, "TOPLEFT") @@ -298,7 +298,7 @@ local function ConstructSizer(frame) texT:Hide() end - local right = CreateFrame("FRAME", nil, frame) + local right = CreateFrame("Frame", nil, frame) right:EnableMouse() right:SetWidth(8) right:SetPoint("BOTTOMRIGHT", bottomright, "TOPRIGHT") @@ -320,7 +320,7 @@ local function ConstructSizer(frame) texR:Hide() end - local bottom = CreateFrame("FRAME", nil, frame) + local bottom = CreateFrame("Frame", nil, frame) bottom:EnableMouse() bottom:SetHeight(8) bottom:SetPoint("BOTTOMLEFT", bottomleft, "BOTTOMRIGHT") @@ -343,7 +343,7 @@ local function ConstructSizer(frame) texB:Hide() end - local left = CreateFrame("FRAME", nil, frame) + local left = CreateFrame("Frame", nil, frame) left:EnableMouse() left:SetWidth(8) left:SetPoint("TOPLEFT", topleft, "BOTTOMLEFT") @@ -417,7 +417,7 @@ local function BuildAlignLines(mover) end local function ConstructMoverSizer(parent) - local frame = CreateFrame("FRAME", nil, parent) + local frame = CreateFrame("Frame", nil, parent) frame:SetBackdrop({ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 12, @@ -439,7 +439,7 @@ local function ConstructMoverSizer(parent) frame.left.Clear() frame.topleft.Clear() - local mover = CreateFrame("FRAME", nil, frame) + local mover = CreateFrame("Frame", nil, frame) mover:RegisterEvent("PLAYER_REGEN_DISABLED") mover:EnableMouse() mover.moving = {} diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index 1bb0e19..37dffad 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs @@ -44,7 +44,7 @@ local function CreateFrameSizer(frame, callback, position) xOffset2, yOffset2 = -1, -1 end - local handle = CreateFrame("BUTTON", nil, frame) + local handle = CreateFrame("Button", nil, frame) handle:SetPoint(position, frame) handle:SetSize(25, 25) handle:EnableMouse() @@ -88,7 +88,7 @@ local minWidth = 750 local minHeight = 240 function OptionsPrivate.CreateFrame() - CreateFrame("frame", "WeakAuras_DropDownMenu", nil, "UIDropDownMenuTemplate") + CreateFrame("Frame", "WeakAuras_DropDownMenu", nil, "UIDropDownMenuTemplate") local frame local db = OptionsPrivate.savedVars.db local odb = OptionsPrivate.savedVars.odb @@ -367,7 +367,7 @@ function OptionsPrivate.CreateFrame() tipPopupLabel:SetJustifyH("LEFT") tipPopupLabel:SetJustifyV("TOP") - local urlWidget = CreateFrame("EDITBOX", nil, tipPopup, "WA_InputBoxTemplate") + local urlWidget = CreateFrame("EditBox", nil, tipPopup, "WA_InputBoxTemplate") urlWidget:SetFont(STANDARD_TEXT_FONT, 12) urlWidget:SetPoint("TOPLEFT", tipPopupLabel, "BOTTOMLEFT", 6, 0) urlWidget:SetPoint("TOPRIGHT", tipPopupLabel, "BOTTOMRIGHT", 0, 0) @@ -490,7 +490,7 @@ function OptionsPrivate.CreateFrame() frame.moversizer, frame.mover = OptionsPrivate.MoverSizer(frame) -- filter line - local filterInput = CreateFrame("editbox", "WeakAurasFilterInput", frame, "WA_InputBoxTemplate") + local filterInput = CreateFrame("EditBox", "WeakAurasFilterInput", frame, "WA_InputBoxTemplate") filterInput:SetAutoFocus(false) filterInput:SetTextInsets(16, 20, 0, 0) diff --git a/WeakAurasOptions/OptionsFrames/TextEditor.lua b/WeakAurasOptions/OptionsFrames/TextEditor.lua index 1b340d7..41aa503 100644 --- a/WeakAurasOptions/OptionsFrames/TextEditor.lua +++ b/WeakAurasOptions/OptionsFrames/TextEditor.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/TexturePicker.lua b/WeakAurasOptions/OptionsFrames/TexturePicker.lua index 4dfad2f..5c7afb4 100644 --- a/WeakAurasOptions/OptionsFrames/TexturePicker.lua +++ b/WeakAurasOptions/OptionsFrames/TexturePicker.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index c6352a7..f36a709 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local AceGUI = LibStub("AceGUI-3.0") diff --git a/WeakAurasOptions/RegionOptions/AuraBar.lua b/WeakAurasOptions/RegionOptions/AuraBar.lua index 99be9f3..76eb233 100644 --- a/WeakAurasOptions/RegionOptions/AuraBar.lua +++ b/WeakAurasOptions/RegionOptions/AuraBar.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -457,7 +457,7 @@ end -- Create preview thumbnail local function createThumbnail() -- Preview frame - local borderframe = CreateFrame("FRAME", nil, UIParent); + local borderframe = CreateFrame("Frame", nil, UIParent); borderframe:SetWidth(32); borderframe:SetHeight(32); @@ -468,13 +468,13 @@ local function createThumbnail() border:SetTexCoord(0.2, 0.8, 0.2, 0.8); -- Main region - local region = CreateFrame("FRAME", nil, borderframe); + local region = CreateFrame("Frame", nil, borderframe); borderframe.region = region; region:SetWidth(32); region:SetHeight(32); -- Status-bar frame - local bar = CreateFrame("FRAME", nil, region); + local bar = CreateFrame("Frame", nil, region); borderframe.bar = bar; -- Fake status-bar diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 25cbe97..8f5d804 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L @@ -463,7 +463,7 @@ end local function createThumbnail() -- frame - local thumbnail = CreateFrame("FRAME", nil, UIParent); + local thumbnail = CreateFrame("Frame", nil, UIParent); thumbnail:SetWidth(32); thumbnail:SetHeight(32); @@ -494,7 +494,7 @@ local function defaultIconAnimation(self, elapsed) end local function createAnimatedDefaultIcon(parent) - local defaultIcon = CreateFrame("FRAME", nil, parent); + local defaultIcon = CreateFrame("Frame", nil, parent); parent.defaultIcon = defaultIcon; local t1 = defaultIcon:CreateTexture(nil, "ARTWORK"); diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index 38a5374..fa0051e 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; @@ -629,7 +629,7 @@ end local function createThumbnail() -- frame - local thumbnail = CreateFrame("FRAME", nil, UIParent); + local thumbnail = CreateFrame("Frame", nil, UIParent); thumbnail:SetWidth(32); thumbnail:SetHeight(32); @@ -648,7 +648,7 @@ end local function createDefaultIcon(parent) -- default Icon - local defaultIcon = CreateFrame("FRAME", nil, parent); + local defaultIcon = CreateFrame("Frame", nil, parent); parent.defaultIcon = defaultIcon; local t1 = defaultIcon:CreateTexture(nil, "ARTWORK"); diff --git a/WeakAurasOptions/RegionOptions/Icon.lua b/WeakAurasOptions/RegionOptions/Icon.lua index 5bdccac..b278530 100644 --- a/WeakAurasOptions/RegionOptions/Icon.lua +++ b/WeakAurasOptions/RegionOptions/Icon.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local Masque = LibStub("Masque", true) @@ -231,7 +231,7 @@ local function createOptions(id, data) end local function createThumbnail() - local frame = CreateFrame("FRAME", nil, UIParent) + local frame = CreateFrame("Frame", nil, UIParent) local icon = frame:CreateTexture(); icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark"); icon:SetAllPoints(frame) diff --git a/WeakAurasOptions/RegionOptions/Model.lua b/WeakAurasOptions/RegionOptions/Model.lua index 177404f..f3df260 100644 --- a/WeakAurasOptions/RegionOptions/Model.lua +++ b/WeakAurasOptions/RegionOptions/Model.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; @@ -128,7 +128,7 @@ local function createOptions(id, data) end local function createThumbnail() - local borderframe = CreateFrame("FRAME", nil, UIParent); + local borderframe = CreateFrame("Frame", nil, UIParent); borderframe:SetWidth(32); borderframe:SetHeight(32); diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index ea72c81..c1981c7 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; @@ -401,7 +401,7 @@ local function Transform(tx, x, y, angle, aspect) -- Translates texture to x, y end local function createThumbnail() - local borderframe = CreateFrame("FRAME", nil, UIParent); + local borderframe = CreateFrame("Frame", nil, UIParent); borderframe:SetWidth(32); borderframe:SetHeight(32); @@ -410,7 +410,7 @@ local function createThumbnail() border:SetTexture("Interface\\BUTTONS\\UI-Quickslot2.blp"); border:SetTexCoord(0.2, 0.8, 0.2, 0.8); - local region = CreateFrame("FRAME", nil, borderframe); + local region = CreateFrame("Frame", nil, borderframe); borderframe.region = region; region:SetWidth(32); region:SetHeight(32); diff --git a/WeakAurasOptions/RegionOptions/StopMotion.lua b/WeakAurasOptions/RegionOptions/StopMotion.lua index 4588872..f972dc1 100644 --- a/WeakAurasOptions/RegionOptions/StopMotion.lua +++ b/WeakAurasOptions/RegionOptions/StopMotion.lua @@ -546,7 +546,7 @@ local function createOptions(id, data) end local function createThumbnail() - local borderframe = CreateFrame("FRAME", nil, UIParent); + local borderframe = CreateFrame("Frame", nil, UIParent); borderframe:SetWidth(32); borderframe:SetHeight(32); diff --git a/WeakAurasOptions/RegionOptions/Text.lua b/WeakAurasOptions/RegionOptions/Text.lua index 01372e6..d503512 100644 --- a/WeakAurasOptions/RegionOptions/Text.lua +++ b/WeakAurasOptions/RegionOptions/Text.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); @@ -321,7 +321,7 @@ local function createOptions(id, data) end local function createThumbnail() - local borderframe = CreateFrame("FRAME", nil, UIParent); + local borderframe = CreateFrame("Frame", nil, UIParent); borderframe:SetWidth(32); borderframe:SetHeight(32); diff --git a/WeakAurasOptions/RegionOptions/Texture.lua b/WeakAurasOptions/RegionOptions/Texture.lua index 6eb03a0..715d7a5 100644 --- a/WeakAurasOptions/RegionOptions/Texture.lua +++ b/WeakAurasOptions/RegionOptions/Texture.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L @@ -121,7 +121,7 @@ local function createOptions(id, data) end local function createThumbnail() - local borderframe = CreateFrame("FRAME", nil, UIParent); + local borderframe = CreateFrame("Frame", nil, UIParent); borderframe:SetWidth(32); borderframe:SetHeight(32); diff --git a/WeakAurasOptions/SubRegionOptions/Background.lua b/WeakAurasOptions/SubRegionOptions/Background.lua index e248125..da1f34f 100644 --- a/WeakAurasOptions/SubRegionOptions/Background.lua +++ b/WeakAurasOptions/SubRegionOptions/Background.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/SubRegionOptions/Border.lua b/WeakAurasOptions/SubRegionOptions/Border.lua index 4647a3c..d1783c6 100644 --- a/WeakAurasOptions/SubRegionOptions/Border.lua +++ b/WeakAurasOptions/SubRegionOptions/Border.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAurasOptions/SubRegionOptions/Glow.lua b/WeakAurasOptions/SubRegionOptions/Glow.lua index 1327ecf..d25e890 100644 --- a/WeakAurasOptions/SubRegionOptions/Glow.lua +++ b/WeakAurasOptions/SubRegionOptions/Glow.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAurasOptions/SubRegionOptions/Model.lua b/WeakAurasOptions/SubRegionOptions/Model.lua index 0d3bb75..b267e09 100644 --- a/WeakAurasOptions/SubRegionOptions/Model.lua +++ b/WeakAurasOptions/SubRegionOptions/Model.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua b/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua index 170e41e..24fb49b 100644 --- a/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua +++ b/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Magic constant diff --git a/WeakAurasOptions/SubRegionOptions/SubText.lua b/WeakAurasOptions/SubRegionOptions/SubText.lua index e50f748..aff9b13 100644 --- a/WeakAurasOptions/SubRegionOptions/SubText.lua +++ b/WeakAurasOptions/SubRegionOptions/SubText.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0") diff --git a/WeakAurasOptions/SubRegionOptions/Tick.lua b/WeakAurasOptions/SubRegionOptions/Tick.lua index 229b69b..b6424aa 100644 --- a/WeakAurasOptions/SubRegionOptions/Tick.lua +++ b/WeakAurasOptions/SubRegionOptions/Tick.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAurasOptions/TriggerOptions.lua b/WeakAurasOptions/TriggerOptions.lua index 1c9cccc..3c90fab 100644 --- a/WeakAurasOptions/TriggerOptions.lua +++ b/WeakAurasOptions/TriggerOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index a8e7c74..75b6167 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() then return end +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs @@ -181,7 +181,7 @@ local frame; local db; local odb; local reopenAfterCombat = false; -local loadedFrame = CreateFrame("FRAME"); +local loadedFrame = CreateFrame("Frame"); loadedFrame:RegisterEvent("ADDON_LOADED"); loadedFrame:RegisterEvent("PLAYER_REGEN_ENABLED"); loadedFrame:RegisterEvent("PLAYER_REGEN_DISABLED"); From 40dcae7bcf1cdce42529ed34248fea83c2d25a4b Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 5 Jan 2025 16:59:33 +0100 Subject: [PATCH 002/153] from retail --- WeakAuras/Conditions.lua | 5 +-- WeakAuras/GenericTrigger.lua | 2 +- WeakAuras/Prototypes.lua | 5 +-- WeakAuras/RegionTypes/Icon.lua | 1 - WeakAuras/RegionTypes/StopMotion.lua | 2 - WeakAuras/RegionTypes/Texture.lua | 3 -- WeakAuras/SubRegionTypes/Glow.lua | 1 - WeakAuras/SubRegionTypes/Model.lua | 1 - WeakAuras/SubRegionTypes/Tick.lua | 3 +- WeakAuras/Transmission.lua | 4 -- WeakAuras/WeakAuras.lua | 42 ++++++++----------- .../AceGUIWidget-WeakAurasDisplayButton.lua | 6 +-- .../AceGUIWidget-WeakAurasExpand.lua | 2 +- .../AceGUIWidget-WeakAurasExpandSmall.lua | 2 +- ...UIWidget-WeakAurasPendingInstallButton.lua | 1 - WeakAurasOptions/ConditionOptions.lua | 18 +------- WeakAurasOptions/GenericTrigger.lua | 5 +-- .../OptionsFrames/FrameChooser.lua | 4 +- WeakAurasOptions/OptionsFrames/IconPicker.lua | 4 -- .../OptionsFrames/ImportExport.lua | 5 +-- .../OptionsFrames/ModelPicker.lua | 1 - WeakAurasOptions/OptionsFrames/MoverSizer.lua | 2 - .../OptionsFrames/OptionsFrame.lua | 4 +- .../OptionsFrames/TexturePicker.lua | 1 - WeakAurasOptions/RegionOptions/AuraBar.lua | 4 +- .../RegionOptions/DynamicGroup.lua | 2 +- WeakAurasOptions/RegionOptions/Group.lua | 8 ++-- WeakAurasOptions/RegionOptions/Model.lua | 4 +- .../RegionOptions/ProgressTexture.lua | 2 +- WeakAurasOptions/RegionOptions/StopMotion.lua | 2 +- WeakAurasOptions/RegionOptions/Text.lua | 6 +-- WeakAurasOptions/RegionOptions/Texture.lua | 2 +- .../SubRegionOptions/Background.lua | 2 - WeakAurasOptions/SubRegionOptions/Border.lua | 3 -- WeakAurasOptions/SubRegionOptions/Glow.lua | 5 --- WeakAurasOptions/SubRegionOptions/Model.lua | 1 - WeakAurasOptions/SubRegionOptions/SubText.lua | 1 - WeakAurasOptions/SubRegionOptions/Tick.lua | 3 -- WeakAurasOptions/TriggerOptions.lua | 1 - WeakAurasOptions/WeakAurasOptions.lua | 4 +- 40 files changed, 54 insertions(+), 120 deletions(-) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index bfd96f2..fa88394 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -17,7 +17,7 @@ local conditionChecksTimers = {}; conditionChecksTimers.recheckTime = {}; conditionChecksTimers.recheckHandle = {}; -local function OnDelete(event, uid) +local function OnDelete(_, uid) checkConditions[uid] = nil conditionChecksTimers.recheckTime[uid] = nil if (conditionChecksTimers.recheckHandle[uid]) then @@ -27,7 +27,7 @@ local function OnDelete(event, uid) end conditionChecksTimers.recheckHandle[uid] = nil - for event, funcs in pairs(dynamicConditions) do + for _, funcs in pairs(dynamicConditions) do funcs[uid] = nil end end @@ -616,7 +616,6 @@ local function ConstructConditionFunction(data) ret = ret .. " local recheckTime;\n" ret = ret .. " local now = GetTime();\n" - local normalConditionCount = data.conditions and #data.conditions; -- First Loop gather which conditions are active ret = ret .. " if (not hideRegion) then\n" local recheckCode = "" diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 8a26d98..7d69fa0 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1459,7 +1459,7 @@ function GenericTrigger.Add(data, region) if (trigger.custom_type == "stateupdate") then tsuConditionVariables = WeakAuras.LoadFunction("return function() return \n" .. (trigger.customVariables or "") .. "\n end"); if not tsuConditionVariables then - tsuConditionVariables = function() return end + tsuConditionVariables = function() end end end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 3fa8e8b..bab65b4 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -9,11 +9,10 @@ local ceil, min = ceil, min -- WoW APIs local GetTalentInfo = GetTalentInfo -local UnitClass, UnitHealth, UnitHealthMax, UnitName, UnitPower, UnitPowerMax = UnitClass, UnitHealth, UnitHealthMax, UnitName, UnitPower, UnitPowerMax +local UnitClass = UnitClass local GetSpellInfo, GetItemInfo, GetItemCount, GetItemIcon = GetSpellInfo, GetItemInfo, GetItemCount, GetItemIcon local GetShapeshiftFormInfo, GetShapeshiftForm = GetShapeshiftFormInfo, GetShapeshiftForm -local GetRuneCooldown, UnitCastingInfo, UnitChannelInfo = GetRuneCooldown, UnitCastingInfo, UnitChannelInfo -local UnitDetailedThreatSituation, UnitThreatSituation = UnitDetailedThreatSituation, UnitThreatSituation +local UnitDetailedThreatSituation = UnitDetailedThreatSituation local WeakAuras = WeakAuras local L = WeakAuras.L diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index b3306ce..ea071cb 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -1,7 +1,6 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -local SharedMedia = LibStub("LibSharedMedia-3.0"); local L = WeakAuras.L local MSQ, MSQ_Version = LibStub("Masque", true); if MSQ then diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index 81a68f2..f598a3b 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -1,9 +1,7 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -local texture_types = WeakAuras.StopMotion.texture_types; local texture_data = WeakAuras.StopMotion.texture_data; -local animation_types = WeakAuras.StopMotion.animation_types; local L = WeakAuras.L; local default = { diff --git a/WeakAuras/RegionTypes/Texture.lua b/WeakAuras/RegionTypes/Texture.lua index cf5fbad..aa6f1ad 100644 --- a/WeakAuras/RegionTypes/Texture.lua +++ b/WeakAuras/RegionTypes/Texture.lua @@ -3,9 +3,6 @@ local AddonName, Private = ... local L = WeakAuras.L; -local root2 = math.sqrt(2); -local halfroot2 = root2/2; - local default = { texture = "Interface\\Addons\\WeakAuras\\PowerAurasMedia\\Auras\\Aura3", desaturate = false, diff --git a/WeakAuras/SubRegionTypes/Glow.lua b/WeakAuras/SubRegionTypes/Glow.lua index 922ea1f..4592fa3 100644 --- a/WeakAuras/SubRegionTypes/Glow.lua +++ b/WeakAuras/SubRegionTypes/Glow.lua @@ -1,7 +1,6 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -local SharedMedia = LibStub("LibSharedMedia-3.0"); local LCG = LibStub("LibCustomGlow-1.0") local MSQ, MSQ_Version = LibStub("Masque", true); if MSQ then diff --git a/WeakAuras/SubRegionTypes/Model.lua b/WeakAuras/SubRegionTypes/Model.lua index 77dc88a..211e32b 100644 --- a/WeakAuras/SubRegionTypes/Model.lua +++ b/WeakAuras/SubRegionTypes/Model.lua @@ -1,7 +1,6 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -local SharedMedia = LibStub("LibSharedMedia-3.0"); local L = WeakAuras.L; Private.barmodels = {} diff --git a/WeakAuras/SubRegionTypes/Tick.lua b/WeakAuras/SubRegionTypes/Tick.lua index 772435e..c9f567a 100644 --- a/WeakAuras/SubRegionTypes/Tick.lua +++ b/WeakAuras/SubRegionTypes/Tick.lua @@ -1,10 +1,9 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -local SharedMedia = LibStub("LibSharedMedia-3.0"); local L = WeakAuras.L; -local default = function(parentType) +local default = function() return { tick_visible = true, tick_color = {1, 1, 1, 1}, diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 77210f7..3094c18 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -27,16 +27,12 @@ local tostring, string_char, strsplit = tostring, string.char, strsplit local pairs, type, unpack = pairs, type, unpack local error = error local bit_band, bit_lshift, bit_rshift = bit.band, bit.lshift, bit.rshift -local coroutine = coroutine local WeakAuras = WeakAuras; local L = WeakAuras.L; local versionString = WeakAuras.versionString; -local regionOptions = WeakAuras.regionOptions; -local regionTypes = WeakAuras.regionTypes; - -- Local functions local decodeB64, GenerateUniqueID local CompressDisplay, ShowTooltip, TableToString, StringToTable diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index a386550..a4d16b6 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -13,11 +13,11 @@ local UnitClass, UnitExists, UnitGUID, UnitAffectingCombat, GetInstanceInfo, IsI = UnitClass, UnitExists, UnitGUID, UnitAffectingCombat, GetInstanceInfo, IsInInstance local UnitIsUnit, GetRaidRosterInfo, UnitInVehicle, UnitHasVehicleUI, GetSpellInfo = UnitIsUnit, GetRaidRosterInfo, UnitInVehicle, UnitHasVehicleUI, GetSpellInfo -local SendChatMessage, GetChannelName, UnitInBattleground, UnitInRaid, UnitInParty, GetTime, GetSpellLink, GetItemInfo - = SendChatMessage, GetChannelName, UnitInBattleground, UnitInRaid, UnitInParty, GetTime, GetSpellLink, GetItemInfo +local SendChatMessage, UnitInBattleground, UnitInRaid, UnitInParty, GetTime + = SendChatMessage, UnitInBattleground, UnitInRaid, UnitInParty, GetTime local CreateFrame, IsShiftKeyDown, GetScreenWidth, GetScreenHeight, GetCursorPosition, UpdateAddOnCPUUsage, GetFrameCPUUsage, debugprofilestop = CreateFrame, IsShiftKeyDown, GetScreenWidth, GetScreenHeight, GetCursorPosition, UpdateAddOnCPUUsage, GetFrameCPUUsage, debugprofilestop -local debugstack, IsSpellKnown = debugstack, IsSpellKnown +local debugstack = debugstack local ADDON_NAME = "WeakAuras" local WeakAuras = WeakAuras @@ -245,8 +245,6 @@ local fallbacksStates = {}; -- List of all trigger systems, contains each system once local triggerSystems = {} -local from_files = {}; - local timers = {}; -- Timers for autohiding, keyed on id, triggernum, cloneid WeakAuras.timers = timers; @@ -1008,8 +1006,8 @@ do -- Archive stuff end function WeakAuras.LoadFromArchive(storeType, storeID) - local Archivist = OpenArchive() - return Archivist:Load(storeType, storeID) + local Archive = OpenArchive() + return Archive:Load(storeType, storeID) end end @@ -1505,7 +1503,7 @@ local function UnloadAll() Private.CancelAnimation(WeakAuras.regions[id].region, true, true, true, true, true, true) end if clones[id] then - for cloneId, region in pairs(clones[id]) do + for _, region in pairs(clones[id]) do Private.CancelAnimation(region, true, true, true, true, true, true) end end @@ -1667,7 +1665,7 @@ function WeakAuras.Delete(data) UIDtoID[data.uid] = nil if(data.controlledChildren) then - for index, childId in pairs(data.controlledChildren) do + for _, childId in pairs(data.controlledChildren) do local childData = db.displays[childId]; if(childData) then childData.parent = nil; @@ -1684,7 +1682,7 @@ function WeakAuras.Delete(data) end if clones[id] then - for cloneId, region in pairs(clones[id]) do + for _, region in pairs(clones[id]) do region:Collapse(); Private.CancelAnimation(region, true, true, true, true, true, true) end @@ -1857,9 +1855,9 @@ function Private.Convert(data, newType) tremove(data.subRegions, index) -- Adjust conditions! if data.conditions then - for conditionIndex, condition in ipairs(data.conditions) do + for _, condition in ipairs(data.conditions) do if type(condition.changes) == "table" then - for changeIndex, change in ipairs(condition.changes) do + for _, change in ipairs(condition.changes) do if change.property then local subRegionIndex, property = change.property:match("^sub%.(%d+)%.(.*)") subRegionIndex = tonumber(subRegionIndex) @@ -2493,7 +2491,7 @@ function WeakAuras.PreAdd(data) Private.Modernize(data); WeakAuras.validate(data, WeakAuras.data_stub); if data.subRegions then - for index, subRegionData in ipairs(data.subRegions) do + for _, subRegionData in ipairs(data.subRegions) do local subType = subRegionData.type if subType and Private.subRegionTypes[subType] then if Private.subRegionTypes[subType].supports(data.regionType) then @@ -2874,7 +2872,7 @@ end function Private.SetAllStatesHidden(id, triggernum) local triggerState = WeakAuras.GetTriggerStateForTrigger(id, triggernum); local changed = false - for id, state in pairs(triggerState) do + for _, state in pairs(triggerState) do changed = changed or state.show state.show = false; state.changed = true; @@ -3078,7 +3076,6 @@ function Private.HandleGlowAction(actions, region) ) then local glow_frame - local original_glow_frame if actions.glow_frame_type == "FRAMESELECTOR" then if actions.glow_frame:sub(1, 10) == "WeakAuras:" then local frame_name = actions.glow_frame:sub(11) @@ -3537,7 +3534,6 @@ end function Private.ApplyFrameLevel(region, frameLevel) frameLevel = frameLevel or GetFrameLevelFor(region.id) - local subforegroundIndex = 0 if region.subRegions then for index, subRegion in pairs(region.subRegions) do if subRegion.type == "subbackground" then @@ -3714,7 +3710,7 @@ do visibleFakeStates[id] = false if triggerState[id] then local changed = false - for triggernum, state in ipairs(triggerState[id]) do + for triggernum in ipairs(triggerState[id]) do changed = Private.SetAllStatesHidden(id, triggernum) or changed end if changed then @@ -3729,7 +3725,7 @@ do if (WeakAuras.IsOptionsOpen() and visibleFakeStates[id]) then local data = WeakAuras.GetData(id) if (data) then - for triggernum, trigger in ipairs(data.triggers) do + for triggernum in ipairs(data.triggers) do Private.SetAllStatesHidden(id, triggernum) local triggerSystem = GetTriggerSystem(data, triggernum) if triggerSystem and triggerSystem.CreateFakeStates then @@ -3853,7 +3849,7 @@ local function evaluateTriggerStateTriggers(id) end end - Private.ActivateAuraEnvironment(nil); + Private.ActivateAuraEnvironment(); return result; end @@ -3981,7 +3977,7 @@ function Private.UpdatedTriggerState(id) end elseif (show) then local needsFallback = true; - for cloneId, state in pairs(activeTriggerState) do + for _, state in pairs(activeTriggerState) do if (state.show) then needsFallback = false; break; @@ -3998,7 +3994,7 @@ function Private.UpdatedTriggerState(id) if (show and not oldShow) then -- Hide => Show ApplyStatesToRegions(id, newActiveTrigger, activeTriggerState); elseif (not show and oldShow) then -- Show => Hide - for cloneId, clone in pairs(clones[id]) do + for _, clone in pairs(clones[id]) do clone:Collapse() end if WeakAuras.regions[id] then @@ -4075,7 +4071,6 @@ function Private.RunCustomTextFunc(region, customFunc) end local function ReplaceValuePlaceHolders(textStr, region, customFunc, state, formatter) - local regionValues = region.values; local value; if string.sub(textStr, 1, 1) == "c" then local custom @@ -4386,7 +4381,7 @@ function Private.CreateFormatters(input, getter, withoutColor) local formatters = {} Private.ParseTextStr(input, function(symbol) if not seenSymbols[symbol] then - local triggerNum, sym = string.match(symbol, "(.+)%.(.+)") + local _, sym = string.match(symbol, "(.+)%.(.+)") sym = sym or symbol if sym == "i" then -- Do nothing @@ -5107,7 +5102,6 @@ function WeakAuras.ParseNameCheck(name) -- state: 2: In Realm -- state: -1: Escape Name -- state: -2: In Escape Realm - local index = 1 local state = 1 local name = "" local realm = "" diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index 57da6ef..72ba348 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -1,9 +1,9 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -local tinsert, tconcat, tremove, wipe = table.insert, table.concat, table.remove, wipe -local select, pairs, next, type, unpack = select, pairs, next, type, unpack -local tostring, error = tostring, error +local tinsert, tremove, wipe = table.insert, table.remove, wipe +local select, pairs, type, unpack = select, pairs, type, unpack +local error = error local Type, Version = "WeakAurasDisplayButton", 59 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua index 9d96e9a..3fee718 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua @@ -9,7 +9,7 @@ local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end -- Lua APIs -local select, pairs, print = select, pairs, print +local select, pairs = select, pairs -- WoW APIs local CreateFrame, UIParent = CreateFrame, UIParent diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua index d7a2ca8..1e7dd7f 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua @@ -10,7 +10,7 @@ local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end -- Lua APIs -local select, pairs, print = select, pairs, print +local select, pairs = select, pairs -- WoW APIs local CreateFrame, UIParent = CreateFrame, UIParent diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua index 40b0555..efc06b5 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua @@ -3,7 +3,6 @@ if not WeakAuras.IsCorrectVersion() then end local AddonName, OptionsPrivate = ... -local L = WeakAuras.L local pairs, next, type, unpack = pairs, next, type, unpack diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 596360b..0d0abd8 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -50,8 +50,6 @@ local AddonName, OptionsPrivate = ... local WeakAuras = WeakAuras; local L = WeakAuras.L; -local debug = false; - local function addSpace(args, order) args["space" .. order] = { type = "description", @@ -64,18 +62,6 @@ local function addSpace(args, order) return order; end -local function addHalfSpace(args, order) - args["space" .. order] = { - type = "description", - name = "", - image = function() return "", 0, 0 end, - order = order, - width = WeakAuras.halfWidth - } - order = order + 1; - return order; -end - local function compareValues(a, b, propertytype) if (propertytype == "color") then if (type(a) ~= "table" or type(b) ~= "table") then @@ -768,7 +754,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA args["condition" .. i .. "value" .. j] = { type = "toggle", width = WeakAuras.normalWidth, - name = blueIfNoValue(data, conditions[i].changes[j], "value", "message_dest_isunit", L["Is Unit"], L["Is Unit"]), + name = blueIfNoValue(data, conditions[i].changes[j], "value", "message_dest_isunit", L["Is Unit"]), desc = descIfNoValue(data, conditions[i].changes[j], "value", "message_dest_isunit", propertyType), order = order, get = function() @@ -792,7 +778,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA desc = descMessage, order = order, get = message_getter, - set = setValueComplex("message", true) + set = setValueComplex("message") } order = order + 1; diff --git a/WeakAurasOptions/GenericTrigger.lua b/WeakAurasOptions/GenericTrigger.lua index 32b72d3..a6b4c71 100644 --- a/WeakAurasOptions/GenericTrigger.lua +++ b/WeakAurasOptions/GenericTrigger.lua @@ -318,7 +318,6 @@ local function GetCustomTriggerOptions(data, triggernum) test = "function", events = "table", values = "table", - display = "string" } local function validateCustomVariables(variables) @@ -491,10 +490,10 @@ local function GetGenericTriggerOptions(data, triggernum) } if (triggerType == "custom") then - WeakAuras.Mixin(options, GetCustomTriggerOptions(data, triggernum, trigger)); + WeakAuras.Mixin(options, GetCustomTriggerOptions(data, triggernum)); elseif (OptionsPrivate.Private.category_event_prototype[triggerType]) then local prototypeOptions; - local trigger, untrigger = data.triggers[triggernum].trigger, data.triggers[triggernum].untrigger; + local trigger = data.triggers[triggernum].trigger if(OptionsPrivate.Private.event_prototypes[trigger.event]) then prototypeOptions = OptionsPrivate.ConstructOptions(OptionsPrivate.Private.event_prototypes[trigger.event], data, 10, triggernum); if (trigger.event == "Combat Log") then diff --git a/WeakAurasOptions/OptionsFrames/FrameChooser.lua b/WeakAurasOptions/OptionsFrames/FrameChooser.lua index 2281812..ec95374 100644 --- a/WeakAurasOptions/OptionsFrames/FrameChooser.lua +++ b/WeakAurasOptions/OptionsFrames/FrameChooser.lua @@ -6,9 +6,7 @@ local pairs = pairs -- WoW APIs local CreateFrame, IsMouseButtonDown, SetCursor, GetMouseFocus, MouseIsOver, ResetCursor - = CreateFrame, IsMouseButtonDown, SetCursor, GetMouseFocus, MouseIsOver, ResetCursor - -local AceConfigDialog = LibStub("AceConfigDialog-3.0") += CreateFrame, IsMouseButtonDown, SetCursor, GetMouseFocus, MouseIsOver, ResetCursor local WeakAuras = WeakAuras local L = WeakAuras.L diff --git a/WeakAurasOptions/OptionsFrames/IconPicker.lua b/WeakAurasOptions/OptionsFrames/IconPicker.lua index 0d06f02..607d7b1 100644 --- a/WeakAurasOptions/OptionsFrames/IconPicker.lua +++ b/WeakAurasOptions/OptionsFrames/IconPicker.lua @@ -8,7 +8,6 @@ local pairs = pairs local CreateFrame, GetSpellInfo = CreateFrame, GetSpellInfo local AceGUI = LibStub("AceGUI-3.0") -local AceConfigDialog = LibStub("AceConfigDialog-3.0") local WeakAuras = WeakAuras local L = WeakAuras.L @@ -33,9 +32,6 @@ local function ConstructIconPicker(frame) local function iconPickerFill(subname, doSort) scroll:ReleaseChildren(); - local distances = {}; - local names = {}; - -- Work around special numbers such as inf and nan if (tonumber(subname)) then local spellId = tonumber(subname); diff --git a/WeakAurasOptions/OptionsFrames/ImportExport.lua b/WeakAurasOptions/OptionsFrames/ImportExport.lua index 85b5fd1..56b7424 100644 --- a/WeakAurasOptions/OptionsFrames/ImportExport.lua +++ b/WeakAurasOptions/OptionsFrames/ImportExport.lua @@ -1,11 +1,8 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... --- Lua APIs -local strtrim, strsub = strtrim, strsub - -- WoW APIs -local GetTime, CreateFrame = GetTime, CreateFrame +local CreateFrame = CreateFrame local AceGUI = LibStub("AceGUI-3.0") diff --git a/WeakAurasOptions/OptionsFrames/ModelPicker.lua b/WeakAurasOptions/OptionsFrames/ModelPicker.lua index 0df16d8..0083ca7 100644 --- a/WeakAurasOptions/OptionsFrames/ModelPicker.lua +++ b/WeakAurasOptions/OptionsFrames/ModelPicker.lua @@ -8,7 +8,6 @@ local rad = rad local CreateFrame = CreateFrame local AceGUI = LibStub("AceGUI-3.0") -local AceConfigDialog = LibStub("AceConfigDialog-3.0") local WeakAuras = WeakAuras local L = WeakAuras.L diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index ff2f885..af38d34 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -7,8 +7,6 @@ local pairs = pairs -- WoW APIs local IsShiftKeyDown, CreateFrame = IsShiftKeyDown, CreateFrame -local AceConfigDialog = LibStub("AceConfigDialog-3.0") - local WeakAuras = WeakAuras local L = WeakAuras.L diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index 37dffad..d513dcc 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -7,8 +7,8 @@ local pairs, type, error = pairs, type, error local _G = _G -- WoW APIs -local GetScreenWidth, GetScreenHeight, CreateFrame, GetAddOnInfo, PlaySound, IsAddOnLoaded, LoadAddOn, UnitName - = GetScreenWidth, GetScreenHeight, CreateFrame, GetAddOnInfo, PlaySound, IsAddOnLoaded, LoadAddOn, UnitName +local GetScreenWidth, GetScreenHeight, CreateFrame, GetAddOnInfo, UnitName + = GetScreenWidth, GetScreenHeight, CreateFrame, GetAddOnInfo, UnitName local AceGUI = LibStub("AceGUI-3.0") local AceConfigDialog = LibStub("AceConfigDialog-3.0") diff --git a/WeakAurasOptions/OptionsFrames/TexturePicker.lua b/WeakAurasOptions/OptionsFrames/TexturePicker.lua index 5c7afb4..ba5452b 100644 --- a/WeakAurasOptions/OptionsFrames/TexturePicker.lua +++ b/WeakAurasOptions/OptionsFrames/TexturePicker.lua @@ -9,7 +9,6 @@ local pairs, next, type = pairs, next, type local CreateFrame = CreateFrame local AceGUI = LibStub("AceGUI-3.0") -local AceConfigDialog = LibStub("AceConfigDialog-3.0") local WeakAuras = WeakAuras local L = WeakAuras.L diff --git a/WeakAurasOptions/RegionOptions/AuraBar.lua b/WeakAurasOptions/RegionOptions/AuraBar.lua index 76eb233..a3dc351 100644 --- a/WeakAurasOptions/RegionOptions/AuraBar.lua +++ b/WeakAurasOptions/RegionOptions/AuraBar.lua @@ -611,7 +611,7 @@ local function modifyThumbnail(parent, borderframe, data, fullModify, width, hei end if data then - local name, icon = WeakAuras.GetNameAndIcon(data) + local _, icon = WeakAuras.GetNameAndIcon(data) borderframe:SetIcon(icon) end @@ -635,7 +635,7 @@ local function createIcon() }; -- Create and configure thumbnail - local thumbnail = createThumbnail(UIParent); + local thumbnail = createThumbnail(); modifyThumbnail(UIParent, thumbnail, data, nil, 32, 18); thumbnail:SetIcon("Interface\\Icons\\INV_Sword_62"); diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 8f5d804..9621fa8 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -557,7 +557,7 @@ local function modifyThumbnail(parent, frame, data) end local function createIcon() - local thumbnail = createThumbnail(UIParent) + local thumbnail = createThumbnail() thumbnail.defaultIcon = createAnimatedDefaultIcon(thumbnail) return thumbnail end diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index fa0051e..cc73a21 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -455,7 +455,7 @@ local function createDistributeAlignOptions(id, data) end local spaced; local previousData; - for index, childId in pairs(data.controlledChildren) do + for _, childId in pairs(data.controlledChildren) do local childData = WeakAuras.GetData(childId); if(childData) then local _, bottom, _, top = getRect(childData); @@ -672,7 +672,7 @@ end -- Modify preview thumbnail local function modifyThumbnail(parent, frame, data) - function frame:SetIcon(path) + function frame:SetIcon() if data.groupIcon then local success = frame.icon:SetTexture(data.groupIcon) if success then @@ -693,12 +693,12 @@ local function modifyThumbnail(parent, frame, data) frame.defaultIcon:Show() end - frame:SetIcon(nil) + frame:SetIcon() end -- Create "new region" preview local function createIcon() - local thumbnail = createThumbnail(UIParent) + local thumbnail = createThumbnail() thumbnail.defaultIcon = createDefaultIcon(thumbnail) return thumbnail end diff --git a/WeakAurasOptions/RegionOptions/Model.lua b/WeakAurasOptions/RegionOptions/Model.lua index f3df260..2e210b1 100644 --- a/WeakAurasOptions/RegionOptions/Model.lua +++ b/WeakAurasOptions/RegionOptions/Model.lua @@ -188,8 +188,8 @@ local function createIcon() width = 40 }; - local thumbnail = createThumbnail(UIParent); - modifyThumbnail(UIParent, thumbnail, data, nil, 50); + local thumbnail = createThumbnail(); + modifyThumbnail(UIParent, thumbnail, data); return thumbnail; end diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index c1981c7..25fe782 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -713,7 +713,7 @@ local function createIcon() backgroundColor = {0.5, 0.5, 0.5, 0.5} }; - local thumbnail = createThumbnail(UIParent); + local thumbnail = createThumbnail(); modifyThumbnail(UIParent, thumbnail, data, nil, 32); thumbnail.elapsed = 0; diff --git a/WeakAurasOptions/RegionOptions/StopMotion.lua b/WeakAurasOptions/RegionOptions/StopMotion.lua index f972dc1..8f0b5d8 100644 --- a/WeakAurasOptions/RegionOptions/StopMotion.lua +++ b/WeakAurasOptions/RegionOptions/StopMotion.lua @@ -689,7 +689,7 @@ local function createIcon() animationType = "progress" }; - local thumbnail = createThumbnail(UIParent); + local thumbnail = createThumbnail(); modifyThumbnail(UIParent, thumbnail, data, nil, 75); thumbnail.elapsed = 0; diff --git a/WeakAurasOptions/RegionOptions/Text.lua b/WeakAurasOptions/RegionOptions/Text.lua index d503512..faf0311 100644 --- a/WeakAurasOptions/RegionOptions/Text.lua +++ b/WeakAurasOptions/RegionOptions/Text.lua @@ -4,7 +4,7 @@ local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); local L = WeakAuras.L; -local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; +local screenWidth = math.ceil(GetScreenWidth() / 20) * 20 local indentWidth = 0.15 local hiddenFontExtra = function() @@ -294,7 +294,7 @@ local function createOptions(id, data) end local total, index = 0, 1 - for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + for _ in OptionsPrivate.Private.TraverseLeafsOrAura(data) do total = total + 1 end @@ -414,7 +414,7 @@ local function createIcon() displayText = "World\nof\nWarcraft"; }; - local thumbnail = createThumbnail(UIParent); + local thumbnail = createThumbnail(); modifyThumbnail(UIParent, thumbnail, data); thumbnail.mask:SetPoint("BOTTOMLEFT", thumbnail, "BOTTOMLEFT", 3, 3); thumbnail.mask:SetPoint("TOPRIGHT", thumbnail, "TOPRIGHT", -3, -3); diff --git a/WeakAurasOptions/RegionOptions/Texture.lua b/WeakAurasOptions/RegionOptions/Texture.lua index 715d7a5..e84616b 100644 --- a/WeakAurasOptions/RegionOptions/Texture.lua +++ b/WeakAurasOptions/RegionOptions/Texture.lua @@ -190,7 +190,7 @@ local function createIcon() rotation = 0; }; - local thumbnail = createThumbnail(UIParent); + local thumbnail = createThumbnail(); modifyThumbnail(UIParent, thumbnail, data, nil, 50); return thumbnail; diff --git a/WeakAurasOptions/SubRegionOptions/Background.lua b/WeakAurasOptions/SubRegionOptions/Background.lua index da1f34f..ec8ea5f 100644 --- a/WeakAurasOptions/SubRegionOptions/Background.lua +++ b/WeakAurasOptions/SubRegionOptions/Background.lua @@ -4,7 +4,6 @@ local L = WeakAuras.L; do local function subCreateOptions(parentData, data, index, subIndex) - local order = 9 local options = { __title = L["Background"], __order = 1, @@ -32,7 +31,6 @@ end do local function subCreateOptions(parentData, data, index, subIndex) - local order = 9 local options = { __title = L["Foreground"], __order = 1, diff --git a/WeakAurasOptions/SubRegionOptions/Border.lua b/WeakAurasOptions/SubRegionOptions/Border.lua index d1783c6..830d441 100644 --- a/WeakAurasOptions/SubRegionOptions/Border.lua +++ b/WeakAurasOptions/SubRegionOptions/Border.lua @@ -1,11 +1,8 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -local SharedMedia = LibStub("LibSharedMedia-3.0"); local L = WeakAuras.L; -local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; - local function createOptions(parentData, data, index, subIndex) local options = { __title = L["Border %s"]:format(subIndex), diff --git a/WeakAurasOptions/SubRegionOptions/Glow.lua b/WeakAurasOptions/SubRegionOptions/Glow.lua index d25e890..ce9bc01 100644 --- a/WeakAurasOptions/SubRegionOptions/Glow.lua +++ b/WeakAurasOptions/SubRegionOptions/Glow.lua @@ -1,15 +1,10 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -local SharedMedia = LibStub("LibSharedMedia-3.0"); local L = WeakAuras.L; -local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; - - local indentWidth = 0.15 - local function createOptions(parentData, data, index, subIndex) local hiddenGlowExtra = function() diff --git a/WeakAurasOptions/SubRegionOptions/Model.lua b/WeakAurasOptions/SubRegionOptions/Model.lua index b267e09..19a4a67 100644 --- a/WeakAurasOptions/SubRegionOptions/Model.lua +++ b/WeakAurasOptions/SubRegionOptions/Model.lua @@ -1,7 +1,6 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -local SharedMedia = LibStub("LibSharedMedia-3.0"); local L = WeakAuras.L; local function createOptions(parentData, data, index, subIndex) diff --git a/WeakAurasOptions/SubRegionOptions/SubText.lua b/WeakAurasOptions/SubRegionOptions/SubText.lua index aff9b13..e492dc7 100644 --- a/WeakAurasOptions/SubRegionOptions/SubText.lua +++ b/WeakAurasOptions/SubRegionOptions/SubText.lua @@ -1,7 +1,6 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -local SharedMedia = LibStub("LibSharedMedia-3.0") local L = WeakAuras.L local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20 diff --git a/WeakAurasOptions/SubRegionOptions/Tick.lua b/WeakAurasOptions/SubRegionOptions/Tick.lua index b6424aa..e6591f6 100644 --- a/WeakAurasOptions/SubRegionOptions/Tick.lua +++ b/WeakAurasOptions/SubRegionOptions/Tick.lua @@ -1,11 +1,8 @@ if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -local SharedMedia = LibStub("LibSharedMedia-3.0"); local L = WeakAuras.L; -local indentWidth = WeakAuras.normalWidth * 0.06 - local function createOptions(parentData, data, index, subIndex) local hiddentickextras = function() return OptionsPrivate.IsCollapsed("subtext", "subtext", "tickextras" .. index, true) diff --git a/WeakAurasOptions/TriggerOptions.lua b/WeakAurasOptions/TriggerOptions.lua index 3c90fab..c8b659e 100644 --- a/WeakAurasOptions/TriggerOptions.lua +++ b/WeakAurasOptions/TriggerOptions.lua @@ -29,7 +29,6 @@ end local function GetGlobalOptions(data) - local triggerCount = 0 local globalTriggerOptions = { __title = L["Trigger Combination"], __order = 1, diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 75b6167..648833a 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -3,8 +3,8 @@ local AddonName, OptionsPrivate = ... -- Lua APIs local tinsert, tremove, wipe = table.insert, table.remove, wipe -local pairs, type, unpack = pairs, type, unpack -local loadstring, error = loadstring, error +local pairs, type = pairs, type +local error = error local coroutine = coroutine local _G = _G From 13ab3350943909d7b674eb038118d5b2e3a41c34 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 5 Jan 2025 17:26:58 +0100 Subject: [PATCH 003/153] from retail --- WeakAuras/BuffTrigger2.lua | 44 +++++++++---------- WeakAurasOptions/AuthorOptions.lua | 34 +++++++------- WeakAurasOptions/BuffTrigger.lua | 14 ++---- WeakAurasOptions/BuffTrigger2.lua | 9 ++-- WeakAurasOptions/CommonOptions.lua | 5 +-- WeakAurasOptions/ConditionOptions.lua | 19 ++++---- WeakAurasOptions/GenericTrigger.lua | 7 ++- WeakAurasOptions/InformationOptions.lua | 2 +- .../OptionsFrames/ImportExport.lua | 2 +- WeakAurasOptions/OptionsFrames/MoverSizer.lua | 2 +- .../OptionsFrames/OptionsFrame.lua | 4 +- WeakAurasOptions/TriggerOptions.lua | 2 +- WeakAurasOptions/WeakAurasOptions.lua | 37 +++++----------- 13 files changed, 75 insertions(+), 106 deletions(-) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 4f3e8b7..f8633b5 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -1708,8 +1708,8 @@ local function RecheckActiveForUnitType(unitType, unit, unitsToRemoveScan) end end -local frame = CreateFrame("Frame") -WeakAuras.frames["WeakAuras Buff2 Frame"] = frame +local Buff2Frame = CreateFrame("Frame") +WeakAuras.frames["WeakAuras Buff2 Frame"] = Buff2Frame local function EventHandler(frame, event, arg1, arg2, ...) @@ -1802,29 +1802,29 @@ local function EventHandler(frame, event, arg1, arg2, ...) Private.StopProfileSystem("bufftrigger2") end -frame:RegisterEvent("UNIT_AURA") -frame:RegisterEvent("UNIT_FACTION") -frame:RegisterEvent("UNIT_NAME_UPDATE") -frame:RegisterEvent("UNIT_FLAGS") -frame:RegisterEvent("PLAYER_FLAGS_CHANGED") -frame:RegisterEvent("UNIT_PET") -frame:RegisterEvent("RAID_TARGET_UPDATE") -frame:RegisterEvent("PLAYER_FOCUS_CHANGED") -frame:RegisterEvent("ARENA_OPPONENT_UPDATE") -frame:RegisterEvent("UNIT_ENTERED_VEHICLE") -frame:RegisterEvent("UNIT_EXITED_VEHICLE") -frame:RegisterEvent("PLAYER_TARGET_CHANGED") -frame:RegisterEvent("PARTY_MEMBERS_CHANGED") -frame:RegisterEvent("RAID_ROSTER_UPDATE") -frame:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT") +Buff2Frame:RegisterEvent("UNIT_AURA") +Buff2Frame:RegisterEvent("UNIT_FACTION") +Buff2Frame:RegisterEvent("UNIT_NAME_UPDATE") +Buff2Frame:RegisterEvent("UNIT_FLAGS") +Buff2Frame:RegisterEvent("PLAYER_FLAGS_CHANGED") +Buff2Frame:RegisterEvent("UNIT_PET") +Buff2Frame:RegisterEvent("RAID_TARGET_UPDATE") +Buff2Frame:RegisterEvent("PLAYER_FOCUS_CHANGED") +Buff2Frame:RegisterEvent("ARENA_OPPONENT_UPDATE") +Buff2Frame:RegisterEvent("UNIT_ENTERED_VEHICLE") +Buff2Frame:RegisterEvent("UNIT_EXITED_VEHICLE") +Buff2Frame:RegisterEvent("PLAYER_TARGET_CHANGED") +Buff2Frame:RegisterEvent("PARTY_MEMBERS_CHANGED") +Buff2Frame:RegisterEvent("RAID_ROSTER_UPDATE") +Buff2Frame:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT") if WeakAuras.isAwesomeEnabled() then - frame:RegisterEvent("NAME_PLATE_UNIT_ADDED") - frame:RegisterEvent("NAME_PLATE_UNIT_REMOVED") + Buff2Frame:RegisterEvent("NAME_PLATE_UNIT_ADDED") + Buff2Frame:RegisterEvent("NAME_PLATE_UNIT_REMOVED") end -frame:RegisterEvent("PLAYER_ENTERING_WORLD") -frame:SetScript("OnEvent", EventHandler) +Buff2Frame:RegisterEvent("PLAYER_ENTERING_WORLD") +Buff2Frame:SetScript("OnEvent", EventHandler) -frame:SetScript("OnUpdate", function() +Buff2Frame:SetScript("OnUpdate", function() if WeakAuras.IsPaused() then return end diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index 301c405..fb86688 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -69,7 +69,7 @@ local conflictBlue = "|cFF4080FF" local conflict = {} -- magic value local function atLeastOneSet(references, key) - for id, optionData in pairs(references) do + for _, optionData in pairs(references) do local childOption = optionData.options[optionData.index] if childOption[key] ~= nil then return true @@ -138,7 +138,7 @@ local function nameUserDesc(option) return option.text else local text = {} - for id, optionData in pairs(option.references) do + for _, optionData in pairs(option.references) do local childOption = optionData.options[optionData.index] if childOption.text and childOption.text ~= nil then tinsert(text, childOption.text) @@ -288,7 +288,7 @@ end local function getUser(option) return function() local value - for id, optionData in pairs(option.references) do + for _, optionData in pairs(option.references) do if not optionData.config then return elseif value == nil then @@ -335,7 +335,7 @@ end local function getValues(option) local values = {} local firstChild = true - for id, optionData in pairs(option.references) do + for _, optionData in pairs(option.references) do local childOption = optionData.options[optionData.index] local childValues = childOption.values local i = 1 @@ -400,7 +400,7 @@ end -- setters for AceConfig local function set(data, option, key) return function(_, value) - for id, optionData in pairs(option.references) do + for _, optionData in pairs(option.references) do local childOption = optionData.options[optionData.index] local childData = optionData.data childOption[key] = value @@ -412,7 +412,7 @@ end local function setUser(data, option) return function(_, value) - for id, optionData in pairs(option.references) do + for _, optionData in pairs(option.references) do local childData = optionData.data local childConfig = optionData.config childConfig[option.key] = value @@ -465,7 +465,7 @@ local function setUserNum(data, option) if value ~= "" then local num = tonumber(value) if not num or math.abs(num) == math.huge or tostring(num) == "nan" then return end - for id, optionData in pairs(option.references) do + for _, optionData in pairs(option.references) do local childData = optionData.data local childConfig = optionData.config childConfig[option.key] = num @@ -532,7 +532,7 @@ local function ensureUniqueKey(candidate, suffix, options, index) local goodKey = true local key = candidate local existingKeys = {} - for index, option in ipairs(options) do + for _, option in ipairs(options) do if option.key then if option.key == key then goodKey = false @@ -836,7 +836,7 @@ typeControlAdders = { type = "input", width = WeakAuras.normalWidth - 0.15, name = (value == conflict and conflictBlue or "") .. L["Value %i"]:format(j), - desc = descSelect(option, j, conflict), + desc = descSelect(option, j), order = order(), get = function() if value ~= conflict then @@ -1015,7 +1015,7 @@ typeControlAdders = { type = "input", width = WeakAuras.normalWidth - 0.15, name = (value == conflict and conflictBlue or "") .. L["Value %i"]:format(j), - desc = descSelect(option, j, conflict), + desc = descSelect(option, j), order = order(), get = function() if value ~= conflict then @@ -1599,7 +1599,6 @@ function addAuthorModeOption(options, args, data, order, prefix, i) local parent = optionData.parent local parentOptions = parent and parent.references[id].options or optionData.data.authorOptions local childOption = tremove(optionData.options, optionData.index) - local childCollapsed = OptionsPrivate.IsCollapsed(id, "author", optionData.path, true) if parent and parent.groupType == "array" then local dereferencedParent = parent.references[id].options[parent.references[id].index] if dereferencedParent.nameSource == optionData.index then @@ -1634,7 +1633,6 @@ function addAuthorModeOption(options, args, data, order, prefix, i) local parent = optionData.parent local parentOptions = parent and parent.references[id].options or optionData.data.authorOptions local childOption = tremove(optionData.options, optionData.index) - local childCollapsed = OptionsPrivate.IsCollapsed(id, "author", optionData.path, true) if parent and parent.groupType == "array" then local dereferencedParent = parent.references[id].options[parent.references[id].index] if dereferencedParent.nameSource == optionData.index then @@ -1867,7 +1865,6 @@ function addAuthorModeOption(options, args, data, order, prefix, i) local addControlsForType = typeControlAdders[option.type] if addControlsForType then addControlsForType(options, args, data, order, prefix, i) - local option = options[i] end end @@ -2220,7 +2217,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) elseif optionType == "number" then userOption.type = "input" userOption.get = getUserNumAsString(option) - userOption.set = setUserNum(data, option, true) + userOption.set = setUserNum(data, option) elseif optionType == "range" then userOption.softMax = option.softMax userOption.softMin = option.softMin @@ -2251,7 +2248,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) return value end userOption.set = function(_, k, v) - for id, optionData in pairs(option.references) do + for _, optionData in pairs(option.references) do optionData.config[option.key][k] = v WeakAuras.Add(optionData.data) end @@ -2264,7 +2261,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) local name = {} local firstName = nil local conflict = false - for id, optionData in pairs(option.references) do + for _, optionData in pairs(option.references) do local childOption = optionData.options[optionData.index] if childOption.useName and #childOption.text > 0 then if firstName == nil then @@ -2347,7 +2344,6 @@ local function mergeOptions(mergedOptions, data, options, config, prepath, paren local nextInsert = 1 for i = 1, #options do local path = CopyTable(prepath) - local option = options[i] path[#path + 1] = i -- find the best place to start inserting the next option to merge local nextToMerge = options[i] @@ -2622,9 +2618,9 @@ function OptionsPrivate.GetAuthorOptions(data) desc = L["Configure what options appear on this panel."], order = order(), func = function() - for data in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + for configData in OptionsPrivate.Private.TraverseLeafsOrAura(data) do -- no need to add, author mode is picked up by ClearAndUpdateOptions - data.authorMode = true + configData.authorMode = true end WeakAuras.ClearAndUpdateOptions(data.id, true) end diff --git a/WeakAurasOptions/BuffTrigger.lua b/WeakAurasOptions/BuffTrigger.lua index 70215e9..521d829 100644 --- a/WeakAurasOptions/BuffTrigger.lua +++ b/WeakAurasOptions/BuffTrigger.lua @@ -6,9 +6,8 @@ local L = WeakAuras.L; local function getAuraMatchesLabel(name) local ids = WeakAuras.spellCache.GetSpellsMatching(name) if(ids) then - local descText = ""; local numMatches = 0; - for id, _ in pairs(ids) do + for _ in pairs(ids) do numMatches = numMatches + 1; end if(numMatches == 1) then @@ -21,19 +20,12 @@ local function getAuraMatchesLabel(name) end end --- the spell id table is sparse, so tremove doesn't work -local function spellId_tremove(tbl, pos) - for i = pos, 9, 1 do - tbl[i] = tbl[i + 1] - end -end - local function getAuraMatchesList(name) local ids = WeakAuras.spellCache.GetSpellsMatching(name) if(ids) then local descText = ""; - for id, _ in pairs(ids) do - local name, _, icon = GetSpellInfo(id); + for id in pairs(ids) do + local _, _, icon = GetSpellInfo(id); if(icon) then if(descText == "") then descText = "|T"..icon..":0|t: "..id; diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index e576353..41a8917 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -7,7 +7,7 @@ local function getAuraMatchesLabel(name) local ids = WeakAuras.spellCache.GetSpellsMatching(name) if ids then local numMatches = 0 - for id, _ in pairs(ids) do + for _ in pairs(ids) do numMatches = numMatches + 1 end return tostring(numMatches) @@ -21,7 +21,7 @@ local function getAuraMatchesList(name) if ids then local descText = "" for id, _ in pairs(ids) do - local name, _, icon = GetSpellInfo(id) + local _, _, icon = GetSpellInfo(id) if icon then if descText == "" then descText = "|T"..icon..":0|t: "..id @@ -113,8 +113,7 @@ local function CreateNameOptions(aura_options, data, trigger, size, isExactSpell if isExactSpellId then aura_options[iconOption].name = function() - local name = GetSpellInfo(WeakAuras.SafeToNumber(trigger[optionKey] and trigger[optionKey][i] or 0)) - return name + return GetSpellInfo(WeakAuras.SafeToNumber(trigger[optionKey] and trigger[optionKey][i] or 0)) end aura_options[iconOption].image = function() local icon @@ -524,7 +523,7 @@ local function GetBuffTriggerOptions(data, triggernum) }, use_stealable = { type = "toggle", - name = function(input) + name = function() local value = trigger.use_stealable if value == nil then return L["Is Stealable"] elseif value == false then return "|cFFFF0000 " .. L["Negator"] .. " " .. L["Is Stealable"] .. "|r" diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index 3196ba4..bdd05cb 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -546,7 +546,6 @@ local function replaceNameDescFuncs(intable, data, subOption) local values = {}; if (get) then values = { get(info) }; - local childOption = getChildOption(childOptions, info) if isToggle and values[1] == nil then values[1] = false end @@ -1372,7 +1371,7 @@ local function AddCodeOption(args, data, name, prefix, url, order, hiddenFunc, p options.extraFunctions = options.extraFunctions or {}; tinsert(options.extraFunctions, 1, { buttonLabel = L["Expand"], - func = function(info) + func = function() OptionsPrivate.OpenTextEditor(OptionsPrivate.GetPickedDisplay(), path, encloseInFunction, options.multipath, options.reloadOptions, options.setOnParent, url, options.validator) end }); @@ -1405,7 +1404,7 @@ local function AddCodeOption(args, data, name, prefix, url, order, hiddenFunc, p OptionsPrivate.ClearOptions(data.id) end end, - get = function(info) + get = function() return GetCustomCode(data, path); end }; diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 0d0abd8..5b15861 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -78,8 +78,8 @@ end local function valueToString(a, propertytype) if (propertytype == "color") then if (type(a) == "table") then - local r, g, b, a = floor((a[1] or 0) * 255), floor((a[2] or 0) * 255), floor((a[3] or 0) * 255), floor((a[4] or 0) * 255) - return string.format("|c%02X%02X%02X%02X", a, r, g, b) .. L["color"]; + local r, g, b, alpha = floor((a[1] or 0) * 255), floor((a[2] or 0) * 255), floor((a[3] or 0) * 255), floor((a[4] or 0) * 255) + return string.format("|c%02X%02X%02X%02X", alpha, r, g, b) .. L["color"]; else return ""; end @@ -822,7 +822,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA if data.controlledChildren then local ordered = {} - for id, reference in pairs(conditions[i].changes[j].references) do + for _, reference in pairs(conditions[i].changes[j].references) do tinsert(ordered, reference) end for index, reference in ipairs(ordered) do @@ -1843,8 +1843,6 @@ local function addControlsForIfLine(args, order, data, conditionVariable, totalA } order = order + 1; - local multipath = {} - args["condition" .. i .. tostring(path) .. "_value"] = { type = "input", width = WeakAuras.doubleWidth, @@ -1865,10 +1863,10 @@ local function addControlsForIfLine(args, order, data, conditionVariable, totalA if (data.controlledChildren) then -- Collect multi paths local multipath = {}; - for id, reference in pairs(conditions[i].check.references) do + for id in pairs(conditions[i].check.references) do local conditionIndex = conditions[i].check.references[id].conditionIndex; multipath[id] ={ "conditions", conditionIndex, "check" } - for i, v in ipairs(path) do + for _, v in ipairs(path) do tinsert(multipath[id], "checks") tinsert(multipath[id], v) end @@ -1877,7 +1875,7 @@ local function addControlsForIfLine(args, order, data, conditionVariable, totalA OptionsPrivate.OpenTextEditor(data, multipath, nil, true, nil, nil, "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-check"); else local fullPath = { "conditions", i, "check" } - for i, v in ipairs(path) do + for _, v in ipairs(path) do tinsert(fullPath, "checks") tinsert(fullPath, v) end @@ -1983,7 +1981,7 @@ local function addControlsForCondition(args, order, data, conditionVariable, tot order = order, disabled = function() if (data.controlledChildren) then - for id, reference in pairs(conditions[i].check.references) do + for _, reference in pairs(conditions[i].check.references) do local index = reference.conditionIndex; if (index > 1) then return false; @@ -2526,7 +2524,6 @@ local function findMatchingProperty(all, change, id) return nil; end -local noop = function() end local function SubPropertiesForChange(change) if change.property == "sound" then return { "sound", "sound_channel", "sound_path", "sound_kit_id", "sound_repeat", "sound_type"} @@ -2705,7 +2702,7 @@ local function mergeConditions(all, aura, id, allConditionTemplates, propertyTyp end local fixupConditions = function(conditions) - for index, condition in ipairs(conditions) do + for _, condition in ipairs(conditions) do condition.check = condition.check or {} condition.changes = condition.changes or {} end diff --git a/WeakAurasOptions/GenericTrigger.lua b/WeakAurasOptions/GenericTrigger.lua index a6b4c71..5dbbd0c 100644 --- a/WeakAurasOptions/GenericTrigger.lua +++ b/WeakAurasOptions/GenericTrigger.lua @@ -4,7 +4,6 @@ local AddonName, OptionsPrivate = ... local L = WeakAuras.L; local function GetCustomTriggerOptions(data, triggernum) - local id = data.id; local trigger = data.triggers[triggernum].trigger local function appendToTriggerPath(...) local ret = {...}; @@ -31,7 +30,7 @@ local function GetCustomTriggerOptions(data, triggernum) width = WeakAuras.doubleWidth, values = OptionsPrivate.Private.custom_trigger_types, hidden = function() return not (trigger.type == "custom") end, - get = function(info) + get = function() return trigger.custom_type end, set = function(info, v) @@ -110,7 +109,7 @@ local function GetCustomTriggerOptions(data, triggernum) name = function() local events = trigger.custom_type == "event" and trigger.events2 or trigger.events -- Check for errors - for index, event in pairs(WeakAuras.split(events)) do + for _, event in pairs(WeakAuras.split(events)) do local trueEvent for i in event:gmatch("[^:]+") do if not trueEvent then @@ -159,7 +158,7 @@ local function GetCustomTriggerOptions(data, triggernum) end local events = trigger.custom_type == "event" and trigger.events2 or trigger.events -- Check for errors - for index, event in pairs(WeakAuras.split(events)) do + for _, event in pairs(WeakAuras.split(events)) do local trueEvent for i in event:gmatch("[^:]+") do if not trueEvent then diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index 247332a..7f0a462 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -127,7 +127,7 @@ function OptionsPrivate.GetInformationOptions(data) -- Show warnings only for single selection for now if not isGroup then - local icon, title, message = OptionsPrivate.Private.AuraWarnings.FormatWarnings(data.uid) + local _, title, message = OptionsPrivate.Private.AuraWarnings.FormatWarnings(data.uid) if title and message then args.warningTitle = { type = "header", diff --git a/WeakAurasOptions/OptionsFrames/ImportExport.lua b/WeakAurasOptions/OptionsFrames/ImportExport.lua index 56b7424..99aa86e 100644 --- a/WeakAurasOptions/OptionsFrames/ImportExport.lua +++ b/WeakAurasOptions/OptionsFrames/ImportExport.lua @@ -80,7 +80,7 @@ local function ConstructImportExport(frame) group:DoLayout() end - function group.Close(self) + function group.Close() input:ClearFocus(); frame.window = "default"; frame:UpdateFrameVisible() diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index af38d34..98a54fd 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -908,7 +908,7 @@ local function ConstructMoverSizer(parent) local numInterim = floor(distance/40) - for index, texture in pairs(self.interims) do + for _, texture in pairs(self.interims) do texture:Hide() end for i = 1, numInterim do diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index d513dcc..9e7f8d9 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -142,7 +142,7 @@ function OptionsPrivate.CreateFrame() data.region:Collapse() data.region:OptionsClosed() if WeakAuras.clones[id] then - for cloneId, cloneRegion in pairs(WeakAuras.clones[id]) do + for _, cloneRegion in pairs(WeakAuras.clones[id]) do cloneRegion:Collapse() cloneRegion:OptionsClosed() end @@ -1375,7 +1375,7 @@ function OptionsPrivate.CreateFrame() alreadySelected[child.id] = true end - for index, id in ipairs(batchSelection) do + for _, id in ipairs(batchSelection) do if not alreadySelected[id] then displayButtons[id]:Pick() tinsert(tempGroup.controlledChildren, id) diff --git a/WeakAurasOptions/TriggerOptions.lua b/WeakAurasOptions/TriggerOptions.lua index c8b659e..5dfca41 100644 --- a/WeakAurasOptions/TriggerOptions.lua +++ b/WeakAurasOptions/TriggerOptions.lua @@ -108,7 +108,7 @@ local function AddOptions(allOptions, data) -- Unknown trigger system, empty options local options = {}; OptionsPrivate.commonOptions.AddCommonTriggerOptions(options, data, index) - OptionsPrivate.AddTriggerMetaFunctions(options, data, index, true) + OptionsPrivate.AddTriggerMetaFunctions(options, data, index) triggerOptions = union(triggerOptions, { ["trigger." .. index .. ".unknown"] = options }) diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 648833a..6a597f4 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -404,7 +404,7 @@ function OptionsPrivate.MultipleDisplayTooltipMenu() local allSameParent = true local commonParent = nil local first = true - for index, id in pairs(tempGroup.controlledChildren) do + for _, id in pairs(tempGroup.controlledChildren) do local childData = WeakAuras.GetData(id); if(childData and childData.controlledChildren) then anyGroup = true; @@ -555,19 +555,6 @@ local function OnAboutToDelete(event, uid, id, parentUid, parentId) collapsedOptions[id] = nil end -local function OnDelete(event, uid, id, parentUid, parentId) - local parentData = OptionsPrivate.Private.GetDataByUID(parentUid) - if(parentData and parentData.controlledChildren and not OptionsPrivate.massDelete) then - for index, childId in pairs(parentData.controlledChildren) do - local childButton = displayButtons[childId]; - if(childButton) then - childButton:SetGroupOrder(index, #parentData.controlledChildren) - end - end - WeakAuras.ClearAndUpdateOptions(parentData.id) - end -end - local function OnRename(event, uid, oldid, newid) local data = OptionsPrivate.Private.GetDataByUID(uid) @@ -582,7 +569,7 @@ local function OnRename(event, uid, oldid, newid) collapsedOptions[oldid] = nil if(data.controlledChildren) then - for index, childId in pairs(data.controlledChildren) do + for _, childId in pairs(data.controlledChildren) do WeakAuras.displayButtons[childId]:SetGroup(newid) end end @@ -722,7 +709,7 @@ local function LayoutDisplayButtons(msg) local func2 = function() local num = frame.loadProgressNum or 0; - for index, id in pairs(unloadedSorted) do + for _, id in pairs(unloadedSorted) do local data = WeakAuras.GetData(id); if(data) then EnsureDisplayButton(data); @@ -764,7 +751,7 @@ local function LayoutDisplayButtons(msg) local func1 = function() local num = frame.loadProgressNum or 0; frame.buttonsScroll:PauseLayout() - for index, id in pairs(loadedSorted) do + for _, id in pairs(loadedSorted) do local data = WeakAuras.GetData(id); if(data) then EnsureDisplayButton(data); @@ -1204,7 +1191,7 @@ function OptionsPrivate.SortDisplayButtons(filter, overrideReset, id) end end - for id, child in pairs(displayButtons) do + for _, child in pairs(displayButtons) do if(not visible[child]) then child.frame:Hide(); if child.ReleaseThumbnail then @@ -1365,7 +1352,7 @@ function OptionsPrivate.StartGrouping(data) children[childId] = true; end -- set grouping for non selected buttons - for id, button in pairs(displayButtons) do + for _, button in pairs(displayButtons) do if not children[button.data.id] then button:StartGrouping(tempGroup.controlledChildren, false); end @@ -1406,7 +1393,7 @@ function OptionsPrivate.Ungroup(data) end function OptionsPrivate.DragReset() - for id, button in pairs(displayButtons) do + for _, button in pairs(displayButtons) do button:DragReset(); end OptionsPrivate.UpdateButtonsScroll() @@ -1502,13 +1489,13 @@ function OptionsPrivate.Drop(mainAura, target, action, area) end end - for index, button in ipairs(buttonsToSort) do + for _, button in ipairs(buttonsToSort) do button:Drop(mode, mainAura, target, action) end -- Update offset, this is a bit wasteful to do for every aura -- But we also need to update the offset if a parent was dragged - for id, button in pairs(displayButtons) do + for _, button in pairs(displayButtons) do button:UpdateOffset(); end @@ -1532,7 +1519,7 @@ function OptionsPrivate.StartDrag(mainAura) children[child.id] = true end -- set dragging for non selected buttons - for id, button in pairs(displayButtons) do + for _, button in pairs(displayButtons) do if not children[button.data.id] then button:DragStart("MULTI", false, mainAura); end @@ -1678,7 +1665,7 @@ function WeakAuras.SetMoverSizer(id) frame.moversizer:SetToRegion(WeakAuras.regions[id].region, db.displays[id]) else if WeakAuras.clones[id] then - local cloneId, clone = next(WeakAuras.clones[id]) + local _, clone = next(WeakAuras.clones[id]) if clone then frame.moversizer:SetToRegion(clone, db.displays[id]) end @@ -1963,7 +1950,7 @@ function OptionsPrivate.AddTextFormatOption(input, withHeader, get, addOption, h local seenSymbols = {} OptionsPrivate.Private.ParseTextStr(input, function(symbol) if not seenSymbols[symbol] then - local triggerNum, sym = string.match(symbol, "(.+)%.(.+)") + local _, sym = string.match(symbol, "(.+)%.(.+)") sym = sym or symbol if sym == "i" then From 873748218a08f0de60aa6c8b9c1426f7196bb28e Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 6 Jan 2025 12:52:38 +0100 Subject: [PATCH 004/153] Add debug log from retail --- WeakAuras/AuraEnvironment.lua | 6 + WeakAuras/AuraWarnings.lua | 10 +- WeakAuras/DebugLog.lua | 114 ++++++++++++++++++ WeakAuras/WeakAuras.lua | 6 + WeakAuras/WeakAuras.toc | 3 + WeakAurasOptions/InformationOptions.lua | 90 +++++++++++++- .../OptionsFrames/DebugLogFrame.lua | 71 +++++++++++ .../OptionsFrames/OptionsFrame.lua | 8 ++ WeakAurasOptions/WeakAurasOptions.lua | 4 + WeakAurasOptions/WeakAurasOptions.toc | 1 + 10 files changed, 309 insertions(+), 4 deletions(-) create mode 100644 WeakAuras/DebugLog.lua create mode 100644 WeakAurasOptions/OptionsFrames/DebugLogFrame.lua diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index 20b4da4..c43cac9 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -276,6 +276,10 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) end end +local function DebugPrint(...) + Private.DebugLog.Print(current_uid, ...) +end + local function blocked(key) Private.AuraWarnings.UpdateWarning(current_uid, "SandboxForbidden", "error", string.format(L["Forbidden function or table: %s"], key)) @@ -392,6 +396,8 @@ local exec_env = setmetatable({}, return env_getglobal elseif k == "aura_env" then return current_aura_env + elseif k == "DebugPrint" then + return DebugPrint elseif blockedFunctions[k] then blocked(k) return function() end diff --git a/WeakAuras/AuraWarnings.lua b/WeakAuras/AuraWarnings.lua index e09ac86..fb5fa85 100644 --- a/WeakAuras/AuraWarnings.lua +++ b/WeakAuras/AuraWarnings.lua @@ -10,6 +10,7 @@ local printedWarnings = {} local function OnDelete(event, uid) warnings[uid] = nil + printedWarnings[uid] = nil end Private.callbacks:RegisterCallback("Delete", OnDelete) @@ -37,6 +38,9 @@ local function UpdateWarning(uid, key, severity, message, printOnConsole) else if warnings[uid][key] then warnings[uid][key] = nil + if printedWarnings[uid] then + printedWarnings[uid][key] = nil + end Private.callbacks:Fire("AuraWarningsUpdated", uid) end end @@ -50,7 +54,7 @@ local severityLevel = { } local icons = { - info = { path = [[Interface\friendsframe\informationicon]] }, + info = { path = [[Interface\FriendsFrame\InformationIcon]] }, sound = { path = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\ChatFrame", texCoords = {0.757812, 0.871094, 0.0078125, 0.234375} }, warning = { path = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\ServicesAtlas", texCoords = {0.000976562, 0.0419922, 0.961914, 0.998047} }, error = { path = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\HelpIcon-Bug" }, @@ -75,9 +79,9 @@ local function AddMessages(result, messages, icon, mixedSeverity) local iconPath = icon.path local texCoords = icon.texCoords if texCoords then - result = result .. string.format("|T%s:12:12:0:0:64:64:%d:%d:%d:%d|t", iconPath, texCoords[1] * 64, texCoords[2] * 64, texCoords[3] * 64, texCoords[4] * 64) + result = result .. string.format("|T%s:12:12:0:0:64:64:%d:%d:%d:%d|t", iconPath, texCoords[1] * 64, texCoords[2] * 64, texCoords[3] * 64, texCoords[4] * 64) else - result = result .. string.format("|T%s:12:12:0:0:64:64:4:60:4:60|t", iconPath) + result = result .. string.format("|T%s:12:12:0:0:64:64:4:60:4:60|t", iconPath) end end result = result .. message diff --git a/WeakAuras/DebugLog.lua b/WeakAuras/DebugLog.lua new file mode 100644 index 0000000..813d1d7 --- /dev/null +++ b/WeakAuras/DebugLog.lua @@ -0,0 +1,114 @@ +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +local AddonName, Private = ... + +local WeakAuras = WeakAuras +local L = WeakAuras.L + +local debugLogs = {} +local enabled = {} + +Private.DebugLog = { + -- Print + -- Clear + -- SetEnabled + -- IsEnabled + -- GetLogs +} + +local function serialize(log, input) + if type(input) == "table" then + if log[#log] == "" then + log[#log] = L["Dumping table"] + else + tinsert(log, L["Dumping table"]) + end + -- Use dump to create a table dump, because that already handles depth limitation + -- and cycles and looks nice + -- But this requires temporarily setting DEFAULT_CHAT_FRAME + -- Nothing can go wrong with that. + local defaultChatFrame = _G.DEFAULT_CHAT_FRAME + _G.DEFAULT_CHAT_FRAME = log + DevTools_Dump(input) + _G.DEFAULT_CHAT_FRAME = defaultChatFrame + tinsert(log, "") + else + if log[#log] == "" then + log[#log] = tostring(input) + else + log[#log] = log[#log] .. " " .. tostring(input) + end + end +end + +function Private.DebugLog.Print(uid, text, ...) + if enabled[uid] then + local log = debugLogs[uid] + tinsert(log, "") + if select('#', ...) == 0 then + serialize(log, text) + else + serialize(log, text) + local texts = {...} + for i = 1, select('#', ...) do + local v = select(i, ...) + serialize(log, v) + end + end + + if #log > 1000 then + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "warning", + L["Debug Log contains more than 1000 entries"], + true) + end + end +end + +local function AddMessage(self, msg) + tinsert(self, msg) +end + +function Private.DebugLog.Clear(uid) + if enabled[uid] then + debugLogs[uid] = { + AddMessage = AddMessage + } + -- Dance to clear a potential console message from the AuraWarnings + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "info") + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "info", L["Debug Logging enabled"]) + end +end + +function Private.DebugLog.SetEnabled(uid, enable) + if enabled[uid] == enable then + return + end + enabled[uid] = enable + if enable then + debugLogs[uid] = { + AddMessage = AddMessage + } + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "info", L["Debug Logging enabled"]) + else + debugLogs[uid] = nil + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "info") + end +end + +function Private.DebugLog.IsEnabled(uid) + return enabled[uid] +end + +function Private.DebugLog.GetLogs(uid) + if debugLogs[uid] then + return table.concat(debugLogs[uid], "\n") + end +end + +local function OnDelete(_, uid) + debugLogs[uid] = nil + enabled[uid] = nil +end + +Private.callbacks:RegisterCallback("Delete", OnDelete) + + diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index a4d16b6..c778430 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1570,6 +1570,10 @@ function Private.LoadDisplays(toLoad, ...) triggerState[id].show = false; triggerState[id].activeTrigger = nil; triggerState[id].activatedConditions = {}; + if Private.DebugLog.IsEnabled(uid) then + WeakAuras.prettyPrint(L["Debug Logging enabled for '%s'"]:format(id)) + Private.DebugLog.Print(uid, L["Aura loaded"]) + end end for _, triggerSystem in pairs(triggerSystems) do triggerSystem.LoadDisplays(toLoad, ...); @@ -2554,6 +2558,8 @@ local function pAdd(data, simpleChange) end Private.UpdatedTriggerState(id) else + Private.DebugLog.SetEnabled(data.uid, data.information.debugLog) + if (data.controlledChildren) then Private.ClearAuraEnvironment(id); for parent in Private.TraverseParents(data) do diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index cb98cff..61e6760 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -44,8 +44,11 @@ Conditions.lua BuffTrigger.lua BuffTrigger2.lua GenericTrigger.lua + +# Helper Systems AuraWarnings.lua AuraEnvironment.lua +DebugLog.lua # Region support RegionTypes\RegionPrototype.lua diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index 7f0a462..e8a7e6b 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -148,7 +148,7 @@ function OptionsPrivate.GetInformationOptions(data) end end - -- compatibility Options + -- compatibility Options args.compabilityTitle = { type = "header", name = L["Compatibility Options"], @@ -245,6 +245,94 @@ function OptionsPrivate.GetInformationOptions(data) end end + -- Debug Log + args.debugLogTitle = { + type = "header", + name = L["Enable Debug Log"], + width = WeakAuras.doubleWidth, + order = order, + } + order = order + 1 + args.debugLogDesc = { + type = "description", + name = L["This enables the collection of debug logs. This requires custom coded auras that use DebugPrints."], + width = WeakAuras.doubleWidth, + order = order, + } + order = order + 1 + local sameDebugLog = true + local commonDebugLog + local debugLogDesc = "" + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + local effectiveDebugLog = child.information.debugLog and true or false + debugLogDesc = debugLogDesc .. "|cFFE0E000"..child.id..": |r".. (effectiveDebugLog and "true" or "false") .. "\n" + if commonDebugLog == nil then + commonDebugLog = effectiveDebugLog + elseif effectiveDebugLog ~= commonDebugLog then + sameDebugLog = false + end + end + args.debugLogToggle = { + type = "toggle", + name = sameDebugLog and L["Enable Debug Logging"] or "|cFF4080FF" .. L["Enable Debug Logging"], + desc = not sameDebugLog and debugLogDesc or nil, + width = WeakAuras.doubleWidth, + order = order, + get = function() + return sameDebugLog and commonDebugLog + end, + set = function(info, v) + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + child.information.debugLog = v + WeakAuras.Add(child) + OptionsPrivate.ClearOptions(child.id) + end + WeakAuras.ClearAndUpdateOptions(data.id) + end + } + order = order + 1 + if not sameDebugLog or commonDebugLog then + args.debugLogShow = { + type = "execute", + name = L["Show Debug Logs"], + width = WeakAuras.normalWidth, + order = order, + func = function() + local fullMessage = L["WeakAuras %s on WoW %s"]:format(WeakAuras.versionString, WeakAuras.BuildInfo) .. "\n\n" + local haveLogs = false + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + local auraLog = OptionsPrivate.Private.DebugLog.GetLogs(child.uid) + if auraLog then + haveLogs = true + fullMessage = fullMessage .. L["Aura: '%s'"]:format(child.id) + local version = child.semver or child.version + if (version) then + fullMessage = fullMessage .. "\n" .. L["Version: %s"]:format(version) + end + fullMessage = fullMessage .. "\n" .. L["Debug Log:"] .. "\n" .. auraLog .. "\n\n" + end + end + if haveLogs then + OptionsPrivate.OpenDebugLog(fullMessage) + else + OptionsPrivate.OpenDebugLog(L["No Logs saved."]) + end + end + } + order = order + 1 + args.debugLogClear = { + type = "execute", + name = L["Clear Debug Logs"], + width = WeakAuras.normalWidth, + order = order, + func = function() + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + OptionsPrivate.Private.DebugLog.Clear(child.uid) + end + end + } + order = order + 1 + end return options end diff --git a/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua b/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua new file mode 100644 index 0000000..836f057 --- /dev/null +++ b/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua @@ -0,0 +1,71 @@ +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +local AddonName, OptionsPrivate = ... + +-- WoW APIs +local CreateFrame = CreateFrame + +local AceGUI = LibStub("AceGUI-3.0") + +local WeakAuras = WeakAuras +local L = WeakAuras.L + +local debugLog + +local function ConstructDebugLog(frame) + local group = AceGUI:Create("WeakAurasInlineGroup"); + group.frame:SetParent(frame); + group.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -63); + group.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 46); + group.frame:Hide(); + group:SetLayout("flow"); + + local copyLabel = AceGUI:Create("Label") + copyLabel:SetFontObject(GameFontNormal) + copyLabel:SetFullWidth(true) + copyLabel:SetText(L["Press Ctrl+C to copy"]) + group:AddChild(copyLabel) + + local input = AceGUI:Create("MultiLineEditBox"); + input:DisableButton(true) + --input.frame:SetClipsChildren(true); + input.editBox:SetScript("OnEscapePressed", function() group:Close(); end); + input.editBox:SetScript("OnMouseUp", function() input.editBox:HighlightText(); end); + input:SetFullWidth(true) + input:SetFullHeight(true) + group:AddChild(input); + + local close = CreateFrame("Button", nil, group.frame, "UIPanelButtonTemplate"); + close:SetScript("OnClick", function() group:Close() end); + close:SetPoint("BOTTOMRIGHT", -20, -24) + close:SetFrameLevel(close:GetFrameLevel() + 1) + close:SetHeight(20); + close:SetWidth(100); + close:SetText(L["Close"]) + + function group.Open(self, text) + frame.window = "debuglog"; + frame:UpdateFrameVisible() + input.editBox:SetScript("OnTextChanged", function() input:SetText(text); input.editBox:HighlightText(); end); + input.editBox:SetScript("OnMouseUp", function() input.editBox:HighlightText(); end); + input:SetLabel(""); + input.button:Hide(); + input:SetText(text); + input.editBox:HighlightText(); + input:SetFocus() + + group:DoLayout() + end + + function group.Close(self) + input:ClearFocus(); + frame.window = "default"; + frame:UpdateFrameVisible() + end + + return group +end + +function OptionsPrivate.DebugLog(frame) + debugLog = debugLog or ConstructDebugLog(frame) + return debugLog +end diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index 9e7f8d9..f614d20 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -212,6 +212,7 @@ function OptionsPrivate.CreateFrame() self.update.frame:Hide() self.texteditor.frame:Hide() self.codereview.frame:Hide() + self.debugLog.frame:Hide() if self.newView then self.newView.frame:Hide() end @@ -292,6 +293,12 @@ function OptionsPrivate.CreateFrame() else self.update.frame:Hide() end + if self.window == "debuglog" then + OptionsPrivate.SetTitle(L["Debug Log"]) + self.debugLog.frame:Show() + else + self.debugLog.frame:Hide() + end if self.window == "default" then if self.loadProgessVisible then self.loadProgress:Show() @@ -486,6 +493,7 @@ function OptionsPrivate.CreateFrame() frame.texteditor = OptionsPrivate.TextEditor(frame) frame.codereview = OptionsPrivate.CodeReview(frame) frame.update = OptionsPrivate.UpdateFrame(frame) + frame.debugLog = OptionsPrivate.DebugLog(frame) frame.moversizer, frame.mover = OptionsPrivate.MoverSizer(frame) diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 6a597f4..eb401a4 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -892,6 +892,10 @@ function OptionsPrivate.ImportFromString() frame.importexport:Open("import"); end +function OptionsPrivate.OpenDebugLog(text) + frame.debugLog:Open(text) +end + function OptionsPrivate.OpenUpdate(data, children, target, sender) return frame.update:Open(data, children, target, sender) end diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index 0357c7a..922f7ca 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -65,6 +65,7 @@ OptionsFrames\ModelPicker.lua OptionsFrames\TextEditor.lua OptionsFrames\TexturePicker.lua OptionsFrames\Update.lua +OptionsFrames\DebugLogFrame.lua # Misc frames OptionsFrames\MoverSizer.lua From 7a185106f2d23237b016ffd99e027305532340ca Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 6 Jan 2025 19:47:37 +0100 Subject: [PATCH 005/153] from retail --- WeakAuras/Animations.lua | 2 +- WeakAuras/AuraEnvironment.lua | 2 +- WeakAuras/AuraWarnings.lua | 2 +- WeakAuras/BuffTrigger.lua | 2 +- WeakAuras/BuffTrigger2.lua | 28 +++-- WeakAuras/Conditions.lua | 2 +- WeakAuras/DebugLog.lua | 2 +- WeakAuras/GenericTrigger.lua | 6 +- WeakAuras/History.lua | 2 +- WeakAuras/Init.lua | 4 - WeakAuras/Modernize.lua | 2 +- WeakAuras/Profiling.lua | 2 +- WeakAuras/Prototypes.lua | 105 ++++++++++++++++-- WeakAuras/RegionTypes/AuraBar.lua | 2 +- WeakAuras/RegionTypes/DynamicGroup.lua | 7 +- WeakAuras/RegionTypes/Group.lua | 2 +- WeakAuras/RegionTypes/Icon.lua | 2 +- WeakAuras/RegionTypes/Model.lua | 2 +- WeakAuras/RegionTypes/ProgressTexture.lua | 2 +- WeakAuras/RegionTypes/RegionPrototype.lua | 18 +-- WeakAuras/RegionTypes/StopMotion.lua | 2 +- WeakAuras/RegionTypes/Text.lua | 2 +- WeakAuras/RegionTypes/Texture.lua | 2 +- WeakAuras/SubRegionTypes/Background.lua | 2 +- WeakAuras/SubRegionTypes/Border.lua | 2 +- WeakAuras/SubRegionTypes/Glow.lua | 2 +- WeakAuras/SubRegionTypes/Model.lua | 2 +- WeakAuras/SubRegionTypes/SubText.lua | 2 +- WeakAuras/SubRegionTypes/Tick.lua | 2 +- WeakAuras/Transmission.lua | 2 +- WeakAuras/Types.lua | 17 ++- WeakAuras/WeakAuras.lua | 61 +++++----- .../AceGUIContainer-WeakAurasInlineGroup.lua | 4 +- .../AceGUIContainer-WeakAurasTreeGroup.lua | 4 +- .../AceGUIWidget-WeakAurasAnchorButtons.lua | 2 +- .../AceGUIWidget-WeakAurasDisplayButton.lua | 2 +- .../AceGUIWidget-WeakAurasExpand.lua | 4 +- .../AceGUIWidget-WeakAurasExpandAnchor.lua | 4 +- .../AceGUIWidget-WeakAurasExpandSmall.lua | 4 +- .../AceGUIWidget-WeakAurasIcon.lua | 4 +- .../AceGUIWidget-WeakAurasIconButton.lua | 4 +- .../AceGUIWidget-WeakAurasImportButton.lua | 4 +- .../AceGUIWidget-WeakAurasInputFocus.lua | 2 +- ...eGUIWidget-WeakAurasLoadedHeaderButton.lua | 2 +- ...AceGUIWidget-WeakAurasMultiLineEditBox.lua | 4 +- ...get-WeakAurasMultiLineEditBoxWithEnter.lua | 2 +- .../AceGUIWidget-WeakAurasNewButton.lua | 4 +- .../AceGUIWidget-WeakAurasNewHeaderButton.lua | 4 +- ...UIWidget-WeakAurasPendingInstallButton.lua | 6 +- ...GUIWidget-WeakAurasPendingUpdateButton.lua | 6 +- .../AceGUIWidget-WeakAurasSnippetButton.lua | 4 +- .../AceGUIWidget-WeakAurasSpacer.lua | 4 +- .../AceGUIWidget-WeakAurasSpinBox.lua | 2 + .../AceGUIWidget-WeakAurasTextureButton.lua | 2 +- .../AceGUIWidget-WeakAurasToolbarButton.lua | 2 + ...ceGUIWidget-WeakAurasTwoColumnDropDown.lua | 4 +- .../AceGuiWidget-WeakAurasProgressBar.lua | 4 +- WeakAurasOptions/ActionOptions.lua | 2 +- WeakAurasOptions/AnimationOptions.lua | 2 +- WeakAurasOptions/AuthorOptions.lua | 14 ++- WeakAurasOptions/BuffTrigger.lua | 2 +- WeakAurasOptions/BuffTrigger2.lua | 6 +- WeakAurasOptions/Cache.lua | 2 +- WeakAurasOptions/CommonOptions.lua | 9 +- WeakAurasOptions/ConditionOptions.lua | 2 +- WeakAurasOptions/DisplayOptions.lua | 2 +- WeakAurasOptions/ForAllIndentsAndPurposes.lua | 2 +- WeakAurasOptions/GenericTrigger.lua | 2 +- WeakAurasOptions/GroupOptions.lua | 2 +- WeakAurasOptions/InformationOptions.lua | 2 +- WeakAurasOptions/LoadOptions.lua | 2 +- WeakAurasOptions/Locales/deDE.lua | 2 +- WeakAurasOptions/Locales/enUS.lua | 2 +- WeakAurasOptions/Locales/esES.lua | 2 +- WeakAurasOptions/Locales/esMX.lua | 2 +- WeakAurasOptions/Locales/frFR.lua | 2 +- WeakAurasOptions/Locales/itIT.lua | 2 +- WeakAurasOptions/Locales/koKR.lua | 2 +- WeakAurasOptions/Locales/ptBR.lua | 2 +- WeakAurasOptions/Locales/ruRU.lua | 2 +- WeakAurasOptions/Locales/zhCN.lua | 2 +- WeakAurasOptions/Locales/zhTW.lua | 2 +- WeakAurasOptions/OptionsFrames/CodeReview.lua | 2 +- .../OptionsFrames/DebugLogFrame.lua | 2 +- .../OptionsFrames/FrameChooser.lua | 2 +- WeakAurasOptions/OptionsFrames/IconPicker.lua | 2 +- .../OptionsFrames/ImportExport.lua | 2 +- .../OptionsFrames/ModelPicker.lua | 2 +- WeakAurasOptions/OptionsFrames/MoverSizer.lua | 2 +- .../OptionsFrames/OptionsFrame.lua | 6 +- WeakAurasOptions/OptionsFrames/TextEditor.lua | 35 +++++- .../OptionsFrames/TexturePicker.lua | 2 +- WeakAurasOptions/OptionsFrames/Update.lua | 2 +- WeakAurasOptions/RegionOptions/AuraBar.lua | 2 +- .../RegionOptions/DynamicGroup.lua | 2 +- WeakAurasOptions/RegionOptions/Group.lua | 6 +- WeakAurasOptions/RegionOptions/Icon.lua | 2 +- WeakAurasOptions/RegionOptions/Model.lua | 2 +- .../RegionOptions/ProgressTexture.lua | 2 +- WeakAurasOptions/RegionOptions/StopMotion.lua | 2 + WeakAurasOptions/RegionOptions/Text.lua | 2 +- WeakAurasOptions/RegionOptions/Texture.lua | 2 +- .../SubRegionOptions/Background.lua | 2 +- WeakAurasOptions/SubRegionOptions/Border.lua | 2 +- WeakAurasOptions/SubRegionOptions/Glow.lua | 2 +- WeakAurasOptions/SubRegionOptions/Model.lua | 2 +- .../SubRegionOptions/SubRegionCommon.lua | 2 +- WeakAurasOptions/SubRegionOptions/SubText.lua | 2 +- WeakAurasOptions/SubRegionOptions/Tick.lua | 2 +- WeakAurasOptions/TriggerOptions.lua | 2 +- WeakAurasOptions/WeakAurasOptions.lua | 2 +- 111 files changed, 359 insertions(+), 195 deletions(-) diff --git a/WeakAuras/Animations.lua b/WeakAuras/Animations.lua index bbf9d71..1a98194 100644 --- a/WeakAuras/Animations.lua +++ b/WeakAuras/Animations.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Animations diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index c43cac9..285fcb3 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras diff --git a/WeakAuras/AuraWarnings.lua b/WeakAuras/AuraWarnings.lua index fb5fa85..ec193e0 100644 --- a/WeakAuras/AuraWarnings.lua +++ b/WeakAuras/AuraWarnings.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras diff --git a/WeakAuras/BuffTrigger.lua b/WeakAuras/BuffTrigger.lua index 538217f..860f30a 100644 --- a/WeakAuras/BuffTrigger.lua +++ b/WeakAuras/BuffTrigger.lua @@ -2,7 +2,7 @@ This used to contains the "aura" trigger for buffs and debuffs. Nowadays all functions do essentially nothing ]]-- -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index f8633b5..23f18dd 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -50,7 +50,7 @@ Returns the tooltip text for additional properties. GetTriggerConditions(data, triggernum) Returns the potential conditions for a trigger ]]-- -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Lua APIs @@ -230,7 +230,6 @@ local function ReferenceMatchDataMulti(matchData, id, triggernum, destGUID) local matchDataByTriggerBase = GetOrCreateSubTable(matchDataByTrigger, id, triggernum, destGUID) tinsert(matchDataByTriggerBase, matchData) end - matchDataChanged[id] = matchDataChanged[id] or {} matchDataChanged[id][triggernum] = true end @@ -566,6 +565,12 @@ local function UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, mat changed = true end + if not state.initialTime then + -- Only set initialTime if it wasn't set before + state.initialTime = time + changed = true + end + if state.expirationTime ~= bestMatch.expirationTime then -- A bit fuzzy checking if state.expirationTime and bestMatch.expirationTime and bestMatch.expirationTime - state.expirationTime > 0.2 then @@ -724,6 +729,15 @@ local function UpdateStateWithNoMatch(time, triggerStates, triggerInfo, cloneId, changed = true end + if state.initialTime then + state.initialTime = nil + changed = true + end + if state.refreshTime then + state.refreshTime = nil + changed = true + end + if state.expirationTime ~= math.huge then state.expirationTime = math.huge changed = true @@ -2582,7 +2596,9 @@ function BuffTrigger.GetAdditionalProperties(data, triggernum) ret = ret .. "|cFFFF0000%".. triggernum .. ".debuffClass|r - " .. L["Debuff Class"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".unitCaster|r - " .. L["Caster Unit"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".casterName|r - " .. L["Caster Name"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".unit|r - " .. L["Unit"] .. "\n" + if trigger.unit ~= "multi" then + ret = ret .. "|cFFFF0000%".. triggernum .. ".unit|r - " .. L["Unit"] .. "\n" + end ret = ret .. "|cFFFF0000%".. triggernum .. ".unitName|r - " .. L["Unit Name"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".matchCount|r - " .. L["Match Count"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".matchCountPerUnit|r - " .. L["Match Count per Unit"] .. "\n" @@ -3126,18 +3142,12 @@ local function AugmentMatchDataMultiWith(matchData, unit, name, icon, stacks, de changed = true end - if (matchData.unit ~= unit) then - matchData.unit = unit - changed = true - end - local unitName = GetUnitName(unit, false) or "" if matchData.unitName ~= unitName then matchData.unitName = unitName changed = true end - if matchData.spellId ~= spellId then matchData.spellId = name changed = true diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index fa88394..dea2034 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L diff --git a/WeakAuras/DebugLog.lua b/WeakAuras/DebugLog.lua index 813d1d7..a90e063 100644 --- a/WeakAuras/DebugLog.lua +++ b/WeakAuras/DebugLog.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 7d69fa0..6768143 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -49,7 +49,7 @@ Returns the a tooltip for the additional properties. GetTriggerConditions(data, triggernum) Returns potential conditions that this trigger provides. ]]-- -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Lua APIs @@ -1634,9 +1634,9 @@ do update_frame = CreateFrame("Frame"); end if not(updating) then - update_frame:SetScript("OnUpdate", function() + update_frame:SetScript("OnUpdate", function(self, elapsed) if not(WeakAuras.IsPaused()) then - WeakAuras.ScanEvents("FRAME_UPDATE"); + WeakAuras.ScanEvents("FRAME_UPDATE", elapsed); end end); updating = true; diff --git a/WeakAuras/History.lua b/WeakAuras/History.lua index 38566a4..c63e91c 100644 --- a/WeakAuras/History.lua +++ b/WeakAuras/History.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index ea3c50c..5e19b18 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -25,10 +25,6 @@ function WeakAuras.IsClassic() return false end -function WeakAuras.IsCorrectVersion() - return true -end - WeakAuras.prettyPrint = function(...) print("|cff9900ffWeakAuras:|r ", ...) end diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 07fb46f..80229d7 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L diff --git a/WeakAuras/Profiling.lua b/WeakAuras/Profiling.lua index 1db3605..c924eb7 100644 --- a/WeakAuras/Profiling.lua +++ b/WeakAuras/Profiling.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index bab65b4..f9bfb33 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Lua APIs @@ -102,6 +102,10 @@ function WeakAuras.TestSchool(spellSchool, test) return spellSchool == test end +function WeakAuras.RaidFlagToIndex(flag) + return Private.combatlog_raidFlags[flag] or 0 +end + Private.function_strings = { count = [[ return function(count) @@ -941,7 +945,7 @@ Private.load_prototype = { display = L["Spell Known"], type = "spell", test = "WeakAuras.IsSpellKnownForLoad(%s, %s)", - events = {"SPELLS_CHANGED"}, + events = {"SPELLS_CHANGED", "UNIT_PET"}, showExactOption = true }, { @@ -949,7 +953,7 @@ Private.load_prototype = { display = WeakAuras.newFeatureString .. L["|cFFFF0000Not|r Spell Known"], type = "spell", test = "not WeakAuras.IsSpellKnownForLoad(%s, %s)", - events = {"SPELLS_CHANGED"}, + events = {"SPELLS_CHANGED", "UNIT_PET"}, showExactOption = true }, { @@ -1835,7 +1839,7 @@ Private.event_prototypes = { }, { name = "deficit", - display = WeakAuras.newFeatureString .. L["Health Deficit"], + display = L["Health Deficit"], type = "number", init = "total - value", store = true, @@ -1965,7 +1969,7 @@ Private.event_prototypes = { }, { name = "includePets", - display = WeakAuras.newFeatureString .. L["Include Pets"], + display = L["Include Pets"], type = "select", values = "include_pets_types", width = WeakAuras.normalWidth, @@ -2175,7 +2179,7 @@ Private.event_prototypes = { }, { name = "deficit", - display = WeakAuras.newFeatureString .. L["Power Deficit"], + display = L["Power Deficit"], type = "number", init = "total - value", store = true, @@ -2305,7 +2309,7 @@ Private.event_prototypes = { }, { name = "includePets", - display = WeakAuras.newFeatureString .. L["Include Pets"], + display = L["Include Pets"], type = "select", values = "include_pets_types", width = WeakAuras.normalWidth, @@ -2473,6 +2477,35 @@ Private.event_prototypes = { return state and state.show and WeakAuras.CheckCombatLogFlagsObjectType(state.sourceFlags, needle); end }, + { + name = "sourceRaidFlags", + display = L["Source Raid Mark"], + type = "select", + values = "combatlog_raid_mark_check_type", + init = "arg", + store = true, + test = "WeakAuras.CheckRaidFlags(sourceRaidFlags, %q)", + conditionType = "select", + conditionTest = function(state, needle) + return state and state.show and WeakAuras.CheckRaidFlags(state.sourceRaidFlags, needle); + end + }, + { + name = "sourceRaidMarkIndex", + display = WeakAuras.newFeatureString .. L["Source unit's raid mark index"], + init = "WeakAuras.RaidFlagToIndex(sourceRaidFlags)", + test = "true", + store = true, + hidden = true, + }, + { + name = "sourceRaidMark", + display = WeakAuras.newFeatureString .. L["Source unit's raid mark texture"], + test = "true", + init = "sourceRaidMarkIndex > 0 and '{rt'..sourceRaidMarkIndex..'}' or ''", + store = true, + hidden = true, + }, { type = "header", name = "destHeader", @@ -2590,6 +2623,54 @@ Private.event_prototypes = { return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); end, }, + { -- destFlags ignore for SPELL_CAST_START + enable = function(trigger) + return (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); + end, + }, + { + name = "destRaidFlags", + display = L["Dest Raid Mark"], + type = "select", + values = "combatlog_raid_mark_check_type", + init = "arg", + store = true, + test = "WeakAuras.CheckRaidFlags(destRaidFlags, %q)", + conditionType = "select", + conditionTest = function(state, needle) + return state and state.show and WeakAuras.CheckRaidFlags(state.destRaidFlags, needle); + end, + enable = function(trigger) + return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); + end, + }, + { -- destRaidFlags ignore for SPELL_CAST_START + enable = function(trigger) + return (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); + end + }, + { + name = "destRaidMarkIndex", + display = WeakAuras.newFeatureString .. L["Destination unit's raid mark index"], + init = "WeakAuras.RaidFlagToIndex(destRaidFlags)", + test = "true", + store = true, + hidden = true, + enable = function(trigger) + return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); + end, + }, + { + name = "destRaidMark", + display = WeakAuras.newFeatureString .. L["Destination unit's raid mark texture"], + test = "true", + init = "destRaidMarkIndex > 0 and '{rt'..destRaidMarkIndex..'}' or ''", + store = true, + hidden = true, + enable = function(trigger) + return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); + end, + }, {-- destFlags ignore for SPELL_CAST_START enable = function(trigger) return (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -2669,7 +2750,7 @@ Private.event_prototypes = { }, { name = "spellSchool", - display = WeakAuras.newFeatureString .. L["Spell School"], + display = L["Spell School"], type = "select", values = "combatlog_spell_school_types_for_ui", sorted = true, @@ -5594,7 +5675,7 @@ Private.event_prototypes = { threatpct, rawthreatpct, threatvalue, threattotal = 100, 100, 0, 100 end ]]; - return ret; + return ret .. unitHelperFunctions.SpecificUnitCheck(trigger); end, canHaveDuration = true, statesParameter = "unit", @@ -5688,6 +5769,10 @@ Private.event_prototypes = { { hidden = true, test = "status ~= nil and ok" + }, + { + hidden = true, + test = "WeakAuras.UnitExistsFixed(unit, smart) and specificUnitCheck" } }, automaticrequired = true @@ -6126,7 +6211,7 @@ Private.event_prototypes = { }, { name = "includePets", - display = WeakAuras.newFeatureString .. L["Include Pets"], + display = L["Include Pets"], type = "select", values = "include_pets_types", width = WeakAuras.normalWidth, diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 1fc87c9..7570f88 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 54ad403..e9877cc 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras @@ -1096,6 +1096,11 @@ local function modify(parent, region, data) end controlPoint:SetWidth(regionData.dimensions.width) controlPoint:SetHeight(regionData.dimensions.height) + if data.anchorFrameParent then + controlPoint:SetParent(frame == "" and self.relativeTo or frame) + else + controlPoint:SetParent(self) + end if self.anchorPerUnit == "UNITFRAME" then Private.dyngroup_unitframe_monitor[regionData] = frame end diff --git a/WeakAuras/RegionTypes/Group.lua b/WeakAuras/RegionTypes/Group.lua index 1ed9f39..6006e4d 100644 --- a/WeakAuras/RegionTypes/Group.lua +++ b/WeakAuras/RegionTypes/Group.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index ea071cb..dac8480 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L diff --git a/WeakAuras/RegionTypes/Model.lua b/WeakAuras/RegionTypes/Model.lua index 73db987..7a5a4ea 100644 --- a/WeakAuras/RegionTypes/Model.lua +++ b/WeakAuras/RegionTypes/Model.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index cf188e4..e7ad55d 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index 443d1c8..8929f52 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras; @@ -757,8 +757,8 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare region.subRegionEvents:Notify("PreHide") if region:IsProtected() then if InCombatLockdown() then - Private.AuraWarnings.UpdateWarning(uid, "protected_frame", "error", - L["Cannot hide secure frame in combat lockdown. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Protected-Frames"], + Private.AuraWarnings.UpdateWarning(uid, "protected_frame_error", "error", + L["Cannot change secure frame in combat lockdown. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Protected-Frames"], true) else Private.AuraWarnings.UpdateWarning(uid, "protected_frame", "warning", @@ -788,8 +788,8 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare if region:IsProtected() then if InCombatLockdown() then - Private.AuraWarnings.UpdateWarning(uid, "protected_frame", "error", - L["Cannot hide secure frame in combat lockdown. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Protected-Frames"], + Private.AuraWarnings.UpdateWarning(uid, "protected_frame_error", "error", + L["Cannot change secure frame in combat lockdown. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Protected-Frames"], true) else Private.AuraWarnings.UpdateWarning(uid, "protected_frame", "warning", @@ -843,8 +843,8 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare Private.ApplyFrameLevel(region) if region:IsProtected() then if InCombatLockdown() then - Private.AuraWarnings.UpdateWarning(uid, "protected_frame", "error", - L["Cannot show secure frame in combat lockdown. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Protected-Frames"], + Private.AuraWarnings.UpdateWarning(uid, "protected_frame_error", "error", + L["Cannot change secure frame in combat lockdown. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Protected-Frames"], true) else Private.AuraWarnings.UpdateWarning(uid, "protected_frame", "warning", @@ -912,8 +912,8 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare if region:IsProtected() then if InCombatLockdown() then - Private.AuraWarnings.UpdateWarning(uid, "protected_frame", "error", - L["Cannot show secure frame in combat lockdown. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Protected-Frames"], + Private.AuraWarnings.UpdateWarning(uid, "protected_frame_error", "error", + L["Cannot change secure frame in combat lockdown. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Protected-Frames"], true) else Private.AuraWarnings.UpdateWarning(uid, "protected_frame", "warning", diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index f598a3b..028a818 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local texture_data = WeakAuras.StopMotion.texture_data; diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index 33df1e4..baf2b94 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAuras/RegionTypes/Texture.lua b/WeakAuras/RegionTypes/Texture.lua index aa6f1ad..e019666 100644 --- a/WeakAuras/RegionTypes/Texture.lua +++ b/WeakAuras/RegionTypes/Texture.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; diff --git a/WeakAuras/SubRegionTypes/Background.lua b/WeakAuras/SubRegionTypes/Background.lua index 97bf3a0..229427f 100644 --- a/WeakAuras/SubRegionTypes/Background.lua +++ b/WeakAuras/SubRegionTypes/Background.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; diff --git a/WeakAuras/SubRegionTypes/Border.lua b/WeakAuras/SubRegionTypes/Border.lua index d1d3984..0a82835 100644 --- a/WeakAuras/SubRegionTypes/Border.lua +++ b/WeakAuras/SubRegionTypes/Border.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAuras/SubRegionTypes/Glow.lua b/WeakAuras/SubRegionTypes/Glow.lua index 4592fa3..a5d8bc0 100644 --- a/WeakAuras/SubRegionTypes/Glow.lua +++ b/WeakAuras/SubRegionTypes/Glow.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local LCG = LibStub("LibCustomGlow-1.0") diff --git a/WeakAuras/SubRegionTypes/Model.lua b/WeakAuras/SubRegionTypes/Model.lua index 211e32b..b8d0bc4 100644 --- a/WeakAuras/SubRegionTypes/Model.lua +++ b/WeakAuras/SubRegionTypes/Model.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index 81e55a1..c7842df 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAuras/SubRegionTypes/Tick.lua b/WeakAuras/SubRegionTypes/Tick.lua index c9f567a..9aa6ae8 100644 --- a/WeakAuras/SubRegionTypes/Tick.lua +++ b/WeakAuras/SubRegionTypes/Tick.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 3094c18..0981c98 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -18,7 +18,7 @@ Imports an aura from a table, which may or may not be encoded as a B64 string. If target is installed data, or is a uid which points to installed data, then the import will be an update to that aura ]]-- -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- Lua APIs diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 0c76851..2eba5bd 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras; @@ -1168,6 +1168,18 @@ Private.combatlog_raid_mark_check_type = { L["Any"] } +Private.combatlog_raidFlags = { + [0] = 0, + [1] = 1, + [2] = 2, + [4] = 3, + [8] = 4, + [16] = 5, + [32] = 6, + [64] = 7, + [128] = 8, +} + Private.raid_mark_check_type = CopyTable(Private.combatlog_raid_mark_check_type) Private.raid_mark_check_type[9] = nil @@ -2620,6 +2632,7 @@ Private.author_option_fields = { hideReorder = true, entryNames = nil, -- handled as a special case in code subOptions = {}, + noMerge = false, } } @@ -2753,11 +2766,13 @@ Private.reset_swing_spells = { [GetSpellInfo(6807)] = true, -- Maul [GetSpellInfo(20549)] = true, -- War Stomp [GetSpellInfo(56815)] = true, -- Rune Strike + [GetSpellInfo(5384)] = true, -- Feign Death } Private.reset_ranged_swing_spells = { [GetSpellInfo(2764)] = true, -- Throw [GetSpellInfo(5019)] = true, -- Shoot Wands [GetSpellInfo(75)] = true, -- Auto Shot + [GetSpellInfo(5384)] = true, -- Feign Death } WeakAuras.StopMotion = {} diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index c778430..a592435 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -107,10 +107,6 @@ end SLASH_WEAKAURAS1, SLASH_WEAKAURAS2 = "/weakauras", "/wa"; function SlashCmdList.WEAKAURAS(input) - if not WeakAuras.IsCorrectVersion() then - prettyPrint(Private.wrongTargetMessage) - return - end local args, msg = {}, nil @@ -141,7 +137,7 @@ function SlashCmdList.WEAKAURAS(input) end end -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end function Private.ToggleMinimap() WeakAurasSaved.minimap.hide = not WeakAurasSaved.minimap.hide @@ -2311,8 +2307,6 @@ local function removeNameplateUnits(data) if trigger and trigger.type == "unit" then if trigger.unit == "nameplate" then trigger.unit = "target" - elseif trigger.threatUnit == "nameplate" then - trigger.threatUnit = "target" end end end @@ -3020,12 +3014,15 @@ do if new_frame and new_frame ~= data.frame then local id = region.id .. (region.cloneId or "") -- remove previous glow - actionGlowStop(data.actions, data.frame, id) + if data.frame then + actionGlowStop(data.actions, data.frame, id) + end -- apply the glow to new_frame data.frame = new_frame actionGlowStart(data.actions, data.frame, id) -- update hidefunc local region = region + region.active_glows_hidefunc = region.active_glows_hidefunc or {} region.active_glows_hidefunc[data.frame] = function() actionGlowStop(data.actions, data.frame, id) glow_frame_monitor[region] = nil @@ -3081,7 +3078,7 @@ function Private.HandleGlowAction(actions, region) or (actions.glow_frame_type == "FRAMESELECTOR" and actions.glow_frame) ) then - local glow_frame + local glow_frame, should_glow_frame if actions.glow_frame_type == "FRAMESELECTOR" then if actions.glow_frame:sub(1, 10) == "WeakAuras:" then local frame_name = actions.glow_frame:sub(11) @@ -3090,45 +3087,55 @@ function Private.HandleGlowAction(actions, region) end if WeakAuras.regions[frame_name] then glow_frame = WeakAuras.regions[frame_name].region + should_glow_frame = true end else glow_frame = Private.GetSanitizedGlobal(actions.glow_frame) + should_glow_frame = true end elseif actions.glow_frame_type == "UNITFRAME" and region.state.unit then glow_frame = WeakAuras.GetUnitFrame(region.state.unit) + should_glow_frame = true elseif actions.glow_frame_type == "NAMEPLATE" and region.state.unit then - glow_frame = WeakAuras.isAwesomeEnabled() and WeakAuras.GetNamePlateForUnit(region.state.unit) or nil + if not(WeakAuras.isAwesomeEnabled()) then return end + glow_frame = WeakAuras.GetNamePlateForUnit(region.state.unit) + should_glow_frame = true end - if glow_frame then + if should_glow_frame then local id = region.id .. (region.cloneId or "") if actions.glow_action == "show" then -- remove previous glow - if region.active_glows_hidefunc - and region.active_glows_hidefunc[glow_frame] - then - region.active_glows_hidefunc[glow_frame]() + if glow_frame then + if region.active_glows_hidefunc + and region.active_glows_hidefunc[glow_frame] + then + region.active_glows_hidefunc[glow_frame]() + end + -- start glow + actionGlowStart(actions, glow_frame, id) + -- make unglow function & monitor unitframe changes + region.active_glows_hidefunc = region.active_glows_hidefunc or {} + if actions.glow_frame_type == "UNITFRAME" then + region.active_glows_hidefunc[glow_frame] = function() + actionGlowStop(actions, glow_frame, id) + glow_frame_monitor[region] = nil + end + else + region.active_glows_hidefunc[glow_frame] = function() + actionGlowStop(actions, glow_frame, id) + end + end end - -- start glow - actionGlowStart(actions, glow_frame, id) - -- make unglow function & monitor unitframe changes - region.active_glows_hidefunc = region.active_glows_hidefunc or {} if actions.glow_frame_type == "UNITFRAME" then glow_frame_monitor = glow_frame_monitor or {} glow_frame_monitor[region] = { actions = actions, frame = glow_frame } - region.active_glows_hidefunc[glow_frame] = function() - actionGlowStop(actions, glow_frame, id) - glow_frame_monitor[region] = nil - end - else - region.active_glows_hidefunc[glow_frame] = function() - actionGlowStop(actions, glow_frame, id) - end end elseif actions.glow_action == "hide" + and glow_frame and region.active_glows_hidefunc and region.active_glows_hidefunc[glow_frame] then diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasInlineGroup.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasInlineGroup.lua index 4dce5a5..fe78a51 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasInlineGroup.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasInlineGroup.lua @@ -3,7 +3,9 @@ WeakAurasInlineGroup based on InlineGroup Container Simple container widget that has the same API as a InlineGroup, without actually showing any borders or a title. -------------------------------------------------------------------------------]] -local Type, Version = "WeakAurasInlineGroup", 1 +if not WeakAuras.IsLibsOK() then return end + +local Type, Version = "WeakAurasInlineGroup", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasTreeGroup.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasTreeGroup.lua index 1fb5ff2..bb9ff11 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasTreeGroup.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIContainer-WeakAurasTreeGroup.lua @@ -3,9 +3,9 @@ WeakAurasTreeGroup Container Container that uses a tree control to switch between groups. This file was forked from AceGUIContainer-TreeGroup.lua version 41 -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasTreeGroup", 2 +local Type, Version = "WeakAurasTreeGroup", 3 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasAnchorButtons.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasAnchorButtons.lua index 773881a..743faaa 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasAnchorButtons.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasAnchorButtons.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasAnchorButtons", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index 72ba348..4f455cc 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local tinsert, tremove, wipe = table.insert, table.remove, wipe diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua index 3fee718..7fa0556 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua @@ -1,9 +1,9 @@ --[[----------------------------------------------------------------------------- Button Widget for our Expand button -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasExpand", 3 +local Type, Version = "WeakAurasExpand", 4 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandAnchor.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandAnchor.lua index a4bb427..2ff8593 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandAnchor.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandAnchor.lua @@ -1,9 +1,9 @@ --[[----------------------------------------------------------------------------- Anchor for a Expandable section -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -local Type, Version = "WeakAurasExpandAnchor", 2 +local Type, Version = "WeakAurasExpandAnchor", 3 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua index 1e7dd7f..ced766b 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpandSmall.lua @@ -1,10 +1,10 @@ --[[----------------------------------------------------------------------------- Button Widget for our Expand button -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -local Type, Version = "WeakAurasExpandSmall", 2 +local Type, Version = "WeakAurasExpandSmall", 3 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIcon.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIcon.lua index bd164aa..99f4db4 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIcon.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIcon.lua @@ -3,9 +3,9 @@ Icon Widget that allows for a tooltip, by preventing SetLabel from actually setting a label Graphical Button. -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasIcon", 1 +local Type, Version = "WeakAurasIcon", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIconButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIconButton.lua index 13a0724..917a3c1 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIconButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasIconButton.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasIconButton", 21 +local Type, Version = "WeakAurasIconButton", 22 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasImportButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasImportButton.lua index c372f97..8d0ce8d 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasImportButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasImportButton.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasImportButton", 20 +local Type, Version = "WeakAurasImportButton", 21 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasInputFocus.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasInputFocus.lua index 478c58e..411aef0 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasInputFocus.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasInputFocus.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- Input Widget that allows to show an alternative text when it does not have focus -------------------------------------------------------------------------------]] -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasInputFocus", 1 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasLoadedHeaderButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasLoadedHeaderButton.lua index 3e0fadd..af1420c 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasLoadedHeaderButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasLoadedHeaderButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasLoadedHeaderButton", 22 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBox.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBox.lua index 2a6a67b..73b68df 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBox.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBox.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasMultiLineEditBox", 35 +local Type, Version = "WeakAurasMultiLineEditBox", 36 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBoxWithEnter.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBoxWithEnter.lua index 3fd968c..3e19416 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBoxWithEnter.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMultiLineEditBoxWithEnter.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -- based on the AceGUI widget, overwrites the enter handling local Type, Version = "WeakAuras-MultiLineEditBoxWithEnter", 1 diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua index 32099fb..3bc471e 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasNewButton", 24 +local Type, Version = "WeakAurasNewButton", 25 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewHeaderButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewHeaderButton.lua index 6d489e5..543a824 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewHeaderButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewHeaderButton.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasNewHeaderButton", 20 +local Type, Version = "WeakAurasNewHeaderButton", 21 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua index efc06b5..5fa6423 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua @@ -1,12 +1,10 @@ -if not WeakAuras.IsCorrectVersion() then - return -end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local pairs, next, type, unpack = pairs, next, type, unpack -local Type, Version = "WeakAurasPendingInstallButton", 2 +local Type, Version = "WeakAurasPendingInstallButton", 3 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua index e2e4ff5..ea4d608 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua @@ -1,13 +1,11 @@ -if not WeakAuras.IsCorrectVersion() then - return -end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L local pairs, next, type, unpack = pairs, next, type, unpack -local Type, Version = "WeakAurasPendingUpdateButton", 2 +local Type, Version = "WeakAurasPendingUpdateButton", 3 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSnippetButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSnippetButton.lua index 21354e3..e884910 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSnippetButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSnippetButton.lua @@ -2,7 +2,9 @@ SnippetButton Widget, based on AceGUI Button (and WA ToolbarButton) Graphical Button. -------------------------------------------------------------------------------]] -local Type, Version = "WeakAurasSnippetButton", 1 +if not WeakAuras.IsLibsOK() then return end + +local Type, Version = "WeakAurasSnippetButton", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSpacer.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSpacer.lua index f05d179..031522c 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSpacer.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSpacer.lua @@ -2,7 +2,9 @@ Spacer Widget Just uses up a bit of horizontal space -------------------------------------------------------------------------------]] -local Type, Version = "WeakAurasSpacer", 1 +if not WeakAuras.IsLibsOK() then return end + +local Type, Version = "WeakAurasSpacer", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSpinBox.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSpinBox.lua index 7864a06..92e119a 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSpinBox.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasSpinBox.lua @@ -1,6 +1,8 @@ --[[----------------------------------------------------------------------------- Spin Box Widget -------------------------------------------------------------------------------]] +if not WeakAuras.IsLibsOK() then return end + local Type, Version = "WeakAurasSpinBox", 5 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua index b321578..6d58a2a 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local Type, Version = "WeakAurasTextureButton", 25 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasToolbarButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasToolbarButton.lua index 745ccc2..11c8c55 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasToolbarButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasToolbarButton.lua @@ -2,6 +2,8 @@ ToolbarButton Widget, based on AceGUI Button Graphical Button. -------------------------------------------------------------------------------]] +if not WeakAuras.IsLibsOK() then return end + local Type, Version = "WeakAurasToolbarButton", 6 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua index 5a99a04..869a22b 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua @@ -1,6 +1,6 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasTwoColumnDropdown", 3 +local Type, Version = "WeakAurasTwoColumnDropdown", 4 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGuiWidget-WeakAurasProgressBar.lua b/WeakAurasOptions/AceGUI-Widgets/AceGuiWidget-WeakAurasProgressBar.lua index 809e95c..65d281b 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGuiWidget-WeakAurasProgressBar.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGuiWidget-WeakAurasProgressBar.lua @@ -2,7 +2,9 @@ Progress Bar Widget A simple progress bar -------------------------------------------------------------------------------]] -local Type, Version = "WeakAurasProgressBar", 1 +if not WeakAuras.IsLibsOK() then return end + +local Type, Version = "WeakAurasProgressBar", 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/ActionOptions.lua b/WeakAurasOptions/ActionOptions.lua index 8779964..4019d72 100644 --- a/WeakAurasOptions/ActionOptions.lua +++ b/WeakAurasOptions/ActionOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/AnimationOptions.lua b/WeakAurasOptions/AnimationOptions.lua index 5d4796c..e237efe 100644 --- a/WeakAurasOptions/AnimationOptions.lua +++ b/WeakAurasOptions/AnimationOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index fb86688..42c4018 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -58,7 +58,7 @@ bigStep (optional) -> step size of the slider. Defaults to 0.05 step (optional) -> like bigStep, but applies to number input as well ]] -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local WeakAuras = WeakAuras @@ -1180,6 +1180,15 @@ typeControlAdders = { end, disabled = function() return not option.useCollapse end } + args[prefix .. "noMerge"] = { + type = "toggle", + name = WeakAuras.newFeatureString .. name(option, "noMerge", L["Prevent Merging"]), + desc = desc(option, "noMerge", L["If checked, then this group will not merge with other group when selecting multiple auras."]), + order = order(), + width = WeakAuras.doubleWidth, + get = get(option, "noMerge"), + set = set(data, option, "noMerge"), + } if option.groupType ~="simple" then args[prefix .. "limitType"] = { type = "select", @@ -1998,7 +2007,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) while i <= #values or i <= #childValues do if firstChild then values[i] = childValues[i][nameSource] or conflictBlue .. L["Entry %i"]:format(i) - elseif childValues[i][nameSource] ~= values[i] then + elseif not childValues[i] or childValues[i][nameSource] ~= values[i] then values[i] = conflictBlue .. L["Entry %i"]:format(i) end i = i + 1 @@ -2106,6 +2115,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) type = "execute", name = L["Delete Entry"], order = order(), + confirm = true, func = function() for id, optionData in pairs(option.references) do local childOption = optionData.options[optionData.index] diff --git a/WeakAurasOptions/BuffTrigger.lua b/WeakAurasOptions/BuffTrigger.lua index 521d829..e9f0013 100644 --- a/WeakAurasOptions/BuffTrigger.lua +++ b/WeakAurasOptions/BuffTrigger.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index 41a8917..949f677 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L @@ -687,7 +687,7 @@ local function GetBuffTriggerOptions(data, triggernum) use_includePets = { type = "toggle", width = WeakAuras.normalWidth, - name = WeakAuras.newFeatureString .. L["Include Pets"], + name = L["Include Pets"], order = 66.1, hidden = function() return not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party")) @@ -697,7 +697,7 @@ local function GetBuffTriggerOptions(data, triggernum) type = "select", values = OptionsPrivate.Private.include_pets_types, width = WeakAuras.normalWidth, - name = WeakAuras.newFeatureString .. L["Include Pets"], + name = L["Include Pets"], order = 66.15, hidden = function() return not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party") and trigger.use_includePets) end, }, diff --git a/WeakAurasOptions/Cache.lua b/WeakAurasOptions/Cache.lua index fbe94da..b036ff9 100644 --- a/WeakAurasOptions/Cache.lua +++ b/WeakAurasOptions/Cache.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index bdd05cb..2c9b6ed 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L @@ -1072,7 +1072,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g return data.anchorFrameParent or data.anchorFrameParent == nil; end, hidden = function() - return (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE" or IsParentDynamicGroup()); + return not IsGroupByFrame() and (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE" or IsParentDynamicGroup()); end, }, anchorFrameSpaceOne = { @@ -1082,7 +1082,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g order = 72, image = function() return "", 0, 0 end, hidden = function() - return IsParentDynamicGroup() or IsGroupByFrame() or not (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE") + return IsParentDynamicGroup() or not (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE") end, }, -- Input field to select frame to anchor on @@ -1142,6 +1142,9 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g if IsGroupByFrame() then return false end + if IsParentDynamicGroup() then + return true + end return data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE"; else return data.anchorFrameType == "MOUSE"; diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 5b15861..44be1bf 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -44,7 +44,7 @@ -- - setter: The setter function, called both on activating and deactivating a property change --- - action: The action function, called on activating a condition -- - type: The type -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local WeakAuras = WeakAuras; diff --git a/WeakAurasOptions/DisplayOptions.lua b/WeakAurasOptions/DisplayOptions.lua index 19e0149..f9d53c1 100644 --- a/WeakAurasOptions/DisplayOptions.lua +++ b/WeakAurasOptions/DisplayOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L local regionOptions = WeakAuras.regionOptions diff --git a/WeakAurasOptions/ForAllIndentsAndPurposes.lua b/WeakAurasOptions/ForAllIndentsAndPurposes.lua index 0e6bc72..10d90ab 100644 --- a/WeakAurasOptions/ForAllIndentsAndPurposes.lua +++ b/WeakAurasOptions/ForAllIndentsAndPurposes.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end -- For All Indents And Purposes local revision = 23 diff --git a/WeakAurasOptions/GenericTrigger.lua b/WeakAurasOptions/GenericTrigger.lua index 5dbbd0c..883f924 100644 --- a/WeakAurasOptions/GenericTrigger.lua +++ b/WeakAurasOptions/GenericTrigger.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/GroupOptions.lua b/WeakAurasOptions/GroupOptions.lua index d45c55c..817be4f 100644 --- a/WeakAurasOptions/GroupOptions.lua +++ b/WeakAurasOptions/GroupOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index e8a7e6b..73ed612 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/LoadOptions.lua b/WeakAurasOptions/LoadOptions.lua index 3d52dec..e27e3eb 100644 --- a/WeakAurasOptions/LoadOptions.lua +++ b/WeakAurasOptions/LoadOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/Locales/deDE.lua b/WeakAurasOptions/Locales/deDE.lua index 708bffb..3deca55 100644 --- a/WeakAurasOptions/Locales/deDE.lua +++ b/WeakAurasOptions/Locales/deDE.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "deDE" then return diff --git a/WeakAurasOptions/Locales/enUS.lua b/WeakAurasOptions/Locales/enUS.lua index 8d00390..b3710df 100644 --- a/WeakAurasOptions/Locales/enUS.lua +++ b/WeakAurasOptions/Locales/enUS.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local L = WeakAuras.L diff --git a/WeakAurasOptions/Locales/esES.lua b/WeakAurasOptions/Locales/esES.lua index d468fd7..1fb0d3c 100644 --- a/WeakAurasOptions/Locales/esES.lua +++ b/WeakAurasOptions/Locales/esES.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "esES" then return diff --git a/WeakAurasOptions/Locales/esMX.lua b/WeakAurasOptions/Locales/esMX.lua index 805889c..f67284b 100644 --- a/WeakAurasOptions/Locales/esMX.lua +++ b/WeakAurasOptions/Locales/esMX.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "esMX" then return diff --git a/WeakAurasOptions/Locales/frFR.lua b/WeakAurasOptions/Locales/frFR.lua index d5abaae..75006b6 100644 --- a/WeakAurasOptions/Locales/frFR.lua +++ b/WeakAurasOptions/Locales/frFR.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "frFR" then return diff --git a/WeakAurasOptions/Locales/itIT.lua b/WeakAurasOptions/Locales/itIT.lua index 8ed5bcb..3a3799c 100644 --- a/WeakAurasOptions/Locales/itIT.lua +++ b/WeakAurasOptions/Locales/itIT.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "itIT" then return diff --git a/WeakAurasOptions/Locales/koKR.lua b/WeakAurasOptions/Locales/koKR.lua index ab55e56..937891f 100644 --- a/WeakAurasOptions/Locales/koKR.lua +++ b/WeakAurasOptions/Locales/koKR.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "koKR" then return diff --git a/WeakAurasOptions/Locales/ptBR.lua b/WeakAurasOptions/Locales/ptBR.lua index 1221ac9..86fa1fe 100644 --- a/WeakAurasOptions/Locales/ptBR.lua +++ b/WeakAurasOptions/Locales/ptBR.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "ptBR" then return diff --git a/WeakAurasOptions/Locales/ruRU.lua b/WeakAurasOptions/Locales/ruRU.lua index 14dc68f..6ff248c 100644 --- a/WeakAurasOptions/Locales/ruRU.lua +++ b/WeakAurasOptions/Locales/ruRU.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "ruRU" then return diff --git a/WeakAurasOptions/Locales/zhCN.lua b/WeakAurasOptions/Locales/zhCN.lua index f1ba902..451a066 100644 --- a/WeakAurasOptions/Locales/zhCN.lua +++ b/WeakAurasOptions/Locales/zhCN.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "zhCN" then return diff --git a/WeakAurasOptions/Locales/zhTW.lua b/WeakAurasOptions/Locales/zhTW.lua index 01eaedb..1fef272 100644 --- a/WeakAurasOptions/Locales/zhTW.lua +++ b/WeakAurasOptions/Locales/zhTW.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end if GetLocale() ~= "zhTW" then return diff --git a/WeakAurasOptions/OptionsFrames/CodeReview.lua b/WeakAurasOptions/OptionsFrames/CodeReview.lua index 2f67f7e..697ed10 100644 --- a/WeakAurasOptions/OptionsFrames/CodeReview.lua +++ b/WeakAurasOptions/OptionsFrames/CodeReview.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua b/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua index 836f057..7ea2bdd 100644 --- a/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua +++ b/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- WoW APIs diff --git a/WeakAurasOptions/OptionsFrames/FrameChooser.lua b/WeakAurasOptions/OptionsFrames/FrameChooser.lua index ec95374..ea83896 100644 --- a/WeakAurasOptions/OptionsFrames/FrameChooser.lua +++ b/WeakAurasOptions/OptionsFrames/FrameChooser.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/IconPicker.lua b/WeakAurasOptions/OptionsFrames/IconPicker.lua index 607d7b1..ca243f3 100644 --- a/WeakAurasOptions/OptionsFrames/IconPicker.lua +++ b/WeakAurasOptions/OptionsFrames/IconPicker.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/ImportExport.lua b/WeakAurasOptions/OptionsFrames/ImportExport.lua index 99aa86e..ecc4075 100644 --- a/WeakAurasOptions/OptionsFrames/ImportExport.lua +++ b/WeakAurasOptions/OptionsFrames/ImportExport.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- WoW APIs diff --git a/WeakAurasOptions/OptionsFrames/ModelPicker.lua b/WeakAurasOptions/OptionsFrames/ModelPicker.lua index 0083ca7..43eeaec 100644 --- a/WeakAurasOptions/OptionsFrames/ModelPicker.lua +++ b/WeakAurasOptions/OptionsFrames/ModelPicker.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index 98a54fd..031b766 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index f614d20..e76c8fc 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs @@ -1159,9 +1159,9 @@ function OptionsPrivate.CreateFrame() containerScroll:AddChild(simpleLabel) local button = AceGUI:Create("WeakAurasNewButton") - button:SetTitle(L["From Template"]) + button:SetTitle(L["Premade Auras"]) button:SetDescription(L["Offer a guided way to create auras for your character"]) - button:SetIcon("Interface\\Icons\\INV_Misc_Book_06") + button:SetIcon("Interface\\Icons\\Inv_misc_book_09") button:SetClick(function() OptionsPrivate.OpenTriggerTemplate(nil, self:GetTargetAura()) end) diff --git a/WeakAurasOptions/OptionsFrames/TextEditor.lua b/WeakAurasOptions/OptionsFrames/TextEditor.lua index 41aa503..cf84a36 100644 --- a/WeakAurasOptions/OptionsFrames/TextEditor.lua +++ b/WeakAurasOptions/OptionsFrames/TextEditor.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs @@ -55,6 +55,7 @@ local editor_themes = { } if not WeakAurasSaved.editor_tab_spaces then WeakAurasSaved.editor_tab_spaces = 4 end +if not WeakAurasSaved.editor_font_size then WeakAurasSaved.editor_font_size = 12 end -- set default font size if missing local color_scheme = {[0] = "|r"} local function set_scheme() if not WeakAurasSaved.editor_theme then @@ -162,7 +163,7 @@ local function ConstructTextEditor(frame) editor:DisableButton(true) local fontPath = SharedMedia:Fetch("font", "Fira Mono Medium") if (fontPath) then - editor.editBox:SetFont(fontPath, 12) + editor.editBox:SetFont(fontPath, WeakAurasSaved.editor_font_size) end group:AddChild(editor) @@ -263,6 +264,14 @@ local function ConstructTextEditor(frame) menuList = "spaces" }, level) + UIDropDownMenu_AddButton( + { + text = WeakAuras.newFeatureString .. L["Font Size"], + hasArrow = true, + notCheckable = true, + menuList = "sizes" + }, + level) elseif menu == "spaces" then local spaces = {2,4} for _, i in pairs(spaces) do @@ -282,6 +291,23 @@ local function ConstructTextEditor(frame) }, level) end + elseif menu == "sizes" then + local sizes = {10, 12, 14, 16} + for _, i in pairs(sizes) do + UIDropDownMenu_AddButton( + { + text = i, + isNotRadio = false, + checked = function() + return WeakAurasSaved.editor_font_size == i + end, + func = function() + WeakAurasSaved.editor_font_size = i + editor.editBox:SetFont(fontPath, WeakAurasSaved.editor_font_size) + end + }, + level) + end end end UIDropDownMenu_Initialize(dropdown, settings_dropdown_initialize, "MENU") @@ -475,16 +501,13 @@ local function ConstructTextEditor(frame) end ) - -- CTRL + S saves and closes, ESC cancels and closes + -- CTRL + S saves and closes editor.editBox:HookScript( "OnKeyDown", function(_, key) if IsControlKeyDown() and key == "S" then group:Close() end - if key == "ESCAPE" then - group:CancelClose() - end end ) diff --git a/WeakAurasOptions/OptionsFrames/TexturePicker.lua b/WeakAurasOptions/OptionsFrames/TexturePicker.lua index ba5452b..8860ae5 100644 --- a/WeakAurasOptions/OptionsFrames/TexturePicker.lua +++ b/WeakAurasOptions/OptionsFrames/TexturePicker.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index f36a709..30090d1 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local AceGUI = LibStub("AceGUI-3.0") diff --git a/WeakAurasOptions/RegionOptions/AuraBar.lua b/WeakAurasOptions/RegionOptions/AuraBar.lua index a3dc351..47c0517 100644 --- a/WeakAurasOptions/RegionOptions/AuraBar.lua +++ b/WeakAurasOptions/RegionOptions/AuraBar.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 9621fa8..b4d0b3f 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index cc73a21..641371a 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; @@ -413,7 +413,7 @@ local function createDistributeAlignOptions(id, data) local childData = WeakAuras.GetData(childId); local childRegion = WeakAuras.GetRegion(childId) if(childData and childRegion) then - if(v > 0) then + if(v >= 0) then if(childData.selfPoint:find("LEFT")) then childData.xOffset = xOffset; elseif(childData.selfPoint:find("RIGHT")) then @@ -497,7 +497,7 @@ local function createDistributeAlignOptions(id, data) local childData = WeakAuras.GetData(childId); local childRegion = WeakAuras.GetRegion(childId) if(childData and childRegion) then - if(v > 0) then + if(v >= 0) then if(childData.selfPoint:find("BOTTOM")) then childData.yOffset = yOffset; elseif(childData.selfPoint:find("TOP")) then diff --git a/WeakAurasOptions/RegionOptions/Icon.lua b/WeakAurasOptions/RegionOptions/Icon.lua index b278530..538cd95 100644 --- a/WeakAurasOptions/RegionOptions/Icon.lua +++ b/WeakAurasOptions/RegionOptions/Icon.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local Masque = LibStub("Masque", true) diff --git a/WeakAurasOptions/RegionOptions/Model.lua b/WeakAurasOptions/RegionOptions/Model.lua index 2e210b1..d17d866 100644 --- a/WeakAurasOptions/RegionOptions/Model.lua +++ b/WeakAurasOptions/RegionOptions/Model.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index 25fe782..01a0625 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/RegionOptions/StopMotion.lua b/WeakAurasOptions/RegionOptions/StopMotion.lua index 8f0b5d8..b31374c 100644 --- a/WeakAurasOptions/RegionOptions/StopMotion.lua +++ b/WeakAurasOptions/RegionOptions/StopMotion.lua @@ -1,3 +1,5 @@ +if not WeakAuras.IsLibsOK() then return end + local L = WeakAuras.L local AddonName, OptionsPrivate = ... diff --git a/WeakAurasOptions/RegionOptions/Text.lua b/WeakAurasOptions/RegionOptions/Text.lua index faf0311..25cd9f7 100644 --- a/WeakAurasOptions/RegionOptions/Text.lua +++ b/WeakAurasOptions/RegionOptions/Text.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local SharedMedia = LibStub("LibSharedMedia-3.0"); diff --git a/WeakAurasOptions/RegionOptions/Texture.lua b/WeakAurasOptions/RegionOptions/Texture.lua index e84616b..e07ce47 100644 --- a/WeakAurasOptions/RegionOptions/Texture.lua +++ b/WeakAurasOptions/RegionOptions/Texture.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/SubRegionOptions/Background.lua b/WeakAurasOptions/SubRegionOptions/Background.lua index ec8ea5f..8ed24ca 100644 --- a/WeakAurasOptions/SubRegionOptions/Background.lua +++ b/WeakAurasOptions/SubRegionOptions/Background.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/SubRegionOptions/Border.lua b/WeakAurasOptions/SubRegionOptions/Border.lua index 830d441..fd12637 100644 --- a/WeakAurasOptions/SubRegionOptions/Border.lua +++ b/WeakAurasOptions/SubRegionOptions/Border.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/SubRegionOptions/Glow.lua b/WeakAurasOptions/SubRegionOptions/Glow.lua index ce9bc01..1eff8fc 100644 --- a/WeakAurasOptions/SubRegionOptions/Glow.lua +++ b/WeakAurasOptions/SubRegionOptions/Glow.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/SubRegionOptions/Model.lua b/WeakAurasOptions/SubRegionOptions/Model.lua index 19a4a67..7384163 100644 --- a/WeakAurasOptions/SubRegionOptions/Model.lua +++ b/WeakAurasOptions/SubRegionOptions/Model.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua b/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua index 24fb49b..8197233 100644 --- a/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua +++ b/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Magic constant diff --git a/WeakAurasOptions/SubRegionOptions/SubText.lua b/WeakAurasOptions/SubRegionOptions/SubText.lua index e492dc7..765250d 100644 --- a/WeakAurasOptions/SubRegionOptions/SubText.lua +++ b/WeakAurasOptions/SubRegionOptions/SubText.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/SubRegionOptions/Tick.lua b/WeakAurasOptions/SubRegionOptions/Tick.lua index e6591f6..fd88de7 100644 --- a/WeakAurasOptions/SubRegionOptions/Tick.lua +++ b/WeakAurasOptions/SubRegionOptions/Tick.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L; diff --git a/WeakAurasOptions/TriggerOptions.lua b/WeakAurasOptions/TriggerOptions.lua index 5dfca41..6236ba5 100644 --- a/WeakAurasOptions/TriggerOptions.lua +++ b/WeakAurasOptions/TriggerOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index eb401a4..15bf849 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -1,4 +1,4 @@ -if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... -- Lua APIs From 74a1a856ac5ac6b1fc8e553263097dcc40b3f0e3 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Tue, 7 Jan 2025 15:03:14 +0100 Subject: [PATCH 006/153] from retail --- WeakAuras/Animations.lua | 17 ++++-- WeakAuras/AuraEnvironment.lua | 6 +- WeakAuras/Conditions.lua | 10 ++-- WeakAuras/GenericTrigger.lua | 60 +++++++++---------- WeakAuras/RegionTypes/DynamicGroup.lua | 13 +++-- WeakAuras/RegionTypes/RegionPrototype.lua | 6 +- WeakAuras/RegionTypes/Text.lua | 2 +- WeakAuras/SubRegionTypes/SubText.lua | 2 +- WeakAuras/WeakAuras.lua | 71 +++++++++++++++++------ 9 files changed, 115 insertions(+), 72 deletions(-) diff --git a/WeakAuras/Animations.lua b/WeakAuras/Animations.lua index 1a98194..59a10a2 100644 --- a/WeakAuras/Animations.lua +++ b/WeakAuras/Animations.lua @@ -1,5 +1,6 @@ if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... +local L = WeakAuras.L -- Animations local animations = {} @@ -14,7 +15,6 @@ local updatingAnimations; local last_update = GetTime(); local function UpdateAnimations() Private.StartProfileSystem("animations"); - local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or geterrorhandler() for groupUid, groupRegion in pairs(pending_controls) do pending_controls[groupUid] = nil; groupRegion:DoPositionChildren(); @@ -72,6 +72,7 @@ local function UpdateAnimations() progress = anim.easeFunc(progress, anim.easeStrength or 3) Private.ActivateAuraEnvironmentForRegion(anim.region) if(anim.translateFunc) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Slide Animation"]) if (anim.region.SetOffsetAnim) then local ok, x, y = pcall(anim.translateFunc, progress, 0, 0, anim.dX, anim.dY); if not ok then @@ -90,6 +91,7 @@ local function UpdateAnimations() end end if(anim.alphaFunc) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Fade Animation"]) local ok, alpha = pcall(anim.alphaFunc, progress, anim.startAlpha, anim.dAlpha); if not ok then errorHandler(alpha) @@ -102,6 +104,7 @@ local function UpdateAnimations() end end if(anim.scaleFunc) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Zoom Animation"]) local ok, scaleX, scaleY = pcall(anim.scaleFunc, progress, 1, 1, anim.scaleX, anim.scaleY); if not ok then errorHandler(scaleX) @@ -115,6 +118,7 @@ local function UpdateAnimations() end end if(anim.rotateFunc and anim.region.Rotate) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Rotate Animation"]) local ok, rotate = pcall(anim.rotateFunc, progress, anim.startRotation, anim.rotate); if not ok then errorHandler(rotate) @@ -123,6 +127,7 @@ local function UpdateAnimations() end end if(anim.colorFunc and anim.region.ColorAnim) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Color Animation"]) local startR, startG, startB, startA = anim.region:GetColor(); startR, startG, startB, startA = startR or 1, startG or 1, startB or 1, startA or 1; local ok, r, g, b, a = pcall(anim.colorFunc, progress, startR, startG, startB, startA, anim.colorR, anim.colorG, anim.colorB, anim.colorA); @@ -240,7 +245,7 @@ function Private.Animate(namespace, uid, type, anim, region, inverse, onFinished anim.translateFunc = anim_function_strings[anim.translateType] end if (anim.translateFunc) then - translateFunc = WeakAuras.LoadFunction("return " .. anim.translateFunc, auraDisplayName, "translate animation"); + translateFunc = WeakAuras.LoadFunction("return " .. anim.translateFunc); else if (region.SetOffsetAnim) then region:SetOffsetAnim(0, 0); @@ -261,7 +266,7 @@ function Private.Animate(namespace, uid, type, anim, region, inverse, onFinished anim.alphaFunc = anim_function_strings[anim.alphaType] end if (anim.alphaFunc) then - alphaFunc = WeakAuras.LoadFunction("return " .. anim.alphaFunc, auraDisplayName, "alpha animation"); + alphaFunc = WeakAuras.LoadFunction("return " .. anim.alphaFunc); else if (region.SetAnimAlpha) then region:SetAnimAlpha(nil); @@ -282,7 +287,7 @@ function Private.Animate(namespace, uid, type, anim, region, inverse, onFinished anim.scaleFunc = anim_function_strings[anim.scaleType] end if (anim.scaleFunc) then - scaleFunc = WeakAuras.LoadFunction("return " .. anim.scaleFunc, auraDisplayName, "scale animation"); + scaleFunc = WeakAuras.LoadFunction("return " .. anim.scaleFunc); else region:Scale(1, 1); end @@ -295,7 +300,7 @@ function Private.Animate(namespace, uid, type, anim, region, inverse, onFinished anim.rotateFunc = anim_function_strings[anim.rotateType] end if (anim.rotateFunc) then - rotateFunc = WeakAuras.LoadFunction("return " .. anim.rotateFunc, auraDisplayName, "rotate animation"); + rotateFunc = WeakAuras.LoadFunction("return " .. anim.rotateFunc); else region:Rotate(startRotation); end @@ -308,7 +313,7 @@ function Private.Animate(namespace, uid, type, anim, region, inverse, onFinished anim.colorFunc = anim_function_strings[anim.colorType] end if (anim.colorFunc) then - colorFunc = WeakAuras.LoadFunction("return " .. anim.colorFunc, auraDisplayName, "color animation"); + colorFunc = WeakAuras.LoadFunction("return " .. anim.colorFunc); else region:ColorAnim(nil); end diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index 285fcb3..ed29fdc 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -269,7 +269,7 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) if(actions and actions.do_custom and actions.custom) then local func = Private.customActionsFunctions[id]["init"] if func then - xpcall(func, geterrorhandler()) + xpcall(func, Private.GetErrorHandlerId(id, "init")) end end end @@ -425,11 +425,11 @@ function env_getglobal(k) end local function_cache = {} -function WeakAuras.LoadFunction(string, id, inTrigger) +function WeakAuras.LoadFunction(string) if function_cache[string] then return function_cache[string] else - local loadedFunction, errorString = loadstring(string, "Error in: " .. (id or "Unknown") .. (inTrigger and ("':'".. inTrigger) or "")) + local loadedFunction, errorString = loadstring(string) if errorString then print(errorString) else diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index dea2034..73fd986 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -151,7 +151,7 @@ end function WeakAuras.CallCustomConditionTest(uid, testFunctionNumber, ...) local ok, result = pcall(WeakAuras.conditionHelpers[uid].customTestFunctions[testFunctionNumber], ...) if not ok then - geterrorhandler()(result) + Private.GetErrorHandlerUid(uid, L["Condition Custom Text"]) elseif (ok) then return result end @@ -223,7 +223,7 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta end elseif (cType == "customcheck") then if value then - local customCheck = WeakAuras.LoadFunction("return " .. value, Private.UIDtoID(uid), "conditions custom check") + local customCheck = WeakAuras.LoadFunction("return " .. value) if customCheck then WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {} WeakAuras.conditionHelpers[uid].customTestFunctions = WeakAuras.conditionHelpers[uid].customTestFunctions or {} @@ -295,7 +295,7 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta fn = fn:format(input.op_range, input.range, op, value) end if fn then - local customCheck = WeakAuras.LoadFunction(fn, Private.UIDtoID(uid), "conditions range check") + local customCheck = WeakAuras.LoadFunction(fn) if customCheck then WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {} WeakAuras.conditionHelpers[uid].customTestFunctions = WeakAuras.conditionHelpers[uid].customTestFunctions or {} @@ -517,7 +517,7 @@ function Private.LoadConditionPropertyFunctions(data) else prefix, suffix = "return function()", "\nend"; end - local customFunc = WeakAuras.LoadFunction(prefix .. custom .. suffix, id, "condition"); + local customFunc = WeakAuras.LoadFunction(prefix .. custom .. suffix); if (customFunc) then WeakAuras.customConditionsFunctions[id][conditionNumber] = WeakAuras.customConditionsFunctions[id][conditionNumber] or {}; WeakAuras.customConditionsFunctions[id][conditionNumber].changes = WeakAuras.customConditionsFunctions[id][conditionNumber].changes or {}; @@ -697,7 +697,7 @@ function Private.LoadConditionFunction(data) CancelTimers(data.uid) local checkConditionsFuncStr = ConstructConditionFunction(data); - local checkCondtionsFunc = checkConditionsFuncStr and WeakAuras.LoadFunction(checkConditionsFuncStr, data.id, "condition checks"); + local checkCondtionsFunc = checkConditionsFuncStr and WeakAuras.LoadFunction(checkConditionsFuncStr); checkConditions[data.uid] = checkCondtionsFunc; end diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 6768143..482cfaa 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -457,7 +457,7 @@ function Private.EndEvent(id, triggernum, force, state) end end -local function RunOverlayFuncs(event, state) +local function RunOverlayFuncs(event, state, id) state.additionalProgress = state.additionalProgress or {}; local changed = false; for i, overlayFunc in ipairs(event.overlayFuncs) do @@ -465,7 +465,7 @@ local function RunOverlayFuncs(event, state) local additionalProgress = state.additionalProgress[i]; local ok, a, b, c = pcall(overlayFunc, event.trigger, state); if (not ok) then - geterrorhandler()(a) + Private.GetErrorHandlerId(id, L["Overlay %s"]:format(i)) additionalProgress.min = nil; additionalProgress.max = nil; additionalProgress.direction = nil; @@ -522,7 +522,7 @@ local function callFunctionForActivateEvent(func, trigger, fallback, errorHandle end end -function Private.ActivateEvent(id, triggernum, data, state, errorHandler) +function Private.ActivateEvent(id, triggernum, data, state) local changed = state.changed or false; if (state.show ~= true) then state.show = true; @@ -553,7 +553,7 @@ function Private.ActivateEvent(id, triggernum, data, state, errorHandler) elseif (data.durationFunc) then local ok, arg1, arg2, arg3, inverse = pcall(data.durationFunc, data.trigger); if not ok then - errorHandler(arg1); + Private.GetErrorHandlerId(id, L["Duration Function"]) arg1 = 0; arg2 = 0; else @@ -619,10 +619,10 @@ function Private.ActivateEvent(id, triggernum, data, state, errorHandler) end end - local name = callFunctionForActivateEvent(data.nameFunc, data.trigger, state.name, errorHandler) - local icon = callFunctionForActivateEvent(data.iconFunc, data.trigger, state.icon, errorHandler) - local texture = callFunctionForActivateEvent(data.textureFunc, data.trigger, state.texture, errorHandler) - local stacks = callFunctionForActivateEvent(data.stacksFunc, data.trigger, state.stacks, errorHandler) + local name = callFunctionForActivateEvent(data.nameFunc, data.trigger, state.name, Private.GetErrorHandlerId(id, L["Name Function"])) + local icon = callFunctionForActivateEvent(data.iconFunc, data.trigger, state.icon, Private.GetErrorHandlerId(id, L["Icon Function"])) + local texture = callFunctionForActivateEvent(data.textureFunc, data.trigger, state.texture, Private.GetErrorHandlerId(id, L["Texture Function"])) + local stacks = callFunctionForActivateEvent(data.stacksFunc, data.trigger, state.stacks, Private.GetErrorHandlerId(id, L["Stacks Function"])) if (state.name ~= name) then state.name = name; @@ -642,7 +642,7 @@ function Private.ActivateEvent(id, triggernum, data, state, errorHandler) end if (data.overlayFuncs) then - RunOverlayFuncs(data, state); + RunOverlayFuncs(data, state, id); else state.additionalProgress = nil; end @@ -658,7 +658,7 @@ end local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2, ...) local optionsEvent = event == "OPTIONS"; - local errorHandler = (optionsEvent and data.ignoreOptionsEventErrors) and ignoreErrorHandler or geterrorhandler() + local errorHandler = (optionsEvent and data.ignoreOptionsEventErrors) and ignoreErrorHandler or Private.GetErrorHandlerId(id, L["Trigger %s"]:format(triggernum)) local updateTriggerState = false; local unitForUnitTrigger @@ -675,7 +675,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 end for key, state in pairs(allStates) do if (type(state) ~= "table") then - errorHandler(string.format(L["Error in aura '%s' in %s. trigger. All States table contains a non table at key: '%s'."], id, triggernum, key)) + errorHandler(string.format(L["All States table contains a non table at key: '%s'."], key)) wipe(allStates) return end @@ -687,7 +687,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 elseif (ok and returnValue) or optionsEvent then for id, state in pairs(allStates) do if (state.changed) then - if (Private.ActivateEvent(id, triggernum, data, state, errorHandler)) then + if (Private.ActivateEvent(id, triggernum, data, state)) then updateTriggerState = true; end end @@ -721,7 +721,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 if not ok then errorHandler(returnValue) elseif (ok and returnValue) or optionsEvent then - if(Private.ActivateEvent(id, triggernum, data, state, errorHandler)) then + if(Private.ActivateEvent(id, triggernum, data, state)) then updateTriggerState = true; end else @@ -735,7 +735,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 if not ok then errorHandler(returnValue) elseif (ok and returnValue) or optionsEvent then - if(Private.ActivateEvent(id, triggernum, data, state, errorHandler)) then + if(Private.ActivateEvent(id, triggernum, data, state)) then updateTriggerState = true; end else @@ -748,7 +748,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 elseif (ok and returnValue) or optionsEvent then allStates[""] = allStates[""] or {}; local state = allStates[""]; - if(Private.ActivateEvent(id, triggernum, data, state, errorHandler)) then + if(Private.ActivateEvent(id, triggernum, data, state)) then updateTriggerState = true; end else @@ -1391,7 +1391,7 @@ function GenericTrigger.Add(data, region) triggerFuncStr = ConstructFunction(prototype, trigger); statesParameter = prototype.statesParameter; - triggerFunc = WeakAuras.LoadFunction(triggerFuncStr, id); + triggerFunc = WeakAuras.LoadFunction(triggerFuncStr); durationFunc = prototype.durationFunc; nameFunc = prototype.nameFunc; @@ -1455,7 +1455,7 @@ function GenericTrigger.Add(data, region) end end else -- CUSTOM - triggerFunc = WeakAuras.LoadFunction("return "..(trigger.custom or ""), id); + triggerFunc = WeakAuras.LoadFunction("return "..(trigger.custom or "")); if (trigger.custom_type == "stateupdate") then tsuConditionVariables = WeakAuras.LoadFunction("return function() return \n" .. (trigger.customVariables or "") .. "\n end"); if not tsuConditionVariables then @@ -1464,35 +1464,35 @@ function GenericTrigger.Add(data, region) end if(trigger.custom_type == "status" or trigger.custom_type == "event" and trigger.custom_hide == "custom") then - untriggerFunc = WeakAuras.LoadFunction("return "..(untrigger.custom or ""), id); + untriggerFunc = WeakAuras.LoadFunction("return "..(untrigger.custom or "")); if (not untriggerFunc) then untriggerFunc = trueFunction; end end if(trigger.custom_type ~= "stateupdate" and trigger.customDuration and trigger.customDuration ~= "") then - durationFunc = WeakAuras.LoadFunction("return "..trigger.customDuration, id); + durationFunc = WeakAuras.LoadFunction("return "..trigger.customDuration); end if(trigger.custom_type ~= "stateupdate") then overlayFuncs = {}; for i = 1, 7 do local property = "customOverlay" .. i; if (trigger[property] and trigger[property] ~= "") then - overlayFuncs[i] = WeakAuras.LoadFunction("return ".. trigger[property], id); + overlayFuncs[i] = WeakAuras.LoadFunction("return ".. trigger[property]); end end end if(trigger.custom_type ~= "stateupdate" and trigger.customName and trigger.customName ~= "") then - nameFunc = WeakAuras.LoadFunction("return "..trigger.customName, id); + nameFunc = WeakAuras.LoadFunction("return "..trigger.customName); end if(trigger.custom_type ~= "stateupdate" and trigger.customIcon and trigger.customIcon ~= "") then - iconFunc = WeakAuras.LoadFunction("return "..trigger.customIcon, id); + iconFunc = WeakAuras.LoadFunction("return "..trigger.customIcon); end if(trigger.custom_type ~= "stateupdate" and trigger.customTexture and trigger.customTexture ~= "") then - textureFunc = WeakAuras.LoadFunction("return "..trigger.customTexture, id); + textureFunc = WeakAuras.LoadFunction("return "..trigger.customTexture); end if(trigger.custom_type ~= "stateupdate" and trigger.customStacks and trigger.customStacks ~= "") then - stacksFunc = WeakAuras.LoadFunction("return "..trigger.customStacks, id); + stacksFunc = WeakAuras.LoadFunction("return "..trigger.customStacks); end if((trigger.custom_type == "status" or trigger.custom_type == "stateupdate") and trigger.check == "update") then @@ -4098,7 +4098,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) if (event.nameFunc) then local ok, name = pcall(event.nameFunc, firstTrigger); if not ok then - geterrorhandler()(name) + Private.GetErrorHandlerUid(data.uid, L["Name Function (fallback state)"]) state.name = nil else state.name = name or nil @@ -4107,7 +4107,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) if (event.iconFunc) then local ok, icon = pcall(event.iconFunc, firstTrigger); if not ok then - geterrorhandler()(icon) + Private.GetErrorHandlerUid(data.uid, L["Icon Function (fallback state)"]) state.icon = nil else state.icon = icon or nil @@ -4117,7 +4117,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) if (event.textureFunc ) then local ok, texture = pcall(event.textureFunc, firstTrigger); if not ok then - geterrorhandler()(texture) + Private.GetErrorHandlerUid(data.uid, L["Texture Function (fallback state)"]) state.texture = nil else state.texture = texture or nil @@ -4127,7 +4127,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) if (event.stacksFunc) then local ok, stacks = pcall(event.stacksFunc, firstTrigger); if not ok then - geterrorhandler()(stacks) + Private.GetErrorHandlerUid(data.uid, L["Stacks Function (fallback state)"]) state.stacks = nil else state.stacks = stacks or nil @@ -4137,7 +4137,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) if (event.durationFunc) then local ok, arg1, arg2, arg3, inverse = pcall(event.durationFunc, firstTrigger); if not ok then - geterrorhandler()(arg1) + Private.GetErrorHandlerUid(data.uid, L["Duration Function (fallback state)"]) state.progressType = "timed"; state.duration = 0; state.expirationTime = math.huge; @@ -4180,7 +4180,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) state.total = nil; end if (event.overlayFuncs) then - RunOverlayFuncs(event, state); + RunOverlayFuncs(event, state, data.id); end Private.ActivateAuraEnvironment(nil); end diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index e9877cc..3f6c294 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -2,6 +2,7 @@ if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local WeakAuras = WeakAuras +local L = WeakAuras.L local SharedMedia = LibStub("LibSharedMedia-3.0") local default = { @@ -317,13 +318,13 @@ local sorters = { end, custom = function(data) local sortStr = data.customSort or "" - local sortFunc = WeakAuras.LoadFunction("return " .. sortStr, data.id, "custom sort") or noop + local sortFunc = WeakAuras.LoadFunction("return " .. sortStr) or noop return function(a, b) Private.ActivateAuraEnvironment(data.id) local ok, result = pcall(sortFunc, a, b) Private.ActivateAuraEnvironment() if not ok then - geterrorhandler()(result) + Private.GetErrorHandlerId(data.id, L["Custom Sort"]) else return result end @@ -398,12 +399,12 @@ local anchorers = { end, ["CUSTOM"] = function(data) local anchorStr = data.customAnchorPerUnit or "" - local anchorFunc = WeakAuras.LoadFunction("return " .. anchorStr, data.id, "custom frame anchor") or noop + local anchorFunc = WeakAuras.LoadFunction("return " .. anchorStr) or noop return function(frames, activeRegions) Private.ActivateAuraEnvironment(data.id) local ok, ret = pcall(anchorFunc, frames, activeRegions) if not ok then - geterrorhandler()(ret) + Private.GetErrorHandlerUid(data.uid, L["Custom Anchor"]) end Private.ActivateAuraEnvironment() end @@ -763,13 +764,13 @@ local growers = { end, CUSTOM = function(data) local growStr = data.customGrow or "" - local growFunc = WeakAuras.LoadFunction("return " .. growStr, data.id, "custom grow") or noop + local growFunc = WeakAuras.LoadFunction("return " .. growStr) or noop return function(newPositions, activeRegions) Private.ActivateAuraEnvironment(data.id) local ok, ret = pcall(growFunc, newPositions, activeRegions) Private.ActivateAuraEnvironment() if not ok then - geterrorhandler()(ret) + Private.GetErrorHandlerId(data.id, L["Custom Sort"]) wipe(newPositions) end end diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index 8929f52..e340535 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -253,7 +253,7 @@ end local function RunCode(self, func) if func and not WeakAuras.IsOptionsOpen() then Private.ActivateAuraEnvironment(self.id, self.cloneId, self.state, self.states); - xpcall(func, geterrorhandler()); + xpcall(func, Private.GetErrorHandlerId(self.id, L["Custom Condition Code"])); Private.ActivateAuraEnvironment(nil); end end @@ -276,7 +276,7 @@ local function UpdatePosition(self) local ok, ret = pcall(self.SetPoint, self, self.anchorPoint, self.relativeTo, self.relativePoint, xOffset, yOffset); if not ok then - geterrorhandler()(ret) + Private.GetErrorHandlerId(self.id, L["Update Position"]) end end @@ -541,7 +541,7 @@ function WeakAuras.regionPrototype.modify(parent, region, data) region:SetOffsetAnim(0, 0); if data.anchorFrameType == "CUSTOM" and data.customAnchor then - region.customAnchorFunc = WeakAuras.LoadFunction("return " .. data.customAnchor, data.id, "custom anchor") + region.customAnchorFunc = WeakAuras.LoadFunction("return " .. data.customAnchor) else region.customAnchorFunc = nil end diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index baf2b94..43f6413 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -195,7 +195,7 @@ local function modify(parent, region, data) local customTextFunc = nil if(Private.ContainsCustomPlaceHolder(data.displayText) and data.customText) then - customTextFunc = WeakAuras.LoadFunction("return "..data.customText, region.id, "custom text") + customTextFunc = WeakAuras.LoadFunction("return "..data.customText) end local Update diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index c7842df..da4553e 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -192,7 +192,7 @@ local function modify(parent, region, parentData, data, first) end if containsCustomText and parentData.customText and parentData.customText ~= "" then - parent.customTextFunc = WeakAuras.LoadFunction("return "..parentData.customText, parentData.id, "custom text") + parent.customTextFunc = WeakAuras.LoadFunction("return "..parentData.customText) else parent.customTextFunc = nil end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index a592435..49c1452 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -63,6 +63,46 @@ function WeakAuras.InternalVersion() return internalVersion; end +do + local currentErrorHandlerId + local currentErrorHandlerUid + local currentErrorHandlerContext + local function waErrorHandler(errorMessage) + local prefix = "" + local data + if currentErrorHandlerId then + data = WeakAuras.GetData(currentErrorHandlerId) + elseif currentErrorHandlerUid then + data = Private.GetDataByUID(currentErrorHandlerUid) + end + if data then + Private.AuraWarnings.UpdateWarning(data.uid, "LuaError", "error", + L["This aura has caused a Lua error."] .. "\n" .. L["Install the addons BugSack and BugGrabber for detailed error logs."], true) + prefix = L["Lua error in aura '%s': %s"]:format(data.id, currentErrorHandlerContext or L["unknown location"]) .. "\n" + else + prefix = L["Lua error"] .. "\n" + end + prefix = prefix .. L["WeakAuras Version: %s"]:format(WeakAuras.versionString) .. "\n" + local version = data and (data.semver or data.version) + if version then + prefix = prefix .. L["Aura Version: %s"]:format(version) .. "\n" + end + geterrorhandler()(prefix .. errorMessage) + end + function Private.GetErrorHandlerId(id, context) + currentErrorHandlerUid = nil + currentErrorHandlerId = id + currentErrorHandlerContext = context + return waErrorHandler + end + function Private.GetErrorHandlerUid(uid, context) + currentErrorHandlerUid = uid + currentErrorHandlerId = nil + currentErrorHandlerContext = context + return waErrorHandler + end +end + function Private.LoadOptions(msg) if not(IsAddOnLoaded("WeakAurasOptions")) then if not WeakAuras.IsLoginFinished() then @@ -796,30 +836,30 @@ local function LoadCustomActionFunctions(data) if (data.actions) then if (data.actions.init and data.actions.init.do_custom and data.actions.init.custom) then - local func = WeakAuras.LoadFunction("return function() "..(data.actions.init.custom).."\n end", id, "initialization"); + local func = WeakAuras.LoadFunction("return function() "..(data.actions.init.custom).."\n end"); Private.customActionsFunctions[id]["init"] = func; end if (data.actions.start) then if (data.actions.start.do_custom and data.actions.start.custom) then - local func = WeakAuras.LoadFunction("return function() "..(data.actions.start.custom).."\n end", id, "show action"); + local func = WeakAuras.LoadFunction("return function() "..(data.actions.start.custom).."\n end"); Private.customActionsFunctions[id]["start"] = func; end if (data.actions.start.do_message and data.actions.start.message_custom) then - local func = WeakAuras.LoadFunction("return "..(data.actions.start.message_custom), id, "show message"); + local func = WeakAuras.LoadFunction("return "..(data.actions.start.message_custom)); Private.customActionsFunctions[id]["start_message"] = func; end end if (data.actions.finish) then if (data.actions.finish.do_custom and data.actions.finish.custom) then - local func = WeakAuras.LoadFunction("return function() "..(data.actions.finish.custom).."\n end", id, "hide action"); + local func = WeakAuras.LoadFunction("return function() "..(data.actions.finish.custom).."\n end"); Private.customActionsFunctions[id]["finish"] = func; end if (data.actions.finish.do_message and data.actions.finish.message_custom) then - local func = WeakAuras.LoadFunction("return "..(data.actions.finish.message_custom), id, "hide message"); + local func = WeakAuras.LoadFunction("return "..(data.actions.finish.message_custom)); Private.customActionsFunctions[id]["finish_message"] = func; end end @@ -2605,11 +2645,11 @@ local function pAdd(data, simpleChange) loadEvents["SCAN_ALL"][id] = true local loadForOptionsFuncStr = ConstructFunction(load_prototype, data.load, true); - local loadFunc = WeakAuras.LoadFunction(loadFuncStr, id, "load"); - local loadForOptionsFunc = WeakAuras.LoadFunction(loadForOptionsFuncStr, id, "options load"); + local loadFunc = WeakAuras.LoadFunction(loadFuncStr); + local loadForOptionsFunc = WeakAuras.LoadFunction(loadForOptionsFuncStr); local triggerLogicFunc; if data.triggers.disjunctive == "custom" then - triggerLogicFunc = WeakAuras.LoadFunction("return "..(data.triggers.customTriggerLogic or ""), id, "trigger combination"); + triggerLogicFunc = WeakAuras.LoadFunction("return "..(data.triggers.customTriggerLogic or "")); end LoadCustomActionFunctions(data); @@ -2668,7 +2708,7 @@ function WeakAuras.Add(data, takeSnapshot, simpleChange) end local ok, ret = pcall(WeakAuras.PreAdd, data) if not ok then - geterrorhandler()(ret) + Private.GetErrorHandlerUid(data.uid, "PreAdd") elseif ok then pAdd(data, simpleChange) end @@ -3177,7 +3217,7 @@ function Private.PerformActions(data, when, region) local func = Private.customActionsFunctions[data.id][when] if func then Private.ActivateAuraEnvironment(region.id, region.cloneId, region.state, region.states); - xpcall(func, geterrorhandler()); + xpcall(func, Private.GetErrorHandlerId(data.id, L["Custom Action"])); Private.ActivateAuraEnvironment(nil); end end @@ -3854,7 +3894,7 @@ local function evaluateTriggerStateTriggers(id) if (triggerState[id].disjunctive == "custom" and triggerState[id].triggerLogicFunc) then local ok, returnValue = pcall(triggerState[id].triggerLogicFunc, triggerState[id].triggers); if not ok then - geterrorhandler()(returnValue) + Private.GetErrorHandlerId(id, L["Custom Trigger Combination"]) result = false else result = returnValue @@ -4073,7 +4113,7 @@ function Private.RunCustomTextFunc(region, customFunc) local custom = {pcall(customFunc, expirationTime or math.huge, duration or 0, progress, dur, name, icon, stacks)} if not custom[1] then - geterrorhandler()(custom[2]) + Private.GetErrorHandlerId(region.id, L["Custom Text Function"]) else table.remove(custom, 1) end @@ -4882,7 +4922,7 @@ local function GetAnchorFrame(data, region, parent) Private.StartProfileSystem("custom region anchor") Private.StartProfileAura(region.id) Private.ActivateAuraEnvironment(region.id, region.cloneId, region.state) - local ok, frame = xpcall(region.customAnchorFunc, geterrorhandler()) + local ok, frame = xpcall(region.customAnchorFunc, Private.GetErrorHandlerId(region.id, L["Custom Anchor"])) Private.ActivateAuraEnvironment() Private.StopProfileSystem("custom region anchor") Private.StopProfileAura(region.id) @@ -4915,12 +4955,9 @@ function Private.AnchorFrame(data, region, parent, force) if not anchorParent then return end if (data.anchorFrameParent or data.anchorFrameParent == nil or data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE") then - local errorhandler = function(text) - geterrorhandler()(L["'ERROR: Anchoring %s': \n"]:format(data.id) .. text) - end local ok, ret = pcall(region.SetParent, region, anchorParent); if not ok then - errorhandler(ret) + Private.GetErrorHandlerId(data.id, L["Anchoring"]) end else region:SetParent(parent or WeakAurasFrame); From 395d4480668a890920822f28c4de3a67b0208f9b Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Tue, 7 Jan 2025 16:12:17 +0100 Subject: [PATCH 007/153] from retail --- WeakAuras/BuffTrigger2.lua | 8 ++-- WeakAuras/Conditions.lua | 2 +- WeakAuras/GenericTrigger.lua | 42 +++++++++---------- WeakAuras/Profiling.lua | 10 +++++ WeakAuras/RegionTypes/DynamicGroup.lua | 4 +- WeakAuras/RegionTypes/StopMotion.lua | 2 +- WeakAuras/Transmission.lua | 10 ++--- WeakAuras/Types.lua | 4 +- WeakAuras/WeakAuras.lua | 6 +-- WeakAurasOptions/AuthorOptions.lua | 29 ++++++++++--- .../OptionsFrames/OptionsFrame.lua | 2 +- WeakAurasOptions/OptionsFrames/TextEditor.lua | 2 +- WeakAurasOptions/OptionsFrames/Update.lua | 25 ++++++----- WeakAurasOptions/WeakAurasOptions.lua | 6 +-- 14 files changed, 92 insertions(+), 60 deletions(-) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 23f18dd..68416b4 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -1746,7 +1746,7 @@ local function EventHandler(frame, event, arg1, arg2, ...) elseif event == "UNIT_PET" then local pet = WeakAuras.unitToPetUnit[arg1] if pet then - ScanGroupUnit(time, matchDataChanged, nil, pet) + ScanGroupUnit(time, matchDataChanged, "group", pet) RecheckActiveForUnitType("group", pet, deactivatedTriggerInfos) if not UnitExistsFixed(pet) then tinsert(unitsToRemove, pet) @@ -2472,7 +2472,7 @@ function BuffTrigger.Add(data) useAffected = unit == "group" and trigger.useAffected, isMulti = trigger.unit == "multi", nameChecker = effectiveNameCheck and WeakAuras.ParseNameCheck(trigger.unitName), - includePets = trigger.use_includePets and trigger.includePets, + includePets = trigger.use_includePets and trigger.includePets or nil, npcId = effectiveNpcId } triggerInfos[id] = triggerInfos[id] or {} @@ -3353,7 +3353,7 @@ end function BuffTrigger.GetTriggerDescription(data, triggernum, namestable) local trigger = data.triggers[triggernum].trigger - if trigger.auranames then + if trigger.useName and trigger.auranames then for index, name in pairs(trigger.auranames) do local left = " " if(index == 1) then @@ -3377,7 +3377,7 @@ function BuffTrigger.GetTriggerDescription(data, triggernum, namestable) end end - if trigger.auraspellids then + if trigger.useExactSpellId and trigger.auraspellids then for index, spellId in pairs(trigger.auraspellids) do local left = " " if index == 1 then diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index 73fd986..0250c26 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -321,7 +321,7 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta -- If adding a new condition type, don't forget to adjust the validator in the options code if (cType == "timer" and value) then - recheckCode = " nextTime = state[" .. trigger .. "] and state[" .. trigger .. "]" .. string.format("[%q]", variable) .. " and (state[" .. trigger .. "]" .. string.format("[%q]", variable) .. " -" .. value .. ")\n"; + recheckCode = " nextTime = state[" .. trigger .. "] and state[" .. trigger .. "]" .. string.format("[%q]", variable) .. " and (state[" .. trigger .. "]" .. string.format("[%q]", variable) .. " - " .. value .. ")\n"; recheckCode = recheckCode .. " if (nextTime and (not recheckTime or nextTime < recheckTime) and nextTime >= now) then\n" recheckCode = recheckCode .. " recheckTime = nextTime\n"; recheckCode = recheckCode .. " end\n" diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 482cfaa..798ab56 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -457,7 +457,7 @@ function Private.EndEvent(id, triggernum, force, state) end end -local function RunOverlayFuncs(event, state, id) +local function RunOverlayFuncs(event, state, id, errorHandler) state.additionalProgress = state.additionalProgress or {}; local changed = false; for i, overlayFunc in ipairs(event.overlayFuncs) do @@ -465,7 +465,7 @@ local function RunOverlayFuncs(event, state, id) local additionalProgress = state.additionalProgress[i]; local ok, a, b, c = pcall(overlayFunc, event.trigger, state); if (not ok) then - Private.GetErrorHandlerId(id, L["Overlay %s"]:format(i)) + (errorHandler or Private.GetErrorHandlerId(id, L["Overlay %s"]:format(i)))(a) additionalProgress.min = nil; additionalProgress.max = nil; additionalProgress.direction = nil; @@ -522,7 +522,7 @@ local function callFunctionForActivateEvent(func, trigger, fallback, errorHandle end end -function Private.ActivateEvent(id, triggernum, data, state) +function Private.ActivateEvent(id, triggernum, data, state, errorHandler) local changed = state.changed or false; if (state.show ~= true) then state.show = true; @@ -553,7 +553,7 @@ function Private.ActivateEvent(id, triggernum, data, state) elseif (data.durationFunc) then local ok, arg1, arg2, arg3, inverse = pcall(data.durationFunc, data.trigger); if not ok then - Private.GetErrorHandlerId(id, L["Duration Function"]) + (errorHandler or Private.GetErrorHandlerId(id, L["Duration Function"]))(arg1) arg1 = 0; arg2 = 0; else @@ -619,10 +619,10 @@ function Private.ActivateEvent(id, triggernum, data, state) end end - local name = callFunctionForActivateEvent(data.nameFunc, data.trigger, state.name, Private.GetErrorHandlerId(id, L["Name Function"])) - local icon = callFunctionForActivateEvent(data.iconFunc, data.trigger, state.icon, Private.GetErrorHandlerId(id, L["Icon Function"])) - local texture = callFunctionForActivateEvent(data.textureFunc, data.trigger, state.texture, Private.GetErrorHandlerId(id, L["Texture Function"])) - local stacks = callFunctionForActivateEvent(data.stacksFunc, data.trigger, state.stacks, Private.GetErrorHandlerId(id, L["Stacks Function"])) + local name = callFunctionForActivateEvent(data.nameFunc, data.trigger, state.name, errorHandler or Private.GetErrorHandlerId(id, L["Name Function"])) + local icon = callFunctionForActivateEvent(data.iconFunc, data.trigger, state.icon, errorHandler or Private.GetErrorHandlerId(id, L["Icon Function"])) + local texture = callFunctionForActivateEvent(data.textureFunc, data.trigger, state.texture, errorHandler or Private.GetErrorHandlerId(id, L["Texture Function"])) + local stacks = callFunctionForActivateEvent(data.stacksFunc, data.trigger, state.stacks, errorHandler or Private.GetErrorHandlerId(id, L["Stacks Function"])) if (state.name ~= name) then state.name = name; @@ -642,7 +642,7 @@ function Private.ActivateEvent(id, triggernum, data, state) end if (data.overlayFuncs) then - RunOverlayFuncs(data, state, id); + RunOverlayFuncs(data, state, id, errorHandler); else state.additionalProgress = nil; end @@ -735,7 +735,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 if not ok then errorHandler(returnValue) elseif (ok and returnValue) or optionsEvent then - if(Private.ActivateEvent(id, triggernum, data, state)) then + if(Private.ActivateEvent(id, triggernum, data, state, (optionsEvent and data.ignoreOptionsEventErrors) and ignoreErrorHandler or nil)) then updateTriggerState = true; end else @@ -748,7 +748,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 elseif (ok and returnValue) or optionsEvent then allStates[""] = allStates[""] or {}; local state = allStates[""]; - if(Private.ActivateEvent(id, triggernum, data, state)) then + if(Private.ActivateEvent(id, triggernum, data, state, (optionsEvent and data.ignoreOptionsEventErrors) and ignoreErrorHandler or nil)) then updateTriggerState = true; end else @@ -756,6 +756,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 end end if (untriggerCheck and not optionsEvent) then + errorHandler = (optionsEvent and data.ignoreOptionsEventErrors) and ignoreErrorHandler or Private.GetErrorHandlerId(id, L["Untrigger %s"]:format(triggernum)) if (data.statesParameter == "all") then if data.untriggerFunc then local ok, returnValue = pcall(data.untriggerFunc, allStates, event, arg1, arg2, ...); @@ -3271,6 +3272,7 @@ do if not(tenchFrame) then tenchFrame = CreateFrame("Frame"); tenchFrame:RegisterEvent("UNIT_INVENTORY_CHANGED"); + tenchFrame:RegisterEvent("PLAYER_ENTERING_WORLD"); tenchTip = WeakAuras.GetHiddenTooltip(); @@ -3323,11 +3325,9 @@ do Private.StopProfileSystem("generictrigger"); end - tenchFrame:SetScript("OnEvent", function(self, event, arg1) + tenchFrame:SetScript("OnEvent", function() Private.StartProfileSystem("generictrigger"); - if (event == "UNIT_INVENTORY_CHANGED" and arg1 == "player") then - timer:ScheduleTimer(tenchUpdate, 0.1); - end + timer:ScheduleTimer(tenchUpdate, 0.1); Private.StopProfileSystem("generictrigger"); end); @@ -4094,9 +4094,9 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) local event = events[data.id][triggernum]; Private.ActivateAuraEnvironment(data.id, "", state); - local firstTrigger = data.triggers[1].trigger + local trigger = data.triggers[triggernum].trigger if (event.nameFunc) then - local ok, name = pcall(event.nameFunc, firstTrigger); + local ok, name = pcall(event.nameFunc, trigger); if not ok then Private.GetErrorHandlerUid(data.uid, L["Name Function (fallback state)"]) state.name = nil @@ -4105,7 +4105,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) end end if (event.iconFunc) then - local ok, icon = pcall(event.iconFunc, firstTrigger); + local ok, icon = pcall(event.iconFunc, trigger); if not ok then Private.GetErrorHandlerUid(data.uid, L["Icon Function (fallback state)"]) state.icon = nil @@ -4115,7 +4115,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) end if (event.textureFunc ) then - local ok, texture = pcall(event.textureFunc, firstTrigger); + local ok, texture = pcall(event.textureFunc, trigger); if not ok then Private.GetErrorHandlerUid(data.uid, L["Texture Function (fallback state)"]) state.texture = nil @@ -4125,7 +4125,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) end if (event.stacksFunc) then - local ok, stacks = pcall(event.stacksFunc, firstTrigger); + local ok, stacks = pcall(event.stacksFunc, trigger); if not ok then Private.GetErrorHandlerUid(data.uid, L["Stacks Function (fallback state)"]) state.stacks = nil @@ -4135,7 +4135,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) end if (event.durationFunc) then - local ok, arg1, arg2, arg3, inverse = pcall(event.durationFunc, firstTrigger); + local ok, arg1, arg2, arg3, inverse = pcall(event.durationFunc, trigger); if not ok then Private.GetErrorHandlerUid(data.uid, L["Duration Function (fallback state)"]) state.progressType = "timed"; diff --git a/WeakAuras/Profiling.lua b/WeakAuras/Profiling.lua index c924eb7..224f46a 100644 --- a/WeakAuras/Profiling.lua +++ b/WeakAuras/Profiling.lua @@ -4,6 +4,7 @@ local AddonName, Private = ... local WeakAuras = WeakAuras local L = WeakAuras.L local prettyPrint = WeakAuras.prettyPrint +-- local LGF = LibStub("LibGetFrame-1.0") local profileData = {} profileData.systems = {} @@ -335,6 +336,7 @@ function WeakAuras.StartProfile(startType) Private.StopProfileSystem = StopProfileSystem Private.StopProfileAura = StopProfileAura Private.StopProfileUID = StopProfileUID + -- LGF.StartProfile() end local function doNothing() @@ -357,6 +359,7 @@ function WeakAuras.StopProfile() Private.StopProfileSystem = doNothing Private.StopProfileAura = doNothing Private.StopProfileUID = doNothing + -- LGF.StopProfile() currentProfileState = nil RealTimeProfilingWindow:UnregisterAllEvents() @@ -466,6 +469,13 @@ function WeakAuras.PrintProfile() PrintOneProfile(popup, k, profileData.systems[k], profileData.systems.wa.elapsed) end end + + -- popup:AddText("") + -- popup:AddText("|cff9900ffLibGetFrame:|r") + -- for id, map in pairs(LGF.GetProfileData()) do + -- PrintOneProfile(popup, id, map) + -- end + popup:Show() end diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 3f6c294..bb2ed19 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -770,7 +770,7 @@ local growers = { local ok, ret = pcall(growFunc, newPositions, activeRegions) Private.ActivateAuraEnvironment() if not ok then - Private.GetErrorHandlerId(data.id, L["Custom Sort"]) + Private.GetErrorHandlerId(data.id, L["Custom Grow"]) wipe(newPositions) end end @@ -833,7 +833,7 @@ local function modify(parent, region, data) end function region:Resume() - -- Allows group to reindex and reposition. + -- Allows group to re-index and reposition. -- TriggersSortUpdatedChildren and PositionChildren to happen if self.suspended > 0 then self.suspended = self.suspended - 1 diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index 028a818..aa51c66 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -98,7 +98,7 @@ local function create(parent) frame.background = background; background:SetAllPoints(frame); - local foreground = frame:CreateTexture(nil, "ART"); + local foreground = frame:CreateTexture(nil, "ARTWORK"); frame.foreground = foreground; foreground:SetAllPoints(frame); diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 0981c98..5c84bec 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -434,14 +434,14 @@ end local delayedImport = CreateFrame("FRAME") -local function ImportNow(data, children, target, sender) +local function ImportNow(data, children, target, sender, callbackFunc) if InCombatLockdown() then WeakAuras.prettyPrint(L["Importing will start after combat ends."]) delayedImport:RegisterEvent("PLAYER_REGEN_ENABLED") delayedImport:SetScript("OnEvent", function() delayedImport:UnregisterEvent("PLAYER_REGEN_ENABLED") - ImportNow(data, children, target, sender) + ImportNow(data, children, target, sender, callbackFunc) end) return end @@ -450,11 +450,11 @@ local function ImportNow(data, children, target, sender) if not WeakAuras.IsOptionsOpen() then WeakAuras.OpenOptions() end - Private.OpenUpdate(data, children, target, sender) + Private.OpenUpdate(data, children, target, sender, callbackFunc) end end -function WeakAuras.Import(inData, target) +function WeakAuras.Import(inData, target, callbackFunc) local data, children, version if type(inData) == 'string' then -- encoded data @@ -508,7 +508,7 @@ function WeakAuras.Import(inData, target) end tooltipLoading = nil; - return ImportNow(data, children, target) + return ImportNow(data, children, target, nil, callbackFunc) end local function crossRealmSendCommMessage(prefix, text, target, queueName, callbackFn, callbackArg) diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 2eba5bd..083f9a5 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -1691,7 +1691,7 @@ Private.texture_types["PowerAuras Separated"] = { [PowerAurasPath.."Aura104"] = "Shield Center", [PowerAurasPath.."Aura105"] = "Shield Full", [PowerAurasPath.."Aura106"] = "Shield Top Right", - [PowerAurasPath.."Aura107"] = "Shiled Top Left", + [PowerAurasPath.."Aura107"] = "Shield Top Left", [PowerAurasPath.."Aura108"] = "Shield Bottom Right", [PowerAurasPath.."Aura109"] = "Shield Bottom Left", [PowerAurasPath.."Aura121"] = "Vine Top Right Leaf", @@ -2330,7 +2330,7 @@ Private.bool_types = { Private.update_categories = { { name = "anchor", - -- Note, these are special cased for child auras and considered arrangment + -- Note, these are special cased for child auras and considered arrangement fields = { "xOffset", "yOffset", diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 49c1452..a60f7b6 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -31,7 +31,7 @@ LibStub("AceTimer-3.0"):Embed(WeakAurasTimers) Private.watched_trigger_events = {} -- The worlds simplest callback system. --- That supports 1:N, but no deregistration and breaks if registrating in a callback +-- That supports 1:N, but no de-registration and breaks if registering in a callback Private.callbacks = {} Private.callbacks.events = {} @@ -882,7 +882,7 @@ local function AddLegacyCompanionData() end function Private.PostAddCompanion() - -- add data from older verion of companion addons + -- add data from older version of companion addons AddLegacyCompanionData() -- nag if updates local count = Private.CountWagoUpdates() @@ -5418,7 +5418,7 @@ do return coroutine.wrap(TraverseLeafs), data end - -- The root if it is a non-group, otherwise non-group childrens + -- The root if it is a non-group, otherwise non-group children function Private.TraverseLeafsOrAura(data) return coroutine.wrap(TraverseLeafsOrAura), data end diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index 42c4018..cc340f7 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -677,8 +677,18 @@ typeControlAdders = { bigStep = option.bigStep min = option.min max = option.max - if max and min then - max = math.max(min, max) + local effectiveMin = softMin or min or 0 + local effectiveMax = softMax or max or 100 + if (effectiveMin > effectiveMax) then + -- This will cause a error inside the slider + -- Fix up either softMax or max, depending on which one is the effective one + if softMax then + softMax = effectiveMin + elseif max then + max = effectiveMin + else + softMax = effectiveMin + end end step = option.step args[prefix .. "default"] = { @@ -967,7 +977,6 @@ typeControlAdders = { end, multiselect = function(options, args, data, order, prefix, i) local option = options[i] - args[prefix .. "width"] = nil local values = getValues(option) local defaultValues = {} for i, v in ipairs(values) do @@ -2234,8 +2243,18 @@ local function addUserModeOption(options, args, data, order, prefix, i) userOption.bigStep = option.bigStep userOption.min = option.min userOption.max = option.max - if userOption.max and userOption.min then - userOption.max = max(userOption.min, userOption.max) + local effectiveMin = userOption.softMin or userOption.min or 0 + local effectiveMax = userOption.softMax or userOption.max or 100 + if (effectiveMin > effectiveMax) then + -- This will cause a error inside the slider + -- Fix up either softMax or max, depending on which one is the effective one + if userOption.softMax then + userOption.softMax = effectiveMin + elseif userOption.max then + userOption.max = effectiveMin + else + userOption.softMax = effectiveMin + end end userOption.step = option.step elseif optionType == "color" then diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index e76c8fc..936c83b 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -1184,7 +1184,7 @@ function OptionsPrivate.CreateFrame() tinsert(regionTypesSorted, regionType) end - -- Sort group + dynamic group first, then the others alphabeticaly + -- Sort group + dynamic group first, then the others alphabetically table.sort(regionTypesSorted, function(a, b) if (a == "group") then return true diff --git a/WeakAurasOptions/OptionsFrames/TextEditor.lua b/WeakAurasOptions/OptionsFrames/TextEditor.lua index cf84a36..884d554 100644 --- a/WeakAurasOptions/OptionsFrames/TextEditor.lua +++ b/WeakAurasOptions/OptionsFrames/TextEditor.lua @@ -624,7 +624,7 @@ local function ConstructTextEditor(frame) editor.editBox:SetScript( "OnEscapePressed", function() - group:CancelClose() + -- catch it so that escape doesn't default to losing focus (after which another escape would close config) end ) self.oldOnTextChanged = editor.editBox:GetScript("OnTextChanged") diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index 30090d1..ef73763 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -12,7 +12,7 @@ local function notEmptyString(str) end local function addCode(codes, text, code, ...) - -- The 4th paramter is a "check" if the code is active + -- The 4th parameter is a "check" if the code is active -- The following line let's distinguish between addCode(a, b, c, nil) and addCode(a, b, c) -- If the 4th parameter is nil, then we want to return if (select("#", ...) > 0) then @@ -182,7 +182,7 @@ local function recurseUpdate(data, chunk) end end -local ignoredForDiffChecking -- Needs to be created lazyly +local ignoredForDiffChecking -- Needs to be created lazily local function RecurseDiff(ours, theirs) local diff, seen, same = {}, {}, true for key, ourVal in pairs(ours) do @@ -315,7 +315,7 @@ local function BuildUidMap(data, children, type) idToUid[data.id] = data.uid for i, child in ipairs(children) do if idToUid[child.id] then - error("Diplicated id in import data") + error("Duplicate id in import data: "..child.id) end idToUid[child.id] = child.uid end @@ -381,7 +381,7 @@ local function BuildUidMap(data, children, type) self.idToUid[data.id] = data.uid self.totalCount = self.totalCount + 1 - -- clean up children/sortHybird + -- clean up children/sortHybrid -- The Update code first inserts children before it inserts us -- But not every child might be inserted, since empty groups aren't inserted -- so clean that up here @@ -1242,7 +1242,7 @@ local function AddAuraList(container, uidMap, list, expandText) end local methods = { - Open = function(self, data, children, target, sender) + Open = function(self, data, children, target, sender, callbackFunc) if(self.optionsWindow.window == "importexport") then self.optionsWindow.importexport:Close(); elseif(self.optionsWindow.window == "texture") then @@ -1264,6 +1264,7 @@ local methods = { self.userChoices = { } + self.callbackFunc = callbackFunc self:ReleaseChildren() self:AddBasicInformationWidgets(data, sender) @@ -1513,7 +1514,7 @@ local methods = { local onePhaseProgress = matchInfo.oldUidMap:GetTotalCount() + matchInfo.newUidMap:GetTotalCount() local IncProgress = function() self:IncProgress() end - -- The progress is more for appereance than anything resembling real calculation + -- The progress is more for appearances than anything resembling real calculation -- The estimate for the total work is wonky, as is how the code compensates for that -- But then again, lying progress bar is a industry standard pratice self:InitializeProgress(onePhaseProgress * 26) @@ -1543,7 +1544,7 @@ local methods = { local GetPhase1Data -- Getting the right data is a bit tricky, and depends on the mode local GetPhase2Data if userChoices.activeCategories.arrangement then - -- new arragement + -- new arrangement structureUidMap = matchInfo.newUidMap if not userChoices.activeCategories.oldchildren then -- Keep old children @@ -1641,8 +1642,7 @@ local methods = { self.closeButton:Enable() OptionsPrivate.Private.callbacks:Fire("Import") - self:Close() - + self:Close(true, pendingPickData.id) if pendingPickData then OptionsPrivate.ClearPicks() @@ -1942,9 +1942,12 @@ local methods = { self.progress = self.total self.progressBar:SetProgress(self.progress, self.total) end, - Close = function(self) + Close = function(self, success, id) self.optionsWindow.window = "default"; self.optionsWindow:UpdateFrameVisible() + if self.callbackFunc then + self.callbackFunc(success, id) + end end, AddBasicInformationWidgets = function(self, data, sender) local title = AceGUI:Create("Label") @@ -2025,7 +2028,7 @@ local function ConstructUpdateFrame(frame) importButton:SetText(L["Import"]) local closeButton = CreateFrame("Button", nil, group.frame, "UIPanelButtonTemplate"); - closeButton:SetScript("OnClick", function() group:Close() end); + closeButton:SetScript("OnClick", function() group:Close(false) end); closeButton:SetPoint("BOTTOMRIGHT", -20, -24); closeButton:SetFrameLevel(closeButton:GetFrameLevel() + 1) closeButton:SetHeight(20); diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 15bf849..ab35b25 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -896,8 +896,8 @@ function OptionsPrivate.OpenDebugLog(text) frame.debugLog:Open(text) end -function OptionsPrivate.OpenUpdate(data, children, target, sender) - return frame.update:Open(data, children, target, sender) +function OptionsPrivate.OpenUpdate(data, children, target, sender, callbackFunc) + return frame.update:Open(data, children, target, sender, callbackFunc) end function OptionsPrivate.ConvertDisplay(data, newType) @@ -1931,7 +1931,7 @@ function OptionsPrivate.AddTextFormatOption(input, withHeader, get, addOption, h headerOption = { type = "execute", control = "WeakAurasExpandSmall", - name = L["|cFFffcc00Format Options|r"], + name = L["|cffffcc00Format Options|r"], width = WeakAuras.doubleWidth, func = function(info, button) setHidden(not hidden()) From 2f96cddc7de6fd9750c98975e6f2b0edd8ded1b2 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Tue, 7 Jan 2025 21:06:03 +0100 Subject: [PATCH 008/153] readd function WeakAuras.IsCorrectVersion due to ElvUI_AddonSkins requiring it --- WeakAuras/Init.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index 5e19b18..ea3c50c 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -25,6 +25,10 @@ function WeakAuras.IsClassic() return false end +function WeakAuras.IsCorrectVersion() + return true +end + WeakAuras.prettyPrint = function(...) print("|cff9900ffWeakAuras:|r ", ...) end From 988145737d4dd96146a65a7ac7ebcf9bf4794859 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Wed, 8 Jan 2025 00:24:04 +0100 Subject: [PATCH 009/153] from retail --- WeakAuras/GenericTrigger.lua | 26 +++++++- WeakAuras/Init.lua | 2 +- WeakAuras/Prototypes.lua | 9 +-- WeakAuras/WeakAuras.lua | 66 ++++++++++++++++----- WeakAuras/WeakAuras.toc | 2 +- WeakAurasOptions/InformationOptions.lua | 2 +- WeakAurasOptions/OptionsFrames/Update.lua | 72 ++++++++++++++++------- WeakAurasOptions/WeakAurasOptions.toc | 2 +- 8 files changed, 132 insertions(+), 49 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 798ab56..f914fb9 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -3370,8 +3370,30 @@ do if not castLatencyFrame then castLatencyFrame = CreateFrame("Frame") castLatencyFrame:RegisterEvent("CURRENT_SPELL_CAST_CHANGED") - castLatencyFrame:SetScript("OnEvent", function(event) - Private.LAST_CURRENT_SPELL_CAST_CHANGED = GetTime() + castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_START") + castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") + + castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_STOP") + castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") + castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED") + + castLatencyFrame:SetScript("OnEvent", function(self, event, unit) + if unit and unit ~= "player" then return end + if event == "UNIT_SPELLCAST_START" then + Private.LAST_CURRENT_SPELL_CAST_START = select(4, UnitCastingInfo("player")) / 1000 + elseif event == "UNIT_SPELLCAST_CHANNEL_START" then + Private.LAST_CURRENT_SPELL_CAST_START = select(4, UnitChannelInfo("player")) / 1000 + elseif event == "CURRENT_SPELL_CAST_CHANGED" then + -- We want to store the CURRENT_SPELL_CAST_CHANGED time + -- that was the last before the actual START event + -- This prevents updating the CURRENT_SPELL_CAST_CHANGED time after + -- we got the start time + if not Private.LAST_CURRENT_SPELL_CAST_START then + Private.LAST_CURRENT_SPELL_CAST_CHANGED = GetTime() + end + else -- STOP EVENTS + Private.LAST_CURRENT_SPELL_CAST_START = nil + end end) end end diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index ea3c50c..d80616e 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -8,7 +8,7 @@ WeakAuras.halfWidth = WeakAuras.normalWidth / 2 WeakAuras.doubleWidth = WeakAuras.normalWidth * 2 local versionStringFromToc = GetAddOnMetadata("WeakAuras", "Version") -local versionString = "4.1.2" +local versionString = "4.1.5" local buildTime = "20240701180000" local isAwesomeEnabled = C_NamePlate and C_NamePlate.GetNamePlateForUnit or false diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index f9bfb33..27e7cb5 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -97,11 +97,6 @@ function WeakAuras.SpellSchool(school) return Private.combatlog_spell_school_types[school] or "" end -function WeakAuras.TestSchool(spellSchool, test) - print(spellSchool, test, type(spellSchool), type(test)) - return spellSchool == test -end - function WeakAuras.RaidFlagToIndex(flag) return Private.combatlog_raidFlags[flag] or 0 end @@ -6256,8 +6251,8 @@ Private.event_prototypes = { { name = L["Latency"], func = function(trigger, state) - if not state.expirationTime or not state.duration then return 0, 0 end - return 0, (state.expirationTime - state.duration) - (Private.LAST_CURRENT_SPELL_CAST_CHANGED or 0) + if not Private.LAST_CURRENT_SPELL_CAST_START or not Private.LAST_CURRENT_SPELL_CAST_CHANGED then return 0, 0 end + return 0, Private.LAST_CURRENT_SPELL_CAST_START - Private.LAST_CURRENT_SPELL_CAST_CHANGED end, enable = function(trigger) return trigger.use_showLatency and trigger.unit == "player" diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index a60f7b6..6a59b76 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1082,6 +1082,7 @@ function Private.Login(initialTime, takeNewSnapshots) print("|cFF8800FFWeakAuras|r detected a corrupt entry in WeakAuras saved displays - '"..tostring(id).."' vs '"..tostring(data.id).."'" ); data.id = id; end + tinsert(toAdd, data); end coroutine.yield(); @@ -2119,26 +2120,39 @@ function Private.SyncParentChildRelationships(silent) end end -function WeakAuras.AddMany(table, takeSnapshots) - local idtable = {}; - for _, data in ipairs(table) do - idtable[data.id] = data; - end +local function loadOrder(tbl, idtable) + local order = {} + local loaded = {}; local function load(id, depends) local data = idtable[id]; if(data.parent) then if(idtable[data.parent]) then - if(tContains(depends, data.parent)) then + if depends[data.parent] then + -- There was an unfortunate bug in update.lua in 2022 that resulted + -- in auras having a circular dependencies + -- Fix one of the two known cases here + -- We can probably remove this code in 2023 again + for d in pairs(depends) do + local uid = idtable[d].uid + if uid == "fjtz3A6LwBW" then -- Fojji - Deathknight UI, need to fixup a lot + local cycleRoot = d + idtable[cycleRoot].parent = nil + for d in pairs(depends) do + tDeleteItem(idtable[d].controlledChildren, cycleRoot) + end + return loadOrder(tbl, idtable) + end + coroutine.yield() + end error("Circular dependency in WeakAuras.AddMany between "..table.concat(depends, ", ")); else if not(loaded[data.parent]) then - local dependsOut = {}; - for i,v in pairs(depends) do - dependsOut[i] = v; - end - tinsert(dependsOut, data.parent); - load(data.parent, dependsOut); + local dependsOut = CopyTable(depends) + dependsOut[data.parent] = true + coroutine.yield() + load(data.parent, dependsOut) + coroutine.yield() end end else @@ -2146,14 +2160,38 @@ function WeakAuras.AddMany(table, takeSnapshots) end end if not(loaded[id]) then - WeakAuras.Add(data, takeSnapshots); coroutine.yield(); loaded[id] = true; + tinsert(order, idtable[id]) end end - local groups = {} + for id, data in pairs(idtable) do load(id, {}); + coroutine.yield() + end + return order +end + +function WeakAuras.AddMany(tbl, takeSnapshots) + local idtable = {}; + for _, data in ipairs(tbl) do + -- There was an unfortunate bug in update.lua in 2022 that resulted + -- in auras having a circular dependencies + -- Fix one of the two known cases here + if data.id == data.parent then + data.parent = nil + tDeleteItem(data.controlledChildren, data.id) + end + idtable[data.id] = data; + end + + local order = loadOrder(tbl, idtable) + coroutine.yield() + local groups = {} + for _, data in ipairs(order) do + WeakAuras.Add(data, takeSnapshots); + coroutine.yield() if data.regionType == "dynamicgroup" or data.regionType == "group" then groups[data] = true end diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index 61e6760..e0e01f8 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -1,7 +1,7 @@ ## Interface: 30300 ## Title: WeakAuras ## Author: The WeakAuras Team -## Version: 4.1.2 +## Version: 4.1.5 ## Notes: A powerful, comprehensive utility for displaying graphics and information based on buffs, debuffs, and other triggers. ## Notes-esES: Potente y completa aplicación que te permitirá mostrar por pantalla múltiples diseños, basados en beneficios, perjuicios y otros activadores. ## Notes-deDE: Ein leistungsfähiges, umfassendes Addon zur grafischen Darstellung von Informationen von Auren, Cooldowns, Timern und vielem mehr. diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index 73ed612..1de2680 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -255,7 +255,7 @@ function OptionsPrivate.GetInformationOptions(data) order = order + 1 args.debugLogDesc = { type = "description", - name = L["This enables the collection of debug logs. This requires custom coded auras that use DebugPrints."], + name = L["This enables the collection of debug logs. Custom code can add debug information to the log through the function DebugPrint."], width = WeakAuras.doubleWidth, order = order, } diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index ef73763..67abe32 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -620,6 +620,14 @@ local function BuildUidMap(data, children, type) return self.map[uid].parent end + uidMap.UnsetParent = function(self, uid) + if not self.map[uid] then + error("GetParent for unknown uid") + return + end + self.map[uid].parent = nil + end + uidMap.GetParentIsDynamicGroup = function(self, uid) if not self.map[uid] then error("GetParentIsDynamicGroup for unknown uid") @@ -1527,14 +1535,20 @@ local methods = { self:SetMinimumProgress(1 * onePhaseProgress) coroutine.yield() - if userChoices.activeCategories.oldchildren then - self:RemoveUnmatchedOld(matchInfo.oldUidMap, matchInfo.oldUidMap:GetRootUID()) + local removeOldGroups = matchInfo.activeCategories.arrangement and userChoices.activeCategories.arrangement + if userChoices.activeCategories.oldchildren or removeOldGroups then + self:RemoveUnmatchedOld(matchInfo.oldUidMap, matchInfo.oldUidMap:GetRootUID(), matchInfo.newUidMap, + userChoices.activeCategories.oldchildren, + removeOldGroups) end self:SetMinimumProgress(2 * onePhaseProgress) - if not userChoices.activeCategories.newchildren then - self:RemoveUnmatchedNew(matchInfo.newUidMap, matchInfo.newUidMap:GetRootUID()) + local removeNewGroups = matchInfo.activeCategories.arrangement and not userChoices.activeCategories.arrangement + if userChoices.activeCategories.newchildren or removeNewGroups then + self:RemoveUnmatchedNew(matchInfo.newUidMap, matchInfo.newUidMap:GetRootUID(), matchInfo.oldUidMap, + userChoices.activeCategories.newchildren, + removeNewGroups) end self:SetMinimumProgress(3 * onePhaseProgress) @@ -1731,7 +1745,7 @@ local methods = { coroutine.yield() return changed end, - RemoveUnmatchedOld = function(self, uidMap, uid) + RemoveUnmatchedOld = function(self, uidMap, uid, otherMap, removeAuras, removeGroups) if uidMap:GetType() ~= "old" then error("Wrong map for delete") end @@ -1739,8 +1753,8 @@ local methods = { local children = uidMap:GetChildren(uid) local removedAllChildren = true for index, childUid in ipairs_reverse(children) do - local removed = self:RemoveUnmatchedOld(uidMap, childUid) - if not removed then + local removed = self:RemoveUnmatchedOld(uidMap, childUid, otherMap, removeAuras, removeGroups) + if not removed and not uidMap:GetUIDMatch(childUid) then removedAllChildren = false end end @@ -1751,21 +1765,28 @@ local methods = { error("Can't remove root") end - local data = OptionsPrivate.Private.GetDataByUID(uid) - if not data then - error("Can't find data") + if (uidMap:GetGroupRegionType(uid) and removeGroups) + or (uidMap:GetGroupRegionType(uid) == nil and removeAuras) + then + for index, childUid in ipairs_reverse(children) do + uidMap:UnsetParent(childUid) + end + local data = OptionsPrivate.Private.GetDataByUID(uid) + if not data then + error("Can't find data") + end + WeakAuras.Delete(data) + uidMap:Remove(uid) + self:IncProgress() + coroutine.yield() + return true end - WeakAuras.Delete(data) - uidMap:Remove(uid) - self:IncProgress() - coroutine.yield() - return true end self:IncProgress() coroutine.yield() return false end, - RemoveUnmatchedNew = function(self, uidMap, uid) + RemoveUnmatchedNew = function(self, uidMap, uid, otherMap, removeAuras, removeGroups) if uidMap:GetType() ~= "new" then error("Wrong map for delete") end @@ -1773,8 +1794,8 @@ local methods = { local children = uidMap:GetChildren(uid) local removedAllChildren = true for index, childUid in ipairs_reverse(children) do - local removed = self:RemoveUnmatchedNew(uidMap, childUid) - if not removed then + local removed = self:RemoveUnmatchedNew(uidMap, childUid, otherMap, removeAuras, removeGroups) + if not removed and not uidMap:GetUIDMatch(childUid) then removedAllChildren = false end end @@ -1785,10 +1806,17 @@ local methods = { error("Can't remove root") end - uidMap:Remove(uid) - self:IncProgress() - coroutine.yield() - return true + if (uidMap:GetGroupRegionType(uid) and removeGroups) + or (uidMap:GetGroupRegionType(uid) == nil and removeAuras) + then + for index, childUid in ipairs_reverse(children) do + uidMap:UnsetParent(childUid) + end + uidMap:Remove(uid) + self:IncProgress() + coroutine.yield() + return true + end end self:IncProgress() coroutine.yield() diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index 922f7ca..fb47c2e 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -1,7 +1,7 @@ ## Interface: 30300 ## Title: WeakAuras Options ## Author: The WeakAuras Team -## Version: 4.1.2 +## Version: 4.1.5 ## Notes: Options for WeakAuras ## Notes-esES: Opciones para WeakAuras ## Notes-deDE: Optionen für WeakAuras From e5938f813d426e5e2c120ac060f13fdd7bf8ee87 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Wed, 8 Jan 2025 16:32:09 +0100 Subject: [PATCH 010/153] from retail --- WeakAuras/AuraEnvironment.lua | 86 ++++++++++++++++++++++++- WeakAuras/Prototypes.lua | 13 ++++ WeakAuras/Types.lua | 6 ++ WeakAuras/WeakAuras.lua | 5 ++ WeakAurasOptions/AnimationOptions.lua | 24 +++---- WeakAurasOptions/CommonOptions.lua | 8 ++- WeakAurasOptions/InformationOptions.lua | 46 +++++++++++++ 7 files changed, 173 insertions(+), 15 deletions(-) diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index ed29fdc..50abe3b 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -5,6 +5,9 @@ local WeakAuras = WeakAuras local L = WeakAuras.L local prettyPrint = WeakAuras.prettyPrint +local LibSerialize = LibStub("LibSerialize") +local LibDeflate = LibStub:GetLibrary("LibDeflate") + local UnitAura = UnitAura -- Unit Aura functions that return info about the first Aura matching the spellName or spellID given on the unit. local WA_GetUnitAura = function(unit, spell, filter) @@ -154,6 +157,7 @@ local blockedTables = { SendMailMoneyGold = true, MailFrameTab2 = true, ChatFrame1 = true, + --WeakAurasSaved = true, WeakAurasOptions = true, WeakAurasOptionsSaved = true } @@ -163,6 +167,7 @@ local aura_environments = {} -- 1 == config initialized -- 2 == fully initialized local environment_initialized = {} +local getDataCallCounts = {} function Private.IsEnvironmentInitialized(id) return environment_initialized[id] == 2 @@ -171,11 +176,13 @@ end function Private.DeleteAuraEnvironment(id) aura_environments[id] = nil environment_initialized[id] = nil + getDataCallCounts[id] = nil end function Private.RenameAuraEnvironment(oldid, newid) aura_environments[oldid], aura_environments[newid] = nil, aura_environments[oldid] environment_initialized[oldid], environment_initialized[newid] = nil, environment_initialized[oldid] + getDataCallCounts[oldid], getDataCallCounts[newid] = nil, getDataCallCounts[oldid] end local current_uid = nil @@ -183,8 +190,71 @@ local current_aura_env = nil -- Stack of of aura environments/uids, allows use of recursive aura activations through calls to WeakAuras.ScanEvents(). local aura_env_stack = {} +local function UpdateSavedDataWarning(uid, size) + local savedDataWarning = 16 * 1024 * 1024 -- 16 KB, but it's only a warning + if size > savedDataWarning then + Private.AuraWarnings.UpdateWarning(uid, "CustomSavedData", "warning", + L["This aura is saving %s KB of data"]:format(ceil(size / 1024))) + else + Private.AuraWarnings.UpdateWarning(uid, "CustomSavedData") + end +end + +function Private.SaveAuraEnvironment(id) + local data = WeakAuras.GetData(id) + if not data then + return + end + + local input = aura_environments[id] and aura_environments[id].saved + if input then + local serialized = LibSerialize:SerializeEx({errorOnUnserializableType = false}, input) + -- We use minimal compression, since that already achieves a reasonable compression ratio, + -- but takes significant less time + local compressed = LibDeflate:CompressDeflate(serialized, {level = 1}) + local encoded = LibDeflate:EncodeForPrint(compressed) + UpdateSavedDataWarning(data.uid, #encoded) + data.information.saved = encoded + else + data.information.saved = nil + end +end + +function Private.RestoreAuraEnvironment(id) + local data = WeakAuras.GetData(id) + if not data then + return + end + + local input = data.information.saved + if input then + local decoded = LibDeflate:DecodeForPrint(input) + local decompressed = LibDeflate:DecompressDeflate(decoded) + local success, deserialized = LibSerialize:Deserialize(decompressed) + if success then + aura_environments[id].saved = deserialized + else + aura_environments[id].saved = nil + end + UpdateSavedDataWarning(data.uid, #input) + else + aura_environments[id].saved = nil + end +end + +function Private.ClearAuraEnvironmentSavedData(id) + if environment_initialized[id] then + aura_environments[id].saved = nil + end +end + function Private.ClearAuraEnvironment(id) - environment_initialized[id] = nil; + if environment_initialized[id] then + Private.SaveAuraEnvironment(id) + environment_initialized[id] = nil + aura_environments[id] = nil + getDataCallCounts[id] = nil + end end function Private.ActivateAuraEnvironmentForRegion(region, onlyConfig) @@ -219,6 +289,7 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) elseif onlyConfig then environment_initialized[id] = 1 aura_environments[id] = {} + getDataCallCounts[id] = 0 current_uid = data.uid current_aura_env = aura_environments[id] current_aura_env.id = id @@ -235,6 +306,7 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) -- Either this aura environment has not yet been initialized, or it was reset via an edit in WeakaurasOptions environment_initialized[id] = 2 aura_environments[id] = aura_environments[id] or {} + getDataCallCounts[id] = getDataCallCounts[id] or 0 current_uid = data.uid current_aura_env = aura_environments[id] current_aura_env.id = id @@ -242,6 +314,7 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) current_aura_env.state = state current_aura_env.states = states current_aura_env.region = region + Private.RestoreAuraEnvironment(id) -- push new environment onto the stack tinsert(aura_env_stack, {current_aura_env, data.uid}) @@ -363,7 +436,16 @@ local FakeWeakAurasMixin = { }, override = { me = UnitName("player"), - myGUID = UnitGUID("player") + myGUID = UnitGUID("player"), + GetData = function(id) + local currentId = Private.UIDtoID(current_uid) + getDataCallCounts[currentId] = getDataCallCounts[currentId] + 1 + if getDataCallCounts[currentId] > 99 then + Private.AuraWarnings.UpdateWarning(current_uid, "FakeWeakAurasGetData", "warning", + L["This aura calls GetData a lot, which is a slow function."]) + end + return CopyTable(WeakAuras.GetData(id)) + end }, blocked = blocked, setBlocked = function() diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 27e7cb5..b05f89c 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -799,6 +799,19 @@ local function valuesForTalentFunction(trigger) end Private.load_prototype = { + -- Each entry + -- name: name of argument for load function/option for options/setting in saved data + -- Options data + -- display: name to be displayed in the options + -- type: type to be used for the options + -- width: width in the options + -- hidden: whether the option is shown in the options, defaults to false + -- Load Function Data + -- enable: whether the test should be tested or not, defaults to true + -- test: overrides the default test + -- init: whether the argument should be a function parameter or not. "arg" for yes. Defaults to no argument + -- events: the events on which the test must be reevaluated + -- optional: whether the test is relevant for the options classification between loaded and unloaded, defaults to false args = { { name ="generalTitle", diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 083f9a5..6a26e9b 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -2466,6 +2466,9 @@ Private.non_transmissable_fields = { skipWagoUpdate = true, ignoreWagoUpdate = true, preferToUpdate = true, + information = { + saved = true + } } -- For nested groups, we do transmit parent + controlledChildren @@ -2474,6 +2477,9 @@ Private.non_transmissable_fields_v2000 = { skipWagoUpdate = true, ignoreWagoUpdate = true, preferToUpdate = true, + information = { + saved = true + } } WeakAuras.data_stub = { diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 6a59b76..7a34bfe 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1146,6 +1146,7 @@ local loadedFrame = CreateFrame("Frame"); WeakAuras.frames["Addon Initialization Handler"] = loadedFrame; loadedFrame:RegisterEvent("ADDON_LOADED"); loadedFrame:RegisterEvent("PLAYER_LOGIN"); +loadedFrame:RegisterEvent("PLAYER_LOGOUT"); loadedFrame:RegisterEvent("PLAYER_ENTERING_WORLD"); loadedFrame:SetScript("OnEvent", function(self, event, addon) if(event == "ADDON_LOADED") then @@ -1200,6 +1201,10 @@ loadedFrame:SetScript("OnEvent", function(self, event, addon) -- db isn't valid. Request permission to run repair tool before logging in StaticPopup_Show("WEAKAURAS_CONFIRM_REPAIR", nil, nil, {reason = "downgrade"}) end + elseif event == "PLAYER_LOGOUT" then + for id in pairs(db.displays) do + Private.SaveAuraEnvironment(id) + end else local callback if(event == "PLAYER_ENTERING_WORLD") then diff --git a/WeakAurasOptions/AnimationOptions.lua b/WeakAurasOptions/AnimationOptions.lua index e237efe..1fe0a05 100644 --- a/WeakAurasOptions/AnimationOptions.lua +++ b/WeakAurasOptions/AnimationOptions.lua @@ -385,10 +385,10 @@ function OptionsPrivate.GetAnimationOptions(data) return (data.animation.start.type ~= "custom" or not OptionsPrivate.Private.EnsureRegion(id).Color) end, get = function() - return data.animation.start.colorR, - data.animation.start.colorG, - data.animation.start.colorB, - data.animation.start.colorA; + return data.animation.start.colorR or 1, + data.animation.start.colorG or 1, + data.animation.start.colorB or 1, + data.animation.start.colorA or 1; end, set = function(info, r, g, b, a) data.animation.start.colorR = r; @@ -661,10 +661,10 @@ function OptionsPrivate.GetAnimationOptions(data) return (data.animation.main.type ~= "custom" or not OptionsPrivate.Private.EnsureRegion(id).Color) end, get = function() - return data.animation.main.colorR, - data.animation.main.colorG, - data.animation.main.colorB, - data.animation.main.colorA; + return data.animation.main.colorR or 1, + data.animation.main.colorG or 1, + data.animation.main.colorB or 1, + data.animation.main.colorA or 1; end, set = function(info, r, g, b, a) data.animation.main.colorR = r; @@ -910,10 +910,10 @@ function OptionsPrivate.GetAnimationOptions(data) return (data.animation.finish.type ~= "custom" or not OptionsPrivate.Private.EnsureRegion(id).Color) end, get = function() - return data.animation.finish.colorR, - data.animation.finish.colorG, - data.animation.finish.colorB, - data.animation.finish.colorA; + return data.animation.finish.colorR or 1, + data.animation.finish.colorG or 1, + data.animation.finish.colorB or 1, + data.animation.finish.colorA or 1; end, set = function(info, r, g, b, a) data.animation.finish.colorR = r; diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index 2c9b6ed..28d24b8 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -885,15 +885,18 @@ local getHelper = { local function CreateGetAll(subOption) return function(data, info, ...) local isToggle = nil + local isColor = nil local allChildren = CopyTable(getHelper) local enabledChildren = CopyTable(getHelper) for child in OptionsPrivate.Private.TraverseLeafs(data) do - if isToggle == nil then + if isToggle == nil or isColor == nil then local childOptions = getChildOption(OptionsPrivate.EnsureOptions(child, subOption), info) isToggle = childOptions and childOptions.type == "toggle" + isColor = childOptions and childOptions.type == "color" end + local childOptions = OptionsPrivate.EnsureOptions(child, subOption) local childOption = childOptions; local childOptionTable = {[0] = childOption}; @@ -915,6 +918,9 @@ local function CreateGetAll(subOption) end if not allChildren:GetSame() and not enabledChildren:GetSame() then + if isColor then + return 0, 0, 0, 1 + end return nil; end break; diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index 1de2680..15be76a 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -245,6 +245,52 @@ function OptionsPrivate.GetInformationOptions(data) end end + -- Saved Data + local savedDataCount = 0 + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + OptionsPrivate.Private.SaveAuraEnvironment(data.id) + if child.information.saved then + savedDataCount = savedDataCount + 1 + end + end + if savedDataCount > 0 then + args.savedDataTitle = { + type = "header", + name = L["Saved Data"], + width = WeakAuras.doubleWidth, + order = order, + } + order = order + 1 + + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + if child.information.saved then + args["savedData." .. child.uid] = { + type = "description", + name = L["%s stores around %s KB of data"]:format(child.id, ceil((#child.information.saved) / 1024)), + width = savedDataCount > 1 and WeakAuras.doubleWidth or WeakAuras.normalWidth, + order = order, + } + order = order + 1 + end + end + + args.savedDataClear = { + type = "execute", + name = L["Clear Saved Data"], + width = savedDataCount > 1 and WeakAuras.doubleWidth or WeakAuras.normalWidth, + order = order, + func = function() + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + OptionsPrivate.Private.ClearAuraEnvironmentSavedData(child.id) + WeakAuras.Add(child) + OptionsPrivate.ClearOptions(child.id) + end + WeakAuras.ClearAndUpdateOptions(data.id) + end + } + order = order + 1 + end + -- Debug Log args.debugLogTitle = { type = "header", From a5dbbd264066e1a360f021affb85745e0ccd7857 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 9 Jan 2025 15:14:12 +0100 Subject: [PATCH 011/153] Clean up WeakAuras table and remove members that no one should touch --- WeakAuras/Animations.lua | 2 +- WeakAuras/AuraEnvironment.lua | 147 ++++++++---- WeakAuras/AuraWarnings.lua | 15 +- WeakAuras/BuffTrigger2.lua | 16 +- WeakAuras/Conditions.lua | 92 ++++---- WeakAuras/GenericTrigger.lua | 61 +++-- WeakAuras/Init.lua | 4 +- WeakAuras/Profiling.lua | 2 +- WeakAuras/Prototypes.lua | 168 +++++++------- WeakAuras/RegionTypes/DynamicGroup.lua | 6 +- WeakAuras/RegionTypes/Group.lua | 2 +- WeakAuras/RegionTypes/Model.lua | 2 +- WeakAuras/RegionTypes/RegionPrototype.lua | 12 +- WeakAuras/RegionTypes/Text.lua | 8 +- WeakAuras/SubRegionTypes/Glow.lua | 2 +- WeakAuras/Types.lua | 2 +- WeakAuras/WeakAuras.lua | 213 +++++++++--------- .../AceGUIWidget-WeakAurasDisplayButton.lua | 48 ++-- .../AceGUIWidget-WeakAurasNewButton.lua | 5 +- ...UIWidget-WeakAurasPendingInstallButton.lua | 6 +- ...GUIWidget-WeakAurasPendingUpdateButton.lua | 6 +- WeakAurasOptions/AnimationOptions.lua | 12 +- WeakAurasOptions/CommonOptions.lua | 3 +- WeakAurasOptions/DisplayOptions.lua | 9 +- WeakAurasOptions/GroupOptions.lua | 5 +- .../OptionsFrames/FrameChooser.lua | 4 +- WeakAurasOptions/OptionsFrames/MoverSizer.lua | 2 +- .../OptionsFrames/OptionsFrame.lua | 21 +- WeakAurasOptions/OptionsFrames/Update.lua | 14 +- WeakAurasOptions/RegionOptions/Model.lua | 2 +- WeakAurasOptions/RegionOptions/StopMotion.lua | 2 +- .../SubRegionOptions/SubRegionCommon.lua | 4 +- WeakAurasOptions/WeakAurasOptions.lua | 99 ++++---- 33 files changed, 529 insertions(+), 467 deletions(-) diff --git a/WeakAuras/Animations.lua b/WeakAuras/Animations.lua index 59a10a2..9c8db06 100644 --- a/WeakAuras/Animations.lua +++ b/WeakAuras/Animations.lua @@ -9,7 +9,7 @@ local anim_function_strings = Private.anim_function_strings; local function noopErrorHandler() end -local frame = WeakAuras.frames["WeakAuras Main Frame"] +local frame = Private.frames["WeakAuras Main Frame"] local updatingAnimations; local last_update = GetTime(); diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index 50abe3b..6175036 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -379,18 +379,29 @@ local function MakeReadOnly(input, options) }) end +--- Wraps a table, so that accessing any key in it creates a deprecated warning +local function MakeDeprecated(input, name, warningMsg) + return setmetatable({}, + { + __index = function(t, k) + Private.AuraWarnings.UpdateWarning(current_uid, "Deprecated_" .. name, "warning", warningMsg) + return input[k] + end, + __metatable = false + }) +end + local FakeWeakAurasMixin = { blockedFunctions = { -- Other addons might use these, so before moving them to the Private space, we need -- to discuss these. But Auras have no purpose for calling these Add = true, - AddMany = true, Delete = true, HideOptions = true, Rename = true, NewAura = true, - OptionsFrame = true, - RegisterDisplay = true, + Import = true, + PreAdd = true, RegisterRegionOptions = true, RegisterSubRegionOptions = true, RegisterSubRegionType = true, @@ -400,39 +411,34 @@ local FakeWeakAurasMixin = { ShowOptions = true, -- Note these shouldn't exist in the WeakAuras namespace, but moving them takes a bit of effort, -- so for now just block them and clean them up later + createSpinner = true, ClearAndUpdateOptions = true, - CloseImportExport = true, CreateTemplateView = true, FillOptions = true, - FindUnusedId = true, GetMoverSizerId = true, - GetDisplayButton = true, - Import = true, + GetNameAndIcon = true, + GetTriggerCategoryFor = true, NewDisplayButton = true, + OpenOptions = true, PickDisplay = true, + setTile = true, SetMoverSizer = true, + SetModel = true, + Toggle = true, ToggleOptions = true, UpdateGroupOrders = true, UpdateThumbnail = true, - validate = true, - getDefaultGlow = true, }, blockedTables = { - AuraWarnings = true, ModelPaths = true, regionPrototype = true, + RealTimeProfilingWindow = true, -- Note these shouldn't exist in the WeakAuras namespace, but moving them takes a bit of effort, -- so for now just block them and clean them up later - data_stub = true, - displayButtons = true, - regionTypes = true, - regionOptions = true, + genericTriggerTypes = true, + newFeatureString = true, spellCache = true, - triggerTemplates = true, - frames = true, - loadFrame = true, - unitLoadFrame = true, - loaded = true + StopMotion = true, }, override = { me = UnitName("player"), @@ -445,7 +451,11 @@ local FakeWeakAurasMixin = { L["This aura calls GetData a lot, which is a slow function."]) end return CopyTable(WeakAuras.GetData(id)) - end + end, + clones = MakeDeprecated(Private.clones, "clones", + L["Using WeakAuras.clones is deprecated. Use WeakAuras.GetRegion(id, cloneId) instead."]), + regions = MakeDeprecated(Private.regions, "regions", + L["Using WeakAuras.regions is deprecated. Use WeakAuras.GetRegion(id) instead."]) }, blocked = blocked, setBlocked = function() @@ -468,14 +478,14 @@ local overridden = { WeakAuras = FakeWeakAuras } -local env_getglobal -local exec_env = setmetatable({}, +local env_getglobal_custom +local exec_env_custom = setmetatable({}, { __index = function(t, k) if k == "_G" then return t elseif k == "getglobal" then - return env_getglobal + return env_getglobal_custom elseif k == "aura_env" then return current_aura_env elseif k == "DebugPrint" then @@ -502,29 +512,88 @@ local exec_env = setmetatable({}, __metatable = false }) -function env_getglobal(k) - return exec_env[k] +function env_getglobal_custom(k) + return exec_env_custom[k] end -local function_cache = {} -function WeakAuras.LoadFunction(string) - if function_cache[string] then - return function_cache[string] - else - local loadedFunction, errorString = loadstring(string) - if errorString then - print(errorString) +local PrivateForBuiltIn = { + ExecEnv = Private.ExecEnv +} +local env_getglobal_builtin +local exec_env_builtin = setmetatable({}, +{ + __index = function(t, k) + if k == "_G" then + return t + elseif k == "getglobal" then + return env_getglobal_builtin + elseif k == "aura_env" then + return current_aura_env + elseif k == "DebugPrint" then + return DebugPrint + elseif k == "Private" then + -- Built in code has access to Private.ExecEnv + -- Which contains a bunch of internal helpers + return PrivateForBuiltIn + elseif blockedFunctions[k] then + blocked(k) + return function() end + elseif blockedTables[k] then + blocked(k) + return {} + elseif overridden[k] then + return overridden[k] else - setfenv(loadedFunction, exec_env) - local success, func = pcall(assert(loadedFunction)) - if success then - function_cache[string] = func - return func + return _G[k] + end + end, + __newindex = function(table, key, value) + if _G[key] then + Private.AuraWarnings.UpdateWarning(current_uid, "OverridingGlobal", "warning", + string.format(L["The aura has overwritten the global '%s', this might affect other auras."], key)) + end + rawset(table, key, value) + end, + __metatable = false +}) + +function env_getglobal_builtin(k) + return exec_env_builtin[k] +end + +local function CreateFunctionCache(exec_env) + local cache = {} + cache.Load = function(self, string) + if self[string] then + return self[string] + else + local loadedFunction, errorString = loadstring(string) + if errorString then + print(errorString) + else + setfenv(loadedFunction, exec_env) + local success, func = pcall(assert(loadedFunction)) + if success then + self[string] = func + return func + end end end end + return cache +end + +local function_cache_custom = CreateFunctionCache(exec_env_custom) +local function_cache_builtin = CreateFunctionCache(exec_env_builtin) + +function WeakAuras.LoadFunction(string) + return function_cache_custom:Load(string) +end + +function Private.LoadFunction(string) + return function_cache_builtin:Load(string) end function Private.GetSanitizedGlobal(key) - return exec_env[key] + return exec_env_custom[key] end diff --git a/WeakAuras/AuraWarnings.lua b/WeakAuras/AuraWarnings.lua index ec193e0..7561ef1 100644 --- a/WeakAuras/AuraWarnings.lua +++ b/WeakAuras/AuraWarnings.lua @@ -4,7 +4,6 @@ local AddonName, Private = ... local WeakAuras = WeakAuras local L = WeakAuras.L --- keyed on uid, key, { severity, message } local warnings = {} local printedWarnings = {} @@ -14,8 +13,9 @@ local function OnDelete(event, uid) end Private.callbacks:RegisterCallback("Delete", OnDelete) +Private.AuraWarnings = {} -local function UpdateWarning(uid, key, severity, message, printOnConsole) +function Private.AuraWarnings.UpdateWarning(uid, key, severity, message, printOnConsole) if not uid then WeakAuras.prettyPrint(L["Warning for unknown aura:"], message) return @@ -64,7 +64,7 @@ local titles = { info = L["Information"], sound = L["Sound"], warning = L["Warning"], - error = L["Error"] + error = L["Error"], } local function AddMessages(result, messages, icon, mixedSeverity) @@ -89,7 +89,7 @@ local function AddMessages(result, messages, icon, mixedSeverity) return result end -local function FormatWarnings(uid) +function Private.AuraWarnings.FormatWarnings(uid) if not warnings[uid] then return end @@ -123,7 +123,7 @@ local function FormatWarnings(uid) return icons[maxSeverity], titles[maxSeverity], result end -local function GetAllWarnings(uid) +function Private.AuraWarnings.GetAllWarnings(uid) local results = {} local thisWarnings local data = Private.GetDataByUID(uid) @@ -163,8 +163,3 @@ local function GetAllWarnings(uid) end return results end - -Private.AuraWarnings = {} -Private.AuraWarnings.UpdateWarning = UpdateWarning -Private.AuraWarnings.FormatWarnings = FormatWarnings -Private.AuraWarnings.GetAllWarnings = GetAllWarnings diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 68416b4..3688f18 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -1723,7 +1723,7 @@ local function RecheckActiveForUnitType(unitType, unit, unitsToRemoveScan) end local Buff2Frame = CreateFrame("Frame") -WeakAuras.frames["WeakAuras Buff2 Frame"] = Buff2Frame +Private.frames["WeakAuras Buff2 Frame"] = Buff2Frame local function EventHandler(frame, event, arg1, arg2, ...) @@ -2340,7 +2340,7 @@ function BuffTrigger.Add(data) local remFunc if trigger.unit ~= "multi" and CanHaveMatchCheck(trigger) and trigger.useRem then local remFuncStr = Private.function_strings.count:format(trigger.remOperator or ">=", tonumber(trigger.rem) or 0) - remFunc = WeakAuras.LoadFunction(remFuncStr) + remFunc = Private.LoadFunction(remFuncStr) end local names @@ -2370,14 +2370,14 @@ function BuffTrigger.Add(data) else group_countFuncStr = Private.function_strings.count:format(">", 0) end - groupCountFunc = WeakAuras.LoadFunction(group_countFuncStr) + groupCountFunc = Private.LoadFunction(group_countFuncStr) end local matchCountFunc if HasMatchCount(trigger) and trigger.match_countOperator and trigger.match_count and tonumber(trigger.match_count) then local count = tonumber(trigger.match_count) local match_countFuncStr = Private.function_strings.count:format(trigger.match_countOperator, count) - matchCountFunc = WeakAuras.LoadFunction(match_countFuncStr) + matchCountFunc = Private.LoadFunction(match_countFuncStr) elseif IsGroupTrigger(trigger) then if trigger.showClones and not trigger.combinePerUnit then matchCountFunc = GreaterEqualOne @@ -2395,7 +2395,7 @@ function BuffTrigger.Add(data) and tonumber(trigger.matchPerUnit_count) and trigger.matchPerUnit_countOperator then local count = tonumber(trigger.matchPerUnit_count) local match_countFuncStr = Private.function_strings.count:format(trigger.matchPerUnit_countOperator, count) - matchPerUnitCountFunc = WeakAuras.LoadFunction(match_countFuncStr) + matchPerUnitCountFunc = Private.LoadFunction(match_countFuncStr) end local groupTrigger = trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party" @@ -2407,7 +2407,7 @@ function BuffTrigger.Add(data) local effectiveIgnoreInvisible = groupTrigger and trigger.ignoreInvisible local effectiveHostility = trigger.unit == "nameplate" and trigger.useHostility and trigger.hostility local effectiveNameCheck = groupTrigger and trigger.useUnitName and trigger.unitName - local effectiveNpcId = trigger.unit == "nameplate" and trigger.useNpcId and WeakAuras.ParseStringCheck(trigger.npcId) + local effectiveNpcId = trigger.unit == "nameplate" and trigger.useNpcId and Private.ExecEnv.ParseStringCheck(trigger.npcId) if trigger.unit == "multi" then BuffTrigger.InitMultiAura() @@ -2471,7 +2471,7 @@ function BuffTrigger.Add(data) matchPerUnitCountFunc = matchPerUnitCountFunc, useAffected = unit == "group" and trigger.useAffected, isMulti = trigger.unit == "multi", - nameChecker = effectiveNameCheck and WeakAuras.ParseNameCheck(trigger.unitName), + nameChecker = effectiveNameCheck and Private.ExecEnv.ParseNameCheck(trigger.unitName), includePets = trigger.use_includePets and trigger.includePets or nil, npcId = effectiveNpcId } @@ -3310,7 +3310,7 @@ function BuffTrigger.InitMultiAura() end multiAuraFrame:RegisterEvent("PLAYER_LEAVING_WORLD") multiAuraFrame:SetScript("OnEvent", BuffTrigger.HandleMultiEvent) - WeakAuras.frames["Multi-target 2 Aura Trigger Handler"] = multiAuraFrame + Private.frames["Multi-target 2 Aura Trigger Handler"] = multiAuraFrame end end diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index 0250c26..d1396dd 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -125,7 +125,7 @@ end -function WeakAuras.scheduleConditionCheck(time, uid, cloneId) +function Private.ExecEnv.ScheduleConditionCheck(time, uid, cloneId) conditionChecksTimers.recheckTime[uid] = conditionChecksTimers.recheckTime[uid] or {} conditionChecksTimers.recheckHandle[uid] = conditionChecksTimers.recheckHandle[uid] or {}; @@ -148,8 +148,8 @@ function WeakAuras.scheduleConditionCheck(time, uid, cloneId) end end -function WeakAuras.CallCustomConditionTest(uid, testFunctionNumber, ...) - local ok, result = pcall(WeakAuras.conditionHelpers[uid].customTestFunctions[testFunctionNumber], ...) +function Private.ExecEnv.CallCustomConditionTest(uid, testFunctionNumber, ...) + local ok, result = pcall(Private.ExecEnv.conditionHelpers[uid].customTestFunctions[testFunctionNumber], ...) if not ok then Private.GetErrorHandlerUid(uid, L["Condition Custom Text"]) elseif (ok) then @@ -203,34 +203,34 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta local preambleString if preamble then - WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {} - WeakAuras.conditionHelpers[uid].preambles = WeakAuras.conditionHelpers[uid].preambles or {} - tinsert(WeakAuras.conditionHelpers[uid].preambles, preamble(value) or ""); - local preambleNumber = #WeakAuras.conditionHelpers[uid].preambles - preambleString = string.format("WeakAuras.conditionHelpers[%q].preambles[%s]", uid, preambleNumber) + Private.ExecEnv.conditionHelpers[uid] = Private.ExecEnv.conditionHelpers[uid] or {} + Private.ExecEnv.conditionHelpers[uid].preambles = Private.ExecEnv.conditionHelpers[uid].preambles or {} + tinsert(Private.ExecEnv.conditionHelpers[uid].preambles, preamble(value) or ""); + local preambleNumber = #Private.ExecEnv.conditionHelpers[uid].preambles + preambleString = string.format("Private.ExecEnv.conditionHelpers[%q].preambles[%s]", uid, preambleNumber) end if (test) then if (value) then - WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {} - WeakAuras.conditionHelpers[uid].customTestFunctions = WeakAuras.conditionHelpers[uid].customTestFunctions or {} - tinsert(WeakAuras.conditionHelpers[uid].customTestFunctions, test); - local testFunctionNumber = #(WeakAuras.conditionHelpers[uid].customTestFunctions); + Private.ExecEnv.conditionHelpers[uid] = Private.ExecEnv.conditionHelpers[uid] or {} + Private.ExecEnv.conditionHelpers[uid].customTestFunctions = Private.ExecEnv.conditionHelpers[uid].customTestFunctions or {} + tinsert(Private.ExecEnv.conditionHelpers[uid].customTestFunctions, test); + local testFunctionNumber = #(Private.ExecEnv.conditionHelpers[uid].customTestFunctions); local valueString = type(value) == "string" and string.format("%q", value) or value; local opString = type(op) == "string" and string.format("%q", op) or op; - check = string.format("state and WeakAuras.CallCustomConditionTest(%q, %s, state[%s], %s, %s, %s)", + check = string.format("state and Private.ExecEnv.CallCustomConditionTest(%q, %s, state[%s], %s, %s, %s)", uid, testFunctionNumber, trigger, valueString, (opString or "nil"), preambleString or "nil"); end elseif (cType == "customcheck") then if value then local customCheck = WeakAuras.LoadFunction("return " .. value) if customCheck then - WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {} - WeakAuras.conditionHelpers[uid].customTestFunctions = WeakAuras.conditionHelpers[uid].customTestFunctions or {} - tinsert(WeakAuras.conditionHelpers[uid].customTestFunctions, customCheck); - local testFunctionNumber = #(WeakAuras.conditionHelpers[uid].customTestFunctions); + Private.ExecEnv.conditionHelpers[uid] = Private.ExecEnv.conditionHelpers[uid] or {} + Private.ExecEnv.conditionHelpers[uid].customTestFunctions = Private.ExecEnv.conditionHelpers[uid].customTestFunctions or {} + tinsert(Private.ExecEnv.conditionHelpers[uid].customTestFunctions, customCheck); + local testFunctionNumber = #(Private.ExecEnv.conditionHelpers[uid].customTestFunctions); - check = string.format("state and WeakAuras.CallCustomConditionTest(%q, %s, state)", + check = string.format("state and Private.ExecEnv.CallCustomConditionTest(%q, %s, state)", uid, testFunctionNumber, trigger); end end @@ -297,12 +297,12 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta if fn then local customCheck = WeakAuras.LoadFunction(fn) if customCheck then - WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {} - WeakAuras.conditionHelpers[uid].customTestFunctions = WeakAuras.conditionHelpers[uid].customTestFunctions or {} - tinsert(WeakAuras.conditionHelpers[uid].customTestFunctions, customCheck); - local testFunctionNumber = #(WeakAuras.conditionHelpers[uid].customTestFunctions); + Private.ExecEnv.conditionHelpers[uid] = Private.ExecEnv.conditionHelpers[uid] or {} + Private.ExecEnv.conditionHelpers[uid].customTestFunctions = Private.ExecEnv.conditionHelpers[uid].customTestFunctions or {} + tinsert(Private.ExecEnv.conditionHelpers[uid].customTestFunctions, customCheck); + local testFunctionNumber = #(Private.ExecEnv.conditionHelpers[uid].customTestFunctions); - check = string.format("state and WeakAuras.CallCustomConditionTest(%q, %s, state)", + check = string.format("state and Private.ExecEnv.CallCustomConditionTest(%q, %s, state)", uid, testFunctionNumber, trigger); end end @@ -423,17 +423,17 @@ local function CreateActivateCondition(ret, id, condition, conditionNumber, prop elseif (propertyData.action) then local pathToCustomFunction = "nil"; local pathToFormatter = "nil" - if (WeakAuras.customConditionsFunctions[id] - and WeakAuras.customConditionsFunctions[id][conditionNumber] - and WeakAuras.customConditionsFunctions[id][conditionNumber].changes - and WeakAuras.customConditionsFunctions[id][conditionNumber].changes[changeNum]) then - pathToCustomFunction = string.format("WeakAuras.customConditionsFunctions[%q][%s].changes[%s]", id, conditionNumber, changeNum); + if (Private.ExecEnv.customConditionsFunctions[id] + and Private.ExecEnv.customConditionsFunctions[id][conditionNumber] + and Private.ExecEnv.customConditionsFunctions[id][conditionNumber].changes + and Private.ExecEnv.customConditionsFunctions[id][conditionNumber].changes[changeNum]) then + pathToCustomFunction = string.format("Private.ExecEnv.customConditionsFunctions[%q][%s].changes[%s]", id, conditionNumber, changeNum); end - if WeakAuras.conditionTextFormatters[id] - and WeakAuras.conditionTextFormatters[id][conditionNumber] - and WeakAuras.conditionTextFormatters[id][conditionNumber].changes - and WeakAuras.conditionTextFormatters[id][conditionNumber].changes[changeNum] then - pathToFormatter = string.format("WeakAuras.conditionTextFormatters[%q][%s].changes[%s]", id, conditionNumber, changeNum); + if Private.ExecEnv.conditionTextFormatters[id] + and Private.ExecEnv.conditionTextFormatters[id][conditionNumber] + and Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes + and Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes[changeNum] then + pathToFormatter = string.format("Private.ExecEnv.conditionTextFormatters[%q][%s].changes[%s]", id, conditionNumber, changeNum); end ret = ret .. " region:" .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction, pathToFormatter) .. ")" .. "\n"; if (debug) then ret = ret .. " print('# " .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction, pathToFormatter) .. "')\n"; end @@ -489,7 +489,7 @@ end function Private.GetProperties(data) local properties; - local propertiesFunction = WeakAuras.regionTypes[data.regionType] and WeakAuras.regionTypes[data.regionType].properties; + local propertiesFunction = Private.regionTypes[data.regionType] and Private.regionTypes[data.regionType].properties; if (type(propertiesFunction) == "function") then properties = propertiesFunction(data); elseif propertiesFunction then @@ -505,7 +505,7 @@ end function Private.LoadConditionPropertyFunctions(data) local id = data.id; if (data.conditions) then - WeakAuras.customConditionsFunctions[id] = {}; + Private.ExecEnv.customConditionsFunctions[id] = {}; for conditionNumber, condition in ipairs(data.conditions) do if (condition.changes) then for changeIndex, change in ipairs(condition.changes) do @@ -519,9 +519,9 @@ function Private.LoadConditionPropertyFunctions(data) end local customFunc = WeakAuras.LoadFunction(prefix .. custom .. suffix); if (customFunc) then - WeakAuras.customConditionsFunctions[id][conditionNumber] = WeakAuras.customConditionsFunctions[id][conditionNumber] or {}; - WeakAuras.customConditionsFunctions[id][conditionNumber].changes = WeakAuras.customConditionsFunctions[id][conditionNumber].changes or {}; - WeakAuras.customConditionsFunctions[id][conditionNumber].changes[changeIndex] = customFunc; + Private.ExecEnv.customConditionsFunctions[id][conditionNumber] = Private.ExecEnv.customConditionsFunctions[id][conditionNumber] or {}; + Private.ExecEnv.customConditionsFunctions[id][conditionNumber].changes = Private.ExecEnv.customConditionsFunctions[id][conditionNumber].changes or {}; + Private.ExecEnv.customConditionsFunctions[id][conditionNumber].changes[changeIndex] = customFunc; end end if change.property == "chat" then @@ -533,10 +533,10 @@ function Private.LoadConditionPropertyFunctions(data) return change.value[fullKey] end local formatters = change.value and Private.CreateFormatters(change.value.message, getter, true) - WeakAuras.conditionTextFormatters[id] = WeakAuras.conditionTextFormatters[id] or {} - WeakAuras.conditionTextFormatters[id][conditionNumber] = WeakAuras.conditionTextFormatters[id][conditionNumber] or {}; - WeakAuras.conditionTextFormatters[id][conditionNumber].changes = WeakAuras.conditionTextFormatters[id][conditionNumber].changes or {}; - WeakAuras.conditionTextFormatters[id][conditionNumber].changes[changeIndex] = formatters; + Private.ExecEnv.conditionTextFormatters[id] = Private.ExecEnv.conditionTextFormatters[id] or {} + Private.ExecEnv.conditionTextFormatters[id][conditionNumber] = Private.ExecEnv.conditionTextFormatters[id][conditionNumber] or {}; + Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes = Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes or {}; + Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes[changeIndex] = formatters; end end end @@ -620,7 +620,7 @@ local function ConstructConditionFunction(data) ret = ret .. " if (not hideRegion) then\n" local recheckCode = "" if (data.conditions) then - WeakAuras.conditionHelpers[data.uid] = nil + Private.ExecEnv.conditionHelpers[data.uid] = nil for conditionNumber, condition in ipairs(data.conditions) do local nextIsLinked = data.conditions[conditionNumber + 1] and data.conditions[conditionNumber + 1].linked local additionalRecheckCode @@ -634,7 +634,7 @@ local function ConstructConditionFunction(data) ret = ret .. " end\n"; ret = ret .. " if (recheckTime) then\n" - ret = ret .. " WeakAuras.scheduleConditionCheck(recheckTime, uid, cloneId);\n" + ret = ret .. " Private.ExecEnv.ScheduleConditionCheck(recheckTime, uid, cloneId);\n" ret = ret .. " end\n" local properties = Private.GetProperties(data); @@ -697,7 +697,7 @@ function Private.LoadConditionFunction(data) CancelTimers(data.uid) local checkConditionsFuncStr = ConstructConditionFunction(data); - local checkCondtionsFunc = checkConditionsFuncStr and WeakAuras.LoadFunction(checkConditionsFuncStr); + local checkCondtionsFunc = checkConditionsFuncStr and Private.LoadFunction(checkConditionsFuncStr) checkConditions[data.uid] = checkCondtionsFunc; end @@ -845,7 +845,7 @@ function Private.RegisterForGlobalConditions(uid) dynamicConditionsFrame = CreateFrame("Frame"); dynamicConditionsFrame:SetScript("OnEvent", handleDynamicConditions); dynamicConditionsFrame.units = {} - WeakAuras.frames["Rerun Conditions Frame"] = dynamicConditionsFrame + Private.frames["Rerun Conditions Frame"] = dynamicConditionsFrame end for event in pairs(register) do diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index f914fb9..ea58ce8 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -74,7 +74,6 @@ local loaded_events = {} local loaded_unit_events = {}; local watched_trigger_events = Private.watched_trigger_events local loaded_auras = {}; -- id to bool map -local timers = WeakAuras.timers; -- Local functions local LoadEvent, HandleEvent, HandleUnitEvent, TestForTriState, TestForToggle, TestForLongString, TestForMultiSelect @@ -1089,7 +1088,7 @@ local genericTriggerRegisteredEvents = {}; local genericTriggerRegisteredUnitEvents = {}; local frame = CreateFrame("Frame"); frame.unitFrames = {}; -WeakAuras.frames["WeakAuras Generic Trigger Frame"] = frame; +Private.frames["WeakAuras Generic Trigger Frame"] = frame; frame:RegisterEvent("PLAYER_ENTERING_WORLD"); genericTriggerRegisteredEvents["PLAYER_ENTERING_WORLD"] = true; if WeakAuras.isAwesomeEnabled() then @@ -1392,7 +1391,7 @@ function GenericTrigger.Add(data, region) triggerFuncStr = ConstructFunction(prototype, trigger); statesParameter = prototype.statesParameter; - triggerFunc = WeakAuras.LoadFunction(triggerFuncStr); + triggerFunc = Private.LoadFunction(triggerFuncStr); durationFunc = prototype.durationFunc; nameFunc = prototype.nameFunc; @@ -1623,7 +1622,7 @@ do local update_clients = {}; local update_clients_num = 0; local update_frame = nil - WeakAuras.frames["Custom Trigger Every Frame Updater"] = update_frame; + Private.frames["Custom Trigger Every Frame Updater"] = update_frame; local updating = false; function Private.RegisterEveryFrameUpdate(id) @@ -2084,9 +2083,9 @@ do local spellDetails = {} - function WeakAuras.InitCooldownReady() + function Private.InitCooldownReady() cdReadyFrame = CreateFrame("Frame"); - WeakAuras.frames["Cooldown Trigger Handler"] = cdReadyFrame + Private.frames["Cooldown Trigger Handler"] = cdReadyFrame cdReadyFrame:RegisterEvent("RUNE_POWER_UPDATE"); cdReadyFrame:RegisterEvent("RUNE_TYPE_UPDATE"); cdReadyFrame:RegisterEvent("PLAYER_TALENT_UPDATE"); @@ -2504,13 +2503,13 @@ do function WeakAuras.WatchGCD() if not(cdReadyFrame) then - WeakAuras.InitCooldownReady(); + Private.InitCooldownReady(); end end function WeakAuras.WatchRuneCooldown(id) if not(cdReadyFrame) then - WeakAuras.InitCooldownReady(); + Private.InitCooldownReady(); end if not id or id == 0 then return end @@ -2538,7 +2537,7 @@ do function WeakAuras.WatchSpellCooldown(id, ignoreRunes) if not(cdReadyFrame) then - WeakAuras.InitCooldownReady(); + Private.InitCooldownReady(); end if not id or id == 0 then return end @@ -2570,7 +2569,7 @@ do function WeakAuras.WatchItemCooldown(id) if not(cdReadyFrame) then - WeakAuras.InitCooldownReady(); + Private.InitCooldownReady(); end if not id or id == 0 then return end @@ -2599,7 +2598,7 @@ do function WeakAuras.WatchItemSlotCooldown(id) if not(cdReadyFrame) then - WeakAuras.InitCooldownReady(); + Private.InitCooldownReady(); end if not id or id == 0 then return end @@ -2644,7 +2643,7 @@ function WeakAuras.WatchUnitChange(unit) watchUnitChange.nameplateFaction = {} watchUnitChange.raidmark = {} - WeakAuras.frames["Unit Change Frame"] = watchUnitChange; + Private.frames["Unit Change Frame"] = watchUnitChange; watchUnitChange:RegisterEvent("PLAYER_TARGET_CHANGED") watchUnitChange:RegisterEvent("PLAYER_FOCUS_CHANGED"); watchUnitChange:RegisterEvent("PLAYER_ROLES_ASSIGNED"); @@ -2916,7 +2915,7 @@ do end end - function WeakAuras.DBMTimerMatches(timerId, id, message, operator, spellId, dbmType, count) + function Private.ExecEnv.DBMTimerMatches(timerId, id, message, operator, spellId, dbmType, count) if not bars[timerId] then return false end @@ -2967,7 +2966,7 @@ do function WeakAuras.GetDBMTimer(id, message, operator, spellId, extendTimer, dbmType, count) local bestMatch for timerId, bar in pairs(bars) do - if WeakAuras.DBMTimerMatches(timerId, id, message, operator, spellId, dbmType, count) + if Private.ExecEnv.DBMTimerMatches(timerId, id, message, operator, spellId, dbmType, count) and (bestMatch == nil or bar.expirationTime < bestMatch.expirationTime) and bar.expirationTime + extendTimer > GetTime() then @@ -2977,7 +2976,7 @@ do return bestMatch end - function WeakAuras.CopyBarToState(bar, states, id, extendTimer) + function Private.ExecEnv.CopyBarToState(bar, states, id, extendTimer) extendTimer = extendTimer or 0 if extendTimer + bar.duration < 0 then return end states[id] = states[id] or {} @@ -3021,7 +3020,7 @@ do scheduled_scans[fireTime] = nil WeakAuras.ScanEvents("DBM_TimerUpdate") end - function WeakAuras.ScheduleDbmCheck(fireTime) + function Private.ExecEnv.ScheduleDbmCheck(fireTime) if not scheduled_scans[fireTime] then scheduled_scans[fireTime] = timer:ScheduleTimer(doDbmScan, fireTime - GetTime() + 0.1, fireTime) end @@ -3126,7 +3125,7 @@ do WeakAuras.RegisterBigWigsCallback("BigWigs_OnBossDisable") end - function WeakAuras.CopyBigWigsTimerToState(bar, states, id, extendTimer) + function Private.ExecEnv.CopyBigWigsTimerToState(bar, states, id, extendTimer) extendTimer = extendTimer or 0 if extendTimer + bar.duration < 0 then return end states[id] = states[id] or {} @@ -3153,7 +3152,7 @@ do end end - function WeakAuras.BigWigsTimerMatches(id, message, operator, spellId, emphasized, count, cast) + function Private.ExecEnv.BigWigsTimerMatches(id, message, operator, spellId, emphasized, count, cast) if not bars[id] then return false end @@ -3201,7 +3200,7 @@ do function WeakAuras.GetBigWigsTimer(text, operator, spellId, extendTimer, emphasized, count, cast) local bestMatch for id, bar in pairs(bars) do - if WeakAuras.BigWigsTimerMatches(id, text, operator, spellId, emphasized, count, cast) + if Private.ExecEnv.BigWigsTimerMatches(id, text, operator, spellId, emphasized, count, cast) and (bestMatch == nil or bar.expirationTime < bestMatch.expirationTime) and bar.expirationTime + extendTimer > GetTime() then @@ -3218,14 +3217,14 @@ do WeakAuras.ScanEvents("BigWigs_Timer_Update") end - function WeakAuras.ScheduleBigWigsCheck(fireTime) + function Private.ExecEnv.ScheduleBigWigsCheck(fireTime) if not scheduled_scans[fireTime] then scheduled_scans[fireTime] = timer:ScheduleTimer(doBigWigsScan, fireTime - GetTime() + 0.1, fireTime) end end end -function WeakAuras.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemOperator) +function Private.ExecEnv.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemOperator) if not totemName or totemName == "" then return false end @@ -3265,7 +3264,7 @@ do local oh_icon = GetInventoryItemTexture("player", oh); local tenchFrame = nil - WeakAuras.frames["Temporary Enchant Handler"] = tenchFrame; + Private.frames["Temporary Enchant Handler"] = tenchFrame; local tenchTip; function WeakAuras.TenchInit() @@ -3347,7 +3346,7 @@ end -- Pets do local petFrame = nil - WeakAuras.frames["Pet Use Handler"] = petFrame; + Private.frames["Pet Use Handler"] = petFrame; function WeakAuras.WatchForPetDeath() if not(petFrame) then petFrame = CreateFrame("Frame"); @@ -3365,7 +3364,7 @@ end -- Cast Latency do local castLatencyFrame = nil - WeakAuras.frames["Cast Latency Handler"] = castLatencyFrame + Private.frames["Cast Latency Handler"] = castLatencyFrame function WeakAuras.WatchForCastLatency() if not castLatencyFrame then castLatencyFrame = CreateFrame("Frame") @@ -3431,7 +3430,7 @@ if WeakAuras.isAwesomeEnabled() then end end - WeakAuras.frames["Nameplate Target Handler"] = nameplateTargetFrame + Private.frames["Nameplate Target Handler"] = nameplateTargetFrame function WeakAuras.WatchForNameplateTargetChange() if not nameplateTargetFrame then nameplateTargetFrame = CreateFrame("Frame") @@ -3468,7 +3467,7 @@ do function WeakAuras.WatchForMounts() if not(mountedFrame) then mountedFrame = CreateFrame("Frame"); - WeakAuras.frames["Mount Use Handler"] = mountedFrame; + Private.frames["Mount Use Handler"] = mountedFrame; mountedFrame:RegisterEvent("COMPANION_UPDATE"); mountedFrame:SetScript("OnEvent", function() elapsed = 0; @@ -3495,7 +3494,7 @@ do function WeakAuras.WatchPlayerMoveSpeed() if not (playerMovingFrame) then playerMovingFrame = CreateFrame("Frame"); - WeakAuras.frames["Player Moving Frame"] = playerMovingFrame; + Private.frames["Player Moving Frame"] = playerMovingFrame; end playerMovingFrame.speed = GetUnitSpeed("player") playerMovingFrame:SetScript("OnUpdate", PlayerMoveSpeedUpdate) @@ -3579,7 +3578,7 @@ do function WeakAuras.WatchNamePlates() if not(watchNameplates) then watchNameplates = CreateFrame("Frame") - WeakAuras.frames["Watch NamePlates Frames"] = watchNameplates + Private.frames["Watch NamePlates Frames"] = watchNameplates end watchNameplates:SetScript("OnUpdate", nameplatesUpdate) end @@ -3627,7 +3626,7 @@ do function WeakAuras.WatchQueuedAction() if not(queuedActionFrame) then queuedActionFrame = CreateFrame("Frame"); - WeakAuras.frames["Queued Action Frame"] = queuedActionFrame + Private.frames["Queued Action Frame"] = queuedActionFrame for slotID = 1, 120 do local spellID = GetActionSpellID(slotID) if spellID then @@ -3663,7 +3662,7 @@ do scheduled_scans[event][fireTime] = nil; WeakAuras.ScanEvents(event); end - function WeakAuras.ScheduleScan(fireTime, event) + function Private.ExecEnv.ScheduleScan(fireTime, event) event = event or "COOLDOWN_REMAINING_CHECK" scheduled_scans[event] = scheduled_scans[event] or {} if not(scheduled_scans[event][fireTime]) then @@ -3684,7 +3683,7 @@ do WeakAuras.ScanEvents("CAST_REMAINING_CHECK_" .. string.lower(unit), unit); end end - function WeakAuras.ScheduleCastCheck(fireTime, unit) + function Private.ExecEnv.ScheduleCastCheck(fireTime, unit) scheduled_scans[unit] = scheduled_scans[unit] or {} if not(scheduled_scans[unit][fireTime]) then scheduled_scans[unit][fireTime] = timer:ScheduleTimer(doCastScan, fireTime - GetTime() + 0.1, fireTime, unit); diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index d80616e..2cb6bb3 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -1,7 +1,7 @@ local AddonName, Private = ... WeakAuras = {} WeakAuras.L = {} -WeakAuras.frames = {} +Private.frames = {} WeakAuras.normalWidth = 1.3 WeakAuras.halfWidth = WeakAuras.normalWidth / 2 @@ -117,6 +117,8 @@ end function Private.StopProfileUID() end +Private.ExecEnv = {} + -- If WeakAuras shuts down due to being installed on the wrong target, keep the bindings from erroring function WeakAuras.StartProfile() end diff --git a/WeakAuras/Profiling.lua b/WeakAuras/Profiling.lua index 224f46a..89d12be 100644 --- a/WeakAuras/Profiling.lua +++ b/WeakAuras/Profiling.lua @@ -13,7 +13,7 @@ profileData.auras = {} local currentProfileState, ProfilingTimer local RealTimeProfilingWindow = CreateFrame("Button", nil, UIParent) -WeakAuras.frames["RealTime Profiling Window"] = RealTimeProfilingWindow +Private.frames["RealTime Profiling Window"] = RealTimeProfilingWindow RealTimeProfilingWindow.width = 500 RealTimeProfilingWindow.height = 300 RealTimeProfilingWindow.barHeight = 20 diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index b05f89c..c443777 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -644,7 +644,7 @@ function WeakAuras.ValidateNumericOrPercent(info, val) return true end -function WeakAuras.CheckGroupMemberType(loadSetting, currentFlags) +function Private.ExecEnv.CheckGroupMemberType(loadSetting, currentFlags) if loadSetting == "LEADER" then return bit.band(currentFlags, 1) == 1 elseif loadSetting == "ASSIST" then @@ -654,13 +654,13 @@ function WeakAuras.CheckGroupMemberType(loadSetting, currentFlags) end end -function WeakAuras.CheckChargesDirection(direction, triggerDirection) +function Private.ExecEnv.CheckChargesDirection(direction, triggerDirection) return triggerDirection == "CHANGED" or (triggerDirection == "GAINED" and direction > 0) or (triggerDirection == "LOST" and direction < 0) end -function WeakAuras.CheckCombatLogFlags(flags, flagToCheck) +function Private.ExecEnv.CheckCombatLogFlags(flags, flagToCheck) if type(flags) ~= "number" then return end if(flagToCheck == "Mine") then return bit.band(flags, COMBATLOG_OBJECT_AFFILIATION_MINE) > 0 @@ -673,7 +673,7 @@ function WeakAuras.CheckCombatLogFlags(flags, flagToCheck) end end -function WeakAuras.CheckCombatLogFlagsReaction(flags, flagToCheck) +function Private.ExecEnv.CheckCombatLogFlagsReaction(flags, flagToCheck) if type(flags) ~= "number" then return end if (flagToCheck == "Hostile") then return bit.band(flags, 64) ~= 0; @@ -692,14 +692,14 @@ local objectTypeToBit = { Player = 1024, } -function WeakAuras.CheckCombatLogFlagsObjectType(flags, flagToCheck) +function Private.ExecEnv.CheckCombatLogFlagsObjectType(flags, flagToCheck) if type(flags) ~= "number" then return end local bitToCheck = objectTypeToBit[flagToCheck] if not bitToCheck then return end return bit.band(flags, bitToCheck) ~= 0; end -function WeakAuras.CheckRaidFlags(flags, flagToCheck) +function Private.ExecEnv.CheckRaidFlags(flags, flagToCheck) flagToCheck = tonumber(flagToCheck) if not flagToCheck or not flags then return end --bailout if flagToCheck == 0 then --no raid mark @@ -893,7 +893,7 @@ Private.load_prototype = { type = "string", multiline = true, test = "nameRealmChecker:Check(player, realm)", - preamble = "local nameRealmChecker = WeakAuras.ParseNameCheck(%q)", + preamble = "local nameRealmChecker = Private.ExecEnv.ParseNameCheck(%q)", desc = constants.nameRealmFilterDesc, }, { @@ -902,7 +902,7 @@ Private.load_prototype = { type = "string", multiline = true, test = "not nameRealmIgnoreChecker:Check(player, realm)", - preamble = "local nameRealmIgnoreChecker = WeakAuras.ParseNameCheck(%q)", + preamble = "local nameRealmIgnoreChecker = Private.ExecEnv.ParseNameCheck(%q)", desc = constants.nameRealmFilterDesc, }, { @@ -1014,7 +1014,7 @@ Private.load_prototype = { init = "arg", events = {"PARTY_LEADER_CHANGED", "RAID_ROSTER_UPDATE"}, values = "group_member_types", - test = "WeakAuras.CheckGroupMemberType(%s, group_leader)", + test = "Private.ExecEnv.CheckGroupMemberType(%s, group_leader)", optional = true, }, { @@ -1028,7 +1028,7 @@ Private.load_prototype = { type = "string", multiline = true, init = "arg", - preamble = "local zoneChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local zoneChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "zoneChecker:Check(zone)", events = {"ZONE_CHANGED", "ZONE_CHANGED_INDOORS", "ZONE_CHANGED_NEW_AREA", "VEHICLE_UPDATE", "WA_DELAYED_PLAYER_ENTERING_WORLD" }, desc = function() @@ -1055,7 +1055,7 @@ Private.load_prototype = { type = "string", multiline = true, init = "arg", - preamble = "local subzoneChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local subzoneChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "subzoneChecker:Check(subzone)", events = { "ZONE_CHANGED", "ZONE_CHANGED_INDOORS", "ZONE_CHANGED_NEW_AREA", "VEHICLE_UPDATE", "WA_DELAYED_PLAYER_ENTERING_WORLD" }, desc = function() @@ -1427,11 +1427,11 @@ Private.event_prototypes = { desc = constants.nameRealmFilterDesc, type = "string", multiline = true, - preamble = "local nameRealmChecker = WeakAuras.ParseNameCheck(%q)", + preamble = "local nameRealmChecker = Private.ExecEnv.ParseNameCheck(%q)", test = "nameRealmChecker:Check(name, realm)", conditionType = "string", conditionPreamble = function(input) - return WeakAuras.ParseNameCheck(input) + return Private.ExecEnv.ParseNameCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.name, state.realm) @@ -1553,10 +1553,10 @@ Private.event_prototypes = { store = true, init = "tostring(tonumber(string.sub(UnitGUID(unit) or '', 8, 12), 16) or '')", conditionType = "string", - preamble = "local npcIdChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local npcIdChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "npcIdChecker:Check(npcId)", conditionPreamble = function(input) - return WeakAuras.ParseStringCheck(input) + return Private.ExecEnv.ParseStringCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.npcId) @@ -1895,11 +1895,11 @@ Private.event_prototypes = { display = L["Unit Name/Realm"], type = "string", multiline = true, - preamble = "local nameRealmChecker = WeakAuras.ParseNameCheck(%q)", + preamble = "local nameRealmChecker = Private.ExecEnv.ParseNameCheck(%q)", test = "nameRealmChecker:Check(name, realm)", conditionType = "string", conditionPreamble = function(input) - return WeakAuras.ParseNameCheck(input) + return Private.ExecEnv.ParseNameCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.name, state.realm) @@ -1915,10 +1915,10 @@ Private.event_prototypes = { store = true, init = "tostring(tonumber(string.sub(UnitGUID(unit) or '', 8, 12), 16) or '')", conditionType = "string", - preamble = "local npcIdChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local npcIdChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "npcIdChecker:Check(npcId)", conditionPreamble = function(input) - return WeakAuras.ParseStringCheck(input) + return Private.ExecEnv.ParseStringCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.npcId) @@ -2235,11 +2235,11 @@ Private.event_prototypes = { display = L["Unit Name/Realm"], type = "string", multiline = true, - preamble = "local nameRealmChecker = WeakAuras.ParseNameCheck(%q)", + preamble = "local nameRealmChecker = Private.ExecEnv.ParseNameCheck(%q)", test = "nameRealmChecker:Check(name, realm)", conditionType = "string", conditionPreamble = function(input) - return WeakAuras.ParseNameCheck(input) + return Private.ExecEnv.ParseNameCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.name, state.realm) @@ -2255,10 +2255,10 @@ Private.event_prototypes = { store = true, init = "tostring(tonumber(string.sub(UnitGUID(unit) or '', 8, 12), 16) or '')", conditionType = "string", - preamble = "local npcIdChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local npcIdChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "npcIdChecker:Check(npcId)", conditionPreamble = function(input) - return WeakAuras.ParseStringCheck(input) + return Private.ExecEnv.ParseStringCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.npcId) @@ -2424,7 +2424,7 @@ Private.event_prototypes = { init = "arg", store = true, conditionType = "string", - preamble = "local sourceNameChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local sourceNameChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "sourceNameChecker:Check(sourceName)", desc = L["Supports multiple entries, separated by commas"], }, @@ -2436,10 +2436,10 @@ Private.event_prototypes = { init = "tostring(tonumber(string.sub(sourceGUID or '', 8, 12), 16) or '')", store = true, conditionType = "string", - preamble = "local sourceNpcIdChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local sourceNpcIdChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "sourceNpcIdChecker:Check(sourceNpcId)", conditionPreamble = function(input) - return WeakAuras.ParseStringCheck(input) + return Private.ExecEnv.ParseStringCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.sourceNpcId) @@ -2457,10 +2457,10 @@ Private.event_prototypes = { values = "combatlog_flags_check_type", init = "arg", store = true, - test = "WeakAuras.CheckCombatLogFlags(sourceFlags, %q)", + test = "Private.ExecEnv.CheckCombatLogFlags(sourceFlags, %q)", conditionType = "select", conditionTest = function(state, needle) - return state and state.show and WeakAuras.CheckCombatLogFlags(state.sourceFlags, needle); + return state and state.show and Private.ExecEnv.CheckCombatLogFlags(state.sourceFlags, needle); end }, { @@ -2468,10 +2468,10 @@ Private.event_prototypes = { display = L["Source Reaction"], type = "select", values = "combatlog_flags_check_reaction", - test = "WeakAuras.CheckCombatLogFlagsReaction(sourceFlags, %q)", + test = "Private.ExecEnv.CheckCombatLogFlagsReaction(sourceFlags, %q)", conditionType = "select", conditionTest = function(state, needle) - return state and state.show and WeakAuras.CheckCombatLogFlagsReaction(state.sourceFlags, needle); + return state and state.show and Private.ExecEnv.CheckCombatLogFlagsReaction(state.sourceFlags, needle); end }, { @@ -2479,10 +2479,10 @@ Private.event_prototypes = { display = L["Source Object Type"], type = "select", values = "combatlog_flags_check_object_type", - test = "WeakAuras.CheckCombatLogFlagsObjectType(sourceFlags, %q)", + test = "Private.ExecEnv.CheckCombatLogFlagsObjectType(sourceFlags, %q)", conditionType = "select", conditionTest = function(state, needle) - return state and state.show and WeakAuras.CheckCombatLogFlagsObjectType(state.sourceFlags, needle); + return state and state.show and Private.ExecEnv.CheckCombatLogFlagsObjectType(state.sourceFlags, needle); end }, { @@ -2492,10 +2492,10 @@ Private.event_prototypes = { values = "combatlog_raid_mark_check_type", init = "arg", store = true, - test = "WeakAuras.CheckRaidFlags(sourceRaidFlags, %q)", + test = "Private.ExecEnv.CheckRaidFlags(sourceRaidFlags, %q)", conditionType = "select", conditionTest = function(state, needle) - return state and state.show and WeakAuras.CheckRaidFlags(state.sourceRaidFlags, needle); + return state and state.show and Private.ExecEnv.CheckRaidFlags(state.sourceRaidFlags, needle); end }, { @@ -2553,7 +2553,7 @@ Private.event_prototypes = { init = "arg", store = true, conditionType = "string", - preamble = "local destNameChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local destNameChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "destNameChecker:Check(destName)", desc = L["Supports multiple entries, separated by commas"], enable = function(trigger) @@ -2568,10 +2568,10 @@ Private.event_prototypes = { init = "tostring(tonumber(string.sub(destGUID or '', 8, 12), 16) or '')", store = true, conditionType = "string", - preamble = "local destNpcIdChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local destNpcIdChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "destNpcIdChecker:Check(destNpcId)", conditionPreamble = function(input) - return WeakAuras.ParseStringCheck(input) + return Private.ExecEnv.ParseStringCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.destNpcId) @@ -2594,10 +2594,10 @@ Private.event_prototypes = { values = "combatlog_flags_check_type", init = "arg", store = true, - test = "WeakAuras.CheckCombatLogFlags(destFlags, %q)", + test = "Private.ExecEnv.CheckCombatLogFlags(destFlags, %q)", conditionType = "select", conditionTest = function(state, needle) - return state and state.show and WeakAuras.CheckCombatLogFlags(state.destFlags, needle); + return state and state.show and Private.ExecEnv.CheckCombatLogFlags(state.destFlags, needle); end, enable = function(trigger) return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -2608,10 +2608,10 @@ Private.event_prototypes = { display = L["Destination Reaction"], type = "select", values = "combatlog_flags_check_reaction", - test = "WeakAuras.CheckCombatLogFlagsReaction(destFlags, %q)", + test = "Private.ExecEnv.CheckCombatLogFlagsReaction(destFlags, %q)", conditionType = "select", conditionTest = function(state, needle) - return state and state.show and WeakAuras.CheckCombatLogFlagsReaction(state.destFlags, needle); + return state and state.show and Private.ExecEnv.CheckCombatLogFlagsReaction(state.destFlags, needle); end, enable = function(trigger) return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -2622,10 +2622,10 @@ Private.event_prototypes = { display = L["Destination Object Type"], type = "select", values = "combatlog_flags_check_object_type", - test = "WeakAuras.CheckCombatLogFlagsObjectType(destFlags, %q)", + test = "Private.ExecEnv.CheckCombatLogFlagsObjectType(destFlags, %q)", conditionType = "select", conditionTest = function(state, needle) - return state and state.show and WeakAuras.CheckCombatLogFlagsObjectType(state.destFlags, needle); + return state and state.show and Private.ExecEnv.CheckCombatLogFlagsObjectType(state.destFlags, needle); end, enable = function(trigger) return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -2643,10 +2643,10 @@ Private.event_prototypes = { values = "combatlog_raid_mark_check_type", init = "arg", store = true, - test = "WeakAuras.CheckRaidFlags(destRaidFlags, %q)", + test = "Private.ExecEnv.CheckRaidFlags(destRaidFlags, %q)", conditionType = "select", conditionTest = function(state, needle) - return state and state.show and WeakAuras.CheckRaidFlags(state.destRaidFlags, needle); + return state and state.show and Private.ExecEnv.CheckRaidFlags(state.destRaidFlags, needle); end, enable = function(trigger) return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -3087,7 +3087,7 @@ Private.event_prototypes = { remaining = expirationTime - GetTime(); local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then - WeakAuras.ScheduleScan(expirationTime - remainingCheck); + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); end end ]]; @@ -3390,12 +3390,12 @@ Private.event_prototypes = { type = "select", values = "charges_change_type", init = "arg", - test = "WeakAuras.CheckChargesDirection(direction, %q)", + test = "Private.ExecEnv.CheckChargesDirection(direction, %q)", store = true, conditionType = "select", conditionValues = "charges_change_condition_type"; conditionTest = function(state, needle) - return state and state.show and state.direction and WeakAuras.CheckChargesDirection(state.direction, needle) + return state and state.show and state.direction and Private.ExecEnv.CheckChargesDirection(state.direction, needle) end, }, { @@ -3471,7 +3471,7 @@ Private.event_prototypes = { local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0; local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then - WeakAuras.ScheduleScan(expirationTime - remainingCheck); + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); end ]]; ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0); @@ -3639,7 +3639,7 @@ Private.event_prototypes = { local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0; local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then - WeakAuras.ScheduleScan(expirationTime - remainingCheck); + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); end ]]; ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0); @@ -3946,7 +3946,7 @@ Private.event_prototypes = { if triggerUseRemaining then local remainingTime = bar.expirationTime - GetTime() + extendTimer if remainingTime %s triggerRemaining then - WeakAuras.CopyBarToState(bar, states, cloneId, extendTimer) + Private.ExecEnv.CopyBarToState(bar, states, cloneId, extendTimer) else local state = states[cloneId] if state and state.show then @@ -3955,16 +3955,16 @@ Private.event_prototypes = { end end if remainingTime >= triggerRemaining then - WeakAuras.ScheduleDbmCheck(bar.expirationTime - triggerRemaining + extendTimer) + Private.ExecEnv.ScheduleDbmCheck(bar.expirationTime - triggerRemaining + extendTimer) end else - WeakAuras.CopyBarToState(bar, states, cloneId, extendTimer) + Private.ExecEnv.CopyBarToState(bar, states, cloneId, extendTimer) end end if useClone then if event == "DBM_TimerStart" then - if WeakAuras.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then + if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then local bar = WeakAuras.GetDBMTimerById(id) if bar then copyOrSchedule(bar, cloneId) @@ -3978,7 +3978,7 @@ Private.event_prototypes = { end elseif event == "DBM_TimerUpdate" then for id, bar in pairs(WeakAuras.GetAllDBMTimers()) do - if WeakAuras.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then + if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then copyOrSchedule(bar, id) else local state = states[id] @@ -3994,7 +3994,7 @@ Private.event_prototypes = { elseif event == "DBM_TimerForce" then wipe(states) for id, bar in pairs(WeakAuras.GetAllDBMTimers()) do - if WeakAuras.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then + if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then copyOrSchedule(bar, cloneId) end end @@ -4002,9 +4002,9 @@ Private.event_prototypes = { else if event == "DBM_TimerStart" or event == "DBM_TimerUpdate" then if extendTimer ~= 0 then - if WeakAuras.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then + if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then local bar = WeakAuras.GetDBMTimerById(id) - WeakAuras.ScheduleDbmCheck(bar.expirationTime + extendTimer) + Private.ExecEnv.ScheduleDbmCheck(bar.expirationTime + extendTimer) end end end @@ -4188,7 +4188,7 @@ Private.event_prototypes = { if triggerUseRemaining then local remainingTime = bar.expirationTime - GetTime() + extendTimer if remainingTime %s triggerRemaining then - WeakAuras.CopyBigWigsTimerToState(bar, states, cloneId, extendTimer) + Private.ExecEnv.CopyBigWigsTimerToState(bar, states, cloneId, extendTimer) else local state = states[cloneId] if state and state.show then @@ -4197,16 +4197,16 @@ Private.event_prototypes = { end end if remainingTime >= triggerRemaining then - WeakAuras.ScheduleBigWigsCheck(bar.expirationTime - triggerRemaining + extendTimer) + Private.ExecEnv.ScheduleBigWigsCheck(bar.expirationTime - triggerRemaining + extendTimer) end else - WeakAuras.CopyBigWigsTimerToState(bar, states, cloneId, extendTimer) + Private.ExecEnv.CopyBigWigsTimerToState(bar, states, cloneId, extendTimer) end end if useClone then if event == "BigWigs_StartBar" then - if WeakAuras.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then local bar = WeakAuras.GetBigWigsTimerById(id) if bar then copyOrSchedule(bar, cloneId) @@ -4220,14 +4220,14 @@ Private.event_prototypes = { end elseif event == "BigWigs_Timer_Update" then for id, bar in pairs(WeakAuras.GetAllBigWigsTimers()) do - if WeakAuras.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then copyOrSchedule(bar, id) end end elseif event == "BigWigs_Timer_Force" then wipe(states) for id, bar in pairs(WeakAuras.GetAllBigWigsTimers()) do - if WeakAuras.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then copyOrSchedule(bar, id) end end @@ -4235,9 +4235,9 @@ Private.event_prototypes = { else if event == "BigWigs_StartBar" then if extendTimer ~= 0 then - if WeakAuras.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then local bar = WeakAuras.GetBigWigsTimerById(id) - WeakAuras.ScheduleBigWigsCheck(bar.expirationTime + extendTimer) + Private.ExecEnv.ScheduleBigWigsCheck(bar.expirationTime + extendTimer) end end end @@ -4410,7 +4410,7 @@ Private.event_prototypes = { local remainingCheck = not triggerRemaining or remaining and remaining %s triggerRemaining if triggerRemaining and remaining and remaining >= triggerRemaining and remaining > 0 then - WeakAuras.ScheduleScan(expirationTime - triggerRemaining, "SWING_TIMER_UPDATE") + Private.ExecEnv.ScheduleScan(expirationTime - triggerRemaining, "SWING_TIMER_UPDATE") end ]=]; return ret:format( @@ -4773,7 +4773,7 @@ Private.event_prototypes = { local _, totemName, startTime, duration, icon = GetTotemInfo(totemType); active = (startTime and startTime ~= 0); - if not WeakAuras.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemPatternOperator) then + if not Private.ExecEnv.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemPatternOperator) then active = false; end @@ -4786,7 +4786,7 @@ Private.event_prototypes = { local expirationTime = startTime and (startTime + duration) or 0; local remainingTime = expirationTime - GetTime() if (remainingTime >= remainingCheck) then - WeakAuras.ScheduleScan(expirationTime - remainingCheck); + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); end active = checkActive(remainingTime); end @@ -4807,7 +4807,7 @@ Private.event_prototypes = { for i = 1, 4 do local _, totemName, startTime, duration, icon = GetTotemInfo(i); if ((startTime and startTime ~= 0) and - WeakAuras.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemPatternOperator) + Private.ExecEnv.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemPatternOperator) ) then found = true; end @@ -4827,14 +4827,14 @@ Private.event_prototypes = { local _, totemName, startTime, duration, icon = GetTotemInfo(i); active = (startTime and startTime ~= 0); - if not WeakAuras.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemPatternOperator) then + if not Private.ExecEnv.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemPatternOperator) then active = false; end if (active and remainingCheck) then local expirationTime = startTime and (startTime + duration) or 0; local remainingTime = expirationTime - GetTime() if (remainingTime >= remainingCheck) then - WeakAuras.ScheduleScan(expirationTime - remainingCheck); + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); end active = checkActive(remainingTime); end @@ -5115,7 +5115,7 @@ Private.event_prototypes = { local found = expirationTime and nameCheck and stackCheck and remainingCheck if(triggerRemaining and remaining and remaining >= triggerRemaining and remaining > 0) then - WeakAuras.ScheduleScan(expirationTime - triggerRemaining, "TENCH_UPDATE"); + Private.ExecEnv.ScheduleScan(expirationTime - triggerRemaining, "TENCH_UPDATE"); end if not found then @@ -5406,7 +5406,7 @@ Private.event_prototypes = { local remaining = expirationTime - GetTime(); local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then - WeakAuras.ScheduleScan(expirationTime - remainingCheck); + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); end ]]; ret = ret..ret2:format(tonumber(trigger.remaining) or 0); @@ -5878,7 +5878,7 @@ Private.event_prototypes = { remaining = expirationTime - GetTime() if remainingCheck and remaining >= remainingCheck and remaining > 0 then - WeakAuras.ScheduleCastCheck(expirationTime - remainingCheck, unit) + Private.ExecEnv.ScheduleCastCheck(expirationTime - remainingCheck, unit) end ]=]; ret = ret:format(trigger.unit == "group" and "true" or "false", @@ -6038,10 +6038,10 @@ Private.event_prototypes = { store = true, init = "tostring(tonumber(string.sub(UnitGUID(unit) or '', 8, 12), 16) or '')", conditionType = "string", - preamble = "local npcIdChecker = WeakAuras.ParseStringCheck(%q)", + preamble = "local npcIdChecker = Private.ExecEnv.ParseStringCheck(%q)", test = "npcIdChecker:Check(npcId)", conditionPreamble = function(input) - return WeakAuras.ParseStringCheck(input) + return Private.ExecEnv.ParseStringCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.npcId) @@ -6140,11 +6140,11 @@ Private.event_prototypes = { display = L["Source Unit Name/Realm"], type = "string", multiline = true, - preamble = "local sourceNameRealmChecker = WeakAuras.ParseNameCheck(%q)", + preamble = "local sourceNameRealmChecker = Private.ExecEnv.ParseNameCheck(%q)", test = "sourceNameRealmChecker:Check(sourceName, sourceRealm)", conditionType = "string", conditionPreamble = function(input) - return WeakAuras.ParseNameCheck(input) + return Private.ExecEnv.ParseNameCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.sourceName, state.sourceRealm) @@ -6189,11 +6189,11 @@ Private.event_prototypes = { display = L["Name/Realm of Caster's Target"], type = "string", multiline = true, - preamble = "local destNameRealmChecker = WeakAuras.ParseNameCheck(%q)", + preamble = "local destNameRealmChecker = Private.ExecEnv.ParseNameCheck(%q)", test = "destNameRealmChecker:Check(destName, destRealm)", conditionType = "string", conditionPreamble = function(input) - return WeakAuras.ParseNameCheck(input) + return Private.ExecEnv.ParseNameCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.destName, state.destRealm) @@ -6829,7 +6829,7 @@ Private.event_prototypes = { display = L["Group Type"], type = "multiselect", values = "group_types", - init = "WeakAuras.GroupType()", + init = "Private.ExecEnv.GroupType()", events = {"PARTY_MEMBERS_CHANGED", "RAID_ROSTER_UPDATE"} }, { @@ -7131,11 +7131,11 @@ Private.event_prototypes = { end, type = "string", multiline = true, - preamble = "local zoneChecker = WeakAuras.ParseZoneCheck(%q)", + preamble = "local zoneChecker = Private.ExecEnv.ParseZoneCheck(%q)", test = "zoneChecker:Check(MapId)", conditionType = "string", conditionPreamble = function(input) - return WeakAuras.ParseZoneCheck(input) + return Private.ExecEnv.ParseZoneCheck(input) end, conditionTest = function(state, needle, op, preamble) return preamble:Check(state.zoneId) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index bb2ed19..ca49dd8 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -928,8 +928,8 @@ local function modify(parent, region, data) self.updatedChildren[regionData] = true end end - if childData and WeakAuras.clones[childID] then - for cloneID, cloneRegion in pairs(WeakAuras.clones[childID]) do + if childData and Private.clones[childID] then + for cloneID, cloneRegion in pairs(Private.clones[childID]) do local regionData = createRegionData(childData, cloneRegion, childID, cloneID, dataIndex) if cloneRegion.toShow then tinsert(self.sortedChildren, regionData) @@ -1266,7 +1266,7 @@ local function modify(parent, region, data) self:Hide() end if WeakAuras.IsOptionsOpen() then - WeakAuras.OptionsFrame().moversizer:ReAnchor() + Private.OptionsFrame().moversizer:ReAnchor() end Private.StopProfileSystem("dynamicgroup") Private.StopProfileAura(data.id) diff --git a/WeakAuras/RegionTypes/Group.lua b/WeakAuras/RegionTypes/Group.lua index 6006e4d..1ed3702 100644 --- a/WeakAuras/RegionTypes/Group.lua +++ b/WeakAuras/RegionTypes/Group.lua @@ -138,7 +138,7 @@ local function modify(parent, region, data) -- Scan children for visibility if not childVisible then for child in Private.TraverseLeafs(data) do - local childRegion = WeakAuras.regions[child.id] and WeakAuras.regions[child.id].region; + local childRegion = Private.regions[child.id] and Private.regions[child.id].region; if childRegion and childRegion.toShow then childVisible = true; break; diff --git a/WeakAuras/RegionTypes/Model.lua b/WeakAuras/RegionTypes/Model.lua index 7a5a4ea..508b224 100644 --- a/WeakAuras/RegionTypes/Model.lua +++ b/WeakAuras/RegionTypes/Model.lua @@ -280,7 +280,7 @@ end do function Private.PreShowModels(self, event) Private.StartProfileSystem("model"); - for id, data in pairs(WeakAuras.regions) do + for id, data in pairs(Private.regions) do Private.StartProfileAura(id); if data.region.toShow then if (data.regionType == "model") then diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index e340535..a106747 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -118,13 +118,13 @@ local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ce function Private.GetAnchorsForData(parentData, type) local result if not parentData.controlledChildren then - if not WeakAuras.regionOptions[parentData.regionType] then + if not Private.regionOptions[parentData.regionType] then return end local anchors - if WeakAuras.regionOptions[parentData.regionType].getAnchors then - anchors = WeakAuras.regionOptions[parentData.regionType].getAnchors(parentData) + if Private.regionOptions[parentData.regionType].getAnchors then + anchors = Private.regionOptions[parentData.regionType].getAnchors(parentData) else anchors = Private.default_types_for_anchor end @@ -452,7 +452,7 @@ end WeakAuras.regionPrototype.AnchorSubRegion = AnchorSubRegion function WeakAuras.regionPrototype.create(region) - local defaultsForRegion = WeakAuras.regionTypes[region.regionType] and WeakAuras.regionTypes[region.regionType].default; + local defaultsForRegion = Private.regionTypes[region.regionType] and Private.regionTypes[region.regionType].default; region.SoundPlay = SoundPlay; region.SoundRepeatStop = SoundRepeatStop; region.SendChat = SendChat; @@ -501,7 +501,7 @@ function WeakAuras.regionPrototype.modify(parent, region, data) region.states = nil region.subRegionEvents:ClearSubscribers() - local defaultsForRegion = WeakAuras.regionTypes[data.regionType] and WeakAuras.regionTypes[data.regionType].default; + local defaultsForRegion = Private.regionTypes[data.regionType] and Private.regionTypes[data.regionType].default; if region.SetRegionAlpha then region:SetRegionAlpha(data.alpha) @@ -626,7 +626,7 @@ local regionsForFrameTick = {} local frameForFrameTick = CreateFrame("Frame"); -WeakAuras.frames["Frame Tick Frame"] = frameForFrameTick +Private.frames["Frame Tick Frame"] = frameForFrameTick local function FrameTick() if WeakAuras.IsOptionsOpen() then diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index 43f6413..30768ee 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -142,8 +142,8 @@ local function modify(parent, region, data) region:SetHeight(height) if data.parent then Private.EnsureRegion(data.parent) - if WeakAuras.regions[data.parent].region.PositionChildren then - WeakAuras.regions[data.parent].region:PositionChildren() + if Private.regions[data.parent].region.PositionChildren then + Private.regions[data.parent].region:PositionChildren() end end end @@ -165,8 +165,8 @@ local function modify(parent, region, data) region.height = height; region:SetWidth(region.width); region:SetHeight(region.height); - if(data.parent and WeakAuras.regions[data.parent].region.PositionChildren) then - WeakAuras.regions[data.parent].region:PositionChildren(); + if(data.parent and Private.regions[data.parent].region.PositionChildren) then + Private.regions[data.parent].region:PositionChildren(); end end end diff --git a/WeakAuras/SubRegionTypes/Glow.lua b/WeakAuras/SubRegionTypes/Glow.lua index a5d8bc0..1b94ae9 100644 --- a/WeakAuras/SubRegionTypes/Glow.lua +++ b/WeakAuras/SubRegionTypes/Glow.lua @@ -346,7 +346,7 @@ local function modify(parent, region, parentData, data, first) end -- This is used by the templates to add glow -function WeakAuras.getDefaultGlow(regionType) +function Private.getDefaultGlow(regionType) if regionType == "aurabar" then return { ["type"] = "subglow", diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 6a26e9b..a29f4b1 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -2482,7 +2482,7 @@ Private.non_transmissable_fields_v2000 = { } } -WeakAuras.data_stub = { +Private.data_stub = { -- note: this is the minimal data stub which prevents false positives in diff upon reimporting an aura. -- pending a refactor of other code which adds unnecessary fields, it is possible to shrink it triggers = { diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 7a34bfe..3a1bdc5 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -112,7 +112,7 @@ function Private.LoadOptions(msg) -- inform the user and queue ooc prettyPrint(L["Options will finish loading after combat ends."]) queueshowooc = msg or ""; - WeakAuras.frames["Addon Initialization Handler"]:RegisterEvent("PLAYER_REGEN_ENABLED") + Private.frames["Addon Initialization Handler"]:RegisterEvent("PLAYER_REGEN_ENABLED") return false; else local loaded, reason = LoadAddOn("WeakAurasOptions"); @@ -216,29 +216,30 @@ local loadFuncsForOptions = {}; local loadEvents = {} -- All regions keyed on id, has properties: region, regionType, also see clones -WeakAuras.regions = {}; +Private.regions = {}; +local regions = Private.regions; -- keyed on id, contains bool indicating whether the aura is loaded Private.loaded = {}; local loaded = Private.loaded; -- contains regions for clones -WeakAuras.clones = {}; -local clones = WeakAuras.clones; +Private.clones = {}; +local clones = Private.clones; -- Unused regions that are kept around for clones local clonePool = {} -- One table per regionType, see RegisterRegionType, notable properties: create, modify and default -WeakAuras.regionTypes = {}; -local regionTypes = WeakAuras.regionTypes; +Private.regionTypes = {}; +local regionTypes = Private.regionTypes; Private.subRegionTypes = {} local subRegionTypes = Private.subRegionTypes -- One table per regionType, see RegisterRegionOptions -WeakAuras.regionOptions = {}; -local regionOptions = WeakAuras.regionOptions; +Private.regionOptions = {}; +local regionOptions = Private.regionOptions; Private.subRegionOptions = {} local subRegionOptions = Private.subRegionOptions @@ -282,7 +283,6 @@ local fallbacksStates = {}; local triggerSystems = {} local timers = {}; -- Timers for autohiding, keyed on id, triggernum, cloneid -WeakAuras.timers = timers; WeakAuras.raidUnits = {}; WeakAuras.raidpetUnits = {}; @@ -319,13 +319,13 @@ local playerLevel = UnitLevel("player"); Private.customActionsFunctions = {}; -- Custom Functions used in conditions, keyed on id, condition number, "changes", property number -WeakAuras.customConditionsFunctions = {}; +Private.ExecEnv.customConditionsFunctions = {}; -- Text format functions for chat messages, keyed on id, condition number, changes, property number -WeakAuras.conditionTextFormatters = {} +Private.ExecEnv.conditionTextFormatters = {} -- Helpers for conditions, that is custom run functions and preamble objects for built in checks -- keyed on UID not on id! -WeakAuras.conditionHelpers = {} +Private.ExecEnv.conditionHelpers = {} local load_prototype = Private.load_prototype; @@ -336,7 +336,7 @@ local levelColors = { [3] = "|cFFFF4040" }; -function WeakAuras.validate(input, default) +function Private.validate(input, default) for field, defaultValue in pairs(default) do if(type(defaultValue) == "table" and type(input[field]) ~= "table") then input[field] = {}; @@ -344,7 +344,7 @@ function WeakAuras.validate(input, default) input[field] = defaultValue; end if(type(input[field]) == "table") then - WeakAuras.validate(input[field], defaultValue); + Private.validate(input[field], defaultValue); end end end @@ -948,7 +948,7 @@ local function tooltip_draw() end local colorFrame = CreateFrame("Frame"); -WeakAuras.frames["LDB Icon Recoloring"] = colorFrame; +Private.frames["LDB Icon Recoloring"] = colorFrame; local colorElapsed = 0; local colorDelay = 2; @@ -956,7 +956,7 @@ local r, g, b = 0.8, 0, 1; local r2, g2, b2 = random(2)-1, random(2)-1, random(2)-1; local tooltip_update_frame = CreateFrame("Frame"); -WeakAuras.frames["LDB Tooltip Updater"] = tooltip_update_frame; +Private.frames["LDB Tooltip Updater"] = tooltip_update_frame; -- function copied from LibDBIcon-1.0.lua local function getAnchors(frame) @@ -1087,7 +1087,7 @@ function Private.Login(initialTime, takeNewSnapshots) end coroutine.yield(); - WeakAuras.AddMany(toAdd, takeNewSnapshots); + Private.AddMany(toAdd, takeNewSnapshots); coroutine.yield(); Private.RegisterLoadEvents(); @@ -1108,7 +1108,7 @@ function Private.Login(initialTime, takeNewSnapshots) loginFinished = true -- Tell Dynamic Groups that we are done with login - for _, region in pairs(WeakAuras.regions) do + for _, region in pairs(Private.regions) do if (region.region.RunDelayedActions) then region.region:RunDelayedActions(); end @@ -1138,12 +1138,12 @@ function Private.Login(initialTime, takeNewSnapshots) end local WeakAurasFrame = CreateFrame("Frame", "WeakAurasFrame", UIParent); -WeakAuras.frames["WeakAuras Main Frame"] = WeakAurasFrame; +Private.frames["WeakAuras Main Frame"] = WeakAurasFrame; WeakAurasFrame:SetAllPoints(UIParent); WeakAurasFrame:SetFrameStrata("BACKGROUND"); local loadedFrame = CreateFrame("Frame"); -WeakAuras.frames["Addon Initialization Handler"] = loadedFrame; +Private.frames["Addon Initialization Handler"] = loadedFrame; loadedFrame:RegisterEvent("ADDON_LOADED"); loadedFrame:RegisterEvent("PLAYER_LOGIN"); loadedFrame:RegisterEvent("PLAYER_LOGOUT"); @@ -1223,7 +1223,7 @@ loadedFrame:SetScript("OnEvent", function(self, event, addon) if (queueshowooc) then WeakAuras.OpenOptions(queueshowooc) queueshowooc = nil - WeakAuras.frames["Addon Initialization Handler"]:UnregisterEvent("PLAYER_REGEN_ENABLED") + Private.frames["Addon Initialization Handler"]:UnregisterEvent("PLAYER_REGEN_ENABLED") end end end @@ -1275,7 +1275,7 @@ end function Private.PauseAllDynamicGroups() local suspended = {} - for id, region in pairs(WeakAuras.regions) do + for id, region in pairs(Private.regions) do if (region.region.Suspend) then region.region:Suspend(); tinsert(suspended, id) @@ -1302,7 +1302,7 @@ function Private.IsOptionsProcessingPaused() return pausedOptionsProcessing; end -function WeakAuras.GroupType() +function Private.ExecEnv.GroupType() if (IsInRaid()) then return "raid"; end @@ -1398,7 +1398,7 @@ local function scanForLoadsImpl(toCheck, event, arg1, ...) end local size, difficulty, instanceType = GetInstanceTypeAndSize() - local group = WeakAuras.GroupType() + local group = Private.ExecEnv.GroupType() local changed = 0; local shouldBeLoaded, couldBeLoaded; @@ -1487,8 +1487,7 @@ function Private.ScanForLoads(toCheck, event, arg1, ...) end local loadFrame = CreateFrame("Frame"); -WeakAuras.loadFrame = loadFrame; -WeakAuras.frames["Display Load Handling"] = loadFrame; +Private.frames["Display Load Handling"] = loadFrame; loadFrame:RegisterEvent("PLAYER_TALENT_UPDATE"); loadFrame:RegisterEvent("SPELL_UPDATE_USABLE"); @@ -1514,8 +1513,7 @@ loadFrame:RegisterEvent("PLAYER_FLAGS_CHANGED") loadFrame:RegisterEvent("PARTY_LEADER_CHANGED") local unitLoadFrame = CreateFrame("Frame"); -WeakAuras.unitLoadFrame = unitLoadFrame; -WeakAuras.frames["Display Load Handling 2"] = unitLoadFrame; +Private.frames["Display Load Handling 2"] = unitLoadFrame; unitLoadFrame:RegisterEvent("UNIT_FLAGS"); unitLoadFrame:RegisterEvent("UNIT_ENTERED_VEHICLE"); @@ -1541,8 +1539,8 @@ end local function UnloadAll() -- Even though auras are collapsed, their finish animation can be running for id in pairs(loaded) do - if WeakAuras.regions[id] and WeakAuras.regions[id].region then - Private.CancelAnimation(WeakAuras.regions[id].region, true, true, true, true, true, true) + if Private.regions[id] and Private.regions[id].region then + Private.CancelAnimation(Private.regions[id].region, true, true, true, true, true, true) end if clones[id] then for _, region in pairs(clones[id]) do @@ -1583,7 +1581,7 @@ function Private.Resume() local suspended = Private.PauseAllDynamicGroups() - for id, region in pairs(WeakAuras.regions) do + for id, region in pairs(Private.regions) do region.region:Collapse(); end @@ -1651,11 +1649,11 @@ function Private.UnloadDisplays(toUnload, ...) local uid = WeakAuras.GetData(id).uid Private.UnloadConditions(uid) - WeakAuras.regions[id].region:Collapse(); + Private.regions[id].region:Collapse(); Private.CollapseAllClones(id); -- Even though auras are collapsed, their finish animation can be running - Private.CancelAnimation(WeakAuras.regions[id].region, true, true, true, true, true, true) + Private.CancelAnimation(Private.regions[id].region, true, true, true, true, true, true) if clones[id] then for cloneId, region in pairs(clones[id]) do Private.CancelAnimation(region, true, true, true, true, true, true) @@ -1720,11 +1718,11 @@ function WeakAuras.Delete(data) end end - if WeakAuras.regions[id] then - WeakAuras.regions[id].region:Collapse() - Private.CancelAnimation(WeakAuras.regions[id].region, true, true, true, true, true, true) - WeakAuras.regions[id].region = nil - WeakAuras.regions[id] = nil + if Private.regions[id] then + Private.regions[id].region:Collapse() + Private.CancelAnimation(Private.regions[id].region, true, true, true, true, true, true) + Private.regions[id].region = nil + Private.regions[id] = nil end if clones[id] then @@ -1762,10 +1760,10 @@ function WeakAuras.Delete(data) end Private.customActionsFunctions[id] = nil; - WeakAuras.customConditionsFunctions[id] = nil; - WeakAuras.conditionTextFormatters[id] = nil + Private.ExecEnv.customConditionsFunctions[id] = nil; + Private.ExecEnv.conditionTextFormatters[id] = nil Private.frameLevels[id] = nil; - WeakAuras.conditionHelpers[data.uid] = nil + Private.ExecEnv.conditionHelpers[data.uid] = nil Private.RemoveHistory(data.uid) @@ -1795,10 +1793,10 @@ function WeakAuras.Rename(data, newid) end UIDtoID[data.uid] = newid - WeakAuras.regions[newid] = WeakAuras.regions[oldid]; - WeakAuras.regions[oldid] = nil; - if WeakAuras.regions[newid] then - WeakAuras.regions[newid].region.id = newid + Private.regions[newid] = Private.regions[oldid]; + Private.regions[oldid] = nil; + if Private.regions[newid] then + Private.regions[newid].region.id = newid end if(clones[oldid]) then clones[newid] = clones[oldid] @@ -1858,11 +1856,11 @@ function WeakAuras.Rename(data, newid) Private.customActionsFunctions[newid] = Private.customActionsFunctions[oldid]; Private.customActionsFunctions[oldid] = nil; - WeakAuras.customConditionsFunctions[newid] = WeakAuras.customConditionsFunctions[oldid]; - WeakAuras.customConditionsFunctions[oldid] = nil; + Private.ExecEnv.customConditionsFunctions[newid] = Private.ExecEnv.customConditionsFunctions[oldid]; + Private.ExecEnv.customConditionsFunctions[oldid] = nil; - WeakAuras.conditionTextFormatters[newid] = WeakAuras.conditionTextFormatters[oldid] - WeakAuras.conditionTextFormatters[oldid] = nil + Private.ExecEnv.conditionTextFormatters[newid] = Private.ExecEnv.conditionTextFormatters[oldid] + Private.ExecEnv.conditionTextFormatters[oldid] = nil Private.frameLevels[newid] = Private.frameLevels[oldid]; Private.frameLevels[oldid] = nil; @@ -1880,9 +1878,9 @@ function Private.Convert(data, newType) Private.FakeStatesFor(id, false) - if WeakAuras.regions[id] then - WeakAuras.regions[id].region = nil - WeakAuras.regions[id] = nil + if Private.regions[id] then + Private.regions[id].region = nil + Private.regions[id] = nil end data.regionType = newType; @@ -2150,7 +2148,7 @@ local function loadOrder(tbl, idtable) end coroutine.yield() end - error("Circular dependency in WeakAuras.AddMany between "..table.concat(depends, ", ")); + error("Circular dependency in Private.AddMany between "..table.concat(depends, ", ")); else if not(loaded[data.parent]) then local dependsOut = CopyTable(depends) @@ -2178,7 +2176,7 @@ local function loadOrder(tbl, idtable) return order end -function WeakAuras.AddMany(tbl, takeSnapshots) +function Private.AddMany(tbl, takeSnapshots) local idtable = {}; for _, data in ipairs(tbl) do -- There was an unfortunate bug in update.lua in 2022 that resulted @@ -2203,8 +2201,8 @@ function WeakAuras.AddMany(tbl, takeSnapshots) end for data in pairs(groups) do if data.type == "dynamicgroup" then - if WeakAuras.regions[data.id] then - WeakAuras.regions[data.id].region:ReloadControlledChildren() + if Private.regions[data.id] then + Private.regions[data.id].region:ReloadControlledChildren() end else WeakAuras.Add(data) @@ -2554,23 +2552,23 @@ end function WeakAuras.PreAdd(data) -- Readd what Compress removed before version 8 if (not data.internalVersion or data.internalVersion < 7) then - WeakAuras.validate(data, oldDataStub) + Private.validate(data, oldDataStub) elseif (data.internalVersion < 8) then - WeakAuras.validate(data, oldDataStub2) + Private.validate(data, oldDataStub2) end - local default = data.regionType and WeakAuras.regionTypes[data.regionType] and WeakAuras.regionTypes[data.regionType].default + local default = data.regionType and Private.regionTypes[data.regionType] and Private.regionTypes[data.regionType].default if default then - WeakAuras.validate(data, default) + Private.validate(data, default) end - local regionValidate = data.regionType and WeakAuras.regionTypes[data.regionType] and WeakAuras.regionTypes[data.regionType].validate + local regionValidate = data.regionType and Private.regionTypes[data.regionType] and Private.regionTypes[data.regionType].validate if regionValidate then regionValidate(data) end Private.Modernize(data); - WeakAuras.validate(data, WeakAuras.data_stub); + Private.validate(data, Private.data_stub); if data.subRegions then for _, subRegionData in ipairs(data.subRegions) do local subType = subRegionData.type @@ -2581,7 +2579,7 @@ function WeakAuras.PreAdd(data) default = default(data.regionType) end if default then - WeakAuras.validate(subRegionData, default) + Private.validate(subRegionData, default) end else WeakAuras.prettyPrint(L["ERROR in '%s' unknown or incompatible sub element type '%s'"]:format(data.id, subType)) @@ -2626,11 +2624,11 @@ local function pAdd(data, simpleChange) if simpleChange then db.displays[id] = data if WeakAuras.GetRegion(data.id) then - WeakAuras.SetRegion(data) + Private.SetRegion(data) end if clones[id] then for cloneId, region in pairs(clones[id]) do - WeakAuras.SetRegion(data, cloneId) + Private.SetRegion(data, cloneId) end end Private.UpdatedTriggerState(id) @@ -2644,7 +2642,7 @@ local function pAdd(data, simpleChange) end db.displays[id] = data; if WeakAuras.GetRegion(data.id) then - WeakAuras.SetRegion(data) + Private.SetRegion(data) end Private.ScanForLoadsGroup({[id] = true}); loadEvents["GROUP"] = loadEvents["GROUP"] or {} @@ -2654,8 +2652,8 @@ local function pAdd(data, simpleChange) if (WeakAuras.IsOptionsOpen()) then visible = Private.FakeStatesFor(id, false) else - if (WeakAuras.regions[id] and WeakAuras.regions[id].region) then - WeakAuras.regions[id].region:Collapse() + if (Private.regions[id] and Private.regions[id].region) then + Private.regions[id].region:Collapse() else Private.CollapseAllClones(id) end @@ -2688,8 +2686,8 @@ local function pAdd(data, simpleChange) loadEvents["SCAN_ALL"][id] = true local loadForOptionsFuncStr = ConstructFunction(load_prototype, data.load, true); - local loadFunc = WeakAuras.LoadFunction(loadFuncStr); - local loadForOptionsFunc = WeakAuras.LoadFunction(loadForOptionsFuncStr); + local loadFunc = Private.LoadFunction(loadFuncStr); + local loadForOptionsFunc = Private.LoadFunction(loadForOptionsFuncStr); local triggerLogicFunc; if data.triggers.disjunctive == "custom" then triggerLogicFunc = WeakAuras.LoadFunction("return "..(data.triggers.customTriggerLogic or "")); @@ -2715,7 +2713,7 @@ local function pAdd(data, simpleChange) end if WeakAuras.GetRegion(data.id) then - WeakAuras.SetRegion(data) + Private.SetRegion(data) end triggerState[id] = { @@ -2766,10 +2764,10 @@ function Private.AddParents(data) end end -function WeakAuras.SetRegion(data, cloneId) +function Private.SetRegion(data, cloneId) local regionType = data.regionType; if not(regionType) then - error("Improper arguments to WeakAuras.SetRegion - regionType not defined"); + error("Improper arguments to Private.SetRegion - regionType not defined"); else if(not regionTypes[regionType]) then regionType = "fallback"; @@ -2778,7 +2776,7 @@ function WeakAuras.SetRegion(data, cloneId) local id = data.id; if not(id) then - error("Improper arguments to WeakAuras.SetRegion - id not defined"); + error("Improper arguments to Private.SetRegion - id not defined"); else local region; if(cloneId) then @@ -2800,9 +2798,9 @@ function WeakAuras.SetRegion(data, cloneId) region = clones[id][cloneId]; end else - if((not WeakAuras.regions[id]) or (not WeakAuras.regions[id].region) or WeakAuras.regions[id].regionType ~= regionType) then + if((not regions[id]) or (not regions[id].region) or regions[id].regionType ~= regionType) then region = regionTypes[regionType].create(WeakAurasFrame, data); - WeakAuras.regions[id] = { + regions[id] = { regionType = regionType, region = region }; @@ -2813,12 +2811,12 @@ function WeakAuras.SetRegion(data, cloneId) region.toShow = true end else - region = WeakAuras.regions[id].region + region = regions[id].region end end region.id = id; region.cloneId = cloneId or ""; - WeakAuras.validate(data, regionTypes[regionType].default); + Private.validate(data, regionTypes[regionType].default); local parent = WeakAurasFrame; if(data.parent) then @@ -2864,7 +2862,7 @@ local function EnsureClone(id, cloneId) clones[id] = clones[id] or {} if not(clones[id][cloneId]) then local data = WeakAuras.GetData(id) - WeakAuras.SetRegion(data, cloneId) + Private.SetRegion(data, cloneId) end return clones[id][cloneId] end @@ -2875,8 +2873,8 @@ function Private.CreatingRegions() end --- Ensures that a region exists local function EnsureRegion(id) - if not WeakAuras.regions[id] or not WeakAuras.regions[id].region then - WeakAuras.regions[id] = WeakAuras.regions[id] or {} + if not Private.regions[id] or not Private.regions[id].region then + Private.regions[id] = Private.regions[id] or {} -- The region doesn't yet exist -- But we must also ensure that our parents exists -- and as an additional wrinkle, for dynamic groups, all children must exist! @@ -2902,20 +2900,20 @@ local function EnsureRegion(id) end for _, toCreateId in ipairs_reverse(aurasToCreate) do local data = WeakAuras.GetData(toCreateId) - WeakAuras.SetRegion(data) + Private.SetRegion(data) if (data.regionType == "dynamicgroup") then for child in Private.TraverseAllChildren(data) do - WeakAuras.SetRegion(child) + Private.SetRegion(child) end end end creatingRegions = false for _, dynamicGroupId in ipairs_reverse(dynamicGroups) do - local dgRegion = WeakAuras.regions[dynamicGroupId].region + local dgRegion = Private.regions[dynamicGroupId].region dgRegion:ReloadControlledChildren() end end - return WeakAuras.regions[id] and WeakAuras.regions[id].region + return Private.regions[id] and Private.regions[id].region end --- Ensures that a region/clone exists and returns it -- Even if we are asked to only create a clone, we create the default region too. @@ -2932,7 +2930,7 @@ function WeakAuras.GetRegion(id, cloneId) if(cloneId and cloneId ~= "") then return clones[id] and clones[id][cloneId] end - return WeakAuras.regions[id] and WeakAuras.regions[id].region + return Private.regions[id] and Private.regions[id].region end -- Note, does not create a clone! @@ -2941,7 +2939,7 @@ function Private.GetRegionByUID(uid, cloneId) if(cloneId and cloneId ~= "") then return id and clones[id] and clones[id][cloneId]; end - return id and WeakAuras.regions[id] and WeakAuras.regions[id].region + return id and Private.regions[id] and Private.regions[id].region end function Private.CollapseAllClones(id, triggernum) @@ -3168,8 +3166,8 @@ function Private.HandleGlowAction(actions, region) if WeakAuras.GetData(frame_name) then Private.EnsureRegion(frame_name) end - if WeakAuras.regions[frame_name] then - glow_frame = WeakAuras.regions[frame_name].region + if Private.regions[frame_name] then + glow_frame = Private.regions[frame_name].region should_glow_frame = true end else @@ -3355,6 +3353,7 @@ Private.CanHaveDuration = wrapTriggerSystemFunction("CanHaveDuration", "firstVal Private.CanHaveClones = wrapTriggerSystemFunction("CanHaveClones", "or"); Private.CanHaveTooltip = wrapTriggerSystemFunction("CanHaveTooltip", "or"); -- This has to be in WeakAuras for now, because GetNameAndIcon can be called from the options +-- before the Options has access to Private WeakAuras.GetNameAndIcon = wrapTriggerSystemFunction("GetNameAndIcon", "nameAndIcon"); Private.GetTriggerDescription = wrapTriggerSystemFunction("GetTriggerDescription", "call"); @@ -3543,7 +3542,7 @@ end local FrameTimes = {}; function WeakAuras.ProfileFrames(all) UpdateAddOnCPUUsage(); - for name, frame in pairs(WeakAuras.frames) do + for name, frame in pairs(Private.frames) do local FrameTime = GetFrameCPUUsage(frame); FrameTimes[name] = FrameTimes[name] or 0; if(all or FrameTime > FrameTimes[name]) then @@ -3556,7 +3555,7 @@ end local DisplayTimes = {}; function WeakAuras.ProfileDisplays(all) UpdateAddOnCPUUsage(); - for id, regionData in pairs(WeakAuras.regions) do + for id, regionData in pairs(Private.regions) do local DisplayTime = GetFrameCPUUsage(regionData.region, true); DisplayTimes[id] = DisplayTimes[id] or 0; if(all or DisplayTime > DisplayTimes[id]) then @@ -3603,8 +3602,8 @@ local function SetFrameLevel(id, frameLevel) if (Private.frameLevels[id] == frameLevel) then return; end - if (WeakAuras.regions[id] and WeakAuras.regions[id].region) then - Private.ApplyFrameLevel(WeakAuras.regions[id].region, frameLevel) + if (Private.regions[id] and Private.regions[id].region) then + Private.ApplyFrameLevel(Private.regions[id].region, frameLevel) end if (clones[id]) then for i,v in pairs(clones[id]) do @@ -4093,8 +4092,8 @@ function Private.UpdatedTriggerState(id) for _, clone in pairs(clones[id]) do clone:Collapse() end - if WeakAuras.regions[id] then - WeakAuras.regions[id].region:Collapse() + if Private.regions[id] then + Private.regions[id].region:Collapse() end elseif (show and oldShow) then -- Already shown, update regions -- Hide old clones @@ -4104,8 +4103,8 @@ function Private.UpdatedTriggerState(id) end end if (not activeTriggerState[""] or not activeTriggerState[""].show) then - if WeakAuras.regions[id] then - WeakAuras.regions[id].region:Collapse() + if Private.regions[id] then + Private.regions[id].region:Collapse() end end -- Show new states @@ -4541,7 +4540,7 @@ end local function xPositionNextToOptions() local xOffset; - local optionsFrame = WeakAuras.OptionsFrame(); + local optionsFrame = Private.OptionsFrame(); local centerX = (optionsFrame:GetLeft() + optionsFrame:GetRight()) / 2; if (centerX > GetScreenWidth() / 2) then if (optionsFrame:GetLeft() > 400) then @@ -4615,7 +4614,7 @@ local function ensureMouseFrame() mouseFrame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", db.mousePointerFrame.xOffset, db.mousePointerFrame.yOffset); else -- Fnd a suitable position - local optionsFrame = WeakAuras.OptionsFrame(); + local optionsFrame = Private.OptionsFrame(); local yOffset = (optionsFrame:GetTop() + optionsFrame:GetBottom()) / 2; local xOffset = xPositionNextToOptions(); -- We use the top right, because the main frame uses the top right as the reference too @@ -4784,7 +4783,7 @@ function Private.ensurePRDFrame() end if (not xOffset or not yOffset) then - local optionsFrame = WeakAuras.OptionsFrame(); + local optionsFrame = Private.OptionsFrame(); yOffset = optionsFrame:GetBottom() + prdHeight - GetScreenHeight(); xOffset = xPositionNextToOptions() + prdWidth / 2 - GetScreenWidth(); end @@ -4871,7 +4870,7 @@ local function tryAnchorAgain() if (data and region) then local parent = WeakAurasFrame; if (data.parent and WeakAuras.GetData(data.parent) and Private.EnsureRegion(data.parent)) then - parent = WeakAuras.regions[data.parent].region; + parent = Private.regions[data.parent].region; end Private.AnchorFrame(data, region, parent); end @@ -4948,8 +4947,8 @@ local function GetAnchorFrame(data, region, parent) if (frame_name == id) then return parent; end - if(WeakAuras.regions[frame_name]) then - return WeakAuras.regions[frame_name].region; + if(Private.regions[frame_name]) then + return Private.regions[frame_name].region; end postponeAnchor(id); else @@ -5030,7 +5029,7 @@ function Private.AnchorFrame(data, region, parent, force) end end -function WeakAuras.FindUnusedId(prefix) +function Private.FindUnusedId(prefix) prefix = prefix or "New" local num = 2; local id = prefix @@ -5183,7 +5182,7 @@ do end end -function WeakAuras.ParseNameCheck(name) +function Private.ExecEnv.ParseNameCheck(name) local matches = { name = {}, realm = {}, @@ -5264,7 +5263,7 @@ function WeakAuras.ParseNameCheck(name) return matches end -function WeakAuras.ParseZoneCheck(input) +function Private.ExecEnv.ParseZoneCheck(input) if not input then return end local matcher = { @@ -5284,7 +5283,7 @@ function WeakAuras.ParseZoneCheck(input) return matcher end -function WeakAuras.ParseStringCheck(input) +function Private.ExecEnv.ParseStringCheck(input) if not input then return end local matcher = { zones = {}, diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index 4f455cc..0abdf48 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -283,7 +283,7 @@ local Actions = { ["Group"] = function(source, groupId, target, before) if source and not source.data.parent then if groupId then - local group = WeakAuras.GetDisplayButton(groupId) + local group = OptionsPrivate.GetDisplayButton(groupId) if group and group:IsGroup() then local children = group.data.controlledChildren if target then @@ -337,7 +337,7 @@ local Actions = { OptionsPrivate.Private.AddParents(parent) WeakAuras.UpdateGroupOrders(parent); WeakAuras.ClearAndUpdateOptions(parent.id); - local group = WeakAuras.GetDisplayButton(parent.id) + local group = OptionsPrivate.GetDisplayButton(parent.id) group.callbacks.UpdateExpandButton(); group:UpdateParentWarning() group:ReloadTooltip() @@ -376,7 +376,7 @@ end ------------------------- local function GetDropTarget() - local buttonList = WeakAuras.displayButtons + local buttonList = OptionsPrivate.displayButtons for id, button in pairs(buttonList) do if not button.dragging and button:IsEnabled() and button:IsShown() then @@ -405,7 +405,7 @@ end local function Show_DropIndicator(id) local indicator = OptionsPrivate.DropIndicator() - local source = WeakAuras.GetDisplayButton(id) + local source = OptionsPrivate.GetDisplayButton(id) local target, pos if source then target, pos = select(2, GetDropTarget()) @@ -519,7 +519,7 @@ local methods = { for index, selectedId in ipairs(self.grouping) do local selectedData = WeakAuras.GetData(selectedId); tinsert(self.data.controlledChildren, selectedId); - local selectedButton = WeakAuras.GetDisplayButton(selectedId); + local selectedButton = OptionsPrivate.GetDisplayButton(selectedId); while selectedData.parent do selectedButton:Ungroup(); end @@ -535,7 +535,7 @@ local methods = { if (selectedData.controlledChildren) then for child in OptionsPrivate.Private.TraverseAllChildren(selectedData) do - local childButton = WeakAuras.GetDisplayButton(child.id) + local childButton = OptionsPrivate.GetDisplayButton(child.id) childButton:UpdateOffset() end end @@ -618,12 +618,12 @@ local methods = { -- And this fills in the leafs DuplicateAuras(self.data, newGroup, mapping) - local button = WeakAuras.GetDisplayButton(newGroup.id) + local button = OptionsPrivate.GetDisplayButton(newGroup.id) button.callbacks.UpdateExpandButton() button:UpdateParentWarning() for old, new in pairs(mapping) do - local button = WeakAuras.GetDisplayButton(new.id) + local button = OptionsPrivate.GetDisplayButton(new.id) button.callbacks.UpdateExpandButton() button:UpdateParentWarning() end @@ -679,7 +679,7 @@ local methods = { OptionsPrivate.Private.AddParents(parentData) WeakAuras.ClearAndUpdateOptions(parentData.id) self:SetGroupOrder(index - 1, #parentData.controlledChildren); - local otherbutton = WeakAuras.GetDisplayButton(parentData.controlledChildren[index]); + local otherbutton = OptionsPrivate.GetDisplayButton(parentData.controlledChildren[index]); otherbutton:SetGroupOrder(index, #parentData.controlledChildren); OptionsPrivate.SortDisplayButtons(); local updata = {duration = 0.15, type = "custom", use_translate = true, x = 0, y = -32}; @@ -718,7 +718,7 @@ local methods = { OptionsPrivate.Private.AddParents(parentData) WeakAuras.ClearAndUpdateOptions(parentData.id) self:SetGroupOrder(index + 1, #parentData.controlledChildren); - local otherbutton = WeakAuras.GetDisplayButton(parentData.controlledChildren[index]); + local otherbutton = OptionsPrivate.GetDisplayButton(parentData.controlledChildren[index]); otherbutton:SetGroupOrder(index, #parentData.controlledChildren); OptionsPrivate.SortDisplayButtons() local updata = {duration = 0.15, type = "custom", use_translate = true, x = 0, y = -32}; @@ -739,12 +739,12 @@ local methods = { local suspended = OptionsPrivate.Private.PauseAllDynamicGroups() if(self.view.visibility == 2) then for child in OptionsPrivate.Private.TraverseAllChildren(self.data) do - WeakAuras.GetDisplayButton(child.id):PriorityHide(2); + OptionsPrivate.GetDisplayButton(child.id):PriorityHide(2); end self:PriorityHide(2) else for child in OptionsPrivate.Private.TraverseAllChildren(self.data) do - WeakAuras.GetDisplayButton(child.id):PriorityShow(2); + OptionsPrivate.GetDisplayButton(child.id):PriorityShow(2); end self:PriorityShow(2) end @@ -837,7 +837,7 @@ local methods = { if (not self.data.controlledChildren) then local convertMenu = {}; - for regionType, regionData in pairs(WeakAuras.regionOptions) do + for regionType, regionData in pairs(OptionsPrivate.Private.regionOptions) do if(regionType ~= "group" and regionType ~= "dynamicgroup" and regionType ~= self.data.regionType) then tinsert(convertMenu, { text = regionData.displayName, @@ -1016,7 +1016,7 @@ local methods = { tinsert(namestable, {" ", "|cFF00FFFF"..L["Control-click to select multiple displays"]}); end tinsert(namestable, {" ", "|cFF00FFFF"..L["Shift-click to create chat link"]}); - local regionData = WeakAuras.regionOptions[data.regionType or ""] + local regionData = OptionsPrivate.Private.regionOptions[data.regionType or ""] local displayName = regionData and regionData.displayName or ""; self:SetDescription({data.id, displayName}, unpack(namestable)); end, @@ -1091,14 +1091,14 @@ local methods = { end WeakAuras.ClearAndUpdateOptions(self.data.id); WeakAuras.UpdateGroupOrders(parentData); - local parentButton = WeakAuras.GetDisplayButton(parentData.id) + local parentButton = OptionsPrivate.GetDisplayButton(parentData.id) if(#parentData.controlledChildren == 0) then parentButton:DisableExpand() end parentButton:UpdateParentWarning() for child in OptionsPrivate.Private.TraverseAllChildren(self.data) do - local button = WeakAuras.GetDisplayButton(child.id) + local button = OptionsPrivate.GetDisplayButton(child.id) button:UpdateOffset() end @@ -1471,7 +1471,7 @@ local methods = { ["UpdateParentWarning"] = function(self) self:UpdateWarning() for parent in OptionsPrivate.Private.TraverseParents(self.data) do - local parentButton = WeakAuras.GetDisplayButton(parent.id) + local parentButton = OptionsPrivate.GetDisplayButton(parent.id) if parentButton then parentButton:UpdateWarning() end @@ -1585,17 +1585,17 @@ local methods = { end, ["RecheckParentVisibility"] = function(self) if self.data.parent then - local parentButton = WeakAuras.GetDisplayButton(self.data.parent) + local parentButton = OptionsPrivate.GetDisplayButton(self.data.parent) parentButton:RecheckVisibility() else - WeakAuras.OptionsFrame().loadedButton:RecheckVisibility() - WeakAuras.OptionsFrame().unloadedButton:RecheckVisibility() + OptionsPrivate.Private.OptionsFrame().loadedButton:RecheckVisibility() + OptionsPrivate.Private.OptionsFrame().unloadedButton:RecheckVisibility() end end, ["RecheckVisibility"] = function(self) local none, all = true, true; for child in OptionsPrivate.Private.TraverseAllChildren(self.data) do - local childButton = WeakAuras.GetDisplayButton(child.id); + local childButton = OptionsPrivate.GetDisplayButton(child.id); if(childButton) then if(childButton:GetVisibility() ~= 2) then all = false; @@ -1693,7 +1693,7 @@ local methods = { self:ReleaseThumbnail() self:AcquireThumbnail() else - local option = WeakAuras.regionOptions[self.thumbnailType] + local option = OptionsPrivate.Private.regionOptions[self.thumbnailType] if option and option.modifyThumbnail then option.modifyThumbnail(self.frame, self.thumbnail, self.data) end @@ -1707,7 +1707,7 @@ local methods = { if self.thumbnail then local regionType = self.thumbnailType - local option = WeakAuras.regionOptions[regionType] + local option = OptionsPrivate.Private.regionOptions[regionType] option.releaseThumbnail(self.thumbnail) self.thumbnail = nil end @@ -1727,7 +1727,7 @@ local methods = { local regionType = self.data.regionType self.thumbnailType = regionType - local option = WeakAuras.regionOptions[regionType] + local option = OptionsPrivate.Private.regionOptions[regionType] if option and option.acquireThumbnail then self.thumbnail = option.acquireThumbnail(button, self.data) self:SetIcon(self.thumbnail) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua index 3bc471e..a017d03 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasNewButton.lua @@ -1,4 +1,5 @@ if not WeakAuras.IsLibsOK() then return end +local AddonName, OptionsPrivate = ... local Type, Version = "WeakAurasNewButton", 25 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) @@ -55,7 +56,7 @@ local methods = { end end, ["SetThumbnail"] = function(self, regionType, data) - local regionData = WeakAuras.regionOptions[regionType] + local regionData = OptionsPrivate.Private.regionOptions[regionType] if regionData and regionData.acquireThumbnail then local thumbnail = regionData.acquireThumbnail(self.frame, data) self:SetIcon(thumbnail) @@ -65,7 +66,7 @@ local methods = { end, ["ReleaseThumbnail"] = function(self) if self.thumbnail then - local regionData = WeakAuras.regionOptions[self.thumbnailType] + local regionData = OptionsPrivate.Private.regionOptions[self.thumbnailType] if regionData and regionData.releaseThumbnail then regionData.releaseThumbnail(self.thumbnail) end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua index 5fa6423..2bb623c 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingInstallButton.lua @@ -84,7 +84,7 @@ local methods = { self:ReleaseThumbnail() self:AcquireThumbnail() else - local option = WeakAuras.regionOptions[self.thumbnailType] + local option = OptionsPrivate.Private.regionOptions[self.thumbnailType] if option and option.modifyThumbnail then option.modifyThumbnail(self.frame, self.thumbnail, self.data) end @@ -98,7 +98,7 @@ local methods = { if self.thumbnail then local regionType = self.thumbnailType - local option = WeakAuras.regionOptions[regionType] + local option = OptionsPrivate.Private.regionOptions[regionType] if self.thumbnail.icon then self.thumbnail.icon:SetDesaturated(false) end @@ -121,7 +121,7 @@ local methods = { local regionType = self.data.regionType self.thumbnailType = regionType - local option = WeakAuras.regionOptions[regionType] + local option = OptionsPrivate.Private.regionOptions[regionType] if option and option.acquireThumbnail then self.thumbnail = option.acquireThumbnail(button, self.data) if self.thumbnail.icon then diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua index ea4d608..6d58dd8 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua @@ -214,7 +214,7 @@ local methods = { self:ReleaseThumbnail() self:AcquireThumbnail() else - local option = WeakAuras.regionOptions[self.thumbnailType] + local option = OptionsPrivate.Private.regionOptions[self.thumbnailType] if option and option.modifyThumbnail then option.modifyThumbnail(self.frame, self.thumbnail, self.data) end @@ -228,7 +228,7 @@ local methods = { if self.thumbnail then local regionType = self.thumbnailType - local option = WeakAuras.regionOptions[regionType] + local option = OptionsPrivate.Private.regionOptions[regionType] if self.thumbnail.icon then self.thumbnail.icon:SetDesaturated(false) end @@ -251,7 +251,7 @@ local methods = { local regionType = self.data.regionType self.thumbnailType = regionType - local option = WeakAuras.regionOptions[regionType] + local option = OptionsPrivate.Private.regionOptions[regionType] if option and option.acquireThumbnail then self.thumbnail = option.acquireThumbnail(button, self.data) if self.thumbnail.icon then diff --git a/WeakAurasOptions/AnimationOptions.lua b/WeakAurasOptions/AnimationOptions.lua index 1fe0a05..bc76cbf 100644 --- a/WeakAurasOptions/AnimationOptions.lua +++ b/WeakAurasOptions/AnimationOptions.lua @@ -17,8 +17,8 @@ local setAll = OptionsPrivate.commonOptions.CreateSetAll("animation", getAll) local function filterAnimPresetTypes(intable, id) local ret = {}; OptionsPrivate.Private.EnsureRegion(id) - local region = WeakAuras.regions[id] and WeakAuras.regions[id].region; - local regionType = WeakAuras.regions[id] and WeakAuras.regions[id].regionType; + local region = OptionsPrivate.Private.regions[id] and OptionsPrivate.Private.regions[id].region; + local regionType = OptionsPrivate.Private.regions[id] and OptionsPrivate.Private.regions[id].regionType; local data = WeakAuras.GetData(id); if data.controlledChildren then @@ -82,8 +82,8 @@ function OptionsPrivate.GetAnimationOptions(data) if(field == "main") then local region = OptionsPrivate.Private.EnsureRegion(id) OptionsPrivate.Private.Animate("display", data.uid, "main", data.animation.main, region, false, nil, true); - if(WeakAuras.clones[id]) then - for cloneId, cloneRegion in pairs(WeakAuras.clones[id]) do + if(OptionsPrivate.Private.clones[id]) then + for cloneId, cloneRegion in pairs(OptionsPrivate.Private.clones[id]) do OptionsPrivate.Private.Animate("display", data.uid, "main", data.animation.main, cloneRegion, false, nil, true, cloneId); end end @@ -928,8 +928,8 @@ function OptionsPrivate.GetAnimationOptions(data) local function extraSetFunction() OptionsPrivate.Private.Animate("display", data.uid, "main", data.animation.main, OptionsPrivate.Private.EnsureRegion(id), false, nil, true) - if(WeakAuras.clones[id]) then - for cloneId, cloneRegion in pairs(WeakAuras.clones[id]) do + if(OptionsPrivate.Private.clones[id]) then + for cloneId, cloneRegion in pairs(OptionsPrivate.Private.clones[id]) do OptionsPrivate.Private.Animate("display", data.uid, "main", data.animation.main, cloneRegion, false, nil, true, cloneId) end diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index 28d24b8..868fcdb 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -2,7 +2,6 @@ if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L -local regionOptions = WeakAuras.regionOptions local commonOptionsCache = {} OptionsPrivate.commonOptionsCache = commonOptionsCache @@ -500,7 +499,7 @@ local function replaceNameDescFuncs(intable, data, subOption) local index = string.find(input, ".", 1, true); if (index) then local regionType = string.sub(input, 1, index - 1); - return regionOptions[regionType] and regionType; + return OptionsPrivate.Private.regionOptions[regionType] and regionType; end return nil; end diff --git a/WeakAurasOptions/DisplayOptions.lua b/WeakAurasOptions/DisplayOptions.lua index f9d53c1..1b8dda3 100644 --- a/WeakAurasOptions/DisplayOptions.lua +++ b/WeakAurasOptions/DisplayOptions.lua @@ -1,7 +1,6 @@ if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L -local regionOptions = WeakAuras.regionOptions local flattenRegionOptions = OptionsPrivate.commonOptions.flattenRegionOptions local fixMetaOrders = OptionsPrivate.commonOptions.fixMetaOrders @@ -90,8 +89,8 @@ function OptionsPrivate.GetDisplayOptions(data) local hasSubElements = false - if(regionOptions[data.regionType]) then - regionOption = regionOptions[data.regionType].create(id, data); + if(OptionsPrivate.Private.regionOptions[data.regionType]) then + regionOption = OptionsPrivate.Private.regionOptions[data.regionType].create(id, data); if data.subRegions then local subIndex = {} @@ -210,8 +209,8 @@ function OptionsPrivate.GetDisplayOptions(data) for child in OptionsPrivate.Private.TraverseLeafs(data) do if child and not handledRegionTypes[child.regionType] then handledRegionTypes[child.regionType] = true; - if regionOptions[child.regionType] then - allOptions = union(allOptions, regionOptions[child.regionType].create(id, data)); + if OptionsPrivate.Private.regionOptions[child.regionType] then + allOptions = union(allOptions, OptionsPrivate.Private.regionOptions[child.regionType].create(id, data)); else unsupportedCount = unsupportedCount + 1 allOptions["__unsupported" .. unsupportedCount] = { diff --git a/WeakAurasOptions/GroupOptions.lua b/WeakAurasOptions/GroupOptions.lua index 817be4f..718eaae 100644 --- a/WeakAurasOptions/GroupOptions.lua +++ b/WeakAurasOptions/GroupOptions.lua @@ -2,15 +2,14 @@ if not WeakAuras.IsLibsOK() then return end local AddonName, OptionsPrivate = ... local L = WeakAuras.L -local regionOptions = WeakAuras.regionOptions; local parsePrefix = OptionsPrivate.commonOptions.parsePrefix local flattenRegionOptions = OptionsPrivate.commonOptions.flattenRegionOptions function OptionsPrivate.GetGroupOptions(data) local regionOption; local id = data.id - if (regionOptions[data.regionType]) then - regionOption = regionOptions[data.regionType].create(id, data); + if (OptionsPrivate.Private.regionOptions[data.regionType]) then + regionOption = OptionsPrivate.Private.regionOptions[data.regionType].create(id, data); else regionOption = { [data.regionType] = { diff --git a/WeakAurasOptions/OptionsFrames/FrameChooser.lua b/WeakAurasOptions/OptionsFrames/FrameChooser.lua index ea83896..039338e 100644 --- a/WeakAurasOptions/OptionsFrames/FrameChooser.lua +++ b/WeakAurasOptions/OptionsFrames/FrameChooser.lua @@ -17,7 +17,7 @@ local frameChooserBox local oldFocus local oldFocusName function OptionsPrivate.StartFrameChooser(data, path) - local frame = WeakAuras.OptionsFrame(); + local frame = OptionsPrivate.Private.OptionsFrame(); if not(frameChooserFrame) then frameChooserFrame = CreateFrame("Frame"); frameChooserBox = CreateFrame("Frame", nil, frameChooserFrame); @@ -50,7 +50,7 @@ function OptionsPrivate.StartFrameChooser(data, path) if(focusName == "WorldFrame" or not focusName) then focusName = nil; local focusIsGroup = false; - for id, regionData in pairs(WeakAuras.regions) do + for id, regionData in pairs(OptionsPrivate.Private.regions) do if(regionData.region:IsVisible() and MouseIsOver(regionData.region)) then local isGroup = regionData.regionType == "group" or regionData.regionType == "dynamicgroup"; if (not focusName or (not isGroup and focusIsGroup)) then diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index 031b766..e076260 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -380,7 +380,7 @@ local function BuildAlignLines(mover) skipIds[child.id] = true end - for k, v in pairs(WeakAuras.displayButtons) do + for k, v in pairs(OptionsPrivate.displayButtons) do local region = WeakAuras.GetRegion(v.data.id) if not skipIds[k] and v.view.visibility ~= 0 and region then local scale = region:GetEffectiveScale() / UIParent:GetEffectiveScale() diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index 936c83b..bc33f2b 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -17,8 +17,7 @@ local AceConfigRegistry = LibStub("AceConfigRegistry-3.0") local WeakAuras = WeakAuras local L = WeakAuras.L -local displayButtons = WeakAuras.displayButtons -local regionOptions = WeakAuras.regionOptions +local displayButtons = OptionsPrivate.displayButtons local tempGroup = OptionsPrivate.tempGroup local aceOptions = {} @@ -138,11 +137,11 @@ function OptionsPrivate.CreateFrame() OptionsPrivate.Private.ClearFakeStates() - for id, data in pairs(WeakAuras.regions) do + for id, data in pairs(OptionsPrivate.Private.regions) do data.region:Collapse() data.region:OptionsClosed() - if WeakAuras.clones[id] then - for _, cloneRegion in pairs(WeakAuras.clones[id]) do + if OptionsPrivate.Private.clones[id] then + for _, cloneRegion in pairs(OptionsPrivate.Private.clones[id]) do cloneRegion:Collapse() cloneRegion:OptionsClosed() end @@ -1126,7 +1125,7 @@ function OptionsPrivate.CreateFrame() end if targetId then - local pickedButton = WeakAuras.GetDisplayButton(targetId) + local pickedButton = OptionsPrivate.GetDisplayButton(targetId) if pickedButton.data.controlledChildren then targetIsDynamicGroup = pickedButton.data.regionType == "dynamicgroup" else @@ -1180,7 +1179,7 @@ function OptionsPrivate.CreateFrame() end local regionTypesSorted = {} - for regionType, regionData in pairs(regionOptions) do + for regionType, regionData in pairs(OptionsPrivate.Private.regionOptions) do tinsert(regionTypesSorted, regionType) end @@ -1201,14 +1200,14 @@ function OptionsPrivate.CreateFrame() return false end - return regionOptions[a].displayName < regionOptions[b].displayName + return OptionsPrivate.Private.regionOptions[a].displayName < OptionsPrivate.Private.regionOptions[b].displayName end) for index, regionType in ipairs(regionTypesSorted) do if (targetIsDynamicGroup and (regionType == "group" or regionType == "dynamicgroup")) then -- Dynamic groups can't contain group/dynamic groups else - local regionData = regionOptions[regionType] + local regionData = OptionsPrivate.Private.regionOptions[regionType] local button = AceGUI:Create("WeakAurasNewButton") button:SetTitle(regionData.displayName) if(type(regionData.icon) == "string" or type(regionData.icon) == "table") then @@ -1262,8 +1261,8 @@ function OptionsPrivate.CreateFrame() } if not frame.importThumbnail then - local thumbnail = regionOptions["text"].createThumbnail(UIParent) - regionOptions["text"].modifyThumbnail(UIParent, thumbnail, data) + local thumbnail = OptionsPrivate.Private.regionOptions["text"].createThumbnail(UIParent) + OptionsPrivate.Private.regionOptions["text"].modifyThumbnail(UIParent, thumbnail, data) thumbnail.mask:SetPoint("BOTTOMLEFT", thumbnail, "BOTTOMLEFT", 3, 3) thumbnail.mask:SetPoint("TOPRIGHT", thumbnail, "TOPRIGHT", -3, -3) frame.importThumbnail = thumbnail diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index 67abe32..15dd6a9 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -1676,7 +1676,7 @@ local methods = { uidMap:ChangeId(uid, existingData.id) else if WeakAuras.GetData(uidMap:GetIdFor(uid)) then - local newId = WeakAuras.FindUnusedId(uidMap:GetIdFor(uid)) + local newId = OptionsPrivate.Private.FindUnusedId(uidMap:GetIdFor(uid)) uidMap:ChangeId(uid, newId) end end @@ -1731,7 +1731,7 @@ local methods = { if string.sub(data.id, 1, #targetName) == targetName then -- Our name is already prefixed with targetName, don't try to improve else - local newId = WeakAuras.FindUnusedId(targetName) + local newId = OptionsPrivate.Private.FindUnusedId(targetName) local oldid = data.id WeakAuras.Rename(data, newId) if targetName[aura.uid] then -- We can hope that the aura the squatter renames itself, so try again @@ -1851,7 +1851,7 @@ local methods = { data.authorMode = nil WeakAuras.Add(data) OptionsPrivate.Private.SetHistory(data.uid, data, "import") - local button = WeakAuras.GetDisplayButton(data.id) + local button = OptionsPrivate.GetDisplayButton(data.id) button:SetData(data) if (data.parent) then local parentIsDynamicGroup = structureUidMap:GetParentIsDynamicGroup(uid) @@ -1875,14 +1875,14 @@ local methods = { for i = #phase2Order, 1, -1 do local uid = phase2Order[i] local data = OptionsPrivate.Private.GetDataByUID(uid) - local displayButton = WeakAuras.GetDisplayButton(data.id) + local displayButton = OptionsPrivate.GetDisplayButton(data.id) displayButton:UpdateOffset() end end, ImportPhase1 = function(self, uidMap, uid, phase2Order) tinsert(phase2Order, uid) local data = uidMap:GetPhase1Data(uid) - local newId = WeakAuras.FindUnusedId(data.id) + local newId = OptionsPrivate.Private.FindUnusedId(data.id) uidMap:ChangeId(uid, newId) data.preferToUpdate = false @@ -1913,7 +1913,7 @@ local methods = { WeakAuras.Add(data) OptionsPrivate.Private.SetHistory(data.uid, data, "import") - local button = WeakAuras.GetDisplayButton(data.id) + local button = OptionsPrivate.GetDisplayButton(data.id) button:SetData(data) if (data.parent) then local parentIsDynamicGroup = uidMap:GetParentIsDynamicGroup(uid) @@ -1936,7 +1936,7 @@ local methods = { for i = #phase2Order, 1, -1 do local uid = phase2Order[i] local data = OptionsPrivate.Private.GetDataByUID(uid) - local displayButton = WeakAuras.GetDisplayButton(data.id) + local displayButton = OptionsPrivate.GetDisplayButton(data.id) displayButton:UpdateOffset() end diff --git a/WeakAurasOptions/RegionOptions/Model.lua b/WeakAurasOptions/RegionOptions/Model.lua index d17d866..d4ac7dd 100644 --- a/WeakAurasOptions/RegionOptions/Model.lua +++ b/WeakAurasOptions/RegionOptions/Model.lua @@ -149,7 +149,7 @@ local function modifyThumbnail(parent, region, data) local model = region.model region:SetScript("OnUpdate", function() - local optionsFrame = WeakAuras.OptionsFrame(); + local optionsFrame = OptionsPrivate.Private.OptionsFrame(); if optionsFrame then model:SetParent(optionsFrame) region:SetScript("OnUpdate", nil) diff --git a/WeakAurasOptions/RegionOptions/StopMotion.lua b/WeakAurasOptions/RegionOptions/StopMotion.lua index b31374c..3239918 100644 --- a/WeakAurasOptions/RegionOptions/StopMotion.lua +++ b/WeakAurasOptions/RegionOptions/StopMotion.lua @@ -6,7 +6,7 @@ local AddonName, OptionsPrivate = ... local texture_types = WeakAuras.StopMotion.texture_types; local texture_data = WeakAuras.StopMotion.texture_data; local animation_types = WeakAuras.StopMotion.animation_types; -local setTile = WeakAuras.setTile; +local setTile = WeakAuras.setTile local function setTextureFunc(textureWidget, texturePath, textureName) local data = texture_data[texturePath]; diff --git a/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua b/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua index 8197233..76e9486 100644 --- a/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua +++ b/WeakAurasOptions/SubRegionOptions/SubRegionCommon.lua @@ -23,7 +23,7 @@ local function AdjustConditions(data, replacements) end end -function WeakAuras.DeleteSubRegion(data, index, regionType) +function OptionsPrivate.DeleteSubRegion(data, index, regionType) if not data.subRegions then return end @@ -123,7 +123,7 @@ function OptionsPrivate.AddUpDownDeleteDuplicate(options, parentData, index, sub end options.__delete = function() for child in OptionsPrivate.Private.TraverseLeafsOrAura(parentData) do - WeakAuras.DeleteSubRegion(child, index, subRegionType) + OptionsPrivate.DeleteSubRegion(child, index, subRegionType) end WeakAuras.ClearAndUpdateOptions(parentData.id) end diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index ab35b25..59266d5 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -19,7 +19,7 @@ local L = WeakAuras.L local ADDON_NAME = "WeakAurasOptions"; local displayButtons = {}; -WeakAuras.displayButtons = displayButtons; +OptionsPrivate.displayButtons = displayButtons; local spellCache = WeakAuras.spellCache; local savedVars = {}; @@ -93,13 +93,13 @@ function OptionsPrivate.DuplicateAura(data, newParent, massEdit, targetIndex) OptionsPrivate.Private.AddParents(parentData) for index, id in pairs(parentData.controlledChildren) do - local childButton = WeakAuras.GetDisplayButton(id) + local childButton = OptionsPrivate.GetDisplayButton(id) childButton:SetGroup(parentData.id, parentData.regionType == "dynamicgroup") childButton:SetGroupOrder(index, #parentData.controlledChildren) end if not massEdit then - local button = WeakAuras.GetDisplayButton(parentData.id) + local button = OptionsPrivate.GetDisplayButton(parentData.id) button.callbacks.UpdateExpandButton() button:UpdateParentWarning() end @@ -244,7 +244,7 @@ local function commonParent(controlledChildren) local targetIndex = math.huge for index, id in ipairs(controlledChildren) do local childData = WeakAuras.GetData(id); - local childButton = WeakAuras.GetDisplayButton(id) + local childButton = OptionsPrivate.GetDisplayButton(id) targetIndex = min(targetIndex, childButton:GetGroupOrder() or math.huge) if (parent == nil) then @@ -262,13 +262,13 @@ end local function CreateNewGroupFromSelection(regionType, resetChildPositions) local data = { - id = WeakAuras.FindUnusedId(tempGroup.controlledChildren[1].." Group"), + id = OptionsPrivate.Private.FindUnusedId(tempGroup.controlledChildren[1].." Group"), regionType = regionType, }; - WeakAuras.DeepMixin(data, WeakAuras.data_stub) + WeakAuras.DeepMixin(data, OptionsPrivate.Private.data_stub) data.internalVersion = WeakAuras.InternalVersion() - WeakAuras.validate(data, WeakAuras.regionTypes[regionType].default); + OptionsPrivate.Private.validate(data, OptionsPrivate.Private.regionTypes[regionType].default); local parent, targetIndex = commonParent(tempGroup.controlledChildren) @@ -283,7 +283,7 @@ local function CreateNewGroupFromSelection(regionType, resetChildPositions) WeakAuras.UpdateGroupOrders(parentData); OptionsPrivate.ClearOptions(parentData.id); - local parentButton = WeakAuras.GetDisplayButton(parent) + local parentButton = OptionsPrivate.GetDisplayButton(parent) parentButton.callbacks.UpdateExpandButton(); parentButton:Expand(); parentButton:ReloadTooltip(); @@ -295,7 +295,7 @@ local function CreateNewGroupFromSelection(regionType, resetChildPositions) for index, childId in pairs(tempGroup.controlledChildren) do local childData = WeakAuras.GetData(childId); - local childButton = WeakAuras.GetDisplayButton(childId) + local childButton = OptionsPrivate.GetDisplayButton(childId) local oldParent = childData.parent local oldParentData = WeakAuras.GetData(oldParent) if (oldParent) then @@ -308,7 +308,7 @@ local function CreateNewGroupFromSelection(regionType, resetChildPositions) OptionsPrivate.Private.AddParents(oldParentData) WeakAuras.UpdateGroupOrders(oldParentData); WeakAuras.ClearAndUpdateOptions(oldParent); - local oldParentButton = WeakAuras.GetDisplayButton(oldParent) + local oldParentButton = OptionsPrivate.GetDisplayButton(oldParent) oldParentButton.callbacks.UpdateExpandButton(); oldParentButton:ReloadTooltip() oldParentButton:UpdateParentWarning() @@ -328,7 +328,7 @@ local function CreateNewGroupFromSelection(regionType, resetChildPositions) childButton:SetGroupOrder(index, #data.controlledChildren); end - local button = WeakAuras.GetDisplayButton(data.id); + local button = OptionsPrivate.GetDisplayButton(data.id); button.callbacks.UpdateExpandButton(); button:UpdateParentWarning() OptionsPrivate.SortDisplayButtons(); @@ -455,7 +455,7 @@ StaticPopupDialogs["WEAKAURAS_CONFIRM_DELETE"] = { if self.data.parents then for id in pairs(self.data.parents) do local parentData = WeakAuras.GetData(id) - local parentButton = WeakAuras.GetDisplayButton(id) + local parentButton = OptionsPrivate.GetDisplayButton(id) WeakAuras.UpdateGroupOrders(parentData) if(#parentData.controlledChildren == 0) then parentButton:DisableExpand() @@ -509,14 +509,6 @@ function OptionsPrivate.ConfirmDelete(toDelete, parents) end end -function WeakAuras.OptionsFrame() - if(frame) then - return frame; - else - return nil; - end -end - local function AfterScanForLoads() if(frame) then if (frame:IsVisible()) then @@ -558,19 +550,19 @@ end local function OnRename(event, uid, oldid, newid) local data = OptionsPrivate.Private.GetDataByUID(uid) - WeakAuras.displayButtons[newid] = WeakAuras.displayButtons[oldid]; - WeakAuras.displayButtons[newid]:SetData(data) - WeakAuras.displayButtons[oldid] = nil; + OptionsPrivate.displayButtons[newid] = OptionsPrivate.displayButtons[oldid]; + OptionsPrivate.displayButtons[newid]:SetData(data) + OptionsPrivate.displayButtons[oldid] = nil; OptionsPrivate.ClearOptions(oldid) - WeakAuras.displayButtons[newid]:SetTitle(newid); + OptionsPrivate.displayButtons[newid]:SetTitle(newid); collapsedOptions[newid] = collapsedOptions[oldid] collapsedOptions[oldid] = nil if(data.controlledChildren) then for _, childId in pairs(data.controlledChildren) do - WeakAuras.displayButtons[childId]:SetGroup(newid) + OptionsPrivate.displayButtons[childId]:SetGroup(newid) end end @@ -589,12 +581,21 @@ local function OnRename(event, uid, oldid, newid) end end +local function OptionsFrame() + if(frame) then + return frame + else + return nil + end +end + function WeakAuras.ToggleOptions(msg, Private) if not Private then return end if not OptionsPrivate.Private then OptionsPrivate.Private = Private + Private.OptionsFrame = OptionsFrame OptionsPrivate.Private.callbacks:RegisterCallback("AuraWarningsUpdated", function(event, uid) local id = OptionsPrivate.Private.UIDtoID(uid) if displayButtons[id] then @@ -603,7 +604,7 @@ function WeakAuras.ToggleOptions(msg, Private) end local data = Private.GetDataByUID(uid) if data and data.parent then - local button = WeakAuras.GetDisplayButton(data.parent); + local button = OptionsPrivate.GetDisplayButton(data.parent); if button then button:UpdateParentWarning() end @@ -741,7 +742,7 @@ local function LayoutDisplayButtons(msg) button:PriorityShow(1); end end - WeakAuras.OptionsFrame().loadedButton:RecheckVisibility() + OptionsPrivate.Private.OptionsFrame().loadedButton:RecheckVisibility() end OptionsPrivate.Private.ResumeAllDynamicGroups(suspended) @@ -905,8 +906,8 @@ function OptionsPrivate.ConvertDisplay(data, newType) local visibility = displayButtons[id]:GetVisibility(); displayButtons[id]:PriorityHide(2); - if WeakAuras.regions[id] then - WeakAuras.regions[id].region:Collapse() + if OptionsPrivate.Private.regions[id] then + OptionsPrivate.Private.regions[id].region:Collapse() end OptionsPrivate.Private.CollapseAllClones(id); @@ -936,7 +937,7 @@ function WeakAuras.UpdateGroupOrders(data) if(data.controlledChildren) then local total = #data.controlledChildren; for index, id in pairs(data.controlledChildren) do - local button = WeakAuras.GetDisplayButton(id); + local button = OptionsPrivate.GetDisplayButton(id); button:SetGroupOrder(index, total); end end @@ -1326,7 +1327,7 @@ function OptionsPrivate.PickDisplayMultipleShift(target) end end -function WeakAuras.GetDisplayButton(id) +function OptionsPrivate.GetDisplayButton(id) if(id and displayButtons[id]) then return displayButtons[id]; end @@ -1351,7 +1352,7 @@ function OptionsPrivate.StartGrouping(data) local children = {}; -- start grouping for selected buttons for index, childId in ipairs(tempGroup.controlledChildren) do - local button = WeakAuras.GetDisplayButton(childId); + local button = OptionsPrivate.GetDisplayButton(childId); button:StartGrouping(tempGroup.controlledChildren, true); children[childId] = true; end @@ -1386,11 +1387,11 @@ function OptionsPrivate.Ungroup(data) if (frame.pickedDisplay == tempGroup and #tempGroup.controlledChildren > 0) then for index, childId in ipairs(tempGroup.controlledChildren) do - local button = WeakAuras.GetDisplayButton(childId); + local button = OptionsPrivate.GetDisplayButton(childId); button:Ungroup(data); end else - local button = WeakAuras.GetDisplayButton(data.id); + local button = OptionsPrivate.GetDisplayButton(data.id); button:Ungroup(data); end WeakAuras.FillOptions() @@ -1438,8 +1439,8 @@ local function CompareButtonOrder(a, b) if (parents[parent]) then -- We have found the common parent, the last node in the chain is -- Compare the previous nodes GroupOrder - local aButton = WeakAuras.GetDisplayButton(parents[parent]) - local bButton = WeakAuras.GetDisplayButton(bNode) + local aButton = OptionsPrivate.GetDisplayButton(parents[parent]) + local bButton = OptionsPrivate.GetDisplayButton(bNode) return aButton:GetGroupOrder() < bButton:GetGroupOrder() end lastBParent = parent @@ -1448,8 +1449,8 @@ local function CompareButtonOrder(a, b) end -- If we are here there was no common parent - local aButton = WeakAuras.GetDisplayButton(lastAParent) - local bButton = WeakAuras.GetDisplayButton(lastBParent) + local aButton = OptionsPrivate.GetDisplayButton(lastAParent) + local bButton = OptionsPrivate.GetDisplayButton(lastBParent) return aButton.data.id < bButton.data.id end @@ -1518,7 +1519,7 @@ function OptionsPrivate.StartDrag(mainAura) -- set dragging for selected buttons in reverse for ordering for child in OptionsPrivate.Private.TraverseAllChildren(tempGroup) do - local button = WeakAuras.GetDisplayButton(child.id); + local button = OptionsPrivate.GetDisplayButton(child.id); button:DragStart("MULTI", true, mainAura, size) children[child.id] = true end @@ -1534,7 +1535,7 @@ function OptionsPrivate.StartDrag(mainAura) local mode = "GROUP" local children = {}; for child in OptionsPrivate.Private.TraverseAll(mainAura) do - local button = WeakAuras.GetDisplayButton(child.id); + local button = OptionsPrivate.GetDisplayButton(child.id); button:DragStart(mode, true, mainAura) children[child.id] = true end @@ -1665,11 +1666,11 @@ end function WeakAuras.SetMoverSizer(id) OptionsPrivate.Private.EnsureRegion(id) - if WeakAuras.regions[id].region.toShow then - frame.moversizer:SetToRegion(WeakAuras.regions[id].region, db.displays[id]) + if OptionsPrivate.Private.regions[id].region.toShow then + frame.moversizer:SetToRegion(OptionsPrivate.Private.regions[id].region, db.displays[id]) else - if WeakAuras.clones[id] then - local _, clone = next(WeakAuras.clones[id]) + if OptionsPrivate.Private.clones[id] then + local _, clone = next(OptionsPrivate.Private.clones[id]) if clone then frame.moversizer:SetToRegion(clone, db.displays[id]) end @@ -1694,25 +1695,25 @@ function WeakAuras.NewAura(sourceData, regionType, targetId) local function ensure(t, k, v) return t and k and v and t[k] == v end - local new_id = WeakAuras.FindUnusedId("New") + local new_id = OptionsPrivate.Private.FindUnusedId("New") local data = {id = new_id, regionType = regionType, uid = WeakAuras.GenerateUniqueID()} - WeakAuras.DeepMixin(data, WeakAuras.data_stub); + WeakAuras.DeepMixin(data, OptionsPrivate.Private.data_stub); if (sourceData) then WeakAuras.DeepMixin(data, sourceData); end data.internalVersion = WeakAuras.InternalVersion(); - WeakAuras.validate(data, WeakAuras.regionTypes[regionType].default); + OptionsPrivate.Private.validate(data, OptionsPrivate.Private.regionTypes[regionType].default); AddDefaultSubRegions(data) if targetId then - local target = WeakAuras.GetDisplayButton(targetId); + local target = OptionsPrivate.GetDisplayButton(targetId); local group if (target) then if (target:IsGroup()) then group = target; else - group = WeakAuras.GetDisplayButton(target.data.parent); + group = OptionsPrivate.GetDisplayButton(target.data.parent); end if (group) then -- Sanity check so that we don't create a group/dynamic group in a group From 671e778a7d43697c4215f75e476c13a6cef3f6d4 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 9 Jan 2025 15:51:07 +0100 Subject: [PATCH 012/153] from retail --- WeakAuras/BuffTrigger.lua | 89 --- WeakAuras/GenericTrigger.lua | 8 +- WeakAuras/Modernize.lua | 20 + WeakAuras/RegionTypes/Icon.lua | 10 +- WeakAuras/WeakAuras.lua | 5 + WeakAuras/WeakAuras.toc | 1 - WeakAurasOptions/BuffTrigger.lua | 887 ------------------------ WeakAurasOptions/InformationOptions.lua | 8 +- WeakAurasOptions/WeakAurasOptions.toc | 1 - 9 files changed, 43 insertions(+), 986 deletions(-) delete mode 100644 WeakAuras/BuffTrigger.lua delete mode 100644 WeakAurasOptions/BuffTrigger.lua diff --git a/WeakAuras/BuffTrigger.lua b/WeakAuras/BuffTrigger.lua deleted file mode 100644 index 860f30a..0000000 --- a/WeakAuras/BuffTrigger.lua +++ /dev/null @@ -1,89 +0,0 @@ ---[[ BuffTrigger.lua -This used to contains the "aura" trigger for buffs and debuffs. Nowadays all functions do essentially nothing -]]-- - -if not WeakAuras.IsLibsOK() then return end -local AddonName, Private = ... - -local L = WeakAuras.L - -local BuffTrigger = {} - -function BuffTrigger.UnloadAll() end - -function BuffTrigger.LoadDisplays(toLoad) end - -function BuffTrigger.UnloadDisplays(toUnload) end - -function BuffTrigger.FinishLoadUnload() end - -function BuffTrigger.Delete(id) end - -function BuffTrigger.Rename(oldid, newid) end - -function BuffTrigger.Add(data) - if data.triggers then - local hasLegacyAuraTrigger = false - for index, t in ipairs(data.triggers) do - if t.trigger.type == "aura" then - hasLegacyAuraTrigger = true - break - end - end - if hasLegacyAuraTrigger then - Private.AuraWarnings.UpdateWarning(data.uid, "legacy", "warning", L["This aura has legacy aura trigger(s), which are no longer supported."]) - else - Private.AuraWarnings.UpdateWarning(data.uid, "legacy") - end - end -end - -function BuffTrigger.CanHaveDuration(data, triggernum) - return false -end - -function BuffTrigger.GetOverlayInfo(data, triggernum) return {} end - -function BuffTrigger.CanHaveClones(data, triggernum) return false end - -function BuffTrigger.CanHaveTooltip(data, triggernum) end - -function BuffTrigger.SetToolTip(trigger, state) end - -function BuffTrigger.GetNameAndIcon(data, triggernum) end - -function BuffTrigger.GetAdditionalProperties(data, triggernum) - return "" -end - -function BuffTrigger.GetTriggerConditions(data, triggernum) - return {} -end - -function BuffTrigger.CreateFallbackState(data, triggernum, state) - state.show = true; - state.changed = true; - state.progressType = "timed"; - state.duration = 0; - state.expirationTime = math.huge; -end - -function BuffTrigger.GetName(triggerType) - if (triggerType == "aura") then - return L["Legacy Aura (disabled)"]; - end -end - -function BuffTrigger.GetTriggerDescription(data, triggernum, namestable) - tinsert(namestable, {L["Legacy Aura (disabled):"], L[""]}); -end - -function BuffTrigger.CreateFakeStates(id, triggernum) - local allStates = WeakAuras.GetTriggerStateForTrigger(id, triggernum); - local data = WeakAuras.GetData(id) - local state = {} - BuffTrigger.CreateFallbackState(data, triggernum, state) - allStates[""] = state -end - -WeakAuras.RegisterTriggerSystem({"aura"}, BuffTrigger); diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index ea58ce8..32af1dd 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1563,7 +1563,9 @@ function GenericTrigger.Add(data, region) else tinsert(trigger_events, event) end - force_events = trigger.custom_type == "status" or trigger.custom_type == "stateupdate"; + if trigger.custom_type == "status" or trigger.custom_type == "stateupdate" then + force_events = data.information.forceEvents or "STATUS" + end end end if (trigger.custom_type == "stateupdate") then @@ -3363,11 +3365,11 @@ end -- Cast Latency do - local castLatencyFrame = nil - Private.frames["Cast Latency Handler"] = castLatencyFrame + local castLatencyFrame function WeakAuras.WatchForCastLatency() if not castLatencyFrame then castLatencyFrame = CreateFrame("Frame") + Private.frames["Cast Latency Handler"] = castLatencyFrame castLatencyFrame:RegisterEvent("CURRENT_SPELL_CAST_CHANGED") castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_START") castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 80229d7..5f1038d 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1206,6 +1206,26 @@ function Private.Modernize(data) end end + if data.internalVersion < 54 then + for _, triggerData in ipairs(data.triggers) do + if triggerData.trigger.type == "aura" then + triggerData.trigger.type = "unit" + triggerData.trigger.event = "Conditions" + triggerData.trigger.use_alwaystrue = false + end + end + end + + if data.internalVersion < 55 then + data.forceEvents = true + end + + -- Internal version 55 contained a incorrect Modernize + if data.internalVersion < 56 then + data.information.forceEvents = data.forceEvents + data.forceEvents = nil + end + if data.internalVersion < 67 or data.internalVersion > WeakAuras.InternalVersion() then local castMigrationNeeded = data.internalVersion < 67 data.internalVersion = WeakAuras.InternalVersion() diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index dac8480..56dee65 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -31,7 +31,7 @@ local default = { zoom = 0, keepAspectRatio = false, frameStrata = 1, - cooldown = false, + cooldown = true, cooldownEdge = false }; @@ -393,8 +393,12 @@ local function modify(parent, region, data) end if region.MSQGroup then - region.MSQGroup:RemoveButton(button) - region.MSQGroup:AddButton(button, {Icon = icon, Cooldown = cooldown}, "WA_Aura", true) + if region.MSQGroup.ReSkin then + region.MSQGroup:ReSkin(button) + else + region.MSQGroup:RemoveButton(button) + region.MSQGroup:AddButton(button, {Icon = icon, Cooldown = cooldown}, "WA_Aura", true) + end end local ulx, uly, llx, lly, urx, ury, lrx, lry = GetTexCoord(region, texWidth, aspectRatio) diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 3a1bdc5..400ea76 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -812,6 +812,11 @@ local function ConstructFunction(prototype, trigger, skipOptional) end local ret = {preambles .. "return function("..table.concat(input, ", ")..")\n"}; table.insert(ret, (init or "")); + -- Enable to debug load function inputs + --ret = ret .. "print('INPUTS')" + --for _, i in ipairs(input) do + -- ret = ret .. "print('" .. i .. "'," .. i .. ")" + --end table.insert(ret, (#debug > 0 and table.concat(debug, "\n") or "")); table.insert(ret, "if("); table.insert(ret, ((#required > 0) and table.concat(required, " and ").." and " or "")); diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index e0e01f8..729e5d7 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -41,7 +41,6 @@ Animations.lua Conditions.lua # Trigger systems -BuffTrigger.lua BuffTrigger2.lua GenericTrigger.lua diff --git a/WeakAurasOptions/BuffTrigger.lua b/WeakAurasOptions/BuffTrigger.lua deleted file mode 100644 index e9f0013..0000000 --- a/WeakAurasOptions/BuffTrigger.lua +++ /dev/null @@ -1,887 +0,0 @@ -if not WeakAuras.IsLibsOK() then return end -local AddonName, OptionsPrivate = ... - -local L = WeakAuras.L; - -local function getAuraMatchesLabel(name) - local ids = WeakAuras.spellCache.GetSpellsMatching(name) - if(ids) then - local numMatches = 0; - for _ in pairs(ids) do - numMatches = numMatches + 1; - end - if(numMatches == 1) then - return L["1 Match"]; - else - return L["%i Matches"]:format(numMatches); - end - else - return ""; - end -end - -local function getAuraMatchesList(name) - local ids = WeakAuras.spellCache.GetSpellsMatching(name) - if(ids) then - local descText = ""; - for id in pairs(ids) do - local _, _, icon = GetSpellInfo(id); - if(icon) then - if(descText == "") then - descText = "|T"..icon..":0|t: "..id; - else - descText = descText.."\n|T"..icon..":0|t: "..id; - end - end - end - return descText; - else - return ""; - end -end - -local noop = function() end - -local function CanShowNameInfo(data) - if(data.regionType == "aurabar" or data.regionType == "icon" or data.regionType == "text") then - return true; - else - return false; - end -end - -local function CanShowStackInfo(data) - if(data.regionType == "aurabar" or data.regionType == "icon" or data.regionType == "text") then - return true; - else - return false; - end -end - -local function GetBuffTriggerOptions(data, triggernum) - local trigger = data.triggers[triggernum].trigger - trigger.names = trigger.names or {} - trigger.spellIds = trigger.spellIds or {} - local spellCache = WeakAuras.spellCache; - local ValidateNumeric = WeakAuras.ValidateNumeric; - local aura_options = { - deleteNote = { - type = "description", - order = 8, - name = L["Note: The legacy buff trigger is now permanently disabled. It will be removed in the near future."], - fontSize = "large" - }, - convertToBuffTrigger2SpaceBeforeDesc = { - type = "description", - width = 0.4, - order = 8.1, - name = "", - }, - convertToBuffTrigger2Desc = { - type = "description", - width = WeakAuras.doubleWidth - 0.8, - order = 8.2, - name = function() - if (not OptionsPrivate.Private.CanConvertBuffTrigger2) then - return ""; - end - local _, err = OptionsPrivate.Private.CanConvertBuffTrigger2(trigger); - return err or ""; - end, - }, - convertToBuffTrigger2SpaceAfterDesc = { - type = "description", - width = 0.4, - order = 8.3, - name = "", - }, - convertToBuffTrigger2SpaceBefore = { - type = "description", - width = 0.3, - order = 8.4, - name = "", - }, - convertToBuffTrigger2 = { - type = "execute", - width = WeakAuras.doubleWidth - 0.6, - name = L["Convert to New Aura Trigger"], - order = 8.5, - disabled = function() - if (not OptionsPrivate.Private.CanConvertBuffTrigger2) then - return true; - end - if (not OptionsPrivate.Private.CanConvertBuffTrigger2(trigger)) then - return true; - end - return false; - end, - desc = function() - local _, err = OptionsPrivate.Private.CanConvertBuffTrigger2(trigger); - return err or "" - end, - func = function() - OptionsPrivate.Private.ConvertBuffTrigger2(trigger); - WeakAuras.Add(data); - WeakAuras.UpdateThumbnail(data) - WeakAuras.ClearAndUpdateOptions(data.id); - end - }, - convertToBuffTrigger2SpaceAfter = { - type = "description", - width = 0.3, - order = 8.6, - name = "", - }, - - fullscan = { - type = "toggle", - name = L["Use Full Scan (High CPU)"], - width = WeakAuras.doubleWidth, - order = 9, - set = noop - }, - autoclone = { - type = "toggle", - name = L["Show all matches (Auto-clone)"], - width = WeakAuras.doubleWidth, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end, - order = 9.5, - set = noop - }, - useName = { - type = "toggle", - name = L["Aura(s)"], - width = WeakAuras.halfWidth, - order = 10, - hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end, - disabled = true, - get = function() return true end, - set = noop - }, - use_name = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Aura Name"], - order = 10, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end, - set = noop - }, - name_operator = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Operator"], - order = 11, - disabled = function() return not trigger.use_name end, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end, - values = OptionsPrivate.Private.string_operator_types, - set = noop - }, - name = { - type = "input", - name = L["Aura Name"], - width = WeakAuras.doubleWidth, - order = 12, - disabled = function() return not trigger.use_name end, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end, - set = noop - }, - use_tooltip = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Tooltip"], - order = 13, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end, - set = noop - }, - tooltip_operator = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Operator"], - order = 14, - disabled = function() return not trigger.use_tooltip end, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end, - values = OptionsPrivate.Private.string_operator_types, - set = noop - }, - tooltip = { - type = "input", - width = WeakAuras.doubleWidth, - name = L["Tooltip"], - order = 15, - disabled = function() return not trigger.use_tooltip end, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end, - set = noop - }, - use_stealable = { - type = "toggle", - width = WeakAuras.doubleWidth, - name = function(input) - local value = trigger.use_stealable; - if(value == nil) then return L["Stealable"]; - elseif(value == false) then return "|cFFFF0000 "..L["Negator"].." "..L["Stealable"]; - else return "|cFF00FF00"..L["Stealable"]; end - end, - order = 16, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end, - get = function() - local value = trigger.use_stealable; - if(value == nil) then return false; - elseif(value == false) then return "false"; - else return "true"; end - end, - set = noop - }, - use_spellId = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Spell ID"], - order = 17, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end, - set = noop - }, - spellId = { - type = "input", - width = WeakAuras.normalWidth, - name = L["Spell ID"], - order = 18, - disabled = function() return not trigger.use_spellId end, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end, - set = noop - }, - use_debuffClass = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Debuff Type"], - order = 19, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end, - set = noop - }, - debuffClass = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Debuff Type"], - order = 20, - disabled = function() return not trigger.use_debuffClass end, - hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end, - values = OptionsPrivate.Private.debuff_class_types, - set = noop - }, - multiuse_name = { - type = "toggle", - width = WeakAuras.halfWidth, - name = L["Aura Name"], - order = 10, - hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit == "multi"); end, - disabled = true, - get = function() return true end, - set = noop - }, - multiicon = { - type = "execute", - width = WeakAuras.halfWidth, - name = "", - image = function() - if (not trigger.name) then return "" end; - local icon = spellCache.GetIcon(trigger.name); - return icon and tostring(icon) or "", 18, 18 end, - order = 11, - disabled = function() return not trigger.name and spellCache.GetIcon(trigger.name) end, - hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit == "multi"); end, - set = noop - }, - multiname = { - type = "input", - width = WeakAuras.normalWidth, - name = L["Aura Name"], - desc = L["Enter an aura name, partial aura name, or spell id"], - order = 12, - hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit == "multi"); end, - get = function(info) return trigger.spellId and tostring(trigger.spellId) or trigger.name end, - set = noop - }, - name1icon = { - type = "execute", - width = WeakAuras.halfWidth, - name = function() return getAuraMatchesLabel(trigger.names[1]) end, - desc = function() return getAuraMatchesList(trigger.names[1]) end, - image = function() - local icon = spellCache.GetIcon(trigger.names[1]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 11, - disabled = function() return not spellCache.GetIcon(trigger.names[1]) end, - hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end, - set = noop - }, - name1 = { - type = "input", - width = WeakAuras.normalWidth, - name = L["Aura Name"], - desc = L["Enter an aura name, partial aura name, or spell id"], - order = 12, - hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[1] and tostring(trigger.spellIds[1]) or trigger.names[1] end, - set = noop - }, - name2space = { - type = "execute", - width = WeakAuras.halfWidth, - name = L["or"], - image = function() return "", 0, 0 end, - order = 13, - hidden = function() return not (trigger.type == "aura" and trigger.names[1] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name2icon = { - type = "execute", - width = WeakAuras.halfWidth, - name = function() return getAuraMatchesLabel(trigger.names[2]) end, - desc = function() return getAuraMatchesList(trigger.names[2]) end, - image = function() - local icon = spellCache.GetIcon(trigger.names[2]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 14, - disabled = function() return not spellCache.GetIcon(trigger.names[2]) end, - hidden = function() return not (trigger.type == "aura" and trigger.names[1] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name2 = { - type = "input", - width = WeakAuras.normalWidth, - order = 15, - name = "", - hidden = function() return not (trigger.type == "aura" and trigger.names[1] and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[2] and tostring(trigger.spellIds[2]) or trigger.names[2] end, - set = noop - }, - name3space = { - type = "execute", - width = WeakAuras.halfWidth, - name = "", - image = function() return "", 0, 0 end, - order = 16, - hidden = function() return not (trigger.type == "aura" and trigger.names[2] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name3icon = { - type = "execute", - width = WeakAuras.halfWidth, - name = function() return getAuraMatchesLabel(trigger.names[3]) end, - desc = function() return getAuraMatchesList(trigger.names[3]) end, - image = function() - local icon = spellCache.GetIcon(trigger.names[3]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 17, - disabled = function() return not spellCache.GetIcon(trigger.names[3]) end, - hidden = function() return not (trigger.type == "aura" and trigger.names[2] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name3 = { - type = "input", - width = WeakAuras.normalWidth, - order = 18, - name = "", - hidden = function() return not (trigger.type == "aura" and trigger.names[2] and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[3] and tostring(trigger.spellIds[3]) or trigger.names[3] end, - set = noop - }, - name4space = { - type = "execute", - width = WeakAuras.halfWidth, - name = "", - image = function() return "", 0, 0 end, - order = 19, - hidden = function() return not (trigger.type == "aura" and trigger.names[3] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name4icon = { - type = "execute", - width = WeakAuras.halfWidth, - name = function() return getAuraMatchesLabel(trigger.names[4]) end, - desc = function() return getAuraMatchesList(trigger.names[4]) end, - image = function() - local icon = spellCache.GetIcon(trigger.names[4]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 20, - disabled = function() return not spellCache.GetIcon(trigger.names[4]) end, - hidden = function() return not (trigger.type == "aura" and trigger.names[3] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name4 = { - type = "input", - order = 21, - name = "", - hidden = function() return not (trigger.type == "aura" and trigger.names[3] and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[4] and tostring(trigger.spellIds[4]) or trigger.names[4] end, - set = noop - }, - name5space = { - type = "execute", - width = WeakAuras.halfWidth, - name = "", - image = function() return "", 0, 0 end, - order = 22, - disabled = function() return not spellCache.GetIcon(trigger.names[5]) end, - hidden = function() return not (trigger.type == "aura" and trigger.names[4] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name5icon = { - type = "execute", - width = WeakAuras.halfWidth, - name = function() return getAuraMatchesLabel(trigger.names[5]) end, - desc = function() return getAuraMatchesList(trigger.names[5]) end, - image = function() - local icon = spellCache.GetIcon(trigger.names[5]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 23, - hidden = function() return not (trigger.type == "aura" and trigger.names[4] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name5 = { - type = "input", - width = WeakAuras.normalWidth, - order = 24, - name = "", - hidden = function() return not (trigger.type == "aura" and trigger.names[4] and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[5] and tostring(trigger.spellIds[5]) or trigger.names[5] end, - set = noop - }, - name6space = { - type = "execute", - name = "", - width = WeakAuras.halfWidth, - image = function() return "", 0, 0 end, - order = 25, - hidden = function() return not (trigger.type == "aura" and trigger.names[5] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name6icon = { - type = "execute", - name = function() return getAuraMatchesLabel(trigger.names[6]) end, - desc = function() return getAuraMatchesList(trigger.names[6]) end, - width = WeakAuras.halfWidth, - image = function() - local icon = spellCache.GetIcon(trigger.names[6]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 26, - disabled = function() return not spellCache.GetIcon(trigger.names[6]) end, - hidden = function() return not (trigger.type == "aura" and trigger.names[5] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name6 = { - type = "input", - width = WeakAuras.normalWidth, - order = 27, - name = "", - hidden = function() return not (trigger.type == "aura" and trigger.names[5] and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[6] and tostring(trigger.spellIds[6]) or trigger.names[6] end, - set = noop - }, - name7space = { - type = "execute", - name = "", - width = WeakAuras.halfWidth, - image = function() return "", 0, 0 end, - order = 28, - hidden = function() return not (trigger.type == "aura" and trigger.names[6] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name7icon = { - type = "execute", - name = function() return getAuraMatchesLabel(trigger.names[7]) end, - desc = function() return getAuraMatchesList(trigger.names[7]) end, - width = WeakAuras.halfWidth, - image = function() - local icon = spellCache.GetIcon(trigger.names[7]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 29, - disabled = function() return not spellCache.GetIcon(trigger.names[7]) end, - hidden = function() return not (trigger.type == "aura" and trigger.names[6] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name7 = { - type = "input", - width = WeakAuras.normalWidth, - order = 30, - name = "", - hidden = function() return not (trigger.type == "aura" and trigger.names[6] and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[7] and tostring(trigger.spellIds[7]) or trigger.names[7] end, - set = noop - }, - name8space = { - type = "execute", - name = "", - width = WeakAuras.halfWidth, - image = function() return "", 0, 0 end, - order = 31, - hidden = function() return not (trigger.type == "aura" and trigger.names[7] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name8icon = { - type = "execute", - name = function() return getAuraMatchesLabel(trigger.names[8]) end, - desc = function() return getAuraMatchesList(trigger.names[8]) end, - width = WeakAuras.halfWidth, - image = function() - local icon = spellCache.GetIcon(trigger.names[8]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 32, - disabled = function() return not spellCache.GetIcon(trigger.names[8]) end, - hidden = function() return not (trigger.type == "aura" and trigger.names[7] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name8 = { - type = "input", - width = WeakAuras.normalWidth, - order = 33, - name = "", - hidden = function() return not (trigger.type == "aura" and trigger.names[7] and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[8] and tostring(trigger.spellIds[8]) or trigger.names[8] end, - set = noop - }, - name9space = { - type = "execute", - name = "", - width = WeakAuras.halfWidth, - image = function() return "", 0, 0 end, - order = 34, - hidden = function() return not (trigger.type == "aura" and trigger.names[8] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name9icon = { - type = "execute", - name = function() return getAuraMatchesLabel(trigger.names[9]) end, - desc = function() return getAuraMatchesList(trigger.names[9]) end, - width = WeakAuras.halfWidth, - image = function() - local icon = spellCache.GetIcon(trigger.names[9]); - return icon and tostring(icon) or "", 18, 18 - end, - order = 35, - disabled = function() return not spellCache.GetIcon(trigger.names[9]) end, - hidden = function() return not (trigger.type == "aura" and trigger.names[8] and not trigger.fullscan and trigger.unit ~= "multi"); end, - }, - name9 = { - type = "input", - width = WeakAuras.normalWidth, - order = 36, - name = "", - hidden = function() return not (trigger.type == "aura" and trigger.names[8] and not trigger.fullscan and trigger.unit ~= "multi"); end, - get = function(info) return trigger.spellIds[9] and tostring(trigger.spellIds[9]) or trigger.names[9] end, - set = noop - }, - useUnit = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Unit"], - order = 40, - disabled = true, - hidden = function() return not (trigger.type == "aura"); end, - get = function() return true end, - set = noop - }, - unit = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Unit"], - order = 41, - values = function() - if(trigger.fullscan) then - return OptionsPrivate.Private.actual_unit_types_with_specific; - else - return OptionsPrivate.Private.unit_types; - end - end, - hidden = function() return not (trigger.type == "aura"); end, - get = function() - if(trigger.fullscan and (trigger.unit == "group" or trigger.unit == "multi")) then - trigger.unit = "player"; - end - return trigger.unit; - end, - set = noop - }, - useSpecificUnit = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Specific Unit"], - order = 42, - disabled = true, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "member") end, - get = function() return true end, - set = noop - }, - specificUnit = { - type = "input", - width = WeakAuras.normalWidth, - name = L["Specific Unit"], - order = 43, - desc = L["Can be a Name or a Unit ID (e.g. party1). A name only works on friendly players in your group."], - hidden = function() return not (trigger.type == "aura" and trigger.unit == "member") end, - set = noop - }, - useGroup_count = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Group Member Count"], - disabled = true, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end, - get = function() return true; end, - order = 45, - set = noop - }, - group_countOperator = { - type = "select", - name = L["Operator"], - order = 46, - width = WeakAuras.halfWidth, - values = OptionsPrivate.Private.operator_types, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end, - get = function() return trigger.group_countOperator; end, - set = noop - }, - group_count = { - type = "input", - name = L["Count"], - desc = function() - local groupType = OptionsPrivate.Private.unit_types[trigger.unit or "group"] or "|cFFFF0000error|r"; - return L["Group aura count description"]:format(groupType, groupType, groupType, groupType, groupType, groupType, groupType); - end, - order = 47, - width = WeakAuras.halfWidth, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end, - get = function() return trigger.group_count; end, - set = noop - }, - ignoreSelf = { - type = "toggle", - name = L["Ignore self"], - order = 47.3, - width = WeakAuras.doubleWidth, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end, - set = noop - }, - groupclone = { - type = "toggle", - name = L["Show all matches (Auto-clone)"], - width = WeakAuras.doubleWidth, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end, - order = 47.4, - set = noop - }, - name_info = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Name Info"], - order = 47.5, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "group" and not trigger.groupclone); end, - disabled = function() return not CanShowNameInfo(data); end, - get = function() - if(CanShowNameInfo(data)) then - return trigger.name_info; - else - return nil; - end - end, - values = OptionsPrivate.Private.group_aura_name_info_types, - set = noop - }, - stack_info = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Stack Info"], - order = 47.6, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "group" and not trigger.groupclone); end, - disabled = function() return not CanShowStackInfo(data); end, - get = function() - if(CanShowStackInfo(data)) then - return trigger.stack_info; - else - return nil; - end - end, - values = OptionsPrivate.Private.group_aura_stack_info_types, - set = noop - }, - hideAlone = { - type = "toggle", - name = L["Hide When Not In Group"], - order = 47.7, - width = WeakAuras.doubleWidth, - hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end, - set = noop - }, - useDebuffType = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Aura Type"], - order = 50, - disabled = true, - hidden = function() return not (trigger.type == "aura"); end, - get = function() return true end, - set = noop - }, - debuffType = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Aura Type"], - order = 51, - values = OptionsPrivate.Private.debuff_types, - hidden = function() return not (trigger.type == "aura"); end, - set = noop - }, - subcount = { - type = "toggle", - width = WeakAuras.doubleWidth, - name = L["Use tooltip \"size\" instead of stacks"], - hidden = function() return not (trigger.type == "aura" and trigger.fullscan) end, - order = 55, - set = noop - }, - subcountCount = { - type = "select", - values = OptionsPrivate.Private.tooltip_count, - width = WeakAuras.doubleWidth, - name = L["Use nth value from tooltip:"], - hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.subcount) end, - order = 55.5, - set = noop - }, - useRem = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Remaining Time"], - hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end, - order = 56, - set = noop - }, - remOperator = { - type = "select", - name = L["Operator"], - order = 57, - width = WeakAuras.halfWidth, - values = OptionsPrivate.Private.operator_types, - disabled = function() return not trigger.useRem; end, - hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end, - get = function() return trigger.useRem and trigger.remOperator or nil end, - set = noop - }, - rem = { - type = "input", - name = L["Remaining Time"], - validate = ValidateNumeric, - order = 58, - width = WeakAuras.halfWidth, - disabled = function() return not trigger.useRem; end, - hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end, - get = function() return trigger.useRem and trigger.rem or nil end, - set = noop - }, - useCount = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Stack Count"], - hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end, - order = 60, - set = noop - }, - countOperator = { - type = "select", - name = L["Operator"], - order = 62, - width = WeakAuras.halfWidth, - values = OptionsPrivate.Private.operator_types, - disabled = function() return not trigger.useCount; end, - hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end, - get = function() return trigger.useCount and trigger.countOperator or nil end, - set = noop - }, - count = { - type = "input", - name = L["Stack Count"], - validate = ValidateNumeric, - order = 65, - width = WeakAuras.halfWidth, - disabled = function() return not trigger.useCount; end, - hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end, - get = function() return trigger.useCount and trigger.count or nil end, - set = noop - }, - ownOnly = { - type = "toggle", - width = WeakAuras.doubleWidth, - name = function() - local value = trigger.ownOnly; - if(value == nil) then return L["Own Only"]; - elseif(value == false) then return "|cFFFF0000 "..L["Negator"].." "..L["Own Only"]; - else return "|cFF00FF00"..L["Own Only"]; end - end, - desc = function() - local value = trigger.ownOnly; - if(value == nil) then return L["Only match auras cast by the player"]; - elseif(value == false) then return L["Only match auras cast by people other than the player"]; - else return L["Only match auras cast by the player"]; end - end, - get = function() - local value = trigger.ownOnly; - if(value == nil) then return false; - elseif(value == false) then return "false"; - else return "true"; end - end, - order = 70, - hidden = function() return not (trigger.type == "aura"); end, - set = noop - }, - useBuffShowOn = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Show On"], - order = 71, - disabled = true, - hidden = function() - return not (trigger.type == "aura" and not(trigger.unit ~= "group" and trigger.fullscan and trigger.autoclone) and trigger.unit ~= "multi" and not(trigger.unit == "group" and not trigger.groupclone)); - end, - get = function() return true end, - set = noop - }, - buffShowOn = { - type = "select", - width = WeakAuras.normalWidth, - name = "", - values = OptionsPrivate.Private.bufftrigger_progress_behavior_types, - order = 71.1, - get = function() return trigger.buffShowOn end, - hidden = function() - return not (trigger.type == "aura" and not(trigger.unit ~= "group" and trigger.fullscan and trigger.autoclone) and trigger.unit ~= "multi" and not(trigger.unit == "group" and not trigger.groupclone)); - end, - set = noop - }, - unitExists = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Show If Unit Is Invalid"], - order = 72, - hidden = function() - return not (trigger.type == "aura" - and not(trigger.unit ~= "group" and trigger.fullscan and trigger.autoclone) - and trigger.unit ~= "multi" - and trigger.unit ~= "group" - and trigger.unit ~= "player"); - end, - set = noop - }, - linespacer = { - type = "description", - order = 73, - width = WeakAuras.doubleWidth, - name = "", - hidden = function() - -- For those that update without restarting - return not OptionsPrivate.Private.CanConvertBuffTrigger2 - end, - }, - - }; - - OptionsPrivate.commonOptions.AddCommonTriggerOptions(aura_options, data, triggernum, true) - OptionsPrivate.commonOptions.AddTriggerGetterSetter(aura_options, data, triggernum) - OptionsPrivate.AddTriggerMetaFunctions(aura_options, data, triggernum) - - return { - ["trigger." .. triggernum .. ".legacy_aura_options"] = aura_options - } -end - -WeakAuras.RegisterTriggerSystemOptions({"aura"}, GetBuffTriggerOptions); diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index 15be76a..8f8ff5b 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -4,7 +4,7 @@ local AddonName, OptionsPrivate = ... local L = WeakAuras.L function OptionsPrivate.GetInformationOptions(data) - local isGroup = data.controlledChildren + local isGroup = data.controlledChildren and true or false local isTmpGroup = type(data.id) == "table" local options = { @@ -159,7 +159,10 @@ function OptionsPrivate.GetInformationOptions(data) local properties = { ignoreOptionsEventErrors = { - name = L["Ignore Lua Errors on OPTIONS event"], + name = L["Custom Trigger: Ignore Lua Errors on OPTIONS event"], + }, + forceEvents = { + name = L["Custom Trigger: Send fake events instead of STATUS event"] }, groupOffset = { name = L["Offset by 1px"], @@ -170,6 +173,7 @@ function OptionsPrivate.GetInformationOptions(data) local same = { ignoreOptionsEventErrors = true, + forceEvents = true, groupOffset = true } diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index fb47c2e..a5f0431 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -47,7 +47,6 @@ ActionOptions.lua AnimationOptions.lua InformationOptions.lua -BuffTrigger.lua BuffTrigger2.lua GenericTrigger.lua From ae98edecb23cfdac5c51fd3f8d473b9d5ebcca7a Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 9 Jan 2025 16:17:05 +0100 Subject: [PATCH 013/153] from retail --- WeakAuras/Modernize.lua | 200 +++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 105 deletions(-) diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 5f1038d..7eab34a 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -4,40 +4,40 @@ local L = WeakAuras.L -- Takes as input a table of display data and attempts to update it to be compatible with the current version function Private.Modernize(data) - if (not data.internalVersion or data.internalVersion < 2) then + if not data.internalVersion or data.internalVersion < 2 then WeakAuras.prettyPrint(string.format("Data for '%s' is too old, can't modernize.", data.id)) - data.internalVersion = 2; + data.internalVersion = 2 end -- Version 3 was introduced April 2018 in Legion - if (data.internalVersion < 3) then - if (data.parent) then - local parentData = WeakAuras.GetData(data.parent); - if(parentData and parentData.regionType == "dynamicgroup") then + if data.internalVersion < 3 then + if data.parent then + local parentData = WeakAuras.GetData(data.parent) + if parentData and parentData.regionType == "dynamicgroup" then -- Version 3 allowed for offsets for dynamic groups, before that they were ignored -- Thus reset them in the V2 to V3 upgrade - data.xOffset = 0; - data.yOffset = 0; + data.xOffset = 0 + data.yOffset = 0 end end end -- Version 4 was introduced July 2018 in BfA - if (data.internalVersion < 4) then - if (data.conditions) then + if data.internalVersion < 4 then + if data.conditions then for conditionIndex, condition in ipairs(data.conditions) do - if (condition.check) then + if condition.check then local triggernum = condition.check.trigger; - if (triggernum) then - local trigger; - if (triggernum == 0) then - trigger = data.trigger; - elseif(data.additional_triggers and data.additional_triggers[triggernum]) then - trigger = data.additional_triggers[triggernum].trigger; + if triggernum then + local trigger + if triggernum == 0 then + trigger = data.trigger + elseif data.additional_triggers and data.additional_triggers[triggernum] then + trigger = data.additional_triggers[triggernum].trigger end - if (trigger and trigger.event == "Cooldown Progress (Spell)") then - if (condition.check.variable == "stacks") then - condition.check.variable = "charges"; + if trigger and trigger.event == "Cooldown Progress (Spell)" then + if condition.check.variable == "stacks" then + condition.check.variable = "charges" end end end @@ -67,7 +67,7 @@ function Private.Modernize(data) if data.internalVersion < 6 then if data.triggers then for triggernum, triggerData in ipairs(data.triggers) do - local trigger = triggerData.trigger; + local trigger = triggerData.trigger if trigger and trigger.type == "aura" then if trigger.showOn == "showOnMissing" then trigger.buffShowOn = "showOnMissing" @@ -88,9 +88,7 @@ function Private.Modernize(data) -- Version 7 was introduced September 1 2018 in BfA -- Triggers were cleaned up into a 1-indexed array - if data.internalVersion < 7 then - -- migrate trigger data data.triggers = data.additional_triggers or {} tinsert(data.triggers, 1, { @@ -113,7 +111,9 @@ function Private.Modernize(data) data.disjunctive = nil -- migrate condition trigger references local function recurseRepairChecks(checks) - if not checks then return end + if not checks then + return + end for _, check in pairs(checks) do if check.trigger and check.trigger >= 0 then check.trigger = check.trigger + 1 @@ -137,11 +137,11 @@ function Private.Modernize(data) local function repairCheck(check) if check and check.variable == "buffed" then local trigger = check.trigger and data.triggers[check.trigger] and data.triggers[check.trigger].trigger; - if (trigger) then - if(trigger.buffShowOn == "showOnActive") then - check.variable = "show"; - elseif (trigger.buffShowOn == "showOnMissing") then - check.variable = "show"; + if trigger then + if trigger.buffShowOn == "showOnActive" then + check.variable = "show" + elseif trigger.buffShowOn == "showOnMissing" then + check.variable = "show" check.value = check.value == 0 and 1 or 0; end end @@ -149,15 +149,17 @@ function Private.Modernize(data) end local function recurseRepairChecks(checks) - if not checks then return end + if not checks then + return + end for _, check in pairs(checks) do - repairCheck(check); - recurseRepairChecks(check.checks); + repairCheck(check) + recurseRepairChecks(check.checks) end end for _, condition in pairs(data.conditions) do - repairCheck(condition.check); - recurseRepairChecks(condition.check.checks); + repairCheck(condition.check) + recurseRepairChecks(condition.check.checks) end end @@ -182,7 +184,7 @@ function Private.Modernize(data) local selfPoints = { default = "CENTER", RIGHT = function(data) - if data.align == "LEFT" then + if data.align == "LEFT" then return "TOPLEFT" elseif data.align == "RIGHT" then return "BOTTOMLEFT" @@ -191,7 +193,7 @@ function Private.Modernize(data) end end, LEFT = function(data) - if data.align == "LEFT" then + if data.align == "LEFT" then return "TOPRIGHT" elseif data.align == "RIGHT" then return "BOTTOMRIGHT" @@ -250,11 +252,12 @@ function Private.Modernize(data) if data.internalVersion < 14 then if data.triggers then for triggerId, triggerData in pairs(data.triggers) do - if type(triggerData) == "table" - and triggerData.trigger - and triggerData.trigger.debuffClass - and type(triggerData.trigger.debuffClass) == "string" - and triggerData.trigger.debuffClass ~= "" + if + type(triggerData) == "table" + and triggerData.trigger + and triggerData.trigger.debuffClass + and type(triggerData.trigger.debuffClass) == "string" + and triggerData.trigger.debuffClass ~= "" then local idx = triggerData.trigger.debuffClass data.triggers[triggerId].trigger.debuffClass = { [idx] = true } @@ -324,7 +327,7 @@ function Private.Modernize(data) text_anchorPoint = convertPoint(data.text1Containment, data.text1Point), anchorXOffset = 0, anchorYOffset = 0, - text_shadowColor = { 0, 0, 0, 1}, + text_shadowColor = { 0, 0, 0, 1 }, text_shadowXOffset = 0, text_shadowYOffset = 0, } @@ -343,7 +346,7 @@ function Private.Modernize(data) text_anchorPoint = convertPoint(data.text2Containment, data.text2Point), anchorXOffset = 0, anchorYOffset = 0, - text_shadowColor = { 0, 0, 0, 1}, + text_shadowColor = { 0, 0, 0, 1 }, text_shadowXOffset = 0, text_shadowYOffset = 0, } @@ -370,16 +373,16 @@ function Private.Modernize(data) text1Color = "sub.1.text_color", text1FontSize = "sub.1.text_fontSize", text2Color = "sub.2.text_color", - text2FontSize = "sub.2.text_fontSize" + text2FontSize = "sub.2.text_fontSize", } data.subRegions = data.subRegions or {} tinsert(data.subRegions, text1) - if (usetext2) then + if usetext2 then tinsert(data.subRegions, text2) end - if (data.conditions) then + if data.conditions then for conditionIndex, condition in ipairs(data.conditions) do for changeIndex, change in ipairs(condition.changes) do if propertyRenames[change.property] then @@ -398,7 +401,7 @@ function Private.Modernize(data) HORIZONTAL_INVERSE = { "INNER_LEFT", "INNER_RIGHT" }, HORIZONTAL = { "INNER_RIGHT", "INNER_LEFT" }, VERTICAL_INVERSE = { "INNER_BOTTOM", "INNER_TOP" }, - VERTICAL = {"INNER_TOP", "INNER_BOTTOM"} + VERTICAL = { "INNER_TOP", "INNER_BOTTOM" }, } local positions = orientationToPostion[data.orientation] or { "INNER_LEFT", "INNER_RIGHT" } @@ -415,10 +418,10 @@ function Private.Modernize(data) text_anchorPoint = positions[1], anchorXOffset = 0, anchorYOffset = 0, - text_shadowColor = { 0, 0, 0, 1}, + text_shadowColor = { 0, 0, 0, 1 }, text_shadowXOffset = 1, text_shadowYOffset = -1, - rotateText = data.rotateText + rotateText = data.rotateText, } local text2 = { @@ -433,10 +436,10 @@ function Private.Modernize(data) text_anchorPoint = positions[2], anchorXOffset = 0, anchorYOffset = 0, - text_shadowColor = { 0, 0, 0, 1}, + text_shadowColor = { 0, 0, 0, 1} , text_shadowXOffset = 1, text_shadowYOffset = -1, - rotateText = data.rotateText + rotateText = data.rotateText, } local text3 = { @@ -451,10 +454,10 @@ function Private.Modernize(data) text_anchorPoint = "ICON_CENTER", anchorXOffset = 0, anchorYOffset = 0, - text_shadowColor = { 0, 0, 0, 1}, + text_shadowColor = { 0, 0, 0, 1 }, text_shadowXOffset = 1, text_shadowYOffset = -1, - rotateText = data.rotateText + rotateText = data.rotateText, } data.timer = nil @@ -490,7 +493,7 @@ function Private.Modernize(data) tinsert(data.subRegions, text2) tinsert(data.subRegions, text3) - if (data.conditions) then + if data.conditions then for conditionIndex, condition in ipairs(data.conditions) do for changeIndex, change in ipairs(condition.changes) do if propertyRenames[change.property] then @@ -499,7 +502,6 @@ function Private.Modernize(data) end end end - end end @@ -541,10 +543,10 @@ function Private.Modernize(data) end local propertyRenames = { - borderColor = "sub.".. #data.subRegions..".border_color", + borderColor = "sub." .. #data.subRegions .. ".border_color", } - if (data.conditions) then + if data.conditions then for conditionIndex, condition in ipairs(data.conditions) do for changeIndex, change in ipairs(condition.changes) do if propertyRenames[change.property] then @@ -568,7 +570,7 @@ function Private.Modernize(data) if value then trigger.form = { multi = { [value] = true } } else - trigger.form = { multi = { } } + trigger.form = { multi = {} } end elseif trigger.use_form then trigger.form = { single = value } @@ -604,7 +606,7 @@ function Private.Modernize(data) data.subRegions = data.subRegions or {} -- Need to check if glow is needed - local prefix = "sub.".. #data.subRegions + 1 .. "." + local prefix = "sub." .. #data.subRegions + 1 .. "." -- For Conditions local propertyRenames = { glow = prefix .. "glow", @@ -622,7 +624,7 @@ function Private.Modernize(data) } local needsGlow = data.glow - if (not needsGlow and data.conditions) then + if not needsGlow and data.conditions then for conditionIndex, condition in ipairs(data.conditions) do for changeIndex, change in ipairs(condition.changes) do if propertyRenames[change.property] then @@ -666,7 +668,7 @@ function Private.Modernize(data) data.glowXOffset = nil data.glowYOffset = nil - if (data.conditions) then + if data.conditions then for conditionIndex, condition in ipairs(data.conditions) do for changeIndex, change in ipairs(condition.changes) do if propertyRenames[change.property] then @@ -704,16 +706,10 @@ function Private.Modernize(data) if data.internalVersion < 29 then if data.actions then - if data.actions.start - and data.actions.start.do_glow - and data.actions.start.glow_type == nil - then + if data.actions.start and data.actions.start.do_glow and data.actions.start.glow_type == nil then data.actions.start.glow_type = "buttonOverlay" end - if data.actions.finish - and data.actions.finish.do_glow - and data.actions.finish.glow_type == nil - then + if data.actions.finish and data.actions.finish.do_glow and data.actions.finish.glow_type == nil then data.actions.finish.glow_type = "buttonOverlay" end end @@ -741,8 +737,8 @@ function Private.Modernize(data) sym = sym or symbol if sym == "p" or sym == "t" then data["displayText_format_" .. symbol .. "_format"] = "timed" - data["displayText_format_" .. symbol .. "_time_precision"], data["displayText_format_" .. symbol .. "_time_dynamic"] - = convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision) + data["displayText_format_" .. symbol .. "_time_precision"], data["displayText_format_" .. symbol .. "_time_dynamic"] = + convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision) end end seenSymbols[symbol] = symbol @@ -759,8 +755,8 @@ function Private.Modernize(data) sym = sym or symbol if sym == "p" or sym == "t" then subRegionData["text_text_format_" .. symbol .. "_format"] = "timed" - subRegionData["text_text_format_" .. symbol .. "_time_precision"], subRegionData["text_text_format_" .. symbol .. "_time_dynamic"] - = convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision) + subRegionData["text_text_format_" .. symbol .. "_time_precision"], subRegionData["text_text_format_" .. symbol .. "_time_dynamic"] = + convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision) end end seenSymbols[symbol] = symbol @@ -770,7 +766,7 @@ function Private.Modernize(data) end if data.actions then - for _, when in ipairs{ "start", "finish" } do + for _, when in ipairs({ "start", "finish" }) do if data.actions[when] then local seenSymbols = {} Private.ParseTextStr(data.actions[when].message, function(symbol) @@ -779,8 +775,8 @@ function Private.Modernize(data) sym = sym or symbol if sym == "p" or sym == "t" then data.actions[when]["message_format_" .. symbol .. "_format"] = "timed" - data.actions[when]["message_format_" .. symbol .. "_time_precision"], data.actions[when]["message_format_" .. symbol .. "_time_dynamic"] - = convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision) + data.actions[when]["message_format_" .. symbol .. "_time_precision"], data.actions[when]["message_format_" .. symbol .. "_time_dynamic"] = + convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision) end end seenSymbols[symbol] = symbol @@ -800,8 +796,8 @@ function Private.Modernize(data) sym = sym or symbol if sym == "p" or sym == "t" then change.value["message_format_" .. symbol .. "_format"] = "timed" - change.value["message_format_" .. symbol .. "_time_precision"], change.value["message_format_" .. symbol .. "_time_dynamic"] - = convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision) + change.value["message_format_" .. symbol .. "_time_precision"], change.value["message_format_" .. symbol .. "_time_dynamic"] = + convertLegacyPrecision(sym == "p" and progressPrecision or totalPrecision) end end seenSymbols[symbol] = symbol @@ -886,15 +882,17 @@ function Private.Modernize(data) end local function recurseRepairChecks(replacements, checks) - if not checks then return end + if not checks then + return + end for _, check in pairs(checks) do - repairCheck(replacements, check); - recurseRepairChecks(replacements, check.checks); + repairCheck(replacements, check) + recurseRepairChecks(replacements, check.checks) end end for _, condition in pairs(data.conditions) do - repairCheck(replacements, condition.check); - recurseRepairChecks(replacements, condition.check.checks); + repairCheck(replacements, condition.check) + recurseRepairChecks(replacements, condition.check.checks) end end end @@ -923,13 +921,11 @@ function Private.Modernize(data) triggerData.trigger.blackauraspellids = nil end end - end -- Introduced in July 2020 in Shadowlands if data.internalVersion < 34 then - if data.regionType == 'dynamicgroup' - and (data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") then + if data.regionType == "dynamicgroup" and (data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") then if data.arcLength == 360 then data.fullCircle = true else @@ -943,7 +939,7 @@ function Private.Modernize(data) end if data.internalVersion < 39 then - if data.regionType == 'icon' or data.regionType == 'aurabar' then + if data.regionType == "icon" or data.regionType == "aurabar" then if data.auto then data.iconSource = -1 else @@ -954,7 +950,7 @@ function Private.Modernize(data) if data.internalVersion < 40 then data.information = data.information or {} - if data.regionType == 'group' then + if data.regionType == "group" then data.information.groupOffset = true end data.information.ignoreOptionsEventErrors = data.ignoreOptionsEventErrors @@ -1067,7 +1063,7 @@ function Private.Modernize(data) end if data.actions then - for _, when in ipairs{ "start", "finish" } do + for _, when in ipairs({ "start", "finish" }) do if data.actions[when] then fixUp(data.actions[when], "message_format_") end @@ -1085,7 +1081,7 @@ function Private.Modernize(data) end end - if (data.internalVersion < 49) then + if data.internalVersion < 49 then if not data.regionType:match("group") then data.subRegions = data.subRegions or {} -- rename aurabar_bar into subforeground, and subbarmodel into submodel @@ -1113,9 +1109,9 @@ function Private.Modernize(data) local prefix, property = change.property:match("(sub%.%d+%.)(.*)") if prefix and property then if property == "bar_model_visible" then - change.property = prefix.."model_visible" + change.property = prefix .. "model_visible" elseif property == "bar_model_alpha" then - change.property = prefix.."model_alpha" + change.property = prefix .. "model_alpha" end end end @@ -1126,7 +1122,7 @@ function Private.Modernize(data) end end - if (data.internalVersion == 49) then + if data.internalVersion == 49 then -- Version 49 was a dud and contained a broken validation. Try to salvage the data, as -- best as we can. local broken = false @@ -1142,7 +1138,7 @@ function Private.Modernize(data) local subRegionIndex, property = change.property:match("^sub%.(%d+)%.(.*)") if subRegionIndex and property then broken = true - for _, offset in ipairs({-1, 1}) do + for _, offset in ipairs({ -1, 1 }) do local newProperty = "sub." .. subRegionIndex + offset .. "." .. property if properties[newProperty] then change.property = newProperty @@ -1160,7 +1156,7 @@ function Private.Modernize(data) end end - if (data.internalVersion < 51) then + if data.internalVersion < 51 then for _, triggerData in ipairs(data.triggers) do if triggerData.trigger.event == "Threat Situation" then triggerData.trigger.unit = triggerData.trigger.threatUnit @@ -1171,7 +1167,7 @@ function Private.Modernize(data) end end - if (data.internalVersion < 52) then + if data.internalVersion < 52 then local function matchTarget(input) return input == "target" or input == "'target'" or input == "\"target\"" or input == "%t" or input == "'%t'" or input == "\"%t\"" end @@ -1189,18 +1185,12 @@ function Private.Modernize(data) end end - if data.actions.start.do_message - and data.actions.start.message_type == "WHISPER" - and matchTarget(data.actions.start.message_dest) - then + if data.actions.start.do_message and data.actions.start.message_type == "WHISPER" and matchTarget(data.actions.start.message_dest) then data.actions.start.message_dest = "target" data.actions.start.message_dest_isunit = true end - if data.actions.finish.do_message - and data.actions.finish.message_type == "WHISPER" - and matchTarget(data.actions.finish.message_dest) - then + if data.actions.finish.do_message and data.actions.finish.message_type == "WHISPER" and matchTarget(data.actions.finish.message_dest) then data.actions.finish.message_dest = "target" data.actions.finish.message_dest_isunit = true end @@ -1404,5 +1394,5 @@ function Private.Modernize(data) end end - data.internalVersion = max(data.internalVersion or 0, WeakAuras.InternalVersion()); + data.internalVersion = max(data.internalVersion or 0, WeakAuras.InternalVersion()) end From 55709443ae63ee447e3778a0c0fdbc87083c71c1 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 9 Jan 2025 16:30:14 +0100 Subject: [PATCH 014/153] from retail --- WeakAuras/AuraEnvironment.lua | 4 ++-- WeakAuras/BuffTrigger2.lua | 4 ++-- WeakAuras/RegionTypes/RegionPrototype.lua | 2 -- WeakAuras/WeakAuras.lua | 27 ++++++++++++++++++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index 6175036..cb63dd4 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -243,13 +243,13 @@ function Private.RestoreAuraEnvironment(id) end function Private.ClearAuraEnvironmentSavedData(id) - if environment_initialized[id] then + if environment_initialized[id] == 2 then aura_environments[id].saved = nil end end function Private.ClearAuraEnvironment(id) - if environment_initialized[id] then + if environment_initialized[id] == 2 then Private.SaveAuraEnvironment(id) environment_initialized[id] = nil aura_environments[id] = nil diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 3688f18..97630a0 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -2165,13 +2165,13 @@ local function createScanFunc(trigger) if trigger.ownOnly then ret = ret .. [[ - if matchData.unitCaster ~= 'player' and matchData.unitCaster ~= 'pet' then + if matchData.unitCaster ~= 'player' and matchData.unitCaster ~= 'pet' and matchData.unitCaster ~= 'vehicle' then return false end ]] elseif trigger.ownOnly == false then ret = ret .. [[ - if matchData.unitCaster == 'player' or matchData.unitCaster == 'pet' then + if matchData.unitCaster == 'player' or matchData.unitCaster == 'pet' or matchData.unitCaster == 'vehicle' then return false end ]] diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index a106747..717ae18 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -815,7 +815,6 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare return; end region.toShow = false; - region:SetScript("OnUpdate", nil) Private.PerformActions(data, "finish", region); if (not Private.Animate("display", data.uid, "finish", data.animation.finish, region, false, hideRegion, nil, cloneId)) then @@ -871,7 +870,6 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare return; end region.toShow = false; - region:SetScript("OnUpdate", nil) Private.PerformActions(data, "finish", region); if (not Private.Animate("display", data.uid, "finish", data.animation.finish, region, false, hideRegion, nil, cloneId)) then diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 400ea76..0aef82b 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1208,7 +1208,7 @@ loadedFrame:SetScript("OnEvent", function(self, event, addon) end elseif event == "PLAYER_LOGOUT" then for id in pairs(db.displays) do - Private.SaveAuraEnvironment(id) + Private.ClearAuraEnvironment(id) end else local callback @@ -2183,6 +2183,7 @@ end function Private.AddMany(tbl, takeSnapshots) local idtable = {}; + local anchorTargets = {} for _, data in ipairs(tbl) do -- There was an unfortunate bug in update.lua in 2022 that resulted -- in auras having a circular dependencies @@ -2192,6 +2193,9 @@ function Private.AddMany(tbl, takeSnapshots) tDeleteItem(data.controlledChildren, data.id) end idtable[data.id] = data; + if data.anchorFrameType == "SELECTFRAME" and data.anchorFrameFrame and data.anchorFrameFrame:sub(1, 10) == "WeakAuras:" then + anchorTargets[data.anchorFrameFrame:sub(11)] = true + end end local order = loadOrder(tbl, idtable) @@ -2204,6 +2208,14 @@ function Private.AddMany(tbl, takeSnapshots) groups[data] = true end end + + for id in pairs(anchorTargets) do + local data = idtable[id] + if data and (data.parent == nil or idtable[data.parent].regionType ~= "dynamicgroup") then + Private.EnsureRegion(id) + end + end + for data in pairs(groups) do if data.type == "dynamicgroup" then if Private.regions[data.id] then @@ -3752,6 +3764,19 @@ end do local visibleFakeStates = {} + + local function OnDelete(_, uid, id) + visibleFakeStates[id] = nil + end + + local function OnRename(_, uid, oldId, newId) + visibleFakeStates[newId] = visibleFakeStates[oldId] + visibleFakeStates[oldId] = nil + end + + Private.callbacks:RegisterCallback("Delete", OnDelete) + Private.callbacks:RegisterCallback("Rename", OnRename) + local UpdateFakeTimesHandle local function UpdateFakeTimers() From aee89075c9ee4ef6eb03222999fb7e8459ddd926 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 9 Jan 2025 17:17:53 +0100 Subject: [PATCH 015/153] from retail --- WeakAuras/AuraEnvironment.lua | 13 ++++++++-- WeakAuras/GenericTrigger.lua | 9 +++++-- WeakAuras/Prototypes.lua | 29 +++++++++++++---------- WeakAuras/RegionTypes/AuraBar.lua | 2 +- WeakAuras/SubRegionTypes/SubText.lua | 18 -------------- WeakAuras/Transmission.lua | 19 +++++++++------ WeakAuras/WeakAuras.lua | 7 ++++++ WeakAurasOptions/OptionsFrames/Update.lua | 15 ++++++++++-- 8 files changed, 67 insertions(+), 45 deletions(-) diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index cb63dd4..a00fb59 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -450,7 +450,8 @@ local FakeWeakAurasMixin = { Private.AuraWarnings.UpdateWarning(current_uid, "FakeWeakAurasGetData", "warning", L["This aura calls GetData a lot, which is a slow function."]) end - return CopyTable(WeakAuras.GetData(id)) + local data = WeakAuras.GetData(id) + return data and CopyTable(data) or nil end, clones = MakeDeprecated(Private.clones, "clones", L["Using WeakAuras.clones is deprecated. Use WeakAuras.GetRegion(id, cloneId) instead."]), @@ -561,13 +562,21 @@ function env_getglobal_builtin(k) return exec_env_builtin[k] end +local function firstLine(string) + local lineBreak = string:find('\n', 1, true) + if lineBreak then + return string:sub(1, lineBreak - 1) + end + return string +end + local function CreateFunctionCache(exec_env) local cache = {} cache.Load = function(self, string) if self[string] then return self[string] else - local loadedFunction, errorString = loadstring(string) + local loadedFunction, errorString = loadstring(string, firstLine(string)) if errorString then print(errorString) else diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 32af1dd..ba0324d 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -3059,7 +3059,7 @@ do if event == "BigWigs_Message" then WeakAuras.ScanEvents("BigWigs_Message", ...) elseif event == "BigWigs_StartBar" then - local addon, spellId, text, duration, icon = ... + local addon, spellId, text, duration, icon, isCD = ... local now = GetTime() local expirationTime = now + duration @@ -3072,6 +3072,7 @@ do bar.duration = duration bar.expirationTime = expirationTime bar.icon = icon + bar.isCooldown = isCD or false local BWColorModule = BigWigs:GetPlugin("Colors") bar.bwBarColor = BWColorModule:GetColorTable("barColor", addon, spellId) bar.bwTextColor = BWColorModule:GetColorTable("barText", addon, spellId) @@ -3152,9 +3153,10 @@ do if extendTimer ~= 0 then state.autoHide = true end + state.isCooldown = bar.isCooldown end - function Private.ExecEnv.BigWigsTimerMatches(id, message, operator, spellId, emphasized, count, cast) + function Private.ExecEnv.BigWigsTimerMatches(id, message, operator, spellId, emphasized, count, cast, cooldown) if not bars[id] then return false end @@ -3188,6 +3190,9 @@ do if cast ~= nil and v.cast ~= cast then return false end + if cooldown ~= nil and v.isCooldown ~= cooldown then + return false + end return true end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index c443777..19be76c 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4181,6 +4181,7 @@ Private.event_prototypes = { local triggerEmphasized = %s local triggerCount = %q local triggerCast = %s + local triggerIsCooldown = %s local cloneId = useClone and id or "" local state = states[cloneId] @@ -4206,7 +4207,7 @@ Private.event_prototypes = { if useClone then if event == "BigWigs_StartBar" then - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast, triggerIsCooldown) then local bar = WeakAuras.GetBigWigsTimerById(id) if bar then copyOrSchedule(bar, cloneId) @@ -4273,6 +4274,7 @@ Private.event_prototypes = { trigger.use_emphasized == nil and "nil" or trigger.use_emphasized and "true" or "false", trigger.use_count and trigger.count or "", trigger.use_cast == nil and "nil" or trigger.use_cast and "true" or "false", + trigger.use_isCooldown == nil and "nil" or trigger.use_isCooldown and "true" or "false", trigger.remaining_operator or "<" ) end, @@ -4326,6 +4328,15 @@ Private.event_prototypes = { init = "false", conditionType = "bool" }, + { + name = "isCooldown", + display = L["Cooldown"], + desc = L["Cooldown bars show time before an ability is ready to be use, BigWigs prefix them with '~'"], + type = "tristate", + test = "true", + init = "false", + conditionType = "bool" + }, { name = "cloneId", display = L["Clone per Event"], @@ -5553,20 +5564,12 @@ Private.event_prototypes = { } }, nameFunc = function(trigger) - if not trigger.use_inverse then - local name = GetItemInfo(trigger.itemName); - return name; - else - return nil; - end + local name = GetItemInfo(trigger.itemName); + return name; end, iconFunc = function(trigger) - if not trigger.use_inverse then - local _, _, _, _, _, _, _, _, _, icon = GetItemInfo(trigger.itemName or 0); - return icon; - else - return nil; - end + local icon = select(10, GetItemInfo(trigger.itemName or 0)); + return icon; end, hasItemID = true, automaticrequired = true diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 7570f88..ecba5ea 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -338,7 +338,7 @@ local barPrototype = { local width = additionalBar.width or 0; local offset = additionalBar.offset or 0; - if (width ~= 0) then + if (width ~= 0 and valueWidth ~= 0) then if (forwardDirection) then startProgress = self.value + offset / valueWidth; endProgress = self.value + (width + offset) / valueWidth; diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index da4553e..09747cb 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -132,24 +132,6 @@ local function modify(parent, region, parentData, data, first) region:SetParent(parent) local text = region.text; - -- Legacy members in icon - -- Can we remove them with 9.0 ? - if parentData.regionType == "icon" then - if not parent.stacks then - parent.stacks = text - elseif not parent.text2 then - parent.text2 = text - end - elseif parentData.regionType == "aurabar" then - if not parent.timer then - parent.timer = text - elseif not parent.text then - parent.text = text - elseif not parent.stacks then - parent.stacks = text - end - end - local fontPath = SharedMedia:Fetch("font", data.text_font); text:SetFont(fontPath, data.text_fontSize < 33 and data.text_fontSize or 33, data.text_fontType); if not text:GetFont() then -- Font invalid, set the font but keep the setting diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 5c84bec..179bdc7 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -302,19 +302,24 @@ function StringToTable(inString, fromChat) end if not decoded then - return "Error decoding." + return L["Error decoding."] end - local decompressed, errorMsg = nil, "unknown compression method" + local decompressed if encodeVersion > 0 then decompressed = LibDeflate:DecompressDeflate(decoded) + if not(decompressed) then + return L["Error decompressing"] + end else - decompressed, errorMsg = Compresser:Decompress(decoded) - end - if not(decompressed) then - return "Error decompressing: " .. errorMsg + -- We ignore the error message, since it's more likely not a weakaura. + decompressed = Compresser:Decompress(decoded) + if not(decompressed) then + return L["Error decompressing. This doesn't look like a WeakAuras import."] + end end + local success, deserialized if encodeVersion < 2 then success, deserialized = Serializer:Deserialize(decompressed) @@ -322,7 +327,7 @@ function StringToTable(inString, fromChat) success, deserialized = LibSerialize:Deserialize(decompressed) end if not(success) then - return "Error deserializing "..deserialized + return L["Error deserializing"] end return deserialized end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 0aef82b..c80e532 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2567,6 +2567,7 @@ function Private.ClearSounds(uid) end function WeakAuras.PreAdd(data) + if not data then return end -- Readd what Compress removed before version 8 if (not data.internalVersion or data.internalVersion < 7) then Private.validate(data, oldDataStub) @@ -3886,6 +3887,12 @@ local function startStopTimers(id, cloneId, triggernum, state) if (state.show ~= false and state.show ~= nil) then state.show = false; state.changed = true; + + -- if the trigger has updated then check to see if it is flagged for WatchedTrigger and send to queue if it is + if Private.watched_trigger_events[id] and Private.watched_trigger_events[id][triggernum] then + Private.AddToWatchedTriggerDelay(id, triggernum) + end + Private.UpdatedTriggerState(id); end end, diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index 15dd6a9..00975ea 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -855,6 +855,17 @@ local function BuildUidMap(data, children, type) self.rootParent = parentId end + uidMap.Dump = function(self, uid) + if uid == nil then + uid = self:GetRootUID() + end + print(self:GetIdFor(uid)) + local children = self:GetChildren(uid) + for i, childUid in ipairs(children) do + uidMap:Dump(childUid) + end + end + return uidMap, uidMap.root end @@ -1545,9 +1556,9 @@ local methods = { self:SetMinimumProgress(2 * onePhaseProgress) local removeNewGroups = matchInfo.activeCategories.arrangement and not userChoices.activeCategories.arrangement - if userChoices.activeCategories.newchildren or removeNewGroups then + if not userChoices.activeCategories.newchildren or removeNewGroups then self:RemoveUnmatchedNew(matchInfo.newUidMap, matchInfo.newUidMap:GetRootUID(), matchInfo.oldUidMap, - userChoices.activeCategories.newchildren, + not userChoices.activeCategories.newchildren, removeNewGroups) end self:SetMinimumProgress(3 * onePhaseProgress) From 9e2bffcd205b3af8a96e1f4bd7e8fed4d470508b Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 9 Jan 2025 20:23:53 +0100 Subject: [PATCH 016/153] from retail --- WeakAuras/RegionTypes/DynamicGroup.lua | 87 ++++++++++++++++++- WeakAuras/Types.lua | 10 +++ WeakAuras/WeakAuras.lua | 47 +++++++++- .../RegionOptions/DynamicGroup.lua | 14 ++- 4 files changed, 150 insertions(+), 8 deletions(-) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index ca49dd8..a7e5d77 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -700,9 +700,9 @@ local growers = { local gridWidth = data.gridWidth local rowSpace = data.rowSpace local colSpace = data.columnSpace - local rowFirst = (gridType:find("^[RL]")) ~= nil + local rowFirst = (gridType:find("^[RLH]")) ~= nil local limit = data.useLimit and data.limit or math.huge - local rowMul, colMul + local rowMul, colMul, primary_horizontal, secondary_horizontal, primary_vertical, secondary_vertical if gridType:find("D") then rowMul = -1 else @@ -713,6 +713,16 @@ local growers = { else colMul = 1 end + if gridType:sub(1, 1) == "H" then + primary_horizontal = true + elseif gridType:sub(2, 2) == "H" then + secondary_horizontal = true + end + if gridType:sub(1, 1) == "V" then + primary_vertical = true + elseif gridType:sub(2, 2) == "V" then + secondary_vertical = true + end local primary = { -- x direction dim = "width", @@ -746,19 +756,81 @@ local growers = { secondary.current = 0 secondary.max = 0 newPositions[frame] = {} + local minX, maxX, minY, maxY, totalMinX, totalMaxX, totalMinY, totalMaxY + local start for i, regionData in ipairs(regionDatas) do if i <= numVisible then - newPositions[frame][regionData] = { [primary.coord] = primary.current, [secondary.coord] = secondary.current, [3] = true } + newPositions[frame][regionData] = { + [primary.coord] = primary.current, + [secondary.coord] = secondary.current, + [3] = true + } + local x, y = newPositions[frame][regionData][1], newPositions[frame][regionData][2] + if minX == nil then + minX, maxX, minY, maxY = x, x, y, y + start = i + else + minX, maxX = math.min(minX, x), math.max(maxX, x) + minY, maxY = math.min(minY, y), math.max(maxY, y) + end + if totalMinX == nil then + totalMinX, totalMaxX, totalMinY, totalMaxY = x, x, y, y + else + totalMinX, totalMaxX = math.min(totalMinX, x), math.max(totalMaxX, x) + totalMinY, totalMaxY = math.min(totalMinY, y), math.max(totalMaxY, y) + end secondary.max = max(secondary.max, getDimension(regionData, secondary.dim)) if i % gridWidth == 0 then + if primary_horizontal then + local offsetX = (maxX - minX) / 2 + for j = start, i do + newPositions[frame][regionDatas[j]][1] = newPositions[frame][regionDatas[j]][1] - offsetX + end + end + if primary_vertical then + local offsetY = (maxY - minY) / 2 + for j = start, i do + newPositions[frame][regionDatas[j]][2] = newPositions[frame][regionDatas[j]][2] - offsetY + end + end primary.current = 0 secondary.current = secondary.current + (secondary.space + secondary.max) * secondary.mul secondary.max = 0 + minX, maxX = nil, nil + minY, maxY = nil, nil else primary.current = primary.current + (primary.space + getDimension(regionData, primary.dim)) * primary.mul end end end + if (primary_horizontal or primary_vertical) and minX then + local offsetX = (maxX - minX) / 2 + local offsetY = (maxY - minY) / 2 + for j = start, #regionDatas do + if j <= numVisible then + if primary_horizontal then + newPositions[frame][regionDatas[j]][1] = newPositions[frame][regionDatas[j]][1] - offsetX + end + if primary_vertical then + newPositions[frame][regionDatas[j]][2] = newPositions[frame][regionDatas[j]][2] - offsetY + end + end + end + end + if (secondary_horizontal or secondary_vertical) and totalMinX then + local offsetX = (totalMaxX - totalMinX) / 2 + local offsetY = (totalMaxY - totalMinY) / 2 + for j = 1, #regionDatas do + if j <= numVisible then + if secondary_horizontal then + newPositions[frame][regionDatas[j]][1] = newPositions[frame][regionDatas[j]][1] - offsetX + end + if secondary_vertical then + newPositions[frame][regionDatas[j]][2] = newPositions[frame][regionDatas[j]][2] - offsetY + end + end + end + end end end end, @@ -795,7 +867,7 @@ local function modify(parent, region, data) region:SetScale(data.scale and data.scale > 0 and data.scale <= 10 and data.scale or 1) WeakAuras.regionPrototype.modify(parent, region, data) - if data.border and (data.grow ~= "CUSTOM" and not data.useAnchorPerUnit) then + if data.border and not data.useAnchorPerUnit then local background = region.background background:SetBackdrop({ edgeFile = data.borderEdge ~= "None" and SharedMedia:Fetch("border", data.borderEdge) or "", @@ -1262,6 +1334,13 @@ local function modify(parent, region, data) self:SetHeight(height) self.currentWidth = width self.currentHeight = height + + local regionLeft = region:GetLeft() + local regionBottom = region:GetBottom() + self.background:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT", minX + -1 * data.borderOffset - regionLeft, + minY + -1 * data.borderOffset - regionBottom) + self.background:SetPoint("TOPRIGHT", region, "BOTTOMLEFT", maxX + data.borderOffset - regionLeft, + maxY + data.borderOffset - regionBottom) else self:Hide() end diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index a29f4b1..f6a1629 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -1821,6 +1821,16 @@ Private.grid_types = { DR = L["Down, then Right"], LD = L["Left, then Down"], DL = L["Down, then Left"], + HD = L["Centered Horizontal, then Down"], + HU = L["Centered Horizontal, then Up"], + VR = L["Centered Vertical, then Right"], + VL = L["Centered Vertical, then Left"], + DH = L["Down, then Centered Horizontal"], + UH = L["Up, then Centered Horizontal"], + LV = L["Left, then Centered Vertical"], + RV = L["Right, then Centered Vertical"], + HV = L["Centered Horizontal, then Centered Vertical"], + VH = L["Centered Vertical, then Centered Horizontal"], } Private.text_rotate_types = { diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index c80e532..d3384ff 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1726,6 +1726,10 @@ function WeakAuras.Delete(data) if Private.regions[id] then Private.regions[id].region:Collapse() Private.CancelAnimation(Private.regions[id].region, true, true, true, true, true, true) + + -- Groups have a empty Collapse method so, we need to hide them here + Private.regions[id].region:Hide(); + Private.regions[id].region = nil Private.regions[id] = nil end @@ -2194,7 +2198,23 @@ function Private.AddMany(tbl, takeSnapshots) end idtable[data.id] = data; if data.anchorFrameType == "SELECTFRAME" and data.anchorFrameFrame and data.anchorFrameFrame:sub(1, 10) == "WeakAuras:" then - anchorTargets[data.anchorFrameFrame:sub(11)] = true + anchorTargets[data.anchorFrameFrame:sub(11)] = data.id + end + end + + -- Now fix up anchors, see #3971, where aura p was anchored to aura c and where c was a child of p, thus c was anchored to p + -- The game used to detect such anchoring circles. We can't detect all of them, but at least detect the one from the ticket. + for target, source in pairs(anchorTargets) do + -- We walk up the parent's of target, to check for source + local parent = target + if idtable[target] then + while(parent) do + if parent == source then + WeakAuras.prettyPrint(L["Warning: Anchoring to your own child '%s' in aura '%s' is imposssible."]:format(target, source)) + idtable[source].anchorFrameType = "SCREEN" + end + parent = idtable[parent].parent + end end end @@ -2653,7 +2673,7 @@ local function pAdd(data, simpleChange) else Private.DebugLog.SetEnabled(data.uid, data.information.debugLog) - if (data.controlledChildren) then + if Private.IsGroupType(data) then Private.ClearAuraEnvironment(id); for parent in Private.TraverseParents(data) do Private.ClearAuraEnvironment(parent.id); @@ -2666,6 +2686,8 @@ local function pAdd(data, simpleChange) loadEvents["GROUP"] = loadEvents["GROUP"] or {} loadEvents["GROUP"][id] = true else -- Non group aura + -- Make sure that we don't have a controlledChildren member. + data.controlledChildren = nil local visible if (WeakAuras.IsOptionsOpen()) then visible = Private.FakeStatesFor(id, false) @@ -4041,6 +4063,16 @@ function Private.AddToWatchedTriggerDelay(id, triggernum) delayed_watched_trigger[id] = delayed_watched_trigger[id] or {} tinsert(delayed_watched_trigger[id], triggernum) end + +Private.callbacks:RegisterCallback("Delete", function(_, uid, id) + delayed_watched_trigger[id] = nil +end) + +Private.callbacks:RegisterCallback("Rename", function(_, uid, oldId, newId) + delayed_watched_trigger[newId] = delayed_watched_trigger[oldId] + delayed_watched_trigger[oldId] = nil +end) + function Private.SendDelayedWatchedTriggers() for id in pairs(delayed_watched_trigger) do local watched = delayed_watched_trigger[id] @@ -4984,6 +5016,17 @@ local function GetAnchorFrame(data, region, parent) if (frame_name == id) then return parent; end + + local targetData = WeakAuras.GetData(frame_name) + if targetData then + for parentData in Private.TraverseParents(targetData) do + if parentData.id == data.id then + WeakAuras.prettyPrint(L["Warning: Anchoring to your own child '%s' in aura '%s' is imposssible."]:format(frame_name, data.id)) + return parent + end + end + end + if(Private.regions[frame_name]) then return Private.regions[frame_name].region; end diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index b4d0b3f..856b9a7 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -72,6 +72,16 @@ local gridSelfPoints = { DR = "TOPLEFT", LD = "TOPRIGHT", DL = "TOPRIGHT", + HD = "TOP", + HU = "BOTTOM", + VR = "LEFT", + VL = "RIGHT", + DH = "TOP", + UH = "BOTTOM", + LV = "RIGHT", + RV = "LEFT", + HV = "CENTER", + VH = "CENTER", } local function createOptions(id, data) @@ -267,7 +277,7 @@ local function createOptions(id, data) width = WeakAuras.normalWidth, name = function() if not data.gridType then return "" end - if data.gridType:find("^[RL]") then + if data.gridType:find("^[RLH]") then return L["Row Width"] else return L["Column Height"] @@ -448,7 +458,7 @@ local function createOptions(id, data) OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Anchor"], "custom_anchor_per_unit", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#group-by-frame", 1.7, function() return not(data.grow ~= "CUSTOM" and data.useAnchorPerUnit and data.anchorPerUnit == "CUSTOM") end, {"customAnchorPerUnit"}, false, { setOnParent = true }) - local borderHideFunc = function() return data.useAnchorPerUnit or data.grow == "CUSTOM" end + local borderHideFunc = function() return data.useAnchorPerUnit end local disableSelfPoint = function() return data.grow ~= "CUSTOM" and data.grow ~= "GRID" and not data.useAnchorPerUnit end for k, v in pairs(OptionsPrivate.commonOptions.BorderOptions(id, data, nil, borderHideFunc, 70)) do From b89c221c348f22635ab30fc868ce81f33fbd9029 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 10 Jan 2025 14:15:01 +0100 Subject: [PATCH 017/153] from retail --- WeakAuras/GenericTrigger.lua | 6 +- WeakAuras/RegionTypes/AuraBar.lua | 6 +- WeakAuras/RegionTypes/DynamicGroup.lua | 15 +++-- WeakAuras/RegionTypes/Model.lua | 2 +- WeakAuras/WeakAuras.lua | 46 +++++++------ .../AceGUIWidget-WeakAurasTextureButton.lua | 5 +- WeakAurasOptions/InformationOptions.lua | 64 ++++++++++++++----- .../OptionsFrames/FrameChooser.lua | 2 +- WeakAurasOptions/OptionsFrames/MoverSizer.lua | 2 +- .../OptionsFrames/OptionsFrame.lua | 14 ++-- WeakAurasOptions/OptionsFrames/Update.lua | 18 +++--- WeakAurasOptions/WeakAurasOptions.lua | 2 +- 12 files changed, 113 insertions(+), 69 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index ba0324d..d1324f4 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1563,11 +1563,11 @@ function GenericTrigger.Add(data, region) else tinsert(trigger_events, event) end - if trigger.custom_type == "status" or trigger.custom_type == "stateupdate" then - force_events = data.information.forceEvents or "STATUS" - end end end + if trigger.custom_type == "status" or trigger.custom_type == "stateupdate" then + force_events = data.information.forceEvents or "STATUS" + end if (trigger.custom_type == "stateupdate") then statesParameter = "full"; end diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index ecba5ea..9dddf53 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -961,7 +961,7 @@ local funcs = { orientVertical(self); end end, - UpdateEffectiveOrientation = function(self) + UpdateEffectiveOrientation = function(self, force) local orientation = self.orientation if self.flipX then @@ -979,7 +979,7 @@ local funcs = { end end - if orientation ~= self.effectiveOrientation then + if orientation ~= self.effectiveOrientation or force then self.effectiveOrientation = orientation self:ReOrient() end @@ -1339,7 +1339,7 @@ local function modify(parent, region, data) self:SetHeight(self.bar.totalHeight); icon:SetHeight(self.bar.iconHeight); - region:UpdateEffectiveOrientation() + region:UpdateEffectiveOrientation(true) end -- region:Scale(1.0, 1.0); if data.smoothProgress then diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index a7e5d77..1f0dd06 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1335,12 +1335,15 @@ local function modify(parent, region, data) self.currentWidth = width self.currentHeight = height - local regionLeft = region:GetLeft() - local regionBottom = region:GetBottom() - self.background:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT", minX + -1 * data.borderOffset - regionLeft, - minY + -1 * data.borderOffset - regionBottom) - self.background:SetPoint("TOPRIGHT", region, "BOTTOMLEFT", maxX + data.borderOffset - regionLeft, - maxY + data.borderOffset - regionBottom) + if data.border and not data.useAnchorPerUnit then + local regionLeft = SafeGetPos(region, region.GetLeft) or minX + local regionBottom = SafeGetPos(region, region.GetBottom) or minY + if regionLeft and regionBottom then + self.background:ClearAllPoints() + self.background:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT", minX + -1 * data.borderOffset - regionLeft, minY + -1 * data.borderOffset - regionBottom) + self.background:SetPoint("TOPRIGHT", region, "BOTTOMLEFT", maxX + data.borderOffset - regionLeft, maxY + data.borderOffset - regionBottom) + end + end else self:Hide() end diff --git a/WeakAuras/RegionTypes/Model.lua b/WeakAuras/RegionTypes/Model.lua index 508b224..b543eac 100644 --- a/WeakAuras/RegionTypes/Model.lua +++ b/WeakAuras/RegionTypes/Model.lua @@ -282,7 +282,7 @@ do Private.StartProfileSystem("model"); for id, data in pairs(Private.regions) do Private.StartProfileAura(id); - if data.region.toShow then + if data.region and data.region.toShow then if (data.regionType == "model") then data.region:PreShow(); end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index d3384ff..e54b9d8 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1114,7 +1114,7 @@ function Private.Login(initialTime, takeNewSnapshots) loginFinished = true -- Tell Dynamic Groups that we are done with login for _, region in pairs(Private.regions) do - if (region.region.RunDelayedActions) then + if (region.region and region.region.RunDelayedActions) then region.region:RunDelayedActions(); end end @@ -1281,7 +1281,7 @@ end function Private.PauseAllDynamicGroups() local suspended = {} for id, region in pairs(Private.regions) do - if (region.region.Suspend) then + if (region.region and region.region.Suspend) then region.region:Suspend(); tinsert(suspended, id) end @@ -1587,7 +1587,9 @@ function Private.Resume() local suspended = Private.PauseAllDynamicGroups() for id, region in pairs(Private.regions) do - region.region:Collapse(); + if region.region then + region.region:Collapse(); + end end for id, cloneList in pairs(clones) do @@ -1723,7 +1725,7 @@ function WeakAuras.Delete(data) end end - if Private.regions[id] then + if Private.regions[id] and Private.regions[id].region then Private.regions[id].region:Collapse() Private.CancelAnimation(Private.regions[id].region, true, true, true, true, true, true) @@ -1804,7 +1806,7 @@ function WeakAuras.Rename(data, newid) UIDtoID[data.uid] = newid Private.regions[newid] = Private.regions[oldid]; Private.regions[oldid] = nil; - if Private.regions[newid] then + if Private.regions[newid] and Private.regions[newid].region then Private.regions[newid].region.id = newid end if(clones[oldid]) then @@ -2238,7 +2240,7 @@ function Private.AddMany(tbl, takeSnapshots) for data in pairs(groups) do if data.type == "dynamicgroup" then - if Private.regions[data.id] then + if Private.regions[data.id] and Private.regions[data.id].region then Private.regions[data.id].region:ReloadControlledChildren() end else @@ -3206,7 +3208,7 @@ function Private.HandleGlowAction(actions, region) if WeakAuras.GetData(frame_name) then Private.EnsureRegion(frame_name) end - if Private.regions[frame_name] then + if Private.regions[frame_name] and Private.regions[frame_name].region then glow_frame = Private.regions[frame_name].region should_glow_frame = true end @@ -3596,12 +3598,14 @@ local DisplayTimes = {}; function WeakAuras.ProfileDisplays(all) UpdateAddOnCPUUsage(); for id, regionData in pairs(Private.regions) do - local DisplayTime = GetFrameCPUUsage(regionData.region, true); - DisplayTimes[id] = DisplayTimes[id] or 0; - if(all or DisplayTime > DisplayTimes[id]) then - print("|cFFFF0000"..id.."|r -", DisplayTime, "-", DisplayTime - DisplayTimes[id]); + if regionData.region then + local DisplayTime = GetFrameCPUUsage(regionData.region, true); + DisplayTimes[id] = DisplayTimes[id] or 0; + if(all or DisplayTime > DisplayTimes[id]) then + print("|cFFFF0000"..id.."|r -", DisplayTime, "-", DisplayTime - DisplayTimes[id]); + end + DisplayTimes[id] = DisplayTime; end - DisplayTimes[id] = DisplayTime; end end @@ -4161,7 +4165,7 @@ function Private.UpdatedTriggerState(id) for _, clone in pairs(clones[id]) do clone:Collapse() end - if Private.regions[id] then + if Private.regions[id] and Private.regions[id].region then Private.regions[id].region:Collapse() end elseif (show and oldShow) then -- Already shown, update regions @@ -4172,7 +4176,7 @@ function Private.UpdatedTriggerState(id) end end if (not activeTriggerState[""] or not activeTriggerState[""].show) then - if Private.regions[id] then + if Private.regions[id] and Private.regions[id].region then Private.regions[id].region:Collapse() end end @@ -4938,10 +4942,16 @@ local function tryAnchorAgain() local region = WeakAuras.GetRegion(id); if (data and region) then local parent = WeakAurasFrame; - if (data.parent and WeakAuras.GetData(data.parent) and Private.EnsureRegion(data.parent)) then - parent = Private.regions[data.parent].region; + local parentData + if data.parent then + parentData = WeakAuras.GetData(data.parent) + if parentData and Private.EnsureRegion(data.parent) then + parent = Private.regions[data.parent].region + end + end + if not parentData or parentData.regionType ~= "dynamicgroup" then + Private.AnchorFrame(data, region, parent) end - Private.AnchorFrame(data, region, parent); end end end @@ -5027,7 +5037,7 @@ local function GetAnchorFrame(data, region, parent) end end - if(Private.regions[frame_name]) then + if Private.regions[frame_name] and Private.regions[frame_name].region then return Private.regions[frame_name].region; end postponeAnchor(id); diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua index 6d58a2a..9d784f2 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTextureButton.lua @@ -33,6 +33,7 @@ local methods = { self.texture:SetTexture(texturePath); self.texture.path = texturePath; self.texture.name = name; + self.texture:SetSize(120, 120); end, ["ChangeTexture"] = function(self, r, g, b, a, rotate, discrete_rotation, rotation, mirror, blendMode) local ulx,uly , llx,lly , urx,ury , lrx,lry; @@ -107,8 +108,8 @@ local function Constructor() button:SetHighlightTexture(highlighttexture); local texture = button:CreateTexture(nil, "OVERLAY"); - texture:SetPoint("BOTTOMLEFT", button, 4, 4); - texture:SetPoint("TOPRIGHT", button, -4, -4); + texture:SetPoint("CENTER") + texture:SetSize(120, 120) button:SetScript("OnEnter", function() Show_Tooltip(button, texture.name, texture.path:gsub("\\", "\n")) end); button:SetScript("OnLeave", Hide_Tooltip); diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index 8f8ff5b..ff0bb37 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -313,13 +313,20 @@ function OptionsPrivate.GetInformationOptions(data) local sameDebugLog = true local commonDebugLog local debugLogDesc = "" - for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do - local effectiveDebugLog = child.information.debugLog and true or false - debugLogDesc = debugLogDesc .. "|cFFE0E000"..child.id..": |r".. (effectiveDebugLog and "true" or "false") .. "\n" - if commonDebugLog == nil then - commonDebugLog = effectiveDebugLog - elseif effectiveDebugLog ~= commonDebugLog then - sameDebugLog = false + + if isGroup and not isTmpGroup then + sameDebugLog = true + commonDebugLog = data.information.debugLog and true or false + else + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + --- @type boolean + local effectiveDebugLog = child.information.debugLog and true or false + debugLogDesc = debugLogDesc .. "|cFFE0E000"..child.id..": |r".. (effectiveDebugLog and "true" or "false") .. "\n" + if commonDebugLog == nil then + commonDebugLog = effectiveDebugLog + elseif effectiveDebugLog ~= commonDebugLog then + sameDebugLog = false + end end end args.debugLogToggle = { @@ -332,10 +339,15 @@ function OptionsPrivate.GetInformationOptions(data) return sameDebugLog and commonDebugLog end, set = function(info, v) - for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do - child.information.debugLog = v - WeakAuras.Add(child) - OptionsPrivate.ClearOptions(child.id) + if isGroup and not isTmpGroup then + data.information.debugLog = v + WeakAuras.Add(data) + else + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + child.information.debugLog = v + WeakAuras.Add(child) + OptionsPrivate.ClearOptions(child.id) + end end WeakAuras.ClearAndUpdateOptions(data.id) end @@ -350,18 +362,32 @@ function OptionsPrivate.GetInformationOptions(data) func = function() local fullMessage = L["WeakAuras %s on WoW %s"]:format(WeakAuras.versionString, WeakAuras.BuildInfo) .. "\n\n" local haveLogs = false - for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do - local auraLog = OptionsPrivate.Private.DebugLog.GetLogs(child.uid) + if isGroup and not isTmpGroup then + local auraLog = OptionsPrivate.Private.DebugLog.GetLogs(data.uid) if auraLog then haveLogs = true - fullMessage = fullMessage .. L["Aura: '%s'"]:format(child.id) - local version = child.semver or child.version + fullMessage = fullMessage .. L["Aura: '%s'"]:format(data.id) + local version = data.semver or data.version if (version) then fullMessage = fullMessage .. "\n" .. L["Version: %s"]:format(version) end fullMessage = fullMessage .. "\n" .. L["Debug Log:"] .. "\n" .. auraLog .. "\n\n" end + else + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + local auraLog = OptionsPrivate.Private.DebugLog.GetLogs(child.uid) + if auraLog then + haveLogs = true + fullMessage = fullMessage .. L["Aura: '%s'"]:format(child.id) + local version = child.semver or child.version + if (version) then + fullMessage = fullMessage .. "\n" .. L["Version: %s"]:format(version) + end + fullMessage = fullMessage .. "\n" .. L["Debug Log:"] .. "\n" .. auraLog .. "\n\n" + end + end end + if haveLogs then OptionsPrivate.OpenDebugLog(fullMessage) else @@ -376,8 +402,12 @@ function OptionsPrivate.GetInformationOptions(data) width = WeakAuras.normalWidth, order = order, func = function() - for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do - OptionsPrivate.Private.DebugLog.Clear(child.uid) + if isGroup and not isTmpGroup then + OptionsPrivate.Private.DebugLog.Clear(data.uid) + else + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + OptionsPrivate.Private.DebugLog.Clear(child.uid) + end end end } diff --git a/WeakAurasOptions/OptionsFrames/FrameChooser.lua b/WeakAurasOptions/OptionsFrames/FrameChooser.lua index 039338e..f1daa70 100644 --- a/WeakAurasOptions/OptionsFrames/FrameChooser.lua +++ b/WeakAurasOptions/OptionsFrames/FrameChooser.lua @@ -51,7 +51,7 @@ function OptionsPrivate.StartFrameChooser(data, path) focusName = nil; local focusIsGroup = false; for id, regionData in pairs(OptionsPrivate.Private.regions) do - if(regionData.region:IsVisible() and MouseIsOver(regionData.region)) then + if(regionData.region and regionData.region:IsVisible() and MouseIsOver(regionData.region)) then local isGroup = regionData.regionType == "group" or regionData.regionType == "dynamicgroup"; if (not focusName or (not isGroup and focusIsGroup)) then focus = regionData.region; diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index e076260..3219a1c 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -634,7 +634,7 @@ local function ConstructMoverSizer(parent) data.yOffset = dY / scale end region:ResetPosition() - WeakAuras.Add(data, nil, true) + WeakAuras.Add(data) WeakAuras.UpdateThumbnail(data) local xOff, yOff mover.selfPoint, mover.anchor, mover.anchorPoint, xOff, yOff = region:GetPoint(1) diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index bc33f2b..f721f03 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -138,12 +138,14 @@ function OptionsPrivate.CreateFrame() for id, data in pairs(OptionsPrivate.Private.regions) do - data.region:Collapse() - data.region:OptionsClosed() - if OptionsPrivate.Private.clones[id] then - for _, cloneRegion in pairs(OptionsPrivate.Private.clones[id]) do - cloneRegion:Collapse() - cloneRegion:OptionsClosed() + if data.region then + data.region:Collapse() + data.region:OptionsClosed() + if OptionsPrivate.Private.clones[id] then + for _, cloneRegion in pairs(OptionsPrivate.Private.clones[id]) do + cloneRegion:Collapse() + cloneRegion:OptionsClosed() + end end end end diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index 00975ea..bba4db8 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -182,15 +182,15 @@ local function recurseUpdate(data, chunk) end end -local ignoredForDiffChecking -- Needs to be created lazily -local function RecurseDiff(ours, theirs) +local function RecurseDiff(ours, theirs, ignoredForDiffChecking) local diff, seen, same = {}, {}, true for key, ourVal in pairs(ours) do - if not ignoredForDiffChecking[key] then + if type(ignoredForDiffChecking) ~= table or ignoredForDiffChecking[key] ~= true then seen[key] = true local theirVal = theirs[key] if type(ourVal) == "table" and type(theirVal) == "table" then - local diffVal = RecurseDiff(ourVal, theirVal) + local diffVal = RecurseDiff(ourVal, theirVal, + type(ignoredForDiffChecking) == table and ignoredForDiffChecking[key] or nil) if diffVal then diff[key] = diffVal same = false @@ -207,7 +207,7 @@ local function RecurseDiff(ours, theirs) end end for key, theirVal in pairs(theirs) do - if not seen[key] and not ignoredForDiffChecking[key] then + if not seen[key] and (type(ignoredForDiffChecking) ~= table or ignoredForDiffChecking[key] ~= true) then diff[key] = theirVal same = false end @@ -243,15 +243,13 @@ local function DebugPrintDiff(diff) end local function Diff(ours, theirs) - if not ignoredForDiffChecking then - ignoredForDiffChecking = WeakAuras.Mixin({}, OptionsPrivate.Private.internal_fields, - OptionsPrivate.Private.non_transmissable_fields) - end + local ignoredForDiffChecking = WeakAuras.Mixin({}, OptionsPrivate.Private.internal_fields, + OptionsPrivate.Private.non_transmissable_fields) -- generates a diff which WeakAuras.Update can use local debug = false if not ours or not theirs then return end - local diff = RecurseDiff(ours, theirs) + local diff = RecurseDiff(ours, theirs, ignoredForDiffChecking) if diff then if debug then DebugPrintDiff(diff, ours.id, theirs.id) diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 59266d5..7dff8f9 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -906,7 +906,7 @@ function OptionsPrivate.ConvertDisplay(data, newType) local visibility = displayButtons[id]:GetVisibility(); displayButtons[id]:PriorityHide(2); - if OptionsPrivate.Private.regions[id] then + if OptionsPrivate.Private.regions[id] and OptionsPrivate.Private.regions[id].region then OptionsPrivate.Private.regions[id].region:Collapse() end OptionsPrivate.Private.CollapseAllClones(id); From a747346a9dc922ef70890d22d1aec70ae7a85770 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 10 Jan 2025 16:16:47 +0100 Subject: [PATCH 018/153] from retail --- WeakAuras/Animations.lua | 5 +- WeakAuras/AuraEnvironment.lua | 4 +- WeakAuras/BuffTrigger2.lua | 2 +- WeakAuras/GenericTrigger.lua | 29 ++++- WeakAuras/Init.lua | 14 +-- WeakAuras/RegionTypes/AuraBar.lua | 4 +- WeakAuras/RegionTypes/DynamicGroup.lua | 105 +++++++++++++++--- WeakAuras/RegionTypes/Icon.lua | 16 ++- WeakAuras/Types.lua | 14 +++ .../AceGUIWidget-WeakAurasDisplayButton.lua | 2 +- WeakAurasOptions/CommonOptions.lua | 13 ++- .../RegionOptions/DynamicGroup.lua | 14 +++ WeakAurasOptions/RegionOptions/Group.lua | 3 +- WeakAurasOptions/RegionOptions/Icon.lua | 54 ++++++++- WeakAurasOptions/RegionOptions/Model.lua | 3 +- 15 files changed, 240 insertions(+), 42 deletions(-) diff --git a/WeakAuras/Animations.lua b/WeakAuras/Animations.lua index 9c8db06..b234022 100644 --- a/WeakAuras/Animations.lua +++ b/WeakAuras/Animations.lua @@ -134,7 +134,10 @@ local function UpdateAnimations() if not ok then errorHandler(r) else - anim.region:ColorAnim(r, g, b, a); + local success = pcall(anim.region.ColorAnim, errorHandler, anim.region, r, g, b, a) + if not success then + Private.GetErrorHandlerId(anim.region.id, "Custom Color") + end end end Private.ActivateAuraEnvironment(nil); diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index a00fb59..dd3d8d7 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -493,7 +493,7 @@ local exec_env_custom = setmetatable({}, return DebugPrint elseif blockedFunctions[k] then blocked(k) - return function() end + return function(_) end elseif blockedTables[k] then blocked(k) return {} @@ -538,7 +538,7 @@ local exec_env_builtin = setmetatable({}, return PrivateForBuiltIn elseif blockedFunctions[k] then blocked(k) - return function() end + return function(_) end elseif blockedTables[k] then blocked(k) return {} diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 97630a0..728d568 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -2180,7 +2180,7 @@ local function createScanFunc(trigger) if use_tooltip and trigger.tooltip_operator and trigger.tooltip then if trigger.tooltip_operator == "==" then local ret2 = [[ - if not matchData.tooltip or not matchData.tooltip == %s then + if not matchData.tooltip or matchData.tooltip ~= %s then return false end ]] diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index d1324f4..32867ba 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -560,6 +560,7 @@ function Private.ActivateEvent(id, triggernum, data, state, errorHandler) arg2 = type(arg2) == "number" and arg2 or 0; end + if (state.inverse ~= inverse) then state.inverse = inverse; changed = true; @@ -601,6 +602,11 @@ function Private.ActivateEvent(id, triggernum, data, state, errorHandler) if (state.duration ~= arg1) then state.duration = arg1; end + -- The Icon's SetCooldown requires that the **startTime** is positive, so ensure that + -- the expirationTime is bigger than the duration + if arg2 <= arg1 then + arg2 = arg1 + end if (state.expirationTime ~= arg2) then state.expirationTime = arg2; changed = true; @@ -2087,6 +2093,7 @@ do function Private.InitCooldownReady() cdReadyFrame = CreateFrame("Frame"); + cdReadyFrame.inWorld = 0 Private.frames["Cooldown Trigger Handler"] = cdReadyFrame cdReadyFrame:RegisterEvent("RUNE_POWER_UPDATE"); cdReadyFrame:RegisterEvent("RUNE_TYPE_UPDATE"); @@ -2100,7 +2107,24 @@ do cdReadyFrame:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN"); cdReadyFrame:RegisterEvent("SPELLS_CHANGED"); cdReadyFrame:RegisterEvent("PLAYER_ENTERING_WORLD"); - cdReadyFrame:SetScript("OnEvent", function(self, event, ...) + cdReadyFrame:RegisterEvent("PLAYER_LEAVING_WORLD"); + cdReadyFrame.HandleEvent = function(self, event, ...) + if (event == "PLAYER_ENTERING_WORLD") then + cdReadyFrame.inWorld = GetTime() + end + if (event == "PLAYER_LEAVING_WORLD") then + cdReadyFrame.inWorld = nil + end + if not cdReadyFrame.inWorld then + return + end + + if GetTime() - cdReadyFrame.inWorld < 2 then + cdReadyFrame:SetScript("OnUpdate", cdReadyFrame.HandleEvent) + return + end + cdReadyFrame:SetScript("OnUpdate", nil) + Private.StartProfileSystem("generictrigger cd tracking"); if(event == "SPELL_UPDATE_COOLDOWN" or event == "RUNE_POWER_UPDATE" or event == "RUNE_TYPE_UPDATE" or event == "ACTIONBAR_UPDATE_COOLDOWN" @@ -2126,7 +2150,8 @@ do Private.CheckItemSlotCooldowns(); end Private.StopProfileSystem("generictrigger cd tracking"); - end); + end + cdReadyFrame:SetScript("OnEvent", cdReadyFrame.HandleEvent) end function WeakAuras.GetRuneCooldown(id) diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index 2cb6bb3..42ae8e9 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -93,22 +93,22 @@ if not WeakAuras.IsLibsOK() then end -- These function stubs are defined here to reduce the number of errors that occur if WeakAuras.lua fails to compile -function WeakAuras.RegisterRegionType() +function WeakAuras.RegisterRegionType(_, _, _ ,_) end -function WeakAuras.RegisterRegionOptions() +function WeakAuras.RegisterRegionOptions(_, _ , _ ,_) end -function Private.StartProfileSystem() +function Private.StartProfileSystem(_) end -function Private.StartProfileAura() +function Private.StartProfileAura(_) end -function Private.StopProfileSystem() +function Private.StopProfileSystem(_) end -function Private.StopProfileAura() +function Private.StopProfileAura(_) end function Private.StartProfileUID() @@ -120,7 +120,7 @@ end Private.ExecEnv = {} -- If WeakAuras shuts down due to being installed on the wrong target, keep the bindings from erroring -function WeakAuras.StartProfile() +function WeakAuras.StartProfile(_) end function WeakAuras.StopProfile() diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 9dddf53..fae8774 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -1014,8 +1014,8 @@ local function create(parent) local bar = CreateFrame("Frame", nil, region); WeakAuras.Mixin(bar, SmoothStatusBarMixin); local fg = bar:CreateTexture(nil, "BORDER"); - local bg = bar:CreateTexture(nil, "BACKGROUND"); - bg:SetAllPoints(); + local bg = region:CreateTexture(nil, "BACKGROUND"); + bg:SetAllPoints(bar); local fgFrame = CreateFrame("Frame", nil, bar) local spark = bar:CreateTexture(nil, "ARTWORK"); bar.fg = fg; diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 1f0dd06..de646a5 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -36,6 +36,7 @@ local default = { useLimit = false, limit = 5, gridType = "RD", + centerType = "LR", gridWidth = 5, rowSpace = 1, columnSpace = 1 @@ -411,6 +412,76 @@ local anchorers = { end } +-- Names are based on the Left->Right layout, +local centeredIndexerStart = { + -- Left to right, e.g: 1 2 3 4 + ["LR"] = function(maxIndex) + return maxIndex > 0 and 1 or nil + end, + ["RL"] = function(maxIndex) + return maxIndex > 0 and maxIndex or nil + end, + -- Center -> Left -> Right, e.g: 4 2 1 3 + ["CLR"] = function(maxIndex) + if maxIndex >= 3 then + return maxIndex - maxIndex % 2 + else + return maxIndex + end + end, + -- Center -> Right -> Left, e.g: 3 1 2 4 + ["CRL"] = function(maxIndex) + if maxIndex % 2 == 1 then + return maxIndex + else + return maxIndex - 1 + end + end +} + +local centeredIndexerNext = { + ["LR"] = function(index, maxIndex) + index = index + 1 + return index <= maxIndex and index or nil + end, + ["RL"] = function(index, maxIndex) + index = index - 1 + return index > 0 and index or nil + end, + ["CLR"] = function(index, maxIndex) + -- Center -> Left -> Right + -- So even -> odd + if index % 2 == 0 then + index = index - 2 + if index == 0 then + index = 1 + end + else + index = index + 2 + end + if index > maxIndex then + return nil + end + return index + end, + ["CRL"] = function(index, maxIndex) + -- Center -> Right -> Left + -- So odd -> even + if index % 2 == 1 then + index = index - 2 + if index == -1 then + index = 2 + end + else + index = index + 2 + end + if index > maxIndex then + return nil + end + return index + end, +} + local function createAnchorPerUnitFunc(data) local anchorer = anchorers[data.anchorPerUnit] or anchorers.NAMEPLATE or anchorers.UNITFRAME return anchorer(data) @@ -539,6 +610,8 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local midX, midY = 0, 0 local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local FirstIndex = centeredIndexerStart[data.centerType] + local NextIndex = centeredIndexerNext[data.centerType] return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -555,13 +628,14 @@ local growers = { end local x, y = midX - totalWidth/2, midY - (stagger * (numVisible - 1)/2) newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - x = x + (regionData.dimensions.width) / 2 - newPositions[frame][regionData] = { x, y, true } - x = x + (regionData.dimensions.width) / 2 + space - y = y + stagger - end + local i = FirstIndex(numVisible) + while i do + local regionData = regionDatas[i] + x = x + (regionData.dimensions.width) / 2 + newPositions[frame][regionData] = { x, y, true } + x = x + (regionData.dimensions.width) / 2 + space + y = y + stagger + i = NextIndex(i, numVisible) end end end @@ -572,6 +646,8 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local midX, midY = 0, 0 local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local FirstIndex = centeredIndexerStart[data.centerType] + local NextIndex = centeredIndexerNext[data.centerType] return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -588,13 +664,14 @@ local growers = { end local x, y = midX - (stagger * (numVisible - 1)/2), midY - totalHeight/2 newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - y = y + (regionData.dimensions.height) / 2 - newPositions[frame][regionData] = { x, y, true } - x = x + stagger - y = y + (regionData.dimensions.height) / 2 + space - end + local i = FirstIndex(numVisible) + while i do + local regionData = regionDatas[i] + y = y + (regionData.dimensions.height) / 2 + newPositions[frame][regionData] = { x, y, true } + x = x + stagger + y = y + (regionData.dimensions.height) / 2 + space + i = NextIndex(i, numVisible) end end end diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index 56dee65..c2e23f5 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -109,7 +109,9 @@ local function GetProperties(data) return result end -local function GetTexCoord(region, texWidth, aspectRatio) +local function GetTexCoord(region, texWidth, aspectRatio, xOffset, yOffset) + xOffset = xOffset or 0 + yOffset = yOffset or 0 region.currentCoord = region.currentCoord or {} local usesMasque = false if region.MSQGroup then @@ -126,8 +128,11 @@ local function GetTexCoord(region, texWidth, aspectRatio) local xRatio = aspectRatio < 1 and aspectRatio or 1; local yRatio = aspectRatio > 1 and 1 / aspectRatio or 1; for i, coord in ipairs(region.currentCoord) do - local aspectRatio = (i % 2 == 1) and xRatio or yRatio; - region.currentCoord[i] = (coord - 0.5) * texWidth * aspectRatio + 0.5; + if(i % 2 == 1) then + region.currentCoord[i] = (coord - 0.5) * texWidth * xRatio + 0.5 - xOffset; + else + region.currentCoord[i] = (coord - 0.5) * texWidth * yRatio + 0.5 - yOffset; + end end return unpack(region.currentCoord) @@ -401,7 +406,8 @@ local function modify(parent, region, data) end end - local ulx, uly, llx, lly, urx, ury, lrx, lry = GetTexCoord(region, texWidth, aspectRatio) + local ulx, uly, llx, lly, urx, ury, lrx, lry + = GetTexCoord(region, texWidth, aspectRatio, region.texXOffset, region.texYOffset and -region.texYOffset) if(mirror_h) then if(mirror_v) then @@ -424,6 +430,8 @@ local function modify(parent, region, data) region.scaley = 1; region.keepAspectRatio = data.keepAspectRatio; region.zoom = data.zoom; + region.texXOffset = data.texXOffset + region.texYOffset = data.texYOffset region:UpdateSize() icon:SetDesaturated(data.desaturate); diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index f6a1629..b9c5234 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -1833,6 +1833,20 @@ Private.grid_types = { VH = L["Centered Vertical, then Centered Horizontal"], } +Private.centered_types_h = { + LR = L["Left to Right"], + RL = L["Right to Left"], + CLR =L["Center, then alternating left and right"], + CRL = L["Center, then alternating right and left"] +} + +Private.centered_types_v = { + LR = L["Bottom to Top"], + RL = L["Top to Bottom"], + CLR =L["Center, then alternating bottom and top"], + CRL = L["Center, then alternating top and bottom"] +} + Private.text_rotate_types = { ["LEFT"] = L["Left"], ["NONE"] = L["None"], diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index 0abdf48..41e4da4 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -5,7 +5,7 @@ local tinsert, tremove, wipe = table.insert, table.remove, wipe local select, pairs, type, unpack = select, pairs, type, unpack local error = error -local Type, Version = "WeakAurasDisplayButton", 59 +local Type, Version = "WeakAurasDisplayButton", 60 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index 868fcdb..ee48941 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -143,7 +143,9 @@ local function addCollapsibleHeader(options, key, input, order, isGroupTab) if notcollapsable then return "Interface\\AddOns\\WeakAuras\\Media\\Textures\\bullet1", 18, 18 else - return isCollapsed() and "Interface\\AddOns\\WeakAuras\\Media\\Textures\\expand" or "Interface\\AddOns\\WeakAuras\\Media\\Textures\\collapse", 18, 18 + return isCollapsed() and "Interface\\AddOns\\WeakAuras\\Media\\Textures\\expand" + or "Interface\\AddOns\\WeakAuras\\Media\\Textures\\collapse", + 18, 18 end end, control = "WeakAurasExpand", @@ -1248,8 +1250,10 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g }, }; - OptionsPrivate.commonOptions.AddCodeOption(positionOptions, data, L["Custom Anchor"], "custom_anchor", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-anchor-function", - 71.5, function() return not(data.anchorFrameType == "CUSTOM" and not IsParentDynamicGroup()) end, {"customAnchor"}, false, { setOnParent = group }) + OptionsPrivate.commonOptions.AddCodeOption(positionOptions, data, L["Custom Anchor"], "custom_anchor", + "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-anchor-function", + 71.5, function() return not(data.anchorFrameType == "CUSTOM" and not IsParentDynamicGroup()) end, + {"customAnchor"}, false, { setOnParent = group }) return positionOptions; end @@ -1380,7 +1384,8 @@ local function AddCodeOption(args, data, name, prefix, url, order, hiddenFunc, p tinsert(options.extraFunctions, 1, { buttonLabel = L["Expand"], func = function() - OptionsPrivate.OpenTextEditor(OptionsPrivate.GetPickedDisplay(), path, encloseInFunction, options.multipath, options.reloadOptions, options.setOnParent, url, options.validator) + OptionsPrivate.OpenTextEditor(OptionsPrivate.GetPickedDisplay(), path, encloseInFunction, options.multipath, + options.reloadOptions, options.setOnParent, url, options.validator) end }); diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 856b9a7..748d23e 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -206,6 +206,20 @@ local function createOptions(id, data) OptionsPrivate.ResetMoverSizer() end, }, + centerType = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Aura Order"], + order = 3, + values = function() + if data.grow == "HORIZONTAL" then + return OptionsPrivate.Private.centered_types_h + else + return OptionsPrivate.Private.centered_types_v + end + end, + hidden = function() return data.grow ~= "HORIZONTAL" and data.grow ~= "VERTICAL" end, + }, -- circle grow options constantFactor = { type = "select", diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index 641371a..be6f75f 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -704,4 +704,5 @@ local function createIcon() end -- Register new region type options with WeakAuras -WeakAuras.RegisterRegionOptions("group", createOptions, createIcon, L["Group"], createThumbnail, modifyThumbnail, L["Controls the positioning and configuration of multiple displays at the same time"]); +WeakAuras.RegisterRegionOptions("group", createOptions, createIcon, L["Group"], createThumbnail, modifyThumbnail, + L["Controls the positioning and configuration of multiple displays at the same time"]) diff --git a/WeakAurasOptions/RegionOptions/Icon.lua b/WeakAurasOptions/RegionOptions/Icon.lua index 538cd95..7709aad 100644 --- a/WeakAurasOptions/RegionOptions/Icon.lua +++ b/WeakAurasOptions/RegionOptions/Icon.lua @@ -94,6 +94,12 @@ local function createOptions(id, data) line = L["%s Keep Aspect Ratio"]:format(line) changed = true end + if data.texXOffset and data.texXOffset ~= 0 then + line = L["%s X offset by %d"]:format(line, data.texXOffset) + end + if data.texYOffset and data.texYOffset ~= 0 then + line = L["%s Y offset by %d"]:format(line, data.texYOffset) + end if not changed then line = L["%s Default Alpha, Zoom, Icon Inset, Aspect Ratio"]:format(line) end @@ -153,12 +159,41 @@ local function createOptions(id, data) order = 7.05, hidden = hiddenIconExtra, }, + texXOffset = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth - indentWidth, + name = L["Texture X Offset"], + order = 7.06, + min = -1, + max = 1, + bigStep = 0.1, + hidden = hiddenIconExtra, + }, + texYOffset = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Texture Y Offset"], + order = 7.07, + min = -1, + max = 1, + bigStep = 0.1, + hidden = hiddenIconExtra, + }, + iconExtra_space3 = { + type = "description", + name = "", + width = indentWidth, + order = 7.08, + hidden = hiddenIconExtra, + }, iconInset = { type = "range", control = "WeakAurasSpinBox", width = WeakAuras.normalWidth - indentWidth, name = L["Icon Inset"], - order = 7.06, + order = 7.09, min = 0, max = 1, bigStep = 0.01, @@ -171,7 +206,7 @@ local function createOptions(id, data) type = "toggle", width = WeakAuras.normalWidth, name = L["Keep Aspect Ratio"], - order = 7.07, + order = 7.10, hidden = hiddenIconExtra, }, iconExtraAnchor = { @@ -222,6 +257,21 @@ local function createOptions(id, data) order = 100, name = "", }, + ccWarning = { + type = "description", + width = WeakAuras.doubleWidth, + name = function() + if OmniCC then + return L["The addon OmniCC is enabled. It might add cooldown numbers to the swipe. You can configure these in the OmniCC settings"] + elseif ElvUI then + return L["The addon ElvUI is enabled. It might add cooldown numbers to the swipe. You can configure these in the ElvUI settings"] + else + return L["Cooldown Numbers might be added by WoW. You can configure these in the game settings."] + end + end, + order = 11.7, + hidden = function() return data.cooldownTextDisabled end + }, }; return { diff --git a/WeakAurasOptions/RegionOptions/Model.lua b/WeakAurasOptions/RegionOptions/Model.lua index d4ac7dd..fd718ed 100644 --- a/WeakAurasOptions/RegionOptions/Model.lua +++ b/WeakAurasOptions/RegionOptions/Model.lua @@ -297,4 +297,5 @@ local templates = { }, } -WeakAuras.RegisterRegionOptions("model", createOptions, createIcon, L["Model"], createThumbnail, modifyThumbnail, L["Shows a 3D model from the game files"], templates); +WeakAuras.RegisterRegionOptions("model", createOptions, createIcon, L["Model"], createThumbnail, modifyThumbnail, + L["Shows a 3D model from the game files"], templates) From 4c4b84863f4fe59308b305493dfe38649a5e52f2 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 10 Jan 2025 19:24:25 +0100 Subject: [PATCH 019/153] from retail --- WeakAuras/AnchorToWeakAuras.lua | 72 +++++++++++++++++++ WeakAuras/AuraEnvironment.lua | 5 +- WeakAuras/GenericTrigger.lua | 61 +++++++++------- WeakAuras/Prototypes.lua | 5 +- WeakAuras/Transmission.lua | 3 + WeakAuras/WeakAuras.lua | 20 ++++-- WeakAuras/WeakAuras.toc | 1 + .../AceGUIWidget-WeakAurasExpand.lua | 3 +- ...GUIWidget-WeakAurasPendingUpdateButton.lua | 5 +- WeakAurasOptions/OptionsFrames/Update.lua | 18 +++++ 10 files changed, 160 insertions(+), 33 deletions(-) create mode 100644 WeakAuras/AnchorToWeakAuras.lua diff --git a/WeakAuras/AnchorToWeakAuras.lua b/WeakAuras/AnchorToWeakAuras.lua new file mode 100644 index 0000000..ae24901 --- /dev/null +++ b/WeakAuras/AnchorToWeakAuras.lua @@ -0,0 +1,72 @@ +--- @type string, Private +local AddonName, Private = ... + +--- @type table +local attachedToTarget = {} +--- @type table> +local targetToAttached = {} + +-- Handles + + +--- @type fun(_: any, uid: uid, id: auraId) +local function OnDelete(_, uid, id) + local target = attachedToTarget[id] + if target then + if targetToAttached[target] then + targetToAttached[target][id] = nil + end + attachedToTarget[id] = nil + end +end + +--- @type fun(_: any, uid: uid, oldId: auraId, newId: auraId) +local function OnRename(_, uid, oldId, newId) + + local target = attachedToTarget[oldId] + if target then + -- renamed aura is an attached aura + attachedToTarget[newId] = attachedToTarget[oldId] + attachedToTarget[oldId] = nil + + targetToAttached[target][oldId] = nil + targetToAttached[target][newId] = true + end + + -- renamed aura is a targeted aura + if targetToAttached[oldId] then + for attached in pairs(targetToAttached[oldId]) do + local data = WeakAuras.GetData(attached) + if data then + data.anchorFrameFrame = "WeakAuras:" .. newId + WeakAuras.Add(data, nil, true) + end + + attachedToTarget[attached] = newId + end + targetToAttached[newId] = targetToAttached[oldId] + targetToAttached[oldId] = nil + end + +end + +--- @type fun(_: any, uid: uid, id: auraId, data: auraData, simpleChange: boolean) +local function OnAdd(_, uid, id, data, simpleChange) + if simpleChange then + return + end + OnDelete(nil, uid, id) + if data.anchorFrameType == "SELECTFRAME" + and data.anchorFrameFrame + and data.anchorFrameFrame:sub(1, 10) == "WeakAuras:" + then + local target = data.anchorFrameFrame:sub(11) + attachedToTarget[data.id] = target + targetToAttached[target] = targetToAttached[target] or {} + targetToAttached[target][data.id] = true + end +end + +Private.callbacks:RegisterCallback("Delete", OnDelete) +Private.callbacks:RegisterCallback("Rename", OnRename) +Private.callbacks:RegisterCallback("Add", OnAdd) diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index dd3d8d7..fa5f8cb 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -436,9 +436,12 @@ local FakeWeakAurasMixin = { -- Note these shouldn't exist in the WeakAuras namespace, but moving them takes a bit of effort, -- so for now just block them and clean them up later genericTriggerTypes = true, - newFeatureString = true, spellCache = true, StopMotion = true, + -- We block the loaded table, even though it doesn't exist anymore, + -- because some versions of ZT Tracker overwrote region:Collpase() and + -- checked for WeakAuras.loaded in there + loaded = true }, override = { me = UnitName("player"), diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 32867ba..c94d868 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -2126,14 +2126,18 @@ do cdReadyFrame:SetScript("OnUpdate", nil) Private.StartProfileSystem("generictrigger cd tracking"); - if(event == "SPELL_UPDATE_COOLDOWN" + if type(event) == "number" then-- Called from OnUpdate! + Private.CheckSpellKnown() + Private.CheckCooldownReady() + Private.CheckItemSlotCooldowns() + elseif(event == "SPELL_UPDATE_COOLDOWN" or event == "RUNE_POWER_UPDATE" or event == "RUNE_TYPE_UPDATE" or event == "ACTIONBAR_UPDATE_COOLDOWN" or event == "PLAYER_TALENT_UPDATE" or event == "CHARACTER_POINTS_CHANGED") then Private.CheckCooldownReady(); elseif(event == "SPELLS_CHANGED") then - Private.CheckSpellKnown(); - Private.CheckCooldownReady(); + Private.CheckSpellKnown() + Private.CheckCooldownReady() elseif(event == "UNIT_SPELLCAST_SENT") then local unit, name, _ = ...; if(unit == "player") then @@ -3403,31 +3407,35 @@ do castLatencyFrame:RegisterEvent("CURRENT_SPELL_CAST_CHANGED") castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_START") castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") - castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_STOP") castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED") + castLatencyFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") - castLatencyFrame:SetScript("OnEvent", function(self, event, unit) + castLatencyFrame:SetScript("OnEvent", function(self, event, unit, ...) if unit and unit ~= "player" then return end - if event == "UNIT_SPELLCAST_START" then - Private.LAST_CURRENT_SPELL_CAST_START = select(4, UnitCastingInfo("player")) / 1000 - elseif event == "UNIT_SPELLCAST_CHANNEL_START" then - Private.LAST_CURRENT_SPELL_CAST_START = select(4, UnitChannelInfo("player")) / 1000 - elseif event == "CURRENT_SPELL_CAST_CHANGED" then - -- We want to store the CURRENT_SPELL_CAST_CHANGED time - -- that was the last before the actual START event - -- This prevents updating the CURRENT_SPELL_CAST_CHANGED time after - -- we got the start time - if not Private.LAST_CURRENT_SPELL_CAST_START then - Private.LAST_CURRENT_SPELL_CAST_CHANGED = GetTime() - end - else -- STOP EVENTS - Private.LAST_CURRENT_SPELL_CAST_START = nil + + if event == "CURRENT_SPELL_CAST_CHANGED" then + castLatencyFrame.sendTime = GetTime() + return + end + if event == "UNIT_SPELLCAST_SUCCEEDED" or event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_CHANNEL_STOP" or event == "UNIT_SPELLCAST_INTERRUPTED" then + castLatencyFrame.sendTime = nil + return + end + if castLatencyFrame.sendTime then + castLatencyFrame.timeDiff = (GetTime() - castLatencyFrame.sendTime) + else + castLatencyFrame.timeDiff = nil end end) end end + + function WeakAuras.GetCastLatency() + return castLatencyFrame and castLatencyFrame.timeDiff or 0 + end + end -- Nameplate Target @@ -3764,9 +3772,14 @@ function GenericTrigger.CanHaveDuration(data, triggernum) return false end +function GenericTrigger.GetTsuConditionVariables(id, triggernum) + local ok, variables = xpcall(events[id][triggernum].tsuConditionVariables, Private.GetErrorHandlerId(id, L["Custom Variables"])); + if ok then + return variables + end +end + --- Returns a table containing the names of all overlays --- @param data --- @param triggernum function GenericTrigger.GetOverlayInfo(data, triggernum) local result; @@ -3786,7 +3799,7 @@ function GenericTrigger.GetOverlayInfo(data, triggernum) if (trigger.type == "custom") then if (trigger.custom_type == "stateupdate") then local count = 0; - local variables = events[data.id][triggernum].tsuConditionVariables(); + local variables = GenericTrigger.GetTsuConditionVariables(data.id, triggernum) if (type(variables) == "table") then if (type(variables.additionalProgress) == "table") then count = #variables.additionalProgress; @@ -3941,7 +3954,7 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) end else if (trigger.custom_type == "stateupdate") then - local variables = events[data.id][triggernum].tsuConditionVariables(); + local variables = GenericTrigger.GetTsuConditionVariables(data.id, triggernum) if (type(variables) == "table") then for var, varData in pairs(variables) do if (type(varData) == "table") then @@ -4115,7 +4128,7 @@ function GenericTrigger.GetTriggerConditions(data, triggernum) elseif (trigger.custom_type == "stateupdate") then if (events[data.id][triggernum] and events[data.id][triggernum].tsuConditionVariables) then Private.ActivateAuraEnvironment(data.id, nil, nil, nil, true) - local result = events[data.id][triggernum].tsuConditionVariables() + local result = GenericTrigger.GetTsuConditionVariables(data.id, triggernum) Private.ActivateAuraEnvironment(nil) if (type(result)) ~= "table" then return nil; diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 19be76c..f83d3d0 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -6267,8 +6267,9 @@ Private.event_prototypes = { { name = L["Latency"], func = function(trigger, state) - if not Private.LAST_CURRENT_SPELL_CAST_START or not Private.LAST_CURRENT_SPELL_CAST_CHANGED then return 0, 0 end - return 0, Private.LAST_CURRENT_SPELL_CAST_START - Private.LAST_CURRENT_SPELL_CAST_CHANGED + local latency = WeakAuras.GetCastLatency() + if not latency then return 0, 0 end + return 0, latency end, enable = function(trigger) return trigger.use_showLatency and trigger.unit == "player" diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 179bdc7..692edea 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -504,6 +504,9 @@ function WeakAuras.Import(inData, target, callbackFunc) else target = targetData end + if data.uid and data.uid ~= target.uid then + return false, "Invalid update target, uids don't match." + end end WeakAuras.PreAdd(data) if children then diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index e54b9d8..7a6ff00 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2672,6 +2672,7 @@ local function pAdd(data, simpleChange) end end Private.UpdatedTriggerState(id) + Private.callbacks:Fire("Add", data.uid, data.id, data, simpleChange) else Private.DebugLog.SetEnabled(data.uid, data.information.debugLog) @@ -2778,6 +2779,7 @@ local function pAdd(data, simpleChange) end Private.UpdateSoundIcon(data) + Private.callbacks:Fire("Add", data.uid, data.id, data, simpleChange) end end @@ -4311,7 +4313,7 @@ local function nextState(char, state) return state end -local function ContainsPlaceHolders(textStr, symbolFunc) +local function ContainsPlaceHolders(textStr, symbolFunc, checkDoublePercent) if not textStr then return false end @@ -4320,13 +4322,17 @@ local function ContainsPlaceHolders(textStr, symbolFunc) local state = 0 local currentPos = 1 local start = 1 + local containsDoublePercent = false while currentPos <= endPos do local char = string.byte(textStr, currentPos); local nextState = nextState(char, state) if state == 1 then -- Last char was a % - if char == 123 then + if char == 123 then -- { start = currentPos + 1 + elseif char == 37 then -- % + containsDoublePercent = true + start = currentPos else start = currentPos end @@ -4350,6 +4356,9 @@ local function ContainsPlaceHolders(textStr, symbolFunc) end end + if checkDoublePercent then + return containsDoublePercent + end return false end @@ -4378,7 +4387,7 @@ function Private.ContainsPlaceHolders(textStr, toCheck) end function Private.ContainsAnyPlaceHolders(textStr) - return ContainsPlaceHolders(textStr, function(symbol) return true end) + return ContainsPlaceHolders(textStr, function(symbol) return true end, true) end local function ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates, formatters) @@ -4432,6 +4441,9 @@ function Private.ReplacePlaceHolders(textStr, region, customFunc, useHiddenState if (endPos == 2) then if string.byte(textStr, 1) == 37 then local symbol = string.sub(textStr, 2) + if symbol == "%" then + return "%" -- Double % input + end local value = ValueForSymbol(symbol, region, customFunc, regionState, regionStates, useHiddenStates, formatters); if (value) then textStr = tostring(value); @@ -4455,7 +4467,7 @@ function Private.ReplacePlaceHolders(textStr, region, customFunc, useHiddenState end end elseif state == 1 then -- Percent Start State - if char == 123 then + if char == 123 then -- { sign start = currentPos + 1 else start = currentPos diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index 729e5d7..9d299e5 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -39,6 +39,7 @@ Transmission.lua Modernize.lua Animations.lua Conditions.lua +AnchorToWeakAuras.lua # Trigger systems BuffTrigger2.lua diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua index 7fa0556..1732ec0 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua @@ -3,7 +3,7 @@ Button Widget for our Expand button -------------------------------------------------------------------------------]] if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasExpand", 4 +local Type, Version = "WeakAurasExpand", 5 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -38,6 +38,7 @@ local methods = { self:SetHeight(110) self:SetWidth(110) self:SetLabel() + self:SetFontObject(GameFontHighlightLarge) self:SetImage(nil) self:SetImageSize(64, 64) self:SetDisabled(false) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua index 6d58dd8..e475d98 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua @@ -99,7 +99,10 @@ local methods = { func = function() local auraData = WeakAuras.GetData(auraId) if auraData then - WeakAuras.Import(self.companionData.encoded, auraData) + local success, error = WeakAuras.Import(self.companionData.encoded, auraData) + if not success then + WeakAuras.prettyPrint(error) + end end end }, diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index bba4db8..26ac567 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -341,6 +341,17 @@ local function BuildUidMap(data, children, type) if data.parent then uidMap.map[data.uid].parent = idToUid[data.parent] end + + -- Handle anchorFrameFrame + if data.anchorFrameType == "SELECTFRAME" + and data.anchorFrameFrame + and data.anchorFrameFrame:sub(1, 10) == "WeakAuras:" + then + local target = data.anchorFrameFrame:sub(11) + if idToUid[target] then + uidMap.map[data.uid].anchorFrameFrame = idToUid[target] + end + end end local function handleSortHybridTable(data) @@ -504,6 +515,13 @@ local function BuildUidMap(data, children, type) data.controlledChildren = nil end + if self.map[uid].anchorFrameFrame then + local target = self:GetIdFor(self.map[uid].anchorFrameFrame) + if target then + data.anchorFrameFrame = "WeakAuras:" .. target + end + end + if data.regionType == "dynamicgroup" then data.sortHybridTable = {} for i, childUid in ipairs(self.map[uid].controlledChildren) do From 713047adb20bcf66a39927a715c2d66bfbe6ff4b Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 10 Jan 2025 19:42:21 +0100 Subject: [PATCH 020/153] revert Fix corner case in anchoring auras --- WeakAuras/WeakAuras.lua | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 7a6ff00..c1fa53c 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2204,22 +2204,6 @@ function Private.AddMany(tbl, takeSnapshots) end end - -- Now fix up anchors, see #3971, where aura p was anchored to aura c and where c was a child of p, thus c was anchored to p - -- The game used to detect such anchoring circles. We can't detect all of them, but at least detect the one from the ticket. - for target, source in pairs(anchorTargets) do - -- We walk up the parent's of target, to check for source - local parent = target - if idtable[target] then - while(parent) do - if parent == source then - WeakAuras.prettyPrint(L["Warning: Anchoring to your own child '%s' in aura '%s' is imposssible."]:format(target, source)) - idtable[source].anchorFrameType = "SCREEN" - end - parent = idtable[parent].parent - end - end - end - local order = loadOrder(tbl, idtable) coroutine.yield() local groups = {} @@ -5039,16 +5023,6 @@ local function GetAnchorFrame(data, region, parent) return parent; end - local targetData = WeakAuras.GetData(frame_name) - if targetData then - for parentData in Private.TraverseParents(targetData) do - if parentData.id == data.id then - WeakAuras.prettyPrint(L["Warning: Anchoring to your own child '%s' in aura '%s' is imposssible."]:format(frame_name, data.id)) - return parent - end - end - end - if Private.regions[frame_name] and Private.regions[frame_name].region then return Private.regions[frame_name].region; end From d7233fe5d7bb0189a06d38813dd3b7cc10232530 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 11 Jan 2025 16:33:30 +0100 Subject: [PATCH 021/153] from retail --- WeakAuras/Modernize.lua | 11 +++ WeakAuras/RegionTypes/DynamicGroup.lua | 93 +++++++++++++++++-- WeakAuras/SubRegionTypes/Glow.lua | 17 ++-- WeakAurasOptions/ActionOptions.lua | 13 ++- WeakAurasOptions/AuthorOptions.lua | 5 +- WeakAurasOptions/ConditionOptions.lua | 13 ++- .../RegionOptions/DynamicGroup.lua | 34 +++++++ 7 files changed, 159 insertions(+), 27 deletions(-) diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 7eab34a..24c673a 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1216,6 +1216,17 @@ function Private.Modernize(data) data.forceEvents = nil end + if data.internalVersion < 62 then + if data.regionType == "dynamicgroup" then + if data.sort == "CUSTOM" and type(data.sortOn) ~= "string" then + data.sortOn = "changed" + end + if data.grow == "CUSTOM" and type(data.growOn) ~= "string" then + data.growOn = "changed" + end + end + end + if data.internalVersion < 67 or data.internalVersion > WeakAuras.InternalVersion() then local castMigrationNeeded = data.internalVersion < 67 data.internalVersion = WeakAuras.InternalVersion() diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index de646a5..57db178 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -112,6 +112,8 @@ local function create(parent) region.sortedChildren = {} region.controlledChildren = {} region.updatedChildren = {} + region.sortStates = {} + region.growStates = {} local background = CreateFrame("Frame", nil, region) region.background = background region.selfPoint = "TOPLEFT" @@ -272,7 +274,7 @@ local sorters = { return WeakAuras.ComposeSorts( WeakAuras.SortAscending({"dataIndex"}), WeakAuras.SortAscending({"region", "state", "index"}) - ) + ), { index = true } end, hybrid = function(data) local sortHybridTable = data.sortHybridTable or {} @@ -303,23 +305,31 @@ local sorters = { sortHybridStatus, sortExpirationTime, WeakAuras.SortAscending({"dataIndex"}) - ) + ), {expirationTime = true} end, ascending = function(data) return WeakAuras.ComposeSorts( WeakAuras.SortAscending({"region", "state", "expirationTime"}), WeakAuras.SortAscending({"dataIndex"}) - ) + ), {expirationTime = true} end, descending = function(data) return WeakAuras.ComposeSorts( WeakAuras.SortDescending({"region", "state", "expirationTime"}), WeakAuras.SortAscending({"dataIndex"}) - ) + ), {expirationTime = true} end, custom = function(data) local sortStr = data.customSort or "" local sortFunc = WeakAuras.LoadFunction("return " .. sortStr) or noop + local sortOn = nil + local events = WeakAuras.split(data.sortOn or "") + if #events > 0 then + sortOn = {} + for _, event in ipairs(events) do + events[event] = true + end + end return function(a, b) Private.ActivateAuraEnvironment(data.id) local ok, result = pcall(sortFunc, a, b) @@ -329,7 +339,7 @@ local sorters = { else return result end - end + end, sortOn end } WeakAuras.SortFunctions = sorters @@ -914,6 +924,14 @@ local growers = { CUSTOM = function(data) local growStr = data.customGrow or "" local growFunc = WeakAuras.LoadFunction("return " .. growStr) or noop + local growOn = nil + local events = WeakAuras.split(data.growOn or "") + if #events > 0 then + growOn = {} + for _, event in ipairs(events) do + events[event] = true + end + end return function(newPositions, activeRegions) Private.ActivateAuraEnvironment(data.id) local ok, ret = pcall(growFunc, newPositions, activeRegions) @@ -922,7 +940,7 @@ local growers = { Private.GetErrorHandlerId(data.id, L["Custom Grow"]) wipe(newPositions) end - end + end, growOn end } WeakAuras.GrowFunctions = growers @@ -939,6 +957,50 @@ local function SafeGetPos(region, func) end end +local function isDifferent(regionData, cache, events) + local id = regionData.id + local cloneId = regionData.cloneId or "" + local state = regionData.region.state + if not events then + return false + elseif events.changed then + return true -- escape hatch, not super recommended + else + local isDifferent = false + if not cache[id] then + isDifferent = true + local cachedState = {} + cache[id] = {[cloneId] = cachedState} + for event in pairs(events) do + cachedState[event] = state[event] + end + elseif not cache[id][cloneId] then + isDifferent = true + local cachedState = {} + cache[id][cloneId] = cachedState + for event in pairs(events) do + cachedState[event] = state[event] + end + else + local cachedState = cache[id][cloneId] + for event in pairs(events) do + if regionData.region.state[event] ~= cachedState[event] then + cachedState[event] = regionData.region.state[event] + isDifferent = true + end + end + end + return isDifferent + end +end + +local function clearCache(cache, id, cloneId) + cloneId = cloneId or "" + if cache[id] then + cache[id][cloneId] = nil + end +end + local function modify(parent, region, data) Private.FixGroupChildrenOrderForGroup(data) region:SetScale(data.scale and data.scale > 0 and data.scale <= 10 and data.scale or 1) @@ -1065,6 +1127,8 @@ local function modify(parent, region, data) Private.StartProfileAura(data.id) self.needToReload = false self.sortedChildren = {} + self.sortStates = {} + self.growStates = {} self.controlledChildren = {} self.updatedChildren = {} self.controlPoints:ReleaseAll() @@ -1128,9 +1192,14 @@ local function modify(parent, region, data) -- if it has been, then don't insert it again if not regionData.active and self.updatedChildren[regionData] == nil then tinsert(self.sortedChildren, regionData) + self.updatedChildren[regionData] = true + self:SortUpdatedChildren() + elseif isDifferent(regionData, self.sortStates, self.sortOn) then + self.updatedChildren[regionData] = true + self:SortUpdatedChildren() + elseif isDifferent(regionData, self.growStates, self.growOn) then + self:PositionChildren() end - self.updatedChildren[regionData] = true - self:SortUpdatedChildren() end function region:RemoveChild(childID, cloneID) @@ -1140,6 +1209,8 @@ local function modify(parent, region, data) if not regionData then return end releaseRegionData(regionData) self.updatedChildren[regionData] = false + clearCache(self.sortStates, childID, cloneID) + clearCache(self.growStates, childID, cloneID) self:SortUpdatedChildren() end @@ -1150,10 +1221,12 @@ local function modify(parent, region, data) if regionData and not regionData.region.toShow then self.updatedChildren[regionData] = false end + clearCache(self.sortStates, childID, cloneID) + clearCache(self.growStates, childID, cloneID) self:SortUpdatedChildren() end - region.sortFunc = createSortFunc(data) + region.sortFunc, region.sortOn = createSortFunc(data) function region:SortUpdatedChildren() -- iterates through cache to insert all updated children in the right spot @@ -1198,7 +1271,7 @@ local function modify(parent, region, data) end end - region.growFunc = createGrowFunc(data) + region.growFunc, region.growOn = createGrowFunc(data) region.anchorPerUnit = data.useAnchorPerUnit and data.anchorPerUnit local animate = data.animate diff --git a/WeakAuras/SubRegionTypes/Glow.lua b/WeakAuras/SubRegionTypes/Glow.lua index 1b94ae9..7baee07 100644 --- a/WeakAuras/SubRegionTypes/Glow.lua +++ b/WeakAuras/SubRegionTypes/Glow.lua @@ -2,13 +2,8 @@ if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local LCG = LibStub("LibCustomGlow-1.0") -local MSQ, MSQ_Version = LibStub("Masque", true); -if MSQ then - if MSQ_Version <= 80100 then - MSQ = nil - end -end -local L = WeakAuras.L; +local MSQ = LibStub("Masque", true); +local L = WeakAuras.L local default = function(parentType) local options = { @@ -177,16 +172,16 @@ local funcs = { if (visible) then self.__MSQ_Shape = self:GetParent().button.__MSQ_Shape self:Show() - glowStart(self, self, color); + glowStart(self, self, color) else - self.glowStop(self); + self.glowStop(self) self:Hide() end elseif (visible) then self:Show() - glowStart(self, self, color); + glowStart(self, self, color) else - self.glowStop(self); + self.glowStop(self) self:Hide() end end, diff --git a/WeakAurasOptions/ActionOptions.lua b/WeakAurasOptions/ActionOptions.lua index 4019d72..6d300ba 100644 --- a/WeakAurasOptions/ActionOptions.lua +++ b/WeakAurasOptions/ActionOptions.lua @@ -23,6 +23,9 @@ else end end +--- a sound from each setter +local lastPlayedSoundFromSet + function OptionsPrivate.GetActionOptions(data) local action = { type = "group", @@ -63,9 +66,15 @@ function OptionsPrivate.GetActionOptions(data) data.actions[field][value] = v; end if(value == "sound" or value == "sound_path") then - pcall(PlaySoundFile, v, "Master"); + if lastPlayedSoundFromSet ~= GetTime() then + pcall(PlaySoundFile, v, "Master") + lastPlayedSoundFromSet = GetTime() + end elseif(value == "sound_kit_id") then - pcall(PlaySound, v, "Master"); + if lastPlayedSoundFromSet ~= GetTime() then + pcall(PlaySound, v, "Master") + lastPlayedSoundFromSet = GetTime() + end end WeakAuras.Add(data); if(value == "message") then diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index cc340f7..2df4147 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -2474,17 +2474,18 @@ local function valuesAreEqual(t1, t2) if ty1 ~= ty2 then return false end + if ty1 == "number" then + return abs(t1 - t2) < 1e-9 + end if ty1 ~= "table" then return false end - for k1, v1 in pairs(t1) do local v2 = t2[k1] if v2 == nil or not valuesAreEqual(v1, v2) then return false end end - for k2, v2 in pairs(t2) do local v1 = t1[k2] if v1 == nil or not valuesAreEqual(v1, v2) then diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 44be1bf..489bf0a 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -187,13 +187,22 @@ local function filterUsedProperties(indexToProperty, allDisplays, usedProperties return filtered; end +--- a sound from each setter +local lastPlayedSoundFromSet + local function wrapWithPlaySound(func, kit) return function(info, v) func(info, v); if (tonumber(v)) then - pcall(PlaySound, tonumber(v), "Master"); + if lastPlayedSoundFromSet ~= GetTime() then + pcall(PlaySound, tonumber(v), "Master") + lastPlayedSoundFromSet = GetTime() + end else - pcall(PlaySoundFile, v, "Master"); + if lastPlayedSoundFromSet ~= GetTime() then + pcall(PlaySoundFile, v, "Master") + lastPlayedSoundFromSet = GetTime() + end end end end diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 748d23e..8d06068 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -139,6 +139,23 @@ local function createOptions(id, data) OptionsPrivate.ResetMoverSizer() end, }, + growOn = { + type = "input", + width = WeakAuras.doubleWidth, + name = L["Run on..."], + desc = L["You can add a comma-separated list of state values here that (when changed) WeakAuras should also run the Grow Code on.\n\nWeakAuras will always run custom grow code if you include 'changed' in this list, or when a region is added, removed, or re-ordered."], + order = 2 - 0.1, + get = function() + return data.growOn or "" + end, + hidden = function() return data.grow ~= "CUSTOM" end, + set = function(info, v) + data.growOn = v + WeakAuras.Add(data) + WeakAuras.ClearAndUpdateOptions(data.id) + OptionsPrivate.ResetMoverSizer() + end + }, useAnchorPerUnit = { type = "toggle", order = 1.5, @@ -366,6 +383,23 @@ local function createOptions(id, data) order = 20, values = OptionsPrivate.Private.group_sort_types }, + sortOn = { + type = "input", + width = WeakAuras.doubleWidth, + name = L["Run on..."], + desc = L["You can add a comma-separated list of state values here that (when changed) WeakAuras should also run the sort code on.WeakAuras will always run custom sort code if you include 'changed' in this list, or when a region is added, removed."], + order = 21 - 0.1, + get = function() + return data.sortOn or "" + end, + hidden = function() return data.sort ~= "custom" end, + set = function(info, v) + data.sortOn = v + WeakAuras.Add(data) + WeakAuras.ClearAndUpdateOptions(data.id) + OptionsPrivate.ResetMoverSizer() + end + }, -- custom sort option added below hybridPosition = { type = "select", From 8fa335c1995444fc51ae9b18a3533e64cdca29ee Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 11 Jan 2025 16:38:26 +0100 Subject: [PATCH 022/153] from retail --- WeakAuras/Types.lua | 33 ++++++++++++ WeakAuras/WeakAuras.lua | 7 ++- WeakAurasOptions/AuthorOptions.lua | 81 ++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index b9c5234..565f6ab 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -2224,8 +2224,11 @@ Private.sound_types = { [" KitID"] = " " .. L["Sound by Kit ID"] } +Private.sound_file_types = {} + for name, path in next, LSM:HashTable("sound") do Private.sound_types[path] = name + Private.sound_file_types[path] = name end LSM.RegisterCallback(WeakAuras, "LibSharedMedia_Registered", function(_, mediatype, key) @@ -2233,6 +2236,7 @@ LSM.RegisterCallback(WeakAuras, "LibSharedMedia_Registered", function(_, mediaty local path = LSM:Fetch(mediatype, key) if path then Private.sound_types[path] = key + Private.sound_file_types[path] = key end end end) @@ -2576,6 +2580,7 @@ Private.author_option_classes = { range = "simple", color = "simple", select = "simple", + media = "simple", multiselect = "simple", description = "noninteractive", space = "noninteractive", @@ -2593,6 +2598,7 @@ Private.author_option_types = { select = L["Dropdown Menu"], space = L["Space"], multiselect = L["Toggle List"], + media = L["Media"], header = L["Separator"], group = L["Option Group"], } @@ -2643,6 +2649,10 @@ Private.author_option_fields = { useHeight = false, height = 1, }, + media = { + mediaType = "sound", + media = "Interface\\AddOns\\WeakAuras\\Media\\Sounds\\AirHorn.ogg" + }, multiselect = { default = {true}, values = {"val1"}, @@ -2666,6 +2676,29 @@ Private.author_option_fields = { } } +Private.shared_media_types = { + sound = L["Sound"], + font = L["Font"], + border = L["Border"], + background = L["Background"], + statusbar = L["Status Bar"] +} + +Private.author_option_media_defaults = { + sound = "Interface\\AddOns\\WeakAuras\\Media\\Sounds\\AirHorn.ogg", + font = "Friz Quadrata TT", + border = "1 Pixel", + background = "None", + statusbar = "Blizzard", +} + +Private.author_option_media_controls = { + statusbar = "LSM30_Statusbar", + border = "LSM30_Border", + background = "LSM30_Background", + font = "LSM30_Font" +} + Private.array_entry_name_types = { [-1] = L["Fixed Names"], [0] = L["Entry Order"], diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index c1fa53c..14c1d30 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2325,7 +2325,12 @@ local function validateUserConfig(data, options, config) local optionClass = Private.author_option_classes[option.type] if optionClass ~= "group" then local option = options[authorOptionKeys[key]] - if type(value) ~= type(option.default) then + if option.type == "media" then + -- sounds can be number or string, other kinds of media can only be string + if type(value) ~= "string" and (type(value) ~= "number" or option.mediaType ~= "sound") then + config[key] = option.default + end + elseif type(value) ~= type(option.default) then -- if type mismatch then we know that it can't be right if type(option.default) ~= "table" then config[key] = option.default diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index 2df4147..dafdd7c 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -975,6 +975,64 @@ typeControlAdders = { step = 1 } end, + media = function(options, args, data, order, prefix, i) + local option = options[i] + args[prefix .. "mediaType"] = { + type = "select", + width = WeakAuras.normalWidth, + name = name(option, "mediaType", L["Media Type"]), + desc = desc(option, "mediaType"), + values = OptionsPrivate.Private.shared_media_types, + order = order(), + get = get(option, "mediaType"), + set = function(_, value) + for _, optionData in pairs(option.references) do + local childOption = optionData.options[optionData.index] + local childData = optionData.data + childOption.mediaType = value + childOption.default = OptionsPrivate.Private.author_option_media_defaults[value] + WeakAuras.Add(childData) + end + WeakAuras.ClearAndUpdateOptions(data.id, true) + end + } + args[prefix .. "default"] = { + type = "select", + width = WeakAuras.doubleWidth, + name = name(option, "default", L["Default"]), + desc = desc(option, "default"), + values = function() + if option.mediaType == "sound" then + return OptionsPrivate.Private.sound_file_types + else + return AceGUIWidgetLSMlists[option.mediaType] + end + end, + sorting = function() + if option.mediaType == "sound" then + return OptionsPrivate.Private.SortOrderForValues(OptionsPrivate.Private.sound_file_types) + else + return nil + end + end, + dialogControl = OptionsPrivate.Private.author_option_media_controls[option.mediaType], + order = order(), + get = get(option, "default"), + set = function(_, value) + if option.mediaType == "sound" then + -- do this outside the deref loop, so we don't play the sound a million times + PlaySoundFile(value) + end + for _, optionData in pairs(option.references) do + local childOption = optionData.options[optionData.index] + local childData = optionData.data + childOption.default = value + WeakAuras.Add(childData) + end + WeakAuras.ClearAndUpdateOptions(data.id, true) + end + } + end, multiselect = function(options, args, data, order, prefix, i) local option = options[i] local values = getValues(option) @@ -2283,6 +2341,28 @@ local function addUserModeOption(options, args, data, order, prefix, i) end WeakAuras.ClearAndUpdateOptions(data.id, true) end + elseif optionType == "media" then + userOption.type = "select" + userOption.dialogControl = OptionsPrivate.Private.author_option_media_controls[option.mediaType] + userOption.values = function() + if option.mediaType == "sound" then + return OptionsPrivate.Private.sound_file_types + else + return AceGUIWidgetLSMlists[option.mediaType] + end + end + userOption.set = function(_, value) + if option.mediaType == "sound" then + PlaySoundFile(value) + end + for _, optionData in pairs(option.references) do + local childData = optionData.data + local childConfig = optionData.config + childConfig[option.key] = value + WeakAuras.Add(childData) + end + WeakAuras.ClearAndUpdateOptions(data.id, true) + end end elseif optionClass == "noninteractive" then if optionType == "header" then @@ -2361,6 +2441,7 @@ local significantFieldsForMerge = { groupType = true, limitType = true, size = true, + mediaType = true, } -- these fields are special cases, generally reserved for when the UI displays something based on the merged options From 96c5618c6b6d50aefbb672870d3035de4ca92dde Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 11 Jan 2025 16:43:29 +0100 Subject: [PATCH 023/153] from retail --- WeakAuras/RegionTypes/RegionPrototype.lua | 4 ++- WeakAuras/SubRegionTypes/SubText.lua | 30 ++++++++++++++--------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index 717ae18..cf5a902 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -24,7 +24,9 @@ local SubRegionEventSystem = end, RemoveSubscriber = function(self, event, subRegion) - tremove(self.events[event], tIndexOf(self.events[event], subRegion)) + if self.events[event] then + tremove(self.events[event], tIndexOf(self.events[event], subRegion)) + end end, Notify = function(self, event, ...) diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index 09747cb..3fa5cfa 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -246,18 +246,6 @@ local function modify(parent, region, parentData, data, first) region.FrameTick = FrameTick region.TimerTick = TimerTick - if Update then - parent.subRegionEvents:AddSubscriber("Update", region) - end - - if FrameTick then - parent.subRegionEvents:AddSubscriber("FrameTick", region) - end - - if TimerTick then - parent.subRegionEvents:AddSubscriber("TimerTick", region) - end - if not UpdateText then if text:GetFont() then local textStr = data.text_text @@ -288,7 +276,25 @@ local function modify(parent, region, parentData, data, first) function region:SetVisible(visible) if visible then self:Show() + if self.Update then + parent.subRegionEvents:AddSubscriber("Update", region) + end + if self.FrameTick then + parent.subRegionEvents:AddSubscriber("FrameTick", region) + end + if self.TimerTick then + parent.subRegionEvents:AddSubscriber("TimerTick", region) + end else + if self.Update then + parent.subRegionEvents:RemoveSubscriber("Update", region) + end + if self.FrameTick then + parent.subRegionEvents:RemoveSubscriber("FrameTick", region) + end + if self.TimerTick then + parent.subRegionEvents:RemoveSubscriber("TimerTick", region) + end self:Hide() end end From 1b50569bcc6bc7691eb81757d89b3830492e91dd Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 11 Jan 2025 17:15:56 +0100 Subject: [PATCH 024/153] from retail --- WeakAuras/RegionTypes/AuraBar.lua | 9 +- WeakAuras/RegionTypes/ProgressTexture.lua | 9 +- WeakAuras/RegionTypes/RegionPrototype.lua | 153 ++++++---------------- WeakAuras/RegionTypes/StopMotion.lua | 3 + WeakAuras/RegionTypes/Text.lua | 5 + WeakAuras/SubRegionTypes/Tick.lua | 2 - WeakAuras/SubscribableObject.lua | 74 +++++++++++ WeakAuras/WeakAuras.toc | 1 + WeakAuras/compat.lua | 9 ++ WeakAurasOptions/AuthorOptions.lua | 4 +- 10 files changed, 147 insertions(+), 122 deletions(-) create mode 100644 WeakAuras/SubscribableObject.lua diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index fae8774..bb785c8 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -1246,6 +1246,7 @@ local function modify(parent, region, data) return region.currentMin or 0, region.currentMax or 0 end + region.TimerTick = nil function region:Update() local state = region.state region:UpdateMinMax() @@ -1257,7 +1258,7 @@ local function modify(parent, region, data) end if region.TimerTick then region.TimerTick = nil - region:UpdateRegionHasTimerTick() + region.subRegionEvents:RemoveSubscriber("TimerTick", self) end expirationTime = GetTime() + (state.remaining or 0) else @@ -1266,7 +1267,7 @@ local function modify(parent, region, data) end if not region.TimerTick then region.TimerTick = TimerTick - region:UpdateRegionHasTimerTick() + region.subRegionEvents:AddSubscriber("TimerTick", self, true) end expirationTime = state.expirationTime and state.expirationTime > 0 and state.expirationTime or math.huge; end @@ -1283,7 +1284,7 @@ local function modify(parent, region, data) region:SetValue(value - region.currentMin, region.currentMax - region.currentMin); if region.TimerTick then region.TimerTick = nil - region:UpdateRegionHasTimerTick() + region.subRegionEvents:RemoveSubscriber("TimerTick", region) end else if region.paused then @@ -1292,7 +1293,7 @@ local function modify(parent, region, data) region:SetTime(0, math.huge) if region.TimerTick then region.TimerTick = nil - region:UpdateRegionHasTimerTick() + region.subRegionEvents:RemoveSubscriber("TimerTick", region) end end diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index e7ad55d..436e494 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -878,6 +878,7 @@ local function modify(parent, region, data) end end + region.TimerTick = nil function region:Update() local state = region.state @@ -890,7 +891,7 @@ local function modify(parent, region, data) end if region.TimerTick then region.TimerTick = nil - region:UpdateRegionHasTimerTick() + region.subRegionEvents:RemoveSubscriber("TimerTick", region) end expirationTime = GetTime() + (state.remaining or 0) else @@ -899,7 +900,7 @@ local function modify(parent, region, data) end if not region.TimerTick then region.TimerTick = TimerTick - region:UpdateRegionHasTimerTick() + region.subRegionEvents:AddSubscriber("TimerTick", region, true) end expirationTime = state.expirationTime and state.expirationTime > 0 and state.expirationTime or math.huge; end @@ -945,7 +946,7 @@ local function modify(parent, region, data) region:SetValue(value - adjustMin, max - adjustMin); if region.TimerTick then region.TimerTick = nil - region:UpdateRegionHasTimerTick() + region.subRegionEvents:RemoveSubscriber("TimerTick", region) end else if region.paused then @@ -954,7 +955,7 @@ local function modify(parent, region, data) region:SetTime(0, math.huge) if region.TimerTick then region.TimerTick = nil - region:UpdateRegionHasTimerTick() + region.subRegionEvents:RemoveSubscriber("TimerTick", region) end end diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index cf5a902..2ba84de 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -6,47 +6,6 @@ local L = WeakAuras.L; WeakAuras.regionPrototype = {}; - -local SubRegionEventSystem = -{ - ClearSubscribers = function(self) - self.events = {} - end, - - AddSubscriber = function(self, event, subRegion) - if not subRegion[event] then - print("Can't register subregion for ", event, " ", subRegion.type) - return - end - - self.events[event] = self.events[event] or {} - tinsert(self.events[event], subRegion) - end, - - RemoveSubscriber = function(self, event, subRegion) - if self.events[event] then - tremove(self.events[event], tIndexOf(self.events[event], subRegion)) - end - end, - - Notify = function(self, event, ...) - if self.events[event] then - for _, subRegion in ipairs(self.events[event]) do - subRegion[event](subRegion, ...) - end - end - end -} - -local function CreateSubRegionEventSystem() - local system = {} - for f, func in pairs(SubRegionEventSystem) do - system[f] = func - system.events = {} - end - return system -end - -- Alpha function WeakAuras.regionPrototype.AddAlphaToDefault(default) default.alpha = 1.0; @@ -391,29 +350,9 @@ local function SetTriggerProvidesTimer(self, timerTick) self:UpdateTimerTick() end -local function UpdateRegionHasTimerTick(self) - local hasTimerTick = false - if self.TimerTick then - hasTimerTick = true - elseif (self.subRegions) then - for index, subRegion in pairs(self.subRegions) do - if subRegion.TimerTick then - hasTimerTick = true - break; - end - end - end - - self.regionHasTimer = hasTimerTick - self:UpdateTimerTick() -end - local function TimerTickForRegion(region) Private.StartProfileSystem("timer tick") Private.StartProfileAura(region.id); - if region.TimerTick then - region:TimerTick(); - end region.subRegionEvents:Notify("TimerTick") Private.StopProfileAura(region.id); @@ -421,7 +360,7 @@ local function TimerTickForRegion(region) end local function UpdateTimerTick(self) - if self.triggerProvidesTimer and self.regionHasTimer and self.toShow then + if self.triggerProvidesTimer and self.subRegionEvents:HasSubscribers("TimerTick") and self.toShow then if not self:GetScript("OnUpdate") then self:SetScript("OnUpdate", function() TimerTickForRegion(self) @@ -434,6 +373,20 @@ local function UpdateTimerTick(self) end end +local function UpdateFrameTick(self) + if self.subRegionEvents:HasSubscribers("FrameTick") and self.toShow then + Private.FrameTick:AddSubscriber("FrameTick", self) + else + Private.FrameTick:RemoveSubscriber("FrameTick", self) + end +end + +local function FrameTick(self) + Private.StartProfileAura(self.id) + self.subRegionEvents:Notify("FrameTick") + Private.StopProfileAura(self.id) +end + local function AnchorSubRegion(self, subRegion, anchorType, selfPoint, anchorPoint, anchorXOffset, anchorYOffset) subRegion:ClearAllPoints() @@ -486,10 +439,11 @@ function WeakAuras.regionPrototype.create(region) region.SetAnimAlpha = SetAnimAlpha; region.SetTriggerProvidesTimer = SetTriggerProvidesTimer - region.UpdateRegionHasTimerTick = UpdateRegionHasTimerTick region.UpdateTimerTick = UpdateTimerTick + region.UpdateFrameTick = UpdateFrameTick + region.FrameTick = FrameTick - region.subRegionEvents = CreateSubRegionEventSystem() + region.subRegionEvents = Private.CreateSubscribableObject() region.AnchorSubRegion = AnchorSubRegion region.values = {} -- For SubText @@ -502,6 +456,8 @@ function WeakAuras.regionPrototype.modify(parent, region, data) region.state = nil region.states = nil region.subRegionEvents:ClearSubscribers() + region.subRegionEvents:ClearCallbacks() + Private.FrameTick:RemoveSubscriber("FrameTick", region) local defaultsForRegion = Private.regionTypes[data.regionType] and Private.regionTypes[data.regionType].default; @@ -581,7 +537,6 @@ function WeakAuras.regionPrototype.modify(parent, region, data) end return data.actions.finish[fullKey] end, true) - end function WeakAuras.regionPrototype.modifyFinish(parent, region, data) @@ -612,7 +567,15 @@ function WeakAuras.regionPrototype.modifyFinish(parent, region, data) end end - region:UpdateRegionHasTimerTick() + region.subRegionEvents:SetOnSubscriptionStatusChanged("TimerTick", function() + region:UpdateTimerTick() + end) + region:UpdateTimerTick() + + region.subRegionEvents:SetOnSubscriptionStatusChanged("FrameTick", function() + region:UpdateFrameTick() + end) + region:UpdateFrameTick() Private.ApplyFrameLevel(region) end @@ -627,55 +590,25 @@ end local regionsForFrameTick = {} local frameForFrameTick = CreateFrame("Frame"); - Private.frames["Frame Tick Frame"] = frameForFrameTick -local function FrameTick() +Private.FrameTick = Private.CreateSubscribableObject() +Private.FrameTick.OnUpdateHandler = function() if WeakAuras.IsOptionsOpen() then return end Private.StartProfileSystem("frame tick") - for region in pairs(regionsForFrameTick) do - Private.StartProfileAura(region.id); - if region.FrameTick then - region.FrameTick() - end - region.subRegionEvents:Notify("FrameTick") - Private.StopProfileAura(region.id); - end + Private.FrameTick:Notify("FrameTick") Private.StopProfileSystem("frame tick") end -local function RegisterForFrameTick(region) - -- Check for a Frame Tick function - local hasFrameTick = region.FrameTick - if not hasFrameTick then - if (region.subRegions) then - for index, subRegion in pairs(region.subRegions) do - if subRegion.FrameTick then - hasFrameTick = true - break - end - end - end - end - - if not hasFrameTick then - return - end - - regionsForFrameTick[region] = true - if not frameForFrameTick:GetScript("OnUpdate") then - frameForFrameTick:SetScript("OnUpdate", FrameTick); - end -end - -local function UnRegisterForFrameTick(region) - regionsForFrameTick[region] = nil - if not next(regionsForFrameTick) then +Private.FrameTick:SetOnSubscriptionStatusChanged("FrameTick", function() + if Private.FrameTick:HasSubscribers("FrameTick") then + frameForFrameTick:SetScript("OnUpdate", Private.FrameTick.OnUpdateHandler); + else frameForFrameTick:SetScript("OnUpdate", nil) end -end +end) local function TimerTickForSetDuration(self) local duration = self.duration @@ -707,13 +640,13 @@ function WeakAuras.regionPrototype.AddSetDurationInfo(region) if customValue then SetProgressValue(region, duration, expirationTime); region.TimerTick = nil - region:UpdateRegionHasTimerTick() + region.subRegionEvents:RemoveSubscriber("TimerTick", self) else local adjustMin = region.adjustedMin or 0; region:SetTime((duration ~= 0 and region.adjustedMax or duration) - adjustMin, expirationTime - adjustMin, inverse); region.TimerTick = TimerTickForSetDuration - region:UpdateRegionHasTimerTick() + region.subRegionEvents:AddSubscriber("TimerTick", self, true) end end elseif (region.generatedSetDurationInfo) then @@ -827,7 +760,7 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare region:SoundRepeatStop(); end - UnRegisterForFrameTick(region) + region:UpdateFrameTick() region:UpdateTimerTick() end function region:Expand() @@ -863,7 +796,7 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare end parent:ActivateChild(data.id, cloneId); - RegisterForFrameTick(region) + region:UpdateFrameTick() region:UpdateTimerTick() end elseif not(data.controlledChildren) then @@ -886,7 +819,7 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare region:SoundRepeatStop(); end - UnRegisterForFrameTick(region) + region:UpdateFrameTick() region:UpdateTimerTick() end function region:Expand() @@ -934,7 +867,7 @@ function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, pare parent:UpdateBorder(region); end - RegisterForFrameTick(region) + region:UpdateFrameTick() region:UpdateTimerTick() end end diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index aa51c66..07bfb2a 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -444,6 +444,9 @@ local function modify(parent, region, data) end; region.FrameTick = onUpdate; + if region.FrameTick then + region.subRegionEvents:AddSubscriber("FrameTick", region, true) + end function region:Update() if region.state.paused then diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index 30768ee..71b153c 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -226,6 +226,11 @@ local function modify(parent, region, data) region.Update = Update region.FrameTick = FrameTick region.TimerTick = TimerTick + if TimerTick then + region.subRegionEvents:AddSubscriber("TimerTick", region, true) + else + region.subRegionEvents:RemoveSubscriber("TimerTick", region) + end if not UpdateText then local textStr = data.displayText diff --git a/WeakAuras/SubRegionTypes/Tick.lua b/WeakAuras/SubRegionTypes/Tick.lua index 9aa6ae8..8737d94 100644 --- a/WeakAuras/SubRegionTypes/Tick.lua +++ b/WeakAuras/SubRegionTypes/Tick.lua @@ -199,13 +199,11 @@ local funcs = { if self.tick_placement_mode == "ValueOffset" and self.state and self.state.progressType == "timed" and not self.paused then if not self.TimerTick then self.TimerTick = self.UpdateTickPlacement - self.parent:UpdateRegionHasTimerTick() self.parent.subRegionEvents:AddSubscriber("TimerTick", self) end else if self.TimerTick then self.TimerTick = nil - self.parent:UpdateRegionHasTimerTick() self.parent.subRegionEvents:RemoveSubscriber("TimerTick", self) end end diff --git a/WeakAuras/SubscribableObject.lua b/WeakAuras/SubscribableObject.lua new file mode 100644 index 0000000..07b3045 --- /dev/null +++ b/WeakAuras/SubscribableObject.lua @@ -0,0 +1,74 @@ +if not WeakAuras.IsLibsOK() then return end +local AddonName, Private = ... + +local WeakAuras = WeakAuras +local L = WeakAuras.L + +local SubscribableObject = +{ + ClearSubscribers = function(self) + self.events = {} + end, + + ClearCallbacks = function(self) + self.callbacks = {} + end, + + AddSubscriber = function(self, event, subscriber, highPriority) + if not subscriber[event] then + print("Can't register for ", event, " ", subscriber, subscriber.type) + return + end + + self.events[event] = self.events[event] or {} + local pos = highPriority and 1 or (#self.events[event] + 1) + if TableHasAnyEntries(self.events[event]) then + tinsert(self.events[event], pos, subscriber) + else + tinsert(self.events[event], pos, subscriber) + if self.callbacks[event] then + self.callbacks[event]() + end + end + end, + + RemoveSubscriber = function(self, event, subscriber) + if self.events[event] then + local index = tIndexOf(self.events[event], subscriber) + if index then + tremove(self.events[event], index) + if not TableHasAnyEntries(self.events[event]) then + if self.callbacks[event] then + self.callbacks[event]() + end + end + end + end + end, + + SetOnSubscriptionStatusChanged = function(self, event, cb) + self.callbacks[event] = cb + end, + + Notify = function(self, event, ...) + if self.events[event] then + for _, subscriber in ipairs(self.events[event]) do + subscriber[event](subscriber, ...) + end + end + end, + + HasSubscribers = function(self, event) + return self.events[event] and TableHasAnyEntries(self.events[event]) + end +} + +function Private.CreateSubscribableObject() + local system = {} + for f, func in pairs(SubscribableObject) do + system[f] = func + system.events = {} + system.callbacks = {} + end + return system +end diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index 9d299e5..7ae40e3 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -49,6 +49,7 @@ GenericTrigger.lua AuraWarnings.lua AuraEnvironment.lua DebugLog.lua +SubscribableObject.lua # Region support RegionTypes\RegionPrototype.lua diff --git a/WeakAuras/compat.lua b/WeakAuras/compat.lua index 801e333..1172119 100644 --- a/WeakAuras/compat.lua +++ b/WeakAuras/compat.lua @@ -44,6 +44,15 @@ function tIndexOf(tbl, item) end end +function TableHasAnyEntries(tbl) + if tbl and type(tbl) == "table" then + for _ in pairs(tbl) do + return true + end + end + return false +end + function IsInGroup() return GetNumPartyMembers() > 0 or GetNumRaidMembers() > 0 end diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index dafdd7c..15c4e61 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -1021,7 +1021,7 @@ typeControlAdders = { set = function(_, value) if option.mediaType == "sound" then -- do this outside the deref loop, so we don't play the sound a million times - PlaySoundFile(value) + PlaySoundFile(value, "Master") end for _, optionData in pairs(option.references) do local childOption = optionData.options[optionData.index] @@ -2353,7 +2353,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) end userOption.set = function(_, value) if option.mediaType == "sound" then - PlaySoundFile(value) + PlaySoundFile(value, "Master") end for _, optionData in pairs(option.references) do local childData = optionData.data From 65383b86649b0eeec284721b0e9f1f2f87acfdc8 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 11 Jan 2025 18:24:34 +0100 Subject: [PATCH 025/153] from retail --- WeakAuras/Modernize.lua | 5 +-- WeakAuras/RegionTypes/DynamicGroup.lua | 6 ++-- WeakAuras/RegionTypes/Text.lua | 6 ++++ WeakAuras/SubRegionTypes/SubText.lua | 44 +++++++++++--------------- WeakAuras/WeakAuras.lua | 3 +- WeakAurasOptions/Locales/enUS.lua | 2 +- WeakAurasOptions/WeakAurasOptions.lua | 2 -- 7 files changed, 33 insertions(+), 35 deletions(-) diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 24c673a..b1afb3d 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1216,9 +1216,10 @@ function Private.Modernize(data) data.forceEvents = nil end - if data.internalVersion < 62 then + -- version 62 became 64 to fix a broken modernize + if data.internalVersion < 64 then if data.regionType == "dynamicgroup" then - if data.sort == "CUSTOM" and type(data.sortOn) ~= "string" then + if data.sort == "custom" and type(data.sortOn) ~= "string" or data.sortOn == "" then data.sortOn = "changed" end if data.grow == "CUSTOM" and type(data.growOn) ~= "string" then diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 57db178..f819a94 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -327,7 +327,7 @@ local sorters = { if #events > 0 then sortOn = {} for _, event in ipairs(events) do - events[event] = true + sortOn[event] = true end end return function(a, b) @@ -929,7 +929,7 @@ local growers = { if #events > 0 then growOn = {} for _, event in ipairs(events) do - events[event] = true + growOn[event] = true end end return function(newPositions, activeRegions) @@ -985,7 +985,7 @@ local function isDifferent(regionData, cache, events) local cachedState = cache[id][cloneId] for event in pairs(events) do if regionData.region.state[event] ~= cachedState[event] then - cachedState[event] = regionData.region.state[event] + cachedState[event] = state[event] isDifferent = true end end diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index 71b153c..49480a6 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -232,6 +232,12 @@ local function modify(parent, region, data) region.subRegionEvents:RemoveSubscriber("TimerTick", region) end + if FrameTick then + region.subRegionEvents:AddSubscriber("FrameTick", region) + else + region.subRegionEvents:RemoveSubscriber("FrameTick", region) + end + if not UpdateText then local textStr = data.displayText textStr = textStr:gsub("\\n", "\n"); diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index 3fa5cfa..b4e04ad 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -179,6 +179,7 @@ local function modify(parent, region, parentData, data, first) parent.customTextFunc = nil end parent.values.custom = nil + parent.values.lastCustomTextUpdate = nil end local UpdateText @@ -202,16 +203,13 @@ local function modify(parent, region, parentData, data, first) end local Update - if first and parent.customTextFunc then - if UpdateText then - Update = function() - parent.values.custom = Private.RunCustomTextFunc(parent, parent.customTextFunc) - UpdateText() - end - else - Update = function() + if parent.customTextFunc and UpdateText then + Update = function() + if parent.values.lastCustomTextUpdate ~= GetTime() then parent.values.custom = Private.RunCustomTextFunc(parent, parent.customTextFunc) + parent.values.lastCustomTextUpdate = GetTime() end + UpdateText() end else Update = UpdateText @@ -224,20 +222,13 @@ local function modify(parent, region, parentData, data, first) local FrameTick if parent.customTextFunc and parentData.customTextUpdate == "update" then - if first then - if Private.ContainsCustomPlaceHolder(data.text_text) then - FrameTick = function() + if Private.ContainsCustomPlaceHolder(data.text_text) then + FrameTick = function() + if parent.values.lastCustomTextUpdate ~= GetTime() then parent.values.custom = Private.RunCustomTextFunc(parent, parent.customTextFunc) - UpdateText() + parent.values.lastCustomTextUpdate = GetTime() end - else - FrameTick = function() - parent.values.custom = Private.RunCustomTextFunc(parent, parent.customTextFunc) - end - end - else - if Private.ContainsCustomPlaceHolder(data.text_text) then - FrameTick = UpdateText + UpdateText() end end end @@ -265,8 +256,6 @@ local function modify(parent, region, parentData, data, first) text:SetTextColor(region.color_anim_r or r, region.color_anim_g or g, region.color_anim_b or b, region.color_anim_a or a); end - region:Color(data.text_color[1], data.text_color[2], data.text_color[3], data.text_color[4]); - function region:SetTextHeight(size) local fontPath = SharedMedia:Fetch("font", data.text_font); region.text:SetFont(fontPath, size < 33 and size or 33, data.text_fontType); @@ -285,6 +274,9 @@ local function modify(parent, region, parentData, data, first) if self.TimerTick then parent.subRegionEvents:AddSubscriber("TimerTick", region) end + if self.Update and parent.state then + self:Update() + end else if self.Update then parent.subRegionEvents:RemoveSubscriber("Update", region) @@ -299,8 +291,6 @@ local function modify(parent, region, parentData, data, first) end end - region:SetVisible(data.text_visible) - local selfPoint = data.text_selfPoint if selfPoint == "AUTO" then if parentData.regionType == "icon" then @@ -333,8 +323,6 @@ local function modify(parent, region, parentData, data, first) parent:AnchorSubRegion(text, "point", selfPoint, data.text_anchorPoint, self.text_anchorXOffset or 0, self.text_anchorYOffset or 0) end - region:UpdateAnchor() - region.SetXOffset = function(self, xOffset) if self.text_anchorXOffset == xOffset then return @@ -350,6 +338,10 @@ local function modify(parent, region, parentData, data, first) self.text_anchorYOffset = yOffset self:UpdateAnchor() end + + region:Color(data.text_color[1], data.text_color[2], data.text_color[3], data.text_color[4]); + region:SetVisible(data.text_visible) + region:UpdateAnchor() end local function addDefaultsForNewAura(data) diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 14c1d30..0135e57 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3090,7 +3090,7 @@ local function actionGlowStart(actions, frame, id) actions.glow_thickness, actions.glow_XOffset, actions.glow_YOffset, - actions.glow_border, + actions.glow_border and true or false, id ) elseif actions.glow_type == "ACShine" then @@ -4408,6 +4408,7 @@ local function ValueForSymbol(symbol, region, customFunc, regionState, regionSta return tostring(value) or "" end end + return "" else local value = (useHiddenStates or regionState.show) and ReplaceValuePlaceHolders(symbol, region, customFunc, regionState, formatters[symbol]); return value or "" diff --git a/WeakAurasOptions/Locales/enUS.lua b/WeakAurasOptions/Locales/enUS.lua index b3710df..c0ad210 100644 --- a/WeakAurasOptions/Locales/enUS.lua +++ b/WeakAurasOptions/Locales/enUS.lua @@ -211,7 +211,7 @@ If the entered number is a whole number (e.g. 5), the number of affected units w If the entered number is a decimal (e.g. 0.5), fraction (e.g. 1/2), or percentage (e.g. 50%%), then that fraction of the %s must be affected. |cFF4444FFFor example:|r -|cFF00CC00> 0|r will trigger when any unit of type '%s' is is affected +|cFF00CC00> 0|r will trigger when any unit of type '%s' is affected |cFF00CC00= 100%%|r will trigger when ever unit of type '%s' is affected |cFF00CC00!= 2|r will trigger when the number of units of type '%s' affected is not exactly 2 |cFF00CC00<= 0.8|r will trigger when less than 80%% of the units of type '%s' is affected (4 of 5 party members, 8 of 10 or 20 of 25 raid members) diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 7dff8f9..414e799 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -300,8 +300,6 @@ local function CreateNewGroupFromSelection(regionType, resetChildPositions) local oldParentData = WeakAuras.GetData(oldParent) if (oldParent) then local oldIndex = childButton:GetGroupOrder() - print("CHILD ID", childId, "OLD PARENT", oldParent, "OLD INDEX", oldIndex) - print("###", oldParentData.controlledChildren[oldIndex]) tremove(oldParentData.controlledChildren, oldIndex) WeakAuras.Add(oldParentData) From 794d8eef84abc728294d9947e83932af5d2e2efa Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 11 Jan 2025 20:23:49 +0100 Subject: [PATCH 026/153] from retail --- WeakAuras/Init.lua | 2 +- WeakAuras/RegionTypes/RegionPrototype.lua | 1 + WeakAuras/WeakAuras.lua | 2 ++ WeakAuras/WeakAuras.toc | 2 +- WeakAurasOptions/BuffTrigger2.lua | 4 ++-- WeakAurasOptions/Locales/enUS.lua | 2 +- WeakAurasOptions/WeakAurasOptions.lua | 12 +++++++----- WeakAurasOptions/WeakAurasOptions.toc | 2 +- 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index 42ae8e9..af72783 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -8,7 +8,7 @@ WeakAuras.halfWidth = WeakAuras.normalWidth / 2 WeakAuras.doubleWidth = WeakAuras.normalWidth * 2 local versionStringFromToc = GetAddOnMetadata("WeakAuras", "Version") -local versionString = "4.1.5" +local versionString = "5.4.0" local buildTime = "20240701180000" local isAwesomeEnabled = C_NamePlate and C_NamePlate.GetNamePlateForUnit or false diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index 2ba84de..af109c5 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -383,6 +383,7 @@ end local function FrameTick(self) Private.StartProfileAura(self.id) + self.values.lastCustomTextUpdate = nil self.subRegionEvents:Notify("FrameTick") Private.StopProfileAura(self.id) end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 0135e57..73f25ed 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3942,6 +3942,8 @@ local function startStopTimers(id, cloneId, triggernum, state) end local function ApplyStateToRegion(id, cloneId, region, parent) + -- Force custom text function to be run again + region.values.lastCustomTextUpdate = nil region:Update(); region.subRegionEvents:Notify("Update", region.state, region.states) diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index 7ae40e3..5f0602f 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -1,7 +1,7 @@ ## Interface: 30300 ## Title: WeakAuras ## Author: The WeakAuras Team -## Version: 4.1.5 +## Version: 5.4.0 ## Notes: A powerful, comprehensive utility for displaying graphics and information based on buffs, debuffs, and other triggers. ## Notes-esES: Potente y completa aplicación que te permitirá mostrar por pantalla múltiples diseños, basados en beneficios, perjuicios y otros activadores. ## Notes-deDE: Ein leistungsfähiges, umfassendes Addon zur grafischen Darstellung von Informationen von Auren, Cooldowns, Timern und vielem mehr. diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index 949f677..4b130cb 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -1152,7 +1152,7 @@ local function GetBuffTriggerOptions(data, triggernum) CreateNameOptions(aura_options, data, trigger, spellOptionsSize, true, false, "spellid", 22, "useExactSpellId", "auraspellids", - L["Spell ID"], L["Enter a Spell ID"], + L["Spell ID"], L["Enter a Spell ID. You can use the addon idTip to determine spell ids."], IsSingleMissing(trigger)) CreateNameOptions(aura_options, data, trigger, ignoreNameOptionSize, @@ -1163,7 +1163,7 @@ local function GetBuffTriggerOptions(data, triggernum) CreateNameOptions(aura_options, data, trigger, ignoreSpellOptionsSize, true, true, "ignorespellid", 42, "useIgnoreExactSpellId", "ignoreAuraSpellids", - L["Ignored Spell ID"], L["Enter a Spell ID"], + L["Ignored Spell ID"], L["Enter a Spell ID. You can use the addon idTip to determine spell ids."], IsSingleMissing(trigger)) OptionsPrivate.commonOptions.AddCommonTriggerOptions(aura_options, data, triggernum, true) diff --git a/WeakAurasOptions/Locales/enUS.lua b/WeakAurasOptions/Locales/enUS.lua index c0ad210..88fa6fa 100644 --- a/WeakAurasOptions/Locales/enUS.lua +++ b/WeakAurasOptions/Locales/enUS.lua @@ -212,7 +212,7 @@ If the entered number is a decimal (e.g. 0.5), fraction (e.g. 1/2), or percentag |cFF4444FFFor example:|r |cFF00CC00> 0|r will trigger when any unit of type '%s' is affected -|cFF00CC00= 100%%|r will trigger when ever unit of type '%s' is affected +|cFF00CC00= 100%%|r will trigger when every unit of type '%s' is affected |cFF00CC00!= 2|r will trigger when the number of units of type '%s' affected is not exactly 2 |cFF00CC00<= 0.8|r will trigger when less than 80%% of the units of type '%s' is affected (4 of 5 party members, 8 of 10 or 20 of 25 raid members) |cFF00CC00> 1/2|r will trigger when more than half of the units of type '%s' is affected diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 414e799..c67c5ae 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -1006,12 +1006,13 @@ function OptionsPrivate.SortDisplayButtons(filter, overrideReset, id) child.frame:Show() child:AcquireThumbnail() frame.buttonsScroll:AddChild(child) + else + if not child.frame:IsShown() then + child.frame:Show() + child:AcquireThumbnail() + end + tinsert(frame.buttonsScroll.children, child) end - if not child.frame:IsShown() then - child.frame:Show() - child:AcquireThumbnail() - end - tinsert(frame.buttonsScroll.children, child) elseif child then child.frame:Hide() if child.ReleaseThumbnail then @@ -1061,6 +1062,7 @@ function OptionsPrivate.SortDisplayButtons(filter, overrideReset, id) child.frame:Show() child:AcquireThumbnail() frame.buttonsScroll:AddChild(child) + buttonsShown[slug] = true end if not child.frame:IsShown() then child.frame:Show() diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index a5f0431..89ad494 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -1,7 +1,7 @@ ## Interface: 30300 ## Title: WeakAuras Options ## Author: The WeakAuras Team -## Version: 4.1.5 +## Version: 5.4.0 ## Notes: Options for WeakAuras ## Notes-esES: Opciones para WeakAuras ## Notes-deDE: Optionen für WeakAuras From 5022fe7ffd0fa65ef3281fc33e148066eb0a6b52 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 11 Jan 2025 21:04:42 +0100 Subject: [PATCH 027/153] from retail --- WeakAuras/BuffTrigger2.lua | 4 +++- WeakAuras/Conditions.lua | 3 +++ WeakAuras/GenericTrigger.lua | 18 +++++++++++++++--- WeakAuras/Types.lua | 2 ++ WeakAuras/WeakAuras.lua | 13 ++++++++----- WeakAurasOptions/BuffTrigger2.lua | 6 +++--- WeakAurasOptions/CommonOptions.lua | 12 ++++++------ WeakAurasOptions/OptionsFrames/Update.lua | 15 +++++++++------ WeakAurasOptions/TriggerOptions.lua | 4 ++-- 9 files changed, 51 insertions(+), 26 deletions(-) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 728d568..6daa6ba 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -2696,7 +2696,9 @@ function BuffTrigger.GetTriggerConditions(data, triggernum) } end - if not IsGroupTrigger(trigger) and trigger.matchesShowOn == "showAlways" then + if not IsGroupTrigger(trigger) and trigger.matchesShowOn == "showAlways" + or IsGroupTrigger(trigger) and trigger.showClones and trigger.unit ~= "multi" and trigger.combinePerUnit + then result["buffed"] = { display = L["Aura(s) Found"], type = "bool", diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index d1396dd..116a6a1 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -853,6 +853,7 @@ function Private.RegisterForGlobalConditions(uid) if (not dynamicConditionsFrame.onUpdate) then dynamicConditionsFrame:SetScript("OnUpdate", handleDynamicConditionsOnUpdate); dynamicConditionsFrame.onUpdate = true; + handleDynamicConditionsOnUpdate(dynamicConditionsFrame, event) end else local unitEvent, unit = event:match("([^:]+):([^:]+)") @@ -864,8 +865,10 @@ function Private.RegisterForGlobalConditions(uid) end dynamicConditionsFrame.units[unit].unit = unit; pcall(dynamicConditionsFrame.RegisterEvent, dynamicConditionsFrame.units[unit], unitEvent); + handleDynamicConditionsPerUnit(dynamicConditionsFrame, event, unit) else pcall(dynamicConditionsFrame.RegisterEvent, dynamicConditionsFrame, event); + handleDynamicConditions(dynamicConditionsFrame, event) end end end diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index c94d868..2813392 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1410,14 +1410,19 @@ function GenericTrigger.Add(data, region) overlayFuncs = {}; local dest = 1; for i, v in ipairs(prototype.overlayFuncs) do - if (v.enable(trigger)) then + local enable = true + if type(v.enable) == "function" then + enable = v.enable(trigger) + elseif type(v.enable) == "boolean" then + enable = v.enable + end + if enable then overlayFuncs[dest] = v.func; dest = dest + 1; end end end - if (prototype.automaticrequired) then untriggerFunc = trueFunction elseif prototype.timedrequired then @@ -3789,7 +3794,13 @@ function GenericTrigger.GetOverlayInfo(data, triggernum) result = {}; local dest = 1; for i, v in ipairs(Private.event_prototypes[trigger.event].overlayFuncs) do - if (v.enable(trigger)) then + local enable = true + if type(v.enable) == "function" then + enable = v.enable(trigger) + elseif type(v.enable) == "boolean" then + enable = v.enable + end + if enable then result[dest] = v.name; dest = dest + 1; end @@ -4209,6 +4220,7 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) state.expirationTime = math.huge; state.value = nil; state.total = nil; + Private.ActivateAuraEnvironment(nil) return; end arg1 = type(arg1) == "number" and arg1 or 0; diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 565f6ab..e2bf10c 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -945,6 +945,7 @@ Private.inverse_point_types = { Private.anchor_frame_types = { SCREEN = L["Screen/Parent Group"], + UIPARENT = L["Screen"], MOUSE = L["Mouse Cursor"], SELECTFRAME = L["Select Frame"], UNITFRAME = L["Unit Frames"], @@ -956,6 +957,7 @@ end Private.anchor_frame_types_group = { SCREEN = L["Screen/Parent Group"], + UIPARENT = L["Screen"], MOUSE = L["Mouse Cursor"], SELECTFRAME = L["Select Frame"], CUSTOM = L["Custom"] diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 73f25ed..1fdc146 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3977,7 +3977,6 @@ end local function evaluateTriggerStateTriggers(id) local result = false; - Private.ActivateAuraEnvironment(id); if WeakAuras.IsOptionsOpen() then -- While the options are open ignore the combination function @@ -3990,7 +3989,9 @@ local function evaluateTriggerStateTriggers(id) result = true; else if (triggerState[id].disjunctive == "custom" and triggerState[id].triggerLogicFunc) then + Private.ActivateAuraEnvironment(id) local ok, returnValue = pcall(triggerState[id].triggerLogicFunc, triggerState[id].triggers); + Private.ActivateAuraEnvironment() if not ok then Private.GetErrorHandlerId(id, L["Custom Trigger Combination"]) result = false @@ -4000,8 +4001,6 @@ local function evaluateTriggerStateTriggers(id) end end - Private.ActivateAuraEnvironment(); - return result; end @@ -4989,6 +4988,10 @@ local function GetAnchorFrame(data, region, parent) return parent; end + if (anchorFrameType == "UIPARENT") then + return UIParent; + end + if (anchorFrameType == "MOUSE") then ensureMouseFrame(); mouseFrame:anchorFrame(id, anchorFrameType); @@ -5080,7 +5083,7 @@ function Private.AnchorFrame(data, region, parent, force) local anchorParent = GetAnchorFrame(data, region, parent); if not anchorParent then return end if (data.anchorFrameParent or data.anchorFrameParent == nil - or data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE") then + or data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE") then local ok, ret = pcall(region.SetParent, region, anchorParent); if not ok then Private.GetErrorHandlerId(data.id, L["Anchoring"]) @@ -5091,7 +5094,7 @@ function Private.AnchorFrame(data, region, parent, force) local anchorPoint = data.anchorPoint if data.parent then - if data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE" then + if data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE" then anchorPoint = "CENTER" end else diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index 4b130cb..f82efc4 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -560,9 +560,9 @@ local function GetBuffTriggerOptions(data, triggernum) end, desc = function() local value = trigger.ownOnly - if value == nil then return L["Only match auras cast by the player or his pet"] - elseif value == false then return L["Only match auras cast by people other than the player or his pet"] - else return L["Only match auras cast by the player or his pet"] end + if value == nil then return L["Only match auras cast by the player or their pet"] + elseif value == false then return L["Only match auras cast by people other than the player or their pet"] + else return L["Only match auras cast by the player or their pet"] end end, get = function() local value = trigger.ownOnly diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index ee48941..735b7b5 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -1079,7 +1079,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g return data.anchorFrameParent or data.anchorFrameParent == nil; end, hidden = function() - return not IsGroupByFrame() and (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE" or IsParentDynamicGroup()); + return not IsGroupByFrame() and (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE" or IsParentDynamicGroup()); end, }, anchorFrameSpaceOne = { @@ -1089,7 +1089,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g order = 72, image = function() return "", 0, 0 end, hidden = function() - return IsParentDynamicGroup() or not (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE") + return IsParentDynamicGroup() or not (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE") end, }, -- Input field to select frame to anchor on @@ -1135,7 +1135,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g type = "select", width = WeakAuras.normalWidth, name = function() - if (data.anchorFrameType == "SCREEN") then + if (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT") then return L["To Screen's"] elseif (data.anchorFrameType == "PRD") then return L["To Personal Ressource Display's"]; @@ -1152,7 +1152,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g if IsParentDynamicGroup() then return true end - return data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE"; + return data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE"; else return data.anchorFrameType == "MOUSE"; end @@ -1169,7 +1169,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g if IsGroupByFrame() then return true end - if (data.anchorFrameType ~= "SCREEN") then + if (data.anchorFrameType ~= "SCREEN" and data.anchorFrameType ~= "UIPARENT") then return true; end if (data.parent) then @@ -1245,7 +1245,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g order = 82, image = function() return "", 0, 0 end, hidden = function() - return not (data.anchorFrameType ~= "SCREEN" or IsParentDynamicGroup()); + return not (data.anchorFrameType ~= "SCREEN" or data.anchorFrameType ~= "UIPARENT" or IsParentDynamicGroup()); end }, }; diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index 26ac567..77dea31 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -185,7 +185,7 @@ end local function RecurseDiff(ours, theirs, ignoredForDiffChecking) local diff, seen, same = {}, {}, true for key, ourVal in pairs(ours) do - if type(ignoredForDiffChecking) ~= table or ignoredForDiffChecking[key] ~= true then + if not (type(ignoredForDiffChecking) == "table" and ignoredForDiffChecking[key] == true) then seen[key] = true local theirVal = theirs[key] if type(ourVal) == "table" and type(theirVal) == "table" then @@ -207,7 +207,7 @@ local function RecurseDiff(ours, theirs, ignoredForDiffChecking) end end for key, theirVal in pairs(theirs) do - if not seen[key] and (type(ignoredForDiffChecking) ~= table or ignoredForDiffChecking[key] ~= true) then + if not seen[key] and not (type(ignoredForDiffChecking) == "table" and ignoredForDiffChecking[key] == true) then diff[key] = theirVal same = false end @@ -230,10 +230,10 @@ local function RecurseSerial(lines, depth, chunk) end end -local function DebugPrintDiff(diff) +local function DebugPrintDiff(diff, id, uid) local lines = { "==========================", - "Diff detected: ", + string.format("Diff detected for %q (%s):", id, uid), "{", } RecurseSerial(lines, 1, diff) @@ -252,7 +252,7 @@ local function Diff(ours, theirs) local diff = RecurseDiff(ours, theirs, ignoredForDiffChecking) if diff then if debug then - DebugPrintDiff(diff, ours.id, theirs.id) + DebugPrintDiff(diff, theirs.id, theirs.uid) end return diff end @@ -516,7 +516,9 @@ local function BuildUidMap(data, children, type) end if self.map[uid].anchorFrameFrame then - local target = self:GetIdFor(self.map[uid].anchorFrameFrame) + data.anchorFrameFrame = nil + local anchorUid = self.map[uid].anchorFrameFrame + local target = self:Contains(anchorUid) and self:GetIdFor(anchorUid) if target then data.anchorFrameFrame = "WeakAuras:" .. target end @@ -1626,6 +1628,7 @@ local methods = { oldData.sortHybridTable = newData.sortHybridTable oldData.uid = uid oldData.id = matchInfo.newUidMap:GetIdFor(uid) + oldData.anchorFrameFrame = newData.anchorFrameFrame return oldData else return matchInfo.newUidMap:GetPhase2Data(uid) diff --git a/WeakAurasOptions/TriggerOptions.lua b/WeakAurasOptions/TriggerOptions.lua index 6236ba5..0f27297 100644 --- a/WeakAurasOptions/TriggerOptions.lua +++ b/WeakAurasOptions/TriggerOptions.lua @@ -199,8 +199,8 @@ local function DeleteConditionsForTriggerHandleSubChecks(checks, triggernum) check.trigger = check.trigger - 1; end - if (checks.checks) then - DeleteConditionsForTriggerHandleSubChecks(checks.checks, triggernum); + if (check.checks) then + DeleteConditionsForTriggerHandleSubChecks(check.checks, triggernum); end end end From e17722f8a9744f6f711d5241b5aaa8f337508e4c Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 12 Jan 2025 17:32:55 +0100 Subject: [PATCH 028/153] from retail --- WeakAuras/Modernize.lua | 19 ++++- WeakAuras/Prototypes.lua | 169 ++++++++++++++++++++++++--------------- WeakAuras/Types.lua | 2 +- 3 files changed, 122 insertions(+), 68 deletions(-) diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index b1afb3d..2c6aa5e 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1206,8 +1206,25 @@ function Private.Modernize(data) end end + -- Internal version 55 contained a incorrect Modernize (data.forceEvents = nil) reused to + -- migrate deathRune to isDeathRune & migrate use_inverse to use_genericShowOn if data.internalVersion < 55 then - data.forceEvents = true + for _, triggerData in ipairs(data.triggers) do + if triggerData.trigger.event == "Death Knight Rune" then + -- migrate deathRune to isDeathRune + if triggerData.trigger.use_deathRune then + triggerData.trigger.use_isDeathRune = triggerData.trigger.use_deathRune + end + triggerData.trigger.use_deathRune = nil + -- migrate use_inverse to use_genericShowOn + if not (triggerData.trigger.use_genericShowOn or triggerData.trigger.genericShowOn) then + triggerData.trigger.use_genericShowOn = true + triggerData.trigger.genericShowOn = triggerData.trigger.use_inverse and "showOnCooldown" + or "showAlways" + end + triggerData.trigger.use_inverse = nil + end + end end -- Internal version 55 contained a incorrect Modernize diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index f83d3d0..c035585 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -5382,36 +5382,38 @@ Private.event_prototypes = { WeakAuras.WatchRuneCooldown(trigger.rune); local ret = [[ local rune = %s; + local genericShowOn = %s + local includeDeathRunes = %s; local startTime, duration = WeakAuras.GetRuneCooldown(rune); - local inverse = %s; - local death = %s; - local numBloodRunes = 0; local numUnholyRunes = 0; local numFrostRunes = 0; local numDeathRunes = 0; + local numRunes = 0; + local isDeathRune = GetRuneType(rune) == 4 for index = 1, 6 do - local startTime = select(1, GetRuneCooldown(index)); + local startTime = GetRuneCooldown(index); if startTime == 0 then - if GetRuneType(index) == 1 then - numBloodRunes = numBloodRunes + 1; - elseif GetRuneType(index) == 2 then + numRunes = numRunes + 1; + local runeType = GetRuneType(index) + if runeType == 1 then + numBloodRunes = numBloodRunes + 1; + elseif runeType == 2 then + numFrostRunes = numFrostRunes + 1; + elseif runeType == 3 then numUnholyRunes = numUnholyRunes + 1; - elseif GetRuneType(index) == 3 then - numFrostRunes = numFrostRunes + 1; - elseif GetRuneType(index) == 4 then - numDeathRunes = numDeathRunes + 1; + elseif runeType == 4 then + numDeathRunes = numDeathRunes + 1; end end end - - if %s then + if includeDeathRunes then numBloodRunes = numBloodRunes + numDeathRunes; numUnholyRunes = numUnholyRunes + numDeathRunes; numFrostRunes = numFrostRunes + numDeathRunes; end ]]; - if(trigger.use_remaining and not trigger.use_inverse) then + if trigger.use_remaining then local ret2 = [[ local expirationTime = startTime + duration local remaining = expirationTime - GetTime(); @@ -5420,105 +5422,140 @@ Private.event_prototypes = { Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); end ]]; - ret = ret..ret2:format(tonumber(trigger.remaining) or 0); + ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0); end - return ret:format(trigger.rune, (trigger.use_inverse and "true" or "false"), (trigger.use_deathRune == true and "true" or trigger.use_deathRune == false and "false" or "nil"), (trigger.use_includeDeath and "true" or "false")); + return ret:format( + trigger.rune, + "[[" .. (trigger.genericShowOn or "") .. "]]", + (trigger.use_includeDeathRunes and "true" or "false") + ); end, + statesParameter = "one", args = { { name = "rune", display = L["Rune"], type = "select", values = "rune_specific_types", - test = [[ - ((inverse and startTime == 0) or (not inverse and startTime > 0)) - and - ((death == nil) or (death == true and GetRuneType(rune) == 4) or (death == false and GetRuneType(rune) ~= 4)) - ]], - enable = function(trigger) return not trigger.use_bloodRunes and not trigger.use_unholyRunes and not trigger.use_frostRunes end, + test = "(genericShowOn == \"showOnReady\" and (startTime == 0)) " .. + "or (genericShowOn == \"showOnCooldown\" and startTime > 0) " .. + "or (genericShowOn == \"showAlways\")", reloadOptions = true }, { - name = "deathRune", - display = L["Death Rune"], + name = "isDeathRune", + display = L["Is Death Rune"], type = "tristate", - test = "true", - enable = function(trigger) return trigger.use_rune end + init = "isDeathRune", + store = true, + conditionType = "bool", + enable = function(trigger) return trigger.use_rune end, }, { name = "remaining", display = L["Remaining Time"], type = "number", - enable = function(trigger) return trigger.use_rune and not(trigger.use_inverse) end + enable = function(trigger) return trigger.use_rune and not(trigger.genericShowOn == "showOnReady") end }, { - name = "inverse", - display = L["Inverse"], - type = "toggle", + name = "genericShowOn", + display = L["Show"], + type = "select", + values = "cooldown_progress_behavior_types", test = "true", + enable = function(trigger) return trigger.use_rune end, + required = true + }, + { + name = "runesCount", + display = L["Rune Count"], + type = "number", + init = "numRunes", + enable = function(trigger) return not trigger.use_rune end + }, + { + hidden = true, + name = "onCooldown", + test = "true", + display = L["On Cooldown"], + conditionType = "bool", + conditionTest = function(state, needle) + return state and state.show and (state.expirationTime and state.expirationTime > GetTime()) == (needle == 1) + end, enable = function(trigger) return trigger.use_rune end }, { name = "bloodRunes", - display = L["Blood Runes"], + display = L["Rune Count - Blood"], type = "number", init = "numBloodRunes", - enable = function(trigger) return not trigger.use_rune end - }, - { - name = "unholyRunes", - display = L["Unholy Runes"], - type = "number", - init = "numUnholyRunes", - enable = function(trigger) return not trigger.use_rune end + store = true, + conditionType = "number", + enable = function(trigger) return not trigger.use_rune end, }, { name = "frostRunes", - display = L["Frost Runes"], + display = L["Rune Count - Frost"], type = "number", init = "numFrostRunes", - enable = function(trigger) return not trigger.use_rune end + store = true, + conditionType = "number", + enable = function(trigger) return not trigger.use_rune end, }, { - name = "includeDeath", + name = "unholyRunes", + display = L["Rune Count - Unholy"], + type = "number", + init = "numUnholyRunes", + store = true, + conditionType = "number", + enable = function(trigger) return not trigger.use_rune end, + }, + { + name = "includeDeathRunes", display = L["Include Death Runes"], type = "toggle", test = "true", - enable = function(trigger) return trigger.use_bloodRunes or trigger.use_unholyRunes or trigger.use_frostRunes end + enable = function(trigger) return trigger.use_bloodRunes or trigger.use_unholyRunes or trigger.use_frostRunes end, }, }, durationFunc = function(trigger) if trigger.use_rune then - local startTime, duration - if not(trigger.use_inverse) then - startTime, duration = WeakAuras.GetRuneCooldown(trigger.rune); - end - - startTime = startTime or 0; - duration = duration or 0; - - return duration, startTime + duration; + local startTime, duration = WeakAuras.GetRuneCooldown(trigger.rune) + return duration, startTime + duration else - return 1, 0; + local numRunes = 0; + for index = 1, 6 do + if GetRuneCooldown(index) == 0 then + numRunes = numRunes + 1; + end + end + return numRunes, 6, true; end end, + stacksFunc = function(trigger) + local numRunes = 0; + for index = 1, 6 do + if GetRuneCooldown(index) == 0 then + numRunes = numRunes + 1; + end + end + return numRunes; + end, nameFunc = function(trigger) - local runeNames = { - [1] = L["Blood"], - [2] = L["Unholy"], - [3] = L["Frost"], - [4] = L["Death"] - }; + local runeNames = { L["Blood"], L["Frost"], L["Unholy"], L["Death"] } return runeNames[GetRuneType(trigger.rune)]; end, iconFunc = function(trigger) - local runeIcons = { - [1] = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Blood", - [2] = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Unholy", - [3] = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Frost", - [4] = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Death" - }; - return runeIcons[GetRuneType(trigger.rune)]; + if trigger.rune then + local runeIcons = { + "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Blood", + "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Frost", + "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Unholy", + "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Death" + }; + return runeIcons[GetRuneType(trigger.rune)]; + end end, automaticrequired = true, }, diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index e2bf10c..f798430 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -1770,7 +1770,7 @@ Private.rune_specific_types = { [3] = L["Unholy Rune #1"], [4] = L["Unholy Rune #2"], [5] = L["Frost Rune #1"], - [6] = L["Frost Rune #2"] + [6] = L["Frost Rune #2"], } Private.custom_trigger_types = { From 8bb5990fad86ed471e3b8be20b3f86b3bc61f714 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 12 Jan 2025 18:20:40 +0100 Subject: [PATCH 029/153] from retail --- WeakAuras/Modernize.lua | 16 +++++++-- WeakAuras/Prototypes.lua | 75 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 2c6aa5e..528fcbd 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1324,6 +1324,20 @@ function Private.Modernize(data) "rangedhasterating_operator", "spellhasterating", "spellhasterating_operator", + "spellpenpercent", + "spellpenpercent_operator", + "armorpenpercent", + "armorpenpercent_operator", + "armorpenrating", + "armorpenrating_operator", + "resiliencerating", + "resiliencerating_operator", + "resiliencepercent", + "resiliencepercent_operator", + "expertisebonus", + "expertisebonus_operator", + "expertiserating", + "expertiserating_operator", "resistancefire", "resistancefire_operator", "resistancenature", @@ -1371,9 +1385,7 @@ function Private.Modernize(data) }, ["Location"] = { "zone", - "zone_operator", "subzone", - "subzone_operator", } } for _, triggerData in ipairs(data.triggers) do diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index c035585..1120dcc 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -6520,6 +6520,81 @@ Private.event_prototypes = { limit = 2 }, }, + { + name = "expertiserating", + display = L["Expertise Rating"], + type = "number", + init = "GetCombatRating(CR_EXPERTISE)", + store = true, + conditionType = "number", + }, + { + name = "expertisebonus", + display = L["Expertise Bonus"], + type = "number", + init = "GetCombatRatingBonus(CR_EXPERTISE)", + store = true, + conditionType = "number", + }, + { + name = "armorpenrating", + display = L["Armor Peneration Rating"], + type = "number", + init = "GetCombatRating(CR_ARMOR_PENETRATION)", + store = true, + conditionType = "number", + }, + { + name = "armorpenpercent", + display = L["Armor Peneration Percent"], + type = "number", + init = "GetArmorPenetration()", + store = true, + conditionType = "number", + }, + { + name = "resiliencerating", + display = L["Resilience Rating"], + type = "number", + init = [[ + local melee = GetCombatRating(CR_CRIT_TAKEN_MELEE); + local ranged = GetCombatRating(CR_CRIT_TAKEN_RANGED); + local spell = GetCombatRating(CR_CRIT_TAKEN_SPELL); + return math.min(melee, ranged, spell); + ]], + store = true, + conditionType = "number", + }, + { + name = "resiliencepercent", + display = L["Resilience Percent"], + type = "number", + init = [[ + local ratings = { + melee = {value = GetCombatRating(CR_CRIT_TAKEN_MELEE), ratingType = CR_CRIT_TAKEN_MELEE}, + ranged = {value = GetCombatRating(CR_CRIT_TAKEN_RANGED), ratingType = CR_CRIT_TAKEN_RANGED}, + spell = {value = GetCombatRating(CR_CRIT_TAKEN_SPELL), ratingType = CR_CRIT_TAKEN_SPELL}, + }; + local lowest = ratings.melee; + if ratings.ranged.value < lowest.value then + lowest = ratings.ranged; + end + if ratings.spell.value < lowest.value then + lowest = ratings.spell; + end + return GetCombatRatingBonus(lowest.ratingType); + ]], + store = true, + conditionType = "number", + }, + { + name = "spellpenpercent", + display = L["Spell Peneration Percent"], + type = "number", + init = "GetSpellPenetration()", + store = true, + conditionType = "number", + }, { type = "header", name = "resistanceHeader", From 01dd663f826562df8861fcb293e56973de344a70 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 12 Jan 2025 20:24:09 +0100 Subject: [PATCH 030/153] from retail item count needs review, looks broken --- WeakAuras/Modernize.lua | 11 +++++ WeakAuras/Prototypes.lua | 91 ++++++++++++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 17 deletions(-) diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 528fcbd..4fa838a 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1245,6 +1245,17 @@ function Private.Modernize(data) end end + if data.internalVersion < 65 then + for triggerId, triggerData in ipairs(data.triggers) do + if triggerData.trigger.type == "item" + and triggerData.trigger.event == "Item Count" + and type(triggerData.trigger.itemName) == "number" + then + triggerData.trigger.use_exact_itemName = true + end + end + end + if data.internalVersion < 67 or data.internalVersion > WeakAuras.InternalVersion() then local castMigrationNeeded = data.internalVersion < 67 data.internalVersion = WeakAuras.InternalVersion() diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 1120dcc..7815597 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4947,9 +4947,19 @@ Private.event_prototypes = { trigger.itemName = trigger.itemName or 0; local itemName = type(trigger.itemName) == "number" and trigger.itemName or "[["..trigger.itemName.."]]"; local ret = [[ - local count = GetItemCount(%s, %s, %s); + local itemName = %s + local exactSpellMatch = %s + if not exactSpellMatch and tonumber(itemName) then + itemName = GetItemInfo(itemName) + end + local count = GetItemCount(itemName, %s, %s); ]]; - return ret:format(itemName, trigger.use_includeBank and "true" or "nil", trigger.use_includeCharges and "true" or "nil"); + return ret:format( + itemName, + trigger.use_exact_itemName and "true" or "nil", + trigger.use_includeBank and "true" or "nil", + trigger.use_includeCharges and "true" or "nil" + ) end, args = { { @@ -4957,8 +4967,19 @@ Private.event_prototypes = { required = true, display = L["Item"], type = "item", + showExactOption = true, test = "true" }, + { + name = "name", + display = L["Name"], + init = "itemName", + type = "string", + hidden = true, + store = true, + test = "true", + conditionType = "string" + }, { name = "includeBank", display = L["Include Bank"], @@ -4975,22 +4996,58 @@ Private.event_prototypes = { name = "count", display = L["Item Count"], type = "number" - } + }, + { + name = "stacks", + display = L["Stacks"], + init = "count", + hidden = true, + store = true, + test = "true", + conditionType = "number" + }, + { + name = "value", + init = "count", + hidden = true, + store = true, + test = "true", + display = L["Progress Value"], + conditionType = "number" + }, + { + name = "total", + init = 0, + hidden = true, + store = true, + test = "true", + display = L["Progress Total"], + conditionType = "number" + }, + { + name = "progressType", + init = "'static'", + hidden = true, + store = true, + test = "true", + conditionType = "number" + }, + { + name = "icon", + init = "GetItemIcon(itemName)", + hidden = true, + store = true, + test = "true" + }, + { + name = "name", + init = "itemName", + hidden = true, + store = true, + test = "true" + }, }, - durationFunc = function(trigger) - local count = GetItemCount(trigger.itemName, trigger.use_includeBank, trigger.use_includeCharges); - return count, 0, true; - end, - stacksFunc = function(trigger) - local count = GetItemCount(trigger.itemName, trigger.use_includeBank, trigger.use_includeCharges); - return count, 0, true; - end, - nameFunc = function(trigger) - return trigger.itemName; - end, - iconFunc = function(trigger) - return GetItemIcon(trigger.itemName); - end, + statesParameter = "one", hasItemID = true, automaticrequired = true }, From ab877bcec157ea80c56a19678d7d675c37bf4b5d Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 13 Jan 2025 00:35:39 +0100 Subject: [PATCH 031/153] from retail --- WeakAuras/GenericTrigger.lua | 30 +++++++ WeakAuras/Prototypes.lua | 158 +++++++++++++++++++++-------------- 2 files changed, 123 insertions(+), 65 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 2813392..ffca714 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -4316,6 +4316,36 @@ do end end +WeakAuras.GetCritChance = function() + -- Based on what the wow paper doll does + local spellCrit = 0 + for i = 2, MAX_SPELL_SCHOOLS or 7 do -- WORKAROUND: MAX_SPELL_SCHOOLS is nil on classic_era + spellCrit = max(spellCrit, GetSpellCritChance(i)) + end + return max(spellCrit, GetRangedCritChance(), GetCritChance()) +end + +WeakAuras.GetHitChance = function() + local melee = (GetCombatRatingBonus(CR_HIT_MELEE) or 0) + local ranged = (GetCombatRatingBonus(CR_HIT_RANGED) or 0) + local spell = (GetCombatRatingBonus(CR_HIT_SPELL) or 0) + return max(melee, ranged, spell) +end + +WeakAuras.GetResilienceDamageReduction = function() + local ratings = { + {value = GetCombatRating(CR_CRIT_TAKEN_MELEE), type = CR_CRIT_TAKEN_MELEE}, + {value = GetCombatRating(CR_CRIT_TAKEN_RANGED), type = CR_CRIT_TAKEN_RANGED}, + {value = GetCombatRating(CR_CRIT_TAKEN_SPELL), type = CR_CRIT_TAKEN_SPELL}, + } + local lowest = ratings[1] + for _, rating in ipairs(ratings) do + if rating.value < lowest.value then lowest = rating end + end + return GetCombatRatingBonus(lowest.type) * 2 +end + + local types = {} tinsert(types, "custom") for type in pairs(Private.category_event_prototype) do diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 7815597..e972b53 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -754,6 +754,25 @@ function WeakAuras.IsSpellKnownIncludingPet(spell) end end +function WeakAuras.GetEffectiveAttackPower() + local base, pos, neg = UnitAttackPower("player") + return base + pos + neg +end + +function WeakAuras.GetEffectiveSpellPower() + -- Straight from the PaperDoll + local spellPower = 0 + for i = 2, MAX_SPELL_SCHOOLS or 7 do + spellPower = max(spellPower, GetSpellBonusDamage(i)) + end + return spellPower +end + +function WeakAuras.GetEffectiveRangedAttackPower() + local base, pos, neg = UnitRangedAttackPower("player") + return base + pos + neg +end + local function valuesForTalentFunction(trigger) return function() local single_class; @@ -6381,7 +6400,7 @@ Private.event_prototypes = { "PLAYER_TARGET_CHANGED" }, ["unit_events"] = { - ["player"] = {"UNIT_STATS"} + ["player"] = {"UNIT_STATS", "UNIT_ATTACK_POWER", "UNIT_AURA", "UNIT_RESISTANCES"} } }, internal_events = function(trigger, untrigger) @@ -6470,10 +6489,10 @@ Private.event_prototypes = { display = L["Secondary Stats"], }, { - name = "meleecriticalrating", - display = L["Melee Critical Rating"], + name = "attackpower", + display = L["Attack Power"], type = "number", - init = "GetCombatRating(CR_CRIT_MELEE)", + init = "WeakAuras.GetEffectiveAttackPower()", store = true, conditionType = "number", multiEntry = { @@ -6482,10 +6501,10 @@ Private.event_prototypes = { }, }, { - name = "rangedcriticalrating", - display = L["Ranged Critical Rating"], + name = "spellpower", + display = L["Spell Power"], type = "number", - init = "GetCombatRating(CR_CRIT_RANGED)", + init = "WeakAuras.GetEffectiveSpellPower()", store = true, conditionType = "number", multiEntry = { @@ -6494,10 +6513,10 @@ Private.event_prototypes = { }, }, { - name = "spellcriticalrating", - display = L["Spell Critical Rating"], + name = "rangedattackpower", + display = L["Ranged Attack Power"], type = "number", - init = "GetCombatRating(CR_CRIT_SPELL)", + init = "WeakAuras.GetEffectiveRangedAttackPower()", store = true, conditionType = "number", multiEntry = { @@ -6506,10 +6525,10 @@ Private.event_prototypes = { }, }, { - name = "meleecriticalpercent", - display = L["Mele Critical (%)"], + name = "criticalrating", + display = L["Critical Rating"], type = "number", - init = "GetCritChance()", + init = "max(GetCombatRating(CR_CRIT_MELEE), GetCombatRating(CR_CRIT_RANGED), GetCombatRating(CR_CRIT_SPELL))", store = true, conditionType = "number", multiEntry = { @@ -6518,10 +6537,10 @@ Private.event_prototypes = { }, }, { - name = "rangedcriticalpercent", - display = L["Ranged Critical (%)"], + name = "criticalpercent", + display = L["Critical (%)"], type = "number", - init = "GetRangedCritChance()", + init = "WeakAuras.GetCritChance()", store = true, conditionType = "number", multiEntry = { @@ -6530,10 +6549,10 @@ Private.event_prototypes = { }, }, { - name = "spellcriticalpercent", - display = L["Spell Critical (%)"], + name = "hitrating", + display = L["Hit Rating"], type = "number", - init = "WeakAuras.GetSpellCritChance()", + init = "max(GetCombatRating(CR_HIT_MELEE), GetCombatRating(CR_HIT_RANGED), GetCombatRating(CR_HIT_SPELL))", store = true, conditionType = "number", multiEntry = { @@ -6542,10 +6561,10 @@ Private.event_prototypes = { }, }, { - name = "meleehasterating", - display = L["Melee Haste Rating"], + name = "hitpercent", + display = L["Hit (%)"], type = "number", - init = "GetCombatRating(CR_HASTE_MELEE)", + init = "WeakAuras.GetHitChance()", store = true, conditionType = "number", multiEntry = { @@ -6554,10 +6573,10 @@ Private.event_prototypes = { }, }, { - name = "rangedhasterating", - display = L["Ranged Haste Rating"], + name = "hasterating", + display = L["Haste Rating"], type = "number", - init = "GetCombatRating(CR_HASTE_RANGED)", + init = "max(GetCombatRating(CR_HASTE_SPELL), GetCombatRating(CR_HASTE_MELEE), GetCombatRating(CR_HASTE_RANGED))", store = true, conditionType = "number", multiEntry = { @@ -6566,10 +6585,10 @@ Private.event_prototypes = { }, }, { - name = "spellhasterating", - display = L["Spell Haste Rating"], + name = "hastepercent", + display = L["Haste (%)"], type = "number", - init = "GetCombatRating(CR_HASTE_SPELL)", + init = "max(GetCombatRatingBonus(CR_HASTE_SPELL), GetCombatRatingBonus(CR_HASTE_MELEE), GetCombatRatingBonus(CR_HASTE_RANGED))", store = true, conditionType = "number", multiEntry = { @@ -6584,6 +6603,10 @@ Private.event_prototypes = { init = "GetCombatRating(CR_EXPERTISE)", store = true, conditionType = "number", + multiEntry = { + operator = "and", + limit = 2 + }, }, { name = "expertisebonus", @@ -6592,6 +6615,10 @@ Private.event_prototypes = { init = "GetCombatRatingBonus(CR_EXPERTISE)", store = true, conditionType = "number", + multiEntry = { + operator = "and", + limit = 2 + }, }, { name = "armorpenrating", @@ -6600,57 +6627,58 @@ Private.event_prototypes = { init = "GetCombatRating(CR_ARMOR_PENETRATION)", store = true, conditionType = "number", + multiEntry = { + operator = "and", + limit = 2 + }, }, { name = "armorpenpercent", - display = L["Armor Peneration Percent"], + display = L["Armor Peneration (%)"], type = "number", init = "GetArmorPenetration()", store = true, conditionType = "number", + multiEntry = { + operator = "and", + limit = 2 + }, + }, + { + name = "spellpenpercent", + display = L["Spell Peneration (%)"], + type = "number", + init = "GetSpellPenetration()", + store = true, + conditionType = "number", + multiEntry = { + operator = "and", + limit = 2 + }, }, { name = "resiliencerating", display = L["Resilience Rating"], type = "number", - init = [[ - local melee = GetCombatRating(CR_CRIT_TAKEN_MELEE); - local ranged = GetCombatRating(CR_CRIT_TAKEN_RANGED); - local spell = GetCombatRating(CR_CRIT_TAKEN_SPELL); - return math.min(melee, ranged, spell); - ]], + init = "min(GetCombatRating(CR_CRIT_TAKEN_MELEE), GetCombatRating(CR_CRIT_TAKEN_RANGED), GetCombatRating(CR_CRIT_TAKEN_SPELL))", store = true, conditionType = "number", + multiEntry = { + operator = "and", + limit = 2 + }, }, { name = "resiliencepercent", - display = L["Resilience Percent"], + display = L["Resilience (%)"], type = "number", - init = [[ - local ratings = { - melee = {value = GetCombatRating(CR_CRIT_TAKEN_MELEE), ratingType = CR_CRIT_TAKEN_MELEE}, - ranged = {value = GetCombatRating(CR_CRIT_TAKEN_RANGED), ratingType = CR_CRIT_TAKEN_RANGED}, - spell = {value = GetCombatRating(CR_CRIT_TAKEN_SPELL), ratingType = CR_CRIT_TAKEN_SPELL}, - }; - local lowest = ratings.melee; - if ratings.ranged.value < lowest.value then - lowest = ratings.ranged; - end - if ratings.spell.value < lowest.value then - lowest = ratings.spell; - end - return GetCombatRatingBonus(lowest.ratingType); - ]], - store = true, - conditionType = "number", - }, - { - name = "spellpenpercent", - display = L["Spell Peneration Percent"], - type = "number", - init = "GetSpellPenetration()", + init = "WeakAuras.GetResilienceDamageReduction()", store = true, conditionType = "number", + multiEntry = { + operator = "and", + limit = 2 + }, }, { type = "header", @@ -6795,10 +6823,10 @@ Private.event_prototypes = { }, }, { - name = "blockrating", - display = L["Block Rating"], + name = "blockpercent", + display = L["Block (%)"], type = "number", - init = "GetCombatRating(CR_BLOCK)", + init = "GetBlockChance()", store = true, conditionType = "number", multiEntry = { @@ -6807,10 +6835,10 @@ Private.event_prototypes = { }, }, { - name = "blockpercent", - display = L["Block (%)"], + name = "blockvalue", + display = L["Block Value"], type = "number", - init = "GetBlockChance()", + init = "GetShieldBlock()", store = true, conditionType = "number", multiEntry = { From 613c9ecefe477edc95b534768d7ab17007631bc6 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 13 Jan 2025 14:24:27 +0100 Subject: [PATCH 032/153] from retail --- WeakAuras/Modernize.lua | 52 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 4fa838a..9d1dd96 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1317,30 +1317,34 @@ function Private.Modernize(data) "intellect_operator", "spirit", "spirit_operator", - "meleecriticalrating", - "meleecriticalrating_operator", - "rangedcriticalrating", - "rangedcriticalrating_operator", - "spellcriticalrating", - "spellcriticalrating_operator", - "meleecriticalpercent", - "meleecriticalpercent_operator", - "rangedcriticalpercent", - "rangedcriticalpercent_operator", - "spellcriticalpercent", - "spellcriticalpercent_operator", - "meleehasterating", - "meleehasterating_operator", - "rangedhasterating", - "rangedhasterating_operator", - "spellhasterating", - "spellhasterating_operator", - "spellpenpercent", - "spellpenpercent_operator", - "armorpenpercent", - "armorpenpercent_operator", + "attackpower", + "attackpower_operator", + "spellpower", + "spellpower_operator", + "rangedattackpower", + "rangedattackpower_operator", + "criticalrating", + "criticalrating_operator", + "criticalpercent", + "criticalpercent_operator", + "hitrating", + "hitrating_operator", + "hitpercent", + "hitpercent_operator", + "hasterating", + "hasterating_operator", + "hastepercent", + "hastepercent_operator", + "expertiserating", + "expertiserating_operator", + "expertisebonus", + "expertisebonus_operator", "armorpenrating", "armorpenrating_operator", + "armorpenpercent", + "armorpenpercent_operator", + "spellpenpercent", + "spellpenpercent_operator", "resiliencerating", "resiliencerating_operator", "resiliencepercent", @@ -1369,10 +1373,10 @@ function Private.Modernize(data) "parryrating_operator", "parrypercent", "parrypercent_operator", - "blockrating", - "blockrating_operator", "blockpercent", "blockpercent_operator", + "blockvalue", + "blockvalue_operator", "armorrating", "armorrating_operator", "armorpercent", From 0291e5b5e75d9c0459013aac802179220609a7fe Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 13 Jan 2025 14:56:26 +0100 Subject: [PATCH 033/153] from retail --- WeakAuras/GenericTrigger.lua | 242 +++++++++++++++++++++++++++++++---- WeakAuras/Prototypes.lua | 11 +- 2 files changed, 228 insertions(+), 25 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index ffca714..1b104da 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -73,6 +73,7 @@ local events = {} local loaded_events = {} local loaded_unit_events = {}; local watched_trigger_events = Private.watched_trigger_events +local delayTimerEvents = {} local loaded_auras = {}; -- id to bool map -- Local functions @@ -672,7 +673,12 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 if(data.triggerFunc) then local untriggerCheck = false; if (data.statesParameter == "full") then - local ok, returnValue = pcall(data.triggerFunc, allStates, event, arg1, arg2, ...); + local ok, returnValue + if data.counter then + ok, returnValue = pcall(data.triggerFunc, allStates, data.counter, event, arg1, arg2, ...); + else + ok, returnValue = pcall(data.triggerFunc, allStates, event, arg1, arg2, ...); + end if not ok then errorHandler(returnValue) elseif ok and returnValue then @@ -686,7 +692,12 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 end end elseif (data.statesParameter == "all") then - local ok, returnValue = pcall(data.triggerFunc, allStates, event, arg1, arg2, ...); + local ok, returnValue + if data.counter then + ok, returnValue = pcall(data.triggerFunc, allStates, data.counter, event, arg1, arg2, ...); + else + ok, returnValue = pcall(data.triggerFunc, allStates, event, arg1, arg2, ...); + end if not ok then errorHandler(returnValue) elseif (ok and returnValue) or optionsEvent then @@ -722,7 +733,12 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 end allStates[cloneIdForUnitTrigger] = allStates[cloneIdForUnitTrigger] or {}; local state = allStates[cloneIdForUnitTrigger]; - local ok, returnValue = pcall(data.triggerFunc, state, event, unitForUnitTrigger, arg1, arg2, ...); + local ok, returnValue + if data.counter then + ok, returnValue = pcall(data.triggerFunc, state, data.counter, event, unitForUnitTrigger, arg1, arg2, ...); + else + ok, returnValue = pcall(data.triggerFunc, state, event, unitForUnitTrigger, arg1, arg2, ...); + end if not ok then errorHandler(returnValue) elseif (ok and returnValue) or optionsEvent then @@ -736,7 +752,12 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 elseif (data.statesParameter == "one") then allStates[""] = allStates[""] or {}; local state = allStates[""]; - local ok, returnValue = pcall(data.triggerFunc, state, event, arg1, arg2, ...); + local ok, returnValue + if data.counter then + ok, returnValue = pcall(data.triggerFunc, state, data.counter, event, arg1, arg2, ...); + else + ok, returnValue = pcall(data.triggerFunc, state, event, arg1, arg2, ...); + end if not ok then errorHandler(returnValue) elseif (ok and returnValue) or optionsEvent then @@ -747,7 +768,12 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 untriggerCheck = true; end else - local ok, returnValue = pcall(data.triggerFunc, event, arg1, arg2, ...); + local ok, returnValue + if data.counter then + ok, returnValue = pcall(data.triggerFunc, data.counter, event, arg1, arg2, ...); + else + ok, returnValue = pcall(data.triggerFunc, event, arg1, arg2, ...); + end if not ok then errorHandler(returnValue) elseif (ok and returnValue) or optionsEvent then @@ -896,8 +922,13 @@ function WeakAuras.ScanEventsInternal(event_list, event, arg1, arg2, ... ) local updateTriggerState = false; for triggernum, data in pairs(triggers) do local allStates = WeakAuras.GetTriggerStateForTrigger(id, triggernum); - if (RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2, ...)) then - updateTriggerState = true; + local delay = GenericTrigger.GetDelay(data) + if delay == 0 then + if (RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2, ...)) then + updateTriggerState = true + end + else + Private.RunTriggerFuncWithDelay(delay, id, triggernum, data, event, arg1, arg2, ...) end end if (updateTriggerState) then @@ -908,6 +939,50 @@ function WeakAuras.ScanEventsInternal(event_list, event, arg1, arg2, ... ) end end +do + local function RunTriggerFuncForDelay(id, triggernum, data, event, ...) + Private.StartProfileAura(id) + Private.ActivateAuraEnvironment(id) + local allStates = WeakAuras.GetTriggerStateForTrigger(id, triggernum) + if (RunTriggerFunc(allStates, data, id, triggernum, event, ...)) then + Private.UpdatedTriggerState(id) + end + Private.StopProfileAura(id) + Private.ActivateAuraEnvironment(nil) + -- clear expired timers + for i, t in ipairs_reverse(delayTimerEvents[id][triggernum]) do + if t.ends <= GetTime() then + table.remove(delayTimerEvents[id][triggernum], i) + end + end + end + + function Private.RunTriggerFuncWithDelay(delay, id, triggernum, data, event, ...) + delayTimerEvents[id] = delayTimerEvents[id] or {} + delayTimerEvents[id][triggernum] = delayTimerEvents[id][triggernum] or {} + local timerId = timer:ScheduleTimer(RunTriggerFuncForDelay, delay, id, triggernum, data, event, ...) + tinsert(delayTimerEvents[id][triggernum], timerId) + end +end + +function Private.CancelDelayedTrigger(id) + if delayTimerEvents[id] then + for triggernum, timers in pairs(delayTimerEvents[id]) do + for _, timerId in ipairs(timers) do + timer:CancelTimer(timerId) + end + end + delayTimerEvents[id] = nil + end +end + +function Private.CancelAllDelayedTriggers() + for id in pairs(delayTimerEvents) do + Private.CancelDelayedTrigger(id) + end +end + + function Private.ScanEventsWatchedTrigger(id, watchedTriggernums) Private.StartProfileAura(id); Private.ActivateAuraEnvironment(id); @@ -1066,6 +1141,7 @@ function GenericTrigger.UnloadAll() wipe(loaded_auras); wipe(loaded_events); wipe(loaded_unit_events); + Private.CancelAllDelayedTriggers(); Private.UnregisterAllEveryFrameUpdate(); end @@ -1086,6 +1162,8 @@ function GenericTrigger.UnloadDisplays(toUnload) auras[id] = nil; end end + + Private.CancelDelayedTrigger(id); Private.UnregisterEveryFrameUpdate(id); end end @@ -1294,6 +1372,10 @@ function GenericTrigger.LoadDisplays(toLoad, loadEvent, ...) end end + if data.counter then + data.counter:Reset() + end + LoadEvent(id, triggernum, data); end end @@ -1343,6 +1425,80 @@ end function GenericTrigger.FinishLoadUnload() end +do + local function ParseCron(pattern) + local tests = {} + for test in pattern:gmatch("[^ ,]+") do + local startString, endString, intervalString = test:match("(%d*)-?(%d*)/?(%d*)") + local intervalNumber = tonumber(intervalString) + local startNumber = startString == "" and 0 or tonumber(startString) or 0 + local endNumber = tonumber(endString) + if not endNumber then + endNumber = intervalNumber and math.huge or startNumber + end + intervalNumber = intervalNumber or 1 + + tinsert(tests, { + startNumber = startNumber, + endNumber = endNumber, + intervalNumber = intervalNumber, + Match = function(self, count) + return (count >= self.startNumber and count <= self.endNumber and (count - self.startNumber) % self.intervalNumber == 0) + end + }) + end + return tests + end + + function Private.CreateTriggerCounter(pattern) + local counter = { + count = 0, + tests = { + + + }, + fastMatches = { + }, + Reset = function(self) + self.count = 0 + end, + GetNext = function(self) + self.count = self.count + 1 + return self.count + end, + } + if pattern then + counter.tests = ParseCron(pattern) + counter.RunTests = function(self, count) + for _, test in ipairs(self.tests) do + if test:Match(count) then + return true + end + end + return false + end + + for i = 1, 20 do + counter.fastMatches[i] = counter.RunTests(counter, i) + end + + counter.Match = function(self) + if self.count <= 20 then + return counter.fastMatches[self.count] + end + return self:RunTests(self.count) + end + + else + counter.Match = function(self) + return true + end + end + + return counter + end +end + --- Adds a display, creating all internal data structures for all triggers. -- @param data -- @param region @@ -1371,6 +1527,7 @@ function GenericTrigger.Add(data, region) local prototype = nil local automaticAutoHide local duration + local counter if(Private.category_event_prototype[triggerType]) then if not(trigger.event) then error("Improper arguments to WeakAuras.Add - trigger type is \"event\" but event is not defined"); @@ -1432,6 +1589,14 @@ function GenericTrigger.Add(data, region) WeakAuras.prettyPrint("Invalid Prototype found: " .. prototype.name) end + if prototype.countEvents then + if trigger.use_count and type(trigger.count) == "string" and trigger.count ~= "" then + counter = Private.CreateTriggerCounter(trigger.count) + else + counter = Private.CreateTriggerCounter() + end + end + if(prototype) then local trigger_all_events = prototype.events; internal_events = prototype.internal_events; @@ -1616,7 +1781,8 @@ function GenericTrigger.Add(data, region) automaticAutoHide = automaticAutoHide, tsuConditionVariables = tsuConditionVariables, prototype = prototype, - ignoreOptionsEventErrors = data.information.ignoreOptionsEventErrors + ignoreOptionsEventErrors = data.information.ignoreOptionsEventErrors, + counter = counter, }; end end @@ -3746,23 +3912,26 @@ function GenericTrigger.CanHaveDuration(data, triggernum) local trigger = data.triggers[triggernum].trigger if (Private.category_event_prototype[trigger.type]) then - if trigger.event and Private.event_prototypes[trigger.event] then - if Private.event_prototypes[trigger.event].durationFunc then - if(type(Private.event_prototypes[trigger.event].init) == "function") then - Private.event_prototypes[trigger.event].init(trigger); + if trigger.event then + local prototype = Private.event_prototypes[trigger.event] + if prototype then + if prototype.durationFunc then + if(type(prototype.init) == "function") then + prototype.init(trigger); + end + local current, maximum, custom = prototype.durationFunc(trigger); + current = type(current) ~= "number" and current or 0 + maximum = type(maximum) ~= "number" and maximum or 0 + if(custom) then + return {current = current, maximum = maximum}; + else + return "timed"; + end + elseif prototype.canHaveDuration then + return prototype.canHaveDuration, prototype.useModRate + elseif prototype.timedrequired then + return "timed" end - local current, maximum, custom = Private.event_prototypes[trigger.event].durationFunc(trigger); - current = type(current) ~= "number" and current or 0 - maximum = type(maximum) ~= "number" and maximum or 0 - if(custom) then - return {current = current, maximum = maximum}; - else - return "timed"; - end - elseif Private.event_prototypes[trigger.event].canHaveDuration then - return Private.event_prototypes[trigger.event].canHaveDuration - elseif Private.event_prototypes[trigger.event].timedrequired then - return "timed" end end elseif (trigger.type == "custom") then @@ -3777,6 +3946,19 @@ function GenericTrigger.CanHaveDuration(data, triggernum) return false end +function GenericTrigger.GetDelay(data) + if data.event then + local prototype = Private.event_prototypes[data.event] + if prototype and prototype.delayEvents then + local trigger = data.trigger + if trigger.use_delay and type(trigger.delay) == "number" and trigger.delay > 0 then + return trigger.delay + end + end + end + return 0 +end + function GenericTrigger.GetTsuConditionVariables(id, triggernum) local ok, variables = xpcall(events[id][triggernum].tsuConditionVariables, Private.GetErrorHandlerId(id, L["Custom Variables"])); if ok then @@ -3959,6 +4141,11 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) end end + if Private.event_prototypes[trigger.event].countEvents then + found = true; + additional = additional .. "|cFFFF0000%".. triggernum .. ".count|r - " .. L["Count"] .. "\n"; + end + if (found) then ret = ret .. additional; end @@ -4106,6 +4293,13 @@ function GenericTrigger.GetTriggerConditions(data, triggernum) end end + if Private.event_prototypes[trigger.event].countEvents then + result.count = { + display = L["Count"], + type = "number" + } + end + return result; end elseif(trigger.type == "custom") then diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index e972b53..284e1bc 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3015,7 +3015,9 @@ Private.event_prototypes = { test = "true" }, }, - timedrequired = true + countEvents = true, + delayEvents = true, + timedrequired = true, }, ["Cooldown Progress (Spell)"] = { type = "spell", @@ -5400,6 +5402,8 @@ Private.event_prototypes = { reloadOptions = true }, }, + countEvents = true, + delayEvents = true, timedrequired = true }, ["Ready Check"] = { @@ -5409,6 +5413,8 @@ Private.event_prototypes = { }, name = L["Ready Check"], args = {}, + statesParameter = "one", + delayEvents = true, timedrequired = true }, ["Combat Events"] = { @@ -5430,6 +5436,9 @@ Private.event_prototypes = { test = "event == %q" } }, + statesParameter = "one", + countEvents = true, + delayEvents = true, timedrequired = true }, ["Death Knight Rune"] = { From d14313d8487c6c716ac1f0dffce071436acdd835 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 13 Jan 2025 17:38:21 +0100 Subject: [PATCH 034/153] from retail --- WeakAuras/Conditions.lua | 13 +++-- WeakAuras/GenericTrigger.lua | 15 +++--- WeakAuras/Prototypes.lua | 63 ++++++++++++++++++++++- WeakAuras/RegionTypes/RegionPrototype.lua | 10 +++- 4 files changed, 83 insertions(+), 18 deletions(-) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index 116a6a1..350fb53 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -742,20 +742,20 @@ local function runDynamicConditionFunctions(funcs) end end -local function handleDynamicConditions(self, event) +local function handleDynamicConditions(self, event, onlyUpdateState) Private.StartProfileSystem("dynamic conditions") if (globalDynamicConditionFuncs[event]) then for i, func in ipairs(globalDynamicConditionFuncs[event]) do func(globalConditionState); end end - if (dynamicConditions[event]) then + if (dynamicConditions[event] and not onlyUpdateState) then runDynamicConditionFunctions(dynamicConditions[event]); end Private.StopProfileSystem("dynamic conditions") end -local function handleDynamicConditionsPerUnit(self, event, unit) +local function handleDynamicConditionsPerUnit(self, event, unit, onlyUpdateState) Private.StartProfileSystem("dynamic conditions") if unit and unit == self.unit then local unitEvent = event..":"..unit @@ -764,7 +764,7 @@ local function handleDynamicConditionsPerUnit(self, event, unit) func(globalConditionState); end end - if (dynamicConditions[unitEvent]) then + if (dynamicConditions[unitEvent] and not onlyUpdateState) then runDynamicConditionFunctions(dynamicConditions[unitEvent]); end end @@ -853,7 +853,6 @@ function Private.RegisterForGlobalConditions(uid) if (not dynamicConditionsFrame.onUpdate) then dynamicConditionsFrame:SetScript("OnUpdate", handleDynamicConditionsOnUpdate); dynamicConditionsFrame.onUpdate = true; - handleDynamicConditionsOnUpdate(dynamicConditionsFrame, event) end else local unitEvent, unit = event:match("([^:]+):([^:]+)") @@ -865,10 +864,10 @@ function Private.RegisterForGlobalConditions(uid) end dynamicConditionsFrame.units[unit].unit = unit; pcall(dynamicConditionsFrame.RegisterEvent, dynamicConditionsFrame.units[unit], unitEvent); - handleDynamicConditionsPerUnit(dynamicConditionsFrame, event, unit) + handleDynamicConditionsPerUnit(dynamicConditionsFrame, event, unit, true) else pcall(dynamicConditionsFrame.RegisterEvent, dynamicConditionsFrame, event); - handleDynamicConditions(dynamicConditionsFrame, event) + handleDynamicConditions(dynamicConditionsFrame, event, true) end end end diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 1b104da..08a295a 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -445,7 +445,7 @@ function ConstructFunction(prototype, trigger) return table.concat(ret); end -function Private.EndEvent(id, triggernum, force, state) +function Private.EndEvent(state) if state then if (state.show ~= false and state.show ~= nil) then state.show = false; @@ -796,7 +796,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 elseif (ok and returnValue) or optionsEvent then for id, state in pairs(allStates) do if (state.changed) then - if (Private.EndEvent(id, triggernum, nil, state)) then + if (Private.EndEvent(state)) then updateTriggerState = true; end end @@ -808,11 +808,11 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 if arg1 then local state = allStates[cloneIdForUnitTrigger] if state then - local ok, returnValue = pcall(data.untriggerFunc, state, event, unitForUnitTrigger, arg2, ...); + local ok, returnValue = pcall(data.untriggerFunc, state, event, unitForUnitTrigger, arg1, arg2, ...); if not ok then errorHandler(returnValue) elseif ok and returnValue then - if (Private.EndEvent(id, triggernum, nil, state)) then + if (Private.EndEvent(state)) then updateTriggerState = true; end end @@ -832,7 +832,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 if not ok then errorHandler(returnValue) elseif (ok and returnValue) then - if (Private.EndEvent(id, triggernum, nil, state)) then + if (Private.EndEvent(state)) then updateTriggerState = true; end end @@ -845,7 +845,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 elseif (ok and returnValue) then allStates[""] = allStates[""] or {}; local state = allStates[""]; - if(Private.EndEvent(id, triggernum, nil, state)) then + if (Private.EndEvent(state)) then updateTriggerState = true; end end @@ -1790,8 +1790,7 @@ function GenericTrigger.Add(data, region) if warnAboutCLEUEvents then Private.AuraWarnings.UpdateWarning(data.uid, "spamy_event_warning", "warning", - L["COMBAT_LOG_EVENT_UNFILTERED with no filter can trigger frame drops in raid environment. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Deprecated-CLEU"], - true) + L["COMBAT_LOG_EVENT_UNFILTERED with no filter can trigger frame drops in raid environment. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Deprecated-CLEU"]) else Private.AuraWarnings.UpdateWarning(data.uid, "spamy_event_warning") end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 284e1bc..243a131 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4713,7 +4713,7 @@ Private.event_prototypes = { tier = %s column = %s local name, icon, _, _, rank = GetTalentInfo(tier, column) - if rank > 0 then + if rank and rank > 0 then active = true; activeName = name; activeIcon = icon; @@ -5406,6 +5406,67 @@ Private.event_prototypes = { delayEvents = true, timedrequired = true }, + -- fixing later + --[[["Spell Cast Succeeded"] = { + type = "event", + events = function(trigger) + local result = {} + local unit = trigger.unit + AddUnitEventForEvents(result, unit, "UNIT_SPELLCAST_SUCCEEDED") + return result + end, + name = L["Spell Cast Succeeded"], + statesParameter = "unit", + args = { + {}, + { + name = "unit", + init = "arg", + display = L["Caster Unit"], + type = "unit", + test = "true", + values = "actual_unit_types_cast", + store = true, + conditionType = "select", + conditionTest = function(state, needle, op) + return state and state.show and (UnitIsUnit(needle, state.unit or '') == (op == "==")) + end + }, + { + name = "spellName", + type = "string", + init = "arg", + test = "true", + store = true, + hidden = true + }, + { + name = "rank", + type = "string", + init = "arg", + test = "true", + store = true, + hidden = true + }, + { + name = "spellId", + display = L["Spell Id"], + type = "string", + store = true, + conditionType = "number" + }, + { + name = "icon", + hidden = true, + init = "select(3, GetSpellInfo(spellId))", + store = true, + test = "true" + }, + }, + countEvents = true, + delayEvents = true, + timedrequired = true + },]] ["Ready Check"] = { type = "event", events = { diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index af109c5..7d1b923 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -338,9 +338,15 @@ local function SetAnimAlpha(self, alpha) end self.animAlpha = alpha; if (WeakAuras.IsOptionsOpen()) then - self:SetAlpha(max(self.animAlpha or self.alpha or 1, 0.5)); + local ok = pcall(self.SetAlpha, self, max(self.animAlpha or self.alpha or 1, 0.5)) + if not ok then + Private.GetErrorHandlerId(self.id, L["Custom Fade Animation"]) + end else - self:SetAlpha(self.animAlpha or self.alpha or 1); + local ok = pcall(self.SetAlpha, self, self.animAlpha or self.alpha or 1) + if not ok then + Private.GetErrorHandlerId(self.id, L["Custom Fade Animation"]) + end end self.subRegionEvents:Notify("AlphaChanged") end From 43c9ccec1c5346f6e2758446b582f468ebd991d5 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 13 Jan 2025 17:54:30 +0100 Subject: [PATCH 035/153] from retail --- WeakAuras/Conditions.lua | 27 +++++++++++----- WeakAuras/GenericTrigger.lua | 36 +++++++++++++--------- WeakAuras/Prototypes.lua | 49 +++++++++++++++++++++--------- WeakAurasOptions/AuthorOptions.lua | 2 ++ 4 files changed, 78 insertions(+), 36 deletions(-) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index 350fb53..e2f4f78 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -742,21 +742,24 @@ local function runDynamicConditionFunctions(funcs) end end -local function handleDynamicConditions(self, event, onlyUpdateState) - Private.StartProfileSystem("dynamic conditions") +local function UpdateDynamicConditonsStates(self, event) if (globalDynamicConditionFuncs[event]) then for i, func in ipairs(globalDynamicConditionFuncs[event]) do func(globalConditionState); end end - if (dynamicConditions[event] and not onlyUpdateState) then +end + +local function handleDynamicConditions(self, event) + Private.StartProfileSystem("dynamic conditions") + UpdateDynamicConditonsStates(self, event) + if (dynamicConditions[event]) then runDynamicConditionFunctions(dynamicConditions[event]); end Private.StopProfileSystem("dynamic conditions") end -local function handleDynamicConditionsPerUnit(self, event, unit, onlyUpdateState) - Private.StartProfileSystem("dynamic conditions") +local function UpdateDynamicConditionsPerUnitState(self, event, unit) if unit and unit == self.unit then local unitEvent = event..":"..unit if globalDynamicConditionFuncs[unitEvent] then @@ -764,7 +767,15 @@ local function handleDynamicConditionsPerUnit(self, event, unit, onlyUpdateState func(globalConditionState); end end - if (dynamicConditions[unitEvent] and not onlyUpdateState) then + end +end + +local function handleDynamicConditionsPerUnit(self, event, unit) + Private.StartProfileSystem("dynamic conditions") + if unit then + local unitEvent = event..":"..unit + UpdateDynamicConditionsPerUnitState(self, event, unit) + if (dynamicConditions[unitEvent]) then runDynamicConditionFunctions(dynamicConditions[unitEvent]); end end @@ -864,10 +875,10 @@ function Private.RegisterForGlobalConditions(uid) end dynamicConditionsFrame.units[unit].unit = unit; pcall(dynamicConditionsFrame.RegisterEvent, dynamicConditionsFrame.units[unit], unitEvent); - handleDynamicConditionsPerUnit(dynamicConditionsFrame, event, unit, true) + UpdateDynamicConditionsPerUnitState(dynamicConditionsFrame, event, unit) else pcall(dynamicConditionsFrame.RegisterEvent, dynamicConditionsFrame, event); - handleDynamicConditions(dynamicConditionsFrame, event, true) + UpdateDynamicConditonsStates(dynamicConditionsFrame, event) end end end diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 08a295a..6370931 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1450,12 +1450,11 @@ do return tests end - function Private.CreateTriggerCounter(pattern) + function Private.ExecEnv.CreateTriggerCounter(pattern) local counter = { count = 0, tests = { - }, fastMatches = { }, @@ -1466,6 +1465,9 @@ do self.count = self.count + 1 return self.count end, + SetCount = function(self, count) + self.count = count + end, } if pattern then counter.tests = ParseCron(pattern) @@ -1591,9 +1593,9 @@ function GenericTrigger.Add(data, region) if prototype.countEvents then if trigger.use_count and type(trigger.count) == "string" and trigger.count ~= "" then - counter = Private.CreateTriggerCounter(trigger.count) + counter = Private.ExecEnv.CreateTriggerCounter(trigger.count) else - counter = Private.CreateTriggerCounter() + counter = Private.ExecEnv.CreateTriggerCounter() end end @@ -3051,7 +3053,7 @@ do bar.icon = icon bar.timerType = timerType bar.spellId = tostring(spellId) - bar.count = msg:match("(%d+)") or "0" + bar.count = msg:match("%((%d+)%)") or "0" bar.dbmType = dbmType local barOptions = DBM.ReleaseRevision >= 20220412000000 and DBT.Options or DBM.Bars.options @@ -3116,7 +3118,7 @@ do end end - function Private.ExecEnv.DBMTimerMatches(timerId, id, message, operator, spellId, dbmType, count) + function Private.ExecEnv.DBMTimerMatches(timerId, id, message, operator, spellId, dbmType, counter) if not bars[timerId] then return false end @@ -3143,8 +3145,11 @@ do end end end - if count and count ~= "" and count ~= v.count then - return false + if counter then + counter:SetCount(tonumber(v.count) or 0) + if not counter:Match() then + return false + end end if dbmType and dbmType ~= v.dbmType then return false @@ -3278,7 +3283,7 @@ do bar.bwBackgroundColor = BWColorModule:GetColorTable("barBackground", addon, spellId) local BWEmphasizedModule = BigWigs:GetPlugin("Super Emphasize") bar.emphasized = BWEmphasizedModule:IsSuperEmphasized(addon, spellId) and true or false - bar.count = text:match("(%d+)") or "0" + bar.count = text:match("%((%d+)%)") or "0" bar.cast = not(text:match("^[^<]") and true) WeakAuras.ScanEvents("BigWigs_StartBar", text) @@ -3355,7 +3360,7 @@ do state.isCooldown = bar.isCooldown end - function Private.ExecEnv.BigWigsTimerMatches(id, message, operator, spellId, emphasized, count, cast, cooldown) + function Private.ExecEnv.BigWigsTimerMatches(id, message, operator, spellId, emphasized, counter, cast, cooldown) if not bars[id] then return false end @@ -3383,8 +3388,11 @@ do if emphasized ~= nil and v.emphasized ~= emphasized then return false end - if count and count ~= "" and count ~= v.count then - return false + if counter then + counter:SetCount(tonumber(v.count) or 0) + if not counter:Match() then + return false + end end if cast ~= nil and v.cast ~= cast then return false @@ -3403,10 +3411,10 @@ do return bars[id] end - function WeakAuras.GetBigWigsTimer(text, operator, spellId, extendTimer, emphasized, count, cast) + function WeakAuras.GetBigWigsTimer(text, operator, spellId, extendTimer, emphasized, counter, cast) local bestMatch for id, bar in pairs(bars) do - if Private.ExecEnv.BigWigsTimerMatches(id, text, operator, spellId, emphasized, count, cast) + if Private.ExecEnv.BigWigsTimerMatches(id, text, operator, spellId, emphasized, counter, cast) and (bestMatch == nil or bar.expirationTime < bestMatch.expirationTime) and bar.expirationTime + extendTimer > GetTime() then diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 243a131..3ef6eb2 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3949,6 +3949,13 @@ Private.event_prototypes = { WeakAuras.RegisterDBMCallback("kill") local ret = [=[ + local triggerCounter = %q + local counter + if triggerCounter and triggerCounter ~= "" then + counter = Private.ExecEnv.CreateTriggerCounter(triggerCounter) + else + counter = Private.ExecEnv.CreateTriggerCounter() + end return function (states, event, id) local triggerId = %q local triggerSpellId = %q @@ -3958,10 +3965,10 @@ Private.event_prototypes = { local extendTimer = %s local triggerUseRemaining = %s local triggerRemaining = %s - local triggerCount = %q local triggerDbmType = %s local cloneId = useClone and id or "" local state = states[cloneId] + local counter = counter function copyOrSchedule(bar, cloneId) if triggerUseRemaining then @@ -3985,7 +3992,7 @@ Private.event_prototypes = { if useClone then if event == "DBM_TimerStart" then - if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then + if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, counter) then local bar = WeakAuras.GetDBMTimerById(id) if bar then copyOrSchedule(bar, cloneId) @@ -3999,7 +4006,7 @@ Private.event_prototypes = { end elseif event == "DBM_TimerUpdate" then for id, bar in pairs(WeakAuras.GetAllDBMTimers()) do - if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then + if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, counter) then copyOrSchedule(bar, id) else local state = states[id] @@ -4015,7 +4022,7 @@ Private.event_prototypes = { elseif event == "DBM_TimerForce" then wipe(states) for id, bar in pairs(WeakAuras.GetAllDBMTimers()) do - if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then + if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, counter) then copyOrSchedule(bar, cloneId) end end @@ -4023,13 +4030,13 @@ Private.event_prototypes = { else if event == "DBM_TimerStart" or event == "DBM_TimerUpdate" then if extendTimer ~= 0 then - if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, triggerCount) then + if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, counter) then local bar = WeakAuras.GetDBMTimerById(id) Private.ExecEnv.ScheduleDbmCheck(bar.expirationTime + extendTimer) end end end - local bar = WeakAuras.GetDBMTimer(triggerId, triggerText, triggerTextOperator, triggerSpellId, extendTimer, triggerDbmType, triggerCount) + local bar = WeakAuras.GetDBMTimer(triggerId, triggerText, triggerTextOperator, triggerSpellId, extendTimer, triggerDbmType, counter) if bar then if extendTimer == 0 or not (state and state.show) @@ -4052,6 +4059,7 @@ Private.event_prototypes = { ]=] return ret:format( + trigger.use_count and trigger.count or "", trigger.use_id and trigger.id or "", trigger.use_spellId and tostring(trigger.spellId) or "", trigger.use_message and trigger.message or "", @@ -4060,7 +4068,6 @@ Private.event_prototypes = { trigger.use_extend and tonumber(trigger.extend or 0) or 0, trigger.use_remaining and "true" or "false", trigger.remaining or 0, - trigger.use_count and trigger.count or "", trigger.use_dbmType and trigger.dbmType or "nil", trigger.remaining_operator or "<" ) @@ -4191,6 +4198,13 @@ Private.event_prototypes = { triggerFunction = function(trigger) WeakAuras.RegisterBigWigsTimer() local ret = [=[ + local triggerCounter = %q + local counter + if triggerCounter and triggerCounter ~= "" then + counter = Private.ExecEnv.CreateTriggerCounter(triggerCounter) + else + counter = Private.ExecEnv.CreateTriggerCounter() + end return function(states, event, id) local triggerSpellId = %q local triggerText = %q @@ -4200,11 +4214,11 @@ Private.event_prototypes = { local triggerUseRemaining = %s local triggerRemaining = %s local triggerEmphasized = %s - local triggerCount = %q local triggerCast = %s local triggerIsCooldown = %s local cloneId = useClone and id or "" local state = states[cloneId] + local counter = counter function copyOrSchedule(bar, cloneId) if triggerUseRemaining then @@ -4228,7 +4242,7 @@ Private.event_prototypes = { if useClone then if event == "BigWigs_StartBar" then - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast, triggerIsCooldown) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, counter, triggerCast, triggerIsCooldown) then local bar = WeakAuras.GetBigWigsTimerById(id) if bar then copyOrSchedule(bar, cloneId) @@ -4242,14 +4256,14 @@ Private.event_prototypes = { end elseif event == "BigWigs_Timer_Update" then for id, bar in pairs(WeakAuras.GetAllBigWigsTimers()) do - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, counter, triggerCast) then copyOrSchedule(bar, id) end end elseif event == "BigWigs_Timer_Force" then wipe(states) for id, bar in pairs(WeakAuras.GetAllBigWigsTimers()) do - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, counter, triggerCast) then copyOrSchedule(bar, id) end end @@ -4257,13 +4271,13 @@ Private.event_prototypes = { else if event == "BigWigs_StartBar" then if extendTimer ~= 0 then - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, triggerCount, triggerCast) then + if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, counter, triggerCast) then local bar = WeakAuras.GetBigWigsTimerById(id) Private.ExecEnv.ScheduleBigWigsCheck(bar.expirationTime + extendTimer) end end end - local bar = WeakAuras.GetBigWigsTimer(triggerText, triggerTextOperator, triggerSpellId, extendTimer, triggerEmphasized, triggerCount, triggerCast) + local bar = WeakAuras.GetBigWigsTimer(triggerText, triggerTextOperator, triggerSpellId, extendTimer, triggerEmphasized, counter, triggerCast) if bar then if extendTimer == 0 or not (state and state.show) @@ -4285,6 +4299,7 @@ Private.event_prototypes = { end ]=] return ret:format( + trigger.use_count and trigger.count or "", trigger.use_spellId and tostring(trigger.spellId) or "", trigger.use_text and trigger.text or "", trigger.use_text and trigger.text_operator or "", @@ -4293,7 +4308,6 @@ Private.event_prototypes = { trigger.use_remaining and "true" or "false", trigger.remaining or 0, trigger.use_emphasized == nil and "nil" or trigger.use_emphasized and "true" or "false", - trigger.use_count and trigger.count or "", trigger.use_cast == nil and "nil" or trigger.use_cast and "true" or "false", trigger.use_isCooldown == nil and "nil" or trigger.use_isCooldown and "true" or "false", trigger.remaining_operator or "<" @@ -5462,6 +5476,13 @@ Private.event_prototypes = { store = true, test = "true" }, + { + name = "name", + hidden = true, + init = "GetSpellInfo(spellId)", + store = true, + test = "true" + }, }, countEvents = true, delayEvents = true, diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index 15c4e61..a0b3380 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -1789,6 +1789,8 @@ function addAuthorModeOption(options, args, data, order, prefix, i) local dereferencedParent = parent.references[id].options[parent.references[id].index] if dereferencedParent.nameSource == optionData.index then dereferencedParent.nameSource = 0 + elseif dereferencedParent.nameSource > optionData.index then + dereferencedParent.nameSource = dereferencedParent.nameSource - 1 end end WeakAuras.Add(childData) From 74cc0c7ee8dba9a38b5a12f55cdd83c72d281a4a Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 13 Jan 2025 19:15:17 +0100 Subject: [PATCH 036/153] from retail --- WeakAuras/BuffTrigger2.lua | 15 +++++++---- WeakAuras/GenericTrigger.lua | 51 +++++++++++++++++++++++++++--------- WeakAuras/WeakAuras.lua | 12 +++++++-- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 6daa6ba..305f54d 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -1434,11 +1434,16 @@ local function CleanUpMatchDataForUnit(unit, filter) for index, data in pairs(matchData[unit][filter]) do matchData[unit][filter][index] = nil for id, triggerData in pairs(data.auras) do - for triggernum in pairs(triggerData) do - matchDataByTrigger[id][triggernum][unit][index] = nil - matchDataChanged[id] = matchDataChanged[id] or {} - matchDataChanged[id][triggernum] = true - end + for triggernum in pairs(triggerData) do + if matchDataByTrigger[id] and matchDataByTrigger[id][triggernum] + and matchDataByTrigger[id][triggernum][unit] + and matchDataByTrigger[id][triggernum][unit][index] + then + matchDataByTrigger[id][triggernum][unit][index] = nil + matchDataChanged[id] = matchDataChanged[id] or {} + matchDataChanged[id][triggernum] = true + end + end end end end diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 6370931..96f82fd 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -899,9 +899,14 @@ function WeakAuras.ScanUnitEvents(event, unit, ...) Private.ActivateAuraEnvironment(id); local updateTriggerState = false; for triggernum, data in pairs(triggers) do - local allStates = WeakAuras.GetTriggerStateForTrigger(id, triggernum); - if (RunTriggerFunc(allStates, data, id, triggernum, event, unit, ...)) then - updateTriggerState = true; + local delay = GenericTrigger.GetDelay(data) + if delay == 0 then + local allStates = WeakAuras.GetTriggerStateForTrigger(id, triggernum); + if (RunTriggerFunc(allStates, data, id, triggernum, event, unit, ...)) then + updateTriggerState = true; + end + else + Private.RunTriggerFuncWithDelay(delay, id, triggernum, data, event, unit, ...) end end if (updateTriggerState) then @@ -2262,6 +2267,7 @@ do local spellCdsRune = CreateSpellCDHandler(); local spellDetails = {} + local mark_ACTIONBAR_UPDATE_COOLDOWN, mark_PLAYER_ENTERING_WORLD function Private.InitCooldownReady() cdReadyFrame = CreateFrame("Frame"); @@ -2292,21 +2298,35 @@ do end if GetTime() - cdReadyFrame.inWorld < 2 then - cdReadyFrame:SetScript("OnUpdate", cdReadyFrame.HandleEvent) + mark_PLAYER_ENTERING_WORLD = true + cdReadyFrame:Show() + return + end + if (event == "ACTIONBAR_UPDATE_COOLDOWN") then + mark_ACTIONBAR_UPDATE_COOLDOWN = true + cdReadyFrame:Show() return end - cdReadyFrame:SetScript("OnUpdate", nil) Private.StartProfileSystem("generictrigger cd tracking"); if type(event) == "number" then-- Called from OnUpdate! - Private.CheckSpellKnown() - Private.CheckCooldownReady() - Private.CheckItemSlotCooldowns() - elseif(event == "SPELL_UPDATE_COOLDOWN" - or event == "RUNE_POWER_UPDATE" or event == "RUNE_TYPE_UPDATE" or event == "ACTIONBAR_UPDATE_COOLDOWN" + if mark_PLAYER_ENTERING_WORLD then + Private.CheckSpellKnown() + Private.CheckCooldownReady() + Private.CheckItemSlotCooldowns() + mark_PLAYER_ENTERING_WORLD = nil + mark_ACTIONBAR_UPDATE_COOLDOWN = nil + elseif mark_ACTIONBAR_UPDATE_COOLDOWN then + Private.CheckCooldownReady() + mark_ACTIONBAR_UPDATE_COOLDOWN = nil + end + elseif(event == "SPELL_UPDATE_COOLDOWN" or event == "RUNE_POWER_UPDATE" or event == "PLAYER_TALENT_UPDATE" - or event == "CHARACTER_POINTS_CHANGED") then - Private.CheckCooldownReady(); + or event == "CHARACTER_POINTS_CHANGED" or event == "RUNE_TYPE_UPDATE") then + if event == "SPELL_UPDATE_COOLDOWN" then + mark_ACTIONBAR_UPDATE_COOLDOWN = nil + end + Private.CheckCooldownReady(); elseif(event == "SPELLS_CHANGED") then Private.CheckSpellKnown() Private.CheckCooldownReady() @@ -2326,8 +2346,15 @@ do Private.CheckItemSlotCooldowns(); end Private.StopProfileSystem("generictrigger cd tracking"); + if mark_PLAYER_ENTERING_WORLD == nil and mark_ACTIONBAR_UPDATE_COOLDOWN == nil then + cdReadyFrame:Hide() + else + cdReadyFrame:Show() + end end + cdReadyFrame:Hide() cdReadyFrame:SetScript("OnEvent", cdReadyFrame.HandleEvent) + cdReadyFrame:SetScript("OnUpdate", cdReadyFrame.HandleEvent) end function WeakAuras.GetRuneCooldown(id) diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 1fdc146..10d60e3 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2691,6 +2691,16 @@ local function pAdd(data, simpleChange) end end + -- If the aura has a onHide animation we need to cancel it to ensure it's truely hidden now + if Private.regions[id] then + Private.CancelAnimation(Private.regions[id].region, true, true, true, true, true, true) + end + if clones[id] then + for _, region in pairs(clones[id]) do + Private.CancelAnimation(region, true, true, true, true, true, true) + end + end + Private.ClearAuraEnvironment(id); for parent in Private.TraverseParents(data) do Private.ClearAuraEnvironment(parent.id); @@ -5581,5 +5591,3 @@ do return data.regionType == "group" or data.regionType == "dynamicgroup" end end - - From 9d6005c82fa31aa42d7489f8507e11bd4cc55546 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Tue, 14 Jan 2025 02:10:45 +0100 Subject: [PATCH 037/153] from retail --- WeakAuras/Conditions.lua | 7 +- WeakAuras/GenericTrigger.lua | 4 +- WeakAuras/Prototypes.lua | 4 +- WeakAuras/SubRegionTypes/SubText.lua | 218 +++++++++++------- WeakAuras/SubscribableObject.lua | 14 ++ WeakAurasOptions/ConditionOptions.lua | 13 ++ WeakAurasOptions/SubRegionOptions/SubText.lua | 19 +- 7 files changed, 189 insertions(+), 90 deletions(-) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index e2f4f78..a0e71b7 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -56,6 +56,11 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path return tostring(value) end return "nil" + elseif (vType == "string") then + if type(value) == "string" then + return string.format("%s", Private.QuotedString(value)) + end + return "nil" elseif(vType == "color") then if (value and type(value) == "table") then return string.format("{%s, %s, %s, %s}", tostring(value[1]), tostring(value[2]), tostring(value[3]), tostring(value[4])); @@ -114,7 +119,7 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path end local function formatValueForCall(type, property) - if (type == "bool" or type == "number" or type == "list" or type == "icon") then + if (type == "bool" or type == "number" or type == "list" or type == "icon" or type == "string") then return "propertyChanges['" .. property .. "']"; elseif (type == "color") then local pcp = "propertyChanges['" .. property .. "']"; diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 96f82fd..72a63a1 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -3080,7 +3080,7 @@ do bar.icon = icon bar.timerType = timerType bar.spellId = tostring(spellId) - bar.count = msg:match("%((%d+)%)") or "0" + bar.count = msg:match("%((%d+)%)") or msg:match("((%d+))") or "0" bar.dbmType = dbmType local barOptions = DBM.ReleaseRevision >= 20220412000000 and DBT.Options or DBM.Bars.options @@ -3310,7 +3310,7 @@ do bar.bwBackgroundColor = BWColorModule:GetColorTable("barBackground", addon, spellId) local BWEmphasizedModule = BigWigs:GetPlugin("Super Emphasize") bar.emphasized = BWEmphasizedModule:IsSuperEmphasized(addon, spellId) and true or false - bar.count = text:match("%((%d+)%)") or "0" + bar.count = text:match("%((%d+)%)") or text:match("((%d+))") or "0" bar.cast = not(text:match("^[^<]") and true) WeakAuras.ScanEvents("BigWigs_StartBar", text) diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 3ef6eb2..3f239ed 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4106,7 +4106,7 @@ Private.event_prototypes = { { name = "count", display = L["Count"], - desc = L["Only if DBM shows it on it's bar"], + desc = L["Occurence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if DBM shows it on it's bar"], type = "string", conditionType = "string", }, @@ -4341,7 +4341,7 @@ Private.event_prototypes = { { name = "count", display = L["Count"], - desc = L["Only if BigWigs shows it on it's bar"], + desc = L["Occurence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if BigWigs shows it on it's bar"], type = "string", conditionType = "string", }, diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index b4e04ad..a8b4c3b 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -68,6 +68,11 @@ local properties = { type = "bool", defaultProperty = true }, + text_text = { + display = L["Text"], + setter = "ChangeText", + type = "string" + }, text_color = { display = L["Color"], setter = "Color", @@ -137,11 +142,12 @@ local function modify(parent, region, parentData, data, first) if not text:GetFont() then -- Font invalid, set the font but keep the setting text:SetFont(STANDARD_TEXT_FONT, data.text_fontSize < 33 and data.text_fontSize or 33, data.text_fontType); end - text:SetTextHeight(data.text_fontSize); if text:GetFont() then text:SetText(WeakAuras.ReplaceRaidMarkerSymbols(data.text_text)); end + text:SetTextHeight(data.text_fontSize); + text:SetShadowColor(unpack(data.text_shadowColor)) text:SetShadowOffset(data.text_shadowXOffset, data.text_shadowYOffset) text:SetJustifyH(data.text_justify or "CENTER") @@ -173,6 +179,23 @@ local function modify(parent, region, parentData, data, first) end end + if type(parentData.conditions) == "table" then + for _, condition in ipairs(parentData.conditions) do + if type(condition.changes) == "table" then + for _, change in ipairs(condition.changes) do + if type(change.property) == "string" + and change.property:match("sub%.%d+%.text_text") + and type(change.value) == "string" + and Private.ContainsCustomPlaceHolder(change.value) + then + containsCustomText = true + break + end + end + end + end + end + if containsCustomText and parentData.customText and parentData.customText ~= "" then parent.customTextFunc = WeakAuras.LoadFunction("return "..parentData.customText) else @@ -182,67 +205,127 @@ local function modify(parent, region, parentData, data, first) parent.values.lastCustomTextUpdate = nil end - local UpdateText - if data.text_text and Private.ContainsAnyPlaceHolders(data.text_text) then - local getter = function(key, default) - local fullKey = "text_text_format_" .. key - if data[fullKey] == nil then - data[fullKey] = default + function region:ConfigureTextUpdate() + local UpdateText + if region.text_text and Private.ContainsAnyPlaceHolders(region.text_text) then + local getter = function(key, default) + local fullKey = "text_text_format_" .. key + if data[fullKey] == nil then + data[fullKey] = default + end + return data[fullKey] end - return data[fullKey] - end - local formatters = Private.CreateFormatters(data.text_text, getter) - UpdateText = function() - local textStr = data.text_text or "" - textStr = Private.ReplacePlaceHolders(textStr, parent, nil, false, formatters) + local formatters = Private.CreateFormatters(region.text_text, getter) + UpdateText = function() + local textStr = region.text_text or "" + textStr = Private.ReplacePlaceHolders(textStr, parent, nil, false, formatters) - if text:GetFont() then - text:SetText(WeakAuras.ReplaceRaidMarkerSymbols(textStr)) + if text:GetFont() then + text:SetText(WeakAuras.ReplaceRaidMarkerSymbols(textStr)) + end + region:UpdateAnchor() end end - end - local Update - if parent.customTextFunc and UpdateText then - Update = function() - if parent.values.lastCustomTextUpdate ~= GetTime() then - parent.values.custom = Private.RunCustomTextFunc(parent, parent.customTextFunc) - parent.values.lastCustomTextUpdate = GetTime() - end - UpdateText() - end - else - Update = UpdateText - end - - local TimerTick - if Private.ContainsPlaceHolders(data.text_text, "p") then - TimerTick = UpdateText - end - - local FrameTick - if parent.customTextFunc and parentData.customTextUpdate == "update" then - if Private.ContainsCustomPlaceHolder(data.text_text) then - FrameTick = function() + local Update + if parent.customTextFunc and UpdateText then + Update = function() if parent.values.lastCustomTextUpdate ~= GetTime() then parent.values.custom = Private.RunCustomTextFunc(parent, parent.customTextFunc) parent.values.lastCustomTextUpdate = GetTime() end UpdateText() end + else + Update = UpdateText + end + + local TimerTick + if Private.ContainsPlaceHolders(region.text_text, "p") then + TimerTick = UpdateText + end + + local FrameTick + if parent.customTextFunc and parentData.customTextUpdate == "update" then + if Private.ContainsCustomPlaceHolder(region.text_text) then + FrameTick = function() + if parent.values.lastCustomTextUpdate ~= GetTime() then + parent.values.custom = Private.RunCustomTextFunc(parent, parent.customTextFunc) + parent.values.lastCustomTextUpdate = GetTime() + end + UpdateText() + end + end + end + + region.Update = Update + region.FrameTick = FrameTick + region.TimerTick = TimerTick + + if not UpdateText then + if text:GetFont() then + local textStr = region.text_text + textStr = textStr:gsub("\\n", "\n"); + text:SetText(WeakAuras.ReplaceRaidMarkerSymbols(textStr)) + end end end - region.Update = Update - region.FrameTick = FrameTick - region.TimerTick = TimerTick - - if not UpdateText then - if text:GetFont() then - local textStr = data.text_text - textStr = textStr:gsub("\\n", "\n"); - text:SetText(WeakAuras.ReplaceRaidMarkerSymbols(textStr)) + function region:ConfigureSubscribers() + local visible = self:IsShown() + if self.Update then + if visible then + parent.subRegionEvents:AddSubscriber("Update", region) + end + else + parent.subRegionEvents:RemoveSubscriber("Update", region) end + if self.FrameTick then + if visible then + parent.subRegionEvents:AddSubscriber("FrameTick", region) + end + else + parent.subRegionEvents:RemoveSubscriber("FrameTick", region) + end + if self.TimerTick then + if visible then + parent.subRegionEvents:AddSubscriber("TimerTick", region) + end + else + parent.subRegionEvents:RemoveSubscriber("TimerTick", region) + end + if self.Update and parent.state and visible then + self:Update() + end + end + + function region:ChangeText(msg) + region.text_text = msg + region:ConfigureTextUpdate() + region:ConfigureSubscribers() + end + + region.text_text = data.text_text + region:ConfigureTextUpdate() + + function region:SetTextHeight(size) + local fontPath = SharedMedia:Fetch("font", data.text_font); + if not text:GetFont() then -- Font invalid, set the font but keep the setting + text:SetFont(STANDARD_TEXT_FONT, size < 33 and size or 33, data.text_fontType); + else + region.text:SetFont(fontPath, size < 33 and size or 33, data.text_fontType); + end + region.text:SetTextHeight(size) + region:UpdateAnchor(); + end + + function region:SetVisible(visible) + if visible then + self:Show() + else + self:Hide() + end + region:ConfigureSubscribers() end function region:Color(r, g, b, a) @@ -253,42 +336,8 @@ local function modify(parent, region, parentData, data, first) if (r or g or b) then a = a or 1; end - text:SetTextColor(region.color_anim_r or r, region.color_anim_g or g, region.color_anim_b or b, region.color_anim_a or a); - end - - function region:SetTextHeight(size) - local fontPath = SharedMedia:Fetch("font", data.text_font); - region.text:SetFont(fontPath, size < 33 and size or 33, data.text_fontType); - region.text:SetTextHeight(size) - end - - function region:SetVisible(visible) - if visible then - self:Show() - if self.Update then - parent.subRegionEvents:AddSubscriber("Update", region) - end - if self.FrameTick then - parent.subRegionEvents:AddSubscriber("FrameTick", region) - end - if self.TimerTick then - parent.subRegionEvents:AddSubscriber("TimerTick", region) - end - if self.Update and parent.state then - self:Update() - end - else - if self.Update then - parent.subRegionEvents:RemoveSubscriber("Update", region) - end - if self.FrameTick then - parent.subRegionEvents:RemoveSubscriber("FrameTick", region) - end - if self.TimerTick then - parent.subRegionEvents:RemoveSubscriber("TimerTick", region) - end - self:Hide() - end + text:SetTextColor(region.color_anim_r or r, region.color_anim_g or g, + region.color_anim_b or b, region.color_anim_a or a) end local selfPoint = data.text_selfPoint @@ -415,4 +464,5 @@ local function supports(regionType) or regionType == "aurabar" end -WeakAuras.RegisterSubRegionType("subtext", L["Text"], supports, create, modify, onAcquire, onRelease, default, addDefaultsForNewAura, properties); +WeakAuras.RegisterSubRegionType("subtext", L["Text"], supports, create, modify, onAcquire, onRelease, + default, addDefaultsForNewAura, properties) diff --git a/WeakAuras/SubscribableObject.lua b/WeakAuras/SubscribableObject.lua index 07b3045..c677286 100644 --- a/WeakAuras/SubscribableObject.lua +++ b/WeakAuras/SubscribableObject.lua @@ -8,6 +8,7 @@ local SubscribableObject = { ClearSubscribers = function(self) self.events = {} + self.subscribers = {} end, ClearCallbacks = function(self) @@ -21,6 +22,12 @@ local SubscribableObject = end self.events[event] = self.events[event] or {} + self.subscribers[event] = self.subscribers[event] or {} + if self.subscribers[event][subscriber] then + -- Already subscribed, just return + return + end + self.subscribers[event][subscriber] = true local pos = highPriority and 1 or (#self.events[event] + 1) if TableHasAnyEntries(self.events[event]) then tinsert(self.events[event], pos, subscriber) @@ -34,6 +41,12 @@ local SubscribableObject = RemoveSubscriber = function(self, event, subscriber) if self.events[event] then + if not self.subscribers[event][subscriber] then + -- Not subscribed + return + end + + self.subscribers[event][subscriber] = nil local index = tIndexOf(self.events[event], subscriber) if index then tremove(self.events[event], index) @@ -68,6 +81,7 @@ function Private.CreateSubscribableObject() for f, func in pairs(SubscribableObject) do system[f] = func system.events = {} + system.subscribers = {} system.callbacks = {} end return system diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 489bf0a..6f8bb54 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -466,6 +466,19 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA args["condition" .. i .. "value" .. j].validate = WeakAuras.ValidateNumeric; end end + elseif (propertyType == "string") then + args["condition" .. i .. "value" .. j] = { + type = "input", + width = WeakAuras.normalWidth, + name = blueIfNoValue(data, conditions[i].changes[j], "value", L["Text"]), + desc = descIfNoValue(data, conditions[i].changes[j], "value", propertyType), + order = order, + get = function() + return conditions[i].changes[j].value; + end, + set = setValue + } + order = order + 1; elseif (propertyType == "icon") then args["condition" .. i .. "value" .. j] = { type = "input", diff --git a/WeakAurasOptions/SubRegionOptions/SubText.lua b/WeakAurasOptions/SubRegionOptions/SubText.lua index 765250d..59c467e 100644 --- a/WeakAurasOptions/SubRegionOptions/SubText.lua +++ b/WeakAurasOptions/SubRegionOptions/SubText.lua @@ -394,11 +394,28 @@ local function createOptions(parentData, data, index, subIndex) return true end - for index, subRegion in ipairs(parentData.subRegions) do + for _, subRegion in ipairs(parentData.subRegions) do if subRegion.type == "subtext" and OptionsPrivate.Private.ContainsCustomPlaceHolder(subRegion.text_text) then return false end end + + if type(parentData.conditions) == "table" then + for _, condition in ipairs(parentData.conditions) do + if type(condition.changes) == "table" then + for _, change in ipairs(condition.changes) do + if type(change.property) == "string" + and change.property:match("sub%.%d+%.text_text") + and type(change.value) == "string" + and OptionsPrivate.Private.ContainsCustomPlaceHolder(change.value) + then + return false + end + end + end + end + end + return true end From 1ff28a4f23dd9f11130077ec1c1827b48edaaea0 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Tue, 14 Jan 2025 17:42:05 +0100 Subject: [PATCH 038/153] from retail --- WeakAuras/Profiling.lua | 397 +++++++++++++++++----------------------- 1 file changed, 164 insertions(+), 233 deletions(-) diff --git a/WeakAuras/Profiling.lua b/WeakAuras/Profiling.lua index 89d12be..b18161a 100644 --- a/WeakAuras/Profiling.lua +++ b/WeakAuras/Profiling.lua @@ -4,7 +4,7 @@ local AddonName, Private = ... local WeakAuras = WeakAuras local L = WeakAuras.L local prettyPrint = WeakAuras.prettyPrint --- local LGF = LibStub("LibGetFrame-1.0") +--local LGF = LibStub("LibGetFrame-1.0") local profileData = {} profileData.systems = {} @@ -12,7 +12,8 @@ profileData.auras = {} local currentProfileState, ProfilingTimer -local RealTimeProfilingWindow = CreateFrame("Button", nil, UIParent) +local RealTimeProfilingWindow = CreateFrame("Frame", "WeakAurasRealTimeProfiling", UIParent, "WA_PortraitFrameTemplate") +RealTimeProfilingWindow:HidePortrait(RealTimeProfilingWindow) Private.frames["RealTime Profiling Window"] = RealTimeProfilingWindow RealTimeProfilingWindow.width = 500 RealTimeProfilingWindow.height = 300 @@ -22,6 +23,7 @@ RealTimeProfilingWindow.statsHeight = 15 RealTimeProfilingWindow.buttonsHeight = 22 RealTimeProfilingWindow.bars = {} RealTimeProfilingWindow:SetMovable(true) +RealTimeProfilingWindow:EnableMouse(true) RealTimeProfilingWindow:Hide() WeakAuras.RealTimeProfilingWindow = RealTimeProfilingWindow @@ -45,174 +47,74 @@ table_to_string = function(tbl, depth) k = '"' .. k ..'"' end - str = (str and str .. "|cff999999,|r " or "|cff999999{|r ") .. "|cffffff99[" .. tostring(k) .. "]|r |cff999999=|r |cffffffff" .. tostring(v) .. "|r" + str = (str and str .. "|cff999999,|r " or "|cff999999{|r ") .. "|cffffff99[" + .. tostring(k) .. "]|r |cff999999=|r |cffffffff" .. tostring(v) .. "|r" end end return (str or "{ ") .. " }" end -local function CreateDecoration(frame) - local deco = CreateFrame("Frame", nil, frame) - deco:SetSize(17, 40) - - local bg1 = deco:CreateTexture(nil, "BACKGROUND") - bg1:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") - bg1:SetTexCoord(0.31, 0.67, 0, 0.63) - bg1:SetAllPoints(deco) - - local bg2 = deco:CreateTexture(nil, "BACKGROUND") - bg2:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") - bg2:SetTexCoord(0.235, 0.275, 0, 0.63) - bg2:SetPoint("RIGHT", bg1, "LEFT") - bg2:SetSize(10, 40) - - local bg3 = deco:CreateTexture(nil, "BACKGROUND") - bg3:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") - bg3:SetTexCoord(0.72, 0.76, 0, 0.63) - bg3:SetPoint("LEFT", bg1, "RIGHT") - bg3:SetSize(10, 40) - - return deco -end - -local function CreateDecorationWide(frame) - local deco1 = frame:CreateTexture(nil, "OVERLAY") - deco1:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") - deco1:SetTexCoord(0.31, 0.67, 0, 0.63) - deco1:SetSize(140, 40) - - local deco2 = frame:CreateTexture(nil, "OVERLAY") - deco2:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") - deco2:SetTexCoord(0.21, 0.31, 0, 0.63) - deco2:SetPoint("RIGHT", deco1, "LEFT") - deco2:SetSize(30, 40) - - local deco3 = frame:CreateTexture(nil, "OVERLAY") - deco3:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") - deco3:SetTexCoord(0.67, 0.77, 0, 0.63) - deco3:SetPoint("LEFT", deco1, "RIGHT") - deco3:SetSize(30, 40) - - return deco1 -end - local profilePopup local function CreateProfilePopup() - local popupFrame = CreateFrame("EditBox", "WADebugEditBox", UIParent) - popupFrame:SetFrameStrata("DIALOG") - popupFrame:SetMultiLine(true) - popupFrame:SetAutoFocus(false) - popupFrame:SetFontObject(ChatFontNormal) - popupFrame:SetSize(450, 300) - popupFrame:SetScript("OnChar", function() popupFrame:SetText(popupFrame.originalText) end); - popupFrame:Hide() + local frame = CreateFrame("Frame", "WeakAurasProfilingReport", UIParent, "WA_PortraitFrameTemplate") + frame:HidePortrait(frame) + WeakAurasProfilingReportTitleText:SetText(L["WeakAuras Profiling Report"]) + frame:SetMovable(true) + frame:SetSize(450, 300) - popupFrame.orig_Hide = popupFrame.Hide - function popupFrame:Hide() - self:SetText("") - self.ScrollFrame:Hide() - self.Background:Hide() - self:orig_Hide() - end + frame:SetScript("OnMouseDown", function(self, button) + if button == "LeftButton" and not self.is_moving then + self:StartMoving() + self.is_moving = true + elseif button == "RightButton" then + self:Stop() + end + end) - popupFrame.orig_Show = popupFrame.Show - function popupFrame:Show() - self.ScrollFrame:Show() - self.Background:Show() - self:orig_Show() - end + frame:SetScript("OnMouseUp", function(self, button) + if button == "LeftButton" and self.is_moving then + self:StopMovingOrSizing() + local xOffset = self:GetLeft() + local yOffset = self:GetTop() - GetScreenHeight() + WeakAurasSaved.ProfilingWindow = WeakAurasSaved.ProfilingWindow or {} + WeakAurasSaved.ProfilingWindow.xOffset = xOffset + WeakAurasSaved.ProfilingWindow.yOffset = yOffset + self.is_moving = nil + end + end) - function popupFrame:AddText(v) + local scrollFrame = CreateFrame("ScrollFrame", "WeakAurasProfilingReportScrollFrame", frame, "UIPanelScrollFrameTemplate") + scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 10, -28) + scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -27, 15) + + local messageFrame = CreateFrame("EditBox", nil, scrollFrame) + frame.messageFrame = messageFrame + messageFrame:SetMultiLine(true) + messageFrame:SetAutoFocus(false) + messageFrame:SetFontObject(ChatFontNormal) + messageFrame:SetSize(440, 260) + messageFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, -5) + messageFrame:SetPoint("BOTTOMRIGHT", scrollFrame, "BOTTOMRIGHT") + messageFrame:Show() + messageFrame:SetScript("OnChar", function() messageFrame:SetText(messageFrame.originalText) end) + + function frame:AddText(v) if not v then return end - local m = popupFrame:GetText() + local m = self.messageFrame:GetText() if m ~= "" then m = m .. "|n" end if type(v) == "table" then v = table_to_string(v) end - popupFrame.originalText = m .. v - popupFrame:SetText(popupFrame.originalText) + self.messageFrame.originalText = m .. v + self.messageFrame:SetText(self.messageFrame.originalText) end - popupFrame:SetScript("OnEscapePressed", function(self) - self:ClearFocus() - if IsModifierKeyDown() then - popupFrame:Hide() - end - end) - - local scrollFrame = CreateFrame("ScrollFrame", "WADebugEditBoxScrollFrame", UIParent, "UIPanelScrollFrameTemplate") - scrollFrame:SetMovable(true) - scrollFrame:SetFrameStrata("DIALOG") - scrollFrame:SetSize(450, 300) - if WeakAurasSaved.ProfilingWindow then - scrollFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", WeakAurasSaved.ProfilingWindow.xOffset or 0, WeakAurasSaved.ProfilingWindow.yOffset or 0) - else - scrollFrame:SetPoint("CENTER") - end scrollFrame:SetHitRectInsets(-8, -8, -8, -8) - scrollFrame:SetScrollChild(popupFrame) - scrollFrame:Hide() + scrollFrame:SetScrollChild(messageFrame) - local bg = CreateFrame("Frame", nil, UIParent) - bg:SetFrameStrata("DIALOG") - bg:SetBackdrop({ - bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", - edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", - tile = true, - tileSize = 32, - edgeSize = 32, - insets = { left = 4, right = 4, top = 4, bottom = 4 } - }) - bg:SetPoint("TOPLEFT", scrollFrame, -20, 20) - bg:SetPoint("BOTTOMRIGHT", scrollFrame, 35, -25) - bg:Hide() - - local title = CreateFrame("Frame", nil, bg) - title:SetSize(200, 40) - title:SetPoint("TOP", 0, 12) - title:EnableMouse(true) - - local titlebg = CreateDecorationWide(bg) - titlebg:SetPoint("TOP", 0, 12) - - local titletext = title:CreateFontString(nil, "OVERLAY", "GameFontNormal") - titletext:SetPoint("TOP", titlebg, "TOP", 0, -14) - titletext:SetText(L["WeakAuras Profiling Report"]) - - local close = CreateDecoration(bg) - close:SetPoint("RIGHT", titlebg, 50, 0) - - local closeButton = CreateFrame("Button", nil, close, "UIPanelCloseButton") - closeButton:SetPoint("CENTER", close, "CENTER", 1, -1) - closeButton:SetScript("OnClick", function() - popupFrame:Hide() - end) - - popupFrame.ScrollFrame = scrollFrame - popupFrame.Background = bg - - title:SetScript("OnMouseDown", function(self, button) - if button == "LeftButton" and not scrollFrame.is_moving then - scrollFrame:StartMoving() - scrollFrame.is_moving = true - end - end) - - title:SetScript("OnMouseUp", function(self, button) - if button == "LeftButton" and scrollFrame.is_moving then - scrollFrame:StopMovingOrSizing() - local xOffset = scrollFrame:GetLeft() - local yOffset = scrollFrame:GetTop() - GetScreenHeight() - WeakAurasSaved.ProfilingWindow = WeakAurasSaved.ProfilingWindow or {} - WeakAurasSaved.ProfilingWindow.xOffset = xOffset - WeakAurasSaved.ProfilingWindow.yOffset = yOffset - scrollFrame.is_moving = nil - end - end) - - profilePopup = popupFrame + profilePopup = frame end local function ProfilePopup() @@ -286,9 +188,16 @@ function Private.ProfileRenameAura(oldid, id) end local RegisterProfile = function(startType) - if startType == "boss" then startType = "combat" end + if startType == "boss" then startType = "encounter" end local delayedStart - if startType == "combat" then + if startType == "encounter" then + RealTimeProfilingWindow:UnregisterAllEvents() + prettyPrint(L["Your next instance of combat will automatically be profiled."]) + RealTimeProfilingWindow:RegisterEvent("PLAYER_REGEN_DISABLED") + RealTimeProfilingWindow:RegisterEvent("PLAYER_REGEN_ENABLED") + currentProfileState = startType + delayedStart = true + elseif startType == "combat" then RealTimeProfilingWindow:UnregisterAllEvents() prettyPrint(L["Your next instance of combat will automatically be profiled."]) RealTimeProfilingWindow:RegisterEvent("PLAYER_REGEN_DISABLED") @@ -336,7 +245,7 @@ function WeakAuras.StartProfile(startType) Private.StopProfileSystem = StopProfileSystem Private.StopProfileAura = StopProfileAura Private.StopProfileUID = StopProfileUID - -- LGF.StartProfile() + --LGF.StartProfile() end local function doNothing() @@ -359,7 +268,7 @@ function WeakAuras.StopProfile() Private.StopProfileSystem = doNothing Private.StopProfileAura = doNothing Private.StopProfileUID = doNothing - -- LGF.StopProfile() + --LGF.StopProfile() currentProfileState = nil RealTimeProfilingWindow:UnregisterAllEvents() @@ -444,11 +353,24 @@ function WeakAuras.PrintProfile() return end - popup:SetText("") + if WeakAurasRealTimeProfiling and WeakAurasRealTimeProfiling:IsShown() then + popup:ClearAllPoints() + popup:SetPoint("TOPLEFT", WeakAurasRealTimeProfiling, "TOPRIGHT", 5, 0) + else + if WeakAurasSaved.ProfilingWindow then + popup:SetPoint("TOPLEFT", UIParent, "TOPLEFT", WeakAurasSaved.ProfilingWindow.xOffset or 0, + WeakAurasSaved.ProfilingWindow.yOffset or 0) + else + popup:SetPoint("CENTER") + end + end + + popup.messageFrame:SetText("") PrintOneProfile(popup, "|cff9900ffTotal time:|r", profileData.systems.time) PrintOneProfile(popup, "|cff9900ffTime inside WA:|r", profileData.systems.wa) - popup:AddText(string.format("|cff9900ffTime spent inside WA:|r %.2f%%", 100 * profileData.systems.wa.elapsed / profileData.systems.time.elapsed)) + popup:AddText(string.format("|cff9900ffTime spent inside WA:|r %.2f%%", + 100 * profileData.systems.wa.elapsed / profileData.systems.time.elapsed)) popup:AddText("") popup:AddText("Note: Not every aspect of each aura can be tracked.") @@ -464,17 +386,18 @@ function WeakAuras.PrintProfile() popup:AddText("") popup:AddText("|cff9900ffSystems:|r") + for i, k in ipairs(SortProfileMap(profileData.systems)) do if (k ~= "time" and k ~= "wa") then PrintOneProfile(popup, k, profileData.systems[k], profileData.systems.wa.elapsed) end end - -- popup:AddText("") - -- popup:AddText("|cff9900ffLibGetFrame:|r") - -- for id, map in pairs(LGF.GetProfileData()) do - -- PrintOneProfile(popup, id, map) - -- end + --popup:AddText("") + --popup:AddText("|cff9900ffLibGetFrame:|r") + --for id, map in pairs(LGF.GetProfileData()) do + -- PrintOneProfile(popup, id, map) + --end popup:Show() end @@ -485,23 +408,25 @@ function RealTimeProfilingWindow:GetBar(name) if self.bars[name] then return self.bars[name] else - local bar = CreateFrame("FRAME", nil, self.barsFrame) + local bar = CreateFrame("Frame", nil, self.barsFrame) self.bars[name] = bar WeakAuras.Mixin(bar, SmoothStatusBarMixin) bar.name = name bar.parent = self - bar:SetSize(self.width, self.barHeight) + bar:SetHeight(self.barHeight) local fg = bar:CreateTexture(nil, "ARTWORK") fg:SetTexture(texture) + fg:SetDrawLayer("ARTWORK", 0) fg:ClearAllPoints() fg:SetPoint("TOPLEFT", bar) fg:SetHeight(self.barHeight) fg:Show() bar.fg = fg - local bg = bar:CreateTexture(nil, "BORDER") + local bg = bar:CreateTexture(nil, "ARTWORK") bg:SetTexture(texture) + bg:SetDrawLayer("ARTWORK", -1) bg:SetAllPoints() bg:Show() bar.bg = bg @@ -541,11 +466,14 @@ function RealTimeProfilingWindow:GetBar(name) end function bar:SetPosition(pos) - if self.parent.barHeight * pos > self.parent.height - self.parent.titleHeight - self.parent.statsHeight - self.parent.buttonsHeight then + if self.parent.barHeight * pos > + self.parent.height - self.parent.titleHeight - self.parent.statsHeight - self.parent.buttonsHeight + then self:Hide() else self:ClearAllPoints() self:SetPoint("TOPLEFT", self.parent.barsFrame, "TOPLEFT", 0, - (pos - 1) * self.parent.barHeight) + self:SetPoint("RIGHT", self.parent.barsFrame, "RIGHT") if pos % 2 == 0 then bar.fg:SetTexture(0.7, 0.7, 0.7, 0.7) bar.bg:SetTexture(0, 0, 0, 0.2) @@ -600,88 +528,67 @@ function RealTimeProfilingWindow:Init() self:SetClampedToScreen(true) if WeakAurasSaved.RealTimeProfilingWindow then - self:SetPoint("TOPLEFT", UIParent, "TOPLEFT", WeakAurasSaved.RealTimeProfilingWindow.xOffset or 0, WeakAurasSaved.RealTimeProfilingWindow.yOffset or 0) + self:SetPoint("TOPLEFT", UIParent, "TOPLEFT", + WeakAurasSaved.RealTimeProfilingWindow.xOffset or 0, + WeakAurasSaved.RealTimeProfilingWindow.yOffset or 0) else self:SetPoint("TOPLEFT", UIParent, "TOPLEFT") end self:Show() - local bg = self:CreateTexture(nil, "BACKGROUND") - self.bg = bg - bg:SetTexture(texture) - bg:SetAllPoints() - bg:Show() - - local titleFrame = CreateFrame("Frame", nil, self) - self.titleFrame = titleFrame - titleFrame:SetSize(self.width, self.titleHeight) - titleFrame:SetPoint("TOPLEFT", self) - titleFrame:Show() - - local titleText = self.titleFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal") - self.titleFrameText = titleText - titleText:SetText(L["WeakAuras Profiling"]) - titleText:SetPoint("CENTER", self.titleFrame) + WeakAurasRealTimeProfilingTitleText:SetText(L["WeakAuras Profiling"]) local barsFrame = CreateFrame("Frame", nil, self) self.barsFrame = barsFrame - barsFrame:SetSize(self.width, self.height - self.titleHeight - self.statsHeight - self.buttonsHeight) - barsFrame:SetPoint("TOPLEFT", self.titleFrame, "BOTTOMLEFT") + barsFrame:SetPoint("TOPLEFT", 7, -20) + barsFrame:SetPoint("BOTTOMRIGHT", -3, 30) barsFrame:Show() - local statsFrame = CreateFrame("Frame", nil, self) - self.statsFrame = statsFrame - statsFrame:SetSize(self.width, self.statsHeight) - statsFrame:SetPoint("TOPLEFT", self.barsFrame, "BOTTOMLEFT") - statsFrame:Show() - - local statsFrameText = self.statsFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal") + local statsFrameText = self:CreateFontString(nil, "OVERLAY", "GameFontNormal") self.statsFrameText = statsFrameText - statsFrameText:SetPoint("LEFT", self.statsFrame, "LEFT", margin, 2) + statsFrameText:SetPoint("BOTTOMLEFT", 15, 25) - local closeButton = CreateFrame("Button", nil, self.titleFrame, "UIPanelCloseButton") - closeButton:SetPoint("TOPRIGHT", self.titleFrame, "TOPRIGHT", 1, 5) - closeButton:SetScript("OnClick", function(self) - self:GetParent():GetParent():Stop() + local minimizeButton = CreateFrame("Button", nil, self, "WA_MaximizeMinimizeButtonFrameTemplate") + minimizeButton:SetPoint("RIGHT", self.CloseButton, "LEFT") + minimizeButton:SetOnMaximizedCallback(function() + self.minimized = false + self.barsFrame:Show() + self.toggleButton:Show() + self.reportButton:Show() + self.combatButton:Show() + self.encounterButton:Show() + self.statsFrameText:Show() + self:ClearAllPoints() + self:SetPoint("TOPRIGHT", UIParent, "BOTTOMLEFT", self.right, self.top) + self:SetHeight(self.prevHeight) end) - - local minimizeButton = CreateFrame("Button", nil, self.titleFrame) - minimizeButton:SetSize(30, 30) - minimizeButton:SetPoint("TOPRIGHT", self.titleFrame, "TOPRIGHT", -25, 5) - minimizeButton:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-CollapseButton-Up.blp") - minimizeButton:SetPushedTexture("Interface\\BUTTONS\\UI-Panel-CollapseButton-Down.blp") - minimizeButton:SetHighlightTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Highlight.blp") - minimizeButton:SetScript("OnClick", function(self) - local parent = self:GetParent():GetParent() - if parent.minimized then - parent.minimized = nil - parent.barsFrame:Show() - parent.statsFrame:Show() - parent:SetHeight(parent.height) - self:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-CollapseButton-Up.blp") - self:SetPushedTexture("Interface\\BUTTONS\\UI-Panel-CollapseButton-Down.blp") - else - parent.minimized = true - parent.barsFrame:Hide() - parent.statsFrame:Hide() - parent:SetHeight(parent.titleHeight) - self:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-ExpandButton-Up.blp") - self:SetPushedTexture("Interface\\BUTTONS\\UI-Panel-ExpandButton-Down.blp") - end + minimizeButton:SetOnMinimizedCallback(function() + self.minimized = true + self.barsFrame:Hide() + self.toggleButton:Hide() + self.reportButton:Hide() + self.combatButton:Hide() + self.encounterButton:Hide() + self.statsFrameText:Hide() + self.right, self.top = self:GetRight(), self:GetTop() + self:ClearAllPoints() + self:SetPoint("TOPRIGHT", UIParent, "BOTTOMLEFT", self.right, self.top) + self.prevHeight = self:GetHeight() + self:SetHeight(60) end) local width = 120 local spacing = 2 - local toggleButton = CreateFrame("Button", nil, statsFrame, "UIPanelButtonTemplate") + local toggleButton = CreateFrame("Button", nil, self, "UIPanelButtonTemplate") self.toggleButton = toggleButton - toggleButton:SetPoint("TOPRIGHT", statsFrame, "BOTTOMRIGHT", -spacing, spacing) - toggleButton:SetFrameLevel(statsFrame:GetFrameLevel() + 1) + toggleButton:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -spacing, spacing) + toggleButton:SetFrameLevel(self:GetFrameLevel() + 1) toggleButton:SetHeight(20) toggleButton:SetWidth(width) toggleButton:SetText(L["Start Now"]) toggleButton:SetScript("OnClick", function(self) - local parent = self:GetParent():GetParent() + local parent = self:GetParent() if (not profileData.systems.time or profileData.systems.time.count ~= 1) then parent:ResetBars() WeakAuras.StartProfile() @@ -690,10 +597,11 @@ function RealTimeProfilingWindow:Init() end end) - local reportButton = CreateFrame("Button", nil, statsFrame, "UIPanelButtonTemplate") + + local reportButton = CreateFrame("Button", nil, self, "UIPanelButtonTemplate") self.reportButton = reportButton - reportButton:SetPoint("TOPLEFT", statsFrame, "BOTTOMLEFT", spacing, spacing) - reportButton:SetFrameLevel(statsFrame:GetFrameLevel() + 1) + reportButton:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", spacing, spacing) + reportButton:SetFrameLevel(self:GetFrameLevel() + 1) reportButton:SetHeight(20) reportButton:SetWidth(width) reportButton:SetText(L["Report Summary"]) @@ -702,14 +610,14 @@ function RealTimeProfilingWindow:Init() end) reportButton:Hide() - local combatButton = CreateFrame("Button", nil, statsFrame, "UIPanelButtonTemplate") + local combatButton = CreateFrame("Button", nil, self, "UIPanelButtonTemplate") self.combatButton = combatButton - combatButton:SetPoint("TOPRIGHT", statsFrame, "BOTTOMRIGHT", -spacing - width , spacing) - combatButton:SetFrameLevel(statsFrame:GetFrameLevel() + 1) + combatButton:SetPoint("BOTTOMRIGHT", -spacing - width , spacing) + combatButton:SetFrameLevel(self:GetFrameLevel() + 1) combatButton:SetHeight(20) combatButton:SetWidth(width) combatButton:SetScript("OnClick", function(self) - local parent = self:GetParent():GetParent() + local parent = self:GetParent() parent:ResetBars() if currentProfileState ~= "combat" then WeakAuras.StartProfile("combat") @@ -718,6 +626,22 @@ function RealTimeProfilingWindow:Init() end end) + local encounterButton = CreateFrame("Button", nil, self, "UIPanelButtonTemplate") + self.encounterButton = encounterButton + encounterButton:SetPoint("BOTTOMRIGHT", -spacing - 2 * width, spacing) + encounterButton:SetFrameLevel(self:GetFrameLevel() + 1) + encounterButton:SetHeight(20) + encounterButton:SetWidth(width) + encounterButton:SetScript("OnClick", function(self) + local parent = self:GetParent() + parent:ResetBars() + if currentProfileState ~= "encounter" then + WeakAuras.StartProfile("encounter") + else + CancelScheduledProfile() + end + end) + self:SetScript("OnMouseDown", function(self, button) if button == "LeftButton" and not self.is_moving then self:StartMoving() @@ -740,12 +664,12 @@ function RealTimeProfilingWindow:Init() end) self:SetScript("OnUpdate", self.RefreshBars) - self.init = true + self.initt = true self:UpdateButtons() end function RealTimeProfilingWindow:UpdateButtons() - if not self.init then + if not self.initt then return end if currentProfileState == "combat" then @@ -753,13 +677,20 @@ function RealTimeProfilingWindow:UpdateButtons() else self.combatButton:SetText(L["Next Combat"]) end + if currentProfileState == "encounter" then + self.encounterButton:SetText(L["Cancel"]) + else + self.encounterButton:SetText(L["Next Encounter"]) + end if currentProfileState == "profiling" then self.toggleButton:SetText(L["Stop"]) self.combatButton:Hide() + self.encounterButton:Hide() self.reportButton:Hide() else self.toggleButton:SetText(L["Start Now"]) self.combatButton:Show() + self.encounterButton:Show() if profileData.systems.time then self.reportButton:Show() end @@ -767,7 +698,7 @@ function RealTimeProfilingWindow:UpdateButtons() end function RealTimeProfilingWindow:Start() - if not self.init then + if not self.initt then self:Init() end self:Show() From ccb4d4af95d6b6cc82660e0528e52ee124174780 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 01:51:26 +0100 Subject: [PATCH 039/153] from retail --- WeakAuras/Prototypes.lua | 4 +- WeakAuras/RegionTypes/AuraBar.lua | 2 +- WeakAuras/RegionTypes/ProgressTexture.lua | 2 +- .../RegionTypes/SmoothStatusBarMixin.lua | 65 +++++++++++ WeakAuras/WeakAuras.lua | 11 +- WeakAuras/WeakAuras.toc | 1 + WeakAuras/compat.lua | 104 ++++-------------- 7 files changed, 96 insertions(+), 93 deletions(-) create mode 100644 WeakAuras/RegionTypes/SmoothStatusBarMixin.lua diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 3f239ed..9e6f476 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4106,7 +4106,7 @@ Private.event_prototypes = { { name = "count", display = L["Count"], - desc = L["Occurence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if DBM shows it on it's bar"], + desc = L["Occurrence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if DBM shows it on it's bar"], type = "string", conditionType = "string", }, @@ -4341,7 +4341,7 @@ Private.event_prototypes = { { name = "count", display = L["Count"], - desc = L["Occurence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if BigWigs shows it on it's bar"], + desc = L["Occurrence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if BigWigs shows it on it's bar"], type = "string", conditionType = "string", }, diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index bb785c8..1e10b83 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -1012,7 +1012,7 @@ local function create(parent) -- Create statusbar (inherit prototype) local bar = CreateFrame("Frame", nil, region); - WeakAuras.Mixin(bar, SmoothStatusBarMixin); + WeakAuras.Mixin(bar, Private.SmoothStatusBarMixin); local fg = bar:CreateTexture(nil, "BORDER"); local bg = region:CreateTexture(nil, "BACKGROUND"); bg:SetAllPoints(bar); diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 436e494..060de36 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -446,7 +446,7 @@ local function create(parent) -- Use a dummy object for the SmoothStatusBarMixin, because our SetValue -- is used for a different purpose region.smoothProgress = {}; - WeakAuras.Mixin(region.smoothProgress, SmoothStatusBarMixin); + WeakAuras.Mixin(region.smoothProgress, Private.SmoothStatusBarMixin); region.smoothProgress.SetValue = function(self, progress) region:SetValueOnTexture(progress); end diff --git a/WeakAuras/RegionTypes/SmoothStatusBarMixin.lua b/WeakAuras/RegionTypes/SmoothStatusBarMixin.lua new file mode 100644 index 0000000..2c60bcd --- /dev/null +++ b/WeakAuras/RegionTypes/SmoothStatusBarMixin.lua @@ -0,0 +1,65 @@ +if not WeakAuras.IsLibsOK() then return end + +local AddonName, Private = ... + +-- This is a more or less 1:1 copy of SmoothStatusBarMixin except that it +-- doesn't clamp the targetValue in ProcesSmoothStatusBars, because that's incorrect for us +local g_updatingBars = {}; + +local function IsCloseEnough(bar, newValue, targetValue) + local min, max = bar:GetMinMaxValues(); + local range = max - min; + if range > 0.0 then + return math.abs((newValue - targetValue) / range) < 0.00001; + end + + return true; +end + +local function ProcessSmoothStatusBars(self, elapsed) + for bar, targetValue in pairs(g_updatingBars) do + local newValue = FrameDeltaLerp(bar:GetValue(), targetValue, 0.25, elapsed); + + if IsCloseEnough(bar, newValue, targetValue) then + g_updatingBars[bar] = nil; + bar:SetValue(targetValue); + else + bar:SetValue(newValue); + end + end +end + +CreateFrame("Frame"):SetScript("OnUpdate", ProcessSmoothStatusBars); + +Private.SmoothStatusBarMixin = {}; + +function Private.SmoothStatusBarMixin:ResetSmoothedValue(value) --If nil, tries to set to the last target value + local targetValue = g_updatingBars[self]; + if targetValue then + g_updatingBars[self] = nil; + self:SetValue(value or targetValue); + elseif value then + self:SetValue(value); + end +end + +function Private.SmoothStatusBarMixin:SetSmoothedValue(value) + g_updatingBars[self] = value; +end + +function Private.SmoothStatusBarMixin:SetMinMaxSmoothedValue(min, max) + self:SetMinMaxValues(min, max); + + local targetValue = g_updatingBars[self]; + if targetValue then + local ratio = 1; + if max ~= 0 and self.lastSmoothedMax and self.lastSmoothedMax ~= 0 then + ratio = max / self.lastSmoothedMax; + end + + g_updatingBars[self] = targetValue * ratio; + end + + self.lastSmoothedMin = min; + self.lastSmoothedMax = max; +end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 10d60e3..e9d54d8 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3561,7 +3561,6 @@ function WeakAuras.GetAuraTooltipInfo(unit, index, filter) local tooltipText = tooltipTextLine and tooltipTextLine:GetObjectType() == "FontString" and tooltipTextLine:GetText() or ""; local debuffType = "none"; - local found = false; local tooltipSize = {}; if(tooltipText) then for t in tooltipText:gmatch("(%d[%d%.,]*)") do @@ -5013,11 +5012,11 @@ local function GetAnchorFrame(data, region, parent) if unit then local frame = unit and WeakAuras.GetNamePlateForUnit(unit) if frame then return frame end - end - if WeakAuras.IsOptionsOpen() then - Private.ensurePRDFrame() - personalRessourceDisplayFrame:anchorFrame(id, anchorFrameType) - return personalRessourceDisplayFrame + if WeakAuras.IsOptionsOpen() then + Private.ensurePRDFrame() + personalRessourceDisplayFrame:anchorFrame(id, anchorFrameType) + return personalRessourceDisplayFrame + end end end diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index 5f0602f..05dd046 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -52,6 +52,7 @@ DebugLog.lua SubscribableObject.lua # Region support +RegionTypes\SmoothStatusBarMixin.lua RegionTypes\RegionPrototype.lua RegionTypes\ProgressTexture.lua RegionTypes\Texture.lua diff --git a/WeakAuras/compat.lua b/WeakAuras/compat.lua index 1172119..f6f24d7 100644 --- a/WeakAuras/compat.lua +++ b/WeakAuras/compat.lua @@ -80,91 +80,29 @@ RAID_CLASS_COLORS.SHAMAN.colorStr = "ff0070de" RAID_CLASS_COLORS.WARRIOR.colorStr = "ffc79c6e" RAID_CLASS_COLORS.DEATHKNIGHT.colorStr = "ffc41f3b" -if not SmoothStatusBarMixin then - function Lerp(startValue, endValue, amount) - return (1 - amount) * startValue + amount * endValue; +function Clamp(value, min, max) + if value > max then + return max; + elseif value < min then + return min; end + return value; +end - function Clamp(value, min, max) - if value > max then - return max; - elseif value < min then - return min; - end - return value; - end +-- This section is mostly used by Private.SmoothStatusBarMixin +function Lerp(startValue, endValue, amount) + return (1 - amount) * startValue + amount * endValue; +end - function Saturate(value) - return Clamp(value, 0, 1); - end +function Saturate(value) + return Clamp(value, 0, 1); +end - local TARGET_FRAME_PER_SEC = 60; - function DeltaLerp(startValue, endValue, amount, timeSec) - return Lerp(startValue, endValue, Saturate(amount * timeSec * TARGET_FRAME_PER_SEC)); - end +local TARGET_FRAME_PER_SEC = 60.0; +function DeltaLerp(startValue, endValue, amount, timeSec) + return Lerp(startValue, endValue, Saturate(amount * timeSec * TARGET_FRAME_PER_SEC)); +end - function FrameDeltaLerp(startValue, endValue, amount, elapsed) - return DeltaLerp(startValue, endValue, amount, elapsed); - end - - local g_updatingBars = {}; - - local function IsCloseEnough(bar, newValue, targetValue) - local min, max = bar:GetMinMaxValues(); - local range = max - min; - if range > 0 then - return abs((newValue - targetValue) / range) < .00001; - end - - return true; - end - - local function ProcessSmoothStatusBars(self, elapsed) - for bar, targetValue in pairs(g_updatingBars) do - local effectiveTargetValue = Clamp(targetValue, bar:GetMinMaxValues()); - local newValue = FrameDeltaLerp(bar:GetValue(), effectiveTargetValue, .25, elapsed); - - if IsCloseEnough(bar, newValue, effectiveTargetValue) then - g_updatingBars[bar] = nil; - bar:SetValue(effectiveTargetValue); - else - bar:SetValue(newValue); - end - end - end - - CreateFrame("Frame"):SetScript("OnUpdate", ProcessSmoothStatusBars) - - SmoothStatusBarMixin = {}; - - function SmoothStatusBarMixin:ResetSmoothedValue(value) --If nil, tries to set to the last target value - local targetValue = g_updatingBars[self]; - if targetValue then - g_updatingBars[self] = nil; - self:SetValue(value or targetValue); - elseif value then - self:SetValue(value); - end - end - - function SmoothStatusBarMixin:SetSmoothedValue(value) - g_updatingBars[self] = value; - end - - function SmoothStatusBarMixin:SetMinMaxSmoothedValue(min, max) - self:SetMinMaxValues(min, max); - - local targetValue = g_updatingBars[self]; - if targetValue then - local ratio = 1; - if max ~= 0 and self.lastSmoothedMax and self.lastSmoothedMax ~= 0 then - ratio = max / self.lastSmoothedMax; - end - - g_updatingBars[self] = targetValue * ratio; - end - - self.lastSmoothedMin = min; - self.lastSmoothedMax = max; - end -end \ No newline at end of file +function FrameDeltaLerp(startValue, endValue, amount, elapsed) + return DeltaLerp(startValue, endValue, amount, elapsed); +end From 24196cd7ce4ebfe9faa0de8d91b010f82151a548 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 02:47:58 +0100 Subject: [PATCH 040/153] from retail --- WeakAuras/AuraEnvironment.lua | 6 +-- WeakAuras/BuffTrigger2.lua | 35 +++++++++++-- WeakAuras/GenericTrigger.lua | 20 +++++-- WeakAuras/Prototypes.lua | 15 ++++-- WeakAuras/RegionTypes/RegionPrototype.lua | 52 ++++++++++++++++--- WeakAuras/WeakAuras.lua | 16 +++--- ...GUIWidget-WeakAurasPendingUpdateButton.lua | 4 +- WeakAurasOptions/BuffTrigger2.lua | 2 +- WeakAurasOptions/InformationOptions.lua | 29 +++++++++++ WeakAurasOptions/OptionsFrames/TextEditor.lua | 1 + WeakAurasOptions/WeakAurasOptions.lua | 36 +++++++------ 11 files changed, 164 insertions(+), 52 deletions(-) diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index fa5f8cb..e6eacd9 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -148,7 +148,7 @@ local blockedFunctions = { GuildUninvite = true, securecall = true, DeleteCursorItem = true, - ChatEdit_SendText = true + ChatEdit_SendText = true, } local blockedTables = { @@ -263,7 +263,6 @@ end function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) local data = id and WeakAuras.GetData(id) - local region = id and Private.EnsureRegion(id, cloneId) if not data then -- Pop the last aura_env from the stack, and update current_aura_env appropriately. tremove(aura_env_stack) @@ -276,6 +275,7 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) else -- Existing config is initialized to a high enough value if environment_initialized[id] == 2 or (onlyConfig and environment_initialized[id] == 1) then + local region = WeakAuras.GetRegion(id, cloneId) -- Point the current environment to the correct table current_uid = data.uid current_aura_env = aura_environments[id] @@ -296,7 +296,6 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) current_aura_env.cloneId = cloneId current_aura_env.state = state current_aura_env.states = states - current_aura_env.region = region tinsert(aura_env_stack, {current_aura_env, data.uid}) if not data.controlledChildren then @@ -304,6 +303,7 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) end else -- Either this aura environment has not yet been initialized, or it was reset via an edit in WeakaurasOptions + local region = id and Private.EnsureRegion(id, cloneId) environment_initialized[id] = 2 aura_environments[id] = aura_environments[id] or {} getDataCallCounts[id] = getDataCallCounts[id] or 0 diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 305f54d..fa15030 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -251,11 +251,11 @@ local function UpdateToolTipDataInMatchData(matchData, time) local changed = false if matchData.unit and matchData.index and matchData.filter then - local tooltip, _, tooltip1, tooltip2, tooltip3 = WeakAuras.GetAuraTooltipInfo(matchData.unit, matchData.index, matchData.filter) + local tooltip, _, tooltip1, tooltip2, tooltip3, tooltip4 = WeakAuras.GetAuraTooltipInfo(matchData.unit, matchData.index, matchData.filter) changed = matchData.tooltip ~= tooltip or matchData.tooltip1 ~= tooltip1 - or matchData.tooltip2 ~= tooltip2 or matchData.tooltip3 ~= tooltip3 - matchData.tooltip, matchData.tooltip1, matchData.tooltip2, matchData.tooltip3 = tooltip, tooltip1, tooltip2, tooltip3 + or matchData.tooltip2 ~= tooltip2 or matchData.tooltip3 ~= tooltip3 or matchData.tooltip4 ~= tooltip4 + matchData.tooltip, matchData.tooltip1, matchData.tooltip2, matchData.tooltip3, matchData.tooltip4 = tooltip, tooltip1, tooltip2, tooltip3, tooltip4 end matchData.tooltipUpdated = time @@ -491,6 +491,7 @@ local function UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, mat tooltip1 = bestMatch.tooltip1, tooltip2 = bestMatch.tooltip2, tooltip3 = bestMatch.tooltip3, + tooltip4 = bestMatch.tooltip4, affected = affected, unaffected = unaffected, totalStacks = totalStacks, @@ -626,6 +627,11 @@ local function UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, mat changed = true end + if state.tooltip4 ~= bestMatch.tooltip4 then + state.tooltip4 = bestMatch.tooltip4 + changed = true + end + if state.matchCount ~= matchCount then state.matchCount = matchCount changed = true @@ -790,8 +796,8 @@ local function UpdateStateWithNoMatch(time, triggerStates, triggerInfo, cloneId, changed = true end - if state.tooltip or state.tooltip1 or state.tooltip2 or state.tooltip3 then - state.tooltip, state.tooltip1, state.tooltip2, state.tooltip3 = nil, nil, nil, nil + if state.tooltip or state.tooltip1 or state.tooltip2 or state.tooltip3 or state.tooltip4 then + state.tooltip, state.tooltip1, state.tooltip2, state.tooltip3, state.tooltip4 = nil, nil, nil, nil, nil changed = true end @@ -1864,6 +1870,8 @@ local function UnloadAura(scanFuncName, id) if triggerInfo.id == id or not id then if triggerInfo.nextScheduledCheckHandle then timer:CancelTimer(triggerInfo.nextScheduledCheckHandle) + triggerInfo.nextScheduledCheck = nil + triggerInfo.nextScheduledCheckHandle = nil end nameData[triggerInfo] = nil end @@ -1890,6 +1898,8 @@ local function UnloadGeneral(scanFuncGeneral, id) if triggerInfo.id == id or not id then if triggerInfo.nextScheduledCheckHandle then timer:CancelTimer(triggerInfo.nextScheduledCheckHandle) + triggerInfo.nextScheduledCheck = nil + triggerInfo.nextScheduledCheckHandle = nil end debuffData[triggerInfo] = nil end @@ -2619,6 +2629,7 @@ function BuffTrigger.GetAdditionalProperties(data, triggernum) ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip1|r - " .. L["First Value of Tooltip Text"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip2|r - " .. L["Second Value of Tooltip Text"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip3|r - " .. L["Third Value of Tooltip Text"] .. "\n" + ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip4|r - " .. L["Fourth Value of Tooltip Text"] .. "\n" end if trigger.unit ~= "multi" and trigger.fetchRaidMark then @@ -2726,6 +2737,10 @@ function BuffTrigger.GetTriggerConditions(data, triggernum) display = L["Tooltip Value 3"], type = "number" } + result["tooltip4"] = { + display = L["Tooltip Value 4"], + type = "number" + } end if trigger.unit ~= "multi" then @@ -3362,6 +3377,11 @@ function BuffTrigger.GetTriggerDescription(data, triggernum, namestable) local trigger = data.triggers[triggernum].trigger if trigger.useName and trigger.auranames then for index, name in pairs(trigger.auranames) do + if index > 10 then + tinsert(namestable, {" ", "[...]"}) + break + end + local left = " " if(index == 1) then if(#trigger.auranames > 0) then @@ -3386,6 +3406,11 @@ function BuffTrigger.GetTriggerDescription(data, triggernum, namestable) if trigger.useExactSpellId and trigger.auraspellids then for index, spellId in pairs(trigger.auraspellids) do + if index > 10 then + tinsert(namestable, {" ", "[...]"}) + break + end + local left = " " if index == 1 then if #trigger.auraspellids > 0 then diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 72a63a1..207929d 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -3136,10 +3136,8 @@ do end end WeakAuras.ScanEvents("DBM_TimerUpdate", id) - elseif event == "DBM_SetStage" then - local mod, modId, stage = ... - currentStage = stage - WeakAuras.ScanEvents("DBM_SetStage", ...) + elseif event == "DBM_SetStage" or event == "DBM_Pull" or event == "DBM_Wipe" or event == "DBM_Kill" then + WeakAuras.ScanEvents("DBM_SetStage") else -- DBM_Announce WeakAuras.ScanEvents(event, ...) end @@ -3185,7 +3183,7 @@ do end function WeakAuras.GetDBMStage() - return currentStage + return DBM:GetStage() end function WeakAuras.GetDBMTimerById(id) @@ -3349,6 +3347,18 @@ do if BigWigsLoader then BigWigsLoader.RegisterMessage(WeakAuras, event, bigWigsEventCallback) registeredBigWigsEvents[event] = true + if event == "BigWigs_SetStage" then + -- on init of BigWigs_SetStage callback, we want to fetch currentStage in case we are already in an encounter when this is run + if BigWigs and BigWigs.IterateBossModules then + local stage = 0 + for _, module in BigWigs:IterateBossModules() do + if module:IsEngaged() then + stage = math.max(stage, module:GetStage() or 1) + end + end + currentStage = stage + end + end end end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 9e6f476..0f7477f 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3868,9 +3868,12 @@ Private.event_prototypes = { internal_events = { "DBM_SetStage" }, + force_events = "DBM_SetStage", name = L["DBM Stage"], init = function(trigger) - WeakAuras.RegisterDBMCallback("DBM_SetStage"); + WeakAuras.RegisterDBMCallback("DBM_SetStage") + WeakAuras.RegisterDBMCallback("DBM_Pull") + WeakAuras.RegisterDBMCallback("DBM_Kill") return "" end, args = { @@ -4150,7 +4153,8 @@ Private.event_prototypes = { { name = "spellId", init = "arg", - display = L["Spell Id"], + display = L["Key"], + desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], type = "longstring" }, { @@ -4306,7 +4310,7 @@ Private.event_prototypes = { trigger.use_cloneId and "true" or "false", trigger.use_extend and tonumber(trigger.extend or 0) or 0, trigger.use_remaining and "true" or "false", - trigger.remaining or 0, + type(trigger.remaining) == "number" and trigger.remaining or 0, trigger.use_emphasized == nil and "nil" or trigger.use_emphasized and "true" or "false", trigger.use_cast == nil and "nil" or trigger.use_cast and "true" or "false", trigger.use_isCooldown == nil and "nil" or trigger.use_isCooldown and "true" or "false", @@ -4317,7 +4321,8 @@ Private.event_prototypes = { args = { { name = "spellId", - display = L["Spell Id"], + display = L["Key"], + desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], type = "string", conditionType = "string", }, @@ -6420,7 +6425,7 @@ Private.event_prototypes = { type = "toggle", test = "true", enable = function(trigger) - return trigger.unit == "player" + return trigger.unit == "player" and not trigger.use_inverse end, reloadOptions = true }, diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index 7d1b923..7ab84e8 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -160,6 +160,16 @@ local function SoundRepeatStop(self) Private.StopProfileSystem("sound"); end +--[[ +local function SoundStop(self) + Private.StartProfileSystem("sound"); + if (self.soundHandle) then + StopSound(self.soundHandle); + end + Private.StopProfileSystem("sound"); +end +]] + local function SoundPlayHelper(self) Private.StartProfileSystem("sound"); local options = self.soundOptions; @@ -174,24 +184,52 @@ local function SoundPlayHelper(self) end if (options.sound == " custom") then - if (options.sound_path) then - pcall(PlaySoundFile, options.sound_path, options.sound_channel or "Master"); - end + local ok, _, handle = pcall(PlaySoundFile, options.sound_path, options.sound_channel or "Master") + --if ok then + --self.soundHandle = handle + --end elseif (options.sound == " KitID") then - if (options.sound_kit_id) then - pcall(PlaySound, options.sound_kit_id, options.sound_channel or "Master"); - end + local ok, _, handle = pcall(PlaySound, options.sound_kit_id, options.sound_channel or "Master") + --if ok then + --self.soundHandle = handle + --end else - pcall(PlaySoundFile, options.sound, options.sound_channel or "Master"); + local ok, _, handle = pcall(PlaySoundFile, options.sound, options.sound_channel or "Master") + --if ok then + --self.soundHandle = handle + --end end Private.StopProfileSystem("sound"); end +local function hasSound(options) + if (options.sound == " custom") then + if (options.sound_path and options.sound_path ~= "") then + return true + end + elseif (options.sound == " KitID") then + if (options.sound_kit_id and options.sound_kit_id ~= "") then + return true + end + else + if options.sound and options.sound ~= "" then + return true + end + end + return false +end + local function SoundPlay(self, options) if (not options or WeakAuras.IsOptionsOpen()) then return end Private.StartProfileSystem("sound"); + if not hasSound(options) then + Private.StopProfileSystem("sound") + return + end + + --self:SoundStop(); self:SoundRepeatStop(); self.soundOptions = options; diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index e9d54d8..e537f46 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1392,8 +1392,8 @@ local function scanForLoadsImpl(toCheck, event, arg1, ...) local inCombat = UnitAffectingCombat("player") -- or UnitAffectingCombat("pet"); local alive = not UnitIsDeadOrGhost('player') local pvp = UnitIsPVPFreeForAll("player") or UnitIsPVP("player") - local vehicle = UnitInVehicle("player") or UnitOnTaxi("player") - local vehicleUi = UnitHasVehicleUI("player") + local vehicle = UnitInVehicle("player") or UnitOnTaxi("player") or false + local vehicleUi = UnitHasVehicleUI("player") or false local raidMemberType = 0 if UnitIsPartyLeader("player") then @@ -2691,7 +2691,7 @@ local function pAdd(data, simpleChange) end end - -- If the aura has a onHide animation we need to cancel it to ensure it's truely hidden now + -- If the aura has a onHide animation we need to cancel it to ensure it's truly hidden now if Private.regions[id] then Private.CancelAnimation(Private.regions[id].region, true, true, true, true, true, true) end @@ -5012,11 +5012,11 @@ local function GetAnchorFrame(data, region, parent) if unit then local frame = unit and WeakAuras.GetNamePlateForUnit(unit) if frame then return frame end - if WeakAuras.IsOptionsOpen() then - Private.ensurePRDFrame() - personalRessourceDisplayFrame:anchorFrame(id, anchorFrameType) - return personalRessourceDisplayFrame - end + end + if WeakAuras.IsOptionsOpen() then + Private.ensurePRDFrame() + personalRessourceDisplayFrame:anchorFrame(id, anchorFrameType) + return personalRessourceDisplayFrame end end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua index e475d98..e3d48bd 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua @@ -5,7 +5,7 @@ local L = WeakAuras.L local pairs, next, type, unpack = pairs, next, type, unpack -local Type, Version = "WeakAurasPendingUpdateButton", 3 +local Type, Version = "WeakAurasPendingUpdateButton", 5 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then @@ -100,7 +100,7 @@ local methods = { local auraData = WeakAuras.GetData(auraId) if auraData then local success, error = WeakAuras.Import(self.companionData.encoded, auraData) - if not success then + if not success and error ~= nil then WeakAuras.prettyPrint(error) end end diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index f82efc4..821c299 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -587,7 +587,7 @@ local function GetBuffTriggerOptions(data, triggernum) fetchTooltip = { type = "toggle", name = L["Fetch Tooltip Information"], - desc = L["This adds %tooltip, %tooltip1, %tooltip2, %tooltip3 as text replacements and also allows filtering based on the tooltip content/values."], + desc = L["This adds %tooltip, %tooltip1, %tooltip2, %tooltip3 and %tooltip4 as text replacements and also allows filtering based on the tooltip content/values."], order = 64.5, width = WeakAuras.doubleWidth, hidden = function() return not (trigger.type == "aura2" and trigger.unit ~= "multi" and not IsSingleMissing(trigger)) end diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index ff0bb37..f8a58f3 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -91,6 +91,35 @@ function OptionsPrivate.GetInformationOptions(data) } order = order + 1 end + if OptionsPrivate.HasWagoUrl(data.id) then + args.ignoreWagoUpdate = { + type = "toggle", + name = L["Ignore Wago updates"], + desc = OptionsPrivate.IsWagoUpdateIgnored(data.id) and L["Do you want to enable updates for this aura"] or L["Do you want to ignore updates for this aura"], + width = WeakAuras.doubleWidth, + get = function() return OptionsPrivate.IsWagoUpdateIgnored(data.id) end, + set = function(info, v) + local auraData = WeakAuras.GetData(data.id) + if auraData then + local ignoreUpdate + if OptionsPrivate.IsWagoUpdateIgnored(data.id) then + ignoreUpdate = nil + else + ignoreUpdate = true + end + for child in OptionsPrivate.Private.TraverseAll(auraData) do + child.ignoreWagoUpdate = ignoreUpdate + OptionsPrivate.ClearOptions(child.id) + end + WeakAuras.ClearAndUpdateOptions(data.id) + end + OptionsPrivate.SortDisplayButtons(nil, true) + + end, + order = order + } + order = order + 1 + end -- Description diff --git a/WeakAurasOptions/OptionsFrames/TextEditor.lua b/WeakAurasOptions/OptionsFrames/TextEditor.lua index 884d554..82e7bd7 100644 --- a/WeakAurasOptions/OptionsFrames/TextEditor.lua +++ b/WeakAurasOptions/OptionsFrames/TextEditor.lua @@ -765,6 +765,7 @@ local function ConstructTextEditor(frame) editor.editBox:SetScript("OnTextChanged", self.oldOnTextChanged) editor:ClearFocus() + frame.window = "default" frame:UpdateFrameVisible() WeakAuras.FillOptions() diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index c67c5ae..b5b75b3 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -479,25 +479,29 @@ StaticPopupDialogs["WEAKAURAS_CONFIRM_DELETE"] = { preferredindex = STATICPOPUP_NUMDIALOGS, } -StaticPopupDialogs["WEAKAURAS_CONFIRM_IGNORE_UPDATES"] = { - text = L["Do you want to ignore all future updates for this aura"], - button1 = L["Yes"], - button2 = L["Cancel"], - OnAccept = function(self) - if self.data then - local auraData = WeakAuras.GetData(self.data) - if auraData then - for child in OptionsPrivate.Private.TraverseAll(auraData) do - child.ignoreWagoUpdate = true +function OptionsPrivate.IsWagoUpdateIgnored(auraId) + local auraData = WeakAuras.GetData(auraId) + if auraData then + for child in OptionsPrivate.Private.TraverseAll(auraData) do + if child.ignoreWagoUpdate then + return true end end - OptionsPrivate.SortDisplayButtons(nil, true) end - end, - OnCancel = function(self) end, - whileDead = true, - preferredindex = STATICPOPUP_NUMDIALOGS, -} + return false +end + +function OptionsPrivate.HasWagoUrl(auraId) +local auraData = WeakAuras.GetData(auraId) + if auraData then + for child in OptionsPrivate.Private.TraverseAll(auraData) do + if child.url and child.url ~= "" then + return true + end + end + end +return false +end function OptionsPrivate.ConfirmDelete(toDelete, parents) if toDelete then From c09030248709c8fa8186ef8bdaf0edc49f831cd3 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 15:41:34 +0100 Subject: [PATCH 041/153] from retail --- WeakAuras/Conditions.lua | 6 +- WeakAuras/GenericTrigger.lua | 9 +- WeakAuras/Profiling.lua | 2 +- WeakAuras/Prototypes.lua | 6 +- WeakAuras/RegionTypes/RegionPrototype.lua | 3 + .../RegionTypes/SmoothStatusBarMixin.lua | 2 +- ...ceGUIWidget-WeakAurasTwoColumnDropDown.lua | 179 +++++++----------- 7 files changed, 90 insertions(+), 117 deletions(-) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index a0e71b7..e7ebee1 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -747,7 +747,7 @@ local function runDynamicConditionFunctions(funcs) end end -local function UpdateDynamicConditonsStates(self, event) +local function UpdateDynamicConditionsStates(self, event) if (globalDynamicConditionFuncs[event]) then for i, func in ipairs(globalDynamicConditionFuncs[event]) do func(globalConditionState); @@ -757,7 +757,7 @@ end local function handleDynamicConditions(self, event) Private.StartProfileSystem("dynamic conditions") - UpdateDynamicConditonsStates(self, event) + UpdateDynamicConditionsStates(self, event) if (dynamicConditions[event]) then runDynamicConditionFunctions(dynamicConditions[event]); end @@ -883,7 +883,7 @@ function Private.RegisterForGlobalConditions(uid) UpdateDynamicConditionsPerUnitState(dynamicConditionsFrame, event, unit) else pcall(dynamicConditionsFrame.RegisterEvent, dynamicConditionsFrame, event); - UpdateDynamicConditonsStates(dynamicConditionsFrame, event) + UpdateDynamicConditionsStates(dynamicConditionsFrame, event) end end end diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 207929d..6b25ceb 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1796,10 +1796,10 @@ function GenericTrigger.Add(data, region) end if warnAboutCLEUEvents then - Private.AuraWarnings.UpdateWarning(data.uid, "spamy_event_warning", "warning", + Private.AuraWarnings.UpdateWarning(data.uid, "spammy_event_warning", "warning", L["COMBAT_LOG_EVENT_UNFILTERED with no filter can trigger frame drops in raid environment. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Deprecated-CLEU"]) else - Private.AuraWarnings.UpdateWarning(data.uid, "spamy_event_warning") + Private.AuraWarnings.UpdateWarning(data.uid, "spammy_event_warning") end end @@ -3183,7 +3183,10 @@ do end function WeakAuras.GetDBMStage() - return DBM:GetStage() + if DBM then + return DBM:GetStage() + end + return 0, 0 end function WeakAuras.GetDBMTimerById(id) diff --git a/WeakAuras/Profiling.lua b/WeakAuras/Profiling.lua index b18161a..361b06e 100644 --- a/WeakAuras/Profiling.lua +++ b/WeakAuras/Profiling.lua @@ -410,7 +410,7 @@ function RealTimeProfilingWindow:GetBar(name) else local bar = CreateFrame("Frame", nil, self.barsFrame) self.bars[name] = bar - WeakAuras.Mixin(bar, SmoothStatusBarMixin) + WeakAuras.Mixin(bar, Private.SmoothStatusBarMixin) bar.name = name bar.parent = self bar:SetHeight(self.barHeight) diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 0f7477f..b8aa9f4 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4070,7 +4070,7 @@ Private.event_prototypes = { trigger.use_cloneId and "true" or "false", trigger.use_extend and tonumber(trigger.extend or 0) or 0, trigger.use_remaining and "true" or "false", - trigger.remaining or 0, + trigger.remaining and tonumber(trigger.remaining or 0) or 0, trigger.use_dbmType and trigger.dbmType or "nil", trigger.remaining_operator or "<" ) @@ -4310,7 +4310,7 @@ Private.event_prototypes = { trigger.use_cloneId and "true" or "false", trigger.use_extend and tonumber(trigger.extend or 0) or 0, trigger.use_remaining and "true" or "false", - type(trigger.remaining) == "number" and trigger.remaining or 0, + trigger.remaining and tonumber(trigger.remaining or 0) or 0, trigger.use_emphasized == nil and "nil" or trigger.use_emphasized and "true" or "false", trigger.use_cast == nil and "nil" or trigger.use_cast and "true" or "false", trigger.use_isCooldown == nil and "nil" or trigger.use_isCooldown and "true" or "false", @@ -4918,7 +4918,7 @@ Private.event_prototypes = { trigger.use_totemNamePattern and trigger.totemNamePattern_operator or "", trigger.use_clones and "true" or "false", trigger.use_inverse and "true" or "false", - trigger.use_remaining and trigger.remaining or "nil", + trigger.use_remaining and tonumber(trigger.remaining or 0) or "nil", trigger.use_remaining and trigger.remaining_operator or "<"); return ret; end, diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index 7ab84e8..b180cf0 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -203,6 +203,9 @@ local function SoundPlayHelper(self) end local function hasSound(options) + --if options.sound_type == "Stop" then + --return true + --end if (options.sound == " custom") then if (options.sound_path and options.sound_path ~= "") then return true diff --git a/WeakAuras/RegionTypes/SmoothStatusBarMixin.lua b/WeakAuras/RegionTypes/SmoothStatusBarMixin.lua index 2c60bcd..1b7fdef 100644 --- a/WeakAuras/RegionTypes/SmoothStatusBarMixin.lua +++ b/WeakAuras/RegionTypes/SmoothStatusBarMixin.lua @@ -3,7 +3,7 @@ if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... -- This is a more or less 1:1 copy of SmoothStatusBarMixin except that it --- doesn't clamp the targetValue in ProcesSmoothStatusBars, because that's incorrect for us +-- doesn't clamp the targetValue in ProcessSmoothStatusBars, because that's incorrect for us local g_updatingBars = {}; local function IsCloseEnough(bar, newValue, targetValue) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua index 869a22b..59491e9 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua @@ -1,95 +1,64 @@ if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasTwoColumnDropdown", 4 +local Type, Version = "WeakAurasTwoColumnDropdown", 6 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end -local tconcat = table.concat -local select = select -local assert, loadstring = assert, loadstring -local setmetatable, rawset = setmetatable, rawset -local xpcall = xpcall - -local function errorhandler(err) - return geterrorhandler()(err) +local secondLevelMt = {} -- Tag for our tables +local function CreateSecondLevelTable() + local t = {} + setmetatable(t, secondLevelMt) + return t end -local function CreateDispatcher(argCount) - local code = [[ - local xpcall, eh = ... - local method, ARGS - local function call() return method(ARGS) end - - local function dispatch(func, ...) - method = func - if not method then return end - ARGS = ... - return xpcall(call, eh) - end - - return dispatch - ]] - - local ARGS = {} - for i = 1, argCount do ARGS[i] = "arg"..i end - code = code:gsub("ARGS", tconcat(ARGS, ", ")) - return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler) +local function IsSecondLevelTable(t) + return getmetatable(t) == secondLevelMt end -local Dispatchers = setmetatable({}, {__index=function(self, argCount) - local dispatcher = CreateDispatcher(argCount) - rawset(self, argCount, dispatcher) - return dispatcher -end}) -Dispatchers[0] = function(func) - return xpcall(func, errorhandler) -end - -local function safecall(func, ...) - return Dispatchers[select("#", ...)](func, ...) -end - -AceGUI:RegisterLayout("TwoColumn", - function(content, children) - local height = 0 - local width = content.width or content:GetWidth() or 0 - for i = 1, #children do - local child = children[i] - - local frame = child.frame - frame:ClearAllPoints() - if child.userdata.hideMe then - frame:Hide() - else - frame:Show() +local function CompareValues(a, b) + if type(a) == "table" and type(b) == "table" then + for ak, av in pairs(a) do + if b[ak] ~= av then + return false end - if i == 1 then - frame:SetPoint("TOPLEFT", content) - else - frame:SetPoint("TOPLEFT", children[i-1].frame, "TOPRIGHT") - end - - if child.width == "relative" then - child:SetWidth(width * child.relWidth) - - if child.DoLayout then - child:DoLayout() - end - end - - height = max(height, frame.height or frame:GetHeight() or 0) end - safecall(content.obj.LayoutFinished, content.obj, nil, height) - end) + for bk, bv in pairs(b) do + if a[bk] ~= bv then + return false + end + end + return true + else + return a == b + end +end local methods = { + ["DoLayout"] = function(self, mode) + self.mode = mode + if mode == "one" then + self.firstDropdown.frame:Show() + self.secondDropDown.frame:Hide() + self.firstDropdown.frame:SetAllPoints(self.frame) + else + local halfWidth = self.frame:GetWidth() / 2 + self.firstDropdown.frame:Show() + self.secondDropDown.frame:Show() + self.firstDropdown.frame:ClearAllPoints() + self.firstDropdown.frame:SetPoint("TOPLEFT", self.frame) + self.firstDropdown.frame:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMLEFT", halfWidth, 0) + self.secondDropDown.frame:SetPoint("TOPLEFT", self.frame, halfWidth, 0) + self.secondDropDown.frame:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT") + end + end, ["OnAcquire"] = function(widget) local firstDropdown = AceGUI:Create("Dropdown") local secondDropDown = AceGUI:Create("Dropdown") - firstDropdown:SetRelativeWidth(0.5) + firstDropdown:SetParent(widget) + secondDropDown:SetParent(widget) firstDropdown:SetPulloutWidth(200) - secondDropDown:SetRelativeWidth(0.5) + secondDropDown:SetLabel(" ") secondDropDown:SetPulloutWidth(200) secondDropDown.userdata.defaultSelection = {} @@ -97,18 +66,10 @@ local methods = { widget.firstDropdown = firstDropdown widget.secondDropDown = secondDropDown - widget:SetLayout("TwoColumn") - widget.SetLayout = function() - -- AceGui wants to set a default layout, but we don't want that - end - - widget:AddChild(firstDropdown) - widget:AddChild(secondDropDown) - local OnFirstDropdownValueChanged = function(self, event, value) local displayName = widget.userdata.firstList[value] local treeValue = widget.userdata.tree[displayName] - if type(treeValue) == "table" then + if IsSecondLevelTable(treeValue) then local oldValue if widget.userdata.secondList then local v = widget.secondDropDown:GetValue() @@ -125,10 +86,7 @@ local methods = { local oldValueIndex = tIndexOf(secondList, oldValue) widget.userdata.secondList = secondList widget.secondDropDown:SetList(secondList) - widget.firstDropdown:SetRelativeWidth(0.5) - widget.secondDropDown:SetRelativeWidth(0.5) - widget.secondDropDown.userdata.hideMe = false - widget:DoLayout() + widget:DoLayout("two") if (oldValueIndex) then widget.secondDropDown:SetValue(oldValueIndex) @@ -151,10 +109,8 @@ local methods = { end end else - widget.firstDropdown:SetRelativeWidth(1) - widget.secondDropDown.userdata.hideMe = true widget.userdata.secondList = nil - widget:DoLayout() + widget:DoLayout("one") widget:Fire("OnValueChanged", treeValue) end end @@ -180,27 +136,37 @@ local methods = { firstDropdown:SetCallback("OnLeave", FireOnLeave) secondDropDown:SetCallback("OnEnter", FireOnEnter) secondDropDown:SetCallback("OnLeave", FireOnLeave) + + + widget:DoLayout("two") end, ["OnRelease"] = function(self) + self.firstDropdown:SetCallback("OnValueChanged", nil) + self.secondDropDown:SetCallback("OnValueChanged", nil) + self.firstDropdown:SetCallback("OnEnter", nil) + self.firstDropdown:SetCallback("OnLeave", nil) + self.secondDropDown:SetCallback("OnEnter", nil) + self.secondDropDown:SetCallback("OnLeave", nil) + + AceGUI:Release(self.firstDropdown) + AceGUI:Release(self.secondDropDown) + + self.firstDropdown = nil + self.secondDropDown = nil end, ["SetLabel"] = function(self, ...) self.firstDropdown:SetLabel(...) end, ["SetValue"] = function(self, value) for displayName, treeValue in pairs(self.userdata.tree) do - if treeValue == value then - self.firstDropdown:SetRelativeWidth(1) - self.secondDropDown.userdata.hideMe = true - self:DoLayout() + if CompareValues(treeValue, value) then + self:DoLayout("one") self.firstDropdown:SetValue(tIndexOf(self.userdata.firstList, displayName)) return - elseif type(treeValue) == "table" then + elseif IsSecondLevelTable(treeValue) then for displayName2, key in pairs(treeValue) do - if (key == value) then - self.firstDropdown:SetRelativeWidth(0.5) - self.secondDropDown:SetRelativeWidth(0.5) - self.secondDropDown.userdata.hideMe = false - self:DoLayout() + if CompareValues(key, value) then + self:DoLayout("two") local index = tIndexOf(self.userdata.firstList, displayName); self.firstDropdown:SetValue(index) self.firstDropdown:OnFirstDropdownValueChanged("", index) @@ -210,9 +176,7 @@ local methods = { end end end - self.firstDropdown:SetRelativeWidth(1) - self.secondDropDown.userdata.hideMe = true - self:DoLayout() + self:DoLayout("one") self.firstDropdown:SetValue(nil) end, ["GetValue"] = function(self) @@ -222,7 +186,7 @@ local methods = { if not treeValue then return nil end - if type(treeValue) ~= "table" then + if not IsSecondLevelTable(treeValue) then return treeValue end @@ -239,7 +203,7 @@ local methods = { if type(displayName) == "table" then local base = displayName[1] local suffix = displayName[2] - tree[base] = tree[base] or {} + tree[base] = tree[base] or CreateSecondLevelTable() tree[base][suffix] = key if displayName[3] == true then self.secondDropDown.userdata.defaultSelection[base] = suffix @@ -257,6 +221,9 @@ local methods = { table.sort(firstList) self.userdata.firstList = firstList self.firstDropdown:SetList(firstList, order, itemType) + end, + ["OnWidthSet"] = function(self) + self:DoLayout(self.mode) end } @@ -277,7 +244,7 @@ local function Constructor() for method, func in pairs(methods) do widget[method] = func end - return AceGUI:RegisterAsContainer(widget) + return AceGUI:RegisterAsWidget(widget) end AceGUI:RegisterWidgetType(Type, Constructor, Version) From bbb47ec07d4dd3283cde09c4cdeca5cce6d51f7f Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 15:49:20 +0100 Subject: [PATCH 042/153] from retail --- WeakAuras/RegionTypes/DynamicGroup.lua | 79 ++++++++++++++----- .../RegionOptions/DynamicGroup.lua | 19 +++++ 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index f819a94..30aa547 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -392,7 +392,7 @@ local anchorers = { tinsert(frames[Private.personalRessourceDisplayFrame], regionData) end end - end + end, {unit = true } end, ["UNITFRAME"] = function(data) return function(frames, activeRegions) @@ -406,11 +406,21 @@ local anchorers = { end end end - end + end, {unit = true } end, ["CUSTOM"] = function(data) local anchorStr = data.customAnchorPerUnit or "" local anchorFunc = WeakAuras.LoadFunction("return " .. anchorStr) or noop + + local anchorOn = nil + local events = WeakAuras.split(data.anchorOn or "") + if #events > 0 then + anchorOn = {} + for _, event in ipairs(events) do + anchorOn[event] = true + end + end + return function(frames, activeRegions) Private.ActivateAuraEnvironment(data.id) local ok, ret = pcall(anchorFunc, frames, activeRegions) @@ -418,7 +428,7 @@ local anchorers = { Private.GetErrorHandlerUid(data.uid, L["Custom Anchor"]) end Private.ActivateAuraEnvironment() - end + end, anchorOn end } @@ -508,7 +518,10 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local startX, startY = 0, 0 local coeff = staggerCoefficient(data.align, data.stagger) - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -528,7 +541,7 @@ local growers = { end end end - end + end, anchorOn end, RIGHT = function(data) local stagger = data.stagger or 0 @@ -536,7 +549,10 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local startX, startY = 0, 0 local coeff = 1 - staggerCoefficient(data.align, stagger) - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -556,7 +572,7 @@ local growers = { end end end - end + end, anchorOn end, UP = function(data) local stagger = data.stagger or 0 @@ -564,7 +580,10 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local startX, startY = 0, 0 local coeff = 1 - staggerCoefficient(data.align, stagger) - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -584,7 +603,7 @@ local growers = { end end end - end + end, anchorOn end, DOWN = function(data) local stagger = data.stagger or 0 @@ -592,7 +611,10 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local startX, startY = 0, 0 local coeff = staggerCoefficient(data.align, stagger) - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -612,14 +634,17 @@ local growers = { end end end - end + end, anchorOn end, HORIZONTAL = function(data) local stagger = data.stagger or 0 local space = data.space or 0 local limit = data.useLimit and data.limit or math.huge local midX, midY = 0, 0 - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end local FirstIndex = centeredIndexerStart[data.centerType] local NextIndex = centeredIndexerNext[data.centerType] return function(newPositions, activeRegions) @@ -648,14 +673,17 @@ local growers = { i = NextIndex(i, numVisible) end end - end + end, anchorOn end, VERTICAL = function(data) local stagger = -(data.stagger or 0) local space = data.space or 0 local limit = data.useLimit and data.limit or math.huge local midX, midY = 0, 0 - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end local FirstIndex = centeredIndexerStart[data.centerType] local NextIndex = centeredIndexerNext[data.centerType] return function(newPositions, activeRegions) @@ -684,7 +712,7 @@ local growers = { i = NextIndex(i, numVisible) end end - end + end, anchorOn end, CIRCLE = function(data) local oX, oY = 0, 0 @@ -694,7 +722,10 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local sAngle = (data.rotation or 0) * math.pi / 180 local arc = (data.fullCircle and 360 or data.arcLength or 0) * math.pi / 180 - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -732,7 +763,7 @@ local growers = { end end end - end + end, anchorOn end, COUNTERCIRCLE = function(data) local oX, oY = 0, 0 @@ -742,7 +773,10 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local sAngle = (data.rotation or 0) * math.pi / 180 local arc = (data.fullCircle and 360 or data.arcLength or 0) * math.pi / 180 - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -780,7 +814,7 @@ local growers = { end end end - end + end, anchorOn end, GRID = function(data) local gridType = data.gridType @@ -829,7 +863,10 @@ local growers = { if not rowFirst then primary, secondary = secondary, primary end - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + local anchorPerUnitFunc, anchorOn + if data.useAnchorPerUnit then + anchorPerUnitFunc, anchorOn = createAnchorPerUnitFunc(data) + end return function(newPositions, activeRegions) local frames = {} if anchorPerUnitFunc then @@ -919,7 +956,7 @@ local growers = { end end end - end + end, anchorOn end, CUSTOM = function(data) local growStr = data.customGrow or "" diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 8d06068..a396a90 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -182,6 +182,25 @@ local function createOptions(id, data) hidden = function() return data.grow == "CUSTOM" end, disabled = function() return not data.useAnchorPerUnit end }, + anchorOn = { + type = "input", + width = WeakAuras.doubleWidth, + name = L["Run on..."], + desc = L["You can add a comma-separated list of state values here that (when changed) WeakAuras should also run the Anchor Code on.\n\nWeakAuras will always run custom anchor code if you include 'changed' in this list, or when a region is added, removed, or re-ordered."], + order = 1.61, + get = function() + return data.anchorOn or "" + end, + hidden = function() + return not(data.grow ~= "CUSTOM" and data.useAnchorPerUnit and data.anchorPerUnit == "CUSTOM") + end, + set = function(info, v) + data.anchorOn = v + WeakAuras.Add(data) + WeakAuras.ClearAndUpdateOptions(data.id) + OptionsPrivate.ResetMoverSizer() + end + }, -- custom grow option added below align = { type = "select", From c080aa96d5ef349a2c820b2b361d7d361112df57 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 16:10:02 +0100 Subject: [PATCH 043/153] from retail --- WeakAuras/Conditions.lua | 4 +- .../AceGUIWidget-WeakAurasExpand.lua | 12 +++- WeakAurasOptions/ConditionOptions.lua | 66 +++++++++++++++---- WeakAurasOptions/TriggerOptions.lua | 22 ++++++- 4 files changed, 88 insertions(+), 16 deletions(-) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index e7ebee1..60044ee 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -484,7 +484,9 @@ function Private.GetSubRegionProperties(data, properties) if subProperties then for key, property in pairs(subProperties) do subIndex[key] = subIndex[key] and subIndex[key] + 1 or 1 - property.display = { subIndex[key] .. ". " .. subRegionTypeData.displayName, property.display, property.defaultProperty } + property.display = { subRegionTypeData.displayName .. " " .. subIndex[key], + property.display, + property.defaultProperty } properties["sub." .. index .. "." .. key ] = property; end end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua index 1732ec0..cc3c0af 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasExpand.lua @@ -3,7 +3,7 @@ Button Widget for our Expand button -------------------------------------------------------------------------------]] if not WeakAuras.IsLibsOK() then return end -local Type, Version = "WeakAurasExpand", 5 +local Type, Version = "WeakAurasExpand", 6 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -30,6 +30,12 @@ local function Button_OnClick(frame, button) AceGUI:ClearFocus() end +local function OnFrameShow(frame) + local self = frame.obj + local fontObject = self.userdata and self.userdata.option and self.userdata.option.fontObject + self:SetFontObject(fontObject or GameFontHighlightLarge) +end + --[[----------------------------------------------------------------------------- Methods -------------------------------------------------------------------------------]] @@ -38,7 +44,6 @@ local methods = { self:SetHeight(110) self:SetWidth(110) self:SetLabel() - self:SetFontObject(GameFontHighlightLarge) self:SetImage(nil) self:SetImageSize(64, 64) self:SetDisabled(false) @@ -111,6 +116,7 @@ local function Constructor() frame:SetScript("OnEnter", Control_OnEnter) frame:SetScript("OnLeave", Control_OnLeave) frame:SetScript("OnClick", Button_OnClick) + frame:SetScript("OnShow", OnFrameShow) local image = frame:CreateTexture(nil, "BACKGROUND") image:SetWidth(64) @@ -119,7 +125,7 @@ local function Constructor() local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightLarge") label:SetJustifyH("LEFT") - label:SetJustifyV("TOP") + label:SetJustifyV("MIDDLE") label:SetPoint("LEFT", image, "RIGHT", 5, 0) label:SetPoint("TOP") label:SetPoint("BOTTOM") diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 6f8bb54..a8380f9 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -1378,14 +1378,14 @@ local function addControlsForIfLine(args, order, data, conditionVariable, totalA local isFirst = path[#path] == 1; if (isFirst) then if (needsTriggerName) then - optionsName = optionsName .. string.format(L["Trigger %s"], check.trigger); + optionsName = optionsName .. OptionsPrivate.GetTriggerTitle(data, check.trigger) end else if (needsTriggerName) then if (parentType == "AND") then - optionsName = optionsName .. string.format(L["and Trigger %s"], check.trigger); + optionsName = optionsName .. string.format(L["and %s"], OptionsPrivate.GetTriggerTitle(data, check.trigger)); else - optionsName = optionsName .. string.format(L["or Trigger %s"], check.trigger); + optionsName = optionsName .. string.format(L["or %s"], OptionsPrivate.GetTriggerTitle(data, check.trigger)); end end end @@ -1393,9 +1393,9 @@ local function addControlsForIfLine(args, order, data, conditionVariable, totalA local isLinked = conditions[i].linked and i > 1 if (needsTriggerName) then if isLinked then - optionsName = optionsName .. string.format(L["Else If Trigger %s"], check.trigger); + optionsName = optionsName .. string.format(L["Else If %s"], OptionsPrivate.GetTriggerTitle(data, check.trigger)); else - optionsName = optionsName .. string.format(L["If Trigger %s"], check.trigger); + optionsName = optionsName .. string.format(L["If %s"], OptionsPrivate.GetTriggerTitle(data, check.trigger)); end else optionsName = optionsName .. (isLinked and L["Else If"] or L["If"]) @@ -1954,6 +1954,49 @@ local function fixUpLinkedInFirstCondition(conditions) end end +local function formatConditionTitle(text, propertyType, value) + if propertyType == "color" and type(value) == "table" then + local r, g, b = unpack(value) + r, g, b = r or 1, g or 1, b or 1 + return ("|cFF%2x%2x%2x%s|r"):format(r * 220 + 35, g * 220 + 35, b * 220 + 35, text) + elseif propertyType == "bool" then + return ("%s: %s"):format(text, value and L["ON"] or L["OFF"]) + elseif propertyType == "sound" and type(value) == "table" and type(value.sound) == "string" and value.sound ~= "" then + if OptionsPrivate.Private.sound_types[value.sound] then + return ("%s: %s"):format(text, OptionsPrivate.Private.sound_types[value.sound]) + end + elseif value ~= nil and type(value) ~= "table" then + return ("%s: %s"):format(text, value) + end + return text +end + +local function GetConditionTitle(changes, conditionnum, allProperties) + if type(changes) == "table" and #changes > 0 then + local outs = {} + for i, change in ipairs(changes) do + local property = change.property + if property and allProperties.propertyMap[property] then + local display = allProperties.propertyMap[property].display + local propertyType = allProperties.propertyMap[property].type + local title + if type(display) == "string" then + title = display + elseif type(display) == "table" then + title = ("%s %s"):format(display[1], display[2]) + end + if title then + tinsert(outs, formatConditionTitle(title, propertyType, change.value)) + end + end + end + if #outs > 0 then + return L["%i. %s"]:format(conditionnum, table.concat(outs, ", ")) + end + end + return L["%i."]:format(conditionnum) +end + local function addControlsForCondition(args, order, data, conditionVariable, totalAuraCount, conditions, i, conditionTemplates, conditionTemplateWithoutCombinations, allProperties) if (not conditions[i].check) then return order; @@ -1975,7 +2018,7 @@ local function addControlsForCondition(args, order, data, conditionVariable, tot args["condition" .. i .. "header"] = { type = "execute", - name = L["Condition %i"]:format(i), + name = GetConditionTitle(conditions[i].changes, i, allProperties), order = order, width = WeakAuras.doubleWidth - 0.6, func = function() @@ -1993,7 +2036,8 @@ local function addControlsForCondition(args, order, data, conditionVariable, tot image = collapsed and "Interface\\AddOns\\WeakAuras\\Media\\Textures\\expand" or "Interface\\AddOns\\WeakAuras\\Media\\Textures\\collapse" , imageWidth = 18, imageHeight = 18, - control = "WeakAurasExpand" + control = "WeakAurasExpand", + fontObject = GameFontHighlight }; order = order + 1; @@ -2292,7 +2336,7 @@ local function mergeConditionTemplates(allConditionTemplates, auraConditionsTemp end end -local function createConditionTemplatesValueList(allConditionTemplates, numTriggers, excludeCombinations) +local function createConditionTemplatesValueList(allConditionTemplates, numTriggers, excludeCombinations, data) local conditionTemplates = {}; conditionTemplates.all = allConditionTemplates; conditionTemplates.indexToTrigger = {}; @@ -2322,7 +2366,7 @@ local function createConditionTemplatesValueList(allConditionTemplates, numTrigg elseif (triggernum == -1) then conditionTemplates.display[index] = string.format(L["Global Conditions"]); else - conditionTemplates.display[index] = string.format(L["Trigger %d"], triggernum); + conditionTemplates.display[index] = OptionsPrivate.GetTriggerTitle(data, triggernum) end index = index + 1; @@ -2381,7 +2425,7 @@ local function createConditionTemplates(data) } allConditionTemplates[-1] = OptionsPrivate.Private.GetGlobalConditions(); - local conditionTemplates = createConditionTemplatesValueList(allConditionTemplates, numTriggers); + local conditionTemplates = createConditionTemplatesValueList(allConditionTemplates, numTriggers, nil, data); if (data.controlledChildren) then conditionTemplates.displayWithCopy = CopyTable(conditionTemplates.display); @@ -2391,7 +2435,7 @@ local function createConditionTemplates(data) conditionTemplates.indexToVariable[9998] = "COPY"; end - local conditionTemplateWithoutCombinations = createConditionTemplatesValueList(allConditionTemplates, numTriggers, true); + local conditionTemplateWithoutCombinations = createConditionTemplatesValueList(allConditionTemplates, numTriggers, true, data); return conditionTemplates, conditionTemplateWithoutCombinations; end diff --git a/WeakAurasOptions/TriggerOptions.lua b/WeakAurasOptions/TriggerOptions.lua index 0f27297..369f6c5 100644 --- a/WeakAurasOptions/TriggerOptions.lua +++ b/WeakAurasOptions/TriggerOptions.lua @@ -253,10 +253,30 @@ function OptionsPrivate.ClearTriggerExpandState() maxTriggerNumForExpand = 0 end +function OptionsPrivate.GetTriggerTitle(data, triggernum) + if data.triggers[triggernum] then + local trigger = data.triggers[triggernum].trigger + if trigger then + local event_prototype = OptionsPrivate.Private.event_prototypes[trigger.event] + local triggerType = trigger.type + local name + if triggerType == "aura2" then + name = L["Aura"] + elseif triggerType == "custom" then + name = L["Custom"] + else + name = event_prototype.name + end + return L["Trigger %i: %s"]:format(triggernum, name) + end + end + return L["Trigger %i"]:format(triggernum) +end + local triggerDeleteDialogOpen = false function OptionsPrivate.AddTriggerMetaFunctions(options, data, triggernum) - options.__title = L["Trigger %s"]:format(triggernum) + options.__title = OptionsPrivate.GetTriggerTitle(data, triggernum) options.__order = triggernum * 10 options.__collapsed = #data.triggers > 1 options.__isCollapsed = function() From c133385b44500004baf024636a00bc67f329872e Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 16:44:32 +0100 Subject: [PATCH 044/153] from retail --- WeakAuras/AuraEnvironment.lua | 4 ++++ WeakAuras/BuffTrigger2.lua | 5 ++++- WeakAuras/GenericTrigger.lua | 4 ++-- WeakAuras/Prototypes.lua | 19 +++++++++---------- WeakAuras/RegionTypes/DynamicGroup.lua | 21 +++++++++++++++------ WeakAuras/RegionTypes/Texture.lua | 1 + WeakAuras/WeakAuras.lua | 2 ++ 7 files changed, 37 insertions(+), 19 deletions(-) diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index e6eacd9..395515b 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -149,6 +149,9 @@ local blockedFunctions = { securecall = true, DeleteCursorItem = true, ChatEdit_SendText = true, + ChatEdit_ActivateChat = true, + ChatEdit_ParseText = true, + ChatEdit_OnEnterPressed = true, } local blockedTables = { @@ -156,6 +159,7 @@ local blockedTables = { SendMailMailButton = true, SendMailMoneyGold = true, MailFrameTab2 = true, + DEFAULT_CHAT_FRAME = true, ChatFrame1 = true, --WeakAurasSaved = true, WeakAurasOptions = true, diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index fa15030..a7ab98a 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -1791,8 +1791,11 @@ local function EventHandler(frame, event, arg1, arg2, ...) elseif event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" then for unit in GetAllUnits("group", true, "PlayersAndPets") do RecheckActiveForUnitType("group", unit, deactivatedTriggerInfos) - if not UnitExistsFixed(unit) then + local exists = UnitExistsFixed(unit) + if not exists then tinsert(unitsToRemove, unit) + elseif exists ~= existingUnits[unit] then + ScanGroupUnit(time, matchDataChanged, "group", unit) end end elseif event == "UNIT_FLAGS" or event == "UNIT_NAME_UPDATE" or event == "PLAYER_FLAGS_CHANGED" then diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 6b25ceb..3c51ebe 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -3069,7 +3069,7 @@ do local function dbmEventCallback(event, ...) if event == "DBM_TimerStart" then - local id, msg, duration, icon, timerType, spellId, dbmType = ... + local id, msg, duration, icon, timerType, spellId, dbmType, _, _, _, _, _, timerCount = ... local now = GetTime() local expirationTime = now + duration bars[id] = bars[id] or {} @@ -3080,7 +3080,7 @@ do bar.icon = icon bar.timerType = timerType bar.spellId = tostring(spellId) - bar.count = msg:match("%((%d+)%)") or msg:match("((%d+))") or "0" + bar.count = timerCount and tostring(timerCount) or "0" bar.dbmType = dbmType local barOptions = DBM.ReleaseRevision >= 20220412000000 and DBT.Options or DBM.Bars.options diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index b8aa9f4..119cf9d 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -7010,17 +7010,10 @@ Private.event_prototypes = { tinsert(events, "RAID_ROSTER_UPDATE") end - if trigger.use_instance_size ~= nil then - tinsert(events, "ZONE_CHANGED") - tinsert(events, "ZONE_CHANGED_INDOORS") - tinsert(events, "ZONE_CHANGED_NEW_AREA") - end - - if trigger.use_instance_difficulty ~= nil then + if trigger.use_instance_difficulty ~= nil + or trigger.use_instance_size ~= nil + then tinsert(events, "PLAYER_DIFFICULTY_CHANGED") - tinsert(events, "ZONE_CHANGED") - tinsert(events, "ZONE_CHANGED_INDOORS") - tinsert(events, "ZONE_CHANGED_NEW_AREA") end return { @@ -7038,6 +7031,12 @@ Private.event_prototypes = { tinsert(events, "PLAYER_MOVE_SPEED_UPDATE"); end + if trigger.use_instance_difficulty ~= nil + or trigger.use_instance_size ~= nil + then + tinsert(events, "WA_DELAYED_PLAYER_ENTERING_WORLD") + end + if (trigger.use_HasPet ~= nil) then AddUnitChangeInternalEvents("pet", events); end diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 30aa547..7e591ff 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1343,12 +1343,21 @@ local function modify(parent, region, data) local controlPoint = regionData.controlPoint controlPoint:ClearAnchorPoint() - controlPoint:SetAnchorPoint( - data.selfPoint, - frame == "" and self.relativeTo or frame, - data.anchorPoint, - x + data.xOffset, y + data.yOffset - ) + if frame == "" then + controlPoint:SetAnchorPoint( + data.selfPoint, + self, + data.selfPoint, + x, y + ) + else + controlPoint:SetAnchorPoint( + data.selfPoint, + frame, + data.anchorPoint, + x + data.xOffset, y + data.yOffset + ) + end if show and frame ~= WeakAuras.HiddenFrames then controlPoint:Show() else diff --git a/WeakAuras/RegionTypes/Texture.lua b/WeakAuras/RegionTypes/Texture.lua index e019666..d4ffd3b 100644 --- a/WeakAuras/RegionTypes/Texture.lua +++ b/WeakAuras/RegionTypes/Texture.lua @@ -94,6 +94,7 @@ local function modify(parent, region, data) --region.texture:SetRotation((data.rotation / 180) * math.pi); local function GetRotatedPoints(degrees) + degrees = degrees or 0 local angle = rad(135 - degrees); local vx = math.cos(angle); local vy = math.sin(angle); diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index e537f46..b1f6f7b 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3046,6 +3046,8 @@ function Private.HandleChatAction(message_type, message, message_dest, message_d message_dest = Private.ReplacePlaceHolders(message_dest, region, customFunc, useHiddenStates, formatters); end if message_dest_isunit == true then + -- send to server like retail doesnt work here + -- message_dest = GetUnitName(message_dest, true) message_dest = UnitName(message_dest) end pcall(function() SendChatMessage(message, "WHISPER", nil, message_dest) end); From 64a21e9030e46a977e8f6a3004d3b2bb24b487ff Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 17:04:03 +0100 Subject: [PATCH 045/153] from retail --- WeakAuras/AuraEnvironment.lua | 13 +- WeakAuras/BossMods.lua | 1591 +++++++++++++++++++++++++++++++++ WeakAuras/GenericTrigger.lua | 438 --------- WeakAuras/Prototypes.lua | 526 ----------- WeakAuras/WeakAuras.toc | 3 +- 5 files changed, 1604 insertions(+), 967 deletions(-) create mode 100644 WeakAuras/BossMods.lua diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index 395515b..2772dd6 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -461,9 +461,18 @@ local FakeWeakAurasMixin = { return data and CopyTable(data) or nil end, clones = MakeDeprecated(Private.clones, "clones", - L["Using WeakAuras.clones is deprecated. Use WeakAuras.GetRegion(id, cloneId) instead."]), + L["Using WeakAuras.clones is deprecated. Use WeakAuras.GetRegion(id, cloneId) instead."]), regions = MakeDeprecated(Private.regions, "regions", - L["Using WeakAuras.regions is deprecated. Use WeakAuras.GetRegion(id) instead."]) + L["Using WeakAuras.regions is deprecated. Use WeakAuras.GetRegion(id) instead."]), + GetAllDBMTimers = function() return Private.ExecEnv.BossMods.DBM:GetAllTimers() end, + GetDBMTimerById = function(...) return Private.ExecEnv.BossMods.DBM:GetTimerById(...) end, + GetDBMTimer = function(...) return Private.ExecEnv.BossMods.DBM:GetTimer(...) end, + GetBigWigsTimerById = function(...) return Private.ExecEnv.BossMods.BigWigs:GetTimerById(...) end, + GetAllBigWigsTimers = function() return Private.ExecEnv.BossMods.BigWigs:GetAllTimers() end, + GetBigWigsStage = function(...) return Private.ExecEnv.BossMods.BigWigs:GetStage(...) end, + RegisterBigWigsTimer = function() Private.ExecEnv.BossMods.BigWigs:RegisterTimer() end, + RegisterDBMCallback = function() Private.ExecEnv.BossMods.DBM:RegisterTimer() end, + GetBossStage = function() return Private.ExecEnv.BossMods.Generic:GetStage() end }, blocked = blocked, setBlocked = function() diff --git a/WeakAuras/BossMods.lua b/WeakAuras/BossMods.lua new file mode 100644 index 0000000..b5cc4c1 --- /dev/null +++ b/WeakAuras/BossMods.lua @@ -0,0 +1,1591 @@ +if not WeakAuras.IsLibsOK() then return end +--- @type string, Private +local AddonName, Private = ... + +local timer = WeakAuras.timer; +local L = WeakAuras.L + +Private.ExecEnv.BossMods = {} + +-- DBM +Private.ExecEnv.BossMods.DBM = { + registeredEvents = {}, + bars = {}, + nextExpire = nil, + recheckTimer = nil, + + CopyBarToState = function(self, bar, states, timerId, extendTimer) + extendTimer = extendTimer or 0 + if extendTimer + bar.duration < 0 then return end + states[timerId] = states[timerId] or {} + local state = states[timerId] + state.show = true + state.changed = true + state.icon = bar.icon + state.message = bar.message + state.text = bar.message + state.name = bar.message + state.expirationTime = bar.expirationTime + extendTimer + state.progressType = 'timed' + state.duration = bar.duration + extendTimer + state.timerType = bar.timerType + state.spellId = bar.spellId + state.count = bar.count + state.dbmType = bar.dbmType + state.dbmColor = bar.dbmColor + state.extend = extendTimer + if extendTimer ~= 0 then + state.autoHide = true + end + state.paused = bar.paused + state.remaining = bar.remaining + end, + + TimerMatches = function(self, timerId, message, operator, spellId, counter, triggerId, dbmType, noCastBar) + if not self.bars[timerId] then + return false + end + + local v = self.bars[timerId] + if triggerId and triggerId ~= "" and triggerId ~= timerId then + return false + end + if spellId and spellId ~= "" and spellId ~= v.spellId then + return false + end + if message and message ~= "" and operator then + if operator == "==" then + if v.message ~= message then + return false + end + elseif operator == "find('%s')" then + if v.message == nil or not v.message:find(message, 1, true) then + return false + end + elseif operator == "match('%s')" then + if v.message == nil or not v.message:match(message) then + return false + end + end + end + if counter then + counter:SetCount(tonumber(v.count) or 0) + if not counter:Match() then + return false + end + end + + if noCastBar and v.timerType:find("^cast") then + return false + end + + if dbmType and dbmType ~= v.dbmType then + return false + end + return true + end, + + TimerMatchesGeneric = function(self, timerId, message, operator, spellId, counter) + return self:TimerMatches(timerId, message, operator, spellId, counter, nil, nil, true) + end, + + GetStage = function() + if DBM then + return DBM:GetStage() + end + return 0, 0 + end, + + GetAllTimers = function(self) + return self.bars + end, + + GetTimerById = function(self, timerId) + return self.bars[timerId] + end, + + GetTimer = function(self, message, operator, spellId, extendTimer, count, triggerId, dbmType, noCastBar) + local bestMatch + for timerId, bar in pairs(self.bars) do + if self:TimerMatches(timerId, message, operator, spellId, count, triggerId, dbmType, noCastBar) + and (bestMatch == nil or bar.expirationTime < bestMatch.expirationTime) + and bar.expirationTime + extendTimer > GetTime() + then + bestMatch = bar + end + end + return bestMatch + end, + + GetTimerGeneric = function(self, message, operator, spellId, extendTimer, count) + return self:GetTimer(message, operator, spellId, extendTimer, count, nil, nil, true) + end, + + RecheckTimers = function(self) + local now = GetTime() + self.nextExpire = nil + for timerId, bar in pairs(self.bars) do + if not bar.paused then + if bar.expirationTime < now then + self.bars[timerId] = nil + WeakAuras.ScanEvents("DBM_TimerStop", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + end + elseif self.nextExpire == nil then + self.nextExpire = bar.expirationTime + elseif bar.expirationTime < self.nextExpire then + self.nextExpire = bar.expirationTime + end + end + end + if self.nextExpire then + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, self.nextExpire - now, self) + end + end, + + EventCallback = function(self, event, ...) + if event == "DBM_Announce" then + local spellId = select(4, ...) + WeakAuras.ScanEvents("DBM_Announce", spellId, ...) + if self.isGeneric then + local message, icon = ... + WeakAuras.ScanEvents("BossMod_Announce", spellId, message, icon) + end + elseif event == "DBM_TimerStart" then + local timerId, msg, duration, icon, timerType, spellId, dbmType, _, _, _, _, _, timerCount = ... + local now = GetTime() + local expirationTime = now + duration + self.bars[timerId] = self.bars[timerId] or {} + local bar = self.bars[timerId] + bar.message = msg + bar.expirationTime = expirationTime + bar.duration = duration + bar.icon = icon + bar.timerType = timerType + bar.spellId = tostring(spellId) + bar.count = timerCount and tostring(timerCount) or "0" + bar.dbmType = dbmType + + local r, g, b = 0, 0, 0 + if DBT.GetColorForType then + r, g, b = DBT:GetColorForType(dbmType) + r, g, b = r or 0, g or 0, b or 0 + else + -- Compability code for DBM versions from around Aberrus + -- Can be removed once we can assume newer versions + local barOptions = DBT.Options + + if dbmType == 1 then + r, g, b = barOptions.StartColorAR, barOptions.StartColorAG, barOptions.StartColorAB + elseif dbmType == 2 then + r, g, b = barOptions.StartColorAER, barOptions.StartColorAEG, barOptions.StartColorAEB + elseif dbmType == 3 then + r, g, b = barOptions.StartColorDR, barOptions.StartColorDG, barOptions.StartColorDB + elseif dbmType == 4 then + r, g, b = barOptions.StartColorIR, barOptions.StartColorIG, barOptions.StartColorIB + elseif dbmType == 5 then + r, g, b = barOptions.StartColorRR, barOptions.StartColorRG, barOptions.StartColorRB + elseif dbmType == 6 then + r, g, b = barOptions.StartColorPR, barOptions.StartColorPG, barOptions.StartColorPB + elseif dbmType == 7 then + r, g, b = barOptions.StartColorUIR, barOptions.StartColorUIG, barOptions.StartColorUIB + elseif dbmType == 8 then + r, g, b = barOptions.StartColorI2R, barOptions.StartColorI2G, barOptions.StartColorI2B + else + r, g, b = barOptions.StartColorR, barOptions.StartColorG, barOptions.StartColorB + end + end + bar.dbmColor = {r, g, b} + + WeakAuras.ScanEvents("DBM_TimerStart", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStart", timerId) + end + if self.nextExpire == nil then + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) + self.nextExpire = expirationTime + elseif expirationTime < self.nextExpire then + timer:CancelTimer(self.recheckTimer) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) + self.nextExpire = expirationTime + end + elseif event == "DBM_TimerStop" then + local timerId = ... + self.bars[timerId] = nil + WeakAuras.ScanEvents("DBM_TimerStop", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + end + elseif event == "DBM_TimerPause" then + local timerId = ... + local bar = self.bars[timerId] + if bar then + bar.paused = true + bar.remaining = bar.expirationTime - GetTime() + WeakAuras.ScanEvents("DBM_TimerPause", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerPause", timerId) + end + if self.recheckTimer then + timer:CancelTimer(self.recheckTimer) + end + self:RecheckTimers() + end + elseif event == "DBM_TimerResume" then + local timerId = ... + local bar = self.bars[timerId] + if bar then + bar.paused = nil + bar.expirationTime = GetTime() + (bar.remaining or 0) + bar.remaining = nil + WeakAuras.ScanEvents("DBM_TimerResume", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerResume", timerId) + end + if self.nextExpire == nil then + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.nextExpire = bar.expirationTime + elseif bar.expirationTime < self.nextExpire then + timer:CancelTimer(self.recheckTimer) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.nextExpire = bar.expirationTime + end + end + elseif event == "DBM_TimerUpdate" then + local timerId, elapsed, duration = ... + local now = GetTime() + local expirationTime = now + duration - elapsed + local bar = self.bars[timerId] + if bar then + bar.duration = duration + bar.expirationTime = expirationTime + if self.nextExpire == nil then + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - now, self) + self.nextExpire = expirationTime + elseif self.nextExpire == nil or expirationTime < self.nextExpire then + timer:CancelTimer(self.recheckTimer) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - now, self) + self.nextExpire = expirationTime + end + end + WeakAuras.ScanEvents("DBM_TimerUpdate", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerUpdate", timerId) + end + elseif event == "DBM_SetStage" or event == "DBM_Pull" or event == "DBM_Wipe" or event == "DBM_Kill" then + WeakAuras.ScanEvents("DBM_SetStage") + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_SetStage") + end + end + end, + + RegisterCallback = function(self, event) + if self.registeredEvents[event] then + return + end + if DBM then + DBM:RegisterCallback(event, function(...) self:EventCallback(...) end) + self.registeredEvents[event] = true + end + end, + + RegisterTimer = function(self) + self:RegisterCallback("DBM_TimerStart") + self:RegisterCallback("DBM_TimerStop") + self:RegisterCallback("DBM_TimerPause") + self:RegisterCallback("DBM_TimerResume") + self:RegisterCallback("DBM_TimerUpdate") + end, + + RegisterMessage = function(self) + self:RegisterCallback("DBM_Announce") + end, + + RegisterStage = function(self) + self:RegisterCallback("DBM_SetStage") + self:RegisterCallback("DBM_Pull") + self:RegisterCallback("DBM_Kill") + end, + + scheduled_scans = {}, + + DoScan = function(self, fireTime) + self.scheduled_scans[fireTime] = nil + WeakAuras.ScanEvents("DBM_TimerUpdate") + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerUpdate") + end + end, + + ScheduleCheck = function(self, fireTime) + if not self.scheduled_scans[fireTime] then + self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime() + 0.1, self, fireTime) + end + end +} + +Private.event_prototypes["DBM Stage"] = { + type = "addons", + events = {}, + internal_events = { + "DBM_SetStage" + }, + force_events = "DBM_SetStage", + name = L["DBM Stage"], + init = function(trigger) + Private.ExecEnv.BossMods.DBM:RegisterStage() + return "" + end, + args = { + { + name = "stage", + init = "Private.ExecEnv.BossMods.DBM:GetStage()", + display = L["Journal Stage"], + desc = L["Matches stage number of encounter journal.\nIntermissions are .5\nE.g. 1;2;1;2;2.5;3"], + type = "number", + conditionType = "number", + store = true, + }, + { + name = "stageTotal", + init = "select(2, Private.ExecEnv.BossMods.DBM:GetStage())", + display = L["Stage Counter"], + desc = L["Increases by one per stage or intermission."], + type = "number", + conditionType = "number", + store = true, + }, + }, + automaticrequired = true, + statesParameter = "one", +} +Private.category_event_prototype.addons["DBM Stage"] = L["DBM Stage"] + +Private.event_prototypes["DBM Announce"] = { + type = "addons", + events = {}, + internal_events = { + "DBM_Announce" + }, + name = L["DBM Announce"], + init = function(trigger) + Private.ExecEnv.BossMods.DBM:RegisterMessage(); + local ret = "local use_cloneId = %s;" + return ret:format(trigger.use_cloneId and "true" or "false"); + end, + statesParameter = "all", + args = { + { + name = "spellId", + init = "arg", + display = L["Spell Id"], + type = "string" + }, + { + name = "message", + init = "arg", + display = L["Message"], + type = "longstring", + store = true, + conditionType = "string" + }, + { + name = "name", + init = "message", + hidden = true, + test = "true", + store = true, + }, + { + name = "icon", + init = "arg", + store = true, + hidden = true, + test = "true" + }, + { + name = "cloneId", + display = L["Clone per Event"], + type = "toggle", + test = "true", + init = "use_cloneId and WeakAuras.GetUniqueCloneId() or ''" + }, + }, + timedrequired = true +} +Private.category_event_prototype.addons["DBM Announce"] = L["DBM Announce"] + +Private.event_prototypes["DBM Timer"] = { + type = "addons", + events = {}, + internal_events = { + "DBM_TimerStart", "DBM_TimerStop", "DBM_TimerUpdate", "DBM_TimerForce", "DBM_TimerResume", "DBM_TimerPause" + }, + force_events = "DBM_TimerForce", + name = L["DBM Timer"], + canHaveDuration = "timed", + triggerFunction = function(trigger) + Private.ExecEnv.BossMods.DBM:RegisterTimer() + local ret = [=[ + local triggerCounter = %q + local counter + if triggerCounter and triggerCounter ~= "" then + counter = Private.ExecEnv.CreateTriggerCounter(triggerCounter) + else + counter = Private.ExecEnv.CreateTriggerCounter() + end + return function (states, event, timerId) + local triggerId = %q + local triggerSpellId = %q + local triggerText = %q + local triggerTextOperator = %q + local useClone = %s + local extendTimer = %s + local triggerUseRemaining = %s + local triggerRemaining = %s + local triggerDbmType = %s + local cloneId = useClone and timerId or "" + local state = states[cloneId] + local counter = counter + + function copyOrSchedule(bar, cloneId) + if triggerUseRemaining then + local remainingTime + if bar.paused then + remainingTime = bar.remaining + extendTimer + else + remainingTime = bar.expirationTime - GetTime() + extendTimer + end + if remainingTime %s triggerRemaining then + Private.ExecEnv.BossMods.DBM:CopyBarToState(bar, states, cloneId, extendTimer) + else + local state = states[cloneId] + if state and state.show then + state.show = false + state.changed = true + end + end + if remainingTime >= triggerRemaining and not bar.paused then + Private.ExecEnv.BossMods.DBM:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + end + else + Private.ExecEnv.BossMods.DBM:CopyBarToState(bar, states, cloneId, extendTimer) + end + end + + if useClone then + if event == "DBM_TimerStart" + or event == "DBM_TimerPause" + or event == "DBM_TimerResume" + then + if Private.ExecEnv.BossMods.DBM:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerId, triggerDbmType) then + local bar = Private.ExecEnv.BossMods.DBM:GetTimerById(timerId) + if bar then + copyOrSchedule(bar, cloneId) + return true + end + end + elseif event == "DBM_TimerStop" and state then + local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) + if state.extend == 0 or bar_remainingTime > 0.2 then + state.show = false + state.changed = true + return true + end + elseif event == "DBM_TimerUpdate" then + local changed + for timerId, bar in pairs(Private.ExecEnv.BossMods.DBM:GetAllTimers()) do + if Private.ExecEnv.BossMods.DBM:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerId, triggerDbmType) then + copyOrSchedule(bar, timerId) + changed = true + else + local state = states[timerId] + if state then + local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) + if state.extend == 0 or bar_remainingTime > 0.2 then + state.show = false + state.changed = true + changed = true + end + end + end + end + return changed + elseif event == "DBM_TimerForce" then + local changed + for _, state in pairs(states) do + state.show = false + state.changed = true + changed = true + end + for timerId, bar in pairs(Private.ExecEnv.BossMods.DBM:GetAllTimers()) do + if Private.ExecEnv.BossMods.DBM:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerId, triggerDbmType) then + copyOrSchedule(bar, timerId) + changed = true + end + end + return changed + end + else + if event == "DBM_TimerStart" or event == "DBM_TimerUpdate" then + if extendTimer ~= 0 then + if Private.ExecEnv.BossMods.DBM:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerId, triggerDbmType) then + local bar = Private.ExecEnv.BossMods.DBM:GetTimerById(timerId) + Private.ExecEnv.BossMods.DBM:ScheduleCheck(bar.expirationTime + extendTimer) + end + end + end + local bar = Private.ExecEnv.BossMods.DBM:GetTimer(triggerText, triggerTextOperator, triggerSpellId, extendTimer, counter, triggerId, triggerDbmType) + if bar then + if extendTimer == 0 + or not (state and state.show) + or (state and state.show and state.expirationTime > (bar.expirationTime + extendTimer)) + then + copyOrSchedule(bar, cloneId) + return true + end + else + if state and state.show then + local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) + if state.extend == 0 or bar_remainingTime > 0.2 then + state.show = false + state.changed = true + return true + end + end + end + end + end + ]=] + + return ret:format( + trigger.use_count and trigger.count or "", + trigger.use_id and trigger.id or "", + trigger.use_spellId and trigger.spellId or "", + trigger.use_message and trigger.message or "", + trigger.use_message and trigger.message_operator or "", + trigger.use_cloneId and "true" or "false", + trigger.use_extend and tonumber(trigger.extend or 0) or 0, + trigger.use_remaining and "true" or "false", + trigger.remaining and tonumber(trigger.remaining or 0) or 0, + trigger.use_dbmType and trigger.dbmType or "nil", + trigger.remaining_operator or "<" + ) + end, + statesParameter = "full", + args = { + { + name = "id", + display = L["Timer Id"], + type = "string", + }, + { + name = "spellId", + display = L["Spell Id"], + type = "string", + store = true, + conditionType = "string" + }, + { + name = "message", + display = L["Message"], + type = "longstring", + store = true, + conditionType = "string" + }, + { + name = "remaining", + display = L["Remaining Time"], + type = "number", + }, + { + name = "extend", + display = L["Offset Timer"], + type = "string", + }, + { + name = "count", + display = L["Count"], + desc = L["Occurrence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if DBM shows it on it's bar"], + type = "string", + conditionType = "string", + }, + { + name = "dbmType", + display = L["Type"], + type = "select", + values = "dbm_types", + conditionType = "select", + test = "true" + }, + { + name = "cloneId", + display = L["Clone per Event"], + type = "toggle" + } + }, + automaticrequired = true, +} +Private.category_event_prototype.addons["DBM Timer"] = L["DBM Timer"] + +-- BigWigs +Private.ExecEnv.BossMods.BigWigs = { + registeredEvents = {}, + bars = {}, + nextExpire = nil, + recheckTimer = nil, + currentStage = 0, + + CopyBarToState = function(self, bar, states, timerId, extendTimer) + extendTimer = extendTimer or 0 + if extendTimer + bar.duration < 0 then return end + states[timerId] = states[timerId] or {} + local state = states[timerId] + state.show = true + state.changed = true + state.addon = bar.addon + state.spellId = bar.spellId + state.text = bar.text + state.name = bar.text + state.duration = bar.duration + extendTimer + state.expirationTime = bar.expirationTime + extendTimer + state.bwBarColor = bar.bwBarColor + state.bwTextColor = bar.bwTextColor + state.bwBackgroundColor = bar.bwBackgroundColor + state.count = bar.count + state.cast = bar.cast + state.progressType = "timed" + state.icon = bar.icon + state.extend = extendTimer + if extendTimer ~= 0 then + state.autoHide = true + end + state.paused = bar.paused + state.remaining = bar.remaining + state.isCooldown = bar.isCooldown + end, + + TimerMatches = function(self, timerId, message, operator, spellId, counter, cast, cooldown) + if not self.bars[timerId] then + return false + end + + local v = self.bars[timerId] + if spellId and spellId ~= "" and spellId ~= v.spellId then + return false + end + if message and message ~= "" and operator then + if operator == "==" then + if v.text ~= message then + return false + end + elseif operator == "find('%s')" then + if v.text == nil or not v.text:find(message, 1, true) then + return false + end + elseif operator == "match('%s')" then + if v.text == nil or not v.text:match(message) then + return false + end + end + end + if counter then + counter:SetCount(tonumber(v.count) or 0) + if not counter:Match() then + return false + end + end + if cast ~= nil and v.cast ~= cast then + return false + end + if cooldown ~= nil and v.isCooldown ~= cooldown then + return false + end + return true + end, + + TimerMatchesGeneric = function(self, timerId, message, operator, spellId, counter) + return self:TimerMatches(timerId, message, operator, spellId, counter, false, nil) + end, + + GetStage = function(self) + return self.currentStage + end, + + GetAllTimers = function(self) + return self.bars + end, + + GetTimerById = function(self, timerId) + return self.bars[timerId] + end, + + GetTimer = function(self, text, operator, spellId, extendTimer, counter, cast, cooldown) + local bestMatch + for timerId, bar in pairs(self.bars) do + if self:TimerMatches(timerId, text, operator, spellId, counter, cast, cooldown) + and (bestMatch == nil or bar.expirationTime < bestMatch.expirationTime) + and bar.expirationTime + extendTimer > GetTime() + then + bestMatch = bar + end + end + return bestMatch + end, + + GetTimerGeneric = function(self, text, operator, spellId, extendTimer, counter) + return self:GetTimer(text, operator, spellId, extendTimer, counter, false, nil) + end, + + RecheckTimers = function(self) + local now = GetTime() + self.nextExpire = nil + for timerId, bar in pairs(self.bars) do + if not bar.paused then + if bar.expirationTime < now then + self.bars[timerId] = nil + WeakAuras.ScanEvents("BigWigs_StopBar", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + end + elseif self.nextExpire == nil then + self.nextExpire = bar.expirationTime + elseif bar.expirationTime < self.nextExpire then + self.nextExpire = bar.expirationTime + end + end + end + + if self.nextExpire then + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, self.nextExpire - now, self) + end + end, + + EventCallback = function(self, event, ...) + if event == "BigWigs_Message" then + WeakAuras.ScanEvents("BigWigs_Message", ...) + if self.isGeneric then + local _, spellId, text, _, icon = ... + WeakAuras.ScanEvents("BossMod_Announce", spellId, text, icon) + end + elseif event == "BigWigs_StartBar" then + local addon, spellId, text, duration, icon, isCD = ... + local now = GetTime() + local expirationTime = now + duration + + self.bars[text] = self.bars[text] or {} + local bar = self.bars[text] + bar.addon = addon + bar.spellId = tostring(spellId) + bar.name = text + bar.text = text + bar.duration = duration + bar.expirationTime = expirationTime + bar.icon = icon + bar.isCooldown = isCD or false + local BWColorModule = BigWigs:GetPlugin("Colors") + bar.bwBarColor = BWColorModule:GetColorTable("barColor", addon, spellId) + bar.bwTextColor = BWColorModule:GetColorTable("barText", addon, spellId) + bar.bwBackgroundColor = BWColorModule:GetColorTable("barBackground", addon, spellId) + bar.count = text:match("%((%d+)%)") or text:match("((%d+))") or "0" + bar.cast = not(text:match("^[^<]") and true) + + WeakAuras.ScanEvents("BigWigs_StartBar", text) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStart", text) + end + if self.nextExpire == nil then + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) + self.nextExpire = expirationTime + elseif expirationTime < self.nextExpire then + timer:CancelTimer(self.recheckTimer) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) + self.nextExpire = expirationTime + end + elseif event == "BigWigs_StopBar" then + local addon, text = ... + if self.bars[text] then + self.bars[text] = nil + WeakAuras.ScanEvents("BigWigs_StopBar", text) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStop", text) + end + end + elseif event == "BigWigs_PauseBar" then + local addon, text = ... + local bar = self.bars[text] + if bar and not bar.paused then + bar.paused = true + bar.remaining = bar.expirationTime - GetTime() + WeakAuras.ScanEvents("BigWigs_PauseBar", text) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerPause", text) + end + if self.recheckTimer then + timer:CancelTimer(self.recheckTimer) + end + self:RecheckTimers() + end + elseif event == "BigWigs_ResumeBar" then + local addon, text = ... + local bar = self.bars[text] + if bar and bar.paused then + bar.paused = nil + bar.expirationTime = GetTime() + (bar.remaining or 0) + bar.remaining = nil + WeakAuras.ScanEvents("BigWigs_ResumeBar", text) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerResume", text) + end + if self.nextExpire == nil then + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) + elseif bar.expirationTime < self.nextExpire then + timer:CancelTimer(self.recheckTimer) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.nextExpire = bar.expirationTime + end + end + elseif event == "BigWigs_StopBars" + or event == "BigWigs_OnBossDisable" + or event == "BigWigs_OnPluginDisable" + then + local addon = ... + for timerId, bar in pairs(self.bars) do + if bar.addon == addon then + self.bars[timerId] = nil + WeakAuras.ScanEvents("BigWigs_StopBar", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + end + end + end + elseif event == "BigWigs_SetStage" then + local addon, stage = ... + self.currentStage = stage + WeakAuras.ScanEvents("BigWigs_SetStage") + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_SetStage") + end + elseif event == "BigWigs_OnBossWipe" or event == "BigWigs_OnBossWin" then + self.currentStage = 0 + WeakAuras.ScanEvents("BigWigs_SetStage") + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_SetStage") + end + end + end, + + RegisterCallback = function(self, event) + if self.registeredEvents[event] then + return + end + if BigWigsLoader then + BigWigsLoader.RegisterMessage(WeakAuras, event, function(...) self:EventCallback(...) end) + self.registeredEvents[event] = true + if event == "BigWigs_SetStage" then + -- on init of BigWigs_SetStage callback, we want to fetch currentStage in case we are already in an encounter when this is run + if BigWigs and BigWigs.IterateBossModules then + local stage = 0 + for _, module in BigWigs:IterateBossModules() do + if module:IsEngaged() then + stage = math.max(stage, module:GetStage() or 1) + end + end + self.currentStage = stage + end + end + end + end, + + RegisterTimer = function(self) + self:RegisterCallback("BigWigs_StartBar") + self:RegisterCallback("BigWigs_StopBar") + self:RegisterCallback("BigWigs_StopBars") + self:RegisterCallback("BigWigs_OnBossDisable") + self:RegisterCallback("BigWigs_PauseBar") + self:RegisterCallback("BigWigs_ResumeBar") + end, + + RegisterMessage = function(self) + self:RegisterCallback("BigWigs_Message") + end, + + RegisterStage = function(self) + self:RegisterCallback("BigWigs_SetStage") + self:RegisterCallback("BigWigs_OnBossWipe") + self:RegisterCallback("BigWigs_OnBossWin") + end, + + scheduled_scans = {}, + + DoScan = function(self, fireTime) + self.scheduled_scans[fireTime] = nil + WeakAuras.ScanEvents("BigWigs_Timer_Update") + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerUpdate") + end + end, + + ScheduleCheck = function(self, fireTime) + if not self.scheduled_scans[fireTime] then + self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime() + 0.1, self, fireTime) + end + end +} + +Private.event_prototypes["BigWigs Stage"] = { + type = "addons", + events = {}, + internal_events = { + "BigWigs_SetStage" + }, + name = L["BigWigs Stage"], + init = function(trigger) + Private.ExecEnv.BossMods.BigWigs:RegisterStage() + return "" + end, + args = { + { + name = "stage", + init = "Private.ExecEnv.BossMods.BigWigs:GetStage()", + display = L["Stage"], + type = "number", + conditionType = "number", + store = true, + } + }, + automaticrequired = true, + statesParameter = "one", +} +Private.category_event_prototype.addons["BigWigs Stage"] = L["BigWigs Stage"] + +Private.event_prototypes["BigWigs Message"] = { + type = "addons", + events = {}, + internal_events = { + "BigWigs_Message" + }, + name = L["BigWigs Message"], + init = function(trigger) + Private.ExecEnv.BossMods.BigWigs:RegisterMessage(); + local ret = "local use_cloneId = %s;" + return ret:format(trigger.use_cloneId and "true" or "false"); + end, + statesParameter = "all", + args = { + { + name = "addon", + init = "arg", + display = L["BigWigs Addon"], + type = "string" + }, + { + name = "spellId", + init = "arg", + display = L["Key"], + desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], + type = "longstring" + }, + { + name = "text", + init = "arg", + display = L["Message"], + type = "longstring", + store = true, + conditionType = "string" + }, + { + name = "name", + init = "text", + hidden = true, + test = "true", + store = true + }, + {}, -- Importance, might be useful + { + name = "icon", + init = "arg", + hidden = true, + test = "true", + store = true + }, + { + name = "cloneId", + display = L["Clone per Event"], + type = "toggle", + test = "true", + init = "use_cloneId and WeakAuras.GetUniqueCloneId() or ''" + }, + }, + timedrequired = true +} +Private.category_event_prototype.addons["BigWigs Message"] = L["BigWigs Message"] + +Private.event_prototypes["BigWigs Timer"] = { + type = "addons", + events = {}, + internal_events = { + "BigWigs_StartBar", "BigWigs_StopBar", "BigWigs_Timer_Update", "BigWigs_PauseBar", "BigWigs_ResumeBar" + }, + force_events = "BigWigs_Timer_Force", + name = L["BigWigs Timer"], + canHaveDuration = "timed", + triggerFunction = function(trigger) + Private.ExecEnv.BossMods.BigWigs:RegisterTimer() + local ret = [=[ + local triggerCounter = %q + local counter + if triggerCounter and triggerCounter ~= "" then + counter = Private.ExecEnv.CreateTriggerCounter(triggerCounter) + else + counter = Private.ExecEnv.CreateTriggerCounter() + end + return function(states, event, timerId) + local triggerSpellId = %q + local triggerText = %q + local triggerTextOperator = %q + local useClone = %s + local extendTimer = %s + local triggerUseRemaining = %s + local triggerRemaining = %s + local triggerCast = %s + local triggerIsCooldown = %s + local cloneId = useClone and timerId or "" + local state = states[cloneId] + local counter = counter + + function copyOrSchedule(bar, cloneId) + if triggerUseRemaining then + local remainingTime + if bar.paused then + remainingTime = bar.remaining + extendTimer + else + remainingTime = bar.expirationTime - GetTime() + extendTimer + end + if remainingTime %s triggerRemaining then + Private.ExecEnv.BossMods.BigWigs:CopyBarToState(bar, states, cloneId, extendTimer) + else + local state = states[cloneId] + if state and state.show then + state.show = false + state.changed = true + end + end + if remainingTime >= triggerRemaining and not bar.paused then + Private.ExecEnv.BossMods.BigWigs:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + end + else + Private.ExecEnv.BossMods.BigWigs:CopyBarToState(bar, states, cloneId, extendTimer) + end + end + + if useClone then + if event == "BigWigs_StartBar" + or event == "BigWigs_PauseBar" + or event == "BigWigs_ResumeBar" + then + if Private.ExecEnv.BossMods.BigWigs:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerCast, triggerIsCooldown) then + local bar = Private.ExecEnv.BossMods.BigWigs:GetTimerById(timerId) + if bar then + copyOrSchedule(bar, cloneId) + return true + end + end + elseif event == "BigWigs_StopBar" and state then + local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) + if state.extend == 0 or bar_remainingTime > 0.2 then + state.show = false + state.changed = true + return true + end + elseif event == "BigWigs_Timer_Update" then + local changed + for timerId, bar in pairs(Private.ExecEnv.BossMods.BigWigs:GetAllTimers()) do + if Private.ExecEnv.BossMods.BigWigs:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerCast, triggerIsCooldown) then + copyOrSchedule(bar, timerId) + changed = true + end + end + return changed + elseif event == "BigWigs_Timer_Force" then + local changed + for _, state in pairs(states) do + state.show = false + state.changed = true + changed = true + end + for timerId, bar in pairs(Private.ExecEnv.BossMods.BigWigs:GetAllTimers()) do + if Private.ExecEnv.BossMods.BigWigs:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerCast, triggerIsCooldown) then + copyOrSchedule(bar, timerId) + changed = true + end + end + return changed + end + else + if event == "BigWigs_StartBar" then + if extendTimer ~= 0 then + if Private.ExecEnv.BossMods.BigWigs:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerCast, triggerIsCooldown) then + local bar = Private.ExecEnv.BossMods.BigWigs:GetTimerById(timerId) + Private.ExecEnv.BossMods.BigWigs:ScheduleCheck(bar.expirationTime + extendTimer) + end + end + end + local bar = Private.ExecEnv.BossMods.BigWigs:GetTimer(triggerText, triggerTextOperator, triggerSpellId, extendTimer, counter, triggerCast, triggerIsCooldown) + if bar then + if extendTimer == 0 + or not (state and state.show) + or (state and state.show and state.expirationTime > (bar.expirationTime + extendTimer)) + then + copyOrSchedule(bar, cloneId) + return true + end + else + if state and state.show then + local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) + if state.extend == 0 or bar_remainingTime > 0.2 then + state.show = false + state.changed = true + return true + end + end + end + end + end + ]=] + return ret:format( + trigger.use_count and trigger.count or "", + trigger.use_spellId and trigger.spellId or "", + trigger.use_text and trigger.text or "", + trigger.use_text and trigger.text_operator or "", + trigger.use_cloneId and "true" or "false", + trigger.use_extend and tonumber(trigger.extend or 0) or 0, + trigger.use_remaining and "true" or "false", + trigger.remaining and tonumber(trigger.remaining or 0) or 0, + trigger.use_cast == nil and "nil" or trigger.use_cast and "true" or "false", + trigger.use_isCooldown == nil and "nil" or trigger.use_isCooldown and "true" or "false", + trigger.remaining_operator or "<" + ) + end, + statesParameter = "full", + args = { + { + name = "spellId", + display = L["Key"], + desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], + type = "string", + conditionType = "string", + }, + { + name = "text", + display = L["Message"], + type = "longstring", + store = true, + conditionType = "string" + }, + { + name = "remaining", + display = L["Remaining Time"], + type = "number", + }, + { + name = "extend", + display = L["Offset Timer"], + type = "string", + }, + { + name = "count", + display = L["Count"], + desc = L["Occurrence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if BigWigs shows it on it's bar"], + type = "string", + store = true, + conditionType = "string", + }, + { + name = "cast", + display = L["Cast Bar"], + desc = L["Filter messages with format "], + type = "tristate", + test = "true", + init = "false", + conditionType = "bool" + }, + { + name = "isCooldown", + display = L["Cooldown"], + desc = L["Cooldown bars show time before an ability is ready to be use, BigWigs prefix them with '~'"], + type = "tristate", + test = "true", + init = "false", + conditionType = "bool" + }, + { + name = "cloneId", + display = L["Clone per Event"], + type = "toggle", + test = "true", + init = "false" + }, + }, + automaticrequired = true, +} +Private.category_event_prototype.addons["BigWigs Timer"] = L["BigWigs Timer"] + +-- Unified +if BigWigsLoader or not DBM then + Private.ExecEnv.BossMods.Generic = Private.ExecEnv.BossMods.BigWigs + Private.ExecEnv.BossMods.BigWigs.isGeneric = true + Private.ExecEnv.BossMods.BigWigs.isInstalled = BigWigsLoader ~= nil +elseif DBM then + Private.ExecEnv.BossMods.Generic = Private.ExecEnv.BossMods.DBM + Private.ExecEnv.BossMods.DBM.isGeneric = true + Private.ExecEnv.BossMods.DBM.isInstalled = true +end + +local ActiveBossModText +if Private.ExecEnv.BossMods.BigWigs.isInstalled then + ActiveBossModText = L["Active boss mod addon: |cFFffcc00BigWigs|r\n\nNote: This trigger will use BigWigs or DBM, in that order if both are installed."] +elseif Private.ExecEnv.BossMods.DBM.isInstalled then + ActiveBossModText = L["Active boss mod addon: |cFFffcc00DBM|r\n\nNote: This trigger will use BigWigs or DBM, in that order if both are installed."] +else + ActiveBossModText = L["No active boss mod addon detected.\n\nNote: This trigger will use BigWigs or DBM, in that order if both are installed."] +end + +Private.event_prototypes["Boss Mod Stage"] = { + type = "addons", + events = {}, + internal_events = { + "BossMod_SetStage" + }, + force_events = "BossMod_SetStage", + name = L["Boss Mod Stage"], + init = function(trigger) + Private.ExecEnv.BossMods.Generic:RegisterStage() + return "" + end, + args = { + { + name = "stage", + init = "Private.ExecEnv.BossMods.Generic:GetStage()", + display = L["Stage"], + type = "number", + conditionType = "number", + store = true, + }, + { + name = "note", + type = "description", + display = "", + text = ActiveBossModText + }, + }, + automaticrequired = true, + statesParameter = "one", +} +Private.category_event_prototype.addons["Boss Mod Stage"] = L["Boss Mod Stage"] + +Private.event_prototypes["Boss Mod Stage (Event)"] = { + type = "event", + events = { + ["events"] = { + "BossMod_SetStage", + } + }, + name = L["Boss Mod Stage (Event)"], + init = function(trigger) + Private.ExecEnv.BossMods.Generic:RegisterStage() + return "" + end, + args = { + { + name = "stage", + init = "Private.ExecEnv.BossMods.Generic:GetStage()", + display = L["Stage"], + type = "number", + conditionType = "number", + store = true, + }, + { + name = "note", + type = "description", + display = "", + text = ActiveBossModText + }, + }, + statesParameter = "one", + canHaveDuration = "timed", + delayEvents = true, + timedrequired = true +} +Private.category_event_prototype.addons["Boss Mod Stage (Event)"] = L["Boss Mod Stage (Event)"] + +Private.event_prototypes["Boss Mod Announce"] = { + type = "addons", + events = {}, + internal_events = { + "BossMod_Announce" + }, + name = L["Boss Mod Announce"], + init = function(trigger) + Private.ExecEnv.BossMods.Generic:RegisterMessage(); + local ret = "local use_cloneId = %s;" + return ret:format(trigger.use_cloneId and "true" or "false"); + end, + statesParameter = "all", + args = { + { + name = "spellId", + init = "arg", + display = L["Key"], + type = "string", + store = true, + conditionType = "string" + }, + { + name = "message", + init = "arg", + display = L["Message"], + type = "longstring", + store = true, + conditionType = "string" + }, + { + name = "name", + init = "message", + hidden = true, + test = "true", + store = true, + }, + { + name = "icon", + init = "arg", + store = true, + hidden = true, + test = "true" + }, + { + name = "cloneId", + display = L["Clone per Event"], + type = "toggle", + test = "true", + init = "use_cloneId and WeakAuras.GetUniqueCloneId() or ''" + }, + { + name = "note", + type = "description", + display = "", + text = ActiveBossModText + }, + }, + timedrequired = true +} +Private.category_event_prototype.addons["Boss Mod Announce"] = L["Boss Mod Announce"] + +Private.event_prototypes["Boss Mod Timer"] = { + type = "addons", + events = {}, + internal_events = { + "BossMod_TimerStart", "BossMod_TimerStop", "BossMod_TimerUpdate", "BossMod_TimerForce", "BossMod_TimerResume", "BossMod_TimerPause" + }, + force_events = "BossMod_TimerForce", + name = L["Boss Mod Timer"], + canHaveDuration = "timed", + triggerFunction = function(trigger) + Private.ExecEnv.BossMods.Generic:RegisterTimer() + local ret = [=[ + local triggerCounter = %q + local counter + if triggerCounter and triggerCounter ~= "" then + counter = Private.ExecEnv.CreateTriggerCounter(triggerCounter) + else + counter = Private.ExecEnv.CreateTriggerCounter() + end + local isBW = Private.ExecEnv.BossMods.Generic == Private.ExecEnv.BossMods.BigWigs + local isDBM = Private.ExecEnv.BossMods.Generic == Private.ExecEnv.BossMods.DBM + + return function (states, event, timerId) + local triggerSpellId = %q + local triggerText = %q + local triggerTextOperator = %q + local useClone = %s + local extendTimer = %s + local triggerUseRemaining = %s + local triggerRemaining = %s + local cloneId = useClone and timerId or "" + local state = states[cloneId] + local counter = counter + + function copyOrSchedule(bar, cloneId) + if triggerUseRemaining then + local remainingTime + if bar.paused then + remainingTime = bar.remaining + extendTimer + else + remainingTime = bar.expirationTime - GetTime() + extendTimer + end + if remainingTime %s triggerRemaining then + Private.ExecEnv.BossMods.Generic:CopyBarToState(bar, states, cloneId, extendTimer) + else + local state = states[cloneId] + if state and state.show then + state.show = false + state.changed = true + end + end + if remainingTime >= triggerRemaining and not bar.paused then + Private.ExecEnv.BossMods.Generic:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + end + else + Private.ExecEnv.BossMods.Generic:CopyBarToState(bar, states, cloneId, extendTimer) + end + end + + if useClone then + if event == "BossMod_TimerStart" + or event == "BossMod_TimerPause" + or event == "BossMod_TimerResume" + then + if Private.ExecEnv.BossMods.Generic:TimerMatchesGeneric(timerId, triggerText, triggerTextOperator, triggerSpellId, counter) then + local bar = Private.ExecEnv.BossMods.Generic:GetTimerById(timerId) + if bar then + copyOrSchedule(bar, cloneId) + return true + end + end + elseif event == "BossMod_TimerStop" and state then + local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) + if state.extend == 0 or bar_remainingTime > 0.2 then + state.show = false + state.changed = true + return true + end + elseif event == "BossMod_TimerUpdate" then + local changed + for timerId, bar in pairs(Private.ExecEnv.BossMods.Generic:GetAllTimers()) do + if Private.ExecEnv.BossMods.Generic:TimerMatchesGeneric(timerId, triggerText, triggerTextOperator, triggerSpellId, counter) then + copyOrSchedule(bar, timerId) + changed = true + else + local state = states[timerId] + if state then + local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) + if state.extend == 0 or bar_remainingTime > 0.2 then + state.show = false + state.changed = true + changed = true + end + end + end + end + return changed + elseif event == "BossMod_TimerForce" then + local changed + for _, state in pairs(states) do + state.show = false + state.changed = true + changed = true + end + for timerId, bar in pairs(Private.ExecEnv.BossMods.Generic:GetAllTimers()) do + if Private.ExecEnv.BossMods.Generic:TimerMatchesGeneric(timerId, triggerText, triggerTextOperator, triggerSpellId, counter) then + copyOrSchedule(bar, timerId) + changed = true + end + end + return changed + end + else + if event == "BossMod_TimerStart" or event == "BossMod_TimerUpdate" then + if extendTimer ~= 0 then + if Private.ExecEnv.BossMods.Generic:TimerMatchesGeneric(timerId, triggerText, triggerTextOperator, triggerSpellId, counter) then + local bar = Private.ExecEnv.BossMods.Generic:GetTimerById(timerId) + Private.ExecEnv.BossMods.Generic:ScheduleCheck(bar.expirationTime + extendTimer) + end + end + end + local bar = Private.ExecEnv.BossMods.Generic:GetTimerGeneric(triggerText, triggerTextOperator, triggerSpellId, extendTimer, counter) + if bar then + if extendTimer == 0 + or not (state and state.show) + or (state and state.show and state.expirationTime > (bar.expirationTime + extendTimer)) + then + copyOrSchedule(bar, cloneId) + return true + end + else + if state and state.show then + local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) + if state.extend == 0 or bar_remainingTime > 0.2 then + state.show = false + state.changed = true + return true + end + end + end + end + end + ]=] + + return ret:format( + trigger.use_count and trigger.count or "", + trigger.use_spellId and trigger.spellId or "", + trigger.use_message and trigger.message or "", + trigger.use_message and trigger.message_operator or "", + trigger.use_cloneId and "true" or "false", + trigger.use_extend and tonumber(trigger.extend or 0) or 0, + trigger.use_remaining and "true" or "false", + trigger.remaining and tonumber(trigger.remaining or 0) or 0, + trigger.remaining_operator or "<" + ) + end, + statesParameter = "full", + args = { + { + name = "spellId", + display = L["Key"], + type = "string", + store = true, + conditionType = "string" + }, + { + name = "message", + display = L["Message"], + type = "longstring", + store = true, + conditionType = "string" + }, + { + name = "remaining", + display = L["Remaining Time"], + type = "number", + }, + { + name = "extend", + display = L["Offset Timer"], + type = "string", + }, + { + name = "count", + display = L["Count"], + desc = L["Occurrence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if DBM shows it on it's bar"], + type = "string", + conditionType = "string", + }, + { + name = "cloneId", + display = L["Clone per Event"], + type = "toggle" + }, + { + name = "note", + type = "description", + display = "", + text = ActiveBossModText + }, + }, + automaticrequired = true, +} +Private.category_event_prototype.addons["Boss Mod Timer"] = L["Boss Mod Timer"] + + diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 3c51ebe..2dd8f4b 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -3040,444 +3040,6 @@ function WeakAuras.GetEquipmentSetInfo(itemSetName, partial) return bestMatchName, bestMatchIcon, bestMatchNumEquipped, bestMatchNumItems; end --- DBM -do - local registeredDBMEvents = {} - local bars = {} - local nextExpire -- time of next expiring timer - local recheckTimer -- handle of timer - local currentStage = 0 - - local function dbmRecheckTimers() - local now = GetTime() - nextExpire = nil - for id, bar in pairs(bars) do - if bar.expirationTime < now then - bars[id] = nil - WeakAuras.ScanEvents("DBM_TimerStop", id) - elseif nextExpire == nil then - nextExpire = bar.expirationTime - elseif bar.expirationTime < nextExpire then - nextExpire = bar.expirationTime - end - end - - if nextExpire then - recheckTimer = timer:ScheduleTimer(dbmRecheckTimers, nextExpire - now) - end - end - - local function dbmEventCallback(event, ...) - if event == "DBM_TimerStart" then - local id, msg, duration, icon, timerType, spellId, dbmType, _, _, _, _, _, timerCount = ... - local now = GetTime() - local expirationTime = now + duration - bars[id] = bars[id] or {} - local bar = bars[id] - bar.message = msg - bar.expirationTime = expirationTime - bar.duration = duration - bar.icon = icon - bar.timerType = timerType - bar.spellId = tostring(spellId) - bar.count = timerCount and tostring(timerCount) or "0" - bar.dbmType = dbmType - - local barOptions = DBM.ReleaseRevision >= 20220412000000 and DBT.Options or DBM.Bars.options - local r, g, b = 0, 0, 0 - if dbmType == 1 then - r, g, b = barOptions.StartColorAR, barOptions.StartColorAG, barOptions.StartColorAB - elseif dbmType == 2 then - r, g, b = barOptions.StartColorAER, barOptions.StartColorAEG, barOptions.StartColorAEB - elseif dbmType == 3 then - r, g, b = barOptions.StartColorDR, barOptions.StartColorDG, barOptions.StartColorDB - elseif dbmType == 4 then - r, g, b = barOptions.StartColorIR, barOptions.StartColorIG, barOptions.StartColorIB - elseif dbmType == 5 then - r, g, b = barOptions.StartColorRR, barOptions.StartColorRG, barOptions.StartColorRB - elseif dbmType == 6 then - r, g, b = barOptions.StartColorPR, barOptions.StartColorPG, barOptions.StartColorPB - elseif dbmType == 7 then - r, g, b = barOptions.StartColorUIR, barOptions.StartColorUIG, barOptions.StartColorUIB - else - r, g, b = barOptions.StartColorR, barOptions.StartColorG, barOptions.StartColorB - end - bar.dbmColor = {r, g, b} - - WeakAuras.ScanEvents("DBM_TimerStart", id) - if nextExpire == nil then - recheckTimer = timer:ScheduleTimer(dbmRecheckTimers, expirationTime - now) - nextExpire = expirationTime - elseif expirationTime < nextExpire then - timer:CancelTimer(recheckTimer) - recheckTimer = timer:ScheduleTimer(dbmRecheckTimers, expirationTime - now) - nextExpire = expirationTime - end - elseif event == "DBM_TimerStop" then - local id = ... - bars[id] = nil - WeakAuras.ScanEvents("DBM_TimerStop", id) - elseif event == "kill" or event == "wipe" then -- Wipe or kill, removing all timers - local id = ... - bars = {} - WeakAuras.ScanEvents("DBM_TimerStopAll", id) - elseif event == "DBM_TimerUpdate" then - local id, elapsed, duration = ... - local now = GetTime() - local expirationTime = now + duration - elapsed - local bar = bars[id] - if bar then - bar.duration = duration - bar.expirationTime = expirationTime - if expirationTime < nextExpire then - timer:CancelTimer(recheckTimer) - recheckTimer = timer:ScheduleTimer(dbmRecheckTimers, duration - elapsed) - nextExpire = expirationTime - end - end - WeakAuras.ScanEvents("DBM_TimerUpdate", id) - elseif event == "DBM_SetStage" or event == "DBM_Pull" or event == "DBM_Wipe" or event == "DBM_Kill" then - WeakAuras.ScanEvents("DBM_SetStage") - else -- DBM_Announce - WeakAuras.ScanEvents(event, ...) - end - end - - function Private.ExecEnv.DBMTimerMatches(timerId, id, message, operator, spellId, dbmType, counter) - if not bars[timerId] then - return false - end - - local v = bars[timerId] - if id and id ~= "" and id ~= timerId then - return false - end - if spellId and spellId ~= "" and spellId ~= v.spellId then - return false - end - if message and message ~= "" and operator then - if operator == "==" then - if v.message ~= message then - return false - end - elseif operator == "find('%s')" then - if v.message == nil or not v.message:find(message, 1, true) then - return false - end - elseif operator == "match('%s')" then - if v.message == nil or not v.message:match(message) then - return false - end - end - end - if counter then - counter:SetCount(tonumber(v.count) or 0) - if not counter:Match() then - return false - end - end - if dbmType and dbmType ~= v.dbmType then - return false - end - return true - end - - function WeakAuras.GetDBMStage() - if DBM then - return DBM:GetStage() - end - return 0, 0 - end - - function WeakAuras.GetDBMTimerById(id) - return bars[id] - end - - function WeakAuras.GetAllDBMTimers() - return bars - end - - function WeakAuras.GetDBMTimer(id, message, operator, spellId, extendTimer, dbmType, count) - local bestMatch - for timerId, bar in pairs(bars) do - if Private.ExecEnv.DBMTimerMatches(timerId, id, message, operator, spellId, dbmType, count) - and (bestMatch == nil or bar.expirationTime < bestMatch.expirationTime) - and bar.expirationTime + extendTimer > GetTime() - then - bestMatch = bar - end - end - return bestMatch - end - - function Private.ExecEnv.CopyBarToState(bar, states, id, extendTimer) - extendTimer = extendTimer or 0 - if extendTimer + bar.duration < 0 then return end - states[id] = states[id] or {} - local state = states[id] - state.show = true - state.changed = true - state.icon = bar.icon - state.message = bar.message - state.name = bar.message - state.expirationTime = bar.expirationTime + extendTimer - state.progressType = 'timed' - state.duration = bar.duration + extendTimer - state.timerType = bar.timerType - state.spellId = bar.spellId - state.count = bar.count - state.dbmType = bar.dbmType - state.dbmColor = bar.dbmColor - state.extend = extendTimer - if extendTimer ~= 0 then - state.autoHide = true - end - end - - function WeakAuras.RegisterDBMCallback(event) - if registeredDBMEvents[event] then - return - end - if DBM then - DBM:RegisterCallback(event, dbmEventCallback) - registeredDBMEvents[event] = true - end - end - - function WeakAuras.GetDBMTimers() - return bars - end - - local scheduled_scans = {} - - local function doDbmScan(fireTime) - scheduled_scans[fireTime] = nil - WeakAuras.ScanEvents("DBM_TimerUpdate") - end - function Private.ExecEnv.ScheduleDbmCheck(fireTime) - if not scheduled_scans[fireTime] then - scheduled_scans[fireTime] = timer:ScheduleTimer(doDbmScan, fireTime - GetTime() + 0.1, fireTime) - end - end -end - --- BigWigs -do - local registeredBigWigsEvents = {} - local bars = {} - local nextExpire -- time of next expiring timer - local recheckTimer -- handle of timer - - local function recheckTimers() - local now = GetTime() - nextExpire = nil - for id, bar in pairs(bars) do - if bar.expirationTime < now then - bars[id] = nil - WeakAuras.ScanEvents("BigWigs_StopBar", id) - elseif nextExpire == nil then - nextExpire = bar.expirationTime - elseif bar.expirationTime < nextExpire then - nextExpire = bar.expirationTime - end - end - - if nextExpire then - recheckTimer = timer:ScheduleTimer(recheckTimers, nextExpire - now) - end - end - - local function bigWigsEventCallback(event, ...) - if event == "BigWigs_Message" then - WeakAuras.ScanEvents("BigWigs_Message", ...) - elseif event == "BigWigs_StartBar" then - local addon, spellId, text, duration, icon, isCD = ... - local now = GetTime() - local expirationTime = now + duration - - local newBar - bars[text] = bars[text] or {} - local bar = bars[text] - bar.addon = addon - bar.spellId = tostring(spellId) - bar.text = text - bar.duration = duration - bar.expirationTime = expirationTime - bar.icon = icon - bar.isCooldown = isCD or false - local BWColorModule = BigWigs:GetPlugin("Colors") - bar.bwBarColor = BWColorModule:GetColorTable("barColor", addon, spellId) - bar.bwTextColor = BWColorModule:GetColorTable("barText", addon, spellId) - bar.bwBackgroundColor = BWColorModule:GetColorTable("barBackground", addon, spellId) - local BWEmphasizedModule = BigWigs:GetPlugin("Super Emphasize") - bar.emphasized = BWEmphasizedModule:IsSuperEmphasized(addon, spellId) and true or false - bar.count = text:match("%((%d+)%)") or text:match("((%d+))") or "0" - bar.cast = not(text:match("^[^<]") and true) - - WeakAuras.ScanEvents("BigWigs_StartBar", text) - if nextExpire == nil then - recheckTimer = timer:ScheduleTimer(recheckTimers, expirationTime - now) - nextExpire = expirationTime - elseif expirationTime < nextExpire then - timer:CancelTimer(recheckTimer) - recheckTimer = timer:ScheduleTimer(recheckTimers, expirationTime - now) - nextExpire = expirationTime - end - elseif event == "BigWigs_StopBar" then - local addon, text = ... - if bars[text] then - bars[text] = nil - WeakAuras.ScanEvents("BigWigs_StopBar", text) - end - elseif event == "BigWigs_StopBars" - or event == "BigWigs_OnBossDisable" - or event == "BigWigs_OnPluginDisable" - then - local addon = ... - for id, bar in pairs(bars) do - if bar.addon == addon then - bars[id] = nil - WeakAuras.ScanEvents("BigWigs_StopBar", id) - end - end - end - end - - function WeakAuras.RegisterBigWigsCallback(event) - if registeredBigWigsEvents[event] then - return - end - if BigWigsLoader then - BigWigsLoader.RegisterMessage(WeakAuras, event, bigWigsEventCallback) - registeredBigWigsEvents[event] = true - if event == "BigWigs_SetStage" then - -- on init of BigWigs_SetStage callback, we want to fetch currentStage in case we are already in an encounter when this is run - if BigWigs and BigWigs.IterateBossModules then - local stage = 0 - for _, module in BigWigs:IterateBossModules() do - if module:IsEngaged() then - stage = math.max(stage, module:GetStage() or 1) - end - end - currentStage = stage - end - end - end - end - - function WeakAuras.RegisterBigWigsTimer() - WeakAuras.RegisterBigWigsCallback("BigWigs_StartBar") - WeakAuras.RegisterBigWigsCallback("BigWigs_StopBar") - WeakAuras.RegisterBigWigsCallback("BigWigs_StopBars") - WeakAuras.RegisterBigWigsCallback("BigWigs_OnBossDisable") - end - - function Private.ExecEnv.CopyBigWigsTimerToState(bar, states, id, extendTimer) - extendTimer = extendTimer or 0 - if extendTimer + bar.duration < 0 then return end - states[id] = states[id] or {} - local state = states[id] - state.show = true - state.changed = true - state.addon = bar.addon - state.spellId = bar.spellId - state.text = bar.text - state.name = bar.text - state.duration = bar.duration + extendTimer - state.expirationTime = bar.expirationTime + extendTimer - state.bwBarColor = bar.bwBarColor - state.bwTextColor = bar.bwTextColor - state.bwBackgroundColor = bar.bwBackgroundColor - state.emphasized = bar.emphasized - state.count = bar.count - state.cast = bar.cast - state.progressType = "timed" - state.icon = bar.icon - state.extend = extendTimer - if extendTimer ~= 0 then - state.autoHide = true - end - state.isCooldown = bar.isCooldown - end - - function Private.ExecEnv.BigWigsTimerMatches(id, message, operator, spellId, emphasized, counter, cast, cooldown) - if not bars[id] then - return false - end - - local v = bars[id] - local bestMatch - if spellId and spellId ~= "" and spellId ~= v.spellId then - return false - end - if message and message ~= "" and operator then - if operator == "==" then - if v.text ~= message then - return false - end - elseif operator == "find('%s')" then - if v.text == nil or not v.text:find(message, 1, true) then - return false - end - elseif operator == "match('%s')" then - if v.text == nil or not v.text:match(message) then - return false - end - end - end - if emphasized ~= nil and v.emphasized ~= emphasized then - return false - end - if counter then - counter:SetCount(tonumber(v.count) or 0) - if not counter:Match() then - return false - end - end - if cast ~= nil and v.cast ~= cast then - return false - end - if cooldown ~= nil and v.isCooldown ~= cooldown then - return false - end - return true - end - - function WeakAuras.GetAllBigWigsTimers() - return bars - end - - function WeakAuras.GetBigWigsTimerById(id) - return bars[id] - end - - function WeakAuras.GetBigWigsTimer(text, operator, spellId, extendTimer, emphasized, counter, cast) - local bestMatch - for id, bar in pairs(bars) do - if Private.ExecEnv.BigWigsTimerMatches(id, text, operator, spellId, emphasized, counter, cast) - and (bestMatch == nil or bar.expirationTime < bestMatch.expirationTime) - and bar.expirationTime + extendTimer > GetTime() - then - bestMatch = bar - end - end - return bestMatch - end - - local scheduled_scans = {} - - local function doBigWigsScan(fireTime) - scheduled_scans[fireTime] = nil - WeakAuras.ScanEvents("BigWigs_Timer_Update") - end - - function Private.ExecEnv.ScheduleBigWigsCheck(fireTime) - if not scheduled_scans[fireTime] then - scheduled_scans[fireTime] = timer:ScheduleTimer(doBigWigsScan, fireTime - GetTime() + 0.1, fireTime) - end - end -end - function Private.ExecEnv.CheckTotemName(totemName, triggerTotemName, triggerTotemPattern, triggerTotemOperator) if not totemName or totemName == "" then return false diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 119cf9d..9e2042f 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3861,532 +3861,6 @@ Private.event_prototypes = { }, timedrequired = true }, - -- DBM events - ["DBM Stage"] = { - type = "addons", - events = {}, - internal_events = { - "DBM_SetStage" - }, - force_events = "DBM_SetStage", - name = L["DBM Stage"], - init = function(trigger) - WeakAuras.RegisterDBMCallback("DBM_SetStage") - WeakAuras.RegisterDBMCallback("DBM_Pull") - WeakAuras.RegisterDBMCallback("DBM_Kill") - return "" - end, - args = { - { - name = "stage", - init = "WeakAuras.GetDBMStage()", - display = L["Stage"], - type = "number", - conditionType = "number", - store = true, - } - }, - automaticrequired = true, - statesParameter = "one", - }, - ["DBM Announce"] = { - type = "addons", - events = {}, - internal_events = { - "DBM_Announce" - }, - name = L["DBM Announce"], - init = function(trigger) - WeakAuras.RegisterDBMCallback("DBM_Announce"); - local ret = "local use_cloneId = %s;" - return ret:format(trigger.use_cloneId and "true" or "false"); - end, - statesParameter = "all", - args = { - { - name = "message", - init = "arg", - display = L["Message"], - type = "longstring", - store = true, - conditionType = "string" - }, - { - name = "name", - init = "message", - hidden = true, - test = "true", - store = true, - }, - { - name = "icon", - init = "arg", - store = true, - hidden = true, - test = "true" - }, - { - name = "cloneId", - display = L["Clone per Event"], - type = "toggle", - test = "true", - init = "use_cloneId and WeakAuras.GetUniqueCloneId() or ''" - }, - }, - timedrequired = true - }, - ["DBM Timer"] = { - type = "addons", - events = {}, - internal_events = { - "DBM_TimerStart", "DBM_TimerStop", "DBM_TimerStopAll", "DBM_TimerUpdate", "DBM_TimerForce" - }, - force_events = "DBM_TimerForce", - name = L["DBM Timer"], - canHaveDuration = "timed", - triggerFunction = function(trigger) - WeakAuras.RegisterDBMCallback("DBM_TimerStart") - WeakAuras.RegisterDBMCallback("DBM_TimerStop") - WeakAuras.RegisterDBMCallback("DBM_TimerUpdate") - WeakAuras.RegisterDBMCallback("wipe") - WeakAuras.RegisterDBMCallback("kill") - - local ret = [=[ - local triggerCounter = %q - local counter - if triggerCounter and triggerCounter ~= "" then - counter = Private.ExecEnv.CreateTriggerCounter(triggerCounter) - else - counter = Private.ExecEnv.CreateTriggerCounter() - end - return function (states, event, id) - local triggerId = %q - local triggerSpellId = %q - local triggerText = %q - local triggerTextOperator = %q - local useClone = %s - local extendTimer = %s - local triggerUseRemaining = %s - local triggerRemaining = %s - local triggerDbmType = %s - local cloneId = useClone and id or "" - local state = states[cloneId] - local counter = counter - - function copyOrSchedule(bar, cloneId) - if triggerUseRemaining then - local remainingTime = bar.expirationTime - GetTime() + extendTimer - if remainingTime %s triggerRemaining then - Private.ExecEnv.CopyBarToState(bar, states, cloneId, extendTimer) - else - local state = states[cloneId] - if state and state.show then - state.show = false - state.changed = true - end - end - if remainingTime >= triggerRemaining then - Private.ExecEnv.ScheduleDbmCheck(bar.expirationTime - triggerRemaining + extendTimer) - end - else - Private.ExecEnv.CopyBarToState(bar, states, cloneId, extendTimer) - end - end - - if useClone then - if event == "DBM_TimerStart" then - if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, counter) then - local bar = WeakAuras.GetDBMTimerById(id) - if bar then - copyOrSchedule(bar, cloneId) - end - end - elseif event == "DBM_TimerStop" and state then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then - state.show = false - state.changed = true - end - elseif event == "DBM_TimerUpdate" then - for id, bar in pairs(WeakAuras.GetAllDBMTimers()) do - if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, counter) then - copyOrSchedule(bar, id) - else - local state = states[id] - if state then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then - state.show = false - state.changed = true - end - end - end - end - elseif event == "DBM_TimerForce" then - wipe(states) - for id, bar in pairs(WeakAuras.GetAllDBMTimers()) do - if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, counter) then - copyOrSchedule(bar, cloneId) - end - end - end - else - if event == "DBM_TimerStart" or event == "DBM_TimerUpdate" then - if extendTimer ~= 0 then - if Private.ExecEnv.DBMTimerMatches(id, triggerId, triggerText, triggerTextOperator, triggerSpellId, triggerDbmType, counter) then - local bar = WeakAuras.GetDBMTimerById(id) - Private.ExecEnv.ScheduleDbmCheck(bar.expirationTime + extendTimer) - end - end - end - local bar = WeakAuras.GetDBMTimer(triggerId, triggerText, triggerTextOperator, triggerSpellId, extendTimer, triggerDbmType, counter) - if bar then - if extendTimer == 0 - or not (state and state.show) - or (state and state.show and state.expirationTime > (bar.expirationTime + extendTimer)) - then - copyOrSchedule(bar, cloneId) - end - else - if state and state.show then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then - state.show = false - state.changed = true - end - end - end - end - return true - end - ]=] - - return ret:format( - trigger.use_count and trigger.count or "", - trigger.use_id and trigger.id or "", - trigger.use_spellId and tostring(trigger.spellId) or "", - trigger.use_message and trigger.message or "", - trigger.use_message and trigger.message_operator or "", - trigger.use_cloneId and "true" or "false", - trigger.use_extend and tonumber(trigger.extend or 0) or 0, - trigger.use_remaining and "true" or "false", - trigger.remaining and tonumber(trigger.remaining or 0) or 0, - trigger.use_dbmType and trigger.dbmType or "nil", - trigger.remaining_operator or "<" - ) - end, - statesParameter = "full", - args = { - { - name = "id", - display = L["Timer Id"], - type = "string", - }, - { - name = "spellId", - display = L["Spell Id"], - type = "string", - store = true, - conditionType = "string" - }, - { - name = "message", - display = L["Message"], - type = "longstring", - store = true, - conditionType = "string" - }, - { - name = "remaining", - display = L["Remaining Time"], - type = "number", - }, - { - name = "extend", - display = L["Offset Timer"], - type = "string", - }, - { - name = "count", - display = L["Count"], - desc = L["Occurrence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if DBM shows it on it's bar"], - type = "string", - conditionType = "string", - }, - { - name = "dbmType", - display = L["Type"], - type = "select", - values = "dbm_types", - conditionType = "select", - test = "true" - }, - { - name = "cloneId", - display = L["Clone per Event"], - type = "toggle" - } - }, - automaticrequired = true, - }, - -- BigWigs - ["BigWigs Message"] = { - type = "addons", - events = {}, - internal_events = { - "BigWigs_Message" - }, - name = L["BigWigs Message"], - init = function(trigger) - WeakAuras.RegisterBigWigsCallback("BigWigs_Message"); - local ret = "local use_cloneId = %s;" - return ret:format(trigger.use_cloneId and "true" or "false"); - end, - statesParameter = "all", - args = { - { - name = "addon", - init = "arg", - display = L["BigWigs Addon"], - type = "string" - }, - { - name = "spellId", - init = "arg", - display = L["Key"], - desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], - type = "longstring" - }, - { - name = "text", - init = "arg", - display = L["Message"], - type = "longstring", - store = true, - conditionType = "string" - }, - { - name = "name", - init = "text", - hidden = true, - test = "true", - store = true - }, - {}, -- Importance, might be useful - { - name = "icon", - init = "arg", - hidden = true, - test = "true", - store = true - }, - { - name = "cloneId", - display = L["Clone per Event"], - type = "toggle", - test = "true", - init = "use_cloneId and WeakAuras.GetUniqueCloneId() or ''" - }, - }, - timedrequired = true - }, - ["BigWigs Timer"] = { - type = "addons", - events = {}, - internal_events = { - "BigWigs_StartBar", "BigWigs_StopBar", "BigWigs_Timer_Update", - }, - force_events = "BigWigs_Timer_Force", - name = L["BigWigs Timer"], - canHaveDuration = "timed", - triggerFunction = function(trigger) - WeakAuras.RegisterBigWigsTimer() - local ret = [=[ - local triggerCounter = %q - local counter - if triggerCounter and triggerCounter ~= "" then - counter = Private.ExecEnv.CreateTriggerCounter(triggerCounter) - else - counter = Private.ExecEnv.CreateTriggerCounter() - end - return function(states, event, id) - local triggerSpellId = %q - local triggerText = %q - local triggerTextOperator = %q - local useClone = %s - local extendTimer = %s - local triggerUseRemaining = %s - local triggerRemaining = %s - local triggerEmphasized = %s - local triggerCast = %s - local triggerIsCooldown = %s - local cloneId = useClone and id or "" - local state = states[cloneId] - local counter = counter - - function copyOrSchedule(bar, cloneId) - if triggerUseRemaining then - local remainingTime = bar.expirationTime - GetTime() + extendTimer - if remainingTime %s triggerRemaining then - Private.ExecEnv.CopyBigWigsTimerToState(bar, states, cloneId, extendTimer) - else - local state = states[cloneId] - if state and state.show then - state.show = false - state.changed = true - end - end - if remainingTime >= triggerRemaining then - Private.ExecEnv.ScheduleBigWigsCheck(bar.expirationTime - triggerRemaining + extendTimer) - end - else - Private.ExecEnv.CopyBigWigsTimerToState(bar, states, cloneId, extendTimer) - end - end - - if useClone then - if event == "BigWigs_StartBar" then - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, counter, triggerCast, triggerIsCooldown) then - local bar = WeakAuras.GetBigWigsTimerById(id) - if bar then - copyOrSchedule(bar, cloneId) - end - end - elseif event == "BigWigs_StopBar" and state then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then - state.show = false - state.changed = true - end - elseif event == "BigWigs_Timer_Update" then - for id, bar in pairs(WeakAuras.GetAllBigWigsTimers()) do - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, counter, triggerCast) then - copyOrSchedule(bar, id) - end - end - elseif event == "BigWigs_Timer_Force" then - wipe(states) - for id, bar in pairs(WeakAuras.GetAllBigWigsTimers()) do - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, counter, triggerCast) then - copyOrSchedule(bar, id) - end - end - end - else - if event == "BigWigs_StartBar" then - if extendTimer ~= 0 then - if Private.ExecEnv.BigWigsTimerMatches(id, triggerText, triggerTextOperator, triggerSpellId, triggerEmphasized, counter, triggerCast) then - local bar = WeakAuras.GetBigWigsTimerById(id) - Private.ExecEnv.ScheduleBigWigsCheck(bar.expirationTime + extendTimer) - end - end - end - local bar = WeakAuras.GetBigWigsTimer(triggerText, triggerTextOperator, triggerSpellId, extendTimer, triggerEmphasized, counter, triggerCast) - if bar then - if extendTimer == 0 - or not (state and state.show) - or (state and state.show and state.expirationTime > (bar.expirationTime + extendTimer)) - then - copyOrSchedule(bar, cloneId) - end - else - if state and state.show then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then - state.show = false - state.changed = true - end - end - end - end - return true - end - ]=] - return ret:format( - trigger.use_count and trigger.count or "", - trigger.use_spellId and tostring(trigger.spellId) or "", - trigger.use_text and trigger.text or "", - trigger.use_text and trigger.text_operator or "", - trigger.use_cloneId and "true" or "false", - trigger.use_extend and tonumber(trigger.extend or 0) or 0, - trigger.use_remaining and "true" or "false", - trigger.remaining and tonumber(trigger.remaining or 0) or 0, - trigger.use_emphasized == nil and "nil" or trigger.use_emphasized and "true" or "false", - trigger.use_cast == nil and "nil" or trigger.use_cast and "true" or "false", - trigger.use_isCooldown == nil and "nil" or trigger.use_isCooldown and "true" or "false", - trigger.remaining_operator or "<" - ) - end, - statesParameter = "full", - args = { - { - name = "spellId", - display = L["Key"], - desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], - type = "string", - conditionType = "string", - }, - { - name = "text", - display = L["Message"], - type = "longstring", - store = true, - conditionType = "string" - }, - { - name = "remaining", - display = L["Remaining Time"], - type = "number", - }, - { - name = "extend", - display = L["Offset Timer"], - type = "string", - }, - { - name = "count", - display = L["Count"], - desc = L["Occurrence of the event, reset when aura is unloaded\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nOnly if BigWigs shows it on it's bar"], - type = "string", - conditionType = "string", - }, - { - name = "emphasized", - display = L["Emphasized"], - type = "tristate", - desc = L["Emphasized option checked in BigWigs's spell options"], - test = "true", - init = "false", - conditionType = "bool" - }, - { - name = "cast", - display = L["Cast Bar"], - desc = L["Filter messages with format "], - type = "tristate", - test = "true", - init = "false", - conditionType = "bool" - }, - { - name = "isCooldown", - display = L["Cooldown"], - desc = L["Cooldown bars show time before an ability is ready to be use, BigWigs prefix them with '~'"], - type = "tristate", - test = "true", - init = "false", - conditionType = "bool" - }, - { - name = "cloneId", - display = L["Clone per Event"], - type = "toggle", - test = "true", - init = "false" - }, - }, - automaticrequired = true, - }, ["Global Cooldown"] = { type = "spell", events = {}, diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index 05dd046..eb42527 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -15,7 +15,7 @@ ## DefaultState: Enabled ## LoadOnDemand: 0 ## SavedVariables: WeakAurasSaved -## OptionalDeps: Ace3, LibCompress, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, Masque, GTFO, LibButtonGlow-1.0, LibSpellRange-1.0, LibRangeCheck-2.0, LibDBIcon-1.0, LibClassicDurations, LibClassicCasterino, LibGetFrame-1.0 +## OptionalDeps: Ace3, LibCompress, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, Masque, GTFO, LibButtonGlow-1.0, LibSpellRange-1.0, LibRangeCheck-2.0, LibDBIcon-1.0, LibClassicDurations, LibClassicCasterino, LibGetFrame-1.0, !!AddonLocale, DBM-Core, BigWigs Templates.lua Templates.xml @@ -44,6 +44,7 @@ AnchorToWeakAuras.lua # Trigger systems BuffTrigger2.lua GenericTrigger.lua +BossMods.lua # Helper Systems AuraWarnings.lua From b0854d38e048dcefec62ea45e8634c4d5c18eeea Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 17:36:46 +0100 Subject: [PATCH 046/153] from retail --- WeakAuras/BossMods.lua | 31 +++++++++++++++++++++--------- WeakAuras/GenericTrigger.lua | 8 ++++++++ WeakAuras/Prototypes.lua | 28 ++++++++++++++++++++------- WeakAurasOptions/BuffTrigger2.lua | 1 + WeakAurasOptions/CommonOptions.lua | 6 ++++++ 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/WeakAuras/BossMods.lua b/WeakAuras/BossMods.lua index b5cc4c1..7502571 100644 --- a/WeakAuras/BossMods.lua +++ b/WeakAuras/BossMods.lua @@ -381,7 +381,9 @@ Private.event_prototypes["DBM Announce"] = { name = "spellId", init = "arg", display = L["Spell Id"], - type = "string" + type = "spell", + noValidation = true, + showExactOption = false, }, { name = "message", @@ -584,9 +586,11 @@ Private.event_prototypes["DBM Timer"] = { { name = "spellId", display = L["Spell Id"], - type = "string", store = true, - conditionType = "string" + type = "spell", + conditionType = "string", + noValidation = true, + showExactOption = false, }, { name = "message", @@ -986,7 +990,10 @@ Private.event_prototypes["BigWigs Message"] = { init = "arg", display = L["Key"], desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], - type = "longstring" + type = "spell", + conditionType = "string", + noValidation = true, + showExactOption = false, }, { name = "text", @@ -1175,8 +1182,10 @@ Private.event_prototypes["BigWigs Timer"] = { name = "spellId", display = L["Key"], desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], - type = "string", + type = "spell", conditionType = "string", + noValidation = true, + showExactOption = false, }, { name = "text", @@ -1339,9 +1348,11 @@ Private.event_prototypes["Boss Mod Announce"] = { name = "spellId", init = "arg", display = L["Key"], - type = "string", store = true, - conditionType = "string" + type = "spell", + conditionType = "string", + noValidation = true, + showExactOption = false, }, { name = "message", @@ -1544,9 +1555,11 @@ Private.event_prototypes["Boss Mod Timer"] = { { name = "spellId", display = L["Key"], - type = "string", store = true, - conditionType = "string" + type = "spell", + conditionType = "string", + noValidation = true, + showExactOption = false, }, { name = "message", diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 2dd8f4b..7292a41 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -3786,6 +3786,13 @@ local commonConditions = { display = L["Total Duration"], type = "number", }, + paused = { + display = L["Is Paused"], + type = "bool", + test = function(state, needle) + return (state.paused and 1 or 0) == needle + end + }, value = { display = L["Progress Value"], type = "number", @@ -3844,6 +3851,7 @@ function GenericTrigger.GetTriggerConditions(data, triggernum) if (timedDuration) then result.expirationTime = commonConditions.expirationTime; result.duration = commonConditions.duration; + result.paused = commonConditions.paused end if (valueDuration) then diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 9e2042f..6ec6f07 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -582,6 +582,27 @@ function WeakAuras.CheckNumericIds(loadids, currentId) return false; end +function WeakAuras.ValidateNumeric(info, val) + if val ~= nil and val ~= "" and (not tonumber(val) or tonumber(val) >= 2^31) then + return false; + end + return true +end + +function WeakAuras.ValidateTime(info, val) + if val ~= nil and val ~= "" then + if not tonumber(val) then + if val:sub(1,1) == "-" then + val = val:sub(2, #val) + end + return (val:match("^%d+:%d+:[%d%.]+$") or val:match("^%d+:[%d+%.]+$")) and true or false + elseif tonumber(val) >= 2^31 then + return false + end + end + return true +end + function WeakAuras.TimeToSeconds(val) if tonumber(val) then return tonumber(val) @@ -626,13 +647,6 @@ Private.tinySecondFormat = function(value) end end -function WeakAuras.ValidateNumeric(info, val) - if val ~= nil and val ~= "" and (not tonumber(val) or tonumber(val) >= 2^31) then - return false; - end - return true -end - function WeakAuras.ValidateNumericOrPercent(info, val) if val ~= nil and val ~= "" then local percent = string.match(val, "(%d+)%%") diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index 821c299..07d7c83 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -205,6 +205,7 @@ local function CreateNameOptions(aura_options, data, trigger, size, isExactSpell end, validate = isExactSpellId and WeakAuras.ValidateNumeric or nil, control = "WeakAurasInputFocus", + getWithFocus = function() return trigger[optionKey] and trigger[optionKey][i] or "" end } end -- VALIDATE ? diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index 735b7b5..2799cd5 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -721,6 +721,12 @@ local function replaceNameDescFuncs(intable, data, subOption) if(type(display) == "number") then display = math.floor(display * 100) / 100; else + local nullBytePos = display:find("\0", nil, true) + + if nullBytePos then + display = display:sub(1, nullBytePos - 1) + end + if #display > 50 then display = display:sub(1, 50) .. "..." end From fcd2d11478997b753da98a136363220c443b936b Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 19:46:24 +0100 Subject: [PATCH 047/153] from retail --- WeakAuras/Media/Textures/VoiceChat-On.blp | Bin 0 -> 2564 bytes .../Media/Textures/VoiceChat-Speaker.blp | Bin 0 -> 2564 bytes WeakAuras/Types.lua | 4 + .../AceGUIWidget-WeakAurasMediaSound.lua | 98 ++++++++++++++++++ WeakAurasOptions/ActionOptions.lua | 2 + WeakAurasOptions/AuthorOptions.lua | 2 + WeakAurasOptions/ConditionOptions.lua | 1 + WeakAurasOptions/WeakAurasOptions.toc | 1 + 8 files changed, 108 insertions(+) create mode 100644 WeakAuras/Media/Textures/VoiceChat-On.blp create mode 100644 WeakAuras/Media/Textures/VoiceChat-Speaker.blp create mode 100644 WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasMediaSound.lua diff --git a/WeakAuras/Media/Textures/VoiceChat-On.blp b/WeakAuras/Media/Textures/VoiceChat-On.blp new file mode 100644 index 0000000000000000000000000000000000000000..8ed7c225e1d6f02c7e2e61f1c4dd2c137cfc1dd4 GIT binary patch literal 2564 zcmZ?r2{2-0U|?Y4U}sbS(jYvA1&BF-n3I9w3J^a5;x9l6Q+~1 z|1$pIoAMoKe_^BQE5RoTL6tY>q(4(&U=dL;d&o%)u&-b=$AP)GMETG8-uWHRHjyeCutQ(k}lL7^G%JMTx&v7hsY# zXngXPfgvI;bgJb$n>zcZ}@CznN{@moeg@Hk}u`=`-*CS{3+Ajjh zKz>-LsOno*X8x}WHrqXU%D@m55f)CY{pjv<%3@$(y^6>$3yVPZ2ZlapUO&IxbHbiS zi$Up6H1w6MB-=!7Un>y5u^=RrwO!KZW)tsibn~di=Wp7U<-9EyZhis7gU9N?@FCTF z-WH(yLqkO^{eXsTOSCQrrRPxbE6RI-{0(z&8lD63Ljqvo#|M^YVutZ^|2rB2bIYou zOeg1xbc&zK2Btq3l`9Sxn5QHw?dmFcepP|P(OpFarvC96V7q8FB0QV-BnU8Yt=xKo zNm1@{=fsl7M-(_5rY$SGD(TTafu}|f6rUAJ|WMB{ldO$VWEW>(R>TOW` zOc4(aUC!j7tmZdK`VE_OC literal 0 HcmV?d00001 diff --git a/WeakAuras/Media/Textures/VoiceChat-Speaker.blp b/WeakAuras/Media/Textures/VoiceChat-Speaker.blp new file mode 100644 index 0000000000000000000000000000000000000000..f2e3cb71fdf57bd3f76e6a9d6e4487149454d645 GIT binary patch literal 2564 zcmeHJZAep57=G`jbtjnv8A&oc)K(z$qmUpd=T{%2f~6i^_JOlNNC#iWlp-UDO$W;gT?R!;^x;R>o!%pyTlu4pfBo>`zMS*$-uLso=WoRhNC>`A z#Ny^Z=7obEXTallJI{E&K66N8EjA}TW}b8j{omG0 zWZ(_tJ$3K`6Jf01VK|7-srfcrQ zXT>Csuh$Fz?=YVxYPSpSM*U%%Ekp2#83K-E>;6NzbI;hfI@b0kS1-BUYW!nk;}zV$ zh&M6(uuSf}>l1wa)8JLqe-ZK1LIl=c$;lD^gC79wM`@Gbrl$ZI>9)gyhYbQ)t;r6< z{U==;>W>H1^XO$Qrof8D*Z4dtG7z|?&$v;BGivrx_LX->4->8BL=)fcwuCIo03JbJ z&9D7W?FKNrO4ai}hCGWJ)bj|w0Z6xJWs7{&_PG z^!?oZ=!y-g{_|E95k^XcXcUv zKZd8)$&uK{xRA@}uRibBy#zR&;7t?u`DkCXyRF;!V&N6rs{ySK|BKowWk=9RQ!iEa z=EgvTyC*J$#??l@whbW7n@}R`Q#**<9o$(exTycLG*{n@B{-4+3|K%6a~<(lI0M&l ze!QbUzHjR)aXzyt-T2AljP*Qcop?W}Asp(!+HcxZVXB=>lIdwBGzS`6g!QsX+ktuY zP#Rr(+ZebV8OW<4a))x3ev%$%Y^%IvSv5lR$$jt76vRBKDhzm>!&CjmayY<_M6^Q; KwN= Version then + return +end +local L = WeakAuras.L +local media = LibStub("LibSharedMedia-3.0") +local prototype = LibStub("AceGUI-3.0-DropDown-ItemBase"):GetItemBase() + +local ignore = { + [" " ..L["Custom"]] = true, + [" " ..L["Sound by Kit ID"]] = true, + [L["None"]] = true +} + +local function updateToggle(self) + if self.value then + self.check:Show() + else + self.check:Hide() + end +end + +local function updateSndButton(self) + local text = self.obj.text:GetText() + if text == nil or ignore[text] then + self.sndButton:Hide() + else + self.sndButton:Show() + end +end + +local function onRelease(self) + prototype.OnRelease(self) + self:SetValue(nil) +end + +local function onClick(frame) + local self = frame.obj + if self.disabled then return end + self.value = not self.value + if self.value then + PlaySound(856) -- SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON + else + PlaySound(857) -- SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF + end + updateToggle(self) + self:Fire("OnValueChanged", self.value) +end + +local function setValue(self, value) + self.value = value + updateToggle(self) +end + +local function getValue(self) + return self.value +end + +local function soundOnClick(self) + local snd = media:Fetch("sound", self.sound:GetText()) + if snd then PlaySoundFile(snd, "Master") end +end + +local function constructor() + local self = prototype.Create(Type) + self.frame:SetScript("OnShow", updateSndButton) + self.frame:SetScript("OnClick", onClick) + self.SetValue = setValue + self.GetValue = getValue + self.OnRelease = onRelease + local frame = self.frame + + local sndButton = CreateFrame("Button", nil, frame) + sndButton:SetWidth(16) + sndButton:SetHeight(16) + sndButton:SetPoint("RIGHT", frame, "RIGHT", -3, -1) + sndButton:SetScript("OnClick", soundOnClick) + sndButton.sound = frame.obj.text + frame.sndButton = sndButton + + local icon = sndButton:CreateTexture(nil, "BACKGROUND") + icon:SetTexture("Interface\\AddOns\\WeakAuras\\Media\\Textures\\VoiceChat-Speaker") --"Interface\\Common\\VoiceChat-Speaker" + icon:SetAllPoints(sndButton) + + local highlight = sndButton:CreateTexture(nil, "HIGHLIGHT") + highlight:SetTexture("Interface\\AddOns\\WeakAuras\\Media\\Textures\\VoiceChat-On") --"Interface\\Common\\VoiceChat-On" + highlight:SetAllPoints(sndButton) + + AceGUI:RegisterAsWidget(self) + return self +end +AceGUI:RegisterWidgetType(Type, constructor, Version) diff --git a/WeakAurasOptions/ActionOptions.lua b/WeakAurasOptions/ActionOptions.lua index 6d300ba..eb9082c 100644 --- a/WeakAurasOptions/ActionOptions.lua +++ b/WeakAurasOptions/ActionOptions.lua @@ -218,6 +218,7 @@ function OptionsPrivate.GetActionOptions(data) width = WeakAuras.normalWidth, name = L["Sound"], order = 8.4, + itemControl = "WeakAurasMediaSound", values = OptionsPrivate.Private.sound_types, sorting = OptionsPrivate.Private.SortOrderForValues(OptionsPrivate.Private.sound_types), disabled = function() return not data.actions.start.do_sound end, @@ -599,6 +600,7 @@ function OptionsPrivate.GetActionOptions(data) width = WeakAuras.normalWidth, name = L["Sound"], order = 28.1, + itemControl = "WeakAurasMediaSound", values = OptionsPrivate.Private.sound_types, sorting = OptionsPrivate.Private.SortOrderForValues(OptionsPrivate.Private.sound_types), disabled = function() return not data.actions.finish.do_sound end, diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index a0b3380..0619249 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -1016,6 +1016,7 @@ typeControlAdders = { end end, dialogControl = OptionsPrivate.Private.author_option_media_controls[option.mediaType], + itemControl = OptionsPrivate.Private.author_option_media_itemControls[option.mediaType], order = order(), get = get(option, "default"), set = function(_, value) @@ -2346,6 +2347,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) elseif optionType == "media" then userOption.type = "select" userOption.dialogControl = OptionsPrivate.Private.author_option_media_controls[option.mediaType] + userOption.itemControl = OptionsPrivate.Private.author_option_media_itemControls[option.mediaType] userOption.values = function() if option.mediaType == "sound" then return OptionsPrivate.Private.sound_file_types diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index a8380f9..2e9af6f 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -581,6 +581,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA width = WeakAuras.normalWidth, values = OptionsPrivate.Private.sound_types, sorting = OptionsPrivate.Private.SortOrderForValues(OptionsPrivate.Private.sound_types), + itemControl = "WeakAurasMediaSound", name = blueIfNoValue2(data, conditions[i].changes[j], "value", "sound", L["Differences"]), desc = descIfNoValue2(data, conditions[i].changes[j], "value", "sound", propertyType, OptionsPrivate.Private.sound_types), order = order, diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index 89ad494..f88f087 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -95,3 +95,4 @@ AceGUI-Widgets\AceGUIWidget-WeakAurasSpacer.lua AceGUI-Widgets\AceGuiWidget-WeakAurasProgressBar.lua AceGUI-Widgets\AceGUIWidget-WeakAurasSpinBox.lua AceGUI-Widgets\AceGUIWidget-WeakAurasInputFocus.lua +AceGUI-Widgets\AceGUIWidget-WeakAurasMediaSound.lua From e924932d63cfd63d5388529f1d3741e340ac2ace Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 20:39:25 +0100 Subject: [PATCH 048/153] from retail --- WeakAuras/Prototypes.lua | 11 +- WeakAuras/RegionTypes/Text.lua | 167 ++++++++++++++++-------- WeakAuras/WeakAuras.lua | 13 +- WeakAurasOptions/RegionOptions/Text.lua | 50 ++++++- WeakAurasOptions/WeakAurasOptions.lua | 12 +- 5 files changed, 187 insertions(+), 66 deletions(-) diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 6ec6f07..ba7cbab 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -2828,10 +2828,17 @@ Private.event_prototypes = { store = true }, { + name = "extraSpellId", + display = WeakAuras.newFeatureString .. L["Extra Spell Id"], + init = "arg", enable = function(trigger) return trigger.subeventSuffix and (trigger.subeventSuffix == "_INTERRUPT" or trigger.subeventSuffix == "_DISPEL" or trigger.subeventSuffix == "_DISPEL_FAILED" or trigger.subeventSuffix == "_STOLEN" or trigger.subeventSuffix == "_AURA_BROKEN_SPELL") - end - }, -- extraSpellId ignored with SPELL_INTERRUPT + end, + type = "spell", + showExactOption = false, + store = true, + conditionType = "number" + }, { name = "extraSpellName", display = L["Extra Spell Name"], diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index 49480a6..7270f61 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -44,7 +44,12 @@ local properties = { softMax = 72, step = 1, default = 12 - } + }, + displayText = { + display = L["Text"], + setter = "ChangeText", + type = "string" + }, } WeakAuras.regionPrototype.AddProperties(properties, default); @@ -172,8 +177,13 @@ local function modify(parent, region, data) end end - local UpdateText - if Private.ContainsAnyPlaceHolders(data.displayText) then + local containsCustomText = false + if Private.ContainsCustomPlaceHolder(data.displayText) then + containsCustomText = true + end + + local formatters + do local getter = function(key, default) local fullKey = "displayText_format_" .. key if (data[fullKey] == nil) then @@ -181,67 +191,102 @@ local function modify(parent, region, data) end return data[fullKey] end - local formatters = Private.CreateFormatters(data.displayText, getter) - UpdateText = function() - local textStr = data.displayText; - textStr = Private.ReplacePlaceHolders(textStr, region, nil, false, formatters); - if (textStr == nil or textStr == "") then - textStr = " "; - end + local texts = {} + tinsert(texts, data.displayText) + + if type(data.conditions) == "table" then + for _, condition in ipairs(data.conditions) do + if type(condition.changes) == "table" then + for _, change in ipairs(condition.changes) do + if type(change.property) == "string" + and change.property == "displayText" + and type(change.value) == "string" + and Private.ContainsAnyPlaceHolders(change.value) + then + if not containsCustomText and Private.ContainsCustomPlaceHolder(change.value) then + containsCustomText = true + end + tinsert(texts, change.value) + end + end + end + end + end + + formatters = Private.CreateFormatters(texts, getter) + end + + local customTextFunc = nil + if containsCustomText and data.customText and data.customText ~= "" then + customTextFunc = WeakAuras.LoadFunction("return "..data.customText) + end + + function region:ConfigureTextUpdate() + local UpdateText + if self.displayText and Private.ContainsAnyPlaceHolders(self.displayText) then + UpdateText = function() + local textStr = self.displayText; + textStr = Private.ReplacePlaceHolders(textStr, self, nil, false, formatters); + if (textStr == nil or textStr == "") then + textStr = " "; + end + + SetText(textStr) + end + end + + local Update + if customTextFunc and self.displayText and Private.ContainsCustomPlaceHolder(self.displayText) then + Update = function() + self.values.custom = Private.RunCustomTextFunc(self, customTextFunc) + UpdateText() + end + else + Update = UpdateText or function() end + end + + local TimerTick + if Private.ContainsPlaceHolders(self.displayText, "p") then + TimerTick = UpdateText + end + + local FrameTick + if customTextFunc and data.customTextUpdate == "update" then + if Private.ContainsCustomPlaceHolder(self.displayText) then + FrameTick = function() + self.values.custom = Private.RunCustomTextFunc(self, customTextFunc) + UpdateText() + end + end + end + + self.Update = Update + self.FrameTick = FrameTick + self.TimerTick = TimerTick + + if not UpdateText then + local textStr = self.displayText + textStr = textStr:gsub("\\n", "\n"); SetText(textStr) end end - local customTextFunc = nil - if(Private.ContainsCustomPlaceHolder(data.displayText) and data.customText) then - customTextFunc = WeakAuras.LoadFunction("return "..data.customText) - end - - local Update - if customTextFunc then - if UpdateText then - Update = function() - region.values.custom = Private.RunCustomTextFunc(region, customTextFunc) - UpdateText() - end + function region:ConfigureSubscribers() + if self.FrameTick then + self.subRegionEvents:AddSubscriber("FrameTick", self) + else + self.subRegionEvents:RemoveSubscriber("FrameTick", self) end - else - Update = UpdateText or function() end - end - local TimerTick - if Private.ContainsPlaceHolders(data.displayText, "p") then - TimerTick = UpdateText - end - - local FrameTick - if customTextFunc and data.customTextUpdate == "update" then - FrameTick = function() - region.values.custom = Private.RunCustomTextFunc(region, customTextFunc) - UpdateText() + if self.TimerTick then + self.subRegionEvents:AddSubscriber("TimerTick", self, true) + else + self.subRegionEvents:RemoveSubscriber("TimerTick", self) + end + if self.Update and self.state then + self:Update() end - end - - region.Update = Update - region.FrameTick = FrameTick - region.TimerTick = TimerTick - if TimerTick then - region.subRegionEvents:AddSubscriber("TimerTick", region, true) - else - region.subRegionEvents:RemoveSubscriber("TimerTick", region) - end - - if FrameTick then - region.subRegionEvents:AddSubscriber("FrameTick", region) - else - region.subRegionEvents:RemoveSubscriber("FrameTick", region) - end - - if not UpdateText then - local textStr = data.displayText - textStr = textStr:gsub("\\n", "\n"); - SetText(textStr) end function region:Color(r, g, b, a) @@ -279,6 +324,16 @@ local function modify(parent, region, data) region.text:SetTextHeight(size) end + function region:ChangeText(msg) + self.displayText = msg + self:ConfigureTextUpdate() + self:ConfigureSubscribers() + end + + region.displayText = data.displayText + region:ConfigureTextUpdate() + region:ConfigureSubscribers() + WeakAuras.regionPrototype.modifyFinish(parent, region, data); end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index b1f6f7b..cac4106 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -4561,7 +4561,8 @@ end function Private.CreateFormatters(input, getter, withoutColor) local seenSymbols = {} local formatters = {} - Private.ParseTextStr(input, function(symbol) + + local parseFn = function(symbol) if not seenSymbols[symbol] then local _, sym = string.match(symbol, "(.+)%.(.+)") sym = sym or symbol @@ -4576,7 +4577,15 @@ function Private.CreateFormatters(input, getter, withoutColor) end end seenSymbols[symbol] = true - end) + end + + if type(input) == "string" then + Private.ParseTextStr(input, parseFn) + elseif type(input) == "table" then + for _, v in ipairs(input) do + Private.ParseTextStr(v, parseFn) + end + end return formatters end diff --git a/WeakAurasOptions/RegionOptions/Text.lua b/WeakAurasOptions/RegionOptions/Text.lua index 25cd9f7..bd34bf7 100644 --- a/WeakAurasOptions/RegionOptions/Text.lua +++ b/WeakAurasOptions/RegionOptions/Text.lua @@ -12,6 +12,30 @@ local hiddenFontExtra = function() end local function createOptions(id, data) + local function hideCustomTextOption() + if OptionsPrivate.Private.ContainsCustomPlaceHolder(data.displayText) then + return false + end + + if type(data.conditions) == "table" then + for _, condition in ipairs(data.conditions) do + if type(condition.changes) == "table" then + for _, change in ipairs(condition.changes) do + if type(change.property) == "string" + and change.property == "displayText" + and type(change.value) == "string" + and OptionsPrivate.Private.ContainsCustomPlaceHolder(change.value) + then + return false + end + end + end + end + end + + return true + end + local options = { __title = L["Text Settings"], __order = 1, @@ -38,7 +62,7 @@ local function createOptions(id, data) customTextUpdate = { type = "select", width = WeakAuras.doubleWidth, - hidden = function() return not OptionsPrivate.Private.ContainsCustomPlaceHolder(data.displayText); end, + hidden = hideCustomTextOption, name = L["Update Custom Text On..."], values = OptionsPrivate.Private.text_check_types, order = 36 @@ -267,7 +291,7 @@ local function createOptions(id, data) }; OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Function"], "customText", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-text", - 37, function() return not OptionsPrivate.Private.ContainsCustomPlaceHolder(data.displayText) end, {"customText"}, false); + 37, hideCustomTextOption, {"customText"}, false); -- Add Text Format Options local hidden = function() @@ -299,11 +323,29 @@ local function createOptions(id, data) end for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + local texts = {} + if child.displayText ~= "" then + tinsert(texts, child.displayText) + end + for _, condition in ipairs(child.conditions) do + if type(condition.changes) == "table" then + for _, change in ipairs(condition.changes) do + if type(change.property) == "string" + and change.property == "displayText" + and type(change.value) == "string" + and change.value ~= "" + then + tinsert(texts, change.value) + end + end + end + end + local get = function(key) return child["displayText_format_" .. key] end - local input = child.displayText - OptionsPrivate.AddTextFormatOption(input, true, get, addOption, hidden, setHidden, false, index, total) + + OptionsPrivate.AddTextFormatOption(texts, true, get, addOption, hidden, setHidden, false, index, total) index = index + 1 end diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index b5b75b3..453861f 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -1957,7 +1957,7 @@ function OptionsPrivate.AddTextFormatOption(input, withHeader, get, addOption, h local seenSymbols = {} - OptionsPrivate.Private.ParseTextStr(input, function(symbol) + local parseFn = function(symbol) if not seenSymbols[symbol] then local _, sym = string.match(symbol, "(.+)%.(.+)") sym = sym or symbol @@ -1987,7 +1987,15 @@ function OptionsPrivate.AddTextFormatOption(input, withHeader, get, addOption, h seenSymbols[symbol] = true end end - end) + end + + if type(input) == "table" then + for _, txt in ipairs(input) do + OptionsPrivate.Private.ParseTextStr(txt, parseFn) + end + else + OptionsPrivate.Private.ParseTextStr(input, parseFn) + end if withHeader and (not index or index == total) then addOption("header_anchor", From ba4039dae289267a465ef6ba9a712b2ac20216b0 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 20:55:38 +0100 Subject: [PATCH 049/153] from retail --- WeakAuras/SubRegionTypes/SubText.lua | 71 +++++++++++++------ WeakAurasOptions/SubRegionOptions/SubText.lua | 52 ++++++++------ 2 files changed, 81 insertions(+), 42 deletions(-) diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index a8b4c3b..5162133 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -178,24 +178,22 @@ local function modify(parent, region, parentData, data, first) break end end - - if type(parentData.conditions) == "table" then - for _, condition in ipairs(parentData.conditions) do - if type(condition.changes) == "table" then - for _, change in ipairs(condition.changes) do - if type(change.property) == "string" - and change.property:match("sub%.%d+%.text_text") - and type(change.value) == "string" - and Private.ContainsCustomPlaceHolder(change.value) - then - containsCustomText = true - break + if not containsCustomText then + if type(parentData.conditions) == "table" then + for _, condition in ipairs(parentData.conditions) do + if type(condition.changes) == "table" then + for _, change in ipairs(condition.changes) do + if type(change.property) == "string" + and change.property:match("sub%.%d+%.text_text") + then + containsCustomText = true + break + end end end end end end - if containsCustomText and parentData.customText and parentData.customText ~= "" then parent.customTextFunc = WeakAuras.LoadFunction("return "..parentData.customText) else @@ -205,20 +203,49 @@ local function modify(parent, region, parentData, data, first) parent.values.lastCustomTextUpdate = nil end + local texts = {} + local textStr = data.text_text or "" + if textStr ~= "" then + tinsert(texts, textStr) + end + + local subRegionIndex = 1 + for index, subRegion in ipairs(parentData.subRegions) do + if subRegion == data then + subRegionIndex = index + break; + end + end + if type(parentData.conditions) == "table" then + local conditionName = "sub."..subRegionIndex..".text_text" + for _, condition in ipairs(parentData.conditions) do + if type(condition.changes) == "table" then + for _, change in ipairs(condition.changes) do + if type(change.property) == "string" and change.property == conditionName then + if type(change.value ) == "string" and change.value ~= "" then + tinsert(texts, change.value) + end + end + end + end + end + end + + local getter = function(key, default) + local fullKey = "text_text_format_" .. key + if (data[fullKey] == nil) then + data[fullKey] = default + end + return data[fullKey] + end + region.subTextFormatters = Private.CreateFormatters(texts, getter) + function region:ConfigureTextUpdate() local UpdateText if region.text_text and Private.ContainsAnyPlaceHolders(region.text_text) then - local getter = function(key, default) - local fullKey = "text_text_format_" .. key - if data[fullKey] == nil then - data[fullKey] = default - end - return data[fullKey] - end - local formatters = Private.CreateFormatters(region.text_text, getter) UpdateText = function() local textStr = region.text_text or "" - textStr = Private.ReplacePlaceHolders(textStr, parent, nil, false, formatters) + textStr = Private.ReplacePlaceHolders(textStr, parent, nil, false, self.subTextFormatters) if text:GetFont() then text:SetText(WeakAuras.ReplaceRaidMarkerSymbols(textStr)) diff --git a/WeakAurasOptions/SubRegionOptions/SubText.lua b/WeakAurasOptions/SubRegionOptions/SubText.lua index 59c467e..613ff2e 100644 --- a/WeakAurasOptions/SubRegionOptions/SubText.lua +++ b/WeakAurasOptions/SubRegionOptions/SubText.lua @@ -465,30 +465,42 @@ local function createOptions(parentData, data, index, subIndex) options["text_text_format_" .. key] = option end - if parentData.controlledChildren then - local list = {} - for child in OptionsPrivate.Private.TraverseLeafs(parentData) do - if child.subRegions then - local childSubRegion = child.subRegions[index] - if childSubRegion then - tinsert(list, childSubRegion) + local list = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(parentData) do + if child.subRegions then + local childSubRegion = child.subRegions[index] + if childSubRegion then + tinsert(list, child) + end + end + end + + for listIndex, child in ipairs(list) do + local childSubRegion = child.subRegions[index] + local get = function(key) + return childSubRegion["text_text_format_" .. key] + end + local texts = {} + if type(childSubRegion.text_text) == "string" and childSubRegion.text_text ~= "" then + -- found text of subregion + tinsert(texts, childSubRegion.text_text) + end + + for _, condition in ipairs(child.conditions) do + if type(condition.changes) == "table" then + for _, change in ipairs(condition.changes) do + if change.property == "sub."..index..".text_text" + and type(change.value) == "string" + and change.value ~= "" + then + -- found a condition editing text of that subregion + tinsert(texts, change.value) + end end end end - for listIndex, childSubRegion in ipairs(list) do - local get = function(key) - return childSubRegion["text_text_format_" .. key] - end - local input = childSubRegion["text_text"] - OptionsPrivate.AddTextFormatOption(input, true, get, addOption, hidden, setHidden, false, listIndex, #list) - end - else - local get = function(key) - return data["text_text_format_" .. key] - end - local input = data["text_text"] - OptionsPrivate.AddTextFormatOption(input, true, get, addOption, hidden, setHidden, false) + OptionsPrivate.AddTextFormatOption(texts, true, get, addOption, hidden, setHidden, false, listIndex, #list) end addOption("footer", { From ec42e803b42d89c29552b9767f29e45e4855afc7 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 21:11:14 +0100 Subject: [PATCH 050/153] from retail --- WeakAuras/BossMods.lua | 252 +++++++++++------- WeakAuras/BuffTrigger2.lua | 17 +- WeakAuras/Modernize.lua | 5 +- WeakAuras/Prototypes.lua | 4 +- WeakAuras/WeakAuras.lua | 2 +- ...GUIWidget-WeakAurasPendingUpdateButton.lua | 42 --- WeakAurasOptions/BuffTrigger2.lua | 1 - WeakAurasOptions/CommonOptions.lua | 4 +- 8 files changed, 186 insertions(+), 141 deletions(-) diff --git a/WeakAuras/BossMods.lua b/WeakAuras/BossMods.lua index 7502571..023ed91 100644 --- a/WeakAuras/BossMods.lua +++ b/WeakAuras/BossMods.lua @@ -16,7 +16,6 @@ Private.ExecEnv.BossMods.DBM = { CopyBarToState = function(self, bar, states, timerId, extendTimer) extendTimer = extendTimer or 0 - if extendTimer + bar.duration < 0 then return end states[timerId] = states[timerId] or {} local state = states[timerId] state.show = true @@ -127,10 +126,21 @@ Private.ExecEnv.BossMods.DBM = { for timerId, bar in pairs(self.bars) do if not bar.paused then if bar.expirationTime < now then - self.bars[timerId] = nil - WeakAuras.ScanEvents("DBM_TimerStop", timerId) - if self.isGeneric then - WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + if bar.scheduledScanExpireAt == nil or bar.scheduledScanExpireAt <= GetTime() then + self.bars[timerId] = nil + else + if self.nextExpire == nil then + self.nextExpire = bar.scheduledScanExpireAt + elseif bar.scheduledScanExpireAt < self.nextExpire then + self.nextExpire = bar.scheduledScanExpireAt + end + end + if not bar.expired then + bar.expired = true + WeakAuras.ScanEvents("DBM_TimerStop", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + end end elseif self.nextExpire == nil then self.nextExpire = bar.expirationTime @@ -166,6 +176,7 @@ Private.ExecEnv.BossMods.DBM = { bar.spellId = tostring(spellId) bar.count = timerCount and tostring(timerCount) or "0" bar.dbmType = dbmType + bar.expired = nil local r, g, b = 0, 0, 0 if DBT.GetColorForType then @@ -212,10 +223,16 @@ Private.ExecEnv.BossMods.DBM = { end elseif event == "DBM_TimerStop" then local timerId = ... - self.bars[timerId] = nil - WeakAuras.ScanEvents("DBM_TimerStop", timerId) - if self.isGeneric then - WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + local bar = self.bars[timerId] + if bar then + if bar.scheduledScanExpireAt == nil or bar.scheduledScanExpireAt <= GetTime() then + self.bars[timerId] = nil + end + bar.expired = true + WeakAuras.ScanEvents("DBM_TimerStop", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + end end elseif event == "DBM_TimerPause" then local timerId = ... @@ -321,7 +338,7 @@ Private.ExecEnv.BossMods.DBM = { ScheduleCheck = function(self, fireTime) if not self.scheduled_scans[fireTime] then - self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime() + 0.1, self, fireTime) + self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime(), self, fireTime) end end } @@ -384,6 +401,7 @@ Private.event_prototypes["DBM Announce"] = { type = "spell", noValidation = true, showExactOption = false, + negativeIsEJ = true }, { name = "message", @@ -453,28 +471,43 @@ Private.event_prototypes["DBM Timer"] = { local counter = counter function copyOrSchedule(bar, cloneId) + local remainingTime + local changed + if bar.paused then + remainingTime = bar.remaining + extendTimer + else + remainingTime = bar.expirationTime - GetTime() + extendTimer + end if triggerUseRemaining then - local remainingTime - if bar.paused then - remainingTime = bar.remaining + extendTimer - else - remainingTime = bar.expirationTime - GetTime() + extendTimer - end - if remainingTime %s triggerRemaining then + if remainingTime > 0 and remainingTime %s triggerRemaining then Private.ExecEnv.BossMods.DBM:CopyBarToState(bar, states, cloneId, extendTimer) + changed = true else local state = states[cloneId] if state and state.show then state.show = false state.changed = true + changed = true end end - if remainingTime >= triggerRemaining and not bar.paused then - Private.ExecEnv.BossMods.DBM:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + if not bar.paused then + if extendTimer > 0 then + bar.scheduledScanExpireAt = math.max(bar.scheduledScanExpireAt or 0, bar.expirationTime + extendTimer) + end + if remainingTime >= triggerRemaining then + Private.ExecEnv.BossMods.DBM:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + end end else - Private.ExecEnv.BossMods.DBM:CopyBarToState(bar, states, cloneId, extendTimer) + if not bar.paused and extendTimer > 0 then + bar.scheduledScanExpireAt = math.max(bar.scheduledScanExpireAt or 0, bar.expirationTime + extendTimer) + end + if remainingTime > 0 then + Private.ExecEnv.BossMods.DBM:CopyBarToState(bar, states, cloneId, extendTimer) + changed = true + end end + return changed end if useClone then @@ -485,13 +518,12 @@ Private.event_prototypes["DBM Timer"] = { if Private.ExecEnv.BossMods.DBM:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerId, triggerDbmType) then local bar = Private.ExecEnv.BossMods.DBM:GetTimerById(timerId) if bar then - copyOrSchedule(bar, cloneId) - return true + return copyOrSchedule(bar, cloneId) end end elseif event == "DBM_TimerStop" and state then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then + local bar_remainingTime = state.expirationTime - GetTime() + (state.extend or 0) + if state.extend == 0 or bar_remainingTime <= 0 then state.show = false state.changed = true return true @@ -500,13 +532,12 @@ Private.event_prototypes["DBM Timer"] = { local changed for timerId, bar in pairs(Private.ExecEnv.BossMods.DBM:GetAllTimers()) do if Private.ExecEnv.BossMods.DBM:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerId, triggerDbmType) then - copyOrSchedule(bar, timerId) - changed = true + changed = copyOrSchedule(bar, timerId) or changed else local state = states[timerId] if state then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then + local bar_remainingTime = state.expirationTime - GetTime() + (state.extend or 0) + if state.extend == 0 or bar_remainingTime <= 0 then state.show = false state.changed = true changed = true @@ -524,8 +555,7 @@ Private.event_prototypes["DBM Timer"] = { end for timerId, bar in pairs(Private.ExecEnv.BossMods.DBM:GetAllTimers()) do if Private.ExecEnv.BossMods.DBM:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerId, triggerDbmType) then - copyOrSchedule(bar, timerId) - changed = true + changed = copyOrSchedule(bar, timerId) or changed end end return changed @@ -545,13 +575,12 @@ Private.event_prototypes["DBM Timer"] = { or not (state and state.show) or (state and state.show and state.expirationTime > (bar.expirationTime + extendTimer)) then - copyOrSchedule(bar, cloneId) - return true + return copyOrSchedule(bar, cloneId) end else if state and state.show then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then + local bar_remainingTime = state.expirationTime - GetTime() + (state.extend or 0) + if state.extend == 0 or bar_remainingTime <= 0 then state.show = false state.changed = true return true @@ -565,7 +594,7 @@ Private.event_prototypes["DBM Timer"] = { return ret:format( trigger.use_count and trigger.count or "", trigger.use_id and trigger.id or "", - trigger.use_spellId and trigger.spellId or "", + trigger.use_spellId and tostring(trigger.spellId) or "", trigger.use_message and trigger.message or "", trigger.use_message and trigger.message_operator or "", trigger.use_cloneId and "true" or "false", @@ -591,6 +620,7 @@ Private.event_prototypes["DBM Timer"] = { conditionType = "string", noValidation = true, showExactOption = false, + negativeIsEJ = true }, { name = "message", @@ -644,7 +674,6 @@ Private.ExecEnv.BossMods.BigWigs = { CopyBarToState = function(self, bar, states, timerId, extendTimer) extendTimer = extendTimer or 0 - if extendTimer + bar.duration < 0 then return end states[timerId] = states[timerId] or {} local state = states[timerId] state.show = true @@ -749,10 +778,21 @@ Private.ExecEnv.BossMods.BigWigs = { for timerId, bar in pairs(self.bars) do if not bar.paused then if bar.expirationTime < now then - self.bars[timerId] = nil - WeakAuras.ScanEvents("BigWigs_StopBar", timerId) - if self.isGeneric then - WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + if bar.scheduledScanExpireAt == nil or bar.scheduledScanExpireAt <= GetTime() then + self.bars[timerId] = nil + else + if self.nextExpire == nil then + self.nextExpire = bar.scheduledScanExpireAt + elseif bar.scheduledScanExpireAt < self.nextExpire then + self.nextExpire = bar.scheduledScanExpireAt + end + end + if not bar.expired then + bar.expired = true + WeakAuras.ScanEvents("BigWigs_StopBar", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerStop", timerId) + end end elseif self.nextExpire == nil then self.nextExpire = bar.expirationTime @@ -789,6 +829,7 @@ Private.ExecEnv.BossMods.BigWigs = { bar.expirationTime = expirationTime bar.icon = icon bar.isCooldown = isCD or false + bar.expired = nil local BWColorModule = BigWigs:GetPlugin("Colors") bar.bwBarColor = BWColorModule:GetColorTable("barColor", addon, spellId) bar.bwTextColor = BWColorModule:GetColorTable("barText", addon, spellId) @@ -810,8 +851,11 @@ Private.ExecEnv.BossMods.BigWigs = { end elseif event == "BigWigs_StopBar" then local addon, text = ... - if self.bars[text] then - self.bars[text] = nil + local bar = self.bars[text] + if bar then + if bar.scheduledScanExpireAt == nil or bar.scheduledScanExpireAt <= GetTime() then + self.bars[text] = nil + end WeakAuras.ScanEvents("BigWigs_StopBar", text) if self.isGeneric then WeakAuras.ScanEvents("BossMod_TimerStop", text) @@ -934,7 +978,7 @@ Private.ExecEnv.BossMods.BigWigs = { ScheduleCheck = function(self, fireTime) if not self.scheduled_scans[fireTime] then - self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime() + 0.1, self, fireTime) + self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime(), self, fireTime) end end } @@ -994,6 +1038,7 @@ Private.event_prototypes["BigWigs Message"] = { conditionType = "string", noValidation = true, showExactOption = false, + negativeIsEJ = true }, { name = "text", @@ -1064,28 +1109,43 @@ Private.event_prototypes["BigWigs Timer"] = { local counter = counter function copyOrSchedule(bar, cloneId) + local remainingTime + local changed + if bar.paused then + remainingTime = bar.remaining + extendTimer + else + remainingTime = bar.expirationTime - GetTime() + extendTimer + end if triggerUseRemaining then - local remainingTime - if bar.paused then - remainingTime = bar.remaining + extendTimer - else - remainingTime = bar.expirationTime - GetTime() + extendTimer - end - if remainingTime %s triggerRemaining then + if remainingTime > 0 and remainingTime %s triggerRemaining then Private.ExecEnv.BossMods.BigWigs:CopyBarToState(bar, states, cloneId, extendTimer) + changed = true else local state = states[cloneId] if state and state.show then state.show = false state.changed = true + changed = true end end - if remainingTime >= triggerRemaining and not bar.paused then - Private.ExecEnv.BossMods.BigWigs:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + if not bar.paused then + if extendTimer > 0 then + bar.scheduledScanExpireAt = math.max(bar.scheduledScanExpireAt or 0, bar.expirationTime + extendTimer) + end + if remainingTime >= triggerRemaining then + Private.ExecEnv.BossMods.BigWigs:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + end end else - Private.ExecEnv.BossMods.BigWigs:CopyBarToState(bar, states, cloneId, extendTimer) + if not bar.paused and extendTimer > 0 then + bar.scheduledScanExpireAt = math.max(bar.scheduledScanExpireAt or 0, bar.expirationTime + extendTimer) + end + if remainingTime > 0 then + Private.ExecEnv.BossMods.BigWigs:CopyBarToState(bar, states, cloneId, extendTimer) + changed = true + end end + return changed end if useClone then @@ -1096,13 +1156,12 @@ Private.event_prototypes["BigWigs Timer"] = { if Private.ExecEnv.BossMods.BigWigs:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerCast, triggerIsCooldown) then local bar = Private.ExecEnv.BossMods.BigWigs:GetTimerById(timerId) if bar then - copyOrSchedule(bar, cloneId) - return true + return copyOrSchedule(bar, cloneId) end end elseif event == "BigWigs_StopBar" and state then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then + local bar_remainingTime = state.expirationTime - GetTime() + (state.extend or 0) + if state.extend == 0 or bar_remainingTime <= 0 then state.show = false state.changed = true return true @@ -1111,8 +1170,7 @@ Private.event_prototypes["BigWigs Timer"] = { local changed for timerId, bar in pairs(Private.ExecEnv.BossMods.BigWigs:GetAllTimers()) do if Private.ExecEnv.BossMods.BigWigs:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerCast, triggerIsCooldown) then - copyOrSchedule(bar, timerId) - changed = true + changed = copyOrSchedule(bar, timerId) or changed end end return changed @@ -1125,8 +1183,7 @@ Private.event_prototypes["BigWigs Timer"] = { end for timerId, bar in pairs(Private.ExecEnv.BossMods.BigWigs:GetAllTimers()) do if Private.ExecEnv.BossMods.BigWigs:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerCast, triggerIsCooldown) then - copyOrSchedule(bar, timerId) - changed = true + changed = copyOrSchedule(bar, timerId) or changed end end return changed @@ -1146,13 +1203,12 @@ Private.event_prototypes["BigWigs Timer"] = { or not (state and state.show) or (state and state.show and state.expirationTime > (bar.expirationTime + extendTimer)) then - copyOrSchedule(bar, cloneId) - return true + return copyOrSchedule(bar, cloneId) end else if state and state.show then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then + local bar_remainingTime = state.expirationTime - GetTime() + (state.extend or 0) + if state.extend == 0 or bar_remainingTime <= 0 then state.show = false state.changed = true return true @@ -1164,7 +1220,7 @@ Private.event_prototypes["BigWigs Timer"] = { ]=] return ret:format( trigger.use_count and trigger.count or "", - trigger.use_spellId and trigger.spellId or "", + trigger.use_spellId and tostring(trigger.spellId) or "", trigger.use_text and trigger.text or "", trigger.use_text and trigger.text_operator or "", trigger.use_cloneId and "true" or "false", @@ -1186,6 +1242,7 @@ Private.event_prototypes["BigWigs Timer"] = { conditionType = "string", noValidation = true, showExactOption = false, + negativeIsEJ = true }, { name = "text", @@ -1353,6 +1410,7 @@ Private.event_prototypes["Boss Mod Announce"] = { conditionType = "string", noValidation = true, showExactOption = false, + negativeIsEJ = true }, { name = "message", @@ -1429,28 +1487,43 @@ Private.event_prototypes["Boss Mod Timer"] = { local counter = counter function copyOrSchedule(bar, cloneId) + local remainingTime + local changed + if bar.paused then + remainingTime = bar.remaining + extendTimer + else + remainingTime = bar.expirationTime - GetTime() + extendTimer + end if triggerUseRemaining then - local remainingTime - if bar.paused then - remainingTime = bar.remaining + extendTimer - else - remainingTime = bar.expirationTime - GetTime() + extendTimer - end - if remainingTime %s triggerRemaining then + if remainingTime > 0 and remainingTime %s triggerRemaining then Private.ExecEnv.BossMods.Generic:CopyBarToState(bar, states, cloneId, extendTimer) + changed = true else local state = states[cloneId] if state and state.show then state.show = false state.changed = true + changed = true end end - if remainingTime >= triggerRemaining and not bar.paused then - Private.ExecEnv.BossMods.Generic:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + if not bar.paused then + if extendTimer > 0 then + bar.scheduledScanExpireAt = math.max(bar.scheduledScanExpireAt or 0, bar.expirationTime + extendTimer) + end + if remainingTime >= triggerRemaining then + Private.ExecEnv.BossMods.Generic:ScheduleCheck(bar.expirationTime - triggerRemaining + extendTimer) + end end else - Private.ExecEnv.BossMods.Generic:CopyBarToState(bar, states, cloneId, extendTimer) + if not bar.paused and extendTimer > 0 then + bar.scheduledScanExpireAt = math.max(bar.scheduledScanExpireAt or 0, bar.expirationTime + extendTimer) + end + if remainingTime > 0 then + Private.ExecEnv.BossMods.Generic:CopyBarToState(bar, states, cloneId, extendTimer) + changed = true + end end + return changed end if useClone then @@ -1461,13 +1534,12 @@ Private.event_prototypes["Boss Mod Timer"] = { if Private.ExecEnv.BossMods.Generic:TimerMatchesGeneric(timerId, triggerText, triggerTextOperator, triggerSpellId, counter) then local bar = Private.ExecEnv.BossMods.Generic:GetTimerById(timerId) if bar then - copyOrSchedule(bar, cloneId) - return true + return copyOrSchedule(bar, cloneId) end end elseif event == "BossMod_TimerStop" and state then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then + local bar_remainingTime = state.expirationTime - GetTime() + (state.extend or 0) + if state.extend == 0 or bar_remainingTime <= 0 then state.show = false state.changed = true return true @@ -1476,13 +1548,12 @@ Private.event_prototypes["Boss Mod Timer"] = { local changed for timerId, bar in pairs(Private.ExecEnv.BossMods.Generic:GetAllTimers()) do if Private.ExecEnv.BossMods.Generic:TimerMatchesGeneric(timerId, triggerText, triggerTextOperator, triggerSpellId, counter) then - copyOrSchedule(bar, timerId) - changed = true + changed = copyOrSchedule(bar, timerId) or changed else local state = states[timerId] if state then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then + local bar_remainingTime = state.expirationTime - GetTime() + (state.extend or 0) + if state.extend == 0 or bar_remainingTime <= 0 then state.show = false state.changed = true changed = true @@ -1500,8 +1571,7 @@ Private.event_prototypes["Boss Mod Timer"] = { end for timerId, bar in pairs(Private.ExecEnv.BossMods.Generic:GetAllTimers()) do if Private.ExecEnv.BossMods.Generic:TimerMatchesGeneric(timerId, triggerText, triggerTextOperator, triggerSpellId, counter) then - copyOrSchedule(bar, timerId) - changed = true + changed = copyOrSchedule(bar, timerId) or changed end end return changed @@ -1521,13 +1591,12 @@ Private.event_prototypes["Boss Mod Timer"] = { or not (state and state.show) or (state and state.show and state.expirationTime > (bar.expirationTime + extendTimer)) then - copyOrSchedule(bar, cloneId) - return true + return copyOrSchedule(bar, cloneId) end else if state and state.show then - local bar_remainingTime = GetTime() - state.expirationTime + (state.extend or 0) - if state.extend == 0 or bar_remainingTime > 0.2 then + local bar_remainingTime = state.expirationTime - GetTime() + (state.extend or 0) + if state.extend == 0 or bar_remainingTime <= 0 then state.show = false state.changed = true return true @@ -1540,7 +1609,7 @@ Private.event_prototypes["Boss Mod Timer"] = { return ret:format( trigger.use_count and trigger.count or "", - trigger.use_spellId and trigger.spellId or "", + trigger.use_spellId and tostring(trigger.spellId) or "", trigger.use_message and trigger.message or "", trigger.use_message and trigger.message_operator or "", trigger.use_cloneId and "true" or "false", @@ -1560,6 +1629,7 @@ Private.event_prototypes["Boss Mod Timer"] = { conditionType = "string", noValidation = true, showExactOption = false, + negativeIsEJ = true }, { name = "message", diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index a7ab98a..c29afe7 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -365,7 +365,11 @@ local function UpdateMatchData(time, matchDataChanged, unit, index, filter, name -- Tell old auras that used this match data for id, triggerData in pairs(data.auras) do for triggernum in pairs(triggerData) do - if matchDataByTrigger[id] and matchDataByTrigger[id][triggernum] and matchDataByTrigger[id][triggernum][unit] and matchDataByTrigger[id][triggernum][unit][index] then + if matchDataByTrigger[id] + and matchDataByTrigger[id][triggernum] + and matchDataByTrigger[id][triggernum][unit] + and matchDataByTrigger[id][triggernum][unit][index] + then matchDataByTrigger[id][triggernum][unit][index] = nil matchDataChanged[id] = matchDataChanged[id] or {} matchDataChanged[id][triggernum] = true @@ -1815,6 +1819,17 @@ local function EventHandler(frame, event, arg1, arg2, ...) tinsert(unitsToRemove, unit) end end + + if arg1 then + -- Initial login has a bug where the tooltip information is not available, + -- so update tooltips 2s after login + timer:ScheduleTimer(function() + for unit, matchtDataPerUnit in pairs(matchData) do + EventHandler(frame, "UNIT_AURA", unit) + end + end, 2) + end + elseif event == "RAID_TARGET_UPDATE" then ScanRaidMarkScanFunc(matchDataChanged) end diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 9d1dd96..cde1b76 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1398,10 +1398,13 @@ function Private.Modernize(data) "spellId", "spellName", }, + ["Spell Cast Succeeded"] = { + "spellId" + }, ["Location"] = { "zone", "subzone", - } + }, } for _, triggerData in ipairs(data.triggers) do local t = triggerData.trigger diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index ba7cbab..6f1927c 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -985,7 +985,7 @@ Private.load_prototype = { name = "spellknown", display = L["Spell Known"], type = "spell", - test = "WeakAuras.IsSpellKnownForLoad(%s, %s)", + test = "WeakAuras.IsSpellKnownForLoad(%q, %s)", events = {"SPELLS_CHANGED", "UNIT_PET"}, showExactOption = true }, @@ -993,7 +993,7 @@ Private.load_prototype = { name = "not_spellknown", display = WeakAuras.newFeatureString .. L["|cFFFF0000Not|r Spell Known"], type = "spell", - test = "not WeakAuras.IsSpellKnownForLoad(%s, %s)", + test = "not WeakAuras.IsSpellKnownForLoad(%q, %s)", events = {"SPELLS_CHANGED", "UNIT_PET"}, showExactOption = true }, diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index cac4106..721635a 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -5114,7 +5114,7 @@ function Private.AnchorFrame(data, region, parent, force) local anchorPoint = data.anchorPoint if data.parent then - if data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE" then + if data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE" then anchorPoint = "CENTER" end else diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua index e3d48bd..9e2a95e 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua @@ -71,54 +71,12 @@ local methods = { self.menu = {} - self.frame:SetScript("OnMouseUp", function() - Hide_Tooltip() - self:SetMenu() - EasyMenu(self.menu, WeakAuras_DropDownMenu, self.frame, 0, 0, "MENU") - end) - self.frame:SetScript("OnEnter", function() self:SetNormalTooltip() Show_Long_Tooltip(self.frame, self.frame.description) end) self.frame:SetScript("OnLeave", Hide_Tooltip) end, - ["SetMenu"] = function(self) - wipe(self.menu) - for auraId in pairs(self.linkedAuras) do - if not self.linkedChildren[auraId] then - tinsert(self.menu, - { - text = auraId, - notCheckable = true, - hasArrow = true, - menuList = { - { - text = L["Update"], - notCheckable = true, - func = function() - local auraData = WeakAuras.GetData(auraId) - if auraData then - local success, error = WeakAuras.Import(self.companionData.encoded, auraData) - if not success and error ~= nil then - WeakAuras.prettyPrint(error) - end - end - end - }, - { - text = L["Ignore updates"], - notCheckable = true, - func = function() - StaticPopup_Show("WEAKAURAS_CONFIRM_IGNORE_UPDATES", "", "", auraId) - end - } - } - } - ) - end - end - end, ["SetLogo"] = function(self, path) self.frame.updateLogo.tex:SetTexture(path) end, diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index 07d7c83..821c299 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -205,7 +205,6 @@ local function CreateNameOptions(aura_options, data, trigger, size, isExactSpell end, validate = isExactSpellId and WeakAuras.ValidateNumeric or nil, control = "WeakAurasInputFocus", - getWithFocus = function() return trigger[optionKey] and trigger[optionKey][i] or "" end } end -- VALIDATE ? diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index 2799cd5..c05975c 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -1158,7 +1158,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g if IsParentDynamicGroup() then return true end - return data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE"; + return data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE"; else return data.anchorFrameType == "MOUSE"; end @@ -1175,7 +1175,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g if IsGroupByFrame() then return true end - if (data.anchorFrameType ~= "SCREEN" and data.anchorFrameType ~= "UIPARENT") then + if (data.anchorFrameType ~= "SCREEN") then return true; end if (data.parent) then From 869ac5c1b4f9e573fa643eabebca9054e4b26ac7 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 21:57:41 +0100 Subject: [PATCH 051/153] from retail --- WeakAurasOptions/WeakAurasOptions.lua | 172 ++++++++++++++++---------- 1 file changed, 110 insertions(+), 62 deletions(-) diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 453861f..73a0951 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -443,31 +443,7 @@ StaticPopupDialogs["WEAKAURAS_CONFIRM_DELETE"] = { button2 = L["Cancel"], OnAccept = function(self) if self.data then - local suspended = OptionsPrivate.Private.PauseAllDynamicGroups() - OptionsPrivate.massDelete = true - for _, auraData in pairs(self.data.toDelete) do - WeakAuras.Delete(auraData) - end - OptionsPrivate.massDelete = false - - if self.data.parents then - for id in pairs(self.data.parents) do - local parentData = WeakAuras.GetData(id) - local parentButton = OptionsPrivate.GetDisplayButton(id) - WeakAuras.UpdateGroupOrders(parentData) - if(#parentData.controlledChildren == 0) then - parentButton:DisableExpand() - else - parentButton:EnableExpand() - end - parentButton:SetNormalTooltip() - WeakAuras.Add(parentData) - WeakAuras.ClearAndUpdateOptions(parentData.id) - parentButton:UpdateParentWarning() - end - end - OptionsPrivate.Private.ResumeAllDynamicGroups(suspended) - OptionsPrivate.SortDisplayButtons(nil, true) + OptionsPrivate.DeleteAuras(self.data.toDelete, self.data.parents) end end, OnCancel = function(self) @@ -784,6 +760,54 @@ local function LayoutDisplayButtons(msg) OptionsPrivate.Private.dynFrame:AddAction("LayoutDisplayButtons1", co1); end +function OptionsPrivate.DeleteAuras(auras, parents) + local func1 = function() + frame:SetLoadProgressVisible(true) + local num = 0 + local total = 0 + for _, auraData in pairs(auras) do + total = total +1 + end + + frame.loadProgress:SetText(L["Deleting auras: "]..num.."/"..total) + + local suspended = OptionsPrivate.Private.PauseAllDynamicGroups() + OptionsPrivate.massDelete = true + for _, auraData in pairs(auras) do + WeakAuras.Delete(auraData) + num = num +1 + frame.loadProgress:SetText(L["Deleting auras: "]..num.."/"..total) + coroutine.yield() + end + OptionsPrivate.massDelete = false + + if parents then + for id in pairs(parents) do + local parentData = WeakAuras.GetData(id) + local parentButton = OptionsPrivate.GetDisplayButton(id) + WeakAuras.UpdateGroupOrders(parentData) + if(#parentData.controlledChildren == 0) then + parentButton:DisableExpand() + else + parentButton:EnableExpand() + end + parentButton:SetNormalTooltip() + WeakAuras.Add(parentData) + WeakAuras.ClearAndUpdateOptions(parentData.id) + frame.loadProgress:SetText(L["Finishing..."]) + coroutine.yield() + end + end + OptionsPrivate.Private.ResumeAllDynamicGroups(suspended) + OptionsPrivate.SortDisplayButtons(nil, true) + + frame:SetLoadProgressVisible(false) + end + + local co1 = coroutine.create(func1) + OptionsPrivate.Private.dynFrame:AddAction("Deleting Auras", co1) +end + function WeakAuras.ShowOptions(msg) local firstLoad = not(frame); OptionsPrivate.Private.Pause(); @@ -1466,51 +1490,75 @@ end function OptionsPrivate.Drop(mainAura, target, action, area) WeakAuras_DropDownMenu:Hide() - local mode = "" - if (frame.pickedDisplay == tempGroup and #tempGroup.controlledChildren > 0) then - mode = "MULTI" - elseif mainAura.controlledChildren then - mode = "GROUP" - else - mode = "SINGLE" - end + local func1 = function() + frame:SetLoadProgressVisible(true) - local buttonsToSort = {} + local total = 0 + local num = 0 + for id, button in pairs(displayButtons) do + if button:IsDragging() then + total = total + 1 + end + end + frame.loadProgress:SetText(L["Moving auras: "]..num.."/"..total) - for id, button in pairs(displayButtons) do - if button:IsDragging() then - tinsert(buttonsToSort, button) + local mode = "" + if (frame.pickedDisplay == tempGroup and #tempGroup.controlledChildren > 0) then + mode = "MULTI" + elseif mainAura.controlledChildren then + mode = "GROUP" else - button:Drop(mode, mainAura, target, action); + mode = "SINGLE" end - end - if mode == "MULTI" then - -- If we are dragging and dropping multiple auras at once, the order in which we drop is important - -- We want to preserve the top-down order - -- Depending on how exactly we find the insert position, we need to use the right order of insertions - if area == "GROUP" then - table.sort(buttonsToSort, CompareButtonOrderReverse) - elseif area == "BEFORE" then - table.sort(buttonsToSort, CompareButtonOrder) - else -- After - table.sort(buttonsToSort, CompareButtonOrderReverse) + local buttonsToSort = {} + + for id, button in pairs(displayButtons) do + if button:IsDragging() then + tinsert(buttonsToSort, button) + num = num + 1 + frame.loadProgress:SetText(L["Preparing auras: "]..num.."/"..total) + else + button:Drop(mode, mainAura, target, action); + end + coroutine.yield() end + + num = 0 + frame.loadProgress:SetText(L["Moving auras: "]..num.."/"..total) + if mode == "MULTI" then + -- If we are dragging and dropping multiple auras at once, the order in which we drop is important + -- We want to preserve the top-down order + -- Depending on how exactly we find the insert position, we need to use the right order of insertions + if area == "GROUP" then + table.sort(buttonsToSort, CompareButtonOrderReverse) + elseif area == "BEFORE" then + table.sort(buttonsToSort, CompareButtonOrder) + else -- After + table.sort(buttonsToSort, CompareButtonOrderReverse) + end + end + + for _, button in ipairs(buttonsToSort) do + button:Drop(mode, mainAura, target, action) + num = num + 1 + frame.loadProgress:SetText(L["Moving auras: "]..num.."/"..total) + coroutine.yield() + end + + -- Update offset, this is a bit wasteful to do for every aura + -- But we also need to update the offset if a parent was dragged + for _, button in pairs(displayButtons) do + button:UpdateOffset(); + end + coroutine.yield() + frame:SetLoadProgressVisible(false) + OptionsPrivate.SortDisplayButtons() + OptionsPrivate.UpdateButtonsScroll() end - for _, button in ipairs(buttonsToSort) do - button:Drop(mode, mainAura, target, action) - end - - -- Update offset, this is a bit wasteful to do for every aura - -- But we also need to update the offset if a parent was dragged - for _, button in pairs(displayButtons) do - button:UpdateOffset(); - end - - OptionsPrivate.SortDisplayButtons() - OptionsPrivate.UpdateButtonsScroll() - WeakAuras.FillOptions() + local co1 = coroutine.create(func1) + OptionsPrivate.Private.dynFrame:AddAction("Dropping Auras", co1) end function OptionsPrivate.StartDrag(mainAura) From db45573d1c47528de2dd2805c950454995d7800a Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 16 Jan 2025 22:58:42 +0100 Subject: [PATCH 052/153] from retail --- WeakAuras/BossMods.lua | 25 ++++- WeakAuras/GenericTrigger.lua | 104 ++++++++++-------- WeakAuras/Modernize.lua | 11 ++ WeakAuras/Prototypes.lua | 30 +++++ WeakAuras/RegionTypes/DynamicGroup.lua | 7 +- WeakAuras/Transmission.lua | 15 ++- WeakAuras/WeakAuras.lua | 4 +- .../AceGUIWidget-WeakAurasDisplayButton.lua | 1 + WeakAurasOptions/OptionsFrames/Update.lua | 27 +++++ WeakAurasOptions/WeakAurasOptions.lua | 1 + 10 files changed, 172 insertions(+), 53 deletions(-) diff --git a/WeakAuras/BossMods.lua b/WeakAuras/BossMods.lua index 023ed91..c4da07c 100644 --- a/WeakAuras/BossMods.lua +++ b/WeakAuras/BossMods.lua @@ -156,11 +156,11 @@ Private.ExecEnv.BossMods.DBM = { EventCallback = function(self, event, ...) if event == "DBM_Announce" then - local spellId = select(4, ...) - WeakAuras.ScanEvents("DBM_Announce", spellId, ...) + local message, icon, _, spellId, _, count = ... + WeakAuras.ScanEvents("DBM_Announce", spellId, message, icon) if self.isGeneric then - local message, icon = ... - WeakAuras.ScanEvents("BossMod_Announce", spellId, message, icon) + count = count and tostring(count) or "0" + WeakAuras.ScanEvents("BossMod_Announce", spellId, message, icon, count) end elseif event == "DBM_TimerStart" then local timerId, msg, duration, icon, timerType, spellId, dbmType, _, _, _, _, _, timerCount = ... @@ -812,7 +812,8 @@ Private.ExecEnv.BossMods.BigWigs = { WeakAuras.ScanEvents("BigWigs_Message", ...) if self.isGeneric then local _, spellId, text, _, icon = ... - WeakAuras.ScanEvents("BossMod_Announce", spellId, text, icon) + local count = text and text:match("%((%d+)%)") or text:match("((%d+))") or "0" + WeakAuras.ScanEvents("BossMod_Announce", spellId, text, icon, count) end elseif event == "BigWigs_StartBar" then local addon, spellId, text, duration, icon, isCD = ... @@ -1434,6 +1435,20 @@ Private.event_prototypes["Boss Mod Announce"] = { hidden = true, test = "true" }, + { + name = "count", + init = "arg", + display = L["Count"], + desc = L["Occurrence of the event\nCan be a range of values\nCan have multiple values separated by a comma or a space\n\nExamples:\n2nd 5th and 6th events: 2, 5, 6\n2nd to 6th: 2-6\nevery 2 events: /2\nevery 3 events starting from 2nd: 2/3\nevery 3 events starting from 2nd and ending at 11th: 2-11/3\n\nWorks only if Boss Mod addon show counter"], + type = "string", + preamble = "local counter = Private.ExecEnv.CreateTriggerCounter(%q)", + test = "counter:SetCount(tonumber(count) or 0) == nil and counter:Match()", + conditionTest = function(state, needle, op, preamble) + return preamble:Check(state.count) + end, + store = true, + conditionType = "string", + }, { name = "cloneId", display = L["Clone per Event"], diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 7292a41..9a7d756 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -712,17 +712,6 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 untriggerCheck = true; end elseif (data.statesParameter == "unit") then - if optionsEvent then - if Private.multiUnitUnits[data.trigger.unit] then - arg1 = next(Private.multiUnitUnits[data.trigger.unit]) - elseif data.trigger.unit == "nameplate" then - arg1 = next(C_NamePlate.GetNamePlates()) - else - arg1 = data.trigger.unit - end - elseif event == "FRAME_UPDATE" and (not Private.multiUnitUnits[data.trigger.unit] or data.trigger.unit ~= "nameplate") then - arg1 = data.trigger.unit - end if arg1 then if Private.multiUnitUnits[data.trigger.unit] or data.trigger.unit == "nameplate" then unitForUnitTrigger = arg1 @@ -1014,7 +1003,12 @@ function Private.ScanEventsWatchedTrigger(id, watchedTriggernums) Private.ActivateAuraEnvironment(nil) end -local function AddFakeTime(state) +local function AddFakeInformation(state, eventData) + state.autoHide = false + local canHaveDuration = eventData.prototype and eventData.prototype.canHaveDuration == "timed" + if canHaveDuration and state.expirationTime == nil then + state.progressType = "timed" + end if state.progressType == "timed" then if state.expirationTime and state.expirationTime ~= math.huge and state.expirationTime > GetTime() then return @@ -1023,38 +1017,50 @@ local function AddFakeTime(state) state.expirationTime = GetTime() + 7 state.duration = 7 end + if eventData.prototype and eventData.prototype.GetNameAndIcon then + local name, icon = Private.event_prototypes[eventData.event].GetNameAndIcon(eventData.trigger) + if state.name == nil then + state.name = name + end + if state.icon == nil then + state.icon = icon + end + end end function GenericTrigger.CreateFakeStates(id, triggernum) local data = WeakAuras.GetData(id) + local eventData = events[id][triggernum] Private.ActivateAuraEnvironment(id); local allStates = WeakAuras.GetTriggerStateForTrigger(id, triggernum); - RunTriggerFunc(allStates, events[id][triggernum], id, triggernum, "OPTIONS") - local canHaveDuration = events[id][triggernum].prototype and events[id][triggernum].prototype.canHaveDuration == "timed" + local arg1 + if eventData.statesParameter == "unit" then + local unit = eventData.trigger.unit + if Private.multiUnitUnits[unit] then + arg1 = next(Private.multiUnitUnits[unit]) + else + arg1 = unit + end + end + RunTriggerFunc(allStates, eventData, id, triggernum, "OPTIONS", arg1) local shown = 0 for id, state in pairs(allStates) do if state.show then shown = shown + 1 end - state.autoHide = false - if canHaveDuration and state.expirationTime == nil then - state.progressType = "timed" - end - AddFakeTime(state) + + AddFakeInformation(state, eventData) end if shown == 0 then local state = {} GenericTrigger.CreateFallbackState(data, triggernum, state) allStates[""] = state - state.autoHide = false - if canHaveDuration and state.expirationTime == nil then - state.progressType = "timed" - end - AddFakeTime(state) + + AddFakeInformation(state, eventData) end Private.ActivateAuraEnvironment(nil); @@ -3558,7 +3564,7 @@ end function GenericTrigger.GetDelay(data) if data.event then local prototype = Private.event_prototypes[data.event] - if prototype and prototype.delayEvents then + if prototype and prototype.type == data.type and prototype.delayEvents then local trigger = data.trigger if trigger.use_delay and type(trigger.delay) == "number" and trigger.delay > 0 then return trigger.delay @@ -3649,11 +3655,15 @@ function GenericTrigger.GetNameAndIcon(data, triggernum) local icon, name if (Private.category_event_prototype[trigger.type]) then if(trigger.event and Private.event_prototypes[trigger.event]) then - if(Private.event_prototypes[trigger.event].iconFunc) then - icon = Private.event_prototypes[trigger.event].iconFunc(trigger); - end - if(Private.event_prototypes[trigger.event].nameFunc) then - name = Private.event_prototypes[trigger.event].nameFunc(trigger); + if (Private.event_prototypes[trigger.event].GetNameAndIcon) then + return Private.event_prototypes[trigger.event].GetNameAndIcon(trigger) + else + if(Private.event_prototypes[trigger.event].iconFunc) then + icon = Private.event_prototypes[trigger.event].iconFunc(trigger); + end + if(Private.event_prototypes[trigger.event].nameFunc) then + name = Private.event_prototypes[trigger.event].nameFunc(trigger); + end end end end @@ -3983,22 +3993,28 @@ function GenericTrigger.CreateFallbackState(data, triggernum, state) Private.ActivateAuraEnvironment(data.id, "", state); local trigger = data.triggers[triggernum].trigger - if (event.nameFunc) then - local ok, name = pcall(event.nameFunc, trigger); + + if event.GetNameAndIcon then + local ok, name, icon = pcall(event.GetNameAndIcon, trigger); + state.name = ok and name or nil; + state.icon = ok and icon or nil; if not ok then - Private.GetErrorHandlerUid(data.uid, L["Name Function (fallback state)"]) - state.name = nil - else - state.name = name or nil + Private.GetErrorHandlerUid(data.uid, L["GetNameAndIcon Function (fallback state)"]) end - end - if (event.iconFunc) then - local ok, icon = pcall(event.iconFunc, trigger); - if not ok then - Private.GetErrorHandlerUid(data.uid, L["Icon Function (fallback state)"]) - state.icon = nil - else - state.icon = icon or nil + else + if (event.nameFunc) then + local ok, name = pcall(event.nameFunc, trigger); + state.name = ok and name or nil; + if not ok then + Private.GetErrorHandlerUid(data.uid, L["Name Function (fallback state)"]) + end + end + if (event.iconFunc) then + local ok, icon = pcall(event.iconFunc, trigger); + state.icon = ok and icon or nil; + if not ok then + Private.GetErrorHandlerUid(data.uid, L["Icon Function (fallback state)"]) + end end end diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index cde1b76..07bff87 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1453,5 +1453,16 @@ function Private.Modernize(data) end end + if data.internalVersion < 68 then + if data.parent then + local parentData = WeakAuras.GetData(data.parent) + if parentData and parentData.regionType == "dynamicgroup" then + if data.anchorFrameParent == nil then + data.anchorFrameParent = false + 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 6f1927c..8408ad7 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -5980,6 +5980,36 @@ Private.event_prototypes = { end }, }, + GetNameAndIcon = function(trigger) + local name, icon, spellId, _ + if trigger.use_spellNames and type(trigger.spellNames) == "table" then + for _, spellName in ipairs(trigger.spellNames) do + spellId = WeakAuras.SafeToNumber(spellName) + if spellId then + name, _, icon = GetSpellInfo(spellName) + if name and icon then + return name, icon + end + elseif not tonumber(spellName) then + name, _, icon = GetSpellInfo(spellName) + if name and icon then + return name, icon + end + end + end + end + if trigger.use_spellIds and type(trigger.spellIds) == "table" then + for _, spellIdString in ipairs(trigger.spellIds) do + spellId = WeakAuras.SafeToNumber(spellIdString) + if spellId then + name, _, icon = GetSpellInfo(spellIdString) + if name and icon then + return name, icon + end + end + end + end + end, automaticrequired = true, }, ["Character Stats"] = { diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 7e591ff..f3a3e1b 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1365,7 +1365,12 @@ local function modify(parent, region, data) end controlPoint:SetWidth(regionData.dimensions.width) controlPoint:SetHeight(regionData.dimensions.height) - if data.anchorFrameParent then + if (data.anchorFrameParent + or data.anchorFrameParent == nil) + and not (data.anchorFrameType == "SCREEN" + or data.anchorFrameType == "UIPARENT" + or data.anchorFrameType == "MOUSE") + and not data.useAnchorPerUnit then controlPoint:SetParent(frame == "" and self.relativeTo or frame) else controlPoint:SetParent(self) diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 692edea..f0ca9b6 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -485,6 +485,20 @@ function WeakAuras.Import(inData, target, callbackFunc) return nil, "Invalid import data." end + --[[ + local highestVersion = data.internalVersion or 0 + if children then + for _, child in ipairs(children) do + highestVersion = max(highestVersion, child.internalVersion or 0) + end + end + if highestVersion > WeakAuras.InternalVersion() then + -- Do not run PreAdd but still show Import Window + tooltipLoading = nil; + return ImportNow(data, children, target, nil, callbackFunc) + end + ]] + if version < 2000 then if children then data.controlledChildren = {} @@ -495,7 +509,6 @@ function WeakAuras.Import(inData, target, callbackFunc) end end - local status, msg = true, "" if type(target) ~= 'nil' then local uid = type(target) == 'table' and target.uid or target local targetData = Private.GetDataByUID(uid) diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 721635a..b51ebca 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1,6 +1,6 @@ local AddonName, Private = ... -local internalVersion = 67 +local internalVersion = 68 -- Lua APIs local insert = table.insert @@ -1998,7 +1998,7 @@ StaticPopupDialogs["WEAKAURAS_CONFIRM_REPAIR"] = { RepairDatabase() end, OnShow = function(self) - local AutomaticRepairText = L["WeakAuras has detected that it has been downgraded.\nYour saved auras may no longer work properly.\nWould you like to run the |cffff0000EXPERIMENTAL|r repair tool? This will overwrite any changes you have made since the last database upgrade.\nLast upgrade: %s"] + local AutomaticRepairText = L["WeakAuras has detected that it has been downgraded.\nYour saved auras may no longer work properly.\nWould you like to run the |cffff0000EXPERIMENTAL|r repair tool? This will overwrite any changes you have made since the last database upgrade.\nLast upgrade: %s\n\n|cffff0000You should BACKUP your WTF folder BEFORE pressing this button.|r"] local ManualRepairText = L["Are you sure you want to run the |cffff0000EXPERIMENTAL|r repair tool?\nThis will overwrite any changes you have made since the last database upgrade.\nLast upgrade: %s"] if self.data.reason == "user" then diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index 41e4da4..894ff34 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -350,6 +350,7 @@ local Actions = { end } + local function GetAction(target, area) if target and area then if area == "GROUP" then diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index 77dea31..840c047 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -1306,6 +1306,32 @@ local methods = { self:ReleaseChildren() self:AddBasicInformationWidgets(data, sender) + --[[ + do + local highestVersion = data.internalVersion or 0 + if children then + for _, child in ipairs(children) do + highestVersion = max(highestVersion, child.internalVersion or 0) + end + end + + if (highestVersion > WeakAuras.InternalVersion()) then + local highestVersionWarning = AceGUI:Create("Label") + highestVersionWarning:SetFontObject(GameFontHighlight) + highestVersionWarning:SetFullWidth(true) + highestVersionWarning:SetText(L["This aura was created with a newer version of WeakAuras.\nUpgrade your version of WeakAuras or wait for next release before installing this aura."]) + highestVersionWarning:SetColor(1, 0, 0) + self:AddChild(highestVersionWarning) + self.importButton:Hide() + self.viewCodeButton:Hide() + self:DoLayout() + return + else + self.importButton:Show() + end + end + ]] + local matchInfoResult = AceGUI:Create("Label") matchInfoResult:SetFontObject(GameFontHighlight) matchInfoResult:SetFullWidth(true) @@ -1420,6 +1446,7 @@ local methods = { self:AddChild(scamCheckText) end + -- Let people install auras that are newer than their version of WeakAuras local highestVersion = data.internalVersion or 0 if children then for _, child in ipairs(children) do diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 73a0951..4a6d2e9 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -1555,6 +1555,7 @@ function OptionsPrivate.Drop(mainAura, target, action, area) frame:SetLoadProgressVisible(false) OptionsPrivate.SortDisplayButtons() OptionsPrivate.UpdateButtonsScroll() + WeakAuras.FillOptions() end local co1 = coroutine.create(func1) From efa2dae58a51fd2a76c0d1dc20e9339d28f69d13 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 17 Jan 2025 15:35:11 +0100 Subject: [PATCH 053/153] from retail --- WeakAuras/AuraEnvironment.lua | 1 - WeakAuras/Prototypes.lua | 40 +++++++++++++++++++ WeakAuras/RegionTypes/AuraBar.lua | 12 +++--- WeakAuras/RegionTypes/DynamicGroup.lua | 6 +-- WeakAuras/RegionTypes/Group.lua | 6 +-- WeakAuras/RegionTypes/Icon.lua | 12 +++--- WeakAuras/RegionTypes/Model.lua | 10 ++--- WeakAuras/RegionTypes/ProgressTexture.lua | 12 +++--- WeakAuras/RegionTypes/RegionPrototype.lua | 22 +++++----- WeakAuras/RegionTypes/StopMotion.lua | 6 +-- WeakAuras/RegionTypes/Text.lua | 12 +++--- WeakAuras/RegionTypes/Texture.lua | 10 ++--- WeakAuras/WeakAuras.lua | 4 +- WeakAurasOptions/CommonOptions.lua | 28 +++++++++++-- WeakAurasOptions/RegionOptions/AuraBar.lua | 2 +- .../RegionOptions/ProgressTexture.lua | 2 +- 16 files changed, 122 insertions(+), 63 deletions(-) diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index 2772dd6..dd90435 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -435,7 +435,6 @@ local FakeWeakAurasMixin = { }, blockedTables = { ModelPaths = true, - regionPrototype = true, RealTimeProfilingWindow = true, -- Note these shouldn't exist in the WeakAuras namespace, but moving them takes a bit of effort, -- so for now just block them and clean them up later diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 8408ad7..64e4e3d 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -1383,6 +1383,9 @@ Private.event_prototypes = { AddUnitEventForEvents(result, unit, "UNIT_NAME_UPDATE") AddUnitEventForEvents(result, unit, "UNIT_FLAGS") AddUnitEventForEvents(result, unit, "PLAYER_FLAGS_CHANGED") + if trigger.use_inRange then + AddUnitEventForEvents(result, unit, "UNIT_IN_RANGE_UPDATE") + end return result; end, internal_events = function(trigger) @@ -1548,6 +1551,16 @@ Private.event_prototypes = { end, init = "UnitIsConnected(unit)" }, + { + name = "inRange", + display = L["In Range"], + type = "toggle", + width = WeakAuras.doubleWidth, + enable = function(trigger) + return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party" + end, + init = "UnitInRange(unit)" + }, { name = "hostility", display = L["Hostility"], @@ -1790,6 +1803,9 @@ Private.event_prototypes = { if trigger.use_ignoreDead or trigger.use_ignoreDisconnected then AddUnitEventForEvents(result, unit, "UNIT_FLAGS") end + if trigger.use_inRange then + AddUnitEventForEvents(result, unit, "UNIT_IN_RANGE_UPDATE") + end return result end, internal_events = function(trigger) @@ -2049,6 +2065,16 @@ Private.event_prototypes = { end, init = "UnitIsConnected(unit)" }, + { + name = "inRange", + display = L["In Range"], + type = "toggle", + width = WeakAuras.doubleWidth, + enable = function(trigger) + return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party" + end, + init = "UnitInRange(unit)" + }, { name = "nameplateType", display = L["Nameplate Type"], @@ -2099,6 +2125,9 @@ Private.event_prototypes = { end tinsert(result.events, "FRAME_UPDATE") end + if trigger.use_inRange then + AddUnitEventForEvents(result, unit, "UNIT_IN_RANGE_UPDATE") + end return result; end, internal_events = function(trigger) @@ -2389,6 +2418,16 @@ Private.event_prototypes = { end, init = "UnitIsConnected(unit)" }, + { + name = "inRange", + display = L["In Range"], + type = "toggle", + width = WeakAuras.doubleWidth, + enable = function(trigger) + return trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party" + end, + init = "UnitInRange(unit)" + }, { name = "nameplateType", display = L["Nameplate Type"], @@ -6558,6 +6597,7 @@ Private.event_prototypes = { if trigger.use_instance_difficulty ~= nil or trigger.use_instance_size ~= nil + or trigger.use_pvpflagged ~= nil then tinsert(events, "WA_DELAYED_PLAYER_ENTERING_WORLD") end diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 1e10b83..6a240bc 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -38,8 +38,8 @@ local default = { zoom = 0 }; -WeakAuras.regionPrototype.AddAdjustedDurationToDefault(default); -WeakAuras.regionPrototype.AddAlphaToDefault(default); +Private.regionPrototype.AddAdjustedDurationToDefault(default); +Private.regionPrototype.AddAlphaToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; @@ -132,7 +132,7 @@ local properties = { }, }; -WeakAuras.regionPrototype.AddProperties(properties, default); +Private.regionPrototype.AddProperties(properties, default); local function GetProperties(data) local overlayInfo = Private.GetOverlayInfo(data); @@ -1051,7 +1051,7 @@ local function create(parent) end end - WeakAuras.regionPrototype.create(region); + Private.regionPrototype.create(region); for k, f in pairs(funcs) do region[k] = f @@ -1075,7 +1075,7 @@ local function modify(parent, region, data) region.text = nil region.stacks = nil - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); -- Localize local bar, iconFrame, icon = region.bar, region.iconFrame, region.icon; @@ -1355,7 +1355,7 @@ local function modify(parent, region, data) --- Update internal bar alignment region.bar:Update(); - WeakAuras.regionPrototype.modifyFinish(parent, region, data); + Private.regionPrototype.modifyFinish(parent, region, data); end local function validate(data) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index f3a3e1b..7451252 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -119,7 +119,7 @@ local function create(parent) region.selfPoint = "TOPLEFT" region.controlPoints = CreateObjectPool(createControlPoint, releaseControlPoint) region.controlPoints.parent = region - WeakAuras.regionPrototype.create(region) + Private.regionPrototype.create(region) region.suspended = 0 local oldSetFrameLevel = region.SetFrameLevel @@ -1041,7 +1041,7 @@ end local function modify(parent, region, data) Private.FixGroupChildrenOrderForGroup(data) region:SetScale(data.scale and data.scale > 0 and data.scale <= 10 and data.scale or 1) - WeakAuras.regionPrototype.modify(parent, region, data) + Private.regionPrototype.modify(parent, region, data) if data.border and not data.useAnchorPerUnit then local background = region.background @@ -1560,7 +1560,7 @@ local function modify(parent, region, data) region:ReloadControlledChildren() - WeakAuras.regionPrototype.modifyFinish(parent, region, data) + Private.regionPrototype.modifyFinish(parent, region, data) end WeakAuras.RegisterRegionType("dynamicgroup", create, modify, default) diff --git a/WeakAuras/RegionTypes/Group.lua b/WeakAuras/RegionTypes/Group.lua index 1ed3702..eab0d7c 100644 --- a/WeakAuras/RegionTypes/Group.lua +++ b/WeakAuras/RegionTypes/Group.lua @@ -35,7 +35,7 @@ local function create(parent) local border = CreateFrame("Frame", nil, region); region.border = border; - WeakAuras.regionPrototype.create(region); + Private.regionPrototype.create(region); local oldSetFrameLevel = region.SetFrameLevel region.SetFrameLevel = function(self, level) @@ -90,7 +90,7 @@ local function modify(parent, region, data) else data.selfPoint = "CENTER"; end - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); -- Localize local border = region.border; @@ -179,7 +179,7 @@ local function modify(parent, region, data) region.border:Hide() end - WeakAuras.regionPrototype.modifyFinish(parent, region, data); + Private.regionPrototype.modifyFinish(parent, region, data); end -- Register new region type with WeakAuras diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index c2e23f5..78b4bf3 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -35,7 +35,7 @@ local default = { cooldownEdge = false }; -WeakAuras.regionPrototype.AddAlphaToDefault(default); +Private.regionPrototype.AddAlphaToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; @@ -101,7 +101,7 @@ local properties = { } }; -WeakAuras.regionPrototype.AddProperties(properties, default); +Private.regionPrototype.AddProperties(properties, default); local function GetProperties(data) local result = CopyTable(properties) @@ -140,7 +140,7 @@ end local function AnchorSubRegion(self, subRegion, anchorType, selfPoint, anchorPoint, anchorXOffset, anchorYOffset) if anchorType == "area" then - WeakAuras.regionPrototype.AnchorSubRegion(selfPoint == "region" and self or self.icon, subRegion, anchorType, selfPoint, anchorPoint, anchorXOffset, anchorYOffset) + Private.regionPrototype.AnchorSubRegion(selfPoint == "region" and self or self.icon, subRegion, anchorType, selfPoint, anchorPoint, anchorXOffset, anchorYOffset) else subRegion:ClearAllPoints() anchorPoint = anchorPoint or "CENTER" @@ -335,7 +335,7 @@ local function create(parent, data) end end - WeakAuras.regionPrototype.create(region); + Private.regionPrototype.create(region); region.AnchorSubRegion = AnchorSubRegion @@ -347,7 +347,7 @@ local function modify(parent, region, data) region.stacks = nil region.text2 = nil - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); local button, icon, cooldown = region.button, region.icon, region.cooldown; @@ -674,7 +674,7 @@ local function modify(parent, region, data) end end - WeakAuras.regionPrototype.modifyFinish(parent, region, data); + Private.regionPrototype.modifyFinish(parent, region, data); --- WORKAROUND -- This fixes a issue with barmodels not appearing on icons if the diff --git a/WeakAuras/RegionTypes/Model.lua b/WeakAuras/RegionTypes/Model.lua index b543eac..b476f09 100644 --- a/WeakAuras/RegionTypes/Model.lua +++ b/WeakAuras/RegionTypes/Model.lua @@ -56,7 +56,7 @@ local properties = { }, } -WeakAuras.regionPrototype.AddProperties(properties, default); +Private.regionPrototype.AddProperties(properties, default); local function GetProperties(data) return properties; @@ -79,13 +79,13 @@ local function create(parent) local border = CreateFrame("Frame", nil, region); region.border = border; - WeakAuras.regionPrototype.create(region); + Private.regionPrototype.create(region); for k, v in pairs (regionFunctions) do region[k] = v end - region.AnchorSubRegion = WeakAuras.regionPrototype.AnchorSubRegion + region.AnchorSubRegion = Private.regionPrototype.AnchorSubRegion -- Return complete region return region; @@ -175,7 +175,7 @@ end -- Modify a given region/display local function modify(parent, region, data) - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); -- Localize local border = region.border; @@ -273,7 +273,7 @@ local function modify(parent, region, data) end end - WeakAuras.regionPrototype.modifyFinish(parent, region, data); + Private.regionPrototype.modifyFinish(parent, region, data); end -- Work around for movies and world map hiding all models diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 060de36..4feea79 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -113,9 +113,9 @@ local default = { slantMode = "INSIDE" }; -WeakAuras.regionPrototype.AddAlphaToDefault(default); +Private.regionPrototype.AddAlphaToDefault(default); -WeakAuras.regionPrototype.AddAdjustedDurationToDefault(default); +Private.regionPrototype.AddAdjustedDurationToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; @@ -176,7 +176,7 @@ local properties = { } } -WeakAuras.regionPrototype.AddProperties(properties, default); +Private.regionPrototype.AddProperties(properties, default); local function GetProperties(data) local overlayInfo = Private.GetOverlayInfo(data); @@ -462,7 +462,7 @@ local function create(parent) region.duration = 0; region.expirationTime = math.huge; - WeakAuras.regionPrototype.create(region); + Private.regionPrototype.create(region); return region; end @@ -474,7 +474,7 @@ local function TimerTick(self) end local function modify(parent, region, data) - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); local background, foreground = region.background, region.foreground; local foregroundSpinner, backgroundSpinner = region.foregroundSpinner, region.backgroundSpinner; @@ -1029,7 +1029,7 @@ local function modify(parent, region, data) end end - WeakAuras.regionPrototype.modifyFinish(parent, region, data); + Private.regionPrototype.modifyFinish(parent, region, data); end local function validate(data) diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index b180cf0..5fbd1f5 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -4,21 +4,21 @@ local AddonName, Private = ... local WeakAuras = WeakAuras; local L = WeakAuras.L; -WeakAuras.regionPrototype = {}; +Private.regionPrototype = {}; -- Alpha -function WeakAuras.regionPrototype.AddAlphaToDefault(default) +function Private.regionPrototype.AddAlphaToDefault(default) default.alpha = 1.0; end -- Adjusted Duration -function WeakAuras.regionPrototype.AddAdjustedDurationToDefault(default) +function Private.regionPrototype.AddAdjustedDurationToDefault(default) default.useAdjustededMax = false; default.useAdjustededMin = false; end -function WeakAuras.regionPrototype.AddAdjustedDurationOptions(options, data, order) +function Private.regionPrototype.AddAdjustedDurationOptions(options, data, order) options.useAdjustededMin = { type = "toggle", width = WeakAuras.normalWidth, @@ -100,7 +100,7 @@ function Private.GetAnchorsForData(parentData, type) end -- Sound / Chat Message / Custom Code -function WeakAuras.regionPrototype.AddProperties(properties, defaultsForRegion) +function Private.regionPrototype.AddProperties(properties, defaultsForRegion) properties["sound"] = { display = L["Sound"], action = "SoundPlay", @@ -452,9 +452,9 @@ local function AnchorSubRegion(self, subRegion, anchorType, selfPoint, anchorPoi end end -WeakAuras.regionPrototype.AnchorSubRegion = AnchorSubRegion +Private.regionPrototype.AnchorSubRegion = AnchorSubRegion -function WeakAuras.regionPrototype.create(region) +function Private.regionPrototype.create(region) local defaultsForRegion = Private.regionTypes[region.regionType] and Private.regionTypes[region.regionType].default; region.SoundPlay = SoundPlay; region.SoundRepeatStop = SoundRepeatStop; @@ -500,7 +500,7 @@ end -- SetDurationInfo -function WeakAuras.regionPrototype.modify(parent, region, data) +function Private.regionPrototype.modify(parent, region, data) region.state = nil region.states = nil region.subRegionEvents:ClearSubscribers() @@ -587,7 +587,7 @@ function WeakAuras.regionPrototype.modify(parent, region, data) end, true) end -function WeakAuras.regionPrototype.modifyFinish(parent, region, data) +function Private.regionPrototype.modifyFinish(parent, region, data) -- Sync subRegions if region.subRegions then for index, subRegion in pairs(region.subRegions) do @@ -674,7 +674,7 @@ local function TimerTickForSetDuration(self) self:SetTime(max - adjustMin, self.expirationTime - adjustMin, self.inverse); end -function WeakAuras.regionPrototype.AddSetDurationInfo(region) +function Private.regionPrototype.AddSetDurationInfo(region) if (region.SetValue and region.SetTime) then region.generatedSetDurationInfo = true; @@ -704,7 +704,7 @@ function WeakAuras.regionPrototype.AddSetDurationInfo(region) end -- Expand/Collapse function -function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, parent, parentRegionType) +function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent, parentRegionType) local uid = data.uid local id = data.id local inDynamicGroup = parentRegionType == "dynamicgroup"; diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index 07bfb2a..575b738 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -85,7 +85,7 @@ local properties = { }, } -WeakAuras.regionPrototype.AddProperties(properties, default); +Private.regionPrototype.AddProperties(properties, default); local function create(parent) local frame = CreateFrame("Frame", nil, UIParent); @@ -102,7 +102,7 @@ local function create(parent) frame.foreground = foreground; foreground:SetAllPoints(frame); - WeakAuras.regionPrototype.create(frame); + Private.regionPrototype.create(frame); return frame; end @@ -151,7 +151,7 @@ local function SetFrameViaFrames(self, texture, frame) end local function modify(parent, region, data) - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); region.foreground = region.foreground or {} region.background = region.background or {} local pattern = "%.x(%d+)y(%d+)f(%d+)%.[tb][gl][ap]" diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index 7270f61..d1b3f5d 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -52,7 +52,7 @@ local properties = { }, } -WeakAuras.regionPrototype.AddProperties(properties, default); +Private.regionPrototype.AddProperties(properties, default); local function GetProperties(data) return properties; @@ -71,13 +71,13 @@ local function create(parent) region.duration = 0; region.expirationTime = math.huge; - WeakAuras.regionPrototype.create(region); + Private.regionPrototype.create(region); return region; end local function modify(parent, region, data) - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); local text = region.text; local fontPath = SharedMedia:Fetch("font", data.font); @@ -334,7 +334,7 @@ local function modify(parent, region, data) region:ConfigureTextUpdate() region:ConfigureSubscribers() - WeakAuras.regionPrototype.modifyFinish(parent, region, data); + Private.regionPrototype.modifyFinish(parent, region, data); end local function validate(data) @@ -346,7 +346,7 @@ WeakAuras.RegisterRegionType("text", create, modify, default, GetProperties, val -- Fallback region type local function fallbackmodify(parent, region, data) - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); local text = region.text; text:SetFont(STANDARD_TEXT_FONT, data.fontSize < 33 and data.fontSize or 33, data.outline and "OUTLINE" or nil); @@ -363,7 +363,7 @@ local function fallbackmodify(parent, region, data) region.Update = function() end - WeakAuras.regionPrototype.modifyFinish(parent, region, data); + Private.regionPrototype.modifyFinish(parent, region, data); end WeakAuras.RegisterRegionType("fallback", create, fallbackmodify, default); diff --git a/WeakAuras/RegionTypes/Texture.lua b/WeakAuras/RegionTypes/Texture.lua index d4ffd3b..1736793 100644 --- a/WeakAuras/RegionTypes/Texture.lua +++ b/WeakAuras/RegionTypes/Texture.lua @@ -22,7 +22,7 @@ local default = { frameStrata = 1 }; -WeakAuras.regionPrototype.AddAlphaToDefault(default); +Private.regionPrototype.AddAlphaToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; @@ -62,7 +62,7 @@ local properties = { } } -WeakAuras.regionPrototype.AddProperties(properties, default); +Private.regionPrototype.AddProperties(properties, default); local function create(parent) local region = CreateFrame("Frame", nil, UIParent); @@ -75,13 +75,13 @@ local function create(parent) region.texture = texture; texture:SetAllPoints(region); - WeakAuras.regionPrototype.create(region); + Private.regionPrototype.create(region); return region; end local function modify(parent, region, data) - WeakAuras.regionPrototype.modify(parent, region, data); + Private.regionPrototype.modify(parent, region, data); region.texture:SetTexture(data.texture); region.texture:SetDesaturated(data.desaturate) region:SetWidth(data.width); @@ -230,7 +230,7 @@ local function modify(parent, region, data) region.GetRotation = nil; end - WeakAuras.regionPrototype.modifyFinish(parent, region, data); + Private.regionPrototype.modifyFinish(parent, region, data); end local function validate(data) diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index b51ebca..22e0ff0 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2873,8 +2873,8 @@ function Private.SetRegion(data, cloneId) local anim_cancelled = loginFinished and Private.CancelAnimation(region, true, true, true, true, true, true); regionTypes[regionType].modify(parent, region, data); - WeakAuras.regionPrototype.AddSetDurationInfo(region); - WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, parent, parent.regionType) + Private.regionPrototype.AddSetDurationInfo(region); + Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent, parent.regionType) data.animation = data.animation or {}; data.animation.start = data.animation.start or {type = "none"}; diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index c05975c..cf00eb3 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -374,8 +374,17 @@ end local function CreateHiddenAll(subOption) return function(data, info) + local mainOptions = OptionsPrivate.EnsureOptions(data, subOption) + for i=1,#info do + mainOptions = mainOptions.args[info[i]]; + end + if(#data.controlledChildren == 0) then - return true; + if mainOptions.hiddenAllIfAnyHidden then + return false + else + return true + end end for child in OptionsPrivate.Private.TraverseLeafs(data) do @@ -387,13 +396,24 @@ local function CreateHiddenAll(subOption) childOptionTable[i] = childOption; end if (childOption) then - if (not hiddenChild(childOptionTable, info)) then - return false; + local childHidden = hiddenChild(childOptionTable, info) + if mainOptions.hiddenAllIfAnyHidden then + if childHidden then + return true + end + else + if not childHidden then + return false + end end end end - return true; + if mainOptions.hiddenAllIfAnyHidden then + return false + else + return true + end end end diff --git a/WeakAurasOptions/RegionOptions/AuraBar.lua b/WeakAurasOptions/RegionOptions/AuraBar.lua index 47c0517..e56f894 100644 --- a/WeakAurasOptions/RegionOptions/AuraBar.lua +++ b/WeakAurasOptions/RegionOptions/AuraBar.lua @@ -385,7 +385,7 @@ local function createOptions(id, data) }, }; - options = WeakAuras.regionPrototype.AddAdjustedDurationOptions(options, data, 36.5); + options = OptionsPrivate.Private.regionPrototype.AddAdjustedDurationOptions(options, data, 36.5); local overlayInfo = OptionsPrivate.Private.GetOverlayInfo(data); if (overlayInfo and next(overlayInfo)) then diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index 01a0625..3238ada 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -288,7 +288,7 @@ local function createOptions(id, data) name = "", }, }; - options = WeakAuras.regionPrototype.AddAdjustedDurationOptions(options, data, 57); + options = OptionsPrivate.Private.regionPrototype.AddAdjustedDurationOptions(options, data, 57); local overlayInfo = OptionsPrivate.Private.GetOverlayInfo(data); if (overlayInfo and next(overlayInfo)) then From c4205b0c2954211a29762f4db16d25de839f7a41 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 17 Jan 2025 16:47:27 +0100 Subject: [PATCH 054/153] from retail --- WeakAuras/GenericTrigger.lua | 290 +++++++++++++++++------------------ 1 file changed, 145 insertions(+), 145 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 9a7d756..89ce08a 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1018,7 +1018,7 @@ local function AddFakeInformation(state, eventData) state.duration = 7 end if eventData.prototype and eventData.prototype.GetNameAndIcon then - local name, icon = Private.event_prototypes[eventData.event].GetNameAndIcon(eventData.trigger) + local name, icon = eventData.prototype.GetNameAndIcon(eventData.trigger) if state.name == nil then state.name = name end @@ -3523,31 +3523,35 @@ function WeakAuras.GetUniqueCloneId() return uniqueId; end +function GenericTrigger.GetPrototype(trigger) + if trigger.type and trigger.event then + if Private.category_event_prototype[trigger.type] then + return Private.event_prototypes[trigger.event] + end + end +end + function GenericTrigger.CanHaveDuration(data, triggernum) local trigger = data.triggers[triggernum].trigger - if (Private.category_event_prototype[trigger.type]) then - if trigger.event then - local prototype = Private.event_prototypes[trigger.event] - if prototype then - if prototype.durationFunc then - if(type(prototype.init) == "function") then - prototype.init(trigger); - end - local current, maximum, custom = prototype.durationFunc(trigger); - current = type(current) ~= "number" and current or 0 - maximum = type(maximum) ~= "number" and maximum or 0 - if(custom) then - return {current = current, maximum = maximum}; - else - return "timed"; - end - elseif prototype.canHaveDuration then - return prototype.canHaveDuration, prototype.useModRate - elseif prototype.timedrequired then - return "timed" - end + local prototype = GenericTrigger.GetPrototype(trigger) + if prototype then + if prototype.durationFunc then + if(type(prototype.init) == "function") then + prototype.init(trigger); end + local current, maximum, custom = prototype.durationFunc(trigger); + current = type(current) ~= "number" and current or 0 + maximum = type(maximum) ~= "number" and maximum or 0 + if(custom) then + return {current = current, maximum = maximum}; + else + return "timed"; + end + elseif prototype.canHaveDuration then + return prototype.canHaveDuration, prototype.useModRate + elseif prototype.timedrequired then + return "timed" end elseif (trigger.type == "custom") then if trigger.custom_type == "event" and trigger.custom_hide == "timed" and trigger.duration then @@ -3563,8 +3567,8 @@ end function GenericTrigger.GetDelay(data) if data.event then - local prototype = Private.event_prototypes[data.event] - if prototype and prototype.type == data.type and prototype.delayEvents then + local prototype = GenericTrigger.GetPrototype(data.trigger) + if prototype and prototype.delayEvents then local trigger = data.trigger if trigger.use_delay and type(trigger.delay) == "number" and trigger.delay > 0 then return trigger.delay @@ -3587,10 +3591,11 @@ function GenericTrigger.GetOverlayInfo(data, triggernum) local trigger = data.triggers[triggernum].trigger - if (trigger.type ~= "custom" and trigger.event and Private.event_prototypes[trigger.event] and Private.event_prototypes[trigger.event].overlayFuncs) then + local prototype = GenericTrigger.GetPrototype(trigger) + if (prototype and prototype.overlayFuncs) then result = {}; local dest = 1; - for i, v in ipairs(Private.event_prototypes[trigger.event].overlayFuncs) do + for i, v in ipairs(prototype.overlayFuncs) do local enable = true if type(v.enable) == "function" then enable = v.enable(trigger) @@ -3653,17 +3658,16 @@ end function GenericTrigger.GetNameAndIcon(data, triggernum) local trigger = data.triggers[triggernum].trigger local icon, name - if (Private.category_event_prototype[trigger.type]) then - if(trigger.event and Private.event_prototypes[trigger.event]) then - if (Private.event_prototypes[trigger.event].GetNameAndIcon) then - return Private.event_prototypes[trigger.event].GetNameAndIcon(trigger) - else - if(Private.event_prototypes[trigger.event].iconFunc) then - icon = Private.event_prototypes[trigger.event].iconFunc(trigger); - end - if(Private.event_prototypes[trigger.event].nameFunc) then - name = Private.event_prototypes[trigger.event].nameFunc(trigger); - end + local prototype = GenericTrigger.GetPrototype(trigger) + if prototype then + if prototype.GetNameAndIcon then + return prototype.GetNameAndIcon(trigger) + else + if prototype.iconFunc then + icon = prototype.iconFunc(trigger) + end + if prototype.nameFunc then + name = prototype.nameFunc(trigger) end end end @@ -3677,13 +3681,12 @@ end -- @return string function GenericTrigger.CanHaveTooltip(data, triggernum) local trigger = data.triggers[triggernum].trigger - if (Private.category_event_prototype[trigger.type]) then - if (trigger.event and Private.event_prototypes[trigger.event]) then - if(Private.event_prototypes[trigger.event].hasSpellID) then - return "spell"; - elseif(Private.event_prototypes[trigger.event].hasItemID) then - return "item"; - end + local prototype = GenericTrigger.GetPrototype(trigger) + if prototype then + if prototype.hasSpellID then + return "spell"; + elseif prototype.hasItemID then + return "item"; end end @@ -3726,15 +3729,14 @@ function GenericTrigger.SetToolTip(trigger, state) end end - if (Private.category_event_prototype[trigger.type]) then - if (trigger.event and Private.event_prototypes[trigger.event]) then - if(Private.event_prototypes[trigger.event].hasSpellID) then - GameTooltip:SetSpellByID(trigger.spellName); - return true - elseif(Private.event_prototypes[trigger.event].hasItemID) then - GameTooltip:SetHyperlink("item:"..trigger.itemName..":0:0:0:0:0:0:0") - return true - end + local prototype = GenericTrigger.GetPrototype(trigger) + if prototype then + if prototype.hasSpellID then + GameTooltip:SetSpellByID(trigger.spellName); + return true + elseif prototype.hasItemID then + GameTooltip:SetHyperlink("item:"..trigger.itemName..":0:0:0:0:0:0:0") + return true end end return false @@ -3743,32 +3745,30 @@ end function GenericTrigger.GetAdditionalProperties(data, triggernum) local trigger = data.triggers[triggernum].trigger local ret = ""; - if (Private.category_event_prototype[trigger.type]) then - if (trigger.event and Private.event_prototypes[trigger.event]) then - local found = false; - local additional = "" - for _, v in pairs(Private.event_prototypes[trigger.event].args) do - local enable = true - if(type(v.enable) == "function") then - enable = v.enable(trigger) - elseif type(v.enable) == "boolean" then - enable = v.enable - end - if (enable and v.store and v.name and v.display) then - found = true; - additional = additional .. "|cFFFF0000%".. triggernum .. "." .. v.name .. "|r - " .. v.display .. "\n"; - end + local prototype = GenericTrigger.GetPrototype(trigger) + if prototype then + local found = false; + local additional = "" + for _, v in pairs(prototype.args) do + local enable = true + if(type(v.enable) == "function") then + enable = v.enable(trigger) + elseif type(v.enable) == "boolean" then + enable = v.enable end - if Private.event_prototypes[trigger.event].countEvents then + if (enable and v.store and v.name and v.display) then found = true; - additional = additional .. "|cFFFF0000%".. triggernum .. ".count|r - " .. L["Count"] .. "\n"; - end - - if (found) then - ret = ret .. additional; + additional = additional .. "|cFFFF0000%".. triggernum .. "." .. v.name .. "|r - " .. v.display .. "\n"; end end + if prototype.countEvents then + found = true; + additional = additional .. "|cFFFF0000%".. triggernum .. ".count|r - " .. L["Count"] .. "\n"; + end + if (found) then + ret = ret .. additional; + end else if (trigger.custom_type == "stateupdate") then local variables = GenericTrigger.GetTsuConditionVariables(data.id, triggernum) @@ -3845,90 +3845,89 @@ end function GenericTrigger.GetTriggerConditions(data, triggernum) local trigger = data.triggers[triggernum].trigger - if (Private.category_event_prototype[trigger.type]) then - if (trigger.event and Private.event_prototypes[trigger.event]) then - local result = {}; + local prototype = GenericTrigger.GetPrototype(trigger) + if prototype then + local result = {}; - local canHaveDuration = GenericTrigger.CanHaveDuration(data, triggernum); - local timedDuration = canHaveDuration; - local valueDuration = canHaveDuration; - if (canHaveDuration == "timed") then - valueDuration = false; - elseif (type(canHaveDuration) == "table") then - timedDuration = false; - end + local canHaveDuration = GenericTrigger.CanHaveDuration(data, triggernum); + local timedDuration = canHaveDuration; + local valueDuration = canHaveDuration; + if (canHaveDuration == "timed") then + valueDuration = false; + elseif (type(canHaveDuration) == "table") then + timedDuration = false; + end - if (timedDuration) then - result.expirationTime = commonConditions.expirationTime; - result.duration = commonConditions.duration; - result.paused = commonConditions.paused - end + if (timedDuration) then + result.expirationTime = commonConditions.expirationTime; + result.duration = commonConditions.duration; + result.paused = commonConditions.paused + end - if (valueDuration) then - result.value = commonConditions.value; - result.total = commonConditions.total; - end + if (valueDuration) then + result.value = commonConditions.value; + result.total = commonConditions.total; + end - if (Private.event_prototypes[trigger.event].stacksFunc) then - result.stacks = commonConditions.stacks; - end + if prototype.stacksFunc then + result.stacks = commonConditions.stacks; + end - if (Private.event_prototypes[trigger.event].nameFunc) then - result.name = commonConditions.name; - end + if prototype.nameFunc then + result.name = commonConditions.name; + end - for _, v in pairs(Private.event_prototypes[trigger.event].args) do - if (v.conditionType and v.name and v.display) then - local enable = true; - if (v.enable ~= nil) then - if type(v.enable) == "function" then - enable = v.enable(trigger); - elseif type(v.enable) == "boolean" then - enable = v.enable - end + for _, v in pairs(prototype.args) do + if (v.conditionType and v.name and v.display) then + local enable = true; + if (v.enable ~= nil) then + if type(v.enable) == "function" then + enable = v.enable(trigger); + elseif type(v.enable) == "boolean" then + enable = v.enable end + end - if (enable) then - result[v.name] = { - display = v.display, - type = v.conditionType - } - if (result[v.name].type == "select" or result[v.name].type == "unit") then - if (v.conditionValues) then - result[v.name].values = Private[v.conditionValues] or WeakAuras[v.conditionValues]; + if (enable) then + result[v.name] = { + display = v.display, + type = v.conditionType + } + if (result[v.name].type == "select" or result[v.name].type == "unit") then + if (v.conditionValues) then + result[v.name].values = Private[v.conditionValues] or WeakAuras[v.conditionValues]; + else + if type(v.values) == "function" then + result[v.name].values = v.values() else - if type(v.values) == "function" then - result[v.name].values = v.values() - else - result[v.name].values = Private[v.values] or WeakAuras[v.values]; - end + result[v.name].values = Private[v.values] or WeakAuras[v.values]; end end - if (v.conditionPreamble) then - result[v.name].preamble = v.conditionPreamble; - end - if (v.conditionTest) then - result[v.name].test = v.conditionTest; - end - if (v.conditionEvents) then - result[v.name].events = v.conditionEvents; - end - if (v.operator_types) then - result[v.name].operator_types = v.operator_types; - end + end + if (v.conditionPreamble) then + result[v.name].preamble = v.conditionPreamble; + end + if (v.conditionTest) then + result[v.name].test = v.conditionTest; + end + if (v.conditionEvents) then + result[v.name].events = v.conditionEvents; + end + if (v.operator_types) then + result[v.name].operator_types = v.operator_types; end end end - - if Private.event_prototypes[trigger.event].countEvents then - result.count = { - display = L["Count"], - type = "number" - } - end - - return result; end + + if prototype.countEvents then + result.count = { + display = L["Count"], + type = "number" + } + end + + return result; elseif(trigger.type == "custom") then if (trigger.custom_type == "status" or trigger.custom_type == "event") then local result = {}; @@ -4096,8 +4095,9 @@ end function GenericTrigger.GetTriggerDescription(data, triggernum, namestable) local trigger = data.triggers[triggernum].trigger - if (Private.category_event_prototype[trigger.type]) then - tinsert(namestable, {L["Trigger:"], (Private.event_prototypes[trigger.event].name or L["Undefined"])}); + local prototype = GenericTrigger.GetPrototype(trigger) + if prototype then + tinsert(namestable, {L["Trigger:"], (prototype.name or L["Undefined"])}); if(trigger.event == "Combat Log" and trigger.subeventPrefix and trigger.subeventSuffix) then tinsert(namestable, {L["Message type:"], (Private.subevent_prefix_types[trigger.subeventPrefix] or L["Undefined"]).." "..(Private.subevent_suffix_types[trigger.subeventSuffix] or L["Undefined"])}); end From b900520d5f2ce813a2b14c870e52e126984f2e51 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 17 Jan 2025 17:01:24 +0100 Subject: [PATCH 055/153] from retail --- WeakAuras/BuffTrigger2.lua | 4 ++-- WeakAuras/Prototypes.lua | 4 ++-- WeakAurasOptions/OptionsFrames/Update.lua | 10 ++++------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index c29afe7..7908dac 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -2553,9 +2553,9 @@ function BuffTrigger.SetToolTip(trigger, state) return false end if state.filter == "HELPFUL" then - GameTooltip:SetUnitBuff(state.unit, state.index) + GameTooltip:SetUnitBuff(state.unit, state.index, state.filter) elseif state.filter == "HARMFUL" then - GameTooltip:SetUnitDebuff(state.unit, state.index) + GameTooltip:SetUnitDebuff(state.unit, state.index, state.filter) end return true end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 64e4e3d..31b335f 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3817,7 +3817,7 @@ Private.event_prototypes = { nameFunc = function(trigger) local item = GetInventoryItemID("player", trigger.itemSlot or 0); if (item) then - return GetItemInfo(item); + return (GetItemInfo(item)) end end, stacksFunc = function(trigger) @@ -6756,7 +6756,7 @@ Private.event_prototypes = { } }, nameFunc = function(trigger) - return GetSpellInfo(trigger.spellId or 0) + return (GetSpellInfo(trigger.spellId or 0)) end, iconFunc = function(trigger) local _, _, icon = GetSpellInfo(trigger.spellId or 0); diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index 840c047..e47fba1 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -300,13 +300,11 @@ local function BuildUidMap(data, children, type) -- index, total, parentIsDynamicGroup: helpers that transport data between phase 1 and 2 }, - type = type -- Either old or new, only used for error checking - -- root: uid of the root - -- totalCount: count of members - -- idToUid maps from id to uid + type = type, -- Either old or new, only used for error checking + root = data.uid, -- root: uid of the root + totalCount = #children + 1, -- totalCount: count of members + idToUid = {} -- idToUid maps from id to uid } - uidMap.root = data.uid - uidMap.totalCount = #children + 1 -- Build helper map from id to uid local idToUid = {} From ad4ada1eb9a4e184f7be09e823d11c2d35c7fdd7 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 17 Jan 2025 17:03:13 +0100 Subject: [PATCH 056/153] from retail --- WeakAuras/Media/Fonts/FiraSans-Black.ttf | Bin 0 -> 491496 bytes WeakAuras/Media/Fonts/FiraSans-Medium.ttf | Bin 0 -> 441384 bytes .../Media/Fonts/FiraSansCondensed-Black.ttf | Bin 0 -> 500312 bytes .../Media/Fonts/FiraSansCondensed-Medium.ttf | Bin 0 -> 440144 bytes WeakAuras/Types.lua | 5 +++++ 5 files changed, 5 insertions(+) create mode 100644 WeakAuras/Media/Fonts/FiraSans-Black.ttf create mode 100644 WeakAuras/Media/Fonts/FiraSans-Medium.ttf create mode 100644 WeakAuras/Media/Fonts/FiraSansCondensed-Black.ttf create mode 100644 WeakAuras/Media/Fonts/FiraSansCondensed-Medium.ttf diff --git a/WeakAuras/Media/Fonts/FiraSans-Black.ttf b/WeakAuras/Media/Fonts/FiraSans-Black.ttf new file mode 100644 index 0000000000000000000000000000000000000000..113cd3b44a9fb2655f5182815e772fd71b8feb5f GIT binary patch literal 491496 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ʮ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%0DJb!yZ(RlZK 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 XZf^G)LoLbtypab!vxlh%1=9Zn1QpZG literal 0 HcmV?d00001 diff --git a/WeakAuras/Media/Fonts/FiraSans-Medium.ttf b/WeakAuras/Media/Fonts/FiraSans-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..001ebe7e6351750e418dbc197de3eb455d63ae56 GIT binary patch literal 441384 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 s7*d5u22S%LdV>eg0 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

jt7oZWxmR(XVVsFb9Dlf1?yCC?c{_LuW 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

`)jx8>&NW*^PLy?E^A1g+}9?R((;h1&sB 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 literal 0 HcmV?d00001 diff --git a/WeakAuras/Media/Fonts/FiraSansCondensed-Medium.ttf b/WeakAuras/Media/Fonts/FiraSansCondensed-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..534c9708abcd57b498c8a60ab544f5a7eeaaddcb GIT binary patch literal 440144 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

rCPPstB@LV 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

  • `+#NVAgTBnl!|De)XaIeER8L}zUk?*ZkgIdcx0 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 Y);(sZ^#oeG9G}> Date: Fri, 17 Jan 2025 17:10:25 +0100 Subject: [PATCH 057/153] from retail --- WeakAuras/Prototypes.lua | 4 ++-- WeakAuras/RegionTypes/DynamicGroup.lua | 9 ++++++--- WeakAurasOptions/CommonOptions.lua | 10 +++++----- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 31b335f..f31fca5 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -985,7 +985,7 @@ Private.load_prototype = { name = "spellknown", display = L["Spell Known"], type = "spell", - test = "WeakAuras.IsSpellKnownForLoad(%q, %s)", + test = "WeakAuras.IsSpellKnownForLoad(%s, %s)", events = {"SPELLS_CHANGED", "UNIT_PET"}, showExactOption = true }, @@ -993,7 +993,7 @@ Private.load_prototype = { name = "not_spellknown", display = WeakAuras.newFeatureString .. L["|cFFFF0000Not|r Spell Known"], type = "spell", - test = "not WeakAuras.IsSpellKnownForLoad(%q, %s)", + test = "not WeakAuras.IsSpellKnownForLoad(%s, %s)", events = {"SPELLS_CHANGED", "UNIT_PET"}, showExactOption = true }, diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 7451252..0f0242b 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1365,12 +1365,15 @@ local function modify(parent, region, data) end controlPoint:SetWidth(regionData.dimensions.width) controlPoint:SetHeight(regionData.dimensions.height) - if (data.anchorFrameParent - or data.anchorFrameParent == nil) + if (data.anchorFrameParent or data.anchorFrameParent == nil) + and (data.useAnchorPerUnit + or ( + not data.useAnchorPerUnit and not (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE") - and not data.useAnchorPerUnit then + )) + then controlPoint:SetParent(frame == "" and self.relativeTo or frame) else controlPoint:SetParent(self) diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index cf00eb3..4b2af34 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -1115,7 +1115,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g order = 72, image = function() return "", 0, 0 end, hidden = function() - return IsParentDynamicGroup() or not (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE") + return IsParentDynamicGroup() or not (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "UIPARENT" or data.anchorFrameType == "MOUSE" or IsGroupByFrame()) end, }, -- Input field to select frame to anchor on @@ -1123,9 +1123,9 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g type = "input", width = WeakAuras.normalWidth, name = L["Frame"], - order = 72.2, + order = 73, hidden = function() - if (IsParentDynamicGroup()) then + if (IsParentDynamicGroup() or IsGroupByFrame()) then return true; end return not (data.anchorFrameType == "SELECTFRAME") @@ -1138,7 +1138,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g name = L["Choose"], order = 74, hidden = function() - if (IsParentDynamicGroup()) then + if (IsParentDynamicGroup() or IsGroupByFrame()) then return true; end return not (data.anchorFrameType == "SELECTFRAME") @@ -1278,7 +1278,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g OptionsPrivate.commonOptions.AddCodeOption(positionOptions, data, L["Custom Anchor"], "custom_anchor", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-anchor-function", - 71.5, function() return not(data.anchorFrameType == "CUSTOM" and not IsParentDynamicGroup()) end, + 71.5, function() return not(data.anchorFrameType == "CUSTOM" and not IsParentDynamicGroup() and not IsGroupByFrame()) end, {"customAnchor"}, false, { setOnParent = group }) return positionOptions; end From 89a247addb240fd44c8ed9f923fb5b19c15ecd17 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 17 Jan 2025 17:37:35 +0100 Subject: [PATCH 058/153] from retail --- WeakAuras/Init.lua | 4 +- WeakAuras/RegionTypes/AuraBar.lua | 2 +- WeakAuras/RegionTypes/DynamicGroup.lua | 2 +- WeakAuras/RegionTypes/Group.lua | 2 +- WeakAuras/RegionTypes/Icon.lua | 2 +- WeakAuras/RegionTypes/Model.lua | 2 +- WeakAuras/RegionTypes/ProgressTexture.lua | 2 +- WeakAuras/RegionTypes/StopMotion.lua | 2 +- WeakAuras/RegionTypes/Text.lua | 4 +- WeakAuras/RegionTypes/Texture.lua | 2 +- WeakAuras/WeakAuras.lua | 44 +++++++++---------- WeakAurasOptions/RegionOptions/AuraBar.lua | 5 ++- .../RegionOptions/DynamicGroup.lua | 5 ++- WeakAurasOptions/RegionOptions/Group.lua | 7 ++- WeakAurasOptions/RegionOptions/Icon.lua | 8 +++- WeakAurasOptions/RegionOptions/Model.lua | 7 ++- .../RegionOptions/ProgressTexture.lua | 5 ++- WeakAurasOptions/RegionOptions/StopMotion.lua | 6 ++- WeakAurasOptions/RegionOptions/Text.lua | 5 ++- WeakAurasOptions/RegionOptions/Texture.lua | 6 ++- WeakAurasOptions/WeakAurasOptions.lua | 4 ++ 21 files changed, 81 insertions(+), 45 deletions(-) diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index af72783..6a46ecd 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -93,10 +93,10 @@ if not WeakAuras.IsLibsOK() then end -- These function stubs are defined here to reduce the number of errors that occur if WeakAuras.lua fails to compile -function WeakAuras.RegisterRegionType(_, _, _ ,_) +function Private.RegisterRegionType(_, _, _ ,_) end -function WeakAuras.RegisterRegionOptions(_, _ , _ ,_) +function Private.RegisterRegionOptions(_, _ , _ ,_) end function Private.StartProfileSystem(_) diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 6a240bc..eb464a5 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -1372,4 +1372,4 @@ local function validate(data) end -- Register new region type with WeakAuras -WeakAuras.RegisterRegionType("aurabar", create, modify, default, GetProperties, validate); +Private.RegisterRegionType("aurabar", create, modify, default, GetProperties, validate); diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 0f0242b..8ab7bde 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1566,4 +1566,4 @@ local function modify(parent, region, data) Private.regionPrototype.modifyFinish(parent, region, data) end -WeakAuras.RegisterRegionType("dynamicgroup", create, modify, default) +Private.RegisterRegionType("dynamicgroup", create, modify, default) diff --git a/WeakAuras/RegionTypes/Group.lua b/WeakAuras/RegionTypes/Group.lua index eab0d7c..2fc0738 100644 --- a/WeakAuras/RegionTypes/Group.lua +++ b/WeakAuras/RegionTypes/Group.lua @@ -183,4 +183,4 @@ local function modify(parent, region, data) end -- Register new region type with WeakAuras -WeakAuras.RegisterRegionType("group", create, modify, default); +Private.RegisterRegionType("group", create, modify, default); diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index 78b4bf3..567c47c 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -687,4 +687,4 @@ local function validate(data) Private.EnforceSubregionExists(data, "subbackground") end -WeakAuras.RegisterRegionType("icon", create, modify, default, GetProperties, validate) +Private.RegisterRegionType("icon", create, modify, default, GetProperties, validate) diff --git a/WeakAuras/RegionTypes/Model.lua b/WeakAuras/RegionTypes/Model.lua index b476f09..ef304ec 100644 --- a/WeakAuras/RegionTypes/Model.lua +++ b/WeakAuras/RegionTypes/Model.lua @@ -301,4 +301,4 @@ local function validate(data) end -- Register new region type with WeakAuras -WeakAuras.RegisterRegionType("model", create, modify, default, GetProperties, validate); +Private.RegisterRegionType("model", create, modify, default, GetProperties, validate); diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 4feea79..8fc2176 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -1036,4 +1036,4 @@ local function validate(data) Private.EnforceSubregionExists(data, "subbackground") end -WeakAuras.RegisterRegionType("progresstexture", create, modify, default, GetProperties, validate); +Private.RegisterRegionType("progresstexture", create, modify, default, GetProperties, validate); diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index 575b738..6b70798 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -488,4 +488,4 @@ local function validate(data) Private.EnforceSubregionExists(data, "subbackground") end -WeakAuras.RegisterRegionType("stopmotion", create, modify, default, properties, validate); +Private.RegisterRegionType("stopmotion", create, modify, default, properties, validate); diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index d1b3f5d..1361e78 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -341,7 +341,7 @@ local function validate(data) Private.EnforceSubregionExists(data, "subbackground") end -WeakAuras.RegisterRegionType("text", create, modify, default, GetProperties, validate); +Private.RegisterRegionType("text", create, modify, default, GetProperties, validate); -- Fallback region type @@ -366,4 +366,4 @@ local function fallbackmodify(parent, region, data) Private.regionPrototype.modifyFinish(parent, region, data); end -WeakAuras.RegisterRegionType("fallback", create, fallbackmodify, default); +Private.RegisterRegionType("fallback", create, fallbackmodify, default); diff --git a/WeakAuras/RegionTypes/Texture.lua b/WeakAuras/RegionTypes/Texture.lua index 1736793..264d155 100644 --- a/WeakAuras/RegionTypes/Texture.lua +++ b/WeakAuras/RegionTypes/Texture.lua @@ -237,4 +237,4 @@ local function validate(data) Private.EnforceSubregionExists(data, "subbackground") end -WeakAuras.RegisterRegionType("texture", create, modify, default, properties, validate); +Private.RegisterRegionType("texture", create, modify, default, properties, validate); diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 22e0ff0..28fdd65 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -349,27 +349,27 @@ function Private.validate(input, default) end end -function WeakAuras.RegisterRegionType(name, createFunction, modifyFunction, default, properties, validate) +function Private.RegisterRegionType(name, createFunction, modifyFunction, default, properties, validate) if not(name) then - error("Improper arguments to WeakAuras.RegisterRegionType - name is not defined", 2); + error("Improper arguments to Private.RegisterRegionType - name is not defined", 2); elseif(type(name) ~= "string") then - error("Improper arguments to WeakAuras.RegisterRegionType - name is not a string", 2); + error("Improper arguments to Private.RegisterRegionType - name is not a string", 2); elseif not(createFunction) then - error("Improper arguments to WeakAuras.RegisterRegionType - creation function is not defined", 2); + error("Improper arguments to Private.RegisterRegionType - creation function is not defined", 2); elseif(type(createFunction) ~= "function") then - error("Improper arguments to WeakAuras.RegisterRegionType - creation function is not a function", 2); + error("Improper arguments to Private.RegisterRegionType - creation function is not a function", 2); elseif not(modifyFunction) then - error("Improper arguments to WeakAuras.RegisterRegionType - modification function is not defined", 2); + error("Improper arguments to Private.RegisterRegionType - modification function is not defined", 2); elseif(type(modifyFunction) ~= "function") then - error("Improper arguments to WeakAuras.RegisterRegionType - modification function is not a function", 2) + error("Improper arguments to Private.RegisterRegionType - modification function is not a function", 2) elseif not(default) then - error("Improper arguments to WeakAuras.RegisterRegionType - default options are not defined", 2); + error("Improper arguments to Private.RegisterRegionType - default options are not defined", 2); elseif(type(default) ~= "table") then - error("Improper arguments to WeakAuras.RegisterRegionType - default options are not a table", 2); + error("Improper arguments to Private.RegisterRegionType - default options are not a table", 2); elseif(type(default) ~= "table" and type(default) ~= "nil") then - error("Improper arguments to WeakAuras.RegisterRegionType - properties options are not a table", 2); + error("Improper arguments to Private.RegisterRegionType - properties options are not a table", 2); elseif(regionTypes[name]) then - error("Improper arguments to WeakAuras.RegisterRegionType - region type \""..name.."\" already defined", 2); + error("Improper arguments to Private.RegisterRegionType - region type \""..name.."\" already defined", 2); else regionTypes[name] = { create = createFunction, @@ -443,27 +443,27 @@ function WeakAuras.RegisterSubRegionType(name, displayName, supportFunction, cre end end -function WeakAuras.RegisterRegionOptions(name, createFunction, icon, displayName, createThumbnail, modifyThumbnail, description, templates, getAnchors) +function Private.RegisterRegionOptions(name, createFunction, icon, displayName, createThumbnail, modifyThumbnail, description, templates, getAnchors) if not(name) then - error("Improper arguments to WeakAuras.RegisterRegionOptions - name is not defined", 2); + error("Improper arguments to Private.RegisterRegionOptions - name is not defined", 2); elseif(type(name) ~= "string") then - error("Improper arguments to WeakAuras.RegisterRegionOptions - name is not a string", 2); + error("Improper arguments to Private.RegisterRegionOptions - name is not a string", 2); elseif not(createFunction) then - error("Improper arguments to WeakAuras.RegisterRegionOptions - creation function is not defined", 2); + error("Improper arguments to Private.RegisterRegionOptions - creation function is not defined", 2); elseif(type(createFunction) ~= "function") then - error("Improper arguments to WeakAuras.RegisterRegionOptions - creation function is not a function", 2); + error("Improper arguments to Private.RegisterRegionOptions - creation function is not a function", 2); elseif not(icon) then - error("Improper arguments to WeakAuras.RegisterRegionOptions - icon is not defined", 2); + error("Improper arguments to Private.RegisterRegionOptions - icon is not defined", 2); elseif not(type(icon) == "string" or type(icon) == "function") then - error("Improper arguments to WeakAuras.RegisterRegionOptions - icon is not a string or a function", 2) + error("Improper arguments to Private.RegisterRegionOptions - icon is not a string or a function", 2) elseif not(displayName) then - error("Improper arguments to WeakAuras.RegisterRegionOptions - display name is not defined".." "..name, 2); + error("Improper arguments to Private.RegisterRegionOptions - display name is not defined".." "..name, 2); elseif(type(displayName) ~= "string") then - error("Improper arguments to WeakAuras.RegisterRegionOptions - display name is not a string", 2); + error("Improper arguments to Private.RegisterRegionOptions - display name is not a string", 2); elseif (getAnchors and type(getAnchors) ~= "function") then - error("Improper arguments to WeakAuras.RegisterRegionOptions - anchors is not a function", 2); + error("Improper arguments to Private.RegisterRegionOptions - anchors is not a function", 2); elseif(regionOptions[name]) then - error("Improper arguments to WeakAuras.RegisterRegionOptions - region type \""..name.."\" already defined", 2); + error("Improper arguments to Private.RegisterRegionOptions - region type \""..name.."\" already defined", 2); else local templateIcon if (type(icon) == "function") then diff --git a/WeakAurasOptions/RegionOptions/AuraBar.lua b/WeakAurasOptions/RegionOptions/AuraBar.lua index e56f894..9d9bdb0 100644 --- a/WeakAurasOptions/RegionOptions/AuraBar.lua +++ b/WeakAurasOptions/RegionOptions/AuraBar.lua @@ -794,4 +794,7 @@ local function GetAnchors(data) end -- Register new region type options with WeakAuras -WeakAuras.RegisterRegionOptions("aurabar", createOptions, createIcon, L["Progress Bar"], createThumbnail, modifyThumbnail, L["Shows a progress bar with name, timer, and icon"], templates, GetAnchors); +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("aurabar", createOptions, createIcon, L["Progress Bar"], createThumbnail, modifyThumbnail, L["Shows a progress bar with name, timer, and icon"], templates, GetAnchors); +end) \ No newline at end of file diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index a396a90..7bbad45 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -639,4 +639,7 @@ local function createIcon() return thumbnail end -WeakAuras.RegisterRegionOptions("dynamicgroup", createOptions, createIcon, L["Dynamic Group"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("dynamicgroup", createOptions, createIcon, L["Dynamic Group"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); +end) diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index be6f75f..525f88b 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -704,5 +704,8 @@ local function createIcon() end -- Register new region type options with WeakAuras -WeakAuras.RegisterRegionOptions("group", createOptions, createIcon, L["Group"], createThumbnail, modifyThumbnail, - L["Controls the positioning and configuration of multiple displays at the same time"]) +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("group", createOptions, createIcon, L["Group"], createThumbnail, modifyThumbnail, + L["Controls the positioning and configuration of multiple displays at the same time"]) +end) diff --git a/WeakAurasOptions/RegionOptions/Icon.lua b/WeakAurasOptions/RegionOptions/Icon.lua index 7709aad..ced05d2 100644 --- a/WeakAurasOptions/RegionOptions/Icon.lua +++ b/WeakAurasOptions/RegionOptions/Icon.lua @@ -488,4 +488,10 @@ local function GetAnchors(data) return anchorPoints; end -WeakAuras.RegisterRegionOptions("icon", createOptions, "interface\\icons\\spell_holy_sealofsalvation.blp", L["Icon"], createThumbnail, modifyThumbnail, L["Shows a spell icon with an optional cooldown overlay"], templates, GetAnchors); +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("icon", createOptions, "interface\\icons\\spell_holy_sealofsalvation.blp", L["Icon"], + createThumbnail, modifyThumbnail, + L["Shows a spell icon with an optional cooldown overlay"], + templates, GetAnchors); +end) diff --git a/WeakAurasOptions/RegionOptions/Model.lua b/WeakAurasOptions/RegionOptions/Model.lua index fd718ed..01fe2c7 100644 --- a/WeakAurasOptions/RegionOptions/Model.lua +++ b/WeakAurasOptions/RegionOptions/Model.lua @@ -297,5 +297,8 @@ local templates = { }, } -WeakAuras.RegisterRegionOptions("model", createOptions, createIcon, L["Model"], createThumbnail, modifyThumbnail, - L["Shows a 3D model from the game files"], templates) +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("model", createOptions, createIcon, L["Model"], createThumbnail, modifyThumbnail, + L["Shows a 3D model from the game files"], templates); +end) diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index 3238ada..442a456 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -797,4 +797,7 @@ local templates = { }, } -WeakAuras.RegisterRegionOptions("progresstexture", createOptions, createIcon, L["Progress Texture"], createThumbnail, modifyThumbnail, L["Shows a texture that changes based on duration"], templates); +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("progresstexture", createOptions, createIcon, L["Progress Texture"], createThumbnail, modifyThumbnail, L["Shows a texture that changes based on duration"], templates); +end) diff --git a/WeakAurasOptions/RegionOptions/StopMotion.lua b/WeakAurasOptions/RegionOptions/StopMotion.lua index 3239918..b232cf3 100644 --- a/WeakAurasOptions/RegionOptions/StopMotion.lua +++ b/WeakAurasOptions/RegionOptions/StopMotion.lua @@ -706,4 +706,8 @@ local function createIcon() return thumbnail; end -WeakAuras.RegisterRegionOptions("stopmotion", createOptions, createIcon, L["Stop Motion"], createThumbnail, modifyThumbnail, L["Shows a stop motion texture"]); +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("stopmotion", createOptions, createIcon, L["Stop Motion"], + createThumbnail, modifyThumbnail, L["Shows a stop motion texture"]); +end) diff --git a/WeakAurasOptions/RegionOptions/Text.lua b/WeakAurasOptions/RegionOptions/Text.lua index bd34bf7..9f17306 100644 --- a/WeakAurasOptions/RegionOptions/Text.lua +++ b/WeakAurasOptions/RegionOptions/Text.lua @@ -473,4 +473,7 @@ local templates = { } } -WeakAuras.RegisterRegionOptions("text", createOptions, createIcon, L["Text"], createThumbnail, modifyThumbnail, L["Shows one or more lines of text, which can include dynamic information such as progress or stacks"], templates); +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("text", createOptions, createIcon, L["Text"], createThumbnail, modifyThumbnail, L["Shows one or more lines of text, which can include dynamic information such as progress or stacks"], templates); +end) diff --git a/WeakAurasOptions/RegionOptions/Texture.lua b/WeakAurasOptions/RegionOptions/Texture.lua index e07ce47..8130d17 100644 --- a/WeakAurasOptions/RegionOptions/Texture.lua +++ b/WeakAurasOptions/RegionOptions/Texture.lua @@ -244,4 +244,8 @@ local templates = { }, } -WeakAuras.RegisterRegionOptions("texture", createOptions, createIcon, L["Texture"], createThumbnail, modifyThumbnail, L["Shows a custom texture"], templates); +OptionsPrivate.registerRegions = OptionsPrivate.registerRegions or {} +table.insert(OptionsPrivate.registerRegions, function() + OptionsPrivate.Private.RegisterRegionOptions("texture", createOptions, createIcon, L["Texture"], createThumbnail, modifyThumbnail, + L["Shows a custom texture"], templates); +end) diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 4a6d2e9..aac6bd8 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -574,6 +574,10 @@ function WeakAuras.ToggleOptions(msg, Private) if not OptionsPrivate.Private then OptionsPrivate.Private = Private Private.OptionsFrame = OptionsFrame + for _, fn in ipairs(OptionsPrivate.registerRegions) do + fn() + end + OptionsPrivate.Private.callbacks:RegisterCallback("AuraWarningsUpdated", function(event, uid) local id = OptionsPrivate.Private.UIDtoID(uid) if displayButtons[id] then From efdbb3c46df417c92f489225500f6216a1690943 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 17 Jan 2025 18:59:10 +0100 Subject: [PATCH 059/153] from retail --- WeakAuras/Bindings.xml | 6 +-- WeakAuras/GenericTrigger.lua | 12 +++-- WeakAuras/Modernize.lua | 13 +++--- WeakAuras/Prototypes.lua | 15 ++++++- WeakAuras/RegionTypes/DynamicGroup.lua | 25 +++++++++-- WeakAuras/RegionTypes/Text.lua | 6 +++ WeakAuras/SubRegionTypes/SubText.lua | 6 +++ WeakAuras/Types.lua | 1 + WeakAuras/WeakAuras.lua | 7 +-- .../RegionOptions/DynamicGroup.lua | 44 +++++++++++++++---- 10 files changed, 107 insertions(+), 28 deletions(-) diff --git a/WeakAuras/Bindings.xml b/WeakAuras/Bindings.xml index eb4d252..66ea3e6 100644 --- a/WeakAuras/Bindings.xml +++ b/WeakAuras/Bindings.xml @@ -1,11 +1,11 @@ - + WeakAuras.OpenOptions() - + WeakAuras.RealTimeProfilingWindow:Toggle() - + WeakAuras.PrintProfile() diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 89ce08a..22ab767 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -2381,9 +2381,11 @@ do if (showgcd) then if ((gcdStart or 0) + (gcdDuration or 0) > startTime + duration) then + if startTime == 0 then + gcdCooldown = true + end startTime = gcdStart; duration = gcdDuration; - gcdCooldown = true; end end @@ -2403,9 +2405,11 @@ do end if (showgcd) then if ((gcdStart or 0) + (gcdDuration or 0) > startTime + duration) then + if startTime == 0 then + gcdCooldown = true + end startTime = gcdStart; duration = gcdDuration; - gcdCooldown = true; end end return startTime, duration, enabled, gcdCooldown; @@ -2437,9 +2441,11 @@ do if (showgcd) then if ((gcdStart or 0) + (gcdDuration or 0) > startTime + duration) then + if startTime == 0 then + gcdCooldown = true + end startTime = gcdStart; duration = gcdDuration; - gcdCooldown = true; end end return startTime, duration, enabled, gcdCooldown; diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 07bff87..6fbba68 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1256,15 +1256,16 @@ function Private.Modernize(data) end end + local function migrateToTable(tab, field) + local value = tab[field] + if value ~= nil and type(value) ~= "table" then + tab[field] = { value } + end + end + if data.internalVersion < 67 or data.internalVersion > WeakAuras.InternalVersion() then local castMigrationNeeded = data.internalVersion < 67 data.internalVersion = WeakAuras.InternalVersion() - local function migrateToTable(tab, field) - local value = tab[field] - if value ~= nil and type(value) ~= "table" then - tab[field] = { value } - end - end do local trigger_migration = { diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index f31fca5..13d7972 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -1040,6 +1040,17 @@ Private.load_prototype = { events = {"PARTY_MEMBERS_CHANGED", "RAID_ROSTER_UPDATE"}, optional = true, }, + { + name = "groupSize", + display = L["Group Size"], + type = "number", + init = "arg", + events = {"PARTY_MEMBERS_CHANGED", "RAID_ROSTER_UPDATE"}, + multiEntry = { + operator = "and", + limit = 2 + }, + }, { name = "group_leader", display = WeakAuras.newFeatureString .. L["Group Leader/Assist"], @@ -3098,7 +3109,7 @@ Private.event_prototypes = { force_events = "SPELL_COOLDOWN_FORCE", name = L["Cooldown/Charges/Count"], loadFunc = function(trigger) - trigger.spellName = trigger.spellName or 0; + trigger.spellName = type(trigger.spellName) ~= "table" and trigger.spellName or 0; local spellName; if (trigger.use_exact_spellName) then spellName = trigger.spellName; @@ -3111,7 +3122,7 @@ Private.event_prototypes = { end end, init = function(trigger) - trigger.spellName = trigger.spellName or 0; + trigger.spellName = type(trigger.spellName) ~= "table" and trigger.spellName or 0; local spellName; if (trigger.use_exact_spellName) then spellName = trigger.spellName; diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 8ab7bde..cec8b5a 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -28,6 +28,7 @@ local default = { yOffset = 0, radius = 200, rotation = 0, + stepAngle = 15, fullCircle = true, arcLength = 360, constantFactor = "RADIUS", @@ -719,6 +720,7 @@ local growers = { local constantFactor = data.constantFactor local space = data.space or 0 local radius = data.radius or 0 + local stepAngle = (data.stepAngle or 0) * math.pi / 180 local limit = data.useLimit and data.limit or math.huge local sAngle = (data.rotation or 0) * math.pi / 180 local arc = (data.fullCircle and 360 or data.arcLength or 0) * math.pi / 180 @@ -736,7 +738,7 @@ local growers = { for frame, regionDatas in pairs(frames) do local numVisible = min(limit, #regionDatas) local r - if constantFactor == "RADIUS" then + if constantFactor == "RADIUS" or constantFactor == "ANGLE" then r = radius else if numVisible <= 1 then @@ -749,6 +751,8 @@ local growers = { local dAngle if numVisible == 1 then dAngle = 0 + elseif constantFactor == "ANGLE" then + dAngle = stepAngle elseif not data.fullCircle then dAngle = arc / (numVisible - 1) else @@ -770,6 +774,7 @@ local growers = { local constantFactor = data.constantFactor local space = data.space or 0 local radius = data.radius or 0 + local stepAngle = (data.stepAngle or 0) * math.pi / 180 local limit = data.useLimit and data.limit or math.huge local sAngle = (data.rotation or 0) * math.pi / 180 local arc = (data.fullCircle and 360 or data.arcLength or 0) * math.pi / 180 @@ -787,7 +792,7 @@ local growers = { for frame, regionDatas in pairs(frames) do local numVisible = min(limit, #regionDatas) local r - if constantFactor == "RADIUS" then + if constantFactor == "RADIUS" or constantFactor == "ANGLE" then r = radius else if numVisible <= 1 then @@ -800,6 +805,8 @@ local growers = { local dAngle if numVisible == 1 then dAngle = 0 + elseif constantFactor == "ANGLE" then + dAngle = -stepAngle elseif not data.fullCircle then dAngle = arc / (1 - numVisible) else @@ -1374,7 +1381,19 @@ local function modify(parent, region, data) or data.anchorFrameType == "MOUSE") )) then - controlPoint:SetParent(frame == "" and self.relativeTo or frame) + local parent + if frame == "" then + parent = self.relativeTo + else + if type(frame) == "string" then + parent = _G[frame] + else + parent = frame + end + end + if parent and parent.IsObjectType and parent:IsObjectType("Frame") then + controlPoint:SetParent(parent) + end else controlPoint:SetParent(self) end diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index 1361e78..f0ed0db 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -81,6 +81,12 @@ local function modify(parent, region, data) local text = region.text; local fontPath = SharedMedia:Fetch("font", data.font); + if not text:GetFont() and fontPath then -- workaround font not loading correctly + local objectName = "WeakAuras-Font-" .. data.font + local fontObject = _G[objectName] or CreateFont(objectName) + fontObject:SetFont(fontPath, data.fontSize < 33 and data.fontSize or 33, data.outline) + text:SetFontObject(fontObject) + end text:SetFont(fontPath, data.fontSize < 33 and data.fontSize or 33, data.outline); if not text:GetFont() then -- Font invalid, set the font but keep the setting text:SetFont(STANDARD_TEXT_FONT, data.fontSize <= 33 and data.fontSize or 33, data.outline); diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index 5162133..f15ac2a 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -139,6 +139,12 @@ local function modify(parent, region, parentData, data, first) local fontPath = SharedMedia:Fetch("font", data.text_font); text:SetFont(fontPath, data.text_fontSize < 33 and data.text_fontSize or 33, data.text_fontType); + if not text:GetFont() and fontPath then -- workaround font not loading correctly + local objectName = "WeakAuras-Font-" .. data.text_font + local fontObject = _G[objectName] or CreateFont(objectName) + fontObject:SetFont(fontPath, data.text_fontSize < 33 and data.text_fontSize or 33, data.text_fontType) + text:SetFontObject(fontObject) + end if not text:GetFont() then -- Font invalid, set the font but keep the setting text:SetFont(STANDARD_TEXT_FONT, data.text_fontSize < 33 and data.text_fontSize or 33, data.text_fontType); end diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 4784246..f97a627 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -32,6 +32,7 @@ if WeakAuras.isAwesomeEnabled() then end Private.circular_group_constant_factor_types = { + ANGLE = L["Angle and Radius"], RADIUS = L["Radius"], SPACING = L["Spacing"] } diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 28fdd65..5ab2ced 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1,6 +1,6 @@ local AddonName, Private = ... -local internalVersion = 68 +local internalVersion = 69 -- Lua APIs local insert = table.insert @@ -1404,6 +1404,7 @@ local function scanForLoadsImpl(toCheck, event, arg1, ...) local size, difficulty, instanceType = GetInstanceTypeAndSize() local group = Private.ExecEnv.GroupType() + local groupSize = GetNumGroupMembers() local changed = 0; local shouldBeLoaded, couldBeLoaded; @@ -1416,8 +1417,8 @@ local function scanForLoadsImpl(toCheck, event, arg1, ...) if (data and not data.controlledChildren) then local loadFunc = loadFuncs[id]; local loadOpt = loadFuncsForOptions[id]; - shouldBeLoaded = loadFunc and loadFunc("ScanForLoads_Auras", inCombat, alive, pvp, vehicle, vehicleUi, player, realm, class, race, faction, playerLevel, raidRole, group, raidMemberType, zone, zoneId, subzone, size, difficulty); - couldBeLoaded = loadOpt and loadOpt("ScanForLoads_Auras", inCombat, alive, pvp, vehicle, vehicleUi, player, realm, class, race, faction, playerLevel, raidRole, group, raidMemberType, zone, zoneId, subzone, size, difficulty); + shouldBeLoaded = loadFunc and loadFunc("ScanForLoads_Auras", inCombat, alive, pvp, vehicle, vehicleUi, player, realm, class, race, faction, playerLevel, raidRole, group, groupSize, raidMemberType, zone, zoneId, subzone, size, difficulty); + couldBeLoaded = loadOpt and loadOpt("ScanForLoads_Auras", inCombat, alive, pvp, vehicle, vehicleUi, player, realm, class, race, faction, playerLevel, raidRole, group, groupSize, raidMemberType, zone, zoneId, subzone, size, difficulty); if(shouldBeLoaded and not loaded[id]) then changed = changed + 1; diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 7bbad45..d93dcdc 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -263,7 +263,7 @@ local function createOptions(id, data) name = L["Constant Factor"], order = 4, values = OptionsPrivate.Private.circular_group_constant_factor_types, - hidden = function() return data.grow ~= "CIRCLE" and data.grow ~= "COUNTERCIRCLE" end + hidden = function() return not(data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") end }, rotation = { type = "range", @@ -274,14 +274,31 @@ local function createOptions(id, data) min = 0, max = 360, bigStep = 3, - hidden = function() return data.grow ~= "CIRCLE" and data.grow ~= "COUNTERCIRCLE" end + hidden = function() return not(data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") end }, fullCircle = { type = "toggle", width = WeakAuras.normalWidth, name = L["Full Circle"], order = 7, - hidden = function() return data.grow ~= "CIRCLE" and data.grow ~= "COUNTERCIRCLE" end + hidden = function() + return not( + (data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") + and (data.constantFactor == "RADIUS" or data.constantFactor == "SPACING")) + end + }, + stepAngle = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Angle Between Auras"], + order = 12, + min = 0, + max = 180, + bigStep = 1, + hidden = function() + return not((data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") and data.constantFactor == "ANGLE") + end }, arcLength = { type = "range", @@ -293,7 +310,11 @@ local function createOptions(id, data) max = 360, bigStep = 3, disabled = function() return data.fullCircle end, - hidden = function() return data.grow ~= "CIRCLE" and data.grow ~= "COUNTERCIRCLE" end + hidden = function() + return not( + (data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") + and (data.constantFactor == "RADIUS" or data.constantFactor == "SPACING")) + end }, radius = { type = "range", @@ -304,7 +325,11 @@ local function createOptions(id, data) softMin = 0, softMax = 500, bigStep = 1, - hidden = function() return data.grow == "CUSTOM" or not((data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") and data.constantFactor == "RADIUS") end + hidden = function() + return not( + (data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") + and (data.constantFactor == "RADIUS" or data.constantFactor == "ANGLE")) + end }, -- grid grow options gridType = { @@ -372,9 +397,12 @@ local function createOptions(id, data) softMax = 300, bigStep = 1, hidden = function() - return data.grow == "CUSTOM" - or data.grow == "GRID" - or ((data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") and data.constantFactor == "RADIUS") + return not( + data.grow == "LEFT" or data.grow == "RIGHT" + or data.grow == "UP" or data.grow == "DOWN" + or data.grow == "HORIZONTAL" or data.grow == "VERTICAL" + or ((data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") + and (data.constantFactor == "SPACING"))) end }, stagger = { From bd46c605bd8635dc98ccbb1c4d615cfd0e02bc6f Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 17 Jan 2025 21:00:15 +0100 Subject: [PATCH 060/153] from retail --- WeakAuras/BuffTrigger2.lua | 45 ++++++++++++++++++++----------- WeakAuras/Modernize.lua | 4 +++ WeakAurasOptions/BuffTrigger2.lua | 2 +- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 7908dac..9cae769 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -466,7 +466,7 @@ local function FindBestMatchDataForUnit(time, id, triggernum, triggerInfo, unit) return bestMatch, matchCount, stackCount, nextCheck end -local function UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, matchCount, unitCount, maxUnitCount, matchCountPerUnit, totalStacks, affected, unaffected, raidMark) +local function UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, matchCount, unitCount, maxUnitCount, matchCountPerUnit, totalStacks, affected, affectedUnits, unaffected, unaffectedUnits, raidMark) if not triggerStates[cloneId] then triggerStates[cloneId] = { show = true, @@ -497,7 +497,9 @@ local function UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, mat tooltip3 = bestMatch.tooltip3, tooltip4 = bestMatch.tooltip4, affected = affected, + affectedUnits = affectedUnits, unaffected = unaffected, + unaffectedUnits = unaffectedUnits, totalStacks = totalStacks, initialTime = time, refreshTime = time, @@ -658,11 +660,13 @@ local function UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, mat if state.affected ~= affected then state.affected = affected + state.affectedUnits = affectedUnits changed = true end if state.unaffected ~= unaffected then state.unaffected = unaffected + state.unaffectedUnits = unaffectedUnits changed = true end @@ -683,7 +687,7 @@ local function UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, mat end end -local function UpdateStateWithNoMatch(time, triggerStates, triggerInfo, cloneId, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit, totalStacks, affected, unaffected, raidMark) +local function UpdateStateWithNoMatch(time, triggerStates, triggerInfo, cloneId, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit, totalStacks, affected, affectedUnits, unaffected, unaffectedUnits, raidMark) local fallbackName, fallbackIcon = BuffTrigger.GetNameAndIconSimple(WeakAuras.GetData(triggerInfo.id), triggerInfo.triggernum) if not triggerStates[cloneId] then triggerStates[cloneId] = { @@ -699,7 +703,9 @@ local function UpdateStateWithNoMatch(time, triggerStates, triggerInfo, cloneId, active = false, time = time, affected = affected, + affectedUnits = affectedUnits, unaffected = unaffected, + unaffectedUnits = unaffectedUnits, unit = unit, raidMark = raidMark, unitName = unit and GetUnitName(unit, false) or "", @@ -832,11 +838,13 @@ local function UpdateStateWithNoMatch(time, triggerStates, triggerInfo, cloneId, if state.affected ~= affected then state.affected = affected + state.affectedUnits = affectedUnits changed = true end if state.unaffected ~= unaffected then state.unaffected = unaffected + state.unaffectedUnits = unaffectedUnits changed = true end @@ -1111,19 +1119,22 @@ end local function FormatAffectedUnaffected(triggerInfo, matchedUnits) local affected = "" local unaffected = "" + local affectedUnits, unaffectedUnits = {}, {} for unit in GetAllUnits(triggerInfo.unit, nil, triggerInfo.includePets) do if activeGroupScanFuncs[unit] and activeGroupScanFuncs[unit][triggerInfo] then if matchedUnits[unit] then affected = affected .. (GetUnitName(unit, false) or unit) .. ", " + tinsert(affectedUnits, unit) else unaffected = unaffected .. (GetUnitName(unit, false) or unit) .. ", " + tinsert(unaffectedUnits, unit) end end end unaffected = unaffected == "" and L["None"] or unaffected:sub(1, -3) affected = affected == "" and L["None"] or affected:sub(1, -3) - return affected, unaffected + return affected, affectedUnits, unaffected, unaffectedUnits end local recheckTriggerInfo @@ -1196,18 +1207,18 @@ local function UpdateTriggerState(time, id, triggernum) end if useMatch then - local affected, unaffected + local affected, unaffected, affectedUnits, unaffectedUnits if triggerInfo.useAffected then - affected, unaffected = FormatAffectedUnaffected(triggerInfo, matchedUnits) + affected, affectedUnits, unaffected, unaffectedUnits = FormatAffectedUnaffected(triggerInfo, matchedUnits) end local unit = bestUnit(triggerInfo, bestMatch) local mark = markForTriggerInfo(triggerInfo, unit) if bestMatch then - updated = UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, matchCount, unitCount, maxUnitCount, matchCount, totalStacks, affected, unaffected, mark) + updated = UpdateStateWithMatch(time, bestMatch, triggerStates, cloneId, matchCount, unitCount, maxUnitCount, matchCount, totalStacks, affected, affectedUnits, unaffected, unaffectedUnits, mark) else - updated = UpdateStateWithNoMatch(time, triggerStates, triggerInfo, cloneId, unit, 0, 0, maxUnitCount, 0, 0, affected, unaffected, mark) + updated = UpdateStateWithNoMatch(time, triggerStates, triggerInfo, cloneId, unit, 0, 0, maxUnitCount, 0, 0, affected, affectedUnits, unaffected, unaffectedUnits, mark) end else updated = RemoveState(triggerStates, cloneId) @@ -1250,9 +1261,9 @@ local function UpdateTriggerState(time, id, triggernum) if useMatches then table.sort(auraDatas, SortMatchDataByUnitIndex) - local affected, unaffected + local affected, affectedUnits, unaffected, unaffectedUnits if triggerInfo.useAffected then - affected, unaffected = FormatAffectedUnaffected(triggerInfo, matchedUnits) + affected, affectedUnits, unaffected, unaffectedUnits = FormatAffectedUnaffected(triggerInfo, matchedUnits) end local usedCloneIds = {}; @@ -1267,7 +1278,7 @@ local function UpdateTriggerState(time, id, triggernum) local mark = markForTriggerInfo(triggerInfo, auraData.unit) updated = UpdateStateWithMatch(time, auraData, triggerStates, cloneId, matchCount, unitCount, maxUnitCount, - matchCountPerUnit[auraData.unit], totalStacks, affected, unaffected, mark) or updated + matchCountPerUnit[auraData.unit], totalStacks, affected, affectedUnits, unaffected, unaffectedUnits, mark) or updated cloneIds[cloneId] = true end @@ -1275,7 +1286,7 @@ local function UpdateTriggerState(time, id, triggernum) local unit = bestUnit(triggerInfo, nil) local mark = markForTriggerInfo(triggerInfo, unit) updated = UpdateStateWithNoMatch(time, triggerStates, triggerInfo, "", nil, 0, 0, maxUnitCount, 0, totalStacks, - affected, unaffected, mark) or updated + affected, affectedUnits, unaffected, unaffectedUnits, mark) or updated cloneIds[""] = true end end @@ -1314,9 +1325,9 @@ local function UpdateTriggerState(time, id, triggernum) local cloneIds = {} if useMatches then - local affected, unaffected + local affected, affectedUnits, unaffected, unaffectedUnits if triggerInfo.useAffected then - affected, unaffected = FormatAffectedUnaffected(triggerInfo, matchedUnits) + affected, affectedUnits, unaffected, unaffectedUnits = FormatAffectedUnaffected(triggerInfo, matchedUnits) end if triggerInfo.perUnitMode == "affected" then @@ -1324,7 +1335,7 @@ local function UpdateTriggerState(time, id, triggernum) if bestMatch then local mark = markForTriggerInfo(triggerInfo, unit) updated = UpdateStateWithMatch(time, bestMatch, triggerStates, unit, matchCount, unitCount, maxUnitCount, - matchCountPerUnit[unit], totalStacks, affected, unaffected, mark) + matchCountPerUnit[unit], totalStacks, affected, affectedUnits, unaffected, unaffectedUnits, mark) or updated cloneIds[unit] = true end @@ -1338,14 +1349,14 @@ local function UpdateTriggerState(time, id, triggernum) if bestMatch then if triggerInfo.perUnitMode == "all" then updated = UpdateStateWithMatch(time, bestMatch, triggerStates, unit, matchCount, unitCount, maxUnitCount, - matchCountPerUnit[unit], totalStacks, affected, unaffected, mark) + matchCountPerUnit[unit], totalStacks, affected, affectedUnits, unaffected, unaffectedUnits, mark) or updated cloneIds[unit] = true end else updated = UpdateStateWithNoMatch(time, triggerStates, triggerInfo, unit, unit, matchCount, unitCount, maxUnitCount, matchCountPerUnit[unit], totalStacks, - affected, unaffected) + affected, affectedUnits, unaffected, unaffectedUnits) or updated cloneIds[unit] = true end @@ -2657,6 +2668,8 @@ function BuffTrigger.GetAdditionalProperties(data, triggernum) if (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party") and trigger.useAffected then ret = ret .. "|cFFFF0000%".. triggernum .. ".affected|r - " .. L["Names of affected Players"] .. "\n" ret = ret .. "|cFFFF0000%".. triggernum .. ".unaffected|r - " .. L["Names of unaffected Players"] .. "\n" + ret = ret .. "|cFFFF0000%".. triggernum .. ".affectedUnits|r - " .. L["Units of affected Players in a table format"] .. "\n" + ret = ret .. "|cFFFF0000%".. triggernum .. ".unaffectedUnits|r - " .. L["Units of unaffected Players in a table format"] .. "\n" end return ret diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 6fbba68..1d8eab5 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1465,5 +1465,9 @@ function Private.Modernize(data) end end + if data.internalVersion < 69 then + migrateToTable(data.load, "itemequiped") + end + data.internalVersion = max(data.internalVersion or 0, WeakAuras.InternalVersion()) end diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index 821c299..436b80c 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -669,7 +669,7 @@ local function GetBuffTriggerOptions(data, triggernum) }, useAffected = { type = "toggle", - name = L["Fetch Affected/Unaffected Names"], + name = L["Fetch Affected/Unaffected Names and Units"], width = WeakAuras.doubleWidth, order = 65.1, hidden = function() return not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party")) end From f72e96ae6ed5250a2df11ff50ec2cba33a26000e Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 18 Jan 2025 17:23:16 +0100 Subject: [PATCH 061/153] from retail --- WeakAuras/Profiling.lua | 38 +++++++- WeakAuras/Prototypes.lua | 91 +++++++++++++++---- WeakAuras/RegionTypes/DynamicGroup.lua | 18 ++-- WeakAuras/RegionTypes/Text.lua | 2 +- WeakAuras/SubRegionTypes/SubText.lua | 2 +- WeakAuras/WeakAuras.lua | 15 +-- WeakAurasOptions/OptionsFrames/IconPicker.lua | 31 ++++--- 7 files changed, 149 insertions(+), 48 deletions(-) diff --git a/WeakAuras/Profiling.lua b/WeakAuras/Profiling.lua index 361b06e..150588f 100644 --- a/WeakAuras/Profiling.lua +++ b/WeakAuras/Profiling.lua @@ -341,6 +341,24 @@ local function TotalProfileTime(map) return total end +local function unitEventToMultiUnit(event) + local count + event, count = event:gsub("nameplate%d+$", "nameplate") + if count == 1 then return event end + event, count = event:gsub("boss%d$", "boss") + if count == 1 then return event end + event, count = event:gsub("arena%d$", "arena") + if count == 1 then return event end + event, count = event:gsub("raid%d+$", "group") + if count == 1 then return event end + event, count = event:gsub("raidpet%d+$", "group") + if count == 1 then return event end + event, count = event:gsub("party%d$", "party") + if count == 1 then return event end + event, count = event:gsub("partypet%d$", "party") + return event +end + function WeakAuras.PrintProfile() local popup = ProfilePopup() if not profileData.systems.time then @@ -387,9 +405,25 @@ function WeakAuras.PrintProfile() popup:AddText("") popup:AddText("|cff9900ffSystems:|r") - for i, k in ipairs(SortProfileMap(profileData.systems)) do + -- make a new table for system data with multiUnits grouped + local systemRegrouped = {} + for k, v in pairs(profileData.systems) do + local event = unitEventToMultiUnit(k) + if systemRegrouped[event] == nil then + systemRegrouped[event] = CopyTable(v) + else + if v.elapsed then + systemRegrouped[event].elapsed = (systemRegrouped[event].elapsed or 0) + v.elapsed + end + if v.spike then + systemRegrouped[event].spike = (systemRegrouped[event].spike or 0) + v.spike + end + end + end + + for i, k in ipairs(SortProfileMap(systemRegrouped)) do if (k ~= "time" and k ~= "wa") then - PrintOneProfile(popup, k, profileData.systems[k], profileData.systems.wa.elapsed) + PrintOneProfile(popup, k, systemRegrouped[k], profileData.systems.wa.elapsed) end end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 13d7972..7ee6a88 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -2542,8 +2542,10 @@ Private.event_prototypes = { store = true, test = "Private.ExecEnv.CheckCombatLogFlags(sourceFlags, %q)", conditionType = "select", - conditionTest = function(state, needle) - return state and state.show and Private.ExecEnv.CheckCombatLogFlags(state.sourceFlags, needle); + conditionTest = function(state, needle, op) + if state and state.show then + return Private.ExecEnv.CheckCombatLogFlags(state.sourceFlags, needle) == (op == "==") + end end }, { @@ -2553,8 +2555,10 @@ Private.event_prototypes = { values = "combatlog_flags_check_reaction", test = "Private.ExecEnv.CheckCombatLogFlagsReaction(sourceFlags, %q)", conditionType = "select", - conditionTest = function(state, needle) - return state and state.show and Private.ExecEnv.CheckCombatLogFlagsReaction(state.sourceFlags, needle); + conditionTest = function(state, needle, op) + if state and state.show then + return Private.ExecEnv.CheckCombatLogFlagsReaction(state.sourceFlags, needle) == (op == "==") + end end }, { @@ -2564,8 +2568,10 @@ Private.event_prototypes = { values = "combatlog_flags_check_object_type", test = "Private.ExecEnv.CheckCombatLogFlagsObjectType(sourceFlags, %q)", conditionType = "select", - conditionTest = function(state, needle) - return state and state.show and Private.ExecEnv.CheckCombatLogFlagsObjectType(state.sourceFlags, needle); + conditionTest = function(state, needle, op) + if state and state.show then + return Private.ExecEnv.CheckCombatLogFlagsObjectType(state.sourceFlags, needle) == (op == "==") + end end }, { @@ -2577,8 +2583,10 @@ Private.event_prototypes = { store = true, test = "Private.ExecEnv.CheckRaidFlags(sourceRaidFlags, %q)", conditionType = "select", - conditionTest = function(state, needle) - return state and state.show and Private.ExecEnv.CheckRaidFlags(state.sourceRaidFlags, needle); + conditionTest = function(state, needle, op) + if state and state.show then + return Private.ExecEnv.CheckRaidFlags(state.sourceRaidFlags, needle) == (op == "==") + end end }, { @@ -2679,8 +2687,10 @@ Private.event_prototypes = { store = true, test = "Private.ExecEnv.CheckCombatLogFlags(destFlags, %q)", conditionType = "select", - conditionTest = function(state, needle) - return state and state.show and Private.ExecEnv.CheckCombatLogFlags(state.destFlags, needle); + conditionTest = function(state, needle, op) + if state and state.show then + return Private.ExecEnv.CheckCombatLogFlags(state.destFlags, needle) == (op == "==") + end end, enable = function(trigger) return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -2693,8 +2703,10 @@ Private.event_prototypes = { values = "combatlog_flags_check_reaction", test = "Private.ExecEnv.CheckCombatLogFlagsReaction(destFlags, %q)", conditionType = "select", - conditionTest = function(state, needle) - return state and state.show and Private.ExecEnv.CheckCombatLogFlagsReaction(state.destFlags, needle); + conditionTest = function(state, needle, op) + if state and state.show then + return Private.ExecEnv.CheckCombatLogFlagsReaction(state.destFlags, needle) == (op == "==") + end end, enable = function(trigger) return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -2707,8 +2719,10 @@ Private.event_prototypes = { values = "combatlog_flags_check_object_type", test = "Private.ExecEnv.CheckCombatLogFlagsObjectType(destFlags, %q)", conditionType = "select", - conditionTest = function(state, needle) - return state and state.show and Private.ExecEnv.CheckCombatLogFlagsObjectType(state.destFlags, needle); + conditionTest = function(state, needle, op) + if state and state.show then + return Private.ExecEnv.CheckCombatLogFlagsObjectType(state.destFlags, needle) == (op == "==") + end end, enable = function(trigger) return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -2728,8 +2742,10 @@ Private.event_prototypes = { store = true, test = "Private.ExecEnv.CheckRaidFlags(destRaidFlags, %q)", conditionType = "select", - conditionTest = function(state, needle) - return state and state.show and Private.ExecEnv.CheckRaidFlags(state.destRaidFlags, needle); + conditionTest = function(state, needle, op) + if state and state.show then + return Private.ExecEnv.CheckRaidFlags(state.destRaidFlags, needle) == (op == "==") + end end, enable = function(trigger) return not (trigger.subeventPrefix == "SPELL" and trigger.subeventSuffix == "_CAST_START"); @@ -4479,7 +4495,8 @@ Private.event_prototypes = { display = L["Totem Name"], type = "string", conditionType = "string", - store = true + store = true, + desc = L["Enter a name or a spellId"] }, { name = "totemNamePattern", @@ -5429,6 +5446,7 @@ Private.event_prototypes = { trigger.unit = trigger.unit or "target"; local ret = [[ unit = string.lower(unit) + local name = UnitName(unit, false) local ok = true local aggro, status, threatpct, rawthreatpct, threatvalue, threattotal if unit and unit ~= "none" then @@ -5510,6 +5528,43 @@ Private.event_prototypes = { limit = 2 }, }, + { + name = "name", + display = L["Unit Name"], + type = "string", + store = true, + multiline = true, + preamble = "local nameChecker = Private.ExecEnv.ParseStringCheck(%q)", + test = "nameChecker:Check(name)", + conditionType = "string", + conditionPreamble = function(input) + return Private.ExecEnv.ParseStringCheck(input) + end, + conditionTest = function(state, needle, op, preamble) + return preamble:Check(state.name) + end, + operator_types = "none", + desc = L["Supports multiple entries, separated by commas"] + }, + { + name = "npcId", + display = L["Npc ID"], + type = "string", + multiline = true, + store = true, + init = "tostring(tonumber(string.sub(UnitGUID(unit) or '', 8, 12), 16) or '')", + conditionType = "string", + preamble = "local npcIdChecker = Private.ExecEnv.ParseStringCheck(%q)", + test = "npcIdChecker:Check(npcId)", + conditionPreamble = function(input) + return Private.ExecEnv.ParseStringCheck(input) + end, + conditionTest = function(state, needle, op, preamble) + return preamble:Check(state.npcId) + end, + operator_types = "none", + desc = L["Supports multiple entries, separated by commas"] + }, { name = "value", hidden = true, @@ -5537,7 +5592,7 @@ Private.event_prototypes = { }, { hidden = true, - test = "WeakAuras.UnitExistsFixed(unit, smart) and specificUnitCheck" + test = "WeakAuras.UnitExistsFixed(unit, false) and specificUnitCheck" } }, automaticrequired = true diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index cec8b5a..961752b 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1139,13 +1139,6 @@ local function modify(parent, region, data) region.controlledChildren[childID] = region.controlledChildren[childID] or {} region.controlledChildren[childID][cloneID] = controlPoint childRegion:SetAnchor(data.selfPoint, controlPoint, data.selfPoint) - if(childData.frameStrata == 1) then - local frameStrata = region:GetFrameStrata() - childRegion:SetFrameStrata(frameStrata ~= "UNKNOWN" and frameStrata or "BACKGROUND"); - else - childRegion:SetFrameStrata(Private.frame_strata_types[childData.frameStrata]); - end - Private.ApplyFrameLevel(childRegion) return regionData end @@ -1397,6 +1390,17 @@ local function modify(parent, region, data) else controlPoint:SetParent(self) end + + local childData = controlPoint.regionData.data + local childRegion = controlPoint.regionData.region + if(childData.frameStrata == 1) then + local frameStrata = region:GetFrameStrata() + childRegion:SetFrameStrata(frameStrata ~= "UNKNOWN" and frameStrata or "BACKGROUND"); + else + childRegion:SetFrameStrata(Private.frame_strata_types[childData.frameStrata]); + end + Private.ApplyFrameLevel(childRegion) + if self.anchorPerUnit == "UNITFRAME" then Private.dyngroup_unitframe_monitor[regionData] = frame end diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index f0ed0db..2b92c01 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -84,7 +84,7 @@ local function modify(parent, region, data) if not text:GetFont() and fontPath then -- workaround font not loading correctly local objectName = "WeakAuras-Font-" .. data.font local fontObject = _G[objectName] or CreateFont(objectName) - fontObject:SetFont(fontPath, data.fontSize < 33 and data.fontSize or 33, data.outline) + fontObject:SetFont(fontPath, data.fontSize < 33 and data.fontSize or 33, data.outline == "None" and "" or data.outline) text:SetFontObject(fontObject) end text:SetFont(fontPath, data.fontSize < 33 and data.fontSize or 33, data.outline); diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index f15ac2a..1f41614 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -142,7 +142,7 @@ local function modify(parent, region, parentData, data, first) if not text:GetFont() and fontPath then -- workaround font not loading correctly local objectName = "WeakAuras-Font-" .. data.text_font local fontObject = _G[objectName] or CreateFont(objectName) - fontObject:SetFont(fontPath, data.text_fontSize < 33 and data.text_fontSize or 33, data.text_fontType) + fontObject:SetFont(fontPath, data.text_fontSize < 33 and data.text_fontSize or 33, data.text_fontType == "None" and "" or data.text_fontType) text:SetFontObject(fontObject) end if not text:GetFont() then -- Font invalid, set the font but keep the setting diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 5ab2ced..412b0bf 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3661,12 +3661,15 @@ local function SetFrameLevel(id, frameLevel) end function Private.FixGroupChildrenOrderForGroup(data) - local frameLevel = 1; - if data.parent == nil then - for child in Private.TraverseAll(data) do - SetFrameLevel(child.id, frameLevel); - frameLevel = frameLevel + 4; - end + local frameLevel, offset + if data.regionType == "dynamicgroup" then + frameLevel, offset = 5, 0 + else + frameLevel, offset = 1, 4 + end + for child in Private.TraverseLeafs(data) do + SetFrameLevel(child.id, frameLevel); + frameLevel = frameLevel + offset; end end diff --git a/WeakAurasOptions/OptionsFrames/IconPicker.lua b/WeakAurasOptions/OptionsFrames/IconPicker.lua index ca243f3..982de59 100644 --- a/WeakAurasOptions/OptionsFrames/IconPicker.lua +++ b/WeakAurasOptions/OptionsFrames/IconPicker.lua @@ -31,19 +31,6 @@ local function ConstructIconPicker(frame) local function iconPickerFill(subname, doSort) scroll:ReleaseChildren(); - - -- Work around special numbers such as inf and nan - if (tonumber(subname)) then - local spellId = tonumber(subname); - if (abs(spellId) < math.huge and tostring(spellId) ~= "nan") then - subname = GetSpellInfo(spellId or 0) - end - end - - if subname then - subname = subname:lower(); - end - local usedIcons = {}; local AddButton = function(name, icon) local button = AceGUI:Create("WeakAurasIconButton"); @@ -57,6 +44,24 @@ local function ConstructIconPicker(frame) usedIcons[icon] = true; end + -- Work around special numbers such as inf and nan + if (tonumber(subname)) then + local spellId = tonumber(subname); + if (abs(spellId) < math.huge and tostring(spellId) ~= "nan") then + local name, _, icon = GetSpellInfo(spellId) + if name and icon then + AddButton(name, icon) + end + return; + end + end + if subname then + subname = subname:lower(); + end + + + + local num = 0; if(subname and subname ~= "") then for name, icons in pairs(spellCache.Get()) do From dccd22b610a3d63dd5507b8f28fcea628e684222 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 19 Jan 2025 14:27:20 +0100 Subject: [PATCH 062/153] from retail --- WeakAuras/BuffTrigger2.lua | 14 +- WeakAuras/Init.lua | 4 - WeakAuras/Prototypes.lua | 147 +++++++++++++++++- WeakAuras/Transmission.lua | 14 +- WeakAuras/Types.lua | 100 +++++++++++- WeakAuras/WeakAuras.lua | 65 ++++---- ...UIWidget-WeakAurasDropDownItemCurrency.lua | 115 ++++++++++++++ ...GUIWidget-WeakAurasPendingUpdateButton.lua | 11 +- WeakAurasOptions/ActionOptions.lua | 11 +- WeakAurasOptions/AuthorOptions.lua | 23 ++- WeakAurasOptions/OptionsFrames/Update.lua | 104 +++++++++++-- WeakAurasOptions/WeakAurasOptions.lua | 12 +- WeakAurasOptions/WeakAurasOptions.toc | 1 + 13 files changed, 530 insertions(+), 91 deletions(-) create mode 100644 WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDropDownItemCurrency.lua diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 9cae769..82b5338 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -2686,10 +2686,22 @@ function BuffTrigger.GetTriggerConditions(data, triggernum) } result["unitCaster"] = { - display = L["Caster"], + display = L["Caster Unit"], type = "string" } + result["nameCaster"] = { + display = L["Casters Name/Realm"], + type = "string", + preamble = function(input) + return Private.ExecEnv.ParseNameCheck(input) + end, + test = function(state, needle, op, preamble) + return state.unitCaster and preamble:Check(WeakAuras.UnitNameWithRealm(state.unitCaster)) + end, + operator_types = "none", + } + result["expirationTime"] = { display = L["Remaining Duration"], type = "timer" diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index 6a46ecd..52a84c3 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -21,10 +21,6 @@ function WeakAuras.isAwesomeEnabled() return isAwesomeEnabled end -function WeakAuras.IsClassic() - return false -end - function WeakAuras.IsCorrectVersion() return true end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 7ee6a88..9df6346 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -1050,6 +1050,7 @@ Private.load_prototype = { operator = "and", limit = 2 }, + optional = true, }, { name = "group_leader", @@ -2191,7 +2192,7 @@ Private.event_prototypes = { display = L["Power Type"], type = "select", values = "power_types", - init = "unitPowerType", + init = "powerTypeToCheck", test = "true", store = true, conditionType = "select", @@ -4892,7 +4893,11 @@ Private.event_prototypes = { }, ["Chat Message"] = { type = "event", - events = { + events = function(trigger) + if trigger.use_messageType and trigger.messageType and Private.chat_message_types[trigger.messageType] then + return { ["events"] = {trigger.messageType} } + end + return { ["events"] = { "CHAT_MSG_BATTLEGROUND", "CHAT_MSG_BATTLEGROUND_LEADER", @@ -4920,9 +4925,11 @@ Private.event_prototypes = { "CHAT_MSG_WHISPER", "CHAT_MSG_YELL", "CHAT_MSG_SYSTEM", - "CHAT_MSG_TEXT_EMOTE" + "CHAT_MSG_TEXT_EMOTE", + "CHAT_MSG_LOOT", } - }, + } + end, name = L["Chat Message"], init = function(trigger) local ret = [[ @@ -7025,6 +7032,138 @@ Private.event_prototypes = { }, automaticrequired = true }, + --[[ Some day i will finish this, soonTM + ["Currency"] = { + type = "unit", + canHaveDuration = false, + events = { + ["events"] = { + "CURRENCY_DISPLAY_UPDATE", + } + }, + force_events = "CURRENCY_DISPLAY_UPDATE", + name = WeakAuras.newFeatureString..L["Currency"], + init = function(trigger) + local ret = [=[ + local currencyInfo = { + name = GetItemInfo(%d), + quantity = GetItemCount(%d), + iconFileID = select(6, GetItemInfo(%d)), + totalEarned = Private.GetTotalCountCurrencies(%d), + discovered = Private.GetDiscoveredCurencies(%d), + } + if not currencyInfo.name then + currencyInfo = { + name = "Unknown Currency", + quantity = 0, + iconFileID = "Interface\\Icons\\INV_Misc_QuestionMark", + totalEarned = 0, + discovered = false + } + end + ]=] + return ret:format(trigger.currencyId or 1, trigger.currencyId or 1, trigger.currencyId or 1, trigger.currencyId or 1, trigger.currencyId or 1) + end, + statesParameter = "one", + args = { + { + name = "currencyId", + type = "currency", + itemControl = "Dropdown-Currency", + values = Private.GetDiscoveredCurencies, + headers = Private.GetDiscoveredCurenciesHeaders, + sorted = true, + sortOrder = function() + local discovered_currencies_sorted = Private.GetDiscoveredCurenciesSorted() + local sortOrder = {} + for key, value in pairs(Private.GetDiscoveredCurencies()) do + tinsert(sortOrder, key) + end + table.sort(sortOrder, function(aKey, bKey) + local aValue = discovered_currencies_sorted[aKey] + local bValue = discovered_currencies_sorted[bKey] + return aValue < bValue + end) + return sortOrder + end, + required = true, + display = L["Currency"], + store = true, + test = "true", + }, + { + name = "name", + init = "currencyInfo.name", + hidden = true, + store = true, + test = "true", + }, + { + name = "value", + init = "currencyInfo.quantity", + type = "number", + display = L["Quantity"], + store = true, + conditionType = "number", + }, + { + name = "total", + init = "currencyInfo.maxQuantity", + type = "number", + hidden = true, + store = true, + test = "true", + }, + { + name = "progressType", + init = "'static'", + hidden = true, + store = true, + test = "true", + }, + { + name = "icon", + init = "currencyInfo.iconFileID", + store = true, + hidden = true, + test = "true", + }, + { + name = "totalEarned", + init = "currencyInfo.totalEarned", + type = "number", + display = L["Total Earned in this Season"], + store = true, + conditionType = "number", + enable = function(trigger) + -- soonTM + end + }, + { + name = "description", + init = "currencyInfo.description", + type = "string", + display = L["Description"], + store = true, + hidden = true, + test = "true", + }, + { + name = "discovered", + init = "currencyInfo.discovered", + type = "tristate", + display = L["Discovered"], + store = true, + conditionType = "bool", + }, + }, + GetNameAndIcon = function(trigger) + local currencyInfo = Private.GetCurrencyInfoForTrigger(trigger) + return currencyInfo and currencyInfo.name, currencyInfo and currencyInfo.iconFileID + end, + automaticrequired = true + }, + ]] ["Location"] = { type = "unit", events = { diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index f0ca9b6..b89e9b5 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -439,14 +439,14 @@ end local delayedImport = CreateFrame("FRAME") -local function ImportNow(data, children, target, sender, callbackFunc) +local function ImportNow(data, children, target, linkedAuras, sender, callbackFunc) if InCombatLockdown() then WeakAuras.prettyPrint(L["Importing will start after combat ends."]) delayedImport:RegisterEvent("PLAYER_REGEN_ENABLED") delayedImport:SetScript("OnEvent", function() delayedImport:UnregisterEvent("PLAYER_REGEN_ENABLED") - ImportNow(data, children, target, sender, callbackFunc) + ImportNow(data, children, target, linkedAuras, sender, callbackFunc) end) return end @@ -455,11 +455,11 @@ local function ImportNow(data, children, target, sender, callbackFunc) if not WeakAuras.IsOptionsOpen() then WeakAuras.OpenOptions() end - Private.OpenUpdate(data, children, target, sender, callbackFunc) + Private.OpenUpdate(data, children, target, linkedAuras, sender, callbackFunc) end end -function WeakAuras.Import(inData, target, callbackFunc) +function WeakAuras.Import(inData, target, callbackFunc, linkedAuras) local data, children, version if type(inData) == 'string' then -- encoded data @@ -495,7 +495,7 @@ function WeakAuras.Import(inData, target, callbackFunc) if highestVersion > WeakAuras.InternalVersion() then -- Do not run PreAdd but still show Import Window tooltipLoading = nil; - return ImportNow(data, children, target, nil, callbackFunc) + return ImportNow(data, children, target, linkedAuras, nil, callbackFunc) end ]] @@ -529,7 +529,7 @@ function WeakAuras.Import(inData, target, callbackFunc) end tooltipLoading = nil; - return ImportNow(data, children, target, nil, callbackFunc) + return ImportNow(data, children, target, linkedAuras, nil, callbackFunc) end local function crossRealmSendCommMessage(prefix, text, target, queueName, callbackFn, callbackArg) @@ -659,7 +659,7 @@ Comm:RegisterComm("WeakAuras", function(prefix, message, distribution, sender) end ItemRefTooltip:Hide() - ImportNow(data, children, nil, sender) + ImportNow(data, children, nil, nil, sender) elseif(received.m == "dR") then if(Private.linked and Private.linked[received.d] and Private.linked[received.d] > GetTime() - linkValidityDuration) then TransmitDisplay(received.d, sender); diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index f97a627..ba911b5 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -565,7 +565,7 @@ Private.format_types = { if abbreviateFunc then return function(guid) local ok, _, class, _, _, _, name, realm = pcall(GetPlayerInfoByGUID, guid) - if ok then + if ok and name then local name = abbreviateFunc(nameFunc(name, realm)) return colorFunc(class, name) end @@ -573,7 +573,7 @@ Private.format_types = { else return function(guid) local ok, _, class, _, _, _, name, realm = pcall(GetPlayerInfoByGUID, guid) - if ok then + if ok and name then return colorFunc(class, nameFunc(name, realm)) end end @@ -582,14 +582,14 @@ Private.format_types = { if abbreviateFunc then return function(guid) local ok, _, class, _, _, _, name, realm = pcall(GetPlayerInfoByGUID, guid) - if ok then + if ok and name then return abbreviateFunc(nameFunc(name, realm)) end end else return function(guid) local ok, _, class, _, _, _, name, realm = pcall(GetPlayerInfoByGUID, guid) - if ok then + if ok and name then return nameFunc(name, realm) end end @@ -1158,6 +1158,94 @@ for id, str in pairs(Private.combatlog_spell_school_types) do Private.combatlog_spell_school_types_for_ui[id] = ("%.3d - %s"):format(id, str) end +Private.item_quality_types = { + [0] = ITEM_QUALITY0_DESC, + [1] = ITEM_QUALITY1_DESC, + [2] = ITEM_QUALITY2_DESC, + [3] = ITEM_QUALITY3_DESC, + [4] = ITEM_QUALITY4_DESC, + [5] = ITEM_QUALITY5_DESC, + [6] = ITEM_QUALITY6_DESC, + [7] = ITEM_QUALITY7_DESC, + [8] = ITEM_QUALITY8_DESC, +} + +Private.totalcount_currencies = { + [45624] = 3018, -- Emblems of Conquest + [40753] = 1465, -- Emblems of Valor + [29434] = 1462, -- Badges of Justice + [40752] = 1464, -- Emblems of Heroism + [47241] = 4729, -- Emblems of Triumph + [49426] = 4730, -- Emblems of Frost +} + +function Private.GetTotalCountCurrencies(currencyID) + local achievementID = Private.totalcount_currencies[currencyID] + if achievementID then + local totalEarned = GetStatistic(achievementID) + return tonumber(totalEarned) or 0 + end + return nil +end + +local function InitializeCurrencies() + if Private.discovered_currencies then + return + end + Private.discovered_currencies = {} + Private.discovered_currencies_sorted = {} + Private.discovered_currencies_headers = {} + + local expanded = {} + for index = GetCurrencyListSize(), 1, -1 do + local name, isHeader, isExpanded, _, _, _, _, _, _ = GetCurrencyListInfo(index) + if isHeader and not isExpanded then + ExpandCurrencyList(index, true) + expanded[name] = true + end + end + + for index = 1, GetCurrencyListSize() do + local name, isHeader, _, _, _, _, _, iconFileID, itemID = GetCurrencyListInfo(index) + local currencyLink = tonumber(itemID) and GetItemInfo(itemID) + + if currencyLink then + local icon = iconFileID or "Interface\\Icons\\INV_Misc_QuestionMark" --iconFileID not available on first login + Private.discovered_currencies[itemID] = "|T" .. icon .. ":0|t" .. name + Private.discovered_currencies_sorted[itemID] = index + elseif isHeader then + Private.discovered_currencies[name] = name + Private.discovered_currencies_sorted[name] = index + Private.discovered_currencies_headers[name] = true + end + end + + for index = GetCurrencyListSize(), 1, -1 do + local name, isHeader = GetCurrencyListInfo(index) + if isHeader and expanded[name] then + ExpandCurrencyList(index, false) + end + end + + Private.discovered_currencies["member"] = "|Tinterface\\common\\ui-searchbox-icon:0:0:0:-2|t"..L["Specific Currency"]; + Private.discovered_currencies_sorted["member"] = -1; +end + +Private.GetDiscoveredCurencies = function() + InitializeCurrencies() + return Private.discovered_currencies +end + +Private.GetDiscoveredCurenciesSorted = function() + InitializeCurrencies() + return Private.discovered_currencies_sorted +end + +Private.GetDiscoveredCurenciesHeaders = function() + InitializeCurrencies() + return Private.discovered_currencies_headers +end + Private.combatlog_raid_mark_check_type = { [0] = RAID_TARGET_NONE, "|TInterface\\TARGETINGFRAME\\UI-RaidTargetingIcon_1:14|t " .. RAID_TARGET_1, -- Star @@ -2071,7 +2159,8 @@ Private.chat_message_types = { CHAT_MSG_SAY = L["Say"], CHAT_MSG_WHISPER = L["Whisper"], CHAT_MSG_YELL = L["Yell"], - CHAT_MSG_SYSTEM = L["System"] + CHAT_MSG_SYSTEM = L["System"], + CHAT_MSG_LOOT = L["Loot"], } Private.send_chat_message_types = { @@ -2474,6 +2563,7 @@ Private.update_categories = { "url", "desc", "version", + "semver" }, default = true, label = L["Meta Data"], diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 412b0bf..5a28e13 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -329,13 +329,6 @@ Private.ExecEnv.conditionHelpers = {} local load_prototype = Private.load_prototype; -local levelColors = { - [0] = "|cFFFFFFFF", - [1] = "|cFF40FF40", - [2] = "|cFF6060FF", - [3] = "|cFFFF4040" -}; - function Private.validate(input, default) for field, defaultValue in pairs(default) do if(type(defaultValue) == "table" and type(input[field]) ~= "table") then @@ -2209,11 +2202,16 @@ function Private.AddMany(tbl, takeSnapshots) coroutine.yield() local groups = {} for _, data in ipairs(order) do - WeakAuras.Add(data, takeSnapshots); - coroutine.yield() + WeakAuras.PreAdd(data) if data.regionType == "dynamicgroup" or data.regionType == "group" then groups[data] = true end + coroutine.yield() + end + + for _, data in ipairs(order) do + WeakAuras.Add(data, takeSnapshots); + coroutine.yield() end for id in pairs(anchorTargets) do @@ -2388,29 +2386,6 @@ local function validateUserConfig(data, options, config) end end -local function removeSpellNames(data) - local trigger - for i = 1, #data.triggers do - trigger = data.triggers[i].trigger - if trigger and trigger.type == "aura" then - if type(trigger.spellName) == "number" then - trigger.realSpellName = GetSpellInfo(trigger.spellName) or trigger.realSpellName - end - if (trigger.spellId) then - trigger.name = GetSpellInfo(trigger.spellId) or trigger.name; - end - if (trigger.spellIds) then - for i = 1, 10 do - if (trigger.spellIds[i]) then - trigger.names = trigger.names or {}; - trigger.names[i] = GetSpellInfo(trigger.spellIds[i]) or trigger.names[i]; - end - end - end - end - end -end - local function removeNameplateUnits(data) for _, triggerData in ipairs(data.triggers) do local trigger = triggerData.trigger @@ -2618,7 +2593,6 @@ function WeakAuras.PreAdd(data) end end validateUserConfig(data, data.authorOptions, data.config) - removeSpellNames(data) if not(WeakAuras.isAwesomeEnabled()) then removeNameplateUnits(data) end @@ -2811,11 +2785,11 @@ end function Private.SetRegion(data, cloneId) local regionType = data.regionType; if not(regionType) then - error("Improper arguments to Private.SetRegion - regionType not defined"); + error("Improper arguments to Private.SetRegion - regionType not defined in ".. data.id) else if(not regionTypes[regionType]) then regionType = "fallback"; - print("Improper arguments to WeakAuras.CreateRegion - regionType \""..data.regionType.."\" is not supported"); + print("Improper arguments to WeakAuras.CreateRegion - regionType \""..data.regionType.."\" is not supported in ".. data.id) end local id = data.id; @@ -3661,15 +3635,19 @@ local function SetFrameLevel(id, frameLevel) end function Private.FixGroupChildrenOrderForGroup(data) + SetFrameLevel(data.id, 0) local frameLevel, offset if data.regionType == "dynamicgroup" then frameLevel, offset = 5, 0 else - frameLevel, offset = 1, 4 + frameLevel, offset = 2, 4 end - for child in Private.TraverseLeafs(data) do - SetFrameLevel(child.id, frameLevel); - frameLevel = frameLevel + offset; + for _, childId in ipairs(data.controlledChildren) do + local data = WeakAuras.GetData(childId) + if data.regionType ~= "group" and data.regionType ~= "dynamicgroup" then + SetFrameLevel(childId, frameLevel); + frameLevel = frameLevel + offset; + end end end @@ -3679,18 +3657,27 @@ end function Private.ApplyFrameLevel(region, frameLevel) frameLevel = frameLevel or GetFrameLevelFor(region.id) + + local setBackgroundFrameLevel = false if region.subRegions then for index, subRegion in pairs(region.subRegions) do if subRegion.type == "subbackground" then subRegion:SetFrameLevel(frameLevel + index) + setBackgroundFrameLevel = true end end + if not setBackgroundFrameLevel then + region:SetFrameLevel(frameLevel) + end + for index, subRegion in pairs(region.subRegions) do if subRegion.type ~= "subbackground" then subRegion:SetFrameLevel(frameLevel + index) end end + else + region:SetFrameLevel(frameLevel) end end diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDropDownItemCurrency.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDropDownItemCurrency.lua new file mode 100644 index 0000000..6eced1a --- /dev/null +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDropDownItemCurrency.lua @@ -0,0 +1,115 @@ +-- Item: Toggle +-- Some sort of checkbox for dropdown menus. +-- Does not close the pullout on click. +-- Based on the AceGUI Toggle Item. Extracts the icon from the text + +local AceGUI = LibStub and LibStub("AceGUI-3.0", true) +local ItemBase = LibStub("AceGUI-3.0-DropDown-ItemBase"):GetItemBase() + +local widgetType = "Dropdown-Currency" +local widgetVersion = 1 + +local function UpdateToggle(self) + if self.value and not self.isHeader then + self.check:Show() + else + self.check:Hide() + end +end + +local function OnRelease(self) + ItemBase.OnRelease(self) + self:SetValue(nil) +end + +local function Frame_OnClick(this, button) + local self = this.obj + if self.disabled then return end + self.value = not self.value + if self.value then + PlaySound(856) -- SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON + else + PlaySound(857) -- SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF + end + UpdateToggle(self) + self:Fire("OnValueChanged", self.value) +end + +local function Frame_OnShow(self) + local userdata = self.obj.userdata + local key = userdata and userdata.value + local dropDownUserData = userdata and userdata.obj and userdata.obj.userdata + local headers = dropDownUserData and dropDownUserData.option and dropDownUserData.option.headers + if type(headers) == "function" then + headers = headers() + end + + local isHeader = headers and key and headers[key] + self.obj.isHeader = isHeader + + if isHeader then + self:SetScript("OnClick", nil) + self.obj.text:SetTextColor(1, 1, 0) + self.obj.text:SetPoint("TOPLEFT", self, "TOPLEFT", 7, 0) + self.obj.icon:Hide() + self.obj.useHighlight = false + else + self:SetScript("OnClick", Frame_OnClick) + self.obj.text:SetTextColor(1, 1, 1) + self.obj.text:SetPoint("TOPLEFT", self, "TOPLEFT", 34, 0) + self.obj.icon:Show() + self.obj.useHighlight = true + end + UpdateToggle(self.obj) +end + +-- exported +local function SetValue(self, value) + self.value = value + UpdateToggle(self) +end + +-- exported +local function GetValue(self) + return self.value +end + +local function SetText(self, text) + text = text or "" + local pos = text:find("|t", 1, true) + if pos then + ItemBase.SetText(self, text:sub(pos + 2)) + + local firstColon = text:find(":", 1, true) + local icon = text:sub(3, firstColon - 1) + self.icon:SetTexture(icon) + else + ItemBase.SetText(self, text) + end + self.fullText = text +end + + +local function Constructor() + local self = ItemBase.Create(widgetType) + + self.text:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 34) + + self.icon = self.frame:CreateTexture(nil, "OVERLAY") + self.icon:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 18, -2) + self.icon:SetWidth(12) + self.icon:SetHeight(12) + + self.frame:SetScript("OnClick", Frame_OnClick) + self.frame:SetScript("OnShow", Frame_OnShow) + + self.SetValue = SetValue + self.GetValue = GetValue + self.OnRelease = OnRelease + self.SetText = SetText + + AceGUI:RegisterAsWidget(self) + return self +end + +AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua index 9e2a95e..703194d 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasPendingUpdateButton.lua @@ -5,7 +5,7 @@ local L = WeakAuras.L local pairs, next, type, unpack = pairs, next, type, unpack -local Type, Version = "WeakAurasPendingUpdateButton", 5 +local Type, Version = "WeakAurasPendingUpdateButton", 6 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then @@ -57,7 +57,14 @@ local methods = { self.linkedChildren = {} function self.callbacks.OnUpdateClick() - WeakAuras.Import(self.companionData.encoded) + local linkedAuras = {} + for auraId in pairs(self.linkedAuras) do + if not self.linkedChildren[auraId] then + tinsert(linkedAuras, auraId) + end + end + + WeakAuras.Import(self.companionData.encoded, nil, nil, linkedAuras) end self:SetTitle(self.companionData.name) diff --git a/WeakAurasOptions/ActionOptions.lua b/WeakAurasOptions/ActionOptions.lua index eb9082c..6de47c1 100644 --- a/WeakAurasOptions/ActionOptions.lua +++ b/WeakAurasOptions/ActionOptions.lua @@ -12,15 +12,8 @@ local hiddenAll = OptionsPrivate.commonOptions.CreateHiddenAll("action") local getAll = OptionsPrivate.commonOptions.CreateGetAll("action") local setAll = OptionsPrivate.commonOptions.CreateSetAll("action", getAll) -local RestrictedChannelCheck -if WeakAuras.IsClassic() then - RestrictedChannelCheck = function() - return false - end -else - RestrictedChannelCheck = function(data) - return data.message_type == "SAY" or data.message_type == "YELL" or data.message_type == "SMARTRAID" - end +local RestrictedChannelCheck = function(data) + return data.message_type == "SAY" or data.message_type == "YELL" or data.message_type == "SMARTRAID" end --- a sound from each setter diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index 0619249..ac61d93 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -1253,10 +1253,21 @@ typeControlAdders = { name = WeakAuras.newFeatureString .. name(option, "noMerge", L["Prevent Merging"]), desc = desc(option, "noMerge", L["If checked, then this group will not merge with other group when selecting multiple auras."]), order = order(), - width = WeakAuras.doubleWidth, + width = option.groupType == "simple" and WeakAuras.doubleWidth or WeakAuras.normalWidth, get = get(option, "noMerge"), set = set(data, option, "noMerge"), } + if option.groupType ~="simple" then + args[prefix .. "sortAlphabetically"] = { + type = "toggle", + name = WeakAuras.newFeatureString .. name(option, "sortAlphabetically", L["Sort"]), + desc = desc(option, "sortAlphabetically", L["If checked, then the combo box in the User settings will be sorted."]), + order = order(), + width = WeakAuras.normalWidth, + get = get(option, "sortAlphabetically"), + set = set(data, option, "sortAlphabetically"), + } + end if option.groupType ~="simple" then args[prefix .. "limitType"] = { type = "select", @@ -2121,6 +2132,7 @@ local function addUserModeOption(options, args, data, order, prefix, i) end WeakAuras.ClearAndUpdateOptions(data.id, true) end, + sorting = option.sortAlphabetically and OptionsPrivate.Private.SortOrderForValues(values) or nil } args[prefix .. "resetEntry"] = { type = "execute", @@ -2355,6 +2367,15 @@ local function addUserModeOption(options, args, data, order, prefix, i) return AceGUIWidgetLSMlists[option.mediaType] end end + + userOption.sorting = function() + if option.mediaType == "sound" then + return OptionsPrivate.Private.SortOrderForValues(OptionsPrivate.Private.sound_file_types) + else + return nil + end + end + userOption.set = function(_, value) if option.mediaType == "sound" then PlaySoundFile(value, "Master") diff --git a/WeakAurasOptions/OptionsFrames/Update.lua b/WeakAurasOptions/OptionsFrames/Update.lua index e47fba1..19e78e9 100644 --- a/WeakAurasOptions/OptionsFrames/Update.lua +++ b/WeakAurasOptions/OptionsFrames/Update.lua @@ -991,7 +991,17 @@ local function SetCategories(globalCategories, categories) end end - +local function OnlyMetaDataCategory(categories) + local metaData = false + for category in pairs(categories) do + if category == "metadata" then + metaData = true + else + return false + end + end + return metaData +end local function GetCategories(diff, isRoot) local categories = {} @@ -1001,6 +1011,7 @@ local function GetCategories(diff, isRoot) categories[category] = true end end + return categories end @@ -1042,11 +1053,22 @@ local function BuildDiffsHelper(uid, newUidMap, oldUidMap, matchInfo) oldUidMap:SetDiff(matchedUid, diff, categories) SetCategories(matchInfo.activeCategories, categories) - matchInfo.diffs[uid] = true - if isGroup then - matchInfo.modifiedGroupCount = matchInfo.modifiedGroupCount + 1 + matchInfo.categories[uid] = categories + + if OnlyMetaDataCategory(categories) then + matchInfo.onlyMetaDataModified[uid] = true + if isGroup then + matchInfo.modifiedMetaDataGroupCount = matchInfo.modifiedMetaDataGroupCount + 1 + else + matchInfo.modifiedMetaDataCount = matchInfo.modifiedMetaDataCount + 1 + end else - matchInfo.modifiedCount = matchInfo.modifiedCount + 1 + matchInfo.modified[uid] = true + if isGroup then + matchInfo.modifiedGroupCount = matchInfo.modifiedGroupCount + 1 + else + matchInfo.modifiedCount = matchInfo.modifiedCount + 1 + end end else matchInfo.unmodified[uid] = true @@ -1140,6 +1162,8 @@ end local function hasChanges(matchInfo) return matchInfo.modifiedCount > 0 or matchInfo.modifiedGroupCount > 0 + or matchInfo.modifiedMetaDataCount > 0 + or matchInfo.modifiedMetaDataGroupCount > 0 or matchInfo.addedCount > 0 or matchInfo.addedGroupCount > 0 or matchInfo.deletedCount > 0 @@ -1151,13 +1175,17 @@ local function BuildDiffs(newUidMap, oldUidMap) local matchInfo = { modifiedCount = 0, modifiedGroupCount = 0, + modifiedMetaDataCount = 0, + modifiedMetaDataGroupCount = 0, unmodifiedCount = 0, unmodifiedGroupCount = 0, addedCount = 0, addedGroupCount = 0, deletedCount = 0, deletedGroupCount = 0, - diffs = {}, -- Contains diffs for new uids + modified = {}, -- Contains uids that were modified + onlyMetaDataModified = {}, -- Contains uids that are only metadata modified + categories = {}, -- Contains categories for uids unmodified = {}, -- Contains new uids that had a empty diff added = {}, -- Contains new uids that were added deleted = {}, -- Contains old uids that were removed @@ -1228,7 +1256,21 @@ local function MatchInfo(data, children, target) return matchInfo end -local function AddAuraList(container, uidMap, list, expandText) +local function CategoriesToDisplayText(categories) + local categoriesDisplayTexts = {} + for _, category in ipairs(OptionsPrivate.Private.update_categories) do + if categories[category.name] then + tinsert(categoriesDisplayTexts, category.label) + end + end + if #categoriesDisplayTexts > 0 then + return table.concat(categoriesDisplayTexts, ", ") + else + return nil + end +end + +local function AddAuraList(container, uidMap, list, categories, expandText) local expand = AceGUI:Create("WeakAurasExpand") local collapsed = true local image = collapsed and "Interface\\AddOns\\WeakAuras\\Media\\Textures\\expand" @@ -1247,7 +1289,16 @@ local function AddAuraList(container, uidMap, list, expandText) local sortedNames = {} for uid in pairs(list) do - tinsert(sortedNames, uidMap:GetIdFor(uid)) + if categories[uid] then + local categoriesText = CategoriesToDisplayText(categories[uid]) + if categoriesText then + tinsert(sortedNames, L["%s (%s)"]:format(uidMap:GetIdFor(uid), categoriesText)) + else + tinsert(sortedNames, uidMap:GetIdFor(uid)) + end + else + tinsert(sortedNames, uidMap:GetIdFor(uid)) + end end table.sort(sortedNames) @@ -1277,7 +1328,7 @@ local function AddAuraList(container, uidMap, list, expandText) end local methods = { - Open = function(self, data, children, target, sender, callbackFunc) + Open = function(self, data, children, target, linkedAuras, sender, callbackFunc) if(self.optionsWindow.window == "importexport") then self.optionsWindow.importexport:Close(); elseif(self.optionsWindow.window == "texture") then @@ -1294,6 +1345,7 @@ local methods = { data = data, children = children or {}, target = target, + linkedAuras = linkedAuras, sender = sender } self.userChoices = { @@ -1355,13 +1407,22 @@ local methods = { local matchInfoText = L["This is a modified version of your group: |cff9900FF%s|r"]:format(oldRootId) matchInfoResult:SetText(matchInfoText) if matchInfo.addedCount ~= 0 then - AddAuraList(self, matchInfo.newUidMap, matchInfo.added, L["%d |4aura:auras; added"]:format(matchInfo.addedCount)) + AddAuraList(self, matchInfo.newUidMap, matchInfo.added, {}, + L["%d |4aura:auras; added"]:format(matchInfo.addedCount)) end - if matchInfo.modifiedCount ~= 0 then - AddAuraList(self, matchInfo.oldUidMap, matchInfo.diffs, L["%d |4aura:auras; modified"]:format(matchInfo.modifiedCount)) + local modifiedCount = matchInfo.modifiedCount + matchInfo.modifiedGroupCount + if modifiedCount ~= 0 then + AddAuraList(self, matchInfo.oldUidMap, matchInfo.modified, matchInfo.categories, + L["%d |4aura:auras; modified"]:format(modifiedCount)) + end + local onlyMetaDataModifiedCount = matchInfo.modifiedMetaDataCount + matchInfo.modifiedMetaDataGroupCount + if onlyMetaDataModifiedCount ~= 0 then + AddAuraList(self, matchInfo.oldUidMap, matchInfo.onlyMetaDataModified, {}, + L["%d |4aura:auras; with meta data modified"]:format(onlyMetaDataModifiedCount)) end if matchInfo.deletedCount ~= 0 then - AddAuraList(self, matchInfo.oldUidMap, matchInfo.deleted, L["%d |4aura:auras; deleted"]:format(matchInfo.deletedCount)) + AddAuraList(self, matchInfo.oldUidMap, matchInfo.deleted, {}, + L["%d |4aura:auras; deleted"]:format(matchInfo.deletedCount)) end else matchInfoResult:SetText(L["This is a modified version of your aura, |cff9900FF%s.|r"]:format(oldRootId)) @@ -1444,6 +1505,23 @@ local methods = { self:AddChild(scamCheckText) end + if linkedAuras and next(linkedAuras) then + self:AddChild(AceGUI:Create("WeakAurasSpacer")) + + local linkedAurasText = AceGUI:Create("Label") + linkedAurasText:SetFontObject(GameFontHighlight) + linkedAurasText:SetFullWidth(true) + + local auraIdText = table.concat(self.pendingData.linkedAuras, ", ") + if #self.pendingData.linkedAuras == 1 then + linkedAurasText:SetText(L["This aura is marked as an update to an aura '%s', but cannot be used to update that aura. This usually happens if an aura is moved out of a group."]:format(auraIdText)) + else + linkedAurasText:SetText(L["This aura is marked as an update to auras '%s', but cannot be used to update them. This usually happens if an aura is moved out of a group."]:format(auraIdText)) + end + linkedAurasText:SetColor(1, 0, 0) + self:AddChild(linkedAurasText) + end + -- Let people install auras that are newer than their version of WeakAuras local highestVersion = data.internalVersion or 0 if children then diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index aac6bd8..ece4963 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -647,7 +647,7 @@ local function GetSortedOptionsLists() tinsert(to_sort, id); end end - table.sort(to_sort, function(a, b) return a < b end); + table.sort(to_sort, function(a, b) return a:lower() < b:lower() end) for _, id in ipairs(to_sort) do local data = WeakAuras.GetData(id); for child in OptionsPrivate.Private.TraverseAll(data) do @@ -663,7 +663,7 @@ local function GetSortedOptionsLists() tinsert(to_sort, id); end end - table.sort(to_sort, function(a, b) return a < b end); + table.sort(to_sort, function(a, b) return a:lower() < b:lower() end) for _, id in ipairs(to_sort) do local data = WeakAuras.GetData(id); for child in OptionsPrivate.Private.TraverseAll(data) do @@ -927,8 +927,8 @@ function OptionsPrivate.OpenDebugLog(text) frame.debugLog:Open(text) end -function OptionsPrivate.OpenUpdate(data, children, target, sender, callbackFunc) - return frame.update:Open(data, children, target, sender, callbackFunc) +function OptionsPrivate.OpenUpdate(data, children, target, linkedAuras, sender, callbackFunc) + return frame.update:Open(data, children, target, linkedAuras, sender, callbackFunc) end function OptionsPrivate.ConvertDisplay(data, newType) @@ -1196,7 +1196,7 @@ function OptionsPrivate.SortDisplayButtons(filter, overrideReset, id) wipe(frame.loadedButton.childButtons) if frame.loadedButton:GetExpanded() then - table.sort(topLevelLoadedAuras) + table.sort(topLevelLoadedAuras, function(a, b) return a:lower() < b:lower() end) for _, id in ipairs(topLevelLoadedAuras) do if aurasMatchingFilter[id] then addButton(displayButtons[id], aurasMatchingFilter, visible) @@ -1214,7 +1214,7 @@ function OptionsPrivate.SortDisplayButtons(filter, overrideReset, id) wipe(frame.unloadedButton.childButtons) if frame.unloadedButton:GetExpanded() then - table.sort(topLevelUnloadedAuras) + table.sort(topLevelUnloadedAuras, function(a, b) return a:lower() < b:lower() end) for _, id in ipairs(topLevelUnloadedAuras) do if aurasMatchingFilter[id] then addButton(displayButtons[id], aurasMatchingFilter, visible) diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index f88f087..3dd6e91 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -76,6 +76,7 @@ AceGUI-Widgets\AceGUIWidget-WeakAurasIcon.lua AceGUI-Widgets\AceGUIWidget-WeakAurasNewHeaderButton.lua AceGUI-Widgets\AceGUIWidget-WeakAurasLoadedHeaderButton.lua AceGUI-Widgets\AceGUIWidget-WeakAurasDisplayButton.lua +AceGUI-Widgets\AceGUIWidget-WeakAurasDropDownItemCurrency.lua AceGUI-Widgets\AceGUIWidget-WeakAurasPendingInstallButton.lua AceGUI-Widgets\AceGUIWidget-WeakAurasPendingUpdateButton.lua AceGUI-Widgets\AceGUIWidget-WeakAurasTextureButton.lua From 87c681b2f39aa1731de80e32d4531a0d03d659cb Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 19 Jan 2025 14:54:14 +0100 Subject: [PATCH 063/153] from retail --- WeakAuras/DebugLog.lua | 10 ++++----- WeakAuras/Profiling.lua | 21 ++++++++++++++++--- WeakAuras/RegionTypes/DynamicGroup.lua | 2 ++ WeakAuras/RegionTypes/Group.lua | 2 ++ WeakAuras/SubscribableObject.lua | 3 +-- WeakAuras/WeakAuras.lua | 5 +++++ WeakAurasArchive/WeakAurasArchive.lua | 12 ----------- WeakAurasArchive/WeakAurasArchive.toc | 4 +--- .../RegionOptions/DynamicGroup.lua | 17 +++++++++++++++ WeakAurasOptions/RegionOptions/Group.lua | 11 ++++++++++ 10 files changed, 62 insertions(+), 25 deletions(-) delete mode 100644 WeakAurasArchive/WeakAurasArchive.lua diff --git a/WeakAuras/DebugLog.lua b/WeakAuras/DebugLog.lua index a90e063..5af1933 100644 --- a/WeakAuras/DebugLog.lua +++ b/WeakAuras/DebugLog.lua @@ -8,11 +8,11 @@ local debugLogs = {} local enabled = {} Private.DebugLog = { - -- Print - -- Clear - -- SetEnabled - -- IsEnabled - -- GetLogs + Print = function(uid, text, ...) end, + Clear = function(uid) end, + SetEnabled = function(uid, enabled) end, + IsEnabled = function(uid) end, + GetLogs = function(uid) end } local function serialize(log, input) diff --git a/WeakAuras/Profiling.lua b/WeakAuras/Profiling.lua index 150588f..649597b 100644 --- a/WeakAuras/Profiling.lua +++ b/WeakAuras/Profiling.lua @@ -311,13 +311,25 @@ local function PrintOneProfile(popup, name, map, total) end local percent = "" if total then - percent = ", " .. string.format("%.2f", 100 * map.elapsed / total) .. "%" + percent = (", %.2f%%"):format(100 * map.elapsed / total) end + local spikeInfo = "" if map.spike then - spikeInfo = string.format("(%.2fms)", map.spike) + local r, g, b + if map.spike < 2 then + r, g, b = WeakAuras.GetHSVTransition(map.spike / 2, 0, 1, 0, 1, 1, 1, 0, 1) + elseif map.spike < 2.5 then + r, g, b = WeakAuras.GetHSVTransition((map.spike - 2) * 2, 1, 1, 0, 1, 1, 0.65, 0, 1) + elseif map.spike < 3 then + r, g, b = WeakAuras.GetHSVTransition((map.spike - 2.5) * 2, 1, 0.65, 0, 1, 1, 0, 0, 1) + else + r, g, b = 1, 0, 0 + end + spikeInfo = ("|cff%02x%02x%02x(%.2fms)|r"):format(r * 255, g * 255, b * 255, map.spike) end - popup:AddText(string.format("%s |cff999999%.2fms%s %s|r", name, map.elapsed, percent, spikeInfo)) + + popup:AddText(("%s |cff999999%.2fms%s %s|r"):format(name, map.elapsed, percent, spikeInfo)) end local function SortProfileMap(map) @@ -327,6 +339,9 @@ local function SortProfileMap(map) end sort(result, function(a, b) + if map[a].spike and map[b].spike then + return map[a].spike > map[b].spike + end return map[a].elapsed > map[b].elapsed end) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 961752b..3e66f6b 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -43,6 +43,8 @@ local default = { columnSpace = 1 } +Private.regionPrototype.AddAlphaToDefault(default); + local controlPointFunctions = { ["SetAnchorPoint"] = function(self, point, relativeFrame, relativePoint, offsetX, offsetY) self:ClearAllPoints(); diff --git a/WeakAuras/RegionTypes/Group.lua b/WeakAuras/RegionTypes/Group.lua index 2fc0738..ae79799 100644 --- a/WeakAuras/RegionTypes/Group.lua +++ b/WeakAuras/RegionTypes/Group.lua @@ -22,6 +22,8 @@ local default = { scale = 1, }; +Private.regionPrototype.AddAlphaToDefault(default); + -- Called when first creating a new region/display local function create(parent) -- Main region diff --git a/WeakAuras/SubscribableObject.lua b/WeakAuras/SubscribableObject.lua index c677286..614e334 100644 --- a/WeakAuras/SubscribableObject.lua +++ b/WeakAuras/SubscribableObject.lua @@ -4,8 +4,7 @@ local AddonName, Private = ... local WeakAuras = WeakAuras local L = WeakAuras.L -local SubscribableObject = -{ +local SubscribableObject ={ ClearSubscribers = function(self) self.events = {} self.subscribers = {} diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 5a28e13..ffb6d92 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1034,6 +1034,9 @@ do -- Archive stuff error(string.format(L["Could not load WeakAuras Archive, the addon is %s"], reason)) end end + if type(WeakAurasArchive) ~= "table" then + WeakAurasArchive = {} + end Archivist:Initialize(WeakAurasArchive) end return Archivist @@ -1164,6 +1167,8 @@ loadedFrame:SetScript("OnEvent", function(self, event, addon) db.displays = db.displays or {}; db.registered = db.registered or {}; + db.migrationCutoff = db.migrationCutoff or 730 + db.historyCutoff = db.historyCutoff or 730 Private.SyncParentChildRelationships(); local isFirstUIDValidation = db.dbVersion == nil or db.dbVersion < 26; diff --git a/WeakAurasArchive/WeakAurasArchive.lua b/WeakAurasArchive/WeakAurasArchive.lua deleted file mode 100644 index 2d26ee0..0000000 --- a/WeakAurasArchive/WeakAurasArchive.lua +++ /dev/null @@ -1,12 +0,0 @@ --- all this is is a frame that ensures that the SV is a table type -local addonName = ... -local loader = CreateFrame("FRAME") -loader:RegisterEvent("ADDON_LOADED") -loader:SetScript("OnEvent", function(self, _, addon) - if addon == addonName then - if type(WeakAurasArchive) ~= "table" then - WeakAurasArchive = {} - end - self:UnregisterEvent("ADDON_LOADED") - end -end) diff --git a/WeakAurasArchive/WeakAurasArchive.toc b/WeakAurasArchive/WeakAurasArchive.toc index 76d38d2..40f81e2 100644 --- a/WeakAurasArchive/WeakAurasArchive.toc +++ b/WeakAurasArchive/WeakAurasArchive.toc @@ -2,6 +2,4 @@ ## Title: WeakAuras Archive ## LoadOnDemand: 1 ## SavedVariables: WeakAurasArchive -## Dependencies: WeakAuras - -WeakAurasArchive.lua +## Dependencies: WeakAuras \ No newline at end of file diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index d93dcdc..63dd083 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -516,6 +516,12 @@ local function createOptions(id, data) name = L["Animated Expand and Collapse"], order = 27 }, + spacer = { + type = "description", + width = WeakAuras.normalWidth, + name = "", + order = 27.5 + }, scale = { type = "range", control = "WeakAurasSpinBox", @@ -539,6 +545,17 @@ local function createOptions(id, data) OptionsPrivate.ResetMoverSizer(); end }, + alpha = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Group Alpha"], + order = 29, + min = 0, + max = 1, + bigStep = 0.01, + isPercent = true + }, endHeader = { type = "header", order = 100, diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index 525f88b..d581c51 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -585,6 +585,17 @@ local function createOptions(id, data) OptionsPrivate.ResetMoverSizer(); end }, + alpha = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Group Alpha"], + order = 46, + min = 0, + max = 1, + bigStep = 0.01, + isPercent = true + }, endHeader = { type = "header", order = 100, From a643b275ba6e73f707976f7b0ca2259807c8ee61 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sun, 19 Jan 2025 16:02:00 +0100 Subject: [PATCH 064/153] from retail --- WeakAuras/AnchorToWeakAuras.lua | 2 +- WeakAuras/BuffTrigger2.lua | 42 ++++---- WeakAuras/GenericTrigger.lua | 25 +++-- WeakAuras/Prototypes.lua | 1 + WeakAuras/Transmission.lua | 5 +- WeakAuras/Types.lua | 4 +- WeakAuras/WeakAuras.lua | 97 +++++++++++++------ .../AceGUIWidget-WeakAurasDisplayButton.lua | 6 +- WeakAurasOptions/OptionsFrames/MoverSizer.lua | 6 +- .../RegionOptions/DynamicGroup.lua | 14 +++ WeakAurasOptions/RegionOptions/Group.lua | 14 +++ 11 files changed, 150 insertions(+), 66 deletions(-) diff --git a/WeakAuras/AnchorToWeakAuras.lua b/WeakAuras/AnchorToWeakAuras.lua index ae24901..008ba91 100644 --- a/WeakAuras/AnchorToWeakAuras.lua +++ b/WeakAuras/AnchorToWeakAuras.lua @@ -39,7 +39,7 @@ local function OnRename(_, uid, oldId, newId) local data = WeakAuras.GetData(attached) if data then data.anchorFrameFrame = "WeakAuras:" .. newId - WeakAuras.Add(data, nil, true) + WeakAuras.Add(data, true) end attachedToTarget[attached] = newId diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 82b5338..46b6743 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -2636,40 +2636,40 @@ end function BuffTrigger.GetAdditionalProperties(data, triggernum) local trigger = data.triggers[triggernum].trigger - local ret = "|cFFFF0000%".. triggernum .. ".spellId|r - " .. L["Spell ID"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".debuffClass|r - " .. L["Debuff Class"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".unitCaster|r - " .. L["Caster Unit"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".casterName|r - " .. L["Caster Name"] .. "\n" + local ret = "|cFFFFCC00%".. triggernum .. ".spellId|r - " .. L["Spell ID"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".debuffClass|r - " .. L["Debuff Class"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".unitCaster|r - " .. L["Caster Unit"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".casterName|r - " .. L["Caster Name"] .. "\n" if trigger.unit ~= "multi" then - ret = ret .. "|cFFFF0000%".. triggernum .. ".unit|r - " .. L["Unit"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".unit|r - " .. L["Unit"] .. "\n" end - ret = ret .. "|cFFFF0000%".. triggernum .. ".unitName|r - " .. L["Unit Name"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".matchCount|r - " .. L["Match Count"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".matchCountPerUnit|r - " .. L["Match Count per Unit"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".unitCount|r - " .. L["Units Affected"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".totalStacks|r - " .. L["Total stacks over all matches"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".unitName|r - " .. L["Unit Name"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".matchCount|r - " .. L["Match Count"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".matchCountPerUnit|r - " .. L["Match Count per Unit"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".unitCount|r - " .. L["Units Affected"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".totalStacks|r - " .. L["Total stacks over all matches"] .. "\n" if trigger.unit ~= "multi" then - ret = ret .. "|cFFFF0000%".. triggernum .. ".maxUnitCount|r - " .. L["Total Units"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".maxUnitCount|r - " .. L["Total Units"] .. "\n" end if not IsSingleMissing(trigger) and trigger.unit ~= "multi" and trigger.fetchTooltip then - ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip|r - " .. L["Tooltip"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip1|r - " .. L["First Value of Tooltip Text"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip2|r - " .. L["Second Value of Tooltip Text"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip3|r - " .. L["Third Value of Tooltip Text"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".tooltip4|r - " .. L["Fourth Value of Tooltip Text"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip|r - " .. L["Tooltip"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip1|r - " .. L["First Value of Tooltip Text"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip2|r - " .. L["Second Value of Tooltip Text"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip3|r - " .. L["Third Value of Tooltip Text"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip4|r - " .. L["Fourth Value of Tooltip Text"] .. "\n" end if trigger.unit ~= "multi" and trigger.fetchRaidMark then - ret = ret .. "|cFFFF0000%".. triggernum .. ".raidMark|r - " .. L["Raid Mark"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".raidMark|r - " .. L["Raid Mark"] .. "\n" end if (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party") and trigger.useAffected then - ret = ret .. "|cFFFF0000%".. triggernum .. ".affected|r - " .. L["Names of affected Players"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".unaffected|r - " .. L["Names of unaffected Players"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".affectedUnits|r - " .. L["Units of affected Players in a table format"] .. "\n" - ret = ret .. "|cFFFF0000%".. triggernum .. ".unaffectedUnits|r - " .. L["Units of unaffected Players in a table format"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".affected|r - " .. L["Names of affected Players"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".unaffected|r - " .. L["Names of unaffected Players"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".affectedUnits|r - " .. L["Units of affected Players in a table format"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".unaffectedUnits|r - " .. L["Units of unaffected Players in a table format"] .. "\n" end return ret diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 22ab767..96b2f48 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -177,12 +177,25 @@ function TestForLongString(trigger, arg) local name = arg.name; local test; local needle = trigger[name] + local caseInsensitive = arg.canBeCaseInsensitive and trigger[name .. "_caseInsensitive"] if(trigger[name.."_operator"] == "==") then - test = ("(%s == %s)"):format(name, Private.QuotedString(needle)) + if caseInsensitive then + test = ("(%s and (%s):lower() == (%s):lower())"):format(name, name, Private.QuotedString(needle)) + else + test = ("(%s == %s)"):format(name, Private.QuotedString(needle)) + end elseif(trigger[name.."_operator"] == "find('%s')") then - test = "(" .. name .. " and " .. name .. string.format(":find(%s, 1, true)", Private.QuotedString(needle)) .. ")" + if caseInsensitive then + test = ("(%s and %s:lower():find((%s):lower(), 1, true))"):format(name, name, Private.QuotedString(needle)) + else + test = ("(%s and %s:find(%s, 1, true))"):format(name, name, Private.QuotedString(needle)) + end elseif(trigger[name.."_operator"] == "match('%s')") then - test = "(" .. name .. " and " .. name .. string.format(":match(%s)", Private.QuotedString(needle)) .. ")" + if caseInsensitive then + test = ("(%s and %s:lower():match((%s):lower()))"):format(name, name, Private.QuotedString(needle)) + else + test = ("(%s and %s:match(%s))"):format(name, name, Private.QuotedString(needle)) + end end return test; end @@ -3765,12 +3778,12 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) if (enable and v.store and v.name and v.display) then found = true; - additional = additional .. "|cFFFF0000%".. triggernum .. "." .. v.name .. "|r - " .. v.display .. "\n"; + additional = additional .. "|cFFFFCC00%".. triggernum .. "." .. v.name .. "|r - " .. v.display .. "\n"; end end if prototype.countEvents then found = true; - additional = additional .. "|cFFFF0000%".. triggernum .. ".count|r - " .. L["Count"] .. "\n"; + additional = additional .. "|cFFFFCC00%".. triggernum .. ".count|r - " .. L["Count"] .. "\n"; end if (found) then ret = ret .. additional; @@ -3782,7 +3795,7 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) for var, varData in pairs(variables) do if (type(varData) == "table") then if varData.display then - ret = ret .. "|cFFFF0000%".. triggernum .. "." .. var .. "|r - " .. varData.display .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. "." .. var .. "|r - " .. varData.display .. "\n" end end end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 9df6346..93383b5 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4958,6 +4958,7 @@ Private.event_prototypes = { display = L["Message"], init = "arg", type = "longstring", + canBeCaseInsensitive = true, store = true, conditionType = "string", }, diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index b89e9b5..5e6f66d 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -146,6 +146,7 @@ local function filterFunc(_, event, msg, player, l, cs, t, flag, channelId, ...) local newMsg = ""; local remaining = msg; local done; + local anyLinkFound = false repeat local start, finish, characterName, displayName = remaining:find("%[WeakAuras: ([^%s]+) %- (.*)%]"); if(characterName and displayName) then @@ -154,11 +155,13 @@ local function filterFunc(_, event, msg, player, l, cs, t, flag, channelId, ...) newMsg = newMsg..remaining:sub(1, start-1); newMsg = newMsg.."|HBNplayer::weakauras|h|cFF8800FF["..characterName.." |r|cFF8800FF- "..displayName.."]|h|r"; remaining = remaining:sub(finish + 1); + anyLinkFound = true else + newMsg = newMsg .. remaining done = true; end until(done) - if newMsg ~= "" then + if anyLinkFound then if event == "CHAT_MSG_WHISPER" and not UnitInRaid(player) and not UnitInParty(player) then -- XXX: Need a guild check local _, num = BNGetNumFriends() for i=1, num do diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index ba911b5..30d44db 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -342,7 +342,7 @@ Private.format_types = { end }, Unit = { - display = L["Formats |cFFFF0000%unit|r"], + display = L["Formats |cFFFFCC00%unit|r"], AddOptions = function(symbol, hidden, addOption, get, withoutColor) if not withoutColor then addOption(symbol .. "_color", { @@ -470,7 +470,7 @@ Private.format_types = { end }, guid = { - display = L["Formats Player's |cFFFF0000%guid|r"], + display = L["Formats Player's |cFFFFCC00%guid|r"], AddOptions = function(symbol, hidden, addOption, get, withoutColor) if not withoutColor then addOption(symbol .. "_color", { diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index ffb6d92..57d19b4 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1112,6 +1112,7 @@ function Private.Login(initialTime, takeNewSnapshots) for _, region in pairs(Private.regions) do if (region.region and region.region.RunDelayedActions) then region.region:RunDelayedActions(); + coroutine.yield() end end end) @@ -2205,34 +2206,58 @@ function Private.AddMany(tbl, takeSnapshots) local order = loadOrder(tbl, idtable) coroutine.yield() - local groups = {} - for _, data in ipairs(order) do - WeakAuras.PreAdd(data) - if data.regionType == "dynamicgroup" or data.regionType == "group" then - groups[data] = true + + if takeSnapshots then + for _, data in ipairs(order) do + Private.SetMigrationSnapshot(data.uid, data) + coroutine.yield() + end + end + + local groups = {} + local bads = {} + for _, data in ipairs(order) do + if data.parent and bads[data.parent] then + bads[data.id] = true + else + local ok = pcall(WeakAuras.PreAdd, data) + if not ok then + geterrorhandler() + prettyPrint(L["Unable to modernize aura '%s'. This is probably due to corrupt data or a bad migration, please report this to the WeakAuras team."]:format(data.id)) + if data.regionType == "dynamicgroup" or data.regionType == "group" then + prettyPrint(L["All children of this aura will also not be loaded, to minimize the chance of further corruption."]) + end + bads[data.id] = true + elseif data.regionType == "dynamicgroup" or data.regionType == "group" then + groups[data] = true + end + coroutine.yield() end - coroutine.yield() end for _, data in ipairs(order) do - WeakAuras.Add(data, takeSnapshots); - coroutine.yield() + if not bads[data.id] then + WeakAuras.Add(data) + coroutine.yield() + end end for id in pairs(anchorTargets) do local data = idtable[id] - if data and (data.parent == nil or idtable[data.parent].regionType ~= "dynamicgroup") then + if data and not bads[data.id] and (data.parent == nil or idtable[data.parent].regionType ~= "dynamicgroup") then Private.EnsureRegion(id) end end for data in pairs(groups) do - if data.type == "dynamicgroup" then - if Private.regions[data.id] and Private.regions[data.id].region then - Private.regions[data.id].region:ReloadControlledChildren() + if not bads[data.id] then + if data.type == "dynamicgroup" then + if Private.regions[data.id] and Private.regions[data.id].region then + Private.regions[data.id].region:ReloadControlledChildren() + end + else + WeakAuras.Add(data) end - else - WeakAuras.Add(data) end coroutine.yield(); end @@ -2762,13 +2787,9 @@ local function pAdd(data, simpleChange) end end -function WeakAuras.Add(data, takeSnapshot, simpleChange) - local snapshot - if takeSnapshot or (data.internalVersion or 0) < internalVersion then - snapshot = CopyTable(data) - end - if takeSnapshot then - Private.SetMigrationSnapshot(data.uid, snapshot) +function WeakAuras.Add(data, simpleChange) + if (data.internalVersion or 0) < internalVersion then + Private.SetMigrationSnapshot(data.uid, data) end local ok, ret = pcall(WeakAuras.PreAdd, data) if not ok then @@ -3639,21 +3660,35 @@ local function SetFrameLevel(id, frameLevel) Private.frameLevels[id] = frameLevel; end -function Private.FixGroupChildrenOrderForGroup(data) - SetFrameLevel(data.id, 0) - local frameLevel, offset - if data.regionType == "dynamicgroup" then - frameLevel, offset = 5, 0 +local function FixGroupChildrenOrderImpl(data, frameLevel) + SetFrameLevel(data.id, frameLevel) + local offset + if data.sharedFrameLevel then + offset = 0 else - frameLevel, offset = 2, 4 + offset = 4 end for _, childId in ipairs(data.controlledChildren) do - local data = WeakAuras.GetData(childId) - if data.regionType ~= "group" and data.regionType ~= "dynamicgroup" then - SetFrameLevel(childId, frameLevel); - frameLevel = frameLevel + offset; + local childData = WeakAuras.GetData(childId) + if childData.regionType ~= "group" and childData.regionType ~= "dynamicgroup" then + frameLevel = frameLevel + offset + SetFrameLevel(childId, frameLevel) + else + frameLevel = frameLevel + offset + local endFrameLevel = FixGroupChildrenOrderImpl(childData, frameLevel) + if not data.sharedFrameLevel then + frameLevel = endFrameLevel + end end end + return frameLevel +end + +function Private.FixGroupChildrenOrderForGroup(data) + if data.parent then + return + end + FixGroupChildrenOrderImpl(data, 0) end local function GetFrameLevelFor(id) diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index 894ff34..cae4661 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -468,7 +468,11 @@ local methods = { fullName = name end end - editbox:Insert("[WeakAuras: "..fullName.." - "..self.data.id.."]"); + local url = "" + if self.data.url then + url = " ".. self.data.url + end + editbox:Insert("[WeakAuras: "..fullName.." - "..self.data.id.."]"..url) OptionsPrivate.Private.linked = OptionsPrivate.Private.linked or {} OptionsPrivate.Private.linked[self.data.id] = GetTime() elseif not self.data.controlledChildren then diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index 3219a1c..26efe73 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -40,7 +40,7 @@ local function moveOnePxl(direction) elseif direction == "right" then data.xOffset = data.xOffset + 1 end - WeakAuras.Add(data, nil, true) + WeakAuras.Add(data, true) WeakAuras.UpdateThumbnail(data) OptionsPrivate.ResetMoverSizer() OptionsPrivate.Private.AddParents(data) @@ -706,7 +706,7 @@ local function ConstructMoverSizer(parent) end end region:ResetPosition() - WeakAuras.Add(data, nil, true) + WeakAuras.Add(data, true) frame:ScaleCorners(region:GetWidth(), region:GetHeight()) WeakAuras.FillOptions() end) @@ -753,7 +753,7 @@ local function ConstructMoverSizer(parent) data.height = height region:ResetPosition() - WeakAuras.Add(data, nil, true) + WeakAuras.Add(data, true) OptionsPrivate.Private.AddParents(data) WeakAuras.UpdateThumbnail(data) diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 63dd083..0cc8850 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -556,6 +556,20 @@ local function createOptions(id, data) bigStep = 0.01, isPercent = true }, + sharedFrameLevel = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Flat Framelevels"], + desc = L["The group and all direct children will share the same base frame level."], + order = 30, + set = function(info, v) + data.sharedFrameLevel = v + WeakAuras.Add(data) + for parent in OptionsPrivate.Private.TraverseParents(data) do + WeakAuras.Add(parent) + end + end + }, endHeader = { type = "header", order = 100, diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index d581c51..aefe3a5 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -596,6 +596,20 @@ local function createOptions(id, data) bigStep = 0.01, isPercent = true }, + sharedFrameLevel = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Flat Framelevels"], + desc = L["The group and all direct children will share the same base frame level."], + order = 47, + set = function(info, v) + data.sharedFrameLevel = v + WeakAuras.Add(data) + for parent in OptionsPrivate.Private.TraverseParents(data) do + WeakAuras.Add(parent) + end + end + }, endHeader = { type = "header", order = 100, From 23c7da5ea6a2985ddbf71798b0a7089c81eefe86 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Wed, 22 Jan 2025 03:37:10 +0100 Subject: [PATCH 065/153] Refactor progress handling probably some regressions --- WeakAuras/Animations.lua | 334 ++++++------ WeakAuras/BossMods.lua | 61 ++- WeakAuras/BuffTrigger2.lua | 113 +++- WeakAuras/Conditions.lua | 116 ++++- WeakAuras/GenericTrigger.lua | 234 +++++---- WeakAuras/Modernize.lua | 23 + WeakAuras/Prototypes.lua | 113 ++-- WeakAuras/RegionTypes/AuraBar.lua | 173 ++----- WeakAuras/RegionTypes/Icon.lua | 134 ++--- WeakAuras/RegionTypes/ProgressTexture.lua | 157 ++---- WeakAuras/RegionTypes/RegionPrototype.lua | 488 +++++++++++------- WeakAuras/RegionTypes/StopMotion.lua | 243 +++++---- WeakAuras/RegionTypes/Text.lua | 22 +- WeakAuras/SubRegionTypes/SubText.lua | 15 +- WeakAuras/SubRegionTypes/Tick.lua | 260 ++++++---- WeakAuras/SubscribableObject.lua | 16 +- WeakAuras/Types.lua | 15 +- WeakAuras/WeakAuras.lua | 261 +++++++--- .../AceGUIWidget-WeakAurasDisplayButton.lua | 3 - ...ceGUIWidget-WeakAurasTwoColumnDropDown.lua | 15 +- WeakAurasOptions/AnimationOptions.lua | 28 +- WeakAurasOptions/CommonOptions.lua | 148 ++++++ WeakAurasOptions/ConditionOptions.lua | 139 ++++- WeakAurasOptions/GenericTrigger.lua | 4 + WeakAurasOptions/RegionOptions/AuraBar.lua | 11 +- WeakAurasOptions/RegionOptions/Icon.lua | 10 +- .../RegionOptions/ProgressTexture.lua | 7 +- WeakAurasOptions/RegionOptions/StopMotion.lua | 20 +- WeakAurasOptions/SubRegionOptions/Tick.lua | 137 ++++- 29 files changed, 2037 insertions(+), 1263 deletions(-) diff --git a/WeakAuras/Animations.lua b/WeakAuras/Animations.lua index b234022..956b16f 100644 --- a/WeakAuras/Animations.lua +++ b/WeakAuras/Animations.lua @@ -11,10 +11,175 @@ local function noopErrorHandler() end local frame = Private.frames["WeakAuras Main Frame"] +local function RunAnimation(key, anim, elapsed, time) + Private.StartProfileUID(anim.auraUID) + local finished = false + if(anim.duration_type == "seconds") then + if anim.duration > 0 then + anim.progress = anim.progress + (elapsed / anim.duration) + else + anim.progress = anim.progress + (elapsed / 1) + end + if(anim.progress >= 1) then + anim.progress = 1 + finished = true + end + elseif(anim.duration_type == "relative") then + local region = anim.region + if ((region.progressType == "timed" and region.duration < 0.01) + or (region.progressType == "static" and region.value < 0.01)) + then + anim.progress = 0 + if(anim.type == "start" or anim.type == "finish") then + finished = true + end + else + local relativeProgress = 0 + if(region.progressType == "static") then + relativeProgress = region.value / region.total + elseif (region.progressType == "timed") then + relativeProgress = 1 - ((region.expirationTime - time) / region.duration) + end + relativeProgress = region.inverse and (1 - relativeProgress) or relativeProgress + anim.progress = anim.duration > 0 and relativeProgress / anim.duration or 0 + local iteration = math.floor(anim.progress) + --anim.progress = anim.progress - iteration + if not(anim.iteration) then + anim.iteration = iteration + elseif(anim.iteration ~= iteration) then + anim.iteration = nil + finished = true + end + end + else + anim.progress = 1 + end + local progress = anim.inverse and (1 - anim.progress) or anim.progress + progress = anim.easeFunc(progress, anim.easeStrength or 3) + Private.ActivateAuraEnvironmentForRegion(anim.region) + if(anim.translateFunc) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Slide Animation"]) + if (anim.region.SetOffsetAnim) then + local ok, x, y = pcall(anim.translateFunc, progress, 0, 0, anim.dX, anim.dY) + if not ok then + errorHandler() + else + anim.region:SetOffsetAnim(x, y) + end + else + anim.region:ClearAllPoints() + local ok, x, y = pcall(anim.translateFunc, progress, anim.startX, anim.startY, anim.dX, anim.dY) + if not ok then + errorHandler() + else + anim.region:SetPoint(anim.selfPoint, anim.anchor, anim.anchorPoint, x, y) + end + end + end + if(anim.alphaFunc) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Fade Animation"]) + local ok, alpha = pcall(anim.alphaFunc, progress, anim.startAlpha, anim.dAlpha) + if not ok then + errorHandler() + else + if (anim.region.SetAnimAlpha) then + anim.region:SetAnimAlpha(alpha) + else + anim.region:SetAlpha(alpha) + end + end + end + if(anim.scaleFunc) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler + or Private.GetErrorHandlerUid(anim.auraUID, L["Zoom Animation"]) + local ok, scaleX, scaleY = pcall(anim.scaleFunc, progress, 1, 1, anim.scaleX, anim.scaleY) + if not ok then + errorHandler() + else + if(anim.region.Scale) then + anim.region:Scale(scaleX, scaleY) + else + anim.region:SetWidth(anim.startWidth * scaleX) + anim.region:SetHeight(anim.startHeight * scaleY) + end + end + end + if(anim.rotateFunc and anim.region.Rotate) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler + or Private.GetErrorHandlerUid(anim.auraUID, L["Rotate Animation"]) + local ok, rotate = pcall(anim.rotateFunc, anim.rotateFunc, progress, anim.startRotation, anim.rotate) + if not ok then + errorHandler() + else + anim.region:Rotate(rotate) + end + end + if(anim.colorFunc and anim.region.ColorAnim) then + local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler + or Private.GetErrorHandlerUid(anim.auraUID, L["Color Animation"]) + local startR, startG, startB, startA = anim.region:GetColor() + startR, startG, startB, startA = startR or 1, startG or 1, startB or 1, startA or 1 + local ok, r, g, b, a = pcall(anim.colorFunc, progress, startR, startG, startB, startA, + anim.colorR, anim.colorG, anim.colorB, anim.colorA) + if not ok then + errorHandler() + else + local errorHandler = Private.GetErrorHandlerId(anim.region.id, "Custom Color") + local success = pcall(anim.region.ColorAnim, anim.region, r, g, b, a) + if not success then + errorHandler() + end + end + end + Private.ActivateAuraEnvironment(nil) + if(finished) then + if not(anim.loop) then + if (anim.region.SetOffsetAnim) then + anim.region:SetOffsetAnim(0, 0) + else + if(anim.startX) then + anim.region:SetPoint(anim.selfPoint, anim.anchor, anim.anchorPoint, anim.startX, anim.startY) + end + end + if (anim.region.SetAnimAlpha) then + anim.region:SetAnimAlpha(nil) + elseif(anim.startAlpha) then + anim.region:SetAlpha(anim.startAlpha) + end + if(anim.startWidth) then + if(anim.region.Scale) then + anim.region:Scale(1, 1) + else + anim.region:SetWidth(anim.startWidth) + anim.region:SetHeight(anim.startHeight) + end + end + if(anim.startRotation) then + if(anim.region.Rotate) then + anim.region:Rotate(anim.startRotation); + end + end + if(anim.region.ColorAnim) then + anim.region:ColorAnim(nil) + end + animations[key] = nil + end + + if(anim.loop) then + Private.Animate(anim.namespace, anim.auraUID, anim.type, anim.anim, anim.region, anim.inverse, anim.onFinished, + anim.loop, anim.region.cloneId) + elseif(anim.onFinished) then + anim.onFinished() + end + end + Private.StopProfileUID(anim.auraUID) +end + local updatingAnimations; local last_update = GetTime(); local function UpdateAnimations() Private.StartProfileSystem("animations"); + for groupUid, groupRegion in pairs(pending_controls) do pending_controls[groupUid] = nil; groupRegion:DoPositionChildren(); @@ -23,164 +188,9 @@ local function UpdateAnimations() local time = GetTime(); local elapsed = time - last_update; last_update = time; - local num = 0; - for key, anim in pairs(animations) do - Private.StartProfileUID(anim.auraUID); - num = num + 1; - local finished = false; - if(anim.duration_type == "seconds") then - if anim.duration > 0 then - anim.progress = anim.progress + (elapsed / anim.duration); - else - anim.progress = anim.progress + (elapsed / 1); - end - if(anim.progress >= 1) then - anim.progress = 1; - finished = true; - end - elseif(anim.duration_type == "relative") then - local state = anim.region.state; - if (not state - or (state.progressType == "timed" and state.duration < 0.01) - or (state.progressType == "static" and state.value < 0.01)) then - anim.progress = 0; - if(anim.type == "start" or anim.type == "finish") then - finished = true; - end - else - local relativeProgress = 0; - if(state.progressType == "static") then - relativeProgress = state.value / state.total; - elseif (state.progressType == "timed") then - relativeProgress = 1 - ((state.expirationTime - time) / state.duration); - end - relativeProgress = state.inverse and (1 - relativeProgress) or relativeProgress; - anim.progress = anim.duration > 0 and relativeProgress / anim.duration or 0 - local iteration = math.floor(anim.progress); - --anim.progress = anim.progress - iteration; - if not(anim.iteration) then - anim.iteration = iteration; - elseif(anim.iteration ~= iteration) then - anim.iteration = nil; - finished = true; - end - end - else - anim.progress = 1; - end - local progress = anim.inverse and (1 - anim.progress) or anim.progress; - progress = anim.easeFunc(progress, anim.easeStrength or 3) - Private.ActivateAuraEnvironmentForRegion(anim.region) - if(anim.translateFunc) then - local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Slide Animation"]) - if (anim.region.SetOffsetAnim) then - local ok, x, y = pcall(anim.translateFunc, progress, 0, 0, anim.dX, anim.dY); - if not ok then - errorHandler(x) - else - anim.region:SetOffsetAnim(x, y); - end - else - anim.region:ClearAllPoints(); - local ok, x, y = pcall(anim.translateFunc, progress, anim.startX, anim.startY, anim.dX, anim.dY); - if not ok then - errorHandler(x) - else - anim.region:SetPoint(anim.selfPoint, anim.anchor, anim.anchorPoint, x, y); - end - end - end - if(anim.alphaFunc) then - local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Fade Animation"]) - local ok, alpha = pcall(anim.alphaFunc, progress, anim.startAlpha, anim.dAlpha); - if not ok then - errorHandler(alpha) - else - if (anim.region.SetAnimAlpha) then - anim.region:SetAnimAlpha(alpha); - else - anim.region:SetAlpha(alpha); - end - end - end - if(anim.scaleFunc) then - local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Zoom Animation"]) - local ok, scaleX, scaleY = pcall(anim.scaleFunc, progress, 1, 1, anim.scaleX, anim.scaleY); - if not ok then - errorHandler(scaleX) - else - if(anim.region.Scale) then - anim.region:Scale(scaleX, scaleY); - else - anim.region:SetWidth(anim.startWidth * scaleX); - anim.region:SetHeight(anim.startHeight * scaleY); - end - end - end - if(anim.rotateFunc and anim.region.Rotate) then - local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Rotate Animation"]) - local ok, rotate = pcall(anim.rotateFunc, progress, anim.startRotation, anim.rotate); - if not ok then - errorHandler(rotate) - else - anim.region:Rotate(rotate); - end - end - if(anim.colorFunc and anim.region.ColorAnim) then - local errorHandler = WeakAuras.IsOptionsOpen() and noopErrorHandler or Private.GetErrorHandlerUid(anim.auraUID, L["Color Animation"]) - local startR, startG, startB, startA = anim.region:GetColor(); - startR, startG, startB, startA = startR or 1, startG or 1, startB or 1, startA or 1; - local ok, r, g, b, a = pcall(anim.colorFunc, progress, startR, startG, startB, startA, anim.colorR, anim.colorG, anim.colorB, anim.colorA); - if not ok then - errorHandler(r) - else - local success = pcall(anim.region.ColorAnim, errorHandler, anim.region, r, g, b, a) - if not success then - Private.GetErrorHandlerId(anim.region.id, "Custom Color") - end - end - end - Private.ActivateAuraEnvironment(nil); - if(finished) then - if not(anim.loop) then - if (anim.region.SetOffsetAnim) then - anim.region:SetOffsetAnim(0, 0); - else - if(anim.startX) then - anim.region:SetPoint(anim.selfPoint, anim.anchor, anim.anchorPoint, anim.startX, anim.startY); - end - end - if (anim.region.SetAnimAlpha) then - anim.region:SetAnimAlpha(nil); - elseif(anim.startAlpha) then - anim.region:SetAlpha(anim.startAlpha); - end - if(anim.startWidth) then - if(anim.region.Scale) then - anim.region:Scale(1, 1); - else - anim.region:SetWidth(anim.startWidth); - anim.region:SetHeight(anim.startHeight); - end - end - if(anim.startRotation) then - if(anim.region.Rotate) then - anim.region:Rotate(anim.startRotation); - end - end - if(anim.region.ColorAnim) then - anim.region:ColorAnim(nil); - end - animations[key] = nil; - end - if(anim.loop) then - Private.Animate(anim.namespace, anim.auraUID, anim.type, anim.anim, anim.region, anim.inverse, anim.onFinished, anim.loop, anim.region.cloneId); - elseif(anim.onFinished) then - anim.onFinished(); - end - end - Private.StopProfileUID(anim.auraUID); + for key, anim in pairs(animations) do + RunAnimation(key, anim, elapsed, time) end Private.StopProfileSystem("animations"); @@ -188,12 +198,14 @@ end function Private.RegisterGroupForPositioning(uid, region) pending_controls[uid] = region - updatingAnimations = true - frame:SetScript("OnUpdate", UpdateAnimations) + if not updatingAnimations then + updatingAnimations = true + last_update = GetTime() + frame:SetScript("OnUpdate", UpdateAnimations) + end end function Private.Animate(namespace, uid, type, anim, region, inverse, onFinished, loop, cloneId) - local auraDisplayName = Private.UIDtoID(uid) local key = tostring(region); local valid; if(anim and anim.type == "custom" and (anim.use_translate or anim.use_alpha or (anim.use_scale and region.Scale) or (anim.use_rotate and region.Rotate) or (anim.use_color and region.Color))) then @@ -388,8 +400,10 @@ function Private.Animate(namespace, uid, type, anim, region, inverse, onFinished if not(updatingAnimations) then frame:SetScript("OnUpdate", UpdateAnimations); + last_update = GetTime() updatingAnimations = true; end + RunAnimation(key, animation, 0, GetTime()) return true; else if(animations[key]) then diff --git a/WeakAuras/BossMods.lua b/WeakAuras/BossMods.lua index c4da07c..f5ff989 100644 --- a/WeakAuras/BossMods.lua +++ b/WeakAuras/BossMods.lua @@ -150,7 +150,7 @@ Private.ExecEnv.BossMods.DBM = { end end if self.nextExpire then - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, self.nextExpire - now, self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, self.nextExpire - now, self) end end, @@ -214,11 +214,11 @@ Private.ExecEnv.BossMods.DBM = { WeakAuras.ScanEvents("BossMod_TimerStart", timerId) end if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, expirationTime - now, self) self.nextExpire = expirationTime elseif expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, expirationTime - now, self) self.nextExpire = expirationTime end elseif event == "DBM_TimerStop" then @@ -261,11 +261,11 @@ Private.ExecEnv.BossMods.DBM = { WeakAuras.ScanEvents("BossMod_TimerResume", timerId) end if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - GetTime(), self) self.nextExpire = bar.expirationTime elseif bar.expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - GetTime(), self) self.nextExpire = bar.expirationTime end end @@ -278,11 +278,11 @@ Private.ExecEnv.BossMods.DBM = { bar.duration = duration bar.expirationTime = expirationTime if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - now, self) self.nextExpire = expirationTime elseif self.nextExpire == nil or expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - now, self) self.nextExpire = expirationTime end end @@ -338,7 +338,7 @@ Private.ExecEnv.BossMods.DBM = { ScheduleCheck = function(self, fireTime) if not self.scheduled_scans[fireTime] then - self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime(), self, fireTime) + self.scheduled_scans[fireTime] = timer:ScheduleTimer(self.DoScan, fireTime - GetTime(), self, fireTime) end end } @@ -377,6 +377,7 @@ Private.event_prototypes["DBM Stage"] = { }, automaticrequired = true, statesParameter = "one", + progressType = "none" } Private.category_event_prototype.addons["DBM Stage"] = L["DBM Stage"] @@ -433,7 +434,8 @@ Private.event_prototypes["DBM Announce"] = { init = "use_cloneId and WeakAuras.GetUniqueCloneId() or ''" }, }, - timedrequired = true + timedrequired = true, + progressType = "timed" } Private.category_event_prototype.addons["DBM Announce"] = L["DBM Announce"] @@ -445,7 +447,7 @@ Private.event_prototypes["DBM Timer"] = { }, force_events = "DBM_TimerForce", name = L["DBM Timer"], - canHaveDuration = "timed", + progressType = "timed", triggerFunction = function(trigger) Private.ExecEnv.BossMods.DBM:RegisterTimer() local ret = [=[ @@ -681,6 +683,7 @@ Private.ExecEnv.BossMods.BigWigs = { state.addon = bar.addon state.spellId = bar.spellId state.text = bar.text + state.message = bar.text state.name = bar.text state.duration = bar.duration + extendTimer state.expirationTime = bar.expirationTime + extendTimer @@ -803,7 +806,7 @@ Private.ExecEnv.BossMods.BigWigs = { end if self.nextExpire then - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, self.nextExpire - now, self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, self.nextExpire - now, self) end end, @@ -843,11 +846,11 @@ Private.ExecEnv.BossMods.BigWigs = { WeakAuras.ScanEvents("BossMod_TimerStart", text) end if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, expirationTime - now, self) self.nextExpire = expirationTime elseif expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, expirationTime - now, self) self.nextExpire = expirationTime end elseif event == "BigWigs_StopBar" then @@ -889,10 +892,10 @@ Private.ExecEnv.BossMods.BigWigs = { WeakAuras.ScanEvents("BossMod_TimerResume", text) end if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - GetTime(), self) elseif bar.expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - GetTime(), self) self.nextExpire = bar.expirationTime end end @@ -979,7 +982,7 @@ Private.ExecEnv.BossMods.BigWigs = { ScheduleCheck = function(self, fireTime) if not self.scheduled_scans[fireTime] then - self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime(), self, fireTime) + self.scheduled_scans[fireTime] = timer:ScheduleTimer(self.DoScan, fireTime - GetTime(), self, fireTime) end end } @@ -1007,6 +1010,7 @@ Private.event_prototypes["BigWigs Stage"] = { }, automaticrequired = true, statesParameter = "one", + progressType = "none" } Private.category_event_prototype.addons["BigWigs Stage"] = L["BigWigs Stage"] @@ -1033,8 +1037,8 @@ Private.event_prototypes["BigWigs Message"] = { { name = "spellId", init = "arg", - display = L["Key"], - desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], + display = L["ID"], + desc = L["The 'ID' value can be found in the BigWigs options of a specific spell"], type = "spell", conditionType = "string", noValidation = true, @@ -1072,7 +1076,8 @@ Private.event_prototypes["BigWigs Message"] = { init = "use_cloneId and WeakAuras.GetUniqueCloneId() or ''" }, }, - timedrequired = true + timedrequired = true, + progressType = "timed" } Private.category_event_prototype.addons["BigWigs Message"] = L["BigWigs Message"] @@ -1084,7 +1089,7 @@ Private.event_prototypes["BigWigs Timer"] = { }, force_events = "BigWigs_Timer_Force", name = L["BigWigs Timer"], - canHaveDuration = "timed", + progressType = "timed", triggerFunction = function(trigger) Private.ExecEnv.BossMods.BigWigs:RegisterTimer() local ret = [=[ @@ -1237,8 +1242,8 @@ Private.event_prototypes["BigWigs Timer"] = { args = { { name = "spellId", - display = L["Key"], - desc = L["The 'Key' value can be found in the BigWigs options of a specific spell"], + display = L["ID"], + desc = L["The 'ID' value can be found in the BigWigs options of a specific spell"], type = "spell", conditionType = "string", noValidation = true, @@ -1350,6 +1355,7 @@ Private.event_prototypes["Boss Mod Stage"] = { }, automaticrequired = true, statesParameter = "one", + progressType = "none" } Private.category_event_prototype.addons["Boss Mod Stage"] = L["Boss Mod Stage"] @@ -1382,7 +1388,7 @@ Private.event_prototypes["Boss Mod Stage (Event)"] = { }, }, statesParameter = "one", - canHaveDuration = "timed", + progressType = "timed", delayEvents = true, timedrequired = true } @@ -1405,7 +1411,7 @@ Private.event_prototypes["Boss Mod Announce"] = { { name = "spellId", init = "arg", - display = L["Key"], + display = L["ID"], store = true, type = "spell", conditionType = "string", @@ -1463,7 +1469,8 @@ Private.event_prototypes["Boss Mod Announce"] = { text = ActiveBossModText }, }, - timedrequired = true + timedrequired = true, + progressType = "timed" } Private.category_event_prototype.addons["Boss Mod Announce"] = L["Boss Mod Announce"] @@ -1475,7 +1482,7 @@ Private.event_prototypes["Boss Mod Timer"] = { }, force_events = "BossMod_TimerForce", name = L["Boss Mod Timer"], - canHaveDuration = "timed", + progressType = "timed", triggerFunction = function(trigger) Private.ExecEnv.BossMods.Generic:RegisterTimer() local ret = [=[ @@ -1638,7 +1645,7 @@ Private.event_prototypes["Boss Mod Timer"] = { args = { { name = "spellId", - display = L["Key"], + display = L["ID"], store = true, type = "spell", conditionType = "string", diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 46b6743..7977473 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -29,15 +29,9 @@ Updates all buff triggers in data. # Helper functions mainly for the WeakAuras Options # ##################################################### -CanHaveDuration(data, triggernum) -Returns whether the trigger can have a duration. - GetOverlayInfo(data, triggernum) Returns a table containing all overlays. Currently there aren't any -CanHaveClones(data, triggernum) -Returns whether the trigger can have clones. - CanHaveTooltip(data, triggernum) Returns the type of tooltip to show for the trigger. @@ -2525,13 +2519,6 @@ function BuffTrigger.Add(data) end end ---- Returns whether the trigger can have a duration. --- @param data --- @param triggernum -function BuffTrigger.CanHaveDuration(data, triggernum) - return "timed" -end - --- Returns a table containing the names of all overlays -- @param data -- @param triggernum @@ -2543,7 +2530,7 @@ end -- @param data -- @param triggernum -- @return -function BuffTrigger.CanHaveClones(data, triggernum) +local function CanHaveClones(data, triggernum) local trigger = data.triggers[triggernum].trigger if not IsSingleMissing(trigger) and trigger.showClones then return true @@ -2661,6 +2648,13 @@ function BuffTrigger.GetAdditionalProperties(data, triggernum) ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip4|r - " .. L["Fourth Value of Tooltip Text"] .. "\n" end + if trigger.unit ~= "multi" then + ret = ret .. "|cFFFFCC00%".. triggernum .. ".stackGainTime|r - " .. L["Since Stack Gain"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".stackLostTime|r - " .. L["Since Stack Lost"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".initialTime|r - " .. L["Since Apply"] .. "\n" + ret = ret .. "|cFFFFCC00%".. triggernum .. ".refreshTime|r - " .. L["Since Apply/Refresh"] .. "\n" + end + if trigger.unit ~= "multi" and trigger.fetchRaidMark then ret = ret .. "|cFFFFCC00%".. triggernum .. ".raidMark|r - " .. L["Raid Mark"] .. "\n" end @@ -2675,6 +2669,95 @@ function BuffTrigger.GetAdditionalProperties(data, triggernum) return ret end +function BuffTrigger.GetProgressSources(data, triggernum, values) + local trigger = data.triggers[triggernum].trigger + tinsert(values, { + trigger = triggernum, + property = "matchCount", + type = "number", + display = L["Match Count"] + }) + tinsert(values, { + trigger = triggernum, + property = "matchCountPerUnit", + type = "number", + display = L["Match Count per Unit"] + }) + tinsert(values, { + trigger = triggernum, + property = "unitCount", + type = "number", + display = L["Units Affected"], + total = trigger.unit ~= "multi" and "maxUnitCount" or nil + }) + tinsert(values, { + trigger = triggernum, + property = "stacks", + type = "number", + display = L["Stacks"] + }) + tinsert(values, { + trigger = triggernum, + property = "totalStacks", + type = "number", + display = L["Total stacks over all matches"] + }) + if not IsSingleMissing(trigger) and trigger.unit ~= "multi" and trigger.fetchTooltip then + tinsert(values, { + trigger = triggernum, + property = "tooltip1", + type = "number", + display = L["Tooltip 1"] + }) + tinsert(values, { + trigger = triggernum, + property = "tooltip2", + type = "number", + display = L["Tooltip 2"] + }) + tinsert(values, { + trigger = triggernum, + property = "tooltip3", + type = "number", + display = L["Tooltip 3"] + }) + end + tinsert(values, { + trigger = triggernum, + property = "expirationTime", + type = "timer", + display = L["Timed Progress"], + total = "duration", + modRate = "modRate", + paused = "paused", + remaining = "remaining" + }) + tinsert(values, { + trigger = triggernum, + property = "stackGainTime", + type = "elapsedTimer", + display = L["Time since stack gain"], + }) + tinsert(values, { + trigger = triggernum, + property = "stackLostTime", + type = "elapsedTimer", + display = L["Time since stack lost"], + }) + tinsert(values, { + trigger = triggernum, + property = "initialTime", + type = "elapsedTimer", + display = L["Time since initial application"], + }) + tinsert(values, { + trigger = triggernum, + property = "refreshTime", + type = "elapsedTimer", + display = L["Time since last refresh"], + }) +end + function BuffTrigger.GetTriggerConditions(data, triggernum) local trigger = data.triggers[triggernum].trigger local result = {} @@ -3481,7 +3564,7 @@ function BuffTrigger.CreateFakeStates(id, triggernum) state.progressType = "timed" state.stacks = 1 allStates[""] = state - if BuffTrigger.CanHaveClones(data, triggernum) then + if CanHaveClones(data, triggernum) then for i = 1, 2 do local state = {} BuffTrigger.CreateFallbackState(data, triggernum, state) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index 60044ee..627fcf3 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -34,7 +34,7 @@ end Private.callbacks:RegisterCallback("Delete", OnDelete) -local function formatValueForAssignment(vType, value, pathToCustomFunction, pathToFormatters) +local function formatValueForAssignment(vType, value, pathToCustomFunction, pathToFormatters, data) if (value == nil) then value = false; end @@ -49,6 +49,41 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path return tostring(value) end return "nil" + elseif vType == "progressSource" then + if type(value) == "table" then + local progressSource = Private.AddProgressSourceMetaData(data, value) + local trigger = progressSource[1] or -1 + local progressType = progressSource[2] or "auto" + local property = progressSource[3] + local totalProperty = progressSource[4] + local inverseProperty = progressSource[5] + local pausedProperty = progressSource[6] + local remainingProperty = progressSource[7] + + if trigger == 0 then + -- Manual progress + local serialized = string.format("{%s, %s, %s, %s}", + trigger, + Private.QuotedString(progressType), + property or "0", -- Actually: value + totalProperty or "100" -- Actually: total + ) + return serialized + else + local serialized = string.format("{%s, %s, %s, %s, %s, %s, %s, %s}", + trigger, + Private.QuotedString(progressType), + Private.QuotedString(property or "nil"), + totalProperty and Private.QuotedString(totalProperty) or "nil", + inverseProperty and Private.QuotedString(inverseProperty) or "nil", + pausedProperty and Private.QuotedString(pausedProperty) or "nil", + remainingProperty and Private.QuotedString(remainingProperty) or "nil" + ) + return serialized + end + else + return "nil" + end elseif (vType == "icon") then if type(value) == "string" then return string.format("%s", Private.QuotedString(value)) @@ -119,7 +154,9 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path end local function formatValueForCall(type, property) - if (type == "bool" or type == "number" or type == "list" or type == "icon" or type == "string") then + if type == "bool" or type == "number" or type == "list" or type == "icon" or type == "string" + or type == "progressSource" + then return "propertyChanges['" .. property .. "']"; elseif (type == "color") then local pcp = "propertyChanges['" .. property .. "']"; @@ -162,7 +199,8 @@ function Private.ExecEnv.CallCustomConditionTest(uid, testFunctionNumber, ...) end end -local function CreateTestForCondition(uid, input, allConditionsTemplate, usedStates) +local function CreateTestForCondition(data, input, allConditionsTemplate, usedStates) + local uid = data.uid local trigger = input and input.trigger; local variable = input and input.variable; local op = input and input.op; @@ -175,7 +213,7 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta local test = {}; if (input.checks) then for i, subcheck in ipairs(input.checks) do - local subtest, subrecheckCode = CreateTestForCondition(uid, subcheck, allConditionsTemplate, usedStates); + local subtest, subrecheckCode = CreateTestForCondition(data, subcheck, allConditionsTemplate, usedStates); if (subtest) then tinsert(test, "(" .. subtest .. ")"); end @@ -201,6 +239,14 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta local cType = conditionTemplate and conditionTemplate.type; local test = conditionTemplate and conditionTemplate.test; local preamble = conditionTemplate and conditionTemplate.preamble; + local progressSource + local pausedProperty + local remainingProperty + if cType == "timer" then + progressSource = Private.GetProgressSourceFor(data, trigger, variable) + pausedProperty = progressSource and progressSource[6] + remainingProperty = progressSource[7] + end local stateCheck = "state[" .. trigger .. "] and state[" .. trigger .. "].show and "; local stateVariableCheck = string.format("state[" .. trigger .. "][%q]", variable) .. "~= nil and "; @@ -247,10 +293,18 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]" .. string.format("[%q]", variable) .. op .. v; end elseif (cType == "timer" and value and op) then + local triggerState = "state[" .. trigger .. "]" + local varString = triggerState .. string.format("[%q]", variable) + local remainingTime = "(" .. varString .. " - now)" + if pausedProperty and remainingProperty then + local pausedString = "state[" .. trigger .. "]" .. string.format("[%q]", pausedProperty) + local remainingString = "(state[" .. trigger .. "]" .. string.format("[%q]", remainingProperty) .. " or 0)" + remainingTime = "((" .. pausedString .. " and " .. remainingString .. ") or " .. remainingTime .. ")" + end if (op == "==") then - check = stateCheck .. stateVariableCheck .. "abs(state[" .. trigger .. "]" .. string.format("[%q]", variable) .. "- now -" .. value .. ") < 0.05"; + check = stateCheck .. stateVariableCheck .. "abs((" .. remainingTime .. "-" .. value .. ")" .. " < 0.05" else - check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]" .. string.format("[%q]", variable) .. "- now" .. op .. value; + check = stateCheck .. stateVariableCheck .. remainingTime .. op .. value end elseif (cType == "elapsedTimer" and value and op) then if (op == "==") then @@ -341,9 +395,9 @@ local function CreateTestForCondition(uid, input, allConditionsTemplate, usedSta return check, recheckCode; end -local function CreateCheckCondition(uid, ret, condition, conditionNumber, allConditionsTemplate, nextIsLinked, debug) +local function CreateCheckCondition(data, ret, condition, conditionNumber, allConditionsTemplate, nextIsLinked, debug) local usedStates = {}; - local check, recheckCode = CreateTestForCondition(uid, condition.check, allConditionsTemplate, usedStates); + local check, recheckCode = CreateTestForCondition(data, condition.check, allConditionsTemplate, usedStates); if not check then check = "false" end @@ -401,8 +455,16 @@ local function CreateDeactivateCondition(ret, condition, conditionNumber, data, local propertyData = properties and properties[change.property] if (propertyData and propertyData.type and propertyData.setter) then usedProperties[change.property] = true; - ret = ret .. " propertyChanges['" .. change.property .. "'] = " .. formatValueForAssignment(propertyData.type, GetBaseProperty(data, change.property)) .. "\n"; - if (debug) then ret = ret .. " print('- " .. change.property .. " " ..formatValueForAssignment(propertyData.type, GetBaseProperty(data, change.property)) .. "')\n"; end + ret = ret .. " propertyChanges['" .. change.property .. "'] = " + .. formatValueForAssignment(propertyData.type, GetBaseProperty(data, change.property), + nil, nil, data) + .. "\n"; + if (debug) then + ret = ret .. " print('- " .. change.property .. " " + .. formatValueForAssignment(propertyData.type, GetBaseProperty(data, change.property), + nil, nil, data) + .. "')\n"; + end end end end @@ -412,7 +474,7 @@ local function CreateDeactivateCondition(ret, condition, conditionNumber, data, return ret; end -local function CreateActivateCondition(ret, id, condition, conditionNumber, properties, debug) +local function CreateActivateCondition(ret, id, condition, conditionNumber, data, properties, debug) if (condition.changes) then ret = ret .. " if (newActiveConditions[" .. conditionNumber .. "]) then\n" ret = ret .. " if (not activatedConditions[".. conditionNumber .. "]) then\n" @@ -423,8 +485,12 @@ local function CreateActivateCondition(ret, id, condition, conditionNumber, prop local propertyData = properties and properties[change.property] if (propertyData and propertyData.type) then if (propertyData.setter) then - ret = ret .. " propertyChanges['" .. change.property .. "'] = " .. formatValueForAssignment(propertyData.type, change.value) .. "\n"; - if (debug) then ret = ret .. " print('- " .. change.property .. " " .. formatValueForAssignment(propertyData.type, change.value) .. "')\n"; end + ret = ret .. " propertyChanges['" .. change.property .. "'] = " + .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "\n" + if (debug) then + ret = ret .. " print('- " .. change.property .. " " + .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "')\n" + end elseif (propertyData.action) then local pathToCustomFunction = "nil"; local pathToFormatter = "nil" @@ -440,8 +506,16 @@ local function CreateActivateCondition(ret, id, condition, conditionNumber, prop and Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes[changeNum] then pathToFormatter = string.format("Private.ExecEnv.conditionTextFormatters[%q][%s].changes[%s]", id, conditionNumber, changeNum); end - ret = ret .. " region:" .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction, pathToFormatter) .. ")" .. "\n"; - if (debug) then ret = ret .. " print('# " .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction, pathToFormatter) .. "')\n"; end + ret = ret .. " region:" .. propertyData.action .. "(" + .. formatValueForAssignment(propertyData.type, change.value, + pathToCustomFunction, pathToFormatter, data) + .. ")" .. "\n"; + if (debug) then + ret = ret .. " print('# " .. propertyData.action .. "(" + .. formatValueForAssignment(propertyData.type, change.value, + pathToCustomFunction, pathToFormatter, data) + .. "')\n"; + end end end end @@ -453,8 +527,10 @@ local function CreateActivateCondition(ret, id, condition, conditionNumber, prop local propertyData = properties and properties[change.property] if (propertyData and propertyData.type and propertyData.setter) then ret = ret .. " if(propertyChanges['" .. change.property .. "'] ~= nil) then\n" - ret = ret .. " propertyChanges['" .. change.property .. "'] = " .. formatValueForAssignment(propertyData.type, change.value) .. "\n"; - if (debug) then ret = ret .. " print('- " .. change.property .. " " .. formatValueForAssignment(propertyData.type, change.value) .. "')\n"; end + ret = ret .. " propertyChanges['" .. change.property .. "'] = " + .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "\n" + if (debug) then ret = ret .. " print('- " .. change.property .. " " + .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "')\n" end ret = ret .. " end\n" end end @@ -539,7 +615,7 @@ function Private.LoadConditionPropertyFunctions(data) end return change.value[fullKey] end - local formatters = change.value and Private.CreateFormatters(change.value.message, getter, true) + local formatters = change.value and Private.CreateFormatters(change.value.message, getter, true, data) Private.ExecEnv.conditionTextFormatters[id] = Private.ExecEnv.conditionTextFormatters[id] or {} Private.ExecEnv.conditionTextFormatters[id][conditionNumber] = Private.ExecEnv.conditionTextFormatters[id][conditionNumber] or {}; Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes = Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes or {}; @@ -631,7 +707,7 @@ local function ConstructConditionFunction(data) for conditionNumber, condition in ipairs(data.conditions) do local nextIsLinked = data.conditions[conditionNumber + 1] and data.conditions[conditionNumber + 1].linked local additionalRecheckCode - ret, additionalRecheckCode = CreateCheckCondition(data.uid, ret, condition, conditionNumber, allConditionsTemplate, nextIsLinked, debug) + ret, additionalRecheckCode = CreateCheckCondition(data, ret, condition, conditionNumber, allConditionsTemplate, nextIsLinked, debug) if additionalRecheckCode then recheckCode = recheckCode .. "\n" .. additionalRecheckCode end @@ -659,7 +735,7 @@ local function ConstructConditionFunction(data) -- Third Loop deals with conditions that are newly active if (data.conditions) then for conditionNumber, condition in ipairs(data.conditions) do - ret = CreateActivateCondition(ret, data.id, condition, conditionNumber, properties, debug) + ret = CreateActivateCondition(ret, data.id, condition, conditionNumber, data, properties, debug) end end diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 96b2f48..8aea94f 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -28,15 +28,9 @@ Modernizes all generic triggers in data. # Helper functions mainly for the WeakAuras Options # ##################################################### -CanHaveDuration(data, triggernum) -Returns whether the trigger can have a duration. - GetOverlayInfo(data, triggernum) Returns a table containing the names of all overlays -CanHaveClones(data) -Returns whether the trigger can have clones. - CanHaveTooltip(data, triggernum) Returns the type of tooltip to show for the trigger. @@ -46,6 +40,9 @@ Returns the name and icon to show in the options. GetAdditionalProperties(data, triggernum) Returns the a tooltip for the additional properties. +GetProgressSources(data, triggernum, outValues) +Fills outValues with the potential progress sources + GetTriggerConditions(data, triggernum) Returns potential conditions that this trigger provides. ]]-- @@ -520,18 +517,20 @@ local function RunOverlayFuncs(event, state, id, errorHandler) state.changed = changed or state.changed; end -local function callFunctionForActivateEvent(func, trigger, fallback, errorHandler) +local function callFunctionForActivateEvent(func, trigger, state, property, errorHandler) if not func then - return fallback + return end local ok, value = pcall(func, trigger) - if ok and value then - return value + if ok then + if state[property] ~= value then + state[property] = value + state.changed = true + end else if not ok then errorHandler(value) end - return fallback end end @@ -638,32 +637,13 @@ function Private.ActivateEvent(id, triggernum, data, state, errorHandler) end end - local name = callFunctionForActivateEvent(data.nameFunc, data.trigger, state.name, errorHandler or Private.GetErrorHandlerId(id, L["Name Function"])) - local icon = callFunctionForActivateEvent(data.iconFunc, data.trigger, state.icon, errorHandler or Private.GetErrorHandlerId(id, L["Icon Function"])) - local texture = callFunctionForActivateEvent(data.textureFunc, data.trigger, state.texture, errorHandler or Private.GetErrorHandlerId(id, L["Texture Function"])) - local stacks = callFunctionForActivateEvent(data.stacksFunc, data.trigger, state.stacks, errorHandler or Private.GetErrorHandlerId(id, L["Stacks Function"])) - - if (state.name ~= name) then - state.name = name; - changed = true; - end - if (state.icon ~= icon) then - state.icon = icon; - changed = true; - end - if (state.texture ~= texture) then - state.texture = texture; - changed = true; - end - if (state.stacks ~= stacks) then - state.stacks = stacks; - changed = true; - end + callFunctionForActivateEvent(data.nameFunc, data.trigger, state, "name", errorHandler or Private.GetErrorHandlerId(id, L["Name Function"])) + callFunctionForActivateEvent(data.iconFunc, data.trigger, state, "icon", errorHandler or Private.GetErrorHandlerId(id, L["Icon Function"])) + callFunctionForActivateEvent(data.textureFunc, data.trigger, state, "texture", errorHandler or Private.GetErrorHandlerId(id, L["Texture Function"])) + callFunctionForActivateEvent(data.stacksFunc, data.trigger, state, "stacks", errorHandler or Private.GetErrorHandlerId(id, L["Stacks Function"])) if (data.overlayFuncs) then RunOverlayFuncs(data, state, id, errorHandler); - else - state.additionalProgress = nil; end state.changed = state.changed or changed; @@ -1016,10 +996,34 @@ function Private.ScanEventsWatchedTrigger(id, watchedTriggernums) Private.ActivateAuraEnvironment(nil) end -local function AddFakeInformation(state, eventData) +local function ProgressType(data, triggernum) + local trigger = data.triggers[triggernum].trigger + local prototype = GenericTrigger.GetPrototype(trigger) + if prototype then + if prototype.progressType then + local progressType = prototype.progressType + if type(progressType) == "function" then + progressType = progressType(trigger) + end + return progressType + elseif prototype.timedrequired then + return "timed" + end + elseif (trigger.type == "custom") then + if trigger.custom_type == "event" and trigger.custom_hide == "timed" and trigger.duration then + return "timed"; + elseif (trigger.customDuration and trigger.customDuration ~= "") then + return "timed"; + elseif (trigger.custom_type == "stateupdate") then + return "timed"; + end + end + return false +end + +local function AddFakeInformation(data, triggernum, state, eventData) state.autoHide = false - local canHaveDuration = eventData.prototype and eventData.prototype.canHaveDuration == "timed" - if canHaveDuration and state.expirationTime == nil then + if ProgressType(data, triggernum) == "timed" and state.expirationTime == nil then state.progressType = "timed" end if state.progressType == "timed" then @@ -1065,7 +1069,7 @@ function GenericTrigger.CreateFakeStates(id, triggernum) shown = shown + 1 end - AddFakeInformation(state, eventData) + AddFakeInformation(data, triggernum, state, eventData) end if shown == 0 then @@ -1073,7 +1077,7 @@ function GenericTrigger.CreateFakeStates(id, triggernum) GenericTrigger.CreateFallbackState(data, triggernum, state) allStates[""] = state - AddFakeInformation(state, eventData) + AddFakeInformation(data, triggernum, state, eventData) end Private.ActivateAuraEnvironment(nil); @@ -3550,40 +3554,6 @@ function GenericTrigger.GetPrototype(trigger) end end -function GenericTrigger.CanHaveDuration(data, triggernum) - local trigger = data.triggers[triggernum].trigger - - local prototype = GenericTrigger.GetPrototype(trigger) - if prototype then - if prototype.durationFunc then - if(type(prototype.init) == "function") then - prototype.init(trigger); - end - local current, maximum, custom = prototype.durationFunc(trigger); - current = type(current) ~= "number" and current or 0 - maximum = type(maximum) ~= "number" and maximum or 0 - if(custom) then - return {current = current, maximum = maximum}; - else - return "timed"; - end - elseif prototype.canHaveDuration then - return prototype.canHaveDuration, prototype.useModRate - elseif prototype.timedrequired then - return "timed" - end - elseif (trigger.type == "custom") then - if trigger.custom_type == "event" and trigger.custom_hide == "timed" and trigger.duration then - return "timed"; - elseif (trigger.customDuration and trigger.customDuration ~= "") then - return "timed"; - elseif (trigger.custom_type == "stateupdate") then - return "timed"; - end - end - return false -end - function GenericTrigger.GetDelay(data) if data.event then local prototype = GenericTrigger.GetPrototype(data.trigger) @@ -3670,10 +3640,6 @@ function GenericTrigger.GetOverlayInfo(data, triggernum) return result; end -function GenericTrigger.CanHaveClones(data) - return false; -end - function GenericTrigger.GetNameAndIcon(data, triggernum) local trigger = data.triggers[triggernum].trigger local icon, name @@ -3806,10 +3772,39 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) return ret; end +function GenericTrigger.GetProgressSources(data, triggernum, values) + local variables = GenericTrigger.GetTriggerConditions(data, triggernum) + if (type(variables) == "table") then + for var, varData in pairs(variables) do + if (type(varData) == "table") then + if (varData.type == "number" or varData.type == "timer" or varData.type == "elapsedTimer") + and not varData.noProgressSource + then + + tinsert(values, { + trigger = triggernum, + property = var, + type = varData.type, + display = varData.display, + total = varData.total, + inverse = varData.inverse, + paused = varData.paused, + remaining = varData.remaining + }) + end + end + end + end +end + local commonConditions = { expirationTime = { display = L["Remaining Duration"], type = "timer", + total = "duration", + inverse = "inverse", + paused = "paused", + remaining = "remaining", }, duration = { display = L["Total Duration"], @@ -3820,11 +3815,12 @@ local commonConditions = { type = "bool", test = function(state, needle) return (state.paused and 1 or 0) == needle - end + end, }, value = { display = L["Progress Value"], type = "number", + total = "total", }, total = { display = L["Progress Total"], @@ -3832,11 +3828,11 @@ local commonConditions = { }, stacks = { display = L["Stacks"], - type = "number" + type = "number", }, name = { display = L["Name"], - type = "string" + type = "string", } } @@ -3861,6 +3857,31 @@ function Private.ExpandCustomVariables(variables) end end +function Private.GetTsuConditionVariablesExpanded(id, triggernum) + if events[id][triggernum] and events[id][triggernum].tsuConditionVariables then + Private.ActivateAuraEnvironment(id, nil, nil, nil, true) + local result = GenericTrigger.GetTsuConditionVariables(id, triggernum) + Private.ActivateAuraEnvironment(nil) + if type(result) ~= "table" then + return nil + end + Private.ExpandCustomVariables(result) + -- Clean up, remove non table entries and check for a valid display name + for k, v in pairs(result) do + if type(v) ~= "table" then + result[k] = nil + elseif (v.display == nil or type(v.display) ~= "string") then + if type(k) == "string" then + v.display = k + else + result[k] = nil + end + end + end + return result + end +end + function GenericTrigger.GetTriggerConditions(data, triggernum) local trigger = data.triggers[triggernum].trigger @@ -3868,22 +3889,14 @@ function GenericTrigger.GetTriggerConditions(data, triggernum) if prototype then local result = {}; - local canHaveDuration = GenericTrigger.CanHaveDuration(data, triggernum); - local timedDuration = canHaveDuration; - local valueDuration = canHaveDuration; - if (canHaveDuration == "timed") then - valueDuration = false; - elseif (type(canHaveDuration) == "table") then - timedDuration = false; - end - - if (timedDuration) then + local progressType = ProgressType(data, triggernum); + if progressType == "timed" then result.expirationTime = commonConditions.expirationTime; result.duration = commonConditions.duration; result.paused = commonConditions.paused end - if (valueDuration) then + if progressType == "static" then result.value = commonConditions.value; result.total = commonConditions.total; end @@ -3935,6 +3948,22 @@ function GenericTrigger.GetTriggerConditions(data, triggernum) if (v.operator_types) then result[v.name].operator_types = v.operator_types; end + -- for ProgressSource + if v.noProgressSource then + result[v.name].noProgressSource = true + end + if v.progressTotal then + result[v.name].total = v.progressTotal + end + if v.progressInverse then + result[v.name].inverse = v.progressInverse + end + if v.progressPaused then + result[v.name].paused = v.progressPaused + end + if v.progressRemaining then + result[v.name].remaining = v.progressRemaining + end end end end @@ -3976,28 +4005,7 @@ function GenericTrigger.GetTriggerConditions(data, triggernum) return result; elseif (trigger.custom_type == "stateupdate") then - if (events[data.id][triggernum] and events[data.id][triggernum].tsuConditionVariables) then - Private.ActivateAuraEnvironment(data.id, nil, nil, nil, true) - local result = GenericTrigger.GetTsuConditionVariables(data.id, triggernum) - Private.ActivateAuraEnvironment(nil) - if (type(result)) ~= "table" then - return nil; - end - Private.ExpandCustomVariables(result) - for k, v in pairs(result) do - if (type(v) ~= "table") then - result[k] = nil; - elseif (v.display == nil or type(v.display) ~= "string") then - if (type(k) == "string") then - v.display = k; - else - result[k] = nil; - end - end - end - - return result; - end + return Private.GetTsuConditionVariablesExpanded(data.id, triggernum) end end diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 1d8eab5..02ccb64 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1469,5 +1469,28 @@ function Private.Modernize(data) migrateToTable(data.load, "itemequiped") end + --[[if data.internalVersion < 71 then + if data.regionType == 'icon' or data.regionType == 'aurabar' + or data.regionType == 'progresstexture' + or data.regionType == 'stopmotion' + then + data.progressSource = {-1, ""} + else + data.progressSource = nil + end + if data.subRegions then + for index, subRegionData in ipairs(data.subRegions) do + if subRegionData.type == "subtick" then + local tick_placement = subRegionData.tick_placement + subRegionData.tick_placements = {} + subRegionData.tick_placements[1] = tick_placement + subRegionData.progressSources = {{-2, ""}} + subRegionData.tick_placement = nil + 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 93383b5..a593455 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -1662,11 +1662,12 @@ Private.event_prototypes = { test = "WeakAuras.UnitExistsFixed(unit, smart) and specificUnitCheck" } }, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Experience"] = { type = "unit", - canHaveDuration = false, + progressType = "static", events = { ["events"] = { "PLAYER_XP_UPDATE", @@ -1704,6 +1705,7 @@ Private.event_prototypes = { operator = "and", limit = 2 }, + progressTotal = "totalXP" }, { name = "totalXP", @@ -1805,7 +1807,7 @@ Private.event_prototypes = { ["Health"] = { type = "unit", includePets = "true", - canHaveDuration = true, + progressType = "static", events = function(trigger) local unit = trigger.unit local result = {} @@ -1872,6 +1874,7 @@ Private.event_prototypes = { operator = "and", limit = 2 }, + progressTotal = "maxhealth" }, { name = "value", @@ -1917,6 +1920,7 @@ Private.event_prototypes = { operator = "and", limit = 2 }, + progressTotal = "total" }, { name = "maxhealth", @@ -2111,7 +2115,7 @@ Private.event_prototypes = { }, ["Power"] = { type = "unit", - canHaveDuration = true, + progressType = "static", events = function(trigger) local unit = trigger.unit local result = {} @@ -2218,6 +2222,7 @@ Private.event_prototypes = { operator = "and", limit = 2 }, + progressTotal = "total" }, { name = "value", @@ -2270,6 +2275,7 @@ Private.event_prototypes = { operator = "and", limit = 2 }, + progressTotal = "total" }, { name = "maxpower", @@ -2899,12 +2905,13 @@ Private.event_prototypes = { display = WeakAuras.newFeatureString .. L["Extra Spell Id"], init = "arg", enable = function(trigger) - return trigger.subeventSuffix and (trigger.subeventSuffix == "_INTERRUPT" or trigger.subeventSuffix == "_DISPEL" or trigger.subeventSuffix == "_DISPEL_FAILED" or trigger.subeventSuffix == "_STOLEN" or trigger.subeventSuffix == "_AURA_BROKEN_SPELL") + return trigger.subeventSuffix and (trigger.subeventSuffix == "_ABSORBED" or trigger.subeventSuffix == "_INTERRUPT" or trigger.subeventSuffix == "_DISPEL" or trigger.subeventSuffix == "_DISPEL_FAILED" or trigger.subeventSuffix == "_STOLEN" or trigger.subeventSuffix == "_AURA_BROKEN_SPELL") end, type = "spell", showExactOption = false, store = true, - conditionType = "number" + conditionType = "number", + noProgressSource = true }, { name = "extraSpellName", @@ -3106,6 +3113,7 @@ Private.event_prototypes = { countEvents = true, delayEvents = true, timedrequired = true, + progressType = "timed" }, ["Cooldown Progress (Spell)"] = { type = "spell", @@ -3206,7 +3214,7 @@ Private.event_prototypes = { return ret; end, statesParameter = "one", - canHaveDuration = "timed", + progressType = "timed", args = { { }, -- Ignore first argument (id) @@ -3266,7 +3274,8 @@ Private.event_prototypes = { display = L["Stacks"], type = "number", store = true, - conditionType = "number" + conditionType = "number", + progressTotal = "maxCharges" }, { name = "spellCount", @@ -3451,7 +3460,8 @@ Private.event_prototypes = { return icon; end, hasSpellID = true, - timedrequired = true + timedrequired = true, + progressType = "timed" }, ["Charges Changed"] = { type = "spell", @@ -3535,7 +3545,8 @@ Private.event_prototypes = { return icon; end, hasSpellID = true, - timedrequired = true + timedrequired = true, + progressType = "timed" }, ["Cooldown Progress (Item)"] = { type = "item", @@ -3701,6 +3712,7 @@ Private.event_prototypes = { end, hasItemID = true, automaticrequired = true, + progressType = "timed" }, ["Cooldown Progress (Equipment Slot)"] = { type = "item", @@ -3859,6 +3871,7 @@ Private.event_prototypes = { return GetInventoryItemTexture("player", trigger.itemSlot or 0) or "Interface\\Icons\\INV_Misc_QuestionMark"; end, automaticrequired = true, + progressType = "timed" }, ["Cooldown Ready (Item)"] = { type = "item", @@ -3896,7 +3909,8 @@ Private.event_prototypes = { return icon; end, hasItemID = true, - timedrequired = true + timedrequired = true, + progressType = "timed" }, ["Cooldown Ready (Equipment Slot)"] = { type = "item", @@ -3927,7 +3941,8 @@ Private.event_prototypes = { return GetInventoryItemTexture("player", trigger.itemSlot or 0) or "Interface\\Icons\\INV_Misc_QuestionMark"; end, hasItemID = true, - timedrequired = true + timedrequired = true, + progressType = "timed" }, ["GTFO"] = { type = "addons", @@ -3947,7 +3962,8 @@ Private.event_prototypes = { conditionType = "select" }, }, - timedrequired = true + timedrequired = true, + progressType = "timed" }, ["Global Cooldown"] = { type = "spell", @@ -3998,6 +4014,7 @@ Private.event_prototypes = { end, hasSpellID = true, automaticrequired = true, + progressType = "timed" }, ["Swing Timer"] = { type = "unit", @@ -4096,7 +4113,7 @@ Private.event_prototypes = { } }, automaticrequired = true, - canHaveDuration = true, + progressType = "timed", statesParameter = "one" }, ["Action Usable"] = { @@ -4184,7 +4201,7 @@ Private.event_prototypes = { type = "number", enable = function(trigger) return not(trigger.use_inverse) end, store = true, - conditionType = "number" + conditionType = "number", }, { name = "spellCount", @@ -4192,7 +4209,7 @@ Private.event_prototypes = { type = "number", enable = function(trigger) return not(trigger.use_inverse) end, store = true, - conditionType = "number" + conditionType = "number", }, { name = "inverse", @@ -4245,7 +4262,8 @@ Private.event_prototypes = { end end, hasSpellID = true, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Talent Known"] = { type = "unit", @@ -4351,6 +4369,7 @@ Private.event_prototypes = { }, automaticrequired = true, statesParameter = "one", + progressType = "none" }, ["Totem"] = { type = "spell", @@ -4366,7 +4385,7 @@ Private.event_prototypes = { force_events = "PLAYER_ENTERING_WORLD", name = L["Totem"], statesParameter = "full", - canHaveDuration = "timed", + progressType = "timed", triggerFunction = function(trigger) local ret = [[return function (states) @@ -4633,7 +4652,6 @@ Private.event_prototypes = { hidden = true, store = true, test = "true", - conditionType = "number" }, { name = "icon", @@ -4652,7 +4670,8 @@ Private.event_prototypes = { }, statesParameter = "one", hasItemID = true, - automaticrequired = true + automaticrequired = true, + progressType = "static" }, ["Stance/Form/Aura"] = { type = "unit", @@ -4751,7 +4770,8 @@ Private.event_prototypes = { end return icon or "Interface\\Icons\\Spell_Nature_WispSplode" end, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Weapon Enchant"] = { type = "item", @@ -4888,7 +4908,7 @@ Private.event_prototypes = { } }, automaticrequired = true, - canHaveDuration = true, + progressType = "timed", statesParameter = "one" }, ["Chat Message"] = { @@ -4993,7 +5013,8 @@ Private.event_prototypes = { }, countEvents = true, delayEvents = true, - timedrequired = true + timedrequired = true, + progressType = "timed" }, -- fixing later --[[["Spell Cast Succeeded"] = { @@ -5061,7 +5082,8 @@ Private.event_prototypes = { }, countEvents = true, delayEvents = true, - timedrequired = true + timedrequired = true, + progressType = "timed" },]] ["Ready Check"] = { type = "event", @@ -5072,7 +5094,8 @@ Private.event_prototypes = { args = {}, statesParameter = "one", delayEvents = true, - timedrequired = true + timedrequired = true, + progressType = "timed" }, ["Combat Events"] = { type = "event", @@ -5096,7 +5119,8 @@ Private.event_prototypes = { statesParameter = "one", countEvents = true, delayEvents = true, - timedrequired = true + timedrequired = true, + progressType = "timed" }, ["Death Knight Rune"] = { type = "unit", @@ -5300,6 +5324,13 @@ Private.event_prototypes = { end end, automaticrequired = true, + progressType = function(trigger) + if trigger.use_rune then + return "timed" + else + return "static" + end + end }, ["Item Equipped"] = { type = "item", @@ -5351,7 +5382,8 @@ Private.event_prototypes = { return icon; end, hasItemID = true, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Equipment Set"] = { type = "item", @@ -5420,7 +5452,8 @@ Private.event_prototypes = { return numEquipped, numItems, true; end, hasItemID = true, - automaticrequired = true + automaticrequired = true, + progressType = "static" }, ["Threat Situation"] = { type = "unit", @@ -5468,7 +5501,7 @@ Private.event_prototypes = { ]]; return ret .. unitHelperFunctions.SpecificUnitCheck(trigger); end, - canHaveDuration = true, + progressType = "static", statesParameter = "unit", args = { { @@ -5667,7 +5700,7 @@ Private.event_prototypes = { AddWatchedUnits(trigger.unit, includePets) end, force_events = unitHelperFunctions.UnitChangedForceEventsWithPets, - canHaveDuration = "timed", + progressType = "timed", name = L["Cast"], init = function(trigger) trigger.unit = trigger.unit or "player"; @@ -6605,7 +6638,8 @@ Private.event_prototypes = { }, }, }, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Conditions"] = { type = "unit", @@ -6784,7 +6818,8 @@ Private.event_prototypes = { init = "WeakAuras.InstanceDifficulty()" }, }, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Spell Known"] = { @@ -6836,7 +6871,8 @@ Private.event_prototypes = { local _, _, icon = GetSpellInfo(trigger.spellId or 0); return icon; end, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Pet Behavior"] = { @@ -6910,7 +6946,8 @@ Private.event_prototypes = { test = "true" }, }, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Queued Action"] = { @@ -6951,7 +6988,8 @@ Private.event_prototypes = { local _, _, icon = GetSpellInfo(trigger.spellName or 0); return icon; end, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, ["Range Check"] = { @@ -7031,12 +7069,13 @@ Private.event_prototypes = { test = "UnitExists(unit)" } }, - automaticrequired = true + automaticrequired = true, + progressType = "none" }, --[[ Some day i will finish this, soonTM ["Currency"] = { type = "unit", - canHaveDuration = false, + progressType = "static", events = { ["events"] = { "CURRENCY_DISPLAY_UPDATE", diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index eb464a5..36063e8 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -9,6 +9,7 @@ local default = { icon = false, desaturate = false, iconSource = -1, + progressSource = {-1, "" }, texture = "Blizzard", width = 200, height = 15, @@ -38,7 +39,7 @@ local default = { zoom = 0 }; -Private.regionPrototype.AddAdjustedDurationToDefault(default); +Private.regionPrototype.AddProgressSourceToDefault(default) Private.regionPrototype.AddAlphaToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; @@ -66,7 +67,7 @@ local properties = { values = {} }, displayIcon = { - display = {L["Icon"], L["Fallback"]}, + display = {L["Icon"], L["Manual"]}, setter = "SetIcon", type = "icon", }, @@ -149,6 +150,7 @@ local function GetProperties(data) end auraProperties.iconSource.values = Private.IconSources(data) + auraProperties.progressSource.values = Private.GetProgressSourcesForUi(data) return auraProperties; end @@ -725,6 +727,17 @@ local function GetTexCoordZoom(texWidth) return unpack(texCoord) end +local function FrameTick(self) + local expirationTime = self.expirationTime + local remaining = expirationTime - GetTime() + local duration = self.duration + local progress = duration ~= 0 and remaining / duration or 0; + if self.inverse then + progress = 1 - progress; + end + self:SetProgress(progress) +end + local funcs = { AnchorSubRegion = function(self, subRegion, anchorType, selfPoint, anchorPoint, anchorXOffset, anchorYOffset) if anchorType == "area" then @@ -816,12 +829,7 @@ local funcs = { self.height = height; self:Scale(self.scalex, self.scaley); end, - SetValue = function(self, value, total) - local progress = 0; - if (total ~= 0) then - progress = value / total; - end - + SetProgress = function(self, progress) if self.inverseDirection then progress = 1 - progress; end @@ -833,22 +841,31 @@ local funcs = { self.bar:SetValue(progress); end end, - SetTime = function(self, duration, expirationTime, inverse) - local remaining = expirationTime - GetTime(); - local progress = duration ~= 0 and remaining / duration or 0; - -- Need to invert? - if ( - (self.inverseDirection and not inverse) - or (inverse and not self.inverseDirection) - ) - then + UpdateValue = function(self) + local progress = 0; + if (self.total ~= 0) then + progress = self.value / self.total; + end + self:SetProgress(progress) + if self.FrameTick then + self.FrameTick = nil + self.subRegionEvents:RemoveSubscriber("FrameTick", self) + end + end, + UpdateTime = function(self) + local remaining = self.expirationTime - GetTime(); + local progress = self.duration ~= 0 and remaining / self.duration or 0; + if self.inverse then progress = 1 - progress; end - if (self.smoothProgress) then - self.bar.targetValue = progress - self.bar:SetSmoothedValue(progress); - else - self.bar:SetValue(progress); + self:SetProgress(progress) + if self.paused and self.FrameTick then + self.FrameTick = nil + self.subRegionEvents:RemoveSubscriber("FrameTick", self) + end + if not self.paused and not self.FrameTick then + self.FrameTick = FrameTick + self.subRegionEvents:AddSubscriber("FrameTick", self) end end, SetInverse = function(self, inverse) @@ -1061,14 +1078,6 @@ local function create(parent) return region; end -local function TimerTick(self) - local state = self.state - local duration = state.duration or 0 - local adjustMin = self.adjustedMin or self.adjustedMinRel or 0; - local expirationTime = state.expirationTime and state.expirationTime > 0 and state.expirationTime or math.huge; - self:SetTime((duration ~= 0 and (self.adjustedMax or self.adjustedMaxRel) or duration) - adjustMin, expirationTime - adjustMin, state.inverse); -end - -- Modify a given region/display local function modify(parent, region, data) region.timer = nil @@ -1201,107 +1210,15 @@ local function modify(parent, region, data) region.tooltipFrame:EnableMouse(false); end - function region:UpdateMinMax() - local state = region.state - local min - local max - if state.progressType == "timed" then - local duration = state.duration or 0 - if region.adjustedMinRelPercent then - region.adjustedMinRel = region.adjustedMinRelPercent * duration - end - - min = region.adjustedMin or region.adjustedMinRel or 0; - - if duration == 0 then - max = 0 - elseif region.adjustedMax then - max = region.adjustedMax - elseif region.adjustedMaxRelPercent then - region.adjustedMaxRel = region.adjustedMaxRelPercent * duration - max = region.adjustedMaxRel - else - max = duration - end - elseif state.progressType == "static" then - local total = state.total or 0; - if region.adjustedMinRelPercent then - region.adjustedMinRel = region.adjustedMinRelPercent * total - end - min = region.adjustedMin or region.adjustedMinRel or 0; - - if region.adjustedMax then - max = region.adjustedMax - elseif region.adjustedMaxRelPercent then - region.adjustedMaxRel = region.adjustedMaxRelPercent * total - max = region.adjustedMaxRel - else - max = total - end - end - region.currentMin, region.currentMax = min, max - end - - function region:GetMinMax() - return region.currentMin or 0, region.currentMax or 0 - end - - region.TimerTick = nil + region.FrameTick = nil function region:Update() - local state = region.state - region:UpdateMinMax() - if state.progressType == "timed" then - local expirationTime - if state.paused == true then - if not region.paused then - region:Pause() - end - if region.TimerTick then - region.TimerTick = nil - region.subRegionEvents:RemoveSubscriber("TimerTick", self) - end - expirationTime = GetTime() + (state.remaining or 0) - else - if region.paused then - region:Resume() - end - if not region.TimerTick then - region.TimerTick = TimerTick - region.subRegionEvents:AddSubscriber("TimerTick", self, true) - end - expirationTime = state.expirationTime and state.expirationTime > 0 and state.expirationTime or math.huge; - end - local duration = state.duration or 0 - - region:SetTime(region.currentMax - region.currentMin, expirationTime - region.currentMin, state.inverse); - elseif state.progressType == "static" then - if region.paused then - region:Resume() - end - local value = state.value or 0; - local total = state.total or 0; - - region:SetValue(value - region.currentMin, region.currentMax - region.currentMin); - if region.TimerTick then - region.TimerTick = nil - region.subRegionEvents:RemoveSubscriber("TimerTick", region) - end - else - if region.paused then - region:Resume() - end - region:SetTime(0, math.huge) - if region.TimerTick then - region.TimerTick = nil - region.subRegionEvents:RemoveSubscriber("TimerTick", region) - end - end - + region:UpdateProgress() region:UpdateIcon() + end - local duration = state.duration or 0 - local effectiveInverse = (state.inverse and not region.inverseDirection) or (not state.inverse and region.inverseDirection); - region.bar:SetAdditionalBars(state.additionalProgress, region.overlays, region.overlaysTexture, region.currentMin, region.currentMax, effectiveInverse, region.overlayclip); + function region:SetAdditionalProgress(additionalProgress, currentMin, currentMax, inverse) + local effectiveInverse = (inverse and not region.inverseDirection) or (not inverse and region.inverseDirection); + region.bar:SetAdditionalBars(additionalProgress, region.overlays, region.overlaysTexture, currentMin, currentMax, effectiveInverse, region.overlayclip); end -- Scale update function diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index 567c47c..98df008 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -19,6 +19,7 @@ local default = { icon = true, desaturate = false, iconSource = -1, + progressSource = {-1, "" }, inverse = false, width = 64, height = 64, @@ -35,6 +36,7 @@ local default = { cooldownEdge = false }; +Private.regionPrototype.AddProgressSourceToDefault(default) Private.regionPrototype.AddAlphaToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; @@ -95,7 +97,7 @@ local properties = { values = {} }, displayIcon = { - display = {L["Icon"], L["Fallback"]}, + display = {L["Icon"], L["Manual"]}, setter = "SetIcon", type = "icon", } @@ -106,12 +108,11 @@ Private.regionPrototype.AddProperties(properties, default); local function GetProperties(data) local result = CopyTable(properties) result.iconSource.values = Private.IconSources(data) + result.progressSource.values = Private.GetProgressSourcesForUi(data) return result end local function GetTexCoord(region, texWidth, aspectRatio, xOffset, yOffset) - xOffset = xOffset or 0 - yOffset = yOffset or 0 region.currentCoord = region.currentCoord or {} local usesMasque = false if region.MSQGroup then @@ -430,8 +431,8 @@ local function modify(parent, region, data) region.scaley = 1; region.keepAspectRatio = data.keepAspectRatio; region.zoom = data.zoom; - region.texXOffset = data.texXOffset - region.texYOffset = data.texYOffset + region.texXOffset = data.texXOffset or 0 + region.texYOffset = data.texYOffset or 0 region:UpdateSize() icon:SetDesaturated(data.desaturate); @@ -451,7 +452,27 @@ local function modify(parent, region, data) region.tooltipFrame:EnableMouse(false); end - cooldown:SetReverse(not data.inverse); + function region:SetInverse(inverse) + if region.inverse == inverse then + return + end + region.inverse = inverse + region:UpdateEffectiveInverse() + end + function region:UpdateEffectiveInverse() + -- If cooldown.inverse == false then effectiveReverse = not inverse + -- If cooldown.inverse == true then effectiveReverse = inverse + local effectiveReverse = not region.inverse == not cooldown.inverse + cooldown:SetReverse(effectiveReverse) + if (cooldown.expirationTime and cooldown.duration and cooldown:IsShown()) then + -- WORKAROUND SetReverse not applying until next frame + cooldown:SetCooldown(0, 0) + cooldown:SetCooldown(cooldown.expirationTime - cooldown.duration, + cooldown.duration, + cooldown.useCooldownModRate and cooldown.modRate or nil) + end + end + region:SetInverse(data.inverse) function region:Color(r, g, b, a) region.color_r = r; @@ -545,15 +566,6 @@ local function modify(parent, region, data) region:UpdateSize(); end - function region:SetInverse(inverse) - cooldown:SetReverse(not inverse); - if (cooldown.expirationTime and cooldown.duration and cooldown:IsShown()) then - -- WORKAROUND SetReverse not applying until next frame - cooldown:SetCooldown(0, 0); - cooldown:SetCooldown(cooldown.expirationTime - cooldown.duration, cooldown.duration); - end - end - function region:SetCooldownEdge(cooldownEdge) region.cooldownEdge = cooldownEdge; cooldown:SetDrawEdge(cooldownEdge); @@ -570,32 +582,40 @@ local function modify(parent, region, data) cooldown.duration = nil; cooldown:Hide() if(data.cooldown) then - function region:SetValue(value, total) - cooldown.value = value - cooldown.total = total - if (value >= 0 and value <= total) then + function region:UpdateValue() + cooldown.value = self.value + cooldown.total = self.total + if (self.value >= 0 and self.value <= self.total) then cooldown:Show() - cooldown:SetCooldown(GetTime() - (total - value), total) + cooldown:SetCooldown(GetTime() - (self.total - self.value), self.total) + cooldown:Pause() else cooldown:Hide(); end end - function region:SetTime(duration, expirationTime) - if (duration > 0 and expirationTime > GetTime()) then - cooldown:Show(); - cooldown.expirationTime = expirationTime; - cooldown.duration = duration; - cooldown:SetCooldown(expirationTime - duration, duration); + function region:UpdateTime() + if self.paused then + cooldown:Pause() else - cooldown.expirationTime = expirationTime; - cooldown.duration = duration; + cooldown:Resume() + end + if (self.duration > 0 and self.expirationTime > GetTime() and self.expirationTime ~= math.huge) then + cooldown:Show(); + cooldown.expirationTime = self.expirationTime + cooldown.duration = self.duration + cooldown.inverse = self.inverse + region:UpdateEffectiveInverse() + cooldown:SetCooldown(self.expirationTime - self.duration, self.duration) + else + cooldown.expirationTime = self.expirationTime + cooldown.duration = self.duration cooldown:Hide(); end end function region:PreShow() - if (cooldown.duration and cooldown.duration > 0.01) then + if (cooldown.duration and cooldown.duration > 0.01 and cooldown.duration ~= math.huge and cooldown.expirationTime ~= math.huge) then cooldown:Show(); cooldown:SetCooldown(cooldown.expirationTime - cooldown.duration, cooldown.duration); cooldown:Resume() @@ -603,64 +623,14 @@ local function modify(parent, region, data) end function region:Update() - local state = region.state - if state.progressType == "timed" then - local expirationTime - if state.paused == true then - if not region.paused then - region:Pause() - end - cooldown:Pause() - expirationTime = GetTime() + (state.remaining or 0) - else - if region.paused then - region:Resume() - end - cooldown:Resume() - expirationTime = state.expirationTime and state.expirationTime > 0 and state.expirationTime or math.huge; - end - - local duration = state.duration or 0 - if region.adjustedMinRelPercent then - region.adjustedMinRel = region.adjustedMinRelPercent * duration - end - local adjustMin = region.adjustedMin or region.adjustedMinRel or 0; - - local max - if duration == 0 then - max = 0 - elseif region.adjustedMax then - max = region.adjustedMax - elseif region.adjustedMaxRelPercent then - region.adjustedMaxRel = region.adjustedMaxRelPercent * duration - max = region.adjustedMaxRel - else - max = duration - end - - region:SetTime(max - adjustMin, expirationTime - adjustMin, state.inverse); - elseif state.progressType == "static" then - local value = state.value or 0; - local total = state.total or 0; - if region.adjustedMinRelPercent then - region.adjustedMinRel = region.adjustedMinRelPercent * total - end - local adjustMin = region.adjustedMin or region.adjustedMinRel or 0; - local max = region.adjustedMax or region.adjustedMaxRel or total; - region:SetValue(value - adjustMin, max - adjustMin); - cooldown:Pause() - else - region:SetTime(0, math.huge) - end - + region:UpdateProgress() region:UpdateIcon() end else - region.SetValue = nil - region.SetTime = nil + region.UpdateValue = nil + region.UpdateTime = nil function region:Update() - local state = region.state region:UpdateIcon() end end diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 8fc2176..44f1887 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -80,6 +80,7 @@ local function Transform(tx, x, y, angle, aspect) -- Translates texture to x, y end local default = { + progressSource = {-1, "" }, foregroundTexture = "Interface\\Addons\\WeakAuras\\PowerAurasMedia\\Auras\\Aura3", backgroundTexture = "Interface\\Addons\\WeakAuras\\PowerAurasMedia\\Auras\\Aura3", desaturateBackground = false, @@ -115,7 +116,7 @@ local default = { Private.regionPrototype.AddAlphaToDefault(default); -Private.regionPrototype.AddAdjustedDurationToDefault(default); +Private.regionPrototype.AddProgressSourceToDefault(default) local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; @@ -180,9 +181,9 @@ Private.regionPrototype.AddProperties(properties, default); local function GetProperties(data) local overlayInfo = Private.GetOverlayInfo(data); + local auraProperties = CopyTable(properties) + auraProperties.progressSource.values = Private.GetProgressSourcesForUi(data) if (overlayInfo and next(overlayInfo)) then - local auraProperties = CopyTable(properties); - for id, display in ipairs(overlayInfo) do auraProperties["overlays." .. id] = { display = string.format(L["%s Overlay Color"], display), @@ -191,10 +192,9 @@ local function GetProperties(data) type = "color", } end - - return auraProperties; + return auraProperties else - return CopyTable(properties); + return auraProperties end end @@ -467,10 +467,27 @@ local function create(parent) return region; end -local function TimerTick(self) - local adjustMin = self.adjustedMin or self.adjustedMinRel or 0; - local duration = self.state.duration - self:SetTime( (duration ~= 0 and (self.adjustedMax or self.adjustedMaxRel) or duration) - adjustMin, self.state.expirationTime - adjustMin, self.state.inverse); +local function FrameTick(self) + local duration = self.duration + local expirationTime = self.expirationTime + local inverse = self.inverse + + local progress = 1; + if (duration ~= 0) then + local remaining = expirationTime - GetTime(); + progress = remaining / duration; + local inversed = (not inverse and self.inverseDirection) or (inverse and not self.inverseDirection); + if(inversed) then + progress = 1 - progress; + end + end + + progress = progress > 0.0001 and progress or 0.0001; + if (self.useSmoothProgress) then + self.smoothProgress:SetSmoothedValue(progress); + else + self:SetValueOnTexture(progress); + end end local function modify(parent, region, data) @@ -486,6 +503,7 @@ local function modify(parent, region, data) region.scalex = 1; region.scaley = 1; region.aspect = data.width / data.height; + region.useSmoothProgress = data.smoothProgress foreground:SetWidth(data.width); foreground:SetHeight(data.height); local scaleWedge = 1 / 1.4142 * (1 + (data.crop or 0.41)); @@ -843,123 +861,62 @@ local function modify(parent, region, data) region:Color(data.foregroundColor[1], data.foregroundColor[2], data.foregroundColor[3], data.foregroundColor[4]); - function region:SetTime(duration, expirationTime, inverse) + function region:UpdateTime() local progress = 1; - if (duration ~= 0) then - local remaining = expirationTime - GetTime(); - progress = remaining / duration; - local inversed = (not inverse and region.inverseDirection) or (inverse and not region.inverseDirection); + if (self.duration ~= 0) then + local remaining = self.expirationTime - GetTime() + progress = remaining / self.duration + local inversed = self.inverse ~= region.inverseDirection if(inversed) then progress = 1 - progress; end end progress = progress > 0.0001 and progress or 0.0001; - if (data.smoothProgress) then + if (region.useSmoothProgress) then region.smoothProgress:SetSmoothedValue(progress); else region:SetValueOnTexture(progress); end + + if self.paused and self.FrameTick then + self.FrameTick = nil + self.subRegionEvents:RemoveSubscriber("FrameTick", region) + end + if not self.paused and not self.FrameTick then + self.FrameTick = FrameTick + self.subRegionEvents:AddSubscriber("FrameTick", region) + end end - function region:SetValue(value, total) + function region:UpdateValue() local progress = 1 - if(total > 0) then - progress = value / total; + if(self.total > 0) then + progress = self.value / self.total; if(region.inverseDirection) then progress = 1 - progress; end end progress = progress > 0.0001 and progress or 0.0001; - if (data.smoothProgress) then + if (region.useSmoothProgress) then region.smoothProgress:SetSmoothedValue(progress); else region:SetValueOnTexture(progress); end end - region.TimerTick = nil - function region:Update() - local state = region.state - - local max - if state.progressType == "timed" then - local expirationTime - if state.paused == true then - if not region.paused then - region:Pause() - end - if region.TimerTick then - region.TimerTick = nil - region.subRegionEvents:RemoveSubscriber("TimerTick", region) - end - expirationTime = GetTime() + (state.remaining or 0) - else - if region.paused then - region:Resume() - end - if not region.TimerTick then - region.TimerTick = TimerTick - region.subRegionEvents:AddSubscriber("TimerTick", region, true) - end - expirationTime = state.expirationTime and state.expirationTime > 0 and state.expirationTime or math.huge; - end - - local duration = state.duration or 0 - if region.adjustedMinRelPercent then - region.adjustedMinRel = region.adjustedMinRelPercent * duration - end - local adjustMin = region.adjustedMin or region.adjustedMinRel or 0; - if duration == 0 then - max = 0 - elseif region.adjustedMax then - max = region.adjustedMax - elseif region.adjustedMaxRelPercent then - region.adjustedMaxRel = region.adjustedMaxRelPercent * duration - max = region.adjustedMaxRel - else - max = duration - end - - region:SetTime(max - adjustMin, expirationTime - adjustMin, state.inverse); - elseif state.progressType == "static" then - if region.paused then - region:Resume() - end - - local value = state.value or 0; - local total = state.total or 0; - if region.adjustedMinRelPercent then - region.adjustedMinRel = region.adjustedMinRelPercent * total - end - local adjustMin = region.adjustedMin or region.adjustedMinRel or 0; - - if region.adjustedMax then - max = region.adjustedMax - elseif region.adjustedMaxRelPercent then - region.adjustedMaxRel = region.adjustedMaxRelPercent * total - max = region.adjustedMaxRel - else - max = total - end - - region:SetValue(value - adjustMin, max - adjustMin); - if region.TimerTick then - region.TimerTick = nil - region.subRegionEvents:RemoveSubscriber("TimerTick", region) - end - else - if region.paused then - region:Resume() - end - region:SetTime(0, math.huge) - if region.TimerTick then - region.TimerTick = nil - region.subRegionEvents:RemoveSubscriber("TimerTick", region) - end + if region.useSmoothProgress then + region.PreShow = function() + region.smoothProgress:ResetSmoothedValue(); end + else + region.PreShow = nil + end - max = max or 0 + region.FrameTick = nil + function region:Update() + region:UpdateProgress() + local state = region.state if state.texture then region:SetTexture(state.texture) diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index 5fbd1f5..edc9c18 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -11,67 +11,11 @@ function Private.regionPrototype.AddAlphaToDefault(default) default.alpha = 1.0; end --- Adjusted Duration - -function Private.regionPrototype.AddAdjustedDurationToDefault(default) - default.useAdjustededMax = false; - default.useAdjustededMin = false; -end - -function Private.regionPrototype.AddAdjustedDurationOptions(options, data, order) - options.useAdjustededMin = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Set Minimum Progress"], - desc = L["Values/Remaining Time below this value are displayed as no progress."], - order = order - }; - - options.adjustedMin = { - type = "input", - validate = WeakAuras.ValidateNumericOrPercent, - width = WeakAuras.normalWidth, - order = order + 0.01, - name = L["Minimum"], - hidden = function() return not data.useAdjustededMin end, - desc = L["Enter static or relative values with %"] - }; - - options.useAdjustedMinSpacer = { - type = "description", - width = WeakAuras.normalWidth, - name = "", - order = order + 0.02, - hidden = function() return not (not data.useAdjustededMin and data.useAdjustededMax) end, - }; - - options.useAdjustededMax = { - type = "toggle", - width = WeakAuras.normalWidth, - name = L["Set Maximum Progress"], - desc = L["Values/Remaining Time above this value are displayed as full progress."], - order = order + 0.03 - }; - - options.adjustedMax = { - type = "input", - width = WeakAuras.normalWidth, - validate = WeakAuras.ValidateNumericOrPercent, - order = order + 0.04, - name = L["Maximum"], - hidden = function() return not data.useAdjustededMax end, - desc = L["Enter static or relative values with %"] - }; - - options.useAdjustedMaxSpacer = { - type = "description", - width = WeakAuras.normalWidth, - name = "", - order = order + 0.05, - hidden = function() return not (data.useAdjustededMin and not data.useAdjustededMax) end, - }; - - return options; +-- Progress Sources +function Private.regionPrototype.AddProgressSourceToDefault(default) + default.progressSource = {-1, ""} + default.useAdjustededMax = false + default.useAdjustededMin = false end local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; @@ -149,6 +93,28 @@ function Private.regionPrototype.AddProperties(properties, defaultsForRegion) isPercent = true } end + if defaultsForRegion and defaultsForRegion.progressSource then + properties["progressSource"] = { + display = L["Progress Source"], + setter = "SetProgressSource", + type = "progressSource", + values = {}, + } + + properties["adjustedMin"] = { + display = L["Minimum Progress"], + setter = "SetAdjustedMin", + type = "string", + validate = WeakAuras.ValidateNumericOrPercent, + } + + properties["adjustedMax"] = { + display = L["Maximum Progress"], + setter = "SetAdjustedMax", + type = "string", + validate = WeakAuras.ValidateNumericOrPercent, + } + end end local function SoundRepeatStop(self) @@ -373,62 +339,253 @@ local function GetRegionAlpha(self) return self.animAlpha or self.alpha or 1; end +local function SetProgressSource(self, progressSource) + self.progressSource = progressSource + self:UpdateProgress() +end +local function SetAdjustedMin(self, adjustedMin) + local percent = string.match(adjustedMin, "(%d+)%%") + if percent then + self.adjustedMinRelPercent = tonumber(percent) / 100 + self.adjustedMin = nil + else + self.adjustedMin = tonumber(adjustedMin) + self.adjustedMinRelPercent = nil + end + self:UpdateProgress() +end +local function SetAdjustedMax(self, adjustedMax) + local percent = string.match(adjustedMax, "(%d+)%%") + if percent then + self.adjustedMaxRelPercent = tonumber(percent) / 100 + else + self.adjustedMax = tonumber(adjustedMax) + end + self:UpdateProgress() +end + +local function GetProgressSource(self) + return self.progressSource +end + +local function GetMinMaxProgress(self) + return self.minProgress or 0, self.maxProgress or 0 +end +local function UpdateProgressFromState(self, minMaxConfig, state, progressSource) + local progressType = progressSource[2] + local property = progressSource[3] + local totalProperty = progressSource[4] + local inverseProperty = progressSource[5] + local pausedProperty = progressSource[6] + local remainingProperty = progressSource[7] + if progressType == "number" then + local value = state[property] or 0 + local total = totalProperty and state[totalProperty] or 0 + -- We don't care about inverse or paused + local adjustMin + if minMaxConfig.adjustedMin then + adjustMin = minMaxConfig.adjustedMin + elseif minMaxConfig.adjustedMinRelPercent then + adjustMin = minMaxConfig.adjustedMinRelPercent * total + else + adjustMin = 0 + end + local max + if minMaxConfig.adjustedMax then + max = minMaxConfig.adjustedMax + elseif minMaxConfig.adjustedMaxRelPercent then + max = minMaxConfig.adjustedMaxRelPercent * total + else + max = total + end + -- The output of UpdateProgress is setting various values on self + -- and calling UpdateTime/UpdateValue. Not an ideal interface, but + -- the animation code/sub elements needs those values in some convenient place + self.minProgress, self.maxProgress = adjustMin, max + self.progressType = "static" + self.value = value - adjustMin + self.total = max - adjustMin + if self.UpdateValue then + self:UpdateValue() + end + elseif progressType == "timer" then + local expirationTime + local paused = pausedProperty and state[pausedProperty] + local inverse = inverseProperty and state[inverseProperty] + local remaining + if paused then + remaining = remainingProperty and state[remainingProperty] + expirationTime = GetTime() + (remaining or 0) + else + expirationTime = state[property] or math.huge + end + local duration = totalProperty and state[totalProperty] or 0 + local adjustMin + if minMaxConfig.adjustedMin then + adjustMin = minMaxConfig.adjustedMin + elseif minMaxConfig.adjustedMinRelPercent then + adjustMin = minMaxConfig.adjustedMinRelPercent * duration + else + adjustMin = 0 + end + local max + if minMaxConfig.adjustedMax then + max = minMaxConfig.adjustedMax + elseif minMaxConfig.adjustedMaxRelPercent then + max = minMaxConfig.adjustedMaxRelPercent * duration + else + max = duration + end + self.minProgress, self.maxProgress = adjustMin, max + self.progressType = "timed" + self.duration = max - adjustMin + self.expirationTime = expirationTime - adjustMin + self.remaining = remaining + self.inverse = inverse + self.paused = paused + if self.UpdateTime then + self:UpdateTime() + end + elseif progressType == "elapsedTimer" then + local startTime = state[property] or math.huge + local duration = totalProperty and state[totalProperty] or 0 + local adjustMin + if minMaxConfig.adjustedMin then + adjustMin = minMaxConfig.adjustedMin + elseif minMaxConfig.adjustedMinRelPercent then + adjustMin = minMaxConfig.adjustedMinRelPercent * duration + else + adjustMin = 0 + end + local max + if minMaxConfig.adjustedMax then + max = minMaxConfig.adjustedMax + elseif minMaxConfig.adjustedMaxRelPercent then + max = minMaxConfig.adjustedMaxRelPercent * duration + else + max = duration + end + self.minProgress, self.maxProgress = adjustMin, max + self.progressType = "timed" + self.duration = max - adjustMin + self.expirationTime = startTime + adjustMin + self.duration + self.inverse = true + self.paused = false + self.remaining = nil + if self.UpdateTime then + self:UpdateTime() + end + end +end + +local autoTimedProgressSource = {-1, "timer", "expirationTime", "duration", "inverse", "paused", "remaining"} +local autoStaticProgressSource = {-1, "number", "value", "total", nil, nil, nil, nil} +local function UpdateProgressFromAuto(self, minMaxConfig, state) + if state.progressType == "timed" then + UpdateProgressFromState(self, minMaxConfig, state, autoTimedProgressSource) + elseif state.progressType == "static"then + UpdateProgressFromState(self, minMaxConfig, state, autoStaticProgressSource) + else + self.minProgress, self.maxProgress = nil, nil + self.progressType = "timed" + self.duration = 0 + self.expirationTime = math.huge + self.inverse = false + self.paused = true + self.remaining = math.huge + if self.UpdateTime then + self:UpdateTime() + end + end +end + +local function UpdateProgressFromManual(self, minMaxConfig, state, value, total) + value = type(value) == "number" and value or 0 + total = type(total) == "number" and total or 0 + local adjustMin + if minMaxConfig.adjustedMin then + adjustMin = minMaxConfig.adjustedMin + elseif minMaxConfig.adjustedMinRelPercent then + adjustMin = minMaxConfig.adjustedMinRelPercent * total + else + adjustMin = 0 + end + local max + if minMaxConfig.adjustedMax then + max = minMaxConfig.adjustedMax + elseif minMaxConfig.adjustedMaxRelPercent then + max = minMaxConfig.adjustedMaxRelPercent * total + else + max = total + end + self.minProgress, self.maxProgress = adjustMin, max + self.progressType = "static" + self.value = value - adjustMin + self.total = max - adjustMin + if self.UpdateValue then + self:UpdateValue() + end +end + +local function UpdateProgressFrom(self, progressSource, minMaxConfig, state, states, parent) + local trigger = progressSource and progressSource[1] or -1 + + if trigger == -2 then + -- sub element'a auto uses the whatever progress the main region has + UpdateProgressFromAuto(self, minMaxConfig, parent) + elseif trigger == -1 then + -- auto for regions uses the state + UpdateProgressFromAuto(self, minMaxConfig, state) + elseif trigger == 0 then + UpdateProgressFromManual(self, minMaxConfig, state, progressSource[3], progressSource[4]) + else + UpdateProgressFromState(self, minMaxConfig, states[trigger] or {}, progressSource) + end +end + +-- For regions +local function UpdateProgress(self) + UpdateProgressFrom(self, self.progressSource, self, self.state, self.states) +end + +Private.UpdateProgressFrom = UpdateProgressFrom + local function SetAnimAlpha(self, alpha) + if alpha then + if alpha > 1 then + alpha = 1 + elseif alpha < 0 then + alpha = 0 + end + end if (self.animAlpha == alpha) then return; end self.animAlpha = alpha; + local errorHandler = Private.GetErrorHandlerId(self.id, L["Custom Fade Animation"]) if (WeakAuras.IsOptionsOpen()) then local ok = pcall(self.SetAlpha, self, max(self.animAlpha or self.alpha or 1, 0.5)) if not ok then - Private.GetErrorHandlerId(self.id, L["Custom Fade Animation"]) + errorHandler() end else local ok = pcall(self.SetAlpha, self, self.animAlpha or self.alpha or 1) if not ok then - Private.GetErrorHandlerId(self.id, L["Custom Fade Animation"]) + errorHandler() end end self.subRegionEvents:Notify("AlphaChanged") end -local function SetTriggerProvidesTimer(self, timerTick) - self.triggerProvidesTimer = timerTick - self:UpdateTimerTick() -end - -local function TimerTickForRegion(region) - Private.StartProfileSystem("timer tick") - Private.StartProfileAura(region.id); - - region.subRegionEvents:Notify("TimerTick") - Private.StopProfileAura(region.id); - Private.StopProfileSystem("timer tick") -end - -local function UpdateTimerTick(self) - if self.triggerProvidesTimer and self.subRegionEvents:HasSubscribers("TimerTick") and self.toShow then - if not self:GetScript("OnUpdate") then - self:SetScript("OnUpdate", function() - TimerTickForRegion(self) - end); - end - else - if self:GetScript("OnUpdate") then - self:SetScript("OnUpdate", nil); - end - end -end - -local function UpdateFrameTick(self) +local function UpdateTick(self) if self.subRegionEvents:HasSubscribers("FrameTick") and self.toShow then - Private.FrameTick:AddSubscriber("FrameTick", self) + Private.FrameTick:AddSubscriber("Tick", self) else - Private.FrameTick:RemoveSubscriber("FrameTick", self) + Private.FrameTick:RemoveSubscriber("Tick", self) end end -local function FrameTick(self) +local function Tick(self) Private.StartProfileAura(self.id) self.values.lastCustomTextUpdate = nil self.subRegionEvents:Notify("FrameTick") @@ -484,12 +641,18 @@ function Private.regionPrototype.create(region) region.SetRegionAlpha = SetRegionAlpha; region.GetRegionAlpha = GetRegionAlpha; end + if defaultsForRegion and defaultsForRegion.progressSource then + region.SetProgressSource = SetProgressSource + region.GetProgressSource = GetProgressSource + region.SetAdjustedMin = SetAdjustedMin + region.SetAdjustedMax = SetAdjustedMax + end + region.UpdateProgress = UpdateProgress + region.GetMinMaxProgress = GetMinMaxProgress region.SetAnimAlpha = SetAnimAlpha; - region.SetTriggerProvidesTimer = SetTriggerProvidesTimer - region.UpdateTimerTick = UpdateTimerTick - region.UpdateFrameTick = UpdateFrameTick - region.FrameTick = FrameTick + region.UpdateTick = UpdateTick + region.Tick = Tick region.subRegionEvents = Private.CreateSubscribableObject() region.AnchorSubRegion = AnchorSubRegion @@ -498,14 +661,12 @@ function Private.regionPrototype.create(region) region:SetPoint("CENTER", UIParent, "CENTER") end --- SetDurationInfo - function Private.regionPrototype.modify(parent, region, data) region.state = nil region.states = nil region.subRegionEvents:ClearSubscribers() region.subRegionEvents:ClearCallbacks() - Private.FrameTick:RemoveSubscriber("FrameTick", region) + Private.FrameTick:RemoveSubscriber("Tick", region) local defaultsForRegion = Private.regionTypes[data.regionType] and Private.regionTypes[data.regionType].default; @@ -513,18 +674,20 @@ function Private.regionPrototype.modify(parent, region, data) region:SetRegionAlpha(data.alpha) end - local hasAdjustedMin = defaultsForRegion and defaultsForRegion.useAdjustededMin ~= nil and data.useAdjustededMin - and data.adjustedMin; - local hasAdjustedMax = defaultsForRegion and defaultsForRegion.useAdjustededMax ~= nil and data.useAdjustededMax - and data.adjustedMax; + local hasProgressSource = defaultsForRegion and defaultsForRegion.progressSource + local hasAdjustedMin = hasProgressSource and data.useAdjustededMin and data.adjustedMin + local hasAdjustedMax = hasProgressSource and data.useAdjustededMax and data.adjustedMax + region.progressSource = nil region.adjustedMin = nil - region.adjustedMinRel = nil region.adjustedMinRelPercent = nil region.adjustedMax = nil - region.adjustedMaxRel = nil region.adjustedMaxRelPercent = nil + if hasProgressSource then + region.progressSource = Private.AddProgressSourceMetaData(data, data.progressSource) + end + if (hasAdjustedMin) then local percent = string.match(data.adjustedMin, "(%d+)%%") if percent then @@ -576,7 +739,7 @@ function Private.regionPrototype.modify(parent, region, data) data.actions.start[fullKey] = default end return data.actions.start[fullKey] - end, true) + end, true, data) region.finishFormatters = Private.CreateFormatters(data.actions.finish.message, function(key, default) local fullKey = "message_format_" .. key @@ -584,7 +747,7 @@ function Private.regionPrototype.modify(parent, region, data) data.actions.finish[fullKey] = default end return data.actions.finish[fullKey] - end, true) + end, true, data) end function Private.regionPrototype.modifyFinish(parent, region, data) @@ -615,91 +778,56 @@ function Private.regionPrototype.modifyFinish(parent, region, data) end end - region.subRegionEvents:SetOnSubscriptionStatusChanged("TimerTick", function() - region:UpdateTimerTick() - end) - region:UpdateTimerTick() - region.subRegionEvents:SetOnSubscriptionStatusChanged("FrameTick", function() - region:UpdateFrameTick() + region:UpdateTick() end) - region:UpdateFrameTick() + region:UpdateTick() Private.ApplyFrameLevel(region) end -local function SetProgressValue(region, value, total) - local adjustMin = region.adjustedMin or 0; - local max = region.adjustedMax or total; - - region:SetValue(value - adjustMin, max - adjustMin); -end - -local regionsForFrameTick = {} - local frameForFrameTick = CreateFrame("Frame"); Private.frames["Frame Tick Frame"] = frameForFrameTick Private.FrameTick = Private.CreateSubscribableObject() Private.FrameTick.OnUpdateHandler = function() - if WeakAuras.IsOptionsOpen() then - return - end Private.StartProfileSystem("frame tick") - Private.FrameTick:Notify("FrameTick") + Private.FrameTick:Notify("Tick") Private.StopProfileSystem("frame tick") end -Private.FrameTick:SetOnSubscriptionStatusChanged("FrameTick", function() - if Private.FrameTick:HasSubscribers("FrameTick") then +Private.FrameTick:SetOnSubscriptionStatusChanged("Tick", function() + if Private.FrameTick:HasSubscribers("Tick") then frameForFrameTick:SetScript("OnUpdate", Private.FrameTick.OnUpdateHandler); else frameForFrameTick:SetScript("OnUpdate", nil) end end) -local function TimerTickForSetDuration(self) - local duration = self.duration - local adjustMin = self.adjustedMin or 0; - - local max - if duration == 0 then - max = 0 - elseif self.adjustedMax then - max = self.adjustedMax - else - max = duration - end - - self:SetTime(max - adjustMin, self.expirationTime - adjustMin, self.inverse); -end - -function Private.regionPrototype.AddSetDurationInfo(region) - if (region.SetValue and region.SetTime) then - region.generatedSetDurationInfo = true; - - -- WeakAuras no longer calls SetDurationInfo, but some people do that, - -- In that case we also need to overwrite TimerTick +function Private.regionPrototype.AddSetDurationInfo(region, uid) + if (region.UpdateValue and region.UpdateTime) then + -- WeakAuras no longer calls SetDurationInfo, but some people do that region.SetDurationInfo = function(self, duration, expirationTime, customValue, inverse) - self.duration = duration or 0 - self.expirationTime = expirationTime; - self.inverse = inverse; - + -- For now don't warn against SetDurationInfo + -- Private.AuraWarnings.UpdateWarning(uid, "SetDurationInfo", "warning", L["Aura is using deprecated SetDurationInfo"]) if customValue then - SetProgressValue(region, duration, expirationTime); - region.TimerTick = nil - region.subRegionEvents:RemoveSubscriber("TimerTick", self) - else local adjustMin = region.adjustedMin or 0; - region:SetTime((duration ~= 0 and region.adjustedMax or duration) - adjustMin, expirationTime - adjustMin, inverse); - - region.TimerTick = TimerTickForSetDuration - region.subRegionEvents:AddSubscriber("TimerTick", self, true) + local max = self.adjustedMax or expirationTime + region.progressType = "static" + region.value = duration - adjustMin + region.total = max - adjustMin + region:UpdateValue() + else + local adjustMin = self.adjustedMin or 0; + self.progressType = "timed" + self.duration = (duration ~= 0 and self.adjustedMax or duration) - adjustMin + self.expirationTime = expirationTime - adjustMin + self.inverse = inverse + self.paused = false + self.remaining = nil + self:UpdateTime() end end - elseif (region.generatedSetDurationInfo) then - region.generatedSetDurationInfo = nil; - region.SetDurationInfo = nil; end end @@ -808,8 +936,7 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent region:SoundRepeatStop(); end - region:UpdateFrameTick() - region:UpdateTimerTick() + region:UpdateTick() end function region:Expand() if (region.toShow) then @@ -844,8 +971,7 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent end parent:ActivateChild(data.id, cloneId); - region:UpdateFrameTick() - region:UpdateTimerTick() + region:UpdateTick() end elseif not(data.controlledChildren) then function region:Collapse() @@ -867,8 +993,7 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent region:SoundRepeatStop(); end - region:UpdateFrameTick() - region:UpdateTimerTick() + region:UpdateTick() end function region:Expand() if data.anchorFrameType == "SELECTFRAME" @@ -915,8 +1040,7 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent parent:UpdateBorder(region); end - region:UpdateFrameTick() - region:UpdateTimerTick() + region:UpdateTick() end end -- Stubs that allow for polymorphism @@ -926,16 +1050,6 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent if not region.Expand then function region:Expand() end end - if not region.Pause then - function region:Pause() - self.paused = true - end - end - if not region.Resume then - function region:Resume() - self.paused = nil - end - end end do diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index 6b70798..df1e60c 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -5,6 +5,7 @@ local texture_data = WeakAuras.StopMotion.texture_data; local L = WeakAuras.L; local default = { + progressSource = {-1, "" }, foregroundTexture = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\StopMotion", backgroundTexture = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\StopMotion", desaturateBackground = false, @@ -44,6 +45,8 @@ local default = { hideBackground = true }; +Private.regionPrototype.AddProgressSourceToDefault(default) + local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; local properties = { @@ -87,6 +90,12 @@ local properties = { Private.regionPrototype.AddProperties(properties, default); +local function GetProperties(data) + local result = CopyTable(properties) + result.progressSource.values = Private.GetProgressSourcesForUi(data) + return result +end + local function create(parent) local frame = CreateFrame("Frame", nil, UIParent); frame.regionType = "stopmotion" @@ -150,10 +159,117 @@ local function SetFrameViaFrames(self, texture, frame) self:SetTexture(texture .. format("%03d", frame)); end +local function SetProgress(self, progress) + local frames + local startFrame = self.startFrame + local endFrame = self.endFrame + local inverse = self.inverseDirection + if (endFrame >= startFrame) then + frames = endFrame - startFrame + 1 + else + frames = startFrame - endFrame + 1 + startFrame, endFrame = endFrame, startFrame + inverse = not inverse + end + local frame = floor( (frames - 1) * progress) + startFrame + + if (inverse) then + frame = endFrame - frame + startFrame; + end + + if (frame > endFrame) then + frame = endFrame + end + + if (frame < startFrame) then + frame = startFrame + end + self.foreground:SetFrame(self.foregroundTexture, frame); +end + +local FrameTickFunctions = { + progressTimer = function(self) + Private.StartProfileSystem("stopmotion") + Private.StartProfileAura(self.id) + local remaining = self.expirationTime - GetTime() + local progress = 1 - (remaining / self.duration) + + self:SetProgress(progress) + + Private.StopProfileAura(self.id) + Private.StopProfileSystem("stopmotion") + end, + timed = function(self) + if (not self.startTime) then return end + + Private.StartProfileSystem("stopmotion") + Private.StartProfileAura(self.id) + + local timeSinceStart = (GetTime() - self.startTime) + local newCurrentFrame = floor(timeSinceStart * (self.frameRate or 15)) + if (newCurrentFrame == self.currentFrame) then + Private.StopProfileAura(self.id) + Private.StopProfileSystem("stopmotion") + return + end + + self.currentFrame = newCurrentFrame + + local frames + local startFrame = self.startFrame + local endFrame = self.endFrame + local inverse = self.inverseDirection + if (endFrame >= startFrame) then + frames = endFrame - startFrame + 1 + else + frames = startFrame - endFrame + 1 + startFrame, endFrame = endFrame, startFrame + inverse = not inverse + end + + local frame = 0 + if (self.animationType == "loop") then + frame = (newCurrentFrame % frames) + startFrame + elseif (self.animationType == "bounce") then + local direction = floor(newCurrentFrame / frames) % 2 + if (direction == 0) then + frame = (newCurrentFrame % frames) + startFrame + else + frame = endFrame - (newCurrentFrame % frames) + end + elseif (self.animationType == "once") then + frame = newCurrentFrame + startFrame + if (frame > endFrame) then + frame = endFrame + end + end + if (inverse) then + frame = endFrame - frame + startFrame + end + + if (frame > endFrame) then + frame = endFrame + end + + if (frame < startFrame) then + frame = startFrame + end + self.foreground:SetFrame(self.foregroundTexture, frame) + + Private.StopProfileAura(self.id) + Private.StopProfileSystem("stopmotion") + end, +} + local function modify(parent, region, data) Private.regionPrototype.modify(parent, region, data); region.foreground = region.foreground or {} region.background = region.background or {} + region.frameRate = data.frameRate + region.inverseDirection = data.inverse + region.animationType = data.animationType + region.foregroundTexture = data.foregroundTexture + region.FrameTick = nil local pattern = "%.x(%d+)y(%d+)f(%d+)%.[tb][gl][ap]" local pattern2 = "%.x(%d+)y(%d+)f(%d+)w(%d+)h(%d+)W(%d+)H(%d+)%.[tb][gl][ap]" @@ -364,101 +480,52 @@ local function modify(parent, region, data) function region:PreShow() region.startTime = GetTime(); + if region.FrameTick then + region:FrameTick() + end end - local function onUpdate() - if (not region.startTime) then return end + region.SetProgress = SetProgress - Private.StartProfileAura(region.id); - Private.StartProfileSystem("stopmotion") - local timeSinceStart = (GetTime() - region.startTime); - local newCurrentFrame = floor(timeSinceStart * (data.frameRate or 15)); - if (newCurrentFrame == region.currentFrame) then - Private.StopProfileAura(region.id); - Private.StopProfileSystem("stopmotion") - return; - end - - region.currentFrame = newCurrentFrame; - - local frames; - local startFrame = region.startFrame; - local endFrame = region.endFrame; - local inverse = data.inverse; - if (endFrame >= startFrame) then - frames = endFrame - startFrame + 1; - else - frames = startFrame - endFrame + 1; - startFrame, endFrame = endFrame, startFrame; - inverse = not inverse; - end - - local frame = 0; - if (data.animationType == "loop") then - frame = (newCurrentFrame % frames) + startFrame; - elseif (data.animationType == "bounce") then - local direction = floor(newCurrentFrame / frames) % 2; - if (direction == 0) then - frame = (newCurrentFrame % frames) + startFrame; - else - frame = endFrame - (newCurrentFrame % frames); - end - elseif (data.animationType == "once") then - frame = newCurrentFrame + startFrame - if (frame > endFrame) then - frame = endFrame; - end - elseif (data.animationType == "progress") then - if (not region.state) then - -- Do nothing - elseif (region.state.progressType == "static") then - local value = region.state.value or 0 - local total = region.state.total ~= 0 and region.state.total or 1 - frame = floor((frames - 1) * value / total) + startFrame; - else - local remaining - if region.state.paused then - remaining = region.state.remaining or 0; - else - remaining = region.state.expirationTime and (region.state.expirationTime - GetTime()) or 0; - end - local progress = region.state.duration and region.state.duration > 0 and (1 - (remaining / region.state.duration)) or 0; - frame = floor( (frames - 1) * progress) + startFrame; - end - end - - if (inverse) then - frame = endFrame - frame + startFrame; - end - - if (frame > endFrame) then - frame = endFrame - end - if (frame < startFrame) then - frame = startFrame - end - region.foreground:SetFrame(data.foregroundTexture, frame); - - Private.StopProfileAura(region.id); - Private.StopProfileSystem("stopmotion") - end; - - region.FrameTick = onUpdate; - if region.FrameTick then + if data.animationType == "loop" or data.animationType == "bounce" or data.animationType == "once" then + region.FrameTick = FrameTickFunctions.timed region.subRegionEvents:AddSubscriber("FrameTick", region, true) - end + function region:Update() + end - function region:Update() - if region.state.paused then - if not region.paused then - region:Pause() + elseif data.animationType == "progress" then + function region:Update() + region:UpdateProgress() + end + + function region:UpdateValue() + local progress = 0; + if (self.total ~= 0) then + progress = self.value / self.total end - else - if region.paused then - region:Resume() + self:SetProgress(progress) + if self.FrameTick then + self.FrameTick = nil + self.subRegionEvents:RemoveSubscriber("FrameTick", self) end end - onUpdate(); + + function region:UpdateTime() + if self.paused and self.FrameTick then + self.FrameTick = nil + self.subRegionEvents:RemoveSubscriber("FrameTick", self) + end + self.expirationTime = self.expirationTime + self.duration = self.duration + if not self.paused then + if not self.FrameTick then + self.FrameTick = FrameTickFunctions.progressTimer + self.subRegionEvents:AddSubscriber("FrameTick", self) + end + self:FrameTick() + end + + end end function region:SetForegroundDesaturated(b) @@ -488,4 +555,4 @@ local function validate(data) Private.EnforceSubregionExists(data, "subbackground") end -Private.RegisterRegionType("stopmotion", create, modify, default, properties, validate); +Private.RegisterRegionType("stopmotion", create, modify, default, GetProperties, validate); diff --git a/WeakAuras/RegionTypes/Text.lua b/WeakAuras/RegionTypes/Text.lua index 2b92c01..8948001 100644 --- a/WeakAuras/RegionTypes/Text.lua +++ b/WeakAuras/RegionTypes/Text.lua @@ -54,10 +54,6 @@ local properties = { Private.regionPrototype.AddProperties(properties, default); -local function GetProperties(data) - return properties; -end - local function create(parent) local region = CreateFrame("Frame", nil, parent); region.regionType = "text" @@ -68,9 +64,6 @@ local function create(parent) text:SetWordWrap(true); text:SetNonSpaceWrap(true); - region.duration = 0; - region.expirationTime = math.huge; - Private.regionPrototype.create(region); return region; @@ -220,7 +213,7 @@ local function modify(parent, region, data) end end - formatters = Private.CreateFormatters(texts, getter) + formatters = Private.CreateFormatters(texts, getter, false, data) end local customTextFunc = nil @@ -252,12 +245,11 @@ local function modify(parent, region, data) Update = UpdateText or function() end end - local TimerTick + local FrameTick if Private.ContainsPlaceHolders(self.displayText, "p") then - TimerTick = UpdateText + FrameTick = UpdateText end - local FrameTick if customTextFunc and data.customTextUpdate == "update" then if Private.ContainsCustomPlaceHolder(self.displayText) then FrameTick = function() @@ -269,7 +261,6 @@ local function modify(parent, region, data) self.Update = Update self.FrameTick = FrameTick - self.TimerTick = TimerTick if not UpdateText then local textStr = self.displayText @@ -285,11 +276,6 @@ local function modify(parent, region, data) self.subRegionEvents:RemoveSubscriber("FrameTick", self) end - if self.TimerTick then - self.subRegionEvents:AddSubscriber("TimerTick", self, true) - else - self.subRegionEvents:RemoveSubscriber("TimerTick", self) - end if self.Update and self.state then self:Update() end @@ -347,7 +333,7 @@ local function validate(data) Private.EnforceSubregionExists(data, "subbackground") end -Private.RegisterRegionType("text", create, modify, default, GetProperties, validate); +Private.RegisterRegionType("text", create, modify, default, properties, validate); -- Fallback region type diff --git a/WeakAuras/SubRegionTypes/SubText.lua b/WeakAuras/SubRegionTypes/SubText.lua index 1f41614..ba49f24 100644 --- a/WeakAuras/SubRegionTypes/SubText.lua +++ b/WeakAuras/SubRegionTypes/SubText.lua @@ -244,7 +244,7 @@ local function modify(parent, region, parentData, data, first) end return data[fullKey] end - region.subTextFormatters = Private.CreateFormatters(texts, getter) + region.subTextFormatters = Private.CreateFormatters(texts, getter, false, parentData) function region:ConfigureTextUpdate() local UpdateText @@ -273,12 +273,11 @@ local function modify(parent, region, parentData, data, first) Update = UpdateText end - local TimerTick + local FrameTick if Private.ContainsPlaceHolders(region.text_text, "p") then - TimerTick = UpdateText + FrameTick = UpdateText end - local FrameTick if parent.customTextFunc and parentData.customTextUpdate == "update" then if Private.ContainsCustomPlaceHolder(region.text_text) then FrameTick = function() @@ -293,7 +292,6 @@ local function modify(parent, region, parentData, data, first) region.Update = Update region.FrameTick = FrameTick - region.TimerTick = TimerTick if not UpdateText then if text:GetFont() then @@ -320,13 +318,6 @@ local function modify(parent, region, parentData, data, first) else parent.subRegionEvents:RemoveSubscriber("FrameTick", region) end - if self.TimerTick then - if visible then - parent.subRegionEvents:AddSubscriber("TimerTick", region) - end - else - parent.subRegionEvents:RemoveSubscriber("TimerTick", region) - end if self.Update and parent.state and visible then self:Update() end diff --git a/WeakAuras/SubRegionTypes/Tick.lua b/WeakAuras/SubRegionTypes/Tick.lua index 8737d94..04c9064 100644 --- a/WeakAuras/SubRegionTypes/Tick.lua +++ b/WeakAuras/SubRegionTypes/Tick.lua @@ -8,7 +8,8 @@ local default = function() tick_visible = true, tick_color = {1, 1, 1, 1}, tick_placement_mode = "AtValue", - tick_placement = "50", + tick_placements = {"50"}, + progressSources = {{-2, ""}}, automatic_length = true, tick_thickness = 2, tick_length = 30, @@ -41,12 +42,6 @@ local properties = { type = "list", values = Private.tick_placement_modes, }, - tick_placement = { - display = L["Placement"], - setter = "SetTickPlacement", - type = "number", - validate = WeakAuras.ValidateNumeric, - }, automatic_length = { display = L["Automatic Length"], setter = "SetAutomaticLength", @@ -91,6 +86,22 @@ local properties = { }, } +local function GetProperties(parentData, data) + local result = CopyTable(properties) + for i in ipairs(data.tick_placements) do + + result["tick_placement" .. i] = { + display = #data.tick_placements > 1 and L["Placement %i"]:format(i) or L["Placement"], + setter = "SetTickPlacementAt", + type = "number", + arg1 = i, + validate = WeakAuras.ValidateNumeric, + } + end + + return result +end + local auraBarAnchor = { ["HORIZONTAL"] = "LEFT", ["HORIZONTAL_INVERSE"] = "RIGHT", @@ -107,9 +118,7 @@ local auraBarAnchorInverse = { local function create() local subRegion = CreateFrame("Frame", nil, UIParent) - subRegion.texture = subRegion:CreateTexture() - subRegion.texture:SetDrawLayer("ARTWORK", 3) - subRegion.texture:SetAllPoints(subRegion) + subRegion.ticks = {} return subRegion end @@ -129,19 +138,14 @@ local function getRotatedPoints(degrees) end local funcs = { - Update = function(self, state) - self.trigger_inverse = state.inverse - self.state = state - if state.progressType == "timed" then - self.trigger_total = state.duration - elseif state.progressType == "static" then - self.trigger_total = state.total - else - self.trigger_total = nil + Update = function(self, state, states) + for i, progressSource in ipairs(self.progressSources) do + self.progressData[i] = {} + Private.UpdateProgressFrom(self.progressData[i], progressSource, {}, state, states, self.parent) end self:UpdateVisible() self:UpdateTickPlacement(); - self:UpdateTimerTick() + self:UpdateFrameTick() end, OrientationChanged = function(self) self.orientation = self.parent:GetEffectiveOrientation() @@ -161,7 +165,7 @@ local funcs = { self:UpdateTickSize() end, InverseChanged = function(self) - self.inverse = self.parent:GetInverse() + self.inverse_direction = self.parent:GetInverse() self:UpdateTickPlacement() end, SetVisible = function(self, visible) @@ -170,21 +174,29 @@ local funcs = { self:UpdateVisible() end end, - UpdateVisible = function(self) - local missingProgress = self.tick_placement_mode ~= "AtPercent" and not self.trigger_total - if self.tick_visible and not missingProgress then - self:Show() + UpdateVisibleOne = function(self, i) + if self.tick_visible and self.hasProgress[i] then + self.ticks[i]:Show() else - self:Hide() + self.ticks[i]:Hide() + end + end, + UpdateVisible = function(self) + for i in ipairs(self.ticks) do + self:UpdateVisibleOne(i) end end, SetTickColor = function(self, r, g, b, a) self.tick_color[1], self.tick_color[2], self.tick_color[3], self.tick_color[4] = r, g, b, a or 1 if self.use_texture then - self.texture:SetVertexColor(r, g, b, a or 1) + for _, tick in ipairs(self.ticks) do + tick:SetVertexColor(r, g, b, a or 1) + end self:UpdateTickDesaturated() else - self.texture:SetTexture(r, g, b, a or 1) + for _, tick in ipairs(self.ticks) do + tick:SetTexture(r, g, b, a or 1) + end end end, SetTickPlacementMode = function(self, placement_mode) @@ -192,74 +204,93 @@ local funcs = { self.tick_placement_mode = placement_mode self:UpdateTickPlacement() self:UpdateVisible() - self:UpdateTimerTick() + self:UpdateFrameTick() end end, - UpdateTimerTick = function(self) - if self.tick_placement_mode == "ValueOffset" and self.state and self.state.progressType == "timed" and not self.paused then - if not self.TimerTick then - self.TimerTick = self.UpdateTickPlacement - self.parent.subRegionEvents:AddSubscriber("TimerTick", self) + UpdateFrameTick = function(self) + local requiresFrameTick = false + if self.tick_placement_mode == "ValueOffset" then + for i, progress in ipairs(self.progressData) do + if progress.progressType == "timed" and not progress.paused then + requiresFrameTick = true + break + end + end + end + if requiresFrameTick then + if not self.FrameTick then + self.FrameTick = self.UpdateTickPlacement + self.parent.subRegionEvents:AddSubscriber("FrameTick", self) end else - if self.TimerTick then - self.TimerTick = nil - self.parent.subRegionEvents:RemoveSubscriber("TimerTick", self) + if self.FrameTick then + self.FrameTick = nil + self.parent.subRegionEvents:RemoveSubscriber("FrameTick", self) end end end, - SetTickPlacement = function(self, placement) + SetTickPlacementAt = function(self, tick, placement) placement = tonumber(placement) - if self.tick_placement ~= placement then - self.tick_placement = placement - self:UpdateTickPlacement() + if self.tick_placements[tick] ~= placement then + self.tick_placements[tick] = placement + self:UpdateTickPlacementOne(tick) end end, + -- For backwards compability + SetTickPlacement = function(self, placement) + self:SetTickPlacementAt(1, placement) + end, UpdateTickPlacement = function(self) - local offset, offsetx, offsety = self.tick_placement, 0, 0 + for i in ipairs(self.tick_placements) do + self:UpdateTickPlacementOne(i) + end + end, + UpdateTickPlacementOne = function(self, i) + local offsetx, offsety = 0, 0 local width = self.parentMajorSize - local minValue, maxValue = self.parent:GetMinMax() + local minValue, maxValue = self.parent:GetMinMaxProgress() local valueRange = maxValue - minValue + local inverse = self.inverse_direction + if self.parent.inverse then + inverse = not inverse + end local tick_placement if self.tick_placement_mode == "AtValue" then - tick_placement = self.tick_placement + tick_placement = self.tick_placements[i] elseif self.tick_placement_mode == "AtMissingValue" then - tick_placement = self.trigger_total and self.trigger_total - self.tick_placement + tick_placement = maxValue - self.tick_placements[i] elseif self.tick_placement_mode == "AtPercent" then - if self.tick_placement >= 0 and self.tick_placement <= 100 and self.trigger_total then - tick_placement = self.tick_placement * self.trigger_total / 100 + if self.tick_placements[i] >= 0 and self.tick_placements[i] <= 100 and maxValue then + tick_placement = minValue + self.tick_placements[i] * valueRange / 100 end elseif self.tick_placement_mode == "ValueOffset" then - if self.trigger_total and self.trigger_total ~= 0 then - if self.state.progressType == "timed" then - if self.state.paused then - if self.state.remaining then - tick_placement = self.state.remaining + self.tick_placement + if maxValue ~= 0 and self.progressData[i] then + if self.progressData[i].progressType == "timed" then + if self.progressData[i].paused then + if self.progressData[i].remaining then + tick_placement = self.progressData[i].remaining + self.tick_placements[i] end else - tick_placement = self.state.expirationTime - GetTime() + self.tick_placement + tick_placement = self.progressData[i].expirationTime - GetTime() + self.tick_placements[i] end - else - tick_placement = self.state.value + self.tick_placement + elseif self.progressType == "static" then + tick_placement = self.progressData[i].value + self.progressData[i].tick_placements[i] end end end + local offset local percent = valueRange ~= 0 and tick_placement and (tick_placement - minValue) / valueRange if not percent or (percent and percent < 0 or percent > 1) then - self.texture:Hide() offset = 0 + self.hasProgress[i] = false else - self.texture:Show() offset = percent * width + self.hasProgress[i] = true end - - local inverse = self.inverse - if self.trigger_inverse then - inverse = not inverse - end + self:UpdateVisible(i) if (self.orientation == "HORIZONTAL_INVERSE") or (self.orientation == "VERTICAL") then offset = -offset @@ -275,8 +306,10 @@ local funcs = { offsetx = offset end local side = inverse and auraBarAnchorInverse or auraBarAnchor - self:ClearAllPoints() - self:SetPoint("CENTER", self.parent.bar, side[self.orientation], offsetx + self.tick_xOffset, offsety + self.tick_yOffset) + self.ticks[i]:ClearAllPoints() + self.ticks[i]:SetPoint("CENTER", self.parent.bar, side[self.orientation], + offsetx + self.tick_xOffset, + offsety + self.tick_yOffset) end, SetAutomaticLength = function(self, automatic_length) if self.automatic_length ~= automatic_length then @@ -298,16 +331,24 @@ local funcs = { end, UpdateTickSize = function(self) if self.vertical then - self:SetHeight(self.tick_thickness) + for i, tick in ipairs(self.ticks) do + tick:SetHeight(self.tick_thickness) + end else - self:SetWidth(self.tick_thickness) + for i, tick in ipairs(self.ticks) do + tick:SetWidth(self.tick_thickness) + end end local length = self.automatic_length and self.parentMinorSize or self.tick_length if self.vertical then - self:SetWidth(length) + for i, tick in ipairs(self.ticks) do + tick:SetWidth(length) + end else - self:SetHeight(length) + for i, tick in ipairs(self.ticks) do + tick:SetHeight(length) + end end end, SetTickDesaturated = function(self, desaturate) @@ -317,7 +358,9 @@ local funcs = { end end, UpdateTickDesaturated = function(self) - self.texture:SetDesaturated(self.tick_desaturate) + for i, tick in ipairs(self.ticks) do + tick:SetDesaturated(self.tick_desaturate) + end end, SetTickRotation = function(self, degrees) if self.tick_rotation ~= degrees then @@ -326,7 +369,10 @@ local funcs = { end end, UpdateTickRotation = function(self) - self:UpdateTexCoord() + local rad = math.rad(self.tick_rotation) + for _, tick in ipairs(self.ticks) do + tick:SetRotation(rad) + end end, SetTickMirror = function(self, mirror) if self.mirror ~= mirror then @@ -335,7 +381,15 @@ local funcs = { end end, UpdateTickMirror = function(self) - self:UpdateTexCoord() + if self.mirror then + for _, tick in ipairs(self.ticks) do + tick:SetTexCoord(0, 1, 1, 1, 0, 0, 1, 0) + end + else + for _, tick in ipairs(self.ticks) do + tick:SetTexCoord(0, 0, 1, 0, 0, 1, 1, 1) + end + end end, SetTickBlendMode = function(self, mode) if self.tick_blend_mode ~= mode then @@ -345,27 +399,22 @@ local funcs = { end, UpdateTickBlendMode = function(self) if self.use_texture then - self.texture:SetBlendMode(self.tick_blend_mode) + for _, tick in ipairs(self.ticks) do + tick:SetBlendMode(self.tick_blend_mode) + end else - self.texture:SetBlendMode("BLEND") - end - end, - UpdateTexCoord = function(self) - local ulx, uly, llx, lly, urx, ury, lrx, lry = getRotatedPoints(self.tick_rotation); - if self.mirror then - self.texture:SetTexCoord(urx, ury, lrx, lry, ulx, uly, llx, lly); - else - self.texture:SetTexCoord(ulx, uly, llx, lly, urx, ury, lrx, lry); + for _, tick in ipairs(self.ticks) do + tick:SetBlendMode("BLEND") + end end end, } local function modify(parent, region, parentData, data, first) - region:SetParent(parent) region.orientation = parent.effectiveOrientation - region.inverse = parentData.inverse - region.trigger_inverse = false + region.inverse_direction = parentData.inverse + region.inverse = false region.vertical = region.orientation == "VERTICAL" or region.orientation == "VERTICAL_INVERSE" if (region.vertical) then region.parentMinorSize, region.parentMajorSize = parent.bar:GetRealSize() @@ -378,7 +427,35 @@ local function modify(parent, region, parentData, data, first) region.tick_visible = data.tick_visible region.tick_color = CopyTable(data.tick_color) region.tick_placement_mode = data.tick_placement_mode - region.tick_placement = tonumber(data.tick_placement) + region.tick_placements = {} + region.progressSources = {} + region.progressData = {} + for i, tick_placement in ipairs(data.tick_placements) do + local value = tonumber(tick_placement) + if region.tick_placement_mode == "ValueOffset" then + local progressSource = Private.AddProgressSourceMetaData(parentData, data.progressSources[i] or {-2, ""}) + if value and progressSource then + tinsert(region.tick_placements, value) + tinsert(region.progressSources, progressSource or {}) + end + else + if value then + tinsert(region.tick_placements, value) + end + end + + if region.ticks[i] == nil then + local texture = region:CreateTexture() + texture:SetDrawLayer("ARTWORK", 3) + texture:SetAllPoints(region) + region.ticks[i] = texture + end + end + + for i = #data.tick_placements + 1, #region.ticks do + region.ticks[i]:Hide() + end + region.automatic_length = data.automatic_length region.tick_thickness = data.tick_thickness region.tick_length = data.tick_length @@ -388,12 +465,16 @@ local function modify(parent, region, parentData, data, first) region.tick_xOffset = data.tick_xOffset region.tick_yOffset = data.tick_yOffset + region.hasProgress = {} + for k, v in pairs(funcs) do region[k] = v end if data.use_texture then - region.texture:SetTexture(data.tick_texture) + for _, tick in ipairs(region.ticks) do + tick:SetTexture(data.tick_texture) + end end region:SetVisible(data.tick_visible) @@ -410,11 +491,14 @@ local function modify(parent, region, parentData, data, first) parent.subRegionEvents:AddSubscriber("InverseChanged", region) parent.subRegionEvents:AddSubscriber("OnRegionSizeChanged", region) - region.TimerTick = nil + region.FrameTick = nil + region:ClearAllPoints() + region:SetAllPoints(parent.bar) end local function supports(regionType) return regionType == "aurabar" end -WeakAuras.RegisterSubRegionType("subtick", L["Tick"], supports, create, modify, onAcquire, onRelease, default, nil, properties); +WeakAuras.RegisterSubRegionType("subtick", L["Tick"], supports, create, modify, onAcquire, onRelease, + default, nil, GetProperties); diff --git a/WeakAuras/SubscribableObject.lua b/WeakAuras/SubscribableObject.lua index 614e334..092b001 100644 --- a/WeakAuras/SubscribableObject.lua +++ b/WeakAuras/SubscribableObject.lua @@ -4,7 +4,12 @@ local AddonName, Private = ... local WeakAuras = WeakAuras local L = WeakAuras.L -local SubscribableObject ={ +local SubscribableObject = +{ + events = {}, + subscribers = {}, + callbacks = {}, + ClearSubscribers = function(self) self.events = {} self.subscribers = {} @@ -76,12 +81,5 @@ local SubscribableObject ={ } function Private.CreateSubscribableObject() - local system = {} - for f, func in pairs(SubscribableObject) do - system[f] = func - system.events = {} - system.subscribers = {} - system.callbacks = {} - end - return system + return CopyTable(SubscribableObject) end diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 30d44db..1c6862e 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -226,7 +226,7 @@ Private.format_types = { disabled = function() return get(symbol .. "_time_dynamic_threshold") == 0 end }) end, - CreateFormatter = function(symbol, get) + CreateFormatter = function(symbol, get, wihoutColor, data) local format = get(symbol .. "_time_format", 0) local threshold = get(symbol .. "_time_dynamic_threshold", 60) local precision = get(symbol .. "_time_precision", 1) @@ -237,7 +237,7 @@ Private.format_types = { end local formatter if threshold == 0 then - formatter = function(value, state) + formatter = function(value, state, trigger) if type(value) ~= 'number' or value == math.huge then return "" end @@ -248,7 +248,7 @@ Private.format_types = { end else local formatString = "%." .. precision .. "f" - formatter = function(value, state) + formatter = function(value, state, trigger) if type(value) ~= 'number' or value == math.huge then return "" end @@ -269,11 +269,11 @@ Private.format_types = { -- Special case %p and %t. Since due to how the formatting -- work previously, the time formatter only formats %p and %t -- if the progress type is timed! - return function(value, state) + return function(value, state, trigger) if not state or state.progressType ~= "timed" then return value end - return formatter(value, state) + return formatter(value, state, trigger) end else return formatter @@ -1290,6 +1290,11 @@ Private.orientation_with_circle_types = { ANTICLOCKWISE = L["Anticlockwise"] } +Private.gradient_orientations = { + HORIZONTAL = L["Horizontal"], + VERTICAL = L["Vertical"] +} + Private.talent_types = {} for tab = 1, 5 do for num_talent = 1, MAX_NUM_TALENTS do diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 57d19b4..9ecfeae 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1,6 +1,6 @@ local AddonName, Private = ... -local internalVersion = 69 +local internalVersion = 71 -- Lua APIs local insert = table.insert @@ -2874,22 +2874,16 @@ function Private.SetRegion(data, cloneId) local anim_cancelled = loginFinished and Private.CancelAnimation(region, true, true, true, true, true, true); regionTypes[regionType].modify(parent, region, data); - Private.regionPrototype.AddSetDurationInfo(region); + Private.regionPrototype.AddSetDurationInfo(region, data.uid) Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent, parent.regionType) data.animation = data.animation or {}; data.animation.start = data.animation.start or {type = "none"}; data.animation.main = data.animation.main or {type = "none"}; data.animation.finish = data.animation.finish or {type = "none"}; - if(Private.CanHaveDuration(data)) then - data.animation.start.duration_type = data.animation.start.duration_type or "seconds"; - data.animation.main.duration_type = data.animation.main.duration_type or "seconds"; - data.animation.finish.duration_type = data.animation.finish.duration_type or "seconds"; - else - data.animation.start.duration_type = "seconds"; - data.animation.main.duration_type = "seconds"; - data.animation.finish.duration_type = "seconds"; - end + data.animation.start.duration_type = data.animation.start.duration_type or "seconds" + data.animation.main.duration_type = data.animation.main.duration_type or "seconds" + data.animation.finish.duration_type = data.animation.finish.duration_type or "seconds" if(cloneId) then clonePool[regionType] = clonePool[regionType] or {}; @@ -3395,8 +3389,6 @@ local function wrapTriggerSystemFunction(functionName, mode) return func; end -Private.CanHaveDuration = wrapTriggerSystemFunction("CanHaveDuration", "firstValue"); -Private.CanHaveClones = wrapTriggerSystemFunction("CanHaveClones", "or"); Private.CanHaveTooltip = wrapTriggerSystemFunction("CanHaveTooltip", "or"); -- This has to be in WeakAuras for now, because GetNameAndIcon can be called from the options -- before the Options has access to Private @@ -3405,7 +3397,7 @@ Private.GetTriggerDescription = wrapTriggerSystemFunction("GetTriggerDescription local wrappedGetOverlayInfo = wrapTriggerSystemFunction("GetOverlayInfo", "table"); -Private.GetAdditionalProperties = function(data, triggernum, ...) +Private.GetAdditionalProperties = function(data) local additionalProperties = "" for i = 1, #data.triggers do local triggerSystem = GetTriggerSystem(data, i); @@ -3429,6 +3421,121 @@ Private.GetAdditionalProperties = function(data, triggernum, ...) return additionalProperties end +Private.GetProgressSources = function(data) + local values = {} + if Private.IsGroupType(data) then + return values + end + for i = 1, #data.triggers do + local triggerSystem = GetTriggerSystem(data, i); + if (triggerSystem) then + triggerSystem.GetProgressSources(data, i, values) + end + end + return values +end + +Private.GetProgressSourceFor = function(data, trigger, property) + local values = {} + local triggerSystem = GetTriggerSystem(data, trigger); + if (triggerSystem) then + triggerSystem.GetProgressSources(data, trigger, values) + for _, v in ipairs(values) do + if v.property == property then + return {trigger, v.type, v.property, v.total, v.inverse, v.paused, v.remaining} + end + end + end + return nil +end + +-- In the aura data we only store trigger + property +-- But for the region we don't want to gather necessary meta data all the time +-- So we collect that in region:modify + on creation of the conditions function +Private.AddProgressSourceMetaData = function(data, progressSource) + if not progressSource then + return {} + end + local trigger = progressSource[1] + local property = progressSource[2] + if trigger == -2 then + return {-2, "auto", ""} + elseif trigger == -1 then + return {-1, "auto", ""} + elseif trigger == 0 then + return {0, "manual", progressSource[3], progressSource[4]} + else + return Private.GetProgressSourceFor(data, trigger, property) + end +end + +-- ProgressSource values +-- For AceOptions to work correctly progress sources need to be comparable +-- via ==. We use a constants table so that identical tables use the same table +-- Additional while data.progressSource does contain additional data e.g. for manual progress +-- This is only for the progress source combobox, which only cares about the first or first two values +-- The greatness of the hacks knows no bounds +-- The constants table has weak keys +do + local function CompareProgressValueTables(a, b) + -- For auto/manual progreess, only compare a[] with b[1] + if a[1] == -1 or a[1] == 0 then + return a[1] == b[1] + end + -- Only care about trigger + property + return a[1] == b[1] and a[2] == b[2] + end + + local progressValueConstants = {} + setmetatable(progressValueConstants, {_mode = "v"}) + + function Private.GetProgressValueConstant(v) + if v == nil then + return v + end + + -- This uses pairs because there could be empty slots + for _, constant in pairs(progressValueConstants) do + if CompareProgressValueTables(v, constant) then + return constant + end + end + -- And this inserts into the first empty slot for the array + tinsert(progressValueConstants, v) + return v + end +end + +function Private.GetProgressSourcesForUi(data, subelement) + local values + + if subelement then + -- Sub elements Automatic means to use the main auras' progress + values = { + [{-2, ""}] = L["Automatic"] + } + else + values = { + [{-1, ""}] = L["Automatic"], + [{0, ""}] = L["Manual"], + } + end + + local triggerValues = Private.GetProgressSources(data) + for _, e in ipairs(triggerValues) do + if e.trigger and e.property then + values[{e.trigger, e.property}] = {L["Trigger %s"]:format(e.trigger), e.display} + end + end + + local result = {} + for k, v in pairs(values) do + result[Private.GetProgressValueConstant(k)] = v + end + + return result +end + function Private.GetOverlayInfo(data, triggernum) local overlayInfo; if (data.controlledChildren) then @@ -3926,59 +4033,65 @@ do end end +local function stopAutoHideTimer(id, triggernum, cloneId) + if(timers[id] and timers[id][triggernum] and timers[id][triggernum][cloneId]) then + local record = timers[id][triggernum][cloneId]; + if (record.handle) then + timer:CancelTimer(record.handle); + end + record.handle = nil; + record.expirationTime = nil; + record.state = nil + end +end + local function startStopTimers(id, cloneId, triggernum, state) - if (state.show) then - if (state.autoHide and state.duration and state.duration > 0 and not state.paused) then -- autohide, update timer - timers[id] = timers[id] or {}; - timers[id][triggernum] = timers[id][triggernum] or {}; - timers[id][triggernum][cloneId] = timers[id][triggernum][cloneId] or {}; - local record = timers[id][triggernum][cloneId]; - if (state.expirationTime == nil) then - state.expirationTime = GetTime() + state.duration; - end - if (record.expirationTime ~= state.expirationTime or record.state ~= state) then - if (record.handle ~= nil) then - timer:CancelTimer(record.handle); - end + if not state.show or not state.autoHide then + stopAutoHideTimer(id, triggernum, cloneId) + return + end - record.handle = timer:ScheduleTimer( - function() - if (state.show ~= false and state.show ~= nil) then - state.show = false; - state.changed = true; + -- state.autoHide can be a timer, or a boolean + -- if it's a bool, for backwards compability we look at paused + local expirationTime + if type(state.autoHide) == "boolean" then + if state.paused then + stopAutoHideTimer(id, triggernum, cloneId) + return + else + expirationTime = state.expirationTime + end + elseif type(state.autoHide) == "number" then + expirationTime = state.autoHide + end - -- if the trigger has updated then check to see if it is flagged for WatchedTrigger and send to queue if it is + timers[id] = timers[id] or {}; + timers[id][triggernum] = timers[id][triggernum] or {}; + timers[id][triggernum][cloneId] = timers[id][triggernum][cloneId] or {}; + local record = timers[id][triggernum][cloneId]; + if (record.expirationTime ~= expirationTime or record.state ~= state) then + if (record.handle ~= nil) then + timer:CancelTimer(record.handle); + end + + if expirationTime then + record.handle = timer:ScheduleTimer( + function() + if (state.show ~= false and state.show ~= nil) then + state.show = false; + state.changed = true; + + -- if the trigger has updated then check to see if it is flagged for WatchedTrigger and send to queue if it is if Private.watched_trigger_events[id] and Private.watched_trigger_events[id][triggernum] then Private.AddToWatchedTriggerDelay(id, triggernum) - end - - Private.UpdatedTriggerState(id); end - end, - state.expirationTime - GetTime()); - record.expirationTime = state.expirationTime; - record.state = state - end - else -- no auto hide, delete timer - if (timers[id] and timers[id][triggernum] and timers[id][triggernum][cloneId]) then - local record = timers[id][triggernum][cloneId]; - if (record.handle) then - timer:CancelTimer(record.handle); - end - record.handle = nil; - record.expirationTime = nil; - record.state = nil - end - end - else -- not shown - if(timers[id] and timers[id][triggernum] and timers[id][triggernum][cloneId]) then - local record = timers[id][triggernum][cloneId]; - if (record.handle) then - timer:CancelTimer(record.handle); - end - record.handle = nil; - record.expirationTime = nil; - record.state = nil + + Private.UpdatedTriggerState(id); + end + end, + expirationTime - GetTime()); + record.expirationTime = expirationTime; + record.state = state end end end @@ -4062,7 +4175,6 @@ local function ApplyStatesToRegions(id, activeTrigger, states) local applyChanges = not region.toShow or state.changed or region.state ~= state region.state = state region.states = region.states or {} - local needsTimerTick = false for triggernum = -1, triggerState[id].numTriggers do local triggerState if triggernum == activeTrigger then @@ -4078,11 +4190,8 @@ local function ApplyStatesToRegions(id, activeTrigger, states) end region.states[triggernum] = triggerState - needsTimerTick = needsTimerTick or (triggerState and triggerState.show and triggerState.progressType == "timed") end - region:SetTriggerProvidesTimer(needsTimerTick) - if (applyChanges) then ApplyStateToRegion(id, cloneId, region, parent); Private.RunConditions(region, data.uid, not state.show) @@ -4272,7 +4381,7 @@ function Private.RunCustomTextFunc(region, customFunc) return custom end -local function ReplaceValuePlaceHolders(textStr, region, customFunc, state, formatter) +local function ReplaceValuePlaceHolders(textStr, region, customFunc, state, formatter, trigger) local value; if string.sub(textStr, 1, 1) == "c" then local custom @@ -4297,7 +4406,7 @@ local function ReplaceValuePlaceHolders(textStr, region, customFunc, state, form end value = variable.get(state) if formatter then - value = formatter(value, state) + value = formatter(value, state, trigger) elseif variable.func then value = variable.func(value) end @@ -4431,12 +4540,12 @@ local function ValueForSymbol(symbol, region, customFunc, regionState, regionSta if regionStates[triggerNum][sym] then local value = regionStates[triggerNum][sym] if formatters[symbol] then - return tostring(formatters[symbol](value, regionStates[triggerNum]) or "") or "" + return tostring(formatters[symbol](value, regionStates[triggerNum], triggerNum) or "") or "" else return tostring(value) or "" end else - local value = ReplaceValuePlaceHolders(sym, region, customFunc, regionStates[triggerNum], formatters[symbol]); + local value = ReplaceValuePlaceHolders(sym, region, customFunc, regionStates[triggerNum], formatters[symbol], triggerNum); return value or "" end end @@ -4446,14 +4555,16 @@ local function ValueForSymbol(symbol, region, customFunc, regionState, regionSta if(useHiddenStates or regionState.show) then local value = regionState[symbol] if formatters[symbol] then - return tostring(formatters[symbol](value, regionState) or "") or "" + return tostring(formatters[symbol](value, regionState, triggerState[regionState.id].activeTrigger) or "") or "" else return tostring(value) or "" end end return "" else - local value = (useHiddenStates or regionState.show) and ReplaceValuePlaceHolders(symbol, region, customFunc, regionState, formatters[symbol]); + local activeTrigger = triggerState[regionState.id].activeTrigger + local value = (useHiddenStates or regionState.show) + and ReplaceValuePlaceHolders(symbol, region, customFunc, regionState, formatters[symbol], activeTrigger) return value or "" end end @@ -4589,7 +4700,7 @@ function Private.ParseTextStr(textStr, symbolCallback) end end -function Private.CreateFormatters(input, getter, withoutColor) +function Private.CreateFormatters(input, getter, withoutColor, data) local seenSymbols = {} local formatters = {} @@ -4603,7 +4714,7 @@ function Private.CreateFormatters(input, getter, withoutColor) local default = (sym == "p" or sym == "t") and "timed" or "none" local selectedFormat = getter(symbol .. "_format", default) if (Private.format_types[selectedFormat]) then - formatters[symbol] = Private.format_types[selectedFormat].CreateFormatter(symbol, getter, withoutColor) + formatters[symbol] = Private.format_types[selectedFormat].CreateFormatter(symbol, getter, withoutColor, data) end end end @@ -5492,8 +5603,8 @@ end function Private.IconSources(data) local values = { - [-1] = L["Dynamic Information"], - [0] = L["Fallback Icon"], + [-1] = L["Automatic"], + [0] = L["Manual Icon"], } for i = 1, #data.triggers do diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index cae4661..f6ba80b 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -990,9 +990,6 @@ local methods = { else OptionsPrivate.Private.GetTriggerDescription(data, -1, namestable) end - if(OptionsPrivate.Private.CanHaveClones(data)) then - tinsert(namestable, {" ", "|cFF00FF00"..L["Auto-cloning enabled"]}) - end local hasDescription = data.desc and data.desc ~= ""; local hasUrl = data.url and data.url ~= ""; diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua index 59491e9..251b8d2 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasTwoColumnDropDown.lua @@ -39,16 +39,18 @@ local methods = { if mode == "one" then self.firstDropdown.frame:Show() self.secondDropDown.frame:Hide() - self.firstDropdown.frame:SetAllPoints(self.frame) + self.firstDropdown.frame:ClearAllPoints() + self.firstDropdown.frame:SetPoint("TOPLEFT", self.frame) + self.firstDropdown.frame:SetPoint("TOPRIGHT", self.frame) else local halfWidth = self.frame:GetWidth() / 2 self.firstDropdown.frame:Show() self.secondDropDown.frame:Show() self.firstDropdown.frame:ClearAllPoints() self.firstDropdown.frame:SetPoint("TOPLEFT", self.frame) - self.firstDropdown.frame:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMLEFT", halfWidth, 0) + self.firstDropdown.frame:SetPoint("TOPRIGHT", self.frame, "TOPLEFT", halfWidth, 0) self.secondDropDown.frame:SetPoint("TOPLEFT", self.frame, halfWidth, 0) - self.secondDropDown.frame:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT") + self.secondDropDown.frame:SetPoint("TOPRIGHT", self.frame, "TOPRIGHT") end end, ["OnAcquire"] = function(widget) @@ -154,8 +156,11 @@ local methods = { self.firstDropdown = nil self.secondDropDown = nil end, - ["SetLabel"] = function(self, ...) - self.firstDropdown:SetLabel(...) + ["SetLabel"] = function(self, v) + if v == "" then + v = " " + end + self.firstDropdown:SetLabel(v) end, ["SetValue"] = function(self, value) for displayName, treeValue in pairs(self.userdata.tree) do diff --git a/WeakAurasOptions/AnimationOptions.lua b/WeakAurasOptions/AnimationOptions.lua index bc76cbf..20c7b2c 100644 --- a/WeakAurasOptions/AnimationOptions.lua +++ b/WeakAurasOptions/AnimationOptions.lua @@ -143,18 +143,6 @@ function OptionsPrivate.GetAnimationOptions(data) values = function() return filterAnimPresetTypes(anim_start_preset_types, id) end, hidden = function() return data.animation.start.type ~= "preset" end }, - start_duration_type_no_choice = { - type = "select", - width = WeakAuras.halfWidth, - name = L["Time in"], - order = 33, - values = duration_types_no_choice, - disabled = true, - hidden = function() - return data.animation.start.type ~= "custom" or OptionsPrivate.Private.CanHaveDuration(data) - end, - get = function() return "seconds" end - }, start_duration_type = { type = "select", width = WeakAuras.halfWidth, @@ -162,7 +150,7 @@ function OptionsPrivate.GetAnimationOptions(data) order = 33, values = duration_types, hidden = function() - return data.animation.start.type ~= "custom" or not OptionsPrivate.Private.CanHaveDuration(data) + return data.animation.start.type ~= "custom" end }, start_duration = { @@ -418,18 +406,6 @@ function OptionsPrivate.GetAnimationOptions(data) values = function() return filterAnimPresetTypes(anim_main_preset_types, id) end, hidden = function() return data.animation.main.type ~= "preset" end }, - main_duration_type_no_choice = { - type = "select", - width = WeakAuras.halfWidth, - name = L["Time in"], - order = 53, - values = duration_types_no_choice, - disabled = true, - hidden = function() - return data.animation.main.type ~= "custom" or OptionsPrivate.Private.CanHaveDuration(data) - end, - get = function() return "seconds" end - }, main_duration_type = { type = "select", width = WeakAuras.halfWidth, @@ -437,7 +413,7 @@ function OptionsPrivate.GetAnimationOptions(data) order = 53, values = duration_types, hidden = function() - return data.animation.main.type ~= "custom" or not OptionsPrivate.Private.CanHaveDuration(data) + return data.animation.main.type ~= "custom" end }, main_duration = { diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index 4b2af34..cb59f9d 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -1038,6 +1038,153 @@ local function CreateExecuteAll(subOption) end end +local function ProgressOptions(data) + local order = 1 + local options = { + __title = L["Progress Settings"], + __order = 98, + } + + options.progressSource = { + type = "select", + width = WeakAuras.doubleWidth, + name = L["Progress Source"], + order = order, + control = "WeakAurasTwoColumnDropdown", + values = OptionsPrivate.Private.GetProgressSourcesForUi(data), + get = function(info) + return OptionsPrivate.Private.GetProgressValueConstant(data.progressSource) + end, + set = function(info, value) + if value then + data.progressSource = data.progressSource or {} + -- Copy only trigger + property + data.progressSource[1] = value[1] + data.progressSource[2] = value[2] + else + data.progressSource = nil + end + WeakAuras.Add(data) + end + } + + options.progressSourceWarning = { + type = "description", + width = WeakAuras.doubleWidth, + name = L["Note: This progress source does not provide a total value/duration. A total value/duration must be set via \"Set Maximum Progress\""], + order = order + 0.5, + hidden = function() + local progressSource = OptionsPrivate.Private.AddProgressSourceMetaData(data, data.progressSource) + -- Auto progress, Manual Progress or the progress source has a total property + if not progressSource or progressSource[2] == "auto" or progressSource[1] == 0 or progressSource[4] ~= nil then + return true + end + return false + end + } + + local function hiddenManual() + if data.progressSource and data.progressSource[1] == 0 then + return false + end + return true + end + + options.progressSourceManualValue = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Value"], + order = order + 0.7, + min = 0, + softMax = 100, + bigStep = 1, + hidden = hiddenManual, + get = function(info) + return data.progressSource and data.progressSource[3] or 0 + end, + set = function(info, value) + data.progressSource = data.progressSource or {} + data.progressSource[3] = value + WeakAuras.Add(data) + end + } + + options.progressSourceManualTotal = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Total"], + order = order + 0.8, + min = 0, + softMax = 100, + bigStep = 1, + hidden = hiddenManual, + get = function(info) + return data.progressSource and data.progressSource[4] or 100 + end, + set = function(info, value) + data.progressSource = data.progressSource or {} + data.progressSource[4] = value + WeakAuras.Add(data) + end + } + + options.useAdjustededMin = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Set Minimum Progress"], + desc = L["Values/Remaining Time below this value are displayed as zero progress."], + order = order + 1 + }; + + options.adjustedMin = { + type = "input", + validate = WeakAuras.ValidateNumericOrPercent, + width = WeakAuras.normalWidth, + order = order + 2, + name = L["Minimum"], + hidden = function() return not data.useAdjustededMin end, + desc = L["Enter static or relative values with %"] + }; + + options.useAdjustedMinSpacer = { + type = "description", + width = WeakAuras.normalWidth, + name = "", + order = order + 3, + hidden = function() return not (not data.useAdjustededMin and data.useAdjustededMax) end, + } + + options.useAdjustededMax = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Set Maximum Progress"], + desc = L["Values/Remaining Time above this value are displayed as full progress."], + order = order + 4 + } + + options.adjustedMax = { + type = "input", + width = WeakAuras.normalWidth, + validate = WeakAuras.ValidateNumericOrPercent, + order = order + 5, + name = L["Maximum"], + hidden = function() return not data.useAdjustededMax end, + desc = L["Enter static or relative values with %"] + } + + options.useAdjustedMaxSpacer = { + type = "description", + width = WeakAuras.normalWidth, + name = "", + order = order + 6, + hidden = function() return not (data.useAdjustededMin and not data.useAdjustededMax) end, + } + + return options +end + local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, group) local metaOrder = 99 local function IsParentDynamicGroup() @@ -1617,6 +1764,7 @@ OptionsPrivate.commonOptions.CreateSetAll = CreateSetAll OptionsPrivate.commonOptions.CreateExecuteAll = CreateExecuteAll OptionsPrivate.commonOptions.PositionOptions = PositionOptions +OptionsPrivate.commonOptions.ProgressOptions = ProgressOptions OptionsPrivate.commonOptions.BorderOptions = BorderOptions OptionsPrivate.commonOptions.AddCodeOption = AddCodeOption diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 2e9af6f..200090c 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -71,6 +71,17 @@ local function compareValues(a, b, propertytype) and a[2] == b[2] and a[3] == b[3] and a[4] == b[4]; + elseif propertytype == "progressSource" then + if type(a) == "table" and type(b) == "table" then + local triggerA, propertyA, triggerB, propertyB = a[1], a[2], b[1], b[2] + if triggerA ~= triggerB or propertyA ~= propertyB then + return false + end + if triggerA == 0 then + return a[3] == b[3] and a[4] == b[4] + end + return true + end end return a == b; end @@ -139,15 +150,36 @@ local function descIfSubset(data, reference, totalAuraCount) return ""; end -local function descIfNoValue(data, object, variable, type, values) +local function descIfNoValue(data, object, variable, propertyType, values) if (data.controlledChildren) then if (object["same" .. variable] == false) then local desc = ""; for id, reference in pairs(object.references) do - if (type == "list" and values) then + if propertyType == "list" and values then desc = desc .."|cFFE0E000".. id .. ": |r" .. (values[reference[variable]] or "") .. "\n"; + elseif propertyType == "progressSource" then + desc = desc .."|cFFE0E000".. id .. ": |r" + local progressSource = reference[variable] + if type(progressSource) == "table" then + local trigger = progressSource[1] + if trigger == 0 then + desc = desc .. L["Manual with %i/%i"]:format(progressSource[3] or 0, progressSource[4] or 100) + else + local p = OptionsPrivate.Private.GetProgressValueConstant(progressSource) + local description = values[p] or "" + if type(description) == "string" then + desc = desc .. description + elseif type(description) == "table" + and type(description[1]) == "string" + and type(description[2]) == "string" + then + desc = desc .. description[1] .. " " .. description[2] + end + end + end + desc = desc .."\n" else - desc = desc .."|cFFE0E000".. id .. ": |r" .. (valueToString(reference[variable], type) or "") .. "\n"; + desc = desc .."|cFFE0E000".. id .. ": |r" .. (valueToString(reference[variable], propertyType) or "") .. "\n"; end end return desc; @@ -298,6 +330,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA order = order + 1; local setValue; + local setValueTable local setValueColor; local setValueComplex; local setValueColorComplex; @@ -313,6 +346,17 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA conditions[i].changes[j].value = v; WeakAuras.ClearAndUpdateOptions(data.id) end + setValueTable = function(info, v) + for id, reference in pairs(conditions[i].changes[j].references) do + local auraData = WeakAuras.GetData(id) + local conditionIndex = conditions[i].check.references[id].conditionIndex + auraData[conditionVariable][conditionIndex].changes[reference.changeIndex].value = CopyTable(v) + WeakAuras.Add(auraData) + OptionsPrivate.ClearOptions(auraData.id) + end + conditions[i].changes[j].value = CopyTable(v) + WeakAuras.ClearAndUpdateOptions(data.id) + end setValueColor = function(info, r, g, b, a) for id, reference in pairs(conditions[i].changes[j].references) do local auraData = WeakAuras.GetData(id); @@ -332,7 +376,11 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA conditions[i].changes[j].value[4] = a; WeakAuras.ClearAndUpdateOptions(data.id) end - + setValueTable = function(info, v) + conditions[i].changes[j].value = CopyTable(v) + WeakAuras.Add(data) + WeakAuras.ClearAndUpdateOptions(data.id) + end setValueComplex = function(property) return function(info, v) for id, reference in pairs(conditions[i].changes[j].references) do @@ -531,21 +579,92 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA set = setValueColor } order = order + 1; - elseif (propertyType == "list") then + elseif (propertyType == "list" or property == "progressSource") then local values = property and allProperties.propertyMap[property] and allProperties.propertyMap[property].values; args["condition" .. i .. "value" .. j] = { type = "select", width = WeakAuras.normalWidth, values = values, - name = blueIfNoValue(data, conditions[i].changes[j], "value", L["Differences"]), - desc = descIfNoValue(data, conditions[i].changes[j], "value", propertyType, values), + name = blueIfNoValue(data, conditions[i].changes[j], "value", L["Differences"], ""), + desc = descIfNoValue(data, conditions[i].changes[j], "value", propertyType, values), order = order, get = function() return conditions[i].changes[j].value; end, - set = setValue + set = setValue, } - order = order + 1; + order = order + 1 + + if propertyType == "progressSource" then + args["condition" .. i .. "value" .. j].control = "WeakAurasTwoColumnDropdown" + args["condition" .. i .. "value" .. j].set = setValueTable + args["condition" .. i .. "value" .. j].get = function() + local v = conditions[i].changes[j].value + return OptionsPrivate.Private.GetProgressValueConstant(v) + end + + args["condition" .. i .. "progressSourceWarning" .. j] = { + type = "description", + width = WeakAuras.doubleWidth, + name = L["Note: This progress source does not provide a total value/duration. A total value/duration must be set via \"Set Maximum Progress\""], + order = order, + hidden = function() + local v = conditions[i].changes[j].value + local progressSource = OptionsPrivate.Private.AddProgressSourceMetaData(data, v) + -- Auto progress, Manual Progress or the progress source has a total property + if progressSource[2] == "auto" or progressSource[1] == 0 or progressSource[4] ~= nil then + return true + end + return false + end + } + order = order + 1 + + local function hiddenManual() + local v = conditions[i].changes[j].value + local progressSource = OptionsPrivate.Private.AddProgressSourceMetaData(data, v) + if progressSource[1] == 0 then + return false + end + return true + end + + args["condition" .. i .. "progressSoruceManualValue" .. j] = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Value"], + order = order, + min = 0, + softMax = 100, + bigStep = 1, + hidden = hiddenManual, + get = function() + local v = conditions[i].changes[j].value + return v and type(v[3]) == "number" and v[3] or 0 + end, + set = setValueComplex(3) + } + order = order + 1 + + args["condition" .. i .. "progressSoruceManualTotal" .. j] = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Total"], + order = order, + min = 0, + softMax = 100, + bigStep = 1, + hidden = hiddenManual, + get = function() + local v = conditions[i].changes[j].value + return v and type(v[4]) == "number" and v[4] or 100 + end, + set = setValueComplex(4) + } + order = order + 1 + end elseif (propertyType == "sound") then args["condition" .. i .. "value" .. j .. "sound_type"] = { type = "select", @@ -2455,7 +2574,7 @@ local function buildAllPotentialProperties(data, category) allProperties.propertyMap[k].type = "incompatible"; end - if (allProperties.propertyMap[k].type == "list") then + if (allProperties.propertyMap[k].type == "list" or allProperties.propertyMap[k].type == "progressSource" ) then -- Merge value lists for key, value in pairs(v.values) do if (allProperties.propertyMap[k].values[key] == nil) then diff --git a/WeakAurasOptions/GenericTrigger.lua b/WeakAurasOptions/GenericTrigger.lua index 883f924..91a6882 100644 --- a/WeakAurasOptions/GenericTrigger.lua +++ b/WeakAurasOptions/GenericTrigger.lua @@ -317,6 +317,10 @@ local function GetCustomTriggerOptions(data, triggernum) test = "function", events = "table", values = "table", + total = "string", + inverse = "string", + paused = "string", + remaining = "string", } local function validateCustomVariables(variables) diff --git a/WeakAurasOptions/RegionOptions/AuraBar.lua b/WeakAurasOptions/RegionOptions/AuraBar.lua index 9d9bdb0..0929ac0 100644 --- a/WeakAurasOptions/RegionOptions/AuraBar.lua +++ b/WeakAurasOptions/RegionOptions/AuraBar.lua @@ -91,21 +91,21 @@ local function createOptions(id, data) width = WeakAuras.normalWidth, name = L["Bar Color"], hasAlpha = true, - order = 39.1 + order = 39.3 }, backgroundColor = { type = "color", width = WeakAuras.normalWidth, name = L["Background Color"], hasAlpha = true, - order = 39.2 + order = 39.5 }, alpha = { type = "range", control = "WeakAurasSpinBox", width = WeakAuras.normalWidth, name = L["Bar Alpha"], - order = 39.3, + order = 39.6, min = 0, max = 1, bigStep = 0.01, @@ -157,7 +157,7 @@ local function createOptions(id, data) displayIcon = { type = "input", width = WeakAuras.normalWidth - 0.15, - name = L["Fallback"], + name = L["Manual"], disabled = function() return not data.icon end, order = 40.5, get = function() @@ -385,8 +385,6 @@ local function createOptions(id, data) }, }; - options = OptionsPrivate.Private.regionPrototype.AddAdjustedDurationOptions(options, data, 36.5); - local overlayInfo = OptionsPrivate.Private.GetOverlayInfo(data); if (overlayInfo and next(overlayInfo)) then options["overlayheader"] = { @@ -450,6 +448,7 @@ local function createOptions(id, data) return { aurabar = options, + progressOptions = OptionsPrivate.commonOptions.ProgressOptions(data), position = OptionsPrivate.commonOptions.PositionOptions(id, data), }; end diff --git a/WeakAurasOptions/RegionOptions/Icon.lua b/WeakAurasOptions/RegionOptions/Icon.lua index ced05d2..5708a01 100644 --- a/WeakAurasOptions/RegionOptions/Icon.lua +++ b/WeakAurasOptions/RegionOptions/Icon.lua @@ -36,7 +36,7 @@ local function createOptions(id, data) displayIcon = { type = "input", width = WeakAuras.normalWidth - 0.15, - name = L["Fallback Icon"], + name = L["Manual Icon"], order = 4, get = function() return data.displayIcon and tostring(data.displayIcon) or ""; @@ -230,8 +230,7 @@ local function createOptions(id, data) name = L["Enable Swipe"], order = 11.1, desc = L["Enable the \"Swipe\" radial overlay"], - disabled = function() return not OptionsPrivate.Private.CanHaveDuration(data); end, - get = function() return OptionsPrivate.Private.CanHaveDuration(data) and data.cooldown; end + get = function() return data.cooldown; end }, inverse = { type = "toggle", @@ -239,8 +238,7 @@ local function createOptions(id, data) name = L["Inverse"], order = 11.2, desc = L["Invert the direction of progress"], - disabled = function() return not (OptionsPrivate.Private.CanHaveDuration(data) and data.cooldown); end, - get = function() return data.inverse and OptionsPrivate.Private.CanHaveDuration(data) and data.cooldown; end, + get = function() return data.inverse and data.cooldown; end, hidden = function() return not data.cooldown end }, cooldownEdge = { @@ -249,7 +247,6 @@ local function createOptions(id, data) name = L["Show \"Edge\""], order = 11.4, desc = "|TInterface\\AddOns\\WeakAuras\\Media\\Textures\\edge-example:30|t\n"..L["Enable \"Edge\" part of the overlay"], - disabled = function() return not OptionsPrivate.Private.CanHaveDuration(data) end, hidden = function() return not data.cooldown end, }, endHeader = { @@ -276,6 +273,7 @@ local function createOptions(id, data) return { icon = options, + progressOptions = OptionsPrivate.commonOptions.ProgressOptions(data), position = OptionsPrivate.commonOptions.PositionOptions(id, data), }; end diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index 442a456..48f1302 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -277,18 +277,12 @@ local function createOptions(id, data) hidden = function() return not data.slanted or data.orientation == "CLOCKWISE" or data.orientation == "ANTICLOCKWISE" end, values = OptionsPrivate.Private.slant_mode }, - spacer = { - type = "header", - name = "", - order = 56 - }, endHeader = { type = "header", order = 100, name = "", }, }; - options = OptionsPrivate.Private.regionPrototype.AddAdjustedDurationOptions(options, data, 57); local overlayInfo = OptionsPrivate.Private.GetOverlayInfo(data); if (overlayInfo and next(overlayInfo)) then @@ -332,6 +326,7 @@ local function createOptions(id, data) return { progresstexture = options, + progressOptions = OptionsPrivate.commonOptions.ProgressOptions(data), position = OptionsPrivate.commonOptions.PositionOptions(id, data), }; end diff --git a/WeakAurasOptions/RegionOptions/StopMotion.lua b/WeakAurasOptions/RegionOptions/StopMotion.lua index b232cf3..682d709 100644 --- a/WeakAurasOptions/RegionOptions/StopMotion.lua +++ b/WeakAurasOptions/RegionOptions/StopMotion.lua @@ -288,7 +288,7 @@ local function createOptions(id, data) name = L["Animation Start"], min = 0, max = 1, - --bigStep = 0.01, + bigStep = 0.01, order = 13, isPercent = true }, @@ -299,7 +299,7 @@ local function createOptions(id, data) name = L["Animation End"], min = 0, max = 1, - --bigStep = 0.01, + bigStep = 0.01, order = 14, isPercent = true }, @@ -534,17 +534,11 @@ local function createOptions(id, data) } }; - if OptionsPrivate.commonOptions then - return { - stopmotion = options, - position = OptionsPrivate.commonOptions.PositionOptions(id, data, 2), - }; - else - return { - stopmotion = options, - position = WeakAuras.PositionOptions(id, data, 2), - }; - end + return { + stopmotion = options, + progressOptions = OptionsPrivate.commonOptions.ProgressOptions(data), + position = OptionsPrivate.commonOptions.PositionOptions(id, data, 2), + } end local function createThumbnail() diff --git a/WeakAurasOptions/SubRegionOptions/Tick.lua b/WeakAurasOptions/SubRegionOptions/Tick.lua index fd88de7..49fb190 100644 --- a/WeakAurasOptions/SubRegionOptions/Tick.lua +++ b/WeakAurasOptions/SubRegionOptions/Tick.lua @@ -23,31 +23,51 @@ local function createOptions(parentData, data, index, subIndex) order = 2, hasAlpha = true, }, - tick_placement_mode = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Tick Mode"], - order = 3, - values = OptionsPrivate.Private.tick_placement_modes, - }, - tick_placement = { - type = "input", - width = WeakAuras.normalWidth, - name = L["Tick Placement"], - order = 4, - validate = WeakAuras.ValidateNumeric, - desc = L["Enter in a value for the tick's placement."], - }, + tick_thickness = { type = "range", control = "WeakAurasSpinBox", width = WeakAuras.normalWidth, name = L["Thickness"], - order = 5, + order = 2.5, min = 0, softMax = 20, step = 1, }, + tick_progress_source_space = { + type = "description", + name = "", + order = 3, + width = WeakAuras.normalWidth, + }, + + tick_placement_mode = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Tick Mode"], + order = 3.1, + values = OptionsPrivate.Private.tick_placement_modes, + }, + + tick_progress_source_space_2 = { + type = "description", + name = "", + order = 3.2, + width = WeakAuras.normalWidth, + }, + + tick_add = { + type = "execute", + name = L["Add"], + order = 5, + width = WeakAuras.normalWidth, + func = function() + tinsert(data.tick_placements, 0) + WeakAuras.Add(parentData) + WeakAuras.ClearAndUpdateOptions(parentData.id) + end + }, + tick_extrasDescription = { type = "execute", control = "WeakAurasExpandSmall", @@ -80,7 +100,7 @@ local function createOptions(parentData, data, index, subIndex) return description end, width = WeakAuras.doubleWidth, - order = 6, + order = 7, func = function(info, button) local collapsed = OptionsPrivate.IsCollapsed("subtext", "subtext", "tickextras" .. index, true) OptionsPrivate.SetCollapsed("subtext", "subtext", "tickextras" .. index, not collapsed) @@ -99,7 +119,7 @@ local function createOptions(parentData, data, index, subIndex) type = "toggle", width = WeakAuras.normalWidth, name = L["Automatic length"], - order = 7, + order = 8, desc = L["Matches the height setting of a horizontal bar or width for a vertical bar."], hidden = hiddentickextras, }, @@ -108,7 +128,7 @@ local function createOptions(parentData, data, index, subIndex) control = "WeakAurasSpinBox", width = WeakAuras.normalWidth, name = L["Length"], - order = 8, + order = 9, min = 0, softMax = 50, step = 1, @@ -119,14 +139,14 @@ local function createOptions(parentData, data, index, subIndex) type = "toggle", width = WeakAuras.normalWidth, name = L["Use Texture"], - order = 9, + order = 10, hidden = hiddentickextras, }, tick_blend_mode = { type = "select", width = WeakAuras.normalWidth, name = L["Blend Mode"], - order = 10, + order = 11, values = OptionsPrivate.Private.blend_types, disabled = function() return not data.use_texture end, hidden = hiddentickextras, @@ -134,7 +154,7 @@ local function createOptions(parentData, data, index, subIndex) tick_texture = { type = "input", name = L["Texture"], - order = 11, + order = 12, width = WeakAuras.doubleWidth - 0.15, disabled = function() return not data.use_texture end, hidden = hiddentickextras, @@ -143,7 +163,7 @@ local function createOptions(parentData, data, index, subIndex) type = "execute", name = L["Choose"], width = 0.15, - order = 11.5, + order = 12.5, func = function() OptionsPrivate.OpenTexturePicker(parentData, { "subRegions", index @@ -164,7 +184,7 @@ local function createOptions(parentData, data, index, subIndex) type = "toggle", width = WeakAuras.doubleWidth, name = L["Desaturate"], - order = 12, + order = 13, hidden = hiddentickextras, }, tick_rotation = { @@ -174,6 +194,7 @@ local function createOptions(parentData, data, index, subIndex) name = L["Rotation"], min = 0, max = 360, + step = 1, order = 14, hidden = hiddentickextras, }, @@ -193,6 +214,7 @@ local function createOptions(parentData, data, index, subIndex) order = 16, softMin = -200, softMax = 200, + step = 1, hidden = hiddentickextras, }, tick_yOffset = { @@ -203,6 +225,7 @@ local function createOptions(parentData, data, index, subIndex) order = 17, softMin = -200, softMax = 200, + step = 1, hidden = hiddentickextras, }, @@ -218,6 +241,72 @@ local function createOptions(parentData, data, index, subIndex) } } + if data then + for i in ipairs(data.tick_placements) do + options["tick_progress_source" .. i] = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Progress Source"], + order = 4 + i / 100, + control = "WeakAurasTwoColumnDropdown", + values = OptionsPrivate.Private.GetProgressSourcesForUi(parentData, true), + get = function(info) + return OptionsPrivate.Private.GetProgressValueConstant(data.progressSources[i] or {-2, ""}) + end, + set = function(info, value) + if value then + data.progressSources = data.progressSources or {} + data.progressSources[i] = data.progressSources[i] or {} + -- Copy only trigger + property + data.progressSources[i][1] = value[1] + data.progressSources[i][2] = value[2] + else + data.progressSources[i] = nil + end + WeakAuras.Add(parentData) + end, + hidden = function() + return not(data.tick_placement_mode == "ValueOffset") + end + } + + options["tick_placement" .. i] = { + type = "input", + width = WeakAuras.normalWidth - 0.15, + name = L["Tick Placement"], + order = 4 + i / 100 + 0.001, + validate = WeakAuras.ValidateNumeric, + desc = L["Enter in a value for the tick's placement."], + get = function(info) + return data.tick_placements[i] or "" + end, + set = function(info, value) + data.tick_placements[i] = value + WeakAuras.Add(parentData) + end + } + + options["tick_placement_delete" .. i] = { + type = "execute", + width = 0.15, + name = L["Delete"], + order = 4 + i / 100 + 0.002, + func = function() + tremove(data.tick_placements, i) + WeakAuras.Add(parentData) + WeakAuras.ClearAndUpdateOptions(parentData.id) + end, + image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\delete", + imageWidth = 24, + imageHeight = 24, + control = "WeakAurasIcon", + disabled = function() + return #data.tick_placements < 2 + end + } + end + end + OptionsPrivate.AddUpDownDeleteDuplicate(options, parentData, index, "subtick") return options From 674ea9fe1e683280fb92a6f7817d592662a64c0c Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Wed, 22 Jan 2025 18:23:23 +0100 Subject: [PATCH 066/153] from retail --- WeakAuras/Conditions.lua | 4 +- WeakAuras/SubRegionTypes/Tick.lua | 36 ++++++++++++++++++ WeakAurasOptions/ConditionOptions.lua | 31 ++++++++++++++- .../OptionsFrames/TexturePicker.lua | 38 ++++++++++--------- WeakAurasOptions/RegionOptions/AuraBar.lua | 7 +++- .../RegionOptions/ProgressTexture.lua | 14 ++++++- WeakAurasOptions/RegionOptions/StopMotion.lua | 25 ++++++++---- WeakAurasOptions/RegionOptions/Texture.lua | 7 +++- WeakAurasOptions/SubRegionOptions/Tick.lua | 9 +++-- WeakAurasOptions/WeakAurasOptions.lua | 4 +- 10 files changed, 137 insertions(+), 38 deletions(-) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index 627fcf3..f1298f1 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -91,7 +91,7 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path return tostring(value) end return "nil" - elseif (vType == "string") then + elseif (vType == "string" or vType == "texture") then if type(value) == "string" then return string.format("%s", Private.QuotedString(value)) end @@ -154,7 +154,7 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path end local function formatValueForCall(type, property) - if type == "bool" or type == "number" or type == "list" or type == "icon" or type == "string" + if type == "bool" or type == "number" or type == "list" or type == "icon" or type == "string" or type == "texture" or type == "progressSource" then return "propertyChanges['" .. property .. "']"; diff --git a/WeakAuras/SubRegionTypes/Tick.lua b/WeakAuras/SubRegionTypes/Tick.lua index 04c9064..4db41ea 100644 --- a/WeakAuras/SubRegionTypes/Tick.lua +++ b/WeakAuras/SubRegionTypes/Tick.lua @@ -84,6 +84,17 @@ local properties = { type = "bool", default = true, }, + tick_use_texture = { + display = L["Use Texture"], + setter = "SetUseTexture", + type = "bool", + default = true, + }, + tick_texture = { + display = L["Texture"], + setter = "SetTexture", + type = "texture" + } } local function GetProperties(parentData, data) @@ -408,6 +419,31 @@ local funcs = { end end end, + UpdateTexture = function(self) + if self.use_texture then + for _, tick in ipairs(self.ticks) do + tick:SetTexture(tick, self.tick_texture) + end + else + for _, tick in ipairs(self.ticks) do + tick:SetTexture(self.tick_color[1], self.tick_color[2], self.tick_color[3], self.tick_color[4]) + end + end + end, + SetTexture = function(self, texture) + if self.tick_texture == texture then + return + end + self.tick_texture = texture + self:UpdateTexture() + end, + SetUseTexture = function(self, use) + if self.use_texture == use then + return + end + self.use_texture = use + self:UpdateTexture() + end } local function modify(parent, region, parentData, data, first) diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 200090c..08b8b4b 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -514,7 +514,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA args["condition" .. i .. "value" .. j].validate = WeakAuras.ValidateNumeric; end end - elseif (propertyType == "string") then + elseif (propertyType == "string" or propertyType == "texture") then args["condition" .. i .. "value" .. j] = { type = "input", width = WeakAuras.normalWidth, @@ -527,6 +527,35 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA set = setValue } order = order + 1; + if propertyType == "texture" then + args["condition" .. i .. "value" .. j].width = WeakAuras.normalWidth - 0.15 + args["condition" .. i .. "value_browse" .. j] = { + type = "execute", + name = L["Choose"], + width = 0.15, + order = order, + func = function() + if data.controlledChildren then + local paths = {} + for id, reference in pairs(conditions[i].changes[j].references) do + paths[id] = {"conditions", conditions[i].check.references[id].conditionIndex, "changes", reference.changeIndex} + end + OptionsPrivate.OpenTexturePicker(data, paths, + {texture = "value"}, + OptionsPrivate.Private.texture_types) + else + OptionsPrivate.OpenTexturePicker(data, {[data.id] = { "conditions", i, "changes", j } }, + {texture = "value"}, + OptionsPrivate.Private.texture_types) + end + end, + imageWidth = 24, + imageHeight = 24, + control = "WeakAurasIcon", + image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\browse", + } + order = order + 1; + end elseif (propertyType == "icon") then args["condition" .. i .. "value" .. j] = { type = "input", diff --git a/WeakAurasOptions/OptionsFrames/TexturePicker.lua b/WeakAurasOptions/OptionsFrames/TexturePicker.lua index 8860ae5..7cd44b7 100644 --- a/WeakAurasOptions/OptionsFrames/TexturePicker.lua +++ b/WeakAurasOptions/OptionsFrames/TexturePicker.lua @@ -36,7 +36,7 @@ local function CompareValues(a, b) end end -local function GetAll(baseObject, path, property, default) +local function GetAll(baseObject, paths, property, default) local valueFromPath = OptionsPrivate.Private.ValueFromPath if not property then return default @@ -45,7 +45,7 @@ local function GetAll(baseObject, path, property, default) local result = default local first = true for child in OptionsPrivate.Private.TraverseLeafsOrAura(baseObject) do - local childObject = valueFromPath(child, path) + local childObject = valueFromPath(child, paths[child.id]) if childObject and childObject[property] then if first then result = childObject[property] @@ -60,10 +60,10 @@ local function GetAll(baseObject, path, property, default) return result end -local function SetAll(baseObject, path, property, value) +local function SetAll(baseObject, paths, property, value) local valueFromPath = OptionsPrivate.Private.ValueFromPath for child in OptionsPrivate.Private.TraverseLeafsOrAura(baseObject) do - local object = valueFromPath(child, path) + local object = valueFromPath(child, paths[child.id]) if object then object[property] = value WeakAuras.Add(child) @@ -163,17 +163,17 @@ local function ConstructTexturePicker(frame) wipe(group.selectedTextures) group.selectedTextures[texturePath] = true - SetAll(self.baseObject, self.path, self.properties.texture, texturePath) + SetAll(self.baseObject, self.paths, self.properties.texture, texturePath) group:UpdateList(); local status = dropdown.status or dropdown.localstatus dropdown.dropdown:SetText(dropdown.list[status.selected]); end - function group.Open(self, baseObject, path, properties, textures, SetTextureFunc) + function group.Open(self, baseObject, paths, properties, textures, SetTextureFunc) local valueFromPath = OptionsPrivate.Private.ValueFromPath self.baseObject = baseObject - self.path = path + self.paths = paths self.properties = properties self.textures = textures; self.SetTextureFunc = SetTextureFunc @@ -181,30 +181,32 @@ local function ConstructTexturePicker(frame) self.selectedTextures = {} for child in OptionsPrivate.Private.TraverseLeafsOrAura(baseObject) do - local object = valueFromPath(child, path) + local object = valueFromPath(child, paths[child.id]) if object and object[properties.texture] then - self.givenPath[child.id] = object[properties.texture] - self.selectedTextures[object[properties.texture]] = true + local texture = object[properties.texture] + self.givenPath[child.id] = texture + self.selectedTextures[texture] = true + else + self.givenPath[child.id] = "" end end - local colorAll = GetAll(baseObject, path, properties.color, {1, 1, 1, 1}); + local colorAll = GetAll(baseObject, paths, properties.color, {1, 1, 1, 1}); self.textureData = { r = colorAll[1] or 1, g = colorAll[2] or 1, b = colorAll[3] or 1, a = colorAll[4] or 1, - rotate = GetAll(baseObject, path, properties.rotate, true), - discrete_rotation = GetAll(baseObject, path, properties.discrete_rotation, 0), - rotation = GetAll(baseObject, path, properties.rotation, 0), - mirror = GetAll(baseObject, path, properties.mirror, false), - blendMode = GetAll(baseObject, path, properties.blendMode, "ADD") + rotate = GetAll(baseObject, paths, properties.rotate, true), + discrete_rotation = GetAll(baseObject, paths, properties.discrete_rotation, 0), + rotation = GetAll(baseObject, paths, properties.rotation, 0), + mirror = GetAll(baseObject, paths, properties.mirror, false), + blendMode = GetAll(baseObject, paths, properties.blendMode, "ADD") } frame.window = "texture"; frame:UpdateFrameVisible() group:UpdateList() - local _, givenPath = next(self.givenPath) local picked = false; for categoryName, category in pairs(self.textures) do if not(picked) then @@ -234,7 +236,7 @@ local function ConstructTexturePicker(frame) function group.CancelClose() local valueFromPath = OptionsPrivate.Private.ValueFromPath for child in OptionsPrivate.Private.TraverseLeafsOrAura(group.baseObject) do - local childObject = valueFromPath(child, group.path) + local childObject = valueFromPath(child, group.paths[child.id]) if childObject then childObject[group.properties.texture] = group.givenPath[child.id] WeakAuras.Add(child); diff --git a/WeakAurasOptions/RegionOptions/AuraBar.lua b/WeakAurasOptions/RegionOptions/AuraBar.lua index 0929ac0..abd9179 100644 --- a/WeakAurasOptions/RegionOptions/AuraBar.lua +++ b/WeakAurasOptions/RegionOptions/AuraBar.lua @@ -242,7 +242,12 @@ local function createOptions(id, data) width = 0.15, order = 44.1, func = function() - OptionsPrivate.OpenTexturePicker(data, {}, { + local path = {} + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(data, paths, { texture = "sparkTexture", color = "sparkColor", rotation = "sparkRotation", diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index 48f1302..7b0aeb5 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -19,7 +19,12 @@ local function createOptions(id, data) width = 0.15, order = 2, func = function() - OptionsPrivate.OpenTexturePicker(data, {}, { + local path = {} + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(data, paths, { texture = "foregroundTexture", color = "foregroundColor", rotation = "rotation", @@ -46,7 +51,12 @@ local function createOptions(id, data) width = 0.15, order = 6, func = function() - OptionsPrivate.OpenTexturePicker(data, {}, { + local path = {} + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(data, paths, { texture = "backgroundTexture", color = "backgroundColor", rotation = "rotation", diff --git a/WeakAurasOptions/RegionOptions/StopMotion.lua b/WeakAurasOptions/RegionOptions/StopMotion.lua index 682d709..9f5a8c4 100644 --- a/WeakAurasOptions/RegionOptions/StopMotion.lua +++ b/WeakAurasOptions/RegionOptions/StopMotion.lua @@ -115,7 +115,12 @@ local function createOptions(id, data) name = L["Choose"], order = 2, func = function() - OptionsPrivate.OpenTexturePicker(data, {}, { + local path = {} + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(data, paths, { texture = "foregroundTexture", color = "foregroundColor", rotation = "rotation", @@ -355,13 +360,17 @@ local function createOptions(id, data) name = L["Choose"], order = 20, func = function() - OptionsPrivate.OpenTexturePicker(data, {}, { - texture = "backgroundTexture", - color = "backgroundColor", - rotation = "rotation", - mirror = "mirror", - blendMode = "blendMode" - }, texture_types, setTextureFunc); + local path = {} + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(data, paths, { + texture = "backgroundTexture", + color = "backgroundColor", + mirror = "mirror", + blendMode = "blendMode" + }, texture_types, setTextureFunc, true); end, disabled = function() return data.sameTexture or data.hideBackground; end, hidden = function() return data.hideBackground end, diff --git a/WeakAurasOptions/RegionOptions/Texture.lua b/WeakAurasOptions/RegionOptions/Texture.lua index 8130d17..32ef9cb 100644 --- a/WeakAurasOptions/RegionOptions/Texture.lua +++ b/WeakAurasOptions/RegionOptions/Texture.lua @@ -19,7 +19,12 @@ local function createOptions(id, data) width = 0.15, order = 1.1, func = function() - OptionsPrivate.OpenTexturePicker(data, {}, { + local path = {} + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(data, paths, { texture = "texture", color = "color", rotate = "rotate", diff --git a/WeakAurasOptions/SubRegionOptions/Tick.lua b/WeakAurasOptions/SubRegionOptions/Tick.lua index 49fb190..d2fb900 100644 --- a/WeakAurasOptions/SubRegionOptions/Tick.lua +++ b/WeakAurasOptions/SubRegionOptions/Tick.lua @@ -165,9 +165,12 @@ local function createOptions(parentData, data, index, subIndex) width = 0.15, order = 12.5, func = function() - OptionsPrivate.OpenTexturePicker(parentData, { - "subRegions", index - }, { + local path = { "subRegions", index } + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(parentData) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(parentData, paths, { texture = "tick_texture", color = "tick_color", blendMode = "tick_blend_mode" diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index ece4963..8f16cce 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -1674,8 +1674,8 @@ function WeakAuras.UpdateThumbnail(data) button:UpdateThumbnail() end -function OptionsPrivate.OpenTexturePicker(baseObject, path, properties, textures, SetTextureFunc) - frame.texturePicker:Open(baseObject, path, properties, textures, SetTextureFunc) +function OptionsPrivate.OpenTexturePicker(baseObject, paths, properties, textures, SetTextureFunc) + frame.texturePicker:Open(baseObject, paths, properties, textures, SetTextureFunc) end function OptionsPrivate.OpenIconPicker(baseObject, paths, groupIcon) From 8dcb62ec8183f155207df9334dc1a8f89af3755a Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Wed, 22 Jan 2025 18:56:11 +0100 Subject: [PATCH 067/153] from retail --- WeakAuras/AuraEnvironment.lua | 2 +- WeakAuras/Prototypes.lua | 4 +-- WeakAuras/RegionTypes/Icon.lua | 6 ++-- WeakAuras/RegionTypes/ProgressTexture.lua | 5 +++ WeakAuras/RegionTypes/RegionPrototype.lua | 5 ++- WeakAuras/WeakAuras.lua | 39 ++++++++--------------- 6 files changed, 29 insertions(+), 32 deletions(-) diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index dd90435..c33e78e 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -328,7 +328,7 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) local childData = WeakAuras.GetData(childID) if childData then if not environment_initialized[childID] then - Private.ActivateAuraEnvironment(childID) + Private.ActivateAuraEnvironment(childID, nil, nil, nil, true) Private.ActivateAuraEnvironment() end current_aura_env.child_envs[dataIndex] = aura_environments[childID] diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index a593455..e4031ef 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4655,14 +4655,14 @@ Private.event_prototypes = { }, { name = "icon", - init = "GetItemIcon(itemName)", + init = "GetItemIcon(itemName or '')", hidden = true, store = true, test = "true" }, { name = "name", - init = "itemName", + init = "itemName and itemName ~= '' and GetItemIcon(itemName) or itemName", hidden = true, store = true, test = "true" diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index 98df008..c50baed 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -453,16 +453,16 @@ local function modify(parent, region, data) end function region:SetInverse(inverse) - if region.inverse == inverse then + if region.inverseDirection == inverse then return end - region.inverse = inverse + region.inverseDirection = inverse region:UpdateEffectiveInverse() end function region:UpdateEffectiveInverse() -- If cooldown.inverse == false then effectiveReverse = not inverse -- If cooldown.inverse == true then effectiveReverse = inverse - local effectiveReverse = not region.inverse == not cooldown.inverse + local effectiveReverse = not region.inverseDirection == not cooldown.inverse cooldown:SetReverse(effectiveReverse) if (cooldown.expirationTime and cooldown.duration and cooldown:IsShown()) then -- WORKAROUND SetReverse not applying until next frame diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 44f1887..385d582 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -903,6 +903,11 @@ local function modify(parent, region, data) else region:SetValueOnTexture(progress); end + + if self.FrameTick then + self.FrameTick = nil + self.subRegionEvents:RemoveSubscriber("FrameTick", region) + end end if region.useSmoothProgress then diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index edc9c18..2f4b574 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -428,8 +428,11 @@ local function UpdateProgressFromState(self, minMaxConfig, state, progressSource else adjustMin = 0 end + local max - if minMaxConfig.adjustedMax then + if duration == 0 then + max = 0 + elseif minMaxConfig.adjustedMax then max = minMaxConfig.adjustedMax elseif minMaxConfig.adjustedMaxRelPercent then max = minMaxConfig.adjustedMaxRelPercent * duration diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 9ecfeae..21cf752 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2592,7 +2592,14 @@ function WeakAuras.PreAdd(data) Private.validate(data, oldDataStub2) end - local default = data.regionType and Private.regionTypes[data.regionType] and Private.regionTypes[data.regionType].default + local ok = pcall(Private.Modernize, data) + if not ok then + Private.GetErrorHandlerId(data.id, L["Modernize"]) + end + + local default = data.regionType and + Private.regionTypes[data.regionType] and + Private.regionTypes[data.regionType].default if default then Private.validate(data, default) end @@ -2602,7 +2609,6 @@ function WeakAuras.PreAdd(data) regionValidate(data) end - Private.Modernize(data); Private.validate(data, Private.data_stub); if data.subRegions then for _, subRegionData in ipairs(data.subRegions) do @@ -2915,40 +2921,19 @@ local function EnsureRegion(id) Private.regions[id] = Private.regions[id] or {} -- The region doesn't yet exist -- But we must also ensure that our parents exists - -- and as an additional wrinkle, for dynamic groups, all children must exist! - -- and we have to call ReloadControlledChildren at the end -- So we go up the list of parents and collect auras that must be created -- If we find a parent already exists, we can stop - -- And dynamic groups require creating all children, thus we don't need - -- to care which path we came to them local aurasToCreate = {} - local dynamicGroups = {} - creatingRegions = true while(id) do local data = WeakAuras.GetData(id) - if (data.regionType == "dynamicgroup") then - wipe(aurasToCreate) - tinsert(aurasToCreate, data.id) - tinsert(dynamicGroups, data.id) - else - tinsert(aurasToCreate, data.id) - end + tinsert(aurasToCreate, data.id) id = data.parent end + for _, toCreateId in ipairs_reverse(aurasToCreate) do local data = WeakAuras.GetData(toCreateId) Private.SetRegion(data) - if (data.regionType == "dynamicgroup") then - for child in Private.TraverseAllChildren(data) do - Private.SetRegion(child) - end - end - end - creatingRegions = false - for _, dynamicGroupId in ipairs_reverse(dynamicGroups) do - local dgRegion = Private.regions[dynamicGroupId].region - dgRegion:ReloadControlledChildren() end end return Private.regions[id] and Private.regions[id].region @@ -4059,6 +4044,10 @@ local function startStopTimers(id, cloneId, triggernum, state) stopAutoHideTimer(id, triggernum, cloneId) return else + if state.expirationTime == nil and type(state.duration) == "number" then + -- Set the expiration time, because users rely on that, even though it's wrong to do + state.expirationTime = GetTime() + state.duration + end expirationTime = state.expirationTime end elseif type(state.autoHide) == "number" then From e1e0744ecf128c4d1584bf134806e00f520397e0 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 23 Jan 2025 18:30:22 +0100 Subject: [PATCH 068/153] from retail --- WeakAuras/Animations.lua | 12 +- WeakAuras/BossMods.lua | 49 ++-- WeakAuras/GenericTrigger.lua | 27 +- WeakAuras/Modernize.lua | 16 +- WeakAuras/Prototypes.lua | 9 +- WeakAuras/RegionTypes/AuraBar.lua | 7 +- WeakAuras/RegionTypes/Icon.lua | 1 + WeakAuras/RegionTypes/ProgressTexture.lua | 6 +- WeakAuras/RegionTypes/RegionPrototype.lua | 13 +- WeakAuras/RegionTypes/Texture.lua | 1 + WeakAuras/SubRegionTypes/Tick.lua | 6 +- WeakAuras/Transmission.lua | 8 +- WeakAuras/Types.lua | 8 +- WeakAuras/WeakAuras.lua | 41 ++- .../WeakAurasStatusbarAtlasWidget.lua | 233 ++++++++++++++++++ WeakAurasOptions/ActionOptions.lua | 5 +- WeakAurasOptions/ConditionOptions.lua | 7 +- .../OptionsFrames/OptionsFrame.lua | 6 +- WeakAurasOptions/RegionOptions/AuraBar.lua | 58 ++++- WeakAurasOptions/WeakAurasOptions.toc | 1 + 20 files changed, 433 insertions(+), 81 deletions(-) create mode 100644 WeakAurasOptions/AceGUI-Widgets/WeakAurasStatusbarAtlasWidget.lua diff --git a/WeakAuras/Animations.lua b/WeakAuras/Animations.lua index 956b16f..40b5c58 100644 --- a/WeakAuras/Animations.lua +++ b/WeakAuras/Animations.lua @@ -9,8 +9,6 @@ local anim_function_strings = Private.anim_function_strings; local function noopErrorHandler() end -local frame = Private.frames["WeakAuras Main Frame"] - local function RunAnimation(key, anim, elapsed, time) Private.StartProfileUID(anim.auraUID) local finished = false @@ -178,6 +176,9 @@ end local updatingAnimations; local last_update = GetTime(); local function UpdateAnimations() + if not updatingAnimations then + return + end Private.StartProfileSystem("animations"); for groupUid, groupRegion in pairs(pending_controls) do @@ -196,12 +197,15 @@ local function UpdateAnimations() Private.StopProfileSystem("animations"); end +local frame = CreateFrame("Frame") +Private.frames["WeakAuras Animation Frame"] = frame +frame:SetScript("OnUpdate", UpdateAnimations) + function Private.RegisterGroupForPositioning(uid, region) pending_controls[uid] = region if not updatingAnimations then updatingAnimations = true last_update = GetTime() - frame:SetScript("OnUpdate", UpdateAnimations) end end @@ -399,11 +403,9 @@ function Private.Animate(namespace, uid, type, anim, region, inverse, onFinished animation.auraUID = uid if not(updatingAnimations) then - frame:SetScript("OnUpdate", UpdateAnimations); last_update = GetTime() updatingAnimations = true; end - RunAnimation(key, animation, 0, GetTime()) return true; else if(animations[key]) then diff --git a/WeakAuras/BossMods.lua b/WeakAuras/BossMods.lua index f5ff989..32fe029 100644 --- a/WeakAuras/BossMods.lua +++ b/WeakAuras/BossMods.lua @@ -150,7 +150,7 @@ Private.ExecEnv.BossMods.DBM = { end end if self.nextExpire then - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, self.nextExpire - now, self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, self.nextExpire - now, self) end end, @@ -214,11 +214,11 @@ Private.ExecEnv.BossMods.DBM = { WeakAuras.ScanEvents("BossMod_TimerStart", timerId) end if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) self.nextExpire = expirationTime elseif expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) self.nextExpire = expirationTime end elseif event == "DBM_TimerStop" then @@ -261,11 +261,11 @@ Private.ExecEnv.BossMods.DBM = { WeakAuras.ScanEvents("BossMod_TimerResume", timerId) end if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) self.nextExpire = bar.expirationTime elseif bar.expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) self.nextExpire = bar.expirationTime end end @@ -278,11 +278,11 @@ Private.ExecEnv.BossMods.DBM = { bar.duration = duration bar.expirationTime = expirationTime if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - now, self) self.nextExpire = expirationTime elseif self.nextExpire == nil or expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - now, self) self.nextExpire = expirationTime end end @@ -290,6 +290,16 @@ Private.ExecEnv.BossMods.DBM = { if self.isGeneric then WeakAuras.ScanEvents("BossMod_TimerUpdate", timerId) end + elseif event == "DBM_TimerUpdateIcon" then + local timerId, icon = ... + local bar = self.bars[timerId] + if bar then + bar.icon = icon + end + WeakAuras.ScanEvents("DBM_TimerUpdateIcon", timerId) + if self.isGeneric then + WeakAuras.ScanEvents("BossMod_TimerUpdateIcon", timerId) + end elseif event == "DBM_SetStage" or event == "DBM_Pull" or event == "DBM_Wipe" or event == "DBM_Kill" then WeakAuras.ScanEvents("DBM_SetStage") if self.isGeneric then @@ -314,6 +324,7 @@ Private.ExecEnv.BossMods.DBM = { self:RegisterCallback("DBM_TimerPause") self:RegisterCallback("DBM_TimerResume") self:RegisterCallback("DBM_TimerUpdate") + self:RegisterCallback("DBM_TimerUpdateIcon") end, RegisterMessage = function(self) @@ -338,7 +349,7 @@ Private.ExecEnv.BossMods.DBM = { ScheduleCheck = function(self, fireTime) if not self.scheduled_scans[fireTime] then - self.scheduled_scans[fireTime] = timer:ScheduleTimer(self.DoScan, fireTime - GetTime(), self, fireTime) + self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime(), self, fireTime) end end } @@ -443,7 +454,8 @@ Private.event_prototypes["DBM Timer"] = { type = "addons", events = {}, internal_events = { - "DBM_TimerStart", "DBM_TimerStop", "DBM_TimerUpdate", "DBM_TimerForce", "DBM_TimerResume", "DBM_TimerPause" + "DBM_TimerStart", "DBM_TimerStop", "DBM_TimerUpdate", "DBM_TimerForce", "DBM_TimerResume", "DBM_TimerPause", + "DBM_TimerUpdateIcon" }, force_events = "DBM_TimerForce", name = L["DBM Timer"], @@ -530,7 +542,7 @@ Private.event_prototypes["DBM Timer"] = { state.changed = true return true end - elseif event == "DBM_TimerUpdate" then + elseif event == "DBM_TimerUpdate" or event == "DBM_TimerUpdateIcon" then local changed for timerId, bar in pairs(Private.ExecEnv.BossMods.DBM:GetAllTimers()) do if Private.ExecEnv.BossMods.DBM:TimerMatches(timerId, triggerText, triggerTextOperator, triggerSpellId, counter, triggerId, triggerDbmType) then @@ -806,7 +818,7 @@ Private.ExecEnv.BossMods.BigWigs = { end if self.nextExpire then - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, self.nextExpire - now, self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, self.nextExpire - now, self) end end, @@ -846,11 +858,11 @@ Private.ExecEnv.BossMods.BigWigs = { WeakAuras.ScanEvents("BossMod_TimerStart", text) end if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) self.nextExpire = expirationTime elseif expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, expirationTime - now, self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, expirationTime - now, self) self.nextExpire = expirationTime end elseif event == "BigWigs_StopBar" then @@ -892,10 +904,10 @@ Private.ExecEnv.BossMods.BigWigs = { WeakAuras.ScanEvents("BossMod_TimerResume", text) end if self.nextExpire == nil then - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) elseif bar.expirationTime < self.nextExpire then timer:CancelTimer(self.recheckTimer) - self.recheckTimer = timer:ScheduleTimer(self.RecheckTimers, bar.expirationTime - GetTime(), self) + self.recheckTimer = timer:ScheduleTimerFixed(self.RecheckTimers, bar.expirationTime - GetTime(), self) self.nextExpire = bar.expirationTime end end @@ -982,7 +994,7 @@ Private.ExecEnv.BossMods.BigWigs = { ScheduleCheck = function(self, fireTime) if not self.scheduled_scans[fireTime] then - self.scheduled_scans[fireTime] = timer:ScheduleTimer(self.DoScan, fireTime - GetTime(), self, fireTime) + self.scheduled_scans[fireTime] = timer:ScheduleTimerFixed(self.DoScan, fireTime - GetTime(), self, fireTime) end end } @@ -1478,7 +1490,8 @@ Private.event_prototypes["Boss Mod Timer"] = { type = "addons", events = {}, internal_events = { - "BossMod_TimerStart", "BossMod_TimerStop", "BossMod_TimerUpdate", "BossMod_TimerForce", "BossMod_TimerResume", "BossMod_TimerPause" + "BossMod_TimerStart", "BossMod_TimerStop", "BossMod_TimerUpdate", "BossMod_TimerForce", "BossMod_TimerResume", + "BossMod_TimerPause", "BossMod_TimerUpdateIcon" }, force_events = "BossMod_TimerForce", name = L["Boss Mod Timer"], @@ -1566,7 +1579,7 @@ Private.event_prototypes["Boss Mod Timer"] = { state.changed = true return true end - elseif event == "BossMod_TimerUpdate" then + elseif event == "BossMod_TimerUpdate" or event == "BossMod_TimerUpdateIcon" then local changed for timerId, bar in pairs(Private.ExecEnv.BossMods.Generic:GetAllTimers()) do if Private.ExecEnv.BossMods.Generic:TimerMatchesGeneric(timerId, triggerText, triggerTextOperator, triggerSpellId, counter) then diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 8aea94f..07c8539 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1015,7 +1015,7 @@ local function ProgressType(data, triggernum) elseif (trigger.customDuration and trigger.customDuration ~= "") then return "timed"; elseif (trigger.custom_type == "stateupdate") then - return "timed"; + return false end end return false @@ -3101,6 +3101,7 @@ end do local mh = GetInventorySlotInfo("MainHandSlot") local oh = GetInventorySlotInfo("SecondaryHandSlot") + local rw = GetInventorySlotInfo("RangedSlot") local mh_name, mh_shortenedName, mh_exp, mh_dur, mh_charges; local mh_icon = GetInventoryItemTexture("player", mh); @@ -3108,6 +3109,9 @@ do local oh_name, oh_shortenedName, oh_exp, oh_dur, oh_charges; local oh_icon = GetInventoryItemTexture("player", oh); + local rw_name, rw_shortenedName, rw_exp, rw_dur, rw_charges; + local rw_icon = GetInventoryItemTexture("player", rw) or "Interface\\Icons\\INV_Misc_QuestionMark" + local tenchFrame = nil Private.frames["Temporary Enchant Handler"] = tenchFrame; local tenchTip; @@ -3140,11 +3144,12 @@ do local function tenchUpdate() Private.StartProfileSystem("generictrigger"); - local _, mh_rem, oh_rem - _, mh_rem, mh_charges, _, oh_rem, oh_charges = GetWeaponEnchantInfo(); + local _, mh_rem, oh_rem, rw_rem, re_charges + _, mh_rem, mh_charges, _, oh_rem, oh_charges, _, rw_rem, rw_charges = GetWeaponEnchantInfo(); local time = GetTime(); local mh_exp_new = mh_rem and (time + (mh_rem / 1000)); local oh_exp_new = oh_rem and (time + (oh_rem / 1000)); + local rw_exp_new = rw_rem and (time + (rw_rem / 1000)); if(math.abs((mh_exp or 0) - (mh_exp_new or 0)) > 1) then mh_exp = mh_exp_new; mh_dur = mh_rem and mh_rem / 1000; @@ -3165,6 +3170,16 @@ do end oh_icon = GetInventoryItemTexture("player", oh) end + if(math.abs((rw_exp or 0) - (rw_exp_new or 0)) > 1) then + rw_exp = rw_exp_new; + rw_dur = rw_rem and rw_rem / 1000; + if rw_exp then + rw_name, rw_shortenedName = getTenchName(rw) + else + rw_name, rw_shortenedName = "None", "None" + end + rw_icon = GetInventoryItemTexture("player", rw) + end WeakAuras.ScanEvents("TENCH_UPDATE"); Private.StopProfileSystem("generictrigger"); end @@ -3186,6 +3201,10 @@ do function WeakAuras.GetOHTenchInfo() return oh_exp, oh_dur, oh_name, oh_shortenedName, oh_icon, oh_charges; end + + function WeakAuras.GetRangeTenchInfo() + return rw_exp, rw_dur, rw_name, rw_shortenedName, rw_icon, rw_charges; + end end -- Pets @@ -3742,7 +3761,7 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) enable = v.enable end - if (enable and v.store and v.name and v.display) then + if (enable and v.store and v.name and v.display and v.conditionType ~= "bool") then found = true; additional = additional .. "|cFFFFCC00%".. triggernum .. "." .. v.name .. "|r - " .. v.display .. "\n"; end diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 02ccb64..dfb0f50 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -1469,7 +1469,7 @@ function Private.Modernize(data) migrateToTable(data.load, "itemequiped") end - --[[if data.internalVersion < 71 then + if data.internalVersion < 71 then if data.regionType == 'icon' or data.regionType == 'aurabar' or data.regionType == 'progresstexture' or data.regionType == 'stopmotion' @@ -1490,7 +1490,19 @@ function Private.Modernize(data) end end - end]] + end + + if data.internalVersion < 73 then + if data.conditions then + for conditionIndex, condition in ipairs(data.conditions) do + for changeIndex, change in ipairs(condition.changes) do + if type(change.property) == "string" then + change.property = string.gsub(change.property, "(sub.%d.tick_placement)(%d)", "%1s.%2") + end + 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 e4031ef..17936ba 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4794,7 +4794,9 @@ Private.event_prototypes = { if triggerWeaponType == "main" then expirationTime, duration, name, shortenedName, icon, stacks = WeakAuras.GetMHTenchInfo() - else + elseif triggerWeaponType == "off" then + expirationTime, duration, name, shortenedName, icon, stacks = WeakAuras.GetOHTenchInfo() + elseif triggerWeaponType == "ranged" then expirationTime, duration, name, shortenedName, icon, stacks = WeakAuras.GetOHTenchInfo() end @@ -4820,10 +4822,10 @@ Private.event_prototypes = { return ret:format(trigger.weapon or "main", trigger.use_enchant and trigger.enchant or "", - showOnActive and trigger.use_stack and tonumber(trigger.stack or 0) or "nil", + showOnActive and trigger.use_stacks and tonumber(trigger.stacks or 0) or "nil", showOnActive and trigger.use_remaining and tonumber(trigger.remaining or 0) or "nil", trigger.showOn or "showOnActive", - trigger.stack_operator or "<", + trigger.stacks_operator or "<", trigger.remaining_operator or "<") end, args = { @@ -4847,6 +4849,7 @@ Private.event_prototypes = { name = "stacks", display = L["Stack Count"], type = "number", + conditionType = "number", test = "true", store = true }, diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 36063e8..457f65f 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -1125,7 +1125,12 @@ local function modify(parent, region, data) end -- Update texture settings - local texturePath = SharedMedia:Fetch("statusbar", data.texture) or ""; + local texturePath + if data.textureSource == "Picker" then + texturePath = data.textureInput or "" + else + texturePath = SharedMedia:Fetch("statusbar", data.texture) or ""; + end bar:SetStatusBarTexture(texturePath); bar:SetBackgroundColor(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]); -- Update spark settings diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index c50baed..34b3b12 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -631,6 +631,7 @@ local function modify(parent, region, data) region.UpdateTime = nil function region:Update() + region:UpdateProgress() region:UpdateIcon() end end diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 385d582..196f184 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -476,13 +476,14 @@ local function FrameTick(self) if (duration ~= 0) then local remaining = expirationTime - GetTime(); progress = remaining / duration; - local inversed = (not inverse and self.inverseDirection) or (inverse and not self.inverseDirection); + local inversed = not inverse ~= not self.inverseDirection if(inversed) then progress = 1 - progress; end end progress = progress > 0.0001 and progress or 0.0001; + if (self.useSmoothProgress) then self.smoothProgress:SetSmoothedValue(progress); else @@ -861,12 +862,13 @@ local function modify(parent, region, data) region:Color(data.foregroundColor[1], data.foregroundColor[2], data.foregroundColor[3], data.foregroundColor[4]); + function region:UpdateTime() local progress = 1; if (self.duration ~= 0) then local remaining = self.expirationTime - GetTime() progress = remaining / self.duration - local inversed = self.inverse ~= region.inverseDirection + local inversed = not self.inverse ~= not region.inverseDirection if(inversed) then progress = 1 - progress; end diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index 2f4b574..96b650c 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -379,8 +379,10 @@ local function UpdateProgressFromState(self, minMaxConfig, state, progressSource local pausedProperty = progressSource[6] local remainingProperty = progressSource[7] if progressType == "number" then - local value = state[property] or 0 - local total = totalProperty and state[totalProperty] or 0 + local value = state[property] + if type(value) ~= "number" then value = 0 end + local total = totalProperty and state[totalProperty] + if type(total) ~= "number" then total = 0 end -- We don't care about inverse or paused local adjustMin if minMaxConfig.adjustedMin then @@ -415,9 +417,12 @@ local function UpdateProgressFromState(self, minMaxConfig, state, progressSource local remaining if paused then remaining = remainingProperty and state[remainingProperty] - expirationTime = GetTime() + (remaining or 0) + expirationTime = GetTime() + (type(remaining) == "number" and remaining or 0) else - expirationTime = state[property] or math.huge + expirationTime = state[property] + if type(expirationTime) ~= "number" then + expirationTime = math.huge + end end local duration = totalProperty and state[totalProperty] or 0 local adjustMin diff --git a/WeakAuras/RegionTypes/Texture.lua b/WeakAuras/RegionTypes/Texture.lua index 264d155..5fffc9a 100644 --- a/WeakAuras/RegionTypes/Texture.lua +++ b/WeakAuras/RegionTypes/Texture.lua @@ -181,6 +181,7 @@ local function modify(parent, region, data) if region.state.texture then region.texture:SetTexture(region.state.texture); end + region:UpdateProgress() end function region:Color(r, g, b, a) diff --git a/WeakAuras/SubRegionTypes/Tick.lua b/WeakAuras/SubRegionTypes/Tick.lua index 4db41ea..93c5244 100644 --- a/WeakAuras/SubRegionTypes/Tick.lua +++ b/WeakAuras/SubRegionTypes/Tick.lua @@ -101,7 +101,7 @@ local function GetProperties(parentData, data) local result = CopyTable(properties) for i in ipairs(data.tick_placements) do - result["tick_placement" .. i] = { + result["tick_placements." .. i] = { display = #data.tick_placements > 1 and L["Placement %i"]:format(i) or L["Placement"], setter = "SetTickPlacementAt", type = "number", @@ -286,8 +286,8 @@ local funcs = { else tick_placement = self.progressData[i].expirationTime - GetTime() + self.tick_placements[i] end - elseif self.progressType == "static" then - tick_placement = self.progressData[i].value + self.progressData[i].tick_placements[i] + elseif self.progressData[i].progressType == "static" then + tick_placement = self.progressData[i].value + self.tick_placements[i] end end end diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 5e6f66d..53b6176 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -537,8 +537,9 @@ end local function crossRealmSendCommMessage(prefix, text, target, queueName, callbackFn, callbackArg) local chattype = "WHISPER" ---[[ - if target then + --[[if target and not UnitIsSameServer(target) then + -- WORKAROUND https://github.com/Stanzilla/WoWUIBugs/issues/535, and use RAID/PARTY comms for connected realms + if target and (UnitRealmRelationship(target) or 0) ~= 1 then if UnitInRaid(target) then chattype = "RAID" text = ("§§%s:%s"):format(target, text) @@ -546,8 +547,7 @@ local function crossRealmSendCommMessage(prefix, text, target, queueName, callba chattype = "PARTY" text = ("§§%s:%s"):format(target, text) end - end -]] + end]] Comm:SendCommMessage(prefix, text, chattype, target, queueName, callbackFn, callbackArg) end diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 1c6862e..df12210 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -25,7 +25,8 @@ Private.glow_action_types = { Private.glow_frame_types = { UNITFRAME = L["Unit Frame"], - FRAMESELECTOR = L["Frame Selector"] + FRAMESELECTOR = L["Frame Selector"], + PARENTFRAME = L["Parent Frame"] } if WeakAuras.isAwesomeEnabled() then Private.glow_frame_types.NAMEPLATE = L["Nameplate"] @@ -159,7 +160,7 @@ Private.format_types = { none = { display = L["None"], AddOptions = function() end, - CreateFormatter = function() end + CreateFormatter = function() return nil end }, string = { display = L["String"], @@ -1849,7 +1850,8 @@ Private.string_operator_types = { Private.weapon_types = { ["main"] = MAINHANDSLOT, - ["off"] = SECONDARYHANDSLOT + ["off"] = SECONDARYHANDSLOT, + ["ranged"] = RANGEDSLOT, } Private.swing_types = { diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 21cf752..8aab8b8 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1,6 +1,6 @@ local AddonName, Private = ... -local internalVersion = 71 +local internalVersion = 73 -- Lua APIs local insert = table.insert @@ -1353,7 +1353,7 @@ local function GetInstanceTypeAndSize() end function WeakAuras.InstanceType() - return GetInstanceTypeAndSize(), nil + return (GetInstanceTypeAndSize()) end function WeakAuras.InstanceDifficulty() @@ -2143,22 +2143,6 @@ local function loadOrder(tbl, idtable) if(data.parent) then if(idtable[data.parent]) then if depends[data.parent] then - -- There was an unfortunate bug in update.lua in 2022 that resulted - -- in auras having a circular dependencies - -- Fix one of the two known cases here - -- We can probably remove this code in 2023 again - for d in pairs(depends) do - local uid = idtable[d].uid - if uid == "fjtz3A6LwBW" then -- Fojji - Deathknight UI, need to fixup a lot - local cycleRoot = d - idtable[cycleRoot].parent = nil - for d in pairs(depends) do - tDeleteItem(idtable[d].controlledChildren, cycleRoot) - end - return loadOrder(tbl, idtable) - end - coroutine.yield() - end error("Circular dependency in Private.AddMany between "..table.concat(depends, ", ")); else if not(loaded[data.parent]) then @@ -2187,6 +2171,7 @@ local function loadOrder(tbl, idtable) return order end +local pAdd function Private.AddMany(tbl, takeSnapshots) local idtable = {}; local anchorTargets = {} @@ -2222,7 +2207,7 @@ function Private.AddMany(tbl, takeSnapshots) else local ok = pcall(WeakAuras.PreAdd, data) if not ok then - geterrorhandler() + Private.GetErrorHandlerUid(data.uid, "PreAdd") prettyPrint(L["Unable to modernize aura '%s'. This is probably due to corrupt data or a bad migration, please report this to the WeakAuras team."]:format(data.id)) if data.regionType == "dynamicgroup" or data.regionType == "group" then prettyPrint(L["All children of this aura will also not be loaded, to minimize the chance of further corruption."]) @@ -2237,9 +2222,17 @@ function Private.AddMany(tbl, takeSnapshots) for _, data in ipairs(order) do if not bads[data.id] then - WeakAuras.Add(data) - coroutine.yield() + if data.parent and bads[data.parent] then + bads[data.id] = true + else + local ok = pcall(pAdd, data) + if not ok then + Private.GetErrorHandlerUid(data.uid, "pAdd") + bads[data.id] = true + end + end end + coroutine.yield() end for id in pairs(anchorTargets) do @@ -2637,7 +2630,7 @@ function WeakAuras.PreAdd(data) data.expanded = nil end -local function pAdd(data, simpleChange) +function pAdd(data, simpleChange) local id = data.id; if not(id) then error("Improper arguments to WeakAuras.Add - id not defined"); @@ -3182,6 +3175,7 @@ function Private.HandleGlowAction(actions, region) and region.state.unit ) or (actions.glow_frame_type == "FRAMESELECTOR" and actions.glow_frame) + or (actions.glow_frame_type == "PARENTFRAME" and region:GetParent()) ) then local glow_frame, should_glow_frame @@ -3206,6 +3200,9 @@ function Private.HandleGlowAction(actions, region) if not(WeakAuras.isAwesomeEnabled()) then return end glow_frame = WeakAuras.GetNamePlateForUnit(region.state.unit) should_glow_frame = true + elseif actions.glow_frame_type == "PARENTFRAME" then + glow_frame = region:GetParent() + should_glow_frame = true end if should_glow_frame then diff --git a/WeakAurasOptions/AceGUI-Widgets/WeakAurasStatusbarAtlasWidget.lua b/WeakAurasOptions/AceGUI-Widgets/WeakAurasStatusbarAtlasWidget.lua new file mode 100644 index 0000000..ff20bb1 --- /dev/null +++ b/WeakAurasOptions/AceGUI-Widgets/WeakAurasStatusbarAtlasWidget.lua @@ -0,0 +1,233 @@ +-- Widget is based on the AceGUIWidget-DropDown.lua supplied with AceGUI-3.0 +-- Original Widget created by Yssaril, modified by WeakAuras Team to handle Atlas + +local AceGUI = LibStub("AceGUI-3.0") +local Media = LibStub("LibSharedMedia-3.0") + +local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0") + +do + local widgetType = "WA_LSM30_StatusbarAtlas" + local widgetVersion = 1 + + local contentFrameCache = {} + local function ReturnSelf(self) + self:ClearAllPoints() + self:Hide() + self.check:Hide() + table.insert(contentFrameCache, self) + end + + local function ContentOnClick(this, button) + local self = this.obj + self:Fire("OnValueChanged", this.text:GetText()) + if self.dropdown then + self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) + end + end + + local function GetContentLine() + local frame + if next(contentFrameCache) then + frame = table.remove(contentFrameCache) + else + frame = CreateFrame("Button", nil, UIParent) + --frame:SetWidth(200) + frame:SetHeight(18) + frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD") + frame:SetScript("OnClick", ContentOnClick) + local check = frame:CreateTexture("OVERLAY") + check:SetWidth(16) + check:SetHeight(16) + check:SetPoint("LEFT",frame,"LEFT",1,-1) + check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") + check:Hide() + frame.check = check + local bar = frame:CreateTexture("ARTWORK") + bar:SetHeight(16) + bar:SetPoint("LEFT",check,"RIGHT",1,0) + bar:SetPoint("RIGHT",frame,"RIGHT",-1,0) + frame.bar = bar + local text = frame:CreateFontString(nil,"OVERLAY","GameFontWhite") + + local font, size = text:GetFont() + text:SetFont(font,size,"OUTLINE") + + text:SetPoint("TOPLEFT", check, "TOPRIGHT", 3, 0) + text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 0) + text:SetJustifyH("LEFT") + text:SetText("Test Test Test Test Test Test Test") + frame.text = text + frame.ReturnSelf = ReturnSelf + end + frame:Show() + return frame + end + + local function OnAcquire(self) + self:SetHeight(44) + self:SetWidth(200) + end + + local function OnRelease(self) + self:SetText("") + self:SetLabel("") + self:SetDisabled(false) + + self.value = nil + self.list = nil + self.open = nil + self.hasClose = nil + + self.frame:ClearAllPoints() + self.frame:Hide() + end + + local function SetValue(self, value) -- Set the value to an item in the List. + if self.list then + self:SetText(value or "") + end + self.value = value + end + + local function GetValue(self) + return self.value + end + + local function SetList(self, list) -- Set the list of values for the dropdown (key => value pairs) + self.list = list or Media:HashTable("statusbar") + end + + + local function SetText(self, text) -- Set the text displayed in the box. + self.frame.text:SetText(text or "") + local statusbar = self.list[text] ~= text and self.list[text] or Media:Fetch('statusbar', text) + self.bar:SetTexture(statusbar) + end + + local function SetLabel(self, text) -- Set the text for the label. + self.frame.label:SetText(text or "") + end + + local function AddItem(self, key, value) -- Add an item to the list. + self.list = self.list or {} + self.list[key] = value + end + local SetItemValue = AddItem -- Set the value of a item in the list. <> + + local function SetMultiselect(self, flag) end -- Toggle multi-selecting. <> + local function GetMultiselect() return false end-- Query the multi-select flag. <> + local function SetItemDisabled(self, key) end-- Disable one item in the list. <> + + local function SetDisabled(self, disabled) -- Disable the widget. + self.disabled = disabled + if disabled then + self.frame:Disable() + else + self.frame:Enable() + end + end + + local function textSort(a,b) + return string.upper(a) < string.upper(b) + end + + local sortedlist = {} + local function ToggleDrop(this) + local self = this.obj + if self.dropdown then + self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) + AceGUI:ClearFocus() + else + AceGUI:SetFocus(self) + self.dropdown = AGSMW:GetDropDownFrame() + local width = self.frame:GetWidth() + self.dropdown:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT") + self.dropdown:SetPoint("TOPRIGHT", self.frame, "BOTTOMRIGHT", width < 160 and (160 - width) or 0, 0) + for k, v in pairs(self.list) do + sortedlist[#sortedlist+1] = k + end + table.sort(sortedlist, textSort) + for i, k in ipairs(sortedlist) do + local f = GetContentLine() + f.text:SetText(k) + --print(k) + if k == self.value then + f.check:Show() + end + + local statusbar = self.list[k] ~= k and self.list[k] or Media:Fetch('statusbar',k) + f.bar:SetTexture(statusbar) + f.obj = self + f.dropdown = self.dropdown + self.dropdown:AddFrame(f) + end + wipe(sortedlist) + end + end + + local function ClearFocus(self) + if self.dropdown then + self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) + end + end + + local function OnHide(this) + local self = this.obj + if self.dropdown then + self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) + end + end + + local function Drop_OnEnter(this) + this.obj:Fire("OnEnter") + end + + local function Drop_OnLeave(this) + this.obj:Fire("OnLeave") + end + + local function Constructor() + local frame = AGSMW:GetBaseFrame() + local self = {} + + self.type = widgetType + self.frame = frame + frame.obj = self + frame.dropButton.obj = self + frame.dropButton:SetScript("OnEnter", Drop_OnEnter) + frame.dropButton:SetScript("OnLeave", Drop_OnLeave) + frame.dropButton:SetScript("OnClick",ToggleDrop) + frame:SetScript("OnHide", OnHide) + + local bar = frame:CreateTexture(nil, "OVERLAY") + bar:SetPoint("TOPLEFT", frame,"TOPLEFT",6,-25) + bar:SetPoint("BOTTOMRIGHT", frame,"BOTTOMRIGHT", -21, 5) + bar:SetAlpha(0.5) + self.bar = bar + + self.alignoffset = 31 + + self.OnRelease = OnRelease + self.OnAcquire = OnAcquire + self.ClearFocus = ClearFocus + self.SetText = SetText + self.SetValue = SetValue + self.GetValue = GetValue + self.SetList = SetList + self.SetLabel = SetLabel + self.SetDisabled = SetDisabled + self.AddItem = AddItem + self.SetMultiselect = SetMultiselect + self.GetMultiselect = GetMultiselect + self.SetItemValue = SetItemValue + self.SetItemDisabled = SetItemDisabled + self.ToggleDrop = ToggleDrop + + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) + +end diff --git a/WeakAurasOptions/ActionOptions.lua b/WeakAurasOptions/ActionOptions.lua index 6de47c1..5b7c137 100644 --- a/WeakAurasOptions/ActionOptions.lua +++ b/WeakAurasOptions/ActionOptions.lua @@ -649,10 +649,7 @@ function OptionsPrivate.GetActionOptions(data) end, name = L["Glow Frame Type"], order = 30.3, - values = { - UNITFRAME = L["Unit Frame"], - FRAMESELECTOR = L["Frame Selector"] - }, + values = OptionsPrivate.Private.glow_frame_types, hidden = function() return not data.actions.finish.do_glow or data.actions.finish.glow_action == nil diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 08b8b4b..22e8da4 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -488,7 +488,6 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA args["condition" .. i .. "value" .. j] = { type = "toggle", width = WeakAuras.normalWidth, - name = blueIfNoValue(data, conditions[i].changes[j], "value", L["Differences"]), desc = descIfNoValue(data, conditions[i].changes[j], "value", propertyType), order = order, get = function() @@ -498,6 +497,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA } order = order + 1; if (propertyType == "number") then + args["condition" .. i .. "value" .. j].name = blueIfNoValue(data, conditions[i].changes[j], "value", L["Differences"]) local properties = allProperties.propertyMap[property]; if (properties.min or properties.softMin) and (properties.max or properties.softMax) then args["condition" .. i .. "value" .. j].type = "range"; @@ -513,6 +513,11 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA args["condition" .. i .. "value" .. j].type = "input"; args["condition" .. i .. "value" .. j].validate = WeakAuras.ValidateNumeric; end + else + args["condition" .. i .. "value" .. j].name = function() + local value = conditions[i].changes[j].value + return blueIfNoValue(data, conditions[i].changes[j], "value", L["Differences"], value and L["ON"] or L["OFF"]) + end end elseif (propertyType == "string" or propertyType == "texture") then args["condition" .. i .. "value" .. j] = { diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index f721f03..31c8bd1 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -1386,8 +1386,10 @@ function OptionsPrivate.CreateFrame() for _, id in ipairs(batchSelection) do if not alreadySelected[id] then - displayButtons[id]:Pick() - tinsert(tempGroup.controlledChildren, id) + if displayButtons[id].frame:IsVisible() then + displayButtons[id]:Pick() + tinsert(tempGroup.controlledChildren, id) + end end end frame:ClearOptions(tempGroup.id) diff --git a/WeakAurasOptions/RegionOptions/AuraBar.lua b/WeakAurasOptions/RegionOptions/AuraBar.lua index abd9179..d3a601b 100644 --- a/WeakAurasOptions/RegionOptions/AuraBar.lua +++ b/WeakAurasOptions/RegionOptions/AuraBar.lua @@ -6,18 +6,70 @@ local L = WeakAuras.L; -- Create region options table local function createOptions(id, data) + local statusbarList = {} + WeakAuras.Mixin(statusbarList, SharedMedia:HashTable("statusbar")) + -- Region options local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; local options = { __title = L["Progress Bar Settings"], __order = 1, - texture = { + textureSource = { type = "select", - dialogControl = "LSM30_Statusbar", order = 1, width = WeakAuras.doubleWidth, + name = L["Texture Selection Mode"], + values = { + LSM = L["LibSharedMedia"], + Picker = L["Texture Picker"] + }, + get = function() + return data.textureSource or "LSM" + end, + }, + texture = { + type = "select", + dialogControl = "WA_LSM30_StatusbarAtlas", + order = 2, + width = WeakAuras.doubleWidth, name = L["Bar Texture"], - values = AceGUIWidgetLSMlists.statusbar + values = statusbarList, + hidden = function() + return data.textureSource == "Picker" + end + }, + textureInput = { + type = "input", + width = WeakAuras.doubleWidth - 0.15, + name = L["Texture"], + order = 3, + hidden = function() + return data.textureSource ~= "Picker" + end + }, + chooseTexture = { + type = "execute", + name = L["Choose"], + width = 0.15, + order = 4, + func = function() + local path = {} + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(data, paths, { + texture = "textureInput", + color = "color", + }, OptionsPrivate.Private.texture_types, nil, true) + end, + imageWidth = 24, + imageHeight = 24, + control = "WeakAurasIcon", + image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\browse", + hidden = function() + return data.textureSource ~= "Picker" + end }, orientation = { type = "select", diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index 3dd6e91..24ba71b 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -97,3 +97,4 @@ AceGUI-Widgets\AceGuiWidget-WeakAurasProgressBar.lua AceGUI-Widgets\AceGUIWidget-WeakAurasSpinBox.lua AceGUI-Widgets\AceGUIWidget-WeakAurasInputFocus.lua AceGUI-Widgets\AceGUIWidget-WeakAurasMediaSound.lua +AceGUI-Widgets\WeakAurasStatusbarAtlasWidget.lua From 4ed4d4159b066a077535638c2c330e3a4afc9453 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 23 Jan 2025 19:40:40 +0100 Subject: [PATCH 069/153] from retail --- WeakAuras/BuffTrigger2.lua | 4 +- WeakAuras/{compat.lua => Compatibility.lua} | 0 WeakAuras/Conditions.lua | 4 +- WeakAuras/Init.lua | 2 +- .../widgets/AceGUIContainer-ScrollFrame.lua | 2 +- WeakAuras/Prototypes.lua | 6 +- WeakAuras/RegionTypes/AuraBar.lua | 66 +++++++++++++++++-- WeakAuras/RegionTypes/Texture.lua | 22 +++++-- WeakAuras/Types.lua | 6 ++ WeakAuras/WeakAuras.lua | 2 +- WeakAuras/WeakAuras.toc | 4 +- WeakAurasOptions/AuthorOptions.lua | 4 ++ WeakAurasOptions/ConditionOptions.lua | 17 ++++- WeakAurasOptions/GenericTrigger.lua | 4 +- WeakAurasOptions/WeakAurasOptions.toc | 2 +- 15 files changed, 118 insertions(+), 27 deletions(-) rename WeakAuras/{compat.lua => Compatibility.lua} (100%) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 7977473..6a5cbcf 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -2279,7 +2279,7 @@ local function createScanFunc(trigger) local names = {} for index, spellName in ipairs(trigger.ignoreAuraNames) do local spellId = WeakAuras.SafeToNumber(spellName) - local name = GetSpellInfo(spellId or 0) or spellName + local name = spellId and GetSpellInfo(spellId or 0) or spellName tinsert(names, name) end @@ -2386,7 +2386,7 @@ function BuffTrigger.Add(data) names = {} for index, spellName in ipairs(trigger.auranames) do local spellId = WeakAuras.SafeToNumber(spellName) - names[index] = GetSpellInfo(spellId or 0) or spellName + names[index] = spellId and GetSpellInfo(spellId or 0) or spellName end end diff --git a/WeakAuras/compat.lua b/WeakAuras/Compatibility.lua similarity index 100% rename from WeakAuras/compat.lua rename to WeakAuras/Compatibility.lua diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index f1298f1..55e7e17 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -42,7 +42,7 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path return value and tostring(value) or "false"; elseif(vType == "number") then return value and tostring(value) or "0"; - elseif (vType == "list") then + elseif (vType == "list" or vType == "textureLSM") then if type(value) == "string" then return string.format("%s", Private.QuotedString(value)) elseif type(value) == "number" then @@ -154,7 +154,7 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path end local function formatValueForCall(type, property) - if type == "bool" or type == "number" or type == "list" or type == "icon" or type == "string" or type == "texture" + if type == "bool" or type == "number" or type == "list" or type == "icon" or type == "string" or type == "texture" or type == "textureLSM" or type == "progressSource" then return "propertyChanges['" .. property .. "']"; diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index 52a84c3..aefcec6 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -8,7 +8,7 @@ WeakAuras.halfWidth = WeakAuras.normalWidth / 2 WeakAuras.doubleWidth = WeakAuras.normalWidth * 2 local versionStringFromToc = GetAddOnMetadata("WeakAuras", "Version") -local versionString = "5.4.0" +local versionString = "5.13.2" local buildTime = "20240701180000" local isAwesomeEnabled = C_NamePlate and C_NamePlate.GetNamePlateForUnit or false diff --git a/WeakAuras/Libs/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua b/WeakAuras/Libs/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua index cc4172f..fca34d1 100644 --- a/WeakAuras/Libs/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua +++ b/WeakAuras/Libs/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua @@ -94,7 +94,7 @@ local methods = { local status = self.status or self.localstatus local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight() local offset = status.offset or 0 - -- Give us a margin of error of 2 pixels to stop some conditions that i would blame on floating point inaccuracys + -- Give us a margin of error of 2 pixels to stop some conditions that i would blame on floating point inaccuracies -- No-one is going to miss 2 pixels at the bottom of the frame, anyhow! if viewheight < height + 2 then if self.scrollBarShown then diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 17936ba..1d23a90 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4918,7 +4918,11 @@ Private.event_prototypes = { type = "event", events = function(trigger) if trigger.use_messageType and trigger.messageType and Private.chat_message_types[trigger.messageType] then - return { ["events"] = {trigger.messageType} } + local events = {trigger.messageType} + if Private.chat_message_leader_event[trigger.messageType] then + table.insert(events, Private.chat_message_leader_event[trigger.messageType]) + end + return { events = events } end return { ["events"] = { diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 457f65f..725896b 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -11,6 +11,7 @@ local default = { iconSource = -1, progressSource = {-1, "" }, texture = "Blizzard", + textureSource = "LSM", width = 200, height = 15, orientation = "HORIZONTAL", @@ -45,6 +46,25 @@ Private.regionPrototype.AddAlphaToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; local properties = { + textureSource = { + display = {L["Bar Texture"], L["Selection Mode"]}, + setter = "SetStatusBarTextureMode", + type = "list", + values = { + LSM = L["LibSharedMedia"], + Picker = L["Texture Picker"] + } + }, + textureInput = { + display = {L["Bar Texture"], L["Texture Picker"]}, + setter = "SetStatusBarTextureInput", + type = "texture", + }, + texture = { + display = {L["Bar Texture"], L["LibSharedMedia"]}, + setter = "SetStatusBarTextureLSM", + type = "textureLSM", + }, barColor = { display = L["Bar Color"], setter = "Color", @@ -896,6 +916,40 @@ local funcs = { end end, + SetStatusBarTextureMode = function(self, mode) + if self.textureSource == mode then + return + end + self.textureSource = mode + self:UpdateStatusBarTexture() + end, + + SetStatusBarTextureInput = function(self, texture) + if self.textureInput == texture then + return + end + self.textureInput = texture + self:UpdateStatusBarTexture() + end, + + SetStatusBarTextureLSM = function(self, texture) + if self.texture == texture then + return + end + self.texture = texture + self:UpdateStatusBarTexture() + end, + + UpdateStatusBarTexture = function(self) + local texturePath + if self.textureSource == "Picker" then + texturePath = self.textureInput or "" + else + texturePath = SharedMedia:Fetch("statusbar", self.texture) or "" + end + self.bar:SetStatusBarTexture(texturePath) + end, + SetIconVisible = function(self, iconVisible) if (self.iconVisible == iconVisible) then return @@ -1125,13 +1179,11 @@ local function modify(parent, region, data) end -- Update texture settings - local texturePath - if data.textureSource == "Picker" then - texturePath = data.textureInput or "" - else - texturePath = SharedMedia:Fetch("statusbar", data.texture) or ""; - end - bar:SetStatusBarTexture(texturePath); + region.textureSource = data.textureSource + region.texture = data.texture + region.textureInput = data.textureInput + + region:UpdateStatusBarTexture(); bar:SetBackgroundColor(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]); -- Update spark settings bar.spark:SetTexture(data.sparkTexture); diff --git a/WeakAuras/RegionTypes/Texture.lua b/WeakAuras/RegionTypes/Texture.lua index 5fffc9a..9285aa4 100644 --- a/WeakAuras/RegionTypes/Texture.lua +++ b/WeakAuras/RegionTypes/Texture.lua @@ -27,6 +27,11 @@ Private.regionPrototype.AddAlphaToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; local properties = { + texture = { + display = L["Texture"], + setter = "SetTexture", + type = "texture", + }, color = { display = L["Color"], setter = "Color", @@ -82,7 +87,6 @@ end local function modify(parent, region, data) Private.regionPrototype.modify(parent, region, data); - region.texture:SetTexture(data.texture); region.texture:SetDesaturated(data.desaturate) region:SetWidth(data.width); region:SetHeight(data.height); @@ -178,12 +182,22 @@ local function modify(parent, region, data) end function region:Update() - if region.state.texture then - region.texture:SetTexture(region.state.texture); + if self.state.texture then + self:SetTexture(self.state.texture) end - region:UpdateProgress() + self:UpdateProgress() end + function region:SetTexture(texture) + if self.textureName == texture then + return + end + self.textureName = texture + self.texture:SetTexture(self.textureName); + DoTexCoord() + end + region:SetTexture(data.texture) + function region:Color(r, g, b, a) region.color_r = r; region.color_g = g; diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index df12210..7c2b734 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -2170,6 +2170,12 @@ Private.chat_message_types = { CHAT_MSG_LOOT = L["Loot"], } +Private.chat_message_leader_event = { + CHAT_MSG_BATTLEGROUND = "CHAT_MSG_BATTLEGROUND_LEADER", + CHAT_MSG_PARTY = "CHAT_MSG_PARTY_LEADER", + CHAT_MSG_RAID = "CHAT_MSG_RAID_LEADER" +} + Private.send_chat_message_types = { WHISPER = L["Whisper"], CHANNEL = L["Channel"], diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 8aab8b8..50570aa 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3460,7 +3460,7 @@ end -- The constants table has weak keys do local function CompareProgressValueTables(a, b) - -- For auto/manual progreess, only compare a[] with b[1] + -- For auto/manual progress, only compare a[] with b[1] if a[1] == -1 or a[1] == 0 then return a[1] == b[1] end diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index eb42527..498509a 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -1,7 +1,7 @@ ## Interface: 30300 ## Title: WeakAuras ## Author: The WeakAuras Team -## Version: 5.4.0 +## Version: 5.13.2 ## Notes: A powerful, comprehensive utility for displaying graphics and information based on buffs, debuffs, and other triggers. ## Notes-esES: Potente y completa aplicación que te permitirá mostrar por pantalla múltiples diseños, basados en beneficios, perjuicios y otros activadores. ## Notes-deDE: Ein leistungsfähiges, umfassendes Addon zur grafischen Darstellung von Informationen von Auren, Cooldowns, Timern und vielem mehr. @@ -19,7 +19,7 @@ Templates.lua Templates.xml -compat.lua +Compatibility.lua Pools.lua # External code + initialization diff --git a/WeakAurasOptions/AuthorOptions.lua b/WeakAurasOptions/AuthorOptions.lua index ac61d93..b2ce0be 100644 --- a/WeakAurasOptions/AuthorOptions.lua +++ b/WeakAurasOptions/AuthorOptions.lua @@ -1472,6 +1472,8 @@ local function up(data, options, index) local dereferencedParent = parent.references[id].options[parent.references[id].index] if dereferencedParent.nameSource == optionID then dereferencedParent.nameSource = optionID - 1 + elseif dereferencedParent.nameSource == optionID - 1 then + dereferencedParent.nameSource = optionID end end OptionsPrivate.MoveCollapseDataUp(id, "author", path) @@ -1501,6 +1503,8 @@ local function down(data, options, index) local dereferencedParent = parent.references[id].options[parent.references[id].index] if dereferencedParent.nameSource == optionID then dereferencedParent.nameSource = optionID + 1 + elseif dereferencedParent.nameSource == optionID + 1 then + dereferencedParent.nameSource = optionID end end local childOptions = optionData.options diff --git a/WeakAurasOptions/ConditionOptions.lua b/WeakAurasOptions/ConditionOptions.lua index 22e8da4..0b10f7d 100644 --- a/WeakAurasOptions/ConditionOptions.lua +++ b/WeakAurasOptions/ConditionOptions.lua @@ -50,6 +50,8 @@ local AddonName, OptionsPrivate = ... local WeakAuras = WeakAuras; local L = WeakAuras.L; +local SharedMedia = LibStub("LibSharedMedia-3.0"); + local function addSpace(args, order) args["space" .. order] = { type = "description", @@ -613,12 +615,21 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA set = setValueColor } order = order + 1; - elseif (propertyType == "list" or property == "progressSource") then + elseif (propertyType == "list" or propertyType == "progressSource" or propertyType == "textureLSM") then local values = property and allProperties.propertyMap[property] and allProperties.propertyMap[property].values; + local dialogControl + + if propertyType == "textureLSM" then + dialogControl = "WA_LSM30_StatusbarAtlas" + local statusbarList = {} + WeakAuras.Mixin(statusbarList, SharedMedia:HashTable("statusbar")) + values = statusbarList + end args["condition" .. i .. "value" .. j] = { type = "select", width = WeakAuras.normalWidth, values = values, + dialogControl = dialogControl, name = blueIfNoValue(data, conditions[i].changes[j], "value", L["Differences"], ""), desc = descIfNoValue(data, conditions[i].changes[j], "value", propertyType, values), order = order, @@ -663,7 +674,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA return true end - args["condition" .. i .. "progressSoruceManualValue" .. j] = { + args["condition" .. i .. "progressSourceManualValue" .. j] = { type = "range", control = "WeakAurasSpinBox", width = WeakAuras.normalWidth, @@ -681,7 +692,7 @@ local function addControlsForChange(args, order, data, conditionVariable, totalA } order = order + 1 - args["condition" .. i .. "progressSoruceManualTotal" .. j] = { + args["condition" .. i .. "progressSourceManualTotal" .. j] = { type = "range", control = "WeakAurasSpinBox", width = WeakAuras.normalWidth, diff --git a/WeakAurasOptions/GenericTrigger.lua b/WeakAurasOptions/GenericTrigger.lua index 91a6882..81a7a8f 100644 --- a/WeakAurasOptions/GenericTrigger.lua +++ b/WeakAurasOptions/GenericTrigger.lua @@ -454,7 +454,7 @@ local function GetGenericTriggerOptions(data, triggernum) { subeventPrefix = { type = "select", - name = L["Message Prefix"], + name = L["Subevent"], width = WeakAuras.normalWidth, order = 8, values = OptionsPrivate.Private.subevent_prefix_types, @@ -471,7 +471,7 @@ local function GetGenericTriggerOptions(data, triggernum) subeventSuffix = { type = "select", width = WeakAuras.normalWidth, - name = L["Message Suffix"], + name = L["Subevent Suffix"], order = 9, values = OptionsPrivate.Private.subevent_suffix_types, sorting = OptionsPrivate.Private.SortOrderForValues(OptionsPrivate.Private.subevent_suffix_types), diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index 24ba71b..98e917e 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -1,7 +1,7 @@ ## Interface: 30300 ## Title: WeakAuras Options ## Author: The WeakAuras Team -## Version: 5.4.0 +## Version: 5.13.2 ## Notes: Options for WeakAuras ## Notes-esES: Opciones para WeakAuras ## Notes-deDE: Optionen für WeakAuras From 10cc1138022d562923a6e9ba1fc0e62fa01744c8 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 23 Jan 2025 20:33:10 +0100 Subject: [PATCH 070/153] from retail --- WeakAuras/GenericTrigger.lua | 109 +++++++++++++++++------------------ WeakAuras/Prototypes.lua | 100 ++++++++++++++++++++++---------- 2 files changed, 121 insertions(+), 88 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 07c8539..9128158 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -842,18 +842,23 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 return updateTriggerState; end +local function getGameEventFromComposedEvent(composedEvent) + local separatorPosition = composedEvent:find(":", 1, true) + return separatorPosition == nil and composedEvent or composedEvent:sub(1, separatorPosition - 1) +end + function WeakAuras.ScanEvents(event, arg1, arg2, ...) - local orgEvent = event; - Private.StartProfileSystem("generictrigger " .. orgEvent ) + local system = getGameEventFromComposedEvent(event) + Private.StartProfileSystem("generictrigger " .. system) local event_list = loaded_events[event]; if (not event_list) then - Private.StopProfileSystem("generictrigger " .. orgEvent ) + Private.StopProfileSystem("generictrigger " .. system) return end if(event == "COMBAT_LOG_EVENT_UNFILTERED") then event_list = event_list[arg2]; if (not event_list) then - Private.StopProfileSystem("generictrigger " .. orgEvent ) + Private.StopProfileSystem("generictrigger " .. system) return; end WeakAuras.ScanEventsInternal(event_list, event, arg1, arg2, ...); @@ -867,7 +872,7 @@ function WeakAuras.ScanEvents(event, arg1, arg2, ...) else WeakAuras.ScanEventsInternal(event_list, event, arg1, arg2, ...); end - Private.StopProfileSystem("generictrigger " .. orgEvent ) + Private.StopProfileSystem("generictrigger " .. system) end function WeakAuras.ScanUnitEvents(event, unit, ...) @@ -1333,6 +1338,15 @@ function LoadEvent(id, triggernum, data) loaded_events[event][id][triggernum] = data; end end + -- this special internal_events function is run when aura load instead of when it is added + if data.loadInternalEventFunc then + local internal_events = data.loadInternalEventFunc(data.trigger) + for index, event in pairs(internal_events) do + loaded_events[event] = loaded_events[event] or {}; + loaded_events[event][id] = loaded_events[event][id] or {}; + loaded_events[event][id][triggernum] = data; + end + end if data.unit_events then local includePets = data.includePets for unit, events in pairs(data.unit_events) do @@ -1552,7 +1566,7 @@ function GenericTrigger.Add(data, region) local includePets local trigger_subevents = {}; local force_events = false; - local durationFunc, overlayFuncs, nameFunc, iconFunc, textureFunc, stacksFunc, loadFunc; + local durationFunc, overlayFuncs, nameFunc, iconFunc, textureFunc, stacksFunc, loadFunc, loadInternalEventFunc; local tsuConditionVariables; local prototype = nil local automaticAutoHide @@ -1592,6 +1606,7 @@ function GenericTrigger.Add(data, region) textureFunc = prototype.textureFunc; stacksFunc = prototype.stacksFunc; loadFunc = prototype.loadFunc; + loadInternalEventFunc = prototype.loadInternalEventFunc; if (prototype.overlayFuncs) then overlayFuncs = {}; @@ -1795,6 +1810,7 @@ function GenericTrigger.Add(data, region) event = trigger.event, events = trigger_events, internal_events = internal_events, + loadInternalEventFunc = loadInternalEventFunc, force_events = force_events, unit_events = trigger_unit_events, includePets = includePets, @@ -1878,26 +1894,6 @@ do end end -local combatLogUpgrade = { - ["sourceunit"] = "sourceUnit", - ["source"] = "sourceName", - ["destunit"] = "destUnit", - ["dest"] = "destName" -} - -local oldPowerTriggers = { - ["Combo Points"] = 4, - ["Holy Power"] = 9, - ["Insanity"] = 13, - ["Chi Power"] = 12, - ["Astral Power"] = 8, - ["Maelstrom"] = 11, - ["Arcane Charges"] = 16, - ["Fury"] = 17, - ["Pain"] = 18, - ["Shards"] = 7, -} - --############################# --# Support code for triggers # --############################# @@ -2365,7 +2361,7 @@ do end end end - elseif(event == "UNIT_INVENTORY_CHANGED" or event == "BAG_UPDATE_COOLDOWN" or event == "PLAYER_EQUIPMENT_CHANGED") then + elseif(event == "UNIT_INVENTORY_CHANGED" and ... and ... == "player" or event == "BAG_UPDATE_COOLDOWN" or event == "PLAYER_EQUIPMENT_CHANGED") then Private.CheckItemSlotCooldowns(); end Private.StopProfileSystem("generictrigger cd tracking"); @@ -2480,14 +2476,14 @@ do itemCdDurs[id] = nil; itemCdExps[id] = nil; itemCdEnabled[id] = 1; - WeakAuras.ScanEvents("ITEM_COOLDOWN_READY", id); + WeakAuras.ScanEvents("ITEM_COOLDOWN_READY:" .. id, id); end local function ItemSlotCooldownFinished(id) itemSlotsCdHandles[id] = nil; itemSlotsCdDurs[id] = nil; itemSlotsCdExps[id] = nil; - WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_READY", id); + WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_READY:" .. id, id); end function Private.CheckRuneCooldown() @@ -2588,7 +2584,7 @@ do end if changed and not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("SPELL_COOLDOWN_CHANGED", id) + WeakAuras.ScanEvents("SPELL_COOLDOWN_CHANGED:" .. id, id) end end end @@ -2613,20 +2609,20 @@ do if not WeakAuras.IsPaused() then if nowReady then - WeakAuras.ScanEvents("SPELL_COOLDOWN_READY", id); + WeakAuras.ScanEvents("SPELL_COOLDOWN_READY:" .. id, id) end if changed or chargesChanged then - WeakAuras.ScanEvents("SPELL_COOLDOWN_CHANGED", id); + WeakAuras.ScanEvents("SPELL_COOLDOWN_CHANGED:" .. id, id) end if (chargesDifference ~= 0 ) then - WeakAuras.ScanEvents("SPELL_CHARGES_CHANGED", id, chargesDifference, spellCount or 0); + WeakAuras.ScanEvents("SPELL_CHARGES_CHANGED:" .. id, id, chargesDifference, spellCount or 0); end end end - function Private.CheckSpellCooldows(runeDuration) + function Private.CheckSpellCooldowns(runeDuration) for id, _ in pairs(spells) do Private.CheckSpellCooldown(id, runeDuration) end @@ -2660,7 +2656,7 @@ do itemCdExps[id] = endTime; itemCdHandles[id] = timer:ScheduleTimer(ItemCooldownFinished, endTime - time, id); if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_COOLDOWN_STARTED", id) + WeakAuras.ScanEvents("ITEM_COOLDOWN_STARTED:" .. id, id) end itemCdEnabledChanged = false; elseif(itemCdExps[id] ~= endTime) then @@ -2672,7 +2668,7 @@ do itemCdExps[id] = endTime; itemCdHandles[id] = timer:ScheduleTimer(ItemCooldownFinished, endTime - time, id); if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_COOLDOWN_CHANGED", id) + WeakAuras.ScanEvents("ITEM_COOLDOWN_CHANGED:" .. id, id) end itemCdEnabledChanged = false; end @@ -2690,7 +2686,7 @@ do end end if (itemCdEnabledChanged and not WeakAuras.IsPaused()) then - WeakAuras.ScanEvents("ITEM_COOLDOWN_CHANGED", id); + WeakAuras.ScanEvents("ITEM_COOLDOWN_CHANGED:" .. id, id); end end end @@ -2715,7 +2711,7 @@ do itemSlotsCdExps[id] = endTime; itemSlotsCdHandles[id] = timer:ScheduleTimer(ItemSlotCooldownFinished, endTime - time, id); if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_STARTED", id) + WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_STARTED:" .. id, id) end elseif(itemSlotsCdExps[id] ~= endTime) then -- Cooldown is now different @@ -2726,7 +2722,7 @@ do itemSlotsCdExps[id] = endTime; itemSlotsCdHandles[id] = timer:ScheduleTimer(ItemSlotCooldownFinished, endTime - time, id); if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_CHANGED", id) + WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_CHANGED:" .. id, id) end end elseif(duration > 0) then @@ -2745,7 +2741,7 @@ do local newItemId = GetInventoryItemID("player", id); if (itemId ~= newItemId) then if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_ITEM_CHANGED") + WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_ITEM_CHANGED:" .. id, id) end itemSlots[id] = newItemId or 0; end @@ -2755,7 +2751,7 @@ do function Private.CheckCooldownReady() CheckGCD(); Private.CheckRuneCooldown(); - Private.CheckSpellCooldows(); + Private.CheckSpellCooldowns(); Private.CheckItemCooldowns(); Private.CheckItemSlotCooldowns(); end @@ -3143,7 +3139,7 @@ do end local function tenchUpdate() - Private.StartProfileSystem("generictrigger"); + Private.StartProfileSystem("generictrigger temporary enchant"); local _, mh_rem, oh_rem, rw_rem, re_charges _, mh_rem, mh_charges, _, oh_rem, oh_charges, _, rw_rem, rw_charges = GetWeaponEnchantInfo(); local time = GetTime(); @@ -3181,13 +3177,14 @@ do rw_icon = GetInventoryItemTexture("player", rw) end WeakAuras.ScanEvents("TENCH_UPDATE"); - Private.StopProfileSystem("generictrigger"); + Private.StopProfileSystem("generictrigger temporary enchant"); end - tenchFrame:SetScript("OnEvent", function() - Private.StartProfileSystem("generictrigger"); + tenchFrame:SetScript("OnEvent", function(_, unit, ...) + if unit and unit ~= "player" then return end + Private.StartProfileSystem("generictrigger temporary enchant"); timer:ScheduleTimer(tenchUpdate, 0.1); - Private.StopProfileSystem("generictrigger"); + Private.StopProfileSystem("generictrigger temporary enchant"); end); tenchUpdate(); @@ -3217,9 +3214,9 @@ do petFrame:RegisterEvent("UNIT_PET") petFrame:SetScript("OnEvent", function(_, event, unit) if unit ~= "player" then return end - Private.StartProfileSystem("generictrigger") + Private.StartProfileSystem("generictrigger pet update") WeakAuras.ScanEvents("PET_UPDATE", "pet") - Private.StopProfileSystem("generictrigger") + Private.StopProfileSystem("generictrigger pet update") end) end end @@ -3319,7 +3316,7 @@ do local isMounted = IsMounted(); local function checkForMounted(self, elaps) - Private.StartProfileSystem("generictrigger"); + Private.StartProfileSystem("generictrigger mounted"); elapsed = elapsed + elaps if(isMounted ~= IsMounted()) then isMounted = IsMounted(); @@ -3329,7 +3326,7 @@ do if(elapsed > delay) then mountedFrame:SetScript("OnUpdate", nil); end - Private.StopProfileSystem("generictrigger"); + Private.StopProfileSystem("generictrigger mounted"); end function WeakAuras.WatchForMounts() @@ -3350,13 +3347,13 @@ do local playerMovingFrame = nil local function PlayerMoveSpeedUpdate() - Private.StartProfileSystem("generictrigger"); + Private.StartProfileSystem("generictrigger player moving"); local speed = GetUnitSpeed("player") if speed ~= playerMovingFrame.speed then playerMovingFrame.speed = speed WeakAuras.ScanEvents("PLAYER_MOVE_SPEED_UPDATE") end - Private.StopProfileSystem("generictrigger"); + Private.StopProfileSystem("generictrigger player moving"); end function WeakAuras.WatchPlayerMoveSpeed() @@ -3460,10 +3457,10 @@ function WeakAuras.RegisterItemCountWatch() itemCountWatchFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED"); itemCountWatchFrame:SetScript("OnEvent", function(_, _, unit) if unit ~= "player" then return end - Private.StartProfileSystem("generictrigger"); + Private.StartProfileSystem("generictrigger item count"); timer:ScheduleTimer(WeakAuras.ScanEvents, 0.2, "ITEM_COUNT_UPDATE"); timer:ScheduleTimer(WeakAuras.ScanEvents, 0.5, "ITEM_COUNT_UPDATE"); - Private.StopProfileSystem("generictrigger"); + Private.StopProfileSystem("generictrigger item count"); end); end end @@ -3505,7 +3502,7 @@ do end queuedActionFrame:RegisterEvent("ACTIONBAR_SLOT_CHANGED") queuedActionFrame:SetScript("OnEvent", function(_, _, slotID) - Private.StartProfileSystem("generictrigger"); + Private.StartProfileSystem("generictrigger queued action"); local spellID = GetActionSpellID(slotID) if spellID then buttonIDList[slotID] = spellID @@ -3514,7 +3511,7 @@ do spellIDList[buttonIDList[slotID]] = nil buttonIDList[slotID] = nil end - Private.StopProfileSystem("generictrigger"); + Private.StopProfileSystem("generictrigger queued action"); end) end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 1d23a90..1da752a 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3118,10 +3118,17 @@ Private.event_prototypes = { ["Cooldown Progress (Spell)"] = { type = "spell", events = {}, - internal_events = function(trigger, untrigger) + loadInternalEventFunc = function(trigger, untrigger) + trigger.spellName = type(trigger.spellName) ~= "table" and trigger.spellName or 0; + local spellName; + if (trigger.use_exact_spellName) then + spellName = trigger.spellName; + else + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; + end local events = { - "SPELL_COOLDOWN_CHANGED", - "COOLDOWN_REMAINING_CHECK", + "SPELL_COOLDOWN_CHANGED:" .. spellName, + "COOLDOWN_REMAINING_CHECK:" .. spellName, "WA_DELAYED_PLAYER_ENTERING_WORLD" }; if (trigger.use_showgcd) then @@ -3204,11 +3211,12 @@ Private.event_prototypes = { remaining = expirationTime - GetTime(); local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then - Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); + local event = "COOLDOWN_REMAINING_CHECK:" .. %s + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck, event); end end ]]; - ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0); + ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0, spellName); end return ret; @@ -3397,9 +3405,16 @@ Private.event_prototypes = { ["Cooldown Ready (Spell)"] = { type = "spell", events = {}, - internal_events = { - "SPELL_COOLDOWN_READY", - }, + loadInternalEventFunc = function(trigger, untrigger) + trigger.spellName = trigger.spellName or 0; + local spellName; + if (trigger.use_exact_spellName) then + spellName = trigger.spellName; + else + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; + end + return { "SPELL_COOLDOWN_READY:" .. spellName } + end, name = L["Cooldown Ready Event"], loadFunc = function(trigger) trigger.spellName = trigger.spellName or 0; @@ -3466,9 +3481,16 @@ Private.event_prototypes = { ["Charges Changed"] = { type = "spell", events = {}, - internal_events = { - "SPELL_CHARGES_CHANGED", - }, + loadInternalEventFunc = function(trigger, untrigger) + trigger.spellName = trigger.spellName or 0; + local spellName; + if (trigger.use_exact_spellName) then + spellName = trigger.spellName; + else + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; + end + return { "SPELL_CHARGES_CHANGED:" .. spellName } + end, name = L["Charges Changed Event"], loadFunc = function(trigger) trigger.spellName = trigger.spellName or 0; @@ -3552,11 +3574,13 @@ Private.event_prototypes = { type = "item", events = {}, internal_events = function(trigger, untrigger) + trigger.itemName = trigger.itemName or 0; + local itemName = type(trigger.itemName) == "number" and trigger.itemName or "[["..trigger.itemName.."]]"; local events = { - "ITEM_COOLDOWN_READY", - "ITEM_COOLDOWN_CHANGED", - "ITEM_COOLDOWN_STARTED", - "COOLDOWN_REMAINING_CHECK", + "ITEM_COOLDOWN_READY:" .. itemName, + "ITEM_COOLDOWN_CHANGED:" .. itemName, + "ITEM_COOLDOWN_STARTED:" .. itemName, + "COOLDOWN_REMAINING_CHECK:" .. itemName, } if (trigger.use_showgcd) then tinsert(events, "GCD_START"); @@ -3569,7 +3593,6 @@ Private.event_prototypes = { name = L["Cooldown Progress (Item)"], loadFunc = function(trigger) trigger.itemName = trigger.itemName or 0; - local itemName = type(trigger.itemName) == "number" and trigger.itemName or "[["..trigger.itemName.."]]"; WeakAuras.WatchItemCooldown(trigger.itemName); if (trigger.use_showgcd) then WeakAuras.WatchGCD(); @@ -3591,10 +3614,11 @@ Private.event_prototypes = { local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0; local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then - Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); + local event = "COOLDOWN_REMAINING_CHECK:" .. %s + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck, event); end ]]; - ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0); + ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0, itemName); end return ret:format(itemName, trigger.use_showgcd and "true" or "false", @@ -3722,12 +3746,13 @@ Private.event_prototypes = { } }, internal_events = function(trigger, untrigger) + local slot = trigger.itemSlot or 0 local events = { - "ITEM_SLOT_COOLDOWN_STARTED", - "ITEM_SLOT_COOLDOWN_CHANGED", - "COOLDOWN_REMAINING_CHECK", - "ITEM_SLOT_COOLDOWN_ITEM_CHANGED", - "ITEM_SLOT_COOLDOWN_READY", + "ITEM_SLOT_COOLDOWN_STARTED:" .. slot, + "ITEM_SLOT_COOLDOWN_CHANGED:" .. slot, + "COOLDOWN_REMAINING_CHECK:" .. slot, + "ITEM_SLOT_COOLDOWN_ITEM_CHANGED:" .. slot, + "ITEM_SLOT_COOLDOWN_READY:" .. slot, "WA_DELAYED_PLAYER_ENTERING_WORLD" } @@ -3760,10 +3785,11 @@ Private.event_prototypes = { local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0; local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then - Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck); + local event = "COOLDOWN_REMAINING_CHECK:" .. %s + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck, event); end ]]; - ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0); + ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0, trigger.itemSlot or 0); end return ret:format(trigger.use_showgcd and "true" or "false", trigger.itemSlot or "0", @@ -3876,9 +3902,10 @@ Private.event_prototypes = { ["Cooldown Ready (Item)"] = { type = "item", events = {}, - internal_events = { - "ITEM_COOLDOWN_READY", - }, + internal_events = function(trigger) + trigger.itemName = trigger.itemName or 0 + return { "ITEM_COOLDOWN_READY:" .. trigger.itemName } + end, name = L["Cooldown Ready Event (Item)"], loadFunc = function(trigger) trigger.itemName = trigger.itemName or 0; @@ -4130,9 +4157,16 @@ Private.event_prototypes = { ["player"] = { "UNIT_POWER", "UNIT_ENERGY", "UNIT_MANA", "UNIT_RAGE" } } }, - internal_events = { - "SPELL_COOLDOWN_CHANGED", - }, + loadInternalEventFunc = function(trigger) + trigger.spellName = trigger.spellName or 0; + local spellName + if (trigger.use_exact_spellName) then + spellName = trigger.spellName + else + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; + end + return { "SPELL_COOLDOWN_CHANGED:" .. spellName } + end, force_events = "SPELL_UPDATE_USABLE", name = L["Action Usable"], statesParameter = "one", @@ -5343,8 +5377,10 @@ Private.event_prototypes = { type = "item", events = { ["events"] = { - "UNIT_INVENTORY_CHANGED", "PLAYER_EQUIPMENT_CHANGED", + }, + ["unit_events"] = { + ["player"] = {"UNIT_INVENTORY_CHANGED"} } }, internal_events = { "WA_DELAYED_PLAYER_ENTERING_WORLD", }, From df23f7238ee7636b1bf5bf70fcb3f29dfb5fd8ef Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 23 Jan 2025 22:04:34 +0100 Subject: [PATCH 071/153] from retail --- WeakAuras/BuffTrigger2.lua | 2 +- WeakAuras/Conditions.lua | 3 +- WeakAuras/GenericTrigger.lua | 374 +++++++++++------- WeakAuras/Prototypes.lua | 78 ++-- WeakAuras/Types.lua | 21 +- WeakAuras/WeakAuras.lua | 5 +- WeakAurasOptions/BuffTrigger2.lua | 12 +- .../OptionsFrames/OptionsFrame.lua | 8 +- 8 files changed, 303 insertions(+), 200 deletions(-) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 6a5cbcf..9585e3f 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -997,7 +997,7 @@ local function GetAllUnits(unit, allUnits, includePets) elseif unit == "arena" then max = 5 elseif unit == "nameplate" then - max = C_NamePlate and C_NamePlate.GetNamePlates and #C_NamePlate.GetNamePlates() or 40 + max = 100 else return function() end end diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index 55e7e17..c673a87 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -341,8 +341,7 @@ local function CreateTestForCondition(data, input, allConditionsTemplate, usedSt local found = 0 local op = %q local range = %s - local max = C_NamePlate and C_NamePlate.GetNamePlates and #C_NamePlate.GetNamePlates() or 40 - for i = 1, max do + for i = 1, 100 do local unit = "nameplate" .. i if UnitExists(unit) and UnitCanAttack("player", unit) and WeakAuras.CheckRange(unit, range, op) then found = found + 1 diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 9128158..aa940e7 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -706,7 +706,7 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 end elseif (data.statesParameter == "unit") then if arg1 then - if Private.multiUnitUnits[data.trigger.unit] or data.trigger.unit == "nameplate" then + if Private.multiUnitUnits[data.trigger.unit] then unitForUnitTrigger = arg1 cloneIdForUnitTrigger = arg1 else @@ -847,6 +847,16 @@ local function getGameEventFromComposedEvent(composedEvent) return separatorPosition == nil and composedEvent or composedEvent:sub(1, separatorPosition - 1) end +function Private.ScanEventsByID(event, id, ...) + if loaded_events[event] then + WeakAuras.ScanEvents(event, id, ...) + end + local eventWithID = event .. ":" .. id + if loaded_events[eventWithID] then + WeakAuras.ScanEvents(eventWithID, id, ...) + end +end + function WeakAuras.ScanEvents(event, arg1, arg2, ...) local system = getGameEventFromComposedEvent(event) Private.StartProfileSystem("generictrigger " .. system) @@ -1142,8 +1152,8 @@ function HandleEvent(frame, event, arg1, arg2, ...) end if (event == "PLAYER_ENTERING_WORLD") then timer:ScheduleTimer(function() - Private.StartProfileSystem("generictrigger WA_DELAYED_PLAYER_ENTERING_WORLD"); HandleEvent(frame, "WA_DELAYED_PLAYER_ENTERING_WORLD"); + Private.StartProfileSystem("generictrigger WA_DELAYED_PLAYER_ENTERING_WORLD"); Private.ScanForLoads(nil, "WA_DELAYED_PLAYER_ENTERING_WORLD") Private.CheckCooldownReady(); Private.StopProfileSystem("generictrigger WA_DELAYED_PLAYER_ENTERING_WORLD"); @@ -1260,7 +1270,7 @@ local function MultiUnitLoop(Func, unit, includePets, ...) Func(unit..i, ...) end elseif unit == "nameplate" then - for i = 1, 400 do + for i = 1, 100 do Func(unit..i, ...) end elseif unit == "group" then @@ -1741,6 +1751,8 @@ function GenericTrigger.Add(data, region) tinsert(trigger_subevents, subevent) hasParam = true end + elseif Private.InternalEventByIDList[trueEvent] then + tinsert(trigger_events, trueEvent..":"..i) elseif trueEvent:match("^UNIT_") then isUnitEvent = true @@ -2476,14 +2488,14 @@ do itemCdDurs[id] = nil; itemCdExps[id] = nil; itemCdEnabled[id] = 1; - WeakAuras.ScanEvents("ITEM_COOLDOWN_READY:" .. id, id); + Private.ScanEventsByID("ITEM_COOLDOWN_READY", id); end local function ItemSlotCooldownFinished(id) itemSlotsCdHandles[id] = nil; itemSlotsCdDurs[id] = nil; itemSlotsCdExps[id] = nil; - WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_READY:" .. id, id); + Private.ScanEventsByID("ITEM_SLOT_COOLDOWN_READY", id); end function Private.CheckRuneCooldown() @@ -2584,7 +2596,7 @@ do end if changed and not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("SPELL_COOLDOWN_CHANGED:" .. id, id) + Private.ScanEventsByID("SPELL_COOLDOWN_CHANGED", id) end end end @@ -2609,15 +2621,15 @@ do if not WeakAuras.IsPaused() then if nowReady then - WeakAuras.ScanEvents("SPELL_COOLDOWN_READY:" .. id, id) + Private.ScanEventsByID("SPELL_COOLDOWN_READY", id) end if changed or chargesChanged then - WeakAuras.ScanEvents("SPELL_COOLDOWN_CHANGED:" .. id, id) + Private.ScanEventsByID("SPELL_COOLDOWN_CHANGED", id) end if (chargesDifference ~= 0 ) then - WeakAuras.ScanEvents("SPELL_CHARGES_CHANGED:" .. id, id, chargesDifference, spellCount or 0); + Private.ScanEventsByID("SPELL_CHARGES_CHANGED", id, chargesDifference, spellCount or 0); end end end @@ -2656,7 +2668,7 @@ do itemCdExps[id] = endTime; itemCdHandles[id] = timer:ScheduleTimer(ItemCooldownFinished, endTime - time, id); if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_COOLDOWN_STARTED:" .. id, id) + Private.ScanEventsByID("ITEM_COOLDOWN_STARTED", id) end itemCdEnabledChanged = false; elseif(itemCdExps[id] ~= endTime) then @@ -2668,7 +2680,7 @@ do itemCdExps[id] = endTime; itemCdHandles[id] = timer:ScheduleTimer(ItemCooldownFinished, endTime - time, id); if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_COOLDOWN_CHANGED:" .. id, id) + Private.ScanEventsByID("ITEM_COOLDOWN_CHANGED", id) end itemCdEnabledChanged = false; end @@ -2686,7 +2698,7 @@ do end end if (itemCdEnabledChanged and not WeakAuras.IsPaused()) then - WeakAuras.ScanEvents("ITEM_COOLDOWN_CHANGED:" .. id, id); + Private.ScanEventsByID("ITEM_COOLDOWN_CHANGED", id); end end end @@ -2711,7 +2723,7 @@ do itemSlotsCdExps[id] = endTime; itemSlotsCdHandles[id] = timer:ScheduleTimer(ItemSlotCooldownFinished, endTime - time, id); if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_STARTED:" .. id, id) + Private.ScanEventsByID("ITEM_SLOT_COOLDOWN_STARTED", id) end elseif(itemSlotsCdExps[id] ~= endTime) then -- Cooldown is now different @@ -2722,7 +2734,7 @@ do itemSlotsCdExps[id] = endTime; itemSlotsCdHandles[id] = timer:ScheduleTimer(ItemSlotCooldownFinished, endTime - time, id); if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_CHANGED:" .. id, id) + Private.ScanEventsByID("ITEM_SLOT_COOLDOWN_CHANGED", id) end end elseif(duration > 0) then @@ -2741,7 +2753,7 @@ do local newItemId = GetInventoryItemID("player", id); if (itemId ~= newItemId) then if not WeakAuras.IsPaused() then - WeakAuras.ScanEvents("ITEM_SLOT_COOLDOWN_ITEM_CHANGED:" .. id, id) + Private.ScanEventsByID("ITEM_SLOT_COOLDOWN_ITEM_CHANGED", id) end itemSlots[id] = newItemId or 0; end @@ -2891,12 +2903,15 @@ function WeakAuras.WatchUnitChange(unit) unit = string.lower(unit) if not watchUnitChange then watchUnitChange = CreateFrame("Frame"); - watchUnitChange.unitChangeGUIDS = {} + watchUnitChange.trackedUnits = {} + watchUnitChange.unitIdToGUID = {} + watchUnitChange.GUIDToUnitIds = {} watchUnitChange.unitRoles = {} watchUnitChange.unitRaidRole = {} watchUnitChange.inRaid = IsInRaid() watchUnitChange.nameplateFaction = {} watchUnitChange.raidmark = {} + watchUnitChange.unitIsUnit = {} Private.frames["Unit Change Frame"] = watchUnitChange; watchUnitChange:RegisterEvent("PLAYER_TARGET_CHANGED") @@ -2915,115 +2930,200 @@ function WeakAuras.WatchUnitChange(unit) watchUnitChange:RegisterEvent("UNIT_PET") watchUnitChange:RegisterEvent("RAID_TARGET_UPDATE") + local function unitUpdate(unitA, eventsToSend) + local oldGUID = watchUnitChange.unitIdToGUID[unitA] + local newGUID = WeakAuras.UnitExistsFixed(unitA) and UnitGUID(unitA) + if oldGUID ~= newGUID then + eventsToSend["UNIT_CHANGED_" .. unitA] = unitA + if watchUnitChange.GUIDToUnitIds[oldGUID] then + for unitB in pairs(watchUnitChange.GUIDToUnitIds[oldGUID]) do + eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitA .. "_" .. unitB] = unitA + eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitB .. "_" .. unitA] = unitB + end + end + if watchUnitChange.GUIDToUnitIds[newGUID] then + for unitB in pairs(watchUnitChange.GUIDToUnitIds[newGUID]) do + eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitA .. "_" .. unitB] = unitA + eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitB .. "_" .. unitA] = unitB + end + end + end + -- update data + if oldGUID and watchUnitChange.GUIDToUnitIds[oldGUID] then + watchUnitChange.GUIDToUnitIds[oldGUID][unitA] = nil + if next(watchUnitChange.GUIDToUnitIds[oldGUID]) == nil then + watchUnitChange.GUIDToUnitIds[oldGUID] = nil + end + end + if newGUID then + watchUnitChange.GUIDToUnitIds[newGUID] = watchUnitChange.GUIDToUnitIds[newGUID] or {} + watchUnitChange.GUIDToUnitIds[newGUID][unitA] = true + end + watchUnitChange.unitIdToGUID[unitA] = newGUID + end + + local function markerUpdate(unit, eventsToSend) + local oldMarker = watchUnitChange.raidmark[unit] + local newMarker = GetRaidTargetIndex(unit) or 0 + if newMarker ~= oldMarker then + eventsToSend["UNIT_CHANGED_" .. unit] = unit + watchUnitChange.raidmark[unit] = newMarker + end + end + + local function markerInit(unit) + watchUnitChange.raidmark[unit] = GetRaidTargetIndex(unit) or 0 + end + + local function markerClear(unit) + watchUnitChange.raidmark[unit] = nil + end + + local function reactionUpdate(unit, eventsToSend) + local oldReaction = watchUnitChange.nameplateFaction[unit] + local newReaction = WeakAuras.GetPlayerReaction(unit) + if oldReaction ~= newReaction then + eventsToSend["UNIT_CHANGED_" .. unit] = unit + watchUnitChange.nameplateFaction[unit] = newReaction + end + end + + local function reactionInit(unit) + watchUnitChange.nameplateFaction[unit] = WeakAuras.GetPlayerReaction(unit) + end + + local function reactionClear(unit) + watchUnitChange.nameplateFaction[unit] = nil + end + + local function roleUpdate(unit, eventsToSend) + local oldRaidRole = watchUnitChange.unitRaidRole[unit] + local newRaidRole = WeakAuras.UnitRaidRole(unit) + if oldRaidRole ~= newRaidRole then + eventsToSend["UNIT_ROLE_CHANGED_" .. unit] = unit + watchUnitChange.unitRaidRole[unit] = newRaidRole + end + end + watchUnitChange:SetScript("OnEvent", function(self, event, unit) Private.StartProfileSystem("generictrigger unit change"); - if event == "UNIT_PET" then - local pet = WeakAuras.unitToPetUnit[unit] - if pet then - WeakAuras.ScanEvents("UNIT_CHANGED_" .. pet, pet) - end - elseif event == "RAID_TARGET_UPDATE" then - for unit, marker in pairs(watchUnitChange.raidmark) do - local newMarker = GetRaidTargetIndex(unit) or 0 - if marker ~= newMarker then - watchUnitChange.raidmark[unit] = newMarker - if unit:find("^nameplate%d+$") then - WeakAuras.ScanEvents("UNIT_CHANGED_nameplate", unit) - else - WeakAuras.ScanEvents("UNIT_CHANGED_" .. unit, unit) - end - end + local eventsToSend = {} + if event == "PLAYER_ENTERING_WORLD" then + for unit in pairs(watchUnitChange.unitIdToGUID) do + unitUpdate(unit, eventsToSend) + markerUpdate(unit, eventsToSend) + reactionUpdate(unit, eventsToSend) end elseif event == "NAME_PLATE_UNIT_ADDED" then - local oldGUID = watchUnitChange.unitChangeGUIDS[unit] - local newGUID = WeakAuras.UnitExistsFixed(unit) and UnitGUID(unit) - if oldGUID ~= newGUID then - WeakAuras.ScanEvents("UNIT_CHANGED_nameplate", unit) + if not watchUnitChange.trackedUnits[unit] then + Private.StopProfileSystem("generictrigger unit change"); + return end - watchUnitChange.unitChangeGUIDS[unit] = newGUID - watchUnitChange.raidmark[unit] = GetRaidTargetIndex(unit) or 0 - watchUnitChange.nameplateFaction[unit] = WeakAuras.GetPlayerReaction(unit) - WeakAuras.ScanEvents("UNIT_CHANGED_nameplate", unit) + unitUpdate(unit, eventsToSend) + markerInit(unit) + reactionInit(unit) elseif event == "NAME_PLATE_UNIT_REMOVED" then - local oldGUID = watchUnitChange.unitChangeGUIDS[unit] - local newGUID = WeakAuras.UnitExistsFixed(unit) and UnitGUID(unit) - if oldGUID ~= newGUID then - WeakAuras.ScanEvents("UNIT_CHANGED_nameplate", unit) + if not watchUnitChange.trackedUnits[unit] then + Private.StopProfileSystem("generictrigger unit change"); + return end - watchUnitChange.unitChangeGUIDS[unit] = newGUID - watchUnitChange.raidmark[unit] = nil - watchUnitChange.nameplateFaction[unit] = nil - WeakAuras.ScanEvents(event, unit) - elseif event == "UNIT_FACTION" then - local oldReaction = watchUnitChange.nameplateFaction[unit] - local newReaction = WeakAuras.GetPlayerReaction(unit) - if oldReaction ~= newReaction then - watchUnitChange.nameplateFaction[unit] = newReaction - if unit:find("^nameplate%d+$") then - WeakAuras.ScanEvents("UNIT_CHANGED_nameplate", unit) - else - WeakAuras.ScanEvents("UNIT_CHANGED_" .. unit, unit) + unitUpdate(unit, eventsToSend) + markerClear(unit) + reactionClear(unit) + elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then + for i = 1, 5 do + local unit = "boss" .. i + if watchUnitChange.trackedUnits[unit] then + unitUpdate(unit, eventsToSend) + markerInit(unit) + reactionInit(unit) end end + elseif event == "PLAYER_TARGET_CHANGED" then + if not watchUnitChange.trackedUnits["target"] then + Private.StopProfileSystem("generictrigger unit change"); + return + end + unitUpdate("target", eventsToSend) + markerInit("target") + reactionInit("target") + elseif event == "PLAYER_FOCUS_CHANGED" then + if not watchUnitChange.trackedUnits["focus"] then + Private.StopProfileSystem("generictrigger unit change"); + return + end + unitUpdate("focus", eventsToSend) + markerInit("focus") + reactionInit("focus") + elseif event == "RAID_TARGET_UPDATE" then + for unit in pairs(watchUnitChange.raidmark) do + markerUpdate(unit, eventsToSend) + end + elseif event == "UNIT_FACTION" then + if watchUnitChange.trackedUnits[unit] then + reactionUpdate(unit, eventsToSend) + end + elseif event == "UNIT_PET" then + local pet = WeakAuras.unitToPetUnit[unit] + if pet and watchUnitChange.trackedUnits[pet] then + eventsToSend["UNIT_CHANGED_" .. pet] = pet + end elseif event == "PLAYER_ROLES_ASSIGNED" then for unit in pairs(Private.multiUnitUnits.group) do - local oldRaidRole = watchUnitChange.unitRaidRole[unit] - local newRaidRole = WeakAuras.UnitRaidRole(unit) - if oldRaidRole ~= newRaidRole then - if unit:find("^nameplate%d+$") then - WeakAuras.ScanEvents("UNIT_ROLE_CHANGED_nameplate", unit) - else - WeakAuras.ScanEvents("UNIT_ROLE_CHANGED_" .. unit, unit) - end - watchUnitChange.unitRaidRole[unit] = newRaidRole + if watchUnitChange.trackedUnits[unit] then + roleUpdate(unit, eventsToSend) + end + end + elseif event == "UNIT_TARGET" then + local unitTarget = unit .. "target" + if not watchUnitChange.trackedUnits[unitTarget] then + Private.StopProfileSystem("generictrigger unit change"); + return + end + unitUpdate(unitTarget, eventsToSend) + markerInit(unitTarget) + reactionInit(unitTarget) + elseif event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" then + for unit in pairs(Private.multiUnitUnits.group) do + if watchUnitChange.trackedUnits[unit] then + unitUpdate(unit, eventsToSend) + markerInit(unit, eventsToSend) + reactionInit(unit, eventsToSend) end end - else local inRaid = IsInRaid() local inRaidChanged = inRaid ~= watchUnitChange.inRaid - - for unit, guid in pairs(watchUnitChange.unitChangeGUIDS) do - local newGuid = WeakAuras.UnitExistsFixed(unit) and UnitGUID(unit) or "" - local newMarker = GetRaidTargetIndex(unit) or 0 - if guid ~= newGuid - or newMarker ~= watchUnitChange.raidmark[unit] - or event == "PLAYER_ENTERING_WORLD" - then - if unit:find("^nameplate%d+$") then - WeakAuras.ScanEvents("UNIT_CHANGED_nameplate", unit) - else - WeakAuras.ScanEvents("UNIT_CHANGED_" .. unit, unit) - end - watchUnitChange.unitChangeGUIDS[unit] = newGuid - watchUnitChange.raidmark[unit] = newMarker - - local oldReaction = watchUnitChange.nameplateFaction[unit] - local newReaction = WeakAuras.GetPlayerReaction(unit) - if oldReaction ~= newReaction then - watchUnitChange.nameplateFaction[unit] = newReaction - if unit:find("^nameplate%d+$") then - WeakAuras.ScanEvents("UNIT_CHANGED_nameplate", unit) - else - WeakAuras.ScanEvents("UNIT_CHANGED_" .. unit, unit) - end - end - - elseif Private.multiUnitUnits.group[unit] then - -- If in raid changed we send a UNIT_CHANGED for the group units - if inRaidChanged then - WeakAuras.ScanEvents("UNIT_CHANGED_" .. unit, unit) + if inRaidChanged then + for unit in pairs(Private.multiUnitUnits.group) do + if watchUnitChange.trackedUnits[unit] and watchUnitChange.unitIdToGUID[unit] then + eventsToSend["UNIT_CHANGED_" .. unit] = unit end end + watchUnitChange.inRaid = inRaid end - watchUnitChange.inRaid = inRaid end + + -- send events + for event, unit in pairs(eventsToSend) do + WeakAuras.ScanEvents(event, unit) + end + Private.StopProfileSystem("generictrigger unit change"); end) end - watchUnitChange.unitChangeGUIDS = watchUnitChange.unitChangeGUIDS or {} - watchUnitChange.unitChangeGUIDS[unit] = UnitGUID(unit) or "" + if watchUnitChange.trackedUnits[unit] then + return + end + local guid = UnitGUID(unit) + watchUnitChange.trackedUnits[unit] = true + watchUnitChange.unitIdToGUID[unit] = guid + if guid then + watchUnitChange.GUIDToUnitIds[guid] = watchUnitChange.GUIDToUnitIds[guid] or {} + watchUnitChange.GUIDToUnitIds[guid][unit] = true + end watchUnitChange.raidmark = watchUnitChange.raidmark or {} watchUnitChange.raidmark[unit] = GetRaidTargetIndex(unit) or 0 + watchUnitChange.inRaid = IsInRaid() end local equipmentItemIDs, equipmentSetItemIDs = {}, {} @@ -3264,46 +3364,44 @@ do end -- Nameplate Target -if WeakAuras.isAwesomeEnabled() then - do - local nameplateTargetFrame = nil - local nameplateTargets = {} +do + local nameplateTargetFrame = nil + local nameplateTargets = {} - local function nameplateTargetOnEvent(self, event, unit) - if event == "NAME_PLATE_UNIT_ADDED" then - nameplateTargets[unit] = UnitGUID(unit.."-target") or true - elseif event == "NAME_PLATE_UNIT_REMOVED" then - nameplateTargets[unit] = nil - end + local function nameplateTargetOnEvent(self, event, unit) + if event == "NAME_PLATE_UNIT_ADDED" then + nameplateTargets[unit] = UnitGUID(unit.."-target") or true + elseif event == "NAME_PLATE_UNIT_REMOVED" then + nameplateTargets[unit] = nil end + end - local tick_throttle = 0.2 - local throttle_update = tick_throttle - local function nameplateTargetOnUpdate(self, delta) - throttle_update = throttle_update - delta - if throttle_update < 0 then - for unit, targetGUID in pairs(nameplateTargets) do - local newTargetGUID = UnitGUID(unit.."-target") - if (newTargetGUID == nil and targetGUID ~= true) - or (newTargetGUID ~= nil and targetGUID ~= newTargetGUID) - then - nameplateTargets[unit] = newTargetGUID or true - WeakAuras.ScanEvents("WA_UNIT_TARGET_NAME_PLATE", unit) - end + local tick_throttle = 0.2 + local throttle_update = tick_throttle + local function nameplateTargetOnUpdate(self, delta) + throttle_update = throttle_update - delta + if throttle_update < 0 then + for unit, targetGUID in pairs(nameplateTargets) do + local newTargetGUID = UnitGUID(unit.."-target") + if (newTargetGUID == nil and targetGUID ~= true) + or (newTargetGUID ~= nil and targetGUID ~= newTargetGUID) + then + nameplateTargets[unit] = newTargetGUID or true + WeakAuras.ScanEvents("WA_UNIT_TARGET_NAME_PLATE", unit) end - throttle_update = tick_throttle end + throttle_update = tick_throttle end + end - Private.frames["Nameplate Target Handler"] = nameplateTargetFrame - function WeakAuras.WatchForNameplateTargetChange() - if not nameplateTargetFrame then - nameplateTargetFrame = CreateFrame("Frame") - nameplateTargetFrame:SetScript("OnUpdate", nameplateTargetOnUpdate) - nameplateTargetFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED") - nameplateTargetFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED") - nameplateTargetFrame:SetScript("OnEvent", nameplateTargetOnEvent) - end + Private.frames["Nameplate Target Handler"] = nameplateTargetFrame + function WeakAuras.WatchForNameplateTargetChange() + if not nameplateTargetFrame then + nameplateTargetFrame = CreateFrame("Frame") + nameplateTargetFrame:SetScript("OnUpdate", nameplateTargetOnUpdate) + nameplateTargetFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED") + nameplateTargetFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED") + nameplateTargetFrame:SetScript("OnEvent", nameplateTargetOnEvent) end end end @@ -3541,13 +3639,9 @@ do local function doCastScan(firetime, unit) scheduled_scans[unit][firetime] = nil; - - if unit:find("^nameplate%d+$") then - WeakAuras.ScanEvents("CAST_REMAINING_CHECK_nameplate", unit); - else - WeakAuras.ScanEvents("CAST_REMAINING_CHECK_" .. string.lower(unit), unit); - end + WeakAuras.ScanEvents("CAST_REMAINING_CHECK_" .. string.lower(unit), unit); end + function Private.ExecEnv.ScheduleCastCheck(fireTime, unit) scheduled_scans[unit] = scheduled_scans[unit] or {} if not(scheduled_scans[unit][fireTime]) then diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 1da752a..4fca9b6 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -1156,7 +1156,7 @@ Private.load_prototype = { } }; -local function AddUnitChangeInternalEvents(triggerUnit, t, includePets) +local function AddUnitChangeInternalEvents(triggerUnit, t, includePets, unitisunit) if (triggerUnit == nil) then return end @@ -1164,16 +1164,6 @@ local function AddUnitChangeInternalEvents(triggerUnit, t, includePets) -- Handled by normal events" elseif triggerUnit == "pet" then tinsert(t, "PET_UPDATE") - elseif (triggerUnit == "nameplate") then - tinsert(t, "UNIT_CHANGED_nameplate") - local nameplates = C_NamePlate.GetNamePlates() - if nameplates then - for i, unitData in pairs(nameplates) do - if unitData then - WeakAuras.WatchUnitChange("nameplate" .. i) - end - end - end else if Private.multiUnitUnits[triggerUnit] then local isPet @@ -1181,17 +1171,21 @@ local function AddUnitChangeInternalEvents(triggerUnit, t, includePets) isPet = WeakAuras.UnitIsPet(unit) if (includePets ~= nil and isPet) or (includePets ~= "PetsOnly" and not isPet) then tinsert(t, "UNIT_CHANGED_" .. string.lower(unit)) - WeakAuras.WatchUnitChange(unit) + if unitisunit then + tinsert(t, "UNIT_IS_UNIT_CHANGED_" .. string.lower(unit) .. "_" .. string.lower(unitisunit)) + end end end else tinsert(t, "UNIT_CHANGED_" .. string.lower(triggerUnit)) - WeakAuras.WatchUnitChange(triggerUnit) + if unitisunit then + tinsert(t, "UNIT_IS_UNIT_CHANGED_" .. string.lower(triggerUnit) .. "_" .. string.lower(unitisunit)) + end end end end -local function AddWatchedUnits(triggerUnit, includePets) +local function AddWatchedUnits(triggerUnit, includePets, unitisunit) if (triggerUnit == nil) then return end @@ -1199,25 +1193,22 @@ local function AddWatchedUnits(triggerUnit, includePets) -- Handled by normal events" elseif triggerUnit == "pet" then WeakAuras.WatchForPetDeath(); - elseif (triggerUnit == "nameplate") then - local nameplates = C_NamePlate.GetNamePlates() - if nameplates then - for i, unitData in pairs(nameplates) do - if unitData then - WeakAuras.WatchUnitChange("nameplate" .. i) - end - end - end else if Private.multiUnitUnits[triggerUnit] then local isPet for unit in pairs(Private.multiUnitUnits[triggerUnit]) do isPet = WeakAuras.UnitIsPet(unit) if (includePets ~= nil and isPet) or (includePets ~= "PetsOnly" and not isPet) then + if unitisunit then + WeakAuras.WatchUnitChange(unitisunit) + end WeakAuras.WatchUnitChange(unit) end end else + if unitisunit then + WeakAuras.WatchUnitChange(unitisunit) + end WeakAuras.WatchUnitChange(triggerUnit) end end @@ -1284,8 +1275,6 @@ local unitHelperFunctions = { tinsert(events, {"UNIT_CHANGED_" .. unit, unit}) end end - elseif trigger.unit == "nameplate" then - tinsert(events, {"UNIT_CHANGED_" .. trigger.unit}) else if trigger.unit then tinsert(events, {"UNIT_CHANGED_" .. trigger.unit, trigger.unit}) @@ -1302,8 +1291,6 @@ local unitHelperFunctions = { tinsert(events, {"UNIT_CHANGED_" .. unit, unit}) end end - elseif trigger.unit == "nameplate" then - tinsert(events, {"UNIT_CHANGED_" .. trigger.unit}) else if trigger.unit then tinsert(events, {"UNIT_CHANGED_" .. trigger.unit, trigger.unit}) @@ -1403,15 +1390,12 @@ Private.event_prototypes = { internal_events = function(trigger) local unit = trigger.unit local result = {} - AddUnitChangeInternalEvents(unit, result) + AddUnitChangeInternalEvents(unit, result, nil, trigger.use_unitisunit and trigger.unitisunit or nil) AddUnitRoleChangeInternalEvents(unit, result) - if trigger.unitisunit then - AddUnitChangeInternalEvents(trigger.unitisunit, result) - end return result end, loadFunc = function(trigger) - AddWatchedUnits(trigger.unit, nil) + AddWatchedUnits(trigger.unit, nil, trigger.use_unitisunit and trigger.unitisunit or nil) end, force_events = unitHelperFunctions.UnitChangedForceEvents, name = L["Unit Characteristics"], @@ -1439,19 +1423,23 @@ Private.event_prototypes = { values = "actual_unit_types_cast", desc = Private.actual_unit_types_cast_tooltip, test = "true", - store = true + store = true, + reloadOptions = true, }, { name = "unitisunit", display = L["Unit is Unit"], type = "unit", init = "UnitIsUnit(unit, extraUnit) == 1 and true or false", - values = "actual_unit_types_with_specific", + values = function(trigger) + if Private.multiUnitUnits[trigger.unit] then + return Private.actual_unit_types + else + return Private.actual_unit_types_with_specific + end + end, test = "unitisunit", - store = true, - conditionType = "bool", desc = function() return L["Can be used for e.g. checking if \"boss1target\" is the same as \"player\"."] end, - enable = function(trigger) return not Private.multiUnitUnits[trigger.unit] end }, { name = "name", @@ -5519,7 +5507,7 @@ Private.event_prototypes = { return result end, loadFunc = function(trigger) - local unit = trigger.threatUnit + local unit = trigger.unit if unit and unit ~= "none" then AddWatchedUnits(unit) end @@ -7507,3 +7495,17 @@ Private.dynamic_texts = { end } }; + +Private.InternalEventByIDList = { + ITEM_COOLDOWN_STARTED = true, + ITEM_COOLDOWN_CHANGED = true, + ITEM_COOLDOWN_READY = true, + ITEM_SLOT_COOLDOWN_STARTED = true, + ITEM_SLOT_COOLDOWN_CHANGED = true, + ITEM_SLOT_COOLDOWN_READY = true, + ITEM_SLOT_COOLDOWN_ITEM_CHANGED = true, + SPELL_COOLDOWN_CHANGED = true, + SPELL_COOLDOWN_READY = true, + SPELL_CHARGES_CHANGED = true, + WA_UPDATE_OVERLAY_GLOW = true, +} diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 7c2b734..c45a5e7 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -789,12 +789,18 @@ if WeakAuras.isAwesomeEnabled() then Private.unit_types_bufftrigger_2.nameplate = L["Nameplate"] end +Private.actual_unit_types = { + player = L["Player"], + pet = L["Pet"], + target = L["Target"], +} + Private.actual_unit_types_with_specific = { player = L["Player"], target = L["Target"], focus = L["Focus"], pet = L["Pet"], - member = L["Specific Unit"] + member = L["Specific Unit"], } Private.actual_unit_types_cast = { @@ -2870,9 +2876,9 @@ Private.multiUnitId = { ["partypetsonly"] = true, ["raid"] = true, } ---if WeakAuras.isAwesomeEnabled() then --- Private.multiUnitId["nameplate"] = true ---end +if WeakAuras.isAwesomeEnabled() then + Private.multiUnitId["nameplate"] = true +end Private.multiUnitUnits = { ["boss"] = {}, @@ -2913,14 +2919,17 @@ end for i = 1, 40 do Private.baseUnitId["raid"..i] = true Private.baseUnitId["raidpet"..i] = true - -- Private.baseUnitId["nameplate"..i] = true -- no need to restrict it, blizzard only allows 40 nameplates, we can get all. - -- Private.multiUnitUnits.nameplate["nameplate"..i] = true -- no need to restrict it, blizzard only allows 40 nameplates, we can get all. Private.multiUnitUnits.group["raid"..i] = true Private.multiUnitUnits.raid["raid"..i] = true Private.multiUnitUnits.group["raidpet"..i] = true Private.multiUnitUnits.raid["raidpet"..i] = true end +for i = 1, 100 do + Private.baseUnitId["nameplate"..i] = true + Private.multiUnitUnits.nameplate["nameplate"..i] = true +end + Private.dbm_types = { [1] = L["Add"], [2] = L["AOE"], diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 50570aa..613d6dd 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3171,7 +3171,8 @@ function Private.HandleGlowAction(actions, region) if actions.glow_action and ( ( - (actions.glow_frame_type == "UNITFRAME" or (actions.glow_frame_type == "NAMEPLATE" and WeakAuras.isAwesomeEnabled())) + (actions.glow_frame_type == "UNITFRAME" or + actions.glow_frame_type == "NAMEPLATE") and region.state.unit ) or (actions.glow_frame_type == "FRAMESELECTOR" and actions.glow_frame) @@ -5405,7 +5406,7 @@ do end function WeakAuras.UntrackableUnit(unit) - return not (trackableUnits[unit] or unit:find("^nameplate%d+$")) + return not trackableUnits[unit] end end diff --git a/WeakAurasOptions/BuffTrigger2.lua b/WeakAurasOptions/BuffTrigger2.lua index 436b80c..445d01f 100644 --- a/WeakAurasOptions/BuffTrigger2.lua +++ b/WeakAurasOptions/BuffTrigger2.lua @@ -801,7 +801,7 @@ local function GetBuffTriggerOptions(data, triggernum) name = L["Filter by Nameplate Type"], order = 69.1, hidden = function() return - not (trigger.type == "aura2" and (WeakAuras.isAwesomeEnabled() and trigger.unit == "nameplate")) + not (trigger.type == "aura2" and trigger.unit == "nameplate") end }, hostility = { @@ -817,7 +817,7 @@ local function GetBuffTriggerOptions(data, triggernum) name = "", order = 69.3, width = WeakAuras.normalWidth, - hidden = function() return not (trigger.type == "aura2" and (WeakAuras.isAwesomeEnabled() and trigger.unit == "nameplate") and not trigger.useHostility) end + hidden = function() return not (trigger.type == "aura2" and trigger.unit == "nameplate" and not trigger.useHostility) end }, useNpcId = { @@ -826,14 +826,14 @@ local function GetBuffTriggerOptions(data, triggernum) name = L["Filter by Npc ID"], order = 69.31, hidden = function() return - not (trigger.type == "aura2" and (WeakAuras.isAwesomeEnabled() and trigger.unit == "nameplate")) + not (trigger.type == "aura2" and trigger.unit == "nameplate") end }, npcId = { type = "input", width = WeakAuras.normalWidth, name = L["Npc ID"], - hidden = function() return not (trigger.type == "aura2" and WeakAuras.isAwesomeEnabled() and trigger.unit == "nameplate" and trigger.useNpcId) end, + hidden = function() return not (trigger.type == "aura2" and trigger.unit == "nameplate" and trigger.useNpcId) end, order = 69.32, desc = L["Supports multiple entries, separated by commas"] }, @@ -842,7 +842,7 @@ local function GetBuffTriggerOptions(data, triggernum) name = "", order = 69.33, width = WeakAuras.normalWidth, - hidden = function() return not (trigger.type == "aura2" and WeakAuras.isAwesomeEnabled() and trigger.unit == "nameplate" and not trigger.useNpcId) end + hidden = function() return not (trigger.type == "aura2" and trigger.unit == "nameplate" and not trigger.useNpcId) end }, ignoreSelf = { @@ -850,7 +850,7 @@ local function GetBuffTriggerOptions(data, triggernum) name = L["Ignore Self"], order = 69.35, width = WeakAuras.doubleWidth, - hidden = function() return not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party" or (WeakAuras.isAwesomeEnabled() and trigger.unit == "nameplate"))) end + hidden = function() return not (trigger.type == "aura2" and (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party" or trigger.unit == "nameplate")) end }, ignoreDead = { diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index 31c8bd1..fe2fd51 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -439,7 +439,7 @@ function OptionsPrivate.CreateFrame() local awesomeWotlkButton if not WeakAuras.isAwesomeEnabled() then awesomeWotlkButton = addFooter("Awesome WotLK", [[Interface\AddOns\WeakAuras\Media\Textures\GitHub.tga]], "https://github.com/FrostAtom/awesome_wotlk", - L["Unlock Nameplate units in WeakAuras with awesome_wotlk binary patch!"]) + L["Unlock Nameplate anchoring and units in WeakAuras with awesome_wotlk client patch!"]) awesomeWotlkButton:SetParent(tipFrame) awesomeWotlkButton:SetPoint("LEFT", documentationButton, "RIGHT", 10, 0) end @@ -1386,10 +1386,8 @@ function OptionsPrivate.CreateFrame() for _, id in ipairs(batchSelection) do if not alreadySelected[id] then - if displayButtons[id].frame:IsVisible() then - displayButtons[id]:Pick() - tinsert(tempGroup.controlledChildren, id) - end + displayButtons[id]:Pick() + tinsert(tempGroup.controlledChildren, id) end end frame:ClearOptions(tempGroup.id) From 56abad943dc21346bff311804b5cc6476503618f Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Thu, 23 Jan 2025 22:26:07 +0100 Subject: [PATCH 072/153] from retail --- WeakAuras/Media/Fonts/PTSansNarrow-Bold.ttf | Bin 0 -> 316452 bytes WeakAuras/Media/Fonts/PTSansNarrow-Regular.ttf | Bin 0 -> 234636 bytes WeakAuras/Types.lua | 2 ++ 3 files changed, 2 insertions(+) create mode 100644 WeakAuras/Media/Fonts/PTSansNarrow-Bold.ttf create mode 100644 WeakAuras/Media/Fonts/PTSansNarrow-Regular.ttf diff --git a/WeakAuras/Media/Fonts/PTSansNarrow-Bold.ttf b/WeakAuras/Media/Fonts/PTSansNarrow-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..960a20ac3f5a7954bb6e9efffb40fca1ccfa315a GIT binary patch literal 316452 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 literal 0 HcmV?d00001 diff --git a/WeakAuras/Media/Fonts/PTSansNarrow-Regular.ttf b/WeakAuras/Media/Fonts/PTSansNarrow-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5e83fc81169aae7f268b6276ec00fce7af4c4486 GIT binary patch literal 234636 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 IRHZ2Y8?;!ZHvj+t literal 0 HcmV?d00001 diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index c45a5e7..79918a1 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -2359,6 +2359,8 @@ LSM:Register("font", "Fira Sans Black", "Interface\\Addons\\WeakAuras\\Media\\Fo LSM:Register("font", "Fira Sans Condensed Black", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSansCondensed-Black.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU) LSM:Register("font", "Fira Sans Condensed Medium", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSansCondensed-Medium.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU) LSM:Register("font", "Fira Sans Medium", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSans-Medium.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU) +LSM:Register("font", "PT Sans Narrow Regular", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\PTSansNarrow-Regular.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU) +LSM:Register("font", "PT Sans Narrow Bold", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\PTSansNarrow-Bold.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU) -- register plain white border LSM:Register("border", "Square Full White", [[Interface\AddOns\WeakAuras\Media\Textures\Square_FullWhite.tga]]) From 4ef5381aaaae20d657ec3ed391a401a494aba253 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 24 Jan 2025 16:27:58 +0100 Subject: [PATCH 073/153] from retail --- WeakAuras/GenericTrigger.lua | 11 + WeakAuras/Prototypes.lua | 759 ++++++++++++++++++++++++----------- 2 files changed, 535 insertions(+), 235 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index aa940e7..9e21a07 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -4280,6 +4280,17 @@ do end end +WeakAuras.CheckForItemEquipped = function(itemName, specificSlot) + if not specificSlot then + return IsEquippedItem(itemName) + end + local equippedItemID = GetInventoryItemID("player", specificSlot) + return itemName and equippedItemID and ( + (type(itemName) == "number" and itemName == equippedItemID) + or itemName == GetItemInfo(equippedItemID) + ) +end + WeakAuras.GetCritChance = function() -- Based on what the wow paper doll does local spellCrit = 0 diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 4fca9b6..e9034d6 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3149,11 +3149,11 @@ Private.event_prototypes = { else spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; end - trigger.realSpellName = spellName; -- Cache local ret = [=[ local spellname = %s local ignoreRuneCD = %s local showgcd = %s; + local name, _, icon = GetSpellInfo(spellname) local startTime, duration, gcdCooldown = WeakAuras.GetSpellCooldown(spellname, ignoreRuneCD, showgcd); local spellCount = WeakAuras.GetSpellCharges(spellname); local stacks = (spellCount and spellCount > 0 and spellCount) or nil; @@ -3209,6 +3209,18 @@ Private.event_prototypes = { return ret; end, + GetNameAndIcon = function(trigger) + local spellName + if (trigger.use_exact_spellName) then + spellName = tonumber(trigger.spellName) + else + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName + end + if spellName then + local name, _, icon = GetSpellInfo(spellName) + return name, icon + end + end, statesParameter = "one", progressType = "timed", args = { @@ -3288,7 +3300,7 @@ Private.event_prototypes = { store = true }, { - hidden = true, + hidden = true, name = "maxCharges", store = true, display = L["Max Charges"], @@ -3367,26 +3379,22 @@ Private.event_prototypes = { { hidden = true, test = "genericShowOn" - } + }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, }, - nameFunc = function(trigger) - local name = GetSpellInfo(trigger.realSpellName or 0); - if(name) then - return name; - end - name = GetSpellInfo(trigger.spellName or 0); - if (name) then - return name; - end - return "Invalid"; - end, - iconFunc = function(trigger) - local _, _, icon = GetSpellInfo(trigger.realSpellName or 0); - if (not icon) then - icon = select(3, GetSpellInfo(trigger.spellName or 0)); - end - return icon; - end, hasSpellID = true, automaticrequired = true, }, @@ -3412,7 +3420,6 @@ Private.event_prototypes = { else spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; end - trigger.realSpellName = spellName; -- Cache WeakAuras.WatchSpellCooldown(spellName); end, init = function(trigger) @@ -3430,9 +3437,23 @@ Private.event_prototypes = { local ret = [=[ local spellname = %s + local name, _, icon = GetSpellInfo(spellname) ]=] return ret:format(spellName); end, + GetNameAndIcon = function(trigger) + local spellName + if (trigger.use_exact_spellName) then + spellName = tonumber(trigger.spellName) + else + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName + end + if spellName then + local name, _, icon = GetSpellInfo(spellName) + return name, icon + end + end, + statesParameter = "one", args = { { name = "spellName", @@ -3442,26 +3463,22 @@ Private.event_prototypes = { init = "arg", showExactOption = true, test = "spellname == spellName" - } + }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, }, - nameFunc = function(trigger) - local name = GetSpellInfo(trigger.realSpellName or 0); - if(name) then - return name; - end - name = GetSpellInfo(trigger.spellName or 0); - if (name) then - return name; - end - return "Invalid"; - end, - iconFunc = function(trigger) - local _, _, icon = GetSpellInfo(trigger.realSpellName or 0); - if (not icon) then - icon = select(3, GetSpellInfo(trigger.spellName or 0)); - end - return icon; - end, hasSpellID = true, timedrequired = true, progressType = "timed" @@ -3488,7 +3505,6 @@ Private.event_prototypes = { else spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; end - trigger.realSpellName = spellName; -- Cache WeakAuras.WatchSpellCooldown(spellName); end, init = function(trigger) @@ -3496,12 +3512,31 @@ Private.event_prototypes = { if (trigger.use_exact_spellName) then spellName = trigger.spellName; else - spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName + spellName = spellName or "" end - spellName = string.format("%q", spellName or ""); - return string.format("local spell = %s;\n", spellName); + if (type(spellName) == "string") then + spellName = string.format("%q", spellName) + end + local ret = [=[ + local spellname = %s + local name, _, icon = GetSpellInfo(spellname) + ]=] + return ret:format(spellName) end, statesParameter = "one", + GetNameAndIcon = function(trigger) + local spellName + if (trigger.use_exact_spellName) then + spellName = tonumber(trigger.spellName) + else + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName + end + if spellName then + local name, _, icon = GetSpellInfo(spellName) + return name, icon + end + end, args = { { name = "spellName", @@ -3534,26 +3569,22 @@ Private.event_prototypes = { init = "arg", store = true, conditionType = "number" - } + }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, }, - nameFunc = function(trigger) - local name = GetSpellInfo(trigger.realSpellName or 0); - if(name) then - return name; - end - name = GetSpellInfo(trigger.spellName or 0); - if (name) then - return name; - end - return "Invalid"; - end, - iconFunc = function(trigger) - local _, _, icon = GetSpellInfo(trigger.realSpellName or 0); - if (not icon) then - icon = select(3, GetSpellInfo(trigger.spellName or 0)); - end - return icon; - end, hasSpellID = true, timedrequired = true, progressType = "timed" @@ -3562,8 +3593,7 @@ Private.event_prototypes = { type = "item", events = {}, internal_events = function(trigger, untrigger) - trigger.itemName = trigger.itemName or 0; - local itemName = type(trigger.itemName) == "number" and trigger.itemName or "[["..trigger.itemName.."]]"; + local itemName = type(trigger.itemName) == "number" and trigger.itemName or string.format("%q", trigger.itemName or "0") local events = { "ITEM_COOLDOWN_READY:" .. itemName, "ITEM_COOLDOWN_CHANGED:" .. itemName, @@ -3580,25 +3610,32 @@ Private.event_prototypes = { force_events = "ITEM_COOLDOWN_FORCE", name = L["Cooldown Progress (Item)"], loadFunc = function(trigger) - trigger.itemName = trigger.itemName or 0; - WeakAuras.WatchItemCooldown(trigger.itemName); + WeakAuras.WatchItemCooldown(trigger.itemName or 0) if (trigger.use_showgcd) then WeakAuras.WatchGCD(); end end, init = function(trigger) - trigger.itemName = trigger.itemName or 0; - local itemName = type(trigger.itemName) == "number" and trigger.itemName or "[["..trigger.itemName.."]]"; + local itemName = type(trigger.itemName) == "number" and trigger.itemName or string.format("%q", trigger.itemName or "0") local ret = [=[ local itemname = %s; + print("Debug: itemname =", itemname) + local name = GetItemInfo(itemname or 0) or "Invalid" + print("Debug: name =", name) + local icon = GetItemIcon(itemname or 0) + print("Debug: icon =", icon) local showgcd = %s + print("Debug: showgcd =", showgcd) local startTime, duration, enabled, gcdCooldown = WeakAuras.GetItemCooldown(itemname, showgcd); + print("Debug: startTime =", startTime, "duration =", duration, "enabled =", enabled, "gcdCooldown =", gcdCooldown) + local expirationTime = startTime + duration + print("Debug: expirationTime =", expirationTime) local genericShowOn = %s + print("Debug: genericShowOn =", genericShowOn) state.itemname = itemname; ]=]; if(trigger.use_remaining and trigger.genericShowOn ~= "showOnReady") then local ret2 = [[ - local expirationTime = startTime + duration local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0; local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then @@ -3612,6 +3649,11 @@ Private.event_prototypes = { trigger.use_showgcd and "true" or "false", "[[" .. (trigger.genericShowOn or "") .. "]]"); end, + GetNameAndIcon = function(trigger) + local name = GetItemInfo(trigger.itemName or 0) + local icon = GetItemIcon(trigger.itemName or 0) + return name, icon + end, statesParameter = "one", args = { { @@ -3697,6 +3739,41 @@ Private.event_prototypes = { store = true, test = "true" }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, + { + name = "progressType", + hidden = true, + init = "'timed'", + store = true, + test = "true" + }, + { + name = "duration", + hidden = true, + init = "duration", + test = "true", + store = true + }, + { + name = "expirationTime", + init = "expirationTime", + hidden = true, + test = "true", + store = true + }, { hidden = true, test = "(genericShowOn == \"showOnReady\" and (startTime == 0 and enabled == 1 or gcdCooldown))" .. @@ -3704,24 +3781,6 @@ Private.event_prototypes = { "or (genericShowOn == \"showAlways\")" } }, - durationFunc = function(trigger) - local startTime, duration = WeakAuras.GetItemCooldown(type(trigger.itemName) == "number" and trigger.itemName or 0, trigger.use_showgcd); - startTime = startTime or 0; - duration = duration or 0; - return duration, startTime + duration; - end, - nameFunc = function(trigger) - local name = GetItemInfo(trigger.itemName or 0); - if(name) then - return name; - else - return "Invalid"; - end - end, - iconFunc = function(trigger) - local _, _, _, _, _, _, _, _, _, icon = GetItemInfo(trigger.itemName or 0); - return icon; - end, hasItemID = true, automaticrequired = true, progressType = "timed" @@ -3763,13 +3822,25 @@ Private.event_prototypes = { init = function(trigger) local ret = [[ local showgcd = %s - local startTime, duration, enable, gcdCooldown = WeakAuras.GetItemSlotCooldown(%s, showgcd); + local itemSlot = %s + local startTime, duration, enable, gcdCooldown = WeakAuras.GetItemSlotCooldown(itemSlot, showgcd) + local expirationTime = startTime + duration local genericShowOn = %s local remaining = startTime + duration - GetTime(); + + local name = "" + local item = GetInventoryItemID("player", itemSlot or 0) + if item then + name = GetItemInfo(item) + end + local icon = GetInventoryItemTexture("player", itemSlot or 0) + local stacks = GetInventoryItemCount("player", itemSlot or 0) + if ((stacks == 1) and (not GetInventoryItemTexture("player", itemSlot or 0))) then + stacks = 0 + end ]]; if(trigger.use_remaining and trigger.genericShowOn ~= "showOnReady") then local ret2 = [[ - local expirationTime = startTime + duration local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0; local remainingCheck = %s; if(remaining >= remainingCheck and remaining > 0) then @@ -3783,6 +3854,15 @@ Private.event_prototypes = { trigger.itemSlot or "0", "[[" .. (trigger.genericShowOn or "") .. "]]"); end, + GetNameAndIcon = function(trigger) + local item = GetInventoryItemID("player", trigger.itemSlot or 0); + local name + if (item) then + name = GetItemInfo(item) + end + local icon = GetInventoryItemTexture("player", trigger.itemSlot or 0) + return name, icon + end, statesParameter = "one", args = { { @@ -3839,6 +3919,48 @@ Private.event_prototypes = { required = true, default = "showOnCooldown" }, + { + name = "progressType", + hidden = true, + init = "'timed'", + store = true, + test = "true" + }, + { + name = "duration", + hidden = true, + init = "duration", + test = "true", + store = true + }, + { + name = "expirationTime", + init = "expirationTime", + hidden = true, + test = "true", + store = true + }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, + { + name = "stacks", + init = "stacks", + hidden = true, + test = "true", + store = true + }, { hidden = true, name = "onCooldown", @@ -3862,28 +3984,6 @@ Private.event_prototypes = { "or (genericShowOn == \"showAlways\")" } }, - durationFunc = function(trigger) - local startTime, duration = WeakAuras.GetItemSlotCooldown(trigger.itemSlot or 0, trigger.use_showgcd); - startTime = startTime or 0; - duration = duration or 0; - return duration, startTime + duration; - end, - nameFunc = function(trigger) - local item = GetInventoryItemID("player", trigger.itemSlot or 0); - if (item) then - return (GetItemInfo(item)) - end - end, - stacksFunc = function(trigger) - local count = GetInventoryItemCount("player", trigger.itemSlot or 0) - if ((count == 1) and (not GetInventoryItemTexture("player", trigger.itemSlot or 0))) then - count = 0 - end - return count - end, - iconFunc = function(trigger) - return GetInventoryItemTexture("player", trigger.itemSlot or 0) or "Interface\\Icons\\INV_Misc_QuestionMark"; - end, automaticrequired = true, progressType = "timed" }, @@ -3891,17 +3991,25 @@ Private.event_prototypes = { type = "item", events = {}, internal_events = function(trigger) - trigger.itemName = trigger.itemName or 0 - return { "ITEM_COOLDOWN_READY:" .. trigger.itemName } + return { "ITEM_COOLDOWN_READY:" .. (trigger.itemName or 0) } end, name = L["Cooldown Ready Event (Item)"], loadFunc = function(trigger) - trigger.itemName = trigger.itemName or 0; - WeakAuras.WatchItemCooldown(trigger.itemName); + WeakAuras.WatchItemCooldown(trigger.itemName or 0) end, init = function(trigger) - trigger.itemName = trigger.itemName or 0; + local ret = [[ + local itemName = %s + local name, _, _, _, _, _, _, _, _, icon = GetItemInfo(itemName) or "Invalid" + ]] + local itemName = type(trigger.itemName) == "number" and trigger.itemName or string.format("%q", trigger.itemName or "0") + return ret:format(itemName) end, + GetNameAndIcon = function(trigger) + local name, _, _, _, _, _, _, _, _, icon = GetItemInfo(trigger.itemName or 0) + return name, icon + end, + statesParameter = "one", args = { { name = "itemName", @@ -3909,20 +4017,22 @@ Private.event_prototypes = { display = L["Item"], type = "item", init = "arg" - } + }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, }, - nameFunc = function(trigger) - local name = GetItemInfo(trigger.itemName or 0); - if(name) then - return name; - else - return "Invalid"; - end - end, - iconFunc = function(trigger) - local _, _, _, _, _, _, _, _, _, icon = GetItemInfo(trigger.itemName or 0); - return icon; - end, hasItemID = true, timedrequired = true, progressType = "timed" @@ -3938,7 +4048,24 @@ Private.event_prototypes = { WeakAuras.WatchItemSlotCooldown(trigger.itemSlot); end, init = function(trigger) + local ret = [[ + local itemSlot = %s + local item = GetInventoryItemID("player", itemSlot) + local name = "" + if (item) then + name = GetItemInfo(item) + end + local icon = GetInventoryItemTexture("player", itemSlot) + ]] + return ret:format(trigger.itemSlot or 0) end, + GetNameAndIcon = function(trigger) + local item = GetInventoryItemID("player", trigger.itemSlot or 0) + local name = item and GetItemInfo(item) or nil + local icon = GetInventoryItemTexture("player", trigger.itemSlot or 0) + return name, icon + end, + statesParameter = "one", args = { { name = "itemSlot", @@ -3947,14 +4074,22 @@ Private.event_prototypes = { type = "select", values = "item_slot_types", init = "arg" - } + }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, }, - nameFunc = function(trigger) - return ""; - end, - iconFunc = function(trigger) - return GetInventoryItemTexture("player", trigger.itemSlot or 0) or "Interface\\Icons\\INV_Misc_QuestionMark"; - end, hasItemID = true, timedrequired = true, progressType = "timed" @@ -3998,11 +4133,12 @@ Private.event_prototypes = { init = function(trigger) local ret = [[ local inverse = %s; - local onGCD = WeakAuras.GetGCDInfo(); + local duration, expirationTime, name, icon = WeakAuras.GetGCDInfo() local hasSpellName = WeakAuras.GcdSpellName(); ]]; return ret:format(trigger.use_inverse and "true" or "false"); end, + statesParameter = "one", args = { { name = "inverse", @@ -4011,22 +4147,45 @@ Private.event_prototypes = { test = "true" }, { + name = "name", hidden = true, - test = "(inverse and onGCD == 0) or (not inverse and onGCD > 0 and hasSpellName)" + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, + { + name = "duration", + hidden = true, + init = "duration", + test = "true", + store = true + }, + { + name = "expirationTime", + init = "expirationTime", + hidden = true, + test = "true", + store = true + }, + { + name = "progressType", + hidden = true, + init = "'timed'", + test = "true", + store = true + }, + { + hidden = true, + test = "(inverse and duration == 0) or (not inverse and duration > 0 and hasSpellName)" } }, - durationFunc = function(trigger) - local duration, expirationTime = WeakAuras.GetGCDInfo(); - return duration, expirationTime; - end, - nameFunc = function(trigger) - local _, _, name = WeakAuras.GetGCDInfo(); - return name; - end, - iconFunc = function(trigger) - local _, _, _, icon = WeakAuras.GetGCDInfo(); - return icon; - end, hasSpellID = true, automaticrequired = true, progressType = "timed" @@ -4098,7 +4257,7 @@ Private.event_prototypes = { { name = "name", hidden = true, - init = "spell", + init = "name", test = "true", store = true }, @@ -4142,7 +4301,12 @@ Private.event_prototypes = { "RUNE_TYPE_UPDATE", }, ["unit_events"] = { - ["player"] = { "UNIT_POWER", "UNIT_ENERGY", "UNIT_MANA", "UNIT_RAGE" } + ["player"] = { + "UNIT_POWER", + "UNIT_ENERGY", + "UNIT_MANA", + "UNIT_RAGE" + } } }, loadInternalEventFunc = function(trigger) @@ -4166,7 +4330,6 @@ Private.event_prototypes = { else spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; end - trigger.realSpellName = spellName; -- Cache WeakAuras.WatchSpellCooldown(spellName); end, init = function(trigger) @@ -4177,13 +4340,15 @@ Private.event_prototypes = { else spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; end - trigger.realSpellName = spellName; -- Cache local ret = [=[ local spellName = %s - local startTime, duration = WeakAuras.GetSpellCooldown(spellName); - startTime = startTime or 0 - duration = duration or 0 - local ready = startTime == 0 + local name, _, icon = GetSpellInfo(spellName) + local startTime, duration, gcdCooldown, readyTime = WeakAuras.GetSpellCooldown(spellName) + local charges = WeakAuras.GetSpellCharges(spellName) + if (charges == nil) then + charges = (duration == 0 or gcdCooldown) and 1 or 0; + end + local ready = startTime == 0 or charges > 0 local active = IsUsableSpell(spellName) and ready ]=] if(trigger.use_targetRequired) then @@ -4194,11 +4359,23 @@ Private.event_prototypes = { end if (type(spellName) == "string") then - spellName = "[[" .. spellName .. "]]"; + spellName = string.format("%q", spellName) end return ret:format(spellName) end, + GetNameAndIcon = function(trigger) + local spellName + if (trigger.use_exact_spellName) then + spellName = tonumber(trigger.spellName) + else + spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName + end + if spellName then + local name, _, icon = GetSpellInfo(spellName) + return name, icon + end + end, args = { { name = "spellName", @@ -4206,8 +4383,8 @@ Private.event_prototypes = { required = true, type = "spell", test = "true", - store = true, - conditionType = "string" + showExactOption = true, + store = true }, -- This parameter uses the IsSpellInRange API function, but it does not check spell range at all -- IsSpellInRange returns nil for invalid targets, 0 for out of range, 1 for in range (0 and 1 are both "positive" values) @@ -4233,6 +4410,30 @@ Private.event_prototypes = { store = true, conditionType = "number", }, + { + hidden = true, + name = "readyTime", + display = L["Since Ready"], + conditionType = "elapsedTimer", + store = true, + test = "true" + }, + { + hidden = true, + name = "chargeGainTime", + display = L["Since Charge Gain"], + conditionType = "elapsedTimer", + store = true, + test = "true" + }, + { + hidden = true, + name = "chargeLostTime", + display = L["Since Charge Lost"], + conditionType = "elapsedTimer", + store = true, + test = "true" + }, { name = "inverse", display = L["Inverse"], @@ -4254,35 +4455,32 @@ Private.event_prototypes = { "WA_SPELL_RANGECHECK", } }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, + { + name = "stacks", + hidden = true, + init = "stacks", + test = "true", + store = true + }, { hidden = true, test = "active" } }, - nameFunc = function(trigger) - local name = GetSpellInfo(trigger.realSpellName or 0); - if(name) then - return name; - end - name = GetSpellInfo(trigger.spellName or 0); - if (name) then - return name; - end - return "Invalid"; - end, - iconFunc = function(trigger) - local _, _, icon = GetSpellInfo(trigger.realSpellName or 0); - if (not icon) then - icon = select(3, GetSpellInfo(trigger.spellName or 0)); - end - return icon; - end, - stacksFunc = function(trigger) - local spellCount = WeakAuras.GetSpellCharges(trigger.realSpellName); - if spellCount and spellCount > 0 then - return spellCount - end - end, hasSpellID = true, automaticrequired = true, progressType = "none" @@ -4588,15 +4786,14 @@ Private.event_prototypes = { end end, init = function(trigger) - trigger.itemName = trigger.itemName or 0; - local itemName = type(trigger.itemName) == "number" and trigger.itemName or "[["..trigger.itemName.."]]"; + local itemName = type(trigger.itemName) == "number" and trigger.itemName or string.format("%q", trigger.itemName or "0") local ret = [[ local itemName = %s local exactSpellMatch = %s if not exactSpellMatch and tonumber(itemName) then itemName = GetItemInfo(itemName) end - local count = GetItemCount(itemName, %s, %s); + local count = GetItemCount(itemName or "", %s, %s); ]]; return ret:format( itemName, @@ -4684,7 +4881,7 @@ Private.event_prototypes = { }, { name = "name", - init = "itemName and itemName ~= '' and GetItemIcon(itemName) or itemName", + init = "itemName and itemName ~= '' and GetItemInfo(itemName) or itemName", hidden = true, store = true, test = "true" @@ -5375,16 +5572,23 @@ Private.event_prototypes = { force_events = "UNIT_INVENTORY_CHANGED", name = L["Item Equipped"], init = function(trigger) - trigger.itemName = trigger.itemName or 0; - local itemName = type(trigger.itemName) == "number" and trigger.itemName or "[[" .. trigger.itemName .. "]]"; + local itemName = type(trigger.itemName) == "number" and trigger.itemName or string.format("%q", trigger.itemName or "0") local ret = [[ local inverse = %s; - local equipped = IsEquippedItem(GetItemInfo(%s)); + local triggerItemName = %s + local itemName, _, _, _, _, _, _, _, _, icon = GetItemInfo(triggerItemName) + local itemSlot = %s; + local equipped = WeakAuras.CheckForItemEquipped(itemName, itemSlot); ]]; - return ret:format(trigger.use_inverse and "true" or "false", itemName); + return ret:format(trigger.use_inverse and "true" or "false", itemName, trigger.use_itemSlot and trigger.itemSlot or "nil"); end, + GetNameAndIcon = function(trigger) + local name, _, _, _, _, _, _, _, _, icon = GetItemInfo(trigger.itemName or 0) + return name, icon + end, + statesParameter = "one", args = { { name = "itemName", @@ -5393,25 +5597,38 @@ Private.event_prototypes = { required = true, test = "true" }, + { + name = "itemSlot", + display = WeakAuras.newFeatureString .. L["Item Slot"], + type = "select", + values = "item_slot_types", + test = "true", + }, { name = "inverse", display = L["Inverse"], type = "toggle", test = "true" }, + { + name = "name", + hidden = true, + init = "itemName", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, { hidden = true, test = "(inverse and not equipped) or (equipped and not inverse)" } }, - nameFunc = function(trigger) - local name = GetItemInfo(trigger.itemName); - return name; - end, - iconFunc = function(trigger) - local icon = select(10, GetItemInfo(trigger.itemName or 0)); - return icon; - end, hasItemID = true, automaticrequired = true, progressType = "none" @@ -5438,11 +5655,15 @@ Private.event_prototypes = { local triggerItemSetName = %s; local inverse = %s; local partial = %s; - + local itemSetName, icon, numEquipped, numItems = WeakAuras.GetEquipmentSetInfo(useItemSetName and triggerItemSetName or nil, partial); ]]; return ret:format(trigger.use_itemSetName and "true" or "false", itemSetName, trigger.use_inverse and "true" or "false", trigger.use_partial and "true" or "false"); end, + GetNameAndIcon = function(trigger) + local name, icon = WeakAuras.GetEquipmentSetInfo(trigger.use_itemSetName and trigger.itemSetName or nil, true) + return name, icon + end, statesParameter = "one", args = { { @@ -5452,7 +5673,7 @@ Private.event_prototypes = { test = "true", store = true, conditionType = "string", - init = "WeakAuras.GetEquipmentSetInfo(useItemSetName and triggerItemSetName or nil, partial)" + init = "itemSetName" }, { name = "partial", @@ -5466,22 +5687,46 @@ Private.event_prototypes = { type = "toggle", test = "true" }, + { + name = "name", + hidden = true, + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, + { + name = "value", + init = "numEquipped", + hidden = true, + store = true, + test = "true", + }, + { + name = "total", + init = "numItems", + hidden = true, + store = true, + test = "true", + }, + { + name = "progressType", + init = "'static'", + hidden = true, + store = true, + test = "true", + }, { hidden = true, test = "(inverse and itemSetName == nil) or (not inverse and itemSetName)" - } + }, }, - nameFunc = function(trigger) - return WeakAuras.GetEquipmentSetInfo(trigger.use_itemSetName and trigger.itemSetName or nil, trigger.use_partial); - end, - iconFunc = function(trigger) - local _, icon = WeakAuras.GetEquipmentSetInfo(trigger.use_itemSetName and trigger.itemSetName or nil, trigger.use_partial); - return icon; - end, - durationFunc = function(trigger) - local _, _, numEquipped, numItems = WeakAuras.GetEquipmentSetInfo(trigger.use_itemSetName and trigger.itemSetName or nil, trigger.use_partial); - return numEquipped, numItems, true; - end, hasItemID = true, automaticrequired = true, progressType = "static" @@ -6866,23 +7111,54 @@ Private.event_prototypes = { }, force_events = "SPELLS_CHANGED", name = L["Spell Known"], + statesParameter = "one", init = function(trigger) - local spellId = trigger.spellId or ""; - local ret = [[ - local spellId = tonumber(%q); - local usePet = %s; - ]] - return ret:format(spellId, trigger.use_petspell and "true" or "false"); + local spellName; + local ret; + if (trigger.use_exact_spellName) then + spellName = tonumber(trigger.spellName) or "nil"; + if spellName == 0 then + spellName = "nil" + end + ret = [[ + local spellName = %s; + local name, _, icon = GetSpellInfo(spellName) + ]] + ret = ret:format(spellName) + else + local name = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName or ""; + ret = [[ + local spellName _, icon = GetSpellInfo(%q) + local name = spellName + ]] + ret = ret:format(name) + end + local ret2 + if (trigger.use_inverse) then + ret2 = [[ + local usePet = %s; + local active = not spellName or not IsSpellKnown(spellName, usePet) + ]] + else + ret2 = [[ + local usePet = %s; + local active = spellName and IsSpellKnown(spellName, usePet) + ]] + end + return ret .. ret2:format(trigger.use_petspell and "true" or "false") + end, + GetNameAndIcon = function(trigger) + local name, _, icon = GetSpellInfo(trigger.spellName or 0) + return name, icon end, args = { { - name = "spellId", + name = "spellName", required = true, - display = L["Spell Id"], + display = L["Spell"], type = "spell", test = "true", - conditionType = "number", - forceExactOption = true + showExactOption = true, }, { name = "petspell", @@ -6891,17 +7167,30 @@ Private.event_prototypes = { test = "true" }, { + name = "inverse", + display = WeakAuras.newFeatureString .. L["Inverse"], + type = "toggle", + test = "true", + }, + { + name = "name", hidden = true, - test = "spellId and WeakAuras.IsSpellKnown(spellId, usePet)"; + init = "name", + test = "true", + store = true + }, + { + name = "icon", + hidden = true, + init = "icon or 'Interface\\AddOns\\WeakAuras\\Media\\Textures\\icon'", + test = "true", + store = true + }, + { + hidden = true, + test = "active" } }, - nameFunc = function(trigger) - return (GetSpellInfo(trigger.spellId or 0)) - end, - iconFunc = function(trigger) - local _, _, icon = GetSpellInfo(trigger.spellId or 0); - return icon; - end, automaticrequired = true, progressType = "none" }, From 3fcb60f399927e506bf4df6278b203b9178a09f3 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 24 Jan 2025 18:12:49 +0100 Subject: [PATCH 074/153] from retail --- WeakAuras/BuffTrigger2.lua | 159 +++++++++++++++---------------- WeakAuras/Conditions.lua | 177 +++++++++++++++++++---------------- WeakAuras/GenericTrigger.lua | 17 +--- WeakAuras/Init.lua | 4 + WeakAuras/Prototypes.lua | 7 -- 5 files changed, 185 insertions(+), 179 deletions(-) diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index 9585e3f..2675297 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -2154,124 +2154,124 @@ local function createScanFunc(trigger) return nil end - local preamble = "" + local preamble = {""} - local ret = [[ + local ret = {[=[ return function(time, matchData) - ]] + ]=]} if use_total then - local ret2 = [[ + local ret2 = [=[ if not(matchData.duration %s %s) then return false end - ]] - ret = ret .. ret2:format(trigger.totalOperator or ">=", tonumber(trigger.total) or 0) + ]=] + table.insert(ret, ret2:format(trigger.totalOperator or ">=", tonumber(trigger.total) or 0)) end if useStacks then - local ret2 = [[ + local ret2 = [=[ if not(matchData.stacks %s %s) then return false end - ]] - ret = ret .. ret2:format(trigger.stacksOperator or ">=", tonumber(trigger.stacks) or 0) + ]=] + table.insert(ret, ret2:format(trigger.stacksOperator or ">=", tonumber(trigger.stacks) or 0)) end if use_stealable then - ret = ret .. [[ + table.insert(ret, [=[ if not matchData.isStealable then return false end - ]] + ]=]) elseif use_stealable == false then - ret = ret .. [[ + table.insert(ret, [=[ if matchData.isStealable then return false end - ]] + ]=]) end if use_debuffClass then - local ret2 = [[ + local ret2 = [=[ local tDebuffClass = %s; if not tDebuffClass[matchData.debuffClass] then return false end - ]] - ret = ret .. ret2:format(trigger.debuffClass and type(trigger.debuffClass) == "table" and Private.SerializeTable(trigger.debuffClass) or "{}") + ]=] + table.insert(ret, ret2:format(trigger.debuffClass and type(trigger.debuffClass) == "table" and Private.SerializeTable(trigger.debuffClass) or "{}")) end if trigger.ownOnly then - ret = ret .. [[ + table.insert(ret, [=[ if matchData.unitCaster ~= 'player' and matchData.unitCaster ~= 'pet' and matchData.unitCaster ~= 'vehicle' then return false end - ]] + ]=]) elseif trigger.ownOnly == false then - ret = ret .. [[ + table.insert(ret, [=[ if matchData.unitCaster == 'player' or matchData.unitCaster == 'pet' or matchData.unitCaster == 'vehicle' then return false end - ]] + ]=]) end if use_tooltip and trigger.tooltip_operator and trigger.tooltip then if trigger.tooltip_operator == "==" then - local ret2 = [[ + local ret2 = [=[ if not matchData.tooltip or matchData.tooltip ~= %s then return false end - ]] - ret = ret .. ret2:format(Private.QuotedString(trigger.tooltip)) + ]=] + table.insert(ret, ret2:format(Private.QuotedString(trigger.tooltip))) elseif trigger.tooltip_operator == "find('%s')" then - local ret2 = [[ + local ret2 = [=[ if not matchData.tooltip or not matchData.tooltip:find(%s, 1, true) then return false end - ]] - ret = ret .. ret2:format(Private.QuotedString(trigger.tooltip)) + ]=] + table.insert(ret, ret2:format(Private.QuotedString(trigger.tooltip))) elseif trigger.tooltip_operator == "match('%s')" then - local ret2 = [[ + local ret2 = [=[ if not matchData.tooltip or not matchData.tooltip:match(%s) then return false end - ]] - ret = ret .. ret2:format(Private.QuotedString(trigger.tooltip)) + ]=] + table.insert(ret, ret2:format(Private.QuotedString(trigger.tooltip))) end end if use_tooltipValue and trigger.tooltipValueNumber and trigger.tooltipValue_operator and trigger.tooltipValue then local property = "tooltip" .. tonumber(trigger.tooltipValueNumber) - local ret2 = [[ + local ret2 = [=[ if not matchData.%s or not (matchData.%s %s %s) then return false end - ]] + ]=] ret = ret .. ret2:format(property, property, trigger.tooltipValue_operator, trigger.tooltipValue) end if trigger.useNamePattern and trigger.namePattern_operator and trigger.namePattern_name then if trigger.namePattern_operator == "==" then - local ret2 = [[ + local ret2 = [=[ if not matchData.name == %s then return false end - ]] - ret = ret .. ret2:format(Private.QuotedString(trigger.namePattern_name)) + ]=] + table.insert(ret, ret2:format(Private.QuotedString(trigger.namePattern_name))) elseif trigger.namePattern_operator == "find('%s')" then - local ret2 = [[ + local ret2 = [=[ if not matchData.name:find(%s, 1, true) then return false end - ]] - ret = ret .. ret2:format(Private.QuotedString(trigger.namePattern_name)) + ]=] + table.insert(ret, ret2:format(Private.QuotedString(trigger.namePattern_name))) elseif trigger.namePattern_operator == "match('%s')" then - local ret2 = [[ + local ret2 = [=[ if not matchData.name:match(%s) then return false end - ]] - ret = ret .. ret2:format(Private.QuotedString(trigger.namePattern_name)) + ]=] + table.insert(ret, ret2:format(Private.QuotedString(trigger.namePattern_name))) end end @@ -2283,40 +2283,40 @@ local function createScanFunc(trigger) tinsert(names, name) end - preamble = preamble .. "local ignoreNames = {\n" + table.insert(preamble, "local ignoreNames = {\n") for index, name in ipairs(names) do - preamble = preamble .. string.format(" [%q] = true,\n", name) + table.insert(preamble, string.format(" [%q] = true,\n", name)) end - preamble = preamble .. "}\n" - ret = ret .. [[ + table.insert(preamble, "}\n") + table.insert(ret, [=[ if ignoreNames[matchData.name] then return false end - ]] + ]=]) end if use_ignore_spellId then - preamble = preamble .. "local ignoreSpellId = {\n" + table.insert(preamble, "local ignoreSpellId = {\n") for index, spellId in ipairs(trigger.ignoreAuraSpellids) do local spell = WeakAuras.SafeToNumber(spellId) if spell then - preamble = preamble .. string.format(" [%s] = true,\n", spell) + table.insert(preamble, string.format(" [%s] = true,\n", spell)) end end - preamble = preamble .. "}\n" - ret = ret .. [[ + table.insert(preamble, "}\n") + table.insert(ret, [=[ if ignoreSpellId[matchData.spellId] then return false end - ]] + ]=]) end - ret = ret .. [[ + table.insert(ret, [=[ return true end - ]] + ]=]) - local func, err = loadstring(preamble .. ret) + local func, err = loadstring(table.concat(preamble) .. table.concat(ret)) if func then return func() @@ -2623,50 +2623,51 @@ end function BuffTrigger.GetAdditionalProperties(data, triggernum) local trigger = data.triggers[triggernum].trigger - local ret = "|cFFFFCC00%".. triggernum .. ".spellId|r - " .. L["Spell ID"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".debuffClass|r - " .. L["Debuff Class"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".unitCaster|r - " .. L["Caster Unit"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".casterName|r - " .. L["Caster Name"] .. "\n" + local ret = {"|cFFFFCC00%".. triggernum .. ".spellId|r - " .. L["Spell ID"] .. "\n"} + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".debuffClass|r - " .. L["Debuff Class"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".debuffClassIcon|r - " .. L["Debuff Class Icon"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".unitCaster|r - " .. L["Caster Unit"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".casterName|r - " .. L["Caster Name"] .. "\n") if trigger.unit ~= "multi" then - ret = ret .. "|cFFFFCC00%".. triggernum .. ".unit|r - " .. L["Unit"] .. "\n" + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".unit|r - " .. L["Unit"] .. "\n") end - ret = ret .. "|cFFFFCC00%".. triggernum .. ".unitName|r - " .. L["Unit Name"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".matchCount|r - " .. L["Match Count"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".matchCountPerUnit|r - " .. L["Match Count per Unit"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".unitCount|r - " .. L["Units Affected"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".totalStacks|r - " .. L["Total stacks over all matches"] .. "\n" + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".unitName|r - " .. L["Unit Name"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".matchCount|r - " .. L["Match Count"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".matchCountPerUnit|r - " .. L["Match Count per Unit"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".unitCount|r - " .. L["Units Affected"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".totalStacks|r - " .. L["Total stacks over all matches"] .. "\n") if trigger.unit ~= "multi" then - ret = ret .. "|cFFFFCC00%".. triggernum .. ".maxUnitCount|r - " .. L["Total Units"] .. "\n" + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".maxUnitCount|r - " .. L["Total Units"] .. "\n") end if not IsSingleMissing(trigger) and trigger.unit ~= "multi" and trigger.fetchTooltip then - ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip|r - " .. L["Tooltip"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip1|r - " .. L["First Value of Tooltip Text"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip2|r - " .. L["Second Value of Tooltip Text"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip3|r - " .. L["Third Value of Tooltip Text"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".tooltip4|r - " .. L["Fourth Value of Tooltip Text"] .. "\n" + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".tooltip|r - " .. L["Tooltip"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".tooltip1|r - " .. L["First Value of Tooltip Text"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".tooltip2|r - " .. L["Second Value of Tooltip Text"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".tooltip3|r - " .. L["Third Value of Tooltip Text"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".tooltip4|r - " .. L["Fourth Value of Tooltip Text"] .. "\n") end if trigger.unit ~= "multi" then - ret = ret .. "|cFFFFCC00%".. triggernum .. ".stackGainTime|r - " .. L["Since Stack Gain"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".stackLostTime|r - " .. L["Since Stack Lost"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".initialTime|r - " .. L["Since Apply"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".refreshTime|r - " .. L["Since Apply/Refresh"] .. "\n" + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".stackGainTime|r - " .. L["Since Stack Gain"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".stackLostTime|r - " .. L["Since Stack Lost"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".initialTime|r - " .. L["Since Apply"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".refreshTime|r - " .. L["Since Apply/Refresh"] .. "\n") end if trigger.unit ~= "multi" and trigger.fetchRaidMark then - ret = ret .. "|cFFFFCC00%".. triggernum .. ".raidMark|r - " .. L["Raid Mark"] .. "\n" + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".raidMark|r - " .. L["Raid Mark"] .. "\n") end if (trigger.unit == "group" or trigger.unit == "raid" or trigger.unit == "party") and trigger.useAffected then - ret = ret .. "|cFFFFCC00%".. triggernum .. ".affected|r - " .. L["Names of affected Players"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".unaffected|r - " .. L["Names of unaffected Players"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".affectedUnits|r - " .. L["Units of affected Players in a table format"] .. "\n" - ret = ret .. "|cFFFFCC00%".. triggernum .. ".unaffectedUnits|r - " .. L["Units of unaffected Players in a table format"] .. "\n" + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".affected|r - " .. L["Names of affected Players"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".unaffected|r - " .. L["Names of unaffected Players"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".affectedUnits|r - " .. L["Units of affected Players in a table format"] .. "\n") + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".unaffectedUnits|r - " .. L["Units of unaffected Players in a table format"] .. "\n") end - return ret + return table.concat(ret) end function BuffTrigger.GetProgressSources(data, triggernum, values) diff --git a/WeakAuras/Conditions.lua b/WeakAuras/Conditions.lua index c673a87..1f20cfb 100644 --- a/WeakAuras/Conditions.lua +++ b/WeakAuras/Conditions.lua @@ -165,7 +165,12 @@ local function formatValueForCall(type, property) return "nil"; end - +function Private.ExecEnv.CancelConditionCheck(uid, cloneId) + if conditionChecksTimers.recheckHandle[uid] and conditionChecksTimers.recheckHandle[uid][cloneId] then + timer:CancelTimer(conditionChecksTimers.recheckHandle[uid][cloneId]) + conditionChecksTimers.recheckHandle[uid][cloneId] = nil + end +end function Private.ExecEnv.ScheduleConditionCheck(time, uid, cloneId) conditionChecksTimers.recheckTime[uid] = conditionChecksTimers.recheckTime[uid] or {} @@ -299,10 +304,11 @@ local function CreateTestForCondition(data, input, allConditionsTemplate, usedSt if pausedProperty and remainingProperty then local pausedString = "state[" .. trigger .. "]" .. string.format("[%q]", pausedProperty) local remainingString = "(state[" .. trigger .. "]" .. string.format("[%q]", remainingProperty) .. " or 0)" + remainingTime = "((" .. pausedString .. " and " .. remainingString .. ") or " .. remainingTime .. ")" end if (op == "==") then - check = stateCheck .. stateVariableCheck .. "abs((" .. remainingTime .. "-" .. value .. ")" .. " < 0.05" + check = stateCheck .. stateVariableCheck .. "abs((" .. remainingTime .. "-" .. value .. ")" .. ") < 0.05" else check = stateCheck .. stateVariableCheck .. remainingTime .. op .. value end @@ -379,7 +385,15 @@ local function CreateTestForCondition(data, input, allConditionsTemplate, usedSt -- If adding a new condition type, don't forget to adjust the validator in the options code if (cType == "timer" and value) then - recheckCode = " nextTime = state[" .. trigger .. "] and state[" .. trigger .. "]" .. string.format("[%q]", variable) .. " and (state[" .. trigger .. "]" .. string.format("[%q]", variable) .. " - " .. value .. ")\n"; + local variableString = "state[" .. trigger .. "]" .. string.format("[%q]", variable) + local andNotPaused = pausedProperty + and "and not " .. "state[" .. trigger .. "]" .. string.format("[%q]", pausedProperty) + or "" + + recheckCode = " nextTime = state[" .. trigger .. "] " .. andNotPaused + .. " and " .. variableString + .. " and " .. "(" .. variableString .. " - " .. value .. ")\n" + recheckCode = recheckCode .. " if (nextTime and (not recheckTime or nextTime < recheckTime) and nextTime >= now) then\n" recheckCode = recheckCode .. " recheckTime = nextTime\n"; recheckCode = recheckCode .. " end\n" @@ -401,19 +415,19 @@ local function CreateCheckCondition(data, ret, condition, conditionNumber, allCo check = "false" end if condition.linked and conditionNumber > 1 then - ret = ret .. " elseif (" .. check .. ") then\n"; + table.insert(ret, " elseif (" .. check .. ") then\n") else - ret = ret .. " if (" .. check .. ") then\n"; + table.insert(ret, " if (" .. check .. ") then\n") end - ret = ret .. " newActiveConditions[" .. conditionNumber .. "] = true;\n"; + table.insert(ret, " newActiveConditions[" .. conditionNumber .. "] = true;\n") if not nextIsLinked then - ret = ret .. " end\n"; + table.insert(ret, " end\n") end if (check) then - ret = ret .. "\n"; + table.insert(ret, "\n") end - return ret, recheckCode; + return recheckCode; end local function ParseProperty(property) @@ -447,27 +461,27 @@ end local function CreateDeactivateCondition(ret, condition, conditionNumber, data, properties, usedProperties, debug) if (condition.changes) then - ret = ret .. " if (activatedConditions[".. conditionNumber .. "] and not newActiveConditions[" .. conditionNumber .. "]) then\n" - if (debug) then ret = ret .. " print('Deactivating condition " .. conditionNumber .. "' )\n"; end + table.insert(ret, " if (activatedConditions[".. conditionNumber .. "] and not newActiveConditions[" .. conditionNumber .. "]) then\n") + if (debug) then table.insert(ret, " print('Deactivating condition " .. conditionNumber .. "' )\n") end for changeNum, change in ipairs(condition.changes) do if (change.property) then local propertyData = properties and properties[change.property] if (propertyData and propertyData.type and propertyData.setter) then usedProperties[change.property] = true; - ret = ret .. " propertyChanges['" .. change.property .. "'] = " + table.insert(ret, " propertyChanges['" .. change.property .. "'] = " .. formatValueForAssignment(propertyData.type, GetBaseProperty(data, change.property), nil, nil, data) - .. "\n"; + .. "\n") if (debug) then - ret = ret .. " print('- " .. change.property .. " " + table.insert(ret, " print('- " .. change.property .. " " .. formatValueForAssignment(propertyData.type, GetBaseProperty(data, change.property), nil, nil, data) - .. "')\n"; + .. "')\n") end end end end - ret = ret .. " end\n" + table.insert(ret, " end\n") end return ret; @@ -475,20 +489,20 @@ end local function CreateActivateCondition(ret, id, condition, conditionNumber, data, properties, debug) if (condition.changes) then - ret = ret .. " if (newActiveConditions[" .. conditionNumber .. "]) then\n" - ret = ret .. " if (not activatedConditions[".. conditionNumber .. "]) then\n" - if (debug) then ret = ret .. " print('Activating condition " .. conditionNumber .. "' )\n"; end + table.insert(ret, " if (newActiveConditions[" .. conditionNumber .. "]) then\n") + table.insert(ret, " if (not activatedConditions[".. conditionNumber .. "]) then\n") + if (debug) then table.insert(ret, " print('Activating condition " .. conditionNumber .. "' )\n") end -- non active => active for changeNum, change in ipairs(condition.changes) do if (change.property) then local propertyData = properties and properties[change.property] if (propertyData and propertyData.type) then if (propertyData.setter) then - ret = ret .. " propertyChanges['" .. change.property .. "'] = " - .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "\n" + table.insert(ret, " propertyChanges['" .. change.property .. "'] = " + .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "\n") if (debug) then - ret = ret .. " print('- " .. change.property .. " " - .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "')\n" + table.insert(ret, " print('- " .. change.property .. " " + .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "')\n") end elseif (propertyData.action) then local pathToCustomFunction = "nil"; @@ -505,39 +519,39 @@ local function CreateActivateCondition(ret, id, condition, conditionNumber, data and Private.ExecEnv.conditionTextFormatters[id][conditionNumber].changes[changeNum] then pathToFormatter = string.format("Private.ExecEnv.conditionTextFormatters[%q][%s].changes[%s]", id, conditionNumber, changeNum); end - ret = ret .. " region:" .. propertyData.action .. "(" + table.insert(ret, " region:" .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction, pathToFormatter, data) - .. ")" .. "\n"; + .. ")" .. "\n") if (debug) then - ret = ret .. " print('# " .. propertyData.action .. "(" + table.insert(ret, " print('# " .. propertyData.action .. "(" .. formatValueForAssignment(propertyData.type, change.value, pathToCustomFunction, pathToFormatter, data) - .. "')\n"; + .. "')\n") end end end end end - ret = ret .. " else\n" + table.insert(ret, " else\n") -- active => active, only override properties for changeNum, change in ipairs(condition.changes) do if (change.property) then local propertyData = properties and properties[change.property] if (propertyData and propertyData.type and propertyData.setter) then - ret = ret .. " if(propertyChanges['" .. change.property .. "'] ~= nil) then\n" - ret = ret .. " propertyChanges['" .. change.property .. "'] = " - .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "\n" - if (debug) then ret = ret .. " print('- " .. change.property .. " " - .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "')\n" end - ret = ret .. " end\n" + table.insert(ret, " if(propertyChanges['" .. change.property .. "'] ~= nil) then\n") + table.insert(ret, " propertyChanges['" .. change.property .. "'] = " + .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "\n") + if (debug) then table.insert(ret, " print('- " .. change.property .. " " + .. formatValueForAssignment(propertyData.type, change.value, nil, nil, data) .. "')\n") end + table.insert(ret, " end\n") end end end - ret = ret .. " end\n" - ret = ret .. " end\n" - ret = ret .. "\n"; - ret = ret .. " activatedConditions[".. conditionNumber .. "] = newActiveConditions[" .. conditionNumber .. "]\n"; + table.insert(ret, " end\n") + table.insert(ret, " end\n") + table.insert(ret, "\n") + table.insert(ret, " activatedConditions[".. conditionNumber .. "] = newActiveConditions[" .. conditionNumber .. "]\n") end return ret; @@ -673,80 +687,81 @@ function Private.GetGlobalConditions() end local function ConstructConditionFunction(data) - local debug = false; + local debug = false if (not data.conditions or #data.conditions == 0) then - return nil; + return nil end - local usedProperties = {}; + local usedProperties = {} - local allConditionsTemplate = Private.GetTriggerConditions(data); - allConditionsTemplate[-1] = Private.GetGlobalConditions(); + local allConditionsTemplate = Private.GetTriggerConditions(data) + allConditionsTemplate[-1] = Private.GetGlobalConditions() - local ret = ""; - ret = ret .. "local newActiveConditions = {};\n" - ret = ret .. "local propertyChanges = {};\n" - ret = ret .. "local nextTime;\n" - ret = ret .. string.format("local uid = %q\n", data.uid) - ret = ret .. "return function(region, hideRegion)\n"; - if (debug) then ret = ret .. " print('check conditions for:', region.id, region.cloneId)\n"; end - ret = ret .. " local id = region.id\n"; - ret = ret .. " local cloneId = region.cloneId or ''\n"; - ret = ret .. " local state = region.states\n" - ret = ret .. " local activatedConditions = WeakAuras.GetActiveConditions(id, cloneId)\n"; - ret = ret .. " wipe(newActiveConditions)\n"; - ret = ret .. " local recheckTime;\n" - ret = ret .. " local now = GetTime();\n" + local ret = {""} + table.insert(ret, "local newActiveConditions = {};\n") + table.insert(ret, "local propertyChanges = {};\n") + table.insert(ret, "local nextTime;\n") + table.insert(ret, string.format("local uid = %q\n", data.uid)) + table.insert(ret, "return function(region, hideRegion)\n") + if (debug) then table.insert(ret, " print('check conditions for:', region.id, region.cloneId)\n") end + table.insert(ret, " local id = region.id\n") + table.insert(ret, " local cloneId = region.cloneId or ''\n") + table.insert(ret, " local state = region.states\n") + table.insert(ret, " local activatedConditions = WeakAuras.GetActiveConditions(id, cloneId)\n") + table.insert(ret, " wipe(newActiveConditions)\n") + table.insert(ret, " local recheckTime;\n") + table.insert(ret, " local now = GetTime();\n") -- First Loop gather which conditions are active - ret = ret .. " if (not hideRegion) then\n" - local recheckCode = "" + table.insert(ret, " if (not hideRegion) then\n") + local recheckCode = {} if (data.conditions) then Private.ExecEnv.conditionHelpers[data.uid] = nil for conditionNumber, condition in ipairs(data.conditions) do local nextIsLinked = data.conditions[conditionNumber + 1] and data.conditions[conditionNumber + 1].linked - local additionalRecheckCode - ret, additionalRecheckCode = CreateCheckCondition(data, ret, condition, conditionNumber, allConditionsTemplate, nextIsLinked, debug) + local additionalRecheckCode = CreateCheckCondition(data, ret, condition, conditionNumber, allConditionsTemplate, nextIsLinked, debug) if additionalRecheckCode then - recheckCode = recheckCode .. "\n" .. additionalRecheckCode + table.insert(recheckCode, additionalRecheckCode) end end end - ret = ret .. recheckCode - ret = ret .. " end\n"; + table.insert(ret, table.concat(recheckCode)) + table.insert(ret, " end\n") - ret = ret .. " if (recheckTime) then\n" - ret = ret .. " Private.ExecEnv.ScheduleConditionCheck(recheckTime, uid, cloneId);\n" - ret = ret .. " end\n" + table.insert(ret, " if (recheckTime) then\n") + table.insert(ret, " Private.ExecEnv.ScheduleConditionCheck(recheckTime, uid, cloneId);\n") + table.insert(ret, " else\n") + table.insert(ret, " Private.ExecEnv.CancelConditionCheck(uid, cloneId)") + table.insert(ret, " end\n") - local properties = Private.GetProperties(data); + local properties = Private.GetProperties(data) -- Now build a property + change list -- Second Loop deals with conditions that are no longer active - ret = ret .. " wipe(propertyChanges)\n" + table.insert(ret, " wipe(propertyChanges)\n") if (data.conditions) then for conditionNumber, condition in ipairs(data.conditions) do - ret = CreateDeactivateCondition(ret, condition, conditionNumber, data, properties, usedProperties, debug) + CreateDeactivateCondition(ret, condition, conditionNumber, data, properties, usedProperties, debug) end end - ret = ret .. "\n"; + table.insert(ret, "\n") -- Third Loop deals with conditions that are newly active if (data.conditions) then for conditionNumber, condition in ipairs(data.conditions) do - ret = CreateActivateCondition(ret, data.id, condition, conditionNumber, data, properties, debug) + CreateActivateCondition(ret, data.id, condition, conditionNumber, data, properties, debug) end end -- Last apply changes to region for property, _ in pairs(usedProperties) do - ret = ret .. " if(propertyChanges['" .. property .. "'] ~= nil) then\n" - local arg1 = ""; + table.insert(ret, " if(propertyChanges['" .. property .. "'] ~= nil) then\n") + local arg1 = "" if (properties[property].arg1) then if (type(properties[property].arg1) == "number") then - arg1 = tostring(properties[property].arg1) .. ", "; + arg1 = tostring(properties[property].arg1) .. ", " else - arg1 = "'" .. properties[property].arg1 .. "', "; + arg1 = "'" .. properties[property].arg1 .. "', " end end @@ -756,13 +771,13 @@ local function ConstructConditionFunction(data) base = "region.subRegions[" .. subIndex .. "]:" end - ret = ret .. " " .. base .. properties[property].setter .. "(" .. arg1 .. formatValueForCall(properties[property].type, property) .. ")\n"; - if (debug) then ret = ret .. " print('Calling " .. properties[property].setter .. " with', " .. arg1 .. formatValueForCall(properties[property].type, property) .. ")\n"; end - ret = ret .. " end\n"; + table.insert(ret, " " .. base .. properties[property].setter .. "(" .. arg1 .. formatValueForCall(properties[property].type, property) .. ")\n") + if (debug) then table.insert(ret, " print('Calling " .. properties[property].setter .. " with', " .. arg1 .. formatValueForCall(properties[property].type, property) .. ")\n") end + table.insert(ret, " end\n") end - ret = ret .. "end\n"; + table.insert(ret, "end\n") - return ret; + return table.concat(ret) end local function CancelTimers(uid) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 9e21a07..14fc0e2 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -3839,11 +3839,9 @@ end function GenericTrigger.GetAdditionalProperties(data, triggernum) local trigger = data.triggers[triggernum].trigger - local ret = ""; + local ret = {""}; local prototype = GenericTrigger.GetPrototype(trigger) if prototype then - local found = false; - local additional = "" for _, v in pairs(prototype.args) do local enable = true if(type(v.enable) == "function") then @@ -3853,16 +3851,11 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) end if (enable and v.store and v.name and v.display and v.conditionType ~= "bool") then - found = true; - additional = additional .. "|cFFFFCC00%".. triggernum .. "." .. v.name .. "|r - " .. v.display .. "\n"; + table.insert(ret, "|cFFFFCC00%".. triggernum .. "." .. v.name .. "|r - " .. v.display .. "\n") end end if prototype.countEvents then - found = true; - additional = additional .. "|cFFFFCC00%".. triggernum .. ".count|r - " .. L["Count"] .. "\n"; - end - if (found) then - ret = ret .. additional; + table.insert(ret, "|cFFFFCC00%".. triggernum .. ".count|r - " .. L["Count"] .. "\n") end else if (trigger.custom_type == "stateupdate") then @@ -3871,7 +3864,7 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) for var, varData in pairs(variables) do if (type(varData) == "table") then if varData.display then - ret = ret .. "|cFFFFCC00%".. triggernum .. "." .. var .. "|r - " .. varData.display .. "\n" + table.insert(ret, "|cFFFFCC00%".. triggernum .. "." .. var .. "|r - " .. varData.display .. "\n") end end end @@ -3879,7 +3872,7 @@ function GenericTrigger.GetAdditionalProperties(data, triggernum) end end - return ret; + return table.concat(ret); end function GenericTrigger.GetProgressSources(data, triggernum, values) diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index aefcec6..65b4f54 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -80,6 +80,10 @@ function WeakAuras.IsLibsOK() return libsAreOk end +if not libsAreOk then + WeakAuras.prettyPrint("WeakAuras is missing necessary libraries. Please reinstall a proper package.") +end + if versionString ~= versionStringFromToc and versionStringFromToc ~= "Dev" then WeakAuras.prettyPrint("You need to restart your game client to complete the WeakAuras update!") end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index e9034d6..d43f4a9 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3619,19 +3619,12 @@ Private.event_prototypes = { local itemName = type(trigger.itemName) == "number" and trigger.itemName or string.format("%q", trigger.itemName or "0") local ret = [=[ local itemname = %s; - print("Debug: itemname =", itemname) local name = GetItemInfo(itemname or 0) or "Invalid" - print("Debug: name =", name) local icon = GetItemIcon(itemname or 0) - print("Debug: icon =", icon) local showgcd = %s - print("Debug: showgcd =", showgcd) local startTime, duration, enabled, gcdCooldown = WeakAuras.GetItemCooldown(itemname, showgcd); - print("Debug: startTime =", startTime, "duration =", duration, "enabled =", enabled, "gcdCooldown =", gcdCooldown) local expirationTime = startTime + duration - print("Debug: expirationTime =", expirationTime) local genericShowOn = %s - print("Debug: genericShowOn =", genericShowOn) state.itemname = itemname; ]=]; if(trigger.use_remaining and trigger.genericShowOn ~= "showOnReady") then From 67cd578d178bb9271b625ddcc67c59e86719da62 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 24 Jan 2025 20:11:34 +0100 Subject: [PATCH 075/153] from retail --- WeakAuras/Prototypes.lua | 187 ++++++++++++++++++++------------------- 1 file changed, 96 insertions(+), 91 deletions(-) diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index d43f4a9..2f2106d 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -2152,19 +2152,19 @@ Private.event_prototypes = { name = L["Power"], init = function(trigger) trigger.unit = trigger.unit or "player"; - local ret = [=[ + local ret = {} + table.insert(ret, ([=[ unit = string.lower(unit) local name, realm = WeakAuras.UnitNameWithRealm(unit) local smart = %s local powerType = %s; local unitPowerType = UnitPowerType(unit); local powerTypeToCheck = powerType or unitPowerType; - ]=]; - ret = ret:format(trigger.unit == "group" and "true" or "false", trigger.use_powertype and trigger.powertype or "nil"); + ]=]):format(trigger.unit == "group" and "true" or "false", trigger.use_powertype and trigger.powertype or "nil")) - ret = ret .. unitHelperFunctions.SpecificUnitCheck(trigger) + table.insert(ret, unitHelperFunctions.SpecificUnitCheck(trigger)) - return ret + return table.concat(ret) end, statesParameter = "unit", args = { @@ -3149,7 +3149,24 @@ Private.event_prototypes = { else spellName = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName; end - local ret = [=[ + local ret = {} + local showOnCheck = "false"; + if (trigger.genericShowOn == "showOnReady") then + showOnCheck = "startTime and startTime == 0 or gcdCooldown"; + elseif (trigger.genericShowOn == "showOnCooldown") then + showOnCheck = "startTime and startTime > 0 and not gcdCooldown"; + elseif (trigger.genericShowOn == "showAlways") then + showOnCheck = "startTime ~= nil"; + end + local trackSpecificCharge = trigger.use_trackcharge and trigger.trackcharge and trigger.trackcharge ~= "" + local track = trigger.track or "auto" + if track == "auto" and trackSpecificCharge then + track = "charges" + end + if (type(spellName) == "string") then + spellName = string.format("%q", spellName) + end + table.insert(ret, ([=[ local spellname = %s local ignoreRuneCD = %s local showgcd = %s; @@ -3160,54 +3177,57 @@ Private.event_prototypes = { local genericShowOn = %s local expirationTime = startTime and duration and startTime + duration state.spellname = spellname; - ]=]; - - local showOnCheck = "false"; - if (trigger.genericShowOn == "showOnReady") then - showOnCheck = "startTime and startTime == 0 or gcdCooldown"; - elseif (trigger.genericShowOn == "showOnCooldown") then - showOnCheck = "startTime and startTime > 0 and not gcdCooldown"; - elseif (trigger.genericShowOn == "showAlways") then - showOnCheck = "startTime ~= nil"; - end - - if (type(spellName) == "string") then - spellName = "[[" .. spellName .. "]]"; - end - ret = ret:format(spellName, + ]=]):format( + spellName, (trigger.use_matchedRune and "true" or "false"), (trigger.use_showgcd and "true" or "false"), showOnCheck - ); + )) - ret = ret .. [=[ - if (state.expirationTime ~= expirationTime) then - state.expirationTime = expirationTime; - state.changed = true; - end - if (state.duration ~= duration) then - state.duration = duration; - state.changed = true; - end - state.progressType = 'timed'; - ]=]; - - if(trigger.use_remaining and trigger.genericShowOn ~= "showOnReady") then - local ret2 = [[ - local remaining = 0; - if (expirationTime and expirationTime > 0) then - remaining = expirationTime - GetTime(); - local remainingCheck = %s; - if(remaining >= remainingCheck and remaining > 0) then - local event = "COOLDOWN_REMAINING_CHECK:" .. %s - Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck, event); + table.insert(ret, [=[ + if paused then + if not state.paused then + state.paused = true + state.expirationTime = nil + state.changed = true + end + if state.remaining ~= startTime then + state.remaining = startTime + state.changed = true + end + else + if (state.expirationTime ~= expirationTime) then + state.expirationTime = expirationTime; + state.changed = true; + end + if state.paused then + state.paused = false + state.remaining = nil + state.changed = true end end - ]]; - ret = ret..ret2:format(tonumber(trigger.remaining or 0) or 0, spellName); - end + if (state.duration ~= duration) then + state.duration = duration; + state.changed = true; + end + state.progressType = 'timed'; + ]=]) - return ret; + if(trigger.use_remaining and trigger.genericShowOn ~= "showOnReady") then + table.insert(ret, ([[ + local remaining = 0; + if (not paused and expirationTime and expirationTime > 0) then + remaining = expirationTime - GetTime(); + local remainingCheck = %s; + if(remaining >= remainingCheck and remaining > 0) then + local event = "COOLDOWN_REMAINING_CHECK:" .. %s + Private.ExecEnv.ScheduleScan(expirationTime - remainingCheck, event); + end + end + ]]):format(tonumber(trigger.remaining or 0) or 0, spellName)) + end + + return table.concat(ret) end, GetNameAndIcon = function(trigger) local spellName @@ -4898,44 +4918,41 @@ Private.event_prototypes = { name = L["Stance/Form/Aura"], init = function(trigger) local inverse = trigger.use_inverse; - local ret = [[ + local ret = {[[ local form = GetShapeshiftForm() local active = false - ]] + ]]} if trigger.use_form and trigger.form and trigger.form.single then -- Single selection - ret = ret .. [[ + table.insert(ret, ([[ local trigger_form = %d active = form == trigger_form - ]] + ]]):format(trigger.form.single)) if inverse then - ret = ret .. [[ + table.insert(ret, [[ active = not active - ]] + ]]) end - return ret:format(trigger.form.single) elseif trigger.use_form == false and trigger.form and trigger.form.multi then for index in pairs(trigger.form.multi) do - local ret2 = [[ + table.insert(ret, ([[ if not active then local index = %d active = form == index end - ]] - ret = ret .. ret2:format(index) + ]]):format(index)) end if inverse then - ret = ret .. [[ + table.insert(ret, [[ active = not active - ]] + ]]) end - return ret elseif trigger.use_form == nil then - ret = ret .. [[ + table.insert(ret, [[ active = true - ]] - return ret + ]]) end + return table.concat(ret) end, statesParameter = "one", args = { @@ -7107,38 +7124,27 @@ Private.event_prototypes = { statesParameter = "one", init = function(trigger) local spellName; - local ret; - if (trigger.use_exact_spellName) then - spellName = tonumber(trigger.spellName) or "nil"; - if spellName == 0 then - spellName = "nil" - end - ret = [[ - local spellName = %s; - local name, _, icon = GetSpellInfo(spellName) - ]] - ret = ret:format(spellName) - else - local name = type(trigger.spellName) == "number" and GetSpellInfo(trigger.spellName) or trigger.spellName or ""; - ret = [[ - local spellName _, icon = GetSpellInfo(%q) - local name = spellName - ]] - ret = ret:format(name) - end - local ret2 + local ret = {}; + + spellName = type(trigger.spellName) == "number" and trigger.spellName or 0; + table.insert(ret, ([[ + local spellName = %s; + local name, _, icon = GetSpellInfo(spellName) + ]]):format(spellName)) + + local spellCheck = spellName ~= 0 and "true" or "false" if (trigger.use_inverse) then - ret2 = [[ + table.insert(ret, ([[ local usePet = %s; - local active = not spellName or not IsSpellKnown(spellName, usePet) - ]] + local active = %s and IsSpellKnown(spellName, usePet) or false + ]]):format(trigger.use_petspell and "true" or "false", spellCheck)) else - ret2 = [[ + table.insert(ret, ([[ local usePet = %s; - local active = spellName and IsSpellKnown(spellName, usePet) - ]] + local active = %s and IsSpellKnown(spellName, usePet) + ]]):format(trigger.use_petspell and "true" or "false", spellCheck)) end - return ret .. ret2:format(trigger.use_petspell and "true" or "false") + return table.concat(ret) end, GetNameAndIcon = function(trigger) local name, _, icon = GetSpellInfo(trigger.spellName or 0) @@ -7151,7 +7157,6 @@ Private.event_prototypes = { display = L["Spell"], type = "spell", test = "true", - showExactOption = true, }, { name = "petspell", From 7671fd3c7bc719fdf80a148d9a921637bab64620 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 24 Jan 2025 20:41:04 +0100 Subject: [PATCH 076/153] from retail --- WeakAuras/Prototypes.lua | 56 ++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 2f2106d..01f7868 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -3402,10 +3402,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -3486,10 +3488,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -3592,10 +3596,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -3754,10 +3760,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -3955,10 +3963,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -3969,10 +3979,12 @@ Private.event_prototypes = { }, { name = "stacks", + display = L["Stacks"], init = "stacks", hidden = true, test = "true", - store = true + store = true, + conditionType = "number" }, { hidden = true, @@ -4033,10 +4045,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -4090,10 +4104,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -4161,10 +4177,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -4470,10 +4488,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -4484,10 +4504,12 @@ Private.event_prototypes = { }, { name = "stacks", + display = L["Stacks"], hidden = true, init = "stacks", test = "true", - store = true + store = true, + conditionType = "number" }, { hidden = true, @@ -5622,10 +5644,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "itemName", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", @@ -5699,10 +5723,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", + store = true, test = "true", - store = true + conditionType = "string" }, { name = "icon", @@ -7172,10 +7198,12 @@ Private.event_prototypes = { }, { name = "name", + display = L["Name"], hidden = true, init = "name", test = "true", - store = true + store = true, + conditionType = "string" }, { name = "icon", From b831fb40093a731e285830993e2773cdb30c7f5f Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 24 Jan 2025 20:50:23 +0100 Subject: [PATCH 077/153] from retail --- WeakAuras/RegionTypes/AuraBar.lua | 2 ++ WeakAuras/RegionTypes/Icon.lua | 2 ++ WeakAuras/RegionTypes/ProgressTexture.lua | 2 ++ WeakAuras/RegionTypes/StopMotion.lua | 2 ++ WeakAuras/WeakAuras.lua | 11 ++++++++++- WeakAurasOptions/CommonOptions.lua | 18 ++++++++++++++++-- 6 files changed, 34 insertions(+), 3 deletions(-) diff --git a/WeakAuras/RegionTypes/AuraBar.lua b/WeakAuras/RegionTypes/AuraBar.lua index 725896b..50de218 100644 --- a/WeakAuras/RegionTypes/AuraBar.lua +++ b/WeakAuras/RegionTypes/AuraBar.lua @@ -10,6 +10,8 @@ local default = { desaturate = false, iconSource = -1, progressSource = {-1, "" }, + adjustedMax = "", + adjustedMin = "", texture = "Blizzard", textureSource = "LSM", width = 200, diff --git a/WeakAuras/RegionTypes/Icon.lua b/WeakAuras/RegionTypes/Icon.lua index 34b3b12..24cd933 100644 --- a/WeakAuras/RegionTypes/Icon.lua +++ b/WeakAuras/RegionTypes/Icon.lua @@ -20,6 +20,8 @@ local default = { desaturate = false, iconSource = -1, progressSource = {-1, "" }, + adjustedMax = "", + adjustedMin = "", inverse = false, width = 64, height = 64, diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 196f184..f22d671 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -81,6 +81,8 @@ end local default = { progressSource = {-1, "" }, + adjustedMax = "", + adjustedMin = "", foregroundTexture = "Interface\\Addons\\WeakAuras\\PowerAurasMedia\\Auras\\Aura3", backgroundTexture = "Interface\\Addons\\WeakAuras\\PowerAurasMedia\\Auras\\Aura3", desaturateBackground = false, diff --git a/WeakAuras/RegionTypes/StopMotion.lua b/WeakAuras/RegionTypes/StopMotion.lua index df1e60c..13d435b 100644 --- a/WeakAuras/RegionTypes/StopMotion.lua +++ b/WeakAuras/RegionTypes/StopMotion.lua @@ -6,6 +6,8 @@ local L = WeakAuras.L; local default = { progressSource = {-1, "" }, + adjustedMax = "", + adjustedMin = "", foregroundTexture = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\StopMotion", backgroundTexture = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\StopMotion", desaturateBackground = false, diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 613d6dd..83ad10d 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -3104,7 +3104,7 @@ do if type(glow_frame_monitor) == "table" then for region, data in pairs(glow_frame_monitor) do - if region.state and region.state.unit == unit + if region.state and UnitIsUnit(region.state.unit, unit) and (data.frame ~= frame) == update_frame then if not new_frame then @@ -3879,6 +3879,15 @@ do end end end); + dynFrame.frame:RegisterEvent("PLAYER_REGEN_ENABLED") + dynFrame.frame:RegisterEvent("PLAYER_REGEN_DISABLED") + dynFrame.frame:SetScript("OnEvent", function(self, event) + if event == "PLAYER_REGEN_ENABLED" and self:IsShown() then + self:Hide() + elseif event == "PLAYER_REGEN_DISABLED" and not self:IsShown() and dynFrame.size > 0 then + self:Show() + end + end) end Private.dynFrame = dynFrame; diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index cb59f9d..6997445 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -1135,7 +1135,14 @@ local function ProgressOptions(data) width = WeakAuras.normalWidth, name = L["Set Minimum Progress"], desc = L["Values/Remaining Time below this value are displayed as zero progress."], - order = order + 1 + order = order + 1, + set = function(info, value) + data.useAdjustededMin = value + if not value then + data.adjustedMin = "" + end + WeakAuras.Add(data) + end }; options.adjustedMin = { @@ -1161,7 +1168,14 @@ local function ProgressOptions(data) width = WeakAuras.normalWidth, name = L["Set Maximum Progress"], desc = L["Values/Remaining Time above this value are displayed as full progress."], - order = order + 4 + order = order + 4, + set = function(info, value) + data.useAdjustededMax = value + if not value then + data.adjustedMax = "" + end + WeakAuras.Add(data) + end } options.adjustedMax = { From bd6985e67a27470d7da45c0981d783017c0b9a5c Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Fri, 24 Jan 2025 21:18:29 +0100 Subject: [PATCH 078/153] from retail --- WeakAuras/GenericTrigger.lua | 93 +++++++------------ WeakAuras/Modernize.lua | 42 ++++++++- WeakAuras/Prototypes.lua | 8 +- WeakAuras/SubRegionTypes/Glow.lua | 11 ++- WeakAuras/Transmission.lua | 66 +++++++++++-- WeakAuras/Types.lua | 15 +++ WeakAuras/WeakAuras.lua | 25 +++-- .../OptionsFrames/ImportExport.lua | 2 +- 8 files changed, 178 insertions(+), 84 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 14fc0e2..7570369 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -2937,14 +2937,18 @@ function WeakAuras.WatchUnitChange(unit) eventsToSend["UNIT_CHANGED_" .. unitA] = unitA if watchUnitChange.GUIDToUnitIds[oldGUID] then for unitB in pairs(watchUnitChange.GUIDToUnitIds[oldGUID]) do - eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitA .. "_" .. unitB] = unitA - eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitB .. "_" .. unitA] = unitB + if unitA ~= unitB then + eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitA .. "_" .. unitB] = unitA + eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitB .. "_" .. unitA] = unitB + end end end if watchUnitChange.GUIDToUnitIds[newGUID] then for unitB in pairs(watchUnitChange.GUIDToUnitIds[newGUID]) do - eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitA .. "_" .. unitB] = unitA - eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitB .. "_" .. unitA] = unitB + if unitA ~= unitB then + eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitA .. "_" .. unitB] = unitA + eventsToSend["UNIT_IS_UNIT_CHANGED_" .. unitB .. "_" .. unitA] = unitB + end end end end @@ -3005,64 +3009,44 @@ function WeakAuras.WatchUnitChange(unit) end end + local function handleUnit(unit, eventsToSend, ...) + if watchUnitChange.trackedUnits[unit] then + local fn + for i = 1, select("#", ...) do + fn = select(i, ...) + fn(unit, eventsToSend) + end + end + end + watchUnitChange:SetScript("OnEvent", function(self, event, unit) Private.StartProfileSystem("generictrigger unit change"); local eventsToSend = {} if event == "PLAYER_ENTERING_WORLD" then for unit in pairs(watchUnitChange.unitIdToGUID) do - unitUpdate(unit, eventsToSend) - markerUpdate(unit, eventsToSend) - reactionUpdate(unit, eventsToSend) + handleUnit(unit, eventsToSend, unitUpdate, markerUpdate, reactionUpdate) end elseif event == "NAME_PLATE_UNIT_ADDED" then - if not watchUnitChange.trackedUnits[unit] then - Private.StopProfileSystem("generictrigger unit change"); - return - end - unitUpdate(unit, eventsToSend) - markerInit(unit) - reactionInit(unit) + handleUnit(unit, eventsToSend, unitUpdate, markerInit, reactionInit) elseif event == "NAME_PLATE_UNIT_REMOVED" then - if not watchUnitChange.trackedUnits[unit] then - Private.StopProfileSystem("generictrigger unit change"); - return - end - unitUpdate(unit, eventsToSend) - markerClear(unit) - reactionClear(unit) + handleUnit(unit, eventsToSend, unitUpdate, markerClear, reactionClear) elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then for i = 1, 5 do - local unit = "boss" .. i - if watchUnitChange.trackedUnits[unit] then - unitUpdate(unit, eventsToSend) - markerInit(unit) - reactionInit(unit) - end + handleUnit("boss" .. i, eventsToSend, unitUpdate, markerInit, reactionInit) + handleUnit("boss" .. i .. "target", eventsToSend, unitUpdate, markerInit, reactionInit) end elseif event == "PLAYER_TARGET_CHANGED" then - if not watchUnitChange.trackedUnits["target"] then - Private.StopProfileSystem("generictrigger unit change"); - return - end - unitUpdate("target", eventsToSend) - markerInit("target") - reactionInit("target") + handleUnit("target", eventsToSend, unitUpdate, markerInit, reactionInit) + handleUnit("targettarget", eventsToSend, unitUpdate, markerInit, reactionInit) elseif event == "PLAYER_FOCUS_CHANGED" then - if not watchUnitChange.trackedUnits["focus"] then - Private.StopProfileSystem("generictrigger unit change"); - return - end - unitUpdate("focus", eventsToSend) - markerInit("focus") - reactionInit("focus") + handleUnit("focus", eventsToSend, unitUpdate, markerInit, reactionInit) + handleUnit("focustarget", eventsToSend, unitUpdate, markerInit, reactionInit) elseif event == "RAID_TARGET_UPDATE" then for unit in pairs(watchUnitChange.raidmark) do - markerUpdate(unit, eventsToSend) + handleUnit(unit, eventsToSend, markerUpdate) end elseif event == "UNIT_FACTION" then - if watchUnitChange.trackedUnits[unit] then - reactionUpdate(unit, eventsToSend) - end + handleUnit(unit, eventsToSend, reactionUpdate) elseif event == "UNIT_PET" then local pet = WeakAuras.unitToPetUnit[unit] if pet and watchUnitChange.trackedUnits[pet] then @@ -3070,26 +3054,13 @@ function WeakAuras.WatchUnitChange(unit) end elseif event == "PLAYER_ROLES_ASSIGNED" then for unit in pairs(Private.multiUnitUnits.group) do - if watchUnitChange.trackedUnits[unit] then - roleUpdate(unit, eventsToSend) - end + handleUnit(unit, eventsToSend, roleUpdate) end elseif event == "UNIT_TARGET" then - local unitTarget = unit .. "target" - if not watchUnitChange.trackedUnits[unitTarget] then - Private.StopProfileSystem("generictrigger unit change"); - return - end - unitUpdate(unitTarget, eventsToSend) - markerInit(unitTarget) - reactionInit(unitTarget) + handleUnit(unit .. "target", eventsToSend, unitUpdate, markerInit, reactionInit) elseif event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" then for unit in pairs(Private.multiUnitUnits.group) do - if watchUnitChange.trackedUnits[unit] then - unitUpdate(unit, eventsToSend) - markerInit(unit, eventsToSend) - reactionInit(unit, eventsToSend) - end + handleUnit(unit, eventsToSend, unitUpdate, markerInit, reactionInit) end local inRaid = IsInRaid() local inRaidChanged = inRaid ~= watchUnitChange.inRaid diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index dfb0f50..40e13e1 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -3,7 +3,7 @@ local AddonName, Private = ... local L = WeakAuras.L -- Takes as input a table of display data and attempts to update it to be compatible with the current version -function Private.Modernize(data) +function Private.Modernize(data, oldSnapshot) if not data.internalVersion or data.internalVersion < 2 then WeakAuras.prettyPrint(string.format("Data for '%s' is too old, can't modernize.", data.id)) data.internalVersion = 2 @@ -1504,5 +1504,45 @@ function Private.Modernize(data) end end + if data.internalVersion < 75 then + -- this commit from nov 2019 https://github.com/WeakAuras/WeakAuras2/commit/6d8f11c17422aeffdb82a0aa05181edfdd137896 + -- changed adjustedMin & adjustedMax type from number to string (range => input) + -- but didn't include a migration + if type(data.adjustedMin) == "number" then + data.adjustedMin = tostring(data.adjustedMin) + end + if type(data.adjustedMax) == "number" then + data.adjustedMax = tostring(data.adjustedMax) + end + -- this commit https://github.com/WeakAuras/WeakAuras2/commit/dbcb70b1e4df262af82f63620b3b0d80741e6df2 + -- set a default for adjustedMin & adjustedMax with an empty string + -- in Private.validate if type of value is different from type of default, value is set to default + -- which had effect to lose data if aura was made before nov 2019 ~ 2020 + -- try detect data loss and restore from Archivist + if data.internalVersion == 74 and oldSnapshot then + local restoreMin = data.useAdjustededMin and data.adjustedMin == "" + local restoreMax = data.useAdjustededMax and data.adjustedMax == "" + if restoreMin or restoreMax then + if restoreMin and type(oldSnapshot.adjustedMin) == "number" then + data.adjustedMin = tostring(oldSnapshot.adjustedMin) + end + if restoreMax and type(oldSnapshot.adjustedMax) == "number" then + data.adjustedMax = tostring(oldSnapshot.adjustedMax) + end + end + end + end + data.internalVersion = max(data.internalVersion or 0, WeakAuras.InternalVersion()) end + +--- Returns true if Modernize will use data from last snapshot before a new one is done +function Private.ModernizeNeedsOldSnapshot(data) + if data.internalVersion == 74 then + local restoreMin = data.useAdjustededMin and data.adjustedMin == "" + local restoreMax = data.useAdjustededMax and data.adjustedMax == "" + if restoreMin or restoreMax then + return true + end + end +end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 01f7868..db4ec37 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4067,9 +4067,11 @@ Private.event_prototypes = { ["Cooldown Ready (Equipment Slot)"] = { type = "item", events = {}, - internal_events = { - "ITEM_SLOT_COOLDOWN_READY" - }, + internal_events = function(trigger) + return { + "ITEM_SLOT_COOLDOWN_READY:" .. (trigger.itemSlot or 0) + } + end, name = L["Cooldown Ready Event (Slot)"], loadFunc = function(trigger) WeakAuras.WatchItemSlotCooldown(trigger.itemSlot); diff --git a/WeakAuras/SubRegionTypes/Glow.lua b/WeakAuras/SubRegionTypes/Glow.lua index 7baee07..5c21662 100644 --- a/WeakAuras/SubRegionTypes/Glow.lua +++ b/WeakAuras/SubRegionTypes/Glow.lua @@ -359,7 +359,7 @@ function Private.getDefaultGlow(regionType) glowYOffset = 0, glow_anchor = "bar" } - elseif regionType == "icon" then + else return { ["type"] = "subglow", glow = false, @@ -378,9 +378,14 @@ function Private.getDefaultGlow(regionType) end end +local supportedRegion = { + icon = true, + aurabar = true, + texture = true, + progresstexture = true +} local function supports(regionType) - return regionType == "icon" - or regionType == "aurabar" + return supportedRegion[regionType] end local function addDefaultsForNewAura(data) diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index 53b6176..13ae159 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -377,8 +377,60 @@ function Private.DisplayToString(id, forChat) end end -local function recurseStringify(data, level, lines) - for k, v in pairs(data) do +local orderedPairs +do + local function __genOrderedIndex(t) + local orderedIndex = {} + for key in pairs(t) do + if key ~= "__orderedIndex" then + table.insert(orderedIndex, key) + end + end + table.sort(orderedIndex, function(a, b) + local typeA, typeB = type(a), type(b) + if typeA ~= typeB then + return typeA < typeB + else + return a < b + end + end) + return orderedIndex + end + + local function orderedNext(t, state) + -- Equivalent of the next function, but returns the keys in the alphabetic + -- order. We use a temporary ordered key table that is stored in the + -- table being iterated. + local key = nil + if state == nil then + -- the first time, generate the index + t.__orderedIndex = __genOrderedIndex(t) + key = t.__orderedIndex[1] + else + -- fetch the next value + for i = 1, table.getn(t.__orderedIndex) do + if t.__orderedIndex[i] == state then + key = t.__orderedIndex[i+1] + end + end + end + + if key then + return key, t[key] + end + + -- no more value to return, cleanup + t.__orderedIndex = nil + end + + function orderedPairs(t) + return orderedNext, t, nil + end +end + +local function recurseStringify(data, level, lines, sorted) + local pairsFn = sorted and orderedPairs or pairs + for k, v in pairsFn(data) do local lineFormat = strrep(" ", level) .. "[%s] = %s" local form1, form2, value local kType, vType = type(k), type(v) @@ -401,7 +453,7 @@ local function recurseStringify(data, level, lines) lineFormat = lineFormat:format(form1, form2) if vType == "table" then tinsert(lines, lineFormat:format(k, "{")) - recurseStringify(v, level + 1, lines) + recurseStringify(v, level + 1, lines, sorted) tinsert(lines, strrep(" ", level) .. "},") else tinsert(lines, lineFormat:format(k, v) .. ",") @@ -409,16 +461,16 @@ local function recurseStringify(data, level, lines) end end -function Private.DataToString(id) +function Private.DataToString(id, sorted) local data = WeakAuras.GetData(id) if data then - return Private.SerializeTable(data):gsub("|", "||") + return Private.SerializeTable(data, sorted):gsub("|", "||") end end -function Private.SerializeTable(data) +function Private.SerializeTable(data, sorted) local lines = {"{"} - recurseStringify(data, 1, lines) + recurseStringify(data, 1, lines, sorted) tinsert(lines, "}") return table.concat(lines, "\n") end diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 79918a1..f726790 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -2349,9 +2349,24 @@ LSM.RegisterCallback(WeakAuras, "LibSharedMedia_Registered", function(_, mediaty Private.sound_types[path] = key Private.sound_file_types[path] = key end + elseif mediatype == "statusbar" then + local path = LSM:Fetch(mediatype, key) + if path then + Private.texture_types["LibSharedMedia Textures"][path] = key + end end end) +Private.texture_types["LibSharedMedia Textures"] = {} +for _, mediaType in ipairs{"statusbar"} do + local mediaTable = LSM:HashTable(mediaType) + if mediaTable then + for name, path in pairs(mediaTable) do + Private.texture_types["LibSharedMedia Textures"][path] = name + end + end +end + -- register options font LSM:Register("font", "Fira Mono Medium", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraMono-Medium.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU) -- Other Fira fonts diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 83ad10d..7b60518 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1,6 +1,6 @@ local AddonName, Private = ... -local internalVersion = 73 +local internalVersion = 75 -- Lua APIs local insert = table.insert @@ -2192,8 +2192,12 @@ function Private.AddMany(tbl, takeSnapshots) local order = loadOrder(tbl, idtable) coroutine.yield() + local oldSnapshots = {} if takeSnapshots then for _, data in ipairs(order) do + if Private.ModernizeNeedsOldSnapshot(data) then + oldSnapshots[data.uid] = Private.GetMigrationSnapshot(data.uid) + end Private.SetMigrationSnapshot(data.uid, data) coroutine.yield() end @@ -2205,7 +2209,8 @@ function Private.AddMany(tbl, takeSnapshots) if data.parent and bads[data.parent] then bads[data.id] = true else - local ok = pcall(WeakAuras.PreAdd, data) + local oldSnapshot = oldSnapshots[data.uid] or nil + local ok = pcall(WeakAuras.PreAdd, data, oldSnapshot) if not ok then Private.GetErrorHandlerUid(data.uid, "PreAdd") prettyPrint(L["Unable to modernize aura '%s'. This is probably due to corrupt data or a bad migration, please report this to the WeakAuras team."]:format(data.id)) @@ -2576,7 +2581,7 @@ function Private.ClearSounds(uid) WeakAuras.FillOptions() end -function WeakAuras.PreAdd(data) +function WeakAuras.PreAdd(data, snapshot) if not data then return end -- Readd what Compress removed before version 8 if (not data.internalVersion or data.internalVersion < 7) then @@ -2585,7 +2590,7 @@ function WeakAuras.PreAdd(data) Private.validate(data, oldDataStub2) end - local ok = pcall(Private.Modernize, data) + local ok = pcall(Private.Modernize, data, snapshot) if not ok then Private.GetErrorHandlerId(data.id, L["Modernize"]) end @@ -2787,14 +2792,18 @@ function pAdd(data, simpleChange) end function WeakAuras.Add(data, simpleChange) + local oldSnapshot + if Private.ModernizeNeedsOldSnapshot(data) then + oldSnapshot = Private.GetMigrationSnapshot(data.uid) + end if (data.internalVersion or 0) < internalVersion then Private.SetMigrationSnapshot(data.uid, data) end - local ok, ret = pcall(WeakAuras.PreAdd, data) - if not ok then - Private.GetErrorHandlerUid(data.uid, "PreAdd") - elseif ok then + local ok, ret = pcall(WeakAuras.PreAdd, data, oldSnapshot) + if ok then pAdd(data, simpleChange) + else + Private.GetErrorHandlerUid(data.uid, "PreAdd") end end diff --git a/WeakAurasOptions/OptionsFrames/ImportExport.lua b/WeakAurasOptions/OptionsFrames/ImportExport.lua index ecc4075..5d19960 100644 --- a/WeakAurasOptions/OptionsFrames/ImportExport.lua +++ b/WeakAurasOptions/OptionsFrames/ImportExport.lua @@ -50,7 +50,7 @@ local function ConstructImportExport(frame) if(mode == "export") then displayStr = OptionsPrivate.Private.DisplayToString(id, true); elseif(mode == "table") then - displayStr = OptionsPrivate.Private.DataToString(id); + displayStr = OptionsPrivate.Private.DataToString(id, true); end input.editBox:SetMaxBytes(nil); input.editBox:SetScript("OnEscapePressed", function() group:Close(); end); From bd4cba924f30e903cbe380a7e458b93c099739e3 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Sat, 25 Jan 2025 16:14:11 +0100 Subject: [PATCH 079/153] from retail --- WeakAuras/GenericTrigger.lua | 58 ++++++++++++------- WeakAuras/Init.lua | 1 - WeakAuras/embeds.xml | 1 - .../AceGUIWidget-WeakAurasSnippetButton.lua | 10 ---- 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 7570369..c34d7e3 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -52,11 +52,7 @@ local AddonName, Private = ... -- Lua APIs local tinsert, tconcat, wipe = table.insert, table.concat, wipe local tonumber, tostring, pairs, type = tonumber, tostring, pairs, type -local error, setmetatable = error, setmetatable - -WeakAurasAceEvents = setmetatable({}, {__tostring=function() return "WeakAuras" end}); -LibStub("AceEvent-3.0"):Embed(WeakAurasAceEvents); -local aceEvents = WeakAurasAceEvents +local error = error local WeakAuras = WeakAuras; local L = WeakAuras.L; @@ -2658,7 +2654,7 @@ do -- We check against 1.5 and gcdDuration, as apparently the durations might not match exactly. -- But there shouldn't be any trinket with a actual cd of less than 1.5 anyway - if(duration > 0 and duration > 1.5 and duration ~= WeakAuras.gcdDuration()) then + if(duration and duration > 0 and duration > 1.5 and duration ~= WeakAuras.gcdDuration()) then -- On non-GCD cooldown local endTime = startTime + duration; @@ -2916,6 +2912,7 @@ function WeakAuras.WatchUnitChange(unit) Private.frames["Unit Change Frame"] = watchUnitChange; watchUnitChange:RegisterEvent("PLAYER_TARGET_CHANGED") watchUnitChange:RegisterEvent("PLAYER_FOCUS_CHANGED"); + watchUnitChange:RegisterEvent("ARENA_OPPONENT_UPDATE") watchUnitChange:RegisterEvent("PLAYER_ROLES_ASSIGNED"); watchUnitChange:RegisterEvent("UNIT_TARGET"); watchUnitChange:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT"); @@ -3019,46 +3016,59 @@ function WeakAuras.WatchUnitChange(unit) end end - watchUnitChange:SetScript("OnEvent", function(self, event, unit) - Private.StartProfileSystem("generictrigger unit change"); - local eventsToSend = {} - if event == "PLAYER_ENTERING_WORLD" then + local handleEvent = { + PLAYER_ENTERING_WORLD = function(_, eventsToSend) for unit in pairs(watchUnitChange.unitIdToGUID) do handleUnit(unit, eventsToSend, unitUpdate, markerUpdate, reactionUpdate) end - elseif event == "NAME_PLATE_UNIT_ADDED" then + end, + NAME_PLATE_UNIT_ADDED = function(unit, eventsToSend) handleUnit(unit, eventsToSend, unitUpdate, markerInit, reactionInit) - elseif event == "NAME_PLATE_UNIT_REMOVED" then + end, + NAME_PLATE_UNIT_REMOVED = function(unit, eventsToSend) handleUnit(unit, eventsToSend, unitUpdate, markerClear, reactionClear) - elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then + end, + INSTANCE_ENCOUNTER_ENGAGE_UNIT = function(_, eventsToSend) for i = 1, 5 do handleUnit("boss" .. i, eventsToSend, unitUpdate, markerInit, reactionInit) handleUnit("boss" .. i .. "target", eventsToSend, unitUpdate, markerInit, reactionInit) end - elseif event == "PLAYER_TARGET_CHANGED" then + end, + ARENA_OPPONENT_UPDATE = function(unit, eventsToSend) + handleUnit(unit, eventsToSend, unitUpdate, markerInit, reactionInit) + handleUnit(unit .. "target", eventsToSend, unitUpdate, markerInit, reactionInit) + end, + PLAYER_TARGET_CHANGED = function(_, eventsToSend) handleUnit("target", eventsToSend, unitUpdate, markerInit, reactionInit) handleUnit("targettarget", eventsToSend, unitUpdate, markerInit, reactionInit) - elseif event == "PLAYER_FOCUS_CHANGED" then + end, + PLAYER_FOCUS_CHANGED = function(_, eventsToSend) handleUnit("focus", eventsToSend, unitUpdate, markerInit, reactionInit) handleUnit("focustarget", eventsToSend, unitUpdate, markerInit, reactionInit) - elseif event == "RAID_TARGET_UPDATE" then + end, + RAID_TARGET_UPDATE = function(_, eventsToSend) for unit in pairs(watchUnitChange.raidmark) do handleUnit(unit, eventsToSend, markerUpdate) end - elseif event == "UNIT_FACTION" then + end, + UNIT_FACTION = function(unit, eventsToSend) handleUnit(unit, eventsToSend, reactionUpdate) - elseif event == "UNIT_PET" then + end, + UNIT_PET = function(unit, eventsToSend) local pet = WeakAuras.unitToPetUnit[unit] if pet and watchUnitChange.trackedUnits[pet] then eventsToSend["UNIT_CHANGED_" .. pet] = pet end - elseif event == "PLAYER_ROLES_ASSIGNED" then + end, + PLAYER_ROLES_ASSIGNED = function(_, eventsToSend) for unit in pairs(Private.multiUnitUnits.group) do handleUnit(unit, eventsToSend, roleUpdate) end - elseif event == "UNIT_TARGET" then + end, + UNIT_TARGET = function(unit, eventsToSend) handleUnit(unit .. "target", eventsToSend, unitUpdate, markerInit, reactionInit) - elseif event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" then + end, + GROUP_ROSTER_UPDATE = function(_, eventsToSend) for unit in pairs(Private.multiUnitUnits.group) do handleUnit(unit, eventsToSend, unitUpdate, markerInit, reactionInit) end @@ -3073,7 +3083,13 @@ function WeakAuras.WatchUnitChange(unit) watchUnitChange.inRaid = inRaid end end + } + handleEvent["RAID_ROSTER_UPDATE"] = handleEvent["GROUP_ROSTER_UPDATE"] + watchUnitChange:SetScript("OnEvent", function(self, event, unit) + Private.StartProfileSystem("generictrigger unit change"); + local eventsToSend = {} + handleEvent[event](unit, eventsToSend) -- send events for event, unit in pairs(eventsToSend) do WeakAuras.ScanEvents(event, unit) diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index 65b4f54..aab0fef 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -44,7 +44,6 @@ do "AceConfig-3.0", "AceConsole-3.0", "AceGUI-3.0", - "AceEvent-3.0", "AceGUISharedMediaWidgets-1.0", "AceTimer-3.0", "AceSerializer-3.0", diff --git a/WeakAuras/embeds.xml b/WeakAuras/embeds.xml index 0f5db4b..0497f38 100644 --- a/WeakAuras/embeds.xml +++ b/WeakAuras/embeds.xml @@ -8,7 +8,6 @@ -