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 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 )
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 ( E.screenWidth + ( E.Border * 2 ) )
AFK.AFKMode . bottom : Height ( E.screenHeight * ( 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 ( E.screenWidth * 2 , E.screenHeight * 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 ( ) )