347 lines
12 KiB
Lua
347 lines
12 KiB
Lua
|
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())
|