initial commit
This commit is contained in:
1399
Modules/ActionBars/ActionBars.lua
Normal file
1399
Modules/ActionBars/ActionBars.lua
Normal file
File diff suppressed because it is too large
Load Diff
397
Modules/ActionBars/Bind.lua
Normal file
397
Modules/ActionBars/Bind.lua
Normal file
@@ -0,0 +1,397 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local AB = E:GetModule('ActionBars')
|
||||
local Skins = E:GetModule('Skins')
|
||||
|
||||
local _G = _G
|
||||
local tonumber, format = tonumber, format
|
||||
local select, pairs, floor = select, pairs, floor
|
||||
local CreateFrame = CreateFrame
|
||||
local HideUIPanel = HideUIPanel
|
||||
local GameTooltip_Hide = GameTooltip_Hide
|
||||
local GameTooltip_ShowCompareItem = GameTooltip_ShowCompareItem
|
||||
local GetBindingKey = GetBindingKey
|
||||
local GetCurrentBindingSet = GetCurrentBindingSet
|
||||
local GetMacroInfo = GetMacroInfo
|
||||
local GetSpellBookItemName = GetSpellBookItemName
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local IsAddOnLoaded = IsAddOnLoaded
|
||||
local IsAltKeyDown, IsControlKeyDown = IsAltKeyDown, IsControlKeyDown
|
||||
local IsShiftKeyDown, IsModifiedClick = IsShiftKeyDown, IsModifiedClick
|
||||
local LoadBindings, SaveBindings = LoadBindings, SaveBindings
|
||||
local SecureActionButton_OnClick = SecureActionButton_OnClick
|
||||
local SetBinding = SetBinding
|
||||
local GameTooltip = GameTooltip
|
||||
local SpellBook_GetSpellBookSlot = SpellBook_GetSpellBookSlot
|
||||
local MAX_ACCOUNT_MACROS = MAX_ACCOUNT_MACROS
|
||||
local CHARACTER_SPECIFIC_KEYBINDING_TOOLTIP = CHARACTER_SPECIFIC_KEYBINDING_TOOLTIP
|
||||
local CHARACTER_SPECIFIC_KEYBINDINGS = CHARACTER_SPECIFIC_KEYBINDINGS
|
||||
-- GLOBALS: ElvUIBindPopupWindow, ElvUIBindPopupWindowCheckButton
|
||||
|
||||
local bind = CreateFrame('Frame', 'ElvUI_KeyBinder', E.UIParent)
|
||||
|
||||
function AB:ActivateBindMode()
|
||||
if InCombatLockdown() then return end
|
||||
|
||||
bind.active = true
|
||||
E:StaticPopupSpecial_Show(ElvUIBindPopupWindow)
|
||||
AB:RegisterEvent('PLAYER_REGEN_DISABLED', 'DeactivateBindMode', false)
|
||||
end
|
||||
|
||||
function AB:DeactivateBindMode(save)
|
||||
if save then
|
||||
SaveBindings(GetCurrentBindingSet())
|
||||
E:Print(L["Binds Saved"])
|
||||
else
|
||||
LoadBindings(GetCurrentBindingSet())
|
||||
E:Print(L["Binds Discarded"])
|
||||
end
|
||||
|
||||
bind.active = false
|
||||
self:BindHide()
|
||||
self:UnregisterEvent('PLAYER_REGEN_DISABLED')
|
||||
E:StaticPopupSpecial_Hide(ElvUIBindPopupWindow)
|
||||
AB.bindingsChanged = false
|
||||
end
|
||||
|
||||
function AB:BindHide()
|
||||
bind:ClearAllPoints()
|
||||
bind:Hide()
|
||||
|
||||
if not _G.GameTooltip:IsForbidden() then
|
||||
_G.GameTooltip:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function AB:BindListener(key)
|
||||
AB.bindingsChanged = true
|
||||
if key == 'ESCAPE' then
|
||||
if bind.button.bindings then
|
||||
for i = 1, #bind.button.bindings do
|
||||
SetBinding(bind.button.bindings[i])
|
||||
end
|
||||
end
|
||||
|
||||
E:Print(format(L["All keybindings cleared for |cff00ff00%s|r."], bind.name))
|
||||
self:BindUpdate(bind.button, bind.spellmacro)
|
||||
|
||||
if bind.spellmacro~='MACRO' and not _G.GameTooltip:IsForbidden() then
|
||||
_G.GameTooltip:Hide()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
--Check if this button can open a flyout menu
|
||||
local isFlyout = (bind.button.FlyoutArrow and bind.button.FlyoutArrow:IsShown())
|
||||
|
||||
if key == 'LSHIFT' or key == 'RSHIFT' or key == 'LCTRL' or key == 'RCTRL'
|
||||
or key == 'LALT' or key == 'RALT' or key == 'UNKNOWN' then return end
|
||||
|
||||
--Redirect LeftButton click to open flyout
|
||||
if key == 'LeftButton' and isFlyout then
|
||||
SecureActionButton_OnClick(bind.button)
|
||||
end
|
||||
|
||||
if key == 'MiddleButton' then key = 'BUTTON3' end
|
||||
if key:find('Button%d') then key = key:upper() end
|
||||
|
||||
local allowBinding = not isFlyout or (key ~= 'LeftButton') --Don't attempt to bind left mouse button for flyout buttons
|
||||
if allowBinding and bind.button.bindstring then
|
||||
local alt = IsAltKeyDown() and 'ALT-' or ''
|
||||
local ctrl = IsControlKeyDown() and 'CTRL-' or ''
|
||||
local shift = IsShiftKeyDown() and 'SHIFT-' or ''
|
||||
|
||||
SetBinding(alt..ctrl..shift..key, bind.button.bindstring)
|
||||
E:Print(alt..ctrl..shift..key..L[" |cff00ff00bound to |r"]..bind.name..'.')
|
||||
end
|
||||
|
||||
self:BindUpdate(bind.button, bind.spellmacro)
|
||||
|
||||
if bind.spellmacro~='MACRO' and bind.spellmacro~='FLYOUT' and not _G.GameTooltip:IsForbidden() then
|
||||
_G.GameTooltip:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function AB:DisplayBindsTooltip()
|
||||
GameTooltip:SetOwner(bind, 'ANCHOR_TOP')
|
||||
GameTooltip:Point('BOTTOM', bind, 'TOP', 0, 1)
|
||||
GameTooltip:AddLine(bind.name, 1, 1, 1)
|
||||
end
|
||||
|
||||
function AB:DisplayBindings()
|
||||
if #bind.button.bindings == 0 then
|
||||
GameTooltip:AddLine(L["No bindings set."], .6, .6, .6)
|
||||
else
|
||||
GameTooltip:AddDoubleLine(L["Binding"], L["Key"], .6, .6, .6, .6, .6, .6)
|
||||
for i = 1, #bind.button.bindings do
|
||||
GameTooltip:AddDoubleLine(L["Binding"]..i, bind.button.bindings[i], 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:BindTooltip(triggerTooltip)
|
||||
if GameTooltip:IsForbidden() then return end
|
||||
|
||||
if triggerTooltip then -- this is needed for some tooltip magic, also it helps show a tooltip when a spell isnt there
|
||||
AB:DisplayBindsTooltip()
|
||||
GameTooltip:AddLine(L["Trigger"])
|
||||
|
||||
GameTooltip:Show()
|
||||
GameTooltip:SetScript('OnHide', function(tt)
|
||||
AB:DisplayBindsTooltip()
|
||||
AB:DisplayBindings()
|
||||
|
||||
tt:Show()
|
||||
tt:SetScript('OnHide', nil)
|
||||
end)
|
||||
else
|
||||
AB:DisplayBindsTooltip()
|
||||
AB:DisplayBindings()
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function AB:BindUpdate(button, spellmacro)
|
||||
if not bind.active or InCombatLockdown() then return end
|
||||
local triggerTooltip = false
|
||||
|
||||
bind.button = button
|
||||
bind.spellmacro = spellmacro
|
||||
bind.name = nil
|
||||
|
||||
bind:ClearAllPoints()
|
||||
bind:SetAllPoints(button)
|
||||
bind:Show()
|
||||
|
||||
_G.ShoppingTooltip1:Hide()
|
||||
|
||||
button.bindstring = nil -- keep this clean
|
||||
|
||||
if spellmacro == 'FLYOUT' then
|
||||
bind.name = button.spellName
|
||||
button.bindstring = spellmacro..' '..bind.name
|
||||
elseif spellmacro == 'SPELL' then
|
||||
button.id = SpellBook_GetSpellBookSlot(button)
|
||||
bind.name = GetSpellBookItemName(button.id, _G.SpellBookFrame.bookType)
|
||||
button.bindstring = spellmacro..' '..bind.name
|
||||
elseif spellmacro == 'MACRO' then
|
||||
button.id = button:GetID()
|
||||
|
||||
-- no clue what this is, leaving it alone tho lol
|
||||
if floor(.5+select(2,_G.MacroFrameTab1Text:GetTextColor())*10)/10==.8 then
|
||||
button.id = button.id + MAX_ACCOUNT_MACROS
|
||||
end
|
||||
|
||||
bind.name = GetMacroInfo(button.id)
|
||||
button.bindstring = spellmacro..' '..bind.name
|
||||
elseif spellmacro == 'MICRO' then
|
||||
bind.name = button.tooltipText
|
||||
button.bindstring = button.commandName
|
||||
triggerTooltip = true
|
||||
elseif spellmacro == 'BAG' then
|
||||
if button.itemID then
|
||||
bind.name = button.name
|
||||
button.bindstring = 'ITEM item:'..button.itemID
|
||||
triggerTooltip = true
|
||||
end
|
||||
else
|
||||
bind.name = button:GetName()
|
||||
if not bind.name then return end
|
||||
triggerTooltip = true
|
||||
|
||||
if button.keyBoundTarget then
|
||||
button.bindstring = button.keyBoundTarget
|
||||
elseif button.commandName then
|
||||
button.bindstring = button.commandName
|
||||
elseif button.action then
|
||||
local action = tonumber(button.action)
|
||||
local modact = 1+(action-1)%12
|
||||
if bind.name == 'ExtraActionButton1' then
|
||||
button.bindstring = 'EXTRAACTIONBUTTON1'
|
||||
elseif action < 25 or action > 72 then
|
||||
button.bindstring = 'ACTIONBUTTON'..modact
|
||||
elseif action < 73 and action > 60 then
|
||||
button.bindstring = 'MULTIACTIONBAR1BUTTON'..modact
|
||||
elseif action < 61 and action > 48 then
|
||||
button.bindstring = 'MULTIACTIONBAR2BUTTON'..modact
|
||||
elseif action < 49 and action > 36 then
|
||||
button.bindstring = 'MULTIACTIONBAR4BUTTON'..modact
|
||||
elseif action < 37 and action > 24 then
|
||||
button.bindstring = 'MULTIACTIONBAR3BUTTON'..modact
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if button.bindstring then
|
||||
button.bindings = {GetBindingKey(button.bindstring)}
|
||||
AB:BindTooltip(triggerTooltip)
|
||||
end
|
||||
end
|
||||
|
||||
local elapsed = 0
|
||||
function AB:Tooltip_OnUpdate(tooltip, e)
|
||||
if tooltip:IsForbidden() then return end
|
||||
|
||||
elapsed = elapsed + e
|
||||
if elapsed < .2 then return else elapsed = 0 end
|
||||
|
||||
local compareItems = IsModifiedClick('COMPAREITEMS')
|
||||
if not tooltip.comparing and compareItems and tooltip:GetItem() then
|
||||
GameTooltip_ShowCompareItem(tooltip)
|
||||
tooltip.comparing = true
|
||||
elseif tooltip.comparing and not compareItems then
|
||||
for _, frame in pairs(tooltip.shoppingTooltips) do frame:Hide() end
|
||||
tooltip.comparing = false
|
||||
end
|
||||
end
|
||||
|
||||
function AB:RegisterMacro(addon)
|
||||
if addon == 'Blizzard_MacroUI' then
|
||||
for i=1, MAX_ACCOUNT_MACROS do
|
||||
_G['MacroButton'..i]:HookScript('OnEnter', function(btn) AB:BindUpdate(btn, 'MACRO') end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:ChangeBindingProfile()
|
||||
if ElvUIBindPopupWindowCheckButton:GetChecked() then
|
||||
LoadBindings(2)
|
||||
SaveBindings(2)
|
||||
else
|
||||
LoadBindings(1)
|
||||
SaveBindings(1)
|
||||
end
|
||||
end
|
||||
|
||||
local function keybindButtonClick()
|
||||
if InCombatLockdown() then return end
|
||||
|
||||
AB:ActivateBindMode()
|
||||
|
||||
HideUIPanel(_G.KeyBindingFrame)
|
||||
HideUIPanel(_G.GameMenuFrame)
|
||||
end
|
||||
|
||||
function AB:SwapKeybindButton(event, addon)
|
||||
if event and addon ~= 'Blizzard_BindingUI' then return end
|
||||
|
||||
local parent = _G.KeyBindingFrame
|
||||
parent.quickKeybindButton:Hide()
|
||||
|
||||
local frame = CreateFrame('Button', 'ElvUI_KeybindButton', parent, 'OptionsButtonTemplate, BackdropTemplate')
|
||||
frame:Width(150)
|
||||
frame:Point('TOPLEFT', parent.quickKeybindButton)
|
||||
frame:SetScript('OnClick', keybindButtonClick)
|
||||
frame:SetText('ElvUI Keybind')
|
||||
|
||||
Skins:HandleButton(frame)
|
||||
end
|
||||
|
||||
function AB:LoadKeyBinder()
|
||||
bind:SetFrameStrata('DIALOG')
|
||||
bind:SetFrameLevel(99)
|
||||
bind:EnableMouse(true)
|
||||
bind:EnableKeyboard(true)
|
||||
bind:EnableMouseWheel(true)
|
||||
bind.texture = bind:CreateTexture()
|
||||
bind.texture:SetAllPoints(bind)
|
||||
bind.texture:SetColorTexture(0, 0, 0, .25)
|
||||
bind:Hide()
|
||||
|
||||
self:SecureHookScript(_G.GameTooltip, 'OnUpdate', 'Tooltip_OnUpdate')
|
||||
|
||||
bind:SetScript('OnEnter', function(b) local db = b.button:GetParent().db if db and db.mouseover then AB:Button_OnEnter(b.button) end end)
|
||||
bind:SetScript('OnLeave', function(b) AB:BindHide() local db = b.button:GetParent().db if db and db.mouseover then AB:Button_OnLeave(b.button) end end)
|
||||
bind:SetScript('OnKeyUp', function(_, key) self:BindListener(key) end)
|
||||
bind:SetScript('OnMouseUp', function(_, key) self:BindListener(key) end)
|
||||
bind:SetScript('OnMouseWheel', function(_, delta) if delta>0 then self:BindListener('MOUSEWHEELUP') else self:BindListener('MOUSEWHEELDOWN') end end)
|
||||
|
||||
for i = 1, 12 do
|
||||
local b = _G['SpellButton'..i]
|
||||
b:HookScript('OnEnter', function(s) AB:BindUpdate(s, 'SPELL') end)
|
||||
end
|
||||
|
||||
local function buttonOnEnter(b) AB:BindUpdate(b) end
|
||||
for b in pairs(self.handledbuttons) do
|
||||
if b:IsProtected() and b:IsObjectType('CheckButton') and not b.isFlyout then
|
||||
b:HookScript('OnEnter', buttonOnEnter)
|
||||
end
|
||||
end
|
||||
|
||||
if not IsAddOnLoaded('Blizzard_MacroUI') then
|
||||
self:SecureHook('LoadAddOn', 'RegisterMacro')
|
||||
else
|
||||
self:RegisterMacro('Blizzard_MacroUI')
|
||||
end
|
||||
|
||||
--Special Popup
|
||||
local Popup = CreateFrame('Frame', 'ElvUIBindPopupWindow', _G.UIParent, 'BackdropTemplate')
|
||||
Popup:SetFrameStrata('DIALOG')
|
||||
Popup:EnableMouse(true)
|
||||
Popup:SetMovable(true)
|
||||
Popup:SetFrameLevel(99)
|
||||
Popup:SetClampedToScreen(true)
|
||||
Popup:Size(360, 130)
|
||||
Popup:SetTemplate('Transparent')
|
||||
Popup:RegisterForDrag('AnyUp', 'AnyDown')
|
||||
Popup:SetScript('OnMouseDown', Popup.StartMoving)
|
||||
Popup:SetScript('OnMouseUp', Popup.StopMovingOrSizing)
|
||||
Popup:Hide()
|
||||
|
||||
Popup.header = CreateFrame('Button', nil, Popup, 'OptionsButtonTemplate, BackdropTemplate')
|
||||
Popup.header:Size(100, 25)
|
||||
Popup.header:Point('CENTER', Popup, 'TOP')
|
||||
Popup.header:RegisterForClicks('AnyUp', 'AnyDown')
|
||||
Popup.header:SetScript('OnMouseDown', function() Popup:StartMoving() end)
|
||||
Popup.header:SetScript('OnMouseUp', function() Popup:StopMovingOrSizing() end)
|
||||
Popup.header:SetText('Key Binds')
|
||||
|
||||
Popup.desc = Popup:CreateFontString(nil, 'ARTWORK')
|
||||
Popup.desc:SetFontObject('GameFontHighlight')
|
||||
Popup.desc:SetJustifyV('TOP')
|
||||
Popup.desc:SetJustifyH('LEFT')
|
||||
Popup.desc:Point('TOPLEFT', 18, -32)
|
||||
Popup.desc:Point('BOTTOMRIGHT', -18, 48)
|
||||
Popup.desc:SetText(L["Hover your mouse over any |cFF1784d1action|r, |cFF1784d1micro|r, |cFF1784d1macro|r, or |cFF1784d1spellbook|r button to bind it. This also works for items in your |cFF1784d1bag|r. Press the |cfd9b9b9bESC|r key to |cfd9b9b9bclear|r the current bindings."])
|
||||
|
||||
Popup.save = CreateFrame('Button', Popup:GetName()..'SaveButton', Popup, 'OptionsButtonTemplate, BackdropTemplate')
|
||||
Popup.save:SetText(L["Save"])
|
||||
Popup.save:Width(150)
|
||||
Popup.save:SetScript('OnClick', function() AB:DeactivateBindMode(true) end)
|
||||
|
||||
Popup.discard = CreateFrame('Button', Popup:GetName()..'DiscardButton', Popup, 'OptionsButtonTemplate, BackdropTemplate')
|
||||
Popup.discard:Width(150)
|
||||
Popup.discard:SetText(L["Discard"])
|
||||
Popup.discard:SetScript('OnClick', function() AB:DeactivateBindMode(false) end)
|
||||
|
||||
Popup.perCharCheck = CreateFrame('CheckButton', Popup:GetName()..'CheckButton', Popup, 'OptionsCheckButtonTemplate, BackdropTemplate')
|
||||
_G[Popup.perCharCheck:GetName()..'Text']:SetText(CHARACTER_SPECIFIC_KEYBINDINGS)
|
||||
Popup.perCharCheck:SetScript('OnLeave', GameTooltip_Hide)
|
||||
Popup.perCharCheck:SetScript('OnShow', function(checkBtn) checkBtn:SetChecked(GetCurrentBindingSet() == 2) end)
|
||||
Popup.perCharCheck:SetScript('OnClick', function()
|
||||
if AB.bindingsChanged then
|
||||
E:StaticPopup_Show('CONFIRM_LOSE_BINDING_CHANGES')
|
||||
else
|
||||
AB:ChangeBindingProfile()
|
||||
end
|
||||
end)
|
||||
|
||||
Popup.perCharCheck:SetScript('OnEnter', function(checkBtn)
|
||||
_G.GameTooltip:SetOwner(checkBtn, 'ANCHOR_RIGHT')
|
||||
_G.GameTooltip:SetText(CHARACTER_SPECIFIC_KEYBINDING_TOOLTIP, nil, nil, nil, nil, 1)
|
||||
end)
|
||||
|
||||
--position buttons
|
||||
Popup.perCharCheck:Point('BOTTOMLEFT', Popup.discard, 'TOPLEFT', 0, 2)
|
||||
Popup.save:Point('BOTTOMRIGHT', -14, 10)
|
||||
Popup.discard:Point('BOTTOMLEFT', 14, 10)
|
||||
|
||||
Skins:HandleCheckBox(Popup.perCharCheck)
|
||||
Skins:HandleButton(Popup.discard)
|
||||
Skins:HandleButton(Popup.header)
|
||||
Skins:HandleButton(Popup.save)
|
||||
|
||||
Popup.discard.backdrop:SetFrameLevel(Popup.discard:GetFrameLevel())
|
||||
Popup.header.backdrop:SetFrameLevel(Popup.header:GetFrameLevel())
|
||||
Popup.save.backdrop:SetFrameLevel(Popup.save:GetFrameLevel())
|
||||
end
|
||||
190
Modules/ActionBars/ExtraAB.lua
Normal file
190
Modules/ActionBars/ExtraAB.lua
Normal file
@@ -0,0 +1,190 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local AB = E:GetModule('ActionBars')
|
||||
|
||||
local _G = _G
|
||||
local pairs = pairs
|
||||
local unpack = unpack
|
||||
local tinsert = tinsert
|
||||
local CreateFrame = CreateFrame
|
||||
local GetBindingKey = GetBindingKey
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
|
||||
local ExtraActionBarHolder, ZoneAbilityHolder
|
||||
local ExtraButtons = {}
|
||||
|
||||
function AB:ExtraButtons_BossStyle(button)
|
||||
if not button.style then return end
|
||||
button.style:SetAlpha(not E.db.actionbar.extraActionButton.clean and E.db.actionbar.extraActionButton.alpha or 0)
|
||||
end
|
||||
|
||||
function AB:ExtraButtons_ZoneStyle()
|
||||
local zoneAlpha = E.db.actionbar.zoneActionButton.alpha
|
||||
_G.ZoneAbilityFrame.Style:SetAlpha(not E.db.actionbar.zoneActionButton.clean and zoneAlpha or 0)
|
||||
|
||||
for button in _G.ZoneAbilityFrame.SpellButtonContainer:EnumerateActive() do
|
||||
button:SetAlpha(zoneAlpha)
|
||||
end
|
||||
end
|
||||
|
||||
function AB:ExtraButtons_OnEnter()
|
||||
if self.holder and self.holder:GetParent() == AB.fadeParent and not AB.fadeParent.mouseLock then
|
||||
E:UIFrameFadeIn(AB.fadeParent, 0.2, AB.fadeParent:GetAlpha(), 1)
|
||||
end
|
||||
end
|
||||
|
||||
function AB:ExtraButtons_OnLeave()
|
||||
if self.holder and self.holder:GetParent() == AB.fadeParent and not AB.fadeParent.mouseLock then
|
||||
E:UIFrameFadeOut(AB.fadeParent, 0.2, AB.fadeParent:GetAlpha(), 1 - AB.db.globalFadeAlpha)
|
||||
end
|
||||
end
|
||||
|
||||
function AB:ExtraButtons_GlobalFade()
|
||||
ExtraActionBarHolder:SetParent(E.db.actionbar.extraActionButton.inheritGlobalFade and AB.fadeParent or E.UIParent)
|
||||
ZoneAbilityHolder:SetParent(E.db.actionbar.zoneActionButton.inheritGlobalFade and AB.fadeParent or E.UIParent)
|
||||
end
|
||||
|
||||
function AB:ExtraButtons_UpdateAlpha()
|
||||
if not E.private.actionbar.enable then return end
|
||||
local bossAlpha = E.db.actionbar.extraActionButton.alpha
|
||||
|
||||
for i = 1, _G.ExtraActionBarFrame:GetNumChildren() do
|
||||
local button = _G['ExtraActionButton'..i]
|
||||
if button then
|
||||
button:SetAlpha(bossAlpha)
|
||||
AB:ExtraButtons_BossStyle(button)
|
||||
end
|
||||
end
|
||||
|
||||
AB:ExtraButtons_ZoneStyle()
|
||||
end
|
||||
|
||||
function AB:ExtraButtons_UpdateScale()
|
||||
if not E.private.actionbar.enable then return end
|
||||
|
||||
AB:ExtraButtons_ZoneScale()
|
||||
|
||||
local scale = E.db.actionbar.extraActionButton.scale
|
||||
_G.ExtraActionBarFrame:SetScale(scale)
|
||||
|
||||
local width, height = _G.ExtraActionBarFrame.button:GetSize()
|
||||
ExtraActionBarHolder:SetSize(width * scale, height * scale)
|
||||
end
|
||||
|
||||
function AB:ExtraButtons_ZoneScale()
|
||||
if not E.private.actionbar.enable then return end
|
||||
|
||||
local scale = E.db.actionbar.zoneActionButton.scale
|
||||
_G.ZoneAbilityFrame.Style:SetScale(scale)
|
||||
_G.ZoneAbilityFrame.SpellButtonContainer:SetScale(scale)
|
||||
|
||||
local width, height = _G.ZoneAbilityFrame.SpellButtonContainer:GetSize()
|
||||
ZoneAbilityHolder:SetSize(width * scale, height * scale)
|
||||
end
|
||||
|
||||
function AB:SetupExtraButton()
|
||||
local ExtraActionBarFrame = _G.ExtraActionBarFrame
|
||||
local ZoneAbilityFrame = _G.ZoneAbilityFrame
|
||||
|
||||
ExtraActionBarHolder = CreateFrame('Frame', nil, E.UIParent)
|
||||
ExtraActionBarHolder:Point('BOTTOM', E.UIParent, 'BOTTOM', -150, 300)
|
||||
|
||||
ZoneAbilityHolder = CreateFrame('Frame', nil, E.UIParent)
|
||||
ZoneAbilityHolder:Point('BOTTOM', E.UIParent, 'BOTTOM', 150, 300)
|
||||
|
||||
ZoneAbilityFrame.SpellButtonContainer.holder = ZoneAbilityHolder
|
||||
ZoneAbilityFrame.SpellButtonContainer:HookScript('OnEnter', AB.ExtraButtons_OnEnter)
|
||||
ZoneAbilityFrame.SpellButtonContainer:HookScript('OnLeave', AB.ExtraButtons_OnLeave)
|
||||
|
||||
-- try to shutdown the container movement and taints
|
||||
_G.UIPARENT_MANAGED_FRAME_POSITIONS.ExtraAbilityContainer = nil
|
||||
_G.ExtraAbilityContainer.SetSize = E.noop
|
||||
|
||||
ZoneAbilityFrame:SetParent(ZoneAbilityHolder)
|
||||
ZoneAbilityFrame:ClearAllPoints()
|
||||
ZoneAbilityFrame:SetAllPoints()
|
||||
ZoneAbilityFrame.ignoreInLayout = true
|
||||
|
||||
ExtraActionBarFrame:SetParent(ExtraActionBarHolder)
|
||||
ExtraActionBarFrame:ClearAllPoints()
|
||||
ExtraActionBarFrame:SetAllPoints()
|
||||
ExtraActionBarFrame.ignoreInLayout = true
|
||||
|
||||
hooksecurefunc(ZoneAbilityFrame.SpellButtonContainer, 'SetSize', AB.ExtraButtons_ZoneScale)
|
||||
hooksecurefunc(ZoneAbilityFrame, 'UpdateDisplayedZoneAbilities', function(frame)
|
||||
AB:ExtraButtons_ZoneStyle()
|
||||
|
||||
for spellButton in frame.SpellButtonContainer:EnumerateActive() do
|
||||
if spellButton and not spellButton.IsSkinned then
|
||||
spellButton.NormalTexture:SetAlpha(0)
|
||||
spellButton:GetHighlightTexture():SetColorTexture(1, 1, 1, .25)
|
||||
spellButton:StyleButton(nil, true)
|
||||
spellButton:CreateBackdrop()
|
||||
spellButton.backdrop:SetAllPoints()
|
||||
spellButton.Icon:SetDrawLayer('ARTWORK')
|
||||
spellButton.Icon:SetTexCoord(unpack(E.TexCoords))
|
||||
spellButton.Icon:SetInside()
|
||||
|
||||
--check these
|
||||
--spellButton.HotKey:SetText(GetBindingKey(spellButton:GetName()))
|
||||
--tinsert(ExtraButtons, spellButton)
|
||||
|
||||
spellButton.holder = ZoneAbilityHolder
|
||||
spellButton:HookScript('OnEnter', AB.ExtraButtons_OnEnter)
|
||||
spellButton:HookScript('OnLeave', AB.ExtraButtons_OnLeave)
|
||||
|
||||
if spellButton.Cooldown then
|
||||
spellButton.Cooldown.CooldownOverride = 'actionbar'
|
||||
E:RegisterCooldown(spellButton.Cooldown)
|
||||
spellButton.Cooldown:SetInside(spellButton)
|
||||
end
|
||||
|
||||
spellButton.IsSkinned = true
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
for i = 1, ExtraActionBarFrame:GetNumChildren() do
|
||||
local button = _G['ExtraActionButton'..i]
|
||||
if button then
|
||||
button.pushed = true
|
||||
button.checked = true
|
||||
|
||||
self:StyleButton(button, true) -- registers cooldown too
|
||||
button.icon:SetDrawLayer('ARTWORK')
|
||||
button:CreateBackdrop()
|
||||
button.backdrop:SetAllPoints()
|
||||
button.backdrop:SetFrameLevel(button:GetFrameLevel())
|
||||
|
||||
AB:ExtraButtons_BossStyle(button)
|
||||
|
||||
button.holder = ExtraActionBarHolder
|
||||
button:HookScript('OnEnter', AB.ExtraButtons_OnEnter)
|
||||
button:HookScript('OnLeave', AB.ExtraButtons_OnLeave)
|
||||
|
||||
local tex = button:CreateTexture(nil, 'OVERLAY')
|
||||
tex:SetColorTexture(0.9, 0.8, 0.1, 0.3)
|
||||
tex:SetInside()
|
||||
button:SetCheckedTexture(tex)
|
||||
|
||||
button.HotKey:SetText(GetBindingKey('ExtraActionButton'..i))
|
||||
tinsert(ExtraButtons, button)
|
||||
end
|
||||
end
|
||||
|
||||
AB:ExtraButtons_UpdateAlpha()
|
||||
AB:ExtraButtons_UpdateScale()
|
||||
AB:ExtraButtons_GlobalFade()
|
||||
|
||||
E:CreateMover(ExtraActionBarHolder, 'BossButton', L["Boss Button"], nil, nil, nil, 'ALL,ACTIONBARS', nil, 'actionbar,extraActionButton')
|
||||
E:CreateMover(ZoneAbilityHolder, 'ZoneAbility', L["Zone Ability"], nil, nil, nil, 'ALL,ACTIONBARS')
|
||||
|
||||
-- Spawn the mover before its available.
|
||||
ZoneAbilityHolder:Size(52 * E.db.actionbar.zoneActionButton.scale)
|
||||
end
|
||||
|
||||
function AB:UpdateExtraBindings()
|
||||
for _, button in pairs(ExtraButtons) do
|
||||
button.HotKey:SetText(_G.GetBindingKey(button:GetName()))
|
||||
AB:FixKeybindText(button)
|
||||
end
|
||||
end
|
||||
8
Modules/ActionBars/Load_ActionBars.xml
Normal file
8
Modules/ActionBars/Load_ActionBars.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='ActionBars.lua'/>
|
||||
<Script file='ExtraAB.lua'/>
|
||||
<Script file='PetBar.lua'/>
|
||||
<Script file='StanceBar.lua'/>
|
||||
<Script file='Bind.lua'/>
|
||||
<Script file='MicroBar.lua'/>
|
||||
</Ui>
|
||||
219
Modules/ActionBars/MicroBar.lua
Normal file
219
Modules/ActionBars/MicroBar.lua
Normal file
@@ -0,0 +1,219 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local AB = E:GetModule('ActionBars')
|
||||
|
||||
local _G = _G
|
||||
local gsub = gsub
|
||||
local pairs = pairs
|
||||
local assert = assert
|
||||
local unpack = unpack
|
||||
local CreateFrame = CreateFrame
|
||||
local C_StorePublic_IsEnabled = C_StorePublic.IsEnabled
|
||||
local UpdateMicroButtonsParent = UpdateMicroButtonsParent
|
||||
local GetCurrentRegionName = GetCurrentRegionName
|
||||
local RegisterStateDriver = RegisterStateDriver
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
|
||||
local microBar = CreateFrame('Frame', 'ElvUI_MicroBar', E.UIParent)
|
||||
microBar:SetSize(100, 100)
|
||||
|
||||
local function onLeaveBar()
|
||||
if AB.db.microbar.mouseover then
|
||||
E:UIFrameFadeOut(microBar, 0.2, microBar:GetAlpha(), 0)
|
||||
end
|
||||
end
|
||||
|
||||
local watcher = 0
|
||||
local function onUpdate(self, elapsed)
|
||||
if watcher > 0.1 then
|
||||
if not self:IsMouseOver() then
|
||||
self.IsMouseOvered = nil
|
||||
self:SetScript('OnUpdate', nil)
|
||||
onLeaveBar()
|
||||
end
|
||||
watcher = 0
|
||||
else
|
||||
watcher = watcher + elapsed
|
||||
end
|
||||
end
|
||||
|
||||
local function onEnter(button)
|
||||
if AB.db.microbar.mouseover and not microBar.IsMouseOvered then
|
||||
microBar.IsMouseOvered = true
|
||||
microBar:SetScript('OnUpdate', onUpdate)
|
||||
E:UIFrameFadeIn(microBar, 0.2, microBar:GetAlpha(), AB.db.microbar.alpha)
|
||||
end
|
||||
|
||||
if button.backdrop and button:IsEnabled() then
|
||||
button.backdrop:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor))
|
||||
end
|
||||
|
||||
-- bag keybind support from actionbar module
|
||||
if E.private.actionbar.enable then
|
||||
AB:BindUpdate(button, 'MICRO')
|
||||
end
|
||||
end
|
||||
|
||||
local function onLeave(button)
|
||||
if button.backdrop and button:IsEnabled() then
|
||||
button.backdrop:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
||||
end
|
||||
end
|
||||
|
||||
function AB:HandleMicroButton(button)
|
||||
assert(button, 'Invalid micro button name.')
|
||||
|
||||
local pushed = button:GetPushedTexture()
|
||||
local normal = button:GetNormalTexture()
|
||||
local disabled = button:GetDisabledTexture()
|
||||
|
||||
button:CreateBackdrop()
|
||||
button.backdrop:SetAllPoints()
|
||||
|
||||
button:SetParent(microBar)
|
||||
button:GetHighlightTexture():Kill()
|
||||
button:HookScript('OnEnter', onEnter)
|
||||
button:HookScript('OnLeave', onLeave)
|
||||
button:SetHitRectInsets(0, 0, 0, 0)
|
||||
|
||||
if button.Flash then
|
||||
button.Flash:SetInside()
|
||||
button.Flash:SetTexture()
|
||||
end
|
||||
|
||||
pushed:SetTexCoord(0.22, 0.81, 0.26, 0.82)
|
||||
pushed:SetInside(button.backdrop)
|
||||
|
||||
normal:SetTexCoord(0.22, 0.81, 0.21, 0.82)
|
||||
normal:SetInside(button.backdrop)
|
||||
|
||||
if disabled then
|
||||
disabled:SetTexCoord(0.22, 0.81, 0.21, 0.82)
|
||||
disabled:SetInside(button.backdrop)
|
||||
end
|
||||
end
|
||||
|
||||
function AB:MainMenuMicroButton_SetNormal()
|
||||
_G.MainMenuBarPerformanceBar:Point('TOPLEFT', _G.MainMenuMicroButton, 'TOPLEFT', 9, -36)
|
||||
end
|
||||
|
||||
function AB:MainMenuMicroButton_SetPushed()
|
||||
_G.MainMenuBarPerformanceBar:Point('TOPLEFT', _G.MainMenuMicroButton, 'TOPLEFT', 8, -37)
|
||||
end
|
||||
|
||||
function AB:UpdateMicroButtonsParent()
|
||||
for _, x in pairs(_G.MICRO_BUTTONS) do
|
||||
_G[x]:SetParent(microBar)
|
||||
end
|
||||
end
|
||||
|
||||
-- we use this table to sort the micro buttons on our bar to match Blizzard's button placements.
|
||||
local __buttonIndex = {
|
||||
[8] = 'CollectionsMicroButton',
|
||||
[9] = 'EJMicroButton',
|
||||
[10] = (not C_StorePublic_IsEnabled() and GetCurrentRegionName() == 'CN') and 'HelpMicroButton' or 'StoreMicroButton',
|
||||
[11] = 'MainMenuMicroButton'
|
||||
}
|
||||
|
||||
function AB:UpdateMicroBarVisibility()
|
||||
if InCombatLockdown() then
|
||||
AB.NeedsUpdateMicroBarVisibility = true
|
||||
AB:RegisterEvent('PLAYER_REGEN_ENABLED')
|
||||
return
|
||||
end
|
||||
|
||||
local visibility = AB.db.microbar.visibility
|
||||
visibility = gsub(visibility, '[\n\r]','')
|
||||
|
||||
RegisterStateDriver(microBar.visibility, 'visibility', (AB.db.microbar.enabled and visibility) or 'hide')
|
||||
end
|
||||
|
||||
function AB:UpdateMicroPositionDimensions()
|
||||
local db = AB.db.microbar
|
||||
microBar.db = db
|
||||
|
||||
microBar.backdrop:SetShown(db.backdrop)
|
||||
microBar.backdrop:ClearAllPoints()
|
||||
|
||||
AB:MoverMagic(microBar)
|
||||
|
||||
db.buttons = #_G.MICRO_BUTTONS-1
|
||||
|
||||
local backdropSpacing = db.backdropSpacing
|
||||
|
||||
local _, horizontal, anchorUp, anchorLeft = AB:GetGrowth(db.point)
|
||||
local lastButton, anchorRowButton = microBar
|
||||
for i = 1, #_G.MICRO_BUTTONS-1 do
|
||||
local button = _G[__buttonIndex[i]] or _G[_G.MICRO_BUTTONS[i]]
|
||||
local lastColumnButton = i - db.buttonsPerRow
|
||||
lastColumnButton = _G[__buttonIndex[lastColumnButton]] or _G[_G.MICRO_BUTTONS[lastColumnButton]]
|
||||
button.db = db
|
||||
|
||||
if i == 1 or i == db.buttonsPerRow then
|
||||
anchorRowButton = button
|
||||
end
|
||||
|
||||
button.handleBackdrop = true -- keep over HandleButton
|
||||
AB:HandleButton(microBar, button, i, lastButton, lastColumnButton)
|
||||
|
||||
lastButton = button
|
||||
end
|
||||
|
||||
microBar:SetAlpha((db.mouseover and not microBar.IsMouseOvered and 0) or db.alpha)
|
||||
|
||||
AB:HandleBackdropMultiplier(microBar, backdropSpacing, db.buttonSpacing, db.widthMult, db.heightMult, anchorUp, anchorLeft, horizontal, lastButton, anchorRowButton)
|
||||
AB:HandleBackdropMover(microBar, backdropSpacing)
|
||||
|
||||
if microBar.mover then
|
||||
if AB.db.microbar.enabled then
|
||||
E:EnableMover(microBar.mover:GetName())
|
||||
else
|
||||
E:DisableMover(microBar.mover:GetName())
|
||||
end
|
||||
end
|
||||
|
||||
AB:UpdateMicroBarVisibility()
|
||||
end
|
||||
|
||||
function AB:UpdateMicroButtons()
|
||||
local GuildMicroButton = _G.GuildMicroButton
|
||||
local GuildMicroButtonTabard = _G.GuildMicroButtonTabard
|
||||
GuildMicroButtonTabard:SetInside(GuildMicroButton)
|
||||
GuildMicroButtonTabard.background:SetInside(GuildMicroButton)
|
||||
GuildMicroButtonTabard.background:SetTexCoord(0.17, 0.87, 0.5, 0.908)
|
||||
GuildMicroButtonTabard.emblem:ClearAllPoints()
|
||||
GuildMicroButtonTabard.emblem:Point('TOPLEFT', GuildMicroButton, 'TOPLEFT', 4, -4)
|
||||
GuildMicroButtonTabard.emblem:Point('BOTTOMRIGHT', GuildMicroButton, 'BOTTOMRIGHT', -4, 8)
|
||||
|
||||
AB:UpdateMicroPositionDimensions()
|
||||
end
|
||||
|
||||
function AB:SetupMicroBar()
|
||||
microBar:CreateBackdrop(AB.db.transparent and 'Transparent')
|
||||
microBar.backdrop:SetFrameLevel(0)
|
||||
|
||||
microBar:Point('TOPLEFT', E.UIParent, 'TOPLEFT', 4, -48)
|
||||
microBar:EnableMouse(false)
|
||||
|
||||
microBar.visibility = CreateFrame('Frame', nil, E.UIParent, 'SecureHandlerStateTemplate')
|
||||
microBar.visibility:SetScript('OnShow', function() microBar:Show() end)
|
||||
microBar.visibility:SetScript('OnHide', function() microBar:Hide() end)
|
||||
|
||||
for _, x in pairs(_G.MICRO_BUTTONS) do
|
||||
AB:HandleMicroButton(_G[x])
|
||||
end
|
||||
|
||||
_G.MicroButtonPortrait:SetInside(_G.CharacterMicroButton.backdrop)
|
||||
|
||||
AB:SecureHook('UpdateMicroButtonsParent')
|
||||
AB:SecureHook('MoveMicroButtons', 'UpdateMicroPositionDimensions')
|
||||
AB:SecureHook('UpdateMicroButtons')
|
||||
UpdateMicroButtonsParent(microBar)
|
||||
AB:MainMenuMicroButton_SetNormal()
|
||||
AB:UpdateMicroPositionDimensions()
|
||||
|
||||
-- With this method we might don't taint anything. Instead of using :Kill()
|
||||
_G.MainMenuBarPerformanceBar:SetAlpha(0)
|
||||
_G.MainMenuBarPerformanceBar:SetScale(0.00001)
|
||||
|
||||
E:CreateMover(microBar, 'MicrobarMover', L["Micro Bar"], nil, nil, nil, 'ALL,ACTIONBARS', nil, 'actionbar,microbar')
|
||||
end
|
||||
258
Modules/ActionBars/PetBar.lua
Normal file
258
Modules/ActionBars/PetBar.lua
Normal file
@@ -0,0 +1,258 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local AB = E:GetModule('ActionBars')
|
||||
|
||||
local _G = _G
|
||||
local gsub = gsub
|
||||
local ipairs = ipairs
|
||||
local CreateFrame = CreateFrame
|
||||
local RegisterStateDriver = RegisterStateDriver
|
||||
local GetBindingKey = GetBindingKey
|
||||
local PetHasActionBar = PetHasActionBar
|
||||
local GetPetActionInfo = GetPetActionInfo
|
||||
local IsPetAttackAction = IsPetAttackAction
|
||||
local PetActionButton_StartFlash = PetActionButton_StartFlash
|
||||
local PetActionButton_StopFlash = PetActionButton_StopFlash
|
||||
local AutoCastShine_AutoCastStart = AutoCastShine_AutoCastStart
|
||||
local AutoCastShine_AutoCastStop = AutoCastShine_AutoCastStop
|
||||
local PetActionBar_ShowGrid = PetActionBar_ShowGrid
|
||||
local PetActionBar_UpdateCooldowns = PetActionBar_UpdateCooldowns
|
||||
local NUM_PET_ACTION_SLOTS = NUM_PET_ACTION_SLOTS
|
||||
|
||||
local Masque = E.Masque
|
||||
local MasqueGroup = Masque and Masque:Group('ElvUI', 'Pet Bar')
|
||||
|
||||
local bar = CreateFrame('Frame', 'ElvUI_BarPet', E.UIParent, 'SecureHandlerStateTemplate')
|
||||
bar:SetFrameStrata('LOW')
|
||||
bar.buttons = {}
|
||||
|
||||
function AB:UpdatePet(event, unit)
|
||||
if event == 'UNIT_AURA' and unit ~= 'pet' then return end
|
||||
|
||||
for i = 1, NUM_PET_ACTION_SLOTS, 1 do
|
||||
local name, texture, isToken, isActive, autoCastAllowed, autoCastEnabled, spellID = GetPetActionInfo(i)
|
||||
local buttonName = 'PetActionButton'..i
|
||||
local autoCast = _G[buttonName..'AutoCastable']
|
||||
local button = _G[buttonName]
|
||||
|
||||
button:SetAlpha(1)
|
||||
button.isToken = isToken
|
||||
button.icon:Show()
|
||||
if not isToken then
|
||||
button.icon:SetTexture(texture)
|
||||
button.tooltipName = name
|
||||
else
|
||||
button.icon:SetTexture(_G[texture])
|
||||
button.tooltipName = _G[name]
|
||||
end
|
||||
|
||||
if spellID then
|
||||
local spell = _G.Spell:CreateFromSpellID(spellID)
|
||||
button.spellDataLoadedCancelFunc = spell:ContinueWithCancelOnSpellLoad(function()
|
||||
button.tooltipSubtext = spell:GetSpellSubtext()
|
||||
end)
|
||||
end
|
||||
|
||||
if isActive and name ~= 'PET_ACTION_FOLLOW' then
|
||||
button:SetChecked(true)
|
||||
|
||||
if IsPetAttackAction(i) then
|
||||
PetActionButton_StartFlash(button)
|
||||
end
|
||||
else
|
||||
button:SetChecked(false)
|
||||
|
||||
if IsPetAttackAction(i) then
|
||||
PetActionButton_StopFlash(button)
|
||||
end
|
||||
end
|
||||
|
||||
if autoCastAllowed then
|
||||
autoCast:Show()
|
||||
else
|
||||
autoCast:Hide()
|
||||
end
|
||||
|
||||
if autoCastEnabled then
|
||||
AutoCastShine_AutoCastStart(button.AutoCastShine)
|
||||
else
|
||||
AutoCastShine_AutoCastStop(button.AutoCastShine)
|
||||
end
|
||||
|
||||
if not PetHasActionBar() and texture and name ~= 'PET_ACTION_FOLLOW' then
|
||||
PetActionButton_StopFlash(button)
|
||||
button.icon:SetDesaturation(true)
|
||||
button:SetChecked(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:PositionAndSizeBarPet()
|
||||
local db = AB.db.barPet
|
||||
|
||||
local buttonSpacing = db.buttonspacing
|
||||
local backdropSpacing = db.backdropSpacing
|
||||
local buttonsPerRow = db.buttonsPerRow
|
||||
local numButtons = db.buttons
|
||||
local buttonWidth = db.buttonsize
|
||||
local buttonHeight = db.keepSizeRatio and db.buttonsize or db.buttonHeight
|
||||
local point = db.point
|
||||
local visibility = db.visibility
|
||||
|
||||
local autoCastWidth = (buttonWidth / 2) - (buttonWidth / 7.5)
|
||||
local autoCastHeight = (buttonHeight / 2) - (buttonHeight / 7.5)
|
||||
|
||||
bar.db = db
|
||||
bar.mouseover = db.mouseover
|
||||
|
||||
if numButtons < buttonsPerRow then buttonsPerRow = numButtons end
|
||||
|
||||
if db.enabled then
|
||||
bar:SetScale(1)
|
||||
bar:SetAlpha(bar.db.alpha)
|
||||
E:EnableMover(bar.mover:GetName())
|
||||
else
|
||||
bar:SetScale(0.0001)
|
||||
bar:SetAlpha(0)
|
||||
E:DisableMover(bar.mover:GetName())
|
||||
end
|
||||
|
||||
bar:SetParent(db.inheritGlobalFade and AB.fadeParent or E.UIParent)
|
||||
bar:EnableMouse(not db.clickThrough)
|
||||
bar:SetAlpha(bar.mouseover and 0 or db.alpha)
|
||||
AB:FadeBarBlings(bar, bar.mouseover and 0 or db.alpha)
|
||||
|
||||
bar.backdrop:SetShown(db.backdrop)
|
||||
bar.backdrop:ClearAllPoints()
|
||||
|
||||
AB:MoverMagic(bar)
|
||||
|
||||
local _, horizontal, anchorUp, anchorLeft = AB:GetGrowth(point)
|
||||
local button, lastButton, lastColumnButton, anchorRowButton, lastShownButton, autoCast
|
||||
|
||||
for i = 1, NUM_PET_ACTION_SLOTS do
|
||||
button = _G['PetActionButton'..i]
|
||||
lastButton = _G['PetActionButton'..i-1]
|
||||
autoCast = _G['PetActionButton'..i..'AutoCastable']
|
||||
lastColumnButton = _G['PetActionButton'..i-buttonsPerRow]
|
||||
button.db = db
|
||||
|
||||
bar.buttons[i] = button
|
||||
|
||||
if i == 1 or i == buttonsPerRow then
|
||||
anchorRowButton = button
|
||||
end
|
||||
|
||||
if i > numButtons then
|
||||
button:SetScale(0.0001)
|
||||
button:SetAlpha(0)
|
||||
button.handleBackdrop = nil
|
||||
else
|
||||
button:SetScale(1)
|
||||
button:SetAlpha(bar.db.alpha)
|
||||
lastShownButton = button
|
||||
button.handleBackdrop = true -- keep over HandleButton
|
||||
end
|
||||
|
||||
autoCast:SetOutside(button, autoCastWidth, autoCastHeight)
|
||||
AB:HandleButton(bar, button, i, lastButton, lastColumnButton)
|
||||
AB:StyleButton(button, nil, MasqueGroup and E.private.actionbar.masque.petBar)
|
||||
end
|
||||
|
||||
AB:HandleBackdropMultiplier(bar, backdropSpacing, buttonSpacing, db.widthMult, db.heightMult, anchorUp, anchorLeft, horizontal, lastShownButton, anchorRowButton)
|
||||
AB:HandleBackdropMover(bar, backdropSpacing)
|
||||
|
||||
visibility = gsub(visibility, '[\n\r]','')
|
||||
RegisterStateDriver(bar, 'show', visibility)
|
||||
|
||||
if MasqueGroup and E.private.actionbar.masque.petBar then
|
||||
MasqueGroup:ReSkin()
|
||||
|
||||
for _, btn in ipairs(bar.buttons) do
|
||||
AB:TrimIcon(btn, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:UpdatePetCooldownSettings()
|
||||
for i = 1, NUM_PET_ACTION_SLOTS do
|
||||
local button = _G['PetActionButton'..i]
|
||||
if button and button.cooldown then
|
||||
button.cooldown:SetDrawBling(not AB.db.hideCooldownBling)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:UpdatePetBindings()
|
||||
for i = 1, NUM_PET_ACTION_SLOTS do
|
||||
if AB.db.hotkeytext then
|
||||
local key = GetBindingKey('BONUSACTIONBUTTON'..i)
|
||||
_G['PetActionButton'..i..'HotKey']:Show()
|
||||
_G['PetActionButton'..i..'HotKey']:SetText(key)
|
||||
AB:FixKeybindText(_G['PetActionButton'..i])
|
||||
else
|
||||
_G['PetActionButton'..i..'HotKey']:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:CreateBarPet()
|
||||
bar.backdrop = CreateFrame('Frame', nil, bar, 'BackdropTemplate')
|
||||
bar.backdrop:SetTemplate(AB.db.transparent and 'Transparent')
|
||||
bar.backdrop:SetFrameLevel(0)
|
||||
|
||||
if AB.db.bar4.enabled then
|
||||
bar:Point('RIGHT', _G.ElvUI_Bar4, 'LEFT', -4, 0)
|
||||
else
|
||||
bar:Point('RIGHT', E.UIParent, 'RIGHT', -4, 0)
|
||||
end
|
||||
|
||||
bar:SetAttribute('_onstate-show', [[
|
||||
if newstate == 'hide' then
|
||||
self:Hide()
|
||||
else
|
||||
self:Show()
|
||||
end
|
||||
]])
|
||||
|
||||
bar:SetScript('OnHide', function()
|
||||
for i = 1, NUM_PET_ACTION_SLOTS, 1 do
|
||||
local button = _G['PetActionButton'..i]
|
||||
if button.spellDataLoadedCancelFunc then
|
||||
button.spellDataLoadedCancelFunc()
|
||||
button.spellDataLoadedCancelFunc = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
_G.PetActionBarFrame.showgrid = 1
|
||||
PetActionBar_ShowGrid()
|
||||
|
||||
AB:RegisterEvent('PET_BAR_UPDATE', 'UpdatePet')
|
||||
AB:RegisterEvent('PLAYER_CONTROL_GAINED', 'UpdatePet')
|
||||
AB:RegisterEvent('PLAYER_CONTROL_LOST', 'UpdatePet')
|
||||
AB:RegisterEvent('PLAYER_ENTERING_WORLD', 'UpdatePet')
|
||||
AB:RegisterEvent('PLAYER_FARSIGHT_FOCUS_CHANGED', 'UpdatePet')
|
||||
AB:RegisterEvent('SPELLS_CHANGED', 'UpdatePet')
|
||||
AB:RegisterEvent('UNIT_FLAGS', 'UpdatePet')
|
||||
AB:RegisterEvent('UNIT_PET', 'UpdatePet')
|
||||
AB:RegisterEvent('PET_BAR_UPDATE_COOLDOWN', PetActionBar_UpdateCooldowns)
|
||||
|
||||
E:CreateMover(bar, 'PetAB', L["Pet Bar"], nil, nil, nil, 'ALL,ACTIONBARS', nil, 'actionbar,barPet')
|
||||
|
||||
AB:PositionAndSizeBarPet()
|
||||
AB:UpdatePetBindings()
|
||||
|
||||
AB:HookScript(bar, 'OnEnter', 'Bar_OnEnter')
|
||||
AB:HookScript(bar, 'OnLeave', 'Bar_OnLeave')
|
||||
|
||||
for i = 1, NUM_PET_ACTION_SLOTS do
|
||||
local button = _G['PetActionButton'..i]
|
||||
|
||||
AB:HookScript(button, 'OnEnter', 'Button_OnEnter')
|
||||
AB:HookScript(button, 'OnLeave', 'Button_OnLeave')
|
||||
|
||||
if MasqueGroup and E.private.actionbar.masque.petBar then
|
||||
MasqueGroup:AddButton(button)
|
||||
end
|
||||
end
|
||||
end
|
||||
270
Modules/ActionBars/StanceBar.lua
Normal file
270
Modules/ActionBars/StanceBar.lua
Normal file
@@ -0,0 +1,270 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local AB = E:GetModule('ActionBars')
|
||||
|
||||
local _G = _G
|
||||
local gsub = gsub
|
||||
local format, ipairs = format, ipairs
|
||||
local CooldownFrame_Set = CooldownFrame_Set
|
||||
local CreateFrame = CreateFrame
|
||||
local GetBindingKey = GetBindingKey
|
||||
local GetNumShapeshiftForms = GetNumShapeshiftForms
|
||||
local GetShapeshiftForm = GetShapeshiftForm
|
||||
local GetShapeshiftFormCooldown = GetShapeshiftFormCooldown
|
||||
local GetShapeshiftFormInfo = GetShapeshiftFormInfo
|
||||
local GetSpellInfo = GetSpellInfo
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local RegisterStateDriver = RegisterStateDriver
|
||||
local NUM_STANCE_SLOTS = NUM_STANCE_SLOTS
|
||||
|
||||
local Masque = E.Masque
|
||||
local MasqueGroup = Masque and Masque:Group('ElvUI', 'Stance Bar')
|
||||
local WispSplode = [[Interface\Icons\Spell_Nature_WispSplode]]
|
||||
local bar = CreateFrame('Frame', 'ElvUI_StanceBar', E.UIParent, 'SecureHandlerStateTemplate')
|
||||
bar.buttons = {}
|
||||
|
||||
function AB:UPDATE_SHAPESHIFT_COOLDOWN()
|
||||
local numForms = GetNumShapeshiftForms()
|
||||
local start, duration, enable, cooldown
|
||||
for i = 1, NUM_STANCE_SLOTS do
|
||||
if i <= numForms then
|
||||
cooldown = _G['ElvUI_StanceBarButton'..i..'Cooldown']
|
||||
start, duration, enable = GetShapeshiftFormCooldown(i)
|
||||
CooldownFrame_Set(cooldown, start, duration, enable)
|
||||
cooldown:SetDrawBling(cooldown:GetEffectiveAlpha() > 0.5) --Cooldown Bling Fix
|
||||
end
|
||||
end
|
||||
|
||||
AB:StyleShapeShift('UPDATE_SHAPESHIFT_COOLDOWN')
|
||||
end
|
||||
|
||||
function AB:StyleShapeShift()
|
||||
local numForms = GetNumShapeshiftForms()
|
||||
local stance = GetShapeshiftForm()
|
||||
local darkenInactive = AB.db.stanceBar.style == 'darkenInactive'
|
||||
|
||||
for i = 1, NUM_STANCE_SLOTS do
|
||||
local buttonName = 'ElvUI_StanceBarButton'..i
|
||||
local button = _G[buttonName]
|
||||
local cooldown = _G[buttonName..'Cooldown']
|
||||
|
||||
if i <= numForms then
|
||||
local texture, isActive, isCastable, spellID, _ = GetShapeshiftFormInfo(i)
|
||||
|
||||
if darkenInactive then
|
||||
_, _, texture = GetSpellInfo(spellID)
|
||||
end
|
||||
|
||||
if not texture then texture = WispSplode end
|
||||
|
||||
button.icon:SetTexture(texture)
|
||||
|
||||
if not button.useMasque then
|
||||
cooldown:SetAlpha(1)
|
||||
|
||||
if isActive then
|
||||
_G.StanceBarFrame.lastSelected = button:GetID()
|
||||
if numForms == 1 then
|
||||
button.checked:SetColorTexture(1, 1, 1, 0.5)
|
||||
button:SetChecked(true)
|
||||
else
|
||||
button.checked:SetColorTexture(1, 1, 1, 0.5)
|
||||
button:SetChecked(not darkenInactive)
|
||||
end
|
||||
else
|
||||
if numForms == 1 or stance == 0 then
|
||||
button:SetChecked(false)
|
||||
else
|
||||
button:SetChecked(darkenInactive)
|
||||
button.checked:SetAlpha(1)
|
||||
if darkenInactive then
|
||||
button.checked:SetColorTexture(0, 0, 0, 0.5)
|
||||
else
|
||||
button.checked:SetColorTexture(1, 1, 1, 0.5)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if isActive then
|
||||
button:SetChecked(true)
|
||||
else
|
||||
button:SetChecked(false)
|
||||
end
|
||||
end
|
||||
|
||||
if isCastable then
|
||||
button.icon:SetVertexColor(1.0, 1.0, 1.0)
|
||||
else
|
||||
button.icon:SetVertexColor(0.4, 0.4, 0.4)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:PositionAndSizeBarShapeShift()
|
||||
local db = AB.db.stanceBar
|
||||
|
||||
local buttonSpacing = db.buttonspacing
|
||||
local backdropSpacing = db.backdropSpacing
|
||||
local buttonsPerRow = db.buttonsPerRow
|
||||
local numButtons = db.buttons
|
||||
local point = db.point
|
||||
local visibility = db.visibility
|
||||
|
||||
bar.db = db
|
||||
bar.mouseover = db.mouseover
|
||||
|
||||
if bar.LastButton then
|
||||
if numButtons > bar.LastButton then numButtons = bar.LastButton end
|
||||
if buttonsPerRow > bar.LastButton then buttonsPerRow = bar.LastButton end
|
||||
end
|
||||
if numButtons < buttonsPerRow then
|
||||
buttonsPerRow = numButtons
|
||||
end
|
||||
|
||||
bar:SetParent(db.inheritGlobalFade and AB.fadeParent or E.UIParent)
|
||||
bar:EnableMouse(not db.clickThrough)
|
||||
bar:SetAlpha(bar.mouseover and 0 or db.alpha)
|
||||
AB:FadeBarBlings(bar, bar.mouseover and 0 or db.alpha)
|
||||
|
||||
bar.backdrop:SetShown(db.backdrop)
|
||||
bar.backdrop:ClearAllPoints()
|
||||
|
||||
AB:MoverMagic(bar)
|
||||
|
||||
local _, horizontal, anchorUp, anchorLeft = AB:GetGrowth(point)
|
||||
local button, lastButton, lastColumnButton, anchorRowButton, lastShownButton
|
||||
local useMasque = MasqueGroup and E.private.actionbar.masque.stanceBar
|
||||
|
||||
for i = 1, NUM_STANCE_SLOTS do
|
||||
button = _G['ElvUI_StanceBarButton'..i]
|
||||
lastButton = _G['ElvUI_StanceBarButton'..i-1]
|
||||
lastColumnButton = _G['ElvUI_StanceBarButton'..i-buttonsPerRow]
|
||||
button.db = db
|
||||
|
||||
if i == 1 or i == buttonsPerRow then
|
||||
anchorRowButton = button
|
||||
end
|
||||
|
||||
if i > numButtons then
|
||||
button:SetAlpha(0)
|
||||
button.handleBackdrop = nil
|
||||
else
|
||||
button:SetAlpha(db.alpha)
|
||||
lastShownButton = button
|
||||
button.handleBackdrop = true -- keep over HandleButton
|
||||
end
|
||||
|
||||
AB:HandleButton(bar, button, i, lastButton, lastColumnButton)
|
||||
|
||||
if useMasque then
|
||||
MasqueGroup:AddButton(bar.buttons[i])
|
||||
end
|
||||
|
||||
if not button.FlyoutUpdateFunc then
|
||||
AB:StyleButton(button, nil, useMasque, true)
|
||||
|
||||
if not useMasque then
|
||||
if db.style == 'darkenInactive' then
|
||||
button.checked:SetBlendMode('BLEND')
|
||||
else
|
||||
button.checked:SetBlendMode('ADD')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AB:HandleBackdropMultiplier(bar, backdropSpacing, buttonSpacing, db.widthMult, db.heightMult, anchorUp, anchorLeft, horizontal, lastShownButton, anchorRowButton)
|
||||
AB:HandleBackdropMover(bar, backdropSpacing)
|
||||
|
||||
if db.enabled then
|
||||
visibility = gsub(visibility,'[\n\r]','')
|
||||
|
||||
RegisterStateDriver(bar, 'visibility', (GetNumShapeshiftForms() == 0 and 'hide') or visibility)
|
||||
E:EnableMover(bar.mover:GetName())
|
||||
else
|
||||
RegisterStateDriver(bar, 'visibility', 'hide')
|
||||
E:DisableMover(bar.mover:GetName())
|
||||
end
|
||||
|
||||
if useMasque then
|
||||
MasqueGroup:ReSkin()
|
||||
|
||||
for _, btn in ipairs(bar.buttons) do
|
||||
AB:TrimIcon(btn, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:AdjustMaxStanceButtons(event)
|
||||
if InCombatLockdown() then
|
||||
AB.NeedsAdjustMaxStanceButtons = event or true
|
||||
AB:RegisterEvent('PLAYER_REGEN_ENABLED')
|
||||
return
|
||||
end
|
||||
|
||||
for _, button in ipairs(bar.buttons) do
|
||||
button:Hide()
|
||||
end
|
||||
|
||||
local numButtons = GetNumShapeshiftForms()
|
||||
for i = 1, NUM_STANCE_SLOTS do
|
||||
if not bar.buttons[i] then
|
||||
bar.buttons[i] = CreateFrame('CheckButton', format(bar:GetName()..'Button%d', i), bar, 'StanceButtonTemplate')
|
||||
bar.buttons[i]:SetID(i)
|
||||
|
||||
AB:HookScript(bar.buttons[i], 'OnEnter', 'Button_OnEnter')
|
||||
AB:HookScript(bar.buttons[i], 'OnLeave', 'Button_OnLeave')
|
||||
end
|
||||
|
||||
local blizz = _G[format('StanceButton%d', i)]
|
||||
if blizz and blizz.commandName then
|
||||
bar.buttons[i].commandName = blizz.commandName
|
||||
end
|
||||
|
||||
if i <= numButtons then
|
||||
bar.buttons[i]:Show()
|
||||
bar.LastButton = i
|
||||
end
|
||||
end
|
||||
|
||||
AB:PositionAndSizeBarShapeShift()
|
||||
|
||||
-- sometimes after combat lock down `event` may be true because of passing it back with `AB.NeedsAdjustMaxStanceButtons`
|
||||
if event == 'UPDATE_SHAPESHIFT_FORMS' or event == 'PLAYER_ENTERING_WORLD' then
|
||||
AB:StyleShapeShift()
|
||||
end
|
||||
end
|
||||
|
||||
function AB:UpdateStanceBindings()
|
||||
for i = 1, NUM_STANCE_SLOTS do
|
||||
local button = _G['ElvUI_StanceBarButton'..i]
|
||||
if not button then break end
|
||||
|
||||
if AB.db.hotkeytext then
|
||||
button.HotKey:Show()
|
||||
button.HotKey:SetText(GetBindingKey('SHAPESHIFTBUTTON'..i))
|
||||
|
||||
AB:FixKeybindText(button)
|
||||
else
|
||||
button.HotKey:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AB:CreateBarShapeShift()
|
||||
bar:CreateBackdrop(AB.db.transparent and 'Transparent')
|
||||
bar.backdrop:SetFrameLevel(0)
|
||||
|
||||
bar:Point('TOPLEFT', E.UIParent, 'BOTTOMLEFT', 4, -769)
|
||||
|
||||
AB:HookScript(bar, 'OnEnter', 'Bar_OnEnter')
|
||||
AB:HookScript(bar, 'OnLeave', 'Bar_OnLeave')
|
||||
|
||||
AB:RegisterEvent('UPDATE_SHAPESHIFT_COOLDOWN')
|
||||
AB:RegisterEvent('UPDATE_SHAPESHIFT_FORMS', 'AdjustMaxStanceButtons')
|
||||
AB:RegisterEvent('UPDATE_SHAPESHIFT_FORM', 'StyleShapeShift')
|
||||
AB:RegisterEvent('UPDATE_SHAPESHIFT_USABLE', 'StyleShapeShift')
|
||||
AB:RegisterEvent('ACTIONBAR_PAGE_CHANGED', 'StyleShapeShift')
|
||||
|
||||
E:CreateMover(bar, 'ShiftAB', L["Stance Bar"], nil, -3, nil, 'ALL,ACTIONBARS', nil, 'actionbar,stanceBar', true)
|
||||
end
|
||||
419
Modules/Auras/Auras.lua
Normal file
419
Modules/Auras/Auras.lua
Normal file
@@ -0,0 +1,419 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local A = E:GetModule('Auras')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local format, tinsert = format, tinsert
|
||||
local select, unpack, strmatch = select, unpack, strmatch
|
||||
local GetInventoryItemQuality = GetInventoryItemQuality
|
||||
local GetInventoryItemTexture = GetInventoryItemTexture
|
||||
local GetItemQualityColor = GetItemQualityColor
|
||||
local GetWeaponEnchantInfo = GetWeaponEnchantInfo
|
||||
local RegisterAttributeDriver = RegisterAttributeDriver
|
||||
local RegisterStateDriver = RegisterStateDriver
|
||||
local CreateFrame = CreateFrame
|
||||
local UnitAura = UnitAura
|
||||
local GetTime = GetTime
|
||||
|
||||
local Masque = E.Masque
|
||||
local MasqueGroupBuffs = Masque and Masque:Group('ElvUI', 'Buffs')
|
||||
local MasqueGroupDebuffs = Masque and Masque:Group('ElvUI', 'Debuffs')
|
||||
|
||||
local DIRECTION_TO_POINT = {
|
||||
DOWN_RIGHT = 'TOPLEFT',
|
||||
DOWN_LEFT = 'TOPRIGHT',
|
||||
UP_RIGHT = 'BOTTOMLEFT',
|
||||
UP_LEFT = 'BOTTOMRIGHT',
|
||||
RIGHT_DOWN = 'TOPLEFT',
|
||||
RIGHT_UP = 'BOTTOMLEFT',
|
||||
LEFT_DOWN = 'TOPRIGHT',
|
||||
LEFT_UP = 'BOTTOMRIGHT',
|
||||
}
|
||||
|
||||
local DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER = {
|
||||
DOWN_RIGHT = 1,
|
||||
DOWN_LEFT = -1,
|
||||
UP_RIGHT = 1,
|
||||
UP_LEFT = -1,
|
||||
RIGHT_DOWN = 1,
|
||||
RIGHT_UP = 1,
|
||||
LEFT_DOWN = -1,
|
||||
LEFT_UP = -1,
|
||||
}
|
||||
|
||||
local DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER = {
|
||||
DOWN_RIGHT = -1,
|
||||
DOWN_LEFT = -1,
|
||||
UP_RIGHT = 1,
|
||||
UP_LEFT = 1,
|
||||
RIGHT_DOWN = -1,
|
||||
RIGHT_UP = 1,
|
||||
LEFT_DOWN = -1,
|
||||
LEFT_UP = 1,
|
||||
}
|
||||
|
||||
local IS_HORIZONTAL_GROWTH = {
|
||||
RIGHT_DOWN = true,
|
||||
RIGHT_UP = true,
|
||||
LEFT_DOWN = true,
|
||||
LEFT_UP = true,
|
||||
}
|
||||
|
||||
local MasqueButtonData = {
|
||||
-- ones we update:
|
||||
Icon = nil,
|
||||
Highlight = nil,
|
||||
|
||||
-- ones we dont update:
|
||||
FloatingBG = nil,
|
||||
Cooldown = nil,
|
||||
Flash = nil,
|
||||
Pushed = nil,
|
||||
Normal = nil,
|
||||
Disabled = nil,
|
||||
Checked = nil,
|
||||
Border = nil,
|
||||
AutoCastable = nil,
|
||||
HotKey = nil,
|
||||
Count = false,
|
||||
Name = nil,
|
||||
Duration = false,
|
||||
AutoCast = nil,
|
||||
}
|
||||
|
||||
function A:MasqueData(texture, highlight)
|
||||
local btnData = E:CopyTable({}, MasqueButtonData)
|
||||
btnData.Icon = texture
|
||||
btnData.Highlight = highlight
|
||||
return btnData
|
||||
end
|
||||
|
||||
function A:UpdateStatusBar(button)
|
||||
local db = A.db[button.auraType]
|
||||
button.statusBar:SetValue(button.timeLeft)
|
||||
|
||||
local threshold = db.fadeThreshold
|
||||
if threshold == -1 then
|
||||
return
|
||||
elseif button.timeLeft > threshold then
|
||||
E:StopFlash(button)
|
||||
else
|
||||
E:Flash(button, 1)
|
||||
end
|
||||
end
|
||||
|
||||
function A:CreateIcon(button)
|
||||
local header = button:GetParent()
|
||||
local auraType = header.filter
|
||||
|
||||
button.auraType = auraType == 'HELPFUL' and 'buffs' or 'debuffs' -- used to update cooldown text
|
||||
button.filter = auraType
|
||||
|
||||
button.texture = button:CreateTexture(nil, 'ARTWORK')
|
||||
button.texture:SetInside()
|
||||
button.texture:SetTexCoord(unpack(E.TexCoords))
|
||||
|
||||
button.count = button:CreateFontString(nil, 'OVERLAY')
|
||||
button.count:FontTemplate()
|
||||
|
||||
button.text = button:CreateFontString(nil, 'OVERLAY')
|
||||
button.text:FontTemplate()
|
||||
|
||||
button.highlight = button:CreateTexture(nil, 'HIGHLIGHT')
|
||||
button.highlight:SetColorTexture(1, 1, 1, .45)
|
||||
button.highlight:SetInside()
|
||||
|
||||
button.statusBar = CreateFrame('StatusBar', nil, button)
|
||||
button.statusBar:SetFrameLevel(button:GetFrameLevel())
|
||||
button.statusBar:SetFrameStrata(button:GetFrameStrata())
|
||||
button.statusBar:CreateBackdrop()
|
||||
|
||||
A:UpdateIcon(button)
|
||||
E:SetSmoothing(button.statusBar)
|
||||
E:SetUpAnimGroup(button)
|
||||
|
||||
-- support cooldown override
|
||||
if not button.isRegisteredCooldown then
|
||||
button.CooldownOverride = 'auras'
|
||||
button.isRegisteredCooldown = true
|
||||
button.forceEnabled = true
|
||||
button.showSeconds = true
|
||||
|
||||
if not E.RegisteredCooldowns.auras then E.RegisteredCooldowns.auras = {} end
|
||||
tinsert(E.RegisteredCooldowns.auras, button)
|
||||
end
|
||||
|
||||
button:SetScript('OnAttributeChanged', A.OnAttributeChanged)
|
||||
A:Update_CooldownOptions(button)
|
||||
|
||||
if auraType == 'HELPFUL' and MasqueGroupBuffs and E.private.auras.masque.buffs then
|
||||
MasqueGroupBuffs:AddButton(button, A:MasqueData(button.texture, button.highlight))
|
||||
if button.__MSQ_BaseFrame then button.__MSQ_BaseFrame:SetFrameLevel(2) end --Lower the framelevel to fix issue with buttons created during combat
|
||||
MasqueGroupBuffs:ReSkin()
|
||||
elseif auraType == 'HARMFUL' and MasqueGroupDebuffs and E.private.auras.masque.debuffs then
|
||||
MasqueGroupDebuffs:AddButton(button, A:MasqueData(button.texture, button.highlight))
|
||||
if button.__MSQ_BaseFrame then button.__MSQ_BaseFrame:SetFrameLevel(2) end --Lower the framelevel to fix issue with buttons created during combat
|
||||
MasqueGroupDebuffs:ReSkin()
|
||||
else
|
||||
button:SetTemplate()
|
||||
end
|
||||
end
|
||||
|
||||
function A:UpdateIcon(button)
|
||||
local db = A.db[button.auraType]
|
||||
|
||||
button.count:ClearAllPoints()
|
||||
button.count:Point('BOTTOMRIGHT', db.countXOffset, db.countYOffset)
|
||||
button.count:FontTemplate(LSM:Fetch('font', db.countFont), db.countFontSize, db.countFontOutline)
|
||||
|
||||
button.text:ClearAllPoints()
|
||||
button.text:Point('TOP', button, 'BOTTOM', db.timeXOffset, db.timeYOffset)
|
||||
button.text:FontTemplate(LSM:Fetch('font', db.timeFont), db.timeFontSize, db.timeFontOutline)
|
||||
|
||||
local pos, spacing, iconSize = db.barPosition, db.barSpacing, db.size - (E.Border * 2)
|
||||
local isOnTop, isOnBottom, isOnLeft = pos == 'TOP', pos == 'BOTTOM', pos == 'LEFT'
|
||||
local isHorizontal = isOnTop or isOnBottom
|
||||
|
||||
button.statusBar:ClearAllPoints()
|
||||
button.statusBar:Size(isHorizontal and iconSize or (db.barSize + (E.PixelMode and 0 or 2)), isHorizontal and (db.barSize + (E.PixelMode and 0 or 2)) or iconSize)
|
||||
button.statusBar:Point(E.InversePoints[pos], button, pos, isHorizontal and 0 or ((isOnLeft and -((E.PixelMode and 1 or 3) + spacing)) or ((E.PixelMode and 1 or 3) + spacing)), not isHorizontal and 0 or ((isOnTop and ((E.PixelMode and 1 or 3) + spacing) or -((E.PixelMode and 1 or 3) + spacing))))
|
||||
button.statusBar:SetStatusBarTexture(LSM:Fetch('statusbar', db.barTexture))
|
||||
button.statusBar:SetOrientation(isHorizontal and 'HORIZONTAL' or 'VERTICAL')
|
||||
button.statusBar:SetRotatesTexture(not isHorizontal)
|
||||
end
|
||||
|
||||
function A:SetAuraTime(button, expiration, duration)
|
||||
button.timeLeft = E:Round(expiration - GetTime(), 3)
|
||||
|
||||
-- this keeps enchants from derping out when they expire
|
||||
if button.timeLeft <= 0.05 then
|
||||
A:ClearAuraTime(button, true)
|
||||
return
|
||||
end
|
||||
|
||||
A:UpdateStatusBar(button)
|
||||
|
||||
local oldEnd = button.endTime
|
||||
button.endTime = expiration
|
||||
|
||||
if oldEnd ~= button.endTime then
|
||||
button.nextUpdate = 0
|
||||
button.statusBar:SetMinMaxValues(0, duration)
|
||||
button:SetScript('OnUpdate', E.Cooldown_OnUpdate)
|
||||
end
|
||||
end
|
||||
|
||||
function A:ClearAuraTime(button, expired)
|
||||
if not expired then
|
||||
button.statusBar:SetValue(1)
|
||||
button.statusBar:SetMinMaxValues(0, 1)
|
||||
end
|
||||
|
||||
button.endTime = nil
|
||||
button.timeLeft = nil
|
||||
button.text:SetText('')
|
||||
button:SetScript('OnUpdate', nil)
|
||||
end
|
||||
|
||||
function A:UpdateAura(button, index)
|
||||
local unit = button:GetParent():GetAttribute('unit')
|
||||
local name, texture, count, dtype, duration, expiration = UnitAura(unit, index, button.filter)
|
||||
|
||||
local DebuffType = dtype or 'none'
|
||||
if name then
|
||||
local db = A.db[button.auraType]
|
||||
if duration > 0 and expiration then
|
||||
A:SetAuraTime(button, expiration, duration)
|
||||
else
|
||||
A:ClearAuraTime(button)
|
||||
end
|
||||
|
||||
local r, g, b = db.barColor.r, db.barColor.g, db.barColor.b
|
||||
if button.timeLeft and db.barColorGradient then
|
||||
r, g, b = E.oUF:ColorGradient(button.timeLeft, duration or 0, .8, 0, 0, .8, .8, 0, 0, .8, 0)
|
||||
end
|
||||
|
||||
button.count:SetText(count > 1 and count)
|
||||
button.text:SetShown(db.showDuration)
|
||||
button.statusBar:SetShown((db.barShow and duration > 0) or (db.barShow and db.barNoDuration and duration == 0))
|
||||
button.statusBar:SetStatusBarColor(r, g, b)
|
||||
button.texture:SetTexture(texture)
|
||||
|
||||
if button.debuffType ~= DebuffType then
|
||||
local color = button.filter == 'HARMFUL' and _G.DebuffTypeColor[DebuffType] or E.db.general.bordercolor
|
||||
button:SetBackdropBorderColor(color.r, color.g, color.b)
|
||||
button.statusBar.backdrop:SetBackdropBorderColor(color.r, color.g, color.b)
|
||||
end
|
||||
end
|
||||
|
||||
button.debuffType = DebuffType
|
||||
end
|
||||
|
||||
function A:UpdateTempEnchant(button, index)
|
||||
local offset = (strmatch(button:GetName(), '2$') and 6) or 2
|
||||
local db = A.db[button.auraType]
|
||||
|
||||
local duration, remaining = 600, 0
|
||||
local expiration = select(offset, GetWeaponEnchantInfo())
|
||||
if expiration then
|
||||
button.texture:SetTexture(GetInventoryItemTexture('player', index))
|
||||
|
||||
local quality = GetInventoryItemQuality('player', index)
|
||||
if quality and quality > 1 then
|
||||
button:SetBackdropBorderColor(GetItemQualityColor(quality))
|
||||
else
|
||||
button:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
||||
end
|
||||
|
||||
remaining = expiration / 1000
|
||||
if remaining <= 3600 and remaining > 1800 then
|
||||
duration = 3600
|
||||
elseif remaining <= 1800 and remaining > 600 then
|
||||
duration = 1800
|
||||
end
|
||||
|
||||
A:SetAuraTime(button, E:Round(remaining + GetTime(), 3), duration)
|
||||
else
|
||||
A:ClearAuraTime(button)
|
||||
end
|
||||
|
||||
local r, g, b = db.barColor.r, db.barColor.g, db.barColor.b
|
||||
if expiration and db.barColorGradient then
|
||||
r, g, b = E.oUF:ColorGradient(remaining, duration, .8, 0, 0, .8, .8, 0, 0, .8, 0)
|
||||
end
|
||||
|
||||
button.text:SetShown(db.showDuration)
|
||||
button.statusBar:SetShown((db.barShow and remaining > 0) or (db.barShow and db.barNoDuration and not expiration))
|
||||
button.statusBar:SetStatusBarColor(r, g, b)
|
||||
end
|
||||
|
||||
function A:Update_CooldownOptions(button)
|
||||
E:Cooldown_Options(button, A.db.cooldown, button)
|
||||
end
|
||||
|
||||
function A:OnAttributeChanged(attribute, value)
|
||||
A:Update_CooldownOptions(self)
|
||||
|
||||
if attribute == 'index' then
|
||||
A:UpdateAura(self, value)
|
||||
elseif attribute == 'target-slot' then
|
||||
A:UpdateTempEnchant(self, value)
|
||||
end
|
||||
end
|
||||
|
||||
function A:UpdateHeader(header)
|
||||
if not E.private.auras.enable then return end
|
||||
|
||||
local db = A.db[header.auraType]
|
||||
local template = format('ElvUIAuraTemplate%d', db.size)
|
||||
|
||||
local colors = db.barColor
|
||||
if E:CheckClassColor(colors.r, colors.g, colors.b) then
|
||||
local classColor = E:ClassColor(E.myclass, true)
|
||||
colors.r, colors.g, colors.b = classColor.r, classColor.g, classColor.b
|
||||
end
|
||||
|
||||
if header.filter == 'HELPFUL' then
|
||||
header:SetAttribute('consolidateTo', 0)
|
||||
header:SetAttribute('weaponTemplate', template)
|
||||
end
|
||||
|
||||
header:SetAttribute('template', template)
|
||||
header:SetAttribute('separateOwn', db.seperateOwn)
|
||||
header:SetAttribute('sortMethod', db.sortMethod)
|
||||
header:SetAttribute('sortDirection', db.sortDir)
|
||||
header:SetAttribute('maxWraps', db.maxWraps)
|
||||
header:SetAttribute('wrapAfter', db.wrapAfter)
|
||||
header:SetAttribute('point', DIRECTION_TO_POINT[db.growthDirection])
|
||||
|
||||
if IS_HORIZONTAL_GROWTH[db.growthDirection] then
|
||||
header:SetAttribute('minWidth', ((db.wrapAfter == 1 and 0 or db.horizontalSpacing) + db.size) * db.wrapAfter)
|
||||
header:SetAttribute('minHeight', (db.verticalSpacing + db.size) * db.maxWraps)
|
||||
header:SetAttribute('xOffset', DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[db.growthDirection] * (db.horizontalSpacing + db.size))
|
||||
header:SetAttribute('yOffset', 0)
|
||||
header:SetAttribute('wrapXOffset', 0)
|
||||
header:SetAttribute('wrapYOffset', DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[db.growthDirection] * (db.verticalSpacing + db.size))
|
||||
else
|
||||
header:SetAttribute('minWidth', (db.horizontalSpacing + db.size) * db.maxWraps)
|
||||
header:SetAttribute('minHeight', ((db.wrapAfter == 1 and 0 or db.verticalSpacing) + db.size) * db.wrapAfter)
|
||||
header:SetAttribute('xOffset', 0)
|
||||
header:SetAttribute('yOffset', DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[db.growthDirection] * (db.verticalSpacing + db.size))
|
||||
header:SetAttribute('wrapXOffset', DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[db.growthDirection] * (db.horizontalSpacing + db.size))
|
||||
header:SetAttribute('wrapYOffset', 0)
|
||||
end
|
||||
|
||||
local index = 1
|
||||
local child = select(index, header:GetChildren())
|
||||
while child do
|
||||
child.db = db
|
||||
child.auraType = header.auraType -- used to update cooldown text
|
||||
child:Size(db.size, db.size)
|
||||
|
||||
A:UpdateIcon(child)
|
||||
|
||||
--Blizzard bug fix, icons arent being hidden when you reduce the amount of maximum buttons
|
||||
if index > (db.maxWraps * db.wrapAfter) and child:IsShown() then
|
||||
child:Hide()
|
||||
end
|
||||
|
||||
index = index + 1
|
||||
child = select(index, header:GetChildren())
|
||||
end
|
||||
|
||||
if MasqueGroupBuffs and E.private.auras.buffsHeader and E.private.auras.masque.buffs then MasqueGroupBuffs:ReSkin() end
|
||||
if MasqueGroupDebuffs and E.private.auras.debuffsHeader and E.private.auras.masque.debuffs then MasqueGroupDebuffs:ReSkin() end
|
||||
end
|
||||
|
||||
function A:CreateAuraHeader(filter)
|
||||
local name, auraType = filter == 'HELPFUL' and 'ElvUIPlayerBuffs' or 'ElvUIPlayerDebuffs', filter == 'HELPFUL' and 'buffs' or 'debuffs'
|
||||
|
||||
local header = CreateFrame('Frame', name, E.UIParent, 'SecureAuraHeaderTemplate')
|
||||
header:SetClampedToScreen(true)
|
||||
header:SetAttribute('unit', 'player')
|
||||
header:SetAttribute('filter', filter)
|
||||
header.filter = filter
|
||||
header.auraType = auraType
|
||||
RegisterStateDriver(header, 'visibility', '[petbattle] hide; show')
|
||||
RegisterAttributeDriver(header, 'unit', '[vehicleui] vehicle; player')
|
||||
|
||||
if filter == 'HELPFUL' then
|
||||
header:SetAttribute('consolidateDuration', -1)
|
||||
header:SetAttribute('includeWeapons', 1)
|
||||
end
|
||||
|
||||
A:UpdateHeader(header)
|
||||
header:Show()
|
||||
|
||||
return header
|
||||
end
|
||||
|
||||
function A:Initialize()
|
||||
if E.private.auras.disableBlizzard then
|
||||
_G.BuffFrame:Kill()
|
||||
_G.TemporaryEnchantFrame:Kill()
|
||||
end
|
||||
|
||||
if not E.private.auras.enable then return end
|
||||
|
||||
A.Initialized = true
|
||||
A.db = E.db.auras
|
||||
|
||||
local xoffset = -(6 + E.Border)
|
||||
if E.private.auras.buffsHeader then
|
||||
A.BuffFrame = A:CreateAuraHeader('HELPFUL')
|
||||
A.BuffFrame:ClearAllPoints()
|
||||
A.BuffFrame:SetPoint('TOPRIGHT', _G.MMHolder or _G.MinimapCluster, 'TOPLEFT', xoffset, -E.Spacing)
|
||||
E:CreateMover(A.BuffFrame, 'BuffsMover', L["Player Buffs"], nil, nil, nil, nil, nil, 'auras,buffs')
|
||||
if Masque and MasqueGroupBuffs then A.BuffsMasqueGroup = MasqueGroupBuffs end
|
||||
end
|
||||
|
||||
if E.private.auras.debuffsHeader then
|
||||
A.DebuffFrame = A:CreateAuraHeader('HARMFUL')
|
||||
A.DebuffFrame:ClearAllPoints()
|
||||
A.DebuffFrame:SetPoint('BOTTOMRIGHT', _G.MMHolder or _G.MinimapCluster, 'BOTTOMLEFT', xoffset, E.Spacing)
|
||||
E:CreateMover(A.DebuffFrame, 'DebuffsMover', L["Player Debuffs"], nil, nil, nil, nil, nil, 'auras,debuffs')
|
||||
if Masque and MasqueGroupDebuffs then A.DebuffsMasqueGroup = MasqueGroupDebuffs end
|
||||
end
|
||||
end
|
||||
|
||||
E:RegisterModule(A:GetName())
|
||||
52
Modules/Auras/Load_Auras.xml
Normal file
52
Modules/Auras/Load_Auras.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Button name='ElvUIAuraTemplate' inherits='SecureActionButtonTemplate, BackdropTemplate' virtual='true' framelevel='4'>
|
||||
<!-- framelevel 4 for Masque support -->
|
||||
<Size x='26' y='26'/>
|
||||
<Attributes>
|
||||
<Attribute name='type' value='cancelaura'/>
|
||||
</Attributes>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
ElvUI[1]:GetModule('Auras'):CreateIcon(self)
|
||||
self:RegisterForClicks('RightButtonUp')
|
||||
</OnLoad>
|
||||
<OnEnter>
|
||||
GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMLEFT', -5, -5)
|
||||
if self:GetAttribute('index') then
|
||||
GameTooltip:SetUnitAura(SecureButton_GetUnit(self:GetParent()), self:GetID(), self:GetParent():GetAttribute('filter'))
|
||||
elseif self:GetAttribute('target-slot') then
|
||||
GameTooltip:SetInventoryItem('player', self:GetID())
|
||||
end
|
||||
</OnEnter>
|
||||
<OnLeave function='GameTooltip_Hide'/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
|
||||
<!-- Theres gotta be a better way to do this.. -->
|
||||
<Button name='ElvUIAuraTemplate16' inherits='ElvUIAuraTemplate' virtual='true'><Size x='16' y='16'/></Button>
|
||||
<Button name='ElvUIAuraTemplate18' inherits='ElvUIAuraTemplate' virtual='true'><Size x='18' y='18'/></Button>
|
||||
<Button name='ElvUIAuraTemplate20' inherits='ElvUIAuraTemplate' virtual='true'><Size x='20' y='20'/></Button>
|
||||
<Button name='ElvUIAuraTemplate22' inherits='ElvUIAuraTemplate' virtual='true'><Size x='22' y='22'/></Button>
|
||||
<Button name='ElvUIAuraTemplate24' inherits='ElvUIAuraTemplate' virtual='true'><Size x='24' y='24'/></Button>
|
||||
<Button name='ElvUIAuraTemplate26' inherits='ElvUIAuraTemplate' virtual='true'><Size x='26' y='26'/></Button>
|
||||
<Button name='ElvUIAuraTemplate28' inherits='ElvUIAuraTemplate' virtual='true'><Size x='28' y='28'/></Button>
|
||||
<Button name='ElvUIAuraTemplate30' inherits='ElvUIAuraTemplate' virtual='true'><Size x='30' y='30'/></Button>
|
||||
<Button name='ElvUIAuraTemplate32' inherits='ElvUIAuraTemplate' virtual='true'><Size x='32' y='32'/></Button>
|
||||
<Button name='ElvUIAuraTemplate34' inherits='ElvUIAuraTemplate' virtual='true'><Size x='34' y='34'/></Button>
|
||||
<Button name='ElvUIAuraTemplate36' inherits='ElvUIAuraTemplate' virtual='true'><Size x='36' y='36'/></Button>
|
||||
<Button name='ElvUIAuraTemplate38' inherits='ElvUIAuraTemplate' virtual='true'><Size x='38' y='38'/></Button>
|
||||
<Button name='ElvUIAuraTemplate40' inherits='ElvUIAuraTemplate' virtual='true'><Size x='40' y='40'/></Button>
|
||||
<Button name='ElvUIAuraTemplate42' inherits='ElvUIAuraTemplate' virtual='true'><Size x='42' y='42'/></Button>
|
||||
<Button name='ElvUIAuraTemplate44' inherits='ElvUIAuraTemplate' virtual='true'><Size x='44' y='44'/></Button>
|
||||
<Button name='ElvUIAuraTemplate46' inherits='ElvUIAuraTemplate' virtual='true'><Size x='46' y='46'/></Button>
|
||||
<Button name='ElvUIAuraTemplate48' inherits='ElvUIAuraTemplate' virtual='true'><Size x='48' y='48'/></Button>
|
||||
<Button name='ElvUIAuraTemplate50' inherits='ElvUIAuraTemplate' virtual='true'><Size x='50' y='50'/></Button>
|
||||
<Button name='ElvUIAuraTemplate52' inherits='ElvUIAuraTemplate' virtual='true'><Size x='52' y='52'/></Button>
|
||||
<Button name='ElvUIAuraTemplate54' inherits='ElvUIAuraTemplate' virtual='true'><Size x='54' y='54'/></Button>
|
||||
<Button name='ElvUIAuraTemplate56' inherits='ElvUIAuraTemplate' virtual='true'><Size x='56' y='56'/></Button>
|
||||
<Button name='ElvUIAuraTemplate58' inherits='ElvUIAuraTemplate' virtual='true'><Size x='58' y='58'/></Button>
|
||||
<Button name='ElvUIAuraTemplate60' inherits='ElvUIAuraTemplate' virtual='true'><Size x='60' y='60'/></Button>
|
||||
|
||||
<!-- Oh, Look! A file we need to load.. -->
|
||||
<Script file='Auras.lua'/>
|
||||
</Ui>
|
||||
180
Modules/Bags/BagBar.lua
Normal file
180
Modules/Bags/BagBar.lua
Normal file
@@ -0,0 +1,180 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Bags')
|
||||
|
||||
local _G = _G
|
||||
local ipairs = ipairs
|
||||
local unpack = unpack
|
||||
local tinsert = tinsert
|
||||
local CreateFrame = CreateFrame
|
||||
local GetBagSlotFlag = GetBagSlotFlag
|
||||
local RegisterStateDriver = RegisterStateDriver
|
||||
local NUM_BAG_FRAMES = NUM_BAG_FRAMES
|
||||
local LE_BAG_FILTER_FLAG_EQUIPMENT = LE_BAG_FILTER_FLAG_EQUIPMENT
|
||||
local NUM_LE_BAG_FILTER_FLAGS = NUM_LE_BAG_FILTER_FLAGS
|
||||
|
||||
local function OnEnter()
|
||||
if not E.db.bags.bagBar.mouseover then return; end
|
||||
E:UIFrameFadeIn(B.BagBar, 0.2, B.BagBar:GetAlpha(), 1)
|
||||
end
|
||||
|
||||
local function OnLeave()
|
||||
if not E.db.bags.bagBar.mouseover then return; end
|
||||
E:UIFrameFadeOut(B.BagBar, 0.2, B.BagBar:GetAlpha(), 0)
|
||||
end
|
||||
|
||||
function B:SkinBag(bag)
|
||||
local icon = _G[bag:GetName()..'IconTexture']
|
||||
bag.oldTex = icon:GetTexture()
|
||||
|
||||
bag:StripTextures()
|
||||
bag:CreateBackdrop()
|
||||
bag:StyleButton(true)
|
||||
bag.IconBorder:Kill()
|
||||
bag.backdrop:SetAllPoints()
|
||||
|
||||
icon:SetInside()
|
||||
icon:SetTexture(bag.oldTex)
|
||||
icon:SetTexCoord(unpack(E.TexCoords))
|
||||
end
|
||||
|
||||
function B:SizeAndPositionBagBar()
|
||||
if not B.BagBar then return; end
|
||||
|
||||
local buttonSpacing = E.db.bags.bagBar.spacing
|
||||
local backdropSpacing = E.db.bags.bagBar.backdropSpacing
|
||||
local bagBarSize = E.db.bags.bagBar.size
|
||||
local showBackdrop = E.db.bags.bagBar.showBackdrop
|
||||
local growthDirection = E.db.bags.bagBar.growthDirection
|
||||
local sortDirection = E.db.bags.bagBar.sortDirection
|
||||
|
||||
local visibility = E.db.bags.bagBar.visibility
|
||||
if visibility and visibility:match('[\n\r]') then
|
||||
visibility = visibility:gsub('[\n\r]','')
|
||||
end
|
||||
|
||||
RegisterStateDriver(B.BagBar, 'visibility', visibility)
|
||||
B.BagBar:SetAlpha(E.db.bags.bagBar.mouseover and 0 or 1)
|
||||
B.BagBar.backdrop:SetShown(showBackdrop)
|
||||
|
||||
local bdpSpacing = (showBackdrop and backdropSpacing + E.Border) or 0
|
||||
local btnSpacing = (buttonSpacing + E.Border)
|
||||
|
||||
for i, button in ipairs(B.BagBar.buttons) do
|
||||
local prevButton = B.BagBar.buttons[i-1]
|
||||
button:Size(bagBarSize, bagBarSize)
|
||||
button:ClearAllPoints()
|
||||
|
||||
if growthDirection == 'HORIZONTAL' and sortDirection == 'ASCENDING' then
|
||||
if i == 1 then
|
||||
button:Point('LEFT', B.BagBar, 'LEFT', bdpSpacing, 0)
|
||||
elseif prevButton then
|
||||
button:Point('LEFT', prevButton, 'RIGHT', btnSpacing, 0)
|
||||
end
|
||||
elseif growthDirection == 'VERTICAL' and sortDirection == 'ASCENDING' then
|
||||
if i == 1 then
|
||||
button:Point('TOP', B.BagBar, 'TOP', 0, -bdpSpacing)
|
||||
elseif prevButton then
|
||||
button:Point('TOP', prevButton, 'BOTTOM', 0, -btnSpacing)
|
||||
end
|
||||
elseif growthDirection == 'HORIZONTAL' and sortDirection == 'DESCENDING' then
|
||||
if i == 1 then
|
||||
button:Point('RIGHT', B.BagBar, 'RIGHT', -bdpSpacing, 0)
|
||||
elseif prevButton then
|
||||
button:Point('RIGHT', prevButton, 'LEFT', -btnSpacing, 0)
|
||||
end
|
||||
else
|
||||
if i == 1 then
|
||||
button:Point('BOTTOM', B.BagBar, 'BOTTOM', 0, bdpSpacing)
|
||||
elseif prevButton then
|
||||
button:Point('BOTTOM', prevButton, 'TOP', 0, btnSpacing)
|
||||
end
|
||||
end
|
||||
for j = LE_BAG_FILTER_FLAG_EQUIPMENT, NUM_LE_BAG_FILTER_FLAGS do
|
||||
local active = GetBagSlotFlag(i - 1, j)
|
||||
if active then
|
||||
button.ElvUIFilterIcon:SetTexture(B.BAG_FILTER_ICONS[j])
|
||||
button.ElvUIFilterIcon:SetShown(E.db.bags.showAssignedIcon)
|
||||
|
||||
local r, g, b, a = unpack(B.AssignmentColors[j])
|
||||
|
||||
button.forcedBorderColors = {r, g, b, a}
|
||||
button.backdrop:SetBackdropBorderColor(r, g, b, a)
|
||||
break -- this loop
|
||||
else
|
||||
button.ElvUIFilterIcon:SetShown(false)
|
||||
|
||||
button.forcedBorderColors = nil
|
||||
button.backdrop:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local btnSize = bagBarSize * (NUM_BAG_FRAMES + 1)
|
||||
local btnSpace = btnSpacing * NUM_BAG_FRAMES
|
||||
local bdpDoubled = bdpSpacing * 2
|
||||
|
||||
if growthDirection == 'HORIZONTAL' then
|
||||
B.BagBar:Width(btnSize + btnSpace + bdpDoubled)
|
||||
B.BagBar:Height(bagBarSize + bdpDoubled)
|
||||
else
|
||||
B.BagBar:Height(btnSize + btnSpace + bdpDoubled)
|
||||
B.BagBar:Width(bagBarSize + bdpDoubled)
|
||||
end
|
||||
end
|
||||
|
||||
function B:LoadBagBar()
|
||||
if not E.private.bags.bagBar then return end
|
||||
|
||||
B.BagBar = CreateFrame('Frame', 'ElvUIBags', E.UIParent)
|
||||
B.BagBar:Point('TOPRIGHT', _G.RightChatPanel, 'TOPLEFT', -4, 0)
|
||||
B.BagBar.buttons = {}
|
||||
B.BagBar:CreateBackdrop(E.db.bags.transparent and 'Transparent')
|
||||
B.BagBar.backdrop:SetAllPoints()
|
||||
B.BagBar:EnableMouse(true)
|
||||
B.BagBar:SetScript('OnEnter', OnEnter)
|
||||
B.BagBar:SetScript('OnLeave', OnLeave)
|
||||
|
||||
_G.MainMenuBarBackpackButton:SetParent(B.BagBar)
|
||||
_G.MainMenuBarBackpackButton:ClearAllPoints()
|
||||
_G.MainMenuBarBackpackButtonCount:FontTemplate(nil, 10)
|
||||
_G.MainMenuBarBackpackButtonCount:ClearAllPoints()
|
||||
_G.MainMenuBarBackpackButtonCount:Point('BOTTOMRIGHT', _G.MainMenuBarBackpackButton, 'BOTTOMRIGHT', -1, 4)
|
||||
_G.MainMenuBarBackpackButton:HookScript('OnEnter', OnEnter)
|
||||
_G.MainMenuBarBackpackButton:HookScript('OnLeave', OnLeave)
|
||||
|
||||
tinsert(B.BagBar.buttons, _G.MainMenuBarBackpackButton)
|
||||
B:SkinBag(_G.MainMenuBarBackpackButton)
|
||||
|
||||
for i = 0, NUM_BAG_FRAMES-1 do
|
||||
local b = _G['CharacterBag'..i..'Slot']
|
||||
b:SetParent(B.BagBar)
|
||||
b:HookScript('OnEnter', OnEnter)
|
||||
b:HookScript('OnLeave', OnLeave)
|
||||
|
||||
B:SkinBag(b)
|
||||
tinsert(B.BagBar.buttons, b)
|
||||
end
|
||||
|
||||
--Item assignment
|
||||
for i, bagButton in ipairs(B.BagBar.buttons) do
|
||||
B:CreateFilterIcon(bagButton)
|
||||
bagButton.id = (i - 1)
|
||||
|
||||
bagButton:SetScript('OnClick', function(holder, button)
|
||||
if button == 'RightButton' then
|
||||
B.AssignBagDropdown.holder = holder
|
||||
_G.ToggleDropDownMenu(1, nil, B.AssignBagDropdown, 'cursor')
|
||||
else
|
||||
if holder.id == 0 then
|
||||
_G.MainMenuBarBackpackButton_OnClick(holder)
|
||||
else
|
||||
_G.BagSlotButton_OnClick(holder)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
B:SizeAndPositionBagBar()
|
||||
E:CreateMover(B.BagBar, 'BagsMover', L["Bags"], nil, nil, nil, nil, nil, 'bags,general')
|
||||
B:RegisterEvent('BAG_SLOT_FLAGS_UPDATED', 'SizeAndPositionBagBar')
|
||||
end
|
||||
2461
Modules/Bags/Bags.lua
Normal file
2461
Modules/Bags/Bags.lua
Normal file
File diff suppressed because it is too large
Load Diff
5
Modules/Bags/Load_Bags.xml
Normal file
5
Modules/Bags/Load_Bags.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='Bags.lua'/>
|
||||
<Script file='BagBar.lua'/>
|
||||
<Script file='Sort.lua'/>
|
||||
</Ui>
|
||||
949
Modules/Bags/Sort.lua
Normal file
949
Modules/Bags/Sort.lua
Normal file
@@ -0,0 +1,949 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Bags')
|
||||
local Search = E.Libs.ItemSearch
|
||||
|
||||
local ipairs, pairs, select, unpack, pcall = ipairs, pairs, select, unpack, pcall
|
||||
local strmatch, gmatch, strfind = strmatch, gmatch, strfind
|
||||
local tinsert, tremove, sort, wipe = tinsert, tremove, sort, wipe
|
||||
local tonumber, floor, band = tonumber, floor, bit.band
|
||||
|
||||
local ContainerIDToInventoryID = ContainerIDToInventoryID
|
||||
local GetContainerItemID = GetContainerItemID
|
||||
local GetContainerItemInfo = GetContainerItemInfo
|
||||
local GetContainerItemLink = GetContainerItemLink
|
||||
local GetContainerNumFreeSlots = GetContainerNumFreeSlots
|
||||
local GetContainerNumSlots = GetContainerNumSlots
|
||||
local GetCurrentGuildBankTab = GetCurrentGuildBankTab
|
||||
local GetCursorInfo = GetCursorInfo
|
||||
local GetGuildBankItemInfo = GetGuildBankItemInfo
|
||||
local GetGuildBankItemLink = GetGuildBankItemLink
|
||||
local GetGuildBankTabInfo = GetGuildBankTabInfo
|
||||
local GetInventoryItemLink = GetInventoryItemLink
|
||||
local GetItemFamily = GetItemFamily
|
||||
local GetItemInfo = GetItemInfo
|
||||
local GetTime = GetTime
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local PickupContainerItem = PickupContainerItem
|
||||
local PickupGuildBankItem = PickupGuildBankItem
|
||||
local QueryGuildBankTab = QueryGuildBankTab
|
||||
local SplitContainerItem = SplitContainerItem
|
||||
local SplitGuildBankItem = SplitGuildBankItem
|
||||
|
||||
local C_PetJournalGetPetInfoBySpeciesID = C_PetJournal.GetPetInfoBySpeciesID
|
||||
local LE_ITEM_CLASS_ARMOR = LE_ITEM_CLASS_ARMOR
|
||||
local LE_ITEM_CLASS_WEAPON = LE_ITEM_CLASS_WEAPON
|
||||
|
||||
local guildBags = {51,52,53,54,55,56,57,58}
|
||||
local bankBags = {BANK_CONTAINER}
|
||||
local MAX_MOVE_TIME = 1.25
|
||||
|
||||
for i = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
|
||||
tinsert(bankBags, i)
|
||||
end
|
||||
|
||||
local playerBags = {}
|
||||
for i = 0, NUM_BAG_SLOTS do
|
||||
tinsert(playerBags, i)
|
||||
end
|
||||
|
||||
local allBags = {}
|
||||
for _,i in ipairs(playerBags) do
|
||||
tinsert(allBags, i)
|
||||
end
|
||||
for _,i in ipairs(bankBags) do
|
||||
tinsert(allBags, i)
|
||||
end
|
||||
|
||||
for _,i in ipairs(guildBags) do
|
||||
tinsert(allBags, i)
|
||||
end
|
||||
|
||||
local coreGroups = {
|
||||
guild = guildBags,
|
||||
bank = bankBags,
|
||||
bags = playerBags,
|
||||
all = allBags,
|
||||
}
|
||||
|
||||
local bagCache = {}
|
||||
local bagIDs = {}
|
||||
local bagQualities = {}
|
||||
local bagPetIDs = {}
|
||||
local bagStacks = {}
|
||||
local bagMaxStacks = {}
|
||||
local bagGroups = {}
|
||||
local initialOrder = {}
|
||||
local bagSorted, bagLocked = {}, {}
|
||||
local bagRole
|
||||
local moves = {}
|
||||
local targetItems = {}
|
||||
local sourceUsed = {}
|
||||
local targetSlots = {}
|
||||
local specialtyBags = {}
|
||||
local emptySlots = {}
|
||||
|
||||
local moveRetries = 0
|
||||
local lastItemID, lockStop, lastDestination, lastMove
|
||||
local moveTracker = {}
|
||||
|
||||
local inventorySlots = {
|
||||
INVTYPE_AMMO = 0,
|
||||
INVTYPE_HEAD = 1,
|
||||
INVTYPE_NECK = 2,
|
||||
INVTYPE_SHOULDER = 3,
|
||||
INVTYPE_BODY = 4,
|
||||
INVTYPE_CHEST = 5,
|
||||
INVTYPE_ROBE = 5,
|
||||
INVTYPE_WAIST = 6,
|
||||
INVTYPE_LEGS = 7,
|
||||
INVTYPE_FEET = 8,
|
||||
INVTYPE_WRIST = 9,
|
||||
INVTYPE_HAND = 10,
|
||||
INVTYPE_FINGER = 11,
|
||||
INVTYPE_TRINKET = 12,
|
||||
INVTYPE_CLOAK = 13,
|
||||
INVTYPE_WEAPON = 14,
|
||||
INVTYPE_SHIELD = 15,
|
||||
INVTYPE_2HWEAPON = 16,
|
||||
INVTYPE_WEAPONMAINHAND = 18,
|
||||
INVTYPE_WEAPONOFFHAND = 19,
|
||||
INVTYPE_HOLDABLE = 20,
|
||||
INVTYPE_RANGED = 21,
|
||||
INVTYPE_THROWN = 22,
|
||||
INVTYPE_RANGEDRIGHT = 23,
|
||||
INVTYPE_RELIC = 24,
|
||||
INVTYPE_TABARD = 25,
|
||||
}
|
||||
|
||||
local conjured_items = {
|
||||
[5512] = true, -- Healthstone
|
||||
[162518] = true, -- Mystical Flask
|
||||
[113509] = true, -- Conjured Mana Bun
|
||||
}
|
||||
|
||||
local safe = {
|
||||
[BANK_CONTAINER] = true,
|
||||
[0] = true
|
||||
}
|
||||
|
||||
local WAIT_TIME = 0.05
|
||||
do
|
||||
local t = 0
|
||||
local frame = CreateFrame('Frame')
|
||||
frame:SetScript('OnUpdate', function(_, elapsed)
|
||||
t = t + (elapsed or 0.01)
|
||||
if t > WAIT_TIME then
|
||||
t = 0
|
||||
B:DoMoves()
|
||||
end
|
||||
end)
|
||||
frame:Hide()
|
||||
B.SortUpdateTimer = frame
|
||||
end
|
||||
|
||||
local function IsGuildBankBag(bagid)
|
||||
return bagid > 50 and bagid <= 58
|
||||
end
|
||||
|
||||
local function UpdateLocation(from, to)
|
||||
if bagIDs[from] == bagIDs[to] and (bagStacks[to] < bagMaxStacks[to]) then
|
||||
local stackSize = bagMaxStacks[to]
|
||||
if (bagStacks[to] + bagStacks[from]) > stackSize then
|
||||
bagStacks[from] = bagStacks[from] - (stackSize - bagStacks[to])
|
||||
bagStacks[to] = stackSize
|
||||
else
|
||||
bagStacks[to] = bagStacks[to] + bagStacks[from]
|
||||
bagStacks[from] = nil
|
||||
bagIDs[from] = nil
|
||||
bagQualities[from] = nil
|
||||
bagMaxStacks[from] = nil
|
||||
end
|
||||
else
|
||||
bagIDs[from], bagIDs[to] = bagIDs[to], bagIDs[from]
|
||||
bagQualities[from], bagQualities[to] = bagQualities[to], bagQualities[from]
|
||||
bagStacks[from], bagStacks[to] = bagStacks[to], bagStacks[from]
|
||||
bagMaxStacks[from], bagMaxStacks[to] = bagMaxStacks[to], bagMaxStacks[from]
|
||||
end
|
||||
end
|
||||
|
||||
local function PrimarySort(a, b)
|
||||
local aName, _, _, aLvl, _, _, _, _, _, _, aPrice = GetItemInfo(bagIDs[a])
|
||||
local bName, _, _, bLvl, _, _, _, _, _, _, bPrice = GetItemInfo(bagIDs[b])
|
||||
|
||||
if aLvl ~= bLvl and aLvl and bLvl then
|
||||
return aLvl > bLvl
|
||||
end
|
||||
if aPrice ~= bPrice and aPrice and bPrice then
|
||||
return aPrice > bPrice
|
||||
end
|
||||
|
||||
if aName and bName then
|
||||
return aName < bName
|
||||
end
|
||||
end
|
||||
|
||||
local function DefaultSort(a, b)
|
||||
local aID = bagIDs[a]
|
||||
local bID = bagIDs[b]
|
||||
|
||||
if not aID or not bID then return aID end
|
||||
|
||||
if bagPetIDs[a] and bagPetIDs[b] then
|
||||
local aName, _, aType = C_PetJournalGetPetInfoBySpeciesID(aID)
|
||||
local bName, _, bType = C_PetJournalGetPetInfoBySpeciesID(bID)
|
||||
|
||||
if aType and bType and aType ~= bType then
|
||||
return aType > bType
|
||||
end
|
||||
|
||||
if aName and bName and aName ~= bName then
|
||||
return aName < bName
|
||||
end
|
||||
end
|
||||
|
||||
local aOrder, bOrder = initialOrder[a], initialOrder[b]
|
||||
|
||||
if aID == bID then
|
||||
local aCount = bagStacks[a]
|
||||
local bCount = bagStacks[b]
|
||||
if aCount and bCount and aCount == bCount then
|
||||
return aOrder < bOrder
|
||||
elseif aCount and bCount then
|
||||
return aCount < bCount
|
||||
end
|
||||
end
|
||||
|
||||
local _, _, _, _, _, _, _, _, aEquipLoc, _, _, aItemClassId, aItemSubClassId = GetItemInfo(aID)
|
||||
local _, _, _, _, _, _, _, _, bEquipLoc, _, _, bItemClassId, bItemSubClassId = GetItemInfo(bID)
|
||||
|
||||
local aRarity, bRarity = bagQualities[a], bagQualities[b]
|
||||
|
||||
if bagPetIDs[a] then
|
||||
aRarity = 1
|
||||
end
|
||||
|
||||
if bagPetIDs[b] then
|
||||
bRarity = 1
|
||||
end
|
||||
|
||||
if conjured_items[aID] then
|
||||
aRarity = -99
|
||||
end
|
||||
|
||||
if conjured_items[bID] then
|
||||
bRarity = -99
|
||||
end
|
||||
|
||||
if aRarity ~= bRarity and aRarity and bRarity then
|
||||
return aRarity > bRarity
|
||||
end
|
||||
|
||||
if aItemClassId ~= bItemClassId then
|
||||
return (aItemClassId or 99) < (bItemClassId or 99)
|
||||
end
|
||||
|
||||
if aItemClassId == LE_ITEM_CLASS_ARMOR or aItemClassId == LE_ITEM_CLASS_WEAPON then
|
||||
aEquipLoc = inventorySlots[aEquipLoc] or -1
|
||||
bEquipLoc = inventorySlots[bEquipLoc] or -1
|
||||
if aEquipLoc == bEquipLoc then
|
||||
return PrimarySort(a, b)
|
||||
end
|
||||
|
||||
if aEquipLoc and bEquipLoc then
|
||||
return aEquipLoc < bEquipLoc
|
||||
end
|
||||
end
|
||||
if aItemClassId == bItemClassId and (aItemSubClassId == bItemSubClassId) then
|
||||
return PrimarySort(a, b)
|
||||
end
|
||||
|
||||
return (aItemSubClassId or 99) < (bItemSubClassId or 99)
|
||||
end
|
||||
|
||||
local function ReverseSort(a, b)
|
||||
return DefaultSort(b, a)
|
||||
end
|
||||
|
||||
local function UpdateSorted(source, destination)
|
||||
for i, bs in pairs(bagSorted) do
|
||||
if bs == source then
|
||||
bagSorted[i] = destination
|
||||
elseif bs == destination then
|
||||
bagSorted[i] = source
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function ShouldMove(source, destination)
|
||||
if destination == source then return end
|
||||
|
||||
if not bagIDs[source] then return end
|
||||
if bagIDs[source] == bagIDs[destination] and bagStacks[source] == bagStacks[destination] then return end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function IterateForwards(bagList, i)
|
||||
i = i + 1
|
||||
local step = 1
|
||||
for _,bag in ipairs(bagList) do
|
||||
local slots = B:GetNumSlots(bag, bagRole)
|
||||
if i > slots + step then
|
||||
step = step + slots
|
||||
else
|
||||
for slot = 1, slots do
|
||||
if step == i then
|
||||
return i, bag, slot
|
||||
end
|
||||
step = step + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
bagRole = nil
|
||||
end
|
||||
|
||||
local function IterateBackwards(bagList, i)
|
||||
i = i + 1
|
||||
local step = 1
|
||||
for ii = #bagList, 1, -1 do
|
||||
local bag = bagList[ii]
|
||||
local slots = B:GetNumSlots(bag, bagRole)
|
||||
if i > slots + step then
|
||||
step = step + slots
|
||||
else
|
||||
for slot=slots, 1, -1 do
|
||||
if step == i then
|
||||
return i, bag, slot
|
||||
end
|
||||
step = step + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
bagRole = nil
|
||||
end
|
||||
|
||||
function B:IterateBags(bagList, reverse, role)
|
||||
bagRole = role
|
||||
return (reverse and IterateBackwards or IterateForwards), bagList, 0
|
||||
end
|
||||
|
||||
function B:GetItemLink(bag, slot)
|
||||
if IsGuildBankBag(bag) then
|
||||
return GetGuildBankItemLink(bag - 50, slot)
|
||||
else
|
||||
return GetContainerItemLink(bag, slot)
|
||||
end
|
||||
end
|
||||
|
||||
function B:GetItemID(bag, slot)
|
||||
if IsGuildBankBag(bag) then
|
||||
local link = B:GetItemLink(bag, slot)
|
||||
return link and tonumber(strmatch(link, 'item:(%d+)'))
|
||||
else
|
||||
return GetContainerItemID(bag, slot)
|
||||
end
|
||||
end
|
||||
|
||||
function B:GetItemInfo(bag, slot)
|
||||
if IsGuildBankBag(bag) then
|
||||
return GetGuildBankItemInfo(bag - 50, slot)
|
||||
else
|
||||
return GetContainerItemInfo(bag, slot)
|
||||
end
|
||||
end
|
||||
|
||||
function B:PickupItem(bag, slot)
|
||||
if IsGuildBankBag(bag) then
|
||||
return PickupGuildBankItem(bag - 50, slot)
|
||||
else
|
||||
return PickupContainerItem(bag, slot)
|
||||
end
|
||||
end
|
||||
|
||||
function B:SplitItem(bag, slot, amount)
|
||||
if IsGuildBankBag(bag) then
|
||||
return SplitGuildBankItem(bag - 50, slot, amount)
|
||||
else
|
||||
return SplitContainerItem(bag, slot, amount)
|
||||
end
|
||||
end
|
||||
|
||||
function B:GetNumSlots(bag)
|
||||
if IsGuildBankBag(bag) then
|
||||
local name, _, canView = GetGuildBankTabInfo(bag - 50)
|
||||
if name and canView then
|
||||
return 98
|
||||
end
|
||||
else
|
||||
return GetContainerNumSlots(bag)
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
function B:ConvertLinkToID(link)
|
||||
if not link then return end
|
||||
|
||||
local item = strmatch(link, 'item:(%d+)')
|
||||
if item then return tonumber(item) end
|
||||
|
||||
local ks = strmatch(link, 'keystone:(%d+)')
|
||||
if ks then return tonumber(ks), nil, true end
|
||||
|
||||
local bp = strmatch(link, 'battlepet:(%d+)')
|
||||
if bp then return tonumber(bp), true end
|
||||
end
|
||||
|
||||
local function DefaultCanMove()
|
||||
return true
|
||||
end
|
||||
|
||||
function B:Encode_BagSlot(bag, slot)
|
||||
return (bag*100) + slot
|
||||
end
|
||||
|
||||
function B:Decode_BagSlot(int)
|
||||
return floor(int/100), int % 100
|
||||
end
|
||||
|
||||
function B:IsPartial(bag, slot)
|
||||
local bagSlot = B:Encode_BagSlot(bag, slot)
|
||||
return ((bagMaxStacks[bagSlot] or 0) - (bagStacks[bagSlot] or 0)) > 0
|
||||
end
|
||||
|
||||
function B:EncodeMove(source, target)
|
||||
return (source * 10000) + target
|
||||
end
|
||||
|
||||
function B:DecodeMove(move)
|
||||
local s = floor(move/10000)
|
||||
local t = move%10000
|
||||
s = (t>9000) and (s+1) or s
|
||||
t = (t>9000) and (t-10000) or t
|
||||
return s, t
|
||||
end
|
||||
|
||||
function B:AddMove(source, destination)
|
||||
UpdateLocation(source, destination)
|
||||
tinsert(moves, 1, B:EncodeMove(source, destination))
|
||||
end
|
||||
|
||||
function B:ScanBags()
|
||||
for _, bag, slot in B:IterateBags(allBags) do
|
||||
local bagSlot = B:Encode_BagSlot(bag, slot)
|
||||
local itemLink = B:GetItemLink(bag, slot)
|
||||
local itemID, isBattlePet, isKeystone = B:ConvertLinkToID(itemLink)
|
||||
if itemID then
|
||||
if isBattlePet then
|
||||
bagPetIDs[bagSlot] = itemID
|
||||
bagMaxStacks[bagSlot] = 1
|
||||
elseif isKeystone then
|
||||
bagMaxStacks[bagSlot] = 1
|
||||
bagQualities[bagSlot] = 4
|
||||
bagStacks[bagSlot] = 1
|
||||
else
|
||||
bagMaxStacks[bagSlot] = select(8, GetItemInfo(itemID))
|
||||
end
|
||||
|
||||
bagIDs[bagSlot] = itemID
|
||||
if not isKeystone then
|
||||
bagQualities[bagSlot] = select(3, GetItemInfo(itemLink))
|
||||
bagStacks[bagSlot] = select(2, B:GetItemInfo(bag, slot))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function B:IsSpecialtyBag(bagID)
|
||||
if safe[bagID] or IsGuildBankBag(bagID) then return false end
|
||||
|
||||
local inventorySlot = ContainerIDToInventoryID(bagID)
|
||||
if not inventorySlot then return false end
|
||||
|
||||
local bag = GetInventoryItemLink('player', inventorySlot)
|
||||
if not bag then return false end
|
||||
|
||||
local family = GetItemFamily(bag)
|
||||
if family == 0 or family == nil then return false end
|
||||
|
||||
return family
|
||||
end
|
||||
|
||||
function B:CanItemGoInBag(bag, slot, targetBag)
|
||||
if IsGuildBankBag(targetBag) then return true end
|
||||
|
||||
local item = bagIDs[B:Encode_BagSlot(bag, slot)]
|
||||
local itemFamily = GetItemFamily(item)
|
||||
if itemFamily and itemFamily > 0 then
|
||||
local equipSlot = select(9, GetItemInfo(item))
|
||||
if equipSlot == 'INVTYPE_BAG' then
|
||||
itemFamily = 1
|
||||
end
|
||||
end
|
||||
local bagFamily = select(2, GetContainerNumFreeSlots(targetBag))
|
||||
if itemFamily then
|
||||
return (bagFamily == 0) or band(itemFamily, bagFamily) > 0
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function B.Compress(...)
|
||||
for i=1, select('#', ...) do
|
||||
local bags = select(i, ...)
|
||||
B.Stack(bags, bags, B.IsPartial)
|
||||
end
|
||||
end
|
||||
|
||||
function B.Stack(sourceBags, targetBags, canMove)
|
||||
if not canMove then canMove = DefaultCanMove end
|
||||
for _, bag, slot in B:IterateBags(targetBags, nil, 'deposit') do
|
||||
local bagSlot = B:Encode_BagSlot(bag, slot)
|
||||
local itemID = bagIDs[bagSlot]
|
||||
|
||||
if itemID and (bagStacks[bagSlot] ~= bagMaxStacks[bagSlot]) then
|
||||
targetItems[itemID] = (targetItems[itemID] or 0) + 1
|
||||
tinsert(targetSlots, bagSlot)
|
||||
end
|
||||
end
|
||||
|
||||
for _, bag, slot in B:IterateBags(sourceBags, true, 'withdraw') do
|
||||
local sourceSlot = B:Encode_BagSlot(bag, slot)
|
||||
local itemID = bagIDs[sourceSlot]
|
||||
if itemID and targetItems[itemID] and canMove(itemID, bag, slot) then
|
||||
for i = #targetSlots, 1, -1 do
|
||||
local targetedSlot = targetSlots[i]
|
||||
if bagIDs[sourceSlot] and bagIDs[targetedSlot] == itemID and targetedSlot ~= sourceSlot and not (bagStacks[targetedSlot] == bagMaxStacks[targetedSlot]) and not sourceUsed[targetedSlot] then
|
||||
B:AddMove(sourceSlot, targetedSlot)
|
||||
sourceUsed[sourceSlot] = true
|
||||
|
||||
if bagStacks[targetedSlot] == bagMaxStacks[targetedSlot] then
|
||||
targetItems[itemID] = (targetItems[itemID] > 1) and (targetItems[itemID] - 1) or nil
|
||||
end
|
||||
if bagStacks[sourceSlot] == 0 then
|
||||
targetItems[itemID] = (targetItems[itemID] > 1) and (targetItems[itemID] - 1) or nil
|
||||
break
|
||||
end
|
||||
if not targetItems[itemID] then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wipe(targetItems)
|
||||
wipe(targetSlots)
|
||||
wipe(sourceUsed)
|
||||
end
|
||||
|
||||
local blackListedSlots = {}
|
||||
local blackList = {}
|
||||
local blackListQueries = {}
|
||||
function B:BuildBlacklist(...)
|
||||
for entry in pairs(...) do
|
||||
local itemName = GetItemInfo(entry)
|
||||
|
||||
if itemName then
|
||||
blackList[itemName] = true
|
||||
elseif entry ~= '' then
|
||||
if strfind(entry, '%[') and strfind(entry, '%]') then
|
||||
--For some reason the entry was not treated as a valid item. Extract the item name.
|
||||
entry = strmatch(entry, '%[(.*)%]')
|
||||
end
|
||||
blackListQueries[#blackListQueries+1] = entry
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function B.Sort(bags, sorter, invertDirection)
|
||||
if not sorter then sorter = invertDirection and ReverseSort or DefaultSort end
|
||||
|
||||
--Wipe tables before we begin
|
||||
wipe(blackList)
|
||||
wipe(blackListQueries)
|
||||
wipe(blackListedSlots)
|
||||
|
||||
--Build blacklist of items based on the profile and global list
|
||||
B:BuildBlacklist(B.db.ignoredItems)
|
||||
B:BuildBlacklist(E.global.bags.ignoredItems)
|
||||
|
||||
for i, bag, slot in B:IterateBags(bags, nil, 'both') do
|
||||
local bagSlot = B:Encode_BagSlot(bag, slot)
|
||||
local link = B:GetItemLink(bag, slot)
|
||||
|
||||
if link then
|
||||
if blackList[GetItemInfo(link)] then
|
||||
blackListedSlots[bagSlot] = true
|
||||
end
|
||||
|
||||
if not blackListedSlots[bagSlot] then
|
||||
local method
|
||||
for _,itemsearchquery in pairs(blackListQueries) do
|
||||
method = Search.Matches
|
||||
if Search.Filters.tipPhrases.keywords[itemsearchquery] then
|
||||
method = Search.TooltipPhrase
|
||||
itemsearchquery = Search.Filters.tipPhrases.keywords[itemsearchquery]
|
||||
end
|
||||
local success, result = pcall(method, Search, link, itemsearchquery)
|
||||
if success and result then
|
||||
blackListedSlots[bagSlot] = result
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not blackListedSlots[bagSlot] then
|
||||
initialOrder[bagSlot] = i
|
||||
tinsert(bagSorted, bagSlot)
|
||||
end
|
||||
end
|
||||
|
||||
sort(bagSorted, sorter)
|
||||
|
||||
local passNeeded = true
|
||||
while passNeeded do
|
||||
passNeeded = false
|
||||
local i = 1
|
||||
for _, bag, slot in B:IterateBags(bags, nil, 'both') do
|
||||
local destination = B:Encode_BagSlot(bag, slot)
|
||||
local source = bagSorted[i]
|
||||
|
||||
if not blackListedSlots[destination] then
|
||||
if ShouldMove(source, destination) then
|
||||
if not (bagLocked[source] or bagLocked[destination]) then
|
||||
B:AddMove(source, destination)
|
||||
UpdateSorted(source, destination)
|
||||
bagLocked[source] = true
|
||||
bagLocked[destination] = true
|
||||
else
|
||||
passNeeded = true
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
wipe(bagLocked)
|
||||
end
|
||||
|
||||
wipe(bagSorted)
|
||||
wipe(initialOrder)
|
||||
end
|
||||
|
||||
function B.FillBags(from, to)
|
||||
B.Stack(from, to)
|
||||
for _, bag in ipairs(to) do
|
||||
if B:IsSpecialtyBag(bag) then
|
||||
tinsert(specialtyBags, bag)
|
||||
end
|
||||
end
|
||||
if #specialtyBags > 0 then
|
||||
B:Fill(from, specialtyBags)
|
||||
end
|
||||
|
||||
B.Fill(from, to)
|
||||
wipe(specialtyBags)
|
||||
end
|
||||
|
||||
function B.Fill(sourceBags, targetBags, reverse, canMove)
|
||||
if not canMove then canMove = DefaultCanMove end
|
||||
|
||||
--Wipe tables before we begin
|
||||
wipe(blackList)
|
||||
wipe(blackListedSlots)
|
||||
|
||||
--Build blacklist of items based on the profile and global list
|
||||
B:BuildBlacklist(B.db.ignoredItems)
|
||||
B:BuildBlacklist(E.global.bags.ignoredItems)
|
||||
|
||||
for _, bag, slot in B:IterateBags(targetBags, reverse, 'deposit') do
|
||||
local bagSlot = B:Encode_BagSlot(bag, slot)
|
||||
if not bagIDs[bagSlot] then
|
||||
tinsert(emptySlots, bagSlot)
|
||||
end
|
||||
end
|
||||
|
||||
for _, bag, slot in B:IterateBags(sourceBags, not reverse, 'withdraw') do
|
||||
if #emptySlots == 0 then break end
|
||||
local bagSlot = B:Encode_BagSlot(bag, slot)
|
||||
local targetBag = B:Decode_BagSlot(emptySlots[1])
|
||||
local link = B:GetItemLink(bag, slot)
|
||||
|
||||
if link and blackList[GetItemInfo(link)] then
|
||||
blackListedSlots[bagSlot] = true
|
||||
end
|
||||
|
||||
if bagIDs[bagSlot] and B:CanItemGoInBag(bag, slot, targetBag) and canMove(bagIDs[bagSlot], bag, slot) and not blackListedSlots[bagSlot] then
|
||||
B:AddMove(bagSlot, tremove(emptySlots, 1))
|
||||
end
|
||||
end
|
||||
wipe(emptySlots)
|
||||
end
|
||||
|
||||
function B.SortBags(...)
|
||||
for i=1, select('#', ...) do
|
||||
local bags = select(i, ...)
|
||||
for _, slotNum in ipairs(bags) do
|
||||
local bagType = B:IsSpecialtyBag(slotNum)
|
||||
if bagType == false then bagType = 'Normal' end
|
||||
if not bagCache[bagType] then bagCache[bagType] = {} end
|
||||
tinsert(bagCache[bagType], slotNum)
|
||||
end
|
||||
|
||||
for bagType, sortedBags in pairs(bagCache) do
|
||||
if bagType ~= 'Normal' then
|
||||
B.Stack(sortedBags, sortedBags, B.IsPartial)
|
||||
B.Stack(bagCache.Normal, sortedBags)
|
||||
B.Fill(bagCache.Normal, sortedBags, B.db.sortInverted)
|
||||
B.Sort(sortedBags, nil, B.db.sortInverted)
|
||||
wipe(sortedBags)
|
||||
end
|
||||
end
|
||||
|
||||
if bagCache.Normal then
|
||||
B.Stack(bagCache.Normal, bagCache.Normal, B.IsPartial)
|
||||
B.Sort(bagCache.Normal, nil, B.db.sortInverted)
|
||||
wipe(bagCache.Normal)
|
||||
end
|
||||
wipe(bagCache)
|
||||
wipe(bagGroups)
|
||||
end
|
||||
end
|
||||
|
||||
function B:StartStacking()
|
||||
wipe(bagMaxStacks)
|
||||
wipe(bagStacks)
|
||||
wipe(bagIDs)
|
||||
wipe(bagQualities)
|
||||
wipe(bagPetIDs)
|
||||
wipe(moveTracker)
|
||||
|
||||
if #moves > 0 then
|
||||
B.SortUpdateTimer:Show()
|
||||
else
|
||||
B:StopStacking()
|
||||
end
|
||||
end
|
||||
|
||||
function B:RegisterUpdateDelayed()
|
||||
local shouldUpdateFade
|
||||
|
||||
for _, bagFrame in pairs(B.BagFrames) do
|
||||
if bagFrame.registerUpdate then
|
||||
B:UpdateAllSlots(bagFrame)
|
||||
|
||||
bagFrame:RegisterEvent('BAG_UPDATE')
|
||||
bagFrame:RegisterEvent('BAG_UPDATE_COOLDOWN')
|
||||
|
||||
for _, event in pairs(bagFrame.events) do
|
||||
bagFrame:RegisterEvent(event)
|
||||
end
|
||||
|
||||
bagFrame.registerUpdate = nil
|
||||
shouldUpdateFade = true -- we should refresh the bag search after sorting
|
||||
end
|
||||
end
|
||||
|
||||
if shouldUpdateFade then
|
||||
B:RefreshSearch() -- this will clear the bag lock look during a sort
|
||||
end
|
||||
end
|
||||
|
||||
function B:StopStacking(message, noUpdate)
|
||||
wipe(moves)
|
||||
wipe(moveTracker)
|
||||
moveRetries, lastItemID, lockStop, lastDestination, lastMove = 0, nil, nil, nil, nil
|
||||
|
||||
B.SortUpdateTimer:Hide()
|
||||
|
||||
if not noUpdate then
|
||||
--Add a delayed update call, as BAG_UPDATE fires slightly delayed
|
||||
-- and we don't want the last few unneeded updates to be catched
|
||||
E:Delay(0.6, B.RegisterUpdateDelayed)
|
||||
end
|
||||
|
||||
if message then
|
||||
E:Print(message)
|
||||
end
|
||||
end
|
||||
|
||||
function B:DoMove(move)
|
||||
if GetCursorInfo() == 'item' then
|
||||
return false, 'cursorhasitem'
|
||||
end
|
||||
|
||||
local source, target = B:DecodeMove(move)
|
||||
local sourceBag, sourceSlot = B:Decode_BagSlot(source)
|
||||
local targetBag, targetSlot = B:Decode_BagSlot(target)
|
||||
|
||||
local _, sourceCount, sourceLocked = B:GetItemInfo(sourceBag, sourceSlot)
|
||||
local _, targetCount, targetLocked = B:GetItemInfo(targetBag, targetSlot)
|
||||
|
||||
if sourceLocked or targetLocked then
|
||||
return false, 'source/target_locked'
|
||||
end
|
||||
|
||||
local sourceItemID = B:GetItemID(sourceBag, sourceSlot)
|
||||
local targetItemID = B:GetItemID(targetBag, targetSlot)
|
||||
|
||||
if not sourceItemID then
|
||||
if moveTracker[source] then
|
||||
return false, 'move incomplete'
|
||||
else
|
||||
return B:StopStacking(L["Confused.. Try Again!"])
|
||||
end
|
||||
end
|
||||
|
||||
local stackSize = select(8, GetItemInfo(sourceItemID))
|
||||
if sourceItemID == targetItemID and (targetCount ~= stackSize) and ((targetCount + sourceCount) > stackSize) then
|
||||
B:SplitItem(sourceBag, sourceSlot, stackSize - targetCount)
|
||||
else
|
||||
B:PickupItem(sourceBag, sourceSlot)
|
||||
end
|
||||
|
||||
if GetCursorInfo() == 'item' then
|
||||
B:PickupItem(targetBag, targetSlot)
|
||||
end
|
||||
|
||||
local sourceGuild = IsGuildBankBag(sourceBag)
|
||||
local targetGuild = IsGuildBankBag(targetBag)
|
||||
|
||||
if sourceGuild then
|
||||
QueryGuildBankTab(sourceBag - 50)
|
||||
end
|
||||
if targetGuild then
|
||||
QueryGuildBankTab(targetBag - 50)
|
||||
end
|
||||
|
||||
return true, sourceItemID, source, targetItemID, target, sourceGuild or targetGuild
|
||||
end
|
||||
|
||||
function B:DoMoves()
|
||||
if InCombatLockdown() then
|
||||
return B:StopStacking(L["Confused.. Try Again!"])
|
||||
end
|
||||
|
||||
local cursorType, cursorItemID = GetCursorInfo()
|
||||
if cursorType == 'item' and cursorItemID then
|
||||
if lastItemID ~= cursorItemID then
|
||||
return B:StopStacking(L["Confused.. Try Again!"])
|
||||
end
|
||||
|
||||
if moveRetries < 100 then
|
||||
local targetBag, targetSlot = B:Decode_BagSlot(lastDestination)
|
||||
local _, _, targetLocked = B:GetItemInfo(targetBag, targetSlot)
|
||||
if not targetLocked then
|
||||
B:PickupItem(targetBag, targetSlot)
|
||||
WAIT_TIME = 0.1
|
||||
lockStop = GetTime()
|
||||
moveRetries = moveRetries + 1
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if lockStop then
|
||||
for slot, itemID in pairs(moveTracker) do
|
||||
local actualItemID = B:GetItemID(B:Decode_BagSlot(slot))
|
||||
if actualItemID ~= itemID then
|
||||
WAIT_TIME = 0.1
|
||||
if (GetTime() - lockStop) > MAX_MOVE_TIME then
|
||||
if lastMove and moveRetries < 100 then
|
||||
local success, moveID, moveSource, targetID, moveTarget, wasGuild = B:DoMove(lastMove)
|
||||
WAIT_TIME = wasGuild and 0.5 or 0.1
|
||||
|
||||
if not success then
|
||||
lockStop = GetTime()
|
||||
moveRetries = moveRetries + 1
|
||||
return
|
||||
end
|
||||
|
||||
moveTracker[moveSource] = targetID
|
||||
moveTracker[moveTarget] = moveID
|
||||
lastDestination = moveTarget
|
||||
-- lastMove = moves[i] --Where does 'i' come from???
|
||||
lastItemID = moveID
|
||||
-- tremove(moves, i) --Where does 'i' come from???
|
||||
return
|
||||
end
|
||||
|
||||
B:StopStacking()
|
||||
return
|
||||
end
|
||||
return --give processing time to happen
|
||||
end
|
||||
moveTracker[slot] = nil
|
||||
end
|
||||
end
|
||||
|
||||
lastItemID, lockStop, lastDestination, lastMove = nil, nil, nil, nil
|
||||
wipe(moveTracker)
|
||||
|
||||
local success, moveID, targetID, moveSource, moveTarget, wasGuild
|
||||
if #moves > 0 then
|
||||
for i = #moves, 1, -1 do
|
||||
success, moveID, moveSource, targetID, moveTarget, wasGuild = B:DoMove(moves[i])
|
||||
if not success then
|
||||
WAIT_TIME = wasGuild and 0.3 or 0.1
|
||||
lockStop = GetTime()
|
||||
return
|
||||
end
|
||||
moveTracker[moveSource] = targetID
|
||||
moveTracker[moveTarget] = moveID
|
||||
lastDestination = moveTarget
|
||||
lastMove = moves[i]
|
||||
lastItemID = moveID
|
||||
tremove(moves, i)
|
||||
|
||||
if moves[i-1] then
|
||||
WAIT_TIME = wasGuild and 0.3 or 0
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
B:StopStacking()
|
||||
end
|
||||
|
||||
function B:GetGroup(id)
|
||||
if strmatch(id, '^[-%d,]+$') then
|
||||
local bags = {}
|
||||
for b in gmatch(id, '-?%d+') do
|
||||
tinsert(bags, tonumber(b))
|
||||
end
|
||||
return bags
|
||||
end
|
||||
return coreGroups[id]
|
||||
end
|
||||
|
||||
function B:CommandDecorator(func, groupsDefaults)
|
||||
return function(groups)
|
||||
if B.SortUpdateTimer:IsShown() then
|
||||
B:StopStacking(L["Already Running.. Bailing Out!"], true)
|
||||
return
|
||||
end
|
||||
|
||||
wipe(bagGroups)
|
||||
if not groups or #groups == 0 then
|
||||
groups = groupsDefaults
|
||||
end
|
||||
for bags in (groups or ''):gmatch('%S+') do
|
||||
if bags == 'guild' then
|
||||
bags = B:GetGroup(bags)
|
||||
if bags then
|
||||
tinsert(bagGroups, {bags[GetCurrentGuildBankTab()]})
|
||||
end
|
||||
else
|
||||
bags = B:GetGroup(bags)
|
||||
if bags then
|
||||
tinsert(bagGroups, bags)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
B:ScanBags()
|
||||
if func(unpack(bagGroups)) == false then
|
||||
return
|
||||
end
|
||||
wipe(bagGroups)
|
||||
B:StartStacking()
|
||||
end
|
||||
end
|
||||
195
Modules/Blizzard/AlertFrame.lua
Normal file
195
Modules/Blizzard/AlertFrame.lua
Normal file
@@ -0,0 +1,195 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
local Misc = E:GetModule('Misc')
|
||||
|
||||
local _G = _G
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local CreateFrame = CreateFrame
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
|
||||
local POSITION, ANCHOR_POINT, YOFFSET = 'TOP', 'BOTTOM', -10
|
||||
|
||||
function E:PostAlertMove()
|
||||
local AlertFrameMover = _G.AlertFrameMover
|
||||
local AlertFrameHolder = _G.AlertFrameHolder
|
||||
|
||||
local _, y = AlertFrameMover:GetCenter()
|
||||
local screenHeight = E.UIParent:GetTop()
|
||||
if y > (screenHeight / 2) then
|
||||
POSITION = 'TOP'
|
||||
ANCHOR_POINT = 'BOTTOM'
|
||||
YOFFSET = -10
|
||||
AlertFrameMover:SetText(AlertFrameMover.textString..' (Grow Down)')
|
||||
else
|
||||
POSITION = 'BOTTOM'
|
||||
ANCHOR_POINT = 'TOP'
|
||||
YOFFSET = 10
|
||||
AlertFrameMover:SetText(AlertFrameMover.textString..' (Grow Up)')
|
||||
end
|
||||
|
||||
local AlertFrame = _G.AlertFrame
|
||||
local GroupLootContainer = _G.GroupLootContainer
|
||||
|
||||
local rollBars = Misc.RollBars
|
||||
if E.private.general.lootRoll then
|
||||
local lastframe, lastShownFrame
|
||||
for i, frame in pairs(rollBars) do
|
||||
frame:ClearAllPoints()
|
||||
if i ~= 1 then
|
||||
if POSITION == 'TOP' then
|
||||
frame:Point('TOP', lastframe, 'BOTTOM', 0, -4)
|
||||
else
|
||||
frame:Point('BOTTOM', lastframe, 'TOP', 0, 4)
|
||||
end
|
||||
else
|
||||
if POSITION == 'TOP' then
|
||||
frame:Point('TOP', AlertFrameHolder, 'BOTTOM', 0, -4)
|
||||
else
|
||||
frame:Point('BOTTOM', AlertFrameHolder, 'TOP', 0, 4)
|
||||
end
|
||||
end
|
||||
lastframe = frame
|
||||
|
||||
if frame:IsShown() then
|
||||
lastShownFrame = frame
|
||||
end
|
||||
end
|
||||
|
||||
AlertFrame:ClearAllPoints()
|
||||
GroupLootContainer:ClearAllPoints()
|
||||
if lastShownFrame then
|
||||
AlertFrame:SetAllPoints(lastShownFrame)
|
||||
GroupLootContainer:Point(POSITION, lastShownFrame, ANCHOR_POINT, 0, YOFFSET)
|
||||
else
|
||||
AlertFrame:SetAllPoints(AlertFrameHolder)
|
||||
GroupLootContainer:Point(POSITION, AlertFrameHolder, ANCHOR_POINT, 0, YOFFSET)
|
||||
end
|
||||
if GroupLootContainer:IsShown() then
|
||||
B.GroupLootContainer_Update(GroupLootContainer)
|
||||
end
|
||||
else
|
||||
AlertFrame:ClearAllPoints()
|
||||
AlertFrame:SetAllPoints(AlertFrameHolder)
|
||||
GroupLootContainer:ClearAllPoints()
|
||||
GroupLootContainer:Point(POSITION, AlertFrameHolder, ANCHOR_POINT, 0, YOFFSET)
|
||||
if GroupLootContainer:IsShown() then
|
||||
B.GroupLootContainer_Update(GroupLootContainer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function B:AdjustAnchors(relativeAlert)
|
||||
if self.alertFrame:IsShown() then
|
||||
self.alertFrame:ClearAllPoints()
|
||||
self.alertFrame:Point(POSITION, relativeAlert, ANCHOR_POINT, 0, YOFFSET)
|
||||
return self.alertFrame
|
||||
end
|
||||
return relativeAlert
|
||||
end
|
||||
|
||||
function B:AdjustAnchorsNonAlert(relativeAlert)
|
||||
if self.anchorFrame:IsShown() then
|
||||
self.anchorFrame:ClearAllPoints()
|
||||
self.anchorFrame:Point(POSITION, relativeAlert, ANCHOR_POINT, 0, YOFFSET)
|
||||
return self.anchorFrame
|
||||
end
|
||||
return relativeAlert
|
||||
end
|
||||
|
||||
function B:AdjustQueuedAnchors(relativeAlert)
|
||||
for alertFrame in self.alertFramePool:EnumerateActive() do
|
||||
alertFrame:ClearAllPoints()
|
||||
alertFrame:Point(POSITION, relativeAlert, ANCHOR_POINT, 0, YOFFSET)
|
||||
relativeAlert = alertFrame
|
||||
end
|
||||
return relativeAlert
|
||||
end
|
||||
|
||||
function B:GroupLootContainer_Update()
|
||||
local lastIdx
|
||||
|
||||
for i=1, self.maxIndex do
|
||||
local frame = self.rollFrames[i]
|
||||
if frame then
|
||||
frame:ClearAllPoints()
|
||||
|
||||
local prevFrame = self.rollFrames[i-1]
|
||||
if prevFrame and prevFrame ~= frame then
|
||||
frame:Point(POSITION, prevFrame, ANCHOR_POINT, 0, YOFFSET)
|
||||
else
|
||||
frame:Point(POSITION, self, POSITION, 0, YOFFSET)
|
||||
end
|
||||
|
||||
lastIdx = i
|
||||
end
|
||||
end
|
||||
|
||||
if lastIdx then
|
||||
self:Height(self.reservedSize * lastIdx)
|
||||
self:Show()
|
||||
else
|
||||
self:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local function AlertSubSystem_AdjustPosition(alertFrameSubSystem)
|
||||
if alertFrameSubSystem.alertFramePool then --queued alert system
|
||||
alertFrameSubSystem.AdjustAnchors = B.AdjustQueuedAnchors
|
||||
elseif not alertFrameSubSystem.anchorFrame then --simple alert system
|
||||
alertFrameSubSystem.AdjustAnchors = B.AdjustAnchors
|
||||
elseif alertFrameSubSystem.anchorFrame then --anchor frame system
|
||||
alertFrameSubSystem.AdjustAnchors = B.AdjustAnchorsNonAlert
|
||||
end
|
||||
end
|
||||
|
||||
function B:AlertMovers()
|
||||
local AlertFrameHolder = CreateFrame('Frame', 'AlertFrameHolder', E.UIParent)
|
||||
AlertFrameHolder:Size(180, 20)
|
||||
AlertFrameHolder:Point('TOP', E.UIParent, 'TOP', -1, -18)
|
||||
|
||||
_G.GroupLootContainer:EnableMouse(false) -- Prevent this weird non-clickable area stuff since 8.1; Monitor this, as it may cause addon compatibility.
|
||||
_G.UIPARENT_MANAGED_FRAME_POSITIONS.GroupLootContainer = nil
|
||||
E:CreateMover(AlertFrameHolder, 'AlertFrameMover', L["Loot / Alert Frames"], nil, nil, E.PostAlertMove, nil, nil, 'general,blizzUIImprovements')
|
||||
|
||||
--Replace AdjustAnchors functions to allow alerts to grow down if needed.
|
||||
--We will need to keep an eye on this in case it taints. It shouldn't, but you never know.
|
||||
for _, alertFrameSubSystem in ipairs(_G.AlertFrame.alertFrameSubSystems) do
|
||||
AlertSubSystem_AdjustPosition(alertFrameSubSystem)
|
||||
end
|
||||
|
||||
--This should catch any alert systems that are created by other addons
|
||||
hooksecurefunc(_G.AlertFrame, 'AddAlertFrameSubSystem', function(_, alertFrameSubSystem)
|
||||
AlertSubSystem_AdjustPosition(alertFrameSubSystem)
|
||||
end)
|
||||
|
||||
self:SecureHook(_G.AlertFrame, 'UpdateAnchors', E.PostAlertMove)
|
||||
hooksecurefunc('GroupLootContainer_Update', B.GroupLootContainer_Update)
|
||||
|
||||
--[=[ Code you can use for alert testing
|
||||
--Queued Alerts:
|
||||
/run AchievementAlertSystem:AddAlert(5192)
|
||||
/run CriteriaAlertSystem:AddAlert(9023, 'Doing great!')
|
||||
/run LootAlertSystem:AddAlert('\124cffa335ee\124Hitem:18832::::::::::\124h[Brutality Blade]\124h\124r', 1, 1, 1, 1, false, false, 0, false, false)
|
||||
/run LootUpgradeAlertSystem:AddAlert('\124cffa335ee\124Hitem:18832::::::::::\124h[Brutality Blade]\124h\124r', 1, 1, 1, nil, nil, false)
|
||||
/run MoneyWonAlertSystem:AddAlert(81500)
|
||||
/run NewRecipeLearnedAlertSystem:AddAlert(204)
|
||||
|
||||
--Simple Alerts
|
||||
/run GuildChallengeAlertSystem:AddAlert(3, 2, 5)
|
||||
/run InvasionAlertSystem:AddAlert(678, DUNGEON_FLOOR_THENEXUS1, true, 1, 1)
|
||||
/run WorldQuestCompleteAlertSystem:AddAlert(AlertFrameMixin:BuildQuestData(42114))
|
||||
/run GarrisonBuildingAlertSystem:AddAlert(GARRISON_CACHE)
|
||||
/run GarrisonFollowerAlertSystem:AddAlert(204, 'Ben Stone', 90, 3, false)
|
||||
/run GarrisonMissionAlertSystem:AddAlert(681) (Requires a mission ID that is in your mission list.)
|
||||
/run GarrisonShipFollowerAlertSystem:AddAlert(592, 'Test', 'Transport', 'GarrBuilding_Barracks_1_H', 3, 2, 1)
|
||||
/run LegendaryItemAlertSystem:AddAlert('\124cffa335ee\124Hitem:18832::::::::::\124h[Brutality Blade]\124h\124r')
|
||||
/run EntitlementDeliveredAlertSystem:AddAlert('', [[Interface\Icons\Ability_pvp_gladiatormedallion]], TRINKET0SLOT, 214)
|
||||
/run RafRewardDeliveredAlertSystem:AddAlert('', [[Interface\Icons\Ability_pvp_gladiatormedallion]], TRINKET0SLOT, 214)
|
||||
/run DigsiteCompleteAlertSystem:AddAlert('Human')
|
||||
|
||||
--Bonus Rolls
|
||||
/run BonusRollFrame_CloseBonusRoll()
|
||||
/run BonusRollFrame_StartBonusRoll(242969,'test',10,515,1273,14) --515 is darkmoon token, change to another currency id you have
|
||||
]=]
|
||||
end
|
||||
178
Modules/Blizzard/AltPower.lua
Normal file
178
Modules/Blizzard/AltPower.lua
Normal file
@@ -0,0 +1,178 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local floor = floor
|
||||
local format = format
|
||||
local CreateFrame = CreateFrame
|
||||
local UnitPowerMax = UnitPowerMax
|
||||
local UnitPower = UnitPower
|
||||
local GetUnitPowerBarInfo = GetUnitPowerBarInfo
|
||||
local GetUnitPowerBarStrings = GetUnitPowerBarStrings
|
||||
|
||||
local function updateTooltip(self)
|
||||
if _G.GameTooltip:IsForbidden() then return end
|
||||
|
||||
if self.powerName and self.powerTooltip then
|
||||
_G.GameTooltip:SetText(self.powerName, 1, 1, 1)
|
||||
_G.GameTooltip:AddLine(self.powerTooltip, nil, nil, nil, 1)
|
||||
_G.GameTooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function onEnter(self)
|
||||
if (not self:IsVisible()) or _G.GameTooltip:IsForbidden() then return end
|
||||
|
||||
_G.GameTooltip:ClearAllPoints()
|
||||
_G.GameTooltip_SetDefaultAnchor(_G.GameTooltip, self)
|
||||
updateTooltip(self)
|
||||
end
|
||||
|
||||
local function onLeave()
|
||||
_G.GameTooltip:Hide()
|
||||
end
|
||||
|
||||
function B:SetAltPowerBarText(text, name, value, max, percent)
|
||||
local textFormat = E.db.general.altPowerBar.textFormat
|
||||
if textFormat == 'NONE' or not textFormat then
|
||||
text:SetText('')
|
||||
elseif textFormat == 'NAME' then
|
||||
text:SetText(format('%s', name))
|
||||
elseif textFormat == 'NAMEPERC' then
|
||||
text:SetText(format('%s: %s%%', name, percent))
|
||||
elseif textFormat == 'NAMECURMAX' then
|
||||
text:SetText(format('%s: %s / %s', name, value, max))
|
||||
elseif textFormat == 'NAMECURMAXPERC' then
|
||||
text:SetText(format('%s: %s / %s - %s%%', name, value, max, percent))
|
||||
elseif textFormat == 'PERCENT' then
|
||||
text:SetText(format('%s%%', percent))
|
||||
elseif textFormat == 'CURMAX' then
|
||||
text:SetText(format('%s / %s', value, max))
|
||||
elseif textFormat == 'CURMAXPERC' then
|
||||
text:SetText(format('%s / %s - %s%%', value, max, percent))
|
||||
end
|
||||
end
|
||||
|
||||
function B:PositionAltPowerBar()
|
||||
local holder = CreateFrame('Frame', 'AltPowerBarHolder', E.UIParent)
|
||||
holder:Point('TOP', E.UIParent, 'TOP', -1, -36)
|
||||
holder:Size(128, 50)
|
||||
|
||||
_G.PlayerPowerBarAlt:ClearAllPoints()
|
||||
_G.PlayerPowerBarAlt:Point('CENTER', holder, 'CENTER')
|
||||
_G.PlayerPowerBarAlt:SetParent(holder)
|
||||
_G.PlayerPowerBarAlt:SetMovable(true)
|
||||
_G.PlayerPowerBarAlt:SetUserPlaced(true)
|
||||
_G.UIPARENT_MANAGED_FRAME_POSITIONS.PlayerPowerBarAlt = nil
|
||||
|
||||
E:CreateMover(holder, 'AltPowerBarMover', L["Alternative Power"], nil, nil, nil, nil, nil, 'general,alternativePowerGroup')
|
||||
end
|
||||
|
||||
function B:UpdateAltPowerBarColors()
|
||||
local bar = _G.ElvUI_AltPowerBar
|
||||
|
||||
if E.db.general.altPowerBar.statusBarColorGradient then
|
||||
if bar.colorGradientR and bar.colorGradientG and bar.colorGradientB then
|
||||
bar:SetStatusBarColor(bar.colorGradientR, bar.colorGradientG, bar.colorGradientB)
|
||||
elseif bar.powerValue then
|
||||
local power, maxPower = bar.powerValue or 0, bar.powerMaxValue or 0
|
||||
local value = (maxPower > 0 and power / maxPower) or 0
|
||||
bar.colorGradientValue = value
|
||||
|
||||
local r, g, b = E:ColorGradient(value, 0.8,0,0, 0.8,0.8,0, 0,0.8,0)
|
||||
bar.colorGradientR, bar.colorGradientG, bar.colorGradientB = r, g, b
|
||||
|
||||
bar:SetStatusBarColor(r, g, b)
|
||||
else
|
||||
bar:SetStatusBarColor(0.6, 0.6, 0.6) -- uh, fallback!
|
||||
end
|
||||
else
|
||||
local color = E.db.general.altPowerBar.statusBarColor
|
||||
bar:SetStatusBarColor(color.r, color.g, color.b)
|
||||
end
|
||||
end
|
||||
|
||||
function B:UpdateAltPowerBarSettings()
|
||||
local bar = _G.ElvUI_AltPowerBar
|
||||
local db = E.db.general.altPowerBar
|
||||
|
||||
bar:Size(db.width or 250, db.height or 20)
|
||||
bar:SetStatusBarTexture(LSM:Fetch('statusbar', db.statusBar))
|
||||
bar.text:FontTemplate(LSM:Fetch('font', db.font), db.fontSize or 12, db.fontOutline or 'OUTLINE')
|
||||
_G.AltPowerBarHolder:Size(bar.backdrop:GetSize())
|
||||
|
||||
E:SetSmoothing(bar, db.smoothbars)
|
||||
|
||||
B:SetAltPowerBarText(bar.text, bar.powerName or '', bar.powerValue or 0, bar.powerMaxValue or 0, bar.powerPercent or 0)
|
||||
end
|
||||
|
||||
function B:UpdateAltPowerBar()
|
||||
_G.PlayerPowerBarAlt:UnregisterAllEvents()
|
||||
_G.PlayerPowerBarAlt:Hide()
|
||||
|
||||
local barInfo = GetUnitPowerBarInfo('player');
|
||||
local powerName, powerTooltip = GetUnitPowerBarStrings('player');
|
||||
if barInfo then
|
||||
local power = UnitPower('player', _G.ALTERNATE_POWER_INDEX)
|
||||
local maxPower = UnitPowerMax('player', _G.ALTERNATE_POWER_INDEX) or 0
|
||||
local perc = (maxPower > 0 and floor(power / maxPower * 100)) or 0
|
||||
|
||||
self.powerMaxValue = maxPower
|
||||
self.powerName = powerName
|
||||
self.powerPercent = perc
|
||||
self.powerTooltip = powerTooltip
|
||||
self.powerValue = power
|
||||
|
||||
self:Show()
|
||||
self:SetMinMaxValues(barInfo.minPower, maxPower)
|
||||
self:SetValue(power)
|
||||
|
||||
if E.db.general.altPowerBar.statusBarColorGradient then
|
||||
local value = (maxPower > 0 and power / maxPower) or 0
|
||||
self.colorGradientValue = value
|
||||
|
||||
local r, g, b = E:ColorGradient(value, 0.8,0,0, 0.8,0.8,0, 0,0.8,0)
|
||||
self.colorGradientR, self.colorGradientG, self.colorGradientB = r, g, b
|
||||
|
||||
self:SetStatusBarColor(r, g, b)
|
||||
end
|
||||
|
||||
B:SetAltPowerBarText(self.text, powerName or '', power or 0, maxPower, perc)
|
||||
else
|
||||
self.powerMaxValue = nil
|
||||
self.powerName = nil
|
||||
self.powerPercent = nil
|
||||
self.powerTooltip = nil
|
||||
self.powerValue = nil
|
||||
|
||||
self:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function B:SkinAltPowerBar()
|
||||
if not E.db.general.altPowerBar.enable then return end
|
||||
|
||||
local powerbar = CreateFrame('StatusBar', 'ElvUI_AltPowerBar', E.UIParent)
|
||||
powerbar:CreateBackdrop(nil, true)
|
||||
powerbar:SetMinMaxValues(0, 200)
|
||||
powerbar:Point('CENTER', _G.AltPowerBarHolder)
|
||||
powerbar:Hide()
|
||||
|
||||
powerbar:SetScript('OnEnter', onEnter)
|
||||
powerbar:SetScript('OnLeave', onLeave)
|
||||
|
||||
powerbar.text = powerbar:CreateFontString(nil, 'OVERLAY')
|
||||
powerbar.text:Point('CENTER', powerbar, 'CENTER')
|
||||
powerbar.text:SetJustifyH('CENTER')
|
||||
|
||||
B:UpdateAltPowerBarSettings()
|
||||
B:UpdateAltPowerBarColors()
|
||||
|
||||
--Event handling
|
||||
powerbar:RegisterEvent('UNIT_POWER_UPDATE')
|
||||
powerbar:RegisterEvent('UNIT_POWER_BAR_SHOW')
|
||||
powerbar:RegisterEvent('UNIT_POWER_BAR_HIDE')
|
||||
powerbar:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
powerbar:SetScript('OnEvent', B.UpdateAltPowerBar)
|
||||
end
|
||||
120
Modules/Blizzard/Blizzard.lua
Normal file
120
Modules/Blizzard/Blizzard.lua
Normal file
@@ -0,0 +1,120 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
local Skins = E:GetModule('Skins')
|
||||
local TT = E:GetModule('Tooltip')
|
||||
|
||||
local _G = _G
|
||||
local CreateFrame = CreateFrame
|
||||
local GetQuestLogRewardXP = GetQuestLogRewardXP
|
||||
local GetRewardXP = GetRewardXP
|
||||
local IsAddOnLoaded = IsAddOnLoaded
|
||||
local UnitXP = UnitXP
|
||||
local UnitXPMax = UnitXPMax
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local C_QuestLog_ShouldShowQuestRewards = C_QuestLog.ShouldShowQuestRewards
|
||||
local C_QuestLog_GetSelectedQuest = C_QuestLog.GetSelectedQuest
|
||||
|
||||
--This changes the growth direction of the toast frame depending on position of the mover
|
||||
local function PostBNToastMove(mover)
|
||||
local x, y = mover:GetCenter();
|
||||
local screenHeight = E.UIParent:GetTop();
|
||||
local screenWidth = E.UIParent:GetRight()
|
||||
|
||||
local anchorPoint
|
||||
if y > (screenHeight / 2) then
|
||||
anchorPoint = (x > (screenWidth/2)) and 'TOPRIGHT' or 'TOPLEFT'
|
||||
else
|
||||
anchorPoint = (x > (screenWidth/2)) and 'BOTTOMRIGHT' or 'BOTTOMLEFT'
|
||||
end
|
||||
mover.anchorPoint = anchorPoint
|
||||
|
||||
_G.BNToastFrame:ClearAllPoints()
|
||||
_G.BNToastFrame:Point(anchorPoint, mover)
|
||||
end
|
||||
|
||||
function B:Initialize()
|
||||
B.Initialized = true
|
||||
|
||||
B:EnhanceColorPicker()
|
||||
B:KillBlizzard()
|
||||
B:DisableHelpTip()
|
||||
B:DisableNPE()
|
||||
B:AlertMovers()
|
||||
B:PositionCaptureBar()
|
||||
B:PositionDurabilityFrame()
|
||||
B:PositionGMFrames()
|
||||
B:SkinBlizzTimers()
|
||||
B:PositionVehicleFrame()
|
||||
B:PositionTalkingHead()
|
||||
B:Handle_LevelUpDisplay_BossBanner()
|
||||
B:Handle_UIWidgets()
|
||||
B:GarrisonDropDown()
|
||||
|
||||
if not IsAddOnLoaded('DugisGuideViewerZ') then
|
||||
B:MoveObjectiveFrame()
|
||||
end
|
||||
|
||||
if not IsAddOnLoaded('SimplePowerBar') then
|
||||
B:PositionAltPowerBar()
|
||||
B:SkinAltPowerBar()
|
||||
end
|
||||
|
||||
E:CreateMover(_G.LossOfControlFrame, 'LossControlMover', L["Loss Control Icon"])
|
||||
|
||||
-- Battle.Net Frame
|
||||
_G.BNToastFrame:Point('TOPRIGHT', _G.MMHolder or _G.Minimap, 'BOTTOMRIGHT', 0, -10)
|
||||
E:CreateMover(_G.BNToastFrame, 'BNETMover', L["BNet Frame"], nil, nil, PostBNToastMove)
|
||||
_G.BNToastFrame.mover:Size(_G.BNToastFrame:GetSize())
|
||||
TT:SecureHook(_G.BNToastFrame, 'SetPoint', 'RepositionBNET')
|
||||
|
||||
-- Quick Join Bug
|
||||
CreateFrame('Frame'):SetScript('OnUpdate', function()
|
||||
if _G.LFRBrowseFrame.timeToClear then
|
||||
_G.LFRBrowseFrame.timeToClear = nil
|
||||
end
|
||||
end)
|
||||
|
||||
--Add (+X%) to quest rewards experience text
|
||||
hooksecurefunc('QuestInfo_Display', function()
|
||||
local unitXP, unitXPMax = UnitXP('player'), UnitXPMax('player')
|
||||
if _G.QuestInfoFrame.questLog then
|
||||
local selectedQuest = C_QuestLog_GetSelectedQuest()
|
||||
if C_QuestLog_ShouldShowQuestRewards(selectedQuest) then
|
||||
local xp = GetQuestLogRewardXP()
|
||||
if xp and xp > 0 then
|
||||
local text = _G.MapQuestInfoRewardsFrame.XPFrame.Name:GetText()
|
||||
if text then _G.MapQuestInfoRewardsFrame.XPFrame.Name:SetFormattedText('%s (|cff4beb2c+%.2f%%|r)', text, (((unitXP + xp) / unitXPMax) - (unitXP / unitXPMax))*100) end
|
||||
end
|
||||
end
|
||||
else
|
||||
local xp = GetRewardXP()
|
||||
if xp and xp > 0 then
|
||||
local text = _G.QuestInfoXPFrame.ValueText:GetText()
|
||||
if text then _G.QuestInfoXPFrame.ValueText:SetFormattedText('%s (|cff4beb2c+%.2f%%|r)', text, (((unitXP + xp) / unitXPMax) - (unitXP / unitXPMax))*100) end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- MicroButton Talent Alert
|
||||
local TalentMicroButtonAlert = _G.TalentMicroButtonAlert
|
||||
if TalentMicroButtonAlert then -- why do we need to check this?
|
||||
if E.global.general.showMissingTalentAlert then
|
||||
TalentMicroButtonAlert:ClearAllPoints()
|
||||
TalentMicroButtonAlert:Point('CENTER', E.UIParent, 'TOP', 0, -75)
|
||||
TalentMicroButtonAlert:StripTextures()
|
||||
TalentMicroButtonAlert.Arrow:Hide()
|
||||
TalentMicroButtonAlert.Text:FontTemplate()
|
||||
TalentMicroButtonAlert:CreateBackdrop('Transparent')
|
||||
Skins:HandleCloseButton(TalentMicroButtonAlert.CloseButton)
|
||||
|
||||
TalentMicroButtonAlert.tex = TalentMicroButtonAlert:CreateTexture(nil, 'OVERLAY')
|
||||
TalentMicroButtonAlert.tex:Point('RIGHT', -10, 0)
|
||||
TalentMicroButtonAlert.tex:SetTexture([[Interface\DialogFrame\UI-Dialog-Icon-AlertNew]])
|
||||
TalentMicroButtonAlert.tex:Size(32, 32)
|
||||
else
|
||||
TalentMicroButtonAlert:Kill() -- Kill it, because then the blizz default will show
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
E:RegisterModule(B:GetName())
|
||||
28
Modules/Blizzard/CaptureBar.lua
Normal file
28
Modules/Blizzard/CaptureBar.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
|
||||
local function CaptureUpdate()
|
||||
if _G.NUM_EXTENDED_UI_FRAMES then
|
||||
local captureBar
|
||||
for i=1, _G.NUM_EXTENDED_UI_FRAMES do
|
||||
captureBar = _G['WorldStateCaptureBar' .. i]
|
||||
|
||||
if captureBar and captureBar:IsVisible() then
|
||||
captureBar:ClearAllPoints()
|
||||
|
||||
if i == 1 then
|
||||
captureBar:Point('TOP', E.UIParent, 'TOP', 0, -170)
|
||||
else
|
||||
captureBar:Point('TOPLEFT', _G['WorldStateCaptureBar' .. i - 1], 'TOPLEFT', 0, -45)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function B:PositionCaptureBar()
|
||||
hooksecurefunc('UIParent_ManageFramePositions', CaptureUpdate)
|
||||
end
|
||||
404
Modules/Blizzard/ColorPicker.lua
Normal file
404
Modules/Blizzard/ColorPicker.lua
Normal file
@@ -0,0 +1,404 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- Credit to Jaslm, most of this code is his from the addon ColorPickerPlus.
|
||||
-- Modified and optimized by Simpy.
|
||||
------------------------------------------------------------------------------
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
local S = E:GetModule('Skins')
|
||||
|
||||
local _G = _G
|
||||
local strlen, strjoin, gsub = strlen, strjoin, gsub
|
||||
local tonumber, floor, strsub, wipe = tonumber, floor, strsub, wipe
|
||||
local CreateFrame = CreateFrame
|
||||
local IsAddOnLoaded = IsAddOnLoaded
|
||||
local IsControlKeyDown = IsControlKeyDown
|
||||
local IsModifierKeyDown = IsModifierKeyDown
|
||||
local CALENDAR_COPY_EVENT, CALENDAR_PASTE_EVENT = CALENDAR_COPY_EVENT, CALENDAR_PASTE_EVENT
|
||||
local CLASS, DEFAULT = CLASS, DEFAULT
|
||||
|
||||
local colorBuffer = {}
|
||||
local function alphaValue(num)
|
||||
return num and floor(((1 - num) * 100) + .05) or 0
|
||||
end
|
||||
|
||||
local function UpdateAlphaText(alpha)
|
||||
if not alpha then alpha = alphaValue(_G.OpacitySliderFrame:GetValue()) end
|
||||
|
||||
_G.ColorPPBoxA:SetText(alpha)
|
||||
end
|
||||
|
||||
local function UpdateAlpha(tbox)
|
||||
local num = tbox:GetNumber()
|
||||
if num > 100 then
|
||||
tbox:SetText(100)
|
||||
num = 100
|
||||
end
|
||||
|
||||
_G.OpacitySliderFrame:SetValue(1 - (num / 100))
|
||||
end
|
||||
|
||||
local function expandFromThree(r, g, b)
|
||||
return strjoin('',r,r,g,g,b,b)
|
||||
end
|
||||
|
||||
local function extendToSix(str)
|
||||
for _=1, 6-strlen(str) do str=str..0 end
|
||||
return str
|
||||
end
|
||||
|
||||
local function GetHexColor(box)
|
||||
local rgb, rgbSize = box:GetText(), box:GetNumLetters()
|
||||
if rgbSize == 3 then
|
||||
rgb = gsub(rgb, '(%x)(%x)(%x)$', expandFromThree)
|
||||
elseif rgbSize < 6 then
|
||||
rgb = gsub(rgb, '(.+)$', extendToSix)
|
||||
end
|
||||
|
||||
local r, g, b = tonumber(strsub(rgb,0,2),16) or 0, tonumber(strsub(rgb,3,4),16) or 0, tonumber(strsub(rgb,5,6),16) or 0
|
||||
|
||||
return r/255, g/255, b/255
|
||||
end
|
||||
|
||||
local function UpdateColorTexts(r, g, b, box)
|
||||
if not (r and g and b) then
|
||||
r, g, b = _G.ColorPickerFrame:GetColorRGB()
|
||||
|
||||
if box then
|
||||
if box == _G.ColorPPBoxH then
|
||||
r, g, b = GetHexColor(box)
|
||||
else
|
||||
local num = box:GetNumber()
|
||||
if num > 255 then num = 255 end
|
||||
local c = num/255
|
||||
if box == _G.ColorPPBoxR then
|
||||
r = c
|
||||
elseif box == _G.ColorPPBoxG then
|
||||
g = c
|
||||
elseif box == _G.ColorPPBoxB then
|
||||
b = c
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- we want those /255 values
|
||||
r, g, b = r*255, g*255, b*255
|
||||
|
||||
_G.ColorPPBoxH:SetText(('%.2x%.2x%.2x'):format(r, g, b))
|
||||
_G.ColorPPBoxR:SetText(r)
|
||||
_G.ColorPPBoxG:SetText(g)
|
||||
_G.ColorPPBoxB:SetText(b)
|
||||
end
|
||||
|
||||
local function UpdateColor()
|
||||
local r, g, b = GetHexColor(_G.ColorPPBoxH)
|
||||
_G.ColorPickerFrame:SetColorRGB(r, g, b)
|
||||
_G.ColorSwatch:SetColorTexture(r, g, b)
|
||||
end
|
||||
|
||||
local function ColorPPBoxA_SetFocus()
|
||||
_G.ColorPPBoxA:SetFocus()
|
||||
end
|
||||
|
||||
local function ColorPPBoxR_SetFocus()
|
||||
_G.ColorPPBoxR:SetFocus()
|
||||
end
|
||||
|
||||
local delayWait, delayFunc = 0.15
|
||||
local function delayCall()
|
||||
if delayFunc then
|
||||
delayFunc()
|
||||
delayFunc = nil
|
||||
end
|
||||
end
|
||||
local function onColorSelect(frame, r, g, b)
|
||||
if frame.noColorCallback then return end
|
||||
|
||||
_G.ColorSwatch:SetColorTexture(r, g, b)
|
||||
UpdateColorTexts(r, g, b)
|
||||
|
||||
if r == 0 and g == 0 and b == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
if not frame:IsVisible() then
|
||||
delayCall()
|
||||
elseif not delayFunc then
|
||||
delayFunc = _G.ColorPickerFrame.func
|
||||
E:Delay(delayWait, delayCall)
|
||||
end
|
||||
end
|
||||
|
||||
local function onValueChanged(frame, value)
|
||||
local alpha = alphaValue(value)
|
||||
if frame.lastAlpha ~= alpha then
|
||||
frame.lastAlpha = alpha
|
||||
|
||||
UpdateAlphaText(alpha)
|
||||
|
||||
if not _G.ColorPickerFrame:IsVisible() then
|
||||
delayCall()
|
||||
else
|
||||
local opacityFunc = _G.ColorPickerFrame.opacityFunc
|
||||
if delayFunc and (delayFunc ~= opacityFunc) then
|
||||
delayFunc = opacityFunc
|
||||
elseif not delayFunc then
|
||||
delayFunc = opacityFunc
|
||||
E:Delay(delayWait, delayCall)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function B:EnhanceColorPicker()
|
||||
if IsAddOnLoaded('ColorPickerPlus') then return end
|
||||
|
||||
--Skin the default frame, move default buttons into place
|
||||
_G.ColorPickerFrame:SetClampedToScreen(true)
|
||||
_G.ColorPickerFrame:CreateBackdrop('Transparent')
|
||||
_G.ColorPickerFrame.Border:Hide()
|
||||
|
||||
_G.ColorPickerFrame.Header:StripTextures()
|
||||
_G.ColorPickerFrame.Header:ClearAllPoints()
|
||||
_G.ColorPickerFrame.Header:Point('TOP', _G.ColorPickerFrame, 0, 0)
|
||||
|
||||
_G.ColorPickerCancelButton:ClearAllPoints()
|
||||
_G.ColorPickerOkayButton:ClearAllPoints()
|
||||
_G.ColorPickerCancelButton:Point('BOTTOMRIGHT', _G.ColorPickerFrame, 'BOTTOMRIGHT', -6, 6)
|
||||
_G.ColorPickerCancelButton:Point('BOTTOMLEFT', _G.ColorPickerFrame, 'BOTTOM', 0, 6)
|
||||
_G.ColorPickerOkayButton:Point('BOTTOMLEFT', _G.ColorPickerFrame,'BOTTOMLEFT', 6,6)
|
||||
_G.ColorPickerOkayButton:Point('RIGHT', _G.ColorPickerCancelButton,'LEFT', -4,0)
|
||||
S:HandleSliderFrame(_G.OpacitySliderFrame)
|
||||
S:HandleButton(_G.ColorPickerOkayButton)
|
||||
S:HandleButton(_G.ColorPickerCancelButton)
|
||||
|
||||
_G.ColorPickerFrame:HookScript('OnShow', function(frame)
|
||||
-- get color that will be replaced
|
||||
local r, g, b = frame:GetColorRGB()
|
||||
_G.ColorPPOldColorSwatch:SetColorTexture(r,g,b)
|
||||
|
||||
-- show/hide the alpha box
|
||||
if frame.hasOpacity then
|
||||
_G.ColorPPBoxA:Show()
|
||||
_G.ColorPPBoxLabelA:Show()
|
||||
_G.ColorPPBoxH:SetScript('OnTabPressed', ColorPPBoxA_SetFocus)
|
||||
UpdateAlphaText()
|
||||
UpdateColorTexts()
|
||||
frame:Width(405)
|
||||
else
|
||||
_G.ColorPPBoxA:Hide()
|
||||
_G.ColorPPBoxLabelA:Hide()
|
||||
_G.ColorPPBoxH:SetScript('OnTabPressed', ColorPPBoxR_SetFocus)
|
||||
UpdateColorTexts()
|
||||
frame:Width(345)
|
||||
end
|
||||
|
||||
-- Memory Fix, Colorpicker will call the self.func() 100x per second, causing fps/memory issues,
|
||||
-- We overwrite these two scripts and set a limit on how often we allow a call their update functions
|
||||
_G.OpacitySliderFrame:SetScript('OnValueChanged', onValueChanged)
|
||||
frame:SetScript('OnColorSelect', onColorSelect)
|
||||
end)
|
||||
|
||||
-- make the Color Picker dialog a bit taller, to make room for edit boxes
|
||||
_G.ColorPickerFrame:Height(_G.ColorPickerFrame:GetHeight() + 40)
|
||||
|
||||
-- move the Color Swatch
|
||||
_G.ColorSwatch:ClearAllPoints()
|
||||
_G.ColorSwatch:Point('TOPLEFT', _G.ColorPickerFrame, 'TOPLEFT', 215, -45)
|
||||
|
||||
-- add Color Swatch for original color
|
||||
local t = _G.ColorPickerFrame:CreateTexture('ColorPPOldColorSwatch')
|
||||
local w, h = _G.ColorSwatch:GetSize()
|
||||
t:Size(w*0.75,h*0.75)
|
||||
t:SetColorTexture(0,0,0)
|
||||
-- OldColorSwatch to appear beneath ColorSwatch
|
||||
t:SetDrawLayer('BORDER')
|
||||
t:Point('BOTTOMLEFT', 'ColorSwatch', 'TOPRIGHT', -(w/2), -(h/3))
|
||||
|
||||
-- add Color Swatch for the copied color
|
||||
t = _G.ColorPickerFrame:CreateTexture('ColorPPCopyColorSwatch')
|
||||
t:SetColorTexture(0,0,0)
|
||||
t:Size(w,h)
|
||||
t:Hide()
|
||||
|
||||
-- add copy button to the _G.ColorPickerFrame
|
||||
local b = CreateFrame('Button', 'ColorPPCopy', _G.ColorPickerFrame, 'UIPanelButtonTemplate, BackdropTemplate')
|
||||
S:HandleButton(b)
|
||||
b:SetText(CALENDAR_COPY_EVENT)
|
||||
b:Size(60, 22)
|
||||
b:Point('TOPLEFT', 'ColorSwatch', 'BOTTOMLEFT', 0, -5)
|
||||
|
||||
-- copy color into buffer on button click
|
||||
b:SetScript('OnClick', function()
|
||||
-- copy current dialog colors into buffer
|
||||
colorBuffer.r, colorBuffer.g, colorBuffer.b = _G.ColorPickerFrame:GetColorRGB()
|
||||
|
||||
-- enable Paste button and display copied color into swatch
|
||||
_G.ColorPPPaste:Enable()
|
||||
_G.ColorPPCopyColorSwatch:SetColorTexture(colorBuffer.r, colorBuffer.g, colorBuffer.b)
|
||||
_G.ColorPPCopyColorSwatch:Show()
|
||||
|
||||
colorBuffer.a = (_G.ColorPickerFrame.hasOpacity and _G.OpacitySliderFrame:GetValue()) or nil
|
||||
end)
|
||||
|
||||
--class color button
|
||||
b = CreateFrame('Button', 'ColorPPClass', _G.ColorPickerFrame, 'UIPanelButtonTemplate, BackdropTemplate')
|
||||
b:SetText(CLASS)
|
||||
S:HandleButton(b)
|
||||
b:Size(80, 22)
|
||||
b:Point('TOP', 'ColorPPCopy', 'BOTTOMRIGHT', 0, -7)
|
||||
|
||||
b:SetScript('OnClick', function()
|
||||
local color = E:ClassColor(E.myclass, true)
|
||||
_G.ColorPickerFrame:SetColorRGB(color.r, color.g, color.b)
|
||||
_G.ColorSwatch:SetColorTexture(color.r, color.g, color.b)
|
||||
if _G.ColorPickerFrame.hasOpacity then
|
||||
_G.OpacitySliderFrame:SetValue(0)
|
||||
end
|
||||
end)
|
||||
|
||||
-- add paste button to the _G.ColorPickerFrame
|
||||
b = CreateFrame('Button', 'ColorPPPaste', _G.ColorPickerFrame, 'UIPanelButtonTemplate, BackdropTemplate')
|
||||
b:SetText(CALENDAR_PASTE_EVENT)
|
||||
S:HandleButton(b)
|
||||
b:Size(60, 22)
|
||||
b:Point('TOPLEFT', 'ColorPPCopy', 'TOPRIGHT', 2, 0)
|
||||
b:Disable() -- enable when something has been copied
|
||||
|
||||
-- paste color on button click, updating frame components
|
||||
b:SetScript('OnClick', function()
|
||||
_G.ColorPickerFrame:SetColorRGB(colorBuffer.r, colorBuffer.g, colorBuffer.b)
|
||||
_G.ColorSwatch:SetColorTexture(colorBuffer.r, colorBuffer.g, colorBuffer.b)
|
||||
if _G.ColorPickerFrame.hasOpacity then
|
||||
if colorBuffer.a then --color copied had an alpha value
|
||||
_G.OpacitySliderFrame:SetValue(colorBuffer.a)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- add defaults button to the _G.ColorPickerFrame
|
||||
b = CreateFrame('Button', 'ColorPPDefault', _G.ColorPickerFrame, 'UIPanelButtonTemplate, BackdropTemplate')
|
||||
b:SetText(DEFAULT)
|
||||
S:HandleButton(b)
|
||||
b:Size(80, 22)
|
||||
b:Point('TOPLEFT', 'ColorPPClass', 'BOTTOMLEFT', 0, -7)
|
||||
b:Disable() -- enable when something has been copied
|
||||
b:SetScript('OnHide', function(btn)
|
||||
if btn.colors then
|
||||
wipe(btn.colors)
|
||||
end
|
||||
end)
|
||||
b:SetScript('OnShow', function(btn)
|
||||
if btn.colors then
|
||||
btn:Enable()
|
||||
else
|
||||
btn:Disable()
|
||||
end
|
||||
end)
|
||||
|
||||
-- paste color on button click, updating frame components
|
||||
b:SetScript('OnClick', function(btn)
|
||||
local colors = btn.colors
|
||||
_G.ColorPickerFrame:SetColorRGB(colors.r, colors.g, colors.b)
|
||||
_G.ColorSwatch:SetColorTexture(colors.r, colors.g, colors.b)
|
||||
if _G.ColorPickerFrame.hasOpacity then
|
||||
if colors.a then
|
||||
_G.OpacitySliderFrame:SetValue(colors.a)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- position Color Swatch for copy color
|
||||
_G.ColorPPCopyColorSwatch:Point('BOTTOM', 'ColorPPPaste', 'TOP', 0, 10)
|
||||
|
||||
-- move the Opacity Slider Frame to align with bottom of Copy ColorSwatch
|
||||
_G.OpacitySliderFrame:ClearAllPoints()
|
||||
_G.OpacitySliderFrame:Point('BOTTOM', 'ColorPPDefault', 'BOTTOM', 0, 0)
|
||||
_G.OpacitySliderFrame:Point('RIGHT', 'ColorPickerFrame', 'RIGHT', -35, 18)
|
||||
|
||||
-- set up edit box frames and interior label and text areas
|
||||
local boxes = { 'R', 'G', 'B', 'H', 'A' }
|
||||
for i = 1, #boxes do
|
||||
local rgb = boxes[i]
|
||||
local box = CreateFrame('EditBox', 'ColorPPBox'..rgb, _G.ColorPickerFrame, 'InputBoxTemplate, BackdropTemplate')
|
||||
box:Point('TOP', 'ColorPickerWheel', 'BOTTOM', 0, -15)
|
||||
box:SetFrameStrata('DIALOG')
|
||||
box:SetAutoFocus(false)
|
||||
box:SetTextInsets(0,7,0,0)
|
||||
box:SetJustifyH('RIGHT')
|
||||
box:Height(24)
|
||||
box:SetID(i)
|
||||
S:HandleEditBox(box)
|
||||
|
||||
-- hex entry box
|
||||
if i == 4 then
|
||||
box:SetMaxLetters(6)
|
||||
box:Width(56)
|
||||
box:SetNumeric(false)
|
||||
else
|
||||
box:SetMaxLetters(3)
|
||||
box:Width(40)
|
||||
box:SetNumeric(true)
|
||||
end
|
||||
|
||||
-- label
|
||||
local label = box:CreateFontString('ColorPPBoxLabel'..rgb, 'ARTWORK', 'GameFontNormalSmall')
|
||||
label:Point('RIGHT', 'ColorPPBox'..rgb, 'LEFT', -5, 0)
|
||||
label:SetText(i == 4 and '#' or rgb)
|
||||
label:SetTextColor(1, 1, 1)
|
||||
|
||||
-- set up scripts to handle event appropriately
|
||||
if i == 5 then
|
||||
box:SetScript('OnKeyUp', function(eb, key)
|
||||
local copyPaste = IsControlKeyDown() and key == 'V'
|
||||
if key == 'BACKSPACE' or copyPaste or (strlen(key) == 1 and not IsModifierKeyDown()) then
|
||||
UpdateAlpha(eb)
|
||||
elseif key == 'ENTER' or key == 'ESCAPE' then
|
||||
eb:ClearFocus()
|
||||
UpdateAlpha(eb)
|
||||
end
|
||||
end)
|
||||
else
|
||||
box:SetScript('OnKeyUp', function(eb, key)
|
||||
local copyPaste = IsControlKeyDown() and key == 'V'
|
||||
if key == 'BACKSPACE' or copyPaste or (strlen(key) == 1 and not IsModifierKeyDown()) then
|
||||
if i ~= 4 then UpdateColorTexts(nil, nil, nil, eb) end
|
||||
if i == 4 and eb:GetNumLetters() ~= 6 then return end
|
||||
UpdateColor()
|
||||
elseif key == 'ENTER' or key == 'ESCAPE' then
|
||||
eb:ClearFocus()
|
||||
UpdateColorTexts(nil, nil, nil, eb)
|
||||
UpdateColor()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
box:SetScript('OnEditFocusGained', function(eb) eb:SetCursorPosition(0) eb:HighlightText() end)
|
||||
box:SetScript('OnEditFocusLost', function(eb) eb:HighlightText(0,0) end)
|
||||
box:Show()
|
||||
end
|
||||
|
||||
-- finish up with placement
|
||||
_G.ColorPPBoxA:Point('RIGHT', 'OpacitySliderFrame', 'RIGHT', 10, 0)
|
||||
_G.ColorPPBoxH:Point('RIGHT', 'ColorPPDefault', 'RIGHT', -10, 0)
|
||||
_G.ColorPPBoxB:Point('RIGHT', 'ColorPPDefault', 'LEFT', -40, 0)
|
||||
_G.ColorPPBoxG:Point('RIGHT', 'ColorPPBoxB', 'LEFT', -25, 0)
|
||||
_G.ColorPPBoxR:Point('RIGHT', 'ColorPPBoxG', 'LEFT', -25, 0)
|
||||
|
||||
-- define the order of tab cursor movement
|
||||
_G.ColorPPBoxR:SetScript('OnTabPressed', function() _G.ColorPPBoxG:SetFocus() end)
|
||||
_G.ColorPPBoxG:SetScript('OnTabPressed', function() _G.ColorPPBoxB:SetFocus() end)
|
||||
_G.ColorPPBoxB:SetScript('OnTabPressed', function() _G.ColorPPBoxH:SetFocus() end)
|
||||
_G.ColorPPBoxA:SetScript('OnTabPressed', function() _G.ColorPPBoxR:SetFocus() end)
|
||||
|
||||
-- make the color picker movable.
|
||||
local mover = CreateFrame('Frame', nil, _G.ColorPickerFrame)
|
||||
mover:Point('TOPLEFT', _G.ColorPickerFrame, 'TOP', -60, 0)
|
||||
mover:Point('BOTTOMRIGHT', _G.ColorPickerFrame, 'TOP', 60, -15)
|
||||
mover:SetScript('OnMouseDown', function() _G.ColorPickerFrame:StartMoving() end)
|
||||
mover:SetScript('OnMouseUp', function() _G.ColorPickerFrame:StopMovingOrSizing() end)
|
||||
mover:EnableMouse(true)
|
||||
|
||||
_G.ColorPickerFrame:SetUserPlaced(true)
|
||||
_G.ColorPickerFrame:EnableKeyboard(false)
|
||||
end
|
||||
32
Modules/Blizzard/Durability.lua
Normal file
32
Modules/Blizzard/Durability.lua
Normal file
@@ -0,0 +1,32 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
--Lua functions
|
||||
local _G = _G
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local CreateFrame = CreateFrame
|
||||
local DurabilityFrame = _G.DurabilityFrame
|
||||
|
||||
local function SetPosition(frame, _, parent)
|
||||
if parent ~= _G.DurabilityFrameHolder then
|
||||
frame:ClearAllPoints()
|
||||
frame:SetPoint('CENTER', _G.DurabilityFrameHolder, 'CENTER')
|
||||
end
|
||||
end
|
||||
|
||||
function B:UpdateDurabilityScale()
|
||||
DurabilityFrame:SetScale(E.db.general.durabilityScale or 1)
|
||||
end
|
||||
|
||||
function B:PositionDurabilityFrame()
|
||||
local DurabilityFrameHolder = CreateFrame('Frame', 'DurabilityFrameHolder', E.UIParent)
|
||||
DurabilityFrameHolder:Size(DurabilityFrame:GetSize())
|
||||
DurabilityFrameHolder:Point('TOPRIGHT', E.UIParent, 'TOPRIGHT', -135, -300)
|
||||
|
||||
E:CreateMover(DurabilityFrameHolder, 'DurabilityFrameMover', L["Durability Frame"], nil, nil, nil, nil, nil, 'all,general')
|
||||
|
||||
DurabilityFrame:SetFrameStrata('HIGH')
|
||||
B:UpdateDurabilityScale()
|
||||
|
||||
hooksecurefunc(DurabilityFrame, 'SetPoint', SetPosition)
|
||||
end
|
||||
23
Modules/Blizzard/GM.lua
Normal file
23
Modules/Blizzard/GM.lua
Normal file
@@ -0,0 +1,23 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
|
||||
local function SetPosition(frame, _, anchor)
|
||||
if anchor and (anchor == _G.UIParent) then
|
||||
frame:ClearAllPoints()
|
||||
frame:Point('TOPLEFT', _G.GMMover, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function B:PositionGMFrames()
|
||||
local TicketStatusFrame = _G.TicketStatusFrame
|
||||
|
||||
TicketStatusFrame:ClearAllPoints()
|
||||
TicketStatusFrame:Point('TOPLEFT', E.UIParent, 'TOPLEFT', 250, -5)
|
||||
E:CreateMover(TicketStatusFrame, 'GMMover', L["GM Ticket Frame"])
|
||||
|
||||
--Blizzard repositions this frame now in UIParent_UpdateTopFramePositions
|
||||
hooksecurefunc(TicketStatusFrame, 'SetPoint', SetPosition)
|
||||
end
|
||||
82
Modules/Blizzard/Garrison.lua
Normal file
82
Modules/Blizzard/Garrison.lua
Normal file
@@ -0,0 +1,82 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
|
||||
local C_Garrison_GetLandingPageGarrisonType = C_Garrison.GetLandingPageGarrisonType
|
||||
local ShowGarrisonLandingPage = ShowGarrisonLandingPage
|
||||
local IsAddOnLoaded = IsAddOnLoaded
|
||||
local HideUIPanel = HideUIPanel
|
||||
local PlaySound = PlaySound
|
||||
local StopSound = StopSound
|
||||
|
||||
local SOUNDKIT_UI_GARRISON_GARRISON_REPORT_OPEN = SOUNDKIT.UI_GARRISON_GARRISON_REPORT_OPEN
|
||||
local SOUNDKIT_UI_GARRISON_GARRISON_REPORT_CLOSE = SOUNDKIT.UI_GARRISON_GARRISON_REPORT_CLOSE
|
||||
|
||||
local WAR_CAMPAIGN = WAR_CAMPAIGN
|
||||
local GARRISON_LANDING_PAGE_TITLE = GARRISON_LANDING_PAGE_TITLE
|
||||
local ORDER_HALL_LANDING_PAGE_TITLE = ORDER_HALL_LANDING_PAGE_TITLE
|
||||
|
||||
function B:GarrisonDropDown()
|
||||
-- Right click Menu for Garrision Button all Credits to Foxlit (WarPlan)
|
||||
if IsAddOnLoaded('WarPlan') then return; end
|
||||
|
||||
local function ShowLanding(page)
|
||||
HideUIPanel(_G.GarrisonLandingPage)
|
||||
ShowGarrisonLandingPage(page)
|
||||
end
|
||||
|
||||
local function MaybeStopSound(sound)
|
||||
return sound and StopSound(sound)
|
||||
end
|
||||
|
||||
local landingChoices
|
||||
_G.GarrisonLandingPageMinimapButton:RegisterForClicks('LeftButtonUp', 'RightButtonUp')
|
||||
_G.GarrisonLandingPageMinimapButton:HookScript('PreClick', function(btn, b)
|
||||
btn.landingVisiblePriorToClick = _G.GarrisonLandingPage and _G.GarrisonLandingPage:IsVisible() and _G.GarrisonLandingPage.garrTypeID
|
||||
if b == 'RightButton' then
|
||||
local openOK, openID = PlaySound(SOUNDKIT_UI_GARRISON_GARRISON_REPORT_OPEN)
|
||||
local closeOK, closeID = PlaySound(SOUNDKIT_UI_GARRISON_GARRISON_REPORT_CLOSE)
|
||||
btn.openSoundID = openOK and openID
|
||||
btn.closeSoundID = closeOK and closeID
|
||||
end
|
||||
end)
|
||||
|
||||
_G.GarrisonLandingPageMinimapButton:HookScript('OnClick', function(btn, b)
|
||||
if b == 'LeftButton' then
|
||||
if _G.GarrisonLandingPage.garrTypeID ~= C_Garrison_GetLandingPageGarrisonType() then
|
||||
ShowLanding(C_Garrison_GetLandingPageGarrisonType())
|
||||
end
|
||||
return
|
||||
elseif b == 'RightButton' then
|
||||
if (C_Garrison_GetLandingPageGarrisonType() or 0) > 3 then
|
||||
if btn.landingVisiblePriorToClick then
|
||||
ShowLanding(btn.landingVisiblePriorToClick)
|
||||
else
|
||||
HideUIPanel(_G.GarrisonLandingPage)
|
||||
end
|
||||
MaybeStopSound(btn.openSoundID)
|
||||
MaybeStopSound(btn.closeSoundID)
|
||||
if not landingChoices then
|
||||
local function ShowLanding_(_, ...)
|
||||
return ShowLanding(...)
|
||||
end
|
||||
landingChoices = {
|
||||
{text = GARRISON_LANDING_PAGE_TITLE, func = ShowLanding_, arg1 = 2, notCheckable = true},
|
||||
{text = ORDER_HALL_LANDING_PAGE_TITLE, func = ShowLanding_, arg1 = 3, notCheckable = true},
|
||||
{text = WAR_CAMPAIGN, func = ShowLanding_, arg1 = C_Garrison_GetLandingPageGarrisonType(), notCheckable = true},
|
||||
}
|
||||
end
|
||||
E.DataTexts:SetEasyMenuAnchor(E.DataTexts.EasyMenu, btn)
|
||||
_G.EasyMenu(landingChoices, E.DataTexts.EasyMenu, nil, nil, nil, 'MENU')
|
||||
elseif _G.GarrisonLandingPage.garrTypeID == 3 then
|
||||
ShowLanding(2)
|
||||
MaybeStopSound(btn.closeSoundID)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
_G.GarrisonLandingPageMinimapButton:HookScript('PostClick', function(btn)
|
||||
btn.closeSoundID, btn.openSoundID = nil, nil
|
||||
end)
|
||||
end
|
||||
45
Modules/Blizzard/Kill.lua
Normal file
45
Modules/Blizzard/Kill.lua
Normal file
@@ -0,0 +1,45 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
|
||||
function B:KillBlizzard()
|
||||
_G.Display_UIScaleSlider:Kill()
|
||||
_G.Display_UseUIScale:Kill()
|
||||
end
|
||||
|
||||
local function AcknowledgeTips()
|
||||
for frame in _G.HelpTip.framePool:EnumerateActive() do
|
||||
frame:Acknowledge()
|
||||
end
|
||||
end
|
||||
|
||||
function B:DisableHelpTip() -- auto complete helptips
|
||||
if not E.global.general.disableTutorialButtons then return end
|
||||
|
||||
hooksecurefunc(_G.HelpTip, 'Show', AcknowledgeTips)
|
||||
E:Delay(1, AcknowledgeTips)
|
||||
end
|
||||
|
||||
-- NOTE: ActionBars heavily conflicts with NPE
|
||||
local function ShutdownNPE(event)
|
||||
local NPE = _G.NewPlayerExperience
|
||||
if NPE then
|
||||
if NPE:GetIsActive() then
|
||||
NPE:Shutdown()
|
||||
end
|
||||
|
||||
if event then
|
||||
B:UnregisterEvent(event)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function B:DisableNPE() -- disable new player experience
|
||||
if _G.NewPlayerExperience then
|
||||
ShutdownNPE()
|
||||
else
|
||||
B:RegisterEvent('ADDON_LOADED', ShutdownNPE)
|
||||
end
|
||||
end
|
||||
32
Modules/Blizzard/LevelUpBossBanner.lua
Normal file
32
Modules/Blizzard/LevelUpBossBanner.lua
Normal file
@@ -0,0 +1,32 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
local Holder
|
||||
local function Reanchor(frame, _, anchor)
|
||||
if anchor and (anchor ~= Holder) then
|
||||
frame:ClearAllPoints()
|
||||
frame:Point('TOP', Holder)
|
||||
end
|
||||
end
|
||||
|
||||
function B:Handle_LevelUpDisplay_BossBanner()
|
||||
if not Holder then
|
||||
Holder = CreateFrame('Frame', 'LevelUpBossBannerHolder', E.UIParent)
|
||||
Holder:Size(200, 20)
|
||||
Holder:Point('TOP', E.UIParent, 'TOP', -1, -120)
|
||||
end
|
||||
|
||||
E:CreateMover(Holder, 'LevelUpBossBannerMover', L["Level Up Display / Boss Banner"])
|
||||
|
||||
_G.LevelUpDisplay:ClearAllPoints()
|
||||
_G.LevelUpDisplay:Point('TOP', Holder)
|
||||
hooksecurefunc(_G.LevelUpDisplay, 'SetPoint', Reanchor)
|
||||
|
||||
_G.BossBanner:ClearAllPoints()
|
||||
_G.BossBanner:Point('TOP', Holder)
|
||||
hooksecurefunc(_G.BossBanner, 'SetPoint', Reanchor)
|
||||
end
|
||||
17
Modules/Blizzard/Load_Blizzard.xml
Normal file
17
Modules/Blizzard/Load_Blizzard.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='Blizzard.lua'/>
|
||||
<Script file='ColorPicker.lua'/>
|
||||
<Script file='Kill.lua'/>
|
||||
<Script file='ObjectiveFrame.lua'/>
|
||||
<Script file='Vehicle.lua'/>
|
||||
<Script file='TimerTracker.lua'/>
|
||||
<Script file='GM.lua'/>
|
||||
<Script file='Durability.lua'/>
|
||||
<Script file='CaptureBar.lua'/>
|
||||
<Script file='AlertFrame.lua'/>
|
||||
<Script file='AltPower.lua'/>
|
||||
<Script file='TalkingHeadFrame.lua'/>
|
||||
<Script file='LevelUpBossBanner.lua'/>
|
||||
<Script file='WidgetsUI.lua'/>
|
||||
<Script file='Garrison.lua'/>
|
||||
</Ui>
|
||||
96
Modules/Blizzard/ObjectiveFrame.lua
Normal file
96
Modules/Blizzard/ObjectiveFrame.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local min = min
|
||||
local CreateFrame = CreateFrame
|
||||
local GetScreenHeight = GetScreenHeight
|
||||
local GetInstanceInfo = GetInstanceInfo
|
||||
local GetScreenWidth = GetScreenWidth
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local RegisterStateDriver = RegisterStateDriver
|
||||
local UnregisterStateDriver = UnregisterStateDriver
|
||||
|
||||
function B:SetObjectiveFrameHeight()
|
||||
local top = _G.ObjectiveTrackerFrame:GetTop() or 0
|
||||
local screenHeight = GetScreenHeight()
|
||||
local gapFromTop = screenHeight - top
|
||||
local maxHeight = screenHeight - gapFromTop
|
||||
local objectiveFrameHeight = min(maxHeight, E.db.general.objectiveFrameHeight)
|
||||
|
||||
_G.ObjectiveTrackerFrame:Height(objectiveFrameHeight)
|
||||
end
|
||||
|
||||
local function IsFramePositionedLeft(frame)
|
||||
local x = frame:GetCenter()
|
||||
local screenWidth = GetScreenWidth()
|
||||
local positionedLeft = false
|
||||
|
||||
if x and x < (screenWidth / 2) then
|
||||
positionedLeft = true
|
||||
end
|
||||
|
||||
return positionedLeft
|
||||
end
|
||||
|
||||
function B:SetObjectiveFrameAutoHide()
|
||||
if not _G.ObjectiveTrackerFrame.AutoHider then return end --Kaliel's Tracker prevents B:MoveObjectiveFrame() from executing
|
||||
|
||||
if E.db.general.objectiveFrameAutoHide then
|
||||
RegisterStateDriver(_G.ObjectiveTrackerFrame.AutoHider, 'objectiveHider', '[@arena1,exists][@arena2,exists][@arena3,exists][@arena4,exists][@arena5,exists][@boss1,exists][@boss2,exists][@boss3,exists][@boss4,exists] 1;0')
|
||||
else
|
||||
UnregisterStateDriver(_G.ObjectiveTrackerFrame.AutoHider, 'objectiveHider')
|
||||
end
|
||||
end
|
||||
|
||||
function B:MoveObjectiveFrame()
|
||||
local ObjectiveFrameHolder = CreateFrame('Frame', 'ObjectiveFrameHolder', E.UIParent)
|
||||
ObjectiveFrameHolder:Point('TOPRIGHT', E.UIParent, 'TOPRIGHT', -135, -300)
|
||||
ObjectiveFrameHolder:Size(130, 22)
|
||||
|
||||
E:CreateMover(ObjectiveFrameHolder, 'ObjectiveFrameMover', L["Objective Frame"], nil, nil, nil, nil, nil, 'general,blizzUIImprovements')
|
||||
ObjectiveFrameHolder:SetAllPoints(_G.ObjectiveFrameMover)
|
||||
|
||||
local ObjectiveTrackerFrame = _G.ObjectiveTrackerFrame
|
||||
ObjectiveTrackerFrame:SetClampedToScreen(false)
|
||||
ObjectiveTrackerFrame:ClearAllPoints()
|
||||
ObjectiveTrackerFrame:Point('TOP', ObjectiveFrameHolder, 'TOP')
|
||||
ObjectiveTrackerFrame:SetMovable(true)
|
||||
ObjectiveTrackerFrame:SetUserPlaced(true) -- UIParent.lua line 3090 stops it from being moved <3
|
||||
B:SetObjectiveFrameHeight()
|
||||
|
||||
local function RewardsFrame_SetPosition(block)
|
||||
local rewardsFrame = _G.ObjectiveTrackerBonusRewardsFrame
|
||||
rewardsFrame:ClearAllPoints()
|
||||
if E.db.general.bonusObjectivePosition == 'RIGHT' or (E.db.general.bonusObjectivePosition == 'AUTO' and IsFramePositionedLeft(ObjectiveTrackerFrame)) then
|
||||
rewardsFrame:Point('TOPLEFT', block, 'TOPRIGHT', -10, -4)
|
||||
else
|
||||
rewardsFrame:Point('TOPRIGHT', block, 'TOPLEFT', 10, -4)
|
||||
end
|
||||
end
|
||||
hooksecurefunc('BonusObjectiveTracker_AnimateReward', RewardsFrame_SetPosition)
|
||||
|
||||
-- objectiveFrameAutoHide
|
||||
ObjectiveTrackerFrame.AutoHider = CreateFrame('Frame', nil, ObjectiveTrackerFrame, 'SecureHandlerStateTemplate')
|
||||
ObjectiveTrackerFrame.AutoHider:SetAttribute('_onstate-objectiveHider', 'if newstate == 1 then self:Hide() else self:Show() end')
|
||||
ObjectiveTrackerFrame.AutoHider:SetScript('OnHide', function()
|
||||
if not ObjectiveTrackerFrame.collapsed then
|
||||
if E.db.general.objectiveFrameAutoHideInKeystone then
|
||||
_G.ObjectiveTracker_Collapse()
|
||||
else
|
||||
local _, _, difficultyID = GetInstanceInfo()
|
||||
if difficultyID and difficultyID ~= 8 then -- ignore hide in keystone runs
|
||||
_G.ObjectiveTracker_Collapse()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
ObjectiveTrackerFrame.AutoHider:SetScript('OnShow', function()
|
||||
if ObjectiveTrackerFrame.collapsed then
|
||||
_G.ObjectiveTracker_Expand()
|
||||
end
|
||||
end)
|
||||
|
||||
self:SetObjectiveFrameAutoHide()
|
||||
end
|
||||
62
Modules/Blizzard/TalkingHeadFrame.lua
Normal file
62
Modules/Blizzard/TalkingHeadFrame.lua
Normal file
@@ -0,0 +1,62 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local ipairs, tremove = ipairs, tremove
|
||||
|
||||
function B:ScaleTalkingHeadFrame()
|
||||
local scale = E.db.general.talkingHeadFrameScale or 1
|
||||
local TalkingHeadFrame = _G.TalkingHeadFrame
|
||||
local width, height = TalkingHeadFrame:GetSize()
|
||||
TalkingHeadFrame.mover:Size(width * scale, height * scale)
|
||||
TalkingHeadFrame:SetScale(scale)
|
||||
|
||||
--Reset Model Camera
|
||||
local model = TalkingHeadFrame.MainFrame.Model
|
||||
if model.uiCameraID then
|
||||
model:RefreshCamera()
|
||||
_G.Model_ApplyUICamera(model, model.uiCameraID)
|
||||
end
|
||||
|
||||
--Use this to prevent the frame from auto closing, so you have time to test things.
|
||||
-- TalkingHeadFrame:UnregisterEvent('SOUNDKIT_FINISHED')
|
||||
-- TalkingHeadFrame:UnregisterEvent('TALKINGHEAD_CLOSE')
|
||||
-- TalkingHeadFrame:UnregisterEvent('LOADING_SCREEN_ENABLED')
|
||||
end
|
||||
|
||||
local function InitializeTalkingHead()
|
||||
local TalkingHeadFrame = _G.TalkingHeadFrame
|
||||
|
||||
--Prevent WoW from moving the frame around
|
||||
_G.UIPARENT_MANAGED_FRAME_POSITIONS.TalkingHeadFrame = nil
|
||||
|
||||
--Set default position
|
||||
TalkingHeadFrame:ClearAllPoints()
|
||||
TalkingHeadFrame:Point('BOTTOM', E.UIParent, 'BOTTOM', -1, 373)
|
||||
|
||||
E:CreateMover(TalkingHeadFrame, 'TalkingHeadFrameMover', L["Talking Head Frame"], nil, nil, nil, nil, nil, 'skins')
|
||||
|
||||
--Iterate through all alert subsystems in order to find the one created for TalkingHeadFrame, and then remove it.
|
||||
--We do this to prevent alerts from anchoring to this frame when it is shown.
|
||||
for index, alertFrameSubSystem in ipairs(_G.AlertFrame.alertFrameSubSystems) do
|
||||
if alertFrameSubSystem.anchorFrame and alertFrameSubSystem.anchorFrame == TalkingHeadFrame then
|
||||
tremove(_G.AlertFrame.alertFrameSubSystems, index)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function LoadTalkingHead()
|
||||
if not _G.TalkingHeadFrame then
|
||||
_G.TalkingHead_LoadUI()
|
||||
end
|
||||
|
||||
InitializeTalkingHead()
|
||||
B:ScaleTalkingHeadFrame()
|
||||
end
|
||||
|
||||
function B:PositionTalkingHead()
|
||||
if not E:IsAddOnEnabled('Blizzard_TalkingHeadUI') then return end
|
||||
|
||||
-- wait until first frame, then load talking head (if it isnt yet) and spawn the mover
|
||||
E:Delay(1, LoadTalkingHead)
|
||||
end
|
||||
46
Modules/Blizzard/TimerTracker.lua
Normal file
46
Modules/Blizzard/TimerTracker.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local select, unpack, pairs = select, unpack, pairs
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
local function SkinIt(bar)
|
||||
for i=1, bar:GetNumRegions() do
|
||||
local region = select(i, bar:GetRegions())
|
||||
if region:IsObjectType('Texture') then
|
||||
region:SetTexture()
|
||||
elseif region:IsObjectType('FontString') then
|
||||
region:FontTemplate(nil, 12, 'OUTLINE')
|
||||
end
|
||||
end
|
||||
|
||||
bar:SetStatusBarTexture(E.media.normTex)
|
||||
if E.PixelMode then
|
||||
bar:SetStatusBarColor(.31, .31, .31)
|
||||
else
|
||||
bar:SetStatusBarColor(unpack(E.media.bordercolor))
|
||||
end
|
||||
|
||||
if not bar.backdrop then
|
||||
bar.backdrop = CreateFrame('Frame', nil, bar, 'BackdropTemplate')
|
||||
bar.backdrop:SetFrameLevel(0)
|
||||
bar.backdrop:SetTemplate('Transparent')
|
||||
bar.backdrop:SetOutside()
|
||||
E:RegisterStatusBar(bar)
|
||||
end
|
||||
end
|
||||
|
||||
function B:START_TIMER()
|
||||
for _, b in pairs(_G.TimerTracker.timerList) do
|
||||
if b.bar and not b.bar.skinned then
|
||||
SkinIt(b.bar)
|
||||
b.bar.skinned = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function B:SkinBlizzTimers()
|
||||
B:RegisterEvent('START_TIMER')
|
||||
B:START_TIMER()
|
||||
end
|
||||
56
Modules/Blizzard/Vehicle.lua
Normal file
56
Modules/Blizzard/Vehicle.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local GetVehicleUIIndicator = GetVehicleUIIndicator
|
||||
local GetVehicleUIIndicatorSeat = GetVehicleUIIndicatorSeat
|
||||
local VehicleSeatIndicator_SetUpVehicle = VehicleSeatIndicator_SetUpVehicle
|
||||
|
||||
local function SetPosition(_,_,anchor)
|
||||
if anchor == 'MinimapCluster' or anchor == _G.MinimapCluster then
|
||||
_G.VehicleSeatIndicator:ClearAllPoints()
|
||||
_G.VehicleSeatIndicator:Point('TOPLEFT', _G.VehicleSeatMover, 'TOPLEFT', 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function VehicleSetUp(vehicleID)
|
||||
local size = E.db.general.vehicleSeatIndicatorSize
|
||||
_G.VehicleSeatIndicator:Size(size)
|
||||
|
||||
local _, numSeatIndicators = GetVehicleUIIndicator(vehicleID)
|
||||
if numSeatIndicators then
|
||||
local fourth = size / 4
|
||||
|
||||
for i = 1, numSeatIndicators do
|
||||
local button = _G['VehicleSeatIndicatorButton'..i]
|
||||
button:Size(fourth)
|
||||
|
||||
local _, xOffset, yOffset = GetVehicleUIIndicatorSeat(vehicleID, i)
|
||||
button:ClearAllPoints()
|
||||
button:Point('CENTER', button:GetParent(), 'TOPLEFT', xOffset * size, -yOffset * size)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function B:UpdateVehicleFrame()
|
||||
if _G.VehicleSeatIndicator.currSkin then
|
||||
VehicleSeatIndicator_SetUpVehicle(_G.VehicleSeatIndicator.currSkin)
|
||||
end
|
||||
end
|
||||
|
||||
function B:PositionVehicleFrame()
|
||||
local VehicleSeatIndicator = _G.VehicleSeatIndicator
|
||||
if not VehicleSeatIndicator.PositionVehicleFrameHooked then
|
||||
hooksecurefunc(VehicleSeatIndicator, 'SetPoint', SetPosition)
|
||||
hooksecurefunc('VehicleSeatIndicator_SetUpVehicle', VehicleSetUp)
|
||||
E:CreateMover(VehicleSeatIndicator, 'VehicleSeatMover', L["Vehicle Seat Frame"], nil, nil, nil, nil, nil, 'general,blizzUIImprovements')
|
||||
VehicleSeatIndicator.PositionVehicleFrameHooked = true
|
||||
end
|
||||
|
||||
VehicleSeatIndicator:Size(E.db.general.vehicleSeatIndicatorSize)
|
||||
|
||||
if VehicleSeatIndicator.currSkin then
|
||||
VehicleSetUp(VehicleSeatIndicator.currSkin)
|
||||
end
|
||||
end
|
||||
53
Modules/Blizzard/WidgetsUI.lua
Normal file
53
Modules/Blizzard/WidgetsUI.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local B = E:GetModule('Blizzard')
|
||||
|
||||
local _G = _G
|
||||
local CreateFrame = CreateFrame
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
|
||||
local function topCenterPosition(self, _, b)
|
||||
local holder = _G.TopCenterContainerHolder
|
||||
if b and (b ~= holder) then
|
||||
self:ClearAllPoints()
|
||||
self:Point('CENTER', holder)
|
||||
self:SetParent(holder)
|
||||
end
|
||||
end
|
||||
|
||||
local function belowMinimapPosition(self, _, b)
|
||||
local holder = _G.BelowMinimapContainerHolder
|
||||
if b and (b ~= holder) then
|
||||
self:ClearAllPoints()
|
||||
self:Point('CENTER', holder, 'CENTER')
|
||||
self:SetParent(holder)
|
||||
end
|
||||
end
|
||||
|
||||
local function UIWidgets()
|
||||
local topCenterContainer = _G.UIWidgetTopCenterContainerFrame
|
||||
local belowMiniMapcontainer = _G.UIWidgetBelowMinimapContainerFrame
|
||||
|
||||
local topCenterHolder = CreateFrame('Frame', 'TopCenterContainerHolder', E.UIParent)
|
||||
topCenterHolder:Point('TOP', E.UIParent, 'TOP', 0, -30)
|
||||
topCenterHolder:Size(10, 58)
|
||||
|
||||
local belowMiniMapHolder = CreateFrame('Frame', 'BelowMinimapContainerHolder', E.UIParent)
|
||||
belowMiniMapHolder:Point('TOPRIGHT', _G.Minimap, 'BOTTOMRIGHT', 0, -16)
|
||||
belowMiniMapHolder:Size(128, 40)
|
||||
|
||||
E:CreateMover(topCenterHolder, 'TopCenterContainerMover', L["UIWidgetTopContainer"], nil, nil, nil,'ALL,SOLO')
|
||||
E:CreateMover(belowMiniMapHolder, 'BelowMinimapContainerMover', L["UIWidgetBelowMinimapContainer"], nil, nil, nil,'ALL,SOLO')
|
||||
|
||||
topCenterContainer:ClearAllPoints()
|
||||
topCenterContainer:Point('CENTER', topCenterHolder)
|
||||
|
||||
belowMiniMapcontainer:ClearAllPoints()
|
||||
belowMiniMapcontainer:Point('CENTER', belowMiniMapHolder, 'CENTER')
|
||||
|
||||
hooksecurefunc(topCenterContainer, 'SetPoint', topCenterPosition)
|
||||
hooksecurefunc(belowMiniMapcontainer, 'SetPoint', belowMinimapPosition)
|
||||
end
|
||||
|
||||
function B:Handle_UIWidgets()
|
||||
UIWidgets()
|
||||
end
|
||||
3315
Modules/Chat/Chat.lua
Normal file
3315
Modules/Chat/Chat.lua
Normal file
File diff suppressed because it is too large
Load Diff
3
Modules/Chat/Load_Chat.xml
Normal file
3
Modules/Chat/Load_Chat.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='Chat.lua'/>
|
||||
</Ui>
|
||||
138
Modules/DataBars/Azerite.lua
Normal file
138
Modules/DataBars/Azerite.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DB = E:GetModule('DataBars')
|
||||
|
||||
local _G = _G
|
||||
local floor = floor
|
||||
local format = format
|
||||
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local HasArtifactEquipped = HasArtifactEquipped
|
||||
local SocketInventoryItem = SocketInventoryItem
|
||||
local UIParentLoadAddOn = UIParentLoadAddOn
|
||||
local ToggleFrame = ToggleFrame
|
||||
local Item = Item
|
||||
|
||||
local C_ArtifactUI_IsEquippedArtifactDisabled = C_ArtifactUI.IsEquippedArtifactDisabled
|
||||
local C_AzeriteItem_FindActiveAzeriteItem = C_AzeriteItem.FindActiveAzeriteItem
|
||||
local C_AzeriteItem_GetAzeriteItemXPInfo = C_AzeriteItem.GetAzeriteItemXPInfo
|
||||
local C_AzeriteItem_GetPowerLevel = C_AzeriteItem.GetPowerLevel
|
||||
local C_AzeriteItem_IsAzeriteItemAtMaxLevel = C_AzeriteItem.IsAzeriteItemAtMaxLevel
|
||||
local ARTIFACT_POWER = ARTIFACT_POWER
|
||||
|
||||
function DB:AzeriteBar_Update(event, unit)
|
||||
if event == 'UNIT_INVENTORY_CHANGED' and unit ~= 'player' then return end
|
||||
|
||||
local bar = DB.StatusBars.Azerite
|
||||
DB:SetVisibility(bar)
|
||||
|
||||
if not bar.db.enable or bar:ShouldHide() then return end
|
||||
|
||||
local item = C_AzeriteItem_FindActiveAzeriteItem()
|
||||
local cur, max = C_AzeriteItem_GetAzeriteItemXPInfo(item)
|
||||
local currentLevel = C_AzeriteItem_GetPowerLevel(item)
|
||||
local color = DB.db.colors.azerite
|
||||
|
||||
bar:SetStatusBarColor(color.r, color.g, color.b, color.a)
|
||||
bar:SetMinMaxValues(0, max)
|
||||
bar:SetValue(cur)
|
||||
|
||||
local textFormat = DB.db.azerite.textFormat
|
||||
if textFormat == 'NONE' then
|
||||
bar.text:SetText('')
|
||||
elseif textFormat == 'PERCENT' then
|
||||
bar.text:SetFormattedText('%s%% [%s]', floor(cur / max * 100), currentLevel)
|
||||
elseif textFormat == 'CURMAX' then
|
||||
bar.text:SetFormattedText('%s - %s [%s]', E:ShortValue(cur), E:ShortValue(max), currentLevel)
|
||||
elseif textFormat == 'CURPERC' then
|
||||
bar.text:SetFormattedText('%s - %s%% [%s]', E:ShortValue(cur), floor(cur / max * 100), currentLevel)
|
||||
elseif textFormat == 'CUR' then
|
||||
bar.text:SetFormattedText('%s [%s]', E:ShortValue(cur), currentLevel)
|
||||
elseif textFormat == 'REM' then
|
||||
bar.text:SetFormattedText('%s [%s]', E:ShortValue(max - cur), currentLevel)
|
||||
elseif textFormat == 'CURREM' then
|
||||
bar.text:SetFormattedText('%s - %s [%s]', E:ShortValue(cur), E:ShortValue(max - cur), currentLevel)
|
||||
elseif textFormat == 'CURPERCREM' then
|
||||
bar.text:SetFormattedText('%s - %s%% (%s) [%s]', E:ShortValue(cur), floor(cur / max * 100), E:ShortValue(max - cur), currentLevel)
|
||||
else
|
||||
bar.text:SetFormattedText('[%s]', currentLevel)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local azeriteItem, currentLevel, curXP, maxXP
|
||||
local function dataLoadedCancelFunc()
|
||||
if _G.GameTooltip:IsForbidden() then return end
|
||||
|
||||
_G.GameTooltip:AddDoubleLine(ARTIFACT_POWER, azeriteItem:GetItemName()..' ('..currentLevel..')', nil, nil, nil, 0.90, 0.80, 0.50) -- Temp Locale
|
||||
_G.GameTooltip:AddLine(' ')
|
||||
|
||||
_G.GameTooltip:AddDoubleLine(L["AP:"], format(' %d / %d (%d%%)', curXP, maxXP, curXP / maxXP * 100), 1, 1, 1)
|
||||
_G.GameTooltip:AddDoubleLine(L["Remaining:"], format(' %d (%d%% - %d '..L["Bars"]..')', maxXP - curXP, (maxXP - curXP) / maxXP * 100, 10 * (maxXP - curXP) / maxXP), 1, 1, 1)
|
||||
|
||||
_G.GameTooltip:Show()
|
||||
end
|
||||
|
||||
function DB:AzeriteBar_OnEnter()
|
||||
local item = C_AzeriteItem_FindActiveAzeriteItem()
|
||||
if item then
|
||||
if DB.db.azerite.mouseover then
|
||||
E:UIFrameFadeIn(self, 0.4, self:GetAlpha(), 1)
|
||||
end
|
||||
|
||||
if not _G.GameTooltip:IsForbidden() then
|
||||
_G.GameTooltip:ClearLines()
|
||||
_G.GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')
|
||||
end
|
||||
|
||||
curXP, maxXP = C_AzeriteItem_GetAzeriteItemXPInfo(item)
|
||||
currentLevel = C_AzeriteItem_GetPowerLevel(item)
|
||||
azeriteItem = Item:CreateFromItemLocation(item)
|
||||
azeriteItem:ContinueWithCancelOnItemLoad(dataLoadedCancelFunc)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DB:AzeriteBar_OnClick()
|
||||
if InCombatLockdown() then return end
|
||||
|
||||
if HasArtifactEquipped() and not C_ArtifactUI_IsEquippedArtifactDisabled() then
|
||||
SocketInventoryItem(_G.INVSLOT_MAINHAND)
|
||||
elseif C_AzeriteItem_FindActiveAzeriteItem() then
|
||||
UIParentLoadAddOn('Blizzard_AzeriteEssenceUI')
|
||||
ToggleFrame(_G.AzeriteEssenceUI)
|
||||
end
|
||||
end
|
||||
|
||||
function DB:AzeriteBar_Toggle()
|
||||
local bar = DB.StatusBars.Azerite
|
||||
bar.db = DB.db.azerite
|
||||
|
||||
if bar.db.enable then
|
||||
E:EnableMover(bar.holder.mover:GetName())
|
||||
|
||||
DB:RegisterEvent('AZERITE_ITEM_EXPERIENCE_CHANGED', 'AzeriteBar_Update')
|
||||
DB:RegisterEvent('PLAYER_EQUIPMENT_CHANGED', 'AzeriteBar_Update')
|
||||
|
||||
DB:AzeriteBar_Update()
|
||||
else
|
||||
E:DisableMover(bar.holder.mover:GetName())
|
||||
|
||||
DB:UnregisterEvent('AZERITE_ITEM_EXPERIENCE_CHANGED')
|
||||
DB:UnregisterEvent('PLAYER_EQUIPMENT_CHANGED')
|
||||
end
|
||||
end
|
||||
|
||||
function DB:AzeriteBar()
|
||||
local Azerite = DB:CreateBar('ElvUI_AzeriteBar', 'Azerite', DB.AzeriteBar_Update, DB.AzeriteBar_OnEnter, DB.AzeriteBar_OnClick, {'TOPRIGHT', E.UIParent, 'TOPRIGHT', -3, -245})
|
||||
DB:CreateBarBubbles(Azerite)
|
||||
|
||||
Azerite.ShouldHide = function()
|
||||
local item = C_AzeriteItem_FindActiveAzeriteItem()
|
||||
local equipped = item and item:IsEquipmentSlot()
|
||||
return not equipped or (DB.db.azerite.hideAtMaxLevel and C_AzeriteItem_IsAzeriteItemAtMaxLevel())
|
||||
end
|
||||
|
||||
E:CreateMover(Azerite.holder, 'AzeriteBarMover', L["Azerite Bar"], nil, nil, nil, nil, nil, 'databars,azerite')
|
||||
|
||||
DB:AzeriteBar_Toggle()
|
||||
end
|
||||
181
Modules/DataBars/DataBars.lua
Normal file
181
Modules/DataBars/DataBars.lua
Normal file
@@ -0,0 +1,181 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DB = E:GetModule('DataBars')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local unpack, select = unpack, select
|
||||
local pairs, ipairs = pairs, ipairs
|
||||
local CreateFrame = CreateFrame
|
||||
local GetInstanceInfo = GetInstanceInfo
|
||||
local UnitAffectingCombat = UnitAffectingCombat
|
||||
local C_PvP_IsWarModeActive = C_PvP.IsWarModeActive
|
||||
|
||||
function DB:OnLeave()
|
||||
if self.db.mouseover then
|
||||
E:UIFrameFadeOut(self, 1, self:GetAlpha(), 0)
|
||||
end
|
||||
|
||||
if not _G.GameTooltip:IsForbidden() then
|
||||
_G.GameTooltip:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function DB:CreateBar(name, key, updateFunc, onEnter, onClick, points)
|
||||
local holder = CreateFrame('Frame', name..'Holder', E.UIParent, 'BackdropTemplate')
|
||||
holder:SetTemplate(DB.db.transparent and 'Transparent')
|
||||
holder:SetScript('OnEnter', onEnter)
|
||||
holder:SetScript('OnLeave', DB.OnLeave)
|
||||
holder:SetScript('OnMouseDown', onClick)
|
||||
|
||||
if points then
|
||||
holder:ClearAllPoints()
|
||||
holder:Point(unpack(points))
|
||||
end
|
||||
|
||||
local bar = CreateFrame('StatusBar', name, holder)
|
||||
bar:SetStatusBarTexture(E.media.normTex)
|
||||
bar:EnableMouse(false)
|
||||
bar:SetInside()
|
||||
bar:Hide()
|
||||
|
||||
bar.barTexture = bar:GetStatusBarTexture()
|
||||
bar.text = bar:CreateFontString(nil, 'OVERLAY', nil, 7)
|
||||
bar.text:FontTemplate()
|
||||
bar.text:Point('CENTER')
|
||||
|
||||
bar.holder = holder
|
||||
bar.Update = updateFunc
|
||||
|
||||
E.FrameLocks[holder] = true
|
||||
DB.StatusBars[key] = bar
|
||||
|
||||
return bar
|
||||
end
|
||||
|
||||
function DB:CreateBarBubbles(bar)
|
||||
if bar.bubbles then return end
|
||||
|
||||
bar.bubbles = {}
|
||||
|
||||
for i = 1, 19 do
|
||||
bar.bubbles[i] = bar:CreateTexture(nil, 'OVERLAY', nil, 0)
|
||||
bar.bubbles[i]:SetColorTexture(0, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function DB:UpdateBarBubbles(bar)
|
||||
if not bar.bubbles then return end
|
||||
|
||||
local width, height = bar.db.width, bar.db.height
|
||||
local vertical = bar:GetOrientation() ~= 'HORIZONTAL'
|
||||
local bubbleWidth, bubbleHeight = vertical and (width - 2) or 1, vertical and 1 or (height - 2)
|
||||
local offset = (vertical and height or width) / 20
|
||||
|
||||
for i, bubble in ipairs(bar.bubbles) do
|
||||
bubble:ClearAllPoints()
|
||||
bubble:SetSize(bubbleWidth, bubbleHeight)
|
||||
bubble:SetShown(bar.db.showBubbles)
|
||||
|
||||
if vertical then
|
||||
bubble:Point('TOP', bar, 'BOTTOM', 0, offset * i)
|
||||
else
|
||||
bubble:Point('RIGHT', bar, 'LEFT', offset * i, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DB:UpdateAll()
|
||||
local texture = DB.db.customTexture and LSM:Fetch('statusbar', DB.db.statusbar) or E.media.normTex
|
||||
|
||||
for _, bar in pairs(DB.StatusBars) do
|
||||
bar.holder.db = bar.db
|
||||
bar.holder:Size(bar.db.width, bar.db.height)
|
||||
bar.holder:SetTemplate(DB.db.transparent and 'Transparent')
|
||||
bar.holder:EnableMouse(not bar.db.clickThrough)
|
||||
bar.text:FontTemplate(LSM:Fetch('font', bar.db.font), bar.db.fontSize, bar.db.fontOutline)
|
||||
bar:SetStatusBarTexture(texture)
|
||||
bar:SetReverseFill(bar.db.reverseFill)
|
||||
|
||||
if bar.db.enable then
|
||||
bar.holder:SetAlpha(bar.db.mouseover and 0 or 1)
|
||||
end
|
||||
|
||||
if bar.db.hideInVehicle then
|
||||
E:RegisterObjectForVehicleLock(bar.holder, E.UIParent)
|
||||
else
|
||||
E:UnregisterObjectForVehicleLock(bar.holder)
|
||||
end
|
||||
|
||||
if bar.db.orientation == 'AUTOMATIC' then
|
||||
bar:SetOrientation(bar.db.height > bar.db.width and 'VERTICAL' or 'HORIZONTAL')
|
||||
bar:SetRotatesTexture(bar.db.height > bar.db.width)
|
||||
else
|
||||
bar:SetOrientation(bar.db.orientation)
|
||||
bar:SetRotatesTexture(bar.db.orientation ~= 'HORIZONTAL')
|
||||
end
|
||||
|
||||
local orientation = bar:GetOrientation()
|
||||
local rotatesTexture = bar:GetRotatesTexture()
|
||||
local reverseFill = bar:GetReverseFill()
|
||||
|
||||
for i = 1, bar.holder:GetNumChildren() do
|
||||
local child = select(i, bar.holder:GetChildren())
|
||||
if child:IsObjectType('StatusBar') then
|
||||
child:SetStatusBarTexture(texture)
|
||||
child:SetOrientation(orientation)
|
||||
child:SetRotatesTexture(rotatesTexture)
|
||||
child:SetReverseFill(reverseFill)
|
||||
end
|
||||
end
|
||||
|
||||
DB:UpdateBarBubbles(bar)
|
||||
end
|
||||
|
||||
DB:HandleVisibility()
|
||||
end
|
||||
|
||||
function DB:SetVisibility(bar)
|
||||
if bar.showBar ~= nil then
|
||||
bar:SetShown(bar.showBar)
|
||||
bar.holder:SetShown(bar.showBar)
|
||||
elseif bar.db.enable then
|
||||
local hideBar = (bar == DB.StatusBars.Threat or bar.db.hideInCombat) and UnitAffectingCombat('player')
|
||||
or (bar.db.hideOutsidePvP and not (C_PvP_IsWarModeActive() or select(2, GetInstanceInfo()) == 'pvp'))
|
||||
or (bar.ShouldHide and bar:ShouldHide())
|
||||
|
||||
bar:SetShown(not hideBar)
|
||||
bar.holder:SetShown(not hideBar)
|
||||
else
|
||||
bar:SetShown(false)
|
||||
bar.holder:SetShown(false)
|
||||
end
|
||||
end
|
||||
|
||||
function DB:HandleVisibility()
|
||||
for _, bar in pairs(DB.StatusBars) do
|
||||
DB:SetVisibility(bar)
|
||||
end
|
||||
end
|
||||
|
||||
function DB:Initialize()
|
||||
DB.Initialized = true
|
||||
DB.StatusBars = {}
|
||||
|
||||
DB.db = E.db.databars
|
||||
|
||||
DB:ExperienceBar()
|
||||
DB:ReputationBar()
|
||||
DB:HonorBar()
|
||||
DB:AzeriteBar()
|
||||
DB:ThreatBar()
|
||||
|
||||
DB:UpdateAll()
|
||||
|
||||
DB:RegisterEvent('PLAYER_LEVEL_UP', 'HandleVisibility')
|
||||
DB:RegisterEvent('PLAYER_ENTERING_WORLD', 'HandleVisibility')
|
||||
DB:RegisterEvent('PLAYER_REGEN_DISABLED', 'HandleVisibility')
|
||||
DB:RegisterEvent('PLAYER_REGEN_ENABLED', 'HandleVisibility')
|
||||
DB:RegisterEvent('PVP_TIMER_UPDATE', 'HandleVisibility')
|
||||
end
|
||||
|
||||
E:RegisterModule(DB:GetName())
|
||||
220
Modules/DataBars/Experience.lua
Normal file
220
Modules/DataBars/Experience.lua
Normal file
@@ -0,0 +1,220 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DB = E:GetModule('DataBars')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local min, format = min, format
|
||||
local CreateFrame = CreateFrame
|
||||
local GetXPExhaustion = GetXPExhaustion
|
||||
local IsXPUserDisabled = IsXPUserDisabled
|
||||
local GetQuestLogRewardXP = GetQuestLogRewardXP
|
||||
local IsPlayerAtEffectiveMaxLevel = IsPlayerAtEffectiveMaxLevel
|
||||
local C_QuestLog_GetNumQuestLogEntries = C_QuestLog.GetNumQuestLogEntries
|
||||
local C_QuestLog_GetQuestIDForLogIndex = C_QuestLog.GetQuestIDForLogIndex
|
||||
local C_QuestLog_ReadyForTurnIn = C_QuestLog.ReadyForTurnIn
|
||||
local C_QuestLog_GetInfo = C_QuestLog.GetInfo
|
||||
local UnitXP, UnitXPMax = UnitXP, UnitXPMax
|
||||
|
||||
local CurrentXP, XPToLevel, RestedXP, PercentRested
|
||||
local PercentXP, RemainXP, RemainTotal, RemainBars
|
||||
local QuestLogXP = 0
|
||||
|
||||
function DB:ExperienceBar_CheckQuests(questID, completedOnly)
|
||||
if not questID then return end
|
||||
|
||||
local isCompleted = C_QuestLog_ReadyForTurnIn(questID)
|
||||
if not completedOnly or isCompleted then
|
||||
QuestLogXP = QuestLogXP + GetQuestLogRewardXP(questID)
|
||||
end
|
||||
end
|
||||
|
||||
function DB:ExperienceBar_ShouldBeVisible()
|
||||
return not IsPlayerAtEffectiveMaxLevel() and not IsXPUserDisabled()
|
||||
end
|
||||
|
||||
function DB:ExperienceBar_Update()
|
||||
local bar = DB.StatusBars.Experience
|
||||
DB:SetVisibility(bar)
|
||||
|
||||
if not bar.db.enable or bar:ShouldHide() then return end
|
||||
|
||||
CurrentXP, XPToLevel, RestedXP = UnitXP('player'), UnitXPMax('player'), GetXPExhaustion()
|
||||
if XPToLevel <= 0 then XPToLevel = 1 end
|
||||
|
||||
local remainXP = XPToLevel - CurrentXP
|
||||
local remainPercent = remainXP / XPToLevel
|
||||
RemainTotal, RemainBars = remainPercent * 100, remainPercent * 20
|
||||
PercentXP, RemainXP = (CurrentXP / XPToLevel) * 100, E:ShortValue(remainXP)
|
||||
|
||||
local expColor, restedColor = DB.db.colors.experience, DB.db.colors.rested
|
||||
bar:SetStatusBarColor(expColor.r, expColor.g, expColor.b, expColor.a)
|
||||
bar.Rested:SetStatusBarColor(restedColor.r, restedColor.g, restedColor.b, restedColor.a)
|
||||
|
||||
local displayString, textFormat = '', DB.db.experience.textFormat
|
||||
|
||||
if not DB:ExperienceBar_ShouldBeVisible() then
|
||||
bar:SetMinMaxValues(0, 1)
|
||||
bar:SetValue(1)
|
||||
|
||||
if textFormat ~= 'NONE' then
|
||||
displayString = IsXPUserDisabled() and L["Disabled"] or L["Max Level"]
|
||||
end
|
||||
else
|
||||
bar:SetMinMaxValues(0, XPToLevel)
|
||||
bar:SetValue(CurrentXP)
|
||||
|
||||
if textFormat == 'PERCENT' then
|
||||
displayString = format('%.2f%%', PercentXP)
|
||||
elseif textFormat == 'CURMAX' then
|
||||
displayString = format('%s - %s', E:ShortValue(CurrentXP), E:ShortValue(XPToLevel))
|
||||
elseif textFormat == 'CURPERC' then
|
||||
displayString = format('%s - %.2f%%', E:ShortValue(CurrentXP), PercentXP)
|
||||
elseif textFormat == 'CUR' then
|
||||
displayString = format('%s', E:ShortValue(CurrentXP))
|
||||
elseif textFormat == 'REM' then
|
||||
displayString = format('%s', RemainXP)
|
||||
elseif textFormat == 'CURREM' then
|
||||
displayString = format('%s - %s', E:ShortValue(CurrentXP), RemainXP)
|
||||
elseif textFormat == 'CURPERCREM' then
|
||||
displayString = format('%s - %.2f%% (%s)', E:ShortValue(CurrentXP), PercentXP, RemainXP)
|
||||
end
|
||||
|
||||
local isRested = RestedXP and RestedXP > 0
|
||||
if isRested then
|
||||
bar.Rested:SetMinMaxValues(0, XPToLevel)
|
||||
bar.Rested:SetValue(min(CurrentXP + RestedXP, XPToLevel))
|
||||
|
||||
PercentRested = (RestedXP / XPToLevel) * 100
|
||||
|
||||
if textFormat == 'PERCENT' then
|
||||
displayString = format('%s R:%.2f%%', displayString, PercentRested)
|
||||
elseif textFormat == 'CURPERC' then
|
||||
displayString = format('%s R:%s [%.2f%%]', displayString, E:ShortValue(RestedXP), PercentRested)
|
||||
elseif textFormat ~= 'NONE' then
|
||||
displayString = format('%s R:%s', displayString, E:ShortValue(RestedXP))
|
||||
end
|
||||
end
|
||||
|
||||
if bar.db.showLevel then
|
||||
displayString = format('%s %s : %s', L['Level'], E.mylevel, displayString)
|
||||
end
|
||||
|
||||
bar.Rested:SetShown(isRested)
|
||||
end
|
||||
|
||||
bar.text:SetText(displayString)
|
||||
end
|
||||
|
||||
function DB:ExperienceBar_QuestXP()
|
||||
if not DB:ExperienceBar_ShouldBeVisible() then return end
|
||||
local bar = DB.StatusBars.Experience
|
||||
|
||||
QuestLogXP = 0
|
||||
|
||||
for i = 1, C_QuestLog_GetNumQuestLogEntries() do
|
||||
local info = C_QuestLog_GetInfo(i)
|
||||
if info and (not info.isHidden) and (bar.db.questCurrentZoneOnly and info.isOnMap or not bar.db.questCurrentZoneOnly) then
|
||||
DB:ExperienceBar_CheckQuests(C_QuestLog_GetQuestIDForLogIndex(i), bar.db.questCompletedOnly)
|
||||
end
|
||||
end
|
||||
|
||||
if QuestLogXP > 0 then
|
||||
bar.Quest:SetMinMaxValues(0, XPToLevel)
|
||||
bar.Quest:SetValue(min(CurrentXP + QuestLogXP, XPToLevel))
|
||||
bar.Quest:SetStatusBarColor(DB.db.colors.quest.r, DB.db.colors.quest.g, DB.db.colors.quest.b, DB.db.colors.quest.a)
|
||||
bar.Quest:Show()
|
||||
else
|
||||
bar.Quest:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function DB:ExperienceBar_OnEnter()
|
||||
if self.db.mouseover then
|
||||
E:UIFrameFadeIn(self, 0.4, self:GetAlpha(), 1)
|
||||
end
|
||||
|
||||
if _G.GameTooltip:IsForbidden() or not DB:ExperienceBar_ShouldBeVisible() then return end
|
||||
|
||||
_G.GameTooltip:ClearLines()
|
||||
_G.GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')
|
||||
|
||||
_G.GameTooltip:AddLine(L["Experience"])
|
||||
_G.GameTooltip:AddLine(' ')
|
||||
|
||||
_G.GameTooltip:AddDoubleLine(L["XP:"], format(' %d / %d (%.2f%%)', CurrentXP, XPToLevel, PercentXP), 1, 1, 1)
|
||||
_G.GameTooltip:AddDoubleLine(L["Remaining:"], format(' %s (%.2f%% - %d '..L["Bars"]..')', RemainXP, RemainTotal, RemainBars), 1, 1, 1)
|
||||
_G.GameTooltip:AddDoubleLine(L["Quest Log XP:"], QuestLogXP, 1, 1, 1)
|
||||
|
||||
if RestedXP and RestedXP > 0 then
|
||||
_G.GameTooltip:AddDoubleLine(L["Rested:"], format('+%d (%.2f%%)', RestedXP, PercentRested), 1, 1, 1)
|
||||
end
|
||||
|
||||
_G.GameTooltip:Show()
|
||||
end
|
||||
|
||||
function DB:ExperienceBar_OnClick() end
|
||||
|
||||
function DB:ExperienceBar_Toggle()
|
||||
local bar = DB.StatusBars.Experience
|
||||
bar.db = DB.db.experience
|
||||
|
||||
if bar.db.enable then
|
||||
E:EnableMover(bar.holder.mover:GetName())
|
||||
else
|
||||
E:DisableMover(bar.holder.mover:GetName())
|
||||
end
|
||||
|
||||
if bar.db.enable and not bar:ShouldHide() then
|
||||
DB:RegisterEvent('PLAYER_XP_UPDATE', 'ExperienceBar_Update')
|
||||
DB:RegisterEvent('DISABLE_XP_GAIN', 'ExperienceBar_Update')
|
||||
DB:RegisterEvent('ENABLE_XP_GAIN', 'ExperienceBar_Update')
|
||||
DB:RegisterEvent('UPDATE_EXHAUSTION', 'ExperienceBar_Update')
|
||||
DB:RegisterEvent('QUEST_LOG_UPDATE', 'ExperienceBar_QuestXP')
|
||||
DB:RegisterEvent('ZONE_CHANGED', 'ExperienceBar_QuestXP')
|
||||
DB:RegisterEvent('ZONE_CHANGED_NEW_AREA', 'ExperienceBar_QuestXP')
|
||||
DB:UnregisterEvent('UPDATE_EXPANSION_LEVEL')
|
||||
|
||||
DB:ExperienceBar_Update()
|
||||
else
|
||||
DB:UnregisterEvent('PLAYER_XP_UPDATE')
|
||||
DB:UnregisterEvent('DISABLE_XP_GAIN')
|
||||
DB:UnregisterEvent('ENABLE_XP_GAIN')
|
||||
DB:UnregisterEvent('UPDATE_EXHAUSTION')
|
||||
DB:UnregisterEvent('QUEST_LOG_UPDATE')
|
||||
DB:UnregisterEvent('ZONE_CHANGED')
|
||||
DB:UnregisterEvent('ZONE_CHANGED_NEW_AREA')
|
||||
DB:RegisterEvent('UPDATE_EXPANSION_LEVEL', 'ExperienceBar_Toggle')
|
||||
end
|
||||
end
|
||||
|
||||
function DB:ExperienceBar()
|
||||
local Experience = DB:CreateBar('ElvUI_ExperienceBar', 'Experience', DB.ExperienceBar_Update, DB.ExperienceBar_OnEnter, DB.ExperienceBar_OnClick, {'BOTTOM', E.UIParent, 'BOTTOM', 0, 43})
|
||||
Experience.barTexture:SetDrawLayer('ARTWORK', 4)
|
||||
DB:CreateBarBubbles(Experience)
|
||||
|
||||
Experience.ShouldHide = function()
|
||||
return DB.db.experience.hideAtMaxLevel and not DB:ExperienceBar_ShouldBeVisible()
|
||||
end
|
||||
|
||||
local Rested = CreateFrame('StatusBar', 'ElvUI_ExperienceBar_Rested', Experience.holder)
|
||||
Rested:SetStatusBarTexture(DB.db.customTexture and LSM:Fetch('statusbar', DB.db.statusbar) or E.media.normTex)
|
||||
Rested:EnableMouse(false)
|
||||
Rested:SetInside()
|
||||
Rested:Hide()
|
||||
Rested.barTexture = Rested:GetStatusBarTexture()
|
||||
Rested.barTexture:SetDrawLayer('ARTWORK', 2)
|
||||
Experience.Rested = Rested
|
||||
|
||||
local Quest = CreateFrame('StatusBar', 'ElvUI_ExperienceBar_Quest', Experience.holder)
|
||||
Quest:SetStatusBarTexture(DB.db.customTexture and LSM:Fetch('statusbar', DB.db.statusbar) or E.media.normTex)
|
||||
Quest:EnableMouse(false)
|
||||
Quest:SetInside()
|
||||
Quest:Hide()
|
||||
Quest.barTexture = Quest:GetStatusBarTexture()
|
||||
Quest.barTexture:SetDrawLayer('ARTWORK', 3)
|
||||
Experience.Quest = Quest
|
||||
|
||||
E:CreateMover(Experience.holder, 'ExperienceBarMover', L["Experience Bar"], nil, nil, nil, nil, nil, 'databars,experience')
|
||||
|
||||
DB:ExperienceBar_Toggle()
|
||||
end
|
||||
111
Modules/DataBars/Honor.lua
Normal file
111
Modules/DataBars/Honor.lua
Normal file
@@ -0,0 +1,111 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DB = E:GetModule('DataBars')
|
||||
|
||||
local _G = _G
|
||||
local format = format
|
||||
local UnitHonor = UnitHonor
|
||||
local UnitHonorLevel = UnitHonorLevel
|
||||
local IsPlayerAtEffectiveMaxLevel = IsPlayerAtEffectiveMaxLevel
|
||||
local UnitHonorMax = UnitHonorMax
|
||||
local TogglePVPUI = TogglePVPUI
|
||||
local HONOR = HONOR
|
||||
|
||||
local CurrentHonor, MaxHonor, CurrentLevel, PercentHonor, RemainingHonor
|
||||
|
||||
function DB:HonorBar_Update(event, unit)
|
||||
if event == 'PLAYER_FLAGS_CHANGED' and unit ~= 'player' then return end
|
||||
|
||||
local bar = DB.StatusBars.Honor
|
||||
DB:SetVisibility(bar)
|
||||
|
||||
if not DB.db.honor.enable then return end
|
||||
|
||||
CurrentHonor, MaxHonor, CurrentLevel = UnitHonor('player'), UnitHonorMax('player'), UnitHonorLevel('player')
|
||||
|
||||
--Guard against division by zero, which appears to be an issue when zoning in/out of dungeons
|
||||
if MaxHonor == 0 then MaxHonor = 1 end
|
||||
|
||||
PercentHonor, RemainingHonor = (CurrentHonor / MaxHonor) * 100, MaxHonor - CurrentHonor
|
||||
|
||||
local displayString, textFormat = '', DB.db.honor.textFormat
|
||||
local color = DB.db.colors.honor
|
||||
|
||||
bar:SetMinMaxValues(0, MaxHonor)
|
||||
bar:SetValue(CurrentHonor)
|
||||
bar:SetStatusBarColor(color.r, color.g, color.b, color.a)
|
||||
|
||||
if textFormat == 'PERCENT' then
|
||||
displayString = format('%d%% - [%s]', PercentHonor, CurrentLevel)
|
||||
elseif textFormat == 'CURMAX' then
|
||||
displayString = format('%s - %s - [%s]', E:ShortValue(CurrentHonor), E:ShortValue(MaxHonor), CurrentLevel)
|
||||
elseif textFormat == 'CURPERC' then
|
||||
displayString = format('%s - %d%% - [%s]', E:ShortValue(CurrentHonor), PercentHonor, CurrentLevel)
|
||||
elseif textFormat == 'CUR' then
|
||||
displayString = format('%s - [%s]', E:ShortValue(CurrentHonor), CurrentLevel)
|
||||
elseif textFormat == 'REM' then
|
||||
displayString = format('%s - [%s]', E:ShortValue(RemainingHonor), CurrentLevel)
|
||||
elseif textFormat == 'CURREM' then
|
||||
displayString = format('%s - %s - [%s]', E:ShortValue(CurrentHonor), E:ShortValue(RemainingHonor), CurrentLevel)
|
||||
elseif textFormat == 'CURPERCREM' then
|
||||
displayString = format('%s - %d%% (%s) - [%s]', E:ShortValue(CurrentHonor), CurrentHonor, E:ShortValue(RemainingHonor), CurrentLevel)
|
||||
end
|
||||
|
||||
bar.text:SetText(displayString)
|
||||
end
|
||||
|
||||
function DB:HonorBar_OnEnter()
|
||||
if self.db.mouseover then
|
||||
E:UIFrameFadeIn(self, .4, self:GetAlpha(), 1)
|
||||
end
|
||||
|
||||
if _G.GameTooltip:IsForbidden() then return end
|
||||
|
||||
_G.GameTooltip:ClearLines()
|
||||
_G.GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')
|
||||
|
||||
_G.GameTooltip:AddLine(HONOR)
|
||||
|
||||
_G.GameTooltip:AddDoubleLine(L["Current Level:"], CurrentLevel, 1, 1, 1)
|
||||
_G.GameTooltip:AddLine(' ')
|
||||
|
||||
_G.GameTooltip:AddDoubleLine(L["Honor XP:"], format(' %d / %d (%d%%)', CurrentHonor, MaxHonor, PercentHonor), 1, 1, 1)
|
||||
_G.GameTooltip:AddDoubleLine(L["Honor Remaining:"], format(' %d (%d%% - %d '..L["Bars"]..')', RemainingHonor, (RemainingHonor) / MaxHonor * 100, 20 * (RemainingHonor) / MaxHonor), 1, 1, 1)
|
||||
|
||||
_G.GameTooltip:Show()
|
||||
end
|
||||
|
||||
function DB:HonorBar_OnClick()
|
||||
TogglePVPUI()
|
||||
end
|
||||
|
||||
function DB:HonorBar_Toggle()
|
||||
local bar = DB.StatusBars.Honor
|
||||
bar.db = DB.db.honor
|
||||
|
||||
if bar.db.enable then
|
||||
E:EnableMover(bar.holder.mover:GetName())
|
||||
|
||||
DB:RegisterEvent('HONOR_XP_UPDATE', 'HonorBar_Update')
|
||||
DB:RegisterEvent('PLAYER_FLAGS_CHANGED', 'HonorBar_Update')
|
||||
|
||||
DB:HonorBar_Update()
|
||||
else
|
||||
E:DisableMover(bar.holder.mover:GetName())
|
||||
|
||||
DB:UnregisterEvent('HONOR_XP_UPDATE')
|
||||
DB:UnregisterEvent('PLAYER_FLAGS_CHANGED')
|
||||
end
|
||||
end
|
||||
|
||||
function DB:HonorBar()
|
||||
local Honor = DB:CreateBar('ElvUI_HonorBar', 'Honor', DB.HonorBar_Update, DB.HonorBar_OnEnter, DB.HonorBar_OnClick, {'TOPRIGHT', E.UIParent, 'TOPRIGHT', -3, -255})
|
||||
DB:CreateBarBubbles(Honor)
|
||||
|
||||
Honor.ShouldHide = function()
|
||||
return DB.db.honor.hideBelowMaxLevel and not IsPlayerAtEffectiveMaxLevel()
|
||||
end
|
||||
|
||||
E:CreateMover(Honor.holder, 'HonorBarMover', L["Honor Bar"], nil, nil, nil, nil, nil, 'databars,honor')
|
||||
|
||||
DB:HonorBar_Toggle()
|
||||
end
|
||||
8
Modules/DataBars/Load_DataBars.xml
Normal file
8
Modules/DataBars/Load_DataBars.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='DataBars.lua'/>
|
||||
<Script file='Experience.lua'/>
|
||||
<Script file='Reputation.lua'/>
|
||||
<Script file='Honor.lua'/>
|
||||
<Script file='Threat.lua'/>
|
||||
<Script file='Azerite.lua'/>
|
||||
</Ui>
|
||||
154
Modules/DataBars/Reputation.lua
Normal file
154
Modules/DataBars/Reputation.lua
Normal file
@@ -0,0 +1,154 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DB = E:GetModule('DataBars')
|
||||
|
||||
local _G = _G
|
||||
local format = format
|
||||
local IsPlayerAtEffectiveMaxLevel = IsPlayerAtEffectiveMaxLevel
|
||||
local C_Reputation_GetFactionParagonInfo = C_Reputation.GetFactionParagonInfo
|
||||
local C_Reputation_IsFactionParagon = C_Reputation.IsFactionParagon
|
||||
local GetFriendshipReputation = GetFriendshipReputation
|
||||
local GetWatchedFactionInfo = GetWatchedFactionInfo
|
||||
local ToggleCharacter = ToggleCharacter
|
||||
local REPUTATION = REPUTATION
|
||||
local STANDING = STANDING
|
||||
|
||||
function DB:ReputationBar_Update()
|
||||
local bar = DB.StatusBars.Reputation
|
||||
DB:SetVisibility(bar)
|
||||
|
||||
if not bar.db.enable or bar:ShouldHide() then return end
|
||||
|
||||
local name, reaction, Min, Max, value, factionID = GetWatchedFactionInfo()
|
||||
local displayString, textFormat = '', DB.db.reputation.textFormat
|
||||
local isCapped, isFriend, friendText, standingLabel
|
||||
local friendshipID = GetFriendshipReputation(factionID)
|
||||
local color = DB.db.colors.useCustomFactionColors and DB.db.colors.factionColors[reaction] or _G.FACTION_BAR_COLORS[reaction]
|
||||
|
||||
if friendshipID then
|
||||
local _, friendRep, _, _, _, _, friendTextLevel, friendThreshold, nextFriendThreshold = GetFriendshipReputation(factionID)
|
||||
isFriend, reaction, friendText = true, 5, friendTextLevel
|
||||
if nextFriendThreshold then
|
||||
Min, Max, value = friendThreshold, nextFriendThreshold, friendRep;
|
||||
else
|
||||
Min, Max, value = 0, 1, 1
|
||||
isCapped = true
|
||||
end
|
||||
elseif C_Reputation_IsFactionParagon(factionID) then
|
||||
local currentValue, threshold, _, hasRewardPending = C_Reputation_GetFactionParagonInfo(factionID)
|
||||
if currentValue and threshold then
|
||||
Min, Max = 0, threshold
|
||||
value = currentValue % threshold
|
||||
if hasRewardPending then
|
||||
value = value + threshold
|
||||
end
|
||||
end
|
||||
elseif reaction == _G.MAX_REPUTATION_REACTION then
|
||||
Min, Max, value = 0, 1, 1
|
||||
isCapped = true
|
||||
end
|
||||
|
||||
bar:SetMinMaxValues(Min, Max)
|
||||
bar:SetValue(value)
|
||||
bar:SetStatusBarColor(color.r, color.g, color.b)
|
||||
|
||||
standingLabel = _G['FACTION_STANDING_LABEL'..reaction]
|
||||
|
||||
--Prevent a division by zero
|
||||
local maxMinDiff = Max - Min
|
||||
if maxMinDiff == 0 then
|
||||
maxMinDiff = 1
|
||||
end
|
||||
|
||||
if isCapped and textFormat ~= 'NONE' then
|
||||
-- show only name and standing on exalted
|
||||
displayString = format('%s: [%s]', name, isFriend and friendText or standingLabel)
|
||||
else
|
||||
if textFormat == 'PERCENT' then
|
||||
displayString = format('%s: %d%% [%s]', name, ((value - Min) / (maxMinDiff) * 100), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CURMAX' then
|
||||
displayString = format('%s: %s - %s [%s]', name, E:ShortValue(value - Min), E:ShortValue(Max - Min), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CURPERC' then
|
||||
displayString = format('%s: %s - %d%% [%s]', name, E:ShortValue(value - Min), ((value - Min) / (maxMinDiff) * 100), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CUR' then
|
||||
displayString = format('%s: %s [%s]', name, E:ShortValue(value - Min), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'REM' then
|
||||
displayString = format('%s: %s [%s]', name, E:ShortValue((Max - Min) - (value-Min)), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CURREM' then
|
||||
displayString = format('%s: %s - %s [%s]', name, E:ShortValue(value - Min), E:ShortValue((Max - Min) - (value-Min)), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CURPERCREM' then
|
||||
displayString = format('%s: %s - %d%% (%s) [%s]', name, E:ShortValue(value - Min), ((value - Min) / (maxMinDiff) * 100), E:ShortValue((Max - Min) - (value-Min)), isFriend and friendText or standingLabel)
|
||||
end
|
||||
end
|
||||
|
||||
bar.text:SetText(displayString)
|
||||
end
|
||||
|
||||
function DB:ReputationBar_OnEnter()
|
||||
if self.db.mouseover then
|
||||
E:UIFrameFadeIn(self, 0.4, self:GetAlpha(), 1)
|
||||
end
|
||||
|
||||
local name, reaction, min, max, value, factionID = GetWatchedFactionInfo()
|
||||
if factionID and C_Reputation_IsFactionParagon(factionID) then
|
||||
local currentValue, threshold, _, hasRewardPending = C_Reputation_GetFactionParagonInfo(factionID)
|
||||
if currentValue and threshold then
|
||||
min, max = 0, threshold
|
||||
value = currentValue % threshold
|
||||
if hasRewardPending then
|
||||
value = value + threshold
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if name and not _G.GameTooltip:IsForbidden() then
|
||||
_G.GameTooltip:ClearLines()
|
||||
_G.GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')
|
||||
_G.GameTooltip:AddLine(name)
|
||||
_G.GameTooltip:AddLine(' ')
|
||||
|
||||
local friendID, friendTextLevel, _
|
||||
if factionID then friendID, _, _, _, _, _, friendTextLevel = GetFriendshipReputation(factionID) end
|
||||
|
||||
_G.GameTooltip:AddDoubleLine(STANDING..':', (friendID and friendTextLevel) or _G['FACTION_STANDING_LABEL'..reaction], 1, 1, 1)
|
||||
if reaction ~= _G.MAX_REPUTATION_REACTION or C_Reputation_IsFactionParagon(factionID) then
|
||||
_G.GameTooltip:AddDoubleLine(REPUTATION..':', format('%d / %d (%d%%)', value - min, max - min, (value - min) / ((max - min == 0) and max or (max - min)) * 100), 1, 1, 1)
|
||||
end
|
||||
_G.GameTooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function DB:ReputationBar_OnClick()
|
||||
ToggleCharacter('ReputationFrame')
|
||||
end
|
||||
|
||||
function DB:ReputationBar_Toggle()
|
||||
local bar = DB.StatusBars.Reputation
|
||||
bar.db = DB.db.reputation
|
||||
|
||||
if bar.db.enable then
|
||||
E:EnableMover(bar.holder.mover:GetName())
|
||||
|
||||
DB:RegisterEvent('UPDATE_FACTION', 'ReputationBar_Update')
|
||||
DB:RegisterEvent('COMBAT_TEXT_UPDATE', 'ReputationBar_Update')
|
||||
|
||||
DB:ReputationBar_Update()
|
||||
else
|
||||
E:DisableMover(bar.holder.mover:GetName())
|
||||
|
||||
DB:UnregisterEvent('UPDATE_FACTION')
|
||||
DB:UnregisterEvent('COMBAT_TEXT_UPDATE')
|
||||
end
|
||||
end
|
||||
|
||||
function DB:ReputationBar()
|
||||
local Reputation = DB:CreateBar('ElvUI_ReputationBar', 'Reputation', DB.ReputationBar_Update, DB.ReputationBar_OnEnter, DB.ReputationBar_OnClick, {'TOPRIGHT', E.UIParent, 'TOPRIGHT', -3, -264})
|
||||
DB:CreateBarBubbles(Reputation)
|
||||
|
||||
Reputation.ShouldHide = function()
|
||||
return (DB.db.reputation.hideBelowMaxLevel and not IsPlayerAtEffectiveMaxLevel()) or not GetWatchedFactionInfo()
|
||||
end
|
||||
|
||||
E:CreateMover(Reputation.holder, 'ReputationBarMover', L["Reputation Bar"], nil, nil, nil, nil, nil, 'databars,reputation')
|
||||
|
||||
DB:ReputationBar_Toggle()
|
||||
end
|
||||
140
Modules/DataBars/Threat.lua
Normal file
140
Modules/DataBars/Threat.lua
Normal file
@@ -0,0 +1,140 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DB = E:GetModule('DataBars')
|
||||
|
||||
local pairs, select, wipe = pairs, select, wipe
|
||||
|
||||
local GetThreatStatusColor = GetThreatStatusColor
|
||||
local IsInGroup, IsInRaid = IsInGroup, IsInRaid
|
||||
local UnitClass = UnitClass
|
||||
local UnitAffectingCombat = UnitAffectingCombat
|
||||
local UnitDetailedThreatSituation = UnitDetailedThreatSituation
|
||||
local UnitExists = UnitExists
|
||||
local UnitIsPlayer = UnitIsPlayer
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
local UnitName = UnitName
|
||||
local UnitReaction = UnitReaction
|
||||
local UNKNOWN = UNKNOWN
|
||||
-- GLOBALS: ElvUF
|
||||
|
||||
function DB:ThreatBar_GetLargestThreatOnList(percent)
|
||||
local largestValue, largestUnit = 0, nil
|
||||
for unit, threatPercent in pairs(DB.StatusBars.Threat.list) do
|
||||
if threatPercent > largestValue then
|
||||
largestValue = threatPercent
|
||||
largestUnit = unit
|
||||
end
|
||||
end
|
||||
|
||||
return (percent - largestValue), largestUnit
|
||||
end
|
||||
|
||||
function DB:ThreatBar_GetColor(unit)
|
||||
local unitReaction = UnitReaction(unit, 'player')
|
||||
local _, unitClass = UnitClass(unit)
|
||||
if (UnitIsPlayer(unit)) then
|
||||
local class = E:ClassColor(unitClass)
|
||||
if not class then return 194, 194, 194 end
|
||||
return class.r*255, class.g*255, class.b*255
|
||||
elseif (unitReaction) then
|
||||
local reaction = ElvUF.colors.reaction[unitReaction]
|
||||
return reaction[1]*255, reaction[2]*255, reaction[3]*255
|
||||
else
|
||||
return 194, 194, 194
|
||||
end
|
||||
end
|
||||
|
||||
function DB:ThreatBar_Update()
|
||||
local bar = DB.StatusBars.Threat
|
||||
local isInGroup, isInRaid, petExists = IsInGroup(), IsInRaid(), UnitExists('pet')
|
||||
|
||||
if UnitAffectingCombat('player') and (isInGroup or petExists) then
|
||||
local _, status, percent = UnitDetailedThreatSituation('player', 'target')
|
||||
local name = UnitName('target') or UNKNOWN
|
||||
bar.showBar = true
|
||||
|
||||
if percent == 100 then
|
||||
if petExists then
|
||||
bar.list.pet = select(3, UnitDetailedThreatSituation('pet', 'target'))
|
||||
end
|
||||
|
||||
if isInRaid then
|
||||
for i = 1, 40 do
|
||||
if UnitExists('raid'..i) and not UnitIsUnit('raid'..i, 'player') then
|
||||
bar.list['raid'..i] = select(3, UnitDetailedThreatSituation('raid'..i, 'target'))
|
||||
end
|
||||
end
|
||||
elseif isInGroup then
|
||||
for i = 1, 4 do
|
||||
if UnitExists('party'..i) then
|
||||
bar.list['party'..i] = select(3, UnitDetailedThreatSituation('party'..i, 'target'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local leadPercent, largestUnit = DB:ThreatBar_GetLargestThreatOnList(percent)
|
||||
if leadPercent > 0 and largestUnit ~= nil then
|
||||
local r, g, b = DB:ThreatBar_GetColor(largestUnit)
|
||||
bar.text:SetFormattedText(L["ABOVE_THREAT_FORMAT"], name, percent, leadPercent, r, g, b, UnitName(largestUnit) or UNKNOWN)
|
||||
|
||||
if E.myrole == 'TANK' then
|
||||
bar:SetStatusBarColor(0, 0.839, 0)
|
||||
bar:SetValue(leadPercent)
|
||||
else
|
||||
bar:SetStatusBarColor(GetThreatStatusColor(status))
|
||||
bar:SetValue(percent)
|
||||
end
|
||||
else
|
||||
bar:SetStatusBarColor(GetThreatStatusColor(status))
|
||||
bar.text:SetFormattedText('%s: %.0f%%', name, percent)
|
||||
bar:SetValue(percent)
|
||||
end
|
||||
elseif percent then
|
||||
bar:SetStatusBarColor(GetThreatStatusColor(status))
|
||||
bar.text:SetFormattedText('%s: %.0f%%', name, percent)
|
||||
bar:SetValue(percent)
|
||||
else
|
||||
bar.showBar = false
|
||||
end
|
||||
else
|
||||
bar.showBar = false
|
||||
end
|
||||
|
||||
DB:SetVisibility(bar) -- lower visibility because of using showBar variable
|
||||
|
||||
wipe(bar.list)
|
||||
end
|
||||
|
||||
function DB:ThreatBar_Toggle()
|
||||
local bar = DB.StatusBars.Threat
|
||||
bar.db = DB.db.threat
|
||||
|
||||
if bar.db.enable then
|
||||
E:EnableMover(bar.holder.mover:GetName())
|
||||
|
||||
DB:RegisterEvent('PLAYER_TARGET_CHANGED', 'ThreatBar_Update')
|
||||
DB:RegisterEvent('UNIT_THREAT_LIST_UPDATE', 'ThreatBar_Update')
|
||||
DB:RegisterEvent('GROUP_ROSTER_UPDATE', 'ThreatBar_Update')
|
||||
DB:RegisterEvent('UNIT_FLAGS', 'ThreatBar_Update')
|
||||
DB:RegisterEvent('UNIT_PET', 'ThreatBar_Update')
|
||||
|
||||
DB:ThreatBar_Update()
|
||||
else
|
||||
E:DisableMover(bar.holder.mover:GetName())
|
||||
|
||||
DB:UnregisterEvent('PLAYER_TARGET_CHANGED')
|
||||
DB:UnregisterEvent('UNIT_THREAT_LIST_UPDATE')
|
||||
DB:UnregisterEvent('GROUP_ROSTER_UPDATE')
|
||||
DB:UnregisterEvent('UNIT_FLAGS')
|
||||
DB:UnregisterEvent('UNIT_PET')
|
||||
end
|
||||
end
|
||||
|
||||
function DB:ThreatBar()
|
||||
local Threat = DB:CreateBar('ElvUI_ThreatBar', 'Threat', DB.ThreatBar_Update, nil, nil, {'TOPRIGHT', E.UIParent, 'TOPRIGHT', -3, -245})
|
||||
Threat:SetMinMaxValues(0, 100)
|
||||
Threat.list = {}
|
||||
|
||||
E:CreateMover(Threat.holder, 'ThreatBarMover', L["Threat Bar"], nil, nil, nil, nil, nil, 'databars,threat')
|
||||
|
||||
DB:ThreatBar_Toggle()
|
||||
end
|
||||
30
Modules/DataTexts/Agility.lua
Normal file
30
Modules/DataTexts/Agility.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...))
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local strjoin = strjoin
|
||||
local UnitStat = UnitStat
|
||||
local ITEM_MOD_AGILITY_SHORT = ITEM_MOD_AGILITY_SHORT
|
||||
local LE_UNIT_STAT_AGILITY = LE_UNIT_STAT_AGILITY
|
||||
local STAT_CATEGORY_ATTRIBUTES = STAT_CATEGORY_ATTRIBUTES
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEvent(self)
|
||||
if E.global.datatexts.settings.Agility.NoLabel then
|
||||
self.text:SetFormattedText(displayString, UnitStat('player', LE_UNIT_STAT_AGILITY))
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Agility.Label ~= '' and E.global.datatexts.settings.Agility.Label or ITEM_MOD_AGILITY_SHORT..': ', UnitStat('player', LE_UNIT_STAT_AGILITY))
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Agility.NoLabel and '' or '%s', hex, '%d|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Agility', STAT_CATEGORY_ATTRIBUTES, {'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE'}, OnEvent, nil, nil, nil, nil, ITEM_MOD_AGILITY_SHORT, nil, ValueColorUpdate)
|
||||
55
Modules/DataTexts/Armor.lua
Normal file
55
Modules/DataTexts/Armor.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local select = select
|
||||
local format = format
|
||||
local strjoin = strjoin
|
||||
local UnitLevel = UnitLevel
|
||||
local UnitArmor = UnitArmor
|
||||
local PaperDollFrame_GetArmorReduction = PaperDollFrame_GetArmorReduction
|
||||
local STAT_CATEGORY_ATTRIBUTES = STAT_CATEGORY_ATTRIBUTES
|
||||
local ARMOR = ARMOR
|
||||
|
||||
local chanceString = '%.2f%%'
|
||||
local displayString, lastPanel, effectiveArmor = ''
|
||||
|
||||
local function OnEvent(self)
|
||||
effectiveArmor = select(2, UnitArmor('player'))
|
||||
|
||||
if E.global.datatexts.settings.Armor.NoLabel then
|
||||
self.text:SetFormattedText(displayString, effectiveArmor)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Armor.Label ~= '' and E.global.datatexts.settings.Armor.Label or ARMOR..': ', effectiveArmor)
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
DT.tooltip:AddLine(L["Mitigation By Level: "])
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
local playerlvl = E.mylevel + 3
|
||||
for _ = 1, 4 do
|
||||
local armorReduction = PaperDollFrame_GetArmorReduction(effectiveArmor, playerlvl)
|
||||
DT.tooltip:AddDoubleLine(playerlvl,format(chanceString, armorReduction),1,1,1)
|
||||
playerlvl = playerlvl - 1
|
||||
end
|
||||
local lv = UnitLevel('target')
|
||||
if lv and lv > 0 and (lv > playerlvl + 3 or lv < playerlvl) then
|
||||
local armorReduction = PaperDollFrame_GetArmorReduction(effectiveArmor, lv)
|
||||
DT.tooltip:AddDoubleLine(lv, format(chanceString, armorReduction),1,1,1)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Armor.NoLabel and '' or '%s', hex, '%d|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Armor', STAT_CATEGORY_ATTRIBUTES, {'UNIT_STATS', 'UNIT_RESISTANCES', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE'}, OnEvent, nil, nil, OnEnter, nil, ARMOR, nil, ValueColorUpdate)
|
||||
117
Modules/DataTexts/Avoidance.lua
Normal file
117
Modules/DataTexts/Avoidance.lua
Normal file
@@ -0,0 +1,117 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local format, strjoin, abs = format, strjoin, abs
|
||||
local GetBlockChance = GetBlockChance
|
||||
local GetBonusBarOffset = GetBonusBarOffset
|
||||
local GetDodgeChance = GetDodgeChance
|
||||
local GetInventoryItemID = GetInventoryItemID
|
||||
local GetInventorySlotInfo = GetInventorySlotInfo
|
||||
local GetItemInfo = GetItemInfo
|
||||
local GetParryChance = GetParryChance
|
||||
local UnitLevel = UnitLevel
|
||||
local BOSS = BOSS
|
||||
local BLOCK_CHANCE = BLOCK_CHANCE
|
||||
local DODGE_CHANCE = DODGE_CHANCE
|
||||
local MISS_CHANCE = MISS_CHANCE
|
||||
local PARRY_CHANCE = PARRY_CHANCE
|
||||
local STAT_CATEGORY_ENHANCEMENTS = STAT_CATEGORY_ENHANCEMENTS
|
||||
|
||||
local displayString, lastPanel, targetlv, playerlv
|
||||
local basemisschance, leveldifference, dodge, parry, block, unhittable
|
||||
local AVD_DECAY_RATE, chanceString = 1.5, '%.2f%%'
|
||||
|
||||
local function IsWearingShield()
|
||||
local slotID = GetInventorySlotInfo('SecondaryHandSlot')
|
||||
local itemID = GetInventoryItemID('player', slotID)
|
||||
|
||||
if itemID then
|
||||
local _, _, _, _, _, _, _, _, itemEquipLoc = GetItemInfo(itemID)
|
||||
return itemEquipLoc == 'INVTYPE_SHIELD'
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
targetlv, playerlv = UnitLevel('target'), E.mylevel
|
||||
|
||||
basemisschance = E.myrace == 'NightElf' and 7 or 5
|
||||
if targetlv == -1 then
|
||||
leveldifference = 3
|
||||
elseif targetlv > playerlv then
|
||||
leveldifference = (targetlv - playerlv)
|
||||
elseif targetlv < playerlv and targetlv > 0 then
|
||||
leveldifference = (targetlv - playerlv)
|
||||
else
|
||||
leveldifference = 0
|
||||
end
|
||||
|
||||
if leveldifference >= 0 then
|
||||
dodge = (GetDodgeChance() - leveldifference * AVD_DECAY_RATE)
|
||||
parry = (GetParryChance() - leveldifference * AVD_DECAY_RATE)
|
||||
block = (GetBlockChance() - leveldifference * AVD_DECAY_RATE)
|
||||
basemisschance = (basemisschance - leveldifference * AVD_DECAY_RATE)
|
||||
else
|
||||
dodge = (GetDodgeChance() + abs(leveldifference * AVD_DECAY_RATE))
|
||||
parry = (GetParryChance() + abs(leveldifference * AVD_DECAY_RATE))
|
||||
block = (GetBlockChance() + abs(leveldifference * AVD_DECAY_RATE))
|
||||
basemisschance = (basemisschance+ abs(leveldifference * AVD_DECAY_RATE))
|
||||
end
|
||||
|
||||
local unhittableMax = 100
|
||||
local numAvoidances = 4
|
||||
if dodge <= 0 then dodge = 0 end
|
||||
if parry <= 0 then parry = 0 end
|
||||
if block <= 0 then block = 0 end
|
||||
|
||||
if E.myclass == 'DRUID' and GetBonusBarOffset() == 3 then
|
||||
parry = 0
|
||||
numAvoidances = numAvoidances - 1
|
||||
end
|
||||
|
||||
if not IsWearingShield() then
|
||||
block = 0
|
||||
numAvoidances = numAvoidances - 1
|
||||
end
|
||||
|
||||
unhittableMax = unhittableMax + ((AVD_DECAY_RATE * leveldifference) * numAvoidances)
|
||||
|
||||
local avoided = (dodge+parry+basemisschance) --First roll on hit table determining if the hit missed
|
||||
local blocked = (100 - avoided)*block/100 --If the hit landed then the second roll determines if the his was blocked
|
||||
local avoidance = (avoided+blocked)
|
||||
unhittable = avoidance - unhittableMax
|
||||
|
||||
if E.global.datatexts.settings.Avoidance.NoLabel then
|
||||
self.text:SetFormattedText(displayString, avoidance)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Avoidance.Label ~= '' and E.global.datatexts.settings.Avoidance.Label or L["AVD: "], avoidance)
|
||||
end
|
||||
|
||||
--print(unhittableMax) -- should report 102.4 for a level differance of +3 for shield classes, 101.2 for druids, 101.8 for monks and dks
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local rightString = targetlv > 1 and strjoin('', ' (', L["lvl"], ' ', targetlv, ')') or targetlv == -1 and strjoin('', ' (', BOSS, ')') or strjoin('', ' (', L["lvl"], ' ', playerlv, ')')
|
||||
DT.tooltip:AddDoubleLine(L["Avoidance Breakdown"], rightString)
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
DT.tooltip:AddDoubleLine(DODGE_CHANCE, format(chanceString, dodge), 1, 1, 1)
|
||||
DT.tooltip:AddDoubleLine(PARRY_CHANCE, format(chanceString, parry), 1, 1, 1)
|
||||
DT.tooltip:AddDoubleLine(BLOCK_CHANCE, format(chanceString, block), 1, 1, 1)
|
||||
DT.tooltip:AddDoubleLine(MISS_CHANCE, format(chanceString, basemisschance), 1, 1, 1)
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
DT.tooltip:AddDoubleLine(L["Unhittable:"], (unhittable > 0 and '+' or '')..format(chanceString, unhittable), 1, 1, 1, (unhittable < 0 and 1 or 0), (unhittable > 0 and 1 or 0), 0)
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Avoidance.NoLabel and '' or '%s', hex, '%.'..E.global.datatexts.settings.Avoidance.decimalLength..'f%%|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Avoidance', STAT_CATEGORY_ENHANCEMENTS, {'UNIT_TARGET', 'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE', 'PLAYER_EQUIPMENT_CHANGED'}, OnEvent, nil, nil, OnEnter, nil, L["Avoidance Breakdown"], nil, ValueColorUpdate)
|
||||
98
Modules/DataTexts/Bags.lua
Normal file
98
Modules/DataTexts/Bags.lua
Normal file
@@ -0,0 +1,98 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local strjoin = strjoin
|
||||
local format = format
|
||||
local GetContainerNumFreeSlots = GetContainerNumFreeSlots
|
||||
local GetContainerNumSlots = GetContainerNumSlots
|
||||
local ToggleAllBags = ToggleAllBags
|
||||
local CURRENCY = CURRENCY
|
||||
local NUM_BAG_SLOTS = NUM_BAG_SLOTS
|
||||
local MAX_WATCHED_TOKENS = MAX_WATCHED_TOKENS
|
||||
local GetBagName = GetBagName
|
||||
local GetInventoryItemQuality = GetInventoryItemQuality
|
||||
local GetItemQualityColor = GetItemQualityColor
|
||||
local GetInventoryItemTexture = GetInventoryItemTexture
|
||||
local C_CurrencyInfo_GetBackpackCurrencyInfo = C_CurrencyInfo.GetBackpackCurrencyInfo
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
local iconString = '|T%s:14:14:0:0:64:64:4:60:4:60|t %s'
|
||||
local bagIcon = 'Interface/Buttons/Button-Backpack-Up'
|
||||
|
||||
local function OnEvent(self)
|
||||
lastPanel = self
|
||||
local free, total, used = 0, 0
|
||||
for i = 0, NUM_BAG_SLOTS do
|
||||
free, total = free + GetContainerNumFreeSlots(i), total + GetContainerNumSlots(i)
|
||||
end
|
||||
used = total - free
|
||||
|
||||
local textFormat = E.global.datatexts.settings.Bags.textFormat
|
||||
|
||||
if textFormat == "FREE" then
|
||||
self.text:SetFormattedText(displayString, L["Bags"]..": ", free)
|
||||
elseif textFormat == "USED" then
|
||||
self.text:SetFormattedText(displayString, L["Bags"]..": ", used)
|
||||
elseif textFormat == "FREE_TOTAL" then
|
||||
self.text:SetFormattedText(displayString, L["Bags"]..": ", free, total)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, L["Bags"]..": ", used, total)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnClick()
|
||||
ToggleAllBags()
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
for i = 0, NUM_BAG_SLOTS do
|
||||
local bagName = GetBagName(i)
|
||||
if bagName then
|
||||
local numSlots = GetContainerNumSlots(i)
|
||||
local freeSlots = GetContainerNumFreeSlots(i)
|
||||
local usedSlots, sumNum = numSlots - freeSlots, 19 + i
|
||||
|
||||
local r2, g2, b2 = E:ColorGradient(usedSlots / numSlots, .1,1,.1, 1,1,.1, 1,.1,.1)
|
||||
local r, g, b, icon
|
||||
|
||||
if i > 0 then
|
||||
r, g, b = GetItemQualityColor(GetInventoryItemQuality('player', sumNum) or 1)
|
||||
icon = GetInventoryItemTexture('player', sumNum)
|
||||
end
|
||||
|
||||
DT.tooltip:AddDoubleLine(format(iconString, icon or bagIcon, bagName), format('%d / %d', usedSlots, numSlots), r or 1, g or 1, b or 1, r2, g2, b2)
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, MAX_WATCHED_TOKENS do
|
||||
local info = C_CurrencyInfo_GetBackpackCurrencyInfo(i)
|
||||
if info then
|
||||
if i == 1 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(CURRENCY)
|
||||
DT.tooltip:AddLine(' ')
|
||||
end
|
||||
if info.quantity then
|
||||
DT.tooltip:AddDoubleLine(format(iconString, info.iconFileID, info.name), info.quantity, 1, 1, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
local textFormat = E.global.datatexts.settings.Bags.textFormat
|
||||
if textFormat == "FREE" or textFormat == "USED" then
|
||||
displayString = strjoin('', '%s', hex, '%d|r')
|
||||
else
|
||||
displayString = strjoin('', '%s', hex, '%d/%d|r')
|
||||
end
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Bags', nil, {'BAG_UPDATE'}, OnEvent, nil, OnClick, OnEnter, nil, L["Bags"], nil, ValueColorUpdate)
|
||||
118
Modules/DataTexts/BattleStats.lua
Normal file
118
Modules/DataTexts/BattleStats.lua
Normal file
@@ -0,0 +1,118 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local sort = sort
|
||||
local ipairs = ipairs
|
||||
local strlen = strlen
|
||||
local strjoin = strjoin
|
||||
local C_PvP_GetMatchPVPStatColumns = C_PvP.GetMatchPVPStatColumns
|
||||
local GetNumBattlefieldScores = GetNumBattlefieldScores
|
||||
local GetBattlefieldStatData = GetBattlefieldStatData
|
||||
local GetBattlefieldScore = GetBattlefieldScore
|
||||
local BATTLEGROUND = BATTLEGROUND
|
||||
|
||||
local displayString = ''
|
||||
local holder = {
|
||||
LEFT = { data = {}, _G.KILLS, _G.KILLING_BLOWS, _G.DEATHS },
|
||||
RIGHT = { data = {}, _G.DAMAGE, _G.SHOW_COMBAT_HEALING, _G.HONOR }
|
||||
}
|
||||
|
||||
DT.BattleStats = holder
|
||||
function DT:UpdateBattlePanel(which)
|
||||
local info = which and holder[which]
|
||||
|
||||
local panel = info and info.panel
|
||||
if not panel then return end
|
||||
|
||||
for i, name in ipairs(info) do
|
||||
local dt = panel[i]
|
||||
if dt and dt.text then
|
||||
dt.text:SetFormattedText(displayString, name, info.data[i] or 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local myIndex
|
||||
local LEFT = holder.LEFT.data
|
||||
local RIGHT = holder.RIGHT.data
|
||||
function DT:UPDATE_BATTLEFIELD_SCORE()
|
||||
myIndex = nil
|
||||
|
||||
for i = 1, GetNumBattlefieldScores() do
|
||||
local name, kb, hks, deaths, honor, _, _, _, _, dmg, heals = GetBattlefieldScore(i)
|
||||
if name == E.myname then
|
||||
LEFT[1], LEFT[2], LEFT[3] = E:ShortValue(hks), E:ShortValue(kb), E:ShortValue(deaths)
|
||||
RIGHT[1], RIGHT[2], RIGHT[3] = E:ShortValue(dmg), E:ShortValue(heals), E:ShortValue(honor)
|
||||
myIndex = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if myIndex then
|
||||
DT:UpdateBattlePanel('LEFT')
|
||||
DT:UpdateBattlePanel('RIGHT')
|
||||
end
|
||||
end
|
||||
|
||||
local function columnSort(lhs,rhs)
|
||||
return lhs.orderIndex < rhs.orderIndex
|
||||
end
|
||||
|
||||
function DT:HoverBattleStats() -- OnEnter
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
if myIndex and DT.ShowingBattleStats == 'pvp' then
|
||||
local columns = C_PvP_GetMatchPVPStatColumns()
|
||||
if columns then
|
||||
sort(columns, columnSort)
|
||||
|
||||
local firstLine
|
||||
local classColor = E:ClassColor(E.myclass)
|
||||
DT.tooltip:AddDoubleLine(BATTLEGROUND, E.MapInfo.name, 1,1,1, classColor.r, classColor.g, classColor.b)
|
||||
|
||||
-- Add extra statistics to watch based on what BG you are in.
|
||||
for i, stat in ipairs(columns) do
|
||||
local name = stat.name
|
||||
if name and strlen(name) > 0 then
|
||||
if not firstLine then
|
||||
DT.tooltip:AddLine(' ')
|
||||
firstLine = true
|
||||
end
|
||||
|
||||
DT.tooltip:AddDoubleLine(name, GetBattlefieldStatData(myIndex, i), 1,1,1)
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:ToggleBattleStats()
|
||||
if DT.ForceHideBGStats then
|
||||
DT.ForceHideBGStats = nil
|
||||
E:Print(L["Battleground datatexts will now show again if you are inside a battleground."])
|
||||
else
|
||||
DT.ForceHideBGStats = true
|
||||
E:Print(L["Battleground datatexts temporarily hidden, to show type /bgstats"])
|
||||
end
|
||||
|
||||
DT:UpdatePanelInfo('LeftChatDataPanel')
|
||||
DT:UpdatePanelInfo('RightChatDataPanel')
|
||||
|
||||
if DT.ShowingBattleStats then
|
||||
DT:UpdateBattlePanel('LEFT')
|
||||
DT:UpdateBattlePanel('RIGHT')
|
||||
end
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', '%s: ', hex, '%s|r')
|
||||
|
||||
if DT.ShowingBattleStats then
|
||||
DT:UpdateBattlePanel('LEFT')
|
||||
DT:UpdateBattlePanel('RIGHT')
|
||||
end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
172
Modules/DataTexts/CallToArms.lua
Normal file
172
Modules/DataTexts/CallToArms.lua
Normal file
@@ -0,0 +1,172 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local strjoin = strjoin
|
||||
|
||||
local GetLFGRandomDungeonInfo = GetLFGRandomDungeonInfo
|
||||
local GetLFGRoleShortageRewards = GetLFGRoleShortageRewards
|
||||
local GetNumRandomDungeons = GetNumRandomDungeons
|
||||
local GetNumRFDungeons = GetNumRFDungeons
|
||||
local GetRFDungeonInfo = GetRFDungeonInfo
|
||||
local PVEFrame_ToggleFrame = PVEFrame_ToggleFrame
|
||||
local LFG_ROLE_NUM_SHORTAGE_TYPES = LFG_ROLE_NUM_SHORTAGE_TYPES
|
||||
local BATTLEGROUND_HOLIDAY = BATTLEGROUND_HOLIDAY
|
||||
local DUNGEONS = DUNGEONS
|
||||
local RAID_FINDER = RAID_FINDER
|
||||
|
||||
local TANK_ICON = E:TextureString(E.Media.Textures.Tank, ':14:14')
|
||||
local HEALER_ICON = E:TextureString(E.Media.Textures.Healer, ':14:14')
|
||||
local DPS_ICON = E:TextureString(E.Media.Textures.DPS, ':14:14')
|
||||
local enteredFrame, lastPanel = false
|
||||
local displayString = ''
|
||||
|
||||
local function MakeIconString(tank, healer, damage)
|
||||
local str = ''
|
||||
if tank then
|
||||
str = str..TANK_ICON
|
||||
end
|
||||
if healer then
|
||||
str = str..HEALER_ICON
|
||||
end
|
||||
if damage then
|
||||
str = str..DPS_ICON
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local tankReward = false
|
||||
local healerReward = false
|
||||
local dpsReward = false
|
||||
local unavailable = true
|
||||
|
||||
--Dungeons
|
||||
for i = 1, GetNumRandomDungeons() do
|
||||
local id = GetLFGRandomDungeonInfo(i)
|
||||
for x = 1, LFG_ROLE_NUM_SHORTAGE_TYPES do
|
||||
local eligible, forTank, forHealer, forDamage, itemCount = GetLFGRoleShortageRewards(id, x)
|
||||
if eligible and forTank and itemCount > 0 then tankReward = true; unavailable = false; end
|
||||
if eligible and forHealer and itemCount > 0 then healerReward = true; unavailable = false; end
|
||||
if eligible and forDamage and itemCount > 0 then dpsReward = true; unavailable = false; end
|
||||
end
|
||||
end
|
||||
|
||||
--LFR
|
||||
for i = 1, GetNumRFDungeons() do
|
||||
local id = GetRFDungeonInfo(i)
|
||||
for x = 1, LFG_ROLE_NUM_SHORTAGE_TYPES do
|
||||
local eligible, forTank, forHealer, forDamage, itemCount = GetLFGRoleShortageRewards(id, x)
|
||||
if eligible and forTank and itemCount > 0 then tankReward = true; unavailable = false; end
|
||||
if eligible and forHealer and itemCount > 0 then healerReward = true; unavailable = false; end
|
||||
if eligible and forDamage and itemCount > 0 then dpsReward = true; unavailable = false; end
|
||||
end
|
||||
end
|
||||
|
||||
if E.global.datatexts.settings.CallToArms.NoLabel then
|
||||
self.text:SetFormattedText(displayString, unavailable and 'N/A' or MakeIconString(tankReward, healerReward, dpsReward))
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.CallToArms.Label ~= '' and E.global.datatexts.settings.CallToArms.Label or BATTLEGROUND_HOLIDAY..": ", unavailable and 'N/A' or MakeIconString(tankReward, healerReward, dpsReward))
|
||||
end
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function OnClick()
|
||||
PVEFrame_ToggleFrame('GroupFinderFrame', _G.LFDParentFrame)
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.CallToArms.NoLabel and '' or '%s', hex, '%s|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
enteredFrame = true
|
||||
|
||||
local numCTA = 0
|
||||
local addTooltipHeader, addTooltipSeparator = true
|
||||
for i = 1, GetNumRandomDungeons() do
|
||||
local id, name = GetLFGRandomDungeonInfo(i)
|
||||
local tankReward = false
|
||||
local healerReward = false
|
||||
local dpsReward = false
|
||||
local unavailable = true
|
||||
for x = 1, LFG_ROLE_NUM_SHORTAGE_TYPES do
|
||||
local eligible, forTank, forHealer, forDamage, itemCount = GetLFGRoleShortageRewards(id, x)
|
||||
if eligible then unavailable = false end
|
||||
if eligible and forTank and itemCount > 0 then tankReward = true end
|
||||
if eligible and forHealer and itemCount > 0 then healerReward = true end
|
||||
if eligible and forDamage and itemCount > 0 then dpsReward = true end
|
||||
end
|
||||
|
||||
if not unavailable then
|
||||
local rolesString = MakeIconString(tankReward, healerReward, dpsReward)
|
||||
if rolesString ~= '' then
|
||||
if addTooltipHeader then
|
||||
DT.tooltip:AddLine(DUNGEONS)
|
||||
addTooltipHeader = false
|
||||
addTooltipSeparator = true
|
||||
end
|
||||
DT.tooltip:AddDoubleLine(name..':', rolesString, 1, 1, 1)
|
||||
end
|
||||
if tankReward or healerReward or dpsReward then numCTA = numCTA + 1 end
|
||||
end
|
||||
end
|
||||
|
||||
addTooltipHeader = true
|
||||
for i = 1, GetNumRFDungeons() do
|
||||
local id, name = GetRFDungeonInfo(i)
|
||||
local tankReward = false
|
||||
local healerReward = false
|
||||
local dpsReward = false
|
||||
local unavailable = true
|
||||
|
||||
for x = 1, LFG_ROLE_NUM_SHORTAGE_TYPES do
|
||||
local eligible, forTank, forHealer, forDamage, itemCount = GetLFGRoleShortageRewards(id, x)
|
||||
if eligible then unavailable = false end
|
||||
if eligible and forTank and itemCount > 0 then tankReward = true end
|
||||
if eligible and forHealer and itemCount > 0 then healerReward = true end
|
||||
if eligible and forDamage and itemCount > 0 then dpsReward = true end
|
||||
end
|
||||
|
||||
if not unavailable then
|
||||
local rolesString = MakeIconString(tankReward, healerReward, dpsReward)
|
||||
if rolesString ~= '' then
|
||||
if addTooltipHeader then
|
||||
if addTooltipSeparator then DT.tooltip:AddLine(' ') end
|
||||
DT.tooltip:AddLine(RAID_FINDER)
|
||||
addTooltipHeader = false
|
||||
end
|
||||
DT.tooltip:AddDoubleLine(name..':', rolesString, 1, 1, 1)
|
||||
end
|
||||
if tankReward or healerReward or dpsReward then numCTA = numCTA + 1 end
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local updateInterval = 10
|
||||
local function Update(self, elapsed)
|
||||
if self.timeSinceUpdate and self.timeSinceUpdate > updateInterval then
|
||||
OnEvent(self)
|
||||
|
||||
if enteredFrame then
|
||||
OnEnter(self)
|
||||
end
|
||||
|
||||
self.timeSinceUpdate = 0
|
||||
else
|
||||
self.timeSinceUpdate = (self.timeSinceUpdate or 0) + elapsed
|
||||
end
|
||||
end
|
||||
|
||||
local function OnLeave()
|
||||
enteredFrame = false
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('CallToArms', nil, {"LFG_UPDATE_RANDOM_INFO"}, OnEvent, Update, OnClick, OnEnter, OnLeave, BATTLEGROUND_HOLIDAY, nil, ValueColorUpdate)
|
||||
55
Modules/DataTexts/CombatTime.lua
Normal file
55
Modules/DataTexts/CombatTime.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local floor, format, strjoin = floor, format, strjoin
|
||||
local GetInstanceInfo = GetInstanceInfo
|
||||
local GetTime = GetTime
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
local timerText, timer, startTime = L["Combat"], 0, 0
|
||||
|
||||
local function UpdateText()
|
||||
return format(E.global.datatexts.settings.Combat.TimeFull and '%02d:%02d:%02d' or '%02d:%02d', floor(timer/60), timer % 60, (timer - floor(timer)) * 100)
|
||||
end
|
||||
|
||||
local function OnUpdate(self)
|
||||
timer = GetTime() - startTime
|
||||
self.text:SetFormattedText(displayString, timerText, UpdateText())
|
||||
end
|
||||
|
||||
local function DelayOnUpdate(self, elapsed)
|
||||
startTime = startTime - elapsed
|
||||
if startTime <= 0 then
|
||||
timer, startTime = 0, GetTime()
|
||||
self:SetScript('OnUpdate', OnUpdate)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEvent(self, event, _, timeSeconds)
|
||||
local _, instanceType = GetInstanceInfo()
|
||||
local isInArena = instanceType == 'arena'
|
||||
|
||||
if event == 'START_TIMER' and isInArena then
|
||||
timerText, timer, startTime = L["Arena"], 0, timeSeconds
|
||||
self.text:SetFormattedText(displayString, timerText, '00:00:00')
|
||||
self:SetScript('OnUpdate', DelayOnUpdate)
|
||||
elseif event == 'PLAYER_REGEN_ENABLED' and not isInArena then
|
||||
self:SetScript('OnUpdate', nil)
|
||||
elseif event == 'PLAYER_REGEN_DISABLED' and not isInArena then
|
||||
timerText, timer, startTime = L["Combat"], 0, GetTime()
|
||||
self:SetScript('OnUpdate', OnUpdate)
|
||||
elseif not self.text:GetText() then
|
||||
self.text:SetFormattedText(displayString, timerText, 'N/A')
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', '%s: ', hex, '%s|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Combat', nil, {'START_TIMER', 'PLAYER_REGEN_DISABLED', 'PLAYER_REGEN_ENABLED'}, OnEvent, nil, nil, nil, nil, L["Combat/Arena Time"], nil, ValueColorUpdate)
|
||||
59
Modules/DataTexts/ConfigElvUI.lua
Normal file
59
Modules/DataTexts/ConfigElvUI.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local pairs, strjoin = pairs, strjoin
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local ReloadUI = ReloadUI
|
||||
|
||||
local displayString = ''
|
||||
local configText = 'ElvUI'
|
||||
local reloadText = RELOADUI
|
||||
local lastPanel
|
||||
|
||||
local function OnEvent(self)
|
||||
lastPanel = self
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.ElvUI.Label ~= '' and E.global.datatexts.settings.ElvUI.Label or configText)
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
DT.tooltip:AddDoubleLine(L["Left Click:"], L["Toggle Configuration"], 1, 1, 1)
|
||||
DT.tooltip:AddDoubleLine(L["Hold Shift + Right Click:"], reloadText, 1, 1, 1)
|
||||
|
||||
if E.Libs.EP.registeredPrefix then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddDoubleLine('Plugins:', 'Version:')
|
||||
|
||||
for _, plugin in pairs(E.Libs.EP.plugins) do
|
||||
if not plugin.isLib then
|
||||
local r, g, b = E:HexToRGB(plugin.old and 'ff3333' or '33ff33')
|
||||
DT.tooltip:AddDoubleLine(plugin.title, plugin.version, 1, 1, 1, r/255, g/255, b/255)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnClick(_, button)
|
||||
if InCombatLockdown() then _G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT) return end
|
||||
|
||||
if button == 'LeftButton' then
|
||||
E:ToggleOptionsUI()
|
||||
elseif button == 'RightButton' and IsShiftKeyDown() then
|
||||
ReloadUI()
|
||||
end
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', hex, '%s|r')
|
||||
|
||||
if lastPanel then
|
||||
OnEvent(lastPanel, 'ELVUI_COLOR_UPDATE')
|
||||
end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('ElvUI', nil, nil, OnEvent, nil, OnClick, OnEnter, nil, L['ElvUI Config'], nil, ValueColorUpdate)
|
||||
43
Modules/DataTexts/Coordinates.lua
Normal file
43
Modules/DataTexts/Coordinates.lua
Normal file
@@ -0,0 +1,43 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local strjoin = strjoin
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
|
||||
local displayString = ''
|
||||
local inRestrictedArea = false
|
||||
local mapInfo = E.MapInfo
|
||||
|
||||
local function Update(self, elapsed)
|
||||
if inRestrictedArea or not mapInfo.coordsWatching then return end
|
||||
|
||||
self.timeSinceUpdate = (self.timeSinceUpdate or 0) + elapsed
|
||||
|
||||
if self.timeSinceUpdate > 0.1 then
|
||||
self.text:SetFormattedText(displayString, mapInfo.xText or 0, mapInfo.yText or 0)
|
||||
self.timeSinceUpdate = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
if mapInfo.x and mapInfo.y then
|
||||
inRestrictedArea = false
|
||||
self.text:SetFormattedText(displayString, mapInfo.xText or 0, mapInfo.yText or 0)
|
||||
else
|
||||
inRestrictedArea = true
|
||||
self.text:SetText('N/A')
|
||||
end
|
||||
end
|
||||
|
||||
local function Click()
|
||||
if InCombatLockdown() then _G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT) return end
|
||||
_G.ToggleFrame(_G.WorldMapFrame)
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', hex, '%.2f|r', ' | ', hex, '%.2f|r')
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Coords', nil, {'LOADING_SCREEN_DISABLED', 'ZONE_CHANGED', 'ZONE_CHANGED_INDOORS', 'ZONE_CHANGED_NEW_AREA'}, OnEvent, Update, Click, nil, nil, L["Coords"], mapInfo, ValueColorUpdate)
|
||||
96
Modules/DataTexts/Crit.lua
Normal file
96
Modules/DataTexts/Crit.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local min = min
|
||||
local format, strjoin = format, strjoin
|
||||
|
||||
local BreakUpLargeNumbers = BreakUpLargeNumbers
|
||||
local GetCombatRating = GetCombatRating
|
||||
local GetCombatRatingBonus = GetCombatRatingBonus
|
||||
local GetCritChance = GetCritChance
|
||||
local GetRangedCritChance = GetRangedCritChance
|
||||
local GetSpellCritChance = GetSpellCritChance
|
||||
local GetCritChanceProvidesParryEffect = GetCritChanceProvidesParryEffect
|
||||
local GetCombatRatingBonusForCombatRatingValue = GetCombatRatingBonusForCombatRatingValue
|
||||
local CR_CRIT_MELEE = CR_CRIT_MELEE
|
||||
local CR_CRIT_RANGED = CR_CRIT_RANGED
|
||||
local CR_CRIT_SPELL = CR_CRIT_SPELL
|
||||
local CR_PARRY = CR_PARRY
|
||||
local MAX_SPELL_SCHOOLS = MAX_SPELL_SCHOOLS
|
||||
local CRIT_ABBR = CRIT_ABBR
|
||||
local FONT_COLOR_CODE_CLOSE = FONT_COLOR_CODE_CLOSE
|
||||
local HIGHLIGHT_FONT_COLOR_CODE = HIGHLIGHT_FONT_COLOR_CODE
|
||||
local MELEE_CRIT_CHANCE = MELEE_CRIT_CHANCE
|
||||
local PAPERDOLLFRAME_TOOLTIP_FORMAT = PAPERDOLLFRAME_TOOLTIP_FORMAT
|
||||
local RANGED_CRIT_CHANCE = RANGED_CRIT_CHANCE
|
||||
local SPELL_CRIT_CHANCE = SPELL_CRIT_CHANCE
|
||||
local STAT_CATEGORY_ENHANCEMENTS = STAT_CATEGORY_ENHANCEMENTS
|
||||
local CR_CRIT_PARRY_RATING_TOOLTIP = CR_CRIT_PARRY_RATING_TOOLTIP
|
||||
local CR_CRIT_TOOLTIP = CR_CRIT_TOOLTIP
|
||||
local displayString, lastPanel = ''
|
||||
local rating, spellCrit, rangedCrit, meleeCrit, critChance
|
||||
local extraCritChance, extraCritRating
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local tooltip, critText
|
||||
if spellCrit >= rangedCrit and spellCrit >= meleeCrit then
|
||||
critText = SPELL_CRIT_CHANCE
|
||||
elseif rangedCrit >= meleeCrit then
|
||||
critText = RANGED_CRIT_CHANCE
|
||||
else
|
||||
critText = MELEE_CRIT_CHANCE;
|
||||
end
|
||||
|
||||
if GetCritChanceProvidesParryEffect() then
|
||||
tooltip = format(CR_CRIT_PARRY_RATING_TOOLTIP, BreakUpLargeNumbers(extraCritRating), extraCritChance, GetCombatRatingBonusForCombatRatingValue(CR_PARRY, extraCritRating));
|
||||
else
|
||||
tooltip = format(CR_CRIT_TOOLTIP, BreakUpLargeNumbers(extraCritRating), extraCritChance);
|
||||
end
|
||||
|
||||
DT.tooltip:AddDoubleLine(HIGHLIGHT_FONT_COLOR_CODE..format(PAPERDOLLFRAME_TOOLTIP_FORMAT, critText)..' '..format('%.2f%%', critChance)..FONT_COLOR_CODE_CLOSE, nil, 1, 1, 1)
|
||||
DT.tooltip:AddLine(tooltip, nil, nil, nil, true)
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local minCrit = GetSpellCritChance(2)
|
||||
for i = 3, MAX_SPELL_SCHOOLS do
|
||||
spellCrit = GetSpellCritChance(i);
|
||||
minCrit = min(minCrit, spellCrit);
|
||||
end
|
||||
spellCrit = minCrit
|
||||
rangedCrit = GetRangedCritChance();
|
||||
meleeCrit = GetCritChance();
|
||||
|
||||
if spellCrit >= rangedCrit and spellCrit >= meleeCrit then
|
||||
critChance = spellCrit;
|
||||
rating = CR_CRIT_SPELL;
|
||||
elseif rangedCrit >= meleeCrit then
|
||||
critChance = rangedCrit;
|
||||
rating = CR_CRIT_RANGED;
|
||||
else
|
||||
critChance = meleeCrit;
|
||||
rating = CR_CRIT_MELEE;
|
||||
end
|
||||
|
||||
extraCritChance, extraCritRating = GetCombatRatingBonus(rating), GetCombatRating(rating)
|
||||
|
||||
if E.global.datatexts.settings.Crit.NoLabel then
|
||||
self.text:SetFormattedText(displayString, critChance)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Crit.Label ~= '' and E.global.datatexts.settings.Crit.Label or CRIT_ABBR..': ', critChance)
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Crit.NoLabel and '' or '%s', hex, '%.'..E.global.datatexts.settings.Crit.decimalLength..'f%%|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Crit', STAT_CATEGORY_ENHANCEMENTS, {'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE', 'PLAYER_DAMAGE_DONE_MODS'}, OnEvent, nil, nil, OnEnter, nil, _G.STAT_CRITICAL_STRIKE, nil, ValueColorUpdate)
|
||||
104
Modules/DataTexts/Currencies.lua
Normal file
104
Modules/DataTexts/Currencies.lua
Normal file
@@ -0,0 +1,104 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local format, tonumber = format, tonumber
|
||||
local type, ipairs, unpack = type, ipairs, unpack
|
||||
local BreakUpLargeNumbers = BreakUpLargeNumbers
|
||||
local GetMoney = GetMoney
|
||||
|
||||
local C_CurrencyInfo_GetBackpackCurrencyInfo = C_CurrencyInfo.GetBackpackCurrencyInfo
|
||||
local C_CurrencyInfo_GetCurrencyInfo = C_CurrencyInfo.GetCurrencyInfo
|
||||
local BONUS_ROLL_REWARD_MONEY = BONUS_ROLL_REWARD_MONEY
|
||||
|
||||
local iconString = '|T%s:16:16:0:0:64:64:4:60:4:60|t'
|
||||
DT.CurrencyList = { GOLD = BONUS_ROLL_REWARD_MONEY, BACKPACK = 'Backpack' }
|
||||
|
||||
local function OnClick()
|
||||
_G.ToggleCharacter('TokenFrame')
|
||||
end
|
||||
|
||||
local function GetInfo(id)
|
||||
local info = C_CurrencyInfo_GetCurrencyInfo(id)
|
||||
if info then
|
||||
return info.name, info.quantity, (info.iconFileID and format(iconString, info.iconFileID)) or '136012'
|
||||
else
|
||||
return '', '', '136012'
|
||||
end
|
||||
end
|
||||
|
||||
local function AddInfo(id)
|
||||
local name, num, icon = GetInfo(id)
|
||||
if name then
|
||||
DT.tooltip:AddDoubleLine(format('%s %s', icon, name), BreakUpLargeNumbers(num), 1, 1, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
local goldText
|
||||
local function OnEvent(self)
|
||||
goldText = E:FormatMoney(GetMoney(), E.global.datatexts.settings.Currencies.goldFormat or 'BLIZZARD', not E.global.datatexts.settings.Currencies.goldCoins)
|
||||
|
||||
local displayed = E.global.datatexts.settings.Currencies.displayedCurrency
|
||||
if displayed == 'BACKPACK' then
|
||||
local displayString = ''
|
||||
for i = 1, 3 do
|
||||
local info = C_CurrencyInfo_GetBackpackCurrencyInfo(i)
|
||||
if info and info.quantity then
|
||||
displayString = (i > 1 and displayString..' ' or displayString)..format('%s %s', format(iconString, info.iconFileID), E:ShortValue(info.quantity))
|
||||
end
|
||||
end
|
||||
|
||||
self.text:SetText(displayString == '' and goldText or displayString)
|
||||
elseif displayed == 'GOLD' then
|
||||
self.text:SetText(goldText)
|
||||
else
|
||||
local id = tonumber(displayed)
|
||||
if not id then return end
|
||||
|
||||
local name, num, icon = GetInfo(id)
|
||||
if not name then return end
|
||||
|
||||
local style = E.global.datatexts.settings.Currencies.displayStyle
|
||||
if style == 'ICON' then
|
||||
self.text:SetFormattedText('%s %s', icon, E:ShortValue(num))
|
||||
elseif style == 'ICON_TEXT' then
|
||||
self.text:SetFormattedText('%s %s %s', icon, name, E:ShortValue(num))
|
||||
else --ICON_TEXT_ABBR
|
||||
self.text:SetFormattedText('%s %s %s', icon, E:AbbreviateString(name), E:ShortValue(num))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local addLine, goldSpace
|
||||
for _, info in ipairs(E.global.datatexts.settings.Currencies.tooltipData) do
|
||||
local name, id, _, enabled = unpack(info)
|
||||
if id and enabled then
|
||||
if type(id) == 'number' then
|
||||
AddInfo(id)
|
||||
end
|
||||
|
||||
goldSpace = true
|
||||
elseif enabled then
|
||||
if addLine then
|
||||
DT.tooltip:AddLine(' ')
|
||||
else
|
||||
addLine = true
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(name)
|
||||
goldSpace = true
|
||||
end
|
||||
end
|
||||
|
||||
if goldSpace then
|
||||
DT.tooltip:AddLine(' ')
|
||||
end
|
||||
|
||||
DT.tooltip:AddDoubleLine(L["Gold"]..':', goldText, nil, nil, nil, 1, 1, 1)
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('Currencies', nil, {'PLAYER_MONEY', 'SEND_MAIL_MONEY_CHANGED', 'SEND_MAIL_COD_CHANGED', 'PLAYER_TRADE_MONEY', 'TRADE_MONEY_CHANGED', 'CHAT_MSG_CURRENCY', 'CURRENCY_DISPLAY_UPDATE'}, OnEvent, nil, OnClick, OnEnter, nil, _G.CURRENCY)
|
||||
155
Modules/DataTexts/CustomCurrency.lua
Normal file
155
Modules/DataTexts/CustomCurrency.lua
Normal file
@@ -0,0 +1,155 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local ipairs, pairs, format = ipairs, pairs, format
|
||||
local tinsert, tremove, next = tinsert, tremove, next
|
||||
local C_CurrencyInfo_GetCurrencyInfo = C_CurrencyInfo.GetCurrencyInfo
|
||||
local C_CurrencyInfo_GetCurrencyListInfo = C_CurrencyInfo.GetCurrencyListInfo
|
||||
local C_CurrencyInfo_GetCurrencyListSize = C_CurrencyInfo.GetCurrencyListSize
|
||||
|
||||
local CustomCurrencies = {}
|
||||
local CurrencyListNameToIndex = {}
|
||||
|
||||
local function OnEvent(self)
|
||||
local currency = CustomCurrencies[self.name]
|
||||
if currency then
|
||||
local info = C_CurrencyInfo_GetCurrencyInfo(currency.ID)
|
||||
if not info then return end
|
||||
|
||||
if currency.DISPLAY_STYLE == 'ICON' then
|
||||
if currency.SHOW_MAX then
|
||||
self.text:SetFormattedText('%s %d / %d', currency.ICON, info.quantity, info.maxQuantity)
|
||||
else
|
||||
self.text:SetFormattedText('%s %d', currency.ICON, info.quantity)
|
||||
end
|
||||
elseif currency.DISPLAY_STYLE == 'ICON_TEXT' then
|
||||
if currency.SHOW_MAX then
|
||||
self.text:SetFormattedText('%s %s %d / %d', currency.ICON, currency.NAME, info.quantity, info.maxQuantity)
|
||||
else
|
||||
self.text:SetFormattedText('%s %s %d', currency.ICON, currency.NAME, info.quantity)
|
||||
end
|
||||
else --ICON_TEXT_ABBR
|
||||
if currency.SHOW_MAX then
|
||||
self.text:SetFormattedText('%s %s %d / %d', currency.ICON, E:AbbreviateString(currency.NAME), info.quantity, info.maxQuantity)
|
||||
else
|
||||
self.text:SetFormattedText('%s %s %d', currency.ICON, E:AbbreviateString(currency.NAME), info.quantity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEnter(self)
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local currency = CustomCurrencies[self.name]
|
||||
if not currency or not currency.USE_TOOLTIP then return end
|
||||
|
||||
local index = CurrencyListNameToIndex[self.name]
|
||||
if not index then return end
|
||||
DT.tooltip:SetCurrencyToken(index)
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function AddCurrencyNameToIndex(name)
|
||||
for index = 1, C_CurrencyInfo_GetCurrencyListSize() do
|
||||
local info = C_CurrencyInfo_GetCurrencyListInfo(index)
|
||||
if info.name == name then
|
||||
CurrencyListNameToIndex[name] = index
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function RegisterNewDT(currencyID)
|
||||
local info = C_CurrencyInfo_GetCurrencyInfo(currencyID)
|
||||
if info.discovered then
|
||||
local name = info.name
|
||||
|
||||
--Add to internal storage, stored with name as key
|
||||
CustomCurrencies[name] = {NAME = name, ID = currencyID, ICON = format('|T%s:16:16:0:0:64:64:4:60:4:60|t', info.iconFileID), DISPLAY_STYLE = 'ICON', USE_TOOLTIP = true, SHOW_MAX = false, DISPLAY_IN_MAIN_TOOLTIP = true}
|
||||
--Register datatext
|
||||
DT:RegisterDatatext(name, _G.CURRENCY, {'CHAT_MSG_CURRENCY', 'CURRENCY_DISPLAY_UPDATE'}, OnEvent, nil, nil, OnEnter, nil, name)
|
||||
--Save info to persistent storage, stored with ID as key
|
||||
E.global.datatexts.customCurrencies[currencyID] = CustomCurrencies[name]
|
||||
--Get the currency index for this currency, so we can use it for a tooltip
|
||||
AddCurrencyNameToIndex(name)
|
||||
|
||||
--Set the HyperDT
|
||||
local menuIndex = DT:GetMenuListCategory(_G.CURRENCY)
|
||||
local hyperList = DT.HyperList[menuIndex]
|
||||
if hyperList then
|
||||
local menuList = hyperList.menuList
|
||||
|
||||
tinsert(menuList, {
|
||||
text = name,
|
||||
checked = function() return DT.EasyMenu.MenuGetItem(DT.SelectedDatatext, name) end,
|
||||
func = function() DT.EasyMenu.MenuSetItem(DT.SelectedDatatext, name) end
|
||||
})
|
||||
|
||||
DT:SortMenuList(menuList)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:UpdateCustomCurrencySettings(currencyName, option, value)
|
||||
if not currencyName or not option then return end
|
||||
|
||||
if option == 'DISPLAY_STYLE' then
|
||||
CustomCurrencies[currencyName].DISPLAY_STYLE = value
|
||||
elseif option == 'USE_TOOLTIP' then
|
||||
CustomCurrencies[currencyName].USE_TOOLTIP = value
|
||||
elseif option == 'SHOW_MAX' then
|
||||
CustomCurrencies[currencyName].SHOW_MAX = value
|
||||
elseif option == 'DISPLAY_IN_MAIN_TOOLTIP' then
|
||||
CustomCurrencies[currencyName].DISPLAY_IN_MAIN_TOOLTIP = value
|
||||
end
|
||||
end
|
||||
|
||||
function DT:RegisterCustomCurrencyDT(currencyID)
|
||||
if currencyID then
|
||||
--We added a new datatext through the config
|
||||
if not next(CustomCurrencies) then -- add Currency category if one didn't already exist
|
||||
tinsert(DT.HyperList, { text = _G.CURRENCY, notCheckable = true, hasArrow = true, menuList = {} } )
|
||||
DT:SortMenuList(DT.HyperList)
|
||||
end
|
||||
|
||||
RegisterNewDT(currencyID)
|
||||
else
|
||||
--We called this in DT:Initialize, so load all the stored currency datatexts
|
||||
for _, info in pairs(E.global.datatexts.customCurrencies) do
|
||||
CustomCurrencies[info.NAME] = {NAME = info.NAME, ID = info.ID, ICON = info.ICON, DISPLAY_STYLE = info.DISPLAY_STYLE, USE_TOOLTIP = info.USE_TOOLTIP, SHOW_MAX = info.SHOW_MAX}
|
||||
DT:RegisterDatatext(info.NAME, _G.CURRENCY, {'CHAT_MSG_CURRENCY', 'CURRENCY_DISPLAY_UPDATE'}, OnEvent, nil, nil, OnEnter, nil, info.NAME)
|
||||
--Get the currency index for this currency, so we can use it for a tooltip
|
||||
AddCurrencyNameToIndex(info.NAME)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:RemoveCustomCurrency(currencyName)
|
||||
--Remove from internal storage
|
||||
CustomCurrencies[currencyName] = nil
|
||||
|
||||
if not next(CustomCurrencies) then
|
||||
for i, menu in ipairs(DT.HyperList) do
|
||||
if menu.text == _G.CURRENCY then
|
||||
tremove(DT.HyperList, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
local menuIndex = DT:GetMenuListCategory(_G.CURRENCY)
|
||||
local hyperList = DT.HyperList[menuIndex]
|
||||
if hyperList then
|
||||
local menuList = hyperList.menuList
|
||||
|
||||
for i, info in ipairs(menuList) do
|
||||
if info.text == currencyName then
|
||||
tremove(menuList, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT:SortMenuList(DT.HyperList)
|
||||
end
|
||||
82
Modules/DataTexts/DPS.lua
Normal file
82
Modules/DataTexts/DPS.lua
Normal file
@@ -0,0 +1,82 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local time, max, strjoin = time, max, strjoin
|
||||
local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
|
||||
local UnitGUID = UnitGUID
|
||||
|
||||
local lastSegment, petGUID = 0
|
||||
local timeStamp, combatTime, DMGTotal, lastDMGAmount = 0, 0, 0, 0
|
||||
local displayString, lastPanel = ''
|
||||
local events = {
|
||||
SWING_DAMAGE = true,
|
||||
RANGE_DAMAGE = true,
|
||||
SPELL_DAMAGE = true,
|
||||
SPELL_PERIODIC_DAMAGE = true,
|
||||
DAMAGE_SHIELD = true,
|
||||
DAMAGE_SPLIT = true,
|
||||
SPELL_EXTRA_ATTACKS = true
|
||||
}
|
||||
|
||||
local function Reset()
|
||||
timeStamp, combatTime, DMGTotal, lastDMGAmount = 0, 0, 0, 0
|
||||
end
|
||||
|
||||
local function GetDPS(self)
|
||||
local DPS
|
||||
if DMGTotal == 0 or combatTime == 0 then
|
||||
DPS = 0
|
||||
else
|
||||
DPS = DMGTotal / combatTime
|
||||
end
|
||||
self.text:SetFormattedText(displayString, L["DPS"], E:ShortValue(DPS))
|
||||
end
|
||||
|
||||
local function OnEvent(self, event)
|
||||
lastPanel = self
|
||||
|
||||
if event == 'UNIT_PET' then
|
||||
petGUID = UnitGUID('pet')
|
||||
elseif event == 'PLAYER_REGEN_DISABLED' or event == 'PLAYER_LEAVE_COMBAT' then
|
||||
local now = time()
|
||||
if now - lastSegment > 20 then --time since the last segment
|
||||
Reset()
|
||||
end
|
||||
lastSegment = now
|
||||
elseif event == 'COMBAT_LOG_EVENT_UNFILTERED' then
|
||||
local timestamp, Event, _, sourceGUID, _, _, _, _, _, _, _, arg12, _, _, arg15, arg16 = CombatLogGetCurrentEventInfo()
|
||||
if not events[Event] then return end
|
||||
|
||||
-- only use events from the player
|
||||
local overKill
|
||||
|
||||
if sourceGUID == E.myguid or sourceGUID == petGUID then
|
||||
if timeStamp == 0 then timeStamp = timestamp end
|
||||
lastSegment = timeStamp
|
||||
combatTime = timestamp - timeStamp
|
||||
if Event == 'SWING_DAMAGE' then
|
||||
lastDMGAmount = arg12
|
||||
else
|
||||
lastDMGAmount = arg15
|
||||
end
|
||||
if arg16 == nil then overKill = 0 else overKill = arg16 end
|
||||
DMGTotal = DMGTotal + max(0, lastDMGAmount - overKill)
|
||||
end
|
||||
end
|
||||
|
||||
GetDPS(self)
|
||||
end
|
||||
|
||||
local function OnClick(self)
|
||||
Reset()
|
||||
GetDPS(self)
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', '%s: ', hex, '%s')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('DPS', nil, {'UNIT_PET', 'COMBAT_LOG_EVENT_UNFILTERED', 'PLAYER_LEAVE_COMBAT', 'PLAYER_REGEN_DISABLED'}, OnEvent, nil, OnClick, nil, nil, _G.STAT_DPS_SHORT, nil, ValueColorUpdate)
|
||||
848
Modules/DataTexts/DataTexts.lua
Normal file
848
Modules/DataTexts/DataTexts.lua
Normal file
@@ -0,0 +1,848 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
local TT = E:GetModule('Tooltip')
|
||||
local LDB = E.Libs.LDB
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local tostring, format, type, pcall = tostring, format, type, pcall
|
||||
local tinsert, ipairs, pairs, wipe, sort = tinsert, ipairs, pairs, wipe, sort
|
||||
local next, strfind, strlen, strsplit = next, strfind, strlen, strsplit
|
||||
local CloseDropDownMenus = CloseDropDownMenus
|
||||
local CreateFrame = CreateFrame
|
||||
local EasyMenu = EasyMenu
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local IsInInstance = IsInInstance
|
||||
local MouseIsOver = MouseIsOver
|
||||
local RegisterStateDriver = RegisterStateDriver
|
||||
local UIDropDownMenu_SetAnchor = UIDropDownMenu_SetAnchor
|
||||
local UnregisterStateDriver = UnregisterStateDriver
|
||||
local C_CurrencyInfo_GetCurrencyInfo = C_CurrencyInfo.GetCurrencyInfo
|
||||
local C_CurrencyInfo_GetCurrencyListSize = C_CurrencyInfo.GetCurrencyListSize
|
||||
local C_CurrencyInfo_GetCurrencyListInfo = C_CurrencyInfo.GetCurrencyListInfo
|
||||
local C_CurrencyInfo_GetCurrencyListLink = C_CurrencyInfo.GetCurrencyListLink
|
||||
local C_CurrencyInfo_GetCurrencyIDFromLink = C_CurrencyInfo.GetCurrencyIDFromLink
|
||||
local C_CurrencyInfo_ExpandCurrencyList = C_CurrencyInfo.ExpandCurrencyList
|
||||
local GetNumSpecializations = GetNumSpecializations
|
||||
local GetSpecializationInfo = GetSpecializationInfo
|
||||
local MISCELLANEOUS = MISCELLANEOUS
|
||||
|
||||
local LFG_TYPE_DUNGEON = LFG_TYPE_DUNGEON
|
||||
local expansion = _G['EXPANSION_NAME'..GetExpansionLevel()]
|
||||
local ActivateHyperMode
|
||||
local HyperList = {}
|
||||
|
||||
DT.tooltip = CreateFrame('GameTooltip', 'DataTextTooltip', E.UIParent, 'GameTooltipTemplate')
|
||||
DT.EasyMenu = CreateFrame('Frame', 'DataTextEasyMenu', E.UIParent, 'UIDropDownMenuTemplate')
|
||||
|
||||
DT.SelectedDatatext = nil
|
||||
DT.HyperList = HyperList
|
||||
DT.RegisteredPanels = {}
|
||||
DT.RegisteredDataTexts = {}
|
||||
DT.LoadedInfo = {}
|
||||
DT.PanelPool = {
|
||||
InUse = {},
|
||||
Free = {},
|
||||
Count = 0
|
||||
}
|
||||
|
||||
DT.FontStrings = {}
|
||||
DT.AssignedDatatexts = {}
|
||||
DT.UnitEvents = {
|
||||
UNIT_AURA = true,
|
||||
UNIT_RESISTANCES = true,
|
||||
UNIT_STATS = true,
|
||||
UNIT_ATTACK_POWER = true,
|
||||
UNIT_RANGED_ATTACK_POWER = true,
|
||||
UNIT_TARGET = true,
|
||||
UNIT_SPELL_HASTE = true
|
||||
}
|
||||
|
||||
DT.SPECIALIZATION_CACHE = {}
|
||||
|
||||
function DT:SetEasyMenuAnchor(menu, dt)
|
||||
local point = E:GetScreenQuadrant(dt)
|
||||
local bottom = point and strfind(point, 'BOTTOM')
|
||||
local left = point and strfind(point, 'LEFT')
|
||||
|
||||
local anchor1 = (bottom and left and 'BOTTOMLEFT') or (bottom and 'BOTTOMRIGHT') or (left and 'TOPLEFT') or 'TOPRIGHT'
|
||||
local anchor2 = (bottom and left and 'TOPLEFT') or (bottom and 'TOPRIGHT') or (left and 'BOTTOMLEFT') or 'BOTTOMRIGHT'
|
||||
|
||||
UIDropDownMenu_SetAnchor(menu, 0, 0, anchor1, dt, anchor2)
|
||||
end
|
||||
|
||||
--> [HyperDT Credits] <--
|
||||
--> Original Work: NihilisticPandemonium
|
||||
--> Modified by Azilroka! :)
|
||||
|
||||
function DT:SingleHyperMode(_, key, active)
|
||||
if DT.SelectedDatatext and (key == 'LALT' or key == 'RALT') then
|
||||
if active == 1 and MouseIsOver(DT.SelectedDatatext) then
|
||||
DT:OnLeave()
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, DT.SelectedDatatext)
|
||||
EasyMenu(HyperList, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
elseif _G.DropDownList1:IsShown() and not _G.DropDownList1:IsMouseOver() then
|
||||
CloseDropDownMenus()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:HyperClick()
|
||||
DT.SelectedDatatext = self
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, DT.SelectedDatatext)
|
||||
EasyMenu(HyperList, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
end
|
||||
|
||||
function DT:EnableHyperMode(Panel)
|
||||
DT:OnLeave()
|
||||
|
||||
if Panel then
|
||||
for _, dt in pairs(Panel.dataPanels) do
|
||||
dt.overlay:Show()
|
||||
dt:SetScript('OnEnter', nil)
|
||||
dt:SetScript('OnLeave', nil)
|
||||
dt:SetScript('OnClick', DT.HyperClick)
|
||||
end
|
||||
else
|
||||
for _, panel in pairs(DT.RegisteredPanels) do
|
||||
for _, dt in pairs(panel.dataPanels) do
|
||||
dt.overlay:Show()
|
||||
dt:SetScript('OnEnter', nil)
|
||||
dt:SetScript('OnLeave', nil)
|
||||
dt:SetScript('OnClick', DT.HyperClick)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:OnEnter()
|
||||
if E.db.datatexts.noCombatHover and InCombatLockdown() then return end
|
||||
|
||||
if self.parent then
|
||||
DT.SelectedDatatext = self
|
||||
DT:SetupTooltip(self)
|
||||
end
|
||||
|
||||
if self.MouseEnters then
|
||||
for _, func in ipairs(self.MouseEnters) do
|
||||
func(self)
|
||||
end
|
||||
end
|
||||
|
||||
DT.MouseEnter(self)
|
||||
end
|
||||
|
||||
function DT:OnLeave()
|
||||
if self.MouseLeaves then
|
||||
for _, func in ipairs(self.MouseLeaves) do
|
||||
func(self)
|
||||
end
|
||||
end
|
||||
|
||||
DT.MouseLeave(self)
|
||||
DT.tooltip:Hide()
|
||||
end
|
||||
|
||||
function DT:MouseEnter()
|
||||
local frame = self.parent or self
|
||||
if frame.db and frame.db.mouseover then
|
||||
E:UIFrameFadeIn(frame, 0.2, frame:GetAlpha(), 1)
|
||||
end
|
||||
end
|
||||
|
||||
function DT:MouseLeave()
|
||||
local frame = self.parent or self
|
||||
if frame.db and frame.db.mouseover then
|
||||
E:UIFrameFadeOut(frame, 0.2, frame:GetAlpha(), 0)
|
||||
end
|
||||
end
|
||||
|
||||
function DT:FetchFrame(givenName)
|
||||
local panelExists = DT.PanelPool.InUse[givenName]
|
||||
if panelExists then return panelExists end
|
||||
|
||||
local count = DT.PanelPool.Count
|
||||
local name = 'ElvUI_DTPanel' .. count
|
||||
local frame
|
||||
|
||||
local poolName, poolFrame = next(DT.PanelPool.Free)
|
||||
if poolName then
|
||||
frame = poolFrame
|
||||
DT.PanelPool.Free[poolName] = nil
|
||||
else
|
||||
frame = CreateFrame('Frame', name, E.UIParent, 'BackdropTemplate')
|
||||
DT.PanelPool.Count = DT.PanelPool.Count + 1
|
||||
end
|
||||
|
||||
DT.PanelPool.InUse[givenName] = frame
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
function DT:EmptyPanel(panel)
|
||||
panel:Hide()
|
||||
|
||||
for _, dt in ipairs(panel.dataPanels) do
|
||||
dt:UnregisterAllEvents()
|
||||
dt:SetScript('OnUpdate', nil)
|
||||
dt:SetScript('OnEvent', nil)
|
||||
dt:SetScript('OnEnter', nil)
|
||||
dt:SetScript('OnLeave', nil)
|
||||
dt:SetScript('OnClick', nil)
|
||||
end
|
||||
|
||||
UnregisterStateDriver(panel, 'visibility')
|
||||
E:DisableMover(panel.moverName)
|
||||
end
|
||||
|
||||
function DT:ReleasePanel(givenName)
|
||||
local panel = DT.PanelPool.InUse[givenName]
|
||||
if panel then
|
||||
DT:EmptyPanel(panel)
|
||||
DT.PanelPool.Free[givenName] = panel
|
||||
DT.PanelPool.InUse[givenName] = nil
|
||||
DT.RegisteredPanels[givenName] = nil
|
||||
E.db.movers[panel.moverName] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function DT:BuildPanelFrame(name, db, fromInit)
|
||||
db = db or E.global.datatexts.customPanels[name] or DT:Panel_DefaultGlobalSettings(name)
|
||||
|
||||
local Panel = DT:FetchFrame(name)
|
||||
Panel:ClearAllPoints()
|
||||
Panel:SetPoint('CENTER')
|
||||
Panel:SetSize(db.width, db.height)
|
||||
|
||||
local MoverName = 'DTPanel'..name..'Mover'
|
||||
Panel.moverName = MoverName
|
||||
Panel.givenName = name
|
||||
|
||||
local holder = E:GetMoverHolder(MoverName)
|
||||
if holder then
|
||||
E:SetMoverPoints(MoverName, Panel)
|
||||
else
|
||||
E:CreateMover(Panel, MoverName, name, nil, nil, nil, nil, nil, 'datatexts,panels')
|
||||
end
|
||||
|
||||
DT:RegisterPanel(Panel, db.numPoints, db.tooltipAnchor, db.tooltipXOffset, db.tooltipYOffset, db.growth == 'VERTICAL')
|
||||
|
||||
if not fromInit then
|
||||
DT:UpdatePanelAttributes(name, db)
|
||||
end
|
||||
end
|
||||
|
||||
local LDBhex, LDBna = '|cffFFFFFF', {['N/A'] = true, ['n/a'] = true, ['N/a'] = true}
|
||||
function DT:BuildPanelFunctions(name, obj)
|
||||
local panel
|
||||
|
||||
local function OnEnter(dt)
|
||||
DT.tooltip:ClearLines()
|
||||
if obj.OnTooltipShow then obj.OnTooltipShow(DT.tooltip) end
|
||||
if obj.OnEnter then obj.OnEnter(dt) end
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnLeave(dt)
|
||||
if obj.OnLeave then obj.OnLeave(dt) end
|
||||
end
|
||||
|
||||
local function OnClick(dt, button)
|
||||
if obj.OnClick then
|
||||
obj.OnClick(dt, button)
|
||||
end
|
||||
end
|
||||
|
||||
local function UpdateText(_, Name, _, Value)
|
||||
if not Value or (strlen(Value) >= 3) or (Value == Name or LDBna[Value]) then
|
||||
panel.text:SetText((not LDBna[Value] and Value) or Name)
|
||||
else
|
||||
panel.text:SetFormattedText('%s: %s%s|r', Name, LDBhex, Value)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnCallback(Hex)
|
||||
if name and obj then
|
||||
LDBhex = Hex
|
||||
LDB.callbacks:Fire('LibDataBroker_AttributeChanged_'..name..'_text', name, nil, obj.text, obj)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEvent(dt)
|
||||
panel = dt
|
||||
LDB:RegisterCallback('LibDataBroker_AttributeChanged_'..name..'_text', UpdateText)
|
||||
LDB:RegisterCallback('LibDataBroker_AttributeChanged_'..name..'_value', UpdateText)
|
||||
OnCallback(LDBhex)
|
||||
end
|
||||
|
||||
return OnEnter, OnLeave, OnClick, OnCallback, OnEvent, UpdateText
|
||||
end
|
||||
|
||||
function DT:SetupObjectLDB(name, obj)
|
||||
local onEnter, onLeave, onClick, onCallback, onEvent = DT:BuildPanelFunctions(name, obj)
|
||||
local data = DT:RegisterDatatext(name, 'Data Broker', nil, onEvent, nil, onClick, onEnter, onLeave)
|
||||
E.valueColorUpdateFuncs[onCallback] = true
|
||||
data.isLibDataBroker = true
|
||||
|
||||
-- Update config if it has been loaded
|
||||
if DT.PanelLayoutOptions then
|
||||
DT:PanelLayoutOptions()
|
||||
end
|
||||
end
|
||||
|
||||
function DT:RegisterLDB()
|
||||
for name, obj in LDB:DataObjectIterator() do
|
||||
DT:SetupObjectLDB(name, obj)
|
||||
end
|
||||
end
|
||||
|
||||
function DT:GetDataPanelPoint(panel, i, numPoints, vertical)
|
||||
if numPoints == 1 then
|
||||
return 'CENTER', panel, 'CENTER'
|
||||
else
|
||||
local point, relativePoint, xOffset, yOffset = 'LEFT', i == 1 and 'LEFT' or 'RIGHT', 4, 0
|
||||
if vertical then
|
||||
point, relativePoint, xOffset, yOffset = 'TOP', i == 1 and 'TOP' or 'BOTTOM', 0, -4
|
||||
end
|
||||
|
||||
local lastPanel = (i == 1 and panel) or panel.dataPanels[i - 1]
|
||||
return point, lastPanel, relativePoint, xOffset, yOffset
|
||||
end
|
||||
end
|
||||
|
||||
function DT:SetupTooltip(panel)
|
||||
local parent = panel:GetParent()
|
||||
DT.tooltip:SetOwner(panel, parent.anchor, parent.xOff, parent.yOff)
|
||||
|
||||
if not _G.GameTooltip:IsForbidden() then
|
||||
_G.GameTooltip:Hide() -- WHY??? BECAUSE FUCK GAMETOOLTIP, THATS WHY!!
|
||||
end
|
||||
end
|
||||
|
||||
function DT:RegisterPanel(panel, numPoints, anchor, xOff, yOff, vertical)
|
||||
local realName = panel:GetName()
|
||||
local name = panel.givenName or realName
|
||||
|
||||
if not name then
|
||||
E:Print('DataTexts: Requires a panel name.')
|
||||
return
|
||||
end
|
||||
|
||||
DT.RegisteredPanels[name] = panel
|
||||
|
||||
panel:SetScript('OnEnter', DT.OnEnter)
|
||||
panel:SetScript('OnLeave', DT.OnLeave)
|
||||
panel:SetScript('OnSizeChanged', DT.PanelSizeChanged)
|
||||
|
||||
panel.dataPanels = panel.dataPanels or {}
|
||||
panel.numPoints = numPoints
|
||||
panel.xOff = xOff
|
||||
panel.yOff = yOff
|
||||
panel.anchor = anchor
|
||||
panel.vertical = vertical
|
||||
end
|
||||
|
||||
function DT:Panel_DefaultGlobalSettings(name)
|
||||
local db = E:CopyTable({}, G.datatexts.newPanelInfo)
|
||||
|
||||
E.global.datatexts.customPanels[name] = db
|
||||
|
||||
return db
|
||||
end
|
||||
|
||||
function DT:AssignPanelToDataText(dt, data, event, ...)
|
||||
dt.name = data.name or '' -- This is needed for Custom Currencies
|
||||
|
||||
if data.events then
|
||||
for _, ev in pairs(data.events) do
|
||||
if data.eventFunc then
|
||||
if data.objectEvent then
|
||||
if not dt.objectEventFunc then
|
||||
dt.objectEvent = data.objectEvent
|
||||
dt.objectEventFunc = function(_, ...)
|
||||
if data.eventFunc then
|
||||
data.eventFunc(dt, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
if not E:HasFunctionForObject(ev, data.objectEvent, dt.objectEventFunc) then
|
||||
E:RegisterEventForObject(ev, data.objectEvent, dt.objectEventFunc)
|
||||
end
|
||||
elseif DT.UnitEvents[ev] then
|
||||
pcall(dt.RegisterUnitEvent, dt, ev, 'player')
|
||||
else
|
||||
pcall(dt.RegisterEvent, dt, ev)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local ev = event or 'ELVUI_FORCE_UPDATE'
|
||||
if data.eventFunc then
|
||||
if not data.objectEvent then
|
||||
dt:SetScript('OnEvent', data.eventFunc)
|
||||
end
|
||||
|
||||
data.eventFunc(dt, ev, ...)
|
||||
end
|
||||
|
||||
if data.onUpdate then
|
||||
dt:SetScript('OnUpdate', data.onUpdate)
|
||||
data.onUpdate(dt, 20000)
|
||||
end
|
||||
|
||||
if data.onClick then
|
||||
dt:SetScript('OnClick', function(p, button)
|
||||
if E.db.datatexts.noCombatClick and InCombatLockdown() then return end
|
||||
data.onClick(p, button)
|
||||
DT.tooltip:Hide()
|
||||
end)
|
||||
end
|
||||
|
||||
if data.onEnter then
|
||||
tinsert(dt.MouseEnters, data.onEnter)
|
||||
end
|
||||
if data.onLeave then
|
||||
tinsert(dt.MouseLeaves, data.onLeave)
|
||||
end
|
||||
end
|
||||
|
||||
function DT:ForceUpdate_DataText(name)
|
||||
for dtSlot, dtName in pairs(DT.AssignedDatatexts) do
|
||||
if dtName.name == name then
|
||||
if dtName.colorUpdate then
|
||||
dtName.colorUpdate(E.media.hexvaluecolor)
|
||||
end
|
||||
if dtName.eventFunc then
|
||||
dtName.eventFunc(dtSlot, 'ELVUI_FORCE_UPDATE')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:GetTextAttributes(panel, db)
|
||||
local panelWidth, panelHeight = panel:GetSize()
|
||||
local numPoints = db and db.numPoints or panel.numPoints or 1
|
||||
local vertical = db and db.vertical or panel.vertical
|
||||
|
||||
local width, height = (panelWidth / numPoints) - 4, panelHeight - 4
|
||||
if vertical then width, height = panelWidth - 4, (panelHeight / numPoints) - 4 end
|
||||
|
||||
return width, height, vertical, numPoints
|
||||
end
|
||||
|
||||
function DT:UpdatePanelInfo(panelName, panel, ...)
|
||||
if not panel then panel = DT.RegisteredPanels[panelName] end
|
||||
local db = panel.db or P.datatexts.panels[panelName] and DT.db.panels[panelName]
|
||||
if not db then return end
|
||||
|
||||
local info = DT.LoadedInfo
|
||||
local font, fontSize, fontOutline = info.font, info.fontSize, info.fontOutline
|
||||
if db and db.fonts and db.fonts.enable then
|
||||
font, fontSize, fontOutline = LSM:Fetch('font', db.fonts.font), db.fonts.fontSize, db.fonts.fontOutline
|
||||
end
|
||||
|
||||
local chatPanel = panelName == 'LeftChatDataPanel' or panelName == 'RightChatDataPanel'
|
||||
local battlePanel = info.isInBattle and chatPanel and (not DT.ForceHideBGStats and E.db.datatexts.battleground)
|
||||
if battlePanel then
|
||||
DT:RegisterEvent('UPDATE_BATTLEFIELD_SCORE')
|
||||
DT.ShowingBattleStats = info.instanceType
|
||||
elseif chatPanel and DT.ShowingBattleStats then
|
||||
DT:UnregisterEvent('UPDATE_BATTLEFIELD_SCORE')
|
||||
DT.ShowingBattleStats = nil
|
||||
end
|
||||
|
||||
local width, height, vertical, numPoints = DT:GetTextAttributes(panel, db)
|
||||
|
||||
for i = 1, numPoints do
|
||||
local dt = panel.dataPanels[i]
|
||||
if not dt then
|
||||
dt = CreateFrame('Button', panelName..'_DataText'..i, panel)
|
||||
dt.MouseEnters = {}
|
||||
dt.MouseLeaves = {}
|
||||
dt:RegisterForClicks('AnyUp')
|
||||
|
||||
local text = dt:CreateFontString(nil, 'ARTWORK')
|
||||
text:SetAllPoints()
|
||||
text:SetJustifyV('MIDDLE')
|
||||
dt.text = text
|
||||
DT.FontStrings[text] = true
|
||||
|
||||
local overlay = dt:CreateTexture(nil, 'OVERLAY')
|
||||
overlay:SetTexture(E.media.blankTex)
|
||||
overlay:SetVertexColor(0.3, 0.9, 0.3, .3)
|
||||
overlay:SetAllPoints()
|
||||
dt.overlay = overlay
|
||||
|
||||
panel.dataPanels[i] = dt
|
||||
end
|
||||
end
|
||||
|
||||
--Note: some plugins dont have db.border, we need the nil checks
|
||||
panel.forcedBorderColors = (db.border == false and {0,0,0,0}) or nil
|
||||
panel:SetTemplate(db.backdrop and (db.panelTransparency and 'Transparent' or 'Default') or 'NoBackdrop', true)
|
||||
|
||||
--Show Border option
|
||||
if db.border ~= nil then
|
||||
if panel.iborder then panel.iborder:SetShown(db.border) end
|
||||
if panel.oborder then panel.oborder:SetShown(db.border) end
|
||||
end
|
||||
|
||||
--Restore Panels
|
||||
for i, dt in ipairs(panel.dataPanels) do
|
||||
dt:SetShown(i <= numPoints)
|
||||
dt:SetSize(width, height)
|
||||
dt:ClearAllPoints()
|
||||
dt:SetPoint(DT:GetDataPanelPoint(panel, i, numPoints, vertical))
|
||||
dt:UnregisterAllEvents()
|
||||
dt:EnableMouseWheel(false)
|
||||
dt:SetScript('OnUpdate', nil)
|
||||
dt:SetScript('OnEvent', nil)
|
||||
dt:SetScript('OnClick', nil)
|
||||
dt:SetScript('OnEnter', DT.OnEnter)
|
||||
dt:SetScript('OnLeave', DT.OnLeave)
|
||||
wipe(dt.MouseEnters)
|
||||
wipe(dt.MouseLeaves)
|
||||
|
||||
dt.overlay:Hide()
|
||||
dt.pointIndex = i
|
||||
dt.parent = panel
|
||||
dt.parentName = panelName
|
||||
dt.battleStats = battlePanel
|
||||
dt.db = db
|
||||
|
||||
E:StopFlash(dt)
|
||||
|
||||
if dt.objectEvent and dt.objectEventFunc then
|
||||
E:UnregisterAllEventsForObject(dt.objectEvent, dt.objectEventFunc)
|
||||
dt.objectEvent, dt.objectEventFunc = nil, nil
|
||||
end
|
||||
|
||||
dt.text:FontTemplate(font, fontSize, fontOutline)
|
||||
dt.text:SetJustifyH(db.textJustify or 'CENTER')
|
||||
dt.text:SetWordWrap(DT.db.wordWrap)
|
||||
dt.text:SetText()
|
||||
|
||||
if battlePanel then
|
||||
dt:SetScript('OnClick', DT.ToggleBattleStats)
|
||||
tinsert(dt.MouseEnters, DT.HoverBattleStats)
|
||||
else
|
||||
local assigned = DT.RegisteredDataTexts[ DT.db.panels[panelName][i] ]
|
||||
DT.AssignedDatatexts[dt] = assigned
|
||||
if assigned then DT:AssignPanelToDataText(dt, assigned, ...) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:LoadDataTexts(...)
|
||||
local data = DT.LoadedInfo
|
||||
data.font, data.fontSize, data.fontOutline = LSM:Fetch('font', DT.db.font), DT.db.fontSize, DT.db.fontOutline
|
||||
data.inInstance, data.instanceType = IsInInstance()
|
||||
data.isInBattle = data.inInstance and data.instanceType == 'pvp'
|
||||
|
||||
for panel, db in pairs(E.global.datatexts.customPanels) do
|
||||
DT:UpdatePanelAttributes(panel, db, true)
|
||||
end
|
||||
|
||||
for panelName, panel in pairs(DT.RegisteredPanels) do
|
||||
local db = DT.db.panels[panelName]
|
||||
if db and db.enable then
|
||||
DT:UpdatePanelInfo(panelName, panel, ...)
|
||||
end
|
||||
end
|
||||
|
||||
if DT.ShowingBattleStats then
|
||||
DT:UPDATE_BATTLEFIELD_SCORE()
|
||||
end
|
||||
end
|
||||
|
||||
function DT:PanelSizeChanged()
|
||||
if not self.dataPanels then return end
|
||||
local db = self.db or P.datatexts.panels[self.name] and DT.db.panels[self.name]
|
||||
local width, height, vertical, numPoints = DT:GetTextAttributes(self, db)
|
||||
|
||||
for i, dt in ipairs(self.dataPanels) do
|
||||
dt:SetSize(width, height)
|
||||
dt:ClearAllPoints()
|
||||
dt:SetPoint(DT:GetDataPanelPoint(self, i, numPoints, vertical))
|
||||
end
|
||||
end
|
||||
|
||||
function DT:UpdatePanelAttributes(name, db, fromLoad)
|
||||
local Panel = DT.PanelPool.InUse[name]
|
||||
DT.OnLeave(Panel)
|
||||
|
||||
Panel.db = db
|
||||
Panel.name = name
|
||||
Panel.numPoints = db.numPoints
|
||||
Panel.xOff = db.tooltipXOffset
|
||||
Panel.yOff = db.tooltipYOffset
|
||||
Panel.anchor = db.tooltipAnchor
|
||||
Panel.vertical = db.growth == 'VERTICAL'
|
||||
Panel:SetSize(db.width, db.height)
|
||||
Panel:SetFrameStrata(db.frameStrata)
|
||||
Panel:SetFrameLevel(db.frameLevel)
|
||||
|
||||
E:UIFrameFadeIn(Panel, 0.2, Panel:GetAlpha(), db.mouseover and 0 or 1)
|
||||
|
||||
if not DT.db.panels[name] or type(DT.db.panels[name]) ~= 'table' then
|
||||
DT.db.panels[name] = { enable = false }
|
||||
end
|
||||
|
||||
for i = 1, (E.global.datatexts.customPanels[name].numPoints or 1) do
|
||||
if not DT.db.panels[name][i] then
|
||||
DT.db.panels[name][i] = ''
|
||||
end
|
||||
end
|
||||
|
||||
if DT.db.panels[name].enable then
|
||||
E:EnableMover(Panel.moverName)
|
||||
RegisterStateDriver(Panel, 'visibility', db.visibility)
|
||||
|
||||
if not fromLoad then
|
||||
DT:UpdatePanelInfo(name, Panel)
|
||||
end
|
||||
else
|
||||
DT:EmptyPanel(Panel)
|
||||
end
|
||||
end
|
||||
|
||||
function DT:GetMenuListCategory(category)
|
||||
for i, info in ipairs(HyperList) do
|
||||
if info.text == category then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local function menuSort(a, b)
|
||||
if a.order and b.order then
|
||||
return a.order < b.order
|
||||
end
|
||||
|
||||
return a.text < b.text
|
||||
end
|
||||
|
||||
function DT:SortMenuList(list)
|
||||
for _, menu in pairs(list) do
|
||||
if menu.menuList then
|
||||
DT:SortMenuList(menu.menuList)
|
||||
end
|
||||
end
|
||||
|
||||
sort(list, menuSort)
|
||||
end
|
||||
end
|
||||
|
||||
function DT:HyperDT()
|
||||
if ActivateHyperMode then
|
||||
ActivateHyperMode = nil
|
||||
DT:LoadDataTexts()
|
||||
else
|
||||
ActivateHyperMode = true
|
||||
DT:EnableHyperMode()
|
||||
end
|
||||
end
|
||||
|
||||
function DT:RegisterHyperDT()
|
||||
for name, info in pairs(DT.RegisteredDataTexts) do
|
||||
local category = DT:GetMenuListCategory(info.category or MISCELLANEOUS)
|
||||
if not category then
|
||||
category = #HyperList + 1
|
||||
tinsert(HyperList, { order = 0, text = info.category or MISCELLANEOUS, notCheckable = true, hasArrow = true, menuList = {} } )
|
||||
end
|
||||
|
||||
tinsert(HyperList[category].menuList, {
|
||||
text = info.localizedName or name,
|
||||
checked = function() return DT.EasyMenu.MenuGetItem(DT.SelectedDatatext, name) end,
|
||||
func = function() DT.EasyMenu.MenuSetItem(DT.SelectedDatatext, name) end
|
||||
})
|
||||
end
|
||||
|
||||
tinsert(HyperList, {
|
||||
order = 100, text = L["NONE"],
|
||||
checked = function() return DT.EasyMenu.MenuGetItem(DT.SelectedDatatext, '') end,
|
||||
func = function() DT.EasyMenu.MenuSetItem(DT.SelectedDatatext, '') end
|
||||
})
|
||||
|
||||
DT:SortMenuList(HyperList)
|
||||
DT:RegisterEvent('MODIFIER_STATE_CHANGED', 'SingleHyperMode')
|
||||
end
|
||||
|
||||
function DT:PopulateData()
|
||||
local Collapsed = {}
|
||||
local listSize, i = C_CurrencyInfo_GetCurrencyListSize(), 1
|
||||
|
||||
local headerIndex
|
||||
while listSize >= i do
|
||||
local info = C_CurrencyInfo_GetCurrencyListInfo(i)
|
||||
if info.isHeader and not info.isHeaderExpanded then
|
||||
C_CurrencyInfo_ExpandCurrencyList(i, true)
|
||||
listSize = C_CurrencyInfo_GetCurrencyListSize()
|
||||
Collapsed[info.name] = true
|
||||
end
|
||||
if info.isHeader then
|
||||
G.datatexts.settings.Currencies.tooltipData[i] = { info.name, nil, nil, (info.name == expansion or info.name == MISCELLANEOUS) or strfind(info.name, LFG_TYPE_DUNGEON) }
|
||||
E.global.datatexts.settings.Currencies.tooltipData[i] = E.global.datatexts.settings.Currencies.tooltipData[i] or { info.name, nil, nil, G.datatexts.settings.Currencies.tooltipData[i][4] }
|
||||
E.global.datatexts.settings.Currencies.tooltipData[i][1] = info.name
|
||||
|
||||
headerIndex = i
|
||||
end
|
||||
if not info.isHeader then
|
||||
local currencyLink = C_CurrencyInfo_GetCurrencyListLink(i)
|
||||
local currencyID = currencyLink and C_CurrencyInfo_GetCurrencyIDFromLink(currencyLink)
|
||||
if currencyID then
|
||||
DT.CurrencyList[tostring(currencyID)] = info.name
|
||||
G.datatexts.settings.Currencies.tooltipData[i] = { info.name, currencyID, headerIndex, G.datatexts.settings.Currencies.tooltipData[headerIndex][4] }
|
||||
E.global.datatexts.settings.Currencies.tooltipData[i] = E.global.datatexts.settings.Currencies.tooltipData[i] or { info.name, currencyID, headerIndex, G.datatexts.settings.Currencies.tooltipData[headerIndex][4] }
|
||||
E.global.datatexts.settings.Currencies.tooltipData[i][1] = info.name
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
for k = 1, listSize do
|
||||
local info = C_CurrencyInfo_GetCurrencyListInfo(k)
|
||||
if not info then
|
||||
break
|
||||
elseif info.isHeader and info.isHeaderExpanded and Collapsed[info.name] then
|
||||
C_CurrencyInfo_ExpandCurrencyList(k, false)
|
||||
end
|
||||
end
|
||||
|
||||
wipe(Collapsed)
|
||||
|
||||
for index = 1, GetNumSpecializations() do
|
||||
local id, name, _, icon, _, statID = GetSpecializationInfo(index)
|
||||
|
||||
if id then
|
||||
DT.SPECIALIZATION_CACHE[index] = { id = id, name = name, icon = icon, statID = statID }
|
||||
DT.SPECIALIZATION_CACHE[id] = { name = name, icon = icon }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:CURRENCY_DISPLAY_UPDATE(_, currencyType)
|
||||
if currencyType and not DT.CurrencyList[tostring(currencyType)] then
|
||||
local info = C_CurrencyInfo_GetCurrencyInfo(currencyType)
|
||||
if info and info.name then
|
||||
DT.CurrencyList[tostring(currencyType)] = info.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DT:PLAYER_ENTERING_WORLD()
|
||||
DT:LoadDataTexts()
|
||||
end
|
||||
|
||||
function DT:Initialize()
|
||||
DT.Initialized = true
|
||||
DT.db = E.db.datatexts
|
||||
|
||||
DT.EasyMenu:SetClampedToScreen(true)
|
||||
DT.EasyMenu:EnableMouse(true)
|
||||
DT.EasyMenu.MenuSetItem = function(dt, value)
|
||||
DT.db.panels[dt.parentName][dt.pointIndex] = value
|
||||
DT:UpdatePanelInfo(dt.parentName, dt.parent)
|
||||
|
||||
if ActivateHyperMode then
|
||||
DT:EnableHyperMode(dt.parent)
|
||||
end
|
||||
|
||||
DT.SelectedDatatext = nil
|
||||
CloseDropDownMenus()
|
||||
end
|
||||
DT.EasyMenu.MenuGetItem = function(dt, value)
|
||||
return dt and (DT.db.panels[dt.parentName] and DT.db.panels[dt.parentName][dt.pointIndex] == value)
|
||||
end
|
||||
|
||||
if E.private.skins.blizzard.enable and E.private.skins.blizzard.tooltip then
|
||||
TT:SetStyle(DT.tooltip)
|
||||
end
|
||||
|
||||
-- Ignore header font size on DatatextTooltip
|
||||
local font = LSM:Fetch('font', E.db.tooltip.font)
|
||||
local fontOutline = E.db.tooltip.fontOutline
|
||||
local textSize = E.db.tooltip.textFontSize
|
||||
_G.DataTextTooltipTextLeft1:FontTemplate(font, textSize, fontOutline)
|
||||
_G.DataTextTooltipTextRight1:FontTemplate(font, textSize, fontOutline)
|
||||
|
||||
LDB.RegisterCallback(E, 'LibDataBroker_DataObjectCreated', DT.SetupObjectLDB)
|
||||
DT:RegisterLDB() -- LibDataBroker
|
||||
DT:RegisterCustomCurrencyDT() -- Register all the user created currency datatexts from the 'CustomCurrency' DT.
|
||||
|
||||
for name, db in pairs(E.global.datatexts.customPanels) do
|
||||
DT:BuildPanelFrame(name, db, true)
|
||||
end
|
||||
|
||||
do -- we need to register the panels to access them for the text
|
||||
DT.BattleStats.LEFT.panel = _G.LeftChatDataPanel.dataPanels
|
||||
DT.BattleStats.RIGHT.panel = _G.RightChatDataPanel.dataPanels
|
||||
end
|
||||
|
||||
DT:PopulateData()
|
||||
DT:RegisterHyperDT()
|
||||
DT:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
DT:RegisterEvent('CURRENCY_DISPLAY_UPDATE')
|
||||
end
|
||||
|
||||
--[[
|
||||
DT:RegisterDatatext(name, events, eventFunc, updateFunc, clickFunc, onEnterFunc, onLeaveFunc, localizedName)
|
||||
|
||||
name - name of the datatext (required)
|
||||
category - name of the category the datatext belongs to.
|
||||
events - must be a table with string values of event names to register
|
||||
eventFunc - function that gets fired when an event gets triggered
|
||||
updateFunc - onUpdate script target function
|
||||
click - function to fire when clicking the datatext
|
||||
onEnterFunc - function to fire OnEnter
|
||||
onLeaveFunc - function to fire OnLeave, if not provided one will be set for you that hides the tooltip.
|
||||
localizedName - localized name of the datetext
|
||||
objectEvent - register events on an object, using E.RegisterEventForObject instead of panel.RegisterEvent
|
||||
colorUpdate - function that fires when called from the config when you change the dt options.
|
||||
]]
|
||||
function DT:RegisterDatatext(name, category, events, eventFunc, updateFunc, clickFunc, onEnterFunc, onLeaveFunc, localizedName, objectEvent, colorUpdate)
|
||||
if not name then return end
|
||||
if type(category) ~= 'string' and category ~= nil then return E:Print(format('%s is an invalid DataText.', name)) end
|
||||
|
||||
local data = { name = name, category = category }
|
||||
|
||||
if type(events) == 'function' then
|
||||
return E:Print(format('%s is an invalid DataText. Events must be registered as a table or a string.', name))
|
||||
else
|
||||
data.events = type(events) == 'string' and { strsplit('[, ]', events) } or events
|
||||
data.eventFunc = eventFunc
|
||||
data.objectEvent = objectEvent
|
||||
end
|
||||
|
||||
if updateFunc and type(updateFunc) == 'function' then
|
||||
data.onUpdate = updateFunc
|
||||
end
|
||||
|
||||
if clickFunc and type(clickFunc) == 'function' then
|
||||
data.onClick = clickFunc
|
||||
end
|
||||
|
||||
if onEnterFunc and type(onEnterFunc) == 'function' then
|
||||
data.onEnter = onEnterFunc
|
||||
end
|
||||
|
||||
if onLeaveFunc and type(onLeaveFunc) == 'function' then
|
||||
data.onLeave = onLeaveFunc
|
||||
end
|
||||
|
||||
if localizedName and type(localizedName) == 'string' then
|
||||
data.localizedName = localizedName
|
||||
end
|
||||
|
||||
if colorUpdate and type(colorUpdate) == 'function' then
|
||||
data.colorUpdate = colorUpdate
|
||||
end
|
||||
|
||||
DT.RegisteredDataTexts[name] = data
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
E:RegisterModule(DT:GetName())
|
||||
30
Modules/DataTexts/Date.lua
Normal file
30
Modules/DataTexts/Date.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local date = date
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local FormatShortDate = FormatShortDate
|
||||
|
||||
local hexColor, lastPanel
|
||||
|
||||
local function OnClick()
|
||||
if InCombatLockdown() then _G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT) return end
|
||||
_G.GameTimeFrame:Click()
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local dateTable = date('*t')
|
||||
|
||||
self.text:SetText(FormatShortDate(dateTable.day, dateTable.month, dateTable.year):gsub('([/.])', hexColor..'%1|r'))
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
hexColor = hex
|
||||
|
||||
if lastPanel ~= nil then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Date', nil, {'UPDATE_INSTANCE_INFO'}, OnEvent, nil, OnClick, nil, nil, nil, nil, ValueColorUpdate)
|
||||
142
Modules/DataTexts/Difficulty.lua
Normal file
142
Modules/DataTexts/Difficulty.lua
Normal file
@@ -0,0 +1,142 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local pairs = pairs
|
||||
local format = format
|
||||
local GetDungeonDifficultyID, GetRaidDifficultyID, GetLegacyRaidDifficultyID = GetDungeonDifficultyID, GetRaidDifficultyID, GetLegacyRaidDifficultyID
|
||||
local SetDungeonDifficultyID, SetRaidDifficultyID, SetLegacyRaidDifficultyID = SetDungeonDifficultyID, SetRaidDifficultyID, SetLegacyRaidDifficultyID
|
||||
local GetInstanceInfo, GetDifficultyInfo, ResetInstances = GetInstanceInfo, GetDifficultyInfo, ResetInstances
|
||||
local C_ChallengeMode_GetActiveChallengeMapID = C_ChallengeMode.GetActiveChallengeMapID
|
||||
local C_ChallengeMode_GetActiveKeystoneInfo = C_ChallengeMode.GetActiveKeystoneInfo
|
||||
local C_ChallengeMode_IsChallengeModeActive = C_ChallengeMode.IsChallengeModeActive
|
||||
local C_MythicPlus_IsMythicPlusActive = C_MythicPlus.IsMythicPlusActive
|
||||
|
||||
local DungeonTexture, RaidTexture, LegacyTexture = CreateAtlasMarkup('Dungeon', 20, 20), CreateAtlasMarkup('Raid', 20, 20), CreateAtlasMarkup('worldquest-icon-raid', 20, 20)
|
||||
local DungeonDifficultyID, RaidDifficultyID, LegacyRaidDifficultyID = GetDungeonDifficultyID(), GetRaidDifficultyID(), GetLegacyRaidDifficultyID()
|
||||
|
||||
local RightClickMenu, DiffLabel = {
|
||||
{ text = _G.DUNGEON_DIFFICULTY, isTitle = true, notCheckable = true },
|
||||
{ text = _G.PLAYER_DIFFICULTY1, checked = function() return GetDungeonDifficultyID() == 1 end, func = function() SetDungeonDifficultyID(1) end },
|
||||
{ text = _G.PLAYER_DIFFICULTY2, checked = function() return GetDungeonDifficultyID() == 2 end, func = function() SetDungeonDifficultyID(2) end },
|
||||
{ text = _G.PLAYER_DIFFICULTY6, checked = function() return GetDungeonDifficultyID() == 23 end, func = function() SetDungeonDifficultyID(23) end },
|
||||
{ text = '', isTitle = true, notCheckable = true };
|
||||
{ text = _G.RAID_DIFFICULTY, isTitle = true, notCheckable = true},
|
||||
{ text = _G.PLAYER_DIFFICULTY1, checked = function() return GetRaidDifficultyID() == 14 end, func = function() SetRaidDifficultyID(14) end },
|
||||
{ text = _G.PLAYER_DIFFICULTY2, checked = function() return GetRaidDifficultyID() == 15 end, func = function() SetRaidDifficultyID(15) end },
|
||||
{ text = _G.PLAYER_DIFFICULTY6, checked = function() return GetRaidDifficultyID() == 16 end, func = function() SetRaidDifficultyID(16) end },
|
||||
{ text = '', isTitle = true, notCheckable = true };
|
||||
{ text = _G.UNIT_FRAME_DROPDOWN_SUBSECTION_TITLE_LEGACY_RAID, isTitle = true, notCheckable = true },
|
||||
{ text = _G.RAID_DIFFICULTY1, checked = function() return GetLegacyRaidDifficultyID() == 3 end, func = function() SetLegacyRaidDifficultyID(3) end },
|
||||
{ text = _G.RAID_DIFFICULTY1..' '.._G.PLAYER_DIFFICULTY2, checked = function() return GetLegacyRaidDifficultyID() == 5 end, func = function() SetLegacyRaidDifficultyID(5) end },
|
||||
{ text = _G.RAID_DIFFICULTY2, checked = function() return GetLegacyRaidDifficultyID() == 4 end, func = function() SetLegacyRaidDifficultyID(4) end },
|
||||
{ text = _G.RAID_DIFFICULTY2..' '.._G.PLAYER_DIFFICULTY2, checked = function() return GetLegacyRaidDifficultyID() == 6 end, func = function() SetLegacyRaidDifficultyID(6) end },
|
||||
{ text = '', isTitle = true, notCheckable = true };
|
||||
{ text = _G.RESET_INSTANCES, notCheckable = true, func = function() ResetInstances() end},
|
||||
}, {}
|
||||
|
||||
|
||||
for i = 1, 200 do
|
||||
if GetDifficultyInfo(i) then
|
||||
local Name = GetDifficultyInfo(i)
|
||||
if not DiffLabel[i] then DiffLabel[i] = Name end
|
||||
end
|
||||
end
|
||||
|
||||
local DiffIDLabel = {
|
||||
['N'] = { 1, 14, 38 },
|
||||
['H'] = { 2, 15, 39 },
|
||||
['M'] = { 16, 23, 40 },
|
||||
['10N'] = { 3 },
|
||||
['25N'] = { 4 },
|
||||
['10H'] = { 5 },
|
||||
['25H'] = { 6 },
|
||||
['LFR'] = { 7, 17 },
|
||||
['CM'] = { 8 },
|
||||
['40'] = { 9 },
|
||||
['TW'] = { 24, 33, 151 },
|
||||
['S'] = { 11, 12, 20, 152, 153 },
|
||||
['E'] = { 18, 19, 30 },
|
||||
['PvP'] = { 25, 29, 32, 34, 45 },
|
||||
['WF'] = { 147 },
|
||||
['WFH'] = { 149 },
|
||||
}
|
||||
|
||||
local IDTexture = {
|
||||
LEGACY = { 3, 4, 5, 6, 9 },
|
||||
RAID = { 14, 15, 16 },
|
||||
}
|
||||
|
||||
local Garrison = {
|
||||
[1152] = true,
|
||||
[1330] = true,
|
||||
[1153] = true,
|
||||
[1154] = true,
|
||||
[1158] = true,
|
||||
[1331] = true,
|
||||
[1159] = true,
|
||||
[1160] = true,
|
||||
}
|
||||
|
||||
local function GetDiffIDLabel(ID)
|
||||
for Name, Info in pairs(DiffIDLabel) do
|
||||
for _, Num in pairs(Info) do
|
||||
if Num == ID then
|
||||
return Name
|
||||
end
|
||||
end
|
||||
end
|
||||
return ID
|
||||
end
|
||||
|
||||
local function GetLabelTexture(ID)
|
||||
for Name, Info in pairs(IDTexture) do
|
||||
for _, Num in pairs(Info) do
|
||||
if Num == ID then
|
||||
return Name == 'LEGACY' and LegacyTexture or RaidTexture
|
||||
end
|
||||
end
|
||||
end
|
||||
return DungeonTexture
|
||||
end
|
||||
|
||||
local function OnClick(self)
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, self)
|
||||
_G.EasyMenu(RightClickMenu, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local name, instanceType, difficultyID, _, _, _, _, instanceID = GetInstanceInfo()
|
||||
local keyStoneLevel = C_MythicPlus_IsMythicPlusActive() and C_ChallengeMode_GetActiveChallengeMapID() and C_ChallengeMode_IsChallengeModeActive() and C_ChallengeMode_GetActiveKeystoneInfo()
|
||||
|
||||
if keyStoneLevel then
|
||||
self.text:SetFormattedText('%s %s +%s', GetLabelTexture(difficultyID), name, keyStoneLevel)
|
||||
elseif instanceType ~= 'none' and difficultyID and not Garrison[instanceID] then
|
||||
self.text:SetFormattedText('%s %s %s', GetLabelTexture(difficultyID), name, GetDiffIDLabel(difficultyID))
|
||||
else
|
||||
DungeonDifficultyID, RaidDifficultyID, LegacyRaidDifficultyID = GetDungeonDifficultyID(), GetRaidDifficultyID(), GetLegacyRaidDifficultyID()
|
||||
self.text:SetFormattedText('%s %s %s %s %s %s', DungeonTexture, GetDiffIDLabel(DungeonDifficultyID), RaidTexture, GetDiffIDLabel(RaidDifficultyID), LegacyTexture, GetDiffIDLabel(LegacyRaidDifficultyID))
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
if not (DungeonDifficultyID or RaidDifficultyID or LegacyRaidDifficultyID) then return end
|
||||
|
||||
DT.tooltip:ClearLines()
|
||||
DT.tooltip:SetText(L["Current Difficulties:"])
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
if DungeonDifficultyID then
|
||||
DT.tooltip:AddLine(format('%s %s', DungeonTexture, DiffLabel[DungeonDifficultyID]), 1, 1, 1)
|
||||
end
|
||||
if RaidDifficultyID then
|
||||
DT.tooltip:AddLine(format('%s %s', RaidTexture, DiffLabel[RaidDifficultyID]), 1, 1, 1)
|
||||
end
|
||||
if LegacyRaidDifficultyID then
|
||||
DT.tooltip:AddLine(format('%s %s', LegacyTexture, DiffLabel[LegacyRaidDifficultyID]), 1, 1, 1)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('Difficulty', nil, {'CHAT_MSG_SYSTEM', 'LOADING_SCREEN_DISABLED'}, OnEvent, nil, OnClick, OnEnter, nil, 'Difficulty')
|
||||
87
Modules/DataTexts/Durability.lua
Normal file
87
Modules/DataTexts/Durability.lua
Normal file
@@ -0,0 +1,87 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local select = select
|
||||
local wipe = wipe
|
||||
local format, pairs = format, pairs
|
||||
local GetInventoryItemDurability = GetInventoryItemDurability
|
||||
local ToggleCharacter = ToggleCharacter
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local GetInventoryItemTexture = GetInventoryItemTexture
|
||||
local GetInventoryItemLink = GetInventoryItemLink
|
||||
local GetMoneyString = GetMoneyString
|
||||
|
||||
local DURABILITY = DURABILITY
|
||||
local REPAIR_COST = REPAIR_COST
|
||||
local displayString = DURABILITY..': %s%d%%|r'
|
||||
local tooltipString = '%d%%'
|
||||
local totalDurability = 0
|
||||
local invDurability = {}
|
||||
local totalRepairCost
|
||||
|
||||
local slots = {
|
||||
[1] = _G.INVTYPE_HEAD,
|
||||
[3] = _G.INVTYPE_SHOULDER,
|
||||
[5] = _G.INVTYPE_CHEST,
|
||||
[6] = _G.INVTYPE_WAIST,
|
||||
[7] = _G.INVTYPE_LEGS,
|
||||
[8] = _G.INVTYPE_FEET,
|
||||
[9] = _G.INVTYPE_WRIST,
|
||||
[10] = _G.INVTYPE_HAND,
|
||||
[16] = _G.INVTYPE_WEAPONMAINHAND,
|
||||
[17] = _G.INVTYPE_WEAPONOFFHAND,
|
||||
}
|
||||
|
||||
local function OnEvent(self)
|
||||
totalDurability = 100
|
||||
totalRepairCost = 0
|
||||
|
||||
wipe(invDurability)
|
||||
|
||||
for index in pairs(slots) do
|
||||
local currentDura, maxDura = GetInventoryItemDurability(index)
|
||||
if currentDura and maxDura > 0 then
|
||||
local perc = (currentDura/maxDura)*100
|
||||
invDurability[index] = perc
|
||||
|
||||
if perc < totalDurability then
|
||||
totalDurability = perc
|
||||
end
|
||||
|
||||
totalRepairCost = totalRepairCost + select(3, E.ScanTooltip:SetInventoryItem('player', index))
|
||||
end
|
||||
end
|
||||
|
||||
local r, g, b = E:ColorGradient(totalDurability * .01, 1, .1, .1, 1, 1, .1, .1, 1, .1)
|
||||
local hex = E:RGBToHex(r, g, b)
|
||||
self.text:SetFormattedText(displayString, hex, totalDurability)
|
||||
|
||||
if totalDurability <= E.global.datatexts.settings.Durability.percThreshold then
|
||||
E:Flash(self, 0.53, true)
|
||||
else
|
||||
E:StopFlash(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function Click()
|
||||
if InCombatLockdown() then _G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT) return end
|
||||
ToggleCharacter('PaperDollFrame')
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
for slot, durability in pairs(invDurability) do
|
||||
DT.tooltip:AddDoubleLine(format('|T%s:14:14:0:0:64:64:4:60:4:60|t %s', GetInventoryItemTexture('player', slot), GetInventoryItemLink('player', slot)), format(tooltipString, durability), 1, 1, 1, E:ColorGradient(durability * 0.01, 1, .1, .1, 1, 1, .1, .1, 1, .1))
|
||||
end
|
||||
|
||||
if totalRepairCost > 0 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddDoubleLine(REPAIR_COST, GetMoneyString(totalRepairCost), .6, .8, 1, 1, 1, 1)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('Durability', nil, {'UPDATE_INVENTORY_DURABILITY', 'MERCHANT_SHOW'}, OnEvent, nil, Click, OnEnter, nil, DURABILITY)
|
||||
80
Modules/DataTexts/Experience.lua
Normal file
80
Modules/DataTexts/Experience.lua
Normal file
@@ -0,0 +1,80 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local format = format
|
||||
local UnitXP, UnitXPMax = UnitXP, UnitXPMax
|
||||
local IsXPUserDisabled, GetXPExhaustion = IsXPUserDisabled, GetXPExhaustion
|
||||
local IsPlayerAtEffectiveMaxLevel = IsPlayerAtEffectiveMaxLevel
|
||||
|
||||
local CurrentXP, XPToLevel, RestedXP, PercentRested
|
||||
local PercentXP, RemainXP, RemainTotal, RemainBars
|
||||
|
||||
local function OnEvent(self)
|
||||
local displayString = ''
|
||||
if IsXPUserDisabled() then
|
||||
displayString = L["Disabled"]
|
||||
elseif IsPlayerAtEffectiveMaxLevel() then
|
||||
displayString = L["Max Level"]
|
||||
else
|
||||
CurrentXP, XPToLevel, RestedXP = UnitXP('player'), UnitXPMax('player'), GetXPExhaustion()
|
||||
if XPToLevel <= 0 then XPToLevel = 1 end
|
||||
|
||||
local remainXP = XPToLevel - CurrentXP
|
||||
local remainPercent = remainXP / XPToLevel
|
||||
|
||||
-- values we also use in OnEnter
|
||||
RemainTotal, RemainBars = remainPercent * 100, remainPercent * 20
|
||||
PercentXP, RemainXP = (CurrentXP / XPToLevel) * 100, E:ShortValue(remainXP)
|
||||
|
||||
local textFormat = E.global.datatexts.settings.Experience.textFormat
|
||||
if textFormat == 'PERCENT' then
|
||||
displayString = format('%.2f%%', PercentXP)
|
||||
elseif textFormat == 'CURMAX' then
|
||||
displayString = format('%s - %s', E:ShortValue(CurrentXP), E:ShortValue(XPToLevel))
|
||||
elseif textFormat == 'CURPERC' then
|
||||
displayString = format('%s - %.2f%%', E:ShortValue(CurrentXP), PercentXP)
|
||||
elseif textFormat == 'CUR' then
|
||||
displayString = format('%s', E:ShortValue(CurrentXP))
|
||||
elseif textFormat == 'REM' then
|
||||
displayString = format('%s', RemainXP)
|
||||
elseif textFormat == 'CURREM' then
|
||||
displayString = format('%s - %s', E:ShortValue(CurrentXP), RemainXP)
|
||||
elseif textFormat == 'CURPERCREM' then
|
||||
displayString = format('%s - %.2f%% (%s)', E:ShortValue(CurrentXP), PercentXP, RemainXP)
|
||||
end
|
||||
|
||||
if RestedXP and RestedXP > 0 then
|
||||
PercentRested = (RestedXP / XPToLevel) * 100
|
||||
|
||||
if textFormat == 'PERCENT' then
|
||||
displayString = format('%s R:%.2f%%', displayString, PercentRested)
|
||||
elseif textFormat == 'CURPERC' then
|
||||
displayString = format('%s R:%s [%.2f%%]', displayString, E:ShortValue(RestedXP), PercentRested)
|
||||
elseif textFormat ~= 'NONE' then
|
||||
displayString = format('%s R:%s', displayString, E:ShortValue(RestedXP))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.text:SetText(displayString)
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
if IsXPUserDisabled() or IsPlayerAtEffectiveMaxLevel() then return end
|
||||
|
||||
DT.tooltip:ClearLines()
|
||||
DT.tooltip:AddLine(L["Experience"])
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
DT.tooltip:AddDoubleLine(L["XP:"], format(' %d / %d (%.2f%%)', CurrentXP, XPToLevel, PercentXP), 1, 1, 1)
|
||||
DT.tooltip:AddDoubleLine(L["Remaining:"], format(' %s (%.2f%% - %d '..L["Bars"]..')', RemainXP, RemainTotal, RemainBars), 1, 1, 1)
|
||||
|
||||
if RestedXP and RestedXP > 0 then
|
||||
DT.tooltip:AddDoubleLine(L["Rested:"], format('+%d (%.2f%%)', RestedXP, PercentRested), 1, 1, 1)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('Experience', nil, {'PLAYER_XP_UPDATE', 'DISABLE_XP_GAIN', 'ENABLE_XP_GAIN', 'UPDATE_EXHAUSTION'}, OnEvent, nil, nil, OnEnter, nil, _G.COMBAT_XP_GAIN)
|
||||
589
Modules/DataTexts/Friends.lua
Normal file
589
Modules/DataTexts/Friends.lua
Normal file
@@ -0,0 +1,589 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local type, ipairs, pairs, select = type, ipairs, pairs, select
|
||||
local sort, next, wipe, tremove, tinsert = sort, next, wipe, tremove, tinsert
|
||||
local format, gsub, strfind, strjoin, strmatch = format, gsub, strfind, strjoin, strmatch
|
||||
|
||||
local BNet_GetValidatedCharacterName = BNet_GetValidatedCharacterName
|
||||
local GetMouseFocus = GetMouseFocus
|
||||
local BNGetInfo = BNGetInfo
|
||||
local BNGetNumFriends = BNGetNumFriends
|
||||
local BNInviteFriend = BNInviteFriend
|
||||
local BNRequestInviteFriend = BNRequestInviteFriend
|
||||
local BNSetCustomMessage = BNSetCustomMessage
|
||||
local GetDisplayedInviteType = GetDisplayedInviteType
|
||||
local GetQuestDifficultyColor = GetQuestDifficultyColor
|
||||
local IsChatAFK = IsChatAFK
|
||||
local IsChatDND = IsChatDND
|
||||
local IsAltKeyDown = IsAltKeyDown
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local SendChatMessage = SendChatMessage
|
||||
local SetItemRef = SetItemRef
|
||||
local ToggleFriendsFrame = ToggleFriendsFrame
|
||||
local UnitInParty = UnitInParty
|
||||
local UnitInRaid = UnitInRaid
|
||||
local C_FriendList_GetNumFriends = C_FriendList.GetNumFriends
|
||||
local C_FriendList_GetNumOnlineFriends = C_FriendList.GetNumOnlineFriends
|
||||
local C_FriendList_GetFriendInfoByIndex = C_FriendList.GetFriendInfoByIndex
|
||||
local ChatFrame_SendBNetTell = ChatFrame_SendBNetTell
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local C_BattleNet_GetFriendAccountInfo = C_BattleNet.GetFriendAccountInfo
|
||||
local C_BattleNet_GetFriendNumGameAccounts = C_BattleNet.GetFriendNumGameAccounts
|
||||
local C_BattleNet_GetFriendGameAccountInfo = C_BattleNet.GetFriendGameAccountInfo
|
||||
local C_PartyInfo_RequestInviteFromUnit = C_PartyInfo.RequestInviteFromUnit
|
||||
local C_PartyInfo_InviteUnit = C_PartyInfo.InviteUnit
|
||||
local PRIEST_COLOR = RAID_CLASS_COLORS.PRIEST
|
||||
|
||||
-- create a popup
|
||||
E.PopupDialogs.SET_BN_BROADCAST = {
|
||||
text = _G.BN_BROADCAST_TOOLTIP,
|
||||
button1 = _G.ACCEPT,
|
||||
button2 = _G.CANCEL,
|
||||
hasEditBox = 1,
|
||||
editBoxWidth = 350,
|
||||
maxLetters = 127,
|
||||
OnAccept = function(self) BNSetCustomMessage(self.editBox:GetText()) end,
|
||||
OnShow = function(self) self.editBox:SetText(select(4, BNGetInfo()) ) self.editBox:SetFocus() end,
|
||||
OnHide = _G.ChatEdit_FocusActiveWindow,
|
||||
EditBoxOnEnterPressed = function(self) BNSetCustomMessage(self:GetText()) self:GetParent():Hide() end,
|
||||
EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
|
||||
timeout = 0,
|
||||
exclusive = 1,
|
||||
whileDead = 1,
|
||||
hideOnEscape = 1,
|
||||
preferredIndex = 3
|
||||
}
|
||||
|
||||
local menuList = {
|
||||
{ text = _G.OPTIONS_MENU, isTitle = true, notCheckable=true},
|
||||
{ text = _G.INVITE, hasArrow = true, notCheckable=true, },
|
||||
{ text = _G.CHAT_MSG_WHISPER_INFORM, hasArrow = true, notCheckable=true, },
|
||||
{ text = _G.PLAYER_STATUS, hasArrow = true, notCheckable=true,
|
||||
menuList = {
|
||||
{ text = '|cff2BC226'.._G.AVAILABLE..'|r', notCheckable=true, func = function() if IsChatAFK() then SendChatMessage('', 'AFK') elseif IsChatDND() then SendChatMessage('', 'DND') end end },
|
||||
{ text = '|cffE7E716'.._G.DND..'|r', notCheckable=true, func = function() if not IsChatDND() then SendChatMessage('', 'DND') end end },
|
||||
{ text = '|cffFF0000'.._G.AFK..'|r', notCheckable=true, func = function() if not IsChatAFK() then SendChatMessage('', 'AFK') end end },
|
||||
},
|
||||
},
|
||||
{ text = _G.BN_BROADCAST_TOOLTIP, notCheckable=true, func = function() E:StaticPopup_Show('SET_BN_BROADCAST') end },
|
||||
}
|
||||
|
||||
local function inviteClick(_, name, guid)
|
||||
DT.EasyMenu:Hide()
|
||||
|
||||
if not (name and name ~= '') then return end
|
||||
local isBNet = type(name) == 'number'
|
||||
|
||||
if guid then
|
||||
local inviteType = GetDisplayedInviteType(guid)
|
||||
if inviteType == 'INVITE' or inviteType == 'SUGGEST_INVITE' then
|
||||
if isBNet then
|
||||
BNInviteFriend(name)
|
||||
else
|
||||
C_PartyInfo_InviteUnit(name)
|
||||
end
|
||||
elseif inviteType == 'REQUEST_INVITE' then
|
||||
if isBNet then
|
||||
BNRequestInviteFriend(name)
|
||||
else
|
||||
C_PartyInfo_RequestInviteFromUnit(name)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- if for some reason guid isnt here fallback and just try to invite them
|
||||
-- this is unlikely but having a fallback doesnt hurt
|
||||
if isBNet then
|
||||
BNInviteFriend(name)
|
||||
else
|
||||
C_PartyInfo_InviteUnit(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function whisperClick(_, name, battleNet)
|
||||
DT.EasyMenu:Hide()
|
||||
|
||||
if battleNet then
|
||||
ChatFrame_SendBNetTell(name)
|
||||
else
|
||||
SetItemRef( 'player:'..name, format('|Hplayer:%1$s|h[%1$s]|h',name), 'LeftButton' )
|
||||
end
|
||||
end
|
||||
|
||||
local levelNameString = '|cff%02x%02x%02x%d|r |cff%02x%02x%02x%s|r'
|
||||
local levelNameClassString = '|cff%02x%02x%02x%d|r %s%s%s'
|
||||
local characterFriend = _G.CHARACTER_FRIEND
|
||||
local battleNetString = _G.BATTLENET_OPTIONS_LABEL
|
||||
local totalOnlineString = strjoin('', _G.FRIENDS_LIST_ONLINE, ': %s/%s')
|
||||
local tthead = {r=0.4, g=0.78, b=1}
|
||||
local activezone, inactivezone = {r=0.3, g=1.0, b=0.3}, {r=0.65, g=0.65, b=0.65}
|
||||
local displayString = ''
|
||||
local friendTable, BNTable, tableList = {}, {}, {}
|
||||
local friendOnline, friendOffline = gsub(_G.ERR_FRIEND_ONLINE_SS,'\124Hplayer:%%s\124h%[%%s%]\124h',''), gsub(_G.ERR_FRIEND_OFFLINE_S,'%%s','')
|
||||
local wowString = _G.BNET_CLIENT_WOW
|
||||
local retailID = _G.WOW_PROJECT_ID
|
||||
local WOW_CLASSIC = _G.BNET_FRIEND_TOOLTIP_WOW_CLASSIC
|
||||
local dataValid, lastPanel = false
|
||||
local statusTable = {
|
||||
AFK = ' |cffFFFFFF[|r|cffFF9900'..L["AFK"]..'|r|cffFFFFFF]|r',
|
||||
DND = ' |cffFFFFFF[|r|cffFF3333'..L["DND"]..'|r|cffFFFFFF]|r'
|
||||
}
|
||||
|
||||
-- Makro for get the client: /run for i,v in pairs(_G) do if type(i)=='string' and i:match('BNET_CLIENT_') then print(i,'=',v) end end
|
||||
local clientSorted = {}
|
||||
local clientTags = {
|
||||
[_G.BNET_CLIENT_WOW] = 'WoW',
|
||||
[_G.BNET_CLIENT_D3] = 'D3',
|
||||
[_G.BNET_CLIENT_WTCG] = 'HS',
|
||||
[_G.BNET_CLIENT_HEROES] = 'HotS',
|
||||
[_G.BNET_CLIENT_OVERWATCH] = 'OW',
|
||||
[_G.BNET_CLIENT_SC] = 'SC',
|
||||
[_G.BNET_CLIENT_SC2] = 'SC2',
|
||||
[_G.BNET_CLIENT_COD] = 'BO4',
|
||||
[_G.BNET_CLIENT_COD_MW] = 'MW',
|
||||
[_G.BNET_CLIENT_COD_MW2] = 'MW2',
|
||||
[_G.BNET_CLIENT_COD_BOCW] = 'CW',
|
||||
BSAp = L["Mobile"],
|
||||
}
|
||||
|
||||
local clientIndex = {
|
||||
[_G.BNET_CLIENT_WOW] = 1,
|
||||
[_G.BNET_CLIENT_D3] = 2,
|
||||
[_G.BNET_CLIENT_WTCG] = 3,
|
||||
[_G.BNET_CLIENT_HEROES] = 4,
|
||||
[_G.BNET_CLIENT_OVERWATCH] = 5,
|
||||
[_G.BNET_CLIENT_SC] = 6,
|
||||
[_G.BNET_CLIENT_SC2] = 7,
|
||||
[_G.BNET_CLIENT_COD] = 8,
|
||||
[_G.BNET_CLIENT_COD_MW] = 9,
|
||||
[_G.BNET_CLIENT_COD_MW2] = 10,
|
||||
[_G.BNET_CLIENT_COD_BOCW] = 11,
|
||||
App = 12,
|
||||
BSAp = 13,
|
||||
}
|
||||
|
||||
local function inGroup(name, realmName)
|
||||
if realmName and realmName ~= '' and realmName ~= E.myrealm then
|
||||
name = name..'-'..realmName
|
||||
end
|
||||
|
||||
return (UnitInParty(name) or UnitInRaid(name)) and '|cffaaaaaa*|r' or ''
|
||||
end
|
||||
|
||||
local function SortAlphabeticName(a, b)
|
||||
if a.name and b.name then
|
||||
return a.name < b.name
|
||||
end
|
||||
end
|
||||
|
||||
local function BuildFriendTable(total)
|
||||
wipe(friendTable)
|
||||
for i = 1, total do
|
||||
local info = C_FriendList_GetFriendInfoByIndex(i)
|
||||
if info and info.connected then
|
||||
local className = E:UnlocalizedClassName(info.className) or ''
|
||||
local status = (info.afk and statusTable.AFK) or (info.dnd and statusTable.DND) or ''
|
||||
friendTable[i] = {
|
||||
name = info.name, --1
|
||||
level = info.level, --2
|
||||
class = className, --3
|
||||
zone = info.area, --4
|
||||
online = info.connected, --5
|
||||
status = status, --6
|
||||
notes = info.notes, --7
|
||||
guid = info.guid --8
|
||||
}
|
||||
end
|
||||
end
|
||||
if next(friendTable) then
|
||||
sort(friendTable, SortAlphabeticName)
|
||||
end
|
||||
end
|
||||
|
||||
--Sort: client-> (WoW: project-> faction-> name) ELSE:btag
|
||||
local function Sort(a, b)
|
||||
if a.client and b.client then
|
||||
if (a.client == b.client) then
|
||||
if (a.client == wowString) and a.wowProjectID and b.wowProjectID then
|
||||
if (a.wowProjectID == b.wowProjectID) and a.faction and b.faction then
|
||||
if (a.faction == b.faction) and a.characterName and b.characterName then
|
||||
return a.characterName < b.characterName
|
||||
end
|
||||
return a.faction < b.faction
|
||||
end
|
||||
return a.wowProjectID < b.wowProjectID
|
||||
elseif (a.battleTag and b.battleTag) then
|
||||
return a.battleTag < b.battleTag
|
||||
end
|
||||
end
|
||||
return a.client < b.client
|
||||
end
|
||||
end
|
||||
|
||||
--Sort client by statically given index (this is a `pairs by keys` sorting method)
|
||||
local function clientSort(a, b)
|
||||
if a and b then
|
||||
if clientIndex[a] and clientIndex[b] then
|
||||
return clientIndex[a] < clientIndex[b]
|
||||
end
|
||||
return a < b
|
||||
end
|
||||
end
|
||||
|
||||
local function AddToBNTable(bnIndex, bnetIDAccount, accountName, battleTag, characterName, bnetIDGameAccount, client, isOnline, isBnetAFK, isBnetDND, noteText, wowProjectID, realmName, faction, race, className, zoneName, level, guid, gameText)
|
||||
className = E:UnlocalizedClassName(className) or ''
|
||||
characterName = BNet_GetValidatedCharacterName(characterName, battleTag, client) or ''
|
||||
|
||||
local obj = {
|
||||
accountID = bnetIDAccount, --1
|
||||
accountName = accountName, --2
|
||||
battleTag = battleTag, --3
|
||||
characterName = characterName, --4
|
||||
gameID = bnetIDGameAccount, --5
|
||||
client = client, --6
|
||||
isOnline = isOnline, --7
|
||||
isBnetAFK = isBnetAFK, --8
|
||||
isBnetDND = isBnetDND, --9
|
||||
noteText = noteText, --10
|
||||
wowProjectID = wowProjectID, --11
|
||||
realmName = realmName, --12
|
||||
faction = faction, --13
|
||||
race = race, --14
|
||||
className = className, --15
|
||||
zoneName = zoneName, --16
|
||||
level = level, --17
|
||||
guid = guid, --18
|
||||
gameText = gameText --19
|
||||
}
|
||||
|
||||
if strmatch(gameText, WOW_CLASSIC) then
|
||||
obj.classicText, obj.realmName = strmatch(gameText, '(.-)%s%-%s(.+)')
|
||||
end
|
||||
|
||||
BNTable[bnIndex] = obj
|
||||
|
||||
if tableList[client] then
|
||||
tableList[client][#tableList[client]+1] = BNTable[bnIndex]
|
||||
else
|
||||
tableList[client] = {}
|
||||
tableList[client][1] = BNTable[bnIndex]
|
||||
end
|
||||
end
|
||||
|
||||
local function PopulateBNTable(bnIndex, bnetIDAccount, accountName, battleTag, characterName, bnetIDGameAccount, client, isOnline, isBnetAFK, isBnetDND, noteText, wowProjectID, realmName, faction, race, class, zoneName, level, guid, gameText, hasFocus)
|
||||
-- `hasFocus` is not added to BNTable[i]; we only need this to keep our friends datatext in sync with the friends list
|
||||
for i = 1, bnIndex do
|
||||
local isAdded, bnInfo = 0, BNTable[i]
|
||||
if bnInfo and (bnInfo.accountID == bnetIDAccount) then
|
||||
if bnInfo.client == 'BSAp' then
|
||||
if client == 'BSAp' then -- unlikely to happen
|
||||
isAdded = 1
|
||||
elseif client == 'App' then
|
||||
isAdded = (hasFocus and 2) or 1
|
||||
else -- Mobile -> Game
|
||||
isAdded = 2 --swap data
|
||||
end
|
||||
elseif bnInfo.client == 'App' then
|
||||
if client == 'App' then -- unlikely to happen
|
||||
isAdded = 1
|
||||
elseif client == 'BSAp' then
|
||||
isAdded = (hasFocus and 2) or 1
|
||||
else -- App -> Game
|
||||
isAdded = 2 --swap data
|
||||
end
|
||||
elseif bnInfo.client then -- Game
|
||||
if client == 'BSAp' or client == 'App' then -- ignore Mobile and App
|
||||
isAdded = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if isAdded == 2 then -- swap data
|
||||
if bnInfo.client and tableList[bnInfo.client] then
|
||||
for n, y in ipairs(tableList[bnInfo.client]) do
|
||||
if y == bnInfo then
|
||||
tremove(tableList[bnInfo.client], n)
|
||||
break -- remove the old one from tableList
|
||||
end
|
||||
end
|
||||
end
|
||||
AddToBNTable(i, bnetIDAccount, accountName, battleTag, characterName, bnetIDGameAccount, client, isOnline, isBnetAFK, isBnetDND, noteText, wowProjectID, realmName, faction, race, class, zoneName, level, guid, gameText)
|
||||
end
|
||||
if isAdded ~= 0 then
|
||||
return bnIndex
|
||||
end
|
||||
end
|
||||
|
||||
bnIndex = bnIndex + 1 --bump the index one for a new addition
|
||||
AddToBNTable(bnIndex, bnetIDAccount, accountName, battleTag, characterName, bnetIDGameAccount, client, isOnline, isBnetAFK, isBnetDND, noteText, wowProjectID, realmName, faction, race, class, zoneName, level, guid, gameText)
|
||||
|
||||
return bnIndex
|
||||
end
|
||||
|
||||
local function BuildBNTable(total)
|
||||
for _, v in pairs(tableList) do wipe(v) end
|
||||
wipe(BNTable)
|
||||
wipe(clientSorted)
|
||||
|
||||
local bnIndex = 0
|
||||
|
||||
for i = 1, total do
|
||||
local accountInfo = C_BattleNet_GetFriendAccountInfo(i)
|
||||
if accountInfo and accountInfo.gameAccountInfo and accountInfo.gameAccountInfo.isOnline then
|
||||
local numGameAccounts = C_BattleNet_GetFriendNumGameAccounts(i)
|
||||
if numGameAccounts and numGameAccounts > 0 then
|
||||
for y = 1, numGameAccounts do
|
||||
local gameAccountInfo = C_BattleNet_GetFriendGameAccountInfo(i, y)
|
||||
bnIndex = PopulateBNTable(bnIndex, accountInfo.bnetAccountID, accountInfo.accountName, accountInfo.battleTag, gameAccountInfo.characterName, gameAccountInfo.gameAccountID, gameAccountInfo.clientProgram, gameAccountInfo.isOnline, accountInfo.isAFK or gameAccountInfo.isGameAFK, accountInfo.isDND or gameAccountInfo.isGameBusy, accountInfo.note, accountInfo.gameAccountInfo.wowProjectID, gameAccountInfo.realmName, gameAccountInfo.factionName, gameAccountInfo.raceName, gameAccountInfo.className, gameAccountInfo.areaName, gameAccountInfo.characterLevel, gameAccountInfo.playerGuid, gameAccountInfo.richPresence, gameAccountInfo.hasFocus)
|
||||
end
|
||||
else
|
||||
bnIndex = PopulateBNTable(bnIndex, accountInfo.bnetAccountID, accountInfo.accountName, accountInfo.battleTag, accountInfo.gameAccountInfo.characterName, accountInfo.gameAccountInfo.gameAccountID, accountInfo.gameAccountInfo.clientProgram, accountInfo.gameAccountInfo.isOnline, accountInfo.isAFK, accountInfo.isDND, accountInfo.note, accountInfo.gameAccountInfo.wowProjectID)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if next(BNTable) then
|
||||
sort(BNTable, Sort)
|
||||
end
|
||||
for c, v in pairs(tableList) do
|
||||
if next(v) then
|
||||
sort(v, Sort)
|
||||
end
|
||||
tinsert(clientSorted, c)
|
||||
end
|
||||
if next(clientSorted) then
|
||||
sort(clientSorted, clientSort)
|
||||
end
|
||||
end
|
||||
|
||||
local function Click(self, btn)
|
||||
if btn == 'RightButton' then
|
||||
local menuCountWhispers = 0
|
||||
local menuCountInvites = 0
|
||||
|
||||
menuList[2].menuList = {}
|
||||
menuList[3].menuList = {}
|
||||
|
||||
if not E.global.datatexts.settings.Friends.hideWoW then
|
||||
for _, info in ipairs(friendTable) do
|
||||
if info.online then
|
||||
local shouldSkip = false
|
||||
if (info.status == statusTable.AFK) and E.global.datatexts.settings.Friends.hideAFK then
|
||||
shouldSkip = true
|
||||
elseif (info.status == statusTable.DND) and E.global.datatexts.settings.Friends.hideDND then
|
||||
shouldSkip = true
|
||||
end
|
||||
if not shouldSkip then
|
||||
local classc, levelc = E:ClassColor(info.class), GetQuestDifficultyColor(info.level)
|
||||
if not classc then classc = levelc end
|
||||
|
||||
menuCountWhispers = menuCountWhispers + 1
|
||||
menuList[3].menuList[menuCountWhispers] = {text = format(levelNameString,levelc.r*255,levelc.g*255,levelc.b*255,info.level,classc.r*255,classc.g*255,classc.b*255,info.name), arg1 = info.name, notCheckable=true, func = whisperClick}
|
||||
|
||||
if inGroup(info.name) == '' then
|
||||
menuCountInvites = menuCountInvites + 1
|
||||
menuList[2].menuList[menuCountInvites] = {text = format(levelNameString,levelc.r*255,levelc.g*255,levelc.b*255,info.level,classc.r*255,classc.g*255,classc.b*255,info.name), arg1 = info.name, arg2 = info.guid, notCheckable=true, func = inviteClick}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, info in ipairs(BNTable) do
|
||||
if info.isOnline then
|
||||
local shouldSkip = false
|
||||
if (info.isBnetAFK == true) and E.global.datatexts.settings.Friends.hideAFK then
|
||||
shouldSkip = true
|
||||
elseif (info.isBnetDND == true) and E.global.datatexts.settings.Friends.hideDND then
|
||||
shouldSkip = true
|
||||
end
|
||||
if info.client and E.global.datatexts.settings.Friends['hide'..info.client] then
|
||||
shouldSkip = true
|
||||
end
|
||||
if not shouldSkip then
|
||||
local realID, hasBnet = info.accountName, false
|
||||
|
||||
for _, z in ipairs(menuList[3].menuList) do
|
||||
if z and z.text and (z.text == realID) then
|
||||
hasBnet = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not hasBnet then -- hasBnet will make sure only one is added to whispers but still allow us to add multiple into invites
|
||||
menuCountWhispers = menuCountWhispers + 1
|
||||
menuList[3].menuList[menuCountWhispers] = {text = realID, arg1 = realID, arg2 = true, notCheckable=true, func = whisperClick}
|
||||
end
|
||||
|
||||
if (info.client and info.client == wowString) and (E.myfaction == info.faction) and inGroup(info.characterName, info.realmName) == '' then
|
||||
local classc, levelc = E:ClassColor(info.className), GetQuestDifficultyColor(info.level)
|
||||
if not classc then classc = levelc end
|
||||
|
||||
if info.wowProjectID == retailID then
|
||||
menuCountInvites = menuCountInvites + 1
|
||||
menuList[2].menuList[menuCountInvites] = {text = format(levelNameString,levelc.r*255,levelc.g*255,levelc.b*255,info.level,classc.r*255,classc.g*255,classc.b*255,info.characterName), arg1 = info.gameID, arg2 = info.guid, notCheckable=true, func = inviteClick}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, self)
|
||||
_G.EasyMenu(menuList, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
elseif InCombatLockdown() then
|
||||
_G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT)
|
||||
else
|
||||
ToggleFriendsFrame(1)
|
||||
end
|
||||
end
|
||||
|
||||
local lastTooltipXLineHeader
|
||||
local function TooltipAddXLine(X, header, ...)
|
||||
X = (X == true and 'AddDoubleLine') or 'AddLine'
|
||||
if lastTooltipXLineHeader ~= header then
|
||||
DT.tooltip[X](DT.tooltip, ' ')
|
||||
DT.tooltip[X](DT.tooltip, header)
|
||||
lastTooltipXLineHeader = header
|
||||
end
|
||||
DT.tooltip[X](DT.tooltip, ...)
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
lastTooltipXLineHeader = nil
|
||||
|
||||
local onlineFriends = C_FriendList_GetNumOnlineFriends()
|
||||
local numberOfFriends = C_FriendList_GetNumFriends()
|
||||
local totalBNet, numBNetOnline = BNGetNumFriends()
|
||||
local totalonline = onlineFriends + numBNetOnline
|
||||
|
||||
-- no friends online, quick exit
|
||||
if totalonline == 0 then return end
|
||||
|
||||
if not dataValid then
|
||||
-- only retrieve information for all on-line members when we actually view the tooltip
|
||||
if numberOfFriends > 0 then BuildFriendTable(numberOfFriends) end
|
||||
if totalBNet > 0 then BuildBNTable(totalBNet) end
|
||||
dataValid = true
|
||||
end
|
||||
|
||||
local totalfriends = numberOfFriends + totalBNet
|
||||
local zonec, classc, levelc, realmc
|
||||
local shiftDown = IsShiftKeyDown()
|
||||
|
||||
DT.tooltip:AddDoubleLine(L["Friends List"], format(totalOnlineString, totalonline, totalfriends),tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
|
||||
if (onlineFriends > 0) and not E.global.datatexts.settings.Friends.hideWoW then
|
||||
for _, info in ipairs(friendTable) do
|
||||
if info.online then
|
||||
local shouldSkip = false
|
||||
if (info.status == statusTable.AFK) and E.global.datatexts.settings.Friends.hideAFK then
|
||||
shouldSkip = true
|
||||
elseif (info.status == statusTable.DND) and E.global.datatexts.settings.Friends.hideDND then
|
||||
shouldSkip = true
|
||||
end
|
||||
if not shouldSkip then
|
||||
if E.MapInfo.zoneText and (E.MapInfo.zoneText == info.zone) then zonec = activezone else zonec = inactivezone end
|
||||
classc, levelc = E:ClassColor(info.class), GetQuestDifficultyColor(info.level)
|
||||
if not classc then classc = levelc end
|
||||
|
||||
TooltipAddXLine(true, characterFriend, format(levelNameClassString,levelc.r*255,levelc.g*255,levelc.b*255,info.level,info.name,inGroup(info.name),info.status),info.zone,classc.r,classc.g,classc.b,zonec.r,zonec.g,zonec.b)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if numBNetOnline > 0 then
|
||||
local status
|
||||
for _, client in ipairs(clientSorted) do
|
||||
local Table = tableList[client]
|
||||
local shouldSkip = E.global.datatexts.settings.Friends['hide'..client]
|
||||
if not shouldSkip then
|
||||
for _, info in ipairs(Table) do
|
||||
if info.isOnline then
|
||||
shouldSkip = false
|
||||
if info.isBnetAFK == true then
|
||||
if E.global.datatexts.settings.Friends.hideAFK then
|
||||
shouldSkip = true
|
||||
end
|
||||
status = statusTable.AFK
|
||||
elseif info.isBnetDND == true then
|
||||
if E.global.datatexts.settings.Friends.hideDND then
|
||||
shouldSkip = true
|
||||
end
|
||||
status = statusTable.DND
|
||||
else
|
||||
status = ''
|
||||
end
|
||||
|
||||
if not shouldSkip then
|
||||
local header = format('%s (%s)', battleNetString, info.classicText or clientTags[client] or client)
|
||||
if info.client and info.client == wowString then
|
||||
classc = E:ClassColor(info.className)
|
||||
if info.level and info.level ~= '' then
|
||||
levelc = GetQuestDifficultyColor(info.level)
|
||||
else
|
||||
classc, levelc = PRIEST_COLOR, PRIEST_COLOR
|
||||
end
|
||||
|
||||
--Sometimes the friend list is fubar with level 0 unknown friends
|
||||
if not classc then classc = PRIEST_COLOR end
|
||||
|
||||
TooltipAddXLine(true, header, format(levelNameString..'%s%s',levelc.r*255,levelc.g*255,levelc.b*255,info.level,classc.r*255,classc.g*255,classc.b*255,info.characterName,inGroup(info.characterName, info.realmName),status),info.accountName,238,238,238,238,238,238)
|
||||
if shiftDown then
|
||||
if E.MapInfo.zoneText and (E.MapInfo.zoneText == info.zoneName) then zonec = activezone else zonec = inactivezone end
|
||||
if E.myrealm == info.realmName then realmc = activezone else realmc = inactivezone end
|
||||
TooltipAddXLine(true, header, info.zoneName, info.realmName, zonec.r, zonec.g, zonec.b, realmc.r, realmc.g, realmc.b)
|
||||
end
|
||||
else
|
||||
TooltipAddXLine(true, header, info.characterName..status, info.accountName, .9, .9, .9, .9, .9, .9)
|
||||
if shiftDown and (info.gameText and info.gameText ~= '') and (info.client and info.client ~= 'App' and info.client ~= 'BSAp') then
|
||||
TooltipAddXLine(false, header, info.gameText, inactivezone.r, inactivezone.g, inactivezone.b)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnEvent(self, event, message)
|
||||
local onlineFriends = C_FriendList_GetNumOnlineFriends()
|
||||
local _, numBNetOnline = BNGetNumFriends()
|
||||
|
||||
-- special handler to detect friend coming online or going offline
|
||||
-- when this is the case, we invalidate our buffered table and update the
|
||||
-- datatext information
|
||||
if event == 'CHAT_MSG_SYSTEM' then
|
||||
if not (strfind(message, friendOnline) or strfind(message, friendOffline)) then return end
|
||||
end
|
||||
-- force update when showing tooltip
|
||||
dataValid = false
|
||||
|
||||
if not IsAltKeyDown() and event == 'MODIFIER_STATE_CHANGED' and GetMouseFocus() == self then
|
||||
OnEnter(self)
|
||||
end
|
||||
|
||||
if E.global.datatexts.settings.Friends.NoLabel then
|
||||
self.text:SetFormattedText(displayString, onlineFriends + numBNetOnline)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Friends.Label ~= '' and E.global.datatexts.settings.Friends.Label or _G.FRIENDS..': ', onlineFriends + numBNetOnline)
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Friends.NoLabel and '' or '%s', hex, '%d|r')
|
||||
|
||||
if lastPanel then
|
||||
OnEvent(lastPanel, 'ELVUI_COLOR_UPDATE')
|
||||
end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Friends', _G.SOCIAL_LABEL, {'BN_FRIEND_ACCOUNT_ONLINE', 'BN_FRIEND_ACCOUNT_OFFLINE', 'BN_FRIEND_INFO_CHANGED', 'FRIENDLIST_UPDATE', 'CHAT_MSG_SYSTEM', 'MODIFIER_STATE_CHANGED'}, OnEvent, nil, Click, OnEnter, nil, _G.FRIENDS, nil, ValueColorUpdate)
|
||||
209
Modules/DataTexts/Gold.lua
Normal file
209
Modules/DataTexts/Gold.lua
Normal file
@@ -0,0 +1,209 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local type, wipe, pairs, ipairs, sort = type, wipe, pairs, ipairs, sort
|
||||
local format, strjoin, tinsert = format, strjoin, tinsert
|
||||
|
||||
local GetMoney = GetMoney
|
||||
local IsControlKeyDown = IsControlKeyDown
|
||||
local IsLoggedIn = IsLoggedIn
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local C_WowTokenPublic_UpdateMarketPrice = C_WowTokenPublic.UpdateMarketPrice
|
||||
local C_WowTokenPublic_GetCurrentMarketPrice = C_WowTokenPublic.GetCurrentMarketPrice
|
||||
local C_Timer_NewTicker = C_Timer.NewTicker
|
||||
local BreakUpLargeNumbers = BreakUpLargeNumbers
|
||||
-- GLOBALS: ElvDB
|
||||
|
||||
local Ticker
|
||||
local CURRENCY = CURRENCY
|
||||
local MAX_WATCHED_TOKENS = MAX_WATCHED_TOKENS
|
||||
local Profit, Spent = 0, 0
|
||||
local resetCountersFormatter = strjoin('', '|cffaaaaaa', L["Reset Session Data: Hold Ctrl + Right Click"], '|r')
|
||||
local resetInfoFormatter = strjoin('', '|cffaaaaaa', L["Reset Character Data: Hold Shift + Right Click"], '|r')
|
||||
local PRIEST_COLOR = RAID_CLASS_COLORS.PRIEST
|
||||
local C_CurrencyInfo_GetBackpackCurrencyInfo = C_CurrencyInfo.GetBackpackCurrencyInfo
|
||||
|
||||
local iconString = '|T%s:16:16:0:0:64:64:4:60:4:60|t'
|
||||
|
||||
local menuList = {}
|
||||
|
||||
local function sortFunction(a, b)
|
||||
return a.amount > b.amount
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
if not IsLoggedIn() then return end
|
||||
|
||||
if not Ticker then
|
||||
C_WowTokenPublic_UpdateMarketPrice()
|
||||
Ticker = C_Timer_NewTicker(60, C_WowTokenPublic_UpdateMarketPrice)
|
||||
end
|
||||
|
||||
ElvDB = ElvDB or {}
|
||||
|
||||
ElvDB.gold = ElvDB.gold or {}
|
||||
ElvDB.gold[E.myrealm] = ElvDB.gold[E.myrealm] or {}
|
||||
|
||||
ElvDB.class = ElvDB.class or {}
|
||||
ElvDB.class[E.myrealm] = ElvDB.class[E.myrealm] or {}
|
||||
ElvDB.class[E.myrealm][E.myname] = E.myclass
|
||||
|
||||
ElvDB.faction = ElvDB.faction or {}
|
||||
ElvDB.faction[E.myrealm] = ElvDB.faction[E.myrealm] or {}
|
||||
ElvDB.faction[E.myrealm][E.myname] = E.myfaction
|
||||
|
||||
ElvDB.serverID = ElvDB.serverID or {}
|
||||
ElvDB.serverID[E.serverID] = ElvDB.serverID[E.serverID] or {}
|
||||
ElvDB.serverID[E.serverID][E.myrealm] = true
|
||||
|
||||
--prevent an error possibly from really old profiles
|
||||
local oldMoney = ElvDB.gold[E.myrealm][E.myname]
|
||||
if oldMoney and type(oldMoney) ~= 'number' then
|
||||
ElvDB.gold[E.myrealm][E.myname] = nil
|
||||
oldMoney = nil
|
||||
end
|
||||
|
||||
local NewMoney = GetMoney()
|
||||
ElvDB.gold[E.myrealm][E.myname] = NewMoney
|
||||
|
||||
local OldMoney = oldMoney or NewMoney
|
||||
local Change = NewMoney-OldMoney -- Positive if we gain money
|
||||
if OldMoney>NewMoney then -- Lost Money
|
||||
Spent = Spent - Change
|
||||
else -- Gained Moeny
|
||||
Profit = Profit + Change
|
||||
end
|
||||
|
||||
self.text:SetText(E:FormatMoney(NewMoney, E.global.datatexts.settings.Gold.goldFormat or "BLIZZARD", not E.global.datatexts.settings.Gold.goldCoins))
|
||||
end
|
||||
|
||||
local function deleteCharacter(self, realm, name)
|
||||
ElvDB.gold[realm][name] = nil
|
||||
ElvDB.class[realm][name] = nil
|
||||
ElvDB.faction[realm][name] = nil
|
||||
|
||||
if name == E.myname and realm == E.myrealm then
|
||||
OnEvent(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function Click(self, btn)
|
||||
if btn == 'RightButton' then
|
||||
if IsShiftKeyDown() then
|
||||
wipe(menuList)
|
||||
tinsert(menuList, { text = 'Delete Character', isTitle = true, notCheckable = true })
|
||||
|
||||
for realm in pairs(ElvDB.serverID[E.serverID]) do
|
||||
for name in pairs(ElvDB.gold[realm]) do
|
||||
tinsert(menuList, {
|
||||
text = format('%s - %s', name, realm),
|
||||
notCheckable = true,
|
||||
func = function()
|
||||
deleteCharacter(self, realm, name)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, self)
|
||||
_G.EasyMenu(menuList, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
elseif IsControlKeyDown() then
|
||||
Profit = 0
|
||||
Spent = 0
|
||||
end
|
||||
else
|
||||
_G.ToggleAllBags()
|
||||
end
|
||||
end
|
||||
|
||||
local myGold = {}
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local textOnly = not E.global.datatexts.settings.Gold.goldCoins and true or false
|
||||
local style = E.global.datatexts.settings.Gold.goldFormat or 'BLIZZARD'
|
||||
|
||||
DT.tooltip:AddLine(L["Session:"])
|
||||
DT.tooltip:AddDoubleLine(L["Earned:"], E:FormatMoney(Profit, style, textOnly), 1, 1, 1, 1, 1, 1)
|
||||
DT.tooltip:AddDoubleLine(L["Spent:"], E:FormatMoney(Spent, style, textOnly), 1, 1, 1, 1, 1, 1)
|
||||
if Profit < Spent then
|
||||
DT.tooltip:AddDoubleLine(L["Deficit:"], E:FormatMoney(Profit-Spent, style, textOnly), 1, 0, 0, 1, 1, 1)
|
||||
elseif (Profit-Spent)>0 then
|
||||
DT.tooltip:AddDoubleLine(L["Profit:"], E:FormatMoney(Profit-Spent, style, textOnly), 0, 1, 0, 1, 1, 1)
|
||||
end
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
local totalGold, totalHorde, totalAlliance = 0, 0, 0
|
||||
DT.tooltip:AddLine(L["Character: "])
|
||||
|
||||
wipe(myGold)
|
||||
for realm in pairs(ElvDB.serverID[E.serverID]) do
|
||||
for k, _ in pairs(ElvDB.gold[realm]) do
|
||||
if ElvDB.gold[realm][k] then
|
||||
local color = E:ClassColor(ElvDB.class[realm][k]) or PRIEST_COLOR
|
||||
tinsert(myGold,
|
||||
{
|
||||
name = k,
|
||||
realm = realm,
|
||||
amount = ElvDB.gold[realm][k],
|
||||
amountText = E:FormatMoney(ElvDB.gold[realm][k], style, textOnly),
|
||||
faction = ElvDB.faction[realm][k] or '',
|
||||
r = color.r, g = color.g, b = color.b,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
if ElvDB.faction[realm][k] == 'Alliance' then
|
||||
totalAlliance = totalAlliance+ElvDB.gold[realm][k]
|
||||
elseif ElvDB.faction[realm][k] == 'Horde' then
|
||||
totalHorde = totalHorde+ElvDB.gold[realm][k]
|
||||
end
|
||||
|
||||
totalGold = totalGold+ElvDB.gold[realm][k]
|
||||
end
|
||||
end
|
||||
|
||||
sort(myGold, sortFunction)
|
||||
|
||||
for _, g in ipairs(myGold) do
|
||||
local nameLine = ''
|
||||
if g.faction ~= '' and g.faction ~= 'Neutral' then
|
||||
nameLine = format('|TInterface/FriendsFrame/PlusManz-%s:14|t ', g.faction)
|
||||
end
|
||||
|
||||
local toonName = format('%s%s%s', nameLine, g.name, (g.realm and g.realm ~= E.myrealm and ' - '..g.realm) or '')
|
||||
DT.tooltip:AddDoubleLine((g.name == E.myname and toonName..' |TInterface/COMMON/Indicator-Green:14|t') or toonName, g.amountText, g.r, g.g, g.b, 1, 1, 1)
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(L["Server: "])
|
||||
if totalAlliance > 0 and totalHorde > 0 then
|
||||
if totalAlliance ~= 0 then DT.tooltip:AddDoubleLine(L["Alliance: "], E:FormatMoney(totalAlliance, style, textOnly), 0, .376, 1, 1, 1, 1) end
|
||||
if totalHorde ~= 0 then DT.tooltip:AddDoubleLine(L["Horde: "], E:FormatMoney(totalHorde, style, textOnly), 1, .2, .2, 1, 1, 1) end
|
||||
DT.tooltip:AddLine(' ')
|
||||
end
|
||||
DT.tooltip:AddDoubleLine(L["Total: "], E:FormatMoney(totalGold, style, textOnly), 1, 1, 1, 1, 1, 1)
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddDoubleLine(L["WoW Token:"], E:FormatMoney(C_WowTokenPublic_GetCurrentMarketPrice() or 0, style, textOnly), 0, .8, 1, 1, 1, 1)
|
||||
|
||||
for i = 1, MAX_WATCHED_TOKENS do
|
||||
local info = C_CurrencyInfo_GetBackpackCurrencyInfo(i)
|
||||
if info then
|
||||
if i == 1 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(CURRENCY)
|
||||
end
|
||||
if info.quantity then
|
||||
DT.tooltip:AddDoubleLine(format('%s %s', format(iconString, info.iconFileID), info.name), BreakUpLargeNumbers(info.quantity), 1, 1, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(resetCountersFormatter)
|
||||
DT.tooltip:AddLine(resetInfoFormatter)
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('Gold', nil, {'PLAYER_MONEY', 'SEND_MAIL_MONEY_CHANGED', 'SEND_MAIL_COD_CHANGED', 'PLAYER_TRADE_MONEY', 'TRADE_MONEY_CHANGED'}, OnEvent, nil, Click, OnEnter, nil, L["Gold"])
|
||||
318
Modules/DataTexts/Guild.lua
Normal file
318
Modules/DataTexts/Guild.lua
Normal file
@@ -0,0 +1,318 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local ipairs, select, sort, unpack, wipe, ceil = ipairs, select, sort, unpack, wipe, ceil
|
||||
local format, strfind, strjoin, strsplit, strmatch = format, strfind, strjoin, strsplit, strmatch
|
||||
|
||||
local GetDisplayedInviteType = GetDisplayedInviteType
|
||||
local GetGuildFactionInfo = GetGuildFactionInfo
|
||||
local GetGuildInfo = GetGuildInfo
|
||||
local GetGuildRosterInfo = GetGuildRosterInfo
|
||||
local GetGuildRosterMOTD = GetGuildRosterMOTD
|
||||
local GetMouseFocus = GetMouseFocus
|
||||
local GetNumGuildApplicants = GetNumGuildApplicants
|
||||
local GetNumGuildMembers = GetNumGuildMembers
|
||||
local GetQuestDifficultyColor = GetQuestDifficultyColor
|
||||
local C_GuildInfo_GuildRoster = C_GuildInfo.GuildRoster
|
||||
local IsInGuild = IsInGuild
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local LoadAddOn = LoadAddOn
|
||||
local SetItemRef = SetItemRef
|
||||
local ToggleGuildFrame = ToggleGuildFrame
|
||||
local UnitInParty = UnitInParty
|
||||
local UnitInRaid = UnitInRaid
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local IsAltKeyDown = IsAltKeyDown
|
||||
|
||||
local C_PartyInfo_InviteUnit = C_PartyInfo.InviteUnit
|
||||
local C_PartyInfo_RequestInviteFromUnit = C_PartyInfo.RequestInviteFromUnit
|
||||
|
||||
local COMBAT_FACTION_CHANGE = COMBAT_FACTION_CHANGE
|
||||
local REMOTE_CHAT = REMOTE_CHAT
|
||||
local GUILD_MOTD = GUILD_MOTD
|
||||
local GUILD = GUILD
|
||||
|
||||
local tthead, ttsubh, ttoff = {r=0.4, g=0.78, b=1}, {r=0.75, g=0.9, b=1}, {r=.3,g=1,b=.3}
|
||||
local activezone, inactivezone = {r=0.3, g=1.0, b=0.3}, {r=0.65, g=0.65, b=0.65}
|
||||
local displayString = ''
|
||||
local noGuildString = ''
|
||||
local guildInfoString = '%s'
|
||||
local guildInfoString2 = GUILD..': %d/%d'
|
||||
local guildMotDString = '%s |cffaaaaaa- |cffffffff%s'
|
||||
local levelNameString = '|cff%02x%02x%02x%d|r |cff%02x%02x%02x%s|r'
|
||||
local levelNameStatusString = '|cff%02x%02x%02x%d|r %s%s %s'
|
||||
local nameRankString = '%s |cff999999-|cffffffff %s'
|
||||
local standingString = E:RGBToHex(ttsubh.r, ttsubh.g, ttsubh.b)..'%s:|r |cFFFFFFFF%s/%s (%s%%)'
|
||||
local moreMembersOnlineString = strjoin('', '+ %d ', _G.FRIENDS_LIST_ONLINE, '...')
|
||||
local noteString = strjoin('', '|cff999999 ', _G.LABEL_NOTE, ':|r %s')
|
||||
local officerNoteString = strjoin('', '|cff999999 ', _G.GUILD_RANK1_DESC, ':|r %s')
|
||||
local guildTable, guildMotD, lastPanel = {}, ''
|
||||
|
||||
local function sortByRank(a, b)
|
||||
if a and b then
|
||||
if a.rankIndex == b.rankIndex then
|
||||
return a.name < b.name
|
||||
end
|
||||
return a.rankIndex < b.rankIndex
|
||||
end
|
||||
end
|
||||
|
||||
local function sortByName(a, b)
|
||||
if a and b then
|
||||
return a.name < b.name
|
||||
end
|
||||
end
|
||||
|
||||
local function SortGuildTable(shift)
|
||||
if shift then
|
||||
sort(guildTable, sortByRank)
|
||||
else
|
||||
sort(guildTable, sortByName)
|
||||
end
|
||||
end
|
||||
|
||||
local onlinestatusstring = '|cffFFFFFF[|r|cffFF0000%s|r|cffFFFFFF]|r'
|
||||
local onlinestatus = {
|
||||
[0] = '',
|
||||
[1] = format(onlinestatusstring, L["AFK"]),
|
||||
[2] = format(onlinestatusstring, L["DND"]),
|
||||
}
|
||||
local mobilestatus = {
|
||||
[0] = [[|TInterface\ChatFrame\UI-ChatIcon-ArmoryChat:14:14:0:0:16:16:0:16:0:16:73:177:73|t]],
|
||||
[1] = [[|TInterface\ChatFrame\UI-ChatIcon-ArmoryChat-AwayMobile:14:14:0:0:16:16:0:16:0:16|t]],
|
||||
[2] = [[|TInterface\ChatFrame\UI-ChatIcon-ArmoryChat-BusyMobile:14:14:0:0:16:16:0:16:0:16|t]],
|
||||
}
|
||||
|
||||
local function inGroup(name)
|
||||
return (UnitInParty(name) or UnitInRaid(name)) and '|cffaaaaaa*|r' or ''
|
||||
end
|
||||
|
||||
local function BuildGuildTable()
|
||||
wipe(guildTable)
|
||||
|
||||
local totalMembers = GetNumGuildMembers()
|
||||
for i = 1, totalMembers do
|
||||
local name, rank, rankIndex, level, _, zone, note, officerNote, connected, memberstatus, className, _, _, isMobile, _, _, guid = GetGuildRosterInfo(i)
|
||||
if not name then return end
|
||||
|
||||
local statusInfo = isMobile and mobilestatus[memberstatus] or onlinestatus[memberstatus]
|
||||
zone = (isMobile and not connected) and REMOTE_CHAT or zone
|
||||
|
||||
if connected or isMobile then
|
||||
guildTable[#guildTable + 1] = {
|
||||
name = E:StripMyRealm(name), --1
|
||||
rank = rank, --2
|
||||
level = level, --3
|
||||
zone = zone, --4
|
||||
note = note, --5
|
||||
officerNote = officerNote, --6
|
||||
online = connected, --7
|
||||
status = statusInfo, --8
|
||||
class = className, --9
|
||||
rankIndex = rankIndex, --10
|
||||
isMobile = isMobile, --11
|
||||
guid = guid --12
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function UpdateGuildMessage()
|
||||
guildMotD = GetGuildRosterMOTD()
|
||||
end
|
||||
|
||||
local FRIEND_ONLINE = select(2, strsplit(' ', _G.ERR_FRIEND_ONLINE_SS, 2))
|
||||
local resendRequest = false
|
||||
local eventHandlers = {
|
||||
PLAYER_GUILD_UPDATE = C_GuildInfo_GuildRoster,
|
||||
CHAT_MSG_SYSTEM = function(_, arg1)
|
||||
if FRIEND_ONLINE ~= nil and arg1 and strfind(arg1, FRIEND_ONLINE) then
|
||||
resendRequest = true
|
||||
end
|
||||
end,
|
||||
-- when we enter the world and guildframe is not available then
|
||||
-- load guild frame, update guild message and guild xp
|
||||
PLAYER_ENTERING_WORLD = function()
|
||||
if not _G.GuildFrame and IsInGuild() then
|
||||
LoadAddOn('Blizzard_GuildUI')
|
||||
C_GuildInfo_GuildRoster()
|
||||
end
|
||||
end,
|
||||
-- Guild Roster updated, so rebuild the guild table
|
||||
GUILD_ROSTER_UPDATE = function(self)
|
||||
if resendRequest then
|
||||
resendRequest = false
|
||||
return C_GuildInfo_GuildRoster()
|
||||
else
|
||||
BuildGuildTable()
|
||||
UpdateGuildMessage()
|
||||
if GetMouseFocus() == self then
|
||||
self:GetScript('OnEnter')(self, nil, true)
|
||||
end
|
||||
end
|
||||
end,
|
||||
-- our guild message of the day changed
|
||||
GUILD_MOTD = function(_, arg1)
|
||||
guildMotD = arg1
|
||||
end
|
||||
}
|
||||
|
||||
local menuList = {
|
||||
{ text = _G.OPTIONS_MENU, isTitle = true, notCheckable=true},
|
||||
{ text = _G.INVITE, hasArrow = true, notCheckable=true,},
|
||||
{ text = _G.CHAT_MSG_WHISPER_INFORM, hasArrow = true, notCheckable=true,}
|
||||
}
|
||||
|
||||
local function inviteClick(_, name, guid)
|
||||
DT.EasyMenu:Hide()
|
||||
|
||||
if not (name and name ~= '') then return end
|
||||
|
||||
if guid then
|
||||
local inviteType = GetDisplayedInviteType(guid)
|
||||
if inviteType == 'INVITE' or inviteType == 'SUGGEST_INVITE' then
|
||||
C_PartyInfo_InviteUnit(name)
|
||||
elseif inviteType == 'REQUEST_INVITE' then
|
||||
C_PartyInfo_RequestInviteFromUnit(name)
|
||||
end
|
||||
else
|
||||
-- if for some reason guid isnt here fallback and just try to invite them
|
||||
-- this is unlikely but having a fallback doesnt hurt
|
||||
C_PartyInfo_InviteUnit(name)
|
||||
end
|
||||
end
|
||||
|
||||
local function whisperClick(_, playerName)
|
||||
DT.EasyMenu:Hide()
|
||||
SetItemRef( 'player:'..playerName, format('|Hplayer:%1$s|h[%1$s]|h',playerName), 'LeftButton' )
|
||||
end
|
||||
|
||||
local function Click(self, btn)
|
||||
if btn == 'RightButton' and IsInGuild() then
|
||||
local menuCountWhispers = 0
|
||||
local menuCountInvites = 0
|
||||
|
||||
menuList[2].menuList = {}
|
||||
menuList[3].menuList = {}
|
||||
|
||||
for _, info in ipairs(guildTable) do
|
||||
if (info.online or info.isMobile) and info.name ~= E.myname then
|
||||
local classc, levelc = E:ClassColor(info.class), GetQuestDifficultyColor(info.level)
|
||||
if not classc then classc = levelc end
|
||||
|
||||
local name = format(levelNameString, levelc.r*255,levelc.g*255,levelc.b*255, info.level, classc.r*255,classc.g*255,classc.b*255, info.name)
|
||||
if inGroup(info.name) ~= '' then
|
||||
name = name..' |cffaaaaaa*|r'
|
||||
elseif not (info.isMobile and info.zone == REMOTE_CHAT) then
|
||||
menuCountInvites = menuCountInvites + 1
|
||||
menuList[2].menuList[menuCountInvites] = {text = name, arg1 = info.name, arg2 = info.guid, notCheckable=true, func = inviteClick}
|
||||
end
|
||||
|
||||
menuCountWhispers = menuCountWhispers + 1
|
||||
menuList[3].menuList[menuCountWhispers] = {text = name, arg1 = info.name, notCheckable=true, func = whisperClick}
|
||||
end
|
||||
end
|
||||
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, self)
|
||||
_G.EasyMenu(menuList, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
elseif InCombatLockdown() then
|
||||
_G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT)
|
||||
else
|
||||
ToggleGuildFrame()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEnter(_, _, noUpdate)
|
||||
if not IsInGuild() then return end
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local shiftDown = IsShiftKeyDown()
|
||||
local total, _, online = GetNumGuildMembers()
|
||||
if #guildTable == 0 then BuildGuildTable() end
|
||||
|
||||
SortGuildTable(shiftDown)
|
||||
|
||||
local guildName, guildRank = GetGuildInfo('player')
|
||||
local applicants = GetNumGuildApplicants()
|
||||
|
||||
if guildName and guildRank then
|
||||
DT.tooltip:AddDoubleLine(format(guildInfoString, guildName), format(guildInfoString2..(applicants > 0 and ' |cFFFFFFFF(|cff33ff33%d|r|cFFFFFFFF)|r' or ''), online, total, applicants), tthead.r, tthead.g, tthead.b, tthead.r, tthead.g, tthead.b)
|
||||
DT.tooltip:AddLine(guildRank, unpack(tthead))
|
||||
end
|
||||
|
||||
if guildMotD ~= '' then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(format(guildMotDString, GUILD_MOTD, guildMotD), ttsubh.r, ttsubh.g, ttsubh.b, 1)
|
||||
end
|
||||
|
||||
local _, _, standingID, barMin, barMax, barValue = GetGuildFactionInfo()
|
||||
if standingID ~= 8 then -- Not Max Rep
|
||||
barMax = barMax - barMin
|
||||
barValue = barValue - barMin
|
||||
DT.tooltip:AddLine(format(standingString, COMBAT_FACTION_CHANGE, E:ShortValue(barValue), E:ShortValue(barMax), ceil((barValue / barMax) * 100)))
|
||||
end
|
||||
|
||||
local zonec
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
for i, info in ipairs(guildTable) do
|
||||
-- if more then 30 guild members are online, we don't Show any more, but inform user there are more
|
||||
if 30 - i < 1 then
|
||||
if online - 30 > 1 then DT.tooltip:AddLine(format(moreMembersOnlineString, online - 30), ttsubh.r, ttsubh.g, ttsubh.b) end
|
||||
break
|
||||
end
|
||||
|
||||
if E.MapInfo.zoneText and (E.MapInfo.zoneText == info.zone) then zonec = activezone else zonec = inactivezone end
|
||||
|
||||
local classc, levelc = E:ClassColor(info.class), GetQuestDifficultyColor(info.level)
|
||||
if not classc then classc = levelc end
|
||||
|
||||
if shiftDown then
|
||||
DT.tooltip:AddDoubleLine(format(nameRankString, info.name, info.rank), info.zone, classc.r, classc.g, classc.b, zonec.r, zonec.g, zonec.b)
|
||||
if info.note ~= '' then DT.tooltip:AddLine(format(noteString, info.note), ttsubh.r, ttsubh.g, ttsubh.b, 1) end
|
||||
if info.officerNote ~= '' then DT.tooltip:AddLine(format(officerNoteString, info.officerNote), ttoff.r, ttoff.g, ttoff.b, 1) end
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(format(levelNameStatusString, levelc.r*255, levelc.g*255, levelc.b*255, info.level, strmatch(info.name,'([^%-]+).*'), inGroup(info.name), info.status), info.zone, classc.r,classc.g,classc.b, zonec.r,zonec.g,zonec.b)
|
||||
end
|
||||
end
|
||||
|
||||
if not noUpdate then
|
||||
C_GuildInfo_GuildRoster()
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnEvent(self, event, ...)
|
||||
lastPanel = self
|
||||
|
||||
if IsInGuild() then
|
||||
local func = eventHandlers[event]
|
||||
if func then func(self, ...) end
|
||||
|
||||
if not IsAltKeyDown() and event == 'MODIFIER_STATE_CHANGED' and GetMouseFocus() == self then
|
||||
OnEnter(self)
|
||||
end
|
||||
|
||||
if E.global.datatexts.settings.Guild.NoLabel then
|
||||
self.text:SetFormattedText(displayString, #guildTable)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Guild.Label ~= '' and E.global.datatexts.settings.Guild.Label or GUILD..': ', #guildTable)
|
||||
end
|
||||
else
|
||||
self.text:SetText(noGuildString)
|
||||
end
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Guild.NoLabel and '' or '%s', hex, '%d|r')
|
||||
noGuildString = hex..L["No Guild"]
|
||||
|
||||
if lastPanel then
|
||||
OnEvent(lastPanel, 'ELVUI_COLOR_UPDATE')
|
||||
end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Guild', _G.SOCIAL_LABEL, {'CHAT_MSG_SYSTEM', 'GUILD_ROSTER_UPDATE', 'PLAYER_GUILD_UPDATE', 'GUILD_MOTD', 'MODIFIER_STATE_CHANGED'}, OnEvent, nil, Click, OnEnter, nil, GUILD, nil, ValueColorUpdate)
|
||||
65
Modules/DataTexts/HPS.lua
Normal file
65
Modules/DataTexts/HPS.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local time, max, strjoin = time, max, strjoin
|
||||
local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
|
||||
local UnitGUID = UnitGUID
|
||||
|
||||
local timeStamp, combatTime, healTotal = 0, 0, 0
|
||||
local lastSegment, petGUID = 0
|
||||
local displayString, lastPanel = ''
|
||||
local events = {SPELL_HEAL = true, SPELL_PERIODIC_HEAL = true}
|
||||
|
||||
local function Reset()
|
||||
timeStamp, combatTime, healTotal = 0, 0, 0
|
||||
end
|
||||
|
||||
local function GetHPS(self)
|
||||
local hps
|
||||
if healTotal == 0 or combatTime == 0 then
|
||||
hps = 0
|
||||
else
|
||||
hps = healTotal / combatTime
|
||||
end
|
||||
self.text:SetFormattedText(displayString, L["HPS"], E:ShortValue(hps))
|
||||
end
|
||||
|
||||
local function OnEvent(self, event)
|
||||
lastPanel = self
|
||||
|
||||
if event == 'UNIT_PET' then
|
||||
petGUID = UnitGUID('pet')
|
||||
elseif event == 'PLAYER_REGEN_DISABLED' or event == 'PLAYER_LEAVE_COMBAT' then
|
||||
local now = time()
|
||||
if now - lastSegment > 20 then
|
||||
Reset()
|
||||
end
|
||||
lastSegment = now
|
||||
elseif event == 'COMBAT_LOG_EVENT_UNFILTERED' then
|
||||
local timestamp, Event, _, sourceGUID, _, _, _, _, _, _, _, _, _, _, lastHealAmount, overHeal = CombatLogGetCurrentEventInfo()
|
||||
if not events[Event] then return end
|
||||
|
||||
if sourceGUID == E.myguid or sourceGUID == petGUID then
|
||||
if timeStamp == 0 then timeStamp = timestamp end
|
||||
lastSegment = timeStamp
|
||||
combatTime = timestamp - timeStamp
|
||||
healTotal = healTotal + max(0, lastHealAmount - overHeal)
|
||||
end
|
||||
end
|
||||
|
||||
GetHPS(self)
|
||||
end
|
||||
|
||||
local function OnClick(self)
|
||||
Reset()
|
||||
GetHPS(self)
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', '%s: ', hex, '%s')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('HPS', nil, {'UNIT_PET', 'COMBAT_LOG_EVENT_UNFILTERED', 'PLAYER_LEAVE_COMBAT', 'PLAYER_REGEN_DISABLED'}, OnEvent, nil, OnClick, nil, nil, L["HPS"], nil, ValueColorUpdate)
|
||||
65
Modules/DataTexts/Haste.lua
Normal file
65
Modules/DataTexts/Haste.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local format, strjoin = format, strjoin
|
||||
local GetHaste = GetHaste
|
||||
local GetCombatRating = GetCombatRating
|
||||
local GetCombatRatingBonus = GetCombatRatingBonus
|
||||
local BreakUpLargeNumbers = BreakUpLargeNumbers
|
||||
local GetPVPGearStatRules = GetPVPGearStatRules
|
||||
local STAT_HASTE = STAT_HASTE
|
||||
local CR_HASTE_MELEE = CR_HASTE_MELEE
|
||||
local HIGHLIGHT_FONT_COLOR_CODE = HIGHLIGHT_FONT_COLOR_CODE
|
||||
local FONT_COLOR_CODE_CLOSE = FONT_COLOR_CODE_CLOSE
|
||||
local PAPERDOLLFRAME_TOOLTIP_FORMAT = PAPERDOLLFRAME_TOOLTIP_FORMAT
|
||||
local STAT_HASTE_TOOLTIP = STAT_HASTE_TOOLTIP
|
||||
local STAT_HASTE_BASE_TOOLTIP = STAT_HASTE_BASE_TOOLTIP
|
||||
local RED_FONT_COLOR_CODE = RED_FONT_COLOR_CODE
|
||||
local STAT_CATEGORY_ENHANCEMENTS = STAT_CATEGORY_ENHANCEMENTS
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local rating = CR_HASTE_MELEE
|
||||
local classTooltip = _G['STAT_HASTE_'..E.myclass..'_TOOLTIP']
|
||||
local haste = GetHaste()
|
||||
|
||||
local hasteFormatString
|
||||
if haste < 0 and not GetPVPGearStatRules() then
|
||||
hasteFormatString = RED_FONT_COLOR_CODE..'%s'..FONT_COLOR_CODE_CLOSE
|
||||
else
|
||||
hasteFormatString = '%s'
|
||||
end
|
||||
|
||||
if not classTooltip then
|
||||
classTooltip = STAT_HASTE_TOOLTIP
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(HIGHLIGHT_FONT_COLOR_CODE..format(PAPERDOLLFRAME_TOOLTIP_FORMAT, STAT_HASTE)..' '..format(hasteFormatString, format('%.2F%%', haste))..FONT_COLOR_CODE_CLOSE)
|
||||
DT.tooltip:AddLine(classTooltip..format(STAT_HASTE_BASE_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(rating)), GetCombatRatingBonus(rating)))
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local haste = GetHaste()
|
||||
|
||||
if E.global.datatexts.settings.Haste.NoLabel then
|
||||
self.text:SetFormattedText(displayString, haste)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Haste.Label ~= '' and E.global.datatexts.settings.Haste.Label or STAT_HASTE..': ', haste)
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Haste.NoLabel and '' or '%s', hex, '%.'..E.global.datatexts.settings.Haste.decimalLength..'f%%|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Haste', STAT_CATEGORY_ENHANCEMENTS, {'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE', 'UNIT_SPELL_HASTE'}, OnEvent, nil, nil, OnEnter, nil, STAT_HASTE, nil, ValueColorUpdate)
|
||||
27
Modules/DataTexts/Intellect.lua
Normal file
27
Modules/DataTexts/Intellect.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local strjoin = strjoin
|
||||
local UnitStat = UnitStat
|
||||
local ITEM_MOD_INTELLECT_SHORT = ITEM_MOD_INTELLECT_SHORT
|
||||
local LE_UNIT_STAT_INTELLECT = LE_UNIT_STAT_INTELLECT
|
||||
local STAT_CATEGORY_ATTRIBUTES = STAT_CATEGORY_ATTRIBUTES
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEvent(self)
|
||||
self.text:SetFormattedText(displayString, ITEM_MOD_INTELLECT_SHORT, UnitStat('player', LE_UNIT_STAT_INTELLECT))
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', '%s: ', hex, '%.f|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Intellect', STAT_CATEGORY_ATTRIBUTES, { 'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE' }, OnEvent, nil, nil, nil, nil, ITEM_MOD_INTELLECT_SHORT, nil, ValueColorUpdate)
|
||||
|
||||
65
Modules/DataTexts/ItemLevel.lua
Normal file
65
Modules/DataTexts/ItemLevel.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local ipairs = ipairs
|
||||
local strjoin = strjoin
|
||||
local format = format
|
||||
local pi = math.pi
|
||||
|
||||
local ITEM_LEVEL_ABBR = ITEM_LEVEL_ABBR
|
||||
local LFG_LIST_ITEM_LEVEL_INSTR_PVP_SHORT = LFG_LIST_ITEM_LEVEL_INSTR_PVP_SHORT
|
||||
local STAT_AVERAGE_ITEM_LEVEL = STAT_AVERAGE_ITEM_LEVEL
|
||||
local GMSURVEYRATING3 = GMSURVEYRATING3
|
||||
local GetAverageItemLevel= GetAverageItemLevel
|
||||
local GetInventoryItemLink = GetInventoryItemLink
|
||||
local GetInventoryItemTexture = GetInventoryItemTexture
|
||||
|
||||
local iconString = '|T%s:13:15:0:0:50:50:4:46:4:46|t %s'
|
||||
local slotID = { 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }
|
||||
local title, lastPanel = ''
|
||||
|
||||
local function colorize(num)
|
||||
if num >= 0 then
|
||||
return .1, 1, .1
|
||||
else
|
||||
return E:ColorGradient(-(pi/num), 1, .1, .1, 1, 1, .1, .1, 1, .1)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local avg, avgEquipped = GetAverageItemLevel()
|
||||
local same = avg == avgEquipped
|
||||
self.text:SetFormattedText(title .. (same and '%0.2f|r' or '%0.2f / %0.2f|r'), ITEM_LEVEL_ABBR, avgEquipped, (not same and avg) or '0')
|
||||
end
|
||||
|
||||
local function OnEnter(self)
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local avg, avgEquipped, avgPvp = GetAverageItemLevel()
|
||||
DT.tooltip:AddDoubleLine(STAT_AVERAGE_ITEM_LEVEL, format('%0.2f', avg), 1, 1, 1, .1, 1, .1)
|
||||
DT.tooltip:AddDoubleLine(GMSURVEYRATING3, format('%0.2f', avgEquipped), 1, 1, 1, colorize(avgEquipped - avg))
|
||||
DT.tooltip:AddDoubleLine(LFG_LIST_ITEM_LEVEL_INSTR_PVP_SHORT, format('%0.2f', avgPvp), 1, 1, 1, colorize(avgPvp - avg))
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
for _, k in ipairs(slotID) do
|
||||
local info = E:GetGearSlotInfo('player', k)
|
||||
local ilvl = (info and info ~= 'tooSoon') and info.iLvl
|
||||
if ilvl then
|
||||
local link = GetInventoryItemLink('player', k)
|
||||
local icon = GetInventoryItemTexture('player', k)
|
||||
DT.tooltip:AddDoubleLine(format(iconString, icon, link), ilvl, 1, 1, 1, colorize(ilvl - avg))
|
||||
end
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
title = strjoin('', '%s: ', hex)
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Item Level', 'Stats', {'PLAYER_AVG_ITEM_LEVEL_UPDATE'}, OnEvent, nil, nil, OnEnter, nil, _G.LFG_LIST_ITEM_LEVEL_INSTR_SHORT, nil, ValueColorUpdate)
|
||||
44
Modules/DataTexts/Leech.lua
Normal file
44
Modules/DataTexts/Leech.lua
Normal file
@@ -0,0 +1,44 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local format, strjoin = format, strjoin
|
||||
|
||||
local BreakUpLargeNumbers = BreakUpLargeNumbers
|
||||
local GetCombatRating = GetCombatRating
|
||||
local GetCombatRatingBonus = GetCombatRatingBonus
|
||||
local GetLifesteal = GetLifesteal
|
||||
local CR_LIFESTEAL = CR_LIFESTEAL
|
||||
local CR_LIFESTEAL_TOOLTIP = CR_LIFESTEAL_TOOLTIP
|
||||
local FONT_COLOR_CODE_CLOSE = FONT_COLOR_CODE_CLOSE
|
||||
local HIGHLIGHT_FONT_COLOR_CODE = HIGHLIGHT_FONT_COLOR_CODE
|
||||
local PAPERDOLLFRAME_TOOLTIP_FORMAT = PAPERDOLLFRAME_TOOLTIP_FORMAT
|
||||
local STAT_CATEGORY_ENHANCEMENTS = STAT_CATEGORY_ENHANCEMENTS
|
||||
local STAT_LIFESTEAL = STAT_LIFESTEAL
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local text = HIGHLIGHT_FONT_COLOR_CODE..format(PAPERDOLLFRAME_TOOLTIP_FORMAT, STAT_LIFESTEAL)..' '..format('%.2F%%', GetLifesteal())..FONT_COLOR_CODE_CLOSE
|
||||
local tooltip = format(CR_LIFESTEAL_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(CR_LIFESTEAL)), GetCombatRatingBonus(CR_LIFESTEAL))
|
||||
|
||||
DT.tooltip:AddDoubleLine(text, nil, 1, 1, 1)
|
||||
DT.tooltip:AddLine(tooltip, nil, nil, nil, true)
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local lifesteal = GetLifesteal()
|
||||
self.text:SetFormattedText(displayString, STAT_LIFESTEAL, lifesteal)
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', '%s: ', hex, '%.2f%%|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Leech', STAT_CATEGORY_ENHANCEMENTS, {'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE', 'PLAYER_DAMAGE_DONE_MODS'}, OnEvent, nil, nil, OnEnter, nil, STAT_LIFESTEAL, nil, ValueColorUpdate)
|
||||
44
Modules/DataTexts/Load_DataTexts.xml
Normal file
44
Modules/DataTexts/Load_DataTexts.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='DataTexts.lua'/>
|
||||
|
||||
<Script file='Agility.lua'/>
|
||||
<Script file='Armor.lua'/>
|
||||
<Script file='Avoidance.lua'/>
|
||||
<Script file='Bags.lua'/>
|
||||
<Script file='BattleStats.lua'/>
|
||||
<Script file='CallToArms.lua'/>
|
||||
<Script file='CombatTime.lua'/>
|
||||
<Script file='ConfigElvUI.lua'/>
|
||||
<Script file='Coordinates.lua'/>
|
||||
<Script file='Crit.lua'/>
|
||||
<Script file='Currencies.lua'/>
|
||||
<Script file='CustomCurrency.lua'/>
|
||||
<Script file='Date.lua'/>
|
||||
<Script file='Difficulty.lua'/>
|
||||
<Script file='DPS.lua'/>
|
||||
<Script file='Durability.lua'/>
|
||||
<Script file='Experience.lua'/>
|
||||
<Script file='Friends.lua'/>
|
||||
<Script file='Gold.lua'/>
|
||||
<Script file='Guild.lua'/>
|
||||
<Script file='Haste.lua'/>
|
||||
<Script file='HPS.lua'/>
|
||||
<Script file='Intellect.lua'/>
|
||||
<Script file='ItemLevel.lua'/>
|
||||
<Script file='Leech.lua'/>
|
||||
<Script file='Mail.lua'/>
|
||||
<Script file='ManaRegen.lua'/>
|
||||
<Script file='Mastery.lua'/>
|
||||
<Script file='Missions.lua'/>
|
||||
<Script file='MovementSpeed.lua'/>
|
||||
<Script file='PrimaryStat.lua'/>
|
||||
<Script file='Quickjoin.lua'/>
|
||||
<Script file='Reputation.lua'/>
|
||||
<Script file='SpecSwitch.lua'/>
|
||||
<Script file='Speed.lua'/>
|
||||
<Script file='Stamina.lua'/>
|
||||
<Script file='Strength.lua'/>
|
||||
<Script file='System.lua'/>
|
||||
<Script file='Time.lua'/>
|
||||
<Script file='Versatility.lua'/>
|
||||
</Ui>
|
||||
42
Modules/DataTexts/Mail.lua
Normal file
42
Modules/DataTexts/Mail.lua
Normal file
@@ -0,0 +1,42 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local next = next
|
||||
local pairs = pairs
|
||||
local strjoin = strjoin
|
||||
local HasNewMail = HasNewMail
|
||||
local GetLatestThreeSenders = GetLatestThreeSenders
|
||||
local HAVE_MAIL_FROM = HAVE_MAIL_FROM
|
||||
local MAIL_LABEL = MAIL_LABEL
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEvent(self)
|
||||
lastPanel = self
|
||||
self.text:SetFormattedText(displayString, HasNewMail() and 'New Mail' or 'No Mail')
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local senders = { GetLatestThreeSenders() }
|
||||
if not next(senders) then return end
|
||||
|
||||
DT.tooltip:AddLine(HasNewMail() and HAVE_MAIL_FROM or MAIL_LABEL, 1, 1, 1)
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
for _, sender in pairs(senders) do
|
||||
DT.tooltip:AddLine(sender)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin(hex, '%s|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Mail', nil, {'MAIL_INBOX_UPDATE', 'UPDATE_PENDING_MAIL', 'MAIL_CLOSED', 'MAIL_SHOW'}, OnEvent, nil, nil, OnEnter, nil, MAIL_LABEL, nil, ValueColorUpdate)
|
||||
30
Modules/DataTexts/ManaRegen.lua
Normal file
30
Modules/DataTexts/ManaRegen.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local strjoin = strjoin
|
||||
local GetManaRegen = GetManaRegen
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local STAT_CATEGORY_ATTRIBUTES = STAT_CATEGORY_ATTRIBUTES
|
||||
local MANA_REGEN = MANA_REGEN
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEvent(self)
|
||||
local baseMR, castingMR = GetManaRegen()
|
||||
if InCombatLockdown() then
|
||||
self.text:SetFormattedText(displayString, MANA_REGEN, castingMR*5)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, MANA_REGEN, baseMR*5)
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', '%s: ', hex, '%.2f|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Mana Regen', STAT_CATEGORY_ATTRIBUTES, {'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE'}, OnEvent, nil, nil, nil, nil, MANA_REGEN, nil, ValueColorUpdate)
|
||||
49
Modules/DataTexts/Mastery.lua
Normal file
49
Modules/DataTexts/Mastery.lua
Normal file
@@ -0,0 +1,49 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local strjoin = strjoin
|
||||
local GetMasteryEffect = GetMasteryEffect
|
||||
local GetSpecialization = GetSpecialization
|
||||
local GetSpecializationMasterySpells = GetSpecializationMasterySpells
|
||||
local STAT_CATEGORY_ENHANCEMENTS = STAT_CATEGORY_ENHANCEMENTS
|
||||
local STAT_MASTERY = STAT_MASTERY
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local primaryTalentTree = GetSpecialization()
|
||||
if primaryTalentTree then
|
||||
local masterySpell, masterySpell2 = GetSpecializationMasterySpells(primaryTalentTree)
|
||||
if masterySpell then
|
||||
DT.tooltip:AddSpellByID(masterySpell)
|
||||
end
|
||||
if masterySpell2 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddSpellByID(masterySpell2)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
lastPanel = self
|
||||
|
||||
local masteryRating = GetMasteryEffect()
|
||||
if E.global.datatexts.settings.Mastery.NoLabel then
|
||||
self.text:SetFormattedText(displayString, masteryRating)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Mastery.Label ~= '' and E.global.datatexts.settings.Mastery.Label or STAT_MASTERY..': ', masteryRating)
|
||||
end
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Mastery.NoLabel and '' or '%s', hex, '%.'..E.global.datatexts.settings.Mastery.decimalLength..'f%%|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Mastery', STAT_CATEGORY_ENHANCEMENTS, {'MASTERY_UPDATE'}, OnEvent, nil, nil, OnEnter, nil, STAT_MASTERY, nil, ValueColorUpdate)
|
||||
357
Modules/DataTexts/Missions.lua
Normal file
357
Modules/DataTexts/Missions.lua
Normal file
@@ -0,0 +1,357 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local next, wipe, ipairs = next, wipe, ipairs
|
||||
local format, sort, select = format, sort, select
|
||||
local GetMouseFocus = GetMouseFocus
|
||||
local HideUIPanel = HideUIPanel
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local BreakUpLargeNumbers = BreakUpLargeNumbers
|
||||
local ShowGarrisonLandingPage = ShowGarrisonLandingPage
|
||||
local C_Garrison_HasGarrison = C_Garrison.HasGarrison
|
||||
local C_Garrison_GetBuildings = C_Garrison.GetBuildings
|
||||
local C_Garrison_GetInProgressMissions = C_Garrison.GetInProgressMissions
|
||||
local C_Garrison_GetLandingPageShipmentInfo = C_Garrison.GetLandingPageShipmentInfo
|
||||
local C_Garrison_GetCompleteTalent = C_Garrison.GetCompleteTalent
|
||||
local C_Garrison_GetFollowerShipments = C_Garrison.GetFollowerShipments
|
||||
local C_Garrison_GetLandingPageShipmentInfoByContainerID = C_Garrison.GetLandingPageShipmentInfoByContainerID
|
||||
local C_Garrison_RequestLandingPageShipmentInfo = C_Garrison.RequestLandingPageShipmentInfo
|
||||
local C_Garrison_GetCompleteMissions = C_Garrison.GetCompleteMissions
|
||||
local C_Garrison_GetLooseShipments = C_Garrison.GetLooseShipments
|
||||
local C_Garrison_GetTalentTreeIDsByClassID = C_Garrison.GetTalentTreeIDsByClassID
|
||||
local C_Garrison_GetTalentTreeInfo = C_Garrison.GetTalentTreeInfo
|
||||
local C_QuestLog_IsQuestFlaggedCompleted = C_QuestLog.IsQuestFlaggedCompleted
|
||||
local C_IslandsQueue_GetIslandsWeeklyQuestID = C_IslandsQueue.GetIslandsWeeklyQuestID
|
||||
local C_CurrencyInfo_GetCurrencyInfo = C_CurrencyInfo.GetCurrencyInfo
|
||||
local C_Covenants_GetActiveCovenantID = C_Covenants.GetActiveCovenantID
|
||||
local C_CovenantCallings_AreCallingsUnlocked = C_CovenantCallings.AreCallingsUnlocked
|
||||
local CovenantCalling_Create = CovenantCalling_Create
|
||||
local GetMaxLevelForExpansionLevel = GetMaxLevelForExpansionLevel
|
||||
local GetQuestObjectiveInfo = GetQuestObjectiveInfo
|
||||
local SecondsToTime = SecondsToTime
|
||||
local IsAltKeyDown = IsAltKeyDown
|
||||
|
||||
local GARRISON_LANDING_NEXT = GARRISON_LANDING_NEXT
|
||||
local CAPACITANCE_WORK_ORDERS = CAPACITANCE_WORK_ORDERS
|
||||
local FOLLOWERLIST_LABEL_TROOPS = FOLLOWERLIST_LABEL_TROOPS
|
||||
local GARRISON_EMPTY_IN_PROGRESS_LIST = GARRISON_EMPTY_IN_PROGRESS_LIST
|
||||
local GARRISON_LANDING_SHIPMENT_COUNT = GARRISON_LANDING_SHIPMENT_COUNT
|
||||
local GOAL_COMPLETED = GOAL_COMPLETED
|
||||
local GREEN_FONT_COLOR = GREEN_FONT_COLOR
|
||||
local ISLANDS_HEADER = ISLANDS_HEADER
|
||||
local ISLANDS_QUEUE_FRAME_TITLE = ISLANDS_QUEUE_FRAME_TITLE
|
||||
local ISLANDS_QUEUE_WEEKLY_QUEST_PROGRESS = ISLANDS_QUEUE_WEEKLY_QUEST_PROGRESS
|
||||
local LE_EXPANSION_BATTLE_FOR_AZEROTH = LE_EXPANSION_BATTLE_FOR_AZEROTH
|
||||
local LE_FOLLOWER_TYPE_GARRISON_6_0 = Enum.GarrisonFollowerType.FollowerType_6_0
|
||||
local LE_FOLLOWER_TYPE_GARRISON_7_0 = Enum.GarrisonFollowerType.FollowerType_7_0
|
||||
local LE_FOLLOWER_TYPE_GARRISON_8_0 = Enum.GarrisonFollowerType.FollowerType_8_0
|
||||
local LE_FOLLOWER_TYPE_GARRISON_6_2 = Enum.GarrisonFollowerType.FollowerType_6_2
|
||||
local LE_FOLLOWER_TYPE_GARRISON_9_0 = Enum.GarrisonFollowerType.FollowerType_9_0
|
||||
local LE_GARRISON_TYPE_6_0 = Enum.GarrisonType.Type_6_0
|
||||
local LE_GARRISON_TYPE_7_0 = Enum.GarrisonType.Type_7_0
|
||||
local LE_GARRISON_TYPE_8_0 = Enum.GarrisonType.Type_8_0
|
||||
local LE_GARRISON_TYPE_9_0 = Enum.GarrisonType.Type_9_0
|
||||
local RESEARCH_TIME_LABEL = RESEARCH_TIME_LABEL
|
||||
local DATE_COMPLETED = DATE_COMPLETED:gsub('(%%s)', '|cFF33FF33%1|r') -- 'Completed: |cFF33FF33%s|r'
|
||||
local EXPANSION_NAME5 = EXPANSION_NAME5 -- 'Warlords of Draenor'
|
||||
local EXPANSION_NAME6 = EXPANSION_NAME6 -- 'Legion'
|
||||
local EXPANSION_NAME7 = EXPANSION_NAME7 -- 'Battle for Azeroth'
|
||||
local EXPANSION_NAME8 = EXPANSION_NAME8 -- 'Shadowlands'
|
||||
|
||||
local MAIN_CURRENCY = 1813
|
||||
local iconString = '|T%s:16:16:0:0:64:64:4:60:4:60|t'
|
||||
local numMissions = 0
|
||||
local callingsData = {}
|
||||
local covenantTreeIDs = {
|
||||
[1] = {308, 312, 316, 320, 327},
|
||||
[2] = {309, 314, 317, 324, 326},
|
||||
[3] = {307, 311, 315, 319, 328},
|
||||
[4] = {310, 313, 318, 321, 329}
|
||||
}
|
||||
|
||||
local function sortFunction(a, b)
|
||||
return a.missionEndTime < b.missionEndTime
|
||||
end
|
||||
|
||||
local function LandingPage(_, ...)
|
||||
if not C_Garrison_HasGarrison(...) then
|
||||
return
|
||||
end
|
||||
|
||||
HideUIPanel(_G.GarrisonLandingPage)
|
||||
ShowGarrisonLandingPage(...)
|
||||
end
|
||||
|
||||
local menuList = {
|
||||
{text = _G.GARRISON_LANDING_PAGE_TITLE, func = LandingPage, arg1 = LE_GARRISON_TYPE_6_0, notCheckable = true},
|
||||
{text = _G.ORDER_HALL_LANDING_PAGE_TITLE, func = LandingPage, arg1 = LE_GARRISON_TYPE_7_0, notCheckable = true},
|
||||
{text = _G.WAR_CAMPAIGN, func = LandingPage, arg1 = LE_GARRISON_TYPE_8_0, notCheckable = true},
|
||||
{text = _G.GARRISON_TYPE_9_0_LANDING_PAGE_TITLE, func = LandingPage, arg1 = LE_GARRISON_TYPE_9_0, notCheckable = true},
|
||||
}
|
||||
|
||||
local data = {}
|
||||
local function AddInProgressMissions(garrisonType)
|
||||
wipe(data)
|
||||
|
||||
C_Garrison_GetInProgressMissions(data, garrisonType)
|
||||
|
||||
if next(data) then
|
||||
sort(data, sortFunction) -- Sort by time left, lowest first
|
||||
|
||||
for _, mission in ipairs(data) do
|
||||
local timeLeft = mission.timeLeftSeconds
|
||||
local r, g, b = 1, 1, 1
|
||||
if mission.isRare then
|
||||
r, g, b = 0.09, 0.51, 0.81
|
||||
end
|
||||
|
||||
if timeLeft and timeLeft == 0 then
|
||||
DT.tooltip:AddDoubleLine(mission.name, GOAL_COMPLETED, r, g, b, GREEN_FONT_COLOR:GetRGB())
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(mission.name, SecondsToTime(timeLeft), r, g, b, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
else
|
||||
DT.tooltip:AddLine(GARRISON_EMPTY_IN_PROGRESS_LIST, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
local function AddFollowerInfo(garrisonType)
|
||||
data = C_Garrison_GetFollowerShipments(garrisonType)
|
||||
|
||||
if next(data) then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(FOLLOWERLIST_LABEL_TROOPS) -- 'Troops'
|
||||
for _, followerShipments in ipairs(data) do
|
||||
local name, _, _, shipmentsReady, shipmentsTotal, _, _, timeleftString = C_Garrison_GetLandingPageShipmentInfoByContainerID(followerShipments)
|
||||
if name and shipmentsReady and shipmentsTotal then
|
||||
if timeleftString then
|
||||
DT.tooltip:AddDoubleLine(name, format(GARRISON_LANDING_SHIPMENT_COUNT, shipmentsReady, shipmentsTotal) .. ' ' .. format(GARRISON_LANDING_NEXT,timeleftString), 1, 1, 1, 1, 1, 1)
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(name, format(GARRISON_LANDING_SHIPMENT_COUNT, shipmentsReady, shipmentsTotal), 1, 1, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local covenantInfo = {}
|
||||
local function AddTalentInfo(garrisonType, currentCovenant)
|
||||
if garrisonType == LE_GARRISON_TYPE_9_0 then
|
||||
local current = covenantTreeIDs[currentCovenant]
|
||||
if current then
|
||||
wipe(covenantInfo)
|
||||
data = E:CopyTable(covenantInfo, current)
|
||||
else
|
||||
wipe(data)
|
||||
end
|
||||
else
|
||||
data = C_Garrison_GetTalentTreeIDsByClassID(garrisonType, E.myClassID)
|
||||
end
|
||||
|
||||
if next(data) then
|
||||
-- This is a talent that has completed, but has not been seen in the talent UI yet.
|
||||
-- No longer provide relevant output in SL. Still used by old content.
|
||||
local completeTalentID = C_Garrison_GetCompleteTalent(garrisonType)
|
||||
if completeTalentID > 0 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(RESEARCH_TIME_LABEL) -- 'Research Time:'
|
||||
|
||||
for _, treeID in ipairs(data) do
|
||||
local treeInfo = C_Garrison_GetTalentTreeInfo(treeID)
|
||||
for _, talent in ipairs(treeInfo.talents) do
|
||||
if talent.isBeingResearched or (talent.id == completeTalentID and garrisonType ~= LE_GARRISON_TYPE_9_0)then
|
||||
if talent.timeRemaining and talent.timeRemaining == 0 then
|
||||
DT.tooltip:AddDoubleLine(talent.name, GOAL_COMPLETED, 1, 1, 1, GREEN_FONT_COLOR:GetRGB())
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(talent.name, SecondsToTime(talent.timeRemaining), 1, 1, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function GetInfo(id)
|
||||
local info = C_CurrencyInfo_GetCurrencyInfo(id)
|
||||
return info.quantity, info.name, (info.iconFileID and format(iconString, info.iconFileID)) or '136012'
|
||||
end
|
||||
|
||||
local function AddInfo(id)
|
||||
local quantity, _, icon = GetInfo(id)
|
||||
return format('%s %s', icon, BreakUpLargeNumbers(quantity))
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
DT.tooltip:AddLine(EXPANSION_NAME8, 1, .5, 0)
|
||||
DT.tooltip:AddDoubleLine(L["Mission(s) Report:"], AddInfo(1813), nil, nil, nil, 1, 1, 1)
|
||||
AddInProgressMissions(LE_FOLLOWER_TYPE_GARRISON_9_0)
|
||||
|
||||
if C_CovenantCallings_AreCallingsUnlocked() then
|
||||
local questNum = 0
|
||||
for _, calling in ipairs(callingsData) do
|
||||
local callingObj = CovenantCalling_Create(calling)
|
||||
if callingObj:GetState() == 0 then
|
||||
questNum = questNum + 1
|
||||
end
|
||||
end
|
||||
if questNum > 0 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(format('%s %s', questNum, L["Calling Quest(s) available."]))
|
||||
end
|
||||
end
|
||||
|
||||
local currentCovenant = C_Covenants_GetActiveCovenantID()
|
||||
if currentCovenant and currentCovenant > 0 then
|
||||
AddTalentInfo(LE_GARRISON_TYPE_9_0, currentCovenant)
|
||||
end
|
||||
|
||||
if IsShiftKeyDown() then
|
||||
-- Battle for Azeroth
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(EXPANSION_NAME7, 1, .5, 0)
|
||||
DT.tooltip:AddDoubleLine(L["Mission(s) Report:"], AddInfo(1560), nil, nil, nil, 1, 1, 1)
|
||||
AddInProgressMissions(LE_FOLLOWER_TYPE_GARRISON_8_0)
|
||||
|
||||
-- Island Expeditions
|
||||
if E.mylevel >= GetMaxLevelForExpansionLevel(LE_EXPANSION_BATTLE_FOR_AZEROTH) then
|
||||
local questID = C_IslandsQueue_GetIslandsWeeklyQuestID()
|
||||
if questID then
|
||||
local _, _, finished, numFulfilled, numRequired = GetQuestObjectiveInfo(questID, 1, false)
|
||||
local text, r1, g1, b1
|
||||
|
||||
if finished or C_QuestLog_IsQuestFlaggedCompleted(questID) then
|
||||
text = GOAL_COMPLETED
|
||||
r1, g1, b1 = GREEN_FONT_COLOR:GetRGB()
|
||||
else
|
||||
text = ISLANDS_QUEUE_WEEKLY_QUEST_PROGRESS:format(numFulfilled, numRequired)
|
||||
r1, g1, b1 = 1, 1, 1
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(ISLANDS_HEADER .. ':')
|
||||
DT.tooltip:AddDoubleLine(ISLANDS_QUEUE_FRAME_TITLE, text, 1, 1, 1, r1, g1, b1)
|
||||
end
|
||||
end
|
||||
|
||||
AddFollowerInfo(LE_GARRISON_TYPE_7_0)
|
||||
AddTalentInfo(LE_GARRISON_TYPE_7_0)
|
||||
|
||||
-- Legion
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(EXPANSION_NAME6, 1, .5, 0)
|
||||
DT.tooltip:AddDoubleLine(L["Mission(s) Report:"], AddInfo(1220), nil, nil, nil, 1, 1, 1)
|
||||
|
||||
AddInProgressMissions(LE_FOLLOWER_TYPE_GARRISON_7_0)
|
||||
AddFollowerInfo(LE_GARRISON_TYPE_7_0)
|
||||
|
||||
-- 'Loose Work Orders' (i.e. research, equipment)
|
||||
data = C_Garrison_GetLooseShipments(LE_GARRISON_TYPE_7_0)
|
||||
if next(data) then
|
||||
DT.tooltip:AddLine(CAPACITANCE_WORK_ORDERS) -- 'Work Orders'
|
||||
|
||||
for _, looseShipments in ipairs(data) do
|
||||
local name, _, _, shipmentsReady, shipmentsTotal, _, _, timeleftString = C_Garrison_GetLandingPageShipmentInfoByContainerID(looseShipments)
|
||||
if name then
|
||||
if timeleftString then
|
||||
DT.tooltip:AddDoubleLine(name, format(GARRISON_LANDING_SHIPMENT_COUNT, shipmentsReady, shipmentsTotal) .. ' ' .. format(GARRISON_LANDING_NEXT,timeleftString), 1, 1, 1, 1, 1, 1)
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(name, format(GARRISON_LANDING_SHIPMENT_COUNT, shipmentsReady, shipmentsTotal), 1, 1, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AddTalentInfo(LE_GARRISON_TYPE_7_0)
|
||||
|
||||
-- Warlords of Draenor
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(EXPANSION_NAME5, 1, .5, 0)
|
||||
DT.tooltip:AddDoubleLine(L["Mission(s) Report:"], AddInfo(824), nil, nil, nil, 1, 1, 1)
|
||||
AddInProgressMissions(LE_FOLLOWER_TYPE_GARRISON_6_0)
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddDoubleLine(L["Naval Mission(s) Report:"], AddInfo(1101), nil, nil, nil, 1, 1 , 1)
|
||||
AddInProgressMissions(LE_FOLLOWER_TYPE_GARRISON_6_2)
|
||||
|
||||
--Buildings
|
||||
data = C_Garrison_GetBuildings(LE_GARRISON_TYPE_6_0)
|
||||
if next(data) then
|
||||
local AddLine = true
|
||||
for _, buildings in ipairs(data) do
|
||||
local name, _, _, shipmentsReady, shipmentsTotal, _, _, timeleftString = C_Garrison_GetLandingPageShipmentInfo(buildings.buildingID)
|
||||
if name and shipmentsTotal then
|
||||
if AddLine then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(L["Building(s) Report:"])
|
||||
AddLine = false
|
||||
end
|
||||
|
||||
if timeleftString then
|
||||
DT.tooltip:AddDoubleLine(name, format(GARRISON_LANDING_SHIPMENT_COUNT, shipmentsReady, shipmentsTotal) .. ' ' .. format(GARRISON_LANDING_NEXT,timeleftString), 1, 1, 1, 1, 1, 1)
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(name, format(GARRISON_LANDING_SHIPMENT_COUNT, shipmentsReady, shipmentsTotal), 1, 1, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine('Hold Shift - Show Previous Expansion', .66, .66, .66)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnClick(self)
|
||||
if InCombatLockdown() then _G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT) return end
|
||||
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, self)
|
||||
_G.EasyMenu(menuList, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
end
|
||||
|
||||
local function OnEvent(self, event, ...)
|
||||
if event == 'CURRENCY_DISPLAY_UPDATE' and select(1, ...) ~= MAIN_CURRENCY then
|
||||
return
|
||||
end
|
||||
|
||||
if event == 'COVENANT_CALLINGS_UPDATED' then
|
||||
wipe(callingsData)
|
||||
callingsData = ...
|
||||
end
|
||||
|
||||
if event == 'GARRISON_SHIPMENT_RECEIVED' or (event == 'SHIPMENT_UPDATE' and select(1, ...) == true) then
|
||||
C_Garrison_RequestLandingPageShipmentInfo()
|
||||
end
|
||||
|
||||
if event == 'GARRISON_MISSION_NPC_OPENED' then
|
||||
self:RegisterEvent('GARRISON_MISSION_LIST_UPDATE')
|
||||
elseif event == 'GARRISON_MISSION_NPC_CLOSED' then
|
||||
self:UnregisterEvent('GARRISON_MISSION_LIST_UPDATE')
|
||||
end
|
||||
|
||||
if event == 'GARRISON_LANDINGPAGE_SHIPMENTS' or event == 'GARRISON_MISSION_FINISHED' or event == 'GARRISON_MISSION_NPC_CLOSED' or event == 'GARRISON_MISSION_LIST_UPDATE' then
|
||||
numMissions = #C_Garrison_GetCompleteMissions(LE_FOLLOWER_TYPE_GARRISON_9_0)
|
||||
+ #C_Garrison_GetCompleteMissions(LE_FOLLOWER_TYPE_GARRISON_8_0)
|
||||
+ #C_Garrison_GetCompleteMissions(LE_FOLLOWER_TYPE_GARRISON_7_0)
|
||||
+ #C_Garrison_GetCompleteMissions(LE_FOLLOWER_TYPE_GARRISON_6_0)
|
||||
+ #C_Garrison_GetCompleteMissions(LE_FOLLOWER_TYPE_GARRISON_6_2)
|
||||
end
|
||||
|
||||
if numMissions > 0 then
|
||||
self.text:SetFormattedText(DATE_COMPLETED, numMissions)
|
||||
else
|
||||
self.text:SetText(AddInfo(MAIN_CURRENCY))
|
||||
end
|
||||
|
||||
if event == 'MODIFIER_STATE_CHANGED' and not IsAltKeyDown() and GetMouseFocus() == self then
|
||||
OnEnter(self)
|
||||
end
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('Missions', nil, {'CURRENCY_DISPLAY_UPDATE', 'GARRISON_LANDINGPAGE_SHIPMENTS', 'GARRISON_TALENT_UPDATE', 'GARRISON_TALENT_COMPLETE', 'GARRISON_SHIPMENT_RECEIVED', 'SHIPMENT_UPDATE', 'GARRISON_MISSION_FINISHED', 'GARRISON_MISSION_NPC_CLOSED', 'GARRISON_MISSION_NPC_OPENED', 'MODIFIER_STATE_CHANGED', 'COVENANT_CALLINGS_UPDATED'}, OnEvent, nil, OnClick, OnEnter, nil, _G.GARRISON_MISSIONS)
|
||||
65
Modules/DataTexts/MovementSpeed.lua
Normal file
65
Modules/DataTexts/MovementSpeed.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local strjoin = strjoin
|
||||
local IsFalling = IsFalling
|
||||
local IsFlying = IsFlying
|
||||
local IsSwimming = IsSwimming
|
||||
local GetUnitSpeed = GetUnitSpeed
|
||||
local STAT_CATEGORY_ENHANCEMENTS = STAT_CATEGORY_ENHANCEMENTS
|
||||
local BASE_MOVEMENT_SPEED = BASE_MOVEMENT_SPEED
|
||||
local STAT_MOVEMENT_SPEED = STAT_MOVEMENT_SPEED
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
local beforeFalling, wasFlying
|
||||
|
||||
local delayed
|
||||
local function DelayUpdate()
|
||||
if not lastPanel then return end
|
||||
|
||||
local _, runSpeed, flightSpeed, swimSpeed = GetUnitSpeed('player')
|
||||
local speed
|
||||
|
||||
if IsSwimming() then
|
||||
speed = swimSpeed
|
||||
wasFlying = false
|
||||
elseif IsFlying() then
|
||||
speed = flightSpeed
|
||||
wasFlying = true
|
||||
else
|
||||
speed = runSpeed
|
||||
wasFlying = false
|
||||
end
|
||||
|
||||
if IsFalling() and wasFlying and beforeFalling then
|
||||
speed = beforeFalling
|
||||
else
|
||||
beforeFalling = speed
|
||||
end
|
||||
|
||||
local percent = speed / BASE_MOVEMENT_SPEED * 100
|
||||
if E.global.datatexts.settings.MovementSpeed.NoLabel then
|
||||
lastPanel.text:SetFormattedText(displayString, percent)
|
||||
else
|
||||
lastPanel.text:SetFormattedText(displayString, E.global.datatexts.settings.MovementSpeed.Label ~= '' and E.global.datatexts.settings.MovementSpeed.Label or STAT_MOVEMENT_SPEED, percent)
|
||||
end
|
||||
|
||||
delayed = nil
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
if not delayed then
|
||||
delayed = E:Delay(0.05, DelayUpdate)
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.MovementSpeed.NoLabel and '' or '%s: ', hex, '%.'..E.global.datatexts.settings.MovementSpeed.decimalLength..'f%%|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('MovementSpeed', STAT_CATEGORY_ENHANCEMENTS, {'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE', 'UNIT_SPELL_HASTE'}, OnEvent, nil, nil, nil, nil, STAT_MOVEMENT_SPEED, nil, ValueColorUpdate)
|
||||
31
Modules/DataTexts/PrimaryStat.lua
Normal file
31
Modules/DataTexts/PrimaryStat.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local strjoin = strjoin
|
||||
local UnitStat = UnitStat
|
||||
local GetSpecialization = GetSpecialization
|
||||
local STAT_CATEGORY_ATTRIBUTES = STAT_CATEGORY_ATTRIBUTES
|
||||
local PRIMARY_STAT = SPEC_FRAME_PRIMARY_STAT:gsub('[::%s]-%%s$','')
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEvent(self)
|
||||
local StatID = DT.SPECIALIZATION_CACHE[GetSpecialization()] and DT.SPECIALIZATION_CACHE[GetSpecialization()].statID
|
||||
|
||||
local name = StatID and _G['SPELL_STAT'..StatID..'_NAME']
|
||||
if name then
|
||||
self.text:SetFormattedText(displayString, name..': ', UnitStat('player', StatID))
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', '%s', hex, '%.f|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Primary Stat', STAT_CATEGORY_ATTRIBUTES, { 'UNIT_STATS', 'UNIT_AURA', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_TALENT_UPDATE' }, OnEvent, nil, nil, nil, nil, PRIMARY_STAT, nil, ValueColorUpdate)
|
||||
125
Modules/DataTexts/Quickjoin.lua
Normal file
125
Modules/DataTexts/Quickjoin.lua
Normal file
@@ -0,0 +1,125 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
local CH = E:GetModule('Chat')
|
||||
|
||||
local next, pairs, select, type = next, pairs, select, type
|
||||
local format, strjoin, wipe, gsub = format, strjoin, wipe, gsub
|
||||
local ToggleQuickJoinPanel = ToggleQuickJoinPanel
|
||||
local SocialQueueUtil_GetQueueName = SocialQueueUtil_GetQueueName
|
||||
local SocialQueueUtil_GetRelationshipInfo = SocialQueueUtil_GetRelationshipInfo
|
||||
local C_SocialQueue_GetAllGroups = C_SocialQueue.GetAllGroups
|
||||
local C_SocialQueue_GetGroupMembers = C_SocialQueue.GetGroupMembers
|
||||
local C_SocialQueue_GetGroupQueues = C_SocialQueue.GetGroupQueues
|
||||
local C_LFGList_GetSearchResultInfo = C_LFGList.GetSearchResultInfo
|
||||
local UNKNOWN, QUICK_JOIN = UNKNOWN, QUICK_JOIN
|
||||
|
||||
local displayString = ''
|
||||
local quickJoin = {}
|
||||
|
||||
local function OnEnter()
|
||||
if not next(quickJoin) then return end
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
DT.tooltip:AddLine(QUICK_JOIN, nil, nil, nil, true)
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
for name, activity in pairs(quickJoin) do
|
||||
DT.tooltip:AddDoubleLine(name, activity, nil, nil, nil, 1, 1, 1)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function Update(self)
|
||||
wipe(quickJoin)
|
||||
|
||||
if not self then return end
|
||||
|
||||
local quickJoinGroups = C_SocialQueue_GetAllGroups()
|
||||
for _, guid in pairs(quickJoinGroups) do
|
||||
local players = C_SocialQueue_GetGroupMembers(guid)
|
||||
if players then
|
||||
local firstMember, numMembers, extraCount = players[1], #players, ''
|
||||
local playerName, nameColor = SocialQueueUtil_GetRelationshipInfo(firstMember.guid, nil, firstMember.clubId)
|
||||
if numMembers > 1 then extraCount = format(' +%s', numMembers - 1) end
|
||||
|
||||
local queues = C_SocialQueue_GetGroupQueues(guid)
|
||||
local firstQueue, numQueues = queues and queues[1], queues and #queues or 0
|
||||
local isLFGList = firstQueue and firstQueue.queueData and firstQueue.queueData.queueType == 'lfglist'
|
||||
local coloredName = (playerName and playerName ~= '' and format('%s%s|r%s', nameColor, playerName, extraCount)) or format('{%s%s}', UNKNOWN, extraCount)
|
||||
|
||||
local activity
|
||||
if isLFGList and firstQueue and firstQueue.eligible then
|
||||
local activityName, isLeader, leaderName
|
||||
if firstQueue.queueData.lfgListID then
|
||||
local searchResultInfo = C_LFGList_GetSearchResultInfo(firstQueue.queueData.lfgListID)
|
||||
if searchResultInfo then
|
||||
activityName, leaderName = searchResultInfo.name, searchResultInfo.leaderName
|
||||
isLeader = CH:SocialQueueIsLeader(playerName, leaderName)
|
||||
end
|
||||
end
|
||||
|
||||
if isLeader then
|
||||
coloredName = format([[|TInterface\GroupFrame\UI-Group-LeaderIcon:16:16|t%s]], coloredName)
|
||||
end
|
||||
|
||||
activity = activityName or UNKNOWN
|
||||
if numQueues > 1 then
|
||||
activity = format('[+%s]%s', numQueues - 1, activity)
|
||||
end
|
||||
elseif firstQueue then
|
||||
local output, queueCount = '', 0
|
||||
for _, queue in pairs(queues) do
|
||||
if type(queue) == 'table' and queue.eligible then
|
||||
local queueName = (queue.queueData and SocialQueueUtil_GetQueueName(queue.queueData)) or ''
|
||||
if queueName ~= '' then
|
||||
if output == '' then
|
||||
output = gsub(queueName,'\n.+','') -- grab only the first queue name
|
||||
queueCount = queueCount + select(2, gsub(queueName,'\n','')) -- collect additional on single queue
|
||||
else
|
||||
queueCount = queueCount + 1 + select(2, gsub(queueName,'\n','')) -- collect additional on additional queues
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if output ~= '' then
|
||||
if queueCount > 0 then
|
||||
activity = format('%s[+%s]', output, queueCount)
|
||||
else
|
||||
activity = output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
quickJoin[coloredName] = activity
|
||||
end
|
||||
end
|
||||
|
||||
if E.global.datatexts.settings.QuickJoin.NoLabel then
|
||||
self.text:SetFormattedText(displayString, #quickJoinGroups)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.QuickJoin.Label ~= '' and E.global.datatexts.settings.QuickJoin.Label or QUICK_JOIN..': ', #quickJoinGroups)
|
||||
end
|
||||
end
|
||||
|
||||
local delayed, lastPanel
|
||||
local function throttle()
|
||||
if lastPanel then Update(lastPanel) end
|
||||
delayed = nil
|
||||
end
|
||||
|
||||
local function OnEvent(self, event)
|
||||
if lastPanel ~= self then lastPanel = self end
|
||||
if delayed then return end
|
||||
|
||||
-- use a nonarg passing function, so that it goes through c_timer instead of the waitframe
|
||||
delayed = E:Delay(event == 'ELVUI_FORCE_UPDATE' and 0 or 1, throttle)
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.QuickJoin.NoLabel and '' or '%s', hex, '%d|r')
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
DT:RegisterDatatext('QuickJoin', _G.SOCIAL_LABEL, {"SOCIAL_QUEUE_UPDATE"}, OnEvent, nil, ToggleQuickJoinPanel, OnEnter, nil, QUICK_JOIN, nil, ValueColorUpdate)
|
||||
114
Modules/DataTexts/Reputation.lua
Normal file
114
Modules/DataTexts/Reputation.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local format = format
|
||||
local C_Reputation_GetFactionParagonInfo = C_Reputation.GetFactionParagonInfo
|
||||
local C_Reputation_IsFactionParagon = C_Reputation.IsFactionParagon
|
||||
local GetFriendshipReputation = GetFriendshipReputation
|
||||
local ToggleCharacter = ToggleCharacter
|
||||
local GetWatchedFactionInfo = GetWatchedFactionInfo
|
||||
local REPUTATION, STANDING = REPUTATION, STANDING
|
||||
|
||||
local function OnEvent(self)
|
||||
local name, reaction, min, max, value, factionID = GetWatchedFactionInfo()
|
||||
if not name then return end
|
||||
|
||||
local friendshipID = GetFriendshipReputation(factionID);
|
||||
local isFriend, friendText, standingLabel
|
||||
local isCapped
|
||||
|
||||
if friendshipID then
|
||||
local _, friendRep, _, _, _, _, friendTextLevel, friendThreshold, nextFriendThreshold = GetFriendshipReputation(factionID);
|
||||
isFriend, reaction, friendText = true, 5, friendTextLevel
|
||||
if nextFriendThreshold then
|
||||
min, max, value = friendThreshold, nextFriendThreshold, friendRep;
|
||||
else
|
||||
isCapped = true;
|
||||
end
|
||||
elseif C_Reputation_IsFactionParagon(factionID) then
|
||||
local currentValue, threshold, _, hasRewardPending = C_Reputation_GetFactionParagonInfo(factionID)
|
||||
if currentValue and threshold then
|
||||
min, max = 0, threshold
|
||||
value = currentValue % threshold
|
||||
if hasRewardPending then
|
||||
value = value + threshold
|
||||
end
|
||||
end
|
||||
else
|
||||
if reaction == _G.MAX_REPUTATION_REACTION then
|
||||
isCapped = true
|
||||
end
|
||||
end
|
||||
|
||||
local color = _G.FACTION_BAR_COLORS[reaction]
|
||||
local text = ''
|
||||
local textFormat = E.global.datatexts.settings.Reputation.textFormat
|
||||
|
||||
standingLabel = E:RGBToHex(color.r, color.g, color.b, nil, _G['FACTION_STANDING_LABEL'..reaction]..'|r')
|
||||
|
||||
--Prevent a division by zero
|
||||
local maxMinDiff = max - min
|
||||
if maxMinDiff == 0 then
|
||||
maxMinDiff = 1
|
||||
end
|
||||
|
||||
if isCapped then
|
||||
text = format('%s: [%s]', name, isFriend and friendText or standingLabel)
|
||||
else
|
||||
if textFormat == 'PERCENT' then
|
||||
text = format('%s: %d%% [%s]', name, ((value - min) / (maxMinDiff) * 100), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CURMAX' then
|
||||
text = format('%s: %s - %s [%s]', name, E:ShortValue(value - min), E:ShortValue(max - min), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CURPERC' then
|
||||
text = format('%s: %s - %d%% [%s]', name, E:ShortValue(value - min), ((value - min) / (maxMinDiff) * 100), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CUR' then
|
||||
text = format('%s: %s [%s]', name, E:ShortValue(value - min), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'REM' then
|
||||
text = format('%s: %s [%s]', name, E:ShortValue((max - min) - (value-min)), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CURREM' then
|
||||
text = format('%s: %s - %s [%s]', name, E:ShortValue(value - min), E:ShortValue((max - min) - (value-min)), isFriend and friendText or standingLabel)
|
||||
elseif textFormat == 'CURPERCREM' then
|
||||
text = format('%s: %s - %d%% (%s) [%s]', name, E:ShortValue(value - min), ((value - min) / (maxMinDiff) * 100), E:ShortValue((max - min) - (value-min)), isFriend and friendText or standingLabel)
|
||||
end
|
||||
end
|
||||
|
||||
self.text:SetText(text)
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local name, reaction, min, max, value, factionID = GetWatchedFactionInfo()
|
||||
if factionID and C_Reputation_IsFactionParagon(factionID) then
|
||||
local currentValue, threshold, _, hasRewardPending = C_Reputation_GetFactionParagonInfo(factionID)
|
||||
if currentValue and threshold then
|
||||
min, max = 0, threshold
|
||||
value = currentValue % threshold
|
||||
if hasRewardPending then
|
||||
value = value + threshold
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if name then
|
||||
DT.tooltip:AddLine(name)
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
local friendID, friendTextLevel, _
|
||||
if factionID then friendID, _, _, _, _, _, friendTextLevel = GetFriendshipReputation(factionID) end
|
||||
|
||||
DT.tooltip:AddDoubleLine(STANDING..':', (friendID and friendTextLevel) or _G['FACTION_STANDING_LABEL'..reaction], 1, 1, 1)
|
||||
if reaction ~= _G.MAX_REPUTATION_REACTION or C_Reputation_IsFactionParagon(factionID) then
|
||||
DT.tooltip:AddDoubleLine(REPUTATION..':', format('%d / %d (%d%%)', value - min, max - min, (value - min) / ((max - min == 0) and max or (max - min)) * 100), 1, 1, 1)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnClick()
|
||||
ToggleCharacter('ReputationFrame')
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('Reputation', nil, {'UPDATE_FACTION', 'COMBAT_TEXT_UPDATE'}, OnEvent, nil, OnClick, OnEnter, nil, REPUTATION)
|
||||
160
Modules/DataTexts/SpecSwitch.lua
Normal file
160
Modules/DataTexts/SpecSwitch.lua
Normal file
@@ -0,0 +1,160 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local ipairs, wipe = ipairs, wipe
|
||||
local format, next, strjoin = format, next, strjoin
|
||||
local GetLootSpecialization = GetLootSpecialization
|
||||
local GetNumSpecializations = GetNumSpecializations
|
||||
local GetPvpTalentInfoByID = GetPvpTalentInfoByID
|
||||
local GetSpecialization = GetSpecialization
|
||||
local GetSpecializationInfo = GetSpecializationInfo
|
||||
local GetTalentInfo = GetTalentInfo
|
||||
local HideUIPanel = HideUIPanel
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local SetLootSpecialization = SetLootSpecialization
|
||||
local SetSpecialization = SetSpecialization
|
||||
local ShowUIPanel = ShowUIPanel
|
||||
local LOOT = LOOT
|
||||
local TALENTS = TALENTS
|
||||
local PVP_TALENTS = PVP_TALENTS
|
||||
local SELECT_LOOT_SPECIALIZATION = SELECT_LOOT_SPECIALIZATION
|
||||
local LOOT_SPECIALIZATION_DEFAULT = LOOT_SPECIALIZATION_DEFAULT
|
||||
local C_SpecializationInfo_GetAllSelectedPvpTalentIDs = C_SpecializationInfo.GetAllSelectedPvpTalentIDs
|
||||
|
||||
local displayString, lastPanel, active = ''
|
||||
local activeString = strjoin('', '|cff00FF00' , _G.ACTIVE_PETS, '|r')
|
||||
local inactiveString = strjoin('', '|cffFF0000', _G.FACTION_INACTIVE, '|r')
|
||||
local menuList = {
|
||||
{ text = SELECT_LOOT_SPECIALIZATION, isTitle = true, notCheckable = true },
|
||||
{ checked = function() return GetLootSpecialization() == 0 end, func = function() SetLootSpecialization(0) end },
|
||||
}
|
||||
|
||||
local specList = {
|
||||
{ text = _G.SPECIALIZATION, isTitle = true, notCheckable = true },
|
||||
}
|
||||
|
||||
local mainIcon = '|T%s:16:16:0:0:64:64:4:60:4:60|t'
|
||||
local function OnEvent(self)
|
||||
lastPanel = self
|
||||
|
||||
if #menuList == 2 then
|
||||
for index = 1, GetNumSpecializations() do
|
||||
local id, name, _, icon = GetSpecializationInfo(index)
|
||||
if id then
|
||||
menuList[index + 2] = { text = name, checked = function() return GetLootSpecialization() == id end, func = function() SetLootSpecialization(id) end }
|
||||
specList[index + 1] = { text = format('|T%s:14:14:0:0:64:64:4:60:4:60|t %s', icon, name), checked = function() return GetSpecialization() == index end, func = function() SetSpecialization(index) end }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local specIndex = GetSpecialization()
|
||||
local specialization = GetLootSpecialization()
|
||||
local info = DT.SPECIALIZATION_CACHE[specIndex]
|
||||
|
||||
if not info then
|
||||
self.text:SetText('N/A')
|
||||
return
|
||||
end
|
||||
|
||||
active = specIndex
|
||||
|
||||
local spec = format(mainIcon, info.icon)
|
||||
|
||||
if specialization == 0 or info.id == specialization then
|
||||
self.text:SetFormattedText('%s %s', spec, info.name)
|
||||
else
|
||||
info = DT.SPECIALIZATION_CACHE[specialization]
|
||||
self.text:SetFormattedText('%s: %s %s: %s', L["Spec"], spec, LOOT, format(mainIcon, info.icon))
|
||||
end
|
||||
end
|
||||
|
||||
local listIcon = '|T%s:16:16:0:0:50:50:4:46:4:46|t'
|
||||
local function AddTexture(texture)
|
||||
return texture and format(listIcon, texture) or ''
|
||||
end
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
for i, info in ipairs(DT.SPECIALIZATION_CACHE) do
|
||||
DT.tooltip:AddLine(strjoin(' ', format(displayString, info.name), AddTexture(info.icon), (i == active and activeString or inactiveString)), 1, 1, 1)
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
|
||||
local specialization = GetLootSpecialization()
|
||||
local sameSpec = specialization == 0 and GetSpecialization()
|
||||
local specIndex = DT.SPECIALIZATION_CACHE[sameSpec or specialization]
|
||||
if specIndex and specIndex.name then
|
||||
DT.tooltip:AddLine(format('|cffFFFFFF%s:|r %s', SELECT_LOOT_SPECIALIZATION, sameSpec and format(LOOT_SPECIALIZATION_DEFAULT, specIndex.name) or specIndex.name))
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(TALENTS, 0.69, 0.31, 0.31)
|
||||
|
||||
for i = 1, _G.MAX_TALENT_TIERS do
|
||||
for j = 1, 3 do
|
||||
local _, name, icon, selected = GetTalentInfo(i, j, 1)
|
||||
if selected then
|
||||
DT.tooltip:AddLine(AddTexture(icon)..' '..name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local pvpTalents = C_SpecializationInfo_GetAllSelectedPvpTalentIDs()
|
||||
if next(pvpTalents) then
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(PVP_TALENTS, 0.69, 0.31, 0.31)
|
||||
|
||||
for i, talentID in next, pvpTalents do
|
||||
if i > 4 then break end
|
||||
local _, name, icon, _, _, _, unlocked = GetPvpTalentInfoByID(talentID)
|
||||
if name and unlocked then
|
||||
DT.tooltip:AddLine(AddTexture(icon)..' '..name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
DT.tooltip:AddLine(L["|cffFFFFFFLeft Click:|r Change Talent Specialization"])
|
||||
DT.tooltip:AddLine(L["|cffFFFFFFShift + Left Click:|r Show Talent Specialization UI"])
|
||||
DT.tooltip:AddLine(L["|cffFFFFFFRight Click:|r Change Loot Specialization"])
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnClick(self, button)
|
||||
local specIndex = GetSpecialization()
|
||||
if not specIndex then return end
|
||||
|
||||
if button == 'LeftButton' then
|
||||
if not _G.PlayerTalentFrame then
|
||||
_G.LoadAddOn('Blizzard_TalentUI')
|
||||
end
|
||||
if IsShiftKeyDown() then
|
||||
if not _G.PlayerTalentFrame:IsShown() then
|
||||
ShowUIPanel(_G.PlayerTalentFrame)
|
||||
else
|
||||
HideUIPanel(_G.PlayerTalentFrame)
|
||||
end
|
||||
else
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, self)
|
||||
_G.EasyMenu(specList, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
end
|
||||
else
|
||||
local _, specName = GetSpecializationInfo(specIndex)
|
||||
menuList[2].text = format(LOOT_SPECIALIZATION_DEFAULT, specName)
|
||||
|
||||
DT:SetEasyMenuAnchor(DT.EasyMenu, self)
|
||||
_G.EasyMenu(menuList, DT.EasyMenu, nil, nil, nil, 'MENU')
|
||||
end
|
||||
end
|
||||
|
||||
local function ValueColorUpdate()
|
||||
displayString = strjoin('', '|cffFFFFFF%s:|r ')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Talent/Loot Specialization', nil, {'CHARACTER_POINTS_CHANGED', 'PLAYER_TALENT_UPDATE', 'ACTIVE_TALENT_GROUP_CHANGED', 'PLAYER_LOOT_SPEC_UPDATED'}, OnEvent, nil, OnClick, OnEnter, nil, L["Talent/Loot Specialization"])
|
||||
49
Modules/DataTexts/Speed.lua
Normal file
49
Modules/DataTexts/Speed.lua
Normal file
@@ -0,0 +1,49 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local format, strjoin = format, strjoin
|
||||
|
||||
local BreakUpLargeNumbers = BreakUpLargeNumbers
|
||||
local GetCombatRating = GetCombatRating
|
||||
local GetCombatRatingBonus = GetCombatRatingBonus
|
||||
local GetSpeed = GetSpeed
|
||||
local CR_SPEED = CR_SPEED
|
||||
local CR_SPEED_TOOLTIP = CR_SPEED_TOOLTIP
|
||||
local FONT_COLOR_CODE_CLOSE = FONT_COLOR_CODE_CLOSE
|
||||
local HIGHLIGHT_FONT_COLOR_CODE = HIGHLIGHT_FONT_COLOR_CODE
|
||||
local PAPERDOLLFRAME_TOOLTIP_FORMAT = PAPERDOLLFRAME_TOOLTIP_FORMAT
|
||||
local STAT_SPEED = STAT_SPEED
|
||||
local STAT_CATEGORY_ENHANCEMENTS = STAT_CATEGORY_ENHANCEMENTS
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local text = HIGHLIGHT_FONT_COLOR_CODE..format(PAPERDOLLFRAME_TOOLTIP_FORMAT, STAT_SPEED)..' '..format('%.2F%%', GetSpeed())..FONT_COLOR_CODE_CLOSE
|
||||
local tooltip = format(CR_SPEED_TOOLTIP, BreakUpLargeNumbers(GetCombatRating(CR_SPEED)), GetCombatRatingBonus(CR_SPEED))
|
||||
|
||||
DT.tooltip:AddDoubleLine(text, nil, 1, 1, 1)
|
||||
DT.tooltip:AddLine(tooltip, nil, nil, nil, true)
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local speed = GetSpeed()
|
||||
if E.global.datatexts.settings.Speed.NoLabel then
|
||||
self.text:SetFormattedText(displayString, speed)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Speed.Label ~= '' and E.global.datatexts.settings.Speed.Label or STAT_SPEED, speed)
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Speed.NoLabel and '' or '%s:', hex, '%.'..E.global.datatexts.settings.Speed.decimalLength..'f%%|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Speed', STAT_CATEGORY_ENHANCEMENTS, {"UNIT_STATS", "UNIT_AURA", "ACTIVE_TALENT_GROUP_CHANGED", "PLAYER_TALENT_UPDATE", "PLAYER_DAMAGE_DONE_MODS"}, OnEvent, nil, nil, OnEnter, nil, STAT_SPEED, nil, ValueColorUpdate)
|
||||
30
Modules/DataTexts/Stamina.lua
Normal file
30
Modules/DataTexts/Stamina.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...))
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local strjoin = strjoin
|
||||
local UnitStat = UnitStat
|
||||
local STAT_CATEGORY_ATTRIBUTES = STAT_CATEGORY_ATTRIBUTES
|
||||
local ITEM_MOD_STAMINA_SHORT = ITEM_MOD_STAMINA_SHORT
|
||||
local LE_UNIT_STAT_STAMINA = LE_UNIT_STAT_STAMINA
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEvent(self)
|
||||
if E.global.datatexts.settings.Stamina.NoLabel then
|
||||
self.text:SetFormattedText(displayString, UnitStat("player", LE_UNIT_STAT_STAMINA))
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Stamina.Label ~= '' and E.global.datatexts.settings.Stamina.Label or ITEM_MOD_STAMINA_SHORT..': ', UnitStat("player", LE_UNIT_STAT_STAMINA))
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Stamina.NoLabel and '' or '%s', hex, '%d|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Stamina', STAT_CATEGORY_ATTRIBUTES, { "UNIT_STATS", "UNIT_AURA", "ACTIVE_TALENT_GROUP_CHANGED", "PLAYER_TALENT_UPDATE" }, OnEvent, nil, nil, nil, nil, ITEM_MOD_STAMINA_SHORT, nil, ValueColorUpdate)
|
||||
30
Modules/DataTexts/Strength.lua
Normal file
30
Modules/DataTexts/Strength.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...))
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local strjoin = strjoin
|
||||
local UnitStat = UnitStat
|
||||
local ITEM_MOD_STRENGTH_SHORT = ITEM_MOD_STRENGTH_SHORT
|
||||
local LE_UNIT_STAT_STRENGTH = LE_UNIT_STAT_STRENGTH
|
||||
local STAT_CATEGORY_ATTRIBUTES = STAT_CATEGORY_ATTRIBUTES
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEvent(self)
|
||||
if E.global.datatexts.settings.Strength.NoLabel then
|
||||
self.text:SetFormattedText(displayString, UnitStat("player", LE_UNIT_STAT_STRENGTH))
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Strength.Label ~= '' and E.global.datatexts.settings.Strength.Label or ITEM_MOD_STRENGTH_SHORT..': ', UnitStat("player", LE_UNIT_STAT_STRENGTH))
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Strength.NoLabel and '' or '%s', hex, '%d|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Strength', STAT_CATEGORY_ATTRIBUTES, { "UNIT_STATS", "UNIT_AURA", "ACTIVE_TALENT_GROUP_CHANGED", "PLAYER_TALENT_UPDATE" }, OnEvent, nil, nil, nil, nil, ITEM_MOD_STRENGTH_SHORT, nil, ValueColorUpdate)
|
||||
271
Modules/DataTexts/System.lua
Normal file
271
Modules/DataTexts/System.lua
Normal file
@@ -0,0 +1,271 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local collectgarbage = collectgarbage
|
||||
local tremove, tinsert, sort, wipe, type = tremove, tinsert, sort, wipe, type
|
||||
local ipairs, pairs, floor, format, strmatch = ipairs, pairs, floor, format, strmatch
|
||||
local GetAddOnCPUUsage = GetAddOnCPUUsage
|
||||
local GetAddOnInfo = GetAddOnInfo
|
||||
local GetAddOnMemoryUsage = GetAddOnMemoryUsage
|
||||
local GetAvailableBandwidth = GetAvailableBandwidth
|
||||
local GetFileStreamingStatus = GetFileStreamingStatus
|
||||
local GetBackgroundLoadingStatus = GetBackgroundLoadingStatus
|
||||
local GetDownloadedPercentage = GetDownloadedPercentage
|
||||
local SetCVar = SetCVar
|
||||
local GetCVar = GetCVar
|
||||
local ReloadUI = ReloadUI
|
||||
local GetCVarBool = GetCVarBool
|
||||
local GetFramerate = GetFramerate
|
||||
local GetNetIpTypes = GetNetIpTypes
|
||||
local GetNetStats = GetNetStats
|
||||
local GetNumAddOns = GetNumAddOns
|
||||
local IsAddOnLoaded = IsAddOnLoaded
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local IsControlKeyDown = IsControlKeyDown
|
||||
local ResetCPUUsage = ResetCPUUsage
|
||||
local UpdateAddOnCPUUsage = UpdateAddOnCPUUsage
|
||||
local UpdateAddOnMemoryUsage = UpdateAddOnMemoryUsage
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local UNKNOWN = UNKNOWN
|
||||
|
||||
local statusColors = {
|
||||
'|cff0CD809',
|
||||
'|cffE8DA0F',
|
||||
'|cffFF9000',
|
||||
'|cffD80909'
|
||||
}
|
||||
|
||||
local enteredFrame = false
|
||||
local bandwidthString = '%.2f Mbps'
|
||||
local percentageString = '%.2f%%'
|
||||
local homeLatencyString = '%d ms'
|
||||
local kiloByteString = '%d kb'
|
||||
local megaByteString = '%.2f mb'
|
||||
local profilingString = '%s%s|r |cffffffff/|r %s%s|r'
|
||||
local cpuProfiling = GetCVar('scriptProfile') == '1'
|
||||
|
||||
local CombineAddOns = {
|
||||
['DBM-Core'] = '^<DBM>',
|
||||
['DataStore'] = '^DataStore',
|
||||
['Altoholic'] = '^Altoholic',
|
||||
['AtlasLoot'] = '^AtlasLoot',
|
||||
['Details'] = '^Details!',
|
||||
['RaiderIO'] = '^RaiderIO',
|
||||
['BigWigs'] = '^BigWigs',
|
||||
}
|
||||
|
||||
local function formatMem(memory)
|
||||
local mult = 10^1
|
||||
if memory >= 1024 then
|
||||
return format(megaByteString, ((memory/1024) * mult) / mult)
|
||||
else
|
||||
return format(kiloByteString, (memory * mult) / mult)
|
||||
end
|
||||
end
|
||||
|
||||
local infoTable = {}
|
||||
DT.SystemInfo = infoTable
|
||||
|
||||
local function BuildAddonList()
|
||||
local addOnCount = GetNumAddOns()
|
||||
if addOnCount == #infoTable then return end
|
||||
|
||||
wipe(infoTable)
|
||||
|
||||
for i = 1, addOnCount do
|
||||
local name, title, _, loadable, reason = GetAddOnInfo(i)
|
||||
if loadable or reason == 'DEMAND_LOADED' then
|
||||
tinsert(infoTable, {name = name, index = i, title = title})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OnClick()
|
||||
if IsShiftKeyDown() then
|
||||
if IsControlKeyDown() then
|
||||
SetCVar('scriptProfile', GetCVarBool('scriptProfile') and 0 or 1)
|
||||
ReloadUI()
|
||||
else
|
||||
collectgarbage('collect')
|
||||
ResetCPUUsage()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function displayData(data, totalMEM, totalCPU)
|
||||
if not data then return end
|
||||
|
||||
local name, mem, cpu = data.title, data.mem, data.cpu
|
||||
if cpu then
|
||||
local memRed, cpuRed = mem / totalMEM, cpu / totalCPU
|
||||
local memGreen, cpuGreen = (1 - memRed) + .5, (1 - cpuRed) + .5
|
||||
DT.tooltip:AddDoubleLine(name, format(profilingString, E:RGBToHex(memRed, memGreen, 0), formatMem(mem), E:RGBToHex(cpuRed, cpuGreen, 0), format(homeLatencyString, cpu)), 1, 1, 1)
|
||||
else
|
||||
local red = mem / totalMEM
|
||||
local green = (1 - red) + .5
|
||||
DT.tooltip:AddDoubleLine(name, formatMem(mem), 1, 1, 1, red or 1, green or 1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function displaySort(a, b)
|
||||
return a.sort > b.sort
|
||||
end
|
||||
|
||||
local infoDisplay, ipTypes = {}, {'IPv4', 'IPv6'}
|
||||
local function OnEnter(_, slow)
|
||||
DT.tooltip:ClearLines()
|
||||
enteredFrame = true
|
||||
|
||||
local _, _, homePing, worldPing = GetNetStats()
|
||||
DT.tooltip:AddDoubleLine(L["Home Latency:"], format(homeLatencyString, homePing), .69, .31, .31, .84, .75, .65)
|
||||
DT.tooltip:AddDoubleLine(L["World Latency:"], format(homeLatencyString, worldPing), .69, .31, .31, .84, .75, .65)
|
||||
|
||||
if GetCVarBool('useIPv6') then
|
||||
local ipTypeHome, ipTypeWorld = GetNetIpTypes()
|
||||
DT.tooltip:AddDoubleLine(L["Home Protocol:"], ipTypes[ipTypeHome or 0] or UNKNOWN, .69, .31, .31, .84, .75, .65)
|
||||
DT.tooltip:AddDoubleLine(L["World Protocol:"], ipTypes[ipTypeWorld or 0] or UNKNOWN, .69, .31, .31, .84, .75, .65)
|
||||
end
|
||||
|
||||
local Downloading = GetFileStreamingStatus() ~= 0 or GetBackgroundLoadingStatus() ~= 0
|
||||
if Downloading then
|
||||
DT.tooltip:AddDoubleLine(L["Bandwidth"] , format(bandwidthString, GetAvailableBandwidth()), .69, .31, .31, .84, .75, .65)
|
||||
DT.tooltip:AddDoubleLine(L["Download"] , format(percentageString, GetDownloadedPercentage() * 100), .69, .31, .31, .84, .75, .65)
|
||||
DT.tooltip:AddLine(' ')
|
||||
end
|
||||
|
||||
if slow == 1 or not slow then
|
||||
UpdateAddOnMemoryUsage()
|
||||
end
|
||||
|
||||
if cpuProfiling and not slow then
|
||||
UpdateAddOnCPUUsage()
|
||||
end
|
||||
|
||||
wipe(infoDisplay)
|
||||
|
||||
local count, totalMEM, totalCPU = 0, 0, 0
|
||||
local showByCPU = cpuProfiling and not IsShiftKeyDown()
|
||||
for _, data in ipairs(infoTable) do
|
||||
local i = data.index
|
||||
if IsAddOnLoaded(i) then
|
||||
local mem = GetAddOnMemoryUsage(i)
|
||||
totalMEM = totalMEM + mem
|
||||
|
||||
local cpu
|
||||
if cpuProfiling then
|
||||
cpu = GetAddOnCPUUsage(i)
|
||||
totalCPU = totalCPU + cpu
|
||||
end
|
||||
|
||||
data.sort = (showByCPU and cpu) or mem
|
||||
data.cpu = showByCPU and cpu
|
||||
data.mem = mem
|
||||
|
||||
count = count + 1
|
||||
infoDisplay[count] = data
|
||||
|
||||
if data.name == 'ElvUI' or data.name == 'ElvUI_OptionsUI' then
|
||||
infoTable[data.name] = data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:AddDoubleLine(L["AddOn Memory:"], formatMem(totalMEM), .69, .31, .31, .84, .75, .65)
|
||||
if cpuProfiling then
|
||||
DT.tooltip:AddDoubleLine(L["Total CPU:"], format(homeLatencyString, totalCPU), .69, .31, .31, .84, .75, .65)
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
if not E.global.datatexts.settings.System.ShowOthers then
|
||||
displayData(infoTable.ElvUI, totalMEM, totalCPU)
|
||||
displayData(infoTable.ElvUI_OptionsUI, totalMEM, totalCPU)
|
||||
DT.tooltip:AddLine(' ')
|
||||
else
|
||||
for addon, searchString in pairs(CombineAddOns) do
|
||||
local addonIndex, memoryUsage, cpuUsage = 0, 0, 0
|
||||
for i, data in pairs(infoDisplay) do
|
||||
if data and data.name == addon then
|
||||
addonIndex = i
|
||||
break
|
||||
end
|
||||
end
|
||||
for k, data in pairs(infoDisplay) do
|
||||
if type(data) == 'table' then
|
||||
local name, mem, cpu = data.title, data.mem, data.cpu
|
||||
local stripName = E:StripString(data.title)
|
||||
if name and (strmatch(stripName, searchString) or data.name == addon) then
|
||||
if data.name ~= addon and stripName ~= addon then
|
||||
memoryUsage = memoryUsage + mem;
|
||||
if showByCPU and cpuProfiling then
|
||||
cpuUsage = cpuUsage + cpu;
|
||||
end
|
||||
infoDisplay[k] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if addonIndex > 0 and infoDisplay[addonIndex] then
|
||||
if memoryUsage > 0 then infoDisplay[addonIndex].mem = memoryUsage end
|
||||
if cpuProfiling and cpuUsage > 0 then infoDisplay[addonIndex].cpu = cpuUsage end
|
||||
end
|
||||
end
|
||||
|
||||
for i = count, 1, -1 do
|
||||
local data = infoDisplay[i]
|
||||
if type(data) == 'boolean' then
|
||||
tremove(infoDisplay, i)
|
||||
end
|
||||
end
|
||||
|
||||
sort(infoDisplay, displaySort)
|
||||
|
||||
for i = 1, count do
|
||||
displayData(infoDisplay[i], totalMEM, totalCPU)
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(' ')
|
||||
if showByCPU then
|
||||
DT.tooltip:AddLine(L["(Hold Shift) Memory Usage"])
|
||||
end
|
||||
end
|
||||
|
||||
DT.tooltip:AddLine(L["(Shift Click) Collect Garbage"])
|
||||
DT.tooltip:AddLine(L["(Ctrl & Shift Click) Toggle CPU Profiling"])
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnLeave()
|
||||
enteredFrame = false
|
||||
end
|
||||
|
||||
local wait, count = 10, 0 -- initial delay for update (let the ui load)
|
||||
local function OnUpdate(self, elapsed)
|
||||
wait = wait - elapsed
|
||||
|
||||
if wait < 0 then
|
||||
wait = 1
|
||||
|
||||
local framerate = floor(GetFramerate())
|
||||
local _, _, _, latency = GetNetStats()
|
||||
|
||||
local fps = framerate >= 30 and 1 or (framerate >= 20 and framerate < 30) and 2 or (framerate >= 10 and framerate < 20) and 3 or 4
|
||||
local ping = latency < 150 and 1 or (latency >= 150 and latency < 300) and 2 or (latency >= 300 and latency < 500) and 3 or 4
|
||||
self.text:SetFormattedText(E.global.datatexts.settings.System.NoLabel and '%s%d|r | %s%d|r' or 'FPS: %s%d|r MS: %s%d|r', statusColors[fps], framerate, statusColors[ping], latency)
|
||||
|
||||
if not enteredFrame then return end
|
||||
|
||||
if InCombatLockdown() then
|
||||
if count > 3 then
|
||||
OnEnter(self)
|
||||
count = 0
|
||||
else
|
||||
OnEnter(self, count)
|
||||
count = count + 1
|
||||
end
|
||||
else
|
||||
OnEnter(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('System', nil, nil, BuildAddonList, OnUpdate, OnClick, OnEnter, OnLeave, L["System"])
|
||||
38
Modules/DataTexts/Template.lua
Normal file
38
Modules/DataTexts/Template.lua
Normal file
@@ -0,0 +1,38 @@
|
||||
----------------------------------------------------------------------------------
|
||||
-- This file is a blank datatext example template, this file will not be loaded.
|
||||
----------------------------------------------------------------------------------
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local function Update(self, t)
|
||||
|
||||
end
|
||||
|
||||
local function OnEvent(self, event, ...)
|
||||
|
||||
end
|
||||
|
||||
local function Click()
|
||||
|
||||
end
|
||||
|
||||
local function OnEnter(self)
|
||||
DT.tooltip:ClearLines()
|
||||
-- code goes here
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
--[[
|
||||
DT:RegisterDatatext(name, events, eventFunc, updateFunc, clickFunc, onEnterFunc, onLeaveFunc, localizedName)
|
||||
|
||||
name - name of the datatext (required)
|
||||
events - must be a table with string values of event names to register
|
||||
eventFunc - function that gets fired when an event gets triggered
|
||||
updateFunc - onUpdate script target function
|
||||
click - function to fire when clicking the datatext
|
||||
onEnterFunc - function to fire OnEnter
|
||||
onLeaveFunc - function to fire OnLeave, if not provided one will be set for you that hides the tooltip.
|
||||
localizedName - localized name of the datetext
|
||||
]]
|
||||
|
||||
DT:RegisterDatatext('DTName', 'Category', {'EVENT1', 'EVENT2', 'EVENT3'}, OnEvent, Update, Click, OnEnter)
|
||||
319
Modules/DataTexts/Time.lua
Normal file
319
Modules/DataTexts/Time.lua
Normal file
@@ -0,0 +1,319 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local _G = _G
|
||||
local next, unpack = next, unpack
|
||||
local format, strjoin = format, strjoin
|
||||
local sort, tinsert = sort, tinsert
|
||||
local date, utf8sub = date, string.utf8sub
|
||||
|
||||
local EJ_GetCurrentTier = EJ_GetCurrentTier
|
||||
local EJ_GetInstanceByIndex = EJ_GetInstanceByIndex
|
||||
local EJ_GetNumTiers = EJ_GetNumTiers
|
||||
local EJ_SelectTier = EJ_SelectTier
|
||||
local GetDifficultyInfo = GetDifficultyInfo
|
||||
local C_DateAndTime_GetCurrentCalendarTime = C_DateAndTime.GetCurrentCalendarTime
|
||||
local GetLocale = GetLocale
|
||||
local GetNumSavedInstances = GetNumSavedInstances
|
||||
local GetNumSavedWorldBosses = GetNumSavedWorldBosses
|
||||
local GetNumWorldPVPAreas = GetNumWorldPVPAreas
|
||||
local GetSavedInstanceInfo = GetSavedInstanceInfo
|
||||
local GetSavedWorldBossInfo = GetSavedWorldBossInfo
|
||||
local GetWorldPVPAreaInfo = GetWorldPVPAreaInfo
|
||||
local RequestRaidInfo = RequestRaidInfo
|
||||
local SecondsToTime = SecondsToTime
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local C_Map_GetAreaInfo = C_Map.GetAreaInfo
|
||||
local QUEUE_TIME_UNAVAILABLE = QUEUE_TIME_UNAVAILABLE
|
||||
local TIMEMANAGER_TOOLTIP_LOCALTIME = TIMEMANAGER_TOOLTIP_LOCALTIME
|
||||
local TIMEMANAGER_TOOLTIP_REALMTIME = TIMEMANAGER_TOOLTIP_REALMTIME
|
||||
local VOICE_CHAT_BATTLEGROUND = VOICE_CHAT_BATTLEGROUND
|
||||
local WINTERGRASP_IN_PROGRESS = WINTERGRASP_IN_PROGRESS
|
||||
local WORLD_BOSSES_TEXT = RAID_INFO_WORLD_BOSS
|
||||
|
||||
local APM = { _G.TIMEMANAGER_PM, _G.TIMEMANAGER_AM }
|
||||
local ukDisplayFormat, europeDisplayFormat = '', ''
|
||||
local europeDisplayFormat_nocolor = strjoin('', '%02d', ':|r%02d')
|
||||
local ukDisplayFormat_nocolor = strjoin('', '', '%d', ':|r%02d', ' %s|r')
|
||||
local lockoutInfoFormat = '%s%s %s |cffaaaaaa(%s, %s/%s)'
|
||||
local lockoutInfoFormatNoEnc = '%s%s %s |cffaaaaaa(%s)'
|
||||
local formatBattleGroundInfo = '%s: '
|
||||
local lockoutColorExtended, lockoutColorNormal = { r=0.3,g=1,b=0.3 }, { r=.8,g=.8,b=.8 }
|
||||
local enteredFrame = false
|
||||
|
||||
local Update, lastPanel
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
europeDisplayFormat = strjoin('', '%02d', hex, ':|r%02d')
|
||||
ukDisplayFormat = strjoin('', '', '%d', hex, ':|r%02d', hex, ' %s|r')
|
||||
|
||||
if lastPanel ~= nil then
|
||||
Update(lastPanel, 20000)
|
||||
end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
local function ConvertTime(h, m)
|
||||
local AmPm
|
||||
if E.global.datatexts.settings.Time.time24 == true then
|
||||
return h, m, -1
|
||||
else
|
||||
if h >= 12 then
|
||||
if h > 12 then h = h - 12 end
|
||||
AmPm = 1
|
||||
else
|
||||
if h == 0 then h = 12 end
|
||||
AmPm = 2
|
||||
end
|
||||
end
|
||||
return h, m, AmPm
|
||||
end
|
||||
|
||||
local function CalculateTimeValues(tooltip)
|
||||
if (tooltip and E.global.datatexts.settings.Time.localTime) or (not tooltip and not E.global.datatexts.settings.Time.localTime) then
|
||||
local dateTable = C_DateAndTime_GetCurrentCalendarTime()
|
||||
return ConvertTime(dateTable.hour, dateTable.minute)
|
||||
else
|
||||
local dateTable = date('*t')
|
||||
return ConvertTime(dateTable.hour, dateTable.min)
|
||||
end
|
||||
end
|
||||
|
||||
local function Click()
|
||||
if InCombatLockdown() then _G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT) return end
|
||||
_G.GameTimeFrame:Click()
|
||||
end
|
||||
|
||||
local function OnLeave()
|
||||
enteredFrame = false
|
||||
end
|
||||
|
||||
local InstanceNameByID = {
|
||||
-- NOTE: for some reason the instanceID from EJ_GetInstanceByIndex doesn't match,
|
||||
-- the instanceID from GetInstanceInfo, so use the collectIDs to find the ID to add.
|
||||
[749] = C_Map_GetAreaInfo(3845) -- 'The Eye' -> 'Tempest Keep'
|
||||
}
|
||||
|
||||
local locale = GetLocale()
|
||||
if locale == 'deDE' then -- O.O
|
||||
InstanceNameByID[1023] = 'Belagerung von Boralus' -- 'Die Belagerung von Boralus'
|
||||
InstanceNameByID[1041] = 'Königsruh' -- 'Die Königsruh'
|
||||
InstanceNameByID[1021] = 'Kronsteiganwesen' -- 'Das Kronsteiganwesen'
|
||||
end
|
||||
|
||||
local instanceIconByName = {}
|
||||
local collectIDs, collectedIDs = false -- for testing; mouse over the dt to show the tinspect table
|
||||
local function GetInstanceImages(index, raid)
|
||||
local instanceID, name, _, _, buttonImage = EJ_GetInstanceByIndex(index, raid)
|
||||
while instanceID do
|
||||
if collectIDs then
|
||||
if not collectedIDs then
|
||||
collectedIDs = {}
|
||||
end
|
||||
|
||||
collectedIDs[instanceID] = name
|
||||
end
|
||||
|
||||
instanceIconByName[InstanceNameByID[instanceID] or name] = buttonImage
|
||||
index = index + 1
|
||||
instanceID, name, _, _, buttonImage = EJ_GetInstanceByIndex(index, raid)
|
||||
end
|
||||
end
|
||||
|
||||
local krcntw = locale == 'koKR' or locale == 'zhCN' or locale == 'zhTW'
|
||||
local difficultyTag = { -- Raid Finder, Normal, Heroic, Mythic
|
||||
(krcntw and _G.PLAYER_DIFFICULTY3) or utf8sub(_G.PLAYER_DIFFICULTY3, 1, 1), -- R
|
||||
(krcntw and _G.PLAYER_DIFFICULTY1) or utf8sub(_G.PLAYER_DIFFICULTY1, 1, 1), -- N
|
||||
(krcntw and _G.PLAYER_DIFFICULTY2) or utf8sub(_G.PLAYER_DIFFICULTY2, 1, 1), -- H
|
||||
(krcntw and _G.PLAYER_DIFFICULTY6) or utf8sub(_G.PLAYER_DIFFICULTY6, 1, 1) -- M
|
||||
}
|
||||
|
||||
local function sortFunc(a,b) return a[1] < b[1] end
|
||||
|
||||
local collectedInstanceImages = false
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
if not enteredFrame then
|
||||
enteredFrame = true
|
||||
RequestRaidInfo()
|
||||
end
|
||||
|
||||
if not collectedInstanceImages then
|
||||
local numTiers = (EJ_GetNumTiers() or 0)
|
||||
if numTiers > 0 then
|
||||
local currentTier = EJ_GetCurrentTier()
|
||||
|
||||
-- Loop through the expansions to collect the textures
|
||||
for i=1, numTiers do
|
||||
EJ_SelectTier(i)
|
||||
GetInstanceImages(1, false); -- Populate for dungeon icons
|
||||
GetInstanceImages(1, true); -- Populate for raid icons
|
||||
end
|
||||
|
||||
if collectIDs then
|
||||
E:Dump(collectedIDs, true)
|
||||
end
|
||||
|
||||
-- Set it back to the previous tier
|
||||
if currentTier then
|
||||
EJ_SelectTier(currentTier)
|
||||
end
|
||||
|
||||
collectedInstanceImages = true
|
||||
end
|
||||
end
|
||||
|
||||
local addedHeader = false
|
||||
|
||||
for i = 1, GetNumWorldPVPAreas() do
|
||||
local _, localizedName, isActive, _, startTime, canEnter = GetWorldPVPAreaInfo(i)
|
||||
|
||||
if isActive then
|
||||
startTime = WINTERGRASP_IN_PROGRESS
|
||||
elseif not startTime then
|
||||
startTime = QUEUE_TIME_UNAVAILABLE
|
||||
elseif startTime ~= 0 then
|
||||
startTime = SecondsToTime(startTime, false, nil, 3)
|
||||
end
|
||||
|
||||
if canEnter and startTime ~= 0 then
|
||||
if not addedHeader then
|
||||
DT.tooltip:AddLine(VOICE_CHAT_BATTLEGROUND)
|
||||
addedHeader = true
|
||||
end
|
||||
|
||||
DT.tooltip:AddDoubleLine(format(formatBattleGroundInfo, localizedName), startTime, 1, 1, 1, lockoutColorNormal.r, lockoutColorNormal.g, lockoutColorNormal.b)
|
||||
end
|
||||
end
|
||||
|
||||
local lockedInstances = {raids = {}, dungeons = {}}
|
||||
|
||||
for i = 1, GetNumSavedInstances() do
|
||||
local name, _, _, difficulty, locked, extended, _, isRaid = GetSavedInstanceInfo(i)
|
||||
if (locked or extended) and name then
|
||||
local isLFR, isHeroicOrMythicDungeon = (difficulty == 7 or difficulty == 17), (difficulty == 2 or difficulty == 23)
|
||||
local _, _, isHeroic, _, displayHeroic, displayMythic = GetDifficultyInfo(difficulty)
|
||||
local sortName = name .. (displayMythic and 4 or (isHeroic or displayHeroic) and 3 or isLFR and 1 or 2)
|
||||
local difficultyLetter = (displayMythic and difficultyTag[4] or (isHeroic or displayHeroic) and difficultyTag[3] or isLFR and difficultyTag[1] or difficultyTag[2])
|
||||
local buttonImg = instanceIconByName[name] and format('|T%s:16:16:0:0:96:96:0:64:0:64|t ', instanceIconByName[name]) or ''
|
||||
|
||||
if isRaid then
|
||||
tinsert(lockedInstances.raids, {sortName, difficultyLetter, buttonImg, {GetSavedInstanceInfo(i)}})
|
||||
elseif isHeroicOrMythicDungeon then
|
||||
tinsert(lockedInstances.dungeons, {sortName, difficultyLetter, buttonImg, {GetSavedInstanceInfo(i)}})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if next(lockedInstances.raids) then
|
||||
if DT.tooltip:NumLines() > 0 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
end
|
||||
DT.tooltip:AddLine(L["Saved Raid(s)"])
|
||||
|
||||
sort(lockedInstances.raids, sortFunc)
|
||||
|
||||
for i = 1, #lockedInstances.raids do
|
||||
local difficultyLetter = lockedInstances.raids[i][2]
|
||||
local buttonImg = lockedInstances.raids[i][3]
|
||||
local name, _, reset, _, _, extended, _, _, maxPlayers, _, numEncounters, encounterProgress = unpack(lockedInstances.raids[i][4])
|
||||
|
||||
local lockoutColor = extended and lockoutColorExtended or lockoutColorNormal
|
||||
if numEncounters and numEncounters > 0 and (encounterProgress and encounterProgress > 0) then
|
||||
DT.tooltip:AddDoubleLine(format(lockoutInfoFormat, buttonImg, maxPlayers, difficultyLetter, name, encounterProgress, numEncounters), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(format(lockoutInfoFormatNoEnc, buttonImg, maxPlayers, difficultyLetter, name), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if next(lockedInstances.dungeons) then
|
||||
if DT.tooltip:NumLines() > 0 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
end
|
||||
DT.tooltip:AddLine(L["Saved Dungeon(s)"])
|
||||
|
||||
sort(lockedInstances.dungeons, sortFunc)
|
||||
|
||||
for i = 1,#lockedInstances.dungeons do
|
||||
local difficultyLetter = lockedInstances.dungeons[i][2]
|
||||
local buttonImg = lockedInstances.dungeons[i][3]
|
||||
local name, _, reset, _, _, extended, _, _, maxPlayers, _, numEncounters, encounterProgress = unpack(lockedInstances.dungeons[i][4])
|
||||
|
||||
local lockoutColor = extended and lockoutColorExtended or lockoutColorNormal
|
||||
if numEncounters and numEncounters > 0 and (encounterProgress and encounterProgress > 0) then
|
||||
DT.tooltip:AddDoubleLine(format(lockoutInfoFormat, buttonImg, maxPlayers, difficultyLetter, name, encounterProgress, numEncounters), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(format(lockoutInfoFormatNoEnc, buttonImg, maxPlayers, difficultyLetter, name), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local addedLine = false
|
||||
local worldbossLockoutList = {}
|
||||
for i = 1, GetNumSavedWorldBosses() do
|
||||
local name, _, reset = GetSavedWorldBossInfo(i)
|
||||
tinsert(worldbossLockoutList, {name, reset})
|
||||
end
|
||||
sort(worldbossLockoutList, sortFunc)
|
||||
for i = 1,#worldbossLockoutList do
|
||||
local name, reset = unpack(worldbossLockoutList[i])
|
||||
if reset then
|
||||
if not addedLine then
|
||||
if DT.tooltip:NumLines() > 0 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
end
|
||||
DT.tooltip:AddLine(WORLD_BOSSES_TEXT)
|
||||
addedLine = true
|
||||
end
|
||||
DT.tooltip:AddDoubleLine(name, SecondsToTime(reset, true, nil, 3), 1, 1, 1, 0.8, 0.8, 0.8)
|
||||
end
|
||||
end
|
||||
|
||||
local Hr, Min, AmPm = CalculateTimeValues(true)
|
||||
if DT.tooltip:NumLines() > 0 then
|
||||
DT.tooltip:AddLine(' ')
|
||||
end
|
||||
if AmPm == -1 then
|
||||
DT.tooltip:AddDoubleLine(E.global.datatexts.settings.Time.localTime and TIMEMANAGER_TOOLTIP_REALMTIME or TIMEMANAGER_TOOLTIP_LOCALTIME, format(europeDisplayFormat_nocolor, Hr, Min), 1, 1, 1, lockoutColorNormal.r, lockoutColorNormal.g, lockoutColorNormal.b)
|
||||
else
|
||||
DT.tooltip:AddDoubleLine(E.global.datatexts.settings.Time.localTime and TIMEMANAGER_TOOLTIP_REALMTIME or TIMEMANAGER_TOOLTIP_LOCALTIME, format(ukDisplayFormat_nocolor, Hr, Min, APM[AmPm]), 1, 1, 1, lockoutColorNormal.r, lockoutColorNormal.g, lockoutColorNormal.b)
|
||||
end
|
||||
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnEvent(self, event)
|
||||
if event == 'UPDATE_INSTANCE_INFO' and enteredFrame then
|
||||
OnEnter(self)
|
||||
end
|
||||
end
|
||||
|
||||
function Update(self, t)
|
||||
self.timeElapsed = (self.timeElapsed or 5) - t
|
||||
if self.timeElapsed > 0 then return end
|
||||
self.timeElapsed = 5
|
||||
|
||||
if _G.GameTimeFrame.flashInvite then
|
||||
E:Flash(self, 0.53, true)
|
||||
else
|
||||
E:StopFlash(self)
|
||||
end
|
||||
|
||||
if enteredFrame then
|
||||
OnEnter(self)
|
||||
end
|
||||
|
||||
local Hr, Min, AmPm = CalculateTimeValues()
|
||||
|
||||
if AmPm == -1 then
|
||||
self.text:SetFormattedText(europeDisplayFormat, Hr, Min)
|
||||
else
|
||||
self.text:SetFormattedText(ukDisplayFormat, Hr, Min, APM[AmPm])
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
DT:RegisterDatatext('Time', nil, {'UPDATE_INSTANCE_INFO'}, OnEvent, Update, Click, OnEnter, OnLeave, nil, nil, ValueColorUpdate)
|
||||
53
Modules/DataTexts/Versatility.lua
Normal file
53
Modules/DataTexts/Versatility.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local DT = E:GetModule('DataTexts')
|
||||
|
||||
local format, strjoin = format, strjoin
|
||||
local BreakUpLargeNumbers = BreakUpLargeNumbers
|
||||
local GetCombatRating = GetCombatRating
|
||||
local GetCombatRatingBonus = GetCombatRatingBonus
|
||||
local GetVersatilityBonus = GetVersatilityBonus
|
||||
local CR_VERSATILITY_DAMAGE_DONE = CR_VERSATILITY_DAMAGE_DONE
|
||||
local CR_VERSATILITY_DAMAGE_TAKEN = CR_VERSATILITY_DAMAGE_TAKEN
|
||||
local CR_VERSATILITY_TOOLTIP = CR_VERSATILITY_TOOLTIP
|
||||
local FONT_COLOR_CODE_CLOSE = FONT_COLOR_CODE_CLOSE
|
||||
local HIGHLIGHT_FONT_COLOR_CODE = HIGHLIGHT_FONT_COLOR_CODE
|
||||
local STAT_VERSATILITY = STAT_VERSATILITY
|
||||
local VERSATILITY_TOOLTIP_FORMAT = VERSATILITY_TOOLTIP_FORMAT
|
||||
local STAT_CATEGORY_ENHANCEMENTS = STAT_CATEGORY_ENHANCEMENTS
|
||||
|
||||
local displayString, lastPanel = ''
|
||||
|
||||
local function OnEnter()
|
||||
DT.tooltip:ClearLines()
|
||||
|
||||
local versatility = GetCombatRating(CR_VERSATILITY_DAMAGE_DONE)
|
||||
local versatilityDamageBonus = GetCombatRatingBonus(CR_VERSATILITY_DAMAGE_DONE) + GetVersatilityBonus(CR_VERSATILITY_DAMAGE_DONE)
|
||||
local versatilityDamageTakenReduction = GetCombatRatingBonus(CR_VERSATILITY_DAMAGE_TAKEN) + GetVersatilityBonus(CR_VERSATILITY_DAMAGE_TAKEN)
|
||||
|
||||
local text = HIGHLIGHT_FONT_COLOR_CODE..format(VERSATILITY_TOOLTIP_FORMAT, STAT_VERSATILITY, versatilityDamageBonus, versatilityDamageTakenReduction)..FONT_COLOR_CODE_CLOSE
|
||||
local tooltip = format(CR_VERSATILITY_TOOLTIP, versatilityDamageBonus, versatilityDamageTakenReduction, BreakUpLargeNumbers(versatility), versatilityDamageBonus, versatilityDamageTakenReduction)
|
||||
|
||||
DT.tooltip:AddDoubleLine(text, nil, 1, 1, 1)
|
||||
DT.tooltip:AddLine(tooltip, nil, nil, nil, true)
|
||||
DT.tooltip:Show()
|
||||
end
|
||||
|
||||
local function OnEvent(self)
|
||||
local versatility = GetCombatRatingBonus(CR_VERSATILITY_DAMAGE_DONE) + GetVersatilityBonus(CR_VERSATILITY_DAMAGE_DONE)
|
||||
if E.global.datatexts.settings.Versatility.NoLabel then
|
||||
self.text:SetFormattedText(displayString, versatility)
|
||||
else
|
||||
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Versatility.Label ~= '' and E.global.datatexts.settings.Versatility.Label or STAT_VERSATILITY, versatility)
|
||||
end
|
||||
|
||||
lastPanel = self
|
||||
end
|
||||
|
||||
local function ValueColorUpdate(hex)
|
||||
displayString = strjoin('', E.global.datatexts.settings.Versatility.NoLabel and '' or '%s: ', hex, '%.'..E.global.datatexts.settings.Versatility.decimalLength..'f%%|r')
|
||||
|
||||
if lastPanel then OnEvent(lastPanel) end
|
||||
end
|
||||
E.valueColorUpdateFuncs[ValueColorUpdate] = true
|
||||
|
||||
DT:RegisterDatatext('Versatility', STAT_CATEGORY_ENHANCEMENTS, {"UNIT_STATS", "UNIT_AURA", "ACTIVE_TALENT_GROUP_CHANGED", "PLAYER_TALENT_UPDATE", "PLAYER_DAMAGE_DONE_MODS"}, OnEvent, nil, nil, OnEnter, nil, STAT_VERSATILITY, nil, ValueColorUpdate)
|
||||
15
Modules/Load_Modules.xml
Normal file
15
Modules/Load_Modules.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Include file='Maps\Load_Maps.xml'/>
|
||||
<Include file='Auras\Load_Auras.xml'/>
|
||||
<Include file='Nameplates\Load_Nameplates.xml'/>
|
||||
<Include file='Tooltip\Load_Tooltip.xml'/>
|
||||
<Include file='DataTexts\Load_DataTexts.xml'/>
|
||||
<Include file='DataBars\Load_DataBars.xml'/>
|
||||
<Include file='ActionBars\Load_ActionBars.xml'/>
|
||||
<Include file='UnitFrames\Load_UnitFrames.xml'/>
|
||||
<Include file='Chat\Load_Chat.xml'/>
|
||||
<Include file='Bags\Load_Bags.xml'/>
|
||||
<Include file='Misc\Load_Misc.xml'/>
|
||||
<Include file='Skins\Load_Skins.xml'/>
|
||||
<Include file='Blizzard\Load_Blizzard.xml'/>
|
||||
</Ui>
|
||||
4
Modules/Maps/Load_Maps.xml
Normal file
4
Modules/Maps/Load_Maps.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='Minimap.lua'/>
|
||||
<Script file='Worldmap.lua'/>
|
||||
</Ui>
|
||||
428
Modules/Maps/Minimap.lua
Normal file
428
Modules/Maps/Minimap.lua
Normal file
@@ -0,0 +1,428 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local M = E:GetModule('Minimap')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local pairs = pairs
|
||||
local tinsert = tinsert
|
||||
local utf8sub = string.utf8sub
|
||||
|
||||
local CloseAllWindows = CloseAllWindows
|
||||
local CloseMenus = CloseMenus
|
||||
local PlaySound = PlaySound
|
||||
local CreateFrame = CreateFrame
|
||||
local GarrisonLandingPageMinimapButton_OnClick = GarrisonLandingPageMinimapButton_OnClick
|
||||
local GetMinimapZoneText = GetMinimapZoneText
|
||||
local GetZonePVPInfo = GetZonePVPInfo
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local IsAddOnLoaded = IsAddOnLoaded
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local MainMenuMicroButton_SetNormal = MainMenuMicroButton_SetNormal
|
||||
local ShowUIPanel, HideUIPanel = ShowUIPanel, HideUIPanel
|
||||
local ToggleAchievementFrame = ToggleAchievementFrame
|
||||
local ToggleCharacter = ToggleCharacter
|
||||
local ToggleCollectionsJournal = ToggleCollectionsJournal
|
||||
local ToggleFrame = ToggleFrame
|
||||
local ToggleFriendsFrame = ToggleFriendsFrame
|
||||
local ToggleGuildFrame = ToggleGuildFrame
|
||||
local ToggleHelpFrame = ToggleHelpFrame
|
||||
local ToggleLFDParentFrame = ToggleLFDParentFrame
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local Minimap = _G.Minimap
|
||||
|
||||
-- GLOBALS: GetMinimapShape
|
||||
|
||||
--Create the new minimap tracking dropdown frame and initialize it
|
||||
local ElvUIMiniMapTrackingDropDown = CreateFrame('Frame', 'ElvUIMiniMapTrackingDropDown', _G.UIParent, 'UIDropDownMenuTemplate')
|
||||
ElvUIMiniMapTrackingDropDown:SetID(1)
|
||||
ElvUIMiniMapTrackingDropDown:SetClampedToScreen(true)
|
||||
ElvUIMiniMapTrackingDropDown:Hide()
|
||||
_G.UIDropDownMenu_Initialize(ElvUIMiniMapTrackingDropDown, _G.MiniMapTrackingDropDown_Initialize, 'MENU')
|
||||
ElvUIMiniMapTrackingDropDown.noResize = true
|
||||
|
||||
--Create the minimap micro menu
|
||||
local menuFrame = CreateFrame('Frame', 'MinimapRightClickMenu', E.UIParent, 'BackdropTemplate')
|
||||
local menuList = {
|
||||
{text = _G.CHARACTER_BUTTON,
|
||||
func = function() ToggleCharacter('PaperDollFrame') end},
|
||||
{text = _G.SPELLBOOK_ABILITIES_BUTTON,
|
||||
func = function()
|
||||
if not _G.SpellBookFrame:IsShown() then
|
||||
ShowUIPanel(_G.SpellBookFrame)
|
||||
else
|
||||
HideUIPanel(_G.SpellBookFrame)
|
||||
end
|
||||
end},
|
||||
{text = _G.TALENTS_BUTTON,
|
||||
func = function()
|
||||
if not _G.PlayerTalentFrame then
|
||||
_G.TalentFrame_LoadUI()
|
||||
end
|
||||
|
||||
local PlayerTalentFrame = _G.PlayerTalentFrame
|
||||
if not PlayerTalentFrame:IsShown() then
|
||||
ShowUIPanel(PlayerTalentFrame)
|
||||
else
|
||||
HideUIPanel(PlayerTalentFrame)
|
||||
end
|
||||
end},
|
||||
{text = _G.COLLECTIONS,
|
||||
func = ToggleCollectionsJournal},
|
||||
{text = _G.CHAT_CHANNELS,
|
||||
func = _G.ToggleChannelFrame},
|
||||
{text = _G.TIMEMANAGER_TITLE,
|
||||
func = function() ToggleFrame(_G.TimeManagerFrame) end},
|
||||
{text = _G.ACHIEVEMENT_BUTTON,
|
||||
func = ToggleAchievementFrame},
|
||||
{text = _G.SOCIAL_BUTTON,
|
||||
func = ToggleFriendsFrame},
|
||||
{text = L["Calendar"],
|
||||
func = function() _G.GameTimeFrame:Click() end},
|
||||
{text = _G.GARRISON_TYPE_8_0_LANDING_PAGE_TITLE,
|
||||
func = function() GarrisonLandingPageMinimapButton_OnClick(_G.GarrisonLandingPageMinimapButton) end},
|
||||
{text = _G.ACHIEVEMENTS_GUILD_TAB,
|
||||
func = ToggleGuildFrame},
|
||||
{text = _G.LFG_TITLE,
|
||||
func = ToggleLFDParentFrame},
|
||||
{text = _G.ENCOUNTER_JOURNAL,
|
||||
func = function()
|
||||
if not IsAddOnLoaded('Blizzard_EncounterJournal') then
|
||||
_G.EncounterJournal_LoadUI()
|
||||
end
|
||||
|
||||
ToggleFrame(_G.EncounterJournal)
|
||||
end},
|
||||
{text = _G.MAINMENU_BUTTON,
|
||||
func = function()
|
||||
if not _G.GameMenuFrame:IsShown() then
|
||||
if _G.VideoOptionsFrame:IsShown() then
|
||||
_G.VideoOptionsFrameCancel:Click()
|
||||
elseif _G.AudioOptionsFrame:IsShown() then
|
||||
_G.AudioOptionsFrameCancel:Click()
|
||||
elseif _G.InterfaceOptionsFrame:IsShown() then
|
||||
_G.InterfaceOptionsFrameCancel:Click()
|
||||
end
|
||||
|
||||
CloseMenus()
|
||||
CloseAllWindows()
|
||||
PlaySound(850) --IG_MAINMENU_OPEN
|
||||
ShowUIPanel(_G.GameMenuFrame)
|
||||
else
|
||||
PlaySound(854) --IG_MAINMENU_QUIT
|
||||
HideUIPanel(_G.GameMenuFrame)
|
||||
MainMenuMicroButton_SetNormal()
|
||||
end
|
||||
end}
|
||||
}
|
||||
|
||||
tinsert(menuList, {text = _G.BLIZZARD_STORE, func = function() _G.StoreMicroButton:Click() end})
|
||||
tinsert(menuList, {text = _G.HELP_BUTTON, func = ToggleHelpFrame})
|
||||
|
||||
function M:HandleGarrisonButton()
|
||||
local button = _G.GarrisonLandingPageMinimapButton
|
||||
if button then
|
||||
local db = E.db.general.minimap.icons.classHall
|
||||
local scale, pos = db.scale or 1, db.position or 'BOTTOMLEFT'
|
||||
button:ClearAllPoints()
|
||||
button:Point(pos, Minimap, pos, db.xOffset or 0, db.yOffset or 0)
|
||||
button:SetScale(scale)
|
||||
|
||||
local box = _G.GarrisonLandingPageTutorialBox
|
||||
if box then
|
||||
box:SetScale(1/scale)
|
||||
box:SetClampedToScreen(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:GetLocTextColor()
|
||||
local pvpType = GetZonePVPInfo()
|
||||
if pvpType == 'arena' then
|
||||
return 0.84, 0.03, 0.03
|
||||
elseif pvpType == 'friendly' then
|
||||
return 0.05, 0.85, 0.03
|
||||
elseif pvpType == 'contested' then
|
||||
return 0.9, 0.85, 0.05
|
||||
elseif pvpType == 'hostile' then
|
||||
return 0.84, 0.03, 0.03
|
||||
elseif pvpType == 'sanctuary' then
|
||||
return 0.035, 0.58, 0.84
|
||||
elseif pvpType == 'combat' then
|
||||
return 0.84, 0.03, 0.03
|
||||
else
|
||||
return 0.9, 0.85, 0.05
|
||||
end
|
||||
end
|
||||
|
||||
function M:SetupHybridMinimap()
|
||||
local MapCanvas = _G.HybridMinimap.MapCanvas
|
||||
MapCanvas:SetMaskTexture(E.Media.Textures.White8x8)
|
||||
MapCanvas:SetScript('OnMouseWheel', M.Minimap_OnMouseWheel)
|
||||
MapCanvas:SetScript('OnMouseDown', M.MapCanvas_OnMouseDown)
|
||||
MapCanvas:SetScript('OnMouseUp', E.noop)
|
||||
end
|
||||
|
||||
function M:ADDON_LOADED(_, addon)
|
||||
if addon == 'Blizzard_TimeManager' then
|
||||
_G.TimeManagerClockButton:Kill()
|
||||
elseif addon == 'Blizzard_FeedbackUI' then
|
||||
_G.FeedbackUIButton:Kill()
|
||||
elseif addon == 'Blizzard_HybridMinimap' then
|
||||
M:SetupHybridMinimap()
|
||||
end
|
||||
end
|
||||
|
||||
function M:Minimap_OnMouseDown(btn)
|
||||
_G.HideDropDownMenu(1, nil, ElvUIMiniMapTrackingDropDown)
|
||||
menuFrame:Hide()
|
||||
|
||||
local position = self:GetPoint()
|
||||
if btn == 'MiddleButton' or (btn == 'RightButton' and IsShiftKeyDown()) then
|
||||
if InCombatLockdown() then _G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT) return end
|
||||
if position:match('LEFT') then
|
||||
E:DropDown(menuList, menuFrame)
|
||||
else
|
||||
E:DropDown(menuList, menuFrame, -160, 0)
|
||||
end
|
||||
elseif btn == 'RightButton' then
|
||||
_G.ToggleDropDownMenu(1, nil, ElvUIMiniMapTrackingDropDown, 'cursor')
|
||||
else
|
||||
_G.Minimap_OnClick(self)
|
||||
end
|
||||
end
|
||||
|
||||
function M:MapCanvas_OnMouseDown(btn)
|
||||
_G.HideDropDownMenu(1, nil, ElvUIMiniMapTrackingDropDown)
|
||||
menuFrame:Hide()
|
||||
|
||||
local position = self:GetPoint()
|
||||
if btn == 'MiddleButton' or (btn == 'RightButton' and IsShiftKeyDown()) then
|
||||
if InCombatLockdown() then _G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT) return end
|
||||
if position:match('LEFT') then
|
||||
E:DropDown(menuList, menuFrame)
|
||||
else
|
||||
E:DropDown(menuList, menuFrame, -160, 0)
|
||||
end
|
||||
elseif btn == 'RightButton' then
|
||||
_G.ToggleDropDownMenu(1, nil, ElvUIMiniMapTrackingDropDown, 'cursor')
|
||||
end
|
||||
end
|
||||
|
||||
function M:Minimap_OnMouseWheel(d)
|
||||
if d > 0 then
|
||||
_G.MinimapZoomIn:Click()
|
||||
elseif d < 0 then
|
||||
_G.MinimapZoomOut:Click()
|
||||
end
|
||||
end
|
||||
|
||||
function M:Update_ZoneText()
|
||||
if E.db.general.minimap.locationText == 'HIDE' then return end
|
||||
Minimap.location:FontTemplate(LSM:Fetch('font', E.db.general.minimap.locationFont), E.db.general.minimap.locationFontSize, E.db.general.minimap.locationFontOutline)
|
||||
Minimap.location:SetText(utf8sub(GetMinimapZoneText(), 1, 46))
|
||||
Minimap.location:SetTextColor(M:GetLocTextColor())
|
||||
end
|
||||
|
||||
do
|
||||
local isResetting
|
||||
local function ResetZoom()
|
||||
Minimap:SetZoom(0)
|
||||
_G.MinimapZoomIn:Enable(); --Reset enabled state of buttons
|
||||
_G.MinimapZoomOut:Disable()
|
||||
isResetting = false
|
||||
end
|
||||
|
||||
local function SetupZoomReset()
|
||||
if E.db.general.minimap.resetZoom.enable and not isResetting then
|
||||
isResetting = true
|
||||
E:Delay(E.db.general.minimap.resetZoom.time, ResetZoom)
|
||||
end
|
||||
end
|
||||
hooksecurefunc(Minimap, 'SetZoom', SetupZoomReset)
|
||||
end
|
||||
|
||||
function M:UpdateSettings()
|
||||
if not E.private.general.minimap.enable then return end
|
||||
|
||||
E.MinimapSize = E.db.general.minimap.size or Minimap:GetWidth()
|
||||
|
||||
local MinimapPanel, MMHolder = _G.MinimapPanel, _G.MMHolder
|
||||
MinimapPanel:SetShown(E.db.datatexts.panels.MinimapPanel.enable)
|
||||
|
||||
local borderWidth, borderHeight = E.PixelMode and 2 or 6, E.PixelMode and 2 or 8
|
||||
local panelSize, joinPanel = (MinimapPanel:IsShown() and MinimapPanel:GetHeight()) or (E.PixelMode and 1 or -1), 1
|
||||
local height, width = E.MinimapSize + (panelSize - joinPanel), E.MinimapSize
|
||||
MMHolder:Size(width + borderWidth, height + borderHeight)
|
||||
_G.MinimapMover:Size(width + borderWidth, height + borderHeight)
|
||||
|
||||
local mmOffset = E.PixelMode and 1 or 3
|
||||
Minimap:ClearAllPoints()
|
||||
Minimap:Point('TOPRIGHT', MMHolder, 'TOPRIGHT', -mmOffset, -mmOffset)
|
||||
Minimap:Size(E.MinimapSize, E.MinimapSize)
|
||||
|
||||
Minimap.location:Width(E.MinimapSize)
|
||||
if E.db.general.minimap.locationText ~= 'SHOW' then
|
||||
Minimap.location:Hide()
|
||||
else
|
||||
Minimap.location:Show()
|
||||
end
|
||||
|
||||
M.HandleGarrisonButton()
|
||||
|
||||
local GameTimeFrame = _G.GameTimeFrame
|
||||
if GameTimeFrame then
|
||||
if E.private.general.minimap.hideCalendar then
|
||||
GameTimeFrame:Hide()
|
||||
else
|
||||
local pos = E.db.general.minimap.icons.calendar.position or 'TOPRIGHT'
|
||||
local scale = E.db.general.minimap.icons.calendar.scale or 1
|
||||
GameTimeFrame:ClearAllPoints()
|
||||
GameTimeFrame:Point(pos, Minimap, pos, E.db.general.minimap.icons.calendar.xOffset or 0, E.db.general.minimap.icons.calendar.yOffset or 0)
|
||||
GameTimeFrame:SetScale(scale)
|
||||
GameTimeFrame:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local MiniMapMailFrame = _G.MiniMapMailFrame
|
||||
if MiniMapMailFrame then
|
||||
local pos = E.db.general.minimap.icons.mail.position or 'TOPRIGHT'
|
||||
local scale = E.db.general.minimap.icons.mail.scale or 1
|
||||
MiniMapMailFrame:ClearAllPoints()
|
||||
MiniMapMailFrame:Point(pos, Minimap, pos, E.db.general.minimap.icons.mail.xOffset or 3, E.db.general.minimap.icons.mail.yOffset or 4)
|
||||
MiniMapMailFrame:SetScale(scale)
|
||||
end
|
||||
|
||||
local QueueStatusMinimapButton = _G.QueueStatusMinimapButton
|
||||
if QueueStatusMinimapButton then
|
||||
local pos = E.db.general.minimap.icons.lfgEye.position or 'BOTTOMRIGHT'
|
||||
local scale = E.db.general.minimap.icons.lfgEye.scale or 1
|
||||
QueueStatusMinimapButton:ClearAllPoints()
|
||||
QueueStatusMinimapButton:Point(pos, Minimap, pos, E.db.general.minimap.icons.lfgEye.xOffset or 3, E.db.general.minimap.icons.lfgEye.yOffset or 0)
|
||||
QueueStatusMinimapButton:SetScale(scale)
|
||||
_G.QueueStatusFrame:SetScale(scale)
|
||||
end
|
||||
|
||||
local MiniMapInstanceDifficulty = _G.MiniMapInstanceDifficulty
|
||||
local GuildInstanceDifficulty = _G.GuildInstanceDifficulty
|
||||
if MiniMapInstanceDifficulty and GuildInstanceDifficulty then
|
||||
local pos = E.db.general.minimap.icons.difficulty.position or 'TOPLEFT'
|
||||
local scale = E.db.general.minimap.icons.difficulty.scale or 1
|
||||
local x = E.db.general.minimap.icons.difficulty.xOffset or 0
|
||||
local y = E.db.general.minimap.icons.difficulty.yOffset or 0
|
||||
MiniMapInstanceDifficulty:ClearAllPoints()
|
||||
MiniMapInstanceDifficulty:Point(pos, Minimap, pos, x, y)
|
||||
MiniMapInstanceDifficulty:SetScale(scale)
|
||||
GuildInstanceDifficulty:ClearAllPoints()
|
||||
GuildInstanceDifficulty:Point(pos, Minimap, pos, x, y)
|
||||
GuildInstanceDifficulty:SetScale(scale)
|
||||
end
|
||||
|
||||
local MiniMapChallengeMode = _G.MiniMapChallengeMode
|
||||
if MiniMapChallengeMode then
|
||||
local pos = E.db.general.minimap.icons.challengeMode.position or 'TOPLEFT'
|
||||
local scale = E.db.general.minimap.icons.challengeMode.scale or 1
|
||||
MiniMapChallengeMode:ClearAllPoints()
|
||||
MiniMapChallengeMode:Point(pos, Minimap, pos, E.db.general.minimap.icons.challengeMode.xOffset or 8, E.db.general.minimap.icons.challengeMode.yOffset or -8)
|
||||
MiniMapChallengeMode:SetScale(scale)
|
||||
end
|
||||
end
|
||||
|
||||
local function MinimapPostDrag()
|
||||
_G.MinimapBackdrop:ClearAllPoints()
|
||||
_G.MinimapBackdrop:SetAllPoints(_G.Minimap)
|
||||
end
|
||||
|
||||
function M:GetMinimapShape()
|
||||
return 'SQUARE'
|
||||
end
|
||||
|
||||
function M:SetGetMinimapShape()
|
||||
GetMinimapShape = M.GetMinimapShape --This is just to support for other mods
|
||||
Minimap:Size(E.db.general.minimap.size, E.db.general.minimap.size)
|
||||
end
|
||||
|
||||
function M:Initialize()
|
||||
if not E.private.general.minimap.enable then return end
|
||||
self.Initialized = true
|
||||
|
||||
menuFrame:SetTemplate('Transparent')
|
||||
|
||||
local mmholder = CreateFrame('Frame', 'MMHolder', Minimap)
|
||||
mmholder:Point('TOPRIGHT', E.UIParent, 'TOPRIGHT', -3, -3)
|
||||
mmholder:Size(Minimap:GetSize())
|
||||
|
||||
Minimap:SetQuestBlobRingAlpha(0)
|
||||
Minimap:SetArchBlobRingAlpha(0)
|
||||
Minimap:CreateBackdrop()
|
||||
Minimap:SetFrameLevel(Minimap:GetFrameLevel() + 2)
|
||||
Minimap:ClearAllPoints()
|
||||
Minimap:Point('TOPRIGHT', mmholder, 'TOPRIGHT', -E.Border, -E.Border)
|
||||
Minimap:HookScript('OnEnter', function(mm) if E.db.general.minimap.locationText == 'MOUSEOVER' then mm.location:Show() end end)
|
||||
Minimap:HookScript('OnLeave', function(mm) if E.db.general.minimap.locationText == 'MOUSEOVER' then mm.location:Hide() end end)
|
||||
|
||||
Minimap.location = Minimap:CreateFontString(nil, 'OVERLAY')
|
||||
Minimap.location:FontTemplate(nil, nil, 'OUTLINE')
|
||||
Minimap.location:Point('TOP', Minimap, 'TOP', 0, -2)
|
||||
Minimap.location:SetJustifyH('CENTER')
|
||||
Minimap.location:SetJustifyV('MIDDLE')
|
||||
if E.db.general.minimap.locationText ~= 'SHOW' then
|
||||
Minimap.location:Hide()
|
||||
end
|
||||
|
||||
local frames = {
|
||||
_G.MinimapBorder,
|
||||
_G.MinimapBorderTop,
|
||||
_G.MinimapZoomIn,
|
||||
_G.MinimapZoomOut,
|
||||
_G.MinimapNorthTag,
|
||||
_G.MinimapZoneTextButton,
|
||||
_G.MiniMapTracking,
|
||||
_G.MiniMapMailBorder
|
||||
}
|
||||
|
||||
for _, frame in pairs(frames) do
|
||||
frame:Kill()
|
||||
end
|
||||
|
||||
_G.MiniMapMailIcon:SetTexture(E.Media.Textures.Mail)
|
||||
|
||||
-- Every GarrisonLandingPageMinimapButton_UpdateIcon() call reanchor the button
|
||||
hooksecurefunc('GarrisonLandingPageMinimapButton_UpdateIcon', M.HandleGarrisonButton)
|
||||
|
||||
--Hide the BlopRing on Minimap
|
||||
Minimap:SetArchBlobRingScalar(0)
|
||||
Minimap:SetQuestBlobRingScalar(0)
|
||||
|
||||
if E.private.general.minimap.hideClassHallReport then
|
||||
_G.GarrisonLandingPageMinimapButton:Kill()
|
||||
_G.GarrisonLandingPageMinimapButton.IsShown = function() return true end
|
||||
end
|
||||
|
||||
_G.QueueStatusMinimapButtonBorder:Hide()
|
||||
_G.QueueStatusFrame:SetClampedToScreen(true)
|
||||
_G.MiniMapWorldMapButton:Hide()
|
||||
_G.MiniMapInstanceDifficulty:SetParent(Minimap)
|
||||
_G.GuildInstanceDifficulty:SetParent(Minimap)
|
||||
_G.MiniMapChallengeMode:SetParent(Minimap)
|
||||
|
||||
if _G.TimeManagerClockButton then _G.TimeManagerClockButton:Kill() end
|
||||
if _G.FeedbackUIButton then _G.FeedbackUIButton:Kill() end
|
||||
if _G.HybridMinimap then M:SetupHybridMinimap() end
|
||||
|
||||
E:CreateMover(_G.MMHolder, 'MinimapMover', L["Minimap"], nil, nil, MinimapPostDrag, nil, nil, 'maps,minimap')
|
||||
|
||||
_G.MinimapCluster:EnableMouse(false)
|
||||
Minimap:EnableMouseWheel(true)
|
||||
Minimap:SetScript('OnMouseWheel', M.Minimap_OnMouseWheel)
|
||||
Minimap:SetScript('OnMouseDown', M.Minimap_OnMouseDown)
|
||||
Minimap:SetScript('OnMouseUp', E.noop)
|
||||
|
||||
self:RegisterEvent('PLAYER_ENTERING_WORLD', 'Update_ZoneText')
|
||||
self:RegisterEvent('ZONE_CHANGED_NEW_AREA', 'Update_ZoneText')
|
||||
self:RegisterEvent('ZONE_CHANGED_INDOORS', 'Update_ZoneText')
|
||||
self:RegisterEvent('ZONE_CHANGED', 'Update_ZoneText')
|
||||
self:RegisterEvent('ADDON_LOADED')
|
||||
self:UpdateSettings()
|
||||
end
|
||||
|
||||
E:RegisterModule(M:GetName())
|
||||
264
Modules/Maps/Worldmap.lua
Normal file
264
Modules/Maps/Worldmap.lua
Normal file
@@ -0,0 +1,264 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local M = E:GetModule('WorldMap')
|
||||
|
||||
local _G = _G
|
||||
local strfind = strfind
|
||||
local CreateFrame = CreateFrame
|
||||
local SetUIPanelAttribute = SetUIPanelAttribute
|
||||
local MOUSE_LABEL = MOUSE_LABEL:gsub('|[TA].-|[ta]','')
|
||||
local PLAYER = PLAYER
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local IsPlayerMoving = IsPlayerMoving
|
||||
local PlayerMovementFrameFader = PlayerMovementFrameFader
|
||||
-- GLOBALS: CoordsHolder
|
||||
|
||||
local INVERTED_POINTS = {
|
||||
TOPLEFT = 'BOTTOMLEFT',
|
||||
TOPRIGHT = 'BOTTOMRIGHT',
|
||||
BOTTOMLEFT = 'TOPLEFT',
|
||||
BOTTOMRIGHT = 'TOPRIGHT',
|
||||
TOP = 'BOTTOM',
|
||||
BOTTOM = 'TOP',
|
||||
}
|
||||
|
||||
-- this will be updated later
|
||||
local smallerMapScale = 0.8
|
||||
|
||||
function M:SetLargeWorldMap()
|
||||
local WorldMapFrame = _G.WorldMapFrame
|
||||
WorldMapFrame:SetParent(E.UIParent)
|
||||
WorldMapFrame:SetScale(1)
|
||||
WorldMapFrame.ScrollContainer.Child:SetScale(smallerMapScale)
|
||||
|
||||
if WorldMapFrame:GetAttribute('UIPanelLayout-area') ~= 'center' then
|
||||
SetUIPanelAttribute(WorldMapFrame, 'area', 'center');
|
||||
end
|
||||
|
||||
if WorldMapFrame:GetAttribute('UIPanelLayout-allowOtherPanels') ~= true then
|
||||
SetUIPanelAttribute(WorldMapFrame, 'allowOtherPanels', true)
|
||||
end
|
||||
|
||||
WorldMapFrame:OnFrameSizeChanged()
|
||||
if WorldMapFrame:GetMapID() then
|
||||
WorldMapFrame.NavBar:Refresh()
|
||||
end
|
||||
end
|
||||
|
||||
function M:UpdateMaximizedSize()
|
||||
local WorldMapFrame = _G.WorldMapFrame
|
||||
local width, height = WorldMapFrame:GetSize()
|
||||
local magicNumber = (1 - smallerMapScale) * 100
|
||||
WorldMapFrame:Size((width * smallerMapScale) - (magicNumber + 2), (height * smallerMapScale) - 2)
|
||||
end
|
||||
|
||||
function M:SynchronizeDisplayState()
|
||||
local WorldMapFrame = _G.WorldMapFrame
|
||||
if WorldMapFrame:IsMaximized() then
|
||||
WorldMapFrame:ClearAllPoints()
|
||||
WorldMapFrame:Point('CENTER', E.UIParent)
|
||||
end
|
||||
end
|
||||
|
||||
function M:SetSmallWorldMap()
|
||||
local WorldMapFrame = _G.WorldMapFrame
|
||||
if not WorldMapFrame:IsMaximized() then
|
||||
WorldMapFrame:ClearAllPoints()
|
||||
WorldMapFrame:Point('TOPLEFT', E.UIParent, 'TOPLEFT', 16, -94)
|
||||
end
|
||||
end
|
||||
|
||||
local inRestrictedArea = false
|
||||
function M:UpdateRestrictedArea()
|
||||
if E.MapInfo.x and E.MapInfo.y then
|
||||
inRestrictedArea = false
|
||||
else
|
||||
inRestrictedArea = true
|
||||
CoordsHolder.playerCoords:SetFormattedText('%s: %s', PLAYER, 'N/A')
|
||||
end
|
||||
end
|
||||
|
||||
function M:UpdateCoords(OnShow)
|
||||
local WorldMapFrame = _G.WorldMapFrame
|
||||
if not WorldMapFrame:IsShown() then return end
|
||||
|
||||
if WorldMapFrame.ScrollContainer:IsMouseOver() then
|
||||
local x, y = WorldMapFrame.ScrollContainer:GetNormalizedCursorPosition()
|
||||
if x and y and x >= 0 and y >= 0 then
|
||||
CoordsHolder.mouseCoords:SetFormattedText('%s: %.2f, %.2f', MOUSE_LABEL, x * 100, y * 100)
|
||||
else
|
||||
CoordsHolder.mouseCoords:SetText('')
|
||||
end
|
||||
else
|
||||
CoordsHolder.mouseCoords:SetText('')
|
||||
end
|
||||
|
||||
if not inRestrictedArea and (OnShow or E.MapInfo.coordsWatching) then
|
||||
if E.MapInfo.x and E.MapInfo.y then
|
||||
CoordsHolder.playerCoords:SetFormattedText('%s: %.2f, %.2f', PLAYER, (E.MapInfo.xText or 0), (E.MapInfo.yText or 0))
|
||||
else
|
||||
CoordsHolder.playerCoords:SetFormattedText('%s: %s', PLAYER, 'N/A')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:PositionCoords()
|
||||
local db = E.global.general.WorldMapCoordinates
|
||||
local position = db.position
|
||||
local xOffset = db.xOffset
|
||||
local yOffset = db.yOffset
|
||||
|
||||
local x, y = 5, 5
|
||||
if strfind(position, 'RIGHT') then x = -5 end
|
||||
if strfind(position, 'TOP') then y = -5 end
|
||||
|
||||
CoordsHolder.playerCoords:ClearAllPoints()
|
||||
CoordsHolder.playerCoords:Point(position, _G.WorldMapFrame.BorderFrame, position, x + xOffset, y + yOffset)
|
||||
CoordsHolder.mouseCoords:ClearAllPoints()
|
||||
CoordsHolder.mouseCoords:Point(position, CoordsHolder.playerCoords, INVERTED_POINTS[position], 0, y)
|
||||
end
|
||||
|
||||
function M:MapShouldFade()
|
||||
-- normally we would check GetCVarBool('mapFade') here instead of the setting
|
||||
return E.global.general.fadeMapWhenMoving and not _G.WorldMapFrame:IsMouseOver()
|
||||
end
|
||||
|
||||
function M:MapFadeOnUpdate(elapsed)
|
||||
self.elapsed = (self.elapsed or 0) + elapsed
|
||||
if self.elapsed > 0.1 then
|
||||
self.elapsed = 0
|
||||
|
||||
local object = self.FadeObject
|
||||
local settings = object and object.FadeSettings
|
||||
if not settings then return end
|
||||
|
||||
local fadeOut = IsPlayerMoving() and (not settings.fadePredicate or settings.fadePredicate())
|
||||
local endAlpha = (fadeOut and (settings.minAlpha or 0.5)) or settings.maxAlpha or 1
|
||||
local startAlpha = _G.WorldMapFrame:GetAlpha()
|
||||
|
||||
object.timeToFade = settings.durationSec or 0.5
|
||||
object.startAlpha = startAlpha
|
||||
object.endAlpha = endAlpha
|
||||
object.diffAlpha = endAlpha - startAlpha
|
||||
|
||||
if object.fadeTimer then
|
||||
object.fadeTimer = nil
|
||||
end
|
||||
|
||||
E:UIFrameFade(_G.WorldMapFrame, object)
|
||||
end
|
||||
end
|
||||
|
||||
local fadeFrame
|
||||
function M:StopMapFromFading()
|
||||
if fadeFrame then
|
||||
fadeFrame:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function M:EnableMapFading(frame)
|
||||
if not fadeFrame then
|
||||
fadeFrame = CreateFrame('FRAME')
|
||||
fadeFrame:SetScript('OnUpdate', M.MapFadeOnUpdate)
|
||||
frame:HookScript('OnHide', M.StopMapFromFading)
|
||||
end
|
||||
|
||||
if not fadeFrame.FadeObject then fadeFrame.FadeObject = {} end
|
||||
if not fadeFrame.FadeObject.FadeSettings then fadeFrame.FadeObject.FadeSettings = {} end
|
||||
|
||||
local settings = fadeFrame.FadeObject.FadeSettings
|
||||
settings.fadePredicate = M.MapShouldFade
|
||||
settings.durationSec = E.global.general.fadeMapDuration
|
||||
settings.minAlpha = E.global.general.mapAlphaWhenMoving
|
||||
settings.maxAlpha = 1
|
||||
|
||||
fadeFrame:Show()
|
||||
end
|
||||
|
||||
function M:UpdateMapFade(minAlpha, maxAlpha, durationSec, fadePredicate) -- self is frame
|
||||
if self:IsShown() and (self == _G.WorldMapFrame and fadePredicate ~= M.MapShouldFade) then
|
||||
-- blizzard spams code in OnUpdate and doesnt finish their functions, so we shut their fader down :L
|
||||
PlayerMovementFrameFader.RemoveFrame(self)
|
||||
|
||||
-- replacement function which is complete :3
|
||||
if E.global.general.fadeMapWhenMoving then
|
||||
M:EnableMapFading(self)
|
||||
end
|
||||
|
||||
-- we can't use the blizzard function because `durationSec` was never finished being implimented?
|
||||
-- PlayerMovementFrameFader.AddDeferredFrame(self, E.global.general.mapAlphaWhenMoving, 1, E.global.general.fadeMapDuration, M.MapShouldFade)
|
||||
end
|
||||
end
|
||||
|
||||
function M:Initialize()
|
||||
self.Initialized = true
|
||||
|
||||
if not E.private.general.worldMap then
|
||||
return
|
||||
end
|
||||
|
||||
local WorldMapFrame = _G.WorldMapFrame
|
||||
if E.global.general.WorldMapCoordinates.enable then
|
||||
local CoordsHolder = CreateFrame('Frame', 'CoordsHolder', WorldMapFrame)
|
||||
CoordsHolder:SetFrameLevel(WorldMapFrame.BorderFrame:GetFrameLevel() + 10)
|
||||
CoordsHolder:SetFrameStrata(WorldMapFrame.BorderFrame:GetFrameStrata())
|
||||
CoordsHolder.playerCoords = CoordsHolder:CreateFontString(nil, 'OVERLAY')
|
||||
CoordsHolder.mouseCoords = CoordsHolder:CreateFontString(nil, 'OVERLAY')
|
||||
CoordsHolder.playerCoords:SetTextColor(1, 1 ,0)
|
||||
CoordsHolder.mouseCoords:SetTextColor(1, 1 ,0)
|
||||
CoordsHolder.playerCoords:SetFontObject(_G.NumberFontNormal)
|
||||
CoordsHolder.mouseCoords:SetFontObject(_G.NumberFontNormal)
|
||||
CoordsHolder.playerCoords:SetText(PLAYER..': 0, 0')
|
||||
CoordsHolder.mouseCoords:SetText(MOUSE_LABEL..': 0, 0')
|
||||
|
||||
WorldMapFrame:HookScript('OnShow', function()
|
||||
if not M.CoordsTimer then
|
||||
M:UpdateCoords(true)
|
||||
M.CoordsTimer = M:ScheduleRepeatingTimer('UpdateCoords', 0.1)
|
||||
end
|
||||
end)
|
||||
WorldMapFrame:HookScript('OnHide', function()
|
||||
M:CancelTimer(M.CoordsTimer)
|
||||
M.CoordsTimer = nil
|
||||
end)
|
||||
|
||||
M:PositionCoords()
|
||||
|
||||
E:RegisterEventForObject('LOADING_SCREEN_DISABLED', E.MapInfo, M.UpdateRestrictedArea)
|
||||
E:RegisterEventForObject('ZONE_CHANGED_NEW_AREA', E.MapInfo, M.UpdateRestrictedArea)
|
||||
E:RegisterEventForObject('ZONE_CHANGED_INDOORS', E.MapInfo, M.UpdateRestrictedArea)
|
||||
E:RegisterEventForObject('ZONE_CHANGED', E.MapInfo, M.UpdateRestrictedArea)
|
||||
end
|
||||
|
||||
if E.global.general.smallerWorldMap then
|
||||
smallerMapScale = E.global.general.smallerWorldMapScale
|
||||
|
||||
WorldMapFrame.BlackoutFrame.Blackout:SetTexture()
|
||||
WorldMapFrame.BlackoutFrame:EnableMouse(false)
|
||||
|
||||
self:SecureHook(WorldMapFrame, 'Maximize', 'SetLargeWorldMap')
|
||||
self:SecureHook(WorldMapFrame, 'Minimize', 'SetSmallWorldMap')
|
||||
self:SecureHook(WorldMapFrame, 'SynchronizeDisplayState')
|
||||
self:SecureHook(WorldMapFrame, 'UpdateMaximizedSize')
|
||||
|
||||
self:SecureHookScript(WorldMapFrame, 'OnShow', function()
|
||||
if WorldMapFrame:IsMaximized() then
|
||||
WorldMapFrame:UpdateMaximizedSize()
|
||||
self:SetLargeWorldMap()
|
||||
else
|
||||
self:SetSmallWorldMap()
|
||||
end
|
||||
|
||||
M:Unhook(WorldMapFrame, 'OnShow', nil)
|
||||
end)
|
||||
end
|
||||
|
||||
-- This lets us control the maps fading function
|
||||
hooksecurefunc(PlayerMovementFrameFader, 'AddDeferredFrame', M.UpdateMapFade)
|
||||
|
||||
-- Enable/Disable map fading when moving
|
||||
-- currently we dont need to touch this cvar because we have our own control for this currently
|
||||
-- see the comment in `M:UpdateMapFade` about `durationSec` for more information
|
||||
-- SetCVar('mapFade', E.global.general.fadeMapWhenMoving and 1 or 0)
|
||||
end
|
||||
|
||||
E:RegisterInitialModule(M:GetName())
|
||||
346
Modules/Misc/AFK.lua
Normal file
346
Modules/Misc/AFK.lua
Normal file
@@ -0,0 +1,346 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local AFK = E:GetModule('AFK')
|
||||
local CH = E:GetModule('Chat')
|
||||
|
||||
local _G = _G
|
||||
local floor = floor
|
||||
local unpack = unpack
|
||||
local tostring, pcall = tostring, pcall
|
||||
local format, strsub, gsub = format, strsub, gsub
|
||||
|
||||
local Chat_GetChatCategory = Chat_GetChatCategory
|
||||
local ChatFrame_GetMobileEmbeddedTexture = ChatFrame_GetMobileEmbeddedTexture
|
||||
local ChatHistory_GetAccessID = ChatHistory_GetAccessID
|
||||
local CloseAllWindows = CloseAllWindows
|
||||
local CreateFrame = CreateFrame
|
||||
local GetBattlefieldStatus = GetBattlefieldStatus
|
||||
local GetGuildInfo = GetGuildInfo
|
||||
local GetScreenHeight = GetScreenHeight
|
||||
local GetScreenWidth = GetScreenWidth
|
||||
local GetTime = GetTime
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local IsInGuild = IsInGuild
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local MoveViewLeftStart = MoveViewLeftStart
|
||||
local MoveViewLeftStop = MoveViewLeftStop
|
||||
local PVEFrame_ToggleFrame = PVEFrame_ToggleFrame
|
||||
local RemoveExtraSpaces = RemoveExtraSpaces
|
||||
local Screenshot = Screenshot
|
||||
local SetCVar = SetCVar
|
||||
local UnitCastingInfo = UnitCastingInfo
|
||||
local UnitIsAFK = UnitIsAFK
|
||||
local CinematicFrame = CinematicFrame
|
||||
local MovieFrame = MovieFrame
|
||||
local C_PetBattles_IsInBattle = C_PetBattles.IsInBattle
|
||||
local DNDstr = _G.DND
|
||||
local AFKstr = _G.AFK
|
||||
|
||||
local CAMERA_SPEED = 0.035
|
||||
local ignoreKeys = {
|
||||
LALT = true,
|
||||
LSHIFT = true,
|
||||
RSHIFT = true,
|
||||
}
|
||||
local printKeys = {
|
||||
PRINTSCREEN = true,
|
||||
}
|
||||
|
||||
if IsMacClient() then
|
||||
printKeys[_G.KEY_PRINTSCREEN_MAC] = true
|
||||
end
|
||||
|
||||
function AFK:UpdateTimer()
|
||||
local time = GetTime() - self.startTime
|
||||
AFK.AFKMode.bottom.time:SetFormattedText('%02d:%02d', floor(time/60), time % 60)
|
||||
end
|
||||
|
||||
function AFK:SetAFK(status)
|
||||
if status then
|
||||
MoveViewLeftStart(CAMERA_SPEED)
|
||||
AFK.AFKMode:Show()
|
||||
CloseAllWindows()
|
||||
_G.UIParent:Hide()
|
||||
|
||||
if IsInGuild() then
|
||||
local guildName, guildRankName = GetGuildInfo('player')
|
||||
AFK.AFKMode.bottom.guild:SetFormattedText('%s-%s', guildName, guildRankName)
|
||||
else
|
||||
AFK.AFKMode.bottom.guild:SetText(L["No Guild"])
|
||||
end
|
||||
|
||||
AFK.AFKMode.bottom.LogoTop:SetVertexColor(unpack(E.media.rgbvaluecolor))
|
||||
AFK.AFKMode.bottom.model.curAnimation = 'wave'
|
||||
AFK.AFKMode.bottom.model.startTime = GetTime()
|
||||
AFK.AFKMode.bottom.model.duration = 2.3
|
||||
AFK.AFKMode.bottom.model:SetUnit('player')
|
||||
AFK.AFKMode.bottom.model.isIdle = nil
|
||||
AFK.AFKMode.bottom.model:SetAnimation(67)
|
||||
AFK.AFKMode.bottom.model.idleDuration = 40
|
||||
AFK.startTime = GetTime()
|
||||
AFK.timer = AFK:ScheduleRepeatingTimer('UpdateTimer', 1)
|
||||
|
||||
AFK.AFKMode.chat:RegisterEvent('CHAT_MSG_WHISPER')
|
||||
AFK.AFKMode.chat:RegisterEvent('CHAT_MSG_BN_WHISPER')
|
||||
AFK.AFKMode.chat:RegisterEvent('CHAT_MSG_GUILD')
|
||||
|
||||
AFK.isAFK = true
|
||||
elseif AFK.isAFK then
|
||||
_G.UIParent:Show()
|
||||
AFK.AFKMode:Hide()
|
||||
MoveViewLeftStop()
|
||||
|
||||
AFK:CancelTimer(AFK.timer)
|
||||
AFK:CancelTimer(AFK.animTimer)
|
||||
AFK.AFKMode.bottom.time:SetText('00:00')
|
||||
|
||||
AFK.AFKMode.chat:UnregisterAllEvents()
|
||||
AFK.AFKMode.chat:Clear()
|
||||
|
||||
if _G.PVEFrame:IsShown() then --odd bug, frame is blank
|
||||
PVEFrame_ToggleFrame()
|
||||
PVEFrame_ToggleFrame()
|
||||
end
|
||||
|
||||
AFK.isAFK = false
|
||||
end
|
||||
end
|
||||
|
||||
function AFK:OnEvent(event, ...)
|
||||
if event == 'PLAYER_REGEN_DISABLED' or event == 'LFG_PROPOSAL_SHOW' or event == 'UPDATE_BATTLEFIELD_STATUS' then
|
||||
if event ~= 'UPDATE_BATTLEFIELD_STATUS' or (GetBattlefieldStatus(...) == 'confirm') then
|
||||
AFK:SetAFK(false)
|
||||
end
|
||||
|
||||
if event == 'PLAYER_REGEN_DISABLED' then
|
||||
AFK:RegisterEvent('PLAYER_REGEN_ENABLED', 'OnEvent')
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if event == 'PLAYER_REGEN_ENABLED' then
|
||||
AFK:UnregisterEvent('PLAYER_REGEN_ENABLED')
|
||||
end
|
||||
|
||||
if not E.db.general.afk or (InCombatLockdown() or CinematicFrame:IsShown() or MovieFrame:IsShown()) then return end
|
||||
|
||||
if UnitCastingInfo('player') then --Don't activate afk if player is crafting stuff, check back in 30 seconds
|
||||
AFK:ScheduleTimer('OnEvent', 30)
|
||||
return
|
||||
end
|
||||
|
||||
AFK:SetAFK(UnitIsAFK('player') and not C_PetBattles_IsInBattle())
|
||||
end
|
||||
|
||||
function AFK:Toggle()
|
||||
if E.db.general.afk then
|
||||
AFK:RegisterEvent('PLAYER_FLAGS_CHANGED', 'OnEvent')
|
||||
AFK:RegisterEvent('PLAYER_REGEN_DISABLED', 'OnEvent')
|
||||
AFK:RegisterEvent('LFG_PROPOSAL_SHOW', 'OnEvent')
|
||||
AFK:RegisterEvent('UPDATE_BATTLEFIELD_STATUS', 'OnEvent')
|
||||
SetCVar('autoClearAFK', '1')
|
||||
else
|
||||
AFK:UnregisterEvent('PLAYER_FLAGS_CHANGED')
|
||||
AFK:UnregisterEvent('PLAYER_REGEN_DISABLED')
|
||||
AFK:UnregisterEvent('LFG_PROPOSAL_SHOW')
|
||||
AFK:UnregisterEvent('UPDATE_BATTLEFIELD_STATUS')
|
||||
end
|
||||
end
|
||||
|
||||
local function OnKeyDown(_, key)
|
||||
if ignoreKeys[key] then return end
|
||||
|
||||
if printKeys[key] then
|
||||
Screenshot()
|
||||
else
|
||||
AFK:SetAFK(false)
|
||||
AFK:ScheduleTimer('OnEvent', 60)
|
||||
end
|
||||
end
|
||||
|
||||
local function Chat_OnMouseWheel(self, delta)
|
||||
if delta == 1 then
|
||||
if IsShiftKeyDown() then
|
||||
self:ScrollToTop()
|
||||
else
|
||||
self:ScrollUp()
|
||||
end
|
||||
elseif delta == -1 then
|
||||
if IsShiftKeyDown() then
|
||||
self:ScrollToBottom()
|
||||
else
|
||||
self:ScrollDown()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function Chat_OnEvent(self, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)
|
||||
local type = strsub(event, 10)
|
||||
local info = _G.ChatTypeInfo[type]
|
||||
|
||||
local coloredName
|
||||
if event == 'CHAT_MSG_BN_WHISPER' then
|
||||
coloredName = CH:GetBNFriendColor(arg2, arg13)
|
||||
else
|
||||
coloredName = CH:GetColoredName(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)
|
||||
end
|
||||
|
||||
arg1 = RemoveExtraSpaces(arg1)
|
||||
|
||||
local chatTarget, body
|
||||
local chatGroup = Chat_GetChatCategory(type)
|
||||
if chatGroup == 'BN_CONVERSATION' then
|
||||
chatTarget = tostring(arg8)
|
||||
elseif chatGroup == 'WHISPER' or chatGroup == 'BN_WHISPER' then
|
||||
if not(strsub(arg2, 1, 2) == '|K') then
|
||||
chatTarget = arg2:upper()
|
||||
else
|
||||
chatTarget = arg2
|
||||
end
|
||||
end
|
||||
|
||||
local playerLink
|
||||
if type ~= 'BN_WHISPER' and type ~= 'BN_CONVERSATION' then
|
||||
playerLink = '|Hplayer:'..arg2..':'..arg11..':'..chatGroup..(chatTarget and ':'..chatTarget or '')..'|h'
|
||||
else
|
||||
playerLink = '|HBNplayer:'..arg2..':'..arg13..':'..arg11..':'..chatGroup..(chatTarget and ':'..chatTarget or '')..'|h'
|
||||
end
|
||||
|
||||
local message = arg1
|
||||
if arg14 then --isMobile
|
||||
message = ChatFrame_GetMobileEmbeddedTexture(info.r, info.g, info.b)..message
|
||||
end
|
||||
|
||||
--Escape any % characters, as it may otherwise cause an 'invalid option in format' error in the next step
|
||||
message = gsub(message, '%%', '%%%%')
|
||||
|
||||
local success
|
||||
success, body = pcall(format, _G['CHAT_'..type..'_GET']..message, playerLink..'['..coloredName..']'..'|h')
|
||||
if not success then
|
||||
E:Print('An error happened in the AFK Chat module. Please screenshot this message and report it. Info:', type, message, _G['CHAT_'..type..'_GET'])
|
||||
end
|
||||
|
||||
local accessID = ChatHistory_GetAccessID(chatGroup, chatTarget)
|
||||
local typeID = ChatHistory_GetAccessID(type, chatTarget, arg12 == '' and arg13 or arg12)
|
||||
if CH.db.shortChannels then
|
||||
body = body:gsub('|Hchannel:(.-)|h%[(.-)%]|h', CH.ShortChannel)
|
||||
body = body:gsub('^(.-|h) '..L["whispers"], '%1')
|
||||
body = body:gsub('<'..AFKstr..'>', '[|cffFF0000'..L["AFK"]..'|r] ')
|
||||
body = body:gsub('<'..DNDstr..'>', '[|cffE7E716'..L["DND"]..'|r] ')
|
||||
body = body:gsub('%[BN_CONVERSATION:', '%['..'')
|
||||
end
|
||||
|
||||
self:AddMessage(body, info.r, info.g, info.b, info.id, false, accessID, typeID)
|
||||
end
|
||||
|
||||
function AFK:LoopAnimations()
|
||||
local ElvUIAFKPlayerModel = _G.ElvUIAFKPlayerModel
|
||||
if ElvUIAFKPlayerModel.curAnimation == 'wave' then
|
||||
ElvUIAFKPlayerModel:SetAnimation(69)
|
||||
ElvUIAFKPlayerModel.curAnimation = 'dance'
|
||||
ElvUIAFKPlayerModel.startTime = GetTime()
|
||||
ElvUIAFKPlayerModel.duration = 300
|
||||
ElvUIAFKPlayerModel.isIdle = false
|
||||
ElvUIAFKPlayerModel.idleDuration = 120
|
||||
end
|
||||
end
|
||||
|
||||
function AFK:Initialize()
|
||||
AFK.Initialized = true
|
||||
|
||||
AFK.AFKMode = CreateFrame('Frame', 'ElvUIAFKFrame')
|
||||
AFK.AFKMode:SetFrameLevel(1)
|
||||
AFK.AFKMode:SetScale(_G.UIParent:GetScale())
|
||||
AFK.AFKMode:SetAllPoints(_G.UIParent)
|
||||
AFK.AFKMode:Hide()
|
||||
AFK.AFKMode:EnableKeyboard(true)
|
||||
AFK.AFKMode:SetScript('OnKeyDown', OnKeyDown)
|
||||
|
||||
AFK.AFKMode.chat = CreateFrame('ScrollingMessageFrame', nil, AFK.AFKMode)
|
||||
AFK.AFKMode.chat:Size(500, 200)
|
||||
AFK.AFKMode.chat:Point('TOPLEFT', AFK.AFKMode, 'TOPLEFT', 4, -4)
|
||||
AFK.AFKMode.chat:FontTemplate()
|
||||
AFK.AFKMode.chat:SetJustifyH('LEFT')
|
||||
AFK.AFKMode.chat:SetMaxLines(500)
|
||||
AFK.AFKMode.chat:EnableMouseWheel(true)
|
||||
AFK.AFKMode.chat:SetFading(false)
|
||||
AFK.AFKMode.chat:SetMovable(true)
|
||||
AFK.AFKMode.chat:EnableMouse(true)
|
||||
AFK.AFKMode.chat:RegisterForDrag('LeftButton')
|
||||
AFK.AFKMode.chat:SetScript('OnDragStart', AFK.AFKMode.chat.StartMoving)
|
||||
AFK.AFKMode.chat:SetScript('OnDragStop', AFK.AFKMode.chat.StopMovingOrSizing)
|
||||
AFK.AFKMode.chat:SetScript('OnMouseWheel', Chat_OnMouseWheel)
|
||||
AFK.AFKMode.chat:SetScript('OnEvent', Chat_OnEvent)
|
||||
|
||||
AFK.AFKMode.bottom = CreateFrame('Frame', nil, AFK.AFKMode, 'BackdropTemplate')
|
||||
AFK.AFKMode.bottom:SetFrameLevel(0)
|
||||
AFK.AFKMode.bottom:SetTemplate('Transparent')
|
||||
AFK.AFKMode.bottom:Point('BOTTOM', AFK.AFKMode, 'BOTTOM', 0, -E.Border)
|
||||
AFK.AFKMode.bottom:Width(GetScreenWidth() + (E.Border*2))
|
||||
AFK.AFKMode.bottom:Height(GetScreenHeight() * (1 / 10))
|
||||
|
||||
AFK.AFKMode.bottom.LogoTop = AFK.AFKMode:CreateTexture(nil, 'OVERLAY')
|
||||
AFK.AFKMode.bottom.LogoTop:Size(320, 150)
|
||||
AFK.AFKMode.bottom.LogoTop:Point('CENTER', AFK.AFKMode.bottom, 'CENTER', 0, 50)
|
||||
AFK.AFKMode.bottom.LogoTop:SetTexture(E.Media.Textures.LogoTop)
|
||||
|
||||
AFK.AFKMode.bottom.LogoBottom = AFK.AFKMode:CreateTexture(nil, 'OVERLAY')
|
||||
AFK.AFKMode.bottom.LogoBottom:Size(320, 150)
|
||||
AFK.AFKMode.bottom.LogoBottom:Point('CENTER', AFK.AFKMode.bottom, 'CENTER', 0, 50)
|
||||
AFK.AFKMode.bottom.LogoBottom:SetTexture(E.Media.Textures.LogoBottom)
|
||||
|
||||
local factionGroup, size, offsetX, offsetY, nameOffsetX, nameOffsetY = E.myfaction, 140, -20, -16, -10, -28
|
||||
if factionGroup == 'Neutral' then
|
||||
factionGroup, size, offsetX, offsetY, nameOffsetX, nameOffsetY = 'Panda', 90, 15, 10, 20, -5
|
||||
end
|
||||
|
||||
AFK.AFKMode.bottom.faction = AFK.AFKMode.bottom:CreateTexture(nil, 'OVERLAY')
|
||||
AFK.AFKMode.bottom.faction:Point('BOTTOMLEFT', AFK.AFKMode.bottom, 'BOTTOMLEFT', offsetX, offsetY)
|
||||
AFK.AFKMode.bottom.faction:SetTexture(format([[Interface\Timer\%s-Logo]], factionGroup))
|
||||
AFK.AFKMode.bottom.faction:Size(size, size)
|
||||
|
||||
local classColor = E:ClassColor(E.myclass)
|
||||
AFK.AFKMode.bottom.name = AFK.AFKMode.bottom:CreateFontString(nil, 'OVERLAY')
|
||||
AFK.AFKMode.bottom.name:FontTemplate(nil, 20)
|
||||
AFK.AFKMode.bottom.name:SetFormattedText('%s-%s', E.myname, E.myrealm)
|
||||
AFK.AFKMode.bottom.name:Point('TOPLEFT', AFK.AFKMode.bottom.faction, 'TOPRIGHT', nameOffsetX, nameOffsetY)
|
||||
AFK.AFKMode.bottom.name:SetTextColor(classColor.r, classColor.g, classColor.b)
|
||||
|
||||
AFK.AFKMode.bottom.guild = AFK.AFKMode.bottom:CreateFontString(nil, 'OVERLAY')
|
||||
AFK.AFKMode.bottom.guild:FontTemplate(nil, 20)
|
||||
AFK.AFKMode.bottom.guild:SetText(L["No Guild"])
|
||||
AFK.AFKMode.bottom.guild:Point('TOPLEFT', AFK.AFKMode.bottom.name, 'BOTTOMLEFT', 0, -6)
|
||||
AFK.AFKMode.bottom.guild:SetTextColor(0.7, 0.7, 0.7)
|
||||
|
||||
AFK.AFKMode.bottom.time = AFK.AFKMode.bottom:CreateFontString(nil, 'OVERLAY')
|
||||
AFK.AFKMode.bottom.time:FontTemplate(nil, 20)
|
||||
AFK.AFKMode.bottom.time:SetText('00:00')
|
||||
AFK.AFKMode.bottom.time:Point('TOPLEFT', AFK.AFKMode.bottom.guild, 'BOTTOMLEFT', 0, -6)
|
||||
AFK.AFKMode.bottom.time:SetTextColor(0.7, 0.7, 0.7)
|
||||
|
||||
--Use this frame to control position of the model
|
||||
AFK.AFKMode.bottom.modelHolder = CreateFrame('Frame', nil, AFK.AFKMode.bottom)
|
||||
AFK.AFKMode.bottom.modelHolder:Size(150, 150)
|
||||
AFK.AFKMode.bottom.modelHolder:Point('BOTTOMRIGHT', AFK.AFKMode.bottom, 'BOTTOMRIGHT', -200, 220)
|
||||
|
||||
AFK.AFKMode.bottom.model = CreateFrame('PlayerModel', 'ElvUIAFKPlayerModel', AFK.AFKMode.bottom.modelHolder)
|
||||
AFK.AFKMode.bottom.model:Point('CENTER', AFK.AFKMode.bottom.modelHolder, 'CENTER')
|
||||
AFK.AFKMode.bottom.model:Size(GetScreenWidth() * 2, GetScreenHeight() * 2) --YES, double screen size. This prevents clipping of models. Position is controlled with the helper frame.
|
||||
AFK.AFKMode.bottom.model:SetCamDistanceScale(4.5) --Since the model frame is huge, we need to zoom out quite a bit.
|
||||
AFK.AFKMode.bottom.model:SetFacing(6)
|
||||
AFK.AFKMode.bottom.model:SetScript('OnUpdate', function(model)
|
||||
if not model.isIdle then
|
||||
local timePassed = GetTime() - model.startTime
|
||||
if timePassed > model.duration then
|
||||
model:SetAnimation(0)
|
||||
model.isIdle = true
|
||||
AFK.animTimer = AFK:ScheduleTimer('LoopAnimations', model.idleDuration)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
AFK:Toggle()
|
||||
AFK.isActive = false
|
||||
end
|
||||
|
||||
E:RegisterModule(AFK:GetName())
|
||||
173
Modules/Misc/ChatBubbles.lua
Normal file
173
Modules/Misc/ChatBubbles.lua
Normal file
@@ -0,0 +1,173 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local M = E:GetModule('Misc')
|
||||
local CH = E:GetModule('Chat')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local format, wipe, unpack, pairs = format, wipe, unpack, pairs
|
||||
local strmatch, strlower, gmatch, gsub = strmatch, strlower, gmatch, gsub
|
||||
|
||||
local Ambiguate = Ambiguate
|
||||
local CreateFrame = CreateFrame
|
||||
local GetInstanceInfo = GetInstanceInfo
|
||||
local RemoveExtraSpaces = RemoveExtraSpaces
|
||||
local PRIEST_COLOR = RAID_CLASS_COLORS.PRIEST
|
||||
local C_ChatBubbles_GetAllChatBubbles = C_ChatBubbles.GetAllChatBubbles
|
||||
|
||||
--Message caches
|
||||
local messageToGUID = {}
|
||||
local messageToSender = {}
|
||||
|
||||
function M:UpdateBubbleBorder()
|
||||
local backdrop = self.backdrop
|
||||
local str = backdrop and backdrop.String
|
||||
if not str then return end
|
||||
|
||||
if E.private.general.chatBubbles == 'backdrop' then
|
||||
backdrop:SetBackdropBorderColor(str:GetTextColor())
|
||||
end
|
||||
|
||||
local name = self.Name and self.Name:GetText()
|
||||
if name then self.Name:SetText() end
|
||||
|
||||
local text = str:GetText()
|
||||
if not text then return end
|
||||
|
||||
if E.private.general.chatBubbleName then
|
||||
M:AddChatBubbleName(self, messageToGUID[text], messageToSender[text])
|
||||
end
|
||||
|
||||
if E.private.chat.enable and E.private.general.classColorMentionsSpeech then
|
||||
local isFirstWord, rebuiltString
|
||||
if text and strmatch(text, '%s-%S+%s*') then
|
||||
for word in gmatch(text, '%s-%S+%s*') do
|
||||
local tempWord = gsub(word, '^[%s%p]-([^%s%p]+)([%-]?[^%s%p]-)[%s%p]*$', '%1%2')
|
||||
local lowerCaseWord = strlower(tempWord)
|
||||
|
||||
local classMatch = CH.ClassNames[lowerCaseWord]
|
||||
local wordMatch = classMatch and lowerCaseWord
|
||||
|
||||
if wordMatch and not E.global.chat.classColorMentionExcludedNames[wordMatch] then
|
||||
local classColorTable = E:ClassColor(classMatch)
|
||||
if classColorTable then
|
||||
word = gsub(word, gsub(tempWord, '%-','%%-'), format('\124cff%.2x%.2x%.2x%s\124r', classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, tempWord))
|
||||
end
|
||||
end
|
||||
|
||||
if not isFirstWord then
|
||||
rebuiltString = word
|
||||
isFirstWord = true
|
||||
else
|
||||
rebuiltString = format('%s%s', rebuiltString, word)
|
||||
end
|
||||
end
|
||||
|
||||
if rebuiltString then
|
||||
str:SetText(RemoveExtraSpaces(rebuiltString))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:AddChatBubbleName(chatBubble, guid, name)
|
||||
if not name then return end
|
||||
|
||||
local color = PRIEST_COLOR
|
||||
local data = guid and guid ~= '' and CH:GetPlayerInfoByGUID(guid)
|
||||
if data and data.classColor then
|
||||
color = data.classColor
|
||||
end
|
||||
|
||||
chatBubble.Name:SetFormattedText('|c%s%s|r', color.colorStr, name)
|
||||
chatBubble.Name:Width(chatBubble:GetWidth()-10)
|
||||
end
|
||||
|
||||
local yOffset --Value set in M:LoadChatBubbles()
|
||||
function M:SkinBubble(frame, backdrop)
|
||||
local bubbleFont = LSM:Fetch('font', E.private.general.chatBubbleFont)
|
||||
if backdrop.String then
|
||||
backdrop.String:FontTemplate(bubbleFont, E.private.general.chatBubbleFontSize, E.private.general.chatBubbleFontOutline)
|
||||
end
|
||||
|
||||
if E.private.general.chatBubbles == 'backdrop' then
|
||||
if not backdrop.template then
|
||||
backdrop:SetBackdrop()
|
||||
backdrop:SetTemplate('Transparent', nil, true)
|
||||
end
|
||||
elseif E.private.general.chatBubbles == 'backdrop_noborder' then
|
||||
if not backdrop.noBorder then
|
||||
backdrop:SetBackdrop()
|
||||
backdrop.noBorder = backdrop:CreateTexture(nil, 'ARTWORK')
|
||||
end
|
||||
|
||||
backdrop.noBorder:SetInside(frame, 4, 4)
|
||||
backdrop.noBorder:SetColorTexture(unpack(E.media.backdropfadecolor))
|
||||
elseif E.private.general.chatBubbles == 'nobackdrop' then
|
||||
backdrop:SetBackdrop()
|
||||
end
|
||||
|
||||
if not frame.Name then
|
||||
local name = frame:CreateFontString(nil, 'BORDER')
|
||||
name:Height(10) --Width set in M:AddChatBubbleName()
|
||||
name:Point('BOTTOM', frame, 'TOP', 0, yOffset)
|
||||
name:FontTemplate(bubbleFont, E.private.general.chatBubbleFontSize * 0.85, E.private.general.chatBubbleFontOutline)
|
||||
name:SetJustifyH('LEFT')
|
||||
frame.Name = name
|
||||
end
|
||||
|
||||
if not frame.backdrop then
|
||||
frame.backdrop = backdrop
|
||||
backdrop.Tail:Hide()
|
||||
|
||||
frame:HookScript('OnShow', M.UpdateBubbleBorder)
|
||||
frame:SetFrameStrata('DIALOG') --Doesn't work currently in Legion due to a bug on Blizzards end
|
||||
frame:SetClampedToScreen(false)
|
||||
|
||||
M.UpdateBubbleBorder(frame)
|
||||
end
|
||||
|
||||
frame.isSkinnedElvUI = true
|
||||
end
|
||||
|
||||
local function ChatBubble_OnEvent(_, event, msg, sender, _, _, _, _, _, _, _, _, _, guid)
|
||||
if event == 'PLAYER_ENTERING_WORLD' then --Clear caches
|
||||
wipe(messageToGUID)
|
||||
wipe(messageToSender)
|
||||
elseif E.private.general.chatBubbleName then
|
||||
messageToGUID[msg] = guid
|
||||
messageToSender[msg] = Ambiguate(sender, 'none')
|
||||
end
|
||||
end
|
||||
|
||||
local function ChatBubble_OnUpdate(eventFrame, elapsed)
|
||||
eventFrame.lastupdate = (eventFrame.lastupdate or -2) + elapsed
|
||||
if eventFrame.lastupdate < 0.1 then return end
|
||||
eventFrame.lastupdate = 0
|
||||
|
||||
for _, frame in pairs(C_ChatBubbles_GetAllChatBubbles()) do
|
||||
local backdrop = frame:GetChildren(1)
|
||||
if backdrop and not backdrop:IsForbidden() and not frame.isSkinnedElvUI then
|
||||
M:SkinBubble(frame, backdrop)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:ToggleChatBubbleScript()
|
||||
local _, instanceType = GetInstanceInfo()
|
||||
if instanceType == 'none' and E.private.general.chatBubbles ~= 'disabled' then
|
||||
M.BubbleFrame:SetScript('OnEvent', ChatBubble_OnEvent)
|
||||
M.BubbleFrame:SetScript('OnUpdate', ChatBubble_OnUpdate)
|
||||
else
|
||||
M.BubbleFrame:SetScript('OnEvent', nil)
|
||||
M.BubbleFrame:SetScript('OnUpdate', nil)
|
||||
end
|
||||
end
|
||||
|
||||
function M:LoadChatBubbles()
|
||||
yOffset = (E.private.general.chatBubbles == 'backdrop' and 2) or (E.private.general.chatBubbles == 'backdrop_noborder' and -2) or 0
|
||||
self.BubbleFrame = CreateFrame('Frame')
|
||||
self.BubbleFrame:RegisterEvent('CHAT_MSG_SAY')
|
||||
self.BubbleFrame:RegisterEvent('CHAT_MSG_YELL')
|
||||
self.BubbleFrame:RegisterEvent('CHAT_MSG_MONSTER_SAY')
|
||||
self.BubbleFrame:RegisterEvent('CHAT_MSG_MONSTER_YELL')
|
||||
self.BubbleFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
end
|
||||
128
Modules/Misc/DebugTools.lua
Normal file
128
Modules/Misc/DebugTools.lua
Normal file
@@ -0,0 +1,128 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local D = E:GetModule('DebugTools')
|
||||
|
||||
local _G = _G
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
local CreateFrame = CreateFrame
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local GetCVarBool = GetCVarBool
|
||||
local StaticPopup_Hide = StaticPopup_Hide
|
||||
|
||||
D.HideFrame = CreateFrame('Frame')
|
||||
|
||||
local function UnHighlightText(self)
|
||||
self:HighlightText(0, 0)
|
||||
end
|
||||
|
||||
local function ScriptErrors_UnHighlightText()
|
||||
_G.ScriptErrorsFrame.ScrollFrame.Text:HighlightText(0, 0)
|
||||
end
|
||||
|
||||
function D:ModifyErrorFrame()
|
||||
local ScriptErrorsFrame = _G.ScriptErrorsFrame
|
||||
ScriptErrorsFrame.ScrollFrame.Text.cursorOffset = 0
|
||||
ScriptErrorsFrame.ScrollFrame.Text.cursorHeight = 0
|
||||
ScriptErrorsFrame.ScrollFrame.Text:SetScript('OnEditFocusGained', nil)
|
||||
|
||||
hooksecurefunc(ScriptErrorsFrame, 'Update', ScriptErrors_UnHighlightText)
|
||||
|
||||
-- Unhighlight text when focus is hit
|
||||
ScriptErrorsFrame.ScrollFrame.Text:HookScript('OnEscapePressed', UnHighlightText)
|
||||
|
||||
ScriptErrorsFrame:Size(500, 300)
|
||||
ScriptErrorsFrame.ScrollFrame:Size(ScriptErrorsFrame:GetWidth() - 45, ScriptErrorsFrame:GetHeight() - 71)
|
||||
|
||||
local BUTTON_WIDTH = 75
|
||||
local BUTTON_HEIGHT = 23
|
||||
local BUTTON_SPACING = 2
|
||||
|
||||
-- Add a first button
|
||||
local firstButton = CreateFrame('Button', nil, ScriptErrorsFrame, 'UIPanelButtonTemplate, BackdropTemplate')
|
||||
firstButton:Point('BOTTOMLEFT', ScriptErrorsFrame.Reload, 'BOTTOMRIGHT', BUTTON_SPACING, 0)
|
||||
firstButton:SetText('First')
|
||||
firstButton:Size(BUTTON_WIDTH, BUTTON_HEIGHT)
|
||||
firstButton:SetScript('OnClick', function()
|
||||
ScriptErrorsFrame.index = 1
|
||||
ScriptErrorsFrame:Update()
|
||||
end)
|
||||
ScriptErrorsFrame.firstButton = firstButton
|
||||
|
||||
-- Also add a Last button for errors
|
||||
local lastButton = CreateFrame('Button', nil, ScriptErrorsFrame, 'UIPanelButtonTemplate, BackdropTemplate')
|
||||
lastButton:Point('BOTTOMRIGHT', ScriptErrorsFrame.Close, 'BOTTOMLEFT', -BUTTON_SPACING, 0)
|
||||
lastButton:Size(BUTTON_WIDTH, BUTTON_HEIGHT)
|
||||
lastButton:SetText('Last')
|
||||
lastButton:SetScript('OnClick', function()
|
||||
ScriptErrorsFrame.index = #(ScriptErrorsFrame.order)
|
||||
ScriptErrorsFrame:Update()
|
||||
end)
|
||||
ScriptErrorsFrame.lastButton = lastButton
|
||||
|
||||
D:ScriptErrorsFrame_UpdateButtons()
|
||||
D:Unhook(ScriptErrorsFrame, 'OnShow')
|
||||
end
|
||||
|
||||
function D:ScriptErrorsFrame_UpdateButtons()
|
||||
local ScriptErrorsFrame = _G.ScriptErrorsFrame
|
||||
if not ScriptErrorsFrame.firstButton then return end
|
||||
|
||||
local numErrors = #ScriptErrorsFrame.order;
|
||||
local index = ScriptErrorsFrame.index;
|
||||
if index == 0 then
|
||||
ScriptErrorsFrame.lastButton:Disable()
|
||||
ScriptErrorsFrame.firstButton:Disable()
|
||||
else
|
||||
if numErrors == 1 then
|
||||
ScriptErrorsFrame.lastButton:Disable()
|
||||
ScriptErrorsFrame.firstButton:Disable()
|
||||
else
|
||||
ScriptErrorsFrame.lastButton:Enable()
|
||||
ScriptErrorsFrame.firstButton:Enable()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function D:ScriptErrorsFrame_OnError(_, _, keepHidden)
|
||||
if keepHidden or D.MessagePrinted or not InCombatLockdown() or GetCVarBool('scriptErrors') ~= true then return; end
|
||||
|
||||
E:Print(L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."])
|
||||
D.MessagePrinted = true;
|
||||
end
|
||||
|
||||
function D:PLAYER_REGEN_ENABLED()
|
||||
_G.ScriptErrorsFrame:SetParent(_G.UIParent)
|
||||
D.MessagePrinted = nil;
|
||||
end
|
||||
|
||||
function D:PLAYER_REGEN_DISABLED()
|
||||
_G.ScriptErrorsFrame:SetParent(self.HideFrame)
|
||||
end
|
||||
|
||||
function D:TaintError(event, addonName, addonFunc)
|
||||
if GetCVarBool('scriptErrors') ~= true or E.db.general.taintLog ~= true then return end
|
||||
_G.ScriptErrorsFrame:OnError(L["%s: %s tried to call the protected function '%s'."]:format(event, addonName or '<name>', addonFunc or '<func>'), false, false)
|
||||
end
|
||||
|
||||
function D:StaticPopup_Show(name)
|
||||
if name == 'ADDON_ACTION_FORBIDDEN' then
|
||||
StaticPopup_Hide(name);
|
||||
end
|
||||
end
|
||||
|
||||
function D:Initialize()
|
||||
self.Initialized = true
|
||||
self.HideFrame:Hide()
|
||||
|
||||
local ScriptErrorsFrame = _G.ScriptErrorsFrame
|
||||
|
||||
self:SecureHookScript(ScriptErrorsFrame, 'OnShow', D.ModifyErrorFrame)
|
||||
self:SecureHook(ScriptErrorsFrame, 'UpdateButtons', D.ScriptErrorsFrame_UpdateButtons)
|
||||
self:SecureHook(ScriptErrorsFrame, 'OnError', D.ScriptErrorsFrame_OnError)
|
||||
self:SecureHook('StaticPopup_Show')
|
||||
self:RegisterEvent('PLAYER_REGEN_DISABLED')
|
||||
self:RegisterEvent('PLAYER_REGEN_ENABLED')
|
||||
self:RegisterEvent('ADDON_ACTION_BLOCKED', 'TaintError')
|
||||
self:RegisterEvent('ADDON_ACTION_FORBIDDEN', 'TaintError')
|
||||
end
|
||||
|
||||
E:RegisterModule(D:GetName())
|
||||
334
Modules/Misc/InfoItemLevel.lua
Normal file
334
Modules/Misc/InfoItemLevel.lua
Normal file
@@ -0,0 +1,334 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local M = E:GetModule('Misc')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local rad = rad
|
||||
local gsub = gsub
|
||||
local wipe = wipe
|
||||
local next = next
|
||||
local pairs = pairs
|
||||
local unpack = unpack
|
||||
local UnitGUID = UnitGUID
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
local InspectItems = {
|
||||
'HeadSlot',
|
||||
'NeckSlot',
|
||||
'ShoulderSlot',
|
||||
'',
|
||||
'ChestSlot',
|
||||
'WaistSlot',
|
||||
'LegsSlot',
|
||||
'FeetSlot',
|
||||
'WristSlot',
|
||||
'HandsSlot',
|
||||
'Finger0Slot',
|
||||
'Finger1Slot',
|
||||
'Trinket0Slot',
|
||||
'Trinket1Slot',
|
||||
'BackSlot',
|
||||
'MainHandSlot',
|
||||
'SecondaryHandSlot',
|
||||
}
|
||||
|
||||
local whileOpenEvents = {
|
||||
UPDATE_INVENTORY_DURABILITY = true,
|
||||
AZERITE_ESSENCE_UPDATE = true
|
||||
}
|
||||
|
||||
function M:CreateInspectTexture(slot, x, y)
|
||||
local texture = slot:CreateTexture()
|
||||
texture:Point('BOTTOM', x, y)
|
||||
texture:SetTexCoord(unpack(E.TexCoords))
|
||||
texture:Size(14)
|
||||
|
||||
local backdrop = CreateFrame('Frame', nil, slot, 'BackdropTemplate')
|
||||
backdrop:SetTemplate(nil, nil, true)
|
||||
backdrop:SetBackdropColor(0,0,0,0)
|
||||
backdrop:SetOutside(texture)
|
||||
backdrop:Hide()
|
||||
|
||||
return texture, backdrop
|
||||
end
|
||||
|
||||
function M:GetInspectPoints(id)
|
||||
if not id then return end
|
||||
|
||||
if id <= 5 or (id == 9 or id == 15) then
|
||||
return 40, 3, 18, 'BOTTOMLEFT' -- Left side
|
||||
elseif (id >= 6 and id <= 8) or (id >= 10 and id <= 14) then
|
||||
return -40, 3, 18, 'BOTTOMRIGHT' -- Right side
|
||||
else
|
||||
return 0, 45, 60, 'BOTTOM'
|
||||
end
|
||||
end
|
||||
|
||||
function M:UpdateInspectInfo(_, arg1)
|
||||
M:UpdatePageInfo(_G.InspectFrame, 'Inspect', arg1)
|
||||
end
|
||||
|
||||
function M:UpdateCharacterInfo(event)
|
||||
if (not E.db.general.itemLevel.displayCharacterInfo)
|
||||
or (whileOpenEvents[event] and not _G.CharacterFrame:IsShown()) then return end
|
||||
|
||||
M:UpdatePageInfo(_G.CharacterFrame, 'Character', nil, event)
|
||||
end
|
||||
|
||||
function M:UpdateCharacterItemLevel()
|
||||
M:UpdateAverageString(_G.CharacterFrame, 'Character')
|
||||
end
|
||||
|
||||
function M:ClearPageInfo(frame, which)
|
||||
if not (frame and frame.ItemLevelText) then return end
|
||||
frame.ItemLevelText:SetText('')
|
||||
|
||||
for i = 1, 17 do
|
||||
if i ~= 4 then
|
||||
local inspectItem = _G[which..InspectItems[i]]
|
||||
inspectItem.enchantText:SetText('')
|
||||
inspectItem.iLvlText:SetText('')
|
||||
|
||||
for y=1, 10 do
|
||||
inspectItem['textureSlot'..y]:SetTexture()
|
||||
inspectItem['textureSlotBackdrop'..y]:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:ToggleItemLevelInfo(setupCharacterPage)
|
||||
if setupCharacterPage then
|
||||
M:CreateSlotStrings(_G.CharacterFrame, 'Character')
|
||||
end
|
||||
|
||||
if E.db.general.itemLevel.displayCharacterInfo then
|
||||
M:RegisterEvent('AZERITE_ESSENCE_UPDATE', 'UpdateCharacterInfo')
|
||||
M:RegisterEvent('PLAYER_EQUIPMENT_CHANGED', 'UpdateCharacterInfo')
|
||||
M:RegisterEvent('UPDATE_INVENTORY_DURABILITY', 'UpdateCharacterInfo')
|
||||
M:RegisterEvent('PLAYER_AVG_ITEM_LEVEL_UPDATE', 'UpdateCharacterItemLevel')
|
||||
|
||||
_G.CharacterStatsPane.ItemLevelFrame.Value:Hide()
|
||||
|
||||
if not _G.CharacterFrame.CharacterInfoHooked then
|
||||
_G.CharacterFrame:HookScript('OnShow', M.UpdateCharacterInfo)
|
||||
_G.CharacterFrame.CharacterInfoHooked = true
|
||||
end
|
||||
|
||||
if not setupCharacterPage then
|
||||
M:UpdateCharacterInfo()
|
||||
end
|
||||
else
|
||||
M:UnregisterEvent('AZERITE_ESSENCE_UPDATE')
|
||||
M:UnregisterEvent('PLAYER_EQUIPMENT_CHANGED')
|
||||
M:UnregisterEvent('UPDATE_INVENTORY_DURABILITY')
|
||||
M:UnregisterEvent('PLAYER_AVG_ITEM_LEVEL_UPDATE')
|
||||
|
||||
_G.CharacterStatsPane.ItemLevelFrame.Value:Show()
|
||||
|
||||
M:ClearPageInfo(_G.CharacterFrame, 'Character')
|
||||
end
|
||||
|
||||
if E.db.general.itemLevel.displayInspectInfo then
|
||||
M:RegisterEvent('INSPECT_READY', 'UpdateInspectInfo')
|
||||
else
|
||||
M:UnregisterEvent('INSPECT_READY')
|
||||
M:ClearPageInfo(_G.InspectFrame, 'Inspect')
|
||||
end
|
||||
end
|
||||
|
||||
function M:UpdatePageStrings(i, iLevelDB, inspectItem, slotInfo, which) -- `which` is used by plugins
|
||||
iLevelDB[i] = slotInfo.iLvl
|
||||
|
||||
inspectItem.enchantText:SetText(slotInfo.enchantTextShort)
|
||||
if slotInfo.enchantColors and next(slotInfo.enchantColors) then
|
||||
inspectItem.enchantText:SetTextColor(unpack(slotInfo.enchantColors))
|
||||
end
|
||||
|
||||
inspectItem.iLvlText:SetText(slotInfo.iLvl)
|
||||
if slotInfo.itemLevelColors and next(slotInfo.itemLevelColors) then
|
||||
inspectItem.iLvlText:SetTextColor(unpack(slotInfo.itemLevelColors))
|
||||
end
|
||||
|
||||
local gemStep, essenceStep = 1, 1
|
||||
for x = 1, 10 do
|
||||
local texture = inspectItem['textureSlot'..x]
|
||||
local backdrop = inspectItem['textureSlotBackdrop'..x]
|
||||
local essenceType = inspectItem['textureSlotEssenceType'..x]
|
||||
if essenceType then essenceType:Hide() end
|
||||
|
||||
local gem = slotInfo.gems and slotInfo.gems[gemStep]
|
||||
local essence = not gem and (slotInfo.essences and slotInfo.essences[essenceStep])
|
||||
if gem then
|
||||
texture:SetTexture(gem)
|
||||
backdrop:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
||||
backdrop:Show()
|
||||
|
||||
gemStep = gemStep + 1
|
||||
elseif essence and next(essence) then
|
||||
local hexColor = essence[4]
|
||||
if hexColor then
|
||||
local r, g, b = E:HexToRGB(hexColor)
|
||||
backdrop:SetBackdropBorderColor(r/255, g/255, b/255)
|
||||
else
|
||||
backdrop:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
||||
end
|
||||
|
||||
if not essenceType then
|
||||
essenceType = inspectItem:CreateTexture()
|
||||
essenceType:SetTexture(2907423)
|
||||
essenceType:SetRotation(rad(90))
|
||||
essenceType:SetParent(backdrop)
|
||||
inspectItem['textureSlotEssenceType'..x] = essenceType
|
||||
end
|
||||
|
||||
essenceType:Point('BOTTOM', texture, 'TOP', 0, -9)
|
||||
essenceType:SetAtlas(gsub(essence[2], '^tooltip%-(heartofazeroth)essence', '%1-list-selected'))
|
||||
essenceType:Size(13, 17)
|
||||
essenceType:Show()
|
||||
|
||||
local selected = essence[1]
|
||||
texture:SetTexture(selected)
|
||||
backdrop:Show()
|
||||
|
||||
if selected then
|
||||
backdrop:SetBackdropColor(0,0,0,0)
|
||||
else
|
||||
local r, g, b = unpack(E.media.backdropcolor)
|
||||
backdrop:SetBackdropColor(r, g, b, 1)
|
||||
end
|
||||
|
||||
essenceStep = essenceStep + 1
|
||||
else
|
||||
texture:SetTexture()
|
||||
backdrop:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:UpdateAverageString(frame, which, iLevelDB)
|
||||
local isCharPage = which == 'Character'
|
||||
local AvgItemLevel = (isCharPage and E:GetPlayerItemLevel()) or E:CalculateAverageItemLevel(iLevelDB, frame.unit)
|
||||
if AvgItemLevel then
|
||||
if isCharPage then
|
||||
frame.ItemLevelText:SetText(AvgItemLevel)
|
||||
frame.ItemLevelText:SetTextColor(_G.CharacterStatsPane.ItemLevelFrame.Value:GetTextColor())
|
||||
else
|
||||
frame.ItemLevelText:SetFormattedText(L["Item level: %.2f"], AvgItemLevel)
|
||||
end
|
||||
else
|
||||
frame.ItemLevelText:SetText('')
|
||||
end
|
||||
end
|
||||
|
||||
function M:TryGearAgain(frame, which, i, deepScan, iLevelDB, inspectItem)
|
||||
E:Delay(0.05, function()
|
||||
if which == 'Inspect' and (not frame or not frame.unit) then return end
|
||||
|
||||
local unit = (which == 'Character' and 'player') or frame.unit
|
||||
local slotInfo = E:GetGearSlotInfo(unit, i, deepScan)
|
||||
if slotInfo == 'tooSoon' then return end
|
||||
|
||||
M:UpdatePageStrings(i, iLevelDB, inspectItem, slotInfo, which)
|
||||
end)
|
||||
end
|
||||
|
||||
do
|
||||
local iLevelDB = {}
|
||||
function M:UpdatePageInfo(frame, which, guid, event)
|
||||
if not (which and frame and frame.ItemLevelText) then return end
|
||||
if which == 'Inspect' and (not frame or not frame.unit or (guid and frame:IsShown() and UnitGUID(frame.unit) ~= guid)) then return end
|
||||
|
||||
wipe(iLevelDB)
|
||||
|
||||
local waitForItems
|
||||
for i = 1, 17 do
|
||||
if i ~= 4 then
|
||||
local inspectItem = _G[which..InspectItems[i]]
|
||||
inspectItem.enchantText:SetText('')
|
||||
inspectItem.iLvlText:SetText('')
|
||||
|
||||
local unit = (which == 'Character' and 'player') or frame.unit
|
||||
local slotInfo = E:GetGearSlotInfo(unit, i, true)
|
||||
if slotInfo == 'tooSoon' then
|
||||
if not waitForItems then waitForItems = true end
|
||||
M:TryGearAgain(frame, which, i, true, iLevelDB, inspectItem)
|
||||
else
|
||||
M:UpdatePageStrings(i, iLevelDB, inspectItem, slotInfo, which)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if event and event == 'PLAYER_EQUIPMENT_CHANGED' then
|
||||
return
|
||||
end
|
||||
|
||||
if waitForItems then
|
||||
E:Delay(0.10, M.UpdateAverageString, M, frame, which, iLevelDB)
|
||||
else
|
||||
M:UpdateAverageString(frame, which, iLevelDB)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:CreateSlotStrings(frame, which)
|
||||
if not (frame and which) then return end
|
||||
|
||||
local itemLevelFont = E.db.general.itemLevel.itemLevelFont
|
||||
local itemLevelFontSize = E.db.general.itemLevel.itemLevelFontSize or 12
|
||||
local itemLevelFontOutline = E.db.general.itemLevel.itemLevelFontOutline or 'OUTLINE'
|
||||
|
||||
if which == 'Inspect' then
|
||||
frame.ItemLevelText = _G.InspectPaperDollItemsFrame:CreateFontString(nil, 'ARTWORK')
|
||||
frame.ItemLevelText:Point('BOTTOMRIGHT', -6, 6)
|
||||
else
|
||||
frame.ItemLevelText = _G.CharacterStatsPane.ItemLevelFrame:CreateFontString(nil, 'ARTWORK')
|
||||
frame.ItemLevelText:Point('BOTTOM', _G.CharacterStatsPane.ItemLevelFrame.Value, 'BOTTOM', 0, 0)
|
||||
end
|
||||
frame.ItemLevelText:FontTemplate(nil, which == 'Inspect' and 12 or 20)
|
||||
|
||||
for i, s in pairs(InspectItems) do
|
||||
if i ~= 4 then
|
||||
local slot = _G[which..s]
|
||||
local x, y, z, justify = M:GetInspectPoints(i)
|
||||
slot.iLvlText = slot:CreateFontString(nil, 'OVERLAY')
|
||||
slot.iLvlText:FontTemplate(LSM:Fetch('font', itemLevelFont), itemLevelFontSize, itemLevelFontOutline)
|
||||
slot.iLvlText:Point('BOTTOM', slot, x, y)
|
||||
|
||||
slot.enchantText = slot:CreateFontString(nil, 'OVERLAY')
|
||||
slot.enchantText:FontTemplate(LSM:Fetch('font', itemLevelFont), itemLevelFontSize, itemLevelFontOutline)
|
||||
|
||||
if i == 16 or i == 17 then
|
||||
slot.enchantText:Point(i==16 and 'BOTTOMRIGHT' or 'BOTTOMLEFT', slot, i==16 and -40 or 40, 3)
|
||||
else
|
||||
slot.enchantText:Point(justify, slot, x + (justify == 'BOTTOMLEFT' and 5 or -5), z)
|
||||
end
|
||||
|
||||
for u=1, 10 do
|
||||
local offset = 8+(u*16)
|
||||
local newX = ((justify == 'BOTTOMLEFT' or i == 17) and x+offset) or x-offset
|
||||
slot['textureSlot'..u], slot['textureSlotBackdrop'..u] = M:CreateInspectTexture(slot, newX, --[[newY or]] y)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:SetupInspectPageInfo()
|
||||
M:CreateSlotStrings(_G.InspectFrame, 'Inspect')
|
||||
end
|
||||
|
||||
function M:UpdateInspectPageFonts(which)
|
||||
local itemLevelFont = E.db.general.itemLevel.itemLevelFont
|
||||
local itemLevelFontSize = E.db.general.itemLevel.itemLevelFontSize or 12
|
||||
local itemLevelFontOutline = E.db.general.itemLevel.itemLevelFontOutline or 'OUTLINE'
|
||||
|
||||
for i, s in pairs(InspectItems) do
|
||||
if i ~= 4 then
|
||||
local slot = _G[which..s]
|
||||
if slot then
|
||||
slot.iLvlText:FontTemplate(LSM:Fetch('font', itemLevelFont), itemLevelFontSize, itemLevelFontOutline)
|
||||
slot.enchantText:FontTemplate(LSM:Fetch('font', itemLevelFont), itemLevelFontSize, itemLevelFontOutline)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
12
Modules/Misc/Load_Misc.xml
Normal file
12
Modules/Misc/Load_Misc.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='Misc.lua'/>
|
||||
<Script file='DebugTools.lua'/>
|
||||
<Script file='ChatBubbles.lua'/>
|
||||
<Script file='RaidMarker.lua'/>
|
||||
<Script file='Loot.lua'/>
|
||||
<Script file='LootRoll.lua'/>
|
||||
<Script file='InfoItemLevel.lua'/>
|
||||
<Script file='RaidUtility.lua'/>
|
||||
<Script file='TotemBar.lua'/>
|
||||
<Script file='AFK.lua'/>
|
||||
</Ui>
|
||||
338
Modules/Misc/Loot.lua
Normal file
338
Modules/Misc/Loot.lua
Normal file
@@ -0,0 +1,338 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local M = E:GetModule('Misc')
|
||||
local LBG = E.Libs.ButtonGlow
|
||||
|
||||
local _G = _G
|
||||
local unpack, pairs = unpack, pairs
|
||||
local tinsert = tinsert
|
||||
local max = max
|
||||
|
||||
local CloseLoot = CloseLoot
|
||||
local CreateFrame = CreateFrame
|
||||
local CursorOnUpdate = CursorOnUpdate
|
||||
local CursorUpdate = CursorUpdate
|
||||
local GetCursorPosition = GetCursorPosition
|
||||
local GetCVarBool = GetCVarBool
|
||||
local GetLootSlotInfo = GetLootSlotInfo
|
||||
local GetLootSlotLink = GetLootSlotLink
|
||||
local GetNumLootItems = GetNumLootItems
|
||||
local HandleModifiedItemClick = HandleModifiedItemClick
|
||||
local IsFishingLoot = IsFishingLoot
|
||||
local IsModifiedClick = IsModifiedClick
|
||||
local LootSlot = LootSlot
|
||||
local LootSlotHasItem = LootSlotHasItem
|
||||
local ResetCursor = ResetCursor
|
||||
local StaticPopup_Hide = StaticPopup_Hide
|
||||
local UnitIsDead = UnitIsDead
|
||||
local UnitIsFriend = UnitIsFriend
|
||||
local UnitName = UnitName
|
||||
|
||||
local LOOT = LOOT
|
||||
local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
|
||||
local TEXTURE_ITEM_QUEST_BANG = TEXTURE_ITEM_QUEST_BANG
|
||||
|
||||
local coinTextureIDs = {
|
||||
[133784] = true,
|
||||
[133785] = true,
|
||||
[133786] = true,
|
||||
[133787] = true,
|
||||
[133788] = true,
|
||||
[133789] = true,
|
||||
}
|
||||
|
||||
--Credit Haste
|
||||
local iconSize, lootFrame, lootFrameHolder = 30
|
||||
|
||||
local OnEnter = function(self)
|
||||
local slot = self:GetID()
|
||||
if LootSlotHasItem(slot) then
|
||||
_G.GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
|
||||
_G.GameTooltip:SetLootItem(slot)
|
||||
CursorUpdate(self)
|
||||
end
|
||||
|
||||
self.drop:Show()
|
||||
self.drop:SetVertexColor(1, 1, 0)
|
||||
end
|
||||
|
||||
local OnLeave = function(self)
|
||||
if self.quality and (self.quality > 1) then
|
||||
local color = ITEM_QUALITY_COLORS[self.quality]
|
||||
self.drop:SetVertexColor(color.r, color.g, color.b)
|
||||
else
|
||||
self.drop:Hide()
|
||||
end
|
||||
|
||||
_G.GameTooltip:Hide()
|
||||
ResetCursor()
|
||||
end
|
||||
|
||||
local OnClick = function(self)
|
||||
local LootFrame = _G.LootFrame
|
||||
LootFrame.selectedQuality = self.quality
|
||||
LootFrame.selectedItemName = self.name:GetText()
|
||||
LootFrame.selectedSlot = self:GetID()
|
||||
LootFrame.selectedLootButton = self:GetName()
|
||||
LootFrame.selectedTexture = self.icon:GetTexture()
|
||||
|
||||
if IsModifiedClick() then
|
||||
HandleModifiedItemClick(GetLootSlotLink(self:GetID()))
|
||||
else
|
||||
StaticPopup_Hide('CONFIRM_LOOT_DISTRIBUTION')
|
||||
LootSlot(self:GetID())
|
||||
end
|
||||
end
|
||||
|
||||
local OnShow = function(self)
|
||||
local GameTooltip = _G.GameTooltip
|
||||
if GameTooltip:IsOwned(self) then
|
||||
GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
|
||||
GameTooltip:SetLootItem(self:GetID())
|
||||
CursorOnUpdate(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function anchorSlots(self)
|
||||
local shownSlots = 0
|
||||
|
||||
for i=1, #self.slots do
|
||||
local frame = self.slots[i]
|
||||
if frame:IsShown() then
|
||||
shownSlots = shownSlots + 1
|
||||
|
||||
frame:Point('TOP', lootFrame, 4, (-8 + iconSize) - (shownSlots * iconSize))
|
||||
end
|
||||
end
|
||||
|
||||
self:Height(max(shownSlots * iconSize + 16, 20))
|
||||
end
|
||||
|
||||
local function createSlot(id)
|
||||
local iconsize = (iconSize - 2)
|
||||
|
||||
local frame = CreateFrame('Button', 'ElvLootSlot'..id, lootFrame)
|
||||
frame:Point('LEFT', 8, 0)
|
||||
frame:Point('RIGHT', -8, 0)
|
||||
frame:Height(iconsize)
|
||||
frame:SetID(id)
|
||||
|
||||
frame:RegisterForClicks('LeftButtonUp', 'RightButtonUp')
|
||||
|
||||
frame:SetScript('OnEnter', OnEnter)
|
||||
frame:SetScript('OnLeave', OnLeave)
|
||||
frame:SetScript('OnClick', OnClick)
|
||||
frame:SetScript('OnShow', OnShow)
|
||||
|
||||
local iconFrame = CreateFrame('Frame', nil, frame, 'BackdropTemplate')
|
||||
iconFrame:Height(iconsize)
|
||||
iconFrame:Width(iconsize)
|
||||
iconFrame:Point('RIGHT', frame)
|
||||
iconFrame:SetTemplate()
|
||||
frame.iconFrame = iconFrame
|
||||
E.frames[iconFrame] = nil
|
||||
|
||||
local icon = iconFrame:CreateTexture(nil, 'ARTWORK')
|
||||
icon:SetTexCoord(unpack(E.TexCoords))
|
||||
icon:SetInside()
|
||||
frame.icon = icon
|
||||
|
||||
local count = iconFrame:CreateFontString(nil, 'OVERLAY')
|
||||
count:SetJustifyH'RIGHT'
|
||||
count:Point('BOTTOMRIGHT', iconFrame, -2, 2)
|
||||
count:FontTemplate(nil, nil, 'OUTLINE')
|
||||
count:SetText(1)
|
||||
frame.count = count
|
||||
|
||||
local name = frame:CreateFontString(nil, 'OVERLAY')
|
||||
name:SetJustifyH('LEFT')
|
||||
name:Point('LEFT', frame)
|
||||
name:Point('RIGHT', icon, 'LEFT')
|
||||
name:SetNonSpaceWrap(true)
|
||||
name:FontTemplate(nil, nil, 'OUTLINE')
|
||||
frame.name = name
|
||||
|
||||
local drop = frame:CreateTexture(nil, 'ARTWORK')
|
||||
drop:SetTexture([[Interface\QuestFrame\UI-QuestLogTitleHighlight]])
|
||||
drop:Point('LEFT', icon, 'RIGHT', 0, 0)
|
||||
drop:Point('RIGHT', frame)
|
||||
drop:SetAllPoints(frame)
|
||||
drop:SetAlpha(.3)
|
||||
frame.drop = drop
|
||||
|
||||
local questTexture = iconFrame:CreateTexture(nil, 'OVERLAY')
|
||||
questTexture:SetInside()
|
||||
questTexture:SetTexture(TEXTURE_ITEM_QUEST_BANG)
|
||||
questTexture:SetTexCoord(unpack(E.TexCoords))
|
||||
frame.questTexture = questTexture
|
||||
|
||||
lootFrame.slots[id] = frame
|
||||
return frame
|
||||
end
|
||||
|
||||
function M:LOOT_SLOT_CLEARED(_, slot)
|
||||
if not lootFrame:IsShown() then return end
|
||||
|
||||
if lootFrame.slots[slot] then
|
||||
lootFrame.slots[slot]:Hide()
|
||||
end
|
||||
|
||||
anchorSlots(lootFrame)
|
||||
end
|
||||
|
||||
function M:LOOT_CLOSED()
|
||||
StaticPopup_Hide('LOOT_BIND')
|
||||
lootFrame:Hide()
|
||||
|
||||
for _, v in pairs(lootFrame.slots) do
|
||||
v:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function M:LOOT_OPENED(_, autoloot)
|
||||
lootFrame:Show()
|
||||
|
||||
if not lootFrame:IsShown() then
|
||||
CloseLoot(not autoloot)
|
||||
end
|
||||
|
||||
if IsFishingLoot() then
|
||||
lootFrame.title:SetText(L["Fishy Loot"])
|
||||
elseif not UnitIsFriend('player', 'target') and UnitIsDead('target') then
|
||||
lootFrame.title:SetText(UnitName('target'))
|
||||
else
|
||||
lootFrame.title:SetText(LOOT)
|
||||
end
|
||||
|
||||
-- Blizzard uses strings here
|
||||
if GetCVarBool('lootUnderMouse') then
|
||||
local x, y = GetCursorPosition()
|
||||
x = x / lootFrame:GetEffectiveScale()
|
||||
y = y / lootFrame:GetEffectiveScale()
|
||||
|
||||
lootFrame:ClearAllPoints()
|
||||
lootFrame:Point('TOPLEFT', _G.UIParent, 'BOTTOMLEFT', x - 40, y + 20)
|
||||
lootFrame:GetCenter()
|
||||
lootFrame:Raise()
|
||||
E:DisableMover('LootFrameMover')
|
||||
else
|
||||
lootFrame:ClearAllPoints()
|
||||
lootFrame:Point('TOPLEFT', lootFrameHolder, 'TOPLEFT')
|
||||
E:EnableMover('LootFrameMover')
|
||||
end
|
||||
|
||||
local m, w, t = 0, 0, lootFrame.title:GetStringWidth()
|
||||
local items = GetNumLootItems()
|
||||
if items > 0 then
|
||||
for i=1, items do
|
||||
local slot = lootFrame.slots[i] or createSlot(i)
|
||||
local textureID, item, quantity, _, quality, _, isQuestItem, questId, isActive = GetLootSlotInfo(i)
|
||||
local color = ITEM_QUALITY_COLORS[quality]
|
||||
|
||||
if coinTextureIDs[textureID] then
|
||||
item = item:gsub('\n', ', ')
|
||||
end
|
||||
|
||||
if quantity and (quantity > 1) then
|
||||
slot.count:SetText(quantity)
|
||||
slot.count:Show()
|
||||
else
|
||||
slot.count:Hide()
|
||||
end
|
||||
|
||||
if quality and (quality > 1) then
|
||||
slot.drop:SetVertexColor(color.r, color.g, color.b)
|
||||
slot.drop:Show()
|
||||
else
|
||||
slot.drop:Hide()
|
||||
end
|
||||
|
||||
slot.quality = quality
|
||||
slot.name:SetText(item)
|
||||
if color then
|
||||
slot.name:SetTextColor(color.r, color.g, color.b)
|
||||
end
|
||||
slot.icon:SetTexture(textureID)
|
||||
|
||||
if quality then
|
||||
m = max(m, quality)
|
||||
end
|
||||
w = max(w, slot.name:GetStringWidth())
|
||||
|
||||
local questTexture = slot.questTexture
|
||||
if questId and not isActive then
|
||||
questTexture:Show()
|
||||
LBG.ShowOverlayGlow(slot.iconFrame)
|
||||
elseif questId or isQuestItem then
|
||||
questTexture:Hide()
|
||||
LBG.ShowOverlayGlow(slot.iconFrame)
|
||||
else
|
||||
questTexture:Hide()
|
||||
LBG.HideOverlayGlow(slot.iconFrame)
|
||||
end
|
||||
|
||||
-- Check for FasterLooting scripts or w/e (if bag is full)
|
||||
if textureID then
|
||||
slot:Enable()
|
||||
slot:Show()
|
||||
end
|
||||
end
|
||||
else
|
||||
local slot = lootFrame.slots[1] or createSlot(1)
|
||||
local color = ITEM_QUALITY_COLORS[0]
|
||||
|
||||
slot.name:SetText(L["Empty Slot"])
|
||||
if color then
|
||||
slot.name:SetTextColor(color.r, color.g, color.b)
|
||||
end
|
||||
slot.icon:SetTexture[[Interface\Icons\INV_Misc_Herb_AncientLichen]]
|
||||
|
||||
w = max(w, slot.name:GetStringWidth())
|
||||
|
||||
slot.count:Hide()
|
||||
slot.drop:Hide()
|
||||
slot:Disable()
|
||||
slot:Show()
|
||||
end
|
||||
anchorSlots(lootFrame)
|
||||
|
||||
w = w + 60
|
||||
t = t + 5
|
||||
|
||||
local color = ITEM_QUALITY_COLORS[m]
|
||||
lootFrame:SetBackdropBorderColor(color.r, color.g, color.b, .8)
|
||||
lootFrame:Width(max(w, t))
|
||||
end
|
||||
|
||||
function M:LoadLoot()
|
||||
if not E.private.general.loot then return end
|
||||
lootFrameHolder = CreateFrame('Frame', 'ElvLootFrameHolder', E.UIParent)
|
||||
lootFrameHolder:Point('TOPLEFT', E.UIParent, 'TOPLEFT', 418, -186)
|
||||
lootFrameHolder:Size(150, 22)
|
||||
|
||||
lootFrame = CreateFrame('Button', 'ElvLootFrame', lootFrameHolder, 'BackdropTemplate')
|
||||
lootFrame:SetClampedToScreen(true)
|
||||
lootFrame:Point('TOPLEFT')
|
||||
lootFrame:Size(256, 64)
|
||||
lootFrame:SetTemplate('Transparent')
|
||||
lootFrame:SetFrameStrata(_G.LootFrame:GetFrameStrata())
|
||||
lootFrame:SetToplevel(true)
|
||||
lootFrame.title = lootFrame:CreateFontString(nil, 'OVERLAY')
|
||||
lootFrame.title:FontTemplate(nil, nil, 'OUTLINE')
|
||||
lootFrame.title:Point('BOTTOMLEFT', lootFrame, 'TOPLEFT', 0, 1)
|
||||
lootFrame.slots = {}
|
||||
lootFrame:SetScript('OnHide', function()
|
||||
StaticPopup_Hide('CONFIRM_LOOT_DISTRIBUTION')
|
||||
CloseLoot()
|
||||
end)
|
||||
E.frames[lootFrame] = nil
|
||||
|
||||
self:RegisterEvent('LOOT_OPENED')
|
||||
self:RegisterEvent('LOOT_SLOT_CLEARED')
|
||||
self:RegisterEvent('LOOT_CLOSED')
|
||||
|
||||
E:CreateMover(lootFrameHolder, 'LootFrameMover', L["Loot Frame"], nil, nil, nil, nil, nil, 'general,blizzUIImprovements')
|
||||
|
||||
-- Fuzz
|
||||
_G.LootFrame:UnregisterAllEvents()
|
||||
tinsert(_G.UISpecialFrames, 'ElvLootFrame')
|
||||
end
|
||||
321
Modules/Misc/LootRoll.lua
Normal file
321
Modules/Misc/LootRoll.lua
Normal file
@@ -0,0 +1,321 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local M = E:GetModule('Misc')
|
||||
|
||||
local _G = _G
|
||||
local pairs, unpack, ipairs, next, tonumber, tinsert = pairs, unpack, ipairs, next, tonumber, tinsert
|
||||
|
||||
local ChatEdit_InsertLink = ChatEdit_InsertLink
|
||||
local CreateFrame = CreateFrame
|
||||
local CursorOnUpdate = CursorOnUpdate
|
||||
local DressUpItemLink = DressUpItemLink
|
||||
local GameTooltip_ShowCompareItem = GameTooltip_ShowCompareItem
|
||||
local IsPlayerAtEffectiveMaxLevel = IsPlayerAtEffectiveMaxLevel
|
||||
local GetLootRollItemInfo = GetLootRollItemInfo
|
||||
local GetLootRollItemLink = GetLootRollItemLink
|
||||
local GetLootRollTimeLeft = GetLootRollTimeLeft
|
||||
local ShowInspectCursor = ShowInspectCursor
|
||||
local IsControlKeyDown = IsControlKeyDown
|
||||
local IsModifiedClick = IsModifiedClick
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local ResetCursor = ResetCursor
|
||||
local RollOnLoot = RollOnLoot
|
||||
|
||||
local C_LootHistoryGetItem = C_LootHistory.GetItem
|
||||
local C_LootHistoryGetPlayerInfo = C_LootHistory.GetPlayerInfo
|
||||
local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
|
||||
local GREED, NEED, PASS = GREED, NEED, PASS
|
||||
local ROLL_DISENCHANT = ROLL_DISENCHANT
|
||||
|
||||
local pos = 'TOP';
|
||||
local cancelled_rolls = {}
|
||||
local cachedRolls = {}
|
||||
local completedRolls = {}
|
||||
local FRAME_WIDTH, FRAME_HEIGHT = 328, 28
|
||||
M.RollBars = {}
|
||||
|
||||
local function ClickRoll(frame)
|
||||
RollOnLoot(frame.parent.rollID, frame.rolltype)
|
||||
end
|
||||
|
||||
local function HideTip() _G.GameTooltip:Hide() end
|
||||
local function HideTip2() _G.GameTooltip:Hide(); ResetCursor() end
|
||||
|
||||
local rolltypes = {[1] = 'need', [2] = 'greed', [3] = 'disenchant', [0] = 'pass'}
|
||||
local function SetTip(frame)
|
||||
local GameTooltip = _G.GameTooltip
|
||||
GameTooltip:SetOwner(frame, 'ANCHOR_RIGHT')
|
||||
GameTooltip:SetText(frame.tiptext)
|
||||
if frame:IsEnabled() == 0 then GameTooltip:AddLine('|cffff3333'..L["Can't Roll"]) end
|
||||
for name, tbl in pairs(frame.parent.rolls) do
|
||||
if rolltypes[tbl[1]] == rolltypes[frame.rolltype] then
|
||||
local classColor = E:ClassColor(tbl[2])
|
||||
GameTooltip:AddLine(name, classColor.r, classColor.g, classColor.b)
|
||||
end
|
||||
end
|
||||
GameTooltip:Show()
|
||||
end
|
||||
|
||||
local function SetItemTip(frame)
|
||||
if not frame.link then return end
|
||||
_G.GameTooltip:SetOwner(frame, 'ANCHOR_TOPLEFT')
|
||||
_G.GameTooltip:SetHyperlink(frame.link)
|
||||
|
||||
if IsShiftKeyDown() then GameTooltip_ShowCompareItem() end
|
||||
if IsModifiedClick('DRESSUP') then ShowInspectCursor() else ResetCursor() end
|
||||
end
|
||||
|
||||
local function ItemOnUpdate(self)
|
||||
if IsShiftKeyDown() then GameTooltip_ShowCompareItem() end
|
||||
CursorOnUpdate(self)
|
||||
end
|
||||
|
||||
local function LootClick(frame)
|
||||
if IsControlKeyDown() then DressUpItemLink(frame.link)
|
||||
elseif IsShiftKeyDown() then ChatEdit_InsertLink(frame.link) end
|
||||
end
|
||||
|
||||
local function OnEvent(frame, _, rollID)
|
||||
cancelled_rolls[rollID] = true
|
||||
if frame.rollID ~= rollID then return end
|
||||
|
||||
frame.rollID = nil
|
||||
frame.time = nil
|
||||
frame:Hide()
|
||||
end
|
||||
|
||||
local function StatusUpdate(frame)
|
||||
if not frame.parent.rollID then return end
|
||||
local t = GetLootRollTimeLeft(frame.parent.rollID)
|
||||
local perc = t / frame.parent.time
|
||||
frame.spark:Point('CENTER', frame, 'LEFT', perc * frame:GetWidth(), 0)
|
||||
frame:SetValue(t)
|
||||
|
||||
if t > 1000000000 then
|
||||
frame:GetParent():Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local function CreateRollButton(parent, ntex, ptex, htex, rolltype, tiptext, ...)
|
||||
local f = CreateFrame('Button', nil, parent)
|
||||
f:Point(...)
|
||||
f:Size(FRAME_HEIGHT - 4)
|
||||
f:SetNormalTexture(ntex)
|
||||
if ptex then f:SetPushedTexture(ptex) end
|
||||
f:SetHighlightTexture(htex)
|
||||
f.rolltype = rolltype
|
||||
f.parent = parent
|
||||
f.tiptext = tiptext
|
||||
f:SetScript('OnEnter', SetTip)
|
||||
f:SetScript('OnLeave', HideTip)
|
||||
f:SetScript('OnClick', ClickRoll)
|
||||
f:SetMotionScriptsWhileDisabled(true)
|
||||
local txt = f:CreateFontString(nil, 'ARTWORK')
|
||||
txt:FontTemplate(nil, nil, 'OUTLINE')
|
||||
txt:Point('CENTER', 0, rolltype == 2 and 1 or rolltype == 0 and -1.2 or 0)
|
||||
return f, txt
|
||||
end
|
||||
|
||||
function M:CreateRollFrame()
|
||||
local frame = CreateFrame('Frame', nil, E.UIParent, 'BackdropTemplate')
|
||||
frame:Size(FRAME_WIDTH, FRAME_HEIGHT)
|
||||
frame:SetTemplate()
|
||||
frame:SetScript('OnEvent', OnEvent)
|
||||
frame:SetFrameStrata('MEDIUM')
|
||||
frame:SetFrameLevel(10)
|
||||
frame:RegisterEvent('CANCEL_LOOT_ROLL')
|
||||
frame:Hide()
|
||||
|
||||
local button = CreateFrame('Button', nil, frame)
|
||||
button:Point('RIGHT', frame, 'LEFT', -(E.Spacing*3), 0)
|
||||
button:Size(FRAME_HEIGHT - (E.Border * 2), FRAME_HEIGHT - (E.Border * 2))
|
||||
button:CreateBackdrop()
|
||||
button:SetScript('OnEnter', SetItemTip)
|
||||
button:SetScript('OnLeave', HideTip2)
|
||||
button:SetScript('OnUpdate', ItemOnUpdate)
|
||||
button:SetScript('OnClick', LootClick)
|
||||
frame.button = button
|
||||
|
||||
button.icon = button:CreateTexture(nil, 'OVERLAY')
|
||||
button.icon:SetAllPoints()
|
||||
button.icon:SetTexCoord(unpack(E.TexCoords))
|
||||
|
||||
local tfade = frame:CreateTexture(nil, 'BORDER')
|
||||
tfade:Point('TOPLEFT', frame, 'TOPLEFT', 4, 0)
|
||||
tfade:Point('BOTTOMRIGHT', frame, 'BOTTOMRIGHT', -4, 0)
|
||||
tfade:SetTexture([[Interface\ChatFrame\ChatFrameBackground]])
|
||||
tfade:SetBlendMode('ADD')
|
||||
tfade:SetGradientAlpha('VERTICAL', .1, .1, .1, 0, .1, .1, .1, 0)
|
||||
|
||||
local status = CreateFrame('StatusBar', nil, frame)
|
||||
status:SetInside()
|
||||
status:SetScript('OnUpdate', StatusUpdate)
|
||||
status:SetFrameLevel(status:GetFrameLevel()-1)
|
||||
status:SetStatusBarTexture(E.media.normTex)
|
||||
E:RegisterStatusBar(status)
|
||||
status:SetStatusBarColor(.8, .8, .8, .9)
|
||||
status.parent = frame
|
||||
frame.status = status
|
||||
|
||||
status.bg = status:CreateTexture(nil, 'BACKGROUND')
|
||||
status.bg:SetAlpha(0.1)
|
||||
status.bg:SetAllPoints()
|
||||
status.bg:SetDrawLayer('BACKGROUND', 2)
|
||||
local spark = frame:CreateTexture(nil, 'OVERLAY')
|
||||
spark:Size(14, FRAME_HEIGHT)
|
||||
spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
|
||||
spark:SetBlendMode('ADD')
|
||||
status.spark = spark
|
||||
|
||||
local need, needtext = CreateRollButton(frame, [[Interface\Buttons\UI-GroupLoot-Dice-Up]], [[Interface\Buttons\UI-GroupLoot-Dice-Highlight]], [[Interface\Buttons\UI-GroupLoot-Dice-Down]], 1, NEED, 'LEFT', frame.button, 'RIGHT', 5, -1)
|
||||
local greed, greedtext = CreateRollButton(frame, [[Interface\Buttons\UI-GroupLoot-Coin-Up]], [[Interface\Buttons\UI-GroupLoot-Coin-Highlight]], [[Interface\Buttons\UI-GroupLoot-Coin-Down]], 2, GREED, 'LEFT', need, 'RIGHT', 0, -1)
|
||||
local de, detext
|
||||
de, detext = CreateRollButton(frame, [[Interface\Buttons\UI-GroupLoot-DE-Up]], [[Interface\Buttons\UI-GroupLoot-DE-Highlight]], [[Interface\Buttons\UI-GroupLoot-DE-Down]], 3, ROLL_DISENCHANT, 'LEFT', greed, 'RIGHT', 0, -1)
|
||||
local pass, passtext = CreateRollButton(frame, [[Interface\Buttons\UI-GroupLoot-Pass-Up]], nil, [[Interface\Buttons\UI-GroupLoot-Pass-Down]], 0, PASS, 'LEFT', de or greed, 'RIGHT', 0, 2)
|
||||
frame.needbutt, frame.greedbutt, frame.disenchantbutt = need, greed, de
|
||||
frame.need, frame.greed, frame.pass, frame.disenchant = needtext, greedtext, passtext, detext
|
||||
|
||||
local bind = frame:CreateFontString(nil, 'ARTWORK')
|
||||
bind:Point('LEFT', pass, 'RIGHT', 3, 1)
|
||||
bind:FontTemplate(nil, nil, 'OUTLINE')
|
||||
frame.fsbind = bind
|
||||
|
||||
local loot = frame:CreateFontString(nil, 'ARTWORK')
|
||||
loot:FontTemplate(nil, nil, 'OUTLINE')
|
||||
loot:Point('LEFT', bind, 'RIGHT', 0, 0)
|
||||
loot:Point('RIGHT', frame, 'RIGHT', -5, 0)
|
||||
loot:Size(200, 10)
|
||||
loot:SetJustifyH('LEFT')
|
||||
frame.fsloot = loot
|
||||
|
||||
frame.rolls = {}
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
local function GetFrame()
|
||||
for _,f in ipairs(M.RollBars) do
|
||||
if not f.rollID then return f end
|
||||
end
|
||||
|
||||
local f = M:CreateRollFrame()
|
||||
if pos == 'TOP' then
|
||||
f:Point('TOP', next(M.RollBars) and M.RollBars[#M.RollBars] or _G.AlertFrameHolder, 'BOTTOM', 0, -4)
|
||||
else
|
||||
f:Point('BOTTOM', next(M.RollBars) and M.RollBars[#M.RollBars] or _G.AlertFrameHolder, 'TOP', 0, 4)
|
||||
end
|
||||
tinsert(M.RollBars, f)
|
||||
return f
|
||||
end
|
||||
|
||||
function M:START_LOOT_ROLL(_, rollID, time)
|
||||
if cancelled_rolls[rollID] then return end
|
||||
local f = GetFrame()
|
||||
f.rollID = rollID
|
||||
f.time = time
|
||||
for i in pairs(f.rolls) do f.rolls[i] = nil end
|
||||
f.need:SetText(0)
|
||||
f.greed:SetText(0)
|
||||
f.pass:SetText(0)
|
||||
f.disenchant:SetText(0)
|
||||
|
||||
local texture, name, _, quality, bop, canNeed, canGreed, canDisenchant = GetLootRollItemInfo(rollID)
|
||||
f.button.icon:SetTexture(texture)
|
||||
f.button.link = GetLootRollItemLink(rollID)
|
||||
|
||||
if canNeed then f.needbutt:Enable() else f.needbutt:Disable() end
|
||||
if canGreed then f.greedbutt:Enable() else f.greedbutt:Disable() end
|
||||
if canDisenchant then f.disenchantbutt:Enable() else f.disenchantbutt:Disable() end
|
||||
|
||||
local needTexture = f.needbutt:GetNormalTexture()
|
||||
local greenTexture = f.greedbutt:GetNormalTexture()
|
||||
local disenchantTexture = f.disenchantbutt:GetNormalTexture()
|
||||
needTexture:SetDesaturation(not canNeed)
|
||||
greenTexture:SetDesaturation(not canGreed)
|
||||
disenchantTexture:SetDesaturation(not canDisenchant)
|
||||
|
||||
if canNeed then f.needbutt:SetAlpha(1) else f.needbutt:SetAlpha(0.2) end
|
||||
if canGreed then f.greedbutt:SetAlpha(1) else f.greedbutt:SetAlpha(0.2) end
|
||||
if canDisenchant then f.disenchantbutt:SetAlpha(1) else f.disenchantbutt:SetAlpha(0.2) end
|
||||
|
||||
f.fsbind:SetText(bop and L["BoP"] or L["BoE"])
|
||||
f.fsbind:SetVertexColor(bop and 1 or .3, bop and .3 or 1, bop and .1 or .3)
|
||||
|
||||
local color = ITEM_QUALITY_COLORS[quality]
|
||||
f.fsloot:SetText(name)
|
||||
f.status:SetStatusBarColor(color.r, color.g, color.b, .7)
|
||||
f.status.bg:SetColorTexture(color.r, color.g, color.b)
|
||||
|
||||
f.status:SetMinMaxValues(0, time)
|
||||
f.status:SetValue(time)
|
||||
|
||||
f:Point('CENTER', _G.WorldFrame, 'CENTER')
|
||||
f:Show()
|
||||
_G.AlertFrame:UpdateAnchors()
|
||||
|
||||
--Add cached roll info, if any
|
||||
for rollid, rollTable in pairs(cachedRolls) do
|
||||
if f.rollID == rollid then --rollid matches cached rollid
|
||||
for rollerName, rollerInfo in pairs(rollTable) do
|
||||
local rollType, class = rollerInfo[1], rollerInfo[2]
|
||||
f.rolls[rollerName] = {rollType, class}
|
||||
f[rolltypes[rollType]]:SetText(tonumber(f[rolltypes[rollType]]:GetText()) + 1)
|
||||
end
|
||||
completedRolls[rollid] = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if E.db.general.autoRoll and IsPlayerAtEffectiveMaxLevel() and quality == 2 and not bop then
|
||||
if canDisenchant then
|
||||
RollOnLoot(rollID, 3)
|
||||
else
|
||||
RollOnLoot(rollID, 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:LOOT_HISTORY_ROLL_CHANGED(_, itemIdx, playerIdx)
|
||||
local rollID = C_LootHistoryGetItem(itemIdx);
|
||||
local name, class, rollType = C_LootHistoryGetPlayerInfo(itemIdx, playerIdx);
|
||||
|
||||
local rollIsHidden = true
|
||||
if name and rollType then
|
||||
for _,f in ipairs(M.RollBars) do
|
||||
if f.rollID == rollID then
|
||||
f.rolls[name] = {rollType, class}
|
||||
f[rolltypes[rollType]]:SetText(tonumber(f[rolltypes[rollType]]:GetText()) + 1)
|
||||
rollIsHidden = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
--History changed for a loot roll that hasn't popped up for the player yet, so cache it for later
|
||||
if rollIsHidden then
|
||||
cachedRolls[rollID] = cachedRolls[rollID] or {}
|
||||
if not cachedRolls[rollID][name] then
|
||||
cachedRolls[rollID][name] = {rollType, class}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:LOOT_HISTORY_ROLL_COMPLETE()
|
||||
--Remove completed rolls from cache
|
||||
for rollID in pairs(completedRolls) do
|
||||
cachedRolls[rollID] = nil
|
||||
completedRolls[rollID] = nil
|
||||
end
|
||||
end
|
||||
M.LOOT_ROLLS_COMPLETE = M.LOOT_HISTORY_ROLL_COMPLETE
|
||||
|
||||
function M:LoadLootRoll()
|
||||
if not E.private.general.lootRoll then return end
|
||||
|
||||
self:RegisterEvent('LOOT_HISTORY_ROLL_CHANGED')
|
||||
self:RegisterEvent('LOOT_HISTORY_ROLL_COMPLETE')
|
||||
self:RegisterEvent('START_LOOT_ROLL')
|
||||
self:RegisterEvent('LOOT_ROLLS_COMPLETE')
|
||||
|
||||
_G.UIParent:UnregisterEvent('START_LOOT_ROLL')
|
||||
_G.UIParent:UnregisterEvent('CANCEL_LOOT_ROLL')
|
||||
end
|
||||
382
Modules/Misc/Misc.lua
Normal file
382
Modules/Misc/Misc.lua
Normal file
@@ -0,0 +1,382 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local M = E:GetModule('Misc')
|
||||
local Bags = E:GetModule('Bags')
|
||||
|
||||
local _G = _G
|
||||
local select = select
|
||||
local format = format
|
||||
|
||||
local CreateFrame = CreateFrame
|
||||
local AcceptGroup = AcceptGroup
|
||||
local C_FriendList_IsFriend = C_FriendList.IsFriend
|
||||
local CanGuildBankRepair = CanGuildBankRepair
|
||||
local CanMerchantRepair = CanMerchantRepair
|
||||
local GetCVarBool, SetCVar = GetCVarBool, SetCVar
|
||||
local GetGuildBankWithdrawMoney = GetGuildBankWithdrawMoney
|
||||
local GetInstanceInfo = GetInstanceInfo
|
||||
local GetItemInfo = GetItemInfo
|
||||
local GetNumGroupMembers = GetNumGroupMembers
|
||||
local GetQuestItemInfo = GetQuestItemInfo
|
||||
local GetQuestItemLink = GetQuestItemLink
|
||||
local GetNumQuestChoices = GetNumQuestChoices
|
||||
local GetRaidRosterInfo = GetRaidRosterInfo
|
||||
local GetRepairAllCost = GetRepairAllCost
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local IsActiveBattlefieldArena = IsActiveBattlefieldArena
|
||||
local IsAddOnLoaded = IsAddOnLoaded
|
||||
local IsArenaSkirmish = IsArenaSkirmish
|
||||
local IsGuildMember = IsGuildMember
|
||||
local IsInGroup = IsInGroup
|
||||
local IsInRaid = IsInRaid
|
||||
local IsPartyLFG = IsPartyLFG
|
||||
local IsShiftKeyDown = IsShiftKeyDown
|
||||
local RaidNotice_AddMessage = RaidNotice_AddMessage
|
||||
local RepairAllItems = RepairAllItems
|
||||
local SendChatMessage = SendChatMessage
|
||||
local StaticPopup_Hide = StaticPopup_Hide
|
||||
local StaticPopupSpecial_Hide = StaticPopupSpecial_Hide
|
||||
local UninviteUnit = UninviteUnit
|
||||
local UnitExists = UnitExists
|
||||
local UnitGUID = UnitGUID
|
||||
local UnitInRaid = UnitInRaid
|
||||
local UnitName = UnitName
|
||||
local IsInGuild = IsInGuild
|
||||
local PlaySound = PlaySound
|
||||
local GetNumFactions = GetNumFactions
|
||||
local GetFactionInfo = GetFactionInfo
|
||||
local GetWatchedFactionInfo = GetWatchedFactionInfo
|
||||
local ExpandAllFactionHeaders = ExpandAllFactionHeaders
|
||||
local SetWatchedFactionIndex = SetWatchedFactionIndex
|
||||
local GetCurrentCombatTextEventInfo = GetCurrentCombatTextEventInfo
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
|
||||
local C_PartyInfo_LeaveParty = C_PartyInfo.LeaveParty
|
||||
local C_BattleNet_GetGameAccountInfoByGUID = C_BattleNet.GetGameAccountInfoByGUID
|
||||
local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
|
||||
local LE_GAME_ERR_GUILD_NOT_ENOUGH_MONEY = LE_GAME_ERR_GUILD_NOT_ENOUGH_MONEY
|
||||
local LE_GAME_ERR_NOT_ENOUGH_MONEY = LE_GAME_ERR_NOT_ENOUGH_MONEY
|
||||
local MAX_PARTY_MEMBERS = MAX_PARTY_MEMBERS
|
||||
|
||||
local BOOST_THANKSFORPLAYING_SMALLER = SOUNDKIT.UI_70_BOOST_THANKSFORPLAYING_SMALLER
|
||||
local INTERRUPT_MSG = L["Interrupted %s's \124cff71d5ff\124Hspell:%d:0\124h[%s]\124h\124r!"]
|
||||
|
||||
function M:ErrorFrameToggle(event)
|
||||
if not E.db.general.hideErrorFrame then return end
|
||||
if event == 'PLAYER_REGEN_DISABLED' then
|
||||
_G.UIErrorsFrame:UnregisterEvent('UI_ERROR_MESSAGE')
|
||||
else
|
||||
_G.UIErrorsFrame:RegisterEvent('UI_ERROR_MESSAGE')
|
||||
end
|
||||
end
|
||||
|
||||
function M:COMBAT_LOG_EVENT_UNFILTERED()
|
||||
local inGroup = IsInGroup()
|
||||
if not inGroup then return end
|
||||
|
||||
local _, event, _, sourceGUID, _, _, _, destGUID, destName, _, _, _, _, _, spellID, spellName = CombatLogGetCurrentEventInfo()
|
||||
local announce = event == 'SPELL_INTERRUPT' and (sourceGUID == E.myguid or sourceGUID == UnitGUID('pet')) and destGUID ~= E.myguid
|
||||
if not announce then return end -- No announce-able interrupt from player or pet, exit.
|
||||
local inRaid, inPartyLFG = IsInRaid(), IsPartyLFG()
|
||||
|
||||
--Skirmish/non-rated arenas need to use INSTANCE_CHAT but IsPartyLFG() returns 'false'
|
||||
local _, instanceType = GetInstanceInfo()
|
||||
if instanceType == 'arena' then
|
||||
local skirmish = IsArenaSkirmish()
|
||||
local _, isRegistered = IsActiveBattlefieldArena()
|
||||
if skirmish or not isRegistered then
|
||||
inPartyLFG = true
|
||||
end
|
||||
inRaid = false --IsInRaid() returns true for arenas and they should not be considered a raid
|
||||
end
|
||||
|
||||
local channel, msg = E.db.general.interruptAnnounce, format(INTERRUPT_MSG, destName, spellID, spellName)
|
||||
if channel == 'PARTY' then
|
||||
SendChatMessage(msg, inPartyLFG and 'INSTANCE_CHAT' or 'PARTY')
|
||||
elseif channel == 'RAID' then
|
||||
SendChatMessage(msg, inPartyLFG and 'INSTANCE_CHAT' or (inRaid and 'RAID' or 'PARTY'))
|
||||
elseif channel == 'RAID_ONLY' and inRaid then
|
||||
SendChatMessage(msg, inPartyLFG and 'INSTANCE_CHAT' or 'RAID')
|
||||
elseif channel == 'SAY' and instanceType ~= 'none' then
|
||||
SendChatMessage(msg, 'SAY')
|
||||
elseif channel == 'YELL' and instanceType ~= 'none' then
|
||||
SendChatMessage(msg, 'YELL')
|
||||
elseif channel == 'EMOTE' then
|
||||
SendChatMessage(msg, 'EMOTE')
|
||||
end
|
||||
end
|
||||
|
||||
function M:COMBAT_TEXT_UPDATE(_, messagetype)
|
||||
if not E.db.general.autoTrackReputation then return end
|
||||
|
||||
if messagetype == 'FACTION' then
|
||||
local faction = GetCurrentCombatTextEventInfo()
|
||||
if faction ~= 'Guild' and faction ~= GetWatchedFactionInfo() then
|
||||
ExpandAllFactionHeaders()
|
||||
|
||||
for i = 1, GetNumFactions() do
|
||||
if faction == GetFactionInfo(i) then
|
||||
SetWatchedFactionIndex(i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do -- Auto Repair Functions
|
||||
local STATUS, TYPE, COST, POSS
|
||||
function M:AttemptAutoRepair(playerOverride)
|
||||
STATUS, TYPE, COST, POSS = '', E.db.general.autoRepair, GetRepairAllCost()
|
||||
|
||||
if POSS and COST > 0 then
|
||||
--This check evaluates to true even if the guild bank has 0 gold, so we add an override
|
||||
if IsInGuild() and TYPE == 'GUILD' and (playerOverride or (not CanGuildBankRepair() or COST > GetGuildBankWithdrawMoney())) then
|
||||
TYPE = 'PLAYER'
|
||||
end
|
||||
|
||||
RepairAllItems(TYPE == 'GUILD')
|
||||
|
||||
--Delay this a bit so we have time to catch the outcome of first repair attempt
|
||||
E:Delay(0.5, M.AutoRepairOutput)
|
||||
end
|
||||
end
|
||||
|
||||
function M:AutoRepairOutput()
|
||||
if TYPE == 'GUILD' then
|
||||
if STATUS == 'GUILD_REPAIR_FAILED' then
|
||||
M:AttemptAutoRepair(true) --Try using player money instead
|
||||
else
|
||||
E:Print(L["Your items have been repaired using guild bank funds for: "]..E:FormatMoney(COST, 'SMART', true)) --Amount, style, textOnly
|
||||
end
|
||||
elseif TYPE == 'PLAYER' then
|
||||
if STATUS == 'PLAYER_REPAIR_FAILED' then
|
||||
E:Print(L["You don't have enough money to repair."])
|
||||
else
|
||||
E:Print(L["Your items have been repaired for: "]..E:FormatMoney(COST, 'SMART', true)) --Amount, style, textOnly
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:UI_ERROR_MESSAGE(_, messageType)
|
||||
if messageType == LE_GAME_ERR_GUILD_NOT_ENOUGH_MONEY then
|
||||
STATUS = 'GUILD_REPAIR_FAILED'
|
||||
elseif messageType == LE_GAME_ERR_NOT_ENOUGH_MONEY then
|
||||
STATUS = 'PLAYER_REPAIR_FAILED'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:MERCHANT_CLOSED()
|
||||
self:UnregisterEvent('UI_ERROR_MESSAGE')
|
||||
self:UnregisterEvent('UPDATE_INVENTORY_DURABILITY')
|
||||
self:UnregisterEvent('MERCHANT_CLOSED')
|
||||
end
|
||||
|
||||
function M:MERCHANT_SHOW()
|
||||
if E.db.bags.vendorGrays.enable then E:Delay(0.5, Bags.VendorGrays, Bags) end
|
||||
|
||||
if E.db.general.autoRepair == 'NONE' or IsShiftKeyDown() or not CanMerchantRepair() then return end
|
||||
|
||||
--Prepare to catch 'not enough money' messages
|
||||
self:RegisterEvent('UI_ERROR_MESSAGE')
|
||||
|
||||
--Use this to unregister events afterwards
|
||||
self:RegisterEvent('MERCHANT_CLOSED')
|
||||
|
||||
M:AttemptAutoRepair()
|
||||
end
|
||||
|
||||
function M:DisbandRaidGroup()
|
||||
if InCombatLockdown() then return end -- Prevent user error in combat
|
||||
|
||||
if UnitInRaid('player') then
|
||||
for i = 1, GetNumGroupMembers() do
|
||||
local name, _, _, _, _, _, _, online = GetRaidRosterInfo(i)
|
||||
if online and name ~= E.myname then
|
||||
UninviteUnit(name)
|
||||
end
|
||||
end
|
||||
else
|
||||
for i = MAX_PARTY_MEMBERS, 1, -1 do
|
||||
if UnitExists('party'..i) then
|
||||
UninviteUnit(UnitName('party'..i))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
C_PartyInfo_LeaveParty()
|
||||
end
|
||||
|
||||
function M:PVPMessageEnhancement(_, msg)
|
||||
if not E.db.general.enhancedPvpMessages then return end
|
||||
local _, instanceType = GetInstanceInfo()
|
||||
if instanceType == 'pvp' or instanceType == 'arena' then
|
||||
RaidNotice_AddMessage(_G.RaidBossEmoteFrame, msg, _G.ChatTypeInfo.RAID_BOSS_EMOTE);
|
||||
end
|
||||
end
|
||||
|
||||
local hideStatic
|
||||
function M:AutoInvite(event, _, _, _, _, _, _, inviterGUID)
|
||||
if not E.db.general.autoAcceptInvite then return end
|
||||
|
||||
if event == 'PARTY_INVITE_REQUEST' then
|
||||
-- Prevent losing que inside LFD if someone invites you to group
|
||||
if _G.QueueStatusMinimapButton:IsShown() or IsInGroup() or (not inviterGUID or inviterGUID == '') then return end
|
||||
|
||||
if C_BattleNet_GetGameAccountInfoByGUID(inviterGUID) or C_FriendList_IsFriend(inviterGUID) or IsGuildMember(inviterGUID) then
|
||||
hideStatic = true
|
||||
AcceptGroup()
|
||||
end
|
||||
elseif event == 'GROUP_ROSTER_UPDATE' and hideStatic then
|
||||
StaticPopupSpecial_Hide(_G.LFGInvitePopup) --New LFD popup when invited in custom created group
|
||||
StaticPopup_Hide('PARTY_INVITE')
|
||||
hideStatic = nil
|
||||
end
|
||||
end
|
||||
|
||||
function M:ForceCVars()
|
||||
if not GetCVarBool('lockActionBars') and E.private.actionbar.enable then
|
||||
SetCVar('lockActionBars', 1)
|
||||
end
|
||||
end
|
||||
|
||||
function M:PLAYER_ENTERING_WORLD()
|
||||
self:ForceCVars()
|
||||
self:ToggleChatBubbleScript()
|
||||
end
|
||||
|
||||
--[[local function OnValueChanged(self, value)
|
||||
local bar = _G.ElvUI_ChallengeModeTimer
|
||||
bar.text:SetText(self:GetParent().TimeLeft:GetText())
|
||||
bar:SetValue(value)
|
||||
|
||||
local r, g, b = E:ColorGradient(value / self:GetParent().timeLimit, 1, 0, 0, 1, 1, 0, 0, 1, 0)
|
||||
bar:SetStatusBarColor(r, g, b)
|
||||
end
|
||||
|
||||
local function ChallengeModeTimer_Update(timerID, elapsedTime, timeLimit)
|
||||
local block = _G.ScenarioChallengeModeBlock;
|
||||
|
||||
_G.ElvUI_ChallengeModeTimer:SetMinMaxValues(0, block.timeLimit)
|
||||
_G.ElvUI_ChallengeModeTimer:Show()
|
||||
OnValueChanged(_G.ScenarioChallengeModeBlock.StatusBar, _G.ScenarioChallengeModeBlock.StatusBar:GetValue())
|
||||
end
|
||||
|
||||
function M:SetupChallengeTimer()
|
||||
local bar = CreateFrame('StatusBar', 'ElvUI_ChallengeModeTimer', E.UIParent)
|
||||
bar:Size(250, 20)
|
||||
bar:Point('TOPLEFT', E.UIParent, 'TOPLEFT', 10, -10)
|
||||
bar:CreateBackdrop('Transparent')
|
||||
bar:SetStatusBarTexture(E.media.normTex)
|
||||
bar.text = bar:CreateFontString(nil, 'OVERLAY')
|
||||
bar.text:Point('CENTER')
|
||||
bar.text:FontTemplate()
|
||||
|
||||
_G.ScenarioChallengeModeBlock.StatusBar:HookScript('OnValueChanged', OnValueChanged)
|
||||
hooksecurefunc('Scenario_ChallengeMode_ShowBlock', ChallengeModeTimer_Update)
|
||||
end]]
|
||||
|
||||
function M:RESURRECT_REQUEST()
|
||||
if E.db.general.resurrectSound then
|
||||
PlaySound(BOOST_THANKSFORPLAYING_SMALLER, 'Master')
|
||||
end
|
||||
end
|
||||
|
||||
function M:ADDON_LOADED(_, addon)
|
||||
if addon == 'Blizzard_InspectUI' then
|
||||
M:SetupInspectPageInfo()
|
||||
--[[elseif addon == 'Blizzard_ObjectiveTracker' then
|
||||
M:SetupChallengeTimer()]]
|
||||
end
|
||||
end
|
||||
|
||||
function M:QUEST_COMPLETE()
|
||||
if not E.db.general.questRewardMostValueIcon then return end
|
||||
|
||||
local firstItem = _G.QuestInfoRewardsFrameQuestInfoItem1
|
||||
if not firstItem then return end
|
||||
|
||||
local numQuests = GetNumQuestChoices()
|
||||
if numQuests < 2 then return end
|
||||
|
||||
local bestValue, bestItem = 0
|
||||
for i = 1, numQuests do
|
||||
local questLink = GetQuestItemLink('choice', i)
|
||||
local _, _, amount = GetQuestItemInfo('choice', i)
|
||||
local itemSellPrice = questLink and select(11, GetItemInfo(questLink))
|
||||
|
||||
local totalValue = (itemSellPrice and itemSellPrice * amount) or 0
|
||||
if totalValue > bestValue then
|
||||
bestValue = totalValue
|
||||
bestItem = i
|
||||
end
|
||||
end
|
||||
|
||||
if bestItem then
|
||||
local btn = _G['QuestInfoRewardsFrameQuestInfoItem'..bestItem]
|
||||
if btn and btn.type == 'choice' then
|
||||
M.QuestRewardGoldIconFrame:ClearAllPoints()
|
||||
M.QuestRewardGoldIconFrame:Point('TOPRIGHT', btn, 'TOPRIGHT', -2, -2)
|
||||
M.QuestRewardGoldIconFrame:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:Initialize()
|
||||
self.Initialized = true
|
||||
self:LoadRaidMarker()
|
||||
self:LoadLootRoll()
|
||||
self:LoadChatBubbles()
|
||||
self:LoadLoot()
|
||||
self:ToggleItemLevelInfo(true)
|
||||
self:RegisterEvent('MERCHANT_SHOW')
|
||||
self:RegisterEvent('RESURRECT_REQUEST')
|
||||
self:RegisterEvent('PLAYER_REGEN_DISABLED', 'ErrorFrameToggle')
|
||||
self:RegisterEvent('PLAYER_REGEN_ENABLED', 'ErrorFrameToggle')
|
||||
self:RegisterEvent('CHAT_MSG_BG_SYSTEM_HORDE', 'PVPMessageEnhancement')
|
||||
self:RegisterEvent('CHAT_MSG_BG_SYSTEM_ALLIANCE', 'PVPMessageEnhancement')
|
||||
self:RegisterEvent('CHAT_MSG_BG_SYSTEM_NEUTRAL', 'PVPMessageEnhancement')
|
||||
self:RegisterEvent('PARTY_INVITE_REQUEST', 'AutoInvite')
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', 'AutoInvite')
|
||||
self:RegisterEvent('CVAR_UPDATE', 'ForceCVars')
|
||||
self:RegisterEvent('COMBAT_TEXT_UPDATE')
|
||||
self:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
self:RegisterEvent('QUEST_COMPLETE')
|
||||
|
||||
do -- questRewardMostValueIcon
|
||||
local MostValue = CreateFrame('Frame', 'ElvUI_QuestRewardGoldIconFrame', _G.UIParent)
|
||||
MostValue:SetFrameStrata('HIGH')
|
||||
MostValue:Size(19)
|
||||
MostValue:Hide()
|
||||
|
||||
MostValue.Icon = MostValue:CreateTexture(nil, 'OVERLAY')
|
||||
MostValue.Icon:SetAllPoints(MostValue)
|
||||
MostValue.Icon:SetTexture([[Interface\MONEYFRAME\UI-GoldIcon]])
|
||||
|
||||
M.QuestRewardGoldIconFrame = MostValue
|
||||
|
||||
hooksecurefunc(_G.QuestFrameRewardPanel, 'Hide', function()
|
||||
if M.QuestRewardGoldIconFrame then
|
||||
M.QuestRewardGoldIconFrame:Hide()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if E.db.general.interruptAnnounce ~= 'NONE' then
|
||||
self:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED')
|
||||
end
|
||||
|
||||
if IsAddOnLoaded('Blizzard_InspectUI') then
|
||||
M:SetupInspectPageInfo()
|
||||
else
|
||||
self:RegisterEvent('ADDON_LOADED')
|
||||
end
|
||||
|
||||
--[[if IsAddOnLoaded('Blizzard_ObjectiveTracker') then
|
||||
M:SetupChallengeTimer()
|
||||
else
|
||||
self:RegisterEvent('ADDON_LOADED')
|
||||
end]]
|
||||
end
|
||||
|
||||
E:RegisterModule(M:GetName())
|
||||
109
Modules/Misc/RaidMarker.lua
Normal file
109
Modules/Misc/RaidMarker.lua
Normal file
@@ -0,0 +1,109 @@
|
||||
--Credit Baudzilla
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local M = E:GetModule('Misc')
|
||||
|
||||
local sin, cos, rad = math.sin, math.cos, rad -- sin~=math.sin, cos~=math.cos, rad==math.rad; why? who knows? :P
|
||||
|
||||
local CreateFrame = CreateFrame
|
||||
local GetNumGroupMembers = GetNumGroupMembers
|
||||
local UnitIsGroupLeader = UnitIsGroupLeader
|
||||
local UnitIsGroupAssistant = UnitIsGroupAssistant
|
||||
local IsInGroup, IsInRaid = IsInGroup, IsInRaid
|
||||
local UnitExists, UnitIsDead = UnitExists, UnitIsDead
|
||||
local GetCursorPosition = GetCursorPosition
|
||||
local PlaySound = PlaySound
|
||||
local SetRaidTarget = SetRaidTarget
|
||||
local SetRaidTargetIconTexture = SetRaidTargetIconTexture
|
||||
local UIErrorsFrame = UIErrorsFrame
|
||||
-- GLOBALS: RaidMark_HotkeyPressed
|
||||
|
||||
local ButtonIsDown
|
||||
|
||||
function M:RaidMarkCanMark()
|
||||
if not self.RaidMarkFrame then return false; end
|
||||
|
||||
if GetNumGroupMembers() > 0 then
|
||||
if UnitIsGroupLeader('player') or UnitIsGroupAssistant('player') then
|
||||
return true;
|
||||
elseif IsInGroup() and not IsInRaid() then
|
||||
return true;
|
||||
else
|
||||
UIErrorsFrame:AddMessage(L["You don't have permission to mark targets."], 1.0, 0.1, 0.1, 1.0);
|
||||
return false;
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function M:RaidMarkShowIcons()
|
||||
if not UnitExists('target') or UnitIsDead('target')then
|
||||
return;
|
||||
end
|
||||
local x, y = GetCursorPosition();
|
||||
local scale = E.UIParent:GetEffectiveScale();
|
||||
self.RaidMarkFrame:Point('CENTER', E.UIParent, 'BOTTOMLEFT', x / scale, y / scale);
|
||||
self.RaidMarkFrame:Show();
|
||||
end
|
||||
|
||||
function RaidMark_HotkeyPressed(keystate)
|
||||
ButtonIsDown = (keystate=='down') and M:RaidMarkCanMark();
|
||||
if ButtonIsDown and M.RaidMarkFrame then
|
||||
M:RaidMarkShowIcons();
|
||||
elseif M.RaidMarkFrame then
|
||||
M.RaidMarkFrame:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
function M:RaidMark_OnEvent()
|
||||
if ButtonIsDown and self.RaidMarkFrame then
|
||||
self:RaidMarkShowIcons();
|
||||
end
|
||||
end
|
||||
M:RegisterEvent('PLAYER_TARGET_CHANGED', 'RaidMark_OnEvent');
|
||||
|
||||
function M:RaidMarkButton_OnEnter()
|
||||
self.Texture:ClearAllPoints();
|
||||
self.Texture:Point('TOPLEFT', -10, 10);
|
||||
self.Texture:Point('BOTTOMRIGHT', 10, -10);
|
||||
end
|
||||
|
||||
function M:RaidMarkButton_OnLeave()
|
||||
self.Texture:SetAllPoints();
|
||||
end
|
||||
|
||||
function M:RaidMarkButton_OnClick(arg1)
|
||||
PlaySound(1115) --U_CHAT_SCROLL_BUTTON
|
||||
SetRaidTarget('target', (arg1~='RightButton') and self:GetID() or 0);
|
||||
self:GetParent():Hide();
|
||||
end
|
||||
|
||||
local ANG_RAD = rad(360) / 7
|
||||
function M:LoadRaidMarker()
|
||||
local marker = CreateFrame('Frame', nil, E.UIParent);
|
||||
marker:EnableMouse(true);
|
||||
marker:SetFrameStrata('DIALOG');
|
||||
marker:Size(100);
|
||||
|
||||
for i = 1, 8 do
|
||||
local button = CreateFrame('Button', 'RaidMarkIconButton'..i, marker);
|
||||
button:Size(40);
|
||||
button:SetID(i);
|
||||
button.Texture = button:CreateTexture(button:GetName()..'NormalTexture', 'ARTWORK');
|
||||
button.Texture:SetTexture([[Interface\TargetingFrame\UI-RaidTargetingIcons]]);
|
||||
button.Texture:SetAllPoints();
|
||||
SetRaidTargetIconTexture(button.Texture, i);
|
||||
button:RegisterForClicks('LeftbuttonUp','RightbuttonUp');
|
||||
button:SetScript('OnClick', M.RaidMarkButton_OnClick);
|
||||
button:SetScript('OnEnter', M.RaidMarkButton_OnEnter);
|
||||
button:SetScript('OnLeave', M.RaidMarkButton_OnLeave);
|
||||
if i == 8 then
|
||||
button:Point('CENTER');
|
||||
else
|
||||
local angle = ANG_RAD * (i - 1)
|
||||
button:Point('CENTER', sin(angle) * 60, cos(angle) * 60);
|
||||
end
|
||||
end
|
||||
|
||||
M.RaidMarkFrame = marker;
|
||||
end
|
||||
408
Modules/Misc/RaidUtility.lua
Normal file
408
Modules/Misc/RaidUtility.lua
Normal file
@@ -0,0 +1,408 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)) -- Import Functions/Constants, Config, Locales
|
||||
local RU = E:GetModule('RaidUtility')
|
||||
|
||||
local _G = _G
|
||||
local unpack, ipairs, pairs, next = unpack, ipairs, pairs, next
|
||||
local strfind, tinsert, wipe, sort = strfind, tinsert, wipe, sort
|
||||
|
||||
local IsInRaid = IsInRaid
|
||||
local CreateFrame = CreateFrame
|
||||
local DoReadyCheck = DoReadyCheck
|
||||
local GameTooltip_Hide = GameTooltip_Hide
|
||||
local GetInstanceInfo = GetInstanceInfo
|
||||
local GetNumGroupMembers = GetNumGroupMembers
|
||||
local GetRaidRosterInfo = GetRaidRosterInfo
|
||||
local GetTexCoordsForRole = GetTexCoordsForRole
|
||||
local InCombatLockdown = InCombatLockdown
|
||||
local InitiateRolePoll = InitiateRolePoll
|
||||
local SecureHandlerSetFrameRef = SecureHandlerSetFrameRef
|
||||
local SecureHandler_OnClick = SecureHandler_OnClick
|
||||
local ToggleFriendsFrame = ToggleFriendsFrame
|
||||
local UnitGroupRolesAssigned = UnitGroupRolesAssigned
|
||||
local UnitIsGroupAssistant = UnitIsGroupAssistant
|
||||
local UnitIsGroupLeader = UnitIsGroupLeader
|
||||
local C_PartyInfo_DoCountdown = C_PartyInfo.DoCountdown
|
||||
|
||||
local PRIEST_COLOR = RAID_CLASS_COLORS.PRIEST
|
||||
local NUM_RAID_GROUPS = NUM_RAID_GROUPS
|
||||
local PANEL_HEIGHT = 110
|
||||
local PANEL_WIDTH = 230
|
||||
local BUTTON_HEIGHT = 20
|
||||
|
||||
--Check if We are Raid Leader or Raid Officer
|
||||
function RU:CheckRaidStatus()
|
||||
if UnitIsGroupLeader('player') or UnitIsGroupAssistant('player') then
|
||||
local _, instanceType = GetInstanceInfo()
|
||||
return instanceType ~= 'pvp' and instanceType ~= 'arena'
|
||||
end
|
||||
end
|
||||
|
||||
--Change border when mouse is inside the button
|
||||
function RU:ButtonEnter()
|
||||
if self.backdrop then self = self.backdrop end
|
||||
self:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor))
|
||||
end
|
||||
|
||||
--Change border back to normal when mouse leaves button
|
||||
function RU:ButtonLeave()
|
||||
if self.backdrop then self = self.backdrop end
|
||||
self:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
||||
end
|
||||
|
||||
-- Function to create buttons in this module
|
||||
function RU:CreateUtilButton(name, parent, template, width, height, point, relativeto, point2, xOfs, yOfs, text, texture)
|
||||
local b = CreateFrame('Button', name, parent, template)
|
||||
b:Size(width, height)
|
||||
b:Point(point, relativeto, point2, xOfs, yOfs)
|
||||
b:HookScript('OnEnter', RU.ButtonEnter)
|
||||
b:HookScript('OnLeave', RU.ButtonLeave)
|
||||
b:SetTemplate(nil, true)
|
||||
|
||||
if text then
|
||||
local t = b:CreateFontString(nil, 'OVERLAY')
|
||||
t:FontTemplate()
|
||||
t:Point('CENTER', b, 'CENTER', 0, -1)
|
||||
t:SetJustifyH('CENTER')
|
||||
t:SetText(text)
|
||||
b:SetFontString(t)
|
||||
b.text = t
|
||||
elseif texture then
|
||||
local t = b:CreateTexture(nil, 'OVERLAY')
|
||||
t:SetTexture(texture)
|
||||
t:Point('TOPLEFT', b, 'TOPLEFT', 1, -1)
|
||||
t:Point('BOTTOMRIGHT', b, 'BOTTOMRIGHT', -1, 1)
|
||||
t.tex = texture
|
||||
b.texture = t
|
||||
end
|
||||
|
||||
RU.Buttons[name] = b
|
||||
return b
|
||||
end
|
||||
|
||||
function RU:UpdateMedia()
|
||||
for _, btn in pairs(RU.Buttons) do
|
||||
if btn.text then btn.text:FontTemplate() end
|
||||
if btn.texture then btn.texture:SetTexture(btn.texture.tex) end
|
||||
btn:SetTemplate(nil, true)
|
||||
end
|
||||
|
||||
if RU.MarkerButton then
|
||||
RU.MarkerButton:CreateBackdrop(nil, true)
|
||||
RU.MarkerButton.backdrop:SetAllPoints()
|
||||
end
|
||||
end
|
||||
|
||||
function RU:ToggleRaidUtil(event)
|
||||
if InCombatLockdown() then
|
||||
self:RegisterEvent('PLAYER_REGEN_ENABLED', 'ToggleRaidUtil')
|
||||
return
|
||||
end
|
||||
|
||||
local RaidUtilityPanel = _G.RaidUtilityPanel
|
||||
local RaidUtility_ShowButton = _G.RaidUtility_ShowButton
|
||||
if RU:CheckRaidStatus() then
|
||||
if RaidUtilityPanel.toggled == true then
|
||||
RaidUtility_ShowButton:Hide()
|
||||
RaidUtilityPanel:Show()
|
||||
else
|
||||
RaidUtility_ShowButton:Show()
|
||||
RaidUtilityPanel:Hide()
|
||||
end
|
||||
else
|
||||
RaidUtility_ShowButton:Hide()
|
||||
RaidUtilityPanel:Hide()
|
||||
end
|
||||
|
||||
if event == 'PLAYER_REGEN_ENABLED' then
|
||||
self:UnregisterEvent('PLAYER_REGEN_ENABLED', 'ToggleRaidUtil')
|
||||
elseif self.updateMedia and event == 'PLAYER_ENTERING_WORLD' then
|
||||
self:UpdateMedia()
|
||||
self.updateMedia = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Credits oRA3 for the RoleIcons
|
||||
local function sortColoredNames(a, b)
|
||||
return a:sub(11) < b:sub(11)
|
||||
end
|
||||
|
||||
local roleIconRoster = {}
|
||||
function RU:RoleOnEnter()
|
||||
wipe(roleIconRoster)
|
||||
|
||||
for i = 1, NUM_RAID_GROUPS do
|
||||
roleIconRoster[i] = {}
|
||||
end
|
||||
|
||||
local role = self.role
|
||||
local point = E:GetScreenQuadrant(_G.RaidUtility_ShowButton)
|
||||
local bottom = point and strfind(point, 'BOTTOM')
|
||||
local left = point and strfind(point, 'LEFT')
|
||||
|
||||
local anchor1 = (bottom and left and 'BOTTOMLEFT') or (bottom and 'BOTTOMRIGHT') or (left and 'TOPLEFT') or 'TOPRIGHT'
|
||||
local anchor2 = (bottom and left and 'BOTTOMRIGHT') or (bottom and 'BOTTOMLEFT') or (left and 'TOPRIGHT') or 'TOPLEFT'
|
||||
local anchorX = left and 2 or -2
|
||||
|
||||
local GameTooltip = _G.GameTooltip
|
||||
GameTooltip:SetOwner(E.UIParent, 'ANCHOR_NONE')
|
||||
GameTooltip:Point(anchor1, self, anchor2, anchorX, 0)
|
||||
GameTooltip:SetText(_G['INLINE_' .. role .. '_ICON'] .. _G[role])
|
||||
|
||||
local name, group, class, groupRole, color, coloredName, _
|
||||
for i = 1, GetNumGroupMembers() do
|
||||
name, _, group, _, _, class, _, _, _, _, _, groupRole = GetRaidRosterInfo(i)
|
||||
if name and groupRole == role then
|
||||
color = E:ClassColor(class, true) or PRIEST_COLOR
|
||||
coloredName = ('|cff%02x%02x%02x%s'):format(color.r * 255, color.g * 255, color.b * 255, name:gsub('%-.+', '*'))
|
||||
tinsert(roleIconRoster[group], coloredName)
|
||||
end
|
||||
end
|
||||
|
||||
for Group, list in ipairs(roleIconRoster) do
|
||||
sort(list, sortColoredNames)
|
||||
for _, Name in ipairs(list) do
|
||||
GameTooltip:AddLine(('[%d] %s'):format(Group, Name), 1, 1, 1)
|
||||
end
|
||||
roleIconRoster[Group] = nil
|
||||
end
|
||||
|
||||
GameTooltip:Show()
|
||||
end
|
||||
|
||||
function RU:PositionRoleIcons()
|
||||
local point = E:GetScreenQuadrant(_G.RaidUtility_ShowButton)
|
||||
local left = point and strfind(point, 'LEFT')
|
||||
_G.RaidUtilityRoleIcons:ClearAllPoints()
|
||||
if left then
|
||||
_G.RaidUtilityRoleIcons:Point('LEFT', _G.RaidUtilityPanel, 'RIGHT', -1, 0)
|
||||
else
|
||||
_G.RaidUtilityRoleIcons:Point('RIGHT', _G.RaidUtilityPanel, 'LEFT', 1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local count = {}
|
||||
local function UpdateIcons(self)
|
||||
if not IsInRaid() then
|
||||
self:Hide()
|
||||
return
|
||||
else
|
||||
self:Show()
|
||||
RU:PositionRoleIcons()
|
||||
end
|
||||
|
||||
wipe(count)
|
||||
|
||||
for i = 1, GetNumGroupMembers() do
|
||||
local role = UnitGroupRolesAssigned('raid'..i)
|
||||
if role and role ~= 'NONE' then
|
||||
count[role] = (count[role] or 0) + 1
|
||||
end
|
||||
end
|
||||
|
||||
for Role, icon in next, _G.RaidUtilityRoleIcons.icons do
|
||||
icon.count:SetText(count[Role] or 0)
|
||||
end
|
||||
end
|
||||
|
||||
function RU:Initialize()
|
||||
if E.private.general.raidUtility == false then return end
|
||||
self.Initialized = true
|
||||
self.updateMedia = true -- update fonts and textures on entering world once, used to set the custom media from a plugin
|
||||
self.Buttons = {}
|
||||
|
||||
local RaidUtilityPanel = CreateFrame('Frame', 'RaidUtilityPanel', E.UIParent, 'SecureHandlerBaseTemplate, BackdropTemplate')
|
||||
RaidUtilityPanel:SetScript('OnMouseUp', function(panel, ...) SecureHandler_OnClick(panel, '_onclick', ...) end)
|
||||
RaidUtilityPanel:SetTemplate('Transparent')
|
||||
RaidUtilityPanel:Size(PANEL_WIDTH, PANEL_HEIGHT)
|
||||
RaidUtilityPanel:Point('TOP', E.UIParent, 'TOP', -400, 1)
|
||||
RaidUtilityPanel:SetFrameLevel(3)
|
||||
RaidUtilityPanel.toggled = false
|
||||
RaidUtilityPanel:SetFrameStrata('HIGH')
|
||||
E.FrameLocks.RaidUtilityPanel = true
|
||||
|
||||
local ShowButton = self:CreateUtilButton('RaidUtility_ShowButton', E.UIParent, 'UIMenuButtonStretchTemplate, SecureHandlerClickTemplate, BackdropTemplate', 136, 18, 'TOP', E.UIParent, 'TOP', -400, E.Border, _G.RAID_CONTROL)
|
||||
SecureHandlerSetFrameRef(ShowButton, 'RaidUtilityPanel', RaidUtilityPanel)
|
||||
ShowButton:SetAttribute('_onclick', ([=[
|
||||
local raidUtil = self:GetFrameRef('RaidUtilityPanel')
|
||||
local closeButton = raidUtil:GetFrameRef('RaidUtility_CloseButton')
|
||||
|
||||
self:Hide()
|
||||
raidUtil:Show()
|
||||
|
||||
local point = self:GetPoint()
|
||||
local raidUtilPoint, closeButtonPoint, yOffset
|
||||
|
||||
if strfind(point, 'BOTTOM') then
|
||||
raidUtilPoint = 'BOTTOM'
|
||||
closeButtonPoint = 'TOP'
|
||||
yOffset = 1
|
||||
else
|
||||
raidUtilPoint = 'TOP'
|
||||
closeButtonPoint = 'BOTTOM'
|
||||
yOffset = -1
|
||||
end
|
||||
|
||||
yOffset = yOffset * (tonumber(%d))
|
||||
|
||||
raidUtil:ClearAllPoints()
|
||||
closeButton:ClearAllPoints()
|
||||
raidUtil:SetPoint(raidUtilPoint, self, raidUtilPoint)
|
||||
closeButton:SetPoint(raidUtilPoint, raidUtil, closeButtonPoint, 0, yOffset)
|
||||
]=]):format(-E.Border + E.Spacing*3))
|
||||
ShowButton:SetScript('OnMouseUp', function()
|
||||
RaidUtilityPanel.toggled = true
|
||||
RU:PositionRoleIcons()
|
||||
end)
|
||||
ShowButton:SetMovable(true)
|
||||
ShowButton:SetClampedToScreen(true)
|
||||
ShowButton:SetClampRectInsets(0, 0, -1, 1)
|
||||
ShowButton:RegisterForDrag('RightButton')
|
||||
ShowButton:SetFrameStrata('HIGH')
|
||||
ShowButton:SetScript('OnDragStart', function(sb)
|
||||
sb:StartMoving()
|
||||
end)
|
||||
ShowButton:SetScript('OnDragStop', function(sb)
|
||||
sb:StopMovingOrSizing()
|
||||
local point = sb:GetPoint()
|
||||
local xOffset = sb:GetCenter()
|
||||
local screenWidth = E.UIParent:GetWidth() / 2
|
||||
xOffset = xOffset - screenWidth
|
||||
sb:ClearAllPoints()
|
||||
if strfind(point, 'BOTTOM') then
|
||||
sb:Point('BOTTOM', E.UIParent, 'BOTTOM', xOffset, -1)
|
||||
else
|
||||
sb:Point('TOP', E.UIParent, 'TOP', xOffset, 1)
|
||||
end
|
||||
end)
|
||||
E.FrameLocks.RaidUtility_ShowButton = true
|
||||
|
||||
local CloseButton = self:CreateUtilButton('RaidUtility_CloseButton', RaidUtilityPanel, 'UIMenuButtonStretchTemplate, SecureHandlerClickTemplate, BackdropTemplate', 136, 18, 'TOP', RaidUtilityPanel, 'BOTTOM', 0, -1, _G.CLOSE)
|
||||
SecureHandlerSetFrameRef(CloseButton, 'RaidUtility_ShowButton', ShowButton)
|
||||
CloseButton:SetAttribute('_onclick', [=[self:GetParent():Hide(); self:GetFrameRef('RaidUtility_ShowButton'):Show();]=])
|
||||
CloseButton:SetScript('OnMouseUp', function() RaidUtilityPanel.toggled = false end)
|
||||
SecureHandlerSetFrameRef(RaidUtilityPanel, 'RaidUtility_CloseButton', CloseButton)
|
||||
|
||||
local RoleIcons = CreateFrame('Frame', 'RaidUtilityRoleIcons', RaidUtilityPanel, 'BackdropTemplate')
|
||||
RoleIcons:Point('LEFT', RaidUtilityPanel, 'RIGHT', -1, 0)
|
||||
RoleIcons:Size(36, PANEL_HEIGHT)
|
||||
RoleIcons:SetTemplate('Transparent')
|
||||
RoleIcons:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
RoleIcons:RegisterEvent('GROUP_ROSTER_UPDATE')
|
||||
RoleIcons:SetScript('OnEvent', UpdateIcons)
|
||||
RoleIcons.icons = {}
|
||||
|
||||
local roles = {'TANK', 'HEALER', 'DAMAGER'}
|
||||
for i, role in ipairs(roles) do
|
||||
local frame = CreateFrame('Frame', '$parent_'..role, RoleIcons)
|
||||
if i == 1 then
|
||||
frame:Point('TOP', 0, -5)
|
||||
else
|
||||
frame:Point('TOP', _G['RaidUtilityRoleIcons_'..roles[i-1]], 'BOTTOM', 0, -8)
|
||||
end
|
||||
|
||||
local texture = frame:CreateTexture(nil, 'OVERLAY')
|
||||
texture:SetTexture(E.Media.Textures.RoleIcons) --(337499)
|
||||
local texA, texB, texC, texD = GetTexCoordsForRole(role)
|
||||
texture:SetTexCoord(texA, texB, texC, texD)
|
||||
texture:Point('TOPLEFT', frame, 'TOPLEFT', -2, 2)
|
||||
texture:Point('BOTTOMRIGHT', frame, 'BOTTOMRIGHT', 2, -2)
|
||||
frame.texture = texture
|
||||
|
||||
local Count = frame:CreateFontString(nil, 'OVERLAY', 'GameFontHighlight')
|
||||
Count:Point('BOTTOMRIGHT', -2, 2)
|
||||
Count:SetText(0)
|
||||
frame.count = Count
|
||||
|
||||
frame.role = role
|
||||
frame:SetScript('OnEnter', RU.RoleOnEnter)
|
||||
frame:SetScript('OnLeave', GameTooltip_Hide)
|
||||
frame:Size(28)
|
||||
|
||||
RoleIcons.icons[role] = frame
|
||||
end
|
||||
|
||||
local BUTTON_WIDTH = PANEL_WIDTH - 20
|
||||
self:CreateUtilButton('DisbandRaidButton', RaidUtilityPanel, 'UIMenuButtonStretchTemplate, BackdropTemplate', BUTTON_WIDTH, BUTTON_HEIGHT, 'TOP', RaidUtilityPanel, 'TOP', 0, -5, L["Disband Group"])
|
||||
_G.DisbandRaidButton:SetScript('OnMouseUp', function()
|
||||
if RU:CheckRaidStatus() then
|
||||
E:StaticPopup_Show('DISBAND_RAID')
|
||||
end
|
||||
end)
|
||||
|
||||
self:CreateUtilButton('RoleCheckButton', RaidUtilityPanel, 'UIMenuButtonStretchTemplate, BackdropTemplate', BUTTON_WIDTH, BUTTON_HEIGHT, 'TOP', _G.DisbandRaidButton, 'BOTTOM', 0, -5, _G.ROLE_POLL)
|
||||
_G.RoleCheckButton:SetScript('OnMouseUp', function() if RU:CheckRaidStatus() then InitiateRolePoll() end end)
|
||||
|
||||
--[[self:CreateUtilButton('MainTankButton', RaidUtilityPanel, 'SecureActionButtonTemplate, UIMenuButtonStretchTemplate, BackdropTemplate', (DisbandRaidButton:GetWidth() / 2) - 2, BUTTON_HEIGHT, 'TOPLEFT', RoleCheckButton, 'BOTTOMLEFT', 0, -5, MAINTANK)
|
||||
MainTankButton:SetAttribute('type', 'maintank')
|
||||
MainTankButton:SetAttribute('unit', 'target')
|
||||
MainTankButton:SetAttribute('action', 'toggle')
|
||||
|
||||
self:CreateUtilButton('MainAssistButton', RaidUtilityPanel, 'SecureActionButtonTemplate, UIMenuButtonStretchTemplate, BackdropTemplate', (DisbandRaidButton:GetWidth() / 2) - 2, BUTTON_HEIGHT, 'TOPRIGHT', RoleCheckButton, 'BOTTOMRIGHT', 0, -5, MAINASSIST)
|
||||
MainAssistButton:SetAttribute('type', 'mainassist')
|
||||
MainAssistButton:SetAttribute('unit', 'target')
|
||||
MainAssistButton:SetAttribute('action', 'toggle')]]
|
||||
|
||||
self:CreateUtilButton('ReadyCheckButton', RaidUtilityPanel, 'UIMenuButtonStretchTemplate, BackdropTemplate', BUTTON_WIDTH * 0.79, BUTTON_HEIGHT, 'TOPLEFT', _G.RoleCheckButton, 'BOTTOMLEFT', 0, -5, _G.READY_CHECK)
|
||||
_G.ReadyCheckButton:SetScript('OnMouseUp', function() if RU:CheckRaidStatus() then DoReadyCheck() end end)
|
||||
|
||||
self:CreateUtilButton('RaidControlButton', RaidUtilityPanel, 'UIMenuButtonStretchTemplate, BackdropTemplate', BUTTON_WIDTH * 0.5, BUTTON_HEIGHT, 'TOPLEFT', _G.ReadyCheckButton, 'BOTTOMLEFT', 0, -5, L["Raid Menu"])
|
||||
_G.RaidControlButton:SetScript('OnMouseUp', function() ToggleFriendsFrame(3) end)
|
||||
|
||||
self:CreateUtilButton('RaidCountdownButton', RaidUtilityPanel, 'UIMenuButtonStretchTemplate, BackdropTemplate', BUTTON_WIDTH * 0.49, BUTTON_HEIGHT, 'TOPLEFT', _G.RaidControlButton, 'TOPRIGHT', 2, 0, _G.PLAYER_COUNTDOWN_BUTTON)
|
||||
_G.RaidCountdownButton:SetScript('OnMouseUp', function() C_PartyInfo_DoCountdown(10) end)
|
||||
|
||||
local buttons = {
|
||||
'DisbandRaidButton',
|
||||
'RoleCheckButton',
|
||||
'ReadyCheckButton',
|
||||
'RaidControlButton',
|
||||
'RaidCountdownButton',
|
||||
'RaidUtility_ShowButton',
|
||||
'RaidUtility_CloseButton'
|
||||
}
|
||||
|
||||
if _G.CompactRaidFrameManager then
|
||||
--Reposition/Resize and Reuse the World Marker Button
|
||||
tinsert(buttons, 'CompactRaidFrameManagerDisplayFrameLeaderOptionsRaidWorldMarkerButton')
|
||||
local marker = _G.CompactRaidFrameManagerDisplayFrameLeaderOptionsRaidWorldMarkerButton
|
||||
marker:SetParent('RaidUtilityPanel')
|
||||
marker:ClearAllPoints()
|
||||
marker:Point('TOPRIGHT', _G.RoleCheckButton, 'BOTTOMRIGHT', 0, -5)
|
||||
marker:Size(BUTTON_WIDTH * 0.2, BUTTON_HEIGHT)
|
||||
marker:HookScript('OnEnter', RU.ButtonEnter)
|
||||
marker:HookScript('OnLeave', RU.ButtonLeave)
|
||||
self.MarkerButton = marker
|
||||
|
||||
-- Since we steal the Marker Button for our utility panel, move the Ready Check button over a bit
|
||||
local readyCheck = _G.CompactRaidFrameManagerDisplayFrameLeaderOptionsInitiateReadyCheck
|
||||
readyCheck:ClearAllPoints()
|
||||
readyCheck:Point('BOTTOMLEFT', _G.CompactRaidFrameManagerDisplayFrameLockedModeToggle, 'TOPLEFT', 0, 1)
|
||||
readyCheck:Point('BOTTOMRIGHT', _G.CompactRaidFrameManagerDisplayFrameHiddenModeToggle, 'TOPRIGHT', 0, 1)
|
||||
self.ReadyCheck = readyCheck
|
||||
else
|
||||
E:StaticPopup_Show('WARNING_BLIZZARD_ADDONS')
|
||||
end
|
||||
|
||||
--Reskin Stuff
|
||||
for _, button in pairs(buttons) do
|
||||
local f = _G[button]
|
||||
f.BottomLeft:SetAlpha(0)
|
||||
f.BottomRight:SetAlpha(0)
|
||||
f.BottomMiddle:SetAlpha(0)
|
||||
f.TopMiddle:SetAlpha(0)
|
||||
f.TopLeft:SetAlpha(0)
|
||||
f.TopRight:SetAlpha(0)
|
||||
f.MiddleLeft:SetAlpha(0)
|
||||
f.MiddleRight:SetAlpha(0)
|
||||
f.MiddleMiddle:SetAlpha(0)
|
||||
|
||||
f:SetHighlightTexture('')
|
||||
f:SetDisabledTexture('')
|
||||
end
|
||||
|
||||
--Automatically show/hide the frame if we have RaidLeader or RaidOfficer
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', 'ToggleRaidUtil')
|
||||
self:RegisterEvent('PLAYER_ENTERING_WORLD', 'ToggleRaidUtil')
|
||||
end
|
||||
|
||||
E:RegisterInitialModule(RU:GetName())
|
||||
117
Modules/Misc/TotemBar.lua
Normal file
117
Modules/Misc/TotemBar.lua
Normal file
@@ -0,0 +1,117 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local TOTEMS = E:GetModule('Totems')
|
||||
|
||||
local _G = _G
|
||||
local unpack = unpack
|
||||
|
||||
local CreateFrame = CreateFrame
|
||||
local GetTotemInfo = GetTotemInfo
|
||||
local CooldownFrame_Set = CooldownFrame_Set
|
||||
local MAX_TOTEMS = MAX_TOTEMS
|
||||
|
||||
function TOTEMS:Update()
|
||||
for i=1, MAX_TOTEMS do
|
||||
local button = _G['TotemFrameTotem'..i];
|
||||
local _, _, startTime, duration, icon = GetTotemInfo(button.slot);
|
||||
|
||||
if button:IsShown() then
|
||||
self.bar[i]:Show()
|
||||
self.bar[i].iconTexture:SetTexture(icon)
|
||||
CooldownFrame_Set(self.bar[i].cooldown, startTime, duration, 1)
|
||||
|
||||
button:ClearAllPoints();
|
||||
button:SetParent(self.bar[i].holder);
|
||||
button:SetAllPoints(self.bar[i].holder);
|
||||
else
|
||||
self.bar[i]:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TOTEMS:PositionAndSize()
|
||||
if not E.private.general.totemBar then return end
|
||||
|
||||
for i=1, MAX_TOTEMS do
|
||||
local button = self.bar[i]
|
||||
local prevButton = self.bar[i-1]
|
||||
button:Size(self.db.size)
|
||||
button:ClearAllPoints()
|
||||
if self.db.growthDirection == 'HORIZONTAL' and self.db.sortDirection == 'ASCENDING' then
|
||||
if i == 1 then
|
||||
button:Point('LEFT', self.bar, 'LEFT', self.db.spacing, 0)
|
||||
elseif prevButton then
|
||||
button:Point('LEFT', prevButton, 'RIGHT', self.db.spacing, 0)
|
||||
end
|
||||
elseif self.db.growthDirection == 'VERTICAL' and self.db.sortDirection == 'ASCENDING' then
|
||||
if i == 1 then
|
||||
button:Point('TOP', self.bar, 'TOP', 0, -self.db.spacing)
|
||||
elseif prevButton then
|
||||
button:Point('TOP', prevButton, 'BOTTOM', 0, -self.db.spacing)
|
||||
end
|
||||
elseif self.db.growthDirection == 'HORIZONTAL' and self.db.sortDirection == 'DESCENDING' then
|
||||
if i == 1 then
|
||||
button:Point('RIGHT', self.bar, 'RIGHT', -self.db.spacing, 0)
|
||||
elseif prevButton then
|
||||
button:Point('RIGHT', prevButton, 'LEFT', -self.db.spacing, 0)
|
||||
end
|
||||
else
|
||||
if i == 1 then
|
||||
button:Point('BOTTOM', self.bar, 'BOTTOM', 0, self.db.spacing)
|
||||
elseif prevButton then
|
||||
button:Point('BOTTOM', prevButton, 'TOP', 0, self.db.spacing)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.db.growthDirection == 'HORIZONTAL' then
|
||||
self.bar:Width(self.db.size*(MAX_TOTEMS) + self.db.spacing*(MAX_TOTEMS) + self.db.spacing)
|
||||
self.bar:Height(self.db.size + self.db.spacing*2)
|
||||
else
|
||||
self.bar:Height(self.db.size*(MAX_TOTEMS) + self.db.spacing*(MAX_TOTEMS) + self.db.spacing)
|
||||
self.bar:Width(self.db.size + self.db.spacing*2)
|
||||
end
|
||||
|
||||
self:Update()
|
||||
end
|
||||
|
||||
function TOTEMS:Initialize()
|
||||
self.Initialized = true
|
||||
|
||||
if not E.private.general.totemBar then return end
|
||||
|
||||
self.db = E.db.general.totems
|
||||
|
||||
local bar = CreateFrame('Frame', 'ElvUI_TotemBar', E.UIParent)
|
||||
bar:Point('BOTTOMLEFT', E.UIParent, 'BOTTOMLEFT', 490, 4)
|
||||
self.bar = bar
|
||||
|
||||
for i=1, MAX_TOTEMS do
|
||||
local frame = CreateFrame('Button', bar:GetName()..'Totem'..i, bar, 'BackdropTemplate')
|
||||
frame:SetID(i)
|
||||
frame:SetTemplate()
|
||||
frame:StyleButton()
|
||||
frame:Hide()
|
||||
frame.holder = CreateFrame('Frame', nil, frame)
|
||||
frame.holder:SetAlpha(0)
|
||||
frame.holder:SetAllPoints()
|
||||
|
||||
frame.iconTexture = frame:CreateTexture(nil, 'ARTWORK')
|
||||
frame.iconTexture:SetTexCoord(unpack(E.TexCoords))
|
||||
frame.iconTexture:SetInside()
|
||||
|
||||
frame.cooldown = CreateFrame('Cooldown', frame:GetName()..'Cooldown', frame, 'CooldownFrameTemplate')
|
||||
frame.cooldown:SetReverse(true)
|
||||
frame.cooldown:SetInside()
|
||||
E:RegisterCooldown(frame.cooldown)
|
||||
self.bar[i] = frame;
|
||||
end
|
||||
|
||||
self:PositionAndSize()
|
||||
|
||||
self:RegisterEvent('PLAYER_TOTEM_UPDATE', 'Update')
|
||||
self:RegisterEvent('PLAYER_ENTERING_WORLD', 'Update')
|
||||
|
||||
E:CreateMover(bar, 'TotemBarMover', L["Class Totems"], nil, nil, nil, nil, nil, 'general,totems');
|
||||
end
|
||||
|
||||
E:RegisterModule(TOTEMS:GetName())
|
||||
164
Modules/Nameplates/Elements/Auras.lua
Normal file
164
Modules/Nameplates/Elements/Auras.lua
Normal file
@@ -0,0 +1,164 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local UF = E:GetModule('UnitFrames')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local floor = floor
|
||||
local unpack = unpack
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
function NP:Construct_Auras(nameplate)
|
||||
local frameName = nameplate:GetName()
|
||||
|
||||
local Buffs = CreateFrame('Frame', frameName..'Buffs', nameplate)
|
||||
Buffs:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
Buffs:SetFrameLevel(5)
|
||||
Buffs:Size(300, 27)
|
||||
Buffs.disableMouse = true
|
||||
Buffs.size = 27
|
||||
Buffs.num = 4
|
||||
Buffs.spacing = E.Border * 2
|
||||
Buffs.onlyShowPlayer = false
|
||||
Buffs.initialAnchor = 'BOTTOMLEFT'
|
||||
Buffs['growth-x'] = 'RIGHT'
|
||||
Buffs['growth-y'] = 'UP'
|
||||
Buffs.type = 'buffs'
|
||||
Buffs.forceShow = nameplate == _G.ElvNP_Test
|
||||
|
||||
local Debuffs = CreateFrame('Frame', frameName..'Debuffs', nameplate)
|
||||
Debuffs:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
Debuffs:SetFrameLevel(5)
|
||||
Debuffs:Size(300, 27)
|
||||
Debuffs.disableMouse = true
|
||||
Debuffs.size = 27
|
||||
Debuffs.num = 4
|
||||
Debuffs.spacing = E.Border * 2
|
||||
Debuffs.onlyShowPlayer = false
|
||||
Debuffs.initialAnchor = 'BOTTOMLEFT'
|
||||
Debuffs['growth-x'] = 'RIGHT'
|
||||
Debuffs['growth-y'] = 'UP'
|
||||
Debuffs.type = 'debuffs'
|
||||
Debuffs.forceShow = nameplate == _G.ElvNP_Test
|
||||
|
||||
Buffs.PostCreateIcon = NP.Construct_AuraIcon
|
||||
Buffs.PostUpdateIcon = UF.PostUpdateAura
|
||||
Buffs.CustomFilter = UF.AuraFilter
|
||||
Debuffs.PostCreateIcon = NP.Construct_AuraIcon
|
||||
Debuffs.PostUpdateIcon = UF.PostUpdateAura
|
||||
Debuffs.CustomFilter = UF.AuraFilter
|
||||
|
||||
nameplate.Buffs_, nameplate.Debuffs_ = Buffs, Debuffs
|
||||
nameplate.Buffs, nameplate.Debuffs = Buffs, Debuffs
|
||||
end
|
||||
|
||||
function NP:Construct_AuraIcon(button)
|
||||
if not button then return end
|
||||
button:SetTemplate(nil, nil, nil, nil, nil, true)
|
||||
|
||||
button.cd:SetReverse(true)
|
||||
button.cd:SetInside(button)
|
||||
|
||||
button.icon:SetDrawLayer('ARTWORK')
|
||||
button.icon:SetInside()
|
||||
|
||||
button.count:ClearAllPoints()
|
||||
button.count:Point('BOTTOMRIGHT', 1, 1)
|
||||
button.count:SetJustifyH('RIGHT')
|
||||
|
||||
button.overlay:SetTexture()
|
||||
button.stealable:SetTexture()
|
||||
|
||||
button.cd.CooldownOverride = 'nameplates'
|
||||
E:RegisterCooldown(button.cd)
|
||||
|
||||
local auras = button:GetParent()
|
||||
button.db = auras and NP.db.units and NP.db.units[auras.__owner.frameType] and NP.db.units[auras.__owner.frameType][auras.type]
|
||||
|
||||
NP:UpdateAuraSettings(button)
|
||||
end
|
||||
|
||||
function NP:Configure_Auras(nameplate, auras, db)
|
||||
auras.size = db.size
|
||||
auras.num = db.numAuras
|
||||
auras.onlyShowPlayer = false
|
||||
auras.spacing = db.spacing
|
||||
auras['growth-y'] = db.growthY
|
||||
auras['growth-x'] = db.growthX
|
||||
auras.initialAnchor = E.InversePoints[db.anchorPoint]
|
||||
|
||||
local index = 1
|
||||
while auras[index] do
|
||||
local button = auras[index]
|
||||
if button then
|
||||
button.db = db
|
||||
NP:UpdateAuraSettings(button)
|
||||
end
|
||||
|
||||
index = index + 1
|
||||
end
|
||||
|
||||
local mult = floor((nameplate.width or 150) / db.size) < db.numAuras
|
||||
auras:Size((nameplate.width or 150), (mult and 1 or 2) * db.size)
|
||||
auras:ClearAllPoints()
|
||||
auras:Point(E.InversePoints[db.anchorPoint] or 'TOPRIGHT', db.attachTo == 'BUFFS' and nameplate.Buffs or nameplate, db.anchorPoint or 'TOPRIGHT', db.xOffset, db.yOffset)
|
||||
end
|
||||
|
||||
function NP:Update_Auras(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if db.debuffs.enable or db.buffs.enable then
|
||||
nameplate:SetAuraUpdateMethod(E.global.nameplate.effectiveAura)
|
||||
nameplate:SetAuraUpdateSpeed(E.global.nameplate.effectiveAuraSpeed)
|
||||
|
||||
if not nameplate:IsElementEnabled('Auras') then
|
||||
nameplate:EnableElement('Auras')
|
||||
end
|
||||
|
||||
if db.debuffs.enable then
|
||||
nameplate.Debuffs = nameplate.Debuffs_
|
||||
NP:Configure_Auras(nameplate, nameplate.Debuffs, db.debuffs)
|
||||
nameplate.Debuffs:Show()
|
||||
nameplate.Debuffs:ForceUpdate()
|
||||
elseif nameplate.Debuffs then
|
||||
nameplate.Debuffs:Hide()
|
||||
nameplate.Debuffs = nil
|
||||
end
|
||||
|
||||
if db.buffs.enable then
|
||||
nameplate.Buffs = nameplate.Buffs_
|
||||
NP:Configure_Auras(nameplate, nameplate.Buffs, db.buffs)
|
||||
nameplate.Buffs:Show()
|
||||
nameplate.Buffs:ForceUpdate()
|
||||
elseif nameplate.Buffs then
|
||||
nameplate.Buffs:Hide()
|
||||
nameplate.Buffs = nil
|
||||
end
|
||||
elseif nameplate:IsElementEnabled('Auras') then
|
||||
nameplate:DisableElement('Auras')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:UpdateAuraSettings(button)
|
||||
if button.db then
|
||||
button.count:FontTemplate(LSM:Fetch('font', button.db.countFont), button.db.countFontSize, button.db.countFontOutline)
|
||||
button.count:ClearAllPoints()
|
||||
|
||||
local point = (button.db and button.db.countPosition) or 'CENTER'
|
||||
if point == 'CENTER' then
|
||||
button.count:Point(point, 1, 0)
|
||||
else
|
||||
local bottom, right = point:find('BOTTOM'), point:find('RIGHT')
|
||||
button.count:SetJustifyH(right and 'RIGHT' or 'LEFT')
|
||||
button.count:Point(point, right and -1 or 1, bottom and 1 or -1)
|
||||
end
|
||||
end
|
||||
|
||||
if button.icon then
|
||||
button.icon:SetTexCoord(unpack(E.TexCoords))
|
||||
end
|
||||
|
||||
button:Size((button.db and button.db.size) or 26)
|
||||
|
||||
button.needsUpdateCooldownPosition = true
|
||||
end
|
||||
233
Modules/Nameplates/Elements/CastBar.lua
Normal file
233
Modules/Nameplates/Elements/CastBar.lua
Normal file
@@ -0,0 +1,233 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local CH = E:GetModule('Chat')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local abs = abs
|
||||
local unpack = unpack
|
||||
local strjoin = strjoin
|
||||
local strmatch = strmatch
|
||||
local CreateFrame = CreateFrame
|
||||
local UnitCanAttack = UnitCanAttack
|
||||
local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
|
||||
local INTERRUPTED = INTERRUPTED
|
||||
|
||||
function NP:Castbar_CheckInterrupt(unit)
|
||||
if unit == 'vehicle' then
|
||||
unit = 'player'
|
||||
end
|
||||
|
||||
if self.notInterruptible and UnitCanAttack('player', unit) then
|
||||
self:SetStatusBarColor(NP.db.colors.castNoInterruptColor.r, NP.db.colors.castNoInterruptColor.g, NP.db.colors.castNoInterruptColor.b)
|
||||
|
||||
if self.Icon and NP.db.colors.castbarDesaturate then
|
||||
self.Icon:SetDesaturated(true)
|
||||
end
|
||||
else
|
||||
self:SetStatusBarColor(NP.db.colors.castColor.r, NP.db.colors.castColor.g, NP.db.colors.castColor.b)
|
||||
|
||||
if self.Icon then
|
||||
self.Icon:SetDesaturated(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Castbar_CustomDelayText(duration)
|
||||
if self.channeling then
|
||||
if self.channelTimeFormat == 'CURRENT' then
|
||||
self.Time:SetFormattedText('%.1f |cffaf5050%.1f|r', abs(duration - self.max), self.delay)
|
||||
elseif self.channelTimeFormat == 'CURRENTMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%.1f|r', duration, self.max, self.delay)
|
||||
elseif self.channelTimeFormat == 'REMAINING' then
|
||||
self.Time:SetFormattedText('%.1f |cffaf5050%.1f|r', duration, self.delay)
|
||||
elseif self.channelTimeFormat == 'REMAININGMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%.1f|r', abs(duration - self.max), self.max, self.delay)
|
||||
end
|
||||
else
|
||||
if self.castTimeFormat == 'CURRENT' then
|
||||
self.Time:SetFormattedText('%.1f |cffaf5050%s %.1f|r', duration, '+', self.delay)
|
||||
elseif self.castTimeFormat == 'CURRENTMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%s %.1f|r', duration, self.max, '+', self.delay)
|
||||
elseif self.castTimeFormat == 'REMAINING' then
|
||||
self.Time:SetFormattedText('%.1f |cffaf5050%s %.1f|r', abs(duration - self.max), '+', self.delay)
|
||||
elseif self.castTimeFormat == 'REMAININGMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%s %.1f|r', abs(duration - self.max), self.max, '+', self.delay)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Castbar_CustomTimeText(duration)
|
||||
if self.channeling then
|
||||
if self.channelTimeFormat == 'CURRENT' then
|
||||
self.Time:SetFormattedText('%.1f', abs(duration - self.max))
|
||||
elseif self.channelTimeFormat == 'CURRENTMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f', abs(duration - self.max), self.max)
|
||||
elseif self.channelTimeFormat == 'REMAINING' then
|
||||
self.Time:SetFormattedText('%.1f', duration)
|
||||
elseif self.channelTimeFormat == 'REMAININGMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f', duration, self.max)
|
||||
end
|
||||
else
|
||||
if self.castTimeFormat == 'CURRENT' then
|
||||
self.Time:SetFormattedText('%.1f', duration)
|
||||
elseif self.castTimeFormat == 'CURRENTMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f', duration, self.max)
|
||||
elseif self.castTimeFormat == 'REMAINING' then
|
||||
self.Time:SetFormattedText('%.1f', abs(duration - self.max))
|
||||
elseif self.castTimeFormat == 'REMAININGMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f', abs(duration - self.max), self.max)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Castbar_PostCastStart(unit)
|
||||
self:CheckInterrupt(unit)
|
||||
NP:StyleFilterUpdate(self.__owner, 'FAKE_Casting')
|
||||
end
|
||||
|
||||
function NP:Castbar_PostCastFail()
|
||||
self:SetStatusBarColor(NP.db.colors.castInterruptedColor.r, NP.db.colors.castInterruptedColor.g, NP.db.colors.castInterruptedColor.b)
|
||||
NP:StyleFilterUpdate(self.__owner, 'FAKE_Casting')
|
||||
end
|
||||
|
||||
function NP:Castbar_PostCastInterruptible(unit)
|
||||
self:CheckInterrupt(unit)
|
||||
end
|
||||
|
||||
function NP:Castbar_PostCastStop()
|
||||
NP:StyleFilterUpdate(self.__owner, 'FAKE_Casting')
|
||||
end
|
||||
|
||||
function NP:Construct_Castbar(nameplate)
|
||||
local Castbar = CreateFrame('StatusBar', nameplate:GetName()..'Castbar', nameplate)
|
||||
Castbar:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
Castbar:SetFrameLevel(5)
|
||||
Castbar:CreateBackdrop('Transparent', nil, nil, nil, nil, true)
|
||||
Castbar:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
|
||||
NP.StatusBars[Castbar] = true
|
||||
|
||||
Castbar.Button = CreateFrame('Frame', nil, Castbar, 'BackdropTemplate')
|
||||
Castbar.Button:SetTemplate()
|
||||
|
||||
Castbar.Icon = Castbar.Button:CreateTexture(nil, 'ARTWORK')
|
||||
Castbar.Icon:SetTexCoord(unpack(E.TexCoords))
|
||||
Castbar.Icon:SetInside()
|
||||
|
||||
Castbar.Time = Castbar:CreateFontString(nil, 'OVERLAY')
|
||||
Castbar.Time:Point('RIGHT', Castbar, 'RIGHT', -4, 0)
|
||||
Castbar.Time:SetJustifyH('RIGHT')
|
||||
Castbar.Time:FontTemplate(LSM:Fetch('font', NP.db.font), NP.db.fontSize, NP.db.fontOutline)
|
||||
|
||||
Castbar.Text = Castbar:CreateFontString(nil, 'OVERLAY')
|
||||
Castbar.Text:SetJustifyH('LEFT')
|
||||
Castbar.Text:FontTemplate(LSM:Fetch('font', NP.db.font), NP.db.fontSize, NP.db.fontOutline)
|
||||
Castbar.Text:SetWordWrap(false)
|
||||
|
||||
Castbar.CheckInterrupt = NP.Castbar_CheckInterrupt
|
||||
Castbar.CustomDelayText = NP.Castbar_CustomDelayText
|
||||
Castbar.CustomTimeText = NP.Castbar_CustomTimeText
|
||||
Castbar.PostCastStart = NP.Castbar_PostCastStart
|
||||
Castbar.PostCastFail = NP.Castbar_PostCastFail
|
||||
Castbar.PostCastInterruptible = NP.Castbar_PostCastInterruptible
|
||||
Castbar.PostCastStop = NP.Castbar_PostCastStop
|
||||
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
Castbar.Hide = Castbar.Show
|
||||
Castbar:Show()
|
||||
Castbar.Text:SetText('Casting')
|
||||
Castbar.Time:SetText('3.1')
|
||||
Castbar.Icon:SetTexture([[Interface\Icons\Achievement_Character_Pandaren_Female]])
|
||||
Castbar:SetStatusBarColor(NP.db.colors.castColor.r, NP.db.colors.castColor.g, NP.db.colors.castColor.b)
|
||||
end
|
||||
|
||||
return Castbar
|
||||
end
|
||||
|
||||
function NP:COMBAT_LOG_EVENT_UNFILTERED()
|
||||
local _, event, _, sourceGUID, sourceName, _, _, targetGUID = CombatLogGetCurrentEventInfo()
|
||||
if (event == 'SPELL_INTERRUPT' or event == 'SPELL_PERIODIC_INTERRUPT') and targetGUID and (sourceName and sourceName ~= '') then
|
||||
local plate, classColor = NP.PlateGUID[targetGUID]
|
||||
if plate and plate.Castbar then
|
||||
local db = plate.frameType and self.db and self.db.units and self.db.units[plate.frameType]
|
||||
if db and db.castbar and db.castbar.enable and db.castbar.sourceInterrupt then
|
||||
if db.castbar.timeToHold > 0 then
|
||||
local name = strmatch(sourceName, '([^%-]+).*')
|
||||
if db.castbar.sourceInterruptClassColor then
|
||||
local data = CH:GetPlayerInfoByGUID(sourceGUID)
|
||||
if data and data.classColor then
|
||||
classColor = data.classColor.colorStr
|
||||
end
|
||||
|
||||
plate.Castbar.Text:SetFormattedText('%s > %s', INTERRUPTED, classColor and strjoin('', '|c', classColor, name) or name)
|
||||
else
|
||||
plate.Castbar.Text:SetFormattedText('%s > %s', INTERRUPTED, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_Castbar(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
nameplate.Castbar:SetAlpha((not db.nameOnly and db.castbar.enable) and 1 or 0)
|
||||
end
|
||||
|
||||
if db.castbar.enable then
|
||||
if not nameplate:IsElementEnabled('Castbar') then
|
||||
nameplate:EnableElement('Castbar')
|
||||
end
|
||||
|
||||
nameplate.Castbar.timeToHold = db.castbar.timeToHold
|
||||
nameplate.Castbar.castTimeFormat = db.castbar.castTimeFormat
|
||||
nameplate.Castbar.channelTimeFormat = db.castbar.channelTimeFormat
|
||||
|
||||
nameplate.Castbar:Size(db.castbar.width, db.castbar.height)
|
||||
nameplate.Castbar:Point('CENTER', nameplate, 'CENTER', db.castbar.xOffset, db.castbar.yOffset)
|
||||
|
||||
if db.castbar.showIcon then
|
||||
nameplate.Castbar.Button:ClearAllPoints()
|
||||
nameplate.Castbar.Button:Point(db.castbar.iconPosition == 'RIGHT' and 'BOTTOMLEFT' or 'BOTTOMRIGHT', nameplate.Castbar, db.castbar.iconPosition == 'RIGHT' and 'BOTTOMRIGHT' or 'BOTTOMLEFT', db.castbar.iconOffsetX, db.castbar.iconOffsetY)
|
||||
nameplate.Castbar.Button:Size(db.castbar.iconSize, db.castbar.iconSize)
|
||||
nameplate.Castbar.Button:Show()
|
||||
else
|
||||
nameplate.Castbar.Button:Hide()
|
||||
end
|
||||
|
||||
nameplate.Castbar.Time:ClearAllPoints()
|
||||
nameplate.Castbar.Text:ClearAllPoints()
|
||||
|
||||
if db.castbar.textPosition == 'BELOW' then
|
||||
nameplate.Castbar.Time:Point('TOPRIGHT', nameplate.Castbar, 'BOTTOMRIGHT')
|
||||
nameplate.Castbar.Text:Point('TOPLEFT', nameplate.Castbar, 'BOTTOMLEFT')
|
||||
elseif db.castbar.textPosition == 'ABOVE' then
|
||||
nameplate.Castbar.Time:Point('BOTTOMRIGHT', nameplate.Castbar, 'TOPRIGHT')
|
||||
nameplate.Castbar.Text:Point('BOTTOMLEFT', nameplate.Castbar, 'TOPLEFT')
|
||||
else
|
||||
nameplate.Castbar.Time:Point('RIGHT', nameplate.Castbar, 'RIGHT', -1, 0)
|
||||
nameplate.Castbar.Text:Point('LEFT', nameplate.Castbar, 'LEFT', 1, 0)
|
||||
end
|
||||
|
||||
nameplate.Castbar.Text:Point('RIGHT', nameplate.Castbar, 'RIGHT', -20, 0)
|
||||
|
||||
if db.castbar.hideTime then
|
||||
nameplate.Castbar.Time:Hide()
|
||||
else
|
||||
nameplate.Castbar.Time:FontTemplate(LSM:Fetch('font', db.castbar.font), db.castbar.fontSize, db.castbar.fontOutline)
|
||||
nameplate.Castbar.Time:Show()
|
||||
end
|
||||
|
||||
if db.castbar.hideSpellName then
|
||||
nameplate.Castbar.Text:Hide()
|
||||
else
|
||||
nameplate.Castbar.Text:FontTemplate(LSM:Fetch('font', db.castbar.font), db.castbar.fontSize, db.castbar.fontOutline)
|
||||
nameplate.Castbar.Text:Show()
|
||||
end
|
||||
elseif nameplate:IsElementEnabled('Castbar') then
|
||||
nameplate:DisableElement('Castbar')
|
||||
end
|
||||
end
|
||||
269
Modules/Nameplates/Elements/ClassPower.lua
Normal file
269
Modules/Nameplates/Elements/ClassPower.lua
Normal file
@@ -0,0 +1,269 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local LSM = E.Libs.LSM
|
||||
local oUF = E.oUF
|
||||
|
||||
local _G = _G
|
||||
local unpack, max = unpack, max
|
||||
local CreateFrame = CreateFrame
|
||||
local UnitHasVehicleUI = UnitHasVehicleUI
|
||||
|
||||
local MAX_POINTS = {
|
||||
DRUID = 5,
|
||||
DEATHKNIGHT = 6,
|
||||
MAGE = 4,
|
||||
MONK = 6,
|
||||
PALADIN = 5,
|
||||
ROGUE = 6,
|
||||
WARLOCK = 5
|
||||
}
|
||||
|
||||
function NP:ClassPower_UpdateColor(powerType)
|
||||
local color, r, g, b = NP.db.colors.classResources[E.myclass] or NP.db.colors.power[powerType]
|
||||
if color then
|
||||
r, g, b = color.r, color.g, color.b
|
||||
else
|
||||
color = oUF.colors.power[powerType]
|
||||
r, g, b = unpack(color)
|
||||
end
|
||||
|
||||
local db = NP.db.units[self.__owner.frameType]
|
||||
local ClassColor = db and db.classpower.classColor and E:ClassColor(E.myclass)
|
||||
for i = 1, #self do
|
||||
local classColor = ClassColor or (powerType == 'COMBO_POINTS' and NP.db.colors.classResources.comboPoints[i] or powerType == 'CHI' and NP.db.colors.classResources.MONK[i])
|
||||
if classColor then r, g, b = classColor.r, classColor.g, classColor.b end
|
||||
|
||||
self[i]:SetStatusBarColor(r, g, b)
|
||||
|
||||
if self[i].bg then self[i].bg:SetVertexColor(r * NP.multiplier, g * NP.multiplier, b * NP.multiplier) end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:ClassPower_PostUpdate(Cur, _, needUpdate)
|
||||
if Cur and Cur > 0 then
|
||||
self:Show()
|
||||
else
|
||||
self:Hide()
|
||||
end
|
||||
|
||||
if needUpdate then
|
||||
NP:Update_ClassPower(self.__owner)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_ClassPower(nameplate)
|
||||
local frameName = nameplate:GetName()
|
||||
local ClassPower = CreateFrame('Frame', frameName..'ClassPower', nameplate)
|
||||
ClassPower:CreateBackdrop('Transparent', nil, nil, nil, nil, true)
|
||||
ClassPower:Hide()
|
||||
ClassPower:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
ClassPower:SetFrameLevel(5)
|
||||
|
||||
local Max = max(MAX_POINTS[E.myclass] or 0, _G.MAX_COMBO_POINTS)
|
||||
local texture = LSM:Fetch('statusbar', NP.db.statusbar)
|
||||
|
||||
for i = 1, Max do
|
||||
ClassPower[i] = CreateFrame('StatusBar', frameName..'ClassPower'..i, ClassPower)
|
||||
ClassPower[i]:SetStatusBarTexture(texture)
|
||||
ClassPower[i]:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
ClassPower[i]:SetFrameLevel(6)
|
||||
NP.StatusBars[ClassPower[i]] = true
|
||||
|
||||
ClassPower[i].bg = ClassPower:CreateTexture(frameName..'ClassPower'..i..'bg', 'BORDER')
|
||||
ClassPower[i].bg:SetAllPoints(ClassPower[i])
|
||||
ClassPower[i].bg:SetTexture(texture)
|
||||
end
|
||||
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
ClassPower.Hide = ClassPower.Show
|
||||
ClassPower:Show()
|
||||
|
||||
for i = 1, Max do
|
||||
ClassPower[i]:SetStatusBarTexture(texture)
|
||||
ClassPower[i].bg:SetTexture(texture)
|
||||
ClassPower[i].bg:SetVertexColor(NP.db.colors.classResources.comboPoints[i].r, NP.db.colors.classResources.comboPoints[i].g, NP.db.colors.classResources.comboPoints[i].b)
|
||||
end
|
||||
end
|
||||
|
||||
ClassPower.UpdateColor = NP.ClassPower_UpdateColor
|
||||
ClassPower.PostUpdate = NP.ClassPower_PostUpdate
|
||||
|
||||
return ClassPower
|
||||
end
|
||||
|
||||
function NP:Update_ClassPower(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
if not db.nameOnly and db.classpower and db.classpower.enable then
|
||||
NP.ClassPower_UpdateColor(nameplate.ClassPower, 'COMBO_POINTS')
|
||||
nameplate.ClassPower:SetAlpha(1)
|
||||
else
|
||||
nameplate.ClassPower:SetAlpha(0)
|
||||
end
|
||||
end
|
||||
|
||||
if (nameplate.frameType == 'PLAYER' or nameplate.frameType == 'TARGET') and db.classpower and db.classpower.enable then
|
||||
if not nameplate:IsElementEnabled('ClassPower') then
|
||||
nameplate:EnableElement('ClassPower')
|
||||
end
|
||||
|
||||
nameplate.ClassPower:ClearAllPoints()
|
||||
nameplate.ClassPower:Point('CENTER', nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
|
||||
|
||||
local maxClassBarButtons = nameplate.ClassPower.__max
|
||||
|
||||
local Width = db.classpower.width / maxClassBarButtons
|
||||
nameplate.ClassPower:Size(db.classpower.width, db.classpower.height)
|
||||
|
||||
for i = 1, #nameplate.ClassPower do
|
||||
nameplate.ClassPower[i]:Hide()
|
||||
nameplate.ClassPower[i].bg:Hide()
|
||||
end
|
||||
|
||||
for i = 1, maxClassBarButtons do
|
||||
nameplate.ClassPower[i]:Show()
|
||||
nameplate.ClassPower[i].bg:Show()
|
||||
nameplate.ClassPower[i]:ClearAllPoints()
|
||||
|
||||
if i == 1 then
|
||||
nameplate.ClassPower[i]:Size(Width - (maxClassBarButtons == 6 and 2 or 0), db.classpower.height)
|
||||
nameplate.ClassPower[i].bg:Size(Width - (maxClassBarButtons == 6 and 2 or 0), db.classpower.height)
|
||||
|
||||
nameplate.ClassPower[i]:ClearAllPoints()
|
||||
nameplate.ClassPower[i]:Point('LEFT', nameplate.ClassPower, 'LEFT', 0, 0)
|
||||
else
|
||||
nameplate.ClassPower[i]:Size(Width - 1, db.classpower.height)
|
||||
nameplate.ClassPower[i].bg:Size(Width - 1, db.classpower.height)
|
||||
|
||||
nameplate.ClassPower[i]:ClearAllPoints()
|
||||
nameplate.ClassPower[i]:Point('LEFT', nameplate.ClassPower[i - 1], 'RIGHT', 1, 0)
|
||||
|
||||
if i == maxClassBarButtons then
|
||||
nameplate.ClassPower[i]:Point('RIGHT', nameplate.ClassPower)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if nameplate:IsElementEnabled('ClassPower') then
|
||||
nameplate:DisableElement('ClassPower')
|
||||
end
|
||||
|
||||
nameplate.ClassPower:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Runes_PostUpdate()
|
||||
if UnitHasVehicleUI('player') then
|
||||
self:Hide()
|
||||
else
|
||||
self:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_Runes(nameplate)
|
||||
local frameName = nameplate:GetName()
|
||||
local Runes = CreateFrame('Frame', frameName..'Runes', nameplate)
|
||||
Runes:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
Runes:SetFrameLevel(5)
|
||||
Runes:CreateBackdrop('Transparent', nil, nil, nil, nil, true)
|
||||
Runes:Hide()
|
||||
|
||||
Runes.UpdateColor = E.noop
|
||||
Runes.PostUpdate = NP.Runes_PostUpdate
|
||||
|
||||
local texture = LSM:Fetch('statusbar', NP.db.statusbar)
|
||||
local color = NP.db.colors.classResources.DEATHKNIGHT
|
||||
|
||||
for i = 1, 6 do
|
||||
Runes[i] = CreateFrame('StatusBar', frameName..'Runes'..i, Runes)
|
||||
Runes[i]:SetStatusBarTexture(texture)
|
||||
Runes[i]:SetStatusBarColor(color.r, color.g, color.b)
|
||||
NP.StatusBars[Runes[i]] = true
|
||||
|
||||
Runes[i].bg = Runes[i]:CreateTexture(frameName..'Runes'..i..'bg', 'BORDER')
|
||||
Runes[i].bg:SetVertexColor(color.r * NP.multiplier, color.g * NP.multiplier, color.b * NP.multiplier)
|
||||
Runes[i].bg:SetTexture(texture)
|
||||
Runes[i].bg:SetAllPoints()
|
||||
end
|
||||
|
||||
return Runes
|
||||
end
|
||||
|
||||
function NP:Update_Runes(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if (nameplate.frameType == 'PLAYER' or nameplate.frameType == 'TARGET') and db.classpower and db.classpower.enable then
|
||||
if not nameplate:IsElementEnabled('Runes') then
|
||||
nameplate:EnableElement('Runes')
|
||||
end
|
||||
|
||||
nameplate.Runes:Show()
|
||||
nameplate.Runes:ClearAllPoints()
|
||||
nameplate.Runes:Point('CENTER', nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
|
||||
|
||||
nameplate.Runes.sortOrder = db.classpower.sortDirection
|
||||
|
||||
local width = db.classpower.width / 6
|
||||
nameplate.Runes:Size(db.classpower.width, db.classpower.height)
|
||||
|
||||
local runeColor = (db.classpower.classColor and E:ClassColor(E.myclass)) or NP.db.colors.classResources.DEATHKNIGHT
|
||||
|
||||
for i = 1, 6 do
|
||||
nameplate.Runes[i]:SetStatusBarColor(runeColor.r, runeColor.g, runeColor.b)
|
||||
|
||||
if i == 1 then
|
||||
nameplate.Runes[i]:Size(width, db.classpower.height)
|
||||
nameplate.Runes[i].bg:Size(width, db.classpower.height)
|
||||
|
||||
nameplate.Runes[i]:ClearAllPoints()
|
||||
nameplate.Runes[i]:Point('LEFT', nameplate.Runes, 'LEFT', 0, 0)
|
||||
else
|
||||
nameplate.Runes[i]:Size(width - 1, db.classpower.height)
|
||||
nameplate.Runes[i].bg:Size(width - 1, db.classpower.height)
|
||||
|
||||
nameplate.Runes[i]:ClearAllPoints()
|
||||
nameplate.Runes[i]:Point('LEFT', nameplate.Runes[i-1], 'RIGHT', 1, 0)
|
||||
|
||||
if i == 6 then
|
||||
nameplate.Runes[6]:Point('RIGHT', nameplate.Runes)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if nameplate:IsElementEnabled('Runes') then
|
||||
nameplate:DisableElement('Runes')
|
||||
end
|
||||
|
||||
nameplate.Runes:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_Stagger(nameplate)
|
||||
local Stagger = CreateFrame('StatusBar', nameplate:GetName()..'Stagger', nameplate)
|
||||
Stagger:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
Stagger:SetFrameLevel(5)
|
||||
Stagger:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
Stagger:CreateBackdrop('Transparent', nil, nil, nil, nil, true)
|
||||
Stagger:Hide()
|
||||
|
||||
NP.StatusBars[Stagger] = true
|
||||
|
||||
return Stagger
|
||||
end
|
||||
|
||||
function NP:Update_Stagger(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if (nameplate.frameType == 'PLAYER' or nameplate.frameType == 'TARGET') and db.classpower and db.classpower.enable then
|
||||
if not nameplate:IsElementEnabled('Stagger') then
|
||||
nameplate:EnableElement('Stagger')
|
||||
end
|
||||
|
||||
nameplate.Stagger:ClearAllPoints()
|
||||
nameplate.Stagger:Point('CENTER', nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
|
||||
nameplate.Stagger:Size(db.classpower.width, db.classpower.height)
|
||||
elseif nameplate:IsElementEnabled('Stagger') then
|
||||
nameplate:DisableElement('Stagger')
|
||||
end
|
||||
end
|
||||
185
Modules/Nameplates/Elements/Health.lua
Normal file
185
Modules/Nameplates/Elements/Health.lua
Normal file
@@ -0,0 +1,185 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local ipairs = ipairs
|
||||
local unpack = unpack
|
||||
local UnitPlayerControlled = UnitPlayerControlled
|
||||
local UnitIsTapDenied = UnitIsTapDenied
|
||||
local UnitClass = UnitClass
|
||||
local UnitReaction = UnitReaction
|
||||
local UnitIsConnected = UnitIsConnected
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
function NP:Health_UpdateColor(_, unit)
|
||||
if not unit or self.unit ~= unit then return end
|
||||
local element = self.Health
|
||||
local Selection = element.colorSelection and NP:UnitSelectionType(unit, element.considerSelectionInCombatHostile)
|
||||
|
||||
local r, g, b, t
|
||||
if element.colorDisconnected and not UnitIsConnected(unit) then
|
||||
t = self.colors.disconnected
|
||||
elseif element.colorTapping and not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
|
||||
t = NP.db.colors.tapped
|
||||
elseif (element.colorClass and self.isPlayer) or (element.colorClassNPC and not self.isPlayer) or (element.colorClassPet and UnitPlayerControlled(unit) and not self.isPlayer) then
|
||||
local _, class = UnitClass(unit)
|
||||
t = self.colors.class[class]
|
||||
elseif Selection then
|
||||
if Selection == 3 then Selection = UnitPlayerControlled(unit) and 5 or 3 end
|
||||
t = NP.db.colors.selection[Selection]
|
||||
elseif element.colorReaction and UnitReaction(unit, 'player') then
|
||||
local reaction = UnitReaction(unit, 'player')
|
||||
if reaction <= 3 then reaction = 'bad' elseif reaction == 4 then reaction = 'neutral' else reaction = 'good' end
|
||||
t = NP.db.colors.reactions[reaction]
|
||||
elseif element.colorSmooth then
|
||||
r, g, b = self:ColorGradient(element.cur or 1, element.max or 1, unpack(element.smoothGradient or self.colors.smooth))
|
||||
elseif element.colorHealth then
|
||||
t = NP.db.colors.health
|
||||
end
|
||||
|
||||
if t then
|
||||
r, g, b = t[1] or t.r, t[2] or t.g, t[3] or t.b
|
||||
element.r, element.g, element.b = r, g, b -- save these for the style filter to switch back
|
||||
end
|
||||
|
||||
local sf = NP:StyleFilterChanges(self)
|
||||
if sf.HealthColor then
|
||||
r, g, b = sf.HealthColor.r, sf.HealthColor.g, sf.HealthColor.b
|
||||
end
|
||||
|
||||
if b then
|
||||
element:SetStatusBarColor(r, g, b)
|
||||
|
||||
if element.bg then
|
||||
element.bg:SetVertexColor(r * NP.multiplier, g * NP.multiplier, b * NP.multiplier)
|
||||
end
|
||||
end
|
||||
|
||||
if element.PostUpdateColor then
|
||||
element:PostUpdateColor(unit, r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_Health(nameplate)
|
||||
local Health = CreateFrame('StatusBar', nameplate:GetName()..'Health', nameplate)
|
||||
Health:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
Health:SetFrameLevel(5)
|
||||
Health:CreateBackdrop('Transparent', nil, nil, nil, nil, true)
|
||||
Health:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
|
||||
local clipFrame = CreateFrame('Frame', nil, Health)
|
||||
clipFrame:SetClipsChildren(true)
|
||||
clipFrame:SetAllPoints()
|
||||
clipFrame:EnableMouse(false)
|
||||
Health.ClipFrame = clipFrame
|
||||
|
||||
--[[Health.bg = Health:CreateTexture(nil, 'BACKGROUND')
|
||||
Health.bg:SetAllPoints()
|
||||
Health.bg:SetTexture(E.media.blankTex)
|
||||
Health.bg.multiplier = 0.2]]
|
||||
|
||||
NP.StatusBars[Health] = true
|
||||
|
||||
local statusBarTexture = Health:GetStatusBarTexture()
|
||||
local healthFlashTexture = Health:CreateTexture(nameplate:GetName()..'FlashTexture', 'OVERLAY')
|
||||
healthFlashTexture:SetTexture(LSM:Fetch('background', 'ElvUI Blank'))
|
||||
healthFlashTexture:Point('BOTTOMLEFT', statusBarTexture, 'BOTTOMLEFT')
|
||||
healthFlashTexture:Point('TOPRIGHT', statusBarTexture, 'TOPRIGHT')
|
||||
healthFlashTexture:Hide()
|
||||
nameplate.HealthFlashTexture = healthFlashTexture
|
||||
|
||||
Health.colorTapping = true
|
||||
Health.colorSelection = true
|
||||
Health.UpdateColor = NP.Health_UpdateColor
|
||||
|
||||
return Health
|
||||
end
|
||||
|
||||
function NP:Update_Health(nameplate, skipUpdate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
nameplate.Health.colorTapping = true
|
||||
nameplate.Health.colorSelection = true
|
||||
nameplate.Health.colorClass = db.health.useClassColor
|
||||
nameplate.Health.considerSelectionInCombatHostile = true
|
||||
if skipUpdate then return end
|
||||
|
||||
if db.health.enable then
|
||||
if not nameplate:IsElementEnabled('Health') then
|
||||
nameplate:EnableElement('Health')
|
||||
end
|
||||
|
||||
nameplate.Health:Point('CENTER')
|
||||
nameplate.Health:Point('LEFT')
|
||||
nameplate.Health:Point('RIGHT')
|
||||
|
||||
nameplate:SetHealthUpdateMethod(E.global.nameplate.effectiveHealth)
|
||||
nameplate:SetHealthUpdateSpeed(E.global.nameplate.effectiveHealthSpeed)
|
||||
|
||||
E:SetSmoothing(nameplate.Health, NP.db.smoothbars)
|
||||
elseif nameplate:IsElementEnabled('Health') then
|
||||
nameplate:DisableElement('Health')
|
||||
end
|
||||
|
||||
nameplate.Health.width = db.health.width
|
||||
nameplate.Health.height = db.health.height
|
||||
nameplate.Health:Height(db.health.height)
|
||||
end
|
||||
|
||||
local bars = { 'myBar', 'otherBar', 'absorbBar', 'healAbsorbBar' }
|
||||
function NP:Construct_HealthPrediction(nameplate)
|
||||
local HealthPrediction = CreateFrame('Frame', nameplate:GetName()..'HealthPrediction', nameplate)
|
||||
|
||||
for _, name in ipairs(bars) do
|
||||
local bar = CreateFrame('StatusBar', nil, nameplate.Health.ClipFrame)
|
||||
bar:SetFrameStrata(nameplate:GetFrameStrata())
|
||||
bar:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
bar:Point('TOP')
|
||||
bar:Point('BOTTOM')
|
||||
bar:Width(150)
|
||||
HealthPrediction[name] = bar
|
||||
NP.StatusBars[bar] = true
|
||||
end
|
||||
|
||||
local healthTexture = nameplate.Health:GetStatusBarTexture()
|
||||
local healthFrameLevel = nameplate.Health:GetFrameLevel()
|
||||
HealthPrediction.myBar:Point('LEFT', healthTexture, 'RIGHT')
|
||||
HealthPrediction.myBar:SetFrameLevel(healthFrameLevel + 2)
|
||||
HealthPrediction.myBar:SetStatusBarColor(NP.db.colors.healPrediction.personal.r, NP.db.colors.healPrediction.personal.g, NP.db.colors.healPrediction.personal.b)
|
||||
HealthPrediction.myBar:SetMinMaxValues(0, 1)
|
||||
|
||||
HealthPrediction.otherBar:Point('LEFT', HealthPrediction.myBar:GetStatusBarTexture(), 'RIGHT')
|
||||
HealthPrediction.otherBar:SetFrameLevel(healthFrameLevel + 1)
|
||||
HealthPrediction.otherBar:SetStatusBarColor(NP.db.colors.healPrediction.others.r, NP.db.colors.healPrediction.others.g, NP.db.colors.healPrediction.others.b)
|
||||
|
||||
HealthPrediction.absorbBar:Point('LEFT', HealthPrediction.otherBar:GetStatusBarTexture(), 'RIGHT')
|
||||
HealthPrediction.absorbBar:SetFrameLevel(healthFrameLevel)
|
||||
HealthPrediction.absorbBar:SetStatusBarColor(NP.db.colors.healPrediction.absorbs.r, NP.db.colors.healPrediction.absorbs.g, NP.db.colors.healPrediction.absorbs.b)
|
||||
|
||||
HealthPrediction.healAbsorbBar:Point('RIGHT', healthTexture)
|
||||
HealthPrediction.healAbsorbBar:SetFrameLevel(healthFrameLevel + 3)
|
||||
HealthPrediction.healAbsorbBar:SetStatusBarColor(NP.db.colors.healPrediction.healAbsorbs.r, NP.db.colors.healPrediction.healAbsorbs.g, NP.db.colors.healPrediction.healAbsorbs.b)
|
||||
HealthPrediction.healAbsorbBar:SetReverseFill(true)
|
||||
|
||||
HealthPrediction.maxOverflow = 1
|
||||
HealthPrediction.frequentUpdates = true
|
||||
|
||||
return HealthPrediction
|
||||
end
|
||||
|
||||
function NP:Update_HealthPrediction(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if db.health.enable and db.health.healPrediction then
|
||||
if not nameplate:IsElementEnabled('HealthPrediction') then
|
||||
nameplate:EnableElement('HealthPrediction')
|
||||
end
|
||||
|
||||
nameplate.HealthPrediction.myBar:SetStatusBarColor(NP.db.colors.healPrediction.personal.r, NP.db.colors.healPrediction.personal.g, NP.db.colors.healPrediction.personal.b)
|
||||
nameplate.HealthPrediction.otherBar:SetStatusBarColor(NP.db.colors.healPrediction.others.r, NP.db.colors.healPrediction.others.g, NP.db.colors.healPrediction.others.b)
|
||||
nameplate.HealthPrediction.absorbBar:SetStatusBarColor(NP.db.colors.healPrediction.absorbs.r, NP.db.colors.healPrediction.absorbs.g, NP.db.colors.healPrediction.absorbs.b)
|
||||
nameplate.HealthPrediction.healAbsorbBar:SetStatusBarColor(NP.db.colors.healPrediction.healAbsorbs.r, NP.db.colors.healPrediction.healAbsorbs.g, NP.db.colors.healPrediction.healAbsorbs.b)
|
||||
elseif nameplate:IsElementEnabled('HealthPrediction') then
|
||||
nameplate:DisableElement('HealthPrediction')
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user