local L = AceLibrary("AceLocale-2.2"):new("GridAlert") L:RegisterTranslations("enUS", function () return { ["GridAlert"] = true, ["Options for %s."] = true, ["Display"] = true, ["Set where messages are displayed."] = true, ["Default Frame"] = true, ["BigWigs frame"] = true, ["Scrolling Combat Text"] = true, ["Mik's Scrolling Battle Text"] = true, ["Minimum pause"] = true, ["Minimum pause between two alerts of any kind, in seconds."] = true, ["Triggers"] = true, ["Options to setup trigger from status"] = true, ["Alerts"] = true, ["Options for the type of alert triggered"] = true, ["Add an alert"] = true, ["Create a new alert"] = true, ["Remove an alert"] = true, ["Sound name"] = true, ["Name of a sound to play (must be a valid sound name)."] = true, ["Sound filename"] = true, ["Filename of a sound to play (must be a valid path), overrides Sound name."] = true, ["Message to display"] = true, ["Message to display, set to off to disable."] = true, ["Message to display, set to off to disable."] = true, ["off"] = true, ["Minimum pause"] = true, ["Minimum pause between two of this kind of alert, in second."] = true, ["Any unit gains"] = true, ["Alert to trigger when any unit gains Status"] = true, ["Player gains"] = true, ["Alert to trigger when the player gains Status"] = true, ["Other players gain"] = true, ["Alert when other players gain Status"] = true, ["All units lose"] = true, ["Alert to trigger when all units have lost Status"] = true, ["Player loses"] = true, ["Alert to trigger when the player loses Status"] = true, ["Other players lose"] = true, ["Alert when other players lose Status"] = true, ["Options for alert %s"] = true, } end) GridAlert = GridStatus:NewModule("GridAlert") --[[ triggers = { <> = { gain = { any = <>, player = <>, units = { ["<>"] = <> }, }, lost = { all = <>, player = <>, units = { ["<>"] = <> }, }, } } alerts = { [<>] = { sound_name = <>, sound_filename = "<>", message = "<>", min_pause = <>, -- optional } } ]] function GridAlert:OnInitialize() self.alert_counts = {} self.notification_times = {} self.player_name = UnitName("player") end GridAlert.defaultDB = { display = L["Default Frame"], debug = false, alerts = {}, triggers = {}, min_pause = 0.2, default_sound = "LEVELUP", } local function validate_alert (alert) return GridAlert.db.profile.alerts[alert] ~= nil end GridAlert.options = { type = "group", name = L["GridAlert"], desc = string.format(L["Options for %s."], GridAlert.name), args = { display = { type = "text", name = L["Display"], desc = L["Set where messages are displayed."], get = function() return GridAlert.db.profile.display end, set = function(v) GridAlert.db.profile.display = v end, validate = { L["Default Frame"], L["BigWigs frame"], L["Scrolling Combat Text"], L["Mik's Scrolling Battle Text"] }, }, min_pause = { type = "range", name = L["Minimum pause"], desc = L["Minimum pause between two alerts of any kind, in seconds."], min = 0, max = 2, step = 0.1, get = function () return GridAlert.db.profile.min_pause end, set = function (v) GridAlert.db.profile.min_pause = v end, }, s_triggers = { order = 110, type = "header", }, triggers = { order = 120, type = "group", name = L["Triggers"], desc = L["Options to setup trigger from status"], args = {}, }, s_alerts = { order = 130, type = "header", }, alerts = { order = 140, type = "group", name = L["Alerts"], desc = L["Options for the type of alert triggered"], args = { add_alert = { type = "text", name = L["Add an alert"], desc = L["Create a new alert"], usage = "", get = false, set = function (v) GridAlert:CreateAlert(v) end, validate = function (v) return not validate_alert(v) end, }, remove_alert = { type = "text", name = L["Remove an alert"], desc = L["Remove an alert"], usage = "", get = false, set = function (v) GridAlert:RemoveAlert(v) end, validate = validate_alert, }, }, }, }, } function GridAlert:CreateAlert(name) self.db.profile.alerts[name] = { message = name, min_pause = 1 } self:AddAlertOptions(name) end function GridAlert:AddAlertOptions(name) self.options.args.alerts.args[name] = { type = "group", name = name, desc = string.format(L["Options for alert %s"], name), order = 200, args = { sound_name = { type = "text", name = L["Sound name"], desc = L["Name of a sound to play (must be a valid sound name)."], usage = "", get = function () return self.db.profile.alerts[name].sound_name or "" end, set = function (v) self.db.profile.alerts[name].sound_name = (v ~= "" and v) end, }, sound_filename = { type = "text", name = L["Sound filename"], desc = L["Filename of a sound to play (must be a valid path), overrides Sound name."], usage = "", get = function () return self.db.profile.alerts[name].sound_filename or "" end, set = function (v) self.db.profile.alerts[name].sound_filename = (v ~= "" and v) end, }, message = { type = "text", name = L["Message to display"], desc = L["Message to display, set to off to disable."], usage = "", get = function () return self.db.profile.alerts[name].message or L["off"] end, set = function (v) self.db.profile.alerts[name].message = (v ~= L["off"] and v) end, }, min_pause = { type = "range", name = L["Minimum pause"], desc = L["Minimum pause between two of this kind of alert, in second."], min = 0, max = 2, step = 0.1, get = function () return self.db.profile.alerts[name].min_pause end, set = function (v) self.db.profile.alerts[name].min_pause = v end, }, } } end function GridAlert:RemoveAlert(name) -- check if alert is used and remove options that use it for _, settings in pairs(self.options.args.triggers.args) do if settings.gain.any == name then settings.gain.any = nil end if settings.gain.player == name then settings.gain.player = nil end for k, v in pairs(settings.gain.units) do if v == name then settings.gain.units[k] = nil end end if settings.lost.all == name then settings.lost.all = nil end if settings.lost.player == name then settings.lost.player = nil end for k, v in pairs(settings.lost.units) do if v == name then settings.lost.units[k] = nil end end end self.db.profile.alerts[name] = nil self.options.args.alerts.args[name] = nil end function GridAlert:AddStatusOptions(status, desc) local triggers = self.options.args.triggers.args if triggers[status] then return end if not self.db.profile.triggers[status] then self.db.profile.triggers[status] = { gain = { units = {} }, lost = { units = {} } } end triggers[status] = { type = "group", name = desc, desc = string.format(L["Options for %s."], desc), args = { gain_any = { type = "text", name = L["Any unit gains"], desc = L["Alert to trigger when any unit gains Status"], usage = "", get = function () return self.db.profile.triggers[status].gain.any or "" end, set = function (v) self.db.profile.triggers[status].gain.any = v end, validate = validate_alert, }, gain_player = { type = "text", name = L["Player gains"], desc = L["Alert to trigger when the player gains Status"], usage = "", get = function () return self.db.profile.triggers[status].gain.player or "" end, set = function (v) self.db.profile.triggers[status].gain.player = v end, validate = validate_alert, }, gain_units = { type = "group", name = L["Other players gain"], desc = L["Alert when other players gain Status"], args = {}, }, lost_all = { type = "text", name = L["All units lose"], desc = L["Alert to trigger when all units have lost Status"], usage = "", get = function () return self.db.profile.triggers[status].lost.all or "" end, set = function (v) self.db.profile.triggers[status].lost.all = v end, validate = validate_alert, }, lost_player = { type = "text", name = L["Player loses"], desc = L["Alert to trigger when the player loses Status"], usage = "", get = function () return self.db.profile.triggers[status].lost.player or "" end, set = function (v) self.db.profile.triggers[status].lost.player = v end, validate = validate_alert, }, lost_units = { type = "group", name = L["Other players lose"], desc = L["Alert when other players lose Status"], args = {}, }, }, } end function GridAlert:Grid_StatusRegistered(status, desc) self:AddStatusOptions(status, desc) end function GridAlert:Grid_StatusUnregistered(status) self.options.args.triggers.args[status] = nil end function GridAlert:OnEnable() local alerts = self.options.args.alerts.args for status, _, desc in self.core:RegisteredStatusIterator() do self:AddStatusOptions(status, desc) end for name in pairs(self.db.profile.alerts) do self:AddAlertOptions(name) end self:RegisterEvent("Grid_StatusRegistered") self:RegisterEvent("Grid_StatusUnregistered") self:RegisterEvent("Grid_StatusGained") self:RegisterEvent("Grid_StatusLost") end function GridAlert:Grid_StatusGained(name, status, priority, range, color, text, value, maxValue, texture) local settings = self.db.profile.triggers[status] local count = self.alert_counts[status] or 0 if settings and settings.gain then local alert = (count == 0 and settings.gain.any) if alert then self:TriggerAlert(alert) end self.alert_counts[status] = count + 1 alert = settings.gain.player if not alert or name ~= self.player_name then alert = settings.gain.units and settings.gain.units[name] end if alert then self:TriggerAlert(alert) end end end function GridAlert:Grid_StatusLost(name, status) local settings = self.db.profile.triggers[status] local count = self.alert_counts[status] if settings and settings.lost then local alert = (count == 1 and settings.lost.all) if alert then self:TriggerAlert(alert) end self.alert_counts[status] = count - 1 alert = settings.lost.player if not alert or name ~= self.player_name then alert = settings.lost.units and settings.lost.units[name] end if alert then self:TriggerAlert(alert) end end end function GridAlert:TriggerAlert(alert) local settings = self.db.profile.alerts[alert] if not settings then self:Debug("Invalid alert played : \"%s\", I don't know it\n", alert) end local cur_time = GetTime() if cur_time - (self.last_play_time or 0) < self.db.profile.min_pause or cur_time - (self.notification_times[alert] or 0) < settings.min_pause then self:Debug("Skipping alert \"%s\"", alert) else self.last_play_time = cur_time self.notification_times[alert] = cur_time self:TriggerEvent("GridAlert_Notify", alert) if settings.sound_filename then PlaySoundFile(settings.sound_filename) elseif settings.sound_name then PlaySound(settings.sound_name) end if settings.message then -- check SCT, Mik, ... (code stolen from Banzai) if self.db.profile.display == L["BigWigs frame"] and BigWigs then -- Big Wigs self:TriggerEvent("BigWigs_Message", settings.message, "Red", true, nil) elseif self.db.profile.display == L["Scrolling Combat Text"] and SCT then -- SCT 5.x SCT_MSG_FRAME:AddMessage(text, 1.0, 0.0, 0.0, 1) elseif self.db.profile.display == L["Mik's Scrolling Battle Text"] and MikSBT then -- MSBT MikSBT.DisplayMessage(settings.message, MikSBT.DISPLAYTYPE_NOTIFICATION, false, 255, 0, 0) elseif CombatText_AddMessage then -- Blizzards FCT CombatText_AddMessage(settings.message, COMBAT_TEXT_SCROLL_FUNCTION, 1.0, 0.0, 0.0, "sticky", nil) else -- Fallback UIErrorsFrame:AddMessage(settings.message, 1.0, 0.0, 0.0, 1, UIERRORS_HOLD_TIME) end end end end