Quantcast
--[[
##############################################################################
_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
 ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
    ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
     _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
      __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
       _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
        ___\///////////___________\///___________\/////////_____\///////////_#
##############################################################################
S U P E R - V I L L A I N - U I   By: Munglunch                              #
##############################################################################
##########################################################
LOCALIZED LUA FUNCTIONS
##########################################################
]]--
--[[ GLOBALS ]]--
local _G = _G;
local unpack    = _G.unpack;
local select    = _G.select;
local pairs     = _G.pairs;
local ipairs    = _G.ipairs;
local type      = _G.type;
local error     = _G.error;
local pcall     = _G.pcall;
local assert    = _G.assert;
local tostring  = _G.tostring;
local tonumber  = _G.tonumber;
local tinsert 	= _G.tinsert;
local string 	= _G.string;
local math 		= _G.math;
local table 	= _G.table;
local bit       = _G.bit;
--[[ STRING METHODS ]]--
local format, sub = string.format, string.sub;
--[[ MATH METHODS ]]--
local abs, ceil, floor, round = math.abs, math.ceil, math.floor, math.round;
--[[ TABLE METHODS ]]--
local tremove, twipe = table.remove, table.wipe;
--[[ BINARY METHODS ]]--
local band, bor = bit.band, bit.bor;
--[[
##########################################################
GET ADDON DATA
##########################################################
]]--
local SVUIAddOnName, PLUGIN = ...;
local SuperVillain, L = unpack(SVUI);
local CONFIGS = SuperVillain.Configs
local NewHook = hooksecurefunc;
local SVUIAddonEventHandler = CreateFrame("Frame", nil)
local version = GetAddOnMetadata(..., "Version")

PLUGIN = SuperVillain:Prototype(SVUIAddOnName, version)

_G["WarVillain"] = PLUGIN;
--[[
##########################################################
GLOBAL SLASH FUNCTIONS
##########################################################
]]--
BINDING_HEADER_SVUIAOW = "SuperVillain UI: Art of War";

function SVUISayIncoming()
	local subzoneText = GetSubZoneText()
	local msg = ("{rt8} Incoming %s {rt8}"):format(subzoneText)
	SendChatMessage(msg, "INSTANCE_CHAT")
	return
end
--[[
##########################################################
LOCAL FUNCTIONS
##########################################################
]]--
local function HeadsUpAlarm(...)
	if not CombatText_AddMessage then return end
	CombatText_AddMessage(...)
end
--[[
##########################################################
CORE FUNCTIONS
##########################################################
]]--
local EnemyCache, AlertedCache = {},{}
local AoWLogs = CreateFrame("Frame", "SVUI_AoWLogs", UIParent)
local playerGUID = UnitGUID('player')
local playerFaction = UnitFactionGroup("player")
local classColor = RAID_CLASS_COLORS
local classColors = SVUI_CLASS_COLORS[SuperVillain.class]
local classR, classG, classB = classColors.r, classColors.g, classColors.b
local classA = 0.35
local fallbackColor = {r=1,g=1,b=1}
local ACTIVE_ZONE = ""
local ICON_FILE = [[Interface\AddOns\SVUI_ArtOfWar\artwork\DOCK-PVP]]
local PVP_SAFE = [[Interface\AddOns\SVUI_ArtOfWar\artwork\PVP-SAFE]]
local PVP_HELP = [[Interface\AddOns\SVUI_ArtOfWar\artwork\PVP-INCOMING]]
local SCAN_ICON = [[Interface\Addons\SVUI_ArtOfWar\artwork\DOCK-SCAN]]
local SCAN_ANIM = [[Interface\Addons\SVUI_ArtOfWar\artwork\SCAN-ANIMATION]]
local PVP_LOST = [[Interface\WorldMap\Skull_64Red]]
local PVP_NODES = {
	[461] = { --Arathi Basin (5)
		"Stables", "Lumber", "Blacksmith", "Mine", "Farm"
	},
	[935] = { --Deepwind Gorge (3)
		"Center Mine", "North Mine", "South Mine"
	},
	[482] = { --Eye of the Storm (4)
		"Fel Reaver", "Blood Elf", "Draenei", "Mage"
	},
	[736] = { --The Battle for Gilneas (3)
		"LightHouse", "WaterWorks", "Mines"
	},
}

