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 tostring  = _G.tostring;
local tonumber  = _G.tonumber;
local tinsert   = _G.tinsert;
local string    = _G.string;
local math      = _G.math;
local bit       = _G.bit;
local table     = _G.table;
--[[ STRING METHODS ]]--
local lower, upper = string.lower, string.upper;
local find, format, len, split = string.find, string.format, string.len, string.split;
local match, sub, join = string.match, string.sub, string.join;
local gmatch, gsub = string.gmatch, string.gsub;
--[[ MATH METHODS ]]--
local abs, ceil, floor, round = math.abs, math.ceil, math.floor, math.round;  -- Basic
local fmod, modf, sqrt = math.fmod, math.modf, math.sqrt;   -- Algebra
local atan2, cos, deg, rad, sin = math.atan2, math.cos, math.deg, math.rad, math.sin;  -- Trigonometry
local parsefloat, huge, random = math.parsefloat, math.huge, math.random;  -- Uncommon
--[[ BINARY METHODS ]]--
local band, bor = bit.band, bit.bor;
--[[ TABLE METHODS ]]--
local tremove, tcopy, twipe, tsort, tconcat, tdump = table.remove, table.copy, table.wipe, table.sort, table.concat, table.dump;
--[[
##########################################################
GET ADDON DATA
##########################################################
]]--
local SVUINameSpace, SVUICore = ...;
--[[
##########################################################
LOCALS
##########################################################
]]--
local bld = select(2,GetBuildInfo());
local toonClass = select(2,UnitClass("player"));
local rez = GetCVar("gxResolution");
local gxHeight = tonumber(match(rez,"%d+x(%d+)"));
local gxWidth = tonumber(match(rez,"(%d+)x%d+"));
local NewHook = hooksecurefunc;
local version = GetAddOnMetadata(..., "Version");
--[[
##########################################################
BUILD ADDON OBJECTS
##########################################################
]]--
local SuperVillain = SVUI_LIB:SetObject(SVUINameSpace, version, true)
local L = SVUI_LOCALE:SetObject()

SVUICore[1] = SuperVillain;
SVUICore[2] = L;
--[[
##########################################################
CREATE GLOBAL NAMESPACE
##########################################################
]]--
_G[SVUINameSpace] = SVUICore;
--[[
##########################################################
SET MANY VARIABLES
##########################################################
]]--
local SVUISystemEventHandler = CreateFrame("Frame", "SVUISystemEventHandler")
local SVUIParent = CreateFrame("Frame", "SVUIParent", UIParent);
local StealthFrame = CreateFrame("Frame", nil, UIParent);
StealthFrame:Hide();
SVUIParent:SetFrameLevel(UIParent:GetFrameLevel());
SVUIParent:SetPoint("CENTER", UIParent, "CENTER");
SVUIParent:SetSize(UIParent:GetSize());

