Xiiph@0: local L = LibStub("AceLocale-3.0"):GetLocale("ICU") Xiiph@0: if not L then return end Xiiph@0: Xiiph@0: local icu = LibStub("AceAddon-3.0"):NewAddon("ICU", "AceEvent-3.0", "AceTimer-3.0"); Xiiph@0: Xiiph@2: -- UTF8 Xiiph@0: -- Accepted flasks Xiiph@0: local flaskID = { Xiiph@0: 79469, -- Flask of Steelskin Xiiph@0: 79470, -- Flask of the Draconic Mind Xiiph@0: 79471, -- Flask of the Winds Xiiph@0: 79472, -- Flask of Titanic Strength Xiiph@0: 94160, -- Flask of Flowing Water Xiiph@0: }; Xiiph@0: Xiiph@0: -- Accepted well-fed buffs Xiiph@0: local foodID = { Xiiph@0: 87545, -- 90 Strength Xiiph@0: 87546, -- 90 Agility Xiiph@0: 87547, -- 90 Intellect Xiiph@0: 87548, -- 90 Spirit Xiiph@0: 87549, -- 90 Mastery Xiiph@0: 87550, -- 90 Hit Xiiph@0: 87551, -- 90 Crit Xiiph@0: 87552, -- 90 Haste Xiiph@0: }; Xiiph@0: Xiiph@0: Xiiph@0: local minFlaskDuration = 10; Xiiph@0: local noFlask, noFood, hasLowDuration = {},{},{}; Xiiph@0: Xiiph@0: local defaults = { Xiiph@0: profile = { Xiiph@0: checkFlask = true, Xiiph@0: checkFood = true, Xiiph@0: checkLowFlaskDuration = true, Xiiph@0: remindRaider = true, Xiiph@0: reportResults = true, Xiiph@0: reportDestination = "OFFICER", Xiiph@0: manualCheckOnly = false, Xiiph@0: checkAfterFinish = true, Xiiph@0: advertiseICU = true, Xiiph@0: noFoodMessage = L["Well Fed reminder!"], Xiiph@0: noFlaskMessage = L["Flask reminder!"], Xiiph@0: lowFlaskDurationMessage = L["Your Flask runs out in less than 10 minutes!"], Xiiph@1: disabledZones = {}, Xiiph@0: } Xiiph@0: } Xiiph@0: Xiiph@0: function icu:OnInitialize() Xiiph@0: self.db = LibStub("AceDB-3.0"):New("icuDB", defaults, true) Xiiph@0: Xiiph@0: self.db.RegisterCallback(self, "OnProfileChanged", "refreshConfig") Xiiph@0: self.db.RegisterCallback(self, "OnProfileCopied", "refreshConfig") Xiiph@0: self.db.RegisterCallback(self, "OnProfileReset", "refreshConfig") Xiiph@0: Xiiph@0: self.options = self:getOptions() Xiiph@0: Xiiph@0: local AceConfig = LibStub("AceConfig-3.0") Xiiph@0: local AceConfigDialog = LibStub("AceConfigDialog-3.0") Xiiph@0: Xiiph@0: AceConfig:RegisterOptionsTable("ICU", self.options, {"icu"}) Xiiph@0: Xiiph@0: AceConfigDialog:AddToBlizOptions("ICU", nil, nil, "general") Xiiph@0: AceConfigDialog:AddToBlizOptions("ICU", "Profiles","ICU","profile") Xiiph@1: AceConfigDialog:AddToBlizOptions("ICU", "Whispers","ICU","messages") Xiiph@1: AceConfigDialog:AddToBlizOptions("ICU", "Disabled Zones","ICU","zones") Xiiph@0: end Xiiph@0: Xiiph@0: function icu:refreshConfig() Xiiph@0: --print("ICU: Config refreshing ..."); Xiiph@0: Xiiph@0: if self.db.profile.manualCheckOnly then Xiiph@0: icu:UnregisterEvent("READY_CHECK"); Xiiph@0: else Xiiph@0: icu:RegisterEvent("READY_CHECK"); Xiiph@0: end Xiiph@0: Xiiph@0: --print("ICU: Config refreshed!"); Xiiph@0: end Xiiph@0: Xiiph@0: function icu:config() Xiiph@0: InterfaceOptionsFrame_OpenToCategory("ICU") Xiiph@0: end Xiiph@0: Xiiph@0: function icu:getOptions() Xiiph@0: local options = { Xiiph@0: handler = icu, Xiiph@0: type = 'group', Xiiph@0: args = { Xiiph@0: config = { Xiiph@0: name = L["Options"], Xiiph@0: desc = L["Shows the blizzard addon configuration window"], Xiiph@0: type = 'execute', Xiiph@0: func = "config", Xiiph@0: hidden = true, Xiiph@0: cmdHidden = false, Xiiph@0: }, Xiiph@0: check = { Xiiph@0: name = L["Raid Check"], Xiiph@0: desc = L["Checks the raid for flask/food buffs"], Xiiph@0: type = 'execute', Xiiph@0: func = function() self:inspectRaid(false) end, Xiiph@0: hidden = true, Xiiph@0: cmdHidden = false, Xiiph@0: }, Xiiph@0: quiet = { Xiiph@0: name = L["Raid Check (Silent)"], Xiiph@0: desc = L["Checks the raid for flask/food buffs, but does not remind raiders, regardless of other settings."], Xiiph@0: type = 'execute', Xiiph@0: func = function() self:inspectRaid(true) end, Xiiph@0: hidden = true, Xiiph@0: cmdHidden = false, Xiiph@0: }, Xiiph@0: general = { Xiiph@0: name = L["General Settings"], Xiiph@0: type = 'group', Xiiph@0: args = { Xiiph@0: checkFlask = { Xiiph@0: type = 'toggle', Xiiph@0: name = L["Check for Flask"], Xiiph@0: desc = L["Checks the raid for valid flasks and reports results"], Xiiph@0: set = function(o,v,...) self.db.profile.checkFlask = v end, Xiiph@0: get = function() return self.db.profile.checkFlask end, Xiiph@0: }, Xiiph@0: checkLowFlaskDuration = { Xiiph@0: type = 'toggle', Xiiph@0: name = L["Flask expiration"], Xiiph@0: desc = L["Check for soon to expire flask buffs"], Xiiph@0: set = function(o,v,...) self.db.profile.checkLowFlaskDuration = v end, Xiiph@0: get = function() return self.db.profile.checkLowFlaskDuration end, Xiiph@0: }, Xiiph@0: checkFood = { Xiiph@0: type = 'toggle', Xiiph@0: name = L["Check for Food"], Xiiph@0: desc = L["Checks the raid for valid food buffs and reports results"], Xiiph@0: set = function(o,v,...) self.db.profile.checkFood = v end, Xiiph@0: get = function() return self.db.profile.checkFood end, Xiiph@0: }, Xiiph@0: advertiseICU = { Xiiph@0: type = 'toggle', Xiiph@0: name = L["Advertise ICU"], Xiiph@0: desc = L["Let everyone know you are using ICU! Prefixes whispers and reports"], Xiiph@0: set = function(o,v,...) self.db.profile.advertiseICU = v end, Xiiph@0: get = function() return self.db.profile.advertiseICU end, Xiiph@0: }, Xiiph@0: remindRaider = { Xiiph@0: type = 'toggle', Xiiph@0: name = L["Raid reminder"], Xiiph@0: desc = L["Whisper the raider lacking (or soon to expire, if enabled) food/flask buff a reminder"], Xiiph@0: set = function(o,v,...) self.db.profile.remindRaider = v end, Xiiph@0: get = function() return self.db.profile.remindRaider end, Xiiph@0: }, Xiiph@0: reportResults = { Xiiph@0: type = 'toggle', Xiiph@0: name = L["Report results"], Xiiph@0: desc = L["Report the results after finishing"], Xiiph@0: set = function(o,v,...) self.db.profile.reportResults = v end, Xiiph@0: get = function() return self.db.profile.reportResults end, Xiiph@0: }, Xiiph@0: reportDestination = { Xiiph@0: type = 'select', Xiiph@0: style = "dropdown", Xiiph@0: name = L["Report Destination"], Xiiph@0: desc = L["Report the results to the following channel"], Xiiph@0: values = { Xiiph@0: ["OFFICER"] = L["Officer"], Xiiph@0: ["SAY"] = L["Say"], Xiiph@0: ["RAID"] = L["Raid"], Xiiph@0: ["GUILD"] = L["Guild"], Xiiph@0: ["SELF"] = L["Self"], Xiiph@0: }, Xiiph@0: set = function(o,v,...) self.db.profile.reportDestination = v end, Xiiph@0: get = function() return self.db.profile.reportDestination end, Xiiph@0: }, Xiiph@0: manualCheckOnly = { Xiiph@0: type = 'toggle', Xiiph@0: name = L["Manual checks only"], Xiiph@0: desc = L["Only perform buff checks if initiated manually (via /icu check)"], Xiiph@0: set = function(o,v,...) self.db.profile.manualCheckOnly = v; self:refreshConfig() end, Xiiph@0: get = function() return self.db.profile.manualCheckOnly end, Xiiph@0: }, Xiiph@0: checkAfterFinish = { Xiiph@0: type = 'toggle', Xiiph@0: name = L["Check after readycheck"], Xiiph@0: desc = L["Don't check buffs until ready check has finished (or timed out)"], Xiiph@0: set = function(o,v,...) self.db.profile.checkAfterFinish = v end, Xiiph@0: get = function() return self.db.profile.checkAfterFinish end, Xiiph@0: }, Xiiph@1: }, Xiiph@1: }, Xiiph@1: messages = { Xiiph@1: name = L["Messages"], Xiiph@1: type = 'group', Xiiph@1: args = { Xiiph@1: noFlaskMessage = { Xiiph@1: type = 'input', Xiiph@1: width = 'double', Xiiph@1: name = L["Flask reminder"], Xiiph@1: desc = L["Message whispered to raiders missing a cataclysm flask"], Xiiph@1: set = function(o,v,...) self.db.profile.noFlaskMessage = v end, Xiiph@1: get = function() return self.db.profile.noFlaskMessage end, Xiiph@1: }, Xiiph@1: lowFlaskDurationMessage = { Xiiph@1: type = 'input', Xiiph@1: width = 'double', Xiiph@1: name = L["Flask expiration"], Xiiph@1: desc = L["Message whispered to raiders with less than 10 minutes left on their flask"], Xiiph@1: set = function(o,v,...) self.db.profile.lowFlaskDurationMessage = v end, Xiiph@1: get = function() return self.db.profile.lowFlaskDurationMessage end, Xiiph@1: }, Xiiph@1: noFoodMessage = { Xiiph@1: type = 'input', Xiiph@1: width = 'double', Xiiph@1: name = L["Food reminder"], Xiiph@1: desc = L["Message whispered to raiders missing the well-fed buff"], Xiiph@1: set = function(o,v,...) self.db.profile.noFoodMessage = v end, Xiiph@1: get = function() return self.db.profile.noFoodMessage end, Xiiph@1: }, Xiiph@1: }, Xiiph@1: }, Xiiph@1: zones = { Xiiph@1: name = L["Disabled Zones"], Xiiph@1: type = 'group', Xiiph@1: set = function(i,v) self.db.profile.disabledZones[i[#i]] = v end, Xiiph@1: get = function(i) return self.db.profile.disabledZones[i[#i]] end, Xiiph@1: args = { Xiiph@1: help = { Xiiph@1: type = 'description', Xiiph@1: name = L['Toggle ICU automatic checking |cffcc0000off|r in the selected zones.'], Xiiph@1: width = 'full', Xiiph@1: order = 0, Xiiph@0: }, Xiiph@1: bwd = { Xiiph@1: type = 'toggle', Xiiph@1: name = L["Blackwing Descent"], Xiiph@1: width = 'double', Xiiph@0: }, Xiiph@1: bot = { Xiiph@1: type = 'toggle', Xiiph@1: name = L["Bastion of Twilight"], Xiiph@1: width = 'double', Xiiph@0: }, Xiiph@1: tfw = { Xiiph@1: type = 'toggle', Xiiph@1: name = L["Throne of the Four Winds"], Xiiph@1: width = 'double', Xiiph@1: }, Xiiph@1: bh = { Xiiph@1: type = 'toggle', Xiiph@1: name = L["Baradin Hold"], Xiiph@1: width = 'double', Xiiph@1: }, Xiiph@0: } Xiiph@0: }, Xiiph@0: profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db), Xiiph@0: }, Xiiph@0: } Xiiph@0: return options Xiiph@0: end Xiiph@0: Xiiph@1: function icu:inspectRaid(silent,automatic) Xiiph@1: -- Check if any zones have been disabled Xiiph@1: if #self.db.profile.disabledZones > 0 and automatic then Xiiph@1: local currentZone = GetRealZoneText(); Xiiph@1: Xiiph@1: for i = 1, #self.db.profile.disabledZones do Xiiph@1: if currentZone == self.db.profile.disabledZones[i] then return true end Xiiph@1: end Xiiph@1: end Xiiph@1: Xiiph@0: -- Not in a raid group Xiiph@0: local icuAd = ""; Xiiph@0: Xiiph@0: if GetNumRaidMembers() == 0 then Xiiph@0: return true Xiiph@0: end Xiiph@0: Xiiph@0: if self.db.profile.advertiseICU then Xiiph@0: icuAd = L["ICU"] .. ": "; Xiiph@0: else Xiiph@0: icuAd = ""; Xiiph@0: end Xiiph@0: Xiiph@0: for i = 1, GetNumRaidMembers() do Xiiph@0: local raider = GetRaidRosterInfo(i); Xiiph@0: if raider then Xiiph@0: Xiiph@0: local hasFood, hasFlask, hasLowDuration = icu:validateBuffs(i); Xiiph@0: Xiiph@0: if not hasFood and self.db.profile.checkFood then Xiiph@0: noFood[#noFood+1] = raider; Xiiph@0: -- Tell player Xiiph@0: if self.db.profile.remindRaider and not silent then Xiiph@0: SendChatMessage(icuAd .. self.db.profile.noFoodMessage,"WHISPER",nil,raider); Xiiph@0: end Xiiph@0: end Xiiph@0: Xiiph@0: if not hasFlask and self.db.profile.checkFlask then Xiiph@0: noFlask[#noFlask+1] = raider; Xiiph@0: -- Tell player Xiiph@0: if self.db.profile.remindRaider and not silent then Xiiph@0: SendChatMessage(icuAd .. self.db.profile.noFlaskMessage,"WHISPER",nil,raider); Xiiph@0: end Xiiph@0: elseif hasLowDuration and not silent then Xiiph@0: if self.db.profile.remindRaider and self.db.profile.checkLowFlaskDuration then Xiiph@0: SendChatMessage(icuAd .. self.db.profile.lowFlaskDurationMessage,"WHISPER",nil,raider); Xiiph@0: end Xiiph@0: end Xiiph@0: end Xiiph@0: Xiiph@0: end Xiiph@0: Xiiph@0: if self.db.profile.reportResults and (#noFlask > 0 or #noFood > 0) and self.db.profile.advertiseICU and self.db.profile.reportDestination ~= "SELF" then Xiiph@0: SendChatMessage("---- "..L["ICU"].." "..L["Report"].." ----",self.db.profile.reportDestination,nil,nil); Xiiph@0: end Xiiph@0: Xiiph@0: if self.db.profile.reportResults then Xiiph@0: if #noFlask > 0 and self.db.profile.checkFlask then Xiiph@0: local reportFlaskMessage = L["Missing Flask"]..": " .. table.concat(noFlask, ", "); Xiiph@0: Xiiph@0: if self.db.profile.reportDestination == "SELF" then Xiiph@0: DEFAULT_CHAT_FRAME:AddMessage(reportFlaskMessage); Xiiph@0: else Xiiph@0: SendChatMessage(reportFlaskMessage,self.db.profile.reportDestination,nil,nil); Xiiph@0: end Xiiph@0: end Xiiph@0: Xiiph@0: if #noFood > 0 and self.db.profile.checkFood then Xiiph@0: local reportFoodMessage = L["Missing Food"]..": " .. table.concat(noFood, ", "); Xiiph@0: Xiiph@0: if self.db.profile.reportDestination == "SELF" then Xiiph@0: DEFAULT_CHAT_FRAME:AddMessage(reportFoodMessage); Xiiph@0: else Xiiph@0: SendChatMessage(reportFoodMessage,self.db.profile.reportDestination,nil,nil); Xiiph@0: end Xiiph@0: end Xiiph@0: end Xiiph@0: Xiiph@0: noFlask, noFood, hasLowDuration = {},{},{}; Xiiph@0: end Xiiph@0: Xiiph@0: function icu:validateBuffs(playerIndex) Xiiph@0: local i = 1; Xiiph@0: local hasFood, hasFlask, hasLowDuration = false, false, false; Xiiph@0: local name, _, _, _, _, _, expirationTime, _, _, _, spellId = UnitBuff("raid"..playerIndex,i); Xiiph@0: Xiiph@0: while name do Xiiph@0: -- Check for food Xiiph@0: if not hasFood then Xiiph@0: for k,v in ipairs(foodID) do Xiiph@0: if v == spellId then Xiiph@0: hasFood = true; Xiiph@0: end Xiiph@0: end Xiiph@0: end Xiiph@0: -- Check for flask Xiiph@0: if not hasFlask then Xiiph@0: for k,v in ipairs(flaskID) do Xiiph@0: if v == spellId then Xiiph@0: hasFlask = true; Xiiph@0: -- Check if low duration Xiiph@0: if expirationTime and ((expirationTime-GetTime())/60) <= minFlaskDuration then Xiiph@0: hasLowDuration = true; Xiiph@0: end Xiiph@0: end Xiiph@0: end Xiiph@0: end Xiiph@0: i = i + 1; Xiiph@0: name, _, _, _, _, _, expirationTime, _, _, _, spellId = UnitBuff("raid"..playerIndex,i); Xiiph@0: end Xiiph@0: Xiiph@0: return hasFood, hasFlask, hasLowDuration; Xiiph@0: end Xiiph@0: Xiiph@0: function icu:READY_CHECK() Xiiph@0: --print("Ready check init!"); Xiiph@0: if self.db.profile.manualCheckOnly then Xiiph@0: icu:UnregisterEvent("READY_CHECK"); Xiiph@0: return true; Xiiph@0: end Xiiph@0: Xiiph@0: if not self.db.profile.checkAfterFinish then Xiiph@1: self:inspectRaid(nil,true); Xiiph@0: else Xiiph@0: self:ScheduleTimer("READY_CHECK_FINISHED", 30); Xiiph@0: self:RegisterEvent("READY_CHECK_FINISHED"); Xiiph@0: end Xiiph@0: end Xiiph@0: Xiiph@0: function icu:READY_CHECK_FINISHED() Xiiph@0: --print("Ready check finish!"); Xiiph@0: self:UnregisterEvent("READY_CHECK_FINISHED"); Xiiph@0: self:CancelAllTimers(); Xiiph@1: self:inspectRaid(nil,true); Xiiph@0: end Xiiph@0: Xiiph@1: function icu:getDB() Xiiph@1: return self.db; Xiiph@0: end Xiiph@1: Xiiph@1: function filterChat(self, event, msg) Xiiph@1: local db = icu:getDB(); Xiiph@1: if msg == db.profile.noFoodMessage or msg == db.profile.noFlaskMessage or msg == db.profile.lowFlaskDurationMessage or msg == L["ICU"]..": "..db.profile.noFoodMessage or msg == L["ICU"]..": "..db.profile.noFlaskMessage or msg == L["ICU"]..": "..db.profile.lowFlaskDurationMessage then return true end Xiiph@1: end Xiiph@1: ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_ICU_INFORM", filterChat) Xiiph@0: Xiiph@0: icu:RegisterEvent("READY_CHECK"); Xiiph@0: Xiiph@0: --@do-not-package@ Xiiph@0: function icu:test(cond) Xiiph@0: if true and not cond then Xiiph@0: print("First.") Xiiph@0: else Xiiph@0: print("Second.") Xiiph@0: end Xiiph@0: end Xiiph@0: Xiiph@0: function icu:grabVar(var) Xiiph@0: print(self.db.profile[var]) Xiiph@0: end Xiiph@0: Xiiph@0: _G.icu = icu; Xiiph@0: --@end-do-not-package@