view ICU.lua @ 5:45a45aa0f492

Corrected name of Bastion of Twilight ... (returned by GetRealZoneText()) Added confirmation when nobody is missing buffs.
author Xiiph
date Mon, 14 Feb 2011 22:21:15 +0100
parents 8ec216b40ded
children 60ac81ad00a2
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
-- 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 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,
	}
}

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")
end

function icu:refreshConfig()
	--print("ICU: Config refreshing ...");
	
	if self.db.profile.manualCheckOnly then
		icu:UnregisterEvent("READY_CHECK");
	else
		icu:RegisterEvent("READY_CHECK");
	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 = {
					checkFlask = {
						type = 'toggle',
						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',
						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',
						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,
					},
					advertiseICU = {
						type = 'toggle',
						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,
					},
					remindRaider = {
						type = 'toggle',
						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,
					},
					reportResults = {
						type = 'toggle',
						name = L["Report results"],
						desc = L["Report the results after finishing"],
						set = function(o,v,...) self.db.profile.reportResults = v end,
						get = function() return self.db.profile.reportResults end,
					},
					reportDestination = {
						type = 'select',
						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,
					},
					manualCheckOnly = {
						type = 'toggle',
						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',
						name = L["Check after readycheck"],
						desc = L["Don't check buffs until 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,
					},
				},
			},
			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',
						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',
						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 i = 1, #self.db.profile.disabledZones do
			if currentZone == self.db.profile.disabledZones[i] and self.db.profile.disabledZones[i] then 
				--@debug@
				print(currentZone,self.db.profile.disabledZones[i],"Cancelling ICU inspection");
				--@end-debug@
				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
	
	if self.db.profile.reportResults and self.db.profile.reportDestination ~= "SELF" then
		SendChatMessage("---- "..L["ICU"].." "..L["Report"].." ----",self.db.profile.reportDestination,nil,nil);
	end
	
	if self.db.profile.reportResults then
		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
		
		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
		
	end
	
	noFlask, noFood, hasLowDuration = {},{},{};
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()
	--print("Ready check init!");
	if self.db.profile.manualCheckOnly then
		icu:UnregisterEvent("READY_CHECK");
		return true;
	end
	
	if not self.db.profile.checkAfterFinish then
		self:inspectRaid(nil,true);
	else
		self:ScheduleTimer("READY_CHECK_FINISHED", 30);
		self:RegisterEvent("READY_CHECK_FINISHED");
	end
end

function icu:READY_CHECK_FINISHED()
	--print("Ready check finish!");
	self:UnregisterEvent("READY_CHECK_FINISHED");
	self:CancelAllTimers();
	self:inspectRaid(nil,true);
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)

icu:RegisterEvent("READY_CHECK");

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