SuperVillain.db = {};
SuperVillain.fubar = function() return end
SuperVillain.Media = {};
SuperVillain.Filters = {};
SuperVillain.DisplayAudit = {};
SuperVillain.DynamicOptions = {};
SuperVillain.snaps = {};
SuperVillain.Dispellable = {};
SuperVillain.Options = { type="group", name="|cff339fffConfig-O-Matic|r", args={}, };
SuperVillain.Shared = LibStub("LibSharedMedia-3.0")
SuperVillain.class = toonClass;
SuperVillain.name = UnitName("player");
SuperVillain.realm = GetRealmName();
SuperVillain.build = tonumber(bld);
SuperVillain.guid = UnitGUID('player');
SuperVillain.mult = 1;
SuperVillain.ConfigurationMode = false;
SuperVillain.ClassRole = "";
SuperVillain.UIParent = SVUIParent;
SuperVillain.Cloaked = StealthFrame;
SuperVillain.snaps[#SuperVillain.snaps + 1] = SuperVillain.UIParent;
--[[
##########################################################
THE CLEANING LADY
##########################################################
]]--
-- local LemonPledge = 0;
-- local Consuela = CreateFrame("Frame")
-- Consuela:RegisterAllEvents()
-- Consuela:SetScript("OnEvent", function(self, event)
-- 	LemonPledge = LemonPledge + 1
-- 	if (InCombatLockdown() and LemonPledge > 25000) or (not InCombatLockdown() and LemonPledge > 10000) then
-- 		collectgarbage("collect")
-- 		LemonPledge = 0;
-- 	end
-- end)
--[[
##########################################################
DISPEL MECHANICS
##########################################################
]]--
local droodSpell1, droodSpell2 = GetSpellInfo(110309), GetSpellInfo(4987);
local RefClassRoles;
local RefMagicSpec;
do
	if(toonClass == "PRIEST") then
		RefClassRoles = {"C", "C", "C"}
		SuperVillain.Dispellable = {["Magic"] = true, ["Disease"] = true}
	elseif(toonClass == "WARLOCK") then
		RefClassRoles = {"C", "C", "C"}
	elseif(toonClass == "WARRIOR") then
		RefClassRoles = {"M", "M", "T"}
	elseif(toonClass == "HUNTER") then
		RefClassRoles = {"M", "M", "M"}
	elseif(toonClass == "ROGUE") then
		RefClassRoles = {"M", "M", "M"}
	elseif(toonClass == "MAGE") then
		RefClassRoles = {"C", "C", "C"}
		SuperVillain.Dispellable = {["Curse"] = true}
	elseif(toonClass == "DEATHKNIGHT") then
		RefClassRoles = {"T", "M", "M"}
	elseif(toonClass == "DRUID") then
		RefMagicSpec = 4
		RefClassRoles = {"C", "M", "T", "C"}
		SuperVillain.Dispellable = {["Curse"] = true, ["Poison"] = true}
	elseif(toonClass == "SHAMAN") then
		RefMagicSpec = 3
		RefClassRoles = {"C", "M", "C"}
		SuperVillain.Dispellable = {["Curse"] = true}
	elseif(toonClass == "MONK") then
		RefMagicSpec = 2
		RefClassRoles = {"T", "C", "M"}
		SuperVillain.Dispellable = {["Disease"] = true, ["Poison"] = true}
	elseif(toonClass == "PALADIN") then
		RefMagicSpec = 1
		RefClassRoles = {"C", "T", "M"}
		SuperVillain.Dispellable = {["Poison"] = true, ["Disease"] = true}
	end
end

local function GetTalentInfo(arg)
	if type(arg) == "number" then
		return arg == GetActiveSpecGroup();
	else
		return false;
	end
end

function SuperVillain:DefinePlayerRole()
	local spec = GetSpecialization()
	local role;
	if spec then
		if(self.CurrentSpec == spec) then return end
		role = RefClassRoles[spec]
		if role == "T" and UnitLevel("player") == MAX_PLAYER_LEVEL then
			local bonus, pvp = GetCombatRatingBonus(COMBAT_RATING_RESILIENCE_PLAYER_DAMAGE_TAKEN), false;
			if bonus > GetDodgeChance() and bonus > GetParryChance() then
				role = "M"
			end
		end
		self.CurrentSpec = spec
	else
		local intellect = select(2, UnitStat("player", 4))
		local agility = select(2, UnitStat("player", 2))
		local baseAP, posAP, negAP = UnitAttackPower("player")
		local totalAP = baseAP  +  posAP  +  negAP;
		if totalAP > intellect or agility > intellect then
			role = "M"
		else
			role = "C"
		end
	end
	if self.ClassRole ~= role then
		self.ClassRole = role;
		self.RoleChangedCallback()
	end
	if RefMagicSpec then
		if(GetTalentInfo(RefMagicSpec)) then
			self.Dispellable["Magic"] = true
		elseif(self.Dispellable["Magic"]) then
			self.Dispellable["Magic"] = nil
		end
	end
	self.RoleIsSet = true
end
--[[
##########################################################
SYSTEM FUNCTIONS
##########################################################
]]--
function SuperVillain:TableSplice(targetTable, mergeTable)
    if type(targetTable) ~= "table" then targetTable = {} end

    if type(mergeTable) == 'table' then
        for key,val in pairs(mergeTable) do
            if type(val) == "table" then
                val = self:TableSplice(targetTable[key], val)
            end
            targetTable[key] = val
        end
    end
    return targetTable
end

function SuperVillain:StaticPopup_Show(arg)
	if arg == "ADDON_ACTION_FORBIDDEN" then
		StaticPopup_Hide(arg)
	end
end

function SuperVillain:ResetAllUI(confirmed)
	if InCombatLockdown()then
		SuperVillain:AddonMessage(ERR_NOT_IN_COMBAT)
		return
	end
	if(not confirmed) then
		self:StaticPopup_Show('RESET_UI_CHECK')
		return
	end
	self:ResetInstallation()
end

function SuperVillain:ResetUI(confirmed)
	if InCombatLockdown()then
		SuperVillain:AddonMessage(ERR_NOT_IN_COMBAT)
		return
	end
	if(not confirmed) then
		self:StaticPopup_Show('RESETMOVERS_CHECK')
		return
	end
	self:ResetMovables()
end

function SuperVillain:ToggleConfig()
	if InCombatLockdown() then
		SuperVillain:AddonMessage(ERR_NOT_IN_COMBAT)
		SVUISystemEventHandler:RegisterEvent('PLAYER_REGEN_ENABLED')
		return
	end
	if not IsAddOnLoaded("SVUI_ConfigOMatic") then
		local _,_,_,_,_,state = GetAddOnInfo("SVUI_ConfigOMatic")
		if state ~= "MISSING" and state ~= "DISABLED" then
			LoadAddOn("SVUI_ConfigOMatic")
			local config_version = GetAddOnMetadata("SVUI_ConfigOMatic","Version")
			if(tonumber(config_version) < 4) then
				self:StaticPopup_Show("CLIENT_UPDATE_REQUEST")
			end
		else
			SuperVillain:AddonMessage("|cffff0000Error -- Addon 'SVUI_ConfigOMatic' not found or is disabled.|r")
			return
		end
	end
	local aceConfig = LibStub("AceConfigDialog-3.0")
	local switch = not aceConfig.OpenFrames[SVUINameSpace] and "Open" or "Close"
	aceConfig[switch](aceConfig,SVUINameSpace)
	GameTooltip:Hide()
end

function SuperVillain:TaintHandler(taint, sourceName, sourceFunc)
	if GetCVarBool('scriptErrors') ~= 1 then return end
	ScriptErrorsFrame_OnError(L["%s: %s has lost it's damn mind and is destroying '%s'."]:format(taint, sourceName or "elements", sourceFunc or "functions"),false)
end
--[[
##########################################################
REGISTRY ADDON_LOADED EVENT AND OPTIONS
##########################################################
]]--
SuperVillain.Registry.EventHandler = CreateFrame("Frame", nil)
SuperVillain.Registry.EventHandler.__owner = Registry
SuperVillain.Registry.EventHandler:RegisterEvent("ADDON_LOADED")
SuperVillain.Registry.EventHandler:SetScript("OnEvent", addonEvent)
SuperVillain.Registry:NewPlugin("SuperVillain Plugins", function()
    SuperVillain.Options.args.plugins = {
        order = -10,
        type = "group",
        name = INFO_NAME,
        guiInline = false,
        args = {
            pluginheader = {
                order = 1,
                type = "header",
                name = format(INFO_HEADER, PLUGIN_VERSION),
            },
            pluginlist = {
                order = 2,
                type = "description",
                name = SuperVillain.Registry:FetchPlugins(),
            },
        }
    }
end)
--[[
##########################################################
ANIMATION CLASS
##########################################################
]]--
local FlickerAlpha = {0.2,0.15,0.1,0.15,0.2,0.15,0.1,0.15}
local Animate = {};
--[[ HANDLERS ]]--

local Anim_OnShow = function(self)
	if not self.anim:IsPlaying() then
		self.anim:Play()
	end
end

local Anim_OnHide = function(self)
	self.anim:Finish()
end

local Anim_OnPlay = function(self)
	local parent = self.parent
	parent:SetAlpha(1)
	if self.hideOnFinished and not parent:IsShown() then
		parent:Show()
	end
end

local Anim_OnStop = function(self)
	local parent = self.parent
	if self.fadeOnFinished then
		parent:SetAlpha(0)
	else
		parent:SetAlpha(1)
	end
	if self.hideOnFinished and parent:IsShown() then
		parent:Hide()
	end
	if self.savedFrameLevel then
		parent:SetScale(1)
		parent:SetFrameLevel(self.savedFrameLevel)
	end
end

local Anim_OnFinished = function(self)
	local parent = self.parent
	self:Stop()
end

local Sprite_OnUpdate = function(self)
	local order = self:GetOrder()
	local parent = self.parent
	local left, right;
	if(self.isFadeFrame) then
		parent:SetAlpha(0)
		return
	end
	left = (order - 1) * 0.25;
	right = left + 0.25;
	parent:SetTexCoord(left,right,0,1)
	if parent.overlay then
		parent.overlay:SetTexCoord(left,right,0,1)
		parent.overlay:SetVertexColor(1,1,1,FlickerAlpha[order])
	end
end

local SmallSprite_OnUpdate = function(self)
	local order = self:GetOrder()
	local parent = self.parent
	local left, right;
	if(self.isFadeFrame) then
		parent:SetAlpha(0)
		return
	end
	left = (order - 1) * 0.125;
	right = left + 0.125;
	parent:SetTexCoord(left,right,0,1)
	if parent.overlay then
		parent.overlay:SetTexCoord(left,right,0,1)
		parent.overlay:SetVertexColor(1,1,1,FlickerAlpha[order])
	end
end

local PulseIn_OnUpdate = function(self)
	local parent = self.parent
	local step = self:GetProgress()
	if(parent.savedFrameLevel) then
		parent:SetFrameLevel(128)
	end
	parent:SetScale(1 + (1.05 * step))
end

local PulseOut_OnUpdate = function(self)
	local parent = self.parent
	local step = self:GetProgress()
	if(parent.savedFrameLevel) then
		parent:SetFrameLevel(128)
	end
	parent:SetScale(1 + (1.05 * (1 - step)))
end

local Slide_OnUpdate = function(self)
	local parent = self.parent
	local step = self:GetProgress()
	parent:SetScale(1 + (1.05 * step))
end

local Slide_OnPlay = function(self)
	local parent = self.parent
	parent:SetScale(0.01)
	parent:SetAlpha(1)
end

local Slide_FadeStart = function(self)
	local parent = self.parent
	UIFrameFadeOut(parent, 0.3, 1, 0)
end

local Slide_FadeStop = function(self)
	self.parent:SetAlpha(0)
end

--[[ HELPER FUNCTION ]]--

local function SetNewAnimation(frame, animType, subType)
	local anim = frame:CreateAnimation(animType, subType)
	anim.parent = frame.parent
	return anim
end

--[[ ANIMATION CLASS METHODS ]]--

function Animate:SetTemplate(frame, animType, hideOnFinished, speed, special, scriptToParent)
	if not animType then return end

	frame.anim = frame:CreateAnimationGroup(animType)
	frame.anim.parent = frame;
	frame.anim.hideOnFinished = hideOnFinished
	if animType ~= 'Flash'then
		frame.anim:SetScript("OnPlay", Anim_OnPlay)
		frame.anim:SetScript("OnFinished", Anim_OnFinished)
		frame.anim:SetScript("OnStop", Anim_OnStop)
	end

	if scriptToParent then
		local frameParent = frame:GetParent();
		if(frameParent.SetScript) then
			frameParent.anim = frame.anim;
			frameParent:SetScript("OnShow", Anim_OnShow)
			frameParent:SetScript("OnHide", Anim_OnHide)
		end
	elseif(frame.SetScript) then
		frame:SetScript("OnShow", Anim_OnShow)
		frame:SetScript("OnHide", Anim_OnHide)
	end

	if animType == 'Flash'then
		frame.anim.fadeOnFinished = true
		if not speed then speed = 0.33 end

		frame.anim[1] = SetNewAnimation(frame.anim, "ALPHA", "FadeIn")
		frame.anim[1]:SetChange(1)
		frame.anim[1]:SetOrder(2)
		frame.anim[1]:SetDuration(speed)

		frame.anim[2] = SetNewAnimation(frame.anim, "ALPHA","FadeOut")
		frame.anim[2]:SetChange(-1)
		frame.anim[2]:SetOrder(1)
		frame.anim[2]:SetDuration(speed)

		if special then
			frame.anim:SetLooping("REPEAT")
		end
	elseif animType == 'Orbit' then
		frame.anim[1] = SetNewAnimation(frame.anim, "Rotation")
		if special then
			frame.anim[1]:SetDegrees(-360)
		else
			frame.anim[1]:SetDegrees(360)
		end
		frame.anim[1]:SetDuration(speed)
		frame.anim:Play()
		frame.anim:SetLooping("REPEAT")
	elseif animType == 'Sprite' then
		frame.anim[1] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[1]:SetOrder(1)
		frame.anim[1]:SetDuration(speed)
		frame.anim[1]:SetScript("OnUpdate", Sprite_OnUpdate)

		frame.anim[2] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[2]:SetOrder(2)
		frame.anim[2]:SetDuration(speed)
		frame.anim[2]:SetScript("OnUpdate", Sprite_OnUpdate)

		frame.anim[3] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[3]:SetOrder(3)
		frame.anim[3]:SetDuration(speed)
		frame.anim[3]:SetScript("OnUpdate", Sprite_OnUpdate)

		frame.anim[4] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[4]:SetOrder(4)
		frame.anim[4]:SetDuration(speed)
		frame.anim[4]:SetScript("OnUpdate", Sprite_OnUpdate)

		if special then
			frame.anim[5] = SetNewAnimation(frame.anim, "Translation")
			frame.anim[5]:SetOrder(5)
			frame.anim[5]:SetDuration(special)
			frame.anim[5].isFadeFrame = true;
			frame.anim[5]:SetScript("OnUpdate", Sprite_OnUpdate)
		end

		frame.anim:SetLooping("REPEAT")
	elseif animType == 'SmallSprite' then
		frame.anim[1] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[1]:SetOrder(1)
		frame.anim[1]:SetDuration(speed)
		frame.anim[1]:SetScript("OnUpdate", SmallSprite_OnUpdate)

		frame.anim[2] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[2]:SetOrder(2)
		frame.anim[2]:SetDuration(speed)
		frame.anim[2]:SetScript("OnUpdate", SmallSprite_OnUpdate)

		frame.anim[3] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[3]:SetOrder(3)
		frame.anim[3]:SetDuration(speed)
		frame.anim[3]:SetScript("OnUpdate", SmallSprite_OnUpdate)

		frame.anim[4] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[4]:SetOrder(4)
		frame.anim[4]:SetDuration(speed)
		frame.anim[4]:SetScript("OnUpdate", SmallSprite_OnUpdate)

		frame.anim[5] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[5]:SetOrder(5)
		frame.anim[5]:SetDuration(speed)
		frame.anim[5]:SetScript("OnUpdate", SmallSprite_OnUpdate)

		frame.anim[6] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[6]:SetOrder(6)
		frame.anim[6]:SetDuration(speed)
		frame.anim[6]:SetScript("OnUpdate", SmallSprite_OnUpdate)

		frame.anim[7] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[7]:SetOrder(7)
		frame.anim[7]:SetDuration(speed)
		frame.anim[7]:SetScript("OnUpdate", SmallSprite_OnUpdate)

		frame.anim[8] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[8]:SetOrder(8)
		frame.anim[8]:SetDuration(speed)
		frame.anim[8]:SetScript("OnUpdate", SmallSprite_OnUpdate)

		if special then
			frame.anim[9] = SetNewAnimation(frame.anim, "Translation")
			frame.anim[9]:SetOrder(9)
			frame.anim[9]:SetDuration(special)
			frame.anim[9].isFadeFrame = true;
			frame.anim[9]:SetScript("OnUpdate", Sprite_OnUpdate)
		end

		frame.anim:SetLooping("REPEAT")
	elseif animType == 'Pulse' then
		frame.anim.savedFrameLevel = frame:GetFrameLevel()

		frame.anim[1] = SetNewAnimation(frame.anim)
		frame.anim[1]:SetDuration(0.2)
		frame.anim[1]:SetEndDelay(0.1)
		frame.anim[1]:SetOrder(1)
		frame.anim[1]:SetScript("OnUpdate", PulseIn_OnUpdate)

		frame.anim[2] = SetNewAnimation(frame.anim)
		frame.anim[2]:SetDuration(0.6)
		frame.anim[2]:SetOrder(2)
		frame.anim[2]:SetScript("OnUpdate", PulseOut_OnUpdate)
	end
end

--[[ ROTATE AND WOBBLE (kinda like twerking i guess...) ]]--

function Animate:Orbit(frame, speed, reversed, hideOnFinished)
	if not frame then return end
	if not speed then speed = 1 end
	self:SetTemplate(frame, 'Orbit', hideOnFinished, speed, reversed)
end

function Animate:Pulse(frame, hideOnFinished)
	if not frame then return end
	self:SetTemplate(frame, 'Pulse', hideOnFinished)
end

--[[ ANIMATED SPRITES ]]--

function Animate:Sprite(frame, speed, fadeTime, scriptToParent)
	if not frame then return end
	speed = speed or 0.08;
	self:SetTemplate(frame, 'Sprite', false, speed, fadeTime, scriptToParent)
end

function Animate:SmallSprite(frame, speed, fadeTime, scriptToParent)
	if not frame then return end
	speed = speed or 0.08;
	self:SetTemplate(frame, 'SmallSprite', false, speed, fadeTime, scriptToParent)
end

function Animate:StopSprite(frame)
	if not frame then return end
	frame.anim:Finish()
end

--[[ FLASHING ]]--

function Animate:Flash(frame, speed, looped)
	if not frame.anim then
		Animate:SetTemplate(frame, 'Flash', false, speed, looped)
	end
	if not frame.anim:IsPlaying() then
		frame.anim:Play()
	end
end

function Animate:StopFlash(frame)
	if not frame.anim then return end
	frame.anim:Finish()
	frame.anim:Stop()
end

--[[ SLIDING ]]--

function Animate:Slide(frame, xDirection, yDirection, bounce)
	if(not frame or (frame and frame.anim)) then return end

	frame.anim = frame:CreateAnimationGroup("Slide")
	frame.anim.hideOnFinished = true;
	frame.anim.parent = frame;
	frame.anim:SetScript("OnPlay", Anim_OnPlay)
	frame.anim:SetScript("OnFinished", Anim_OnFinished)
	frame.anim:SetScript("OnStop", Anim_OnStop)

	frame.anim[1] = SetNewAnimation(frame.anim, "Translation")
	frame.anim[1]:SetDuration(0)
	frame.anim[1]:SetOrder(1)

	frame.anim[2] = SetNewAnimation(frame.anim, "Translation")
	frame.anim[2]:SetDuration(0.3)
	frame.anim[2]:SetOrder(2)
	frame.anim[2]:SetSmoothing("OUT")

	if bounce then
		frame.anim[3] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[3]:SetDuration(0.5)
		frame.anim[3]:SetOrder(3)

		frame.anim[4] = SetNewAnimation(frame.anim, "Translation")
		frame.anim[4]:SetDuration(0.3)
		frame.anim[4]:SetOrder(4)
		frame.anim[4]:SetSmoothing("IN")
		frame.anim[4]:SetOffset(xDirection, yDirection)
	end
end

function Animate:RandomSlide(frame, raised)
	if not frame then return end
	if raised then
		frame:SetFrameLevel(30)
	else
		frame:SetFrameLevel(20)
	end
	frame:SetPoint("CENTER", SuperVillain.UIParent, "CENTER", 0, -150)

	frame.anim = frame:CreateAnimationGroup("RandomSlide")
	frame.anim.parent = frame;
	frame.anim[1] = SetNewAnimation(frame.anim, "Translation")
	frame.anim[1]:SetOrder(1)
	frame.anim[1]:SetDuration(0.1)
	frame.anim[1]:SetScript("OnUpdate", Slide_OnUpdate)
	frame.anim[1]:SetScript("OnPlay", Slide_OnPlay)

	frame.anim[2] = SetNewAnimation(frame.anim, "Translation")
	frame.anim[2]:SetOrder(2)
	frame.anim[2]:SetDuration(1)

	frame.anim[3] = SetNewAnimation(frame.anim, "Translation")
	frame.anim[3]:SetOrder(3)
	frame.anim[3]:SetDuration(0.3)
	frame.anim[3]:SetSmoothing("OUT")
	frame.anim[3]:SetScript("OnPlay", Slide_FadeStart)
	frame.anim[3]:SetScript("OnStop", Slide_FadeStop)

	frame.anim:SetScript("OnFinished", Slide_FadeStop)
end

function Animate:SlideIn(frame)
	if not frame.anim then return end
	frame:Show()
	frame.anim:Play()
end

function Animate:SlideOut(frame)
	if not frame.anim then return end
	frame.anim:Finish()
	frame.anim:Stop()
end

SuperVillain.Animate = Animate;
--[[
##########################################################
SYSTEM UPDATES
##########################################################
]]--
function SuperVillain:VersionCheck()
	local minimumVersion = 4.06;
	local installedVersion = SVUI_Profile.SAFEDATA.install_version
	if(installedVersion) then
		if(type(installedVersion) == "string") then
			installedVersion = tonumber(SVUI_Profile.SAFEDATA.install_version)
		end
		if(type(installedVersion) == "number" and installedVersion < minimumVersion) then
			self:Install(true)
		end
	else
		self:Install(true)
	end
end

function SuperVillain:RefreshEverything(bypass)
	self:RefreshAllSystemMedia();

	SuperVillain.UIParent:Hide();

	self:SetSVMovablesPositions();
	self.Registry:Update('SVUnit');
	self.Registry:UpdateAll();

	SuperVillain.UIParent:Show();

	collectgarbage("collect");

	if not bypass then
		self:VersionCheck()
	end
end
--[[
##########################################################
SVUI LOAD PROCESS
##########################################################
]]--
local function PreLoad(self)
	--[[ BEGIN DEPRECATED ]]--
    if SVUI_DATA then SVUI_DATA = nil end
    if SVUI_SAFE_DATA then SVUI_SAFE_DATA = nil end
    if SVUI_TRACKER then SVUI_TRACKER = nil end
    if SVUI_ENEMIES then SVUI_ENEMIES = nil end
    if SVUI_JOURNAL then SVUI_JOURNAL = nil end
    if SVUI_CHARACTER_LOG then SVUI_CHARACTER_LOG = nil end
    if SVUI_MOVED_FRAMES then SVUI_MOVED_FRAMES = nil end
    if SVUI_SystemData then SVUI_SystemData = nil end
    if SVUI_ProfileData then SVUI_ProfileData = nil end
    --[[ END DEPRECATED ]]--

	if not SVUI_Global then SVUI_Global = {} end
    if not SVUI_Global["profiles"] then SVUI_Global["profiles"] = {} end

    if SVUI_Global["gold"] then SVUI_Global["gold"] = nil end
    if SVUI_Global["profileKeys"] then SVUI_Global["profileKeys"] = nil end

    if not SVUI_Profile then SVUI_Profile = {} end
    if not SVUI_Profile.SAFEDATA then SVUI_Profile.SAFEDATA = {} end
    if(SVUI_Profile.SAFEDATA.install_complete) then SVUI_Profile.SAFEDATA.install_complete = nil end

    if SVUI_Filters then SVUI_Filters = nil end
    if not SVUI_AuraFilters then SVUI_AuraFilters = {} end
    if not SVUI_AuraWatch then SVUI_AuraWatch = {} end

    if not SVUI_Cache then SVUI_Cache = {} end
    if not SVUI_Cache["Dock"] then SVUI_Cache["Dock"] = {} end
    if not SVUI_Cache["Mentalo"] then SVUI_Cache["Mentalo"] = {} end
    if(not SVUI_Cache["screenheight"] or (SVUI_Cache["screenheight"] and type(SVUI_Cache["screenheight"]) ~= "number")) then
    	SVUI_Cache["screenheight"] = gxHeight
    end
    if(not SVUI_Cache["screenwidth"] or (SVUI_Cache["screenwidth"] and type(SVUI_Cache["screenwidth"]) ~= "number")) then
    	SVUI_Cache["screenwidth"] = gxWidth
    end

    --[[ MORE DEPRECATED ]]--
    if SVUI_Cache["Mentalo"]["Blizzard"] then SVUI_Cache["Mentalo"]["Blizzard"] = nil end
    if SVUI_Cache["Mentalo"]["UI"] then SVUI_Cache["Mentalo"]["UI"] = nil end
    --[[ END DEPRECATED ]]--

    self:SetDatabaseObjects(true)

	self:UIScale();
	self:RefreshSystemFonts();
	self:LoadSystemAlerts();
	self.Registry:Lights();
	SVUISystemEventHandler:RegisterEvent('PLAYER_REGEN_DISABLED');
end

local function FullLoad(self)
	self:SetDatabaseObjects()
	self:UIScale("PLAYER_LOGIN");
	self.Registry:Camera();
	self.Registry:Action();
	self:DefinePlayerRole();
	self:LoadMovables();
	self:SetSVMovablesPositions();
	self.CoreEnabled = true;

	self:VersionCheck()

	self:RefreshAllSystemMedia();
	NewHook("StaticPopup_Show", self.StaticPopup_Show)

	SVUISystemEventHandler:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED");
	SVUISystemEventHandler:RegisterEvent("PLAYER_TALENT_UPDATE");
	SVUISystemEventHandler:RegisterEvent("CHARACTER_POINTS_CHANGED");
	SVUISystemEventHandler:RegisterEvent("UNIT_INVENTORY_CHANGED");
	SVUISystemEventHandler:RegisterEvent("UPDATE_BONUS_ACTIONBAR");
	SVUISystemEventHandler:RegisterEvent("UI_SCALE_CHANGED");
	SVUISystemEventHandler:RegisterEvent("PLAYER_ENTERING_WORLD");
	SVUISystemEventHandler:RegisterEvent("PET_BATTLE_CLOSE");
	SVUISystemEventHandler:RegisterEvent("PET_BATTLE_OPENING_START");
	SVUISystemEventHandler:RegisterEvent("ADDON_ACTION_BLOCKED");
	SVUISystemEventHandler:RegisterEvent("ADDON_ACTION_FORBIDDEN");
	SVUISystemEventHandler:RegisterEvent("SPELLS_CHANGED");

	self.Registry:Update("SVMap");
	self.Registry:Update("SVUnit", true);

	_G["SVUI_Mentalo"]:SetFixedPanelTemplate("Component")
	_G["SVUI_Mentalo"]:SetPanelColor("yellow")
	_G["SVUI_MentaloPrecision"]:SetPanelTemplate("Transparent")

	if self.db.system.loginmessage then
		self:AddonMessage(format(L["LOGIN_MSG"], "|cffffcc1a", "|cffff801a", self.version));
	end
end

SVUISystemEventHandler:RegisterEvent("ADDON_LOADED")
SVUISystemEventHandler:RegisterEvent("PLAYER_LOGIN")
--[[
##########################################################
EVENT HANDLER
##########################################################
]]--
local SVUISystem_OnEvent = function(self, event, arg, ...)
	if(event == "ADDON_LOADED"  and arg ~= "Blizzard_DebugTools") then
		PreLoad(SuperVillain)
		self:UnregisterEvent("ADDON_LOADED")
	elseif(event == "PLAYER_LOGIN" and IsLoggedIn()) then
		FullLoad(SuperVillain)
		self:UnregisterEvent("PLAYER_LOGIN")
	elseif(event == "ACTIVE_TALENT_GROUP_CHANGED" or event == "PLAYER_TALENT_UPDATE" or event == "CHARACTER_POINTS_CHANGED" or event == "UNIT_INVENTORY_CHANGED" or event == "UPDATE_BONUS_ACTIONBAR") then
		SuperVillain:DefinePlayerRole()
	elseif(event == "UI_SCALE_CHANGED") then
		SuperVillain:UIScale("UI_SCALE_CHANGED")
	elseif(event == "PLAYER_ENTERING_WORLD") then
		if(not SuperVillain.RoleIsSet) then
			SuperVillain:DefinePlayerRole()
		end
		if(not SuperVillain.MediaInitialized) then
			SuperVillain:RefreshAllSystemMedia()
		end
		local a,b = IsInInstance()
		if(b == "pvp") then
			SuperVillain.BGTimer = SuperVillain:ExecuteLoop(RequestBattlefieldScoreData, 5)
		elseif(SuperVillain.BGTimer) then
			SuperVillain:RemoveLoop(SuperVillain.BGTimer)
			SuperVillain.BGTimer = nil
		end
		collectgarbage("collect")
	elseif(event == "SPELLS_CHANGED") then
		if (toonClass ~= "DRUID") then
			self:UnregisterEvent("SPELLS_CHANGED")
			return
		end
		if GetSpellInfo(droodSpell1) == droodSpell2 then
			SuperVillain.Dispellable["Disease"] = true
		elseif(SuperVillain.Dispellable["Disease"]) then
			SuperVillain.Dispellable["Disease"] = nil
		end
	elseif(event == "PET_BATTLE_CLOSE") then
		SuperVillain:PushDisplayAudit()
	elseif(event == "PET_BATTLE_OPENING_START") then
		SuperVillain:FlushDisplayAudit()
	elseif(event == "ADDON_ACTION_BLOCKED" or event == "ADDON_ACTION_FORBIDDEN") then
		SuperVillain:TaintHandler(arg, ...)
	elseif(event == "PLAYER_REGEN_DISABLED") then
		local forceClosed = false;
		if IsAddOnLoaded("SVUI_ConfigOMatic") then
			local aceConfig=LibStub("AceConfigDialog-3.0")
			if aceConfig.OpenFrames[SVUINameSpace] then
				self:RegisterEvent('PLAYER_REGEN_ENABLED')
				aceConfig:Close(SVUINameSpace)
				forceClosed = true
			end
		end
		if SuperVillain.MentaloFrames then
			for frame,_ in pairs(SuperVillain.MentaloFrames) do
				if _G[frame] and _G[frame]:IsShown() then
					forceClosed = true;
					_G[frame]:Hide()
				end
			end
		end
		if(HenchmenFrameModel and HenchmenFrame and HenchmenFrame:IsShown()) then
			HenchmenFrame:Hide()
			HenchmenFrameBG:Hide()
			forceClosed = true;
		end
		if forceClosed == true then
			SuperVillain:AddonMessage(ERR_NOT_IN_COMBAT)
		end
	elseif(event == "PLAYER_REGEN_ENABLED") then
		SuperVillain:ToggleConfig()
		self:UnregisterEvent('PLAYER_REGEN_ENABLED')
	end
end
SVUISystemEventHandler:SetScript("OnEvent", SVUISystem_OnEvent)