Compare with Previous | Blame | View Log
PVPScan = LibStub ("AceAddon-3.0"):NewAddon ("PVPScan", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0") local PVPScan = PVPScan local LDB = LibStub ("LibDataBroker-1.1", true) local LDBIcon = LDB and LibStub ("LibDBIcon-1.0", true) local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0") local _bit_band = bit.band local GetTime = GetTime local REACTION_HOSTILE = 0x00000040 local REACTION_NEUTRAL = 0x00000020 local OBJECT_TYPE_PLAYER = 0x00000400 PVPScan.IsInBattleground = false PVPScan.IsInCity = false PVPScan.IsInArena = false PVPScan.IsInOutDoors = true PVPScan.ScanEnabled = true local default_db = { profile = { SpotBarHeight = 20, SpotBarAmount = 5, SpotBarWidth = 150, SpotBarTexture = "Blizzard Character Skills Bar", SpotBarTimeOut = 10, SpotBarCooldown = 5, SpotBarPlayerCooldown = 10, Locked = false, SoundPlay = false, SoundFile = "", Minimap = {hide = false, radius = 160, minimapPos = 220}, }, } function PVPScan:OnEnable() end function PVPScan:OnDisable() end local OptionsTable = { name = "PVPScan", type = "group", args = { SpotBarHeight = { type = "range", name = "Bar Height", desc = "Change the height of spot bars.", min = 10, max = 40, step = 1, get = function() return PVPScan.db.profile.SpotBarHeight end, set = function (self, val) PVPScan.db.profile.SpotBarHeight = val; PVPScan:RefreshSpotBars() end, order = 1, }, SpotBarWidth = { type = "range", name = "Bar Width", desc = "Change the width of spot bars.", min = 50, max = 250, step = 1, get = function() return PVPScan.db.profile.SpotBarWidth end, set = function (self, val) PVPScan.db.profile.SpotBarWidth = val; PVPScan:RefreshSpotBars() end, order = 2, }, SpotBarAmount = { type = "range", name = "Bar Amount", desc = "Change the amount of spot bars.", min = 1, max = 40, step = 1, get = function() return PVPScan.db.profile.SpotBarAmount end, set = function (self, val) PVPScan.db.profile.SpotBarAmount = val; PVPScan:RefreshSpotBars() end, order = 3, }, SpotBarTexture = { type = "select", name = "Bar Texture", desc = "Choose the texture used on target bars.", values = function() local TextureTable = {} for name, _ in pairs (SharedMedia:HashTable ("statusbar")) do TextureTable [name] = name end return TextureTable end, get = function() return PVPScan.db.profile.SpotBarTexture end, set = function (self, file) PVPScan.db.profile.SpotBarTexture = file; PVPScan:RefreshSpotBars() end, order = 4, }, SpotBarTimeOut = { type = "range", name = "Time Out", desc = "How many time wait until the bar auto hide.", min = 5, max = 120, step = 5, get = function() return PVPScan.db.profile.SpotBarTimeOut end, set = function (self, val) PVPScan.db.profile.SpotBarTimeOut = val; end, order = 9, }, Locked = { type = "toggle", name = "Lock Scan Frame", desc = "Lock or unlock the SpotBars Frame.", order = 5, get = function() return PVPScan.db.profile.Locked end, set = function (self, val) PVPScan.db.profile.Locked = not PVPScan.db.profile.Locked; PVPScan:LockScanFrame (PVPScan.db.profile.Locked) end, }, SoundPlay = { type = "toggle", name = "Play Sound", desc = "Play a sound when a enemy is found.", order = 7, get = function() return PVPScan.db.profile.SoundPlay end, set = function (self, val) PVPScan.db.profile.SoundPlay = not PVPScan.db.profile.SoundPlay end, }, SoundFile = { type = "select", name = "Sound File", desc = "Choose the sound to play when a enemy is found.", values = function() local SoundTable = {} for name, _ in pairs (SharedMedia:HashTable ("sound")) do SoundTable [name] = name end return SoundTable end, get = function() return PVPScan.db.profile.SoundFile end, set = function (self, file) PVPScan.db.profile.SoundFile = file end, order = 8, }, Minimap = { type = "toggle", name = "Hide Minimap Icon", desc = "Show or hide the minimap icon.", order = 6, get = function() return PVPScan.db.profile.Minimap.hide end, set = function (self, val) PVPScan.db.profile.Minimap.hide = not PVPScan.db.profile.Minimap.hide LDBIcon:Refresh ("PVPScan", PVPScan.db.profile.Minimap) if (PVPScan.db.profile.Minimap.hide) then LDBIcon:Hide ("PVPScan") else LDBIcon:Show ("PVPScan") end end, }, }, } function PVPScan:OnInitialize() --declarar primeiro o db usando a global que é declarada no toc. self.db = LibStub ("AceDB-3.0"):New ("PVPScanDB", default_db, true) --declara agora as opções da tab raiz LibStub("AceConfig-3.0"):RegisterOptionsTable ("PVPScan", OptionsTable) PVPScan.OptionsFrame1 = LibStub ("AceConfigDialog-3.0"):AddToBlizOptions ("PVPScan", "PVPScan") --sub tab LibStub ("AceConfig-3.0"):RegisterOptionsTable ("PVPScan-Profiles", LibStub ("AceDBOptions-3.0"):GetOptionsTable (self.db)) PVPScan.OptionsFrame2 = LibStub ("AceConfigDialog-3.0"):AddToBlizOptions ("PVPScan-Profiles", "Profiles", "PVPScan") if LDB then local databroker = LDB:NewDataObject ("PVPScan", { type = "launcher", icon = [[Interface\PvPRankBadges\PvPRank15]], --HotCornerIgnore = true, OnClick = function (self, button) InterfaceOptionsFrame_OpenToCategory ("PVPScan") InterfaceOptionsFrame_OpenToCategory ("PVPScan") end }) if (databroker and not LDBIcon:IsRegistered ("PVPScan")) then LDBIcon:Register ("PVPScan", databroker, PVPScan.db.profile.Minimap) end end PVPScan:RefreshSpotBars() PVPScan:LockScanFrame (PVPScan.db.profile.Locked) PVPScan.EventFrame:SetScript ("OnEvent", PVPScan.OnParserEvent) end PVPScan:RegisterChatCommand ("pvpscan", function() InterfaceOptionsFrame_OpenToCategory ("PVPScan") InterfaceOptionsFrame_OpenToCategory ("PVPScan") end) ------------------------------------------------------------------------------------------------------------------------------------------------------------ --> general function PVPScan:ChangeZones() local name, type, difficulty, difficultyName, maxPlayers, playerDifficulty, isDynamicInstance, mapID, instanceGroupSize = GetInstanceInfo() local pvpType, isFFA, faction = GetZonePVPInfo() PVPScan.IsInBattleground = false PVPScan.IsInCity = false PVPScan.IsInArena = false PVPScan.IsInOutDoors = false PVPScan.ScanEnabled = false if (pvpType == "contested" and (not type or type == "none")) then PVPScan.IsInOutDoors = true PVPScan.ScanEnabled = true elseif (type == "pvp") then PVPScan.IsInBattleground = true elseif (type == "arena") then PVPScan.IsInArena = true elseif (type and (type == "scenario" or type == "party" or type == "raid" or pvpType == "friendly" or pvpType == "sanctuary")) then PVPScan.ScanEnabled = false else PVPScan.IsInOutDoors = true PVPScan.ScanEnabled = true end if (PVPScan.ScanEnabled) then PVPScan:EnableScan() else PVPScan:DisableScan() end end PVPScan:RegisterEvent ("ZONE_CHANGED_NEW_AREA", "ChangeZones") PVPScan:RegisterEvent ("PLAYER_ENTERING_WORLD", "ChangeZones") function PVPScan:EnableScan() PVPScan.EventFrame:RegisterEvent ("COMBAT_LOG_EVENT_UNFILTERED") PVPScan:RefreshSpotBars() PVPScan.NextBarCheckForHide = GetTime() + PVPScan.db.profile.SpotBarTimeOut PVPScan.BarChecker = PVPScan:ScheduleRepeatingTimer ("CheckBarTimeOut", 5) end function PVPScan:DisableScan() PVPScan.EventFrame:UnregisterEvent ("COMBAT_LOG_EVENT_UNFILTERED") PVPScan:RefreshSpotBars() if (PVPScan.BarChecker) then PVPScan:CancelTimer (PVPScan.BarChecker, true) PVPScan.BarChecker = nil end end function PVPScan:LockScanFrame (IsLocked) if (IsLocked) then PVPScanFrame.text:SetText ("") PVPScanFrame:SetBackdrop (nil) PVPScanFrame:EnableMouse (false) else PVPScanFrame.text:SetText ("PVPScan Anchor") PVPScanFrame:SetBackdrop ({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tile = true, TileSize = 64}) PVPScanFrame:SetBackdropColor (0, 0, 0, 1) PVPScanFrame:EnableMouse (true) end end ------------------------------------------------------------------------------------------------------------------------------------------------------------ --> outside world scan --> parser PVPScan.SpotBars = {} -- container para os objetos das barras PVPScan.NeedClass = {} -- container para os jogadores que precisam saber a classe PVPScan.CurrentShownPlayers = {} -- nomes dos jogadores que estão sendo mostrados com o index da barra no valos PVPScan.CooldownShownPlayers = {} -- nomes dos jogadores com o tempo de quando eles podem ser mostrados novamente nas barras PVPScan.EventFrame = CreateFrame ("frame", "PVPScanCombatLobReader", UIParent) PVPScan.EventFrame:RegisterEvent ("COMBAT_LOG_EVENT_UNFILTERED") function PVPScan:OnParserEvent (event, time, token, hidding, who_serial, who_name, who_flags, who_flags2, target_serial, target_name, target_flags, target_flags2, ...) if (PVPScan.NeedClass [who_name]) then local class = PVPScan:GuessClass (...) if (class) then PVPScan:UpdateBar (PVPScan.SpotBars [PVPScan.CurrentShownPlayers [who_name]], who_name, class, true) PVPScan.NeedClass [who_name] = nil end return end if (not PVPScan.CurrentShownPlayers [target_name] and _bit_band (target_flags, OBJECT_TYPE_PLAYER) ~= 0) then --> is player if (_bit_band (target_flags, REACTION_HOSTILE) ~= 0) then --> is hostile local class = PVPScan:GuessClass (...) PVPScan:EnemySpoted (target_name, target_serial, target_flags, class) end end if (not PVPScan.CurrentShownPlayers [who_name] and _bit_band (who_flags, OBJECT_TYPE_PLAYER) ~= 0) then --> is player if (_bit_band (who_flags, REACTION_HOSTILE) ~= 0) then --> is hostile local class = PVPScan:GuessClass (...) PVPScan:EnemySpoted (who_name, who_serial, who_flags, class) end end end function PVPScan:LeftCombatLockdown() if (PVPScan.schedule_frame_update) then PVPScan.schedule_frame_update = false PVPScan:RefreshSpotBars() end PVPScan:CheckNonCombatSpotBars() end function PVPScan:GotCombatLockdown() end function PVPScan:GetNextSpotBar() for i = 1, PVPScan.db.profile.SpotBarAmount do local bar = PVPScan.SpotBars [i] if (not bar) then print (i, #PVPScan.SpotBars) end if (not bar.InUse and bar.Cooldown < GetTime()) then return bar end end return nil end PVPScan:RegisterEvent ("PLAYER_REGEN_DISABLED", "GotCombatLockdown") PVPScan:RegisterEvent ("PLAYER_REGEN_ENABLED", "LeftCombatLockdown") -- found a enemy on the scan function PVPScan:EnemySpoted (name, serial, flags, class) --se nao tiver nome, nao interessa if (not name) then return end --se o player tiver no cooldown para mostrar, ignora-lo if (PVPScan.CooldownShownPlayers [name] and PVPScan.CooldownShownPlayers [name] > GetTime()) then return end local SpotBar = PVPScan:GetNextSpotBar() if (not SpotBar) then return end --seta o cooldown deste jogador PVPScan.CooldownShownPlayers [name] = GetTime() + PVPScan.db.profile.SpotBarPlayerCooldown --seta em qual barra o jogador esta sendo mostrado PVPScan.CurrentShownPlayers [name] = SpotBar.Index --se nao tiver uma classe, agendar uma pesquisa if (not class) then PVPScan.NeedClass [name] = true end --atualiza a barra PVPScan:UpdateBar (SpotBar, name, class) --toca o som se a configuracao permitir if (PVPScan.db.profile.SoundPlay) then local sound = PVPScan.db.profile.SoundFile sound = SharedMedia:Fetch ("sound", sound) if (sound) then PlaySoundFile (sound, "Master") end end end -- frames function PVPScanOnFrameEnter (self) GameTooltip:SetOwner (self, "ANCHOR_TOPLEFT") GameTooltip:ClearLines() GameTooltip:AddLine ("Right Click To Open Options Panel") GameTooltip:Show() end function PVPScanOnFrameLeave (self) GameTooltip:Hide() end function PVPScanOnFrameMouseDown (self, button) if (button == "LeftButton") then if (not self.IsMoving) then self:StartMoving() self.IsMoving = true end end end function PVPScanOnFrameMouseUp (self, button) if (button == "LeftButton") then if (self.IsMoving) then self:StopMovingOrSizing() self.IsMoving = false end elseif (button == "RightButton") then InterfaceOptionsFrame_OpenToCategory ("PVPScan") InterfaceOptionsFrame_OpenToCategory ("PVPScan") end end function PVPScan:CheckNonCombatSpotBars() for i = 1, PVPScan.db.profile.SpotBarAmount do local SpotObject = PVPScan.SpotBars [i] if (SpotObject.InUse and (SpotObject.NonTargetFrame:IsShown() or SpotObject.NeedUpdate)) then PVPScan:UpdateBar (SpotObject, SpotObject.PlayerName, SpotObject.PlayerClass) end end end function PVPScan:UpdateBar (SpotObject, Name, Class, ClassUpdate) SpotObject.IsShown = true SpotObject.InUse = true SpotObject.PlayerName = Name SpotObject.PlayerClass = Class SpotObject.Cooldown = GetTime() + PVPScan.db.profile.SpotBarCooldown SpotObject.ExpireAt = GetTime() + PVPScan.db.profile.SpotBarTimeOut SpotObject.NeedUpdate = false if (ClassUpdate) then if (SpotObject.TargetFrame:IsShown()) then if (not UnitAffectingCombat ("player") and not InCombatLockdown()) then local color = RAID_CLASS_COLORS [Class] local texcoord = CLASS_ICON_TCOORDS [Class] SpotObject.TargetFrame.classtexture:SetVertexColor (color.r, color.g, color.b) SpotObject.TargetFrame.classicon:SetTexture ([[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-CLASSES]]) SpotObject.TargetFrame.classicon:SetTexCoord (unpack (texcoord)) else SpotObject.NeedUpdate = true end else local color = RAID_CLASS_COLORS [Class] local texcoord = CLASS_ICON_TCOORDS [Class] SpotObject.NonTargetFrame.classtexture:SetVertexColor (color.r, color.g, color.b) SpotObject.NonTargetFrame.classicon:SetTexture ([[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-CLASSES]]) SpotObject.NonTargetFrame.classicon:SetTexCoord (unpack (texcoord)) end end if (UnitAffectingCombat ("player") or InCombatLockdown()) then --> enable in combat bat if (Class) then local color = RAID_CLASS_COLORS [Class] local texcoord = CLASS_ICON_TCOORDS [Class] SpotObject.NonTargetFrame.classtexture:SetVertexColor (color.r, color.g, color.b) SpotObject.NonTargetFrame.classicon:SetTexture ([[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-CLASSES]]) SpotObject.NonTargetFrame.classicon:SetTexCoord (unpack (texcoord)) else SpotObject.NonTargetFrame.classtexture:SetVertexColor (.7, .7, .7) SpotObject.NonTargetFrame.classicon:SetTexture ([[Interface\InventoryItems\WoWUnknownItem01]]) SpotObject.NonTargetFrame.classicon:SetTexCoord (0, 1, 0, 1) end SpotObject.NonTargetFrame.name:SetText (Name) SpotObject.NonTargetFrame:Show() SpotObject.NeedUpdate = true else --> enable spot bar if (Class) then local color = RAID_CLASS_COLORS [Class] local texcoord = CLASS_ICON_TCOORDS [Class] SpotObject.TargetFrame.classtexture:SetVertexColor (color.r, color.g, color.b) SpotObject.TargetFrame.classicon:SetTexture ([[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-CLASSES]]) SpotObject.TargetFrame.classicon:SetTexCoord (unpack (texcoord)) else SpotObject.TargetFrame.classtexture:SetVertexColor (.7, .7, .7) SpotObject.TargetFrame.classicon:SetTexture ([[Interface\InventoryItems\WoWUnknownItem01]]) SpotObject.TargetFrame.classicon:SetTexCoord (0, 1, 0, 1) end SpotObject.TargetFrame:SetAttribute ("macrotext", "/cleartarget\n/targetexact " .. Name) SpotObject.TargetFrame.name:SetText (Name) SpotObject.TargetFrame.SpotObject = SpotObject SpotObject.NonTargetFrame:Hide() SpotObject.TargetFrame:Show() end end function PVPScan:CheckBarTimeOut() if (not UnitAffectingCombat ("player") and not InCombatLockdown()) then local time = GetTime() for repeat_twice = 1, 2 do for i = 1, PVPScan.db.profile.SpotBarAmount do local SpotObject = PVPScan.SpotBars [i] if (SpotObject.InUse) then --verifica se expirou if (SpotObject.ExpireAt < time) then PVPScan:DisableSpotBar (SpotObject) end else for o = i+1, PVPScan.db.profile.SpotBarAmount do local NextSpotObject = PVPScan.SpotBars [o] if (NextSpotObject.InUse) then --> transferir pra cá --seta a nova barra local PlayerName = NextSpotObject.PlayerName PVPScan:UpdateBar (SpotObject, PlayerName, NextSpotObject.PlayerClass) --desliga a barra antiga PVPScan:DisableSpotBar (NextSpotObject) --seta em qual barra o jogador esta sendo mostrado PVPScan.CurrentShownPlayers [PlayerName] = i break end end end end end end end function PVPScanSpotBarClick (self) if (self.SpotObject) then self.SpotObject.Cooldown = GetTime() + PVPScan.db.profile.SpotBarCooldown self.SpotObject.ExpireAt = GetTime() + PVPScan.db.profile.SpotBarTimeOut end end function PVPScan:DisableSpotBar (SpotObject) SpotObject.TargetFrame:Hide() SpotObject.TargetFrame.SpotObject = nil SpotObject.NonTargetFrame:Hide() SpotObject.IsShown = false SpotObject.NeedUpdate = false SpotObject.InUse = false SpotObject.Cooldown = 0 SpotObject.ExpireAt = 0 local name = SpotObject.PlayerName if (name) then PVPScan.NeedClass [name] = nil PVPScan.CurrentShownPlayers [name] = nil PVPScan.CooldownShownPlayers [name] = nil end SpotObject.PlayerName = nil SpotObject.PlayerClass = nil end function PVPScan:RefreshSpotBars() if (UnitAffectingCombat ("player") or InCombatLockdown()) then PVPScan.schedule_frame_update = true PVPScan:Print ("When the combat finishes, the frame will be updated.") return end if (not PVPScan.ScanEnabled) then PVPScanFrame:Hide() else PVPScanFrame:Show() end local amount_bars = PVPScan.db.profile.SpotBarAmount PVPScanFrame:SetSize (PVPScan.db.profile.SpotBarWidth, 20) --> we need extra bars? if (amount_bars > #PVPScan.SpotBars) then for i = #PVPScan.SpotBars+1, amount_bars do local NewBarObject = { Index = i, TargetFrame = CreateFrame ("Button", "PVPScanSpotBar" .. i, PVPScanFrame, "PVPScanSpotBarTemplate"), NonTargetFrame = CreateFrame ("Button", "PVPScanSpotBarInCombat" .. i, PVPScanFrame, "PVPScanSpotBarInCombatTemplate"), IsShown = false, -- se a barra esta sendo mostrada PlayerName = nil, -- nome do jogador que esta sendo mostrado PlayerClass = nil, NeedUpdate = false, -- se a barra precisa de um update após o termino do combate InUse = false, -- se a barra esta em uso ExpireAt = 0, -- quando a barra ira sumir automaticamente Cooldown = 0, -- tempo para poder por outro jogador nesta barra } NewBarObject.NonTargetFrame:SetFrameLevel (NewBarObject.TargetFrame:GetFrameLevel()+1) local y = (i-1) * PVPScan.db.profile.SpotBarHeight * -1 NewBarObject.TargetFrame:SetPoint ("topleft", PVPScanFrame, "topleft", 0, y) NewBarObject.NonTargetFrame:SetPoint ("topleft", PVPScanFrame, "topleft", 0, y) NewBarObject.TargetFrame:SetSize (PVPScan.db.profile.SpotBarWidth, PVPScan.db.profile.SpotBarHeight) NewBarObject.NonTargetFrame:SetSize (PVPScan.db.profile.SpotBarWidth, PVPScan.db.profile.SpotBarHeight) tinsert (PVPScan.SpotBars, NewBarObject) end end if (#PVPScan.SpotBars > amount_bars) then for i = #PVPScan.SpotBars, amount_bars+1, -1 do PVPScan:DisableSpotBar (PVPScan.SpotBars [i]) end end --> refresh existing for Index, BarObject in ipairs (PVPScan.SpotBars) do local y = (Index-1) * PVPScan.db.profile.SpotBarHeight * -1 --point BarObject.TargetFrame:SetPoint ("topleft", PVPScanFrame, "bottomleft", 0, y) BarObject.NonTargetFrame:SetPoint ("topleft", PVPScanFrame, "bottomleft", 0, y) --size BarObject.TargetFrame:SetSize (PVPScan.db.profile.SpotBarWidth, PVPScan.db.profile.SpotBarHeight) BarObject.NonTargetFrame:SetSize (PVPScan.db.profile.SpotBarWidth, PVPScan.db.profile.SpotBarHeight) --texture size BarObject.TargetFrame.classtexture:SetSize (PVPScan.db.profile.SpotBarWidth, PVPScan.db.profile.SpotBarHeight) BarObject.NonTargetFrame.classtexture:SetSize (PVPScan.db.profile.SpotBarWidth, PVPScan.db.profile.SpotBarHeight) --bar texture BarObject.TargetFrame.classtexture:SetTexture (SharedMedia:Fetch ("statusbar", PVPScan.db.profile.SpotBarTexture) or [[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]]) BarObject.NonTargetFrame.classtexture:SetTexture (SharedMedia:Fetch ("statusbar", PVPScan.db.profile.SpotBarTexture) or [[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]]) --icon size BarObject.TargetFrame.classicon:SetSize (PVPScan.db.profile.SpotBarHeight, PVPScan.db.profile.SpotBarHeight) BarObject.NonTargetFrame.classicon:SetSize (PVPScan.db.profile.SpotBarHeight, PVPScan.db.profile.SpotBarHeight) end end --> misc function PVPScan:GuessClass (...) local arg1, arg2, arg3, arg4 = select (1, ...) if (type (arg1) == "number") then return PVPScan.ClassSpellList [arg1] end return nil end ------------------------------------------------------------------------------------------------------------------------------------------------------------ --> battlegrounds