local Safe_OnEnter = function(self)
	if InCombatLockdown() then return end
	local zone = self.name
	if(zone and zone ~= "") then
		self:SetBackdropBorderColor(1,0.45,0)
		GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT", 0, 4)
		GameTooltip:ClearLines()
		GameTooltip:AddLine(("%s Is Safe!"):format(zone), 1, 1, 1)
		GameTooltip:Show()
	end
end

local Safe_OnLeave = function(self)
	if InCombatLockdown() then return end
	self:SetBackdropBorderColor(0,0,0)
	if(GameTooltip:IsShown()) then GameTooltip:Hide() end
end

local Safe_OnClick = function(self)
	local zone = self.name
	if(zone and zone ~= "") then
		SendChatMessage(("{rt4} %s Is Safe {rt4}"):format(zone), "INSTANCE_CHAT")
	end
end

local Help_OnEnter = function(self)
	if InCombatLockdown() then return end
	local zone = self.name
	if(zone and zone ~= "") then
		self:SetBackdropBorderColor(1,0.45,0)
		GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT", 0, 4)
		GameTooltip:ClearLines()
		GameTooltip:AddLine(("%s Needs Help!"):format(zone), 1, 1, 1)
		GameTooltip:Show()
	end
end

local Help_OnLeave = function(self)
	if InCombatLockdown() then return end
	self:SetBackdropBorderColor(0,0,0)
	if(GameTooltip:IsShown()) then GameTooltip:Hide() end
end

local Help_OnClick = function(self)
	if(self.name and self.name ~= "") then
		local msg = ("{rt8} Incoming %s {rt8}"):format(self.name)
		SendChatMessage(msg, "INSTANCE_CHAT")
	end
end

local function AddEnemyScan(guid, timestamp)
	if(EnemyCache[guid]) then
		return EnemyCache[guid]
	end
	local class, classToken, race, raceToken, sex, name, realm = GetPlayerInfoByGUID(guid)
	local colors = classColor[classToken] or fallbackColor
	EnemyCache[guid] = {
        ["name"] = name,
        ["realm"] = realm,
        ["class"] = class,
        ["race"] = race,
        ["sex"] = sex,
        ["colors"] = colors,
        ["time"] = timestamp
    }
    PLUGIN:ScannerLog(EnemyCache[guid])
    return EnemyCache[guid];
end

local function SaveEnemyScan(guid, timestamp)
	local e = EnemyCache[guid]
	if(not e) then e = AddEnemyScan(guid, timestamp) end
	SVAOW_Cache[guid] = {
        ["name"] = e.name,
        ["realm"] = e.realm,
        ["class"] = e.class,
        ["race"] = e.race,
        ["sex"] = e.sex,
        ["colors"] = e.colors,
        ["time"] = e.timestamp
    }
    local msg = ("Killed By: %s"):format(e.name);
    HeadsUpAlarm(msg, CombatText_StandardScroll, e.colors.r, e.colors.g, e.colors.b, "sticky");
    PLUGIN:UpdateSummary()
end

local function KilledEnemyHandler(guid)
	local e = SVAOW_Cache[guid]
	if(e) then
		HeadsUpAlarm(("Killed Mortal Enemy: %s"):format(e.name), CombatText_StandardScroll, 0.2, 1, 0.1, "sticky");
	end
	e = EnemyCache[guid]
	if(e) then
		HeadsUpAlarm(("Killed Enemy: %s"):format(e.name), CombatText_StandardScroll, 0.1, 0.8, 0);
	end
end

local function ClearCacheScans()
	wipe(EnemyCache)
	wipe(AlertedCache)
	PLUGIN.LogWindow:Clear();
end

local function ClearSavedScans()
	SVAOW_Cache = {}
end

