----------------------------------------------------------------------- -- Module Declaration ----------------------------------------------------------------------- local plugin = BigWigs:New("Health", "$Revision: 5734 $") if not plugin then return end ----------------------------------------------------------------------- -- Are you local? ----------------------------------------------------------------------- local dew = AceLibrary("Dewdrop-2.0") local lockWarned = nil local active = nil -- The module we're currently tracking health for. local anchor = nil local units = {} local display = {} local OnOptionToggled = nil -- Function invoked when the health option is toggled on a module. ----------------------------------------------------------------------- -- Localization ----------------------------------------------------------------------- local L = AceLibrary("AceLocale-2.2"):new("BigWigsHealth") L:RegisterTranslations("enUS", function() return { ["Health"] = true, ["Options for the Health Display."] = true, ["Disabled"] = true, ["Disable the health display for all modules that use it."] = true, ["The health display will show next time. To disable it completely for this encounter, you need to toggle it off in the encounter options."] = true, ["The health display has been locked, you need to right click the Big Wigs icon, go to Extras -> Health -> Display and toggle the Lock option if you want to move it or access the other options."] = true, health = "Health display", health_desc = "Show the health window when appropriate for this encounter, listing players who are standing too close to you.", font = "Fonts\\FRIZQT__.TTF", ["Close"] = true, ["Closes the health display.\n\nTo disable it completely for any encounter, you have to go into the options for the relevant boss module and toggle the 'Health' option off."] = true, ["Test"] = true, ["Perform a Health test."] = true, ["Display"] = true, ["Options for the Health display window."] = true, ["Lock"] = true, ["Locks the display in place, preventing moving and resizing."] = true, ["Title"] = true, ["Shows or hides the title."] = true, ["Background"] = true, ["Shows or hides the background."] = true, } end) -------------------------------------------------------------------------------- -- Options -- plugin.defaultDB = { posx = nil, posy = nil, title = true, background = true, lock = nil, width = 100, height = 80, disabled = nil, health = true, } plugin.external = true plugin.consoleCmd = L["Health"] plugin.consoleOptions = { type = "group", name = L["Health"], desc = L["Options for the Health Display."], handler = plugin, pass = true, get = function(key) return plugin.db.profile[key] end, set = function(key, value) plugin.db.profile[key] = value if key == "disabled" then if value then plugin:CloseHealth() else plugin:OpenHealth() end end end, args = { test = { type = "execute", name = L["Test"], desc = L["Perform a Health test."], func = "TestHealth", order = 99, }, disabled = { type = "toggle", name = L["Disabled"], desc = L["Disable the health display for all modules that use it."], order = 101, }, spacer = { type = "header", name = " ", order = 102, }, display = { type = "group", name = L["Display"], desc = L["Options for the Health display window."], order = 103, pass = true, handler = plugin, set = function(key, value) plugin.db.profile[key] = value if key == "lock" and value and not lockWarned then BigWigs:Print(L["The health display has been locked, you need to right click the Big Wigs icon, go to Extras -> Health -> Display and toggle the Lock option if you want to move it or access the other options."]) lockWarned = true end plugin:RestyleWindow() end, get = function(key) return plugin.db.profile[key] end, args = { lock = { type = "toggle", name = L["Lock"], desc = L["Locks the display in place, preventing moving and resizing."], order = 1, }, title = { type = "toggle", name = L["Title"], desc = L["Shows or hides the title."], order = 2, }, background = { type = "toggle", name = L["Background"], desc = L["Shows or hides the background."], order = 3, }, close = { type = "execute", name = L["Close"], desc = L["Closes the health display.\n\nTo disable it completely for any encounter, you have to go into the options for the relevant boss module and toggle the 'Health' option off."], func = "CloseHealth", order = 4, }, }, }, } } ----------------------------------------------------------------------- -- Initialization ----------------------------------------------------------------------- function plugin:OnRegister() BigWigs:RegisterBossOption("health", L["health"], L["health_desc"], OnOptionToggled) end function plugin:OnEnable() self:RegisterEvent("Ace2_AddonDisabled") self:RegisterEvent("BigWigs_ShowHealth") self:RegisterEvent("BigWigs_HideHealth") end function plugin:OnDisable() self:CloseHealth() end ----------------------------------------------------------------------- -- Event Handlers ----------------------------------------------------------------------- function plugin:BigWigs_ShowHealth(module) if active then error("The health window is already running for another module.") end active = module self:OpenHealth() end function plugin:BigWigs_HideHealth(module) active = nil self:CloseHealth() end OnOptionToggled = function(module) if active and active == module then if active.db.profile.health then plugin:OpenHealth() else plugin:CloseHealth() end end end function plugin:Ace2_AddonDisabled(module) if active and active == module then self:BigWigs_HideHealth(active) end end ----------------------------------------------------------------------- -- Util ----------------------------------------------------------------------- function plugin:CloseHealth() if anchor then anchor:Hide() end self:CancelScheduledEvent("bwhealthupdate") dew:Close() end function plugin:OpenHealth() if self.db.profile.disabled then return end if active and (not active.health or not active.db.profile.health) then return end self:SetupFrames() anchor.text:SetText(L["Health"]) anchor.header:SetText(active and active.healthHeader or L["Health"]) anchor:Show() if active.health then if not self:IsEventScheduled("bwhealthscan") then self:ScheduleRepeatingEvent("bwhealthscan", self.ScanUnits, .5, self) end self:RegisterEvent('UPDATE_MOUSEOVER_UNIT') self:RegisterEvent('PLAYER_TARGET_CHANGED') elseif not self:IsEventScheduled("bwhealthupdate") then self:ScheduleRepeatingEvent("bwhealthupdate", self.UpdateHealth, .5, self) end end function plugin:UPDATE_MOUSEOVER_UNIT() table.insert(units, 'mouseover') if not self:IsEventScheduled("bwhealthupdate") then self:ScheduleRepeatingEvent("bwhealthupdate", self.UpdateHealth, .5, self) end end function plugin:PLAYER_TARGET_CHANGED() table.insert(units, 'target') if not self:IsEventScheduled("bwhealthupdate") then self:ScheduleRepeatingEvent("bwhealthupdate", self.UpdateHealth, .5, self) end end function plugin:ScanUnits() if UnitInRaid("player") then for i = 1, GetNumRaidMembers() do table.insert(units, string.format('raid%starget',i)) end elseif GetNumPartyMembers() > 0 then for i = 1, GetNumPartyMembers() do table.insert(units, string.format('party%starget',i)) end end if UnitExists('pet') then table.insert(units, 'pettarget') end if UnitExists('vehicle') then table.insert(units, 'vehicletarget') end if not self:IsEventScheduled("bwhealthupdate") then self:ScheduleRepeatingEvent("bwhealthupdate", self.UpdateHealth, .5, self) end end function plugin:UpdateHealth() wipe(display) if not active.health then table.insert(units, 'player') end for i, unit in pairs(units) do local name = UnitName(unit) local guid = UnitGUID(unit) local mobid = guid and tonumber((guid):sub(-12,-7),16) if unit == 'player' or active.health[mobid] then local cur = UnitHealth(unit) local max = UnitHealthMax(unit) local pct = (cur / max * 100) table.insert(display, string.format('%s: %s/%s (%s)',name, cur, max, pct)) end end anchor.text:SetText(table.concat(display, "\n")) wipe(units) end function plugin:TestHealth() if active then error("The health module is already running for another boss module.") end self:OpenHealth() end ------------------------------ -- Create the Anchor -- ------------------------------ local function showConfig() dew:FeedAceOptionsTable(plugin.consoleOptions.args.display) end local function onDragStart(self) self:StartMoving() end local function onDragStop(self) self:StopMovingOrSizing() plugin:SavePosition() end local function OnDragHandleMouseDown(self) self.frame:StartSizing("BOTTOMRIGHT") end local function OnDragHandleMouseUp(self, button) self.frame:StopMovingOrSizing() end local function onResize(self, width, height) plugin.db.profile.width = width plugin.db.profile.height = height end local function displayOnMouseDown(self, button) if button == "RightButton" then dew:Open(self, "children", showConfig) end end local locked = nil local function lockDisplay() if locked then return end anchor:EnableMouse(false) anchor:SetMovable(false) anchor:SetResizable(false) anchor:RegisterForDrag() anchor:SetScript("OnSizeChanged", nil) anchor:SetScript("OnDragStart", nil) anchor:SetScript("OnDragStop", nil) anchor:SetScript("OnMouseDown", nil) anchor.drag:Hide() anchor.header:Hide() anchor.close:Hide() locked = true end local function unlockDisplay() if not locked then return end anchor:EnableMouse(true) anchor:SetMovable(true) anchor:SetResizable(true) anchor:RegisterForDrag("LeftButton") anchor:SetScript("OnSizeChanged", onResize) anchor:SetScript("OnDragStart", onDragStart) anchor:SetScript("OnDragStop", onDragStop) anchor:SetScript("OnMouseDown", displayOnMouseDown) anchor.drag:Show() anchor.header:Show() anchor.close:Show() locked = nil end local function onControlEnter(self) GameTooltip:ClearLines() GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT") GameTooltip:AddLine(self.tooltipHeader) GameTooltip:AddLine(self.tooltipText, 1, 1, 1, 1) GameTooltip:Show() end local function onControlLeave() GameTooltip:Hide() end function plugin:SetupFrames() if anchor then return end local display = CreateFrame("Frame", "BigWigsHealth", UIParent) display:SetWidth(self.db.profile.width) display:SetHeight(self.db.profile.height) display:SetMinResize(100, 30) display:SetClampedToScreen(true) local bg = display:CreateTexture(nil, "PARENT") bg:SetAllPoints(display) bg:SetBlendMode("BLEND") bg:SetTexture(0, 0, 0, 0.3) display.background = bg local close = CreateFrame("Button", nil, display) close:SetPoint("BOTTOMRIGHT", display, "TOPRIGHT", -2, 2) close:SetHeight(16) close:SetWidth(16) close.tooltipHeader = L["Close"] close.tooltipText = L["Closes the health display.\n\nTo disable it completely for any encounter, you have to go into the options for the relevant boss module and toggle the 'Health' option off."] close:SetScript("OnEnter", onControlEnter) close:SetScript("OnLeave", onControlLeave) close:SetScript("OnClick", function() if active then BigWigs:Print(L["The health display will show next time. To disable it completely for this encounter, you need to toggle it off in the encounter options."]) end plugin:CloseHealth() end) close:SetNormalTexture("Interface\\AddOns\\BigWigs\\Textures\\icons\\close") display.close = close local header = display:CreateFontString(nil, "OVERLAY") header:SetFontObject(GameFontNormal) header:SetText(L["Health"]) header:SetPoint("BOTTOM", display, "TOP", 0, 4) display.header = header local text = display:CreateFontString(nil, "OVERLAY") text:SetFontObject(GameFontNormal) text:SetFont(L["font"], 12) text:SetText("") text:SetAllPoints(display) display.text = text local drag = CreateFrame("Frame", nil, display) drag.frame = display drag:SetFrameLevel(display:GetFrameLevel() + 10) -- place this above everything drag:SetWidth(16) drag:SetHeight(16) drag:SetPoint("BOTTOMRIGHT", display, -1, 1) drag:EnableMouse(true) drag:SetScript("OnMouseDown", OnDragHandleMouseDown) drag:SetScript("OnMouseUp", OnDragHandleMouseUp) drag:SetAlpha(0.5) display.drag = drag local tex = drag:CreateTexture(nil, "BACKGROUND") tex:SetTexture("Interface\\AddOns\\BigWigs\\Textures\\draghandle") tex:SetWidth(16) tex:SetHeight(16) tex:SetBlendMode("ADD") tex:SetPoint("CENTER", drag) anchor = display self:RestyleWindow() local x = self.db.profile.posx local y = self.db.profile.posy if x and y then local s = display:GetEffectiveScale() display:ClearAllPoints() display:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x / s, y / s) else self:ResetAnchor() end end function plugin:RestyleWindow() if not anchor then return end if self.db.profile.lock then locked = nil lockDisplay() else locked = true unlockDisplay() end if self.db.profile.title then anchor.header:Show() else anchor.header:Hide() end if self.db.profile.background then anchor.background:Show() else anchor.background:Hide() end end function plugin:ResetAnchor() if not anchor then self:SetupFrames() end anchor:ClearAllPoints() anchor:SetPoint("CENTER", UIParent, "CENTER") self.db.profile.posx = nil self.db.profile.posy = nil end function plugin:SavePosition() if not anchor then self:SetupFrames() end local s = anchor:GetEffectiveScale() self.db.profile.posx = anchor:GetLeft() * s self.db.profile.posy = anchor:GetTop() * s end