Add audible/visible threat warnings. Use LibSink-2.0. Fix LDB/FuBar related bugs. Fix list of events needed to trigger updates.

This commit is contained in:
Xinhuan
2008-10-13 03:38:10 +08:00
parent 89715aa336
commit 7428e397a4
4 changed files with 377 additions and 146 deletions
+1
View File
@@ -14,3 +14,4 @@ externals:
Libs/AceTimer-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceTimer-3.0 Libs/AceTimer-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceTimer-3.0
Libs/LibSharedMedia-3.0: svn://svn.wowace.com/wow/libsharedmedia-3-0/mainline/trunk/LibSharedMedia-3.0 Libs/LibSharedMedia-3.0: svn://svn.wowace.com/wow/libsharedmedia-3-0/mainline/trunk/LibSharedMedia-3.0
Libs/AceGUI-3.0-SharedMediaWidgets: svn://svn.wowace.com/wow/ace-gui-3-0-shared-media-widgets/mainline/trunk/AceGUI-3.0-SharedMediaWidgets Libs/AceGUI-3.0-SharedMediaWidgets: svn://svn.wowace.com/wow/ace-gui-3-0-shared-media-widgets/mainline/trunk/AceGUI-3.0-SharedMediaWidgets
Libs/LibSink-2.0: svn://svn.wowace.com/wow/libsink-2-0/mainline/trunk/LibSink-2.0
+16 -7
View File
@@ -4,6 +4,10 @@ if not L then return end
-- Main Omen window -- Main Omen window
L["<Unknown>"] = true L["<Unknown>"] = true
L["Test Mode"] = true
-- Warnings
L["|cffff0000Error:|r Omen cannot use shake warning if you have turned on nameplates at least once since logging in."] = true
-- Config module titles -- Config module titles
L["General Settings"] = true L["General Settings"] = true
@@ -120,7 +124,18 @@ L["Center Omen"] = true
L["Configure"] = true L["Configure"] = true
L["Open the configuration dialog"] = true L["Open the configuration dialog"] = true
-- For Fubar -- Config strings, warning settings section
L["Warning Settings"] = true
L["OMEN_WARNINGS_DESC"] = "This section allows you to customize when and how Omen notifies you if you are about to pull aggro."
L["Enable Warning Message"] = true
L["Print a message to screen when you accumulate too much threat"] = true
L["Warning Threshold %"] = true
L["Sound to play"] = true
L["Disable while tanking"] = true
L["DISABLE_WHILE_TANKING_DESC"] = "Do not give out any warnings if Defensive Stance, Bear Form, Righteous Fury or Frost Presence is active."
L["Test warnings"] = true
-- Config strings, for Fubar
L["Click|r to toggle the Omen window"] = true L["Click|r to toggle the Omen window"] = true
L["Right-click|r to open the options menu"] = true L["Right-click|r to open the options menu"] = true
L["FuBar Options"] = true L["FuBar Options"] = true
@@ -211,9 +226,3 @@ Vigilance ____________ 10% of target's generated threat (stance modifier is not
You do not gain threat for refecting spells targetted at allies with Improved Spell Reflect. When you reflect a spell for an ally, your ally gains the threat for the damage dealt by the reflected spell. You do not gain threat for refecting spells targetted at allies with Improved Spell Reflect. When you reflect a spell for an ally, your ally gains the threat for the damage dealt by the reflected spell.
]] ]]
-- Slash command
BINDING_HEADER_OMEN = "Omen"
BINDING_NAME_OMENTOGGLE = "Toggle Omen"
+358 -138
View File
@@ -9,22 +9,27 @@
LoadAddOn("Ace3") LoadAddOn("Ace3")
LoadAddOn("LibSharedMedia-3.0") LoadAddOn("LibSharedMedia-3.0")
LoadAddOn("AceGUI-3.0-SharedMediaWidgets") LoadAddOn("AceGUI-3.0-SharedMediaWidgets")
LoadAddOn("LibSink-2.0")
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Addon declaration -- Addon declaration
local Omen = LibStub("AceAddon-3.0"):NewAddon("Omen", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0") local Omen = LibStub("AceAddon-3.0"):NewAddon("Omen", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "LibSink-2.0")
local L = LibStub("AceLocale-3.0"):GetLocale("Omen", false) local L = LibStub("AceLocale-3.0"):GetLocale("Omen", false)
local LSM = LibStub("LibSharedMedia-3.0") local LSM = LibStub("LibSharedMedia-3.0")
_G["Omen"] = Omen _G["Omen"] = Omen
-- TODO: Add TPS calculations -- TODO: Add TPS calculations
-- TODO: Add visible/audible warnings
-- TODO: Add Sink/SharedMedia stuff
-- TODO: Code optimizations -- TODO: Code optimizations
-----------------------------------------------------------------------------
-- Keybinding globals
BINDING_HEADER_OMEN = "Omen"
BINDING_NAME_OMENTOGGLE = L["Toggle Omen"]
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Register some media -- Register some media
LSM:Register("sound", "Rubber Ducky", [[Sound\Doodad\Goblin_Lottery_Open01.wav]]) LSM:Register("sound", "Rubber Ducky", [[Sound\Doodad\Goblin_Lottery_Open01.wav]])
@@ -122,6 +127,16 @@ local defaults = {
HideMinimapButton = true, HideMinimapButton = true,
AttachMinimap = false, AttachMinimap = false,
}, },
Warnings = {
Sound = true,
Flash = true,
Shake = false,
Message = false,
SinkOptions = {},
Threshold = 90,
SoundFile = "Fel Nova",
DisableWhileTanking = true,
},
}, },
} }
local guidNameLookup = {} -- Format: guidNameLookup[guid] = "Unit Name" local guidNameLookup = {} -- Format: guidNameLookup[guid] = "Unit Name"
@@ -129,11 +144,13 @@ local guidClassLookup = {} -- Format: guidClassLookup[guid] = "CLASS"
local timers = {} -- Format: timers.timerName = timer returned from AceTimer-3.0 local timers = {} -- Format: timers.timerName = timer returned from AceTimer-3.0
local bars = {} -- Format: bars[i] = frame containing the i-th bar from the top of Omen local bars = {} -- Format: bars[i] = frame containing the i-th bar from the top of Omen
local inRaid, inParty -- boolean variables indicating if the player is in a raid and/or party local inRaid, inParty -- boolean variables indicating if the player is in a raid and/or party
local testMode = false -- boolean: Are we in test mode?
Omen.GuidNameLookup = guidNameLookup Omen.GuidNameLookup = guidNameLookup
Omen.GuidClassLookup = guidClassLookup Omen.GuidClassLookup = guidClassLookup
Omen.Timers = timers Omen.Timers = timers
Omen.Bars = bars Omen.Bars = bars
setmetatable(guidNameLookup, {__index = function(self, guid) return L["<Unknown>"] end})
local default_color = { -- Default bar color for units not in the player's raid/party local default_color = { -- Default bar color for units not in the player's raid/party
r = 1, r = 1,
@@ -271,6 +288,7 @@ function Omen:OnInitialize()
self.db.RegisterCallback(self, "OnProfileCopied", "OnProfileChanged") self.db.RegisterCallback(self, "OnProfileCopied", "OnProfileChanged")
self.db.RegisterCallback(self, "OnProfileReset", "OnProfileChanged") self.db.RegisterCallback(self, "OnProfileReset", "OnProfileChanged")
db = self.db.profile db = self.db.profile
self:SetSinkStorage(db.Warnings.SinkOptions)
self:CreateFrames() self:CreateFrames()
self:SetupOptions() self:SetupOptions()
@@ -278,9 +296,7 @@ function Omen:OnInitialize()
self:UpdateBackdrop() self:UpdateBackdrop()
self:UpdateTitleBar() self:UpdateTitleBar()
-- Register events that are "always on". The rest are in :OnEnable()
self:RegisterEvent("PLAYER_LOGIN") self:RegisterEvent("PLAYER_LOGIN")
self:RegisterEvent("PLAYER_ENTERING_WORLD")
end end
function Omen:PLAYER_LOGIN() function Omen:PLAYER_LOGIN()
@@ -294,9 +310,9 @@ function Omen:PLAYER_LOGIN()
-- Optional launcher support for LDB-1.1 if present, this code is placed here so -- Optional launcher support for LDB-1.1 if present, this code is placed here so
-- that it runs after all other addons have loaded since we don't embed LDB-1.1 -- that it runs after all other addons have loaded since we don't embed LDB-1.1
local DataBroker = LibStub("LibDataBroker-1.1", true) if LibStub("LibDataBroker-1.1", true) and not IsAddOnLoaded("Broker2FuBar") then
if DataBroker then local LDB = LibStub("LibDataBroker-1.1", true)
local launcher = DataBroker:NewDataObject("Omen", { local launcher = LDB:NewDataObject("Omen", {
type = "launcher", type = "launcher",
icon = "Interface\\AddOns\\Omen\\icon", icon = "Interface\\AddOns\\Omen\\icon",
OnClick = function(clickedframe, button) OnClick = function(clickedframe, button)
@@ -309,14 +325,14 @@ function Omen:PLAYER_LOGIN()
-- that it runs after all other addons have loaded since we don't embed LFBP-3.0 -- that it runs after all other addons have loaded since we don't embed LFBP-3.0
-- Yes, this is one big hack since LFBP-3.0 is a Rock library, and we embed it -- Yes, this is one big hack since LFBP-3.0 is a Rock library, and we embed it
-- via Ace3. OnEmbedInitialize() needs to be called manually. -- via Ace3. OnEmbedInitialize() needs to be called manually.
if LibStub:GetLibrary("LibFuBarPlugin-3.0", true) then if LibStub:GetLibrary("LibFuBarPlugin-3.0", true) and not IsAddOnLoaded("FuBar2Broker") then
local LFBP = LibStub:GetLibrary("LibFuBarPlugin-3.0") local LFBP = LibStub:GetLibrary("LibFuBarPlugin-3.0")
LibStub("AceAddon-3.0"):EmbedLibrary(self, "LibFuBarPlugin-3.0") LibStub("AceAddon-3.0"):EmbedLibrary(self, "LibFuBarPlugin-3.0")
self:SetFuBarOption("tooltipType", "GameTooltip") self:SetFuBarOption("tooltipType", "GameTooltip")
self:SetFuBarOption("hasNoColor", true) self:SetFuBarOption("hasNoColor", true)
self:SetFuBarOption("cannotDetachTooltip", true) self:SetFuBarOption("cannotDetachTooltip", true)
self:SetFuBarOption("hideWithoutStandby", true) self:SetFuBarOption("hideWithoutStandby", true)
self:SetFuBarOption("iconPath", [[Interface\AddOns\Omen\icon]]) self:SetFuBarOption("iconPath", [[Interface\AddOns\Omen\icon]])
self:SetFuBarOption("hasIcon", true) self:SetFuBarOption("hasIcon", true)
self:SetFuBarOption("defaultPosition", "RIGHT") self:SetFuBarOption("defaultPosition", "RIGHT")
self:SetFuBarOption("tooltipHiddenWhenEmpty", true) self:SetFuBarOption("tooltipHiddenWhenEmpty", true)
@@ -338,20 +354,21 @@ function Omen:OnEnable()
self:RegisterEvent("UNIT_THREAT_LIST_UPDATE") self:RegisterEvent("UNIT_THREAT_LIST_UPDATE")
self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE") self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE")
self:RegisterEvent("PLAYER_TARGET_CHANGED") self:RegisterEvent("PLAYER_TARGET_CHANGED")
self:RegisterEvent("UNIT_PET")
self:RegisterEvent("PARTY_MEMBERS_CHANGED") self:RegisterEvent("PARTY_MEMBERS_CHANGED")
self:RegisterEvent("UNIT_PET", "PARTY_MEMBERS_CHANGED")
self:RegisterEvent("UNIT_NAME_UPDATE", "PARTY_MEMBERS_CHANGED")
self:RegisterEvent("PLAYER_PET_CHANGED", "PARTY_MEMBERS_CHANGED")
--self:RegisterEvent("RAID_ROSTER_UPDATE", "PARTY_MEMBERS_CHANGED") -- Is this needed?
self:RegisterEvent("PLAYER_UPDATE_RESTING", "UpdateVisible")
self:RegisterEvent("PLAYER_ENTERING_WORLD", "UpdateVisible")
self:PARTY_MEMBERS_CHANGED() self:PARTY_MEMBERS_CHANGED()
self:PLAYER_TARGET_CHANGED() self:PLAYER_TARGET_CHANGED()
end end
function Omen:Disable() function Omen:OnDisable()
self:UnregisterEvent("UNIT_THREAT_LIST_UPDATE")
self:UnregisterEvent("UNIT_THREAT_SITUATION_UPDATE")
self:UnregisterEvent("PLAYER_TARGET_CHANGED")
self:UnregisterEvent("UNIT_PET")
self:UnregisterEvent("PARTY_MEMBERS_CHANGED")
-- Cancel all timers (well at least nil them all -- Cancel all timers (well at least nil them all
-- out in timers[], since AceTimer-3.0 cancels -- out in timers[], since AceTimer-3.0 cancels
-- them all OnDisable anyway). -- them all OnDisable anyway).
@@ -456,7 +473,7 @@ function Omen:UpdateBackdrop()
bgFrame.insets.bottom = inset bgFrame.insets.bottom = inset
self.Title:SetBackdrop(bgFrame) self.Title:SetBackdrop(bgFrame)
self.BarList:SetBackdrop(bgFrame) self.BarList:SetBackdrop(bgFrame)
local c = db.Background.Color local c = db.Background.Color
self.Title:SetBackdropColor(c.r, c.g, c.b, c.a) self.Title:SetBackdropColor(c.r, c.g, c.b, c.a)
self.BarList:SetBackdropColor(c.r, c.g, c.b, c.a) self.BarList:SetBackdropColor(c.r, c.g, c.b, c.a)
@@ -495,14 +512,113 @@ end
function Omen:UpdateFuBarSettings() function Omen:UpdateFuBarSettings()
if LibStub:GetLibrary("LibFuBarPlugin-3.0", true) then if LibStub:GetLibrary("LibFuBarPlugin-3.0", true) then
if self:IsFuBarMinimapAttached() ~= db.FuBar.AttachMinimap then if db.FuBar.HideMinimapButton then
self:ToggleFuBarMinimapAttached() self:Hide()
else
self:Show()
if self:IsFuBarMinimapAttached() ~= db.FuBar.AttachMinimap then
self:ToggleFuBarMinimapAttached()
end
end end
if db.FuBar.HideMinimapButton then self:Hide() else self:Show() end
end end
end end
-----------------------------------------------------------------------------
-- Omen warnings
function Omen:Flash()
if not self.FlashFrame then
local flasher = CreateFrame("Frame", "OmenFlashFrame")
flasher:SetToplevel(true)
flasher:SetFrameStrata("FULLSCREEN_DIALOG")
flasher:SetAllPoints(UIParent)
flasher:EnableMouse(false)
flasher:Hide()
flasher.texture = flasher:CreateTexture(nil, "BACKGROUND")
flasher.texture:SetTexture("Interface\\FullScreenTextures\\LowHealth")
flasher.texture:SetAllPoints(UIParent)
flasher.texture:SetBlendMode("ADD")
flasher:SetScript("OnShow", function(self)
self.elapsed = 0
self:SetAlpha(0)
end)
flasher:SetScript("OnUpdate", function(self, elapsed)
elapsed = self.elapsed + elapsed
if elapsed < 2.6 then
local alpha = elapsed % 1.3
if alpha < 0.15 then
self:SetAlpha(alpha / 0.15)
elseif alpha < 0.9 then
self:SetAlpha(1 - (alpha - 0.15) / 0.6)
else
self:SetAlpha(0)
end
else
self:Hide()
end
self.elapsed = elapsed
end)
self.FlashFrame = flasher
end
self.FlashFrame:Show()
end
-- This function is adapted from Omen2 to be self-contained,
-- which was initially taken from BigWigs
function Omen:Shake()
local shaker = self.ShakerFrame
if not shaker then
shaker = CreateFrame("Frame", "OmenShaker", UIParent)
shaker:Hide()
shaker:SetScript("OnUpdate", function(self, elapsed)
elapsed = self.elapsed + elapsed
local x, y = 0, 0 -- Resets to original position if we're supposed to stop.
if elapsed >= 0.8 then
self:Hide()
else
x, y = random(-8, 8), random(-8, 8)
end
if WorldFrame:IsProtected() and InCombatLockdown() then
if not shaker.fail then
Omen:Print(L["|cffff0000Error:|r Omen cannot use shake warning if you have turned on nameplates at least once since logging in."])
shaker.fail = true
end
self:Hide()
else
WorldFrame:ClearAllPoints()
for i = 1, #self.originalPoints do
local v = self.originalPoints[i]
WorldFrame:SetPoint(v[1], v[2], v[3], v[4] + x, v[5] + y)
end
end
self.elapsed = elapsed
end)
shaker:SetScript("OnShow", function(self)
-- Store old worldframe positions, we need them all, people have frame modifiers for it
if not self.originalPoints then
self.originalPoints = {}
for i = 1, WorldFrame:GetNumPoints() do
tinsert(self.originalPoints, {WorldFrame:GetPoint(i)})
end
end
self.elapsed = 0
end)
self.ShakerFrame = shaker
end
shaker:Show()
end
function Omen:Warn(sound, flash, shake, message)
if sound then PlaySoundFile(LSM:Fetch("sound", db.Warnings.SoundFile)) end
if flash then self:Flash() end
if shake then self:Shake() end
if message then self:Pour(message, 1, 0, 0, nil, 24, "OUTLINE", true) end
end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Omen bar stuff -- Omen bar stuff
@@ -539,7 +655,7 @@ do
self:SetScript("OnUpdate", animate) self:SetScript("OnUpdate", animate)
end end
-- Create bars on demand -- Create bars on demand
setmetatable(bars, {__index = function(self, barID) setmetatable(bars, {__index = function(self, barID)
local bar = CreateFrame("Frame", nil, Omen.BarList) local bar = CreateFrame("Frame", nil, Omen.BarList)
self[barID] = bar self[barID] = bar
@@ -640,17 +756,6 @@ function Omen:PLAYER_TARGET_CHANGED()
end end
end end
function Omen:UNIT_PET()
self:PARTY_MEMBERS_CHANGED()
end
function Omen:PLAYER_ENTERING_WORLD()
if UnitGUID("player") then
guidNameLookup[UnitGUID("player")] = UnitName("player")
end
self:UpdateVisible()
end
local lastPartyUpdateTime = GetTime() local lastPartyUpdateTime = GetTime()
function Omen:PARTY_MEMBERS_CHANGED() function Omen:PARTY_MEMBERS_CHANGED()
@@ -679,7 +784,10 @@ function Omen:UpdatePartyGUIDs()
for k, v in pairs(guidClassLookup) do for k, v in pairs(guidClassLookup) do
guidClassLookup[k] = nil guidClassLookup[k] = nil
end end
_, guidClassLookup[UnitGUID("player")] = UnitClass("player") if UnitGUID("player") then
guidNameLookup[UnitGUID("player")] = UnitName("player")
_, guidClassLookup[UnitGUID("player")] = UnitClass("player")
end
if UnitExists("pet") then if UnitExists("pet") then
guidClassLookup[UnitGUID("pet")] = "PET" guidClassLookup[UnitGUID("pet")] = "PET"
guidNameLookup[UnitGUID("pet")] = UnitName("pet")--.." ["..UnitName("player").."]" guidNameLookup[UnitGUID("pet")] = UnitName("pet")--.." ["..UnitName("player").."]"
@@ -689,15 +797,15 @@ function Omen:UpdatePartyGUIDs()
local playerFmt = inRaid and rID or pID local playerFmt = inRaid and rID or pID
local petFmt = inRaid and rpID or ppID local petFmt = inRaid and rpID or ppID
local currentPartySize = inRaid and GetNumRaidMembers() or GetNumPartyMembers() local currentPartySize = inRaid and GetNumRaidMembers() or GetNumPartyMembers()
for i = 1, currentPartySize do for i = 1, currentPartySize do
local unitID = playerFmt[i] local unitID = playerFmt[i]
local pGUID = UnitGUID(unitID) local pGUID = UnitGUID(unitID)
if pGUID then if pGUID then
guidNameLookup[pGUID] = UnitName(unitID) guidNameLookup[pGUID] = UnitName(unitID)
_, guidClassLookup[pGUID] = UnitClass(unitID) _, guidClassLookup[pGUID] = UnitClass(unitID)
-- lookup pet (if existing) -- lookup pet (if existing)
local petID = petFmt[i] local petID = petFmt[i]
local petGUID = UnitGUID(petID) local petGUID = UnitGUID(petID)
@@ -746,12 +854,15 @@ threatValue is the amount of threat that the unit has on the mob's threat list.
--------- ---------
r, g, b = GetThreatStatusColor(state) r, g, b = GetThreatStatusColor(state)
Returns the colors used in the UI to represent each major threat state. Returns the colors used in the UI to represent each major threat state.
]] ]]
local threatTable = {} -- Format: threatTable[guid] = threatValue local threatTable = {} -- Format: threatTable[guid] = threatValue
local sortTable = {} -- Format: threatTable[i] = guid -- used for sorting by sortfunction() local sortTable = {} -- Format: threatTable[i] = guid -- used for sorting by sortfunction()
local tankGUID -- Used to store which unit is tanking and hence has 100% threat by definition local tankGUID -- Used to store which unit is tanking and hence has 100% threat by definition
local lastWarn = { -- Used to store information for threat warnings
threatpercent = 0,
}
local function sortfunction(a, b) local function sortfunction(a, b)
return threatTable[a] > threatTable[b] return threatTable[a] > threatTable[b]
@@ -768,84 +879,88 @@ end
function Omen:UpdateBars() function Omen:UpdateBars()
if not self.Anchor:IsShown() and not db.CollapseHide then return end if not self.Anchor:IsShown() and not db.CollapseHide then return end
-- TODO: Put a update throtle on this function -- TODO: Put a update throtle on this function
-- Figure out which mob to show threat on, either "target" or "targettarget" local mobGUID, mobTargetGUID
-- It has to be attackable and not human controlled, otherwise return
local mob = "target"
if UnitExists(mob) and (UnitIsPlayer(mob) or UnitPlayerControlled(mob) or not UnitCanAttack("player", mob)) then
guidNameLookup[UnitGUID(mob)] = UnitName(mob)
mob = "targettarget"
end
if not UnitExists(mob) or UnitIsPlayer(mob) or UnitPlayerControlled(mob) or not UnitCanAttack("player", mob) then
self:ClearAll()
return
end
local mobGUID = UnitGUID(mob)
guidNameLookup[mobGUID] = UnitName(mob)
self.TitleText:SetText(guidNameLookup[mobGUID])
-- Schedule a repeating timer for updating threat on "targettarget" if testMode then
-- since we get no events on a targettarget change. for k, v in pairs(threatTable) do
if mob == "targettarget" and not timers.UpdateBars then threatTable[k] = nil
timers.UpdateBars = self:ScheduleRepeatingTimer("UpdateBars", 0.5)
end
-- We want the mob's target just in case the tank isn't
-- in our raid (say an NPC or some other player)
local mobTarget = mob.."target"
local mobTargetGUID = UnitGUID(mobTarget)
if mobTargetGUID and not guidNameLookup[mobTargetGUID] then
guidNameLookup[mobTargetGUID] = UnitName(mobTarget)
end
-- Clear the threat table
for k, v in pairs(threatTable) do
threatTable[k] = nil
end
threatTable[mobGUID] = -1
tankGUID = nil
-- Get data for threat on mob by scanning the whole raid
if inParty or inRaid then
if inRaid then
for i = 1, GetNumRaidMembers() do
updatethreat(rID[i], mob)
updatethreat(rpID[i], mob)
updatethreat(rtID[i], mob)
updatethreat(rptID[i], mob)
end
else
for i = 1, GetNumPartyMembers() do
updatethreat(pID[i], mob)
updatethreat(ppID[i], mob)
updatethreat(ptID[i], mob)
updatethreat(pptID[i], mob)
end
end end
for i = 1, 25 do
end threatTable[i] = i*5000
if not inRaid then end
updatethreat("player", mob) tankGUID = 25
updatethreat("pet", mob) self.TitleText:SetText(L["Test Mode"])
updatethreat("target", mob) else
updatethreat("pettarget", mob) -- Figure out which mob to show threat on, either "target" or "targettarget"
end -- It has to be attackable and not human controlled, otherwise return
updatethreat("focus", mob) local mob = "target"
updatethreat("focustarget", mob) if UnitExists(mob) and (UnitIsPlayer(mob) or UnitPlayerControlled(mob) or not UnitCanAttack("player", mob)) then
updatethreat(mobTarget, mob) guidNameLookup[UnitGUID(mob)] = UnitName(mob)
updatethreat("mouseover", mob) mob = "targettarget"
updatethreat("mouseovertarget", mob) end
if not UnitExists(mob) or UnitIsPlayer(mob) or UnitPlayerControlled(mob) or not UnitCanAttack("player", mob) then
self:ClearAll()
return
end
mobGUID = UnitGUID(mob)
guidNameLookup[mobGUID] = UnitName(mob)
self.TitleText:SetText(guidNameLookup[mobGUID])
-- This is for testing purposes -- Schedule a repeating timer for updating threat on "targettarget"
--[[for k, v in pairs(threatTable) do -- since we get no events on a targettarget change.
threatTable[k] = nil if mob == "targettarget" and not timers.UpdateBars then
timers.UpdateBars = self:ScheduleRepeatingTimer("UpdateBars", 0.5)
end
-- We want the mob's target just in case the tank isn't
-- in our raid (say an NPC or some other player)
local mobTarget = mob.."target"
local mobTargetGUID = UnitGUID(mobTarget)
if mobTargetGUID and not guidNameLookup[mobTargetGUID] then
guidNameLookup[mobTargetGUID] = UnitName(mobTarget)
end
-- Clear the threat table
for k, v in pairs(threatTable) do
threatTable[k] = nil
end
threatTable[mobGUID] = -1
tankGUID = nil
-- Get data for threat on mob by scanning the whole raid
if inParty or inRaid then
if inRaid then
for i = 1, GetNumRaidMembers() do
updatethreat(rID[i], mob)
updatethreat(rpID[i], mob)
updatethreat(rtID[i], mob)
updatethreat(rptID[i], mob)
end
else
for i = 1, GetNumPartyMembers() do
updatethreat(pID[i], mob)
updatethreat(ppID[i], mob)
updatethreat(ptID[i], mob)
updatethreat(pptID[i], mob)
end
end
end
if not inRaid then
updatethreat("player", mob)
updatethreat("pet", mob)
updatethreat("target", mob)
updatethreat("pettarget", mob)
end
updatethreat("focus", mob)
updatethreat("focustarget", mob)
updatethreat(mobTarget, mob)
updatethreat("mouseover", mob)
updatethreat("mouseovertarget", mob)
end end
for i = 1, 25 do
threatTable[i] = i*5000
end
tankGUID = 25]]
-- Sort the threatTable -- Sort the threatTable
local i = 1 local i = 1
@@ -884,7 +999,7 @@ function Omen:UpdateBars()
end end
local bar = bars[j] local bar = bars[j]
local threat = threatTable[guid] local threat = threatTable[guid]
bar.Text1:SetText(guidNameLookup[guid] or L["<Unknown>"]) bar.Text1:SetText(guidNameLookup[guid])
if db.Bar.ShortNumbers and threat > 100000 then if db.Bar.ShortNumbers and threat > 100000 then
bar.Text2:SetFormattedText("%2.1fk [%d%%]", threat / 100000, tankThreat == 0 and 0 or threat / tankThreat * 100) bar.Text2:SetFormattedText("%2.1fk [%d%%]", threat / 100000, tankThreat == 0 and 0 or threat / tankThreat * 100)
else else
@@ -912,6 +1027,22 @@ function Omen:UpdateBars()
end end
self.Anchor:Show() self.Anchor:Show()
self.BarList:Show() self.BarList:Show()
-- Threat warnings
local pGUID = UnitGUID("player")
local pClass = guidClassLookup[pGUID]
local myThreatPercent = threatTable[pGUID] / tankThreat * 100
local t = db.Warnings
if lastWarn.mobGUID == mobGUID and myThreatPercent >= t.Threshold and t.Threshold > lastWarn.threatpercent then
if not t.DisableWhileTanking or not (pClass == "WARRIOR" and GetBonusBarOffset() == 2 or
pClass == "DRUID" and GetBonusBarOffset() == 3 or
pClass == "PALADIN" and UnitAura("player", GetSpellInfo(25780)) or
pClass == "DEATHKNIGHT" and GetShapeshiftFormInfo(GetShapeshiftForm()) == "Interface\\Icons\\Spell_Deathknight_FrostPresence") then
self:Warn(t.Sound, t.Flash, t.Shake, t.Message and L["Passed %s%% of %s's threat!"]:format(t.Threshold, guidNameLookup[tankGUID or mobTargetGUID or sortTable[1]]))
end
end
lastWarn.mobGUID = mobGUID
lastWarn.threatpercent = myThreatPercent
end end
function Omen:ClearAll() function Omen:ClearAll()
@@ -926,6 +1057,8 @@ function Omen:ClearAll()
self.Anchor:Hide() self.Anchor:Hide()
end end
end end
lastWarn.mobGUID = nil
lastWarn.threatpercent = 0
end end
@@ -942,16 +1075,18 @@ local function GetFuBarMinimapAttachedStatus(info)
return Omen:IsFuBarMinimapAttached() or db.FuBar.HideMinimapButton return Omen:IsFuBarMinimapAttached() or db.FuBar.HideMinimapButton
end end
-- Option table for the AceGUI config only
local options = { local options = {
type = "group", type = "group",
name = "Omen", name = "Omen",
get = function(info) return db[ info[#info] ] end, get = function(info) return db[ info[#info] ] end,
set = function(info, value) db[ info[#info] ] = value end, set = function(info, value) db[ info[#info] ] = value end,
args = { args = {
general = { General = {
order = 1, order = 1,
type = "group", type = "group",
name = L["General Settings"], name = L["General Settings"],
desc = L["General Settings"],
args = { args = {
intro = { intro = {
order = 1, order = 1,
@@ -992,11 +1127,6 @@ local options = {
if value then Omen.Grip:Hide() else Omen.Grip:Show() end if value then Omen.Grip:Hide() else Omen.Grip:Show() end
end, end,
}, },
linebreak = {
order = 9,
type = "description",
name = "",
},
Autocollapse = { Autocollapse = {
type = "toggle", type = "toggle",
name = L["Autocollapse"], name = L["Autocollapse"],
@@ -1136,6 +1266,7 @@ local options = {
}, },
}, },
ShowWhen = { ShowWhen = {
order = 2,
type = "group", type = "group",
name = L["Show When..."], name = L["Show When..."],
desc = L["Show Omen when..."], desc = L["Show Omen when..."],
@@ -1189,6 +1320,7 @@ local options = {
}, },
}, },
TitleBar = { TitleBar = {
order = 3,
type = "group", type = "group",
name = L["Title Bar Settings"], name = L["Title Bar Settings"],
desc = L["Title Bar Settings"], desc = L["Title Bar Settings"],
@@ -1258,6 +1390,7 @@ local options = {
}, },
}, },
Bars = { Bars = {
order = 4,
type = "group", type = "group",
name = L["Bar Settings"], name = L["Bar Settings"],
desc = L["Bar Settings"], desc = L["Bar Settings"],
@@ -1374,15 +1507,100 @@ local options = {
}, },
}, },
}, },
Warnings = {
order = 5,
type = "group",
name = L["Warning Settings"],
desc = L["Warning Settings"],
get = function(info) return db.Warnings[ info[#info] ] end,
set = function(info, value)
db.Warnings[ info[#info] ] = value
end,
args = {
intro = {
order = 1,
type = "description",
name = L["OMEN_WARNINGS_DESC"],
},
Sound = {
type = "toggle",
order = 2,
name = "Enable Sound",
desc = "Enable Sound",
},
Flash = {
type = "toggle",
order = 3,
name = "Enable Screen Flash",
desc = "Enable Screen Flash",
},
Shake = {
type = "toggle",
order = 4,
name = "Enable Screen Shake",
desc = "Enable Screen Shake",
},
Message = {
type = "toggle",
order = 5,
name = L["Enable Warning Message"],
desc = L["Print a message to screen when you accumulate too much threat"],
},
Output = Omen:GetSinkAce3OptionsDataTable(),
Threshold = {
type = "range",
order = 7,
name = L["Warning Threshold %"],
desc = L["Warning Threshold %"],
min = 60, max = 130, step = 1,
},
SoundFile = {
type = "select", dialogControl = 'LSM30_Sound',
order = 8,
name = L["Sound to play"],
desc = L["Sound to play"],
values = AceGUIWidgetLSMlists.sound,
disabled = function() return not db.Warnings.Sound end,
},
DisableWhileTanking = {
type = "toggle",
order = 9,
name = L["Disable while tanking"],
desc = L["DISABLE_WHILE_TANKING_DESC"],
},
test = {
type = "execute",
order = -1,
name = L["Test warnings"],
desc = L["Test warnings"],
func = function()
local t = db.Warnings
Omen:Warn(t.Sound, t.Flash, t.Shake, t.Message and L["Test warnings"])
end,
},
},
},
FuBar = { FuBar = {
order = -4,
type = "group", type = "group",
name = L["FuBar Options"], name = L["FuBar Options"],
desc = L["FuBar Options"], desc = L["FuBar Options"],
hidden = function() return Omen.IsFuBarMinimapAttached == nil end, hidden = function() return Omen.IsFuBarMinimapAttached == nil end,
args = { args = {
attachMinimap = { hideIcon = {
type = "toggle", type = "toggle",
order = 1, order = 1,
name = L["Hide minimap/FuBar icon"],
desc = L["Hide minimap/FuBar icon"],
get = function(info) return db.FuBar.HideMinimapButton end,
set = function(info, v)
db.FuBar.HideMinimapButton = v
Omen:UpdateFuBarSettings()
end,
},
attachMinimap = {
type = "toggle",
order = 2,
name = L["Attach to minimap"], name = L["Attach to minimap"],
desc = L["Attach to minimap"], desc = L["Attach to minimap"],
get = function(info) return Omen:IsFuBarMinimapAttached() end, get = function(info) return Omen:IsFuBarMinimapAttached() end,
@@ -1390,17 +1608,7 @@ local options = {
Omen:ToggleFuBarMinimapAttached() Omen:ToggleFuBarMinimapAttached()
db.FuBar.AttachMinimap = Omen:IsFuBarMinimapAttached() db.FuBar.AttachMinimap = Omen:IsFuBarMinimapAttached()
end, end,
}, disabled = function() return db.FuBar.HideMinimapButton end,
hideIcon = {
type = "toggle",
order = 2,
name = L["Hide minimap/FuBar icon"],
desc = L["Hide minimap/FuBar icon"],
get = function(info) return db.FuBar.HideMinimapButton end,
set = function(info, v)
db.FuBar.HideMinimapButton = v
if v then Omen:Hide() else Omen:Show() end
end,
}, },
showIcon = { showIcon = {
type = "toggle", type = "toggle",
@@ -1438,6 +1646,7 @@ local options = {
}, },
Help = { Help = {
type = "group", type = "group",
order = -1,
name = L["Help File"], name = L["Help File"],
desc = L["A collection of help pages"], desc = L["A collection of help pages"],
childGroups = "select", childGroups = "select",
@@ -1479,10 +1688,15 @@ local options = {
}, },
} }
Omen.Options = options Omen.Options = options
options.args.Warnings.args.Output.order = 6
options.args.Warnings.args.Output.inline = true
options.args.Warnings.args.Output.disabled = function() return not db.Warnings.Message end
-- Option table for the slash command only
local optionsSlash = { local optionsSlash = {
type = "group", type = "group",
name = L["Slash Command"], name = L["Slash Command"],
order = -3,
args = { args = {
intro = { intro = {
order = 1, order = 1,
@@ -1521,20 +1735,26 @@ local optionsSlash = {
} }
Omen.OptionsSlash = optionsSlash Omen.OptionsSlash = optionsSlash
function Omen:SetupOptions() function Omen:SetupOptions()
self.optionsFrames = {} self.optionsFrames = {}
-- setup options table -- setup options table
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Omen", options) LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Omen", options)
LibStub("AceConfig-3.0"):RegisterOptionsTable("OmenSlashCommand", optionsSlash, "omen") LibStub("AceConfig-3.0"):RegisterOptionsTable("OmenSlashCommand", optionsSlash, "omen")
self.optionsFrames.Omen = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Omen", nil, nil, "general") local ACD3 = LibStub("AceConfigDialog-3.0")
self.optionsFrames.Help = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Omen", L["Help File"], "Omen", "Help")
self.optionsFrames.ShowWhen = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Omen", L["Show When..."], "Omen", "ShowWhen") -- The ordering here matters, it determines the order in the Blizzard Interface Options
self.optionsFrames.Bars = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Omen", L["Bar Settings"], "Omen", "Bars") self.optionsFrames.Omen = ACD3:AddToBlizOptions("Omen", nil, nil, "General")
self.optionsFrames.TitleBar = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Omen", L["Title Bar Settings"], "Omen", "TitleBar") self.optionsFrames.ShowWhen = ACD3:AddToBlizOptions("Omen", L["Show When..."], "Omen", "ShowWhen")
self:RegisterModuleOptions("Profiles", LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db), L["Profiles"]) self.optionsFrames.TitleBar = ACD3:AddToBlizOptions("Omen", L["Title Bar Settings"], "Omen", "TitleBar")
self.optionsFrames.Bars = ACD3:AddToBlizOptions("Omen", L["Bar Settings"], "Omen", "Bars")
self.optionsFrames.Warnings = ACD3:AddToBlizOptions("Omen", L["Warning Settings"], "Omen", "Warnings")
self:RegisterModuleOptions("OmenSlashCommand", optionsSlash, L["Slash Command"]) self:RegisterModuleOptions("OmenSlashCommand", optionsSlash, L["Slash Command"])
self:RegisterModuleOptions("Profiles", LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db), L["Profiles"])
self.optionsFrames.Help = ACD3:AddToBlizOptions("Omen", L["Help File"], "Omen", "Help")
-- Add ordering data to the option table generated by AceDBOptions-3.0
options.args.Profiles.order = -2
end end
function Omen:RegisterModuleOptions(name, optionTbl, displayName) function Omen:RegisterModuleOptions(name, optionTbl, displayName)
+2 -1
View File
@@ -8,7 +8,7 @@
## Notes-zhTW: 一個輕量級、有彈性、可監視多個目標的仇恨統計插件。 ## Notes-zhTW: 一個輕量級、有彈性、可監視多個目標的仇恨統計插件。
## Notes-koKR: 다중-대상에 대한 위협수준 미터기로 보여줍니다. ## Notes-koKR: 다중-대상에 대한 위협수준 미터기로 보여줍니다.
## Author: Xinhuan ## Author: Xinhuan
## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets ## OptionalDeps: Ace3, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibSink-2.0
## X-Category: Combat ## X-Category: Combat
## SavedVariables: Omen3DB ## SavedVariables: Omen3DB
@@ -26,6 +26,7 @@ Libs\AceTimer-3.0\AceTimer-3.0.xml
Libs\AceDBOptions-3.0\AceDBOptions-3.0.xml Libs\AceDBOptions-3.0\AceDBOptions-3.0.xml
Libs\LibSharedMedia-3.0\lib.xml Libs\LibSharedMedia-3.0\lib.xml
Libs\AceGUI-3.0-SharedMediaWidgets\widget.xml Libs\AceGUI-3.0-SharedMediaWidgets\widget.xml
Libs\LibSink-2.0\lib.xml
#@end-no-lib-strip@ #@end-no-lib-strip@
Localization\enUS.lua Localization\enUS.lua