--[[ ############################################################################## _____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_ # ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__ # __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____ # ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____ # ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____ # _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____ # __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ # _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_# ___\///////////___________\///___________\/////////_____\///////////_# ############################################################################## 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) if not name then return end 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) elseif(class and colors) then 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); SVUI_AoWLogsClear:Show() 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:SwitchToLogs() if(not AoWLogs:IsShown()) then AoWLogs:Show() end self.TitleWindow:Clear(); self.SummaryWindow:Clear(); self.LogWindow:Clear(); self.TitleWindow:AddMessage(("Scanning %s"):format(ACTIVE_ZONE), 1, 1, 0); SVUI_AoWLogsClear:Show() 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); for _,data in pairs(EnemyCache) do if type(data) == "table" and data.name and data.class and data.race then local hex = ("%s - %s %s"):format(data.name, data.race, data.class) self.LogWindow:AddMessage(hex, data.colors.r, data.colors.g, data.colors.b); end end end function PLUGIN:SwitchToBG() if(self.InPVP) then if(AoWLogs:IsShown()) then AoWLogs:Hide() end else if(not AoWLogs:IsShown()) then AoWLogs:Show() end self.TitleWindow:Clear(); self.SummaryWindow:Clear(); self.LogWindow:Clear(); self.TitleWindow:AddMessage("Scanning Paused", 1, 0.1, 0); self.SummaryWindow:AddMessage(ACTIVE_ZONE, 1, 0.75, 0); SVUI_AoWLogsClear:Hide() self.LogWindow:AddMessage(" ", 1, 1, 1); self.LogWindow:AddMessage(" ", 1, 1, 1); self.LogWindow:AddMessage("The Enenmy Scanner Will Resume", 0.8, 0.8, 0.8); self.LogWindow:AddMessage("When You Leave This BattleGround", 0.8, 0.8, 0.8); end 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() 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() self.Scanning = true self:SwitchToLogs() 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") then PLUGIN:SwitchToBG() PLUGIN.Scanning = false if(not PLUGIN.InPVP) then PLUGIN:UpdateCommunicator() end 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_REGEN_ENABLED") then PLUGIN.HitBy = false; elseif(event == "COMBAT_LOG_EVENT_UNFILTERED") then PLUGIN:CombatLogScanner(...) else local inInstance, instanceType = IsInInstance() if(instanceType == "pvp") then PLUGIN.Scanning = false end if(event == "PLAYER_ENTERING_WORLD" or event == "UPDATE_BATTLEFIELD_SCORE") then PLUGIN:UpdateCommunicator() elseif(event == "PLAYER_TARGET_CHANGED") then if(instanceType ~= "pvp") then PLUGIN:TargetChanged() end elseif(event == "PLAYER_DEAD") then if(instanceType ~= "pvp") then PLUGIN:TheyGotMe() end else PLUGIN:UpdateZoneStatus() end 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", "SVUI_AoWLogsClear", 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, AoWLogs) summary:SetSpacing(4) summary:SetClampedToScreen(false) summary:SetFrameStrata("MEDIUM") summary:SetPoint("TOPLEFT", title, "BOTTOMLEFT",0,0) summary:SetPoint("BOTTOMRIGHT", title, "BOTTOMRIGHT",0,-20) 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)