view PVPScan.lua @ 26:9e810626ddfb v8.2.0.026

- ToC Update for Patch 8.2
author Tercioo
date Fri, 28 Jun 2019 20:12:43 -0300
parents fedcd7c21db9
children
line wrap: on
line source


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 LibWindow = LibStub ("LibWindow-1.1")
local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0")

SharedMedia:Register ("statusbar", "Details Serenity", [[Interface\AddOns\PVPScan\media\bar_serenity]])
SharedMedia:Register ("statusbar", "Skyline", [[Interface\AddOns\PVPScan\media\bar_skyline]])
SharedMedia:Register ("statusbar", "DGround", [[Interface\AddOns\PVPScan\media\bar_background]])

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 = "DGround",
		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,
		},		
	},
}

local WaitToRestore = function()
	if (not UnitAffectingCombat ("player") and not InCombatLockdown()) then
		PVPScan.RestoreTick:Cancel()
		LibWindow.RestorePosition (PVPScanFrame)
		PVPScan:LockScanFrame (PVPScan.db.profile.Locked)
		PVPScan:RefreshSpotBars()
	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
	
	if (not self.db.profile.point) then
		PVPScan.db.profile.Locked = false
	end
	
	LibWindow.RegisterConfig (PVPScanFrame, self.db.profile)
	LibWindow.RestorePosition (PVPScanFrame)
	LibWindow.SavePosition (PVPScanFrame)
	
	if (UnitAffectingCombat ("player") or InCombatLockdown()) then
		PVPScan:LockScanFrame (true)
		self.RestoreTick = C_Timer.NewTicker (1, WaitToRestore)
	else
		PVPScan:RefreshSpotBars()
	end
	
	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

local check_zone = function()
	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

function PVPScan:ChangeZones()
	C_Timer.After (5, check_zone)
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)
		LibWindow.SavePosition (PVPScanFrame)
	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()
	
		local time, token, hidding, who_serial, who_name, who_flags, who_flags2, target_serial, target_name, target_flags, target_flags2, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12 = CombatLogGetCurrentEventInfo()

		if (PVPScan.NeedClass [who_name]) then
			local class = PVPScan:GuessClass (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)
			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 pvpType, isFFA, faction = GetZonePVPInfo()
				if (pvpType ~= "contested" and pvpType ~= "hostile") then
					return
				end
				local class = PVPScan:GuessClass (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)
				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 pvpType, isFFA, faction = GetZonePVPInfo()
				if (pvpType ~= "contested" and pvpType ~= "hostile") then
					return
				end
				local class = PVPScan:GuessClass (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)
				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 ("PvPScan no bar for", i, #PVPScan.SpotBars)
				return
			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()
				LibWindow.SavePosition (PVPScanFrame)
				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 and 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 = select (1, ...)
		
		if (type (arg1) == "number") then
			local spellname = GetSpellInfo (arg1)
			local class = PVPScan.ClassSpellList [arg1]
			--print ("found enemy:", arg1, class, spellname)
			return PVPScan.ClassSpellList [arg1]
		end

		return nil
	end


------------------------------------------------------------------------------------------------------------------------------------------------------------
--> battlegrounds