diff --git a/WeakAuras/BuffTrigger2.lua b/WeakAuras/BuffTrigger2.lua index c5579b8..e46675f 100644 --- a/WeakAuras/BuffTrigger2.lua +++ b/WeakAuras/BuffTrigger2.lua @@ -64,6 +64,8 @@ local timer = WeakAuras.timer local BuffTrigger = {} local triggerInfos = {} +local watched_trigger_events = Private.watched_trigger_events + -- keyed on unit, debuffType, spellname, with a scan object value -- scan object: id, triggernum, scanFunc local scanFuncName = {} @@ -1348,6 +1350,13 @@ local function UpdateTriggerState(time, id, triggernum) triggerInfo.nextScheduledCheckHandle = nil triggerInfo.nextScheduledCheck = nil end + + -- if the trigger has updated then check to see if it is flagged for WatchedTrigger and send to queue if it is + if updated then + if watched_trigger_events[id] and watched_trigger_events[id][triggernum] then + Private.AddToWatchedTriggerDelay(id, triggernum) + end + end return updated end diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 68bf589..381feea 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -72,6 +72,7 @@ local timer = WeakAuras.timer; local events = {} 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; @@ -711,6 +712,10 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2 end end end + if updateTriggerState and watched_trigger_events[id] and watched_trigger_events[id][triggernum] then + -- if this trigger's udpates are requested to be sent into one of the Aura's custom triggers + Private.AddToWatchedTriggerDelay(id, triggernum) + end return updateTriggerState; end @@ -788,6 +793,31 @@ function WeakAuras.ScanEventsInternal(event_list, event, arg1, arg2, ... ) end end +function Private.ScanEventsWatchedTrigger(id, watchedTriggernums) + Private.StartProfileAura(id); + Private.ActivateAuraEnvironment(id); + local updateTriggerState = false + for _, wathcedTrigger in ipairs(watchedTriggernums) do + if watched_trigger_events[id] and watched_trigger_events[id][wathcedTrigger] then + local updatedTriggerStates = WeakAuras.GetTriggerStateForTrigger(id, wathcedTrigger) + for observerTrigger in pairs(watched_trigger_events[id][wathcedTrigger]) do + local data = events and events[id] and events[id][observerTrigger] + local allstates = WeakAuras.GetTriggerStateForTrigger(id, observerTrigger) + if data and allstates and updatedTriggerStates then + if RunTriggerFunc(allstates, data, id, observerTrigger, "TRIGGER", wathcedTrigger, updatedTriggerStates) then + updateTriggerState = true + end + end + end + end + end + if (updateTriggerState) then + Private.UpdatedTriggerState(id) + end + Private.StopProfileAura(id) + Private.ActivateAuraEnvironment(nil) +end + local function AddFakeTime(state) if state.progressType == "timed" then if state.expirationTime and state.expirationTime ~= math.huge and state.expirationTime > GetTime() then @@ -985,6 +1015,9 @@ function GenericTrigger.Rename(oldid, newid) end end + watched_trigger_events[newid] = watched_trigger_events[oldid] + watched_trigger_events[oldid] = nil + Private.EveryFrameUpdateRename(oldid, newid) end @@ -1199,6 +1232,7 @@ end function GenericTrigger.Add(data, region) local id = data.id; events[id] = nil; + watched_trigger_events[id] = nil for triggernum, triggerData in ipairs(data.triggers) do local trigger, untrigger = triggerData.trigger, triggerData.untrigger @@ -1358,10 +1392,12 @@ function GenericTrigger.Add(data, region) local hasParam = false local isCLEU = false local isUnitEvent = false + local isTrigger = false for i in event:gmatch("[^:]+") do if not trueEvent then trueEvent = string.upper(i) isCLEU = trueEvent == "CLEU" or trueEvent == "COMBAT_LOG_EVENT_UNFILTERED" + isTrigger = trueEvent == "TRIGGER" elseif isCLEU then local subevent = string.upper(i) if Private.IsCLEUSubevent(subevent) then @@ -1381,6 +1417,17 @@ function GenericTrigger.Add(data, region) trigger_unit_events[i] = trigger_unit_events[i] or {} tinsert(trigger_unit_events[i], trueEvent) + elseif isTrigger then + local requestedTriggernum = tonumber(i) + if requestedTriggernum then + if watched_trigger_events[id] and watched_trigger_events[id][triggernum] and watched_trigger_events[id][triggernum][requestedTriggernum] then + -- if the request is reciprocal (2 custom triggers request each other which would cause a stack overflow) then prevent the reciprocal one being added. + elseif requestedTriggernum and requestedTriggernum ~= triggernum then + watched_trigger_events[id] = watched_trigger_events[id] or {} + watched_trigger_events[id][requestedTriggernum] = watched_trigger_events[id][requestedTriggernum] or {} + watched_trigger_events[id][requestedTriggernum][triggernum] = true + end + end end end if isCLEU then @@ -1395,6 +1442,8 @@ function GenericTrigger.Add(data, region) end elseif isUnitEvent then -- not added to trigger_events + elseif isTrigger then + -- not added to trigger_events else tinsert(trigger_events, event) end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 1e0b639..2d7532d 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -28,6 +28,8 @@ local prettyPrint = WeakAuras.prettyPrint WeakAurasTimers = setmetatable({}, {__tostring=function() return "WeakAuras" end}) 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 Private.callbacks = {} @@ -3686,6 +3688,23 @@ local function ApplyStatesToRegions(id, activeTrigger, states) end end +-- handle trigger updates that have been requested to be sent into custom +-- we need the id and triggernum that's changing, but can't send the ScanEvents to the custom trigger until after UpdatedTriggerState has fired +local delayed_watched_trigger = {} +function Private.AddToWatchedTriggerDelay(id, triggernum) + delayed_watched_trigger[id] = delayed_watched_trigger[id] or {} + tinsert(delayed_watched_trigger[id], triggernum) +end +function Private.SendDelayedWatchedTriggers() + for id in pairs(delayed_watched_trigger) do + local watched = delayed_watched_trigger[id] + -- Since the observers are themselves observable, we set the list of observers to + -- empty here. + delayed_watched_trigger[id] = {} + Private.ScanEventsWatchedTrigger(id, watched) + end +end + function Private.UpdatedTriggerState(id) if (not triggerState[id]) then return; @@ -3788,6 +3807,9 @@ function Private.UpdatedTriggerState(id) state.changed = false; end end + + -- once updatedTriggerStates is complete, and empty states removed, etc., then check for queued watched triggers update + Private.SendDelayedWatchedTriggers() end function Private.RunCustomTextFunc(region, customFunc) diff --git a/WeakAurasOptions/GenericTrigger.lua b/WeakAurasOptions/GenericTrigger.lua index 552727e..1f306ee 100644 --- a/WeakAurasOptions/GenericTrigger.lua +++ b/WeakAurasOptions/GenericTrigger.lua @@ -120,6 +120,15 @@ local function GetCustomTriggerOptions(data, triggernum) if not (OptionsPrivate.Private.baseUnitId[unit] and OptionsPrivate.Private.multiUnitId[unit]) and not string.find(unit, "^nameplate%d+$") then return "|cFFFF0000"..L["Unit %s is not a valid unit for RegisterUnitEvent"]:format(unit) end + elseif trueEvent == "TRIGGER" then + local requestedTriggernum = tonumber(i) + if requestedTriggernum then + if OptionsPrivate.Private.watched_trigger_events[data.id] + and OptionsPrivate.Private.watched_trigger_events[data.id][triggernum] + and OptionsPrivate.Private.watched_trigger_events[data.id][triggernum][requestedTriggernum] then + return "|cFFFF0000"..L["Reciprocal TRIGGER:# requests will be ignored!"] + end + end end end end @@ -151,6 +160,15 @@ local function GetCustomTriggerOptions(data, triggernum) if not (OptionsPrivate.Private.baseUnitId[unit] or string.find(unit, "^nameplate%d+$")) then return false end + elseif trueEvent == "TRIGGER" then + local requestedTriggernum = tonumber(i) + if requestedTriggernum then + if OptionsPrivate.Private.watched_trigger_events[data.id] + and OptionsPrivate.Private.watched_trigger_events[data.id][triggernum] + and OptionsPrivate.Private.watched_trigger_events[data.id][triggernum][requestedTriggernum] then + return false + end + end end end end diff --git a/WeakAurasOptions/Locales/enUS.lua b/WeakAurasOptions/Locales/enUS.lua index 983f6da..e312099 100644 --- a/WeakAurasOptions/Locales/enUS.lua +++ b/WeakAurasOptions/Locales/enUS.lua @@ -106,14 +106,20 @@ L["Crusader"] = "Crusader" L["Custom Code"] = "Custom Code" L["Custom Trigger"] = "Custom Trigger" L["Custom trigger event tooltip"] = [=[ -Choose which events cause the custom trigger to be checked. -Multiple events can be specified using commas or spaces. +Choose which events cause the custom trigger to be checked. Multiple events can be specified using commas or spaces. +• "UNIT" events can use colons to define which unitIDs will be registered. In addition to UnitIDs Unit types can be used, they include "nameplate", "group", "raid", "party", "arena", "boss". +• "CLEU" can be used instead of COMBAT_LOG_EVENT_UNFILTERED and colons can be used to separate specific "subEvents" you want to recieve. +• The keyword "TRIGGER" can be used, with colons separating trigger numbers, to have the custom trigger get updated when the specified trigger(s) update. |cFF4444FFFor example:|r -UNIT_POWER_UPDATE, UNIT_AURA PLAYER_TARGET_CHANGED +UNIT_POWER_UPDATE:player, UNIT_AURA:nameplate:group PLAYER_TARGET_CHANGED CLEU:SPELL_CAST_SUCCESS TRIGGER:3:1 ]=] L["Custom trigger status tooltip"] = [=[ -Choose which events cause the custom trigger to be checked. +Choose which events cause the custom trigger to be checked. Multiple events can be specified using commas or spaces. +• "UNIT" events can use colons to define which unitIDs will be registered. In addition to UnitIDs Unit types can be used, they include "nameplate", "group", "raid", "party", "arena", "boss". +• "CLEU" can be used instead of COMBAT_LOG_EVENT_UNFILTERED and colons can be used to separate specific "subEvents" you want to recieve. +• The keyword "TRIGGER" can be used, with colons separating trigger numbers, to have the custom trigger get updated when the specified trigger(s) update. + Since this is a status-type trigger, the specified events may be called by WeakAuras without the expected arguments. Multiple events can be specified using commas or spaces. @@ -127,7 +133,7 @@ This can be different than the events defined for the trigger. Multiple events can be specified using commas or spaces. |cFF4444FFFor example:|r -UNIT_POWER_UPDATE, UNIT_AURA PLAYER_TARGET_CHANGED +UNIT_POWER_UPDATE:player, UNIT_AURA:nameplate:group PLAYER_TARGET_CHANGED CLEU:SPELL_CAST_SUCCESS TRIGGER:3:1 ]=] L["Death"] = "Death" L["Death Rune"] = "Death Rune"