initial commit
This commit is contained in:
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())
|
||||
Reference in New Issue
Block a user