local function EnemyAlarm(name, class, colors, kos)
	local inInstance, instanceType = IsInInstance()
	if(instanceType ~= "pvp" and not AlertedCache[name]) then
		local msg
		if(kos) then
			msg = ("Mortal Enemy Detected!: %s"):format(name);
			HeadsUpAlarm(msg, CombatText_StandardScroll, 1, 0, 0)
		else
			msg = ("%s Detected"):format(class);
			HeadsUpAlarm(msg, CombatText_StandardScroll, colors.r, colors.g, colors.b)
	    end
	    AlertedCache[name] = true
	end
end

local function StealthAlarm(name)
	local msg = ("%s Detected!"):format(name);
    HeadsUpAlarm(msg, CombatText_StandardScroll, 1, 0.5, 0);
end

function PLUGIN:UpdateSummary()
	self.SummaryWindow:Clear();
	local stored = SVAOW_Cache;
	local amount = 0
	for _,data in pairs(stored) do
		if type(data) == "table" and data.name and data.class then
			amount = amount + 1;
		end
	end
	self.SummaryWindow:AddMessage(("You Have |cffff5500%s|r Mortal Enemies"):format(amount), 0.8, 0.8, 0.8);
end

function PLUGIN:ResetLogs()
	wipe(EnemyCache)
	self.TitleWindow:Clear();
	self.SummaryWindow:Clear();
	self.LogWindow:Clear();
	self.TitleWindow:AddMessage(("Scanning %s"):format(ACTIVE_ZONE), 1, 1, 0);
	local stored = SVAOW_Cache;
	local amount = 0
	for _,data in pairs(stored) do
		if type(data) == "table" and data.name and data.class then
			amount = amount + 1;
		end
	end
	self.SummaryWindow:AddMessage(("You Have |cffff5500%s|r Mortal Enemies"):format(amount), 0.8, 0.8, 0.8);
	collectgarbage("collect")
end

function PLUGIN:ScannerLog(enemy)
	if(not enemy.name or not enemy.race or not enemy.class) then return end
    local hex = ("%s - %s %s"):format(enemy.name, enemy.race, enemy.class)
	self.LogWindow:AddMessage(hex, enemy.colors.r, enemy.colors.g, enemy.colors.b);
	EnemyAlarm(enemy.name, enemy.class, enemy.colors)
end

