Mercurial > wow > icu
view ICU.lua @ 8:deb31e7b9ae4
Tagging as beta
author | Xiiph |
---|---|
date | Fri, 18 Feb 2011 23:58:47 +0100 |
parents | f020d96ccfc8 |
children | 0ed4c1a0412e |
line wrap: on
line source
local L = LibStub("AceLocale-3.0"):GetLocale("ICU") if not L then return end local icu = LibStub("AceAddon-3.0"):NewAddon("ICU", "AceEvent-3.0", "AceTimer-3.0"); -- Move global namespace to local local _G = _G; -- UTF8 local raidMap = { bwd = L["Blackwing Descent"], bot = L["The Bastion of Twilight"], tfw = L["Throne of the Four Winds"], bh = L["Baradin Hold"], } -- Accepted flasks local flaskID = { 79469, -- Flask of Steelskin 79470, -- Flask of the Draconic Mind 79471, -- Flask of the Winds 79472, -- Flask of Titanic Strength 94160, -- Flask of Flowing Water }; -- Accepted well-fed buffs local foodID = { 87545, -- 90 Strength 87546, -- 90 Agility 87547, -- 90 Intellect 87548, -- 90 Spirit 87549, -- 90 Mastery 87550, -- 90 Hit 87551, -- 90 Crit 87552, -- 90 Haste }; local minFlaskDuration = 10; local noFlask, noFood, hasLowDuration = {},{},{}; local notReady, notReadyAFK, responders = {}, {}, {}; local defaults = { profile = { checkFlask = true, checkFood = true, checkLowFlaskDuration = true, remindRaider = true, reportResults = true, reportDestination = "OFFICER", manualCheckOnly = false, checkAfterFinish = true, advertiseICU = true, noFoodMessage = L["Well Fed reminder!"], noFlaskMessage = L["Flask reminder!"], lowFlaskDurationMessage = L["Your Flask runs out in less than 10 minutes!"], disabledZones = {}, enableAllZones = true, announceReadyCheck = true, } } function icu:OnInitialize() self.db = LibStub("AceDB-3.0"):New("icuDB", defaults, true) self.db.RegisterCallback(self, "OnProfileChanged", "refreshConfig") self.db.RegisterCallback(self, "OnProfileCopied", "refreshConfig") self.db.RegisterCallback(self, "OnProfileReset", "refreshConfig") self.options = self:getOptions() local AceConfig = LibStub("AceConfig-3.0") local AceConfigDialog = LibStub("AceConfigDialog-3.0") AceConfig:RegisterOptionsTable("ICU", self.options, {"icu"}) AceConfigDialog:AddToBlizOptions("ICU", nil, nil, "general") AceConfigDialog:AddToBlizOptions("ICU", "Whispers","ICU","messages") AceConfigDialog:AddToBlizOptions("ICU", "Disabled Zones","ICU","zones") AceConfigDialog:AddToBlizOptions("ICU", "Profiles","ICU","profile") -- Ready check confirm event registration if self.db.profile.announceReadyCheck then self:RegisterEvent("READY_CHECK_CONFIRM"); end -- Ready check event registration if not self.db.profile.manualCheckOnly then icu:RegisterEvent("READY_CHECK"); end end function icu:refreshConfig() --print("ICU: Config refreshing ..."); if self.db.profile.manualCheckOnly then icu:UnregisterEvent("READY_CHECK"); else icu:RegisterEvent("READY_CHECK"); end if not self.db.profile.announceReadyCheck then icu:UnregisterEvent("READY_CHECK_CONFIRM"); else icu:RegisterEvent("READY_CHECK_CONFIRM"); end --print("ICU: Config refreshed!"); end function icu:config() InterfaceOptionsFrame_OpenToCategory("ICU") end function icu:getOptions() local options = { handler = icu, type = 'group', args = { config = { name = L["Options"], desc = L["Shows the blizzard addon configuration window"], type = 'execute', func = "config", hidden = true, cmdHidden = false, }, check = { name = L["Raid Check"], desc = L["Checks the raid for flask/food buffs"], type = 'execute', func = function() self:inspectRaid(false) end, hidden = true, cmdHidden = false, }, quiet = { name = L["Raid Check (Silent)"], desc = L["Checks the raid for flask/food buffs, but does not remind raiders, regardless of other settings."], type = 'execute', func = function() self:inspectRaid(true) end, hidden = true, cmdHidden = false, }, general = { name = L["General Settings"], type = 'group', args = { advertiseICU = { type = 'toggle', order = 1, width = 'full', name = L["Advertise ICU"], desc = L["Let everyone know you are using ICU! Prefixes whispers and reports"], set = function(o,v,...) self.db.profile.advertiseICU = v end, get = function() return self.db.profile.advertiseICU end, }, checkFlask = { type = 'toggle', order = 2, name = L["Check for Flask"], desc = L["Checks the raid for valid flasks and reports results"], set = function(o,v,...) self.db.profile.checkFlask = v end, get = function() return self.db.profile.checkFlask end, }, checkLowFlaskDuration = { type = 'toggle', order = 3, name = L["Flask expiration"], desc = L["Check for soon to expire flask buffs"], set = function(o,v,...) self.db.profile.checkLowFlaskDuration = v end, get = function() return self.db.profile.checkLowFlaskDuration end, }, checkFood = { type = 'toggle', order = 4, name = L["Check for Food"], desc = L["Checks the raid for valid food buffs and reports results"], set = function(o,v,...) self.db.profile.checkFood = v end, get = function() return self.db.profile.checkFood end, }, remindRaider = { type = 'toggle', order = 5, width = 'full', name = L["Raid reminder"], desc = L["Whisper the raider lacking (or soon to expire, if enabled) food/flask buff a reminder"], set = function(o,v,...) self.db.profile.remindRaider = v end, get = function() return self.db.profile.remindRaider end, }, breakOne = { type = 'description', fontSize = 'large', name = ' ', order = 7, width = 'full', }, manualCheckOnly = { type = 'toggle', order = 8, name = L["Manual checks only"], desc = L["Only perform buff checks if initiated manually (via /icu check)"], set = function(o,v,...) self.db.profile.manualCheckOnly = v; self:refreshConfig() end, get = function() return self.db.profile.manualCheckOnly end, }, checkAfterFinish = { type = 'toggle', order = 9, width = 'full', name = L["Inspect AFTER ready check finishes"], desc = L["Don't check buffs until the ready check has finished (or timed out)"], set = function(o,v,...) self.db.profile.checkAfterFinish = v end, get = function() return self.db.profile.checkAfterFinish end, }, breakTwo = { type = 'description', fontSize = 'large', name = ' ', order = 10, width = 'full', }, announceReadyCheck = { type = 'toggle', order = 11, name = L["Report ready checks"], desc = L["Report the results of ready checks"], width = 'double', set = function(o,v,...) self.db.profile.announceReadyCheck = v; self:refreshConfig() end, get = function() return self.db.profile.announceReadyCheck end, }, reportResults = { type = 'toggle', order = 12, width = 'full', name = L["Report buff checks"], desc = L["Report flask/food check results"], set = function(o,v,...) self.db.profile.reportResults = v end, get = function() return self.db.profile.reportResults end, }, reportDestination = { type = 'select', order = 13, style = "dropdown", name = L["Report Destination"], desc = L["Report the results to the following channel"], values = { ["OFFICER"] = L["Officer"], ["SAY"] = L["Say"], ["RAID"] = L["Raid"], ["GUILD"] = L["Guild"], ["SELF"] = L["Self"], }, set = function(o,v,...) self.db.profile.reportDestination = v end, get = function() return self.db.profile.reportDestination end, }, }, }, messages = { name = L["Messages"], type = 'group', args = { noFlaskMessage = { type = 'input', width = 'double', name = L["Flask reminder"], desc = L["Message whispered to raiders missing a cataclysm flask"], set = function(o,v,...) self.db.profile.noFlaskMessage = v end, get = function() return self.db.profile.noFlaskMessage end, }, lowFlaskDurationMessage = { type = 'input', width = 'double', name = L["Flask expiration"], desc = L["Message whispered to raiders with less than 10 minutes left on their flask"], set = function(o,v,...) self.db.profile.lowFlaskDurationMessage = v end, get = function() return self.db.profile.lowFlaskDurationMessage end, }, noFoodMessage = { type = 'input', width = 'double', name = L["Food reminder"], desc = L["Message whispered to raiders missing the well-fed buff"], set = function(o,v,...) self.db.profile.noFoodMessage = v end, get = function() return self.db.profile.noFoodMessage end, }, }, }, zones = { name = L["Disabled Zones"], type = 'group', set = function(i,v) self.db.profile.disabledZones[i[#i]] = v; end, get = function(i) return self.db.profile.disabledZones[i[#i]]; end, args = { help = { type = 'description', name = L['Toggle ICU automatic checking |cffcc0000off|r in the selected zones.'], width = 'full', order = 0, }, breakOne = { type = 'description', fontSize = 'large', name = ' ', order = 1, width = 'full', }, enableAllZones = { type = 'toggle', name = L["Enable ICU in all zones"], order = 2, width = 'full', set = function (i,v) self.db.profile.enableAllZones = v; self.options.args.zones.args.bwd.disabled = v; self.options.args.zones.args.bot.disabled = v; self.options.args.zones.args.tfw.disabled = v; self.options.args.zones.args.bh.disabled = v; end, get = function (i) return self.db.profile.enableAllZones end, }, breakTwo = { type = 'description', fontSize = 'large', name = ' ', order = 3, width = 'full', }, bwd = { type = 'toggle', name = L["Blackwing Descent"], width = 'double', disabled = self.db.profile.enableAllZones, }, bot = { type = 'toggle', name = L["The Bastion of Twilight"], width = 'double', disabled = self.db.profile.enableAllZones, }, tfw = { type = 'toggle', name = L["Throne of the Four Winds"], width = 'double', disabled = self.db.profile.enableAllZones, }, bh = { type = 'toggle', name = L["Baradin Hold"], width = 'double', disabled = self.db.profile.enableAllZones, }, } }, profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db), }, } return options end function icu:inspectRaid(silent,automatic) -- Check if any zones have been disabled if automatic and not self.db.profile.enableAllZones then local currentZone = GetRealZoneText(); for k,v in pairs(self.db.profile.disabledZones) do if currentZone == raidMap[k] and v then return true end end end local icuAd = ""; -- Not in a raid group if GetNumRaidMembers() == 0 then return true end if self.db.profile.advertiseICU then icuAd = L["ICU"] .. ": "; else icuAd = ""; end for i = 1, GetNumRaidMembers() do local raider = GetRaidRosterInfo(i); if raider then local hasFood, hasFlask, hasLowDuration = icu:validateBuffs(i); if not hasFood and self.db.profile.checkFood then noFood[#noFood+1] = raider; -- Tell player if self.db.profile.remindRaider and not silent then SendChatMessage(icuAd .. self.db.profile.noFoodMessage,"WHISPER",nil,raider); end end if not hasFlask and self.db.profile.checkFlask then noFlask[#noFlask+1] = raider; -- Tell player if self.db.profile.remindRaider and not silent then SendChatMessage(icuAd .. self.db.profile.noFlaskMessage,"WHISPER",nil,raider); end elseif hasLowDuration and not silent then if self.db.profile.remindRaider and self.db.profile.checkLowFlaskDuration then SendChatMessage(icuAd .. self.db.profile.lowFlaskDurationMessage,"WHISPER",nil,raider); end end end end -- Announce the report if inspectRaid was by a slash command instead of ready check event if not automatic then self:announceReport(false); end end function icu:announceReport(automatic) SendChatMessage("---- "..L["ICU"].." "..L["Report"].." ----",self.db.profile.reportDestination,nil,nil); -- Check flask if #noFlask > 0 and self.db.profile.checkFlask then local reportFlaskMessage = L["Missing Flask"]..": " .. table.concat(noFlask, ", "); if self.db.profile.reportDestination == "SELF" then DEFAULT_CHAT_FRAME:AddMessage(reportFlaskMessage); else SendChatMessage(reportFlaskMessage,self.db.profile.reportDestination,nil,nil); end elseif self.db.profile.checkFlask then -- Nobody is missing a flask if self.db.profile.reportDestination == "SELF" then DEFAULT_CHAT_FRAME:AddMessage(L["Nobody is missing a proper flask."]); else SendChatMessage(L["Nobody is missing a proper flask."],self.db.profile.reportDestination,nil,nil); end end -- Check food if #noFood > 0 and self.db.profile.checkFood then local reportFoodMessage = L["Missing Food"]..": " .. table.concat(noFood, ", "); if self.db.profile.reportDestination == "SELF" then DEFAULT_CHAT_FRAME:AddMessage(reportFoodMessage); else SendChatMessage(reportFoodMessage,self.db.profile.reportDestination,nil,nil); end elseif self.db.profile.checkFood then -- Nobody is missing a food buff if self.db.profile.reportDestination == "SELF" then DEFAULT_CHAT_FRAME:AddMessage(L["Nobody is missing a proper food buff."]); else SendChatMessage(L["Nobody is missing a proper food buff."],self.db.profile.reportDestination,nil,nil); end end -- Check ready if automatic and self.db.profile.announceReadyCheck then -- Check was initialized by ready check event if (#notReady > 0) or (#notReadyAFK > 0) then local reportNotReady = L["Not Ready"]..": " .. table.concat(notReady, ", ") .. (#notReadyAFK > 0 and #notReady > 0 and ", " or "") .. table.concat(notReadyAFK, ", "); if self.db.profile.reportDestination == "SELF" then DEFAULT_CHAT_FRAME:AddMessage(reportNotReady); else SendChatMessage(reportNotReady,self.db.profile.reportDestination,nil,nil); end else -- Everyone is ready if self.db.profile.reportDestination == "SELF" then DEFAULT_CHAT_FRAME:AddMessage(L["Everyone is ready."]); else SendChatMessage(L["Everyone is ready."],self.db.profile.reportDestination,nil,nil); end end end self:wipeTables(); end function icu:validateBuffs(playerIndex) local i = 1; local hasFood, hasFlask, hasLowDuration = false, false, false; local name, _, _, _, _, _, expirationTime, _, _, _, spellId = UnitBuff("raid"..playerIndex,i); while name do -- Check for food if not hasFood then for k,v in ipairs(foodID) do if v == spellId then hasFood = true; end end end -- Check for flask if not hasFlask then for k,v in ipairs(flaskID) do if v == spellId then hasFlask = true; -- Check if low duration if expirationTime and ((expirationTime-GetTime())/60) <= minFlaskDuration then hasLowDuration = true; end end end end i = i + 1; name, _, _, _, _, _, expirationTime, _, _, _, spellId = UnitBuff("raid"..playerIndex,i); end return hasFood, hasFlask, hasLowDuration; end function icu:READY_CHECK(event,requester) --print("Ready check init!"); if self.db.profile.manualCheckOnly then icu:UnregisterEvent("READY_CHECK"); return true; end responders[#responders+1] = requester; if not self.db.profile.checkAfterFinish and GetNumRaidMembers() then self:inspectRaid(nil,true); else self:ScheduleTimer("READY_CHECK_FINISHED", 30); self:RegisterEvent("READY_CHECK_FINISHED"); end end function icu:wipeTables() -- Wipe tables wipe(noFlask); wipe(noFood); wipe(hasLowDuration); wipe(notReady); wipe(notReadyAFK); wipe(responders); end function icu:READY_CHECK_FINISHED() --print("Ready check finish!"); self:UnregisterEvent("READY_CHECK_FINISHED"); self:CancelAllTimers(); -- Not in a raid group if GetNumRaidMembers() then self:inspectRaid(nil,true); if self.db.profile.announceReadyCheck then self:confirmReady(); end self:announceReport(true); end end function icu:READY_CHECK_CONFIRM(event,unit,status) local raider = UnitName(unit); -- Seeing we only check in raids, and this event fires twice for unites in your subgroup -- Such as Raid1, and Party1 == Same unit -- Dont parse the party event if string.match(unit,"party") then return true; end -- Raider is NOT afk, but might not be ready responders[#responders+1] = raider; -- 1 ready, 0 not ready if not status then notReady[#notReady+1] = raider; end end function icu:confirmReady() local numRaiders, matchFound = GetNumRaidMembers(), false; --@debug@ print(#responders); --@end-debug@ if #responders < numRaiders then for i = 1, numRaiders do matchFound = false; -- Get raider name local raider = GetRaidRosterInfo(i); --@debug@ print(raider); --@end-debug@ for i = 1, #responders do print("Iterating through responders ..."); print(responders[i],raider); if responders[i] == raider then --@debug@ print(responders[i],raider); --@end-debug@ matchFound = true; break; end end if not matchFound and raider then --@debug@ print("Tag following raider as AFK: ",raider,matchFound); --@end-debug@ notReadyAFK[#notReadyAFK+1] = raider .. " (AFK)"; elseif not raider then -- GetRaidRosterInfo did not return a proper name, out of bounds?? print("Something is wrong ..."); else --@debug@ print(i,raider); --@end-debug@ end end end end function icu:getDB() return self.db; end local function filterChat(self, event, msg) local db = icu:getDB(); 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 end ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_ICU_INFORM", filterChat) --@do-not-package@ function icu:test(cond) if true and not cond then print("First.") else print("Second.") end end function icu:grabVar(var) print(self.db.profile[var]) end _G.icu = icu; --@end-do-not-package@