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:
@@ -14,3 +14,4 @@ externals:
|
||||
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/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
@@ -4,6 +4,10 @@ if not L then return end
|
||||
|
||||
-- Main Omen window
|
||||
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
|
||||
L["General Settings"] = true
|
||||
@@ -120,7 +124,18 @@ L["Center Omen"] = true
|
||||
L["Configure"] = 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["Right-click|r to open the options menu"] = 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.
|
||||
]]
|
||||
|
||||
-- Slash command
|
||||
|
||||
BINDING_HEADER_OMEN = "Omen"
|
||||
BINDING_NAME_OMENTOGGLE = "Toggle Omen"
|
||||
|
||||
|
||||
|
||||
@@ -9,22 +9,27 @@
|
||||
LoadAddOn("Ace3")
|
||||
LoadAddOn("LibSharedMedia-3.0")
|
||||
LoadAddOn("AceGUI-3.0-SharedMediaWidgets")
|
||||
LoadAddOn("LibSink-2.0")
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- 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 LSM = LibStub("LibSharedMedia-3.0")
|
||||
_G["Omen"] = Omen
|
||||
|
||||
|
||||
-- TODO: Add TPS calculations
|
||||
-- TODO: Add visible/audible warnings
|
||||
-- TODO: Add Sink/SharedMedia stuff
|
||||
-- TODO: Code optimizations
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Keybinding globals
|
||||
BINDING_HEADER_OMEN = "Omen"
|
||||
BINDING_NAME_OMENTOGGLE = L["Toggle Omen"]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Register some media
|
||||
LSM:Register("sound", "Rubber Ducky", [[Sound\Doodad\Goblin_Lottery_Open01.wav]])
|
||||
@@ -122,6 +127,16 @@ local defaults = {
|
||||
HideMinimapButton = true,
|
||||
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"
|
||||
@@ -129,11 +144,13 @@ local guidClassLookup = {} -- Format: guidClassLookup[guid] = "CLASS"
|
||||
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 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.GuidClassLookup = guidClassLookup
|
||||
Omen.Timers = timers
|
||||
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
|
||||
r = 1,
|
||||
@@ -271,6 +288,7 @@ function Omen:OnInitialize()
|
||||
self.db.RegisterCallback(self, "OnProfileCopied", "OnProfileChanged")
|
||||
self.db.RegisterCallback(self, "OnProfileReset", "OnProfileChanged")
|
||||
db = self.db.profile
|
||||
self:SetSinkStorage(db.Warnings.SinkOptions)
|
||||
|
||||
self:CreateFrames()
|
||||
self:SetupOptions()
|
||||
@@ -278,9 +296,7 @@ function Omen:OnInitialize()
|
||||
self:UpdateBackdrop()
|
||||
self:UpdateTitleBar()
|
||||
|
||||
-- Register events that are "always on". The rest are in :OnEnable()
|
||||
self:RegisterEvent("PLAYER_LOGIN")
|
||||
self:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
end
|
||||
|
||||
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
|
||||
-- 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 DataBroker then
|
||||
local launcher = DataBroker:NewDataObject("Omen", {
|
||||
if LibStub("LibDataBroker-1.1", true) and not IsAddOnLoaded("Broker2FuBar") then
|
||||
local LDB = LibStub("LibDataBroker-1.1", true)
|
||||
local launcher = LDB:NewDataObject("Omen", {
|
||||
type = "launcher",
|
||||
icon = "Interface\\AddOns\\Omen\\icon",
|
||||
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
|
||||
-- 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.
|
||||
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")
|
||||
LibStub("AceAddon-3.0"):EmbedLibrary(self, "LibFuBarPlugin-3.0")
|
||||
self:SetFuBarOption("tooltipType", "GameTooltip")
|
||||
self:SetFuBarOption("hasNoColor", true)
|
||||
self:SetFuBarOption("cannotDetachTooltip", 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("defaultPosition", "RIGHT")
|
||||
self:SetFuBarOption("tooltipHiddenWhenEmpty", true)
|
||||
@@ -338,20 +354,21 @@ function Omen:OnEnable()
|
||||
self:RegisterEvent("UNIT_THREAT_LIST_UPDATE")
|
||||
self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE")
|
||||
self:RegisterEvent("PLAYER_TARGET_CHANGED")
|
||||
self:RegisterEvent("UNIT_PET")
|
||||
|
||||
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:PLAYER_TARGET_CHANGED()
|
||||
end
|
||||
|
||||
function Omen:Disable()
|
||||
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")
|
||||
|
||||
function Omen:OnDisable()
|
||||
-- Cancel all timers (well at least nil them all
|
||||
-- out in timers[], since AceTimer-3.0 cancels
|
||||
-- them all OnDisable anyway).
|
||||
@@ -456,7 +473,7 @@ function Omen:UpdateBackdrop()
|
||||
bgFrame.insets.bottom = inset
|
||||
self.Title:SetBackdrop(bgFrame)
|
||||
self.BarList:SetBackdrop(bgFrame)
|
||||
|
||||
|
||||
local c = db.Background.Color
|
||||
self.Title: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()
|
||||
if LibStub:GetLibrary("LibFuBarPlugin-3.0", true) then
|
||||
if self:IsFuBarMinimapAttached() ~= db.FuBar.AttachMinimap then
|
||||
self:ToggleFuBarMinimapAttached()
|
||||
if db.FuBar.HideMinimapButton then
|
||||
self:Hide()
|
||||
else
|
||||
self:Show()
|
||||
if self:IsFuBarMinimapAttached() ~= db.FuBar.AttachMinimap then
|
||||
self:ToggleFuBarMinimapAttached()
|
||||
end
|
||||
end
|
||||
if db.FuBar.HideMinimapButton then self:Hide() else self:Show() 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
|
||||
|
||||
@@ -539,7 +655,7 @@ do
|
||||
self:SetScript("OnUpdate", animate)
|
||||
end
|
||||
|
||||
-- Create bars on demand
|
||||
-- Create bars on demand
|
||||
setmetatable(bars, {__index = function(self, barID)
|
||||
local bar = CreateFrame("Frame", nil, Omen.BarList)
|
||||
self[barID] = bar
|
||||
@@ -640,17 +756,6 @@ function Omen:PLAYER_TARGET_CHANGED()
|
||||
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()
|
||||
|
||||
function Omen:PARTY_MEMBERS_CHANGED()
|
||||
@@ -679,7 +784,10 @@ function Omen:UpdatePartyGUIDs()
|
||||
for k, v in pairs(guidClassLookup) do
|
||||
guidClassLookup[k] = nil
|
||||
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
|
||||
guidClassLookup[UnitGUID("pet")] = "PET"
|
||||
guidNameLookup[UnitGUID("pet")] = UnitName("pet")--.." ["..UnitName("player").."]"
|
||||
@@ -689,15 +797,15 @@ function Omen:UpdatePartyGUIDs()
|
||||
local playerFmt = inRaid and rID or pID
|
||||
local petFmt = inRaid and rpID or ppID
|
||||
local currentPartySize = inRaid and GetNumRaidMembers() or GetNumPartyMembers()
|
||||
|
||||
|
||||
for i = 1, currentPartySize do
|
||||
local unitID = playerFmt[i]
|
||||
local pGUID = UnitGUID(unitID)
|
||||
|
||||
|
||||
if pGUID then
|
||||
guidNameLookup[pGUID] = UnitName(unitID)
|
||||
_, guidClassLookup[pGUID] = UnitClass(unitID)
|
||||
|
||||
|
||||
-- lookup pet (if existing)
|
||||
local petID = petFmt[i]
|
||||
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)
|
||||
|
||||
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 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 lastWarn = { -- Used to store information for threat warnings
|
||||
threatpercent = 0,
|
||||
}
|
||||
|
||||
local function sortfunction(a, b)
|
||||
return threatTable[a] > threatTable[b]
|
||||
@@ -768,84 +879,88 @@ end
|
||||
|
||||
function Omen:UpdateBars()
|
||||
if not self.Anchor:IsShown() and not db.CollapseHide then return end
|
||||
|
||||
|
||||
-- TODO: Put a update throtle on this function
|
||||
|
||||
-- Figure out which mob to show threat on, either "target" or "targettarget"
|
||||
-- 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])
|
||||
local mobGUID, mobTargetGUID
|
||||
|
||||
-- Schedule a repeating timer for updating threat on "targettarget"
|
||||
-- since we get no events on a targettarget change.
|
||||
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
|
||||
if testMode then
|
||||
for k, v in pairs(threatTable) do
|
||||
threatTable[k] = nil
|
||||
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)
|
||||
for i = 1, 25 do
|
||||
threatTable[i] = i*5000
|
||||
end
|
||||
tankGUID = 25
|
||||
self.TitleText:SetText(L["Test Mode"])
|
||||
else
|
||||
-- Figure out which mob to show threat on, either "target" or "targettarget"
|
||||
-- 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
|
||||
mobGUID = UnitGUID(mob)
|
||||
guidNameLookup[mobGUID] = UnitName(mob)
|
||||
self.TitleText:SetText(guidNameLookup[mobGUID])
|
||||
|
||||
-- This is for testing purposes
|
||||
--[[for k, v in pairs(threatTable) do
|
||||
threatTable[k] = nil
|
||||
-- Schedule a repeating timer for updating threat on "targettarget"
|
||||
-- since we get no events on a targettarget change.
|
||||
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
|
||||
for i = 1, 25 do
|
||||
threatTable[i] = i*5000
|
||||
end
|
||||
tankGUID = 25]]
|
||||
|
||||
-- Sort the threatTable
|
||||
local i = 1
|
||||
@@ -884,7 +999,7 @@ function Omen:UpdateBars()
|
||||
end
|
||||
local bar = bars[j]
|
||||
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
|
||||
bar.Text2:SetFormattedText("%2.1fk [%d%%]", threat / 100000, tankThreat == 0 and 0 or threat / tankThreat * 100)
|
||||
else
|
||||
@@ -912,6 +1027,22 @@ function Omen:UpdateBars()
|
||||
end
|
||||
self.Anchor: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
|
||||
|
||||
function Omen:ClearAll()
|
||||
@@ -926,6 +1057,8 @@ function Omen:ClearAll()
|
||||
self.Anchor:Hide()
|
||||
end
|
||||
end
|
||||
lastWarn.mobGUID = nil
|
||||
lastWarn.threatpercent = 0
|
||||
end
|
||||
|
||||
|
||||
@@ -942,16 +1075,18 @@ local function GetFuBarMinimapAttachedStatus(info)
|
||||
return Omen:IsFuBarMinimapAttached() or db.FuBar.HideMinimapButton
|
||||
end
|
||||
|
||||
-- Option table for the AceGUI config only
|
||||
local options = {
|
||||
type = "group",
|
||||
name = "Omen",
|
||||
get = function(info) return db[ info[#info] ] end,
|
||||
set = function(info, value) db[ info[#info] ] = value end,
|
||||
args = {
|
||||
general = {
|
||||
General = {
|
||||
order = 1,
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
desc = L["General Settings"],
|
||||
args = {
|
||||
intro = {
|
||||
order = 1,
|
||||
@@ -992,11 +1127,6 @@ local options = {
|
||||
if value then Omen.Grip:Hide() else Omen.Grip:Show() end
|
||||
end,
|
||||
},
|
||||
linebreak = {
|
||||
order = 9,
|
||||
type = "description",
|
||||
name = "",
|
||||
},
|
||||
Autocollapse = {
|
||||
type = "toggle",
|
||||
name = L["Autocollapse"],
|
||||
@@ -1136,6 +1266,7 @@ local options = {
|
||||
},
|
||||
},
|
||||
ShowWhen = {
|
||||
order = 2,
|
||||
type = "group",
|
||||
name = L["Show When..."],
|
||||
desc = L["Show Omen when..."],
|
||||
@@ -1189,6 +1320,7 @@ local options = {
|
||||
},
|
||||
},
|
||||
TitleBar = {
|
||||
order = 3,
|
||||
type = "group",
|
||||
name = L["Title Bar Settings"],
|
||||
desc = L["Title Bar Settings"],
|
||||
@@ -1258,6 +1390,7 @@ local options = {
|
||||
},
|
||||
},
|
||||
Bars = {
|
||||
order = 4,
|
||||
type = "group",
|
||||
name = 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 = {
|
||||
order = -4,
|
||||
type = "group",
|
||||
name = L["FuBar Options"],
|
||||
desc = L["FuBar Options"],
|
||||
hidden = function() return Omen.IsFuBarMinimapAttached == nil end,
|
||||
args = {
|
||||
attachMinimap = {
|
||||
hideIcon = {
|
||||
type = "toggle",
|
||||
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"],
|
||||
desc = L["Attach to minimap"],
|
||||
get = function(info) return Omen:IsFuBarMinimapAttached() end,
|
||||
@@ -1390,17 +1608,7 @@ local options = {
|
||||
Omen:ToggleFuBarMinimapAttached()
|
||||
db.FuBar.AttachMinimap = Omen:IsFuBarMinimapAttached()
|
||||
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,
|
||||
disabled = function() return db.FuBar.HideMinimapButton end,
|
||||
},
|
||||
showIcon = {
|
||||
type = "toggle",
|
||||
@@ -1438,6 +1646,7 @@ local options = {
|
||||
},
|
||||
Help = {
|
||||
type = "group",
|
||||
order = -1,
|
||||
name = L["Help File"],
|
||||
desc = L["A collection of help pages"],
|
||||
childGroups = "select",
|
||||
@@ -1479,10 +1688,15 @@ local 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 = {
|
||||
type = "group",
|
||||
name = L["Slash Command"],
|
||||
order = -3,
|
||||
args = {
|
||||
intro = {
|
||||
order = 1,
|
||||
@@ -1521,20 +1735,26 @@ local optionsSlash = {
|
||||
}
|
||||
Omen.OptionsSlash = optionsSlash
|
||||
|
||||
|
||||
function Omen:SetupOptions()
|
||||
self.optionsFrames = {}
|
||||
|
||||
|
||||
-- setup options table
|
||||
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Omen", options)
|
||||
LibStub("AceConfig-3.0"):RegisterOptionsTable("OmenSlashCommand", optionsSlash, "omen")
|
||||
self.optionsFrames.Omen = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Omen", nil, nil, "general")
|
||||
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")
|
||||
self.optionsFrames.Bars = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Omen", L["Bar Settings"], "Omen", "Bars")
|
||||
self.optionsFrames.TitleBar = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Omen", L["Title Bar Settings"], "Omen", "TitleBar")
|
||||
self:RegisterModuleOptions("Profiles", LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db), L["Profiles"])
|
||||
local ACD3 = LibStub("AceConfigDialog-3.0")
|
||||
|
||||
-- The ordering here matters, it determines the order in the Blizzard Interface Options
|
||||
self.optionsFrames.Omen = ACD3:AddToBlizOptions("Omen", nil, nil, "General")
|
||||
self.optionsFrames.ShowWhen = ACD3:AddToBlizOptions("Omen", L["Show When..."], "Omen", "ShowWhen")
|
||||
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("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
|
||||
|
||||
function Omen:RegisterModuleOptions(name, optionTbl, displayName)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
## Notes-zhTW: 一個輕量級、有彈性、可監視多個目標的仇恨統計插件。
|
||||
## Notes-koKR: 다중-대상에 대한 위협수준 미터기로 보여줍니다.
|
||||
## 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
|
||||
## SavedVariables: Omen3DB
|
||||
|
||||
@@ -26,6 +26,7 @@ Libs\AceTimer-3.0\AceTimer-3.0.xml
|
||||
Libs\AceDBOptions-3.0\AceDBOptions-3.0.xml
|
||||
Libs\LibSharedMedia-3.0\lib.xml
|
||||
Libs\AceGUI-3.0-SharedMediaWidgets\widget.xml
|
||||
Libs\LibSink-2.0\lib.xml
|
||||
#@end-no-lib-strip@
|
||||
|
||||
Localization\enUS.lua
|
||||
|
||||
Reference in New Issue
Block a user