function PLUGIN:UpdateCommunicator()
	local docklet = _G["SVUI_ArtOfWarDock_ToolBarButton"]
	if(not self.InPVP) then
		local mapID = GetCurrentMapAreaID()
		if(mapID) then
			local points = PVP_NODES[mapID]
			if(points) then
				for i = 1, 5 do
					local nodeName = ("SVUI_PVPNode%d"):format(i)
					local node = _G[nodeName]
					local safe = node.Safe
					local help = node.Help
					if(i <= #points) then
						local name = points[i]
						safe.name = name
						help.name = name
						node.Text:SetText(name)
						node:Show()
					else
						safe.name = ""
						help.name = ""
						node.Text:SetText("")
						node:Hide()
					end
				end
				self.InPVP = true
				SVUIAddonEventHandler:UnregisterEvent("UPDATE_BATTLEFIELD_SCORE")
				self.DockButton:SaveColors("yellow", "yellow", true)
				self.DockButton.icon:SetTexture(ICON_FILE)
				self.DockButton.Scanner:Hide()
				AoWLogs:Hide()
				self.Scanning = false
			end
		end
	elseif(self.InPVP) then
		for i = 1, 5 do
			local nodeName = ("SVUI_PVPNode%d"):format(i)
			local node = _G[nodeName]
			local safe = node.Safe
			local help = node.Help
			safe.name = ""
			help.name = ""
			node.Text:SetText("")
			node:Hide()
		end
		self.InPVP = nil
		SVUIAddonEventHandler:RegisterEvent("UPDATE_BATTLEFIELD_SCORE")
		self.DockButton:SaveColors("special", "icon", false)
		self.DockButton.icon:SetTexture(0,0,0,0)
		self.DockButton.Scanner:Show()
		AoWLogs:Show()
		self.Scanning = true
	end
end

function PLUGIN:UpdateZoneStatus()
	local zoneText = GetRealZoneText() or GetZoneText()
	if(not zoneText or zoneText == "") then
		SuperVillain:ExecuteTimer(PLUGIN.UpdateZoneStatus, 5)
		return
	end
	if(zoneText ~= ACTIVE_ZONE) then
		ClearCacheScans()
		ACTIVE_ZONE = zoneText
		PLUGIN.TitleWindow:Clear();
		PLUGIN.TitleWindow:AddMessage(("Scanning %s"):format(ACTIVE_ZONE), 1, 1, 0);
	end
	local zonePvP = GetZonePVPInfo()
	if(zonePvP == "sanctuary" or zoneText == "") then
		PLUGIN.Scanning = false
	else
		PLUGIN.Scanning = true
		local inInstance, instanceType = IsInInstance()
		if(inInstance and ((instanceType == "party") or (instanceType == "raid"))) then
			PLUGIN.Scanning = false
		elseif (not zonePvP or (zonePvP == "friendly") or (not UnitIsPVP("player"))) then
			PLUGIN.Scanning = false
		elseif(instanceType == "pvp" and not PLUGIN.InPVP and PLUGIN.Scanning == true) then
			PLUGIN:UpdateCommunicator()
		end
	end
end

local function ParseIncomingLog(timestamp, event, eGuid, eName, pGuid)
	local cached = SVAOW_Cache[eGuid]
	local kos, needsUpdate = false, false

	if(cached) then
		kos = true
	else
		cached = EnemyCache[eGuid]
	end

	if(cached and cached.time) then
		needsUpdate = (cached.time + 60) < timestamp;
	else
		cached = AddEnemyScan(eGuid, timestamp)
		needsUpdate = true
	end

	if(cached) then
		if(needsUpdate) then
			EnemyAlarm(eName, cached.class, cached.colors, kos)
			cached.time = timeStamp
		end

		if(pGuid == playerGUID and not AlertedCache[eName]) then
			AlertedCache[eName] = true
			local incoming = ("%s Attacking You!"):format(eName);
			HeadsUpAlarm(incoming, CombatText_StandardScroll, 1, 0.05, 0, "crit")
		end
	end
end

local function GetSourceType(guid)
	local subStr, binStr, bitVal, srcType
	subStr  = guid:sub(3, 5)
	binStr  = ("0x%s"):format(subStr)
	bitVal  = tonumber(binStr)
	srcType = band(bitVal, 0x00F)
	return srcType
end

function PLUGIN:CombatLogScanner(timestamp, event, _, srcGUID, srcName, srcFlags, sourceRaidFlags, dstGUID, dstName, dstFlags, destRaidFlags, _, spellName)
	local flagParse = band(srcFlags, COMBATLOG_OBJECT_REACTION_HOSTILE)
	local flagged = flagParse == COMBATLOG_OBJECT_REACTION_HOSTILE

	if(flagged) then
		if(srcGUID and srcName) then
			local isHostile = CombatLog_Object_IsA(srcFlags, COMBATLOG_FILTER_HOSTILE_PLAYERS)
			local srcType = GetSourceType(srcGUID)
			if((srcType == 0 or srcType == 8) and isHostile) then
				if(event == "SPELL_AURA_APPLIED" and (spellName == L["Stealth"] or spellName == L["Prowl"])) then
					StealthAlarm(spellName)
				end
				if(dstGUID == playerGUID) then
					PLUGIN.HitBy = srcGUID
				end
				if(not PLUGIN.Scanning) then return end
				ParseIncomingLog(timestamp, event, srcGUID, srcName, dstGUID)
			end
		end

		if(PLUGIN.Scanning and dstGUID and dstName) then
			local isHostile = CombatLog_Object_IsA(dstFlags, COMBATLOG_FILTER_HOSTILE_PLAYERS)
			local srcType = GetSourceType(dstGUID)
			if((srcType == 0 or srcType == 8) and isHostile) then
				ParseIncomingLog(timestamp, event, dstGUID, dstName, srcGUID)
			end
		end
	end

	if(PLUGIN.Scanning and event == "PARTY_KILL") then
		if(srcGUID == playerGUID and dstName) then
			KilledEnemyHandler(dstGUID)
		end
	end
end

function PLUGIN:TargetChanged()
	if(UnitIsPlayer("target") and UnitIsEnemy("target", "player")) then
		local guid = UnitGUID("target")
		if(not EnemyCache[guid]) then
			local timestamp = time()
			AddEnemyScan(guid, timestamp)
		end
		if(SVAOW_Cache[guid]) then
			HeadsUpAlarm("Kill On Sight!", CombatText_StandardScroll, 1, 0, 0, "crit")
		end
	end
end

function PLUGIN:TheyGotMe()
	local guid = PLUGIN.HitBy
	if(guid and guid ~= "") then
		local stamp = time()
		SaveEnemyScan(guid, stamp)
	end
end

local Registry_OnEvent = function(self, event, ...)
	if(event == "PLAYER_TARGET_CHANGED") then
		PLUGIN:TargetChanged()
	elseif(event == "COMBAT_LOG_EVENT_UNFILTERED") then
		PLUGIN:CombatLogScanner(...)
	elseif(event == "PLAYER_ENTERING_WORLD" or event == "UPDATE_BATTLEFIELD_SCORE") then
		PLUGIN:UpdateCommunicator()
	elseif(event == "PLAYER_DEAD") then
		PLUGIN:TheyGotMe()
	elseif(event == "PLAYER_REGEN_ENABLED") then
		PLUGIN.HitBy = false;
	else
		PLUGIN:UpdateZoneStatus()
	end
end

SVUIAddonEventHandler:SetScript("OnEvent", Registry_OnEvent)

local LogClear_OnClick = function(self, button)
	if(IsShiftKeyDown()) then
		ClearSavedScans()
		PLUGIN:ResetLogs()
	end
	ClearCacheScans()
end

local LogClear_OnEnter = function(self)
	GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT", 0, 4)
	GameTooltip:ClearLines()
	GameTooltip:AddDoubleLine("Click", "To Clear Scan", 0.1, 1, 0.2, 1, 1, 1)
	GameTooltip:AddDoubleLine("[SHIFT] Click", "To Clear All", 0.1, 1, 0.2, 1, 1, 1)
	GameTooltip:Show()
end

local LogClear_OnLeave = function(self)
	GameTooltip:Hide()
end

local onMouseWheel = function(self, delta)
	if (delta > 0) then
		self:ScrollUp()
	elseif (delta < 0) then
		self:ScrollDown()
	end
end

local function MakeLogWindow()
	AoWLogs:SetFrameStrata("MEDIUM")
	AoWLogs:FillInner(SVUI_ArtOfWarDock)
	AoWLogs:SetParent(SVUI_ArtOfWarDock)

	local title = CreateFrame("ScrollingMessageFrame", nil, AoWLogs)
	title:SetSpacing(4)
	title:SetClampedToScreen(false)
	title:SetFrameStrata("MEDIUM")
	title:SetPoint("TOPLEFT", AoWLogs, "TOPLEFT",0,0)
	title:SetPoint("BOTTOMRIGHT", AoWLogs, "TOPRIGHT",0,-20)
	title:SetFontTemplate(SuperVillain.Media.font.names, 16, "OUTLINE", "CENTER", "MIDDLE")
	title:SetMaxLines(1)
	title:EnableMouseWheel(false)
	title:SetFading(false)
	title:SetInsertMode('TOP')

	title.divider = title:CreateTexture(nil,"OVERLAY")
    title.divider:SetTexture(classR, classG, classB)
    title.divider:SetAlpha(classA)
    title.divider:SetPoint("BOTTOMLEFT")
    title.divider:SetPoint("BOTTOMRIGHT")
    title.divider:SetHeight(1)

    local clearcount = CreateFrame("Button", nil, AoWLogs)
    clearcount:SetPoint("TOPLEFT", title, "BOTTOMLEFT",0,0)
	clearcount:SetPoint("BOTTOMRIGHT", title, "BOTTOMRIGHT",0,-20)
	clearcount:SetButtonTemplate(true)
	clearcount:SetScript("OnEnter", LogClear_OnEnter)
	clearcount:SetScript("OnLeave", LogClear_OnLeave)
	clearcount:SetScript("OnClick", LogClear_OnClick)

    local summary = CreateFrame("ScrollingMessageFrame", nil, clearcount)
	summary:SetSpacing(4)
	summary:SetClampedToScreen(false)
	summary:SetFrameStrata("MEDIUM")
	summary:SetAllPoints(clearcount)
	summary:SetFontTemplate(SuperVillain.Media.font.system, 16, "OUTLINE", "CENTER", "MIDDLE")
	summary:SetMaxLines(1)
	summary:EnableMouse(false)
	summary:SetFading(false)
	summary:SetInsertMode('TOP')

	summary.divider = summary:CreateTexture(nil,"OVERLAY")
    summary.divider:SetTexture(classR, classG, classB)
    summary.divider:SetAlpha(classA)
    summary.divider:SetPoint("BOTTOMLEFT")
    summary.divider:SetPoint("BOTTOMRIGHT")
    summary.divider:SetHeight(1)

	local log = CreateFrame("ScrollingMessageFrame", nil, AoWLogs)
	log:SetSpacing(4)
	log:SetClampedToScreen(false)
	log:SetFrameStrata("MEDIUM")
	log:SetPoint("TOPLEFT",summary,"BOTTOMLEFT",0,0)
	log:SetPoint("BOTTOMRIGHT",AoWLogs,"BOTTOMRIGHT",0,0)
	log:SetFont(SuperVillain.Media.font.system, 11, "OUTLINE")
	log:SetJustifyH("CENTER")
	log:SetJustifyV("MIDDLE")
	log:SetShadowColor(0, 0, 0, 0)
	log:SetMaxLines(120)
	log:EnableMouseWheel(true)
	log:SetScript("OnMouseWheel", onMouseWheel)
	log:SetFading(false)
	log:SetInsertMode('TOP')

	PLUGIN.TitleWindow = title
	PLUGIN.SummaryWindow = summary
	PLUGIN.LogWindow = log

	SVUIAddonEventHandler:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	SVUIAddonEventHandler:RegisterEvent("ZONE_CHANGED")
	SVUIAddonEventHandler:RegisterEvent("ZONE_CHANGED_NEW_AREA")
	SVUIAddonEventHandler:RegisterEvent("PLAYER_ENTERING_WORLD")
	SVUIAddonEventHandler:RegisterEvent("PLAYER_TARGET_CHANGED")
	SVUIAddonEventHandler:RegisterEvent("PLAYER_REGEN_ENABLED")
	SVUIAddonEventHandler:RegisterEvent("PLAYER_DEAD")
	SVUIAddonEventHandler:RegisterEvent("UNIT_FACTION")
	SVUIAddonEventHandler:RegisterEvent("UPDATE_BATTLEFIELD_SCORE")
end
--[[
##########################################################
BUILD FUNCTION
##########################################################
]]--
local function LoadOptions()
	SuperVillain.Options.args.plugins.args.pluginOptions.args.SVAOW = {
		type = "group",
		name = L["Art of War"],
		childGroups = "tree",
		args = {
			enable = {
				order = 1,
				type = "toggle",
				name = "Enable",
				get = function(a) return SuperVillain.db.SVAOW.enable end,
				set = function(a,b)SuperVillain.db.SVAOW.enable = b; SuperVillain:StaticPopup_Show("RL_CLIENT") end
			}
		}
	}
end

local function LoadWarVillain()
	if(not SuperVillain.db.SVAOW.enable) then return end
	PLUGIN.db = SuperVillain.db.SVAOW

	if(not SVAOW_Data) then SVAOW_Data = {} end
	if(not SVAOW_Cache) then SVAOW_Cache = {} end

	PLUGIN.HitBy = false;
	PLUGIN.Scanning = false;
	PLUGIN.InPVP = false

	local holder = CreateFrame("Frame", "SVUI_ArtOfWarDock", SuperDockWindowRight)
	holder:SetFrameStrata("BACKGROUND")
	MakeLogWindow()
	SuperVillain:RegisterDocklet("SVUI_ArtOfWarDock", "Art of War", ICON_FILE)

	local dockbutton = _G["SVUI_ArtOfWarDock_ToolBarButton"];

	local scanner = CreateFrame("Frame", nil, dockbutton)
	scanner:SetAllPoints(dockbutton)
	scanner:SetFrameLevel(dockbutton:GetFrameLevel()  +  2)

	-- local blip = scanner:CreateTexture(nil, "BORDER")
	-- blip:SetAllPoints(scanner)
	-- blip:SetTexture(SCAN_ICON)
	-- blip:SetVertexColor(0,0.8,0)
	-- blip:SetAlpha(0.5)

	scanner.Spinner = scanner:CreateTexture(nil, "ARTWORK", nil, 2)
	scanner.Spinner:SetTexture(SCAN_ANIM)
	scanner.Spinner:SetVertexColor(0.5,0.5,0.5)
	scanner.Spinner:Size(dockbutton:GetSize())
	scanner.Spinner:SetPoint("CENTER", scanner, "CENTER", 0, 0)

	SuperVillain.Animate:Orbit(scanner.Spinner, 8, true)

	dockbutton.Scanner = scanner

	PLUGIN.DockButton = dockbutton
	PLUGIN.DockButton.icon:SetTexture(0,0,0,0)

	local width = holder:GetWidth()
	local height = holder:GetHeight()
	local sectionWidth = (width / 6) - 2
	local sectionHeight = (height / 5) - 2
	local iconSize = sectionHeight * 0.5

	for i = 1, 5 do
		local yOffset = (sectionHeight * (i - 1)) + 2

		local poiName = ("SVUI_PVPNode%d"):format(i)
		local poi = CreateFrame("Frame", poiName, holder)
		poi:SetSize((width - 2), sectionHeight)
		poi:SetPoint("TOP", holder, "TOP", 0, -yOffset)
		poi:SetPanelTemplate("Transparent")

		local safe = CreateFrame("Button", nil, poi)
		safe:SetSize(sectionWidth, sectionHeight)
		safe:SetPoint("RIGHT", poi, "RIGHT", -2, 0)
		safe:SetButtonTemplate()
		safe:SetPanelColor("green")
		local sicon = safe:CreateTexture(nil, "OVERLAY")
		sicon:SetPoint("CENTER", safe, "CENTER", 0, 0)
		sicon:SetSize(iconSize,iconSize)
		sicon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
		sicon:SetTexture(PVP_SAFE)
		safe:SetScript("OnEnter", Safe_OnEnter)
		safe:SetScript("OnLeave", Safe_OnLeave)
		safe:SetScript("OnClick", Safe_OnClick)

		poi.Safe = safe

		local help = CreateFrame("Button", nil, poi)
		help:SetSize(sectionWidth, sectionHeight)
		help:SetPoint("RIGHT", safe, "LEFT", -2, 0)
		help:SetButtonTemplate()
		help:SetPanelColor("red")
		local hicon = help:CreateTexture(nil, "OVERLAY")
		hicon:SetPoint("CENTER", help, "CENTER", 0, 0)
		hicon:SetSize(iconSize,iconSize)
		hicon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
		hicon:SetTexture(PVP_HELP)
		help:SetScript("OnEnter", Help_OnEnter)
		help:SetScript("OnLeave", Help_OnLeave)
		help:SetScript("OnClick", Help_OnClick)

		poi.Help = help

		poi.Text = poi:CreateFontString(nil,"OVERLAY")
		poi.Text:SetFont(SuperVillain.Media.font.roboto, 12, "NONE")
		poi.Text:SetPoint("TOPLEFT", poi, "TOPLEFT", 2, 0)
		poi.Text:SetPoint("BOTTOMRIGHT", help, "BOTTOMLEFT", -2, 0)
		poi.Text:SetJustifyH("CENTER")
		poi.Text:SetText("")
		poi:Hide()
	end

	holder:Hide()

	PLUGIN:ResetLogs()
end

CONFIGS["SVAOW"] = {
	["enable"] = true
}

SuperVillain.Registry:NewScript(LoadWarVillain)
SuperVillain.Registry:NewPlugin(PLUGIN, "SVAOW", LoadOptions)