This commit is contained in:
Andrew6810
2022-10-21 07:09:01 -07:00
parent cbdabfbcca
commit 60ef8a38af
614 changed files with 138573 additions and 2 deletions
+348
View File
@@ -0,0 +1,348 @@
local E, L, V, P, G = unpack(select(2, ...)) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local mod = E:GetModule("AFK")
local CH = E:GetModule("Chat")
--Lua functions
local _G = _G
local tostring = tostring
local floor = math.floor
local format, gsub, sub, upper = string.format, string.gsub, string.sub, string.upper
--WoW API / Variables
local ChatHistory_GetAccessID = ChatHistory_GetAccessID
local Chat_GetChatCategory = Chat_GetChatCategory
local CinematicFrame = CinematicFrame
local CreateFrame = CreateFrame
local GetBattlefieldStatus = GetBattlefieldStatus
local GetColoredName = GetColoredName
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 MovieFrame = MovieFrame
local Screenshot = Screenshot
local SetCVar = SetCVar
local UnitCastingInfo = UnitCastingInfo
local UnitIsAFK = UnitIsAFK
local AFK, DND = AFK, DND
local CHAT_BN_CONVERSATION_GET_LINK = CHAT_BN_CONVERSATION_GET_LINK
local MAX_WOW_CHAT_CHANNELS = MAX_WOW_CHAT_CHANNELS
local cameraSpeed = 0.035
local ignoreKeys = {
["LALT"] = true,
["LSHIFT"] = true,
["RSHIFT"] = true
}
local printKeys = {
["PRINTSCREEN"] = true,
}
if E.isMacClient then
printKeys[_G["KEY_PRINTSCREEN_MAC"]] = true
end
function mod:UpdateTimer()
local time = GetTime() - self.startTime
self.AFKMode.bottom.time:SetFormattedText("%02d:%02d", floor(time / 60), time % 60)
end
local function StopAnimation(self)
self:SetSequenceTime(0, 0)
self:SetScript("OnUpdate", nil)
self:SetScript("OnAnimFinished", nil)
end
local function UpdateAnimation(self, elapsed)
self.animTime = self.animTime + (elapsed * 1000)
self:SetSequenceTime(67, self.animTime)
if self.animTime >= 3000 then
StopAnimation(self)
end
end
local function OnAnimFinished(self)
if self.animTime > 500 then
StopAnimation(self)
end
end
function mod:SetAFK(status)
if status and not self.isAFK then
if InspectFrame then
InspectFrame:Hide()
end
UIParent:Hide()
self.AFKMode:Show()
E.global.afkEnabled = true
MoveViewLeftStart(cameraSpeed)
if IsInGuild() then
local guildName, guildRankName = GetGuildInfo("player")
self.AFKMode.bottom.guild:SetFormattedText("%s - %s", guildName, guildRankName)
else
self.AFKMode.bottom.guild:SetText(L["No Guild"])
end
self.startTime = GetTime()
self.timer = self:ScheduleRepeatingTimer("UpdateTimer", 1)
self.AFKMode.chat:RegisterEvent("CHAT_MSG_WHISPER")
self.AFKMode.chat:RegisterEvent("CHAT_MSG_BN_WHISPER")
self.AFKMode.chat:RegisterEvent("CHAT_MSG_BN_CONVERSATION")
self.AFKMode.chat:RegisterEvent("CHAT_MSG_GUILD")
self.AFKMode.bottom.model:SetModelScale(1)
self.AFKMode.bottom.model:RefreshUnit()
self.AFKMode.bottom.model:SetModelScale(0.8)
self.AFKMode.bottom.model.animTime = 0
self.AFKMode.bottom.model:SetScript("OnUpdate", UpdateAnimation)
self.AFKMode.bottom.model:SetScript("OnAnimFinished", OnAnimFinished)
self.isAFK = true
elseif not status and self.isAFK then
self.AFKMode:Hide()
UIParent:Show()
E.global.afkEnabled = nil
MoveViewLeftStop()
self:CancelTimer(self.timer)
self.AFKMode.bottom.time:SetText("00:00")
self.AFKMode.chat:UnregisterEvent("CHAT_MSG_WHISPER")
self.AFKMode.chat:UnregisterEvent("CHAT_MSG_BN_WHISPER")
self.AFKMode.chat:UnregisterEvent("CHAT_MSG_BN_CONVERSATION")
self.AFKMode.chat:UnregisterEvent("CHAT_MSG_GUILD")
self.AFKMode.chat:Clear()
self.isAFK = false
end
end
function mod:OnEvent(event, ...)
if event == "PLAYER_REGEN_DISABLED" or event == "LFG_PROPOSAL_SHOW" or event == "UPDATE_BATTLEFIELD_STATUS" then
if event == "UPDATE_BATTLEFIELD_STATUS" then
local status = GetBattlefieldStatus(...)
if status == "confirm" then
self:SetAFK(false)
end
else
self:SetAFK(false)
end
if event == "PLAYER_REGEN_DISABLED" then
self:RegisterEvent("PLAYER_REGEN_ENABLED", "OnEvent")
end
return
end
if event == "PLAYER_REGEN_ENABLED" then
self:ScheduleTimer("OnEvent", 10)
self:UnregisterEvent("PLAYER_REGEN_ENABLED")
return
end
if not E.db.general.afk then return end
if InCombatLockdown() or CinematicFrame:IsShown() or MovieFrame:IsShown() then return end
if UnitCastingInfo("player") ~= nil then
--Don't activate afk if player is crafting stuff, check back in 30 seconds
self:ScheduleTimer("OnEvent", 30)
return
end
self:SetAFK(UnitIsAFK("player"))
end
function mod:Toggle()
if E.db.general.afk then
self:RegisterEvent("PLAYER_FLAGS_CHANGED", "OnEvent")
self:RegisterEvent("PLAYER_REGEN_DISABLED", "OnEvent")
self:RegisterEvent("LFG_PROPOSAL_SHOW", "OnEvent")
self:RegisterEvent("UPDATE_BATTLEFIELD_STATUS", "OnEvent")
SetCVar("autoClearAFK", "1")
else
self:UnregisterEvent("PLAYER_FLAGS_CHANGED")
self:UnregisterEvent("PLAYER_REGEN_DISABLED")
self:UnregisterEvent("LFG_PROPOSAL_SHOW")
self:UnregisterEvent("UPDATE_BATTLEFIELD_STATUS")
self:CancelAllTimers()
end
end
local function OnKeyDown(_, key)
if ignoreKeys[key] then return end
if printKeys[key] then
Screenshot()
else
mod:SetAFK(false)
mod:ScheduleTimer("OnEvent", 60)
end
end
local function Chat_OnMouseWheel(self, delta)
if delta > 0 then
if IsShiftKeyDown() then
self:ScrollToTop()
else
self:ScrollUp()
end
elseif delta < 0 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)
local coloredName = GetColoredName(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)
local chatType = sub(event, 10)
local info = ChatTypeInfo[chatType]
local chatGroup = Chat_GetChatCategory(chatType)
local chatTarget
if chatGroup == "BN_CONVERSATION" then
chatTarget = tostring(arg8)
elseif chatGroup == "WHISPER" or chatGroup == "BN_WHISPER" then
chatTarget = upper(arg2)
end
local playerLink
if chatType ~= "BN_WHISPER" and chatType ~= "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
arg1 = gsub(arg1, "%%", "%%%%")
local body = format(_G["CHAT_"..chatType.."_GET"]..arg1, playerLink.."["..coloredName.."]".."|h")
if chatGroup == "BN_CONVERSATION" then
body = format(CHAT_BN_CONVERSATION_GET_LINK, arg8, MAX_WOW_CHAT_CHANNELS + arg8)..body
end
local accessID = ChatHistory_GetAccessID(chatGroup, chatTarget)
local typeID = ChatHistory_GetAccessID(chatType, chatTarget)
if E.db.chat.shortChannels then
body = gsub(body, "|Hchannel:(.-)|h%[(.-)%]|h", CH.ShortChannel)
body = gsub(body, "^(.-|h) "..L["whispers"], "%1")
body = gsub(body, "<"..AFK..">", "[|cffFF0000"..AFK.."|r] ")
body = gsub(body, "<"..DND..">", "[|cffE7E716"..DND.."|r] ")
body = gsub(body, "%[BN_CONVERSATION:", "%[".."")
end
if CH.db ~= nil and CH.db.timeStampFormat ~= "NONE" then
local timeStamp = BetterDate(CH.db.timeStampFormat, time())
if CH.db.useCustomTimeColor then
local color = CH.db.customTimeColor
local hexColor = E:RGBToHex(color.r, color.g, color.b)
body = format("%s[%s]|r %s", hexColor, timeStamp, body)
else
body = format("[%s] %s", timeStamp, body)
end
end
self:AddMessage(body, info.r, info.g, info.b, info.id, false, accessID, typeID)
end
function mod:Initialize()
self.AFKMode = CreateFrame("Frame", "ElvUIAFKFrame")
self.AFKMode:SetFrameLevel(1)
self.AFKMode:SetScale(UIParent:GetScale())
self.AFKMode:SetAllPoints(UIParent)
self.AFKMode:Hide()
self.AFKMode:EnableKeyboard(true)
self.AFKMode:SetScript("OnKeyDown", OnKeyDown)
self.AFKMode.chat = CreateFrame("ScrollingMessageFrame", "AFKChat", self.AFKMode)
self.AFKMode.chat:Size(500, 200)
self.AFKMode.chat:Point("TOPLEFT", self.AFKMode, "TOPLEFT", 4, -3)
self.AFKMode.chat:FontTemplate()
self.AFKMode.chat:SetJustifyH("LEFT")
self.AFKMode.chat:SetMaxLines(500)
self.AFKMode.chat:EnableMouseWheel(true)
self.AFKMode.chat:SetFading(false)
self.AFKMode.chat:SetMovable(true)
self.AFKMode.chat:EnableMouse(true)
self.AFKMode.chat:SetClampedToScreen(true)
self.AFKMode.chat:SetClampRectInsets(-4, 3, 3, -4)
self.AFKMode.chat:RegisterForDrag("LeftButton")
self.AFKMode.chat:SetScript("OnDragStart", self.AFKMode.chat.StartMoving)
self.AFKMode.chat:SetScript("OnDragStop", self.AFKMode.chat.StopMovingOrSizing)
self.AFKMode.chat:SetScript("OnMouseWheel", Chat_OnMouseWheel)
self.AFKMode.chat:SetScript("OnEvent", Chat_OnEvent)
self.AFKMode.bottom = CreateFrame("Frame", nil, self.AFKMode)
self.AFKMode.bottom:SetFrameLevel(0)
self.AFKMode.bottom:SetTemplate("Transparent")
self.AFKMode.bottom:Point("BOTTOM", self.AFKMode, "BOTTOM", 0, -E.Border)
self.AFKMode.bottom:Width(GetScreenWidth() + (E.Border*2))
self.AFKMode.bottom:Height(GetScreenHeight() * 0.1)
self.AFKMode.bottom.logo = self.AFKMode:CreateTexture(nil, "OVERLAY")
self.AFKMode.bottom.logo:Size(320, 150)
self.AFKMode.bottom.logo:Point("CENTER", self.AFKMode.bottom, "CENTER", 0, 50)
self.AFKMode.bottom.logo:SetTexture(E.Media.Textures.Logo)
self.AFKMode.bottom.faction = self.AFKMode.bottom:CreateTexture(nil, "OVERLAY")
self.AFKMode.bottom.faction:Point("BOTTOMLEFT", self.AFKMode.bottom, "BOTTOMLEFT", -20, -16)
self.AFKMode.bottom.faction:SetTexture("Interface\\AddOns\\ElvUI\\media\\textures\\"..E.myfaction.."-Logo")
self.AFKMode.bottom.faction:Size(140)
local classColor = E.media.herocolor
self.AFKMode.bottom.name = self.AFKMode.bottom:CreateFontString(nil, "OVERLAY")
self.AFKMode.bottom.name:FontTemplate(nil, 20)
self.AFKMode.bottom.name:SetFormattedText("%s - %s", E.myname, E.myrealm)
self.AFKMode.bottom.name:Point("TOPLEFT", self.AFKMode.bottom.faction, "TOPRIGHT", -10, -28)
self.AFKMode.bottom.name:SetTextColor(classColor.r, classColor.g, classColor.b)
self.AFKMode.bottom.guild = self.AFKMode.bottom:CreateFontString(nil, "OVERLAY")
self.AFKMode.bottom.guild:FontTemplate(nil, 20)
self.AFKMode.bottom.guild:SetText(L["No Guild"])
self.AFKMode.bottom.guild:Point("TOPLEFT", self.AFKMode.bottom.name, "BOTTOMLEFT", 0, -6)
self.AFKMode.bottom.guild:SetTextColor(0.7, 0.7, 0.7)
self.AFKMode.bottom.time = self.AFKMode.bottom:CreateFontString(nil, "OVERLAY")
self.AFKMode.bottom.time:FontTemplate(nil, 20)
self.AFKMode.bottom.time:SetText("00:00")
self.AFKMode.bottom.time:Point("TOPLEFT", self.AFKMode.bottom.guild, "BOTTOMLEFT", 0, -6)
self.AFKMode.bottom.time:SetTextColor(0.7, 0.7, 0.7)
self.AFKMode.bottom.model = CreateFrame("PlayerModel", "ElvUIAFKPlayerModel", self.AFKMode.bottom)
self.AFKMode.bottom.model:Point("BOTTOMRIGHT", self.AFKMode.bottom, "BOTTOMRIGHT", 120, -100)
self.AFKMode.bottom.model:Size(800)
self.AFKMode.bottom.model:SetFacing(6)
self.AFKMode.bottom.model:SetUnit("player")
if E.db.general.afk then
self:Toggle()
end
self.Initialized = true
end
local function InitializeCallback()
mod:Initialize()
end
E:RegisterModule(mod:GetName(), InitializeCallback)
+262
View File
@@ -0,0 +1,262 @@
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")
--Lua functions
local select, unpack = select, unpack
local format, gmatch, gsub, lower, match = string.format, string.gmatch, string.gsub, string.lower, string.match
--WoW API / Variables
local GetPlayerInfoByGUID = GetPlayerInfoByGUID
local WorldFrame = WorldFrame
local WorldGetChildren = WorldFrame.GetChildren
local WorldGetNumChildren = WorldFrame.GetNumChildren
--Message caches
local messageToGUID = {}
local messageToSender = {}
function M:UpdateBubbleBorder()
if not self.text then return end
if E.private.general.chatBubbles == "backdrop" then
if E.PixelMode then
self:SetBackdropBorderColor(self.text:GetTextColor())
else
local r, g, b = self.text:GetTextColor()
self.bordertop:SetTexture(r, g, b)
self.borderbottom:SetTexture(r, g, b)
self.borderleft:SetTexture(r, g, b)
self.borderright:SetTexture(r, g, b)
end
end
local text = self.text:GetText()
if self.Name then
self.Name:SetText("") --Always reset it
if text and E.private.general.chatBubbleName then
M:AddChatBubbleName(self, messageToGUID[text], messageToSender[text])
end
end
if E.private.chat.enable and E.private.general.classColorMentionsSpeech then
if text and match(text, "%s-%S+%s*") then
local classColorTable, lowerCaseWord, isFirstWord, rebuiltString, tempWord, wordMatch, classMatch
for word in gmatch(text, "%s-%S+%s*") do
tempWord = gsub(word, "^[%s%p]-([^%s%p]+)([%-]?[^%s%p]-)[%s%p]*$", "%1%2")
lowerCaseWord = lower(tempWord)
classMatch = CH.ClassNames[lowerCaseWord]
wordMatch = classMatch and lowerCaseWord
if wordMatch and not E.global.chat.classColorMentionExcludedNames[wordMatch] then
classColorTable = E.media.herocolor
word = gsub(word, gsub(tempWord, "%-", "%%-"), format("\124cff%.2x%.2x%.2x%s\124r", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, tempWord))
end
if not isFirstWord then
rebuiltString = word
isFirstWord = true
else
rebuiltString = format("%s%s", rebuiltString, word)
end
end
if rebuiltString then
self.text:SetText(rebuiltString)
end
end
end
end
function M:AddChatBubbleName(chatBubble, guid, name)
if not name then return end
local color
if guid and guid ~= "" then
local _, class = GetPlayerInfoByGUID(guid)
if class then
color = E:RGBToHex(E.media.herocolor.r, E.media.herocolor.g, E.media.herocolor.b)
end
else
color = "|cffffffff"
end
chatBubble.Name:SetFormattedText("%s%s|r", color, name)
end
function M:SkinBubble(frame)
local mult = E.mult * UIParent:GetScale()
for i = 1, frame:GetNumRegions() do
local region = select(i, frame:GetRegions())
if region:IsObjectType("Texture") then
region:SetTexture(nil)
elseif region:IsObjectType("FontString") then
frame.text = region
end
end
local name = frame:CreateFontString(nil, "OVERLAY")
if E.private.general.chatBubbles == "backdrop" then
name:SetPoint("TOPLEFT", 5, E.PixelMode and 15 or 18)
else
name:SetPoint("TOPLEFT", 5, 6)
end
name:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", -5, -5)
name:SetJustifyH("LEFT")
name:FontTemplate(E.Libs.LSM:Fetch("font", E.private.general.chatBubbleFont), E.private.general.chatBubbleFontSize * 0.85, E.private.general.chatBubbleFontOutline)
frame.Name = name
if E.private.general.chatBubbles == "backdrop" then
if E.PixelMode then
frame:SetBackdrop({
bgFile = E.media.blankTex,
edgeFile = E.media.blankTex,
tile = false, tileSize = 0, edgeSize = mult,
insets = {left = 0, right = 0, top = 0, bottom = 0}
})
frame:SetBackdropColor(unpack(E.media.backdropfadecolor))
frame:SetBackdropBorderColor(0, 0, 0)
else
frame:SetBackdrop(nil)
end
local r, g, b = frame.text:GetTextColor()
if not E.PixelMode then
local mult2 = mult * 2
local mult3 = mult * 3
frame.backdrop = frame:CreateTexture(nil, "BACKGROUND")
frame.backdrop:SetAllPoints(frame)
frame.backdrop:SetTexture(unpack(E.media.backdropfadecolor))
frame.bordertop = frame:CreateTexture(nil, "ARTWORK")
frame.bordertop:SetPoint("TOPLEFT", frame, "TOPLEFT", -mult2, mult2)
frame.bordertop:SetPoint("TOPRIGHT", frame, "TOPRIGHT", mult2, mult2)
frame.bordertop:SetHeight(mult)
frame.bordertop:SetTexture(r, g, b)
frame.bordertop.backdrop = frame:CreateTexture(nil, "BORDER")
frame.bordertop.backdrop:SetPoint("TOPLEFT", frame.bordertop, "TOPLEFT", -mult, mult)
frame.bordertop.backdrop:SetPoint("TOPRIGHT", frame.bordertop, "TOPRIGHT", mult, mult)
frame.bordertop.backdrop:SetHeight(mult3)
frame.bordertop.backdrop:SetTexture(0, 0, 0)
frame.borderbottom = frame:CreateTexture(nil, "ARTWORK")
frame.borderbottom:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", -mult2, -mult2)
frame.borderbottom:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", mult2, -mult2)
frame.borderbottom:SetHeight(mult)
frame.borderbottom:SetTexture(r, g, b)
frame.borderbottom.backdrop = frame:CreateTexture(nil, "BORDER")
frame.borderbottom.backdrop:SetPoint("BOTTOMLEFT", frame.borderbottom, "BOTTOMLEFT", -mult, -mult)
frame.borderbottom.backdrop:SetPoint("BOTTOMRIGHT", frame.borderbottom, "BOTTOMRIGHT", mult, -mult)
frame.borderbottom.backdrop:SetHeight(mult3)
frame.borderbottom.backdrop:SetTexture(0, 0, 0)
frame.borderleft = frame:CreateTexture(nil, "ARTWORK")
frame.borderleft:SetPoint("TOPLEFT", frame, "TOPLEFT", -mult2, mult2)
frame.borderleft:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", mult2, -mult2)
frame.borderleft:SetWidth(mult)
frame.borderleft:SetTexture(r, g, b)
frame.borderleft.backdrop = frame:CreateTexture(nil, "BORDER")
frame.borderleft.backdrop:SetPoint("TOPLEFT", frame.borderleft, "TOPLEFT", -mult, mult)
frame.borderleft.backdrop:SetPoint("BOTTOMLEFT", frame.borderleft, "BOTTOMLEFT", -mult, -mult)
frame.borderleft.backdrop:SetWidth(mult3)
frame.borderleft.backdrop:SetTexture(0, 0, 0)
frame.borderright = frame:CreateTexture(nil, "ARTWORK")
frame.borderright:SetPoint("TOPRIGHT", frame, "TOPRIGHT", mult2, mult2)
frame.borderright:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -mult2, -mult2)
frame.borderright:SetWidth(mult)
frame.borderright:SetTexture(r, g, b)
frame.borderright.backdrop = frame:CreateTexture(nil, "BORDER")
frame.borderright.backdrop:SetPoint("TOPRIGHT", frame.borderright, "TOPRIGHT", mult, mult)
frame.borderright.backdrop:SetPoint("BOTTOMRIGHT", frame.borderright, "BOTTOMRIGHT", mult, -mult)
frame.borderright.backdrop:SetWidth(mult3)
frame.borderright.backdrop:SetTexture(0, 0, 0)
else
frame:SetBackdropColor(unpack(E.media.backdropfadecolor))
frame:SetBackdropBorderColor(r, g, b)
end
frame.text:FontTemplate(E.LSM:Fetch("font", E.private.general.chatBubbleFont), E.private.general.chatBubbleFontSize, E.private.general.chatBubbleFontOutline)
elseif E.private.general.chatBubbles == "backdrop_noborder" then
frame:SetBackdrop(nil)
if not frame.backdrop then
frame.backdrop = frame:CreateTexture(nil, "ARTWORK")
frame.backdrop:SetInside(frame, 4, 4)
frame.backdrop:SetTexture(unpack(E.media.backdropfadecolor))
end
frame.text:FontTemplate(E.LSM:Fetch("font", E.private.general.chatBubbleFont), E.private.general.chatBubbleFontSize, E.private.general.chatBubbleFontOutline)
frame:SetClampedToScreen(false)
elseif E.private.general.chatBubbles == "nobackdrop" then
frame:SetBackdrop(nil)
frame.text:FontTemplate(E.LSM:Fetch("font", E.private.general.chatBubbleFont), E.private.general.chatBubbleFontSize, E.private.general.chatBubbleFontOutline)
frame:SetClampedToScreen(false)
end
frame:HookScript("OnShow", M.UpdateBubbleBorder)
frame:SetFrameStrata("DIALOG")
M.UpdateBubbleBorder(frame)
frame.isSkinnedElvUI = true
end
function M:IsChatBubble(frame)
for i = 1, frame:GetNumRegions() do
local region = select(i, frame:GetRegions())
if region.GetTexture and region:GetTexture() and region:GetTexture() == [[Interface\Tooltips\ChatBubble-Background]] then
return true
end
end
end
local function ChatBubble_OnEvent(self, event, msg, sender, _, _, _, _, _, _, _, _, _, guid)
if not E.private.general.chatBubbleName then return end
messageToGUID[msg] = guid
messageToSender[msg] = sender
end
local lastChildern, numChildren = 0, 0
local function findChatBubbles(...)
for i = lastChildern + 1, numChildren do
local frame = select(i, ...)
if not frame.isSkinnedElvUI and M:IsChatBubble(frame) then
M:SkinBubble(frame)
end
end
end
local function ChatBubble_OnUpdate(self, elapsed)
self.lastupdate = self.lastupdate + elapsed
if self.lastupdate < .1 then return end
self.lastupdate = 0
numChildren = WorldGetNumChildren(WorldFrame)
if lastChildern ~= numChildren then
findChatBubbles(WorldGetChildren(WorldFrame))
lastChildern = numChildren
end
end
function M:LoadChatBubbles()
if E.private.general.chatBubbles == "disabled" then return end
self.BubbleFrame = CreateFrame("Frame")
self.BubbleFrame.lastupdate = -2 -- wait 2 seconds before hooking frames
self.BubbleFrame:RegisterEvent("CHAT_MSG_SAY")
self.BubbleFrame:RegisterEvent("CHAT_MSG_YELL")
self.BubbleFrame:RegisterEvent("CHAT_MSG_PARTY")
self.BubbleFrame:RegisterEvent("CHAT_MSG_PARTY_LEADER")
self.BubbleFrame:RegisterEvent("CHAT_MSG_MONSTER_SAY")
self.BubbleFrame:RegisterEvent("CHAT_MSG_MONSTER_YELL")
self.BubbleFrame:SetScript("OnEvent", ChatBubble_OnEvent)
self.BubbleFrame:SetScript("OnUpdate", ChatBubble_OnUpdate)
end
+162
View File
@@ -0,0 +1,162 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local D = E:GetModule("DebugTools")
--Lua functions
local format = string.format
--WoW API / Variables
local GetCVarBool = GetCVarBool
local InCombatLockdown = InCombatLockdown
function D:ModifyErrorFrame()
ScriptErrorsFrameScrollFrameText.cursorOffset = 0
ScriptErrorsFrameScrollFrameText.cursorHeight = 0
ScriptErrorsFrameScrollFrameText:SetScript("OnEditFocusGained", nil)
local Orig_ScriptErrorsFrame_Update = ScriptErrorsFrame_Update
ScriptErrorsFrame_Update = function(...)
if GetCVarBool("scriptErrors") ~= 1 then
Orig_ScriptErrorsFrame_Update(...)
return
end
-- Sometimes the locals table does not have an entry for an index, which can cause an argument #6 error
-- in Blizzard_DebugTools.lua:430 and then cause a C stack overflow, this will prevent that
local index = ScriptErrorsFrame.index
if not index or not ScriptErrorsFrame.order[index] then
index = #(ScriptErrorsFrame.order)
end
if index > 0 then
ScriptErrorsFrame.locals[index] = ScriptErrorsFrame.locals[index] or "No locals to dump"
end
Orig_ScriptErrorsFrame_Update(...)
-- Stop text highlighting again
ScriptErrorsFrameScrollFrameText:HighlightText(0, 0)
end
-- Unhighlight text when focus is hit
ScriptErrorsFrameScrollFrameText:HookScript("OnEscapePressed", function(self)
self:HighlightText(0, 0)
end)
ScriptErrorsFrame:Size(500, 300)
ScriptErrorsFrameScrollFrame:Size(ScriptErrorsFrame:GetWidth() - 45, ScriptErrorsFrame:GetHeight() - 71)
ScriptErrorsFrameScrollFrameText:Width(ScriptErrorsFrameScrollFrame:GetWidth())
local BUTTON_WIDTH = 75
local BUTTON_HEIGHT = 24
local BUTTON_SPACING = 2
-- Add a first button
local firstButton = CreateFrame("Button", nil, ScriptErrorsFrame, "UIPanelButtonTemplate")
firstButton:SetPoint("BOTTOM", -((BUTTON_WIDTH + BUTTON_WIDTH/2) + (BUTTON_SPACING * 4)), 8)
firstButton:SetText("First")
firstButton:SetHeight(BUTTON_HEIGHT)
firstButton:SetWidth(BUTTON_WIDTH)
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")
lastButton:SetPoint("BOTTOMLEFT", ScriptErrorsFrame.next, "BOTTOMRIGHT", BUTTON_SPACING, 0)
lastButton:SetHeight(BUTTON_HEIGHT)
lastButton:SetWidth(BUTTON_WIDTH)
lastButton:SetText("Last")
lastButton:SetScript("OnClick", function()
ScriptErrorsFrame.index = #(ScriptErrorsFrame.order)
ScriptErrorsFrame_Update()
end)
ScriptErrorsFrame.lastButton = lastButton
ScriptErrorsFrame.previous:ClearAllPoints()
ScriptErrorsFrame.previous:SetPoint("BOTTOMLEFT", firstButton, "BOTTOMRIGHT", BUTTON_SPACING, 0)
ScriptErrorsFrame.previous:SetWidth(BUTTON_WIDTH)
ScriptErrorsFrame.previous:SetHeight(BUTTON_HEIGHT)
ScriptErrorsFrame.next:ClearAllPoints()
ScriptErrorsFrame.next:SetPoint("BOTTOMLEFT", ScriptErrorsFrame.previous, "BOTTOMRIGHT", BUTTON_SPACING, 0)
ScriptErrorsFrame.next:SetWidth(BUTTON_WIDTH)
ScriptErrorsFrame.next:SetHeight(BUTTON_HEIGHT)
ScriptErrorsFrame.close:ClearAllPoints()
ScriptErrorsFrame.close:SetPoint("BOTTOMRIGHT", -8, 8)
ScriptErrorsFrame.close:SetSize(75, BUTTON_HEIGHT)
ScriptErrorsFrame.indexLabel:ClearAllPoints()
ScriptErrorsFrame.indexLabel:SetPoint("BOTTOMLEFT", 0, 12)
end
function D:ScriptErrorsFrame_UpdateButtons()
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 self.MessagePrinted or not InCombatLockdown() or GetCVarBool("scriptErrors") ~= 1 then return end
E:Print(L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."])
self.MessagePrinted = true
end
function D:PLAYER_REGEN_ENABLED()
ScriptErrorsFrame:SetParent(UIParent)
self.MessagePrinted = nil
end
function D:PLAYER_REGEN_DISABLED()
ScriptErrorsFrame:SetParent(self.HideFrame)
end
function D:TaintError(event, addonName, addonFunc)
if GetCVarBool("scriptErrors") ~= 1 or E.db.general.taintLog ~= true then return end
ScriptErrorsFrame_OnError(format(L["%s: %s tried to call the protected function '%s'."], event, addonName or "<name>", addonFunc or "<func>"), false)
end
function D:StaticPopup_Show(name)
if name == "ADDON_ACTION_FORBIDDEN" and E.db.general.taintLog ~= true then
StaticPopup_Hide(name)
end
end
function D:Initialize()
self.Initialized = true
self.HideFrame = CreateFrame("Frame")
self.HideFrame:Hide()
if not IsAddOnLoaded("Blizzard_DebugTools") then
LoadAddOn("Blizzard_DebugTools")
end
self:ModifyErrorFrame()
self:SecureHook("ScriptErrorsFrame_UpdateButtons")
self:SecureHook("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
local function InitializeCallback()
D:Initialize()
end
E:RegisterModule(D:GetName(), InitializeCallback)
+13
View File
@@ -0,0 +1,13 @@
<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="Raidbuffreminder.lua"/>
<Script file="Threat.lua"/>
<Script file="TotemBar.lua"/>
<Script file="RaidUtility.lua"/>
<Script file="AFK.lua"/>
</Ui>
+352
View File
@@ -0,0 +1,352 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local M = E:GetModule("Misc")
--Lua functions
local unpack, pairs = unpack, pairs
local max = math.max
local find, gsub = string.find, string.gsub
local tinsert = table.insert
--WoW API / Variables
local CloseLoot = CloseLoot
local CreateFrame = CreateFrame
local CursorOnUpdate = CursorOnUpdate
local CursorUpdate = CursorUpdate
local GetCVar = GetCVar
local GetCursorPosition = GetCursorPosition
local GetLootSlotInfo = GetLootSlotInfo
local GetLootSlotLink = GetLootSlotLink
local GetNumLootItems = GetNumLootItems
local GiveMasterLoot = GiveMasterLoot
local HandleModifiedItemClick = HandleModifiedItemClick
local IsFishingLoot = IsFishingLoot
local IsModifiedClick = IsModifiedClick
local LootSlot = LootSlot
local LootSlotIsItem = LootSlotIsItem
local ResetCursor = ResetCursor
local StaticPopup_Hide = StaticPopup_Hide
local ToggleDropDownMenu = ToggleDropDownMenu
local UnitIsDead = UnitIsDead
local UnitIsFriend = UnitIsFriend
local UnitName = UnitName
local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
local TEXTURE_ITEM_QUEST_BANG = TEXTURE_ITEM_QUEST_BANG
local LOOT = LOOT
-- Credit Haste
local lootFrame, lootFrameHolder
local iconSize = 30
local sq, ss, sn
local OnEnter = function(self)
local slot = self:GetID()
if LootSlotIsItem(slot) then
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetLootItem(slot)
CursorUpdate(self)
end
self.drop:Show()
self.drop:SetVertexColor(1, 1, 1)
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
GameTooltip:Hide()
ResetCursor()
end
local OnClick = function(self)
LootFrame.selectedQuality = self.quality
LootFrame.selectedItemName = self.name:GetText()
LootFrame.selectedSlot = self:GetID()
LootFrame.selectedLootButton = self:GetName()
if IsModifiedClick() then
HandleModifiedItemClick(GetLootSlotLink(self:GetID()))
else
StaticPopup_Hide("CONFIRM_LOOT_DISTRIBUTION")
ss = self:GetID()
sq = self.quality
sn = self.name:GetText()
LootSlot(ss)
end
end
local OnShow = function(self)
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 frame = CreateFrame("Button", "ElvLootSlot"..id, lootFrame)
frame:Point("LEFT", 8, 0)
frame:Point("RIGHT", -8, 0)
frame:Height(iconSize - 2)
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)
iconFrame:Size(iconSize - 2)
iconFrame:Point("RIGHT", frame)
iconFrame:SetTemplate("Default")
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(1, 1, 1, 0.15)
drop:Point("LEFT", icon, "RIGHT", 0, 0)
drop:Point("RIGHT", frame)
drop:SetAllPoints(frame)
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
lootFrame.slots[slot]:Hide()
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:OPEN_MASTER_LOOT_LIST()
ToggleDropDownMenu(1, nil, GroupLootDropDown, lootFrame.slots[ss], 0, 0)
end
function M:UPDATE_MASTER_LOOT_LIST()
UIDropDownMenu_Refresh(GroupLootDropDown)
end
function M:LOOT_OPENED(_, autoLoot)
lootFrame:Show()
if not lootFrame:IsShown() then
CloseLoot(autoLoot == 0)
end
local items = GetNumLootItems()
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 GetCVar("lootUnderMouse") == "1" then
local x, y = GetCursorPosition()
x = x / lootFrame:GetEffectiveScale()
y = y / lootFrame:GetEffectiveScale()
lootFrame:ClearAllPoints()
lootFrame:Point("TOPLEFT", 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()
if items > 0 then
for i = 1, items do
local slot = lootFrame.slots[i] or createSlot(i)
local texture, item, quantity, quality, _, isQuestItem, questId, isActive = GetLootSlotInfo(i)
local color = ITEM_QUALITY_COLORS[quality]
if texture and find(texture, "INV_Misc_Coin") then
item = gsub(item, "\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(texture)
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:SetTexture(TEXTURE_ITEM_QUEST_BANG)
questTexture:Show()
elseif questId or isQuestItem then
questTexture:SetTexture(TEXTURE_ITEM_QUEST_BORDER)
questTexture:Show()
else
questTexture:Hide()
end
-- Check for FasterLooting scripts or w/e (if bag is full)
if texture 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("TOP", 0, -50)
lootFrameHolder:Size(150, 22)
lootFrame = CreateFrame("Button", "ElvLootFrame", lootFrameHolder)
lootFrame:SetClampedToScreen(true)
lootFrame:SetPoint("TOPLEFT")
lootFrame:Size(256, 64)
lootFrame:SetTemplate("Transparent")
lootFrame:SetFrameStrata("DIALOG")
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")
self:RegisterEvent("OPEN_MASTER_LOOT_LIST")
self:RegisterEvent("UPDATE_MASTER_LOOT_LIST")
E:CreateMover(lootFrameHolder, "LootFrameMover", L["Loot Frame"], nil, nil, nil, nil, nil, "general,blizzUIImprovements")
-- Fuzz
LootFrame:UnregisterAllEvents()
tinsert(UISpecialFrames, "ElvLootFrame")
function _G.GroupLootDropDown_GiveLoot(self)
if sq >= MASTER_LOOT_THREHOLD then
local dialog = StaticPopup_Show("CONFIRM_LOOT_DISTRIBUTION", ITEM_QUALITY_COLORS[sq].hex..sn..FONT_COLOR_CODE_CLOSE, self:GetText())
if dialog then
dialog.data = self.value
end
else
GiveMasterLoot(ss, self.value)
end
CloseDropDownMenus()
end
E.PopupDialogs.CONFIRM_LOOT_DISTRIBUTION.OnAccept = function(_, data)
GiveMasterLoot(ss, data)
end
StaticPopupDialogs.CONFIRM_LOOT_DISTRIBUTION.preferredIndex = 3
end
+474
View File
@@ -0,0 +1,474 @@
local E, L, V, P, G = unpack(select(2, ...)) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local M = E:GetModule("Misc")
--Lua functions
local pairs, ipairs, unpack = pairs, ipairs, unpack
local find, format = string.find, string.format
local tinsert, twipe = table.insert, table.wipe
--WoW API / Variables
local ChatEdit_InsertLink = ChatEdit_InsertLink
local CreateFrame = CreateFrame
local CursorOnUpdate = CursorOnUpdate
local CursorUpdate = CursorUpdate
local DressUpItemLink = DressUpItemLink
local GetLootRollItemInfo = GetLootRollItemInfo
local GetLootRollItemLink = GetLootRollItemLink
local GetLootRollTimeLeft = GetLootRollTimeLeft
local IsModifiedClick = IsModifiedClick
local ResetCursor = ResetCursor
local RollOnLoot = RollOnLoot
local SetDesaturation = SetDesaturation
local UnitClass = UnitClass
local ITEM_QUALITY_COLORS = ITEM_QUALITY_COLORS
local ROLL_DISENCHANT = ROLL_DISENCHANT
local POSITION = "TOP"
local FRAME_WIDTH, FRAME_HEIGHT = 328, 28
M.RollBars = {}
local locale = GetLocale()
local rollMessages = locale == "deDE" and {
["(.*) passt automatisch bei (.+), weil [ersi]+ den Gegenstand nicht benutzen kann.$"] = 0,
["(.*) würfelt nicht für: (.+|r)$"] = 0,
["(.*) hat für (.+) 'Bedarf' ausgewählt"] = 1,
["(.*) hat für (.+) 'Gier' ausgewählt"] = 2,
["(.*) hat für '(.+)' Entzauberung gewählt."] = 3,
} or locale == "frFR" and {
["(.*) a passé pour : (.+) parce qu'((il)|(elle)) ne peut pas ramasser cette objet.$"] = 0,
["(.*) a passé pour : (.+)"] = 0,
["(.*) a choisi Besoin pour : (.+)"] = 1,
["(.*) a choisi Cupidité pour : (.+)"] = 2,
["(.*) a choisi Désenchantement pour : (.+)"] = 3,
} or locale == "zhCN" and {
["(.*)自动放弃了:(.+),因为他无法拾取该物品$"] = 0,
["(.*)自动放弃了:(.+),因为她无法拾取该物品$"] = 0,
["(.*)放弃了:(.+)"] = 0,
["(.*)选择了需求取向:(.+)"] = 1,
["(.*)选择了贪婪取向:(.+)"] = 2,
["(.*)选择了分解取向:(.+)"] = 3,
} or locale == "zhTW" and {
["(.*)自動放棄:(.+),因為他無法拾取該物品$"] = 0,
["(.*)自動放棄:(.+),因為她無法拾取該物品$"] = 0,
["(.*)放棄了:(.+)"] = 0,
["(.*)選擇了需求:(.+)"] = 1,
["(.*)選擇了貪婪:(.+)"] = 2,
["(.*)選擇了分解:(.+)"] = 3,
} or locale == "ruRU" and {
["(.*) автоматически передает предмет (.+), поскольку не может его забрать"] = 0,
["(.*) пропускает розыгрыш предмета \"(.+)\", поскольку не может его забрать"] = 0,
["(.*) отказывается от предмета (.+)%."] = 0,
["Разыгрывается: (.+)%. (.*): \"Мне это нужно\""] = 1,
["Разыгрывается: (.+)%. (.*): \"Не откажусь\""] = 2,
["Разыгрывается: (.+)%. (.*): \"Распылить\""] = 3,
} or locale == "koKR" and {
["(.*)님이 획득할 수 없는 아이템이어서 자동으로 주사위 굴리기를 포기했습니다: (.+)"] = 0,
["(.*)님이 주사위 굴리기를 포기했습니다: (.+)"] = 0,
["(.*)님이 입찰을 선택했습니다: (.+)"] = 1,
["(.*)님이 차비를 선택했습니다: (.+)"] = 2,
["(.*)님이 마력 추출을 선택했습니다: (.+)"] = 3,
} or locale == "esES" and {
["^(.*) pasó automáticamente de: (.+) porque no puede despojar este objeto.$"] = 0,
["^(.*) pasó de: (.+|r)$"] = 0,
["(.*) eligió Necesidad para: (.+)"] = 1,
["(.*) eligió Codicia para: (.+)"] = 2,
["(.*) eligió Desencantar para: (.+)"] = 3,
} or locale == "esMX" and {
["^(.*) pasó automáticamente de: (.+) porque no puede despojar este objeto.$"] = 0,
["^(.*) pasó de: (.+|r)$"] = 0,
["(.*) eligió Necesidad para: (.+)"] = 1,
["(.*) eligió Codicia para: (.+)"] = 2,
["(.*) eligió Desencantar para: (.+)"] = 3,
} or {
["^(.*) automatically passed on: (.+) because s?he cannot loot that item.$"] = 0,
["^(.*) passed on: (.+|r)$"] = 0,
["(.*) has selected Need for: (.+)"] = 1,
["(.*) has selected Greed for: (.+)"] = 2,
["(.*) has selected Disenchant for: (.+)"] = 3
}
local rollTypes = {
[0] = {
tooltipText = PASS,
normalTexture = "Interface\\Buttons\\UI-GroupLoot-Pass-Up",
pushedTexture = "Interface\\Buttons\\UI-GroupLoot-Pass-Down",
highlightTexture = nil,
},
[1] = {
tooltipText = NEED,
newbieText = NEED_NEWBIE,
normalTexture = "Interface\\Buttons\\UI-GroupLoot-Dice-Up",
pushedTexture = "Interface\\Buttons\\UI-GroupLoot-Dice-Down",
highlightTexture = "Interface\\Buttons\\UI-GroupLoot-Dice-Highlight",
},
[2] = {
tooltipText = GREED,
newbieText = GREED_NEWBIE,
normalTexture = "Interface\\Buttons\\UI-GroupLoot-Coin-Up",
pushedTexture = "Interface\\Buttons\\UI-GroupLoot-Coin-Down",
highlightTexture = "Interface\\Buttons\\UI-GroupLoot-Coin-Highlight",
},
[3] = {
tooltipText = ROLL_DISENCHANT,
newbieText = ROLL_DISENCHANT_NEWBIE,
normalTexture = "Interface\\Buttons\\UI-GroupLoot-DE-Up",
pushedTexture = "Interface\\Buttons\\UI-GroupLoot-DE-Down",
highlightTexture = "Interface\\Buttons\\UI-GroupLoot-DE-Highlight",
},
}
local reasons = {
LOOT_ROLL_INELIGIBLE_REASON1,
LOOT_ROLL_INELIGIBLE_REASON2,
LOOT_ROLL_INELIGIBLE_REASON3,
LOOT_ROLL_INELIGIBLE_REASON4,
LOOT_ROLL_INELIGIBLE_REASON5,
}
local function buttonOnEnter(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(self.tooltipText)
if self.newbieText and SHOW_NEWBIE_TIPS == "1" then
GameTooltip:AddLine(self.newbieText, 1, 0.82, 0, true)
end
if self:IsEnabled() == 0 then
GameTooltip:AddLine(self.reason, 1, 0.1, 0.1, true)
end
for playerName, rollData in pairs(self.parent.rollResults) do
if self.rollType == rollData[1] and rollData[2] then
local classColor = E.media.herocolor
GameTooltip:AddLine(playerName, classColor.r, classColor.g, classColor.b)
end
end
GameTooltip:Show()
end
local function buttonOnLeave()
GameTooltip:Hide()
end
local function buttonOnClick(self)
RollOnLoot(self.parent.rollID, self.rollType)
end
local function toggleLootButton(self, state, reason, reasonValue)
if state then
self:Enable()
self:SetAlpha(1)
self.reason = nil
SetDesaturation(self:GetNormalTexture(), false)
else
self:Disable()
self:SetAlpha(0.2)
self.reason = reasonValue and format(reasons[reason], reasonValue) or reasons[reason]
SetDesaturation(self:GetNormalTexture(), true)
end
end
local function increaseRollCount(self, count)
local text = self.text:GetText()
if not text or text == "" then
self.text:SetText(count or 1)
else
self.text:SetText(self.text:GetText() + (count or 1))
end
end
function M:CreateRollButton(parent, rollType)
local data = rollTypes[rollType]
local button = CreateFrame("Button", nil, parent)
button:Size(FRAME_HEIGHT - 4)
button:SetNormalTexture(data.normalTexture)
button:SetPushedTexture(data.highlightTexture)
button:SetHighlightTexture(data.pushedTexture)
button:SetMotionScriptsWhileDisabled(true)
button:SetScript("OnEnter", buttonOnEnter)
button:SetScript("OnLeave", buttonOnLeave)
button:SetScript("OnClick", buttonOnClick)
button.ToggleLootButton = toggleLootButton
button.IncreaseRollCount = increaseRollCount
button.parent = parent
button.rollType = rollType
button.tooltipText = data.tooltipText
button.newbieText = data.newbieText
button.text = button:CreateFontString(nil, nil)
button.text:FontTemplate(E.Media.Fonts.Homespun, nil, "MONOCHROMEOUTLINE")
return button
end
local function itemOnEnter(self)
GameTooltip:SetOwner(self, POSITION == "TOP" and "ANCHOR_BOTTOMLEFT" or "ANCHOR_TOPLEFT")
GameTooltip:SetLootRollItem(self.rollID)
CursorUpdate(self)
end
local function itemOnLeave()
GameTooltip:Hide()
ResetCursor()
end
local function itemOnUpdate(self)
if GameTooltip:IsOwned(self) then
GameTooltip:SetOwner(self, POSITION == "TOP" and "ANCHOR_BOTTOMLEFT" or "ANCHOR_TOPLEFT")
GameTooltip:SetLootRollItem(self.rollID)
end
CursorOnUpdate(self)
end
local function itemOnClick(self)
if IsModifiedClick("CHATLINK") then
ChatEdit_InsertLink(self.link)
elseif IsModifiedClick("DRESSUP") then
DressUpItemLink(self.link)
end
end
local function statusbarOnUpdate(self)
local timeLeft = GetLootRollTimeLeft(self.parent.rollID)
if timeLeft < 0 or timeLeft > self.parent.rollTime then
timeLeft = 0
else
self.spark:Point("CENTER", self, "LEFT", (timeLeft / self.parent.rollTime) * self:GetWidth(), 0)
end
self:SetValue(timeLeft)
end
function M:CreateRollFrame()
self.numFrames = self.numFrames + 1
local frame = CreateFrame("Frame", format("ElvUI_GroupLootFrame%d", self.numFrames), E.UIParent)
frame:Size(FRAME_WIDTH, FRAME_HEIGHT)
frame:SetTemplate()
frame:SetFrameStrata("DIALOG")
frame:Hide()
if POSITION == "TOP" then
frame:Point("TOP", self.numFrames > 1 and self.RollBars[self.numFrames - 1] or AlertFrameHolder, "BOTTOM", 0, -4)
else
frame:Point("BOTTOM", self.numFrames > 1 and self.RollBars[self.numFrames - 1] or AlertFrameHolder, "TOP", 0, 4)
end
local itemButton = CreateFrame("Button", "$parentIconFrame", frame)
itemButton:Size(FRAME_HEIGHT - (E.Border * 2))
itemButton:Point("RIGHT", frame, "LEFT", -(E.Spacing * 3), 0)
itemButton:CreateBackdrop()
itemButton:SetScript("OnEnter", itemOnEnter)
itemButton:SetScript("OnLeave", itemOnLeave)
itemButton:SetScript("OnUpdate", itemOnUpdate)
itemButton:SetScript("OnClick", itemOnClick)
itemButton.hasItem = 1
frame.itemButton = itemButton
itemButton.icon = itemButton:CreateTexture(nil, "OVERLAY")
itemButton.icon:SetAllPoints()
itemButton.icon:SetTexCoord(unpack(E.TexCoords))
local fade = frame:CreateTexture(nil, "BORDER")
fade:Point("TOPLEFT", frame, "TOPLEFT", 4, 0)
fade:Point("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -4, 0)
fade:SetTexture("Interface\\ChatFrame\\ChatFrameBackground")
fade:SetBlendMode("ADD")
fade:SetGradientAlpha("VERTICAL", 0.1, 0.1, 0.1, 0, 0.1, 0.1, 0.1, 0)
frame.fade = fade
local status = CreateFrame("StatusBar", "$parentStatusBar", frame)
status:SetInside()
status:SetFrameLevel(status:GetFrameLevel() - 1)
status:SetStatusBarTexture(E.media.normTex)
status:SetStatusBarColor(0.8, 0.8, 0.8, 0.9)
status.parent = frame
E:RegisterStatusBar(status)
status:SetScript("OnUpdate", statusbarOnUpdate)
frame.status = status
status.bg = status:CreateTexture(nil, "BACKGROUND")
status.bg:SetAlpha(0.1)
status.bg:SetAllPoints()
local spark = frame:CreateTexture(nil, "OVERLAY")
spark:Size(14, FRAME_HEIGHT)
spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
spark:SetBlendMode("ADD")
status.spark = spark
frame.passButton = self:CreateRollButton(frame, 0)
frame.needButton = self:CreateRollButton(frame, 1)
frame.greedButton = self:CreateRollButton(frame, 2)
frame.disenchantButton = self:CreateRollButton(frame, 3)
frame.needButton:SetHitRectInsets(0, 0, -2, 0)
frame.greedButton:SetHitRectInsets(0, 0, -3, 1)
frame.disenchantButton:SetHitRectInsets(0, 0, -2, 0)
frame.passButton:SetHitRectInsets(0, 0, 0, -2)
frame.needButton:Point("LEFT", frame.itemButton, "RIGHT", 4, -1)
frame.greedButton:Point("LEFT", frame.needButton, "RIGHT", 1, -1)
frame.disenchantButton:Point("LEFT", frame.greedButton, "RIGHT", 0, 1)
frame.passButton:Point("LEFT", frame.disenchantButton, "RIGHT", 0, 2)
frame.needButton.text:Point("CENTER", -1, 4)
frame.greedButton.text:Point("CENTER", 1, 5)
frame.disenchantButton.text:Point("CENTER", 1, 4)
frame.passButton.text:Point("CENTER", 1, 2)
frame.bindText = frame:CreateFontString()
frame.bindText:Point("LEFT", frame.passButton, "RIGHT", 2, 0)
frame.bindText:FontTemplate(nil, nil, "OUTLINE")
local itemName = frame:CreateFontString(nil, "ARTWORK")
itemName:FontTemplate(nil, nil, "OUTLINE")
itemName:Point("LEFT", frame.bindText, "RIGHT", 1, 0)
itemName:Point("RIGHT", frame, "RIGHT", -5, 0)
itemName:Size(200, 10)
itemName:SetJustifyH("LEFT")
frame.itemName = itemName
frame.rollResults = {}
frame.rollButtons = {
[0] = frame.passButton,
[1] = frame.needButton,
[2] = frame.greedButton,
[3] = frame.disenchantButton,
}
tinsert(self.RollBars, frame)
return frame
end
function M:ReleaseFrame(frame)
frame:Hide()
frame.rollID = nil
frame.rollTime = nil
for i = 0, 3 do
frame.rollButtons[i].text:SetText("")
end
twipe(frame.rollResults)
end
function M:GetFrame()
for _, frame in ipairs(M.RollBars) do
if not frame.rollID then
return frame
end
end
return self:CreateRollFrame()
end
function M:START_LOOT_ROLL(_, rollID, rollTime)
local f = self:GetFrame()
f.rollID = rollID
f.rollTime = rollTime
local texture, name, count, quality, bindOnPickUp, canNeed, canGreed, canDisenchant, reasonNeed, reasonGreed, reasonDisenchant, deSkillRequired = GetLootRollItemInfo(rollID)
f.itemButton.icon:SetTexture(texture)
f.itemButton.rollID = rollID
f.itemButton.link = GetLootRollItemLink(rollID)
if count > 1 then
f.itemName:SetFormattedText("%dx %s", count, name)
else
f.itemName:SetText(name)
end
f.status:SetMinMaxValues(0, rollTime)
f.status:SetValue(rollTime)
local color = ITEM_QUALITY_COLORS[quality]
f.status:SetStatusBarColor(color.r, color.g, color.b, 0.7)
f.status.bg:SetTexture(color.r, color.g, color.b)
f.bindText:SetText(bindOnPickUp and "BoP" or "BoE")
f.bindText:SetVertexColor(bindOnPickUp and 1 or 0.3, bindOnPickUp and 0.3 or 1, bindOnPickUp and 0.1 or 0.3)
f.needButton:ToggleLootButton(canNeed, reasonNeed)
f.greedButton:ToggleLootButton(canGreed, reasonGreed)
f.disenchantButton:ToggleLootButton(canDisenchant, reasonDisenchant, deSkillRequired)
f:Show()
AlertFrame_FixAnchors()
if E.db.general.autoRoll and E.mylevel == MAX_PLAYER_LEVEL and quality == 2 and not bindOnPickUp then
if canDisenchant then
RollOnLoot(rollID, 3)
else
RollOnLoot(rollID, 2)
end
end
end
function M:CANCEL_LOOT_ROLL(_, rollID)
for _, frame in ipairs(self.RollBars) do
if frame.rollID == rollID then
self:ReleaseFrame(frame)
E:StaticPopup_Hide("CONFIRM_LOOT_ROLL", self.rollID)
break
end
end
end
function M:ParseRollChoice(msg)
for regex, rollType in pairs(rollMessages) do
local _, _, playerName, itemName = find(msg, regex)
if playerName and itemName and playerName ~= "Everyone" then
if locale == "ruRU" and rollType ~= 0 then
playerName, itemName = itemName, playerName
end
return playerName, itemName, rollType
end
end
end
function M:CHAT_MSG_LOOT(_, msg)
local playerName, itemName, rollType = self:ParseRollChoice(msg)
if playerName and itemName then
local _, class = UnitClass(playerName)
for _, frame in ipairs(self.RollBars) do
if frame.rollID and frame.itemButton.link == itemName and not frame.rollResults[playerName] then
frame.rollResults[playerName] = {rollType, class}
frame.rollButtons[rollType]:IncreaseRollCount()
break
end
end
end
end
function M:LoadLootRoll()
if not E.private.general.lootRoll then return end
self.numFrames = 0
self:RegisterEvent("CHAT_MSG_LOOT")
self:RegisterEvent("START_LOOT_ROLL")
self:RegisterEvent("CANCEL_LOOT_ROLL")
UIParent:UnregisterEvent("START_LOOT_ROLL")
UIParent:UnregisterEvent("CANCEL_LOOT_ROLL")
for i = 1, NUM_GROUP_LOOT_FRAMES do
_G["GroupLootFrame"..i]:UnregisterEvent("CANCEL_LOOT_ROLL")
end
end
+355
View File
@@ -0,0 +1,355 @@
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")
--Lua functions
local ipairs = ipairs
local format = string.format
--WoW API / Variables
local AcceptGroup = AcceptGroup
local CanGuildBankRepair = CanGuildBankRepair
local CanMerchantRepair = CanMerchantRepair
local GetCVarBool, SetCVar = GetCVarBool, SetCVar
local GetFriendInfo = GetFriendInfo
local GetGuildBankMoney = GetGuildBankMoney
local GetGuildBankWithdrawMoney = GetGuildBankWithdrawMoney
local GetGuildRosterInfo = GetGuildRosterInfo
local GetMoney = GetMoney
local GetNumFriends = GetNumFriends
local GetNumGuildMembers = GetNumGuildMembers
local GetNumPartyMembers = GetNumPartyMembers
local GetNumRaidMembers = GetNumRaidMembers
local GetPartyMember = GetPartyMember
local GetRaidRosterInfo = GetRaidRosterInfo
local GetRepairAllCost = GetRepairAllCost
local GuildRoster = GuildRoster
local HideRepairCursor = HideRepairCursor
local InCombatLockdown = InCombatLockdown
local IsInGuild = IsInGuild
local IsInInstance = IsInInstance
local IsShiftKeyDown = IsShiftKeyDown
local LeaveParty = LeaveParty
local PickupInventoryItem = PickupInventoryItem
local RaidNotice_AddMessage = RaidNotice_AddMessage
local RepairAllItems = RepairAllItems
local SendChatMessage = SendChatMessage
local ShowFriends = ShowFriends
local ShowRepairCursor = ShowRepairCursor
local StaticPopup_Hide = StaticPopup_Hide
local UninviteUnit = UninviteUnit
local UnitGUID = UnitGUID
local UnitName = UnitName
local MAX_PARTY_MEMBERS = MAX_PARTY_MEMBERS
do
local function EventHandler(event)
if event == "PLAYER_REGEN_DISABLED" then
UIErrorsFrame:UnregisterEvent("UI_ERROR_MESSAGE")
else
UIErrorsFrame:RegisterEvent("UI_ERROR_MESSAGE")
end
end
function M:ToggleErrorHandling()
if E.db.general.hideErrorFrame then
self:RegisterEvent("PLAYER_REGEN_ENABLED", EventHandler)
self:RegisterEvent("PLAYER_REGEN_DISABLED", EventHandler)
else
self:UnregisterEvent("PLAYER_REGEN_ENABLED", EventHandler)
self:UnregisterEvent("PLAYER_REGEN_DISABLED", EventHandler)
end
end
end
do
local interruptMsg = INTERRUPTED.." %s's \124cff71d5ff\124Hspell:%d\124h[%s]\124h\124r!"
function M:ToggleInterruptAnnounce()
if E.db.general.interruptAnnounce == "NONE" then
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
else
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
end
function M:COMBAT_LOG_EVENT_UNFILTERED(_, _, event, sourceGUID, _, _, _, destName, _, _, _, _, spellID, spellName)
if not (event == "SPELL_INTERRUPT" and (sourceGUID == E.myguid or sourceGUID == UnitGUID("pet"))) then return end
if E.db.general.interruptAnnounce == "SAY" then
SendChatMessage(format(interruptMsg, destName, spellID, spellName), "SAY")
elseif E.db.general.interruptAnnounce == "EMOTE" then
SendChatMessage(format(interruptMsg, destName, spellID, spellName), "EMOTE")
else
local _, instanceType = IsInInstance()
local battleground = instanceType == "pvp"
if E.db.general.interruptAnnounce == "PARTY" then
if GetNumPartyMembers() > 0 then
SendChatMessage(format(interruptMsg, destName, spellID, spellName), battleground and "BATTLEGROUND" or "PARTY")
end
elseif E.db.general.interruptAnnounce == "RAID" then
if GetNumRaidMembers() > 0 then
SendChatMessage(format(interruptMsg, destName, spellID, spellName), battleground and "BATTLEGROUND" or "RAID")
elseif GetNumPartyMembers() > 0 then
SendChatMessage(format(interruptMsg, destName, spellID, spellName), battleground and "BATTLEGROUND" or "PARTY")
end
elseif E.db.general.interruptAnnounce == "RAID_ONLY" then
if GetNumRaidMembers() > 0 then
SendChatMessage(format(interruptMsg, destName, spellID, spellName), battleground and "BATTLEGROUND" or "RAID")
end
end
end
end
end
do
local repairInventoryPriority = {
16, -- MainHandSlot
17, -- SecondaryHandSlot
18, -- RangedSlot
1, -- HeadSlot
5, -- ChestSlot
7, -- LegsSlot
3, -- ShoulderSlot
10, -- HandsSlot
6, -- WaistSlot
8, -- FeetSlot
9, -- WristSlot
}
local function RepairInventoryByPriority(playerMoney)
local money = playerMoney
ShowRepairCursor()
for _, slotID in ipairs(repairInventoryPriority) do
local hasItem, _, repairCost = GameTooltip:SetInventoryItem("player", slotID)
if hasItem and repairCost and repairCost > 0 and repairCost <= money then
PickupInventoryItem(slotID)
money = money - repairCost
end
end
HideRepairCursor()
GameTooltip:Hide()
return playerMoney - money
end
local function FullRepairMessage(repairAllCost)
E:Print(format("%s%s", L["Your items have been repaired for: "], E:FormatMoney(repairAllCost, "SMART", true)))
end
function M:AutoRepair(repairMode, greyValue)
if not CanMerchantRepair() or IsShiftKeyDown() then return end
local repairAllCost, canRepair = GetRepairAllCost()
if not canRepair or repairAllCost <= 0 then return end
if repairMode == "GUILD" then
if not CanGuildBankRepair() then
repairMode = "PLAYER"
else
local guildWithdrawMoney = GetGuildBankWithdrawMoney()
local guildMoney = GetGuildBankMoney()
local availableGuildMoney
if guildWithdrawMoney == -1 or guildMoney < guildWithdrawMoney then
availableGuildMoney = guildMoney
else
availableGuildMoney = guildWithdrawMoney
end
if repairAllCost > availableGuildMoney then
repairMode = "PLAYER"
end
end
end
if repairMode == "GUILD" then
RepairAllItems(true)
E:Print(format("%s%s", L["Your items have been repaired using guild bank funds for: "], E:FormatMoney(repairAllCost, "SMART", true)))
else
local playerMoney = GetMoney()
if playerMoney >= repairAllCost then
RepairAllItems()
FullRepairMessage(repairAllCost)
elseif greyValue and playerMoney + greyValue >= repairAllCost then
self.playerMoney = playerMoney
self.repairAllCost = repairAllCost
self:RegisterEvent("MERCHANT_CLOSED")
E.RegisterCallback(M, "VendorGreys_ItemSold")
elseif playerMoney > 0 then
local spent = RepairInventoryByPriority(playerMoney)
if spent > 0 then
E:Print(format("%s%s", L["Your items have been repaired for: "], E:FormatMoney(spent, "SMART", true)))
E:Print(L["You don't have enough money to repair all items."])
else
E:Print(L["You don't have enough money to repair."])
end
else
E:Print(L["You don't have enough money to repair."])
end
end
end
function M:VendorGreys_ItemSold(_, moneyGained)
self.playerMoney = self.playerMoney + moneyGained
if self.playerMoney >= self.repairAllCost then
if self.playerMoney > GetMoney() then
self:RegisterEvent("PLAYER_MONEY")
E.UnregisterCallback(M, "VendorGreys_ItemSold")
else
RepairAllItems()
FullRepairMessage(self.repairAllCost)
end
end
end
function M:PLAYER_MONEY()
if self.playerMoney <= GetMoney() then
RepairAllItems()
FullRepairMessage(self.repairAllCost)
self:MERCHANT_CLOSED()
end
end
function M:MERCHANT_CLOSED()
self.playerMoney = nil
self.repairAllCost = nil
self:UnregisterEvent("PLAYER_MONEY")
self:UnregisterEvent("MERCHANT_CLOSED")
E.UnregisterCallback(M, "VendorGreys_ItemSold")
end
end
function M:MERCHANT_SHOW()
local greyValue
if E.db.bags.vendorGrays.enable then
local itemCount
itemCount, greyValue = Bags:GetGraysInfo()
if itemCount > 0 then
Bags:VendorGrays()
end
end
local repairMode = E.db.general.autoRepair
if repairMode ~= "NONE" then
E:Delay(0.03, self.AutoRepair, self, repairMode, greyValue)
end
end
function M:DisbandRaidGroup()
if InCombatLockdown() then return end -- Prevent user error in combat
local numRaid = GetNumRaidMembers()
if numRaid > 0 then
for i = 1, numRaid 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 GetPartyMember(i) then
UninviteUnit(UnitName("party"..i))
end
end
end
LeaveParty()
end
function M:PVPMessageEnhancement(_, msg)
if not E.db.general.enhancedPvpMessages then return end
local _, instanceType = IsInInstance()
if instanceType == "pvp" or instanceType == "arena" then
RaidNotice_AddMessage(RaidBossEmoteFrame, msg, ChatTypeInfo.RAID_BOSS_EMOTE)
end
end
function M:AutoInvite(event, leaderName)
if not E.db.general.autoAcceptInvite then return end
if MiniMapLFGFrame:IsShown() then return end
if GetNumPartyMembers() > 0 or GetNumRaidMembers() > 0 then return end
local numFriends = GetNumFriends()
if numFriends > 0 then
ShowFriends()
for i = 1, numFriends do
if GetFriendInfo(i) == leaderName then
AcceptGroup()
StaticPopup_Hide("PARTY_INVITE")
return
end
end
end
if not IsInGuild() then return end
GuildRoster()
for i = 1, GetNumGuildMembers() do
if GetGuildRosterInfo(i) == leaderName then
AcceptGroup()
StaticPopup_Hide("PARTY_INVITE")
return
end
end
end
function M:ForceCVars(event)
if not GetCVarBool("lockActionBars") then
SetCVar("lockActionBars", 1)
end
if event == "PLAYER_ENTERING_WORLD" then
self:UnregisterEvent("PLAYER_ENTERING_WORLD")
end
end
function M:Initialize()
self:LoadRaidMarker()
self:LoadLoot()
self:LoadLootRoll()
self:LoadChatBubbles()
self:ToggleErrorHandling()
self:ToggleInterruptAnnounce()
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("MERCHANT_SHOW")
if E.private.actionbar.enable then
self:RegisterEvent("CVAR_UPDATE", "ForceCVars")
self:RegisterEvent("PLAYER_ENTERING_WORLD", "ForceCVars")
end
self.Initialized = true
end
local function InitializeCallback()
M:Initialize()
end
E:RegisterModule(M:GetName(), InitializeCallback)
+395
View File
@@ -0,0 +1,395 @@
local E, L, V, P, G = unpack(select(2, ...)) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local RB = E:GetModule("ReminderBuffs")
local LSM = E.Libs.LSM
--Lua functions
local ipairs, unpack = ipairs, unpack
--WoW API / Variables
local CooldownFrame_SetTimer = CooldownFrame_SetTimer
local CreateFrame = CreateFrame
local GetSpellInfo = GetSpellInfo
local GetTime = GetTime
local UnitAura = UnitAura
RB.Spell1Buffs = {
67016, -- Flask of the North (SP)
67017, -- Flask of the North (AP)
67018, -- Flask of the North (STR)
53755, -- Flask of the Frost Wyrm
53758, -- Flask of Stoneblood
53760, -- Flask of Endless Rage
54212, -- Flask of Pure Mojo
53752, -- Lesser Flask of Toughness (50 Resilience)
17627, -- Flask of Distilled Wisdom
33721, -- Spellpower Elixir
53746, -- Wrath Elixir
28497, -- Elixir of Mighty Agility
53748, -- Elixir of Mighty Strength
60346, -- Elixir of Lightning Speed
60344, -- Elixir of Expertise
60341, -- Elixir of Deadly Strikes
60345, -- Elixir of Armor Piercing
60340, -- Elixir of Accuracy
53749, -- Guru's Elixir
60343, -- Elixir of Mighty Defense
53751, -- Elixir of Mighty Fortitude
53764, -- Elixir of Mighty Mageblood
60347, -- Elixir of Mighty Thoughts
53763, -- Elixir of Protection
53747, -- Elixir of Spirit
}
RB.Spell2Buffs = {
57325, -- 80 AP
57327, -- 46 SP
57329, -- 40 Critical Strike Rating
57332, -- 40 Haste Rating
57334, -- 20 MP5
57356, -- 40 Expertise Rating
57358, -- 40 ARP
57360, -- 40 Hit Rating
57363, -- Tracking Humanoids
57365, -- 40 Spirit
57367, -- 40 AGI
57371, -- 40 STR
57373, -- Tracking Beasts
57399, -- 80 AP, 46 SP
59230, -- 40 Dodge Rating
65247, -- 20 STR
}
RB.Spell3Buffs = {
72588, -- Gift of the Wild
48469, -- Mark of the Wild
}
RB.Spell4Buffs = {
25898, -- Greater Blessing of Kings
20217, -- Blessing of Kings
72586, -- Blessing of Forgotten Kings
}
RB.Spell5Buffs = {
48162, -- Prayer of Fortitude
48161, -- Power Word: Fortitude
72590, -- Fortitude
}
RB.Spell6Buffs = {
20911, -- Blessing of Sanctuary
25899, -- Greater Blessing of Sanctuary
}
RB.CasterSpell7Buffs = {
61316, -- Dalaran Brilliance
43002, -- Arcane Brilliance
42995, -- Arcane Intellect
}
RB.AttackSpell7Buffs = {
48934, -- Greater Blessing of Might
48932, -- Blessing of Might
47436, -- Battle Shout
}
RB.Spell8Buffs = {
6307, -- Blood Pact
469, -- Commanding Shout
}
-- Armor buffs
RB.Spell9Buffs = {
25506, -- Stoneskin Totem
465, -- Devotion Aura
}
-- Concentration / Thorns
RB.CasterSpell10Buffs = {
19746, -- Concentration Aura
}
RB.AttackSpell10Buffs = {
467, -- Thorns
7294, -- Retribution Aura
}
-- SP / Str+Dex totems
RB.CasterSpell11Buffs = {
30706, -- Totem of Wrath
8227, -- Flametongue Totem
47236, -- Demonic Pact
}
RB.AttackSpell11Buffs = {
25527, -- Strength of Earth Totem
}
-- Mana regen
RB.Spell12Buffs = {
48938, -- Greater Blessing of Wisdom
48936, -- Blessing of Wisdom
58777, -- Mana Spring
}
-- Crit % Increase
RB.CasterSpell13Buffs = {
51471, -- Elemental Oath
24907, -- Moonkin Aura
}
RB.AttackSpell13Buffs = {
17007, -- Leader of the Pack
29801, -- Rampage
}
-- Haste % Increase
RB.CasterSpell14Buffs = {
50172, -- Moonkin's Presence
2895, -- Wrath of Air
853648, -- Swift Retribution
}
RB.AttackSpell14Buffs = {
8512, -- Windfury Totem
}
-- Spirit Buff
RB.CasterSpell15Buffs = {
14752, -- Divine Spirit
27681, -- Prayer of Spirit
}
-- Percent AP
RB.AttackSpell15Buffs = {
19506, -- Trueshot Aura
30802, -- Unleashed Rage
53137, -- Abomination's Might
}
-- Percent Damage
RB.Spell16Buffs = {
31579, -- Arcane Empowerment
31869, -- Sanctified Retribution
34455, -- Ferocious Inspiration
}
function RB:CheckFilterForActiveBuff(filter)
for _, spell in ipairs(filter) do
local spellName = GetSpellInfo(spell)
local name, _, texture, _, _, duration, expirationTime = UnitAura("player", spellName)
if name then
return texture, duration, expirationTime
end
end
end
function RB:UpdateReminderTime(elapsed)
self.expiration = self.expiration - elapsed
if self.nextUpdate > 0 then
self.nextUpdate = self.nextUpdate - elapsed
return
end
if self.expiration <= 0 then
self.timer:SetText("")
self:SetScript("OnUpdate", nil)
return
end
local value, id, nextUpdate, remainder = E:GetTimeInfo(self.expiration, 4)
self.nextUpdate = nextUpdate
local style = E.TimeFormats[id]
if style then
self.timer:SetFormattedText(style[1], value, remainder)
end
end
function RB:UpdateReminder(event, unit)
if event == "UNIT_AURA" and unit ~= "player" then return end
for i = 1, 16 do
local texture, duration, expirationTime = self:CheckFilterForActiveBuff(self["Spell"..i.."Buffs"])
local button = self.frame[i]
if texture then
button.t:SetTexture(texture)
if (duration == 0 and expirationTime == 0) or E.db.general.reminder.durations ~= true then
button.t:SetAlpha(E.db.general.reminder.reverse and 1 or 0.3)
button:SetScript("OnUpdate", nil)
button.timer:SetText(nil)
CooldownFrame_SetTimer(button.cd, 0, 0, 0)
else
button.expiration = expirationTime - GetTime()
button.nextUpdate = 0
button.t:SetAlpha(1)
CooldownFrame_SetTimer(button.cd, expirationTime - duration, duration, 1)
button.cd:SetReverse(E.db.general.reminder.reverse)
button:SetScript("OnUpdate", self.UpdateReminderTime)
end
else
CooldownFrame_SetTimer(button.cd, 0, 0, 0)
button.t:SetAlpha(E.db.general.reminder.reverse and 0.3 or 1)
button:SetScript("OnUpdate", nil)
button.timer:SetText(nil)
button.t:SetTexture(self.DefaultIcons[i])
end
end
end
function RB:CreateButton()
local button = CreateFrame("Button", nil, ElvUI_ReminderBuffs)
button:SetTemplate("Default")
button.t = button:CreateTexture(nil, "OVERLAY")
button.t:SetTexCoord(unpack(E.TexCoords))
button.t:SetInside()
button.t:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
button.cd = CreateFrame("Cooldown", nil, button, "CooldownFrameTemplate")
button.cd:SetInside()
button.cd.noOCC = true
button.cd.noCooldownCount = true
button.timer = button.cd:CreateFontString(nil, "OVERLAY")
button.timer:SetPoint("CENTER")
return button
end
function RB:EnableRB()
ElvUI_ReminderBuffs:Show()
self:RegisterEvent("UNIT_AURA", "UpdateReminder")
self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED", "UpdateReminder")
self:RegisterEvent("CHARACTER_POINTS_CHANGED", "UpdateReminder")
E.RegisterCallback(self, "RoleChanged", "UpdateSettings")
self:UpdateReminder()
end
function RB:DisableRB()
ElvUI_ReminderBuffs:Hide()
self:UnregisterEvent("UNIT_AURA")
self:UnregisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
self:UnregisterEvent("CHARACTER_POINTS_CHANGED")
E.UnregisterCallback(self, "RoleChanged", "UpdateSettings")
end
function RB:UpdateSettings(isCallback)
local frame = self.frame
frame:Width(E.RBRWidth * 2)
self:UpdateDefaultIcons()
for i = 1, 16 do
local button = frame[i]
button:ClearAllPoints()
button:SetWidth(E.RBRWidth)
button:SetHeight(E.RBRWidth)
if i == 1 then
button:SetPoint("TOPLEFT", ElvUI_ReminderBuffs, "TOPLEFT", 0, -1)
elseif i == 9 then
button:SetPoint("TOPRIGHT", ElvUI_ReminderBuffs, "TOPRIGHT", 0, -1)
else
button:Point("TOP", frame[i - 1], "BOTTOM", 0, E.Border - E.Spacing*3)
end
if E.db.general.reminder.durations then
button.cd:SetAlpha(1)
else
button.cd:SetAlpha(0)
end
button.timer:FontTemplate(LSM:Fetch("font", E.db.general.reminder.font), E.db.general.reminder.fontSize, E.db.general.reminder.fontOutline)
end
if not isCallback then
if E.db.general.reminder.enable then
RB:EnableRB()
else
RB:DisableRB()
end
else
self:UpdateReminder()
end
end
function RB:UpdatePosition()
Minimap:ClearAllPoints()
ElvConfigToggle:ClearAllPoints()
ElvUI_ReminderBuffs:ClearAllPoints()
if E.db.general.reminder.position == "LEFT" then
Minimap:Point("TOPRIGHT", MMHolder, "TOPRIGHT", -E.Border, -E.Border)
ElvConfigToggle:SetPoint("TOPRIGHT", LeftMiniPanel, "TOPLEFT", E.Border - E.Spacing*3, 0)
ElvConfigToggle:SetPoint("BOTTOMRIGHT", LeftMiniPanel, "BOTTOMLEFT", E.Border - E.Spacing*3, 0)
ElvUI_ReminderBuffs:SetPoint("TOPRIGHT", Minimap.backdrop, "TOPLEFT", E.Border - E.Spacing*3, 0)
ElvUI_ReminderBuffs:SetPoint("BOTTOMRIGHT", Minimap.backdrop, "BOTTOMLEFT", E.Border - E.Spacing*3, 0)
else
Minimap:Point("TOPLEFT", MMHolder, "TOPLEFT", E.Border, -E.Border)
ElvConfigToggle:SetPoint("TOPLEFT", RightMiniPanel, "TOPRIGHT", -E.Border + E.Spacing*3, 0)
ElvConfigToggle:SetPoint("BOTTOMLEFT", RightMiniPanel, "BOTTOMRIGHT", -E.Border + E.Spacing*3, 0)
ElvUI_ReminderBuffs:SetPoint("TOPLEFT", Minimap.backdrop, "TOPRIGHT", -E.Border + E.Spacing*3, 0)
ElvUI_ReminderBuffs:SetPoint("BOTTOMLEFT", Minimap.backdrop, "BOTTOMRIGHT", -E.Border + E.Spacing*3, 0)
end
end
function RB:UpdateDefaultIcons()
local isCaster = E.private.general.reminder.classtype == "Caster"
self.DefaultIcons = {
[1] = "Interface\\Icons\\INV_Potion_97",
[2] = "Interface\\Icons\\Spell_Misc_Food",
[3] = "Interface\\Icons\\Spell_Nature_Regeneration",
[4] = "Interface\\Icons\\Spell_Magic_GreaterBlessingofKings",
[5] = "Interface\\Icons\\Spell_Holy_WordFortitude",
[6] = "Interface\\Icons\\spell_nature_lightningshield",
[7] = (isCaster and "Interface\\Icons\\Spell_Holy_MagicalSentry") or "Interface\\Icons\\spell_holy_fistofjustice",
[8] = "Interface\\Icons\\ability_warrior_rallyingcry",
[9] = "Interface\\Icons\\spell_nature_stoneskintotem",
[10] = (isCaster and "Interface\\Icons\\spell_holy_mindsooth") or "Interface\\Icons\\spell_nature_thorns",
[11] = (isCaster and "Interface\\Icons\\spell_fire_totemofwrath") or "Interface\\Icons\\spell_nature_earthbindtotem",
[12] = "Interface\\Icons\\Spell_Holy_GreaterBlessingofWisdom",
[13] = (isCaster and "Interface\\Icons\\spell_nature_moonglow") or "Interface\\Icons\\spell_nature_unyeildingstamina",
[14] = (isCaster and "Interface\\Icons\\spell_nature_forceofnature") or "Interface\\Icons\\spell_nature_windfury",
[15] = (isCaster and "Interface\\Icons\\spell_holy_prayerofspirit") or "Interface\\Icons\\ability_trueshot",
[16] = "Interface\\Icons\\spell_nature_starfall",
}
self.Spell7Buffs = isCaster and self.CasterSpell7Buffs or self.AttackSpell7Buffs
self.Spell10Buffs = isCaster and self.CasterSpell10Buffs or self.AttackSpell10Buffs
self.Spell11Buffs = isCaster and self.CasterSpell11Buffs or self.AttackSpell11Buffs
self.Spell13Buffs = isCaster and self.CasterSpell13Buffs or self.AttackSpell13Buffs
self.Spell14Buffs = isCaster and self.CasterSpell14Buffs or self.AttackSpell14Buffs
self.Spell15Buffs = isCaster and self.CasterSpell15Buffs or self.AttackSpell15Buffs
end
function RB:Initialize()
if not E.private.general.minimap.enable then return end
self.db = E.db.general.reminder
local frame = CreateFrame("Frame", "ElvUI_ReminderBuffs", Minimap)
frame:Width(E.RBRWidth)
if E.db.general.reminder.position == "LEFT" then
frame:Point("TOPRIGHT", Minimap.backdrop, "TOPLEFT", E.Border - E.Spacing*3, 0)
frame:Point("BOTTOMRIGHT", Minimap.backdrop, "BOTTOMLEFT", E.Border - E.Spacing*3, 0)
else
frame:Point("TOPLEFT", Minimap.backdrop, "TOPRIGHT", -E.Border + E.Spacing*3, 0)
frame:Point("BOTTOMLEFT", Minimap.backdrop, "BOTTOMRIGHT", -E.Border + E.Spacing*3, 0)
end
self.frame = frame
for i = 1, 16 do
frame[i] = self:CreateButton()
frame[i]:SetID(i)
end
self:UpdateSettings()
end
local function InitializeCallback()
RB:Initialize()
end
E:RegisterModule(RB:GetName(), InitializeCallback)
+104
View File
@@ -0,0 +1,104 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local M = E:GetModule("Misc")
--Lua functions
local sin, cos, pi = math.sin, math.cos, math.pi
--WoW API / Variables
local CreateFrame = CreateFrame
local GetNumPartyMembers = GetNumPartyMembers
local UnitInRaid = UnitInRaid
local UnitIsPartyLeader = UnitIsPartyLeader
local UnitIsRaidOfficer = UnitIsRaidOfficer
local UnitExists, UnitIsDead = UnitExists, UnitIsDead
local GetCursorPosition = GetCursorPosition
local PlaySound = PlaySound
local SetRaidTarget = SetRaidTarget
local SetRaidTargetIconTexture = SetRaidTargetIconTexture
local UIErrorsFrame = UIErrorsFrame
local ButtonIsDown
function M:RaidMarkCanMark()
if not self.RaidMarkFrame then return false end
if GetNumPartyMembers() > 0 then
if UnitIsPartyLeader("player") or (UnitInRaid("player") and UnitIsRaidOfficer("player") and not UnitIsPartyLeader("player")) 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(button)
PlaySound("UChatScrollButton")
SetRaidTarget("target", (button ~= "RightButton") and self:GetID() or 0)
self:GetParent():Hide()
end
function M:LoadRaidMarker()
local marker = CreateFrame("Frame", nil, E.UIParent)
marker:EnableMouse(true)
marker:Size(100)
marker:SetFrameStrata("DIALOG")
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 = pi / 0.7 * i
button:Point("CENTER", sin(angle) * 60, cos(angle) * 60)
end
end
M.RaidMarkFrame = marker
end
+225
View File
@@ -0,0 +1,225 @@
local E, L = unpack(select(2, ...)); --Import: Engine, Locales
local RU = E:GetModule("RaidUtility")
local S = E:GetModule("Skins")
--Lua functions
local find = string.find
--WoW API / Variables
local CreateFrame = CreateFrame
local IsInInstance = IsInInstance
local GetNumRaidMembers = GetNumRaidMembers
local GetNumPartyMembers = GetNumPartyMembers
local IsPartyLeader = IsPartyLeader
local IsRaidLeader = IsRaidLeader
local IsRaidOfficer = IsRaidOfficer
local InCombatLockdown = InCombatLockdown
local DoReadyCheck = DoReadyCheck
local ToggleFriendsFrame = ToggleFriendsFrame
local PANEL_HEIGHT = 100
local function CheckRaidStatus()
local inInstance, instanceType = IsInInstance()
if (((IsRaidLeader() or IsRaidOfficer()) and GetNumRaidMembers() > 0) or (IsPartyLeader() and GetNumPartyMembers() > 0)) and not (inInstance and (instanceType == "pvp" or instanceType == "arena")) then
return true
else
return false
end
end
-- Function to create buttons in this module
function RU:CreateUtilButton(name, parent, template, width, height, point, relativeto, point2, xOfs, yOfs, text, texture)
local button = CreateFrame("Button", name, parent, template)
button:Width(width)
button:Height(height)
button:Point(point, relativeto, point2, xOfs, yOfs)
S:HandleButton(button)
if text then
button.text = button:CreateFontString(nil, "OVERLAY", button)
button.text:FontTemplate()
button.text:Point("CENTER", button, "CENTER", 0, -1)
button.text:SetJustifyH("CENTER")
button.text:SetText(text)
button:SetFontString(button.text)
elseif texture then
button.texture = button:CreateTexture(nil, "OVERLAY", nil)
button.texture:SetTexture(texture)
button.texture:Point("TOPLEFT", button, "TOPLEFT", E.mult, -E.mult)
button.texture:Point("BOTTOMRIGHT", button, "BOTTOMRIGHT", -E.mult, E.mult)
end
end
function RU:ToggleRaidUtil(event)
if InCombatLockdown() then
self:RegisterEvent("PLAYER_REGEN_ENABLED", "ToggleRaidUtil")
return
end
if 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")
end
end
function RU:Initialize()
if not E.private.general.raidUtility then return end
self.Initialized = true
--Create main frame
local RaidUtilityPanel = CreateFrame("Frame", "RaidUtilityPanel", E.UIParent, "SecureHandlerClickTemplate")
RaidUtilityPanel:SetTemplate("Transparent")
RaidUtilityPanel:Width(230)
RaidUtilityPanel:Height(PANEL_HEIGHT)
RaidUtilityPanel:Point("TOP", E.UIParent, "TOP", -400, 1)
RaidUtilityPanel:SetFrameLevel(3)
RaidUtilityPanel.toggled = false
RaidUtilityPanel:SetFrameStrata("HIGH")
self:CreateUtilButton("RaidUtility_ShowButton", E.UIParent, "SecureHandlerClickTemplate", 136, 18, "TOP", E.UIParent, "TOP", -400, E.Border, RAID_CONTROL, nil)
RaidUtility_ShowButton:SetFrameRef("RaidUtilityPanel", RaidUtilityPanel)
RaidUtility_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 string.find(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))
RaidUtility_ShowButton:SetScript("OnMouseUp", function()
RaidUtilityPanel.toggled = true
end)
RaidUtility_ShowButton:SetMovable(true)
RaidUtility_ShowButton:SetClampedToScreen(true)
RaidUtility_ShowButton:SetClampRectInsets(0, 0, -1, 1)
RaidUtility_ShowButton:RegisterForDrag("RightButton")
RaidUtility_ShowButton:SetFrameStrata("HIGH")
RaidUtility_ShowButton:SetScript("OnDragStart", function(self)
if InCombatLockdown() then E:Print(ERR_NOT_IN_COMBAT) return end
self:StartMoving()
end)
RaidUtility_ShowButton:SetScript("OnDragStop", function(self)
self:StopMovingOrSizing()
local point = self:GetPoint()
local xOffset = self:GetCenter()
local screenWidth = E.UIParent:GetWidth() / 2
xOffset = xOffset - screenWidth
self:ClearAllPoints()
if find(point, "BOTTOM") then
self:Point("BOTTOM", E.UIParent, "BOTTOM", xOffset, -1)
else
self:Point("TOP", E.UIParent, "TOP", xOffset, 1)
end
end)
self:CreateUtilButton("RaidUtility_CloseButton", RaidUtilityPanel, "SecureHandlerClickTemplate", 136, 18, "TOP", RaidUtilityPanel, "BOTTOM", 0, -1, CLOSE, nil)
RaidUtility_CloseButton:SetFrameRef("RaidUtility_ShowButton", RaidUtility_ShowButton)
RaidUtility_CloseButton:SetAttribute("_onclick", [=[self:GetParent():Hide(); self:GetFrameRef("RaidUtility_ShowButton"):Show();]=])
RaidUtility_CloseButton:SetScript("OnMouseUp", function() RaidUtilityPanel.toggled = false end)
RaidUtilityPanel:SetFrameRef("RaidUtility_CloseButton", RaidUtility_CloseButton)
self:CreateUtilButton("DisbandRaidButton", RaidUtilityPanel, nil, RaidUtilityPanel:GetWidth() * 0.8, 18, "TOP", RaidUtilityPanel, "TOP", 0, -5, L["Disband Group"], nil)
DisbandRaidButton:SetScript("OnMouseUp", function()
if CheckRaidStatus() then
E:StaticPopup_Show("DISBAND_RAID")
end
end)
self:CreateUtilButton("MainTankButton", RaidUtilityPanel, "SecureActionButtonTemplate", (DisbandRaidButton:GetWidth() / 2) - 2, 18, "TOPLEFT", DisbandRaidButton, "BOTTOMLEFT", 0, -5, MAINTANK, nil)
MainTankButton:SetAttribute("type", "maintank")
MainTankButton:SetAttribute("unit", "target")
MainTankButton:SetAttribute("action", "toggle")
self:CreateUtilButton("MainAssistButton", RaidUtilityPanel, "SecureActionButtonTemplate", (DisbandRaidButton:GetWidth() / 2) - 2, 18, "TOPRIGHT", DisbandRaidButton, "BOTTOMRIGHT", 0, -5, MAINASSIST, nil)
MainAssistButton:SetAttribute("type", "mainassist")
MainAssistButton:SetAttribute("unit", "target")
MainAssistButton:SetAttribute("action", "toggle")
self:CreateUtilButton("ReadyCheckButton", RaidUtilityPanel, nil, RaidUtilityPanel:GetWidth() * 0.8, 18, "TOPLEFT", MainTankButton, "BOTTOMLEFT", 0, -5, READY_CHECK, nil)
ReadyCheckButton:SetScript("OnMouseUp", function()
if CheckRaidStatus() then
DoReadyCheck()
end
end)
ReadyCheckButton:SetScript("OnEvent", function(btn)
if not (IsRaidLeader("player") or IsRaidOfficer("player")) then
btn:Disable()
else
btn:Enable()
end
end)
ReadyCheckButton:RegisterEvent("RAID_ROSTER_UPDATE")
ReadyCheckButton:RegisterEvent("PARTY_MEMBERS_CHANGED")
ReadyCheckButton:RegisterEvent("PLAYER_ENTERING_WORLD")
self:CreateUtilButton("RaidControlButton", RaidUtilityPanel, nil, MainTankButton:GetWidth(), 18, "TOPLEFT", ReadyCheckButton, "BOTTOMLEFT", 0, -5, L["Raid Menu"], nil)
RaidControlButton:SetScript("OnMouseUp", function()
if InCombatLockdown() then E:Print(ERR_NOT_IN_COMBAT) return end
ToggleFriendsFrame(5)
end)
self:CreateUtilButton("ConvertRaidButton", RaidUtilityPanel, nil, MainAssistButton:GetWidth(), 18, "TOPRIGHT", ReadyCheckButton, "BOTTOMRIGHT", 0, -5, CONVERT_TO_RAID, nil)
ConvertRaidButton:SetScript("OnMouseUp", function()
if CheckRaidStatus() then
ConvertToRaid()
SetLootMethod("master", "player")
end
end)
ConvertRaidButton:SetScript("OnEvent", function(btn)
if GetNumRaidMembers() == 0 and GetNumPartyMembers() > 0 and IsPartyLeader() then
if not btn:IsShown() then
RaidControlButton:Width(MainAssistButton:GetWidth())
btn:Show()
end
elseif btn:IsShown() then
RaidControlButton:Width(DisbandRaidButton:GetWidth())
btn:Hide()
end
end)
ConvertRaidButton:RegisterEvent("RAID_ROSTER_UPDATE")
ConvertRaidButton:RegisterEvent("PARTY_MEMBERS_CHANGED")
ConvertRaidButton:RegisterEvent("PLAYER_ENTERING_WORLD")
--Automatically show/hide the frame if we have RaidLeader or RaidOfficer
self:RegisterEvent("RAID_ROSTER_UPDATE", "ToggleRaidUtil")
self:RegisterEvent("PLAYER_ENTERING_WORLD", "ToggleRaidUtil")
self:RegisterEvent("PARTY_MEMBERS_CHANGED", "ToggleRaidUtil")
end
local function InitializeCallback()
RU:Initialize()
end
E:RegisterInitialModule(RU:GetName(), InitializeCallback)
+176
View File
@@ -0,0 +1,176 @@
local E, L, V, P, G = unpack(select(2, ...)) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local THREAT = E:GetModule("Threat")
local DT = E:GetModule("DataTexts")
--Lua functions
local pairs, select = pairs, select
local wipe = table.wipe
--WoW API / Variables
local GetNumPartyMembers = GetNumPartyMembers
local GetNumRaidMembers = GetNumRaidMembers
local GetThreatStatusColor = GetThreatStatusColor
local UnitDetailedThreatSituation = UnitDetailedThreatSituation
local UnitExists = UnitExists
local UnitIsPlayer = UnitIsPlayer
local UnitIsUnit = UnitIsUnit
local UnitName = UnitName
local UnitReaction = UnitReaction
local UNKNOWN = UNKNOWN
local partyUnits, raidUnits = {}, {}
for i = 1, 4 do partyUnits[i] = "party"..i end
for i = 1, 40 do raidUnits[i] = "raid"..i end
function THREAT:UpdatePosition()
if self.db.position == "RIGHTCHAT" then
self.bar:SetInside(RightChatDataPanel)
self.bar:SetParent(RightChatDataPanel)
else
self.bar:SetInside(LeftChatDataPanel)
self.bar:SetParent(LeftChatDataPanel)
end
self.bar.text:FontTemplate(nil, self.db.textSize)
self.bar:SetFrameStrata("MEDIUM")
end
function THREAT:GetLargestThreatOnList(percent)
local largestValue, largestUnit = 0
for unit, threatPercent in pairs(self.list) do
if threatPercent > largestValue then
largestValue = threatPercent
largestUnit = unit
end
end
return (percent - largestValue), largestUnit
end
function THREAT:GetColor(unit)
if UnitIsPlayer(unit) then
local class = E.media.herocolor
if not class then
return 194, 194, 194
end
return class.r*255, class.g*255, class.b*255
end
local unitReaction = UnitReaction(unit, "player")
if unitReaction then
local reaction = ElvUF.colors.reaction[unitReaction]
return reaction[1]*255, reaction[2]*255, reaction[3]*255
else
return 194, 194, 194
end
end
function THREAT:Update()
if not UnitExists("target") or (DT and DT.ShowingBGStats) then
if self.bar:IsShown() then
self.bar:Hide()
end
return
end
local _, status, percent = UnitDetailedThreatSituation("player", "target")
local petExists = HasPetUI()
if percent and percent > 0 and (GetNumPartyMembers() > 0 or petExists == 1) then
local name = UnitName("target")
self.bar:Show()
if percent == 100 then
if petExists == 1 then
self.list.pet = select(3, UnitDetailedThreatSituation("pet", "target"))
end
if GetNumRaidMembers() > 0 then
for i = 1, 40 do
if UnitExists(raidUnits[i]) and not UnitIsUnit(raidUnits[i], "player") then
self.list[raidUnits[i]] = select(3, UnitDetailedThreatSituation(raidUnits[i], "target"))
end
end
else
for i = 1, 4 do
if UnitExists(partyUnits[i]) then
self.list[partyUnits[i]] = select(3, UnitDetailedThreatSituation(partyUnits[i], "target"))
end
end
end
local leadPercent, largestUnit = self:GetLargestThreatOnList(percent)
if leadPercent > 0 and largestUnit then
local r, g, b = self:GetColor(largestUnit)
self.bar.text:SetFormattedText(L["ABOVE_THREAT_FORMAT"], name, percent, leadPercent, r, g, b, UnitName(largestUnit) or UNKNOWN)
if E.Role == "Tank" then
self.bar:SetStatusBarColor(0, 0.839, 0)
self.bar:SetValue(leadPercent)
else
self.bar:SetStatusBarColor(GetThreatStatusColor(status))
self.bar:SetValue(percent)
end
else
self.bar:SetStatusBarColor(GetThreatStatusColor(status))
self.bar:SetValue(percent)
self.bar.text:SetFormattedText("%s: %.0f%%", name, percent)
end
else
self.bar:SetStatusBarColor(GetThreatStatusColor(status))
self.bar:SetValue(percent)
self.bar.text:SetFormattedText("%s: %.0f%%", name, percent)
end
else
self.bar:Hide()
end
wipe(self.list)
end
function THREAT:ToggleEnable()
if self.db.enable then
self:RegisterEvent("PLAYER_TARGET_CHANGED", "Update")
self:RegisterEvent("UNIT_THREAT_LIST_UPDATE", "Update")
self:RegisterEvent("PARTY_MEMBERS_CHANGED", "Update")
self:RegisterEvent("RAID_ROSTER_UPDATE", "Update")
self:RegisterEvent("UNIT_PET", "Update")
self:Update()
else
self.bar:Hide()
self:UnregisterEvent("PLAYER_TARGET_CHANGED")
self:UnregisterEvent("UNIT_THREAT_LIST_UPDATE")
self:UnregisterEvent("PARTY_MEMBERS_CHANGED")
self:UnregisterEvent("RAID_ROSTER_UPDATE")
self:UnregisterEvent("UNIT_PET")
end
end
function THREAT:Initialize()
self.db = E.db.general.threat
self.bar = CreateFrame("StatusBar", "ElvUI_ThreatBar", E.UIParent)
self.bar:CreateBackdrop("Default")
self.bar:SetMinMaxValues(0, 100)
self.bar:SetStatusBarTexture(E.media.normTex)
E:RegisterStatusBar(self.bar)
self.bar.text = self.bar:CreateFontString(nil, "OVERLAY")
self.bar.text:FontTemplate(nil, self.db.textSize)
self.bar.text:Point("CENTER", self.bar, "CENTER")
self.list = {}
self:UpdatePosition()
self:ToggleEnable()
self.Initialized = true
end
local function InitializeCallback()
THREAT:Initialize()
end
E:RegisterModule(THREAT:GetName(), InitializeCallback)
+181
View File
@@ -0,0 +1,181 @@
local E, L, V, P, G = unpack(select(2, ...)) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local TOTEMS = E:GetModule("Totems")
--Lua functions
local unpack = unpack
--WoW API / Variables
local CooldownFrame_SetTimer = CooldownFrame_SetTimer
local CreateFrame = CreateFrame
local DestroyTotem = DestroyTotem
local GetTotemInfo = GetTotemInfo
local MAX_TOTEMS = MAX_TOTEMS
local TOTEM_PRIORITIES = TOTEM_PRIORITIES
local SLOT_BORDER_COLORS = {
[EARTH_TOTEM_SLOT] = {r = 0.23, g = 0.45, b = 0.13}, -- [2]
[FIRE_TOTEM_SLOT] = {r = 0.58, g = 0.23, b = 0.10}, -- [1]
[WATER_TOTEM_SLOT] = {r = 0.19, g = 0.48, b = 0.60}, -- [3]
[AIR_TOTEM_SLOT] = {r = 0.42, g = 0.18, b = 0.74} -- [4]
}
function TOTEMS:UpdateAllTotems()
for i = 1, MAX_TOTEMS do
self:UpdateTotem(nil, i)
end
end
function TOTEMS:UpdateTotem(event, slot)
local slotID = TOTEM_PRIORITIES[slot]
local _, _, startTime, duration, icon = GetTotemInfo(slot)
if icon ~= "" then
local color = SLOT_BORDER_COLORS[slot]
self.bar[slotID].iconTexture:SetTexture(icon)
self.bar[slotID]:SetBackdropBorderColor(color.r, color.g, color.b)
CooldownFrame_SetTimer(self.bar[slotID].cooldown, startTime, duration, 1)
self.bar[slotID]:Show()
else
self.bar[slotID]:Hide()
end
end
function TOTEMS:ToggleEnable()
if E.db.general.totems.enable then
if self.Initialized then
self.bar:Show()
self:RegisterEvent("PLAYER_TOTEM_UPDATE", "UpdateTotem")
self:RegisterEvent("PLAYER_ENTERING_WORLD", "UpdateAllTotems")
self:UpdateAllTotems()
E:EnableMover("TotemBarMover")
else
self:Initialize()
self:UpdateAllTotems()
end
elseif self.Initialized then
self.bar:Hide()
self:UnregisterEvent("PLAYER_TOTEM_UPDATE")
self:UnregisterEvent("PLAYER_ENTERING_WORLD")
E:DisableMover("TotemBarMover")
end
end
function TOTEMS:PositionAndSize()
if not self.Initialized 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
end
local function Button_OnClick(self)
DestroyTotem(self.slot)
end
local function Button_OnEnter(self)
GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT")
self:UpdateTooltip()
end
local function Button_OnLeave(self)
GameTooltip:Hide()
end
local function UpdateTooltip(self)
if GameTooltip:IsOwned(self) then
GameTooltip:SetTotem(self.slot)
end
end
function TOTEMS:Initialize()
if not E.db.general.totems.enable then return end
self.db = E.db.general.totems
local bar = CreateFrame("Frame", "ElvUI_TotemBar", E.UIParent)
bar:Point("TOPLEFT", LeftChatPanel, "TOPRIGHT", 14, 0)
self.bar = bar
for i = 1, MAX_TOTEMS do
local frame = CreateFrame("Button", "$parentTotem"..i, bar)
frame.slot = TOTEM_PRIORITIES[i]
frame:SetTemplate("Default")
frame:StyleButton()
frame.ignoreBorderColors = true
frame:Hide()
frame.UpdateTooltip = UpdateTooltip
frame:RegisterForClicks("RightButtonUp")
frame:SetScript("OnClick", Button_OnClick)
frame:SetScript("OnEnter", Button_OnEnter)
frame:SetScript("OnLeave", Button_OnLeave)
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", "$parentCooldown", frame, "CooldownFrameTemplate")
frame.cooldown:SetReverse(true)
frame.cooldown:SetInside()
E:RegisterCooldown(frame.cooldown)
self.bar[i] = frame
end
self.Initialized = true
self:PositionAndSize()
E:CreateMover(bar, "TotemBarMover", TUTORIAL_TITLE47, nil, nil, nil, nil, nil, "general,totems")
self:RegisterEvent("PLAYER_TOTEM_UPDATE", "UpdateTotem")
self:RegisterEvent("PLAYER_ENTERING_WORLD", "UpdateAllTotems")
end
local function InitializeCallback()
TOTEMS:Initialize()
end
E:RegisterModule(TOTEMS:GetName(), InitializeCallback)