diff --git a/ConRO.toc b/ConRO.toc
index 088fc88..ebefaa3 100644
--- a/ConRO.toc
+++ b/ConRO.toc
@@ -1,6 +1,6 @@
## Title:-|cffFFFFFFConRO|r- Conflict Rotation Optimizer
## Notes: Rotation helper framework.
-## Version: 11.0.11
+## Version: 11.0.12
## Author: Vae
## Interface: 110007
## SavedVariables: ConROPreferences
@@ -9,7 +9,6 @@
# Libraries
Libs\Libs.xml
-Libs\LibDualSpec-1.0\LibDualSpec-1.0.lua
core.lua
buttons.lua
diff --git a/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua b/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua
deleted file mode 100644
index 46d6448..0000000
--- a/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua
+++ /dev/null
@@ -1,584 +0,0 @@
---@curseforge-project-slug: libdbicon-1-0@
------------------------------------------------------------------------
--- LibDBIcon-1.0
---
--- Allows addons to easily create a lightweight minimap icon as an alternative to heavier LDB displays.
---
-
-local DBICON10 = "LibDBIcon-1.0"
-local DBICON10_MINOR = 55 -- Bump on changes
-if not LibStub then error(DBICON10 .. " requires LibStub.") end
-local ldb = LibStub("LibDataBroker-1.1", true)
-if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end
-local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR)
-if not lib then return end
-
-lib.objects = lib.objects or {}
-lib.callbackRegistered = lib.callbackRegistered or nil
-lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
-lib.radius = lib.radius or 5
-local next, Minimap, CreateFrame, AddonCompartmentFrame = next, Minimap, CreateFrame, AddonCompartmentFrame
-lib.tooltip = lib.tooltip or CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, "GameTooltipTemplate")
-local isDraggingButton = false
-
-function lib:IconCallback(event, name, key, value)
- if lib.objects[name] then
- if key == "icon" then
- lib.objects[name].icon:SetTexture(value)
- if lib:IsButtonInCompartment(name) and lib:IsButtonCompartmentAvailable() then
- local addonList = AddonCompartmentFrame.registeredAddons
- for i =1, #addonList do
- if addonList[i].text == name then
- addonList[i].icon = value
- return
- end
- end
- end
- elseif key == "iconCoords" then
- lib.objects[name].icon:UpdateCoord()
- elseif key == "iconR" then
- local _, g, b = lib.objects[name].icon:GetVertexColor()
- lib.objects[name].icon:SetVertexColor(value, g, b)
- elseif key == "iconG" then
- local r, _, b = lib.objects[name].icon:GetVertexColor()
- lib.objects[name].icon:SetVertexColor(r, value, b)
- elseif key == "iconB" then
- local r, g = lib.objects[name].icon:GetVertexColor()
- lib.objects[name].icon:SetVertexColor(r, g, value)
- end
- end
-end
-if not lib.callbackRegistered then
- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback")
- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback")
- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconR", "IconCallback")
- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconG", "IconCallback")
- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconB", "IconCallback")
- lib.callbackRegistered = true
-end
-
-local function getAnchors(frame)
- local x, y = frame:GetCenter()
- if not x or not y then return "CENTER" end
- local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
- local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
- return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
-end
-
-local function onEnter(self)
- if isDraggingButton then return end
-
- for _, button in next, lib.objects do
- if button.showOnMouseover then
- button.fadeOut:Stop()
- button:SetAlpha(1)
- end
- end
-
- local obj = self.dataObject
- if obj.OnTooltipShow then
- lib.tooltip:SetOwner(self, "ANCHOR_NONE")
- lib.tooltip:SetPoint(getAnchors(self))
- obj.OnTooltipShow(lib.tooltip)
- lib.tooltip:Show()
- elseif obj.OnEnter then
- obj.OnEnter(self)
- end
-end
-
-local function onLeave(self)
- lib.tooltip:Hide()
-
- if not isDraggingButton then
- for _, button in next, lib.objects do
- if button.showOnMouseover then
- button.fadeOut:Play()
- end
- end
- end
-
- local obj = self.dataObject
- if obj.OnLeave then
- obj.OnLeave(self)
- end
-end
-
-local function onEnterCompartment(self, menu)
- local buttonName = menu.text
- local object = lib.objects[buttonName]
- if object and object.dataObject then
- if object.dataObject.OnTooltipShow then
- lib.tooltip:SetOwner(self, "ANCHOR_NONE")
- lib.tooltip:SetPoint(getAnchors(self))
- object.dataObject.OnTooltipShow(lib.tooltip)
- lib.tooltip:Show()
- elseif object.dataObject.OnEnter then
- object.dataObject.OnEnter(self)
- end
- end
-end
-
-local function onLeaveCompartment(self, menu)
- lib.tooltip:Hide()
-
- local buttonName = menu.text
- local object = lib.objects[buttonName]
- if object and object.dataObject then
- if object.dataObject.OnLeave then
- object.dataObject.OnLeave(self)
- end
- end
-end
-
---------------------------------------------------------------------------------
-
-local onDragStart, updatePosition
-
-do
- local minimapShapes = {
- ["ROUND"] = {true, true, true, true},
- ["SQUARE"] = {false, false, false, false},
- ["CORNER-TOPLEFT"] = {false, false, false, true},
- ["CORNER-TOPRIGHT"] = {false, false, true, false},
- ["CORNER-BOTTOMLEFT"] = {false, true, false, false},
- ["CORNER-BOTTOMRIGHT"] = {true, false, false, false},
- ["SIDE-LEFT"] = {false, true, false, true},
- ["SIDE-RIGHT"] = {true, false, true, false},
- ["SIDE-TOP"] = {false, false, true, true},
- ["SIDE-BOTTOM"] = {true, true, false, false},
- ["TRICORNER-TOPLEFT"] = {false, true, true, true},
- ["TRICORNER-TOPRIGHT"] = {true, false, true, true},
- ["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
- ["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false},
- }
-
- local rad, cos, sin, sqrt, max, min = math.rad, math.cos, math.sin, math.sqrt, math.max, math.min
- function updatePosition(button, position)
- local angle = rad(position or 225)
- local x, y, q = cos(angle), sin(angle), 1
- if x < 0 then q = q + 1 end
- if y > 0 then q = q + 2 end
- local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
- local quadTable = minimapShapes[minimapShape]
- local w = (Minimap:GetWidth() / 2) + lib.radius
- local h = (Minimap:GetHeight() / 2) + lib.radius
- if quadTable[q] then
- x, y = x*w, y*h
- else
- local diagRadiusW = sqrt(2*(w)^2)-10
- local diagRadiusH = sqrt(2*(h)^2)-10
- x = max(-w, min(x*diagRadiusW, w))
- y = max(-h, min(y*diagRadiusH, h))
- end
- button:SetPoint("CENTER", Minimap, "CENTER", x, y)
- end
-end
-
-local function onClick(self, b)
- if self.dataObject.OnClick then
- self.dataObject.OnClick(self, b)
- end
-end
-
-local function onMouseDown(self)
- self.isMouseDown = true
- self.icon:UpdateCoord()
-end
-
-local function onMouseUp(self)
- self.isMouseDown = false
- self.icon:UpdateCoord()
-end
-
-do
- local deg, atan2 = math.deg, math.atan2
- local function onUpdate(self)
- local mx, my = Minimap:GetCenter()
- local px, py = GetCursorPosition()
- local scale = Minimap:GetEffectiveScale()
- px, py = px / scale, py / scale
- local pos = 225
- if self.db then
- pos = deg(atan2(py - my, px - mx)) % 360
- self.db.minimapPos = pos
- else
- pos = deg(atan2(py - my, px - mx)) % 360
- self.minimapPos = pos
- end
- updatePosition(self, pos)
- end
-
- function onDragStart(self)
- self:LockHighlight()
- self.isMouseDown = true
- self.icon:UpdateCoord()
- self:SetScript("OnUpdate", onUpdate)
- isDraggingButton = true
- lib.tooltip:Hide()
- for _, button in next, lib.objects do
- if button.showOnMouseover then
- button.fadeOut:Stop()
- button:SetAlpha(1)
- end
- end
- end
-end
-
-local function onDragStop(self)
- self:SetScript("OnUpdate", nil)
- self.isMouseDown = false
- self.icon:UpdateCoord()
- self:UnlockHighlight()
- isDraggingButton = false
- for _, button in next, lib.objects do
- if button.showOnMouseover then
- button.fadeOut:Play()
- end
- end
-end
-
-local defaultCoords = {0, 1, 0, 1}
-local function updateCoord(self)
- local coords = self:GetParent().dataObject.iconCoords or defaultCoords
- local deltaX, deltaY = 0, 0
- if not self:GetParent().isMouseDown then
- deltaX = (coords[2] - coords[1]) * 0.05
- deltaY = (coords[4] - coords[3]) * 0.05
- end
- self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY)
-end
-
-local function createButton(name, object, db, customCompartmentIcon)
- local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap)
- button.dataObject = object
- button.db = db
- button:SetFrameStrata("MEDIUM")
- button:SetFixedFrameStrata(true)
- button:SetFrameLevel(8)
- button:SetFixedFrameLevel(true)
- button:SetSize(31, 31)
- button:RegisterForClicks("anyUp")
- button:RegisterForDrag("LeftButton")
- button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight"
- if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
- local overlay = button:CreateTexture(nil, "OVERLAY")
- overlay:SetSize(50, 50)
- overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder"
- overlay:SetPoint("TOPLEFT", button, "TOPLEFT")
- local background = button:CreateTexture(nil, "BACKGROUND")
- background:SetSize(24, 24)
- background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background"
- background:SetPoint("CENTER", button, "CENTER")
- local icon = button:CreateTexture(nil, "ARTWORK")
- icon:SetSize(18, 18)
- icon:SetTexture(object.icon)
- icon:SetPoint("CENTER", button, "CENTER")
- button.icon = icon
- else
- local overlay = button:CreateTexture(nil, "OVERLAY")
- overlay:SetSize(53, 53)
- overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder"
- overlay:SetPoint("TOPLEFT")
- local background = button:CreateTexture(nil, "BACKGROUND")
- background:SetSize(20, 20)
- background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background"
- background:SetPoint("TOPLEFT", 7, -5)
- local icon = button:CreateTexture(nil, "ARTWORK")
- icon:SetSize(17, 17)
- icon:SetTexture(object.icon)
- icon:SetPoint("TOPLEFT", 7, -6)
- button.icon = icon
- end
-
- button.isMouseDown = false
- local r, g, b = button.icon:GetVertexColor()
- button.icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b)
-
- button.icon.UpdateCoord = updateCoord
- button.icon:UpdateCoord()
-
- button:SetScript("OnEnter", onEnter)
- button:SetScript("OnLeave", onLeave)
- button:SetScript("OnClick", onClick)
- if not db or not db.lock then
- button:SetScript("OnDragStart", onDragStart)
- button:SetScript("OnDragStop", onDragStop)
- end
- button:SetScript("OnMouseDown", onMouseDown)
- button:SetScript("OnMouseUp", onMouseUp)
-
- button.fadeOut = button:CreateAnimationGroup()
- local animOut = button.fadeOut:CreateAnimation("Alpha")
- animOut:SetOrder(1)
- animOut:SetDuration(0.2)
- animOut:SetFromAlpha(1)
- animOut:SetToAlpha(0)
- animOut:SetStartDelay(1)
- button.fadeOut:SetToFinalAlpha(true)
-
- lib.objects[name] = button
-
- if lib.loggedIn then
- updatePosition(button, db and db.minimapPos)
- if not db or not db.hide then
- button:Show()
- else
- button:Hide()
- end
- end
-
- if db and db.showInCompartment then
- lib:AddButtonToCompartment(name, customCompartmentIcon)
- end
- lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback
-end
-
--- Wait a bit with the initial positioning to let any GetMinimapShape addons
--- load up.
-if not lib.loggedIn then
- local frame = CreateFrame("Frame")
- frame:SetScript("OnEvent", function(self)
- for _, button in next, lib.objects do
- updatePosition(button, button.db and button.db.minimapPos)
- if not button.db or not button.db.hide then
- button:Show()
- else
- button:Hide()
- end
- end
- lib.loggedIn = true
- self:SetScript("OnEvent", nil)
- end)
- frame:RegisterEvent("PLAYER_LOGIN")
-end
-
-do
- local function OnMinimapEnter()
- if isDraggingButton then return end
- for _, button in next, lib.objects do
- if button.showOnMouseover then
- button.fadeOut:Stop()
- button:SetAlpha(1)
- end
- end
- end
- local function OnMinimapLeave()
- if isDraggingButton then return end
- for _, button in next, lib.objects do
- if button.showOnMouseover then
- button.fadeOut:Play()
- end
- end
- end
- Minimap:HookScript("OnEnter", OnMinimapEnter)
- Minimap:HookScript("OnLeave", OnMinimapLeave)
-end
-
---------------------------------------------------------------------------------
--- Button API
---
-
-function lib:Register(name, object, db, customCompartmentIcon)
- if not object.icon then error("Can't register LDB objects without icons set!") end
- if lib:GetMinimapButton(name) then error(DBICON10.. ": Object '".. name .."' is already registered.") end
- createButton(name, object, db, customCompartmentIcon)
-end
-
-function lib:Lock(name)
- local button = lib:GetMinimapButton(name)
- if button then
- button:SetScript("OnDragStart", nil)
- button:SetScript("OnDragStop", nil)
- if button.db then
- button.db.lock = true
- end
- end
-end
-
-function lib:Unlock(name)
- local button = lib:GetMinimapButton(name)
- if button then
- button:SetScript("OnDragStart", onDragStart)
- button:SetScript("OnDragStop", onDragStop)
- if button.db then
- button.db.lock = nil
- end
- end
-end
-
-function lib:Hide(name)
- local button = lib:GetMinimapButton(name)
- if button then
- button:Hide()
- end
-end
-
-function lib:Show(name)
- local button = lib:GetMinimapButton(name)
- if button then
- button:Show()
- updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
- end
-end
-
-function lib:IsRegistered(name)
- return lib.objects[name] and true or false
-end
-
-function lib:Refresh(name, db)
- local button = lib:GetMinimapButton(name)
- if button then
- if db then
- button.db = db
- end
- updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
- if not button.db or not button.db.hide then
- button:Show()
- else
- button:Hide()
- end
- if not button.db or not button.db.lock then
- button:SetScript("OnDragStart", onDragStart)
- button:SetScript("OnDragStop", onDragStop)
- else
- button:SetScript("OnDragStart", nil)
- button:SetScript("OnDragStop", nil)
- end
- end
-end
-
-function lib:ShowOnEnter(name, value)
- local button = lib:GetMinimapButton(name)
- if button then
- if value then
- button.showOnMouseover = true
- button.fadeOut:Stop()
- button:SetAlpha(0)
- else
- button.showOnMouseover = false
- button.fadeOut:Stop()
- button:SetAlpha(1)
- end
- end
-end
-
-function lib:GetMinimapButton(name)
- return lib.objects[name]
-end
-
-function lib:GetButtonList()
- local t = {}
- for name in next, lib.objects do
- t[#t+1] = name
- end
- return t
-end
-
-function lib:SetButtonRadius(radius)
- if type(radius) == "number" then
- lib.radius = radius
- for _, button in next, lib.objects do
- updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
- end
- end
-end
-
-function lib:SetButtonToPosition(button, position)
- updatePosition(lib.objects[button] or button, position)
-end
-
---------------------------------------------------------------------------------
--- Addon Compartment API
---
-
-function lib:IsButtonCompartmentAvailable()
- if AddonCompartmentFrame then
- return true
- end
-end
-
-function lib:IsButtonInCompartment(buttonName)
- local object = lib.objects[buttonName]
- if object and object.db and object.db.showInCompartment then
- return true
- end
- return false
-end
-
-function lib:AddButtonToCompartment(buttonName, customIcon)
- if lib:IsButtonCompartmentAvailable() then
- local object = lib.objects[buttonName]
- if object and not object.compartmentData then
- if object.db then
- object.db.showInCompartment = true
- end
- object.compartmentData = {
- text = buttonName,
- icon = customIcon or object.dataObject.icon,
- notCheckable = true,
- registerForAnyClick = true,
- func = function(_, menuInputData, menu)
- object.dataObject.OnClick(menu, menuInputData.buttonName)
- end,
- funcOnEnter = onEnterCompartment,
- funcOnLeave = onLeaveCompartment,
- }
- AddonCompartmentFrame:RegisterAddon(object.compartmentData)
- end
- end
-end
-
-function lib:RemoveButtonFromCompartment(buttonName)
- if lib:IsButtonCompartmentAvailable() then
- local object = lib.objects[buttonName]
- if object and object.compartmentData then
- for i = 1, #AddonCompartmentFrame.registeredAddons do
- local entry = AddonCompartmentFrame.registeredAddons[i]
- if entry == object.compartmentData then
- object.compartmentData = nil
- if object.db then
- object.db.showInCompartment = nil
- end
- table.remove(AddonCompartmentFrame.registeredAddons, i)
- AddonCompartmentFrame:UpdateDisplay()
- return
- end
- end
- end
- end
-end
-
---------------------------------------------------------------------------------
--- Upgrades
---
-
-for name, button in next, lib.objects do
- local db = button.db
- if not db or not db.lock then
- button:SetScript("OnDragStart", onDragStart)
- button:SetScript("OnDragStop", onDragStop)
- end
- button:SetScript("OnEnter", onEnter)
- button:SetScript("OnLeave", onLeave)
- button:SetScript("OnClick", onClick)
- button:SetScript("OnMouseDown", onMouseDown)
- button:SetScript("OnMouseUp", onMouseUp)
-
- if not button.fadeOut then -- Upgrade to 39
- button.fadeOut = button:CreateAnimationGroup()
- local animOut = button.fadeOut:CreateAnimation("Alpha")
- animOut:SetOrder(1)
- animOut:SetDuration(0.2)
- animOut:SetFromAlpha(1)
- animOut:SetToAlpha(0)
- animOut:SetStartDelay(1)
- button.fadeOut:SetToFinalAlpha(true)
- end
-end
-lib:SetButtonRadius(lib.radius) -- Upgrade to 40
-if lib.notCreated then -- Upgrade to 50
- for name in next, lib.notCreated do
- createButton(name, lib.notCreated[name][1], lib.notCreated[name][2])
- end
- lib.notCreated = nil
-end
diff --git a/Libs/LibDBIcon-1.0/lib.xml b/Libs/LibDBIcon-1.0/lib.xml
deleted file mode 100644
index 5dca17c..0000000
--- a/Libs/LibDBIcon-1.0/lib.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
diff --git a/Libs/LibDataBroker-1.1/LibDataBroker-1.1.lua b/Libs/LibDataBroker-1.1/LibDataBroker-1.1.lua
deleted file mode 100644
index f47c0cd..0000000
--- a/Libs/LibDataBroker-1.1/LibDataBroker-1.1.lua
+++ /dev/null
@@ -1,90 +0,0 @@
-
-assert(LibStub, "LibDataBroker-1.1 requires LibStub")
-assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
-
-local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
-if not lib then return end
-oldminor = oldminor or 0
-
-
-lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
-lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
-local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
-
-if oldminor < 2 then
- lib.domt = {
- __metatable = "access denied",
- __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
- }
-end
-
-if oldminor < 3 then
- lib.domt.__newindex = function(self, key, value)
- if not attributestorage[self] then attributestorage[self] = {} end
- if attributestorage[self][key] == value then return end
- attributestorage[self][key] = value
- local name = namestorage[self]
- if not name then return end
- callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
- callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
- callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
- callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
- end
-end
-
-if oldminor < 2 then
- function lib:NewDataObject(name, dataobj)
- if self.proxystorage[name] then return end
-
- if dataobj then
- assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
- self.attributestorage[dataobj] = {}
- for i,v in pairs(dataobj) do
- self.attributestorage[dataobj][i] = v
- dataobj[i] = nil
- end
- end
- dataobj = setmetatable(dataobj or {}, self.domt)
- self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
- self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
- return dataobj
- end
-end
-
-if oldminor < 1 then
- function lib:DataObjectIterator()
- return pairs(self.proxystorage)
- end
-
- function lib:GetDataObjectByName(dataobjectname)
- return self.proxystorage[dataobjectname]
- end
-
- function lib:GetNameByDataObject(dataobject)
- return self.namestorage[dataobject]
- end
-end
-
-if oldminor < 4 then
- local next = pairs(attributestorage)
- function lib:pairs(dataobject_or_name)
- local t = type(dataobject_or_name)
- assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
-
- local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
- assert(attributestorage[dataobj], "Data object not found")
-
- return next, attributestorage[dataobj], nil
- end
-
- local ipairs_iter = ipairs(attributestorage)
- function lib:ipairs(dataobject_or_name)
- local t = type(dataobject_or_name)
- assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
-
- local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
- assert(attributestorage[dataobj], "Data object not found")
-
- return ipairs_iter, attributestorage[dataobj], 0
- end
-end
diff --git a/Libs/LibDualSpec-1.0/LibDualSpec-1.0.lua b/Libs/LibDualSpec-1.0/LibDualSpec-1.0.lua
deleted file mode 100644
index 60c9ae3..0000000
--- a/Libs/LibDualSpec-1.0/LibDualSpec-1.0.lua
+++ /dev/null
@@ -1,505 +0,0 @@
---[[
-LibDualSpec-1.0 - Adds dual spec support to individual AceDB-3.0 databases
-Copyright (C) 2009-2024 Adirelle
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Redistribution of a stand alone version is strictly prohibited without
- prior written authorization from the LibDualSpec project manager.
- * Neither the name of the LibDualSpec authors nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---]]
-
--- Only load in Classic Era on Season of Discovery realms
-if WOW_PROJECT_ID == WOW_PROJECT_CLASSIC and C_Seasons.GetActiveSeason() ~= 2 then return end
-
-local MAJOR, MINOR = "LibDualSpec-1.0", 24
-assert(LibStub, MAJOR.." requires LibStub")
-local lib, minor = LibStub:NewLibrary(MAJOR, MINOR)
-if not lib then return end
-
--- ----------------------------------------------------------------------------
--- Library data
--- ----------------------------------------------------------------------------
-
-lib.eventFrame = lib.eventFrame or CreateFrame("Frame")
-
-lib.registry = lib.registry or {}
-lib.options = lib.options or {}
-lib.mixin = lib.mixin or {}
-lib.upgrades = lib.upgrades or {}
-lib.currentSpec = tonumber(lib.currentSpec) or 0
-
-if minor and minor < 15 then
- lib.talentsLoaded, lib.talentGroup = nil, nil
- lib.specLoaded, lib.specGroup = nil, nil
- lib.eventFrame:UnregisterAllEvents()
- wipe(lib.options)
-end
-
--- ----------------------------------------------------------------------------
--- Locals
--- ----------------------------------------------------------------------------
-
-local registry = lib.registry
-local options = lib.options
-local mixin = lib.mixin
-local upgrades = lib.upgrades
-
--- "Externals"
-local AceDB3 = LibStub('AceDB-3.0', true)
-local AceDBOptions3 = LibStub('AceDBOptions-3.0', true)
-local AceConfigRegistry3 = LibStub('AceConfigRegistry-3.0', true)
-
-local isRetail = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE
-local numSpecs = 2
-local specNames = {TALENT_SPEC_PRIMARY, TALENT_SPEC_SECONDARY}
-if isRetail then
- -- class id specialization functions don't require player data to be loaded
- local _, classId = UnitClassBase("player")
- numSpecs = GetNumSpecializationsForClassID(classId)
- for i = 1, numSpecs do
- local _, name = GetSpecializationInfoForClassID(classId, i)
- specNames[i] = name
- end
-end
-
-local GetSpecialization = isRetail and GetSpecialization or GetActiveTalentGroup
-local CanPlayerUseTalentSpecUI = isRetail and C_SpecializationInfo.CanPlayerUseTalentSpecUI or function()
- return true, HELPFRAME_CHARACTER_BULLET5
-end
-
--- ----------------------------------------------------------------------------
--- Localization
--- ----------------------------------------------------------------------------
-
-local L_ENABLED = "Enable spec profiles"
-local L_ENABLED_DESC = "When enabled, your profile will be set to the specified profile when you change specialization."
-local L_CURRENT = "%s - Active"
-
-do
- local locale = GetLocale()
- if locale == "deDE" then
- L_ENABLED = "Spezialisierungsprofile aktivieren"
- L_ENABLED_DESC = "Falls diese Option aktiviert ist, wird dein Profil auf das angegebene Profil gesetzt, wenn du die Spezialisierung wechselst."
- L_CURRENT = "%s - Aktiv"
- elseif locale == "esES" or locale == "esMX" then
- L_ENABLED = "Activar perfiles de especialización"
- L_ENABLED_DESC = "Cuando está habilitado, su perfil se establecerá en el perfil especificado cuando cambie de especialización."
- L_CURRENT = "%s - Activo"
- elseif locale == "frFR" then
- L_ENABLED = "Activer les profils de spécialisation"
- L_ENABLED_DESC = "Lorsque cette option est activée, votre profil sera défini sur le profil spécifié lorsque vous changerez de spécialisation."
- L_CURRENT = "%s - Actifs"
- elseif locale == "itIT" then
- L_ENABLED = "Abilita i profili per la specializzazione"
- L_ENABLED_DESC = "Quando abilitato, il tuo profilo verrà impostato in base alla specializzazione usata."
- L_CURRENT = "%s - Attivi"
- elseif locale == "koKR" then
- L_ENABLED = "전문화 프로필 활성화"
- L_ENABLED_DESC = "활성화하면 전문화를 변경할 때 프로필이 지정된 프로필로 설정됩니다."
- L_CURRENT = "%s - 활성화"
- elseif locale == "ptBR" then
- L_ENABLED = "Ativar perfis de especialização"
- L_ENABLED_DESC = "Quando ativado, seu perfil será definido para o perfil especificado quando você alterar a especialização."
- L_CURRENT = "%s – ativo"
- elseif locale == "ruRU" then
- L_ENABLED = "Включить профили специализации"
- L_ENABLED_DESC = "Если включено, ваш профиль будет зависеть от выбранной специализации."
- L_CURRENT = "%s - активен"
- elseif locale == "zhCN" then
- L_ENABLED = "启用专精配置文件"
- L_ENABLED_DESC = "当启用后,当切换专精时配置文件将设置为专精配置文件。"
- L_CURRENT = "%s - 开启"
- elseif locale == "zhTW" then
- L_ENABLED = "啟用專精設定檔"
- L_ENABLED_DESC = "當啟用後,當你切換專精時設定檔會設定為專精設定檔。"
- L_CURRENT = "%s - 啟動"
- end
-end
-
--- ----------------------------------------------------------------------------
--- Mixin
--- ----------------------------------------------------------------------------
-
---- Get dual spec feature status.
--- @return (boolean) true is dual spec feature enabled.
--- @name enhancedDB:IsDualSpecEnabled
-function mixin:IsDualSpecEnabled()
- return lib.currentSpec > 0 and registry[self].db.char.enabled
-end
-
---- Enable/disabled dual spec feature.
--- @param enabled (boolean) true to enable dual spec feature, false to disable it.
--- @name enhancedDB:SetDualSpecEnabled
-function mixin:SetDualSpecEnabled(enabled)
- local db = registry[self].db.char
- db.enabled = not not enabled
-
- local currentProfile = self:GetCurrentProfile()
- for i = 1, numSpecs do
- -- nil out entries on disable, set nil entries to the current profile on enable
- db[i] = enabled and (db[i] or currentProfile) or nil
- end
-
- self:CheckDualSpecState()
-end
-
---- Get the profile assigned to a specialization.
--- Defaults to the current profile.
--- @param spec (number) the specialization index.
--- @return (string) the profile name.
--- @name enhancedDB:GetDualSpecProfile
-function mixin:GetDualSpecProfile(spec)
- return registry[self].db.char[spec or lib.currentSpec] or self:GetCurrentProfile()
-end
-
---- Set the profile assigned to a specialization.
--- No validation are done to ensure the profile is valid.
--- @param profileName (string) the profile name to use.
--- @param spec (number) the specialization index.
--- @name enhancedDB:SetDualSpecProfile
-function mixin:SetDualSpecProfile(profileName, spec)
- spec = spec or lib.currentSpec
- if spec < 1 or spec > numSpecs then return end
-
- registry[self].db.char[spec] = profileName
- self:CheckDualSpecState()
-end
-
---- Check if a profile swap should occur.
--- There is normally no reason to call this method directly as LibDualSpec
--- takes care of calling it at the appropriate time.
--- @name enhancedDB:CheckDualSpecState
-function mixin:CheckDualSpecState()
- if not registry[self].db.char.enabled then return end
- if lib.currentSpec == 0 then return end
-
- local profileName = self:GetDualSpecProfile()
- if profileName ~= self:GetCurrentProfile() then
- self:SetProfile(profileName)
- end
-end
-
--- ----------------------------------------------------------------------------
--- AceDB-3.0 support
--- ----------------------------------------------------------------------------
-
-local function EmbedMixin(target)
- for k,v in next, mixin do
- rawset(target, k, v)
- end
-end
-
--- Upgrade settings from current/alternate system.
--- This sets the current profile as the profile for your current spec and your
--- swapped profile as the profile for the rest of your specs.
-local function UpgradeDatabase(target)
- if lib.currentSpec == 0 then
- upgrades[target] = true
- return
- end
-
- local db = target:GetNamespace(MAJOR, true)
- if db and db.char.profile then
- for i = 1, numSpecs do
- if i == lib.currentSpec then
- db.char[i] = target:GetCurrentProfile()
- else
- db.char[i] = db.char.profile
- end
- end
- db.char.profile = nil
- db.char.specGroup = nil
- end
-end
-
--- Reset a spec profile to the current one if its profile is deleted.
-function lib:OnProfileDeleted(event, target, profileName)
- local db = registry[target].db.char
- if not db.enabled then return end
-
- for i = 1, numSpecs do
- if db[i] == profileName then
- db[i] = target:GetCurrentProfile()
- end
- end
-end
-
--- Actually enhance the database
--- This is used on first initialization and everytime the database is reset using :ResetDB
-function lib:_EnhanceDatabase(event, target)
- registry[target].db = target:GetNamespace(MAJOR, true) or target:RegisterNamespace(MAJOR)
- EmbedMixin(target)
- target:CheckDualSpecState()
-end
-
---- Embed dual spec feature into an existing AceDB-3.0 database.
--- LibDualSpec specific methods are added to the instance.
--- @name LibDualSpec:EnhanceDatabase
--- @param target (table) the AceDB-3.0 instance.
--- @param name (string) a user-friendly name of the database (best bet is the addon name).
-function lib:EnhanceDatabase(target, name)
- AceDB3 = AceDB3 or LibStub('AceDB-3.0', true)
- if type(target) ~= "table" then
- error("Usage: LibDualSpec:EnhanceDatabase(target, name): target should be a table.", 2)
- elseif type(name) ~= "string" then
- error("Usage: LibDualSpec:EnhanceDatabase(target, name): name should be a string.", 2)
- elseif not AceDB3 or not AceDB3.db_registry[target] then
- error("Usage: LibDualSpec:EnhanceDatabase(target, name): target should be an AceDB-3.0 database.", 2)
- elseif target.parent then
- error("Usage: LibDualSpec:EnhanceDatabase(target, name): cannot enhance a namespace.", 2)
- elseif registry[target] then
- return
- end
- registry[target] = { name = name }
- UpgradeDatabase(target)
- lib:_EnhanceDatabase("EnhanceDatabase", target)
- target.RegisterCallback(lib, "OnDatabaseReset", "_EnhanceDatabase")
- target.RegisterCallback(lib, "OnProfileDeleted")
-end
-
--- ----------------------------------------------------------------------------
--- AceDBOptions-3.0 support
--- ----------------------------------------------------------------------------
-
-options.new = {
- name = "New",
- type = "input",
- order = 30,
- get = false,
- set = function(info, value)
- local db = info.handler.db
- if db:IsDualSpecEnabled() then
- db:SetDualSpecProfile(value, lib.currentSpec)
- else
- db:SetProfile(value)
- end
- end,
-}
-
-options.choose = {
- name = "Existing Profiles",
- type = "select",
- order = 40,
- get = "GetCurrentProfile",
- set = "SetProfile",
- values = "ListProfiles",
- arg = "common",
- disabled = function(info)
- return info.handler.db:IsDualSpecEnabled()
- end
-}
-
-options.enabled = {
- type = "toggle",
- name = "|cffffd200"..L_ENABLED.."|r",
- desc = function()
- local desc = L_ENABLED_DESC
- if lib.currentSpec == 0 then
- local _, reason = CanPlayerUseTalentSpecUI()
- if not reason or reason == "" then
- reason = TALENT_MICRO_BUTTON_NO_SPEC
- end
- desc = desc .. "\n\n" .. RED_FONT_COLOR:WrapTextInColorCode(reason)
- end
- return desc
- end,
- descStyle = "inline",
- order = 41,
- width = "full",
- get = function(info) return info.handler.db:IsDualSpecEnabled() end,
- set = function(info, value) info.handler.db:SetDualSpecEnabled(value) end,
- disabled = function() return lib.currentSpec == 0 end,
-}
-
-local points = {}
-for i = 1, numSpecs do
- options["specProfile" .. i] = {
- type = "select",
- name = function(info)
- local specIndex = tonumber(info[#info]:sub(-1))
- return lib.currentSpec == specIndex and L_CURRENT:format(specNames[specIndex]) or specNames[specIndex]
- end,
- desc = not isRetail and function(info)
- local specIndex = tonumber(info[#info]:sub(-1))
- local highPointsSpentIndex = nil
- for treeIndex = 1, 3 do
- local name, pointsSpent, previewPointsSpent, _
- if WOW_PROJECT_ID == WOW_PROJECT_WRATH_CLASSIC then
- name, _, pointsSpent, _, previewPointsSpent = GetTalentTabInfo(treeIndex, nil, nil, specIndex)
- else
- _, name, _, _, pointsSpent, _, previewPointsSpent = GetTalentTabInfo(treeIndex, nil, nil, specIndex)
- end
- if name then
- local displayPointsSpent = pointsSpent + previewPointsSpent
- points[treeIndex] = displayPointsSpent
- if displayPointsSpent > 0 and (not highPointsSpentIndex or displayPointsSpent > points[highPointsSpentIndex]) then
- highPointsSpentIndex = treeIndex
- end
- else
- points[treeIndex] = 0
- end
- end
- if highPointsSpentIndex then
- points[highPointsSpentIndex] = GREEN_FONT_COLOR:WrapTextInColorCode(points[highPointsSpentIndex])
- end
- return ("|cffffffff%s / %s / %s|r"):format(unpack(points))
- end or nil,
- order = 42 + i,
- get = function(info)
- local specIndex = tonumber(info[#info]:sub(-1))
- return info.handler.db:GetDualSpecProfile(specIndex)
- end,
- set = function(info, value)
- local specIndex = tonumber(info[#info]:sub(-1))
- info.handler.db:SetDualSpecProfile(value, specIndex)
- end,
- values = "ListProfiles",
- arg = "common",
- disabled = function(info) return not info.handler.db:IsDualSpecEnabled() end,
- }
-end
-
---- Embed dual spec options into an existing AceDBOptions-3.0 option table.
--- @name LibDualSpec:EnhanceOptions
--- @param optionTable (table) The option table returned by AceDBOptions-3.0.
--- @param target (table) The AceDB-3.0 the options operate on.
-function lib:EnhanceOptions(optionTable, target)
- AceDBOptions3 = AceDBOptions3 or LibStub('AceDBOptions-3.0', true)
- AceConfigRegistry3 = AceConfigRegistry3 or LibStub('AceConfigRegistry-3.0', true)
- if type(optionTable) ~= "table" then
- error("Usage: LibDualSpec:EnhanceOptions(optionTable, target): optionTable should be a table.", 2)
- elseif type(target) ~= "table" then
- error("Usage: LibDualSpec:EnhanceOptions(optionTable, target): target should be a table.", 2)
- elseif not AceDBOptions3 or not AceDBOptions3.optionTables[target] then
- error("Usage: LibDualSpec:EnhanceOptions(optionTable, target): optionTable is not an AceDBOptions-3.0 table.", 2)
- elseif optionTable.handler.db ~= target then
- error("Usage: LibDualSpec:EnhanceOptions(optionTable, target): optionTable must be the option table of target.", 2)
- elseif not registry[target] then
- error("Usage: LibDualSpec:EnhanceOptions(optionTable, target): EnhanceDatabase should be called before EnhanceOptions(optionTable, target).", 2)
- end
-
- -- localize our replacements
- options.new.name = optionTable.args.new.name
- options.new.desc = optionTable.args.new.desc
- options.choose.name = optionTable.args.choose.name
- options.choose.desc = optionTable.args.choose.desc
-
- -- add our new options
- if not optionTable.plugins then
- optionTable.plugins = {}
- end
- optionTable.plugins[MAJOR] = options
-end
-
--- ----------------------------------------------------------------------------
--- Upgrade existing
--- ----------------------------------------------------------------------------
-
-for target in next, registry do
- UpgradeDatabase(target)
- EmbedMixin(target)
- target:CheckDualSpecState()
- local optionTable = AceDBOptions3 and AceDBOptions3.optionTables[target]
- if optionTable then
- lib:EnhanceOptions(optionTable, target)
- end
-end
-
--- ----------------------------------------------------------------------------
--- Inspection
--- ----------------------------------------------------------------------------
-
-do
- local function iterator(t, key)
- local data
- key, data = next(t, key)
- if key then
- return key, data.name
- end
- end
-
- --- Iterate through enhanced AceDB3.0 instances.
- -- The iterator returns (instance, name) pairs where instance and name are the
- -- arguments that were provided to lib:EnhanceDatabase.
- -- @name LibDualSpec:IterateDatabases
- -- @return Values to be used in a for .. in .. do statement.
- function lib:IterateDatabases()
- return iterator, lib.registry
- end
-end
-
--- ----------------------------------------------------------------------------
--- Switching logic
--- ----------------------------------------------------------------------------
-
-local function eventHandler(self, event)
- local spec = GetSpecialization() or 0
- -- Newly created characters start at 5 instead of 1 in 9.0.1.
- if spec == 5 or not CanPlayerUseTalentSpecUI() then
- spec = 0
- end
- lib.currentSpec = spec
-
- if event == "PLAYER_LOGIN" then
- self:UnregisterEvent(event)
- self:RegisterEvent("PLAYER_ENTERING_WORLD")
- if isRetail then
- self:RegisterUnitEvent("PLAYER_SPECIALIZATION_CHANGED", "player")
- self:RegisterEvent("PLAYER_LEVEL_CHANGED")
- else
- self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
- end
- end
-
- if spec > 0 and next(upgrades) then
- for target in next, upgrades do
- UpgradeDatabase(target)
- end
- wipe(upgrades)
- end
-
- for target in next, registry do
- target:CheckDualSpecState()
- end
-
- if AceConfigRegistry3 and next(registry) then
- -- Update the "Current" text in options
- -- We don't get the key for the actual registered options table, and we can't
- -- really check for our enhanced options without walking every options table,
- -- so just refresh anything.
- for appName in AceConfigRegistry3:IterateOptionsTables() do
- AceConfigRegistry3:NotifyChange(appName)
- end
- end
-end
-
-lib.eventFrame:SetScript("OnEvent", eventHandler)
-if IsLoggedIn() then
- eventHandler(lib.eventFrame, "PLAYER_LOGIN")
-else
- lib.eventFrame:RegisterEvent("PLAYER_LOGIN")
-end
-
diff --git a/Libs/LibDualSpec-1.0/LibDualSpec-1.0.toc b/Libs/LibDualSpec-1.0/LibDualSpec-1.0.toc
deleted file mode 100644
index 2109a1c..0000000
--- a/Libs/LibDualSpec-1.0/LibDualSpec-1.0.toc
+++ /dev/null
@@ -1,11 +0,0 @@
-## Interface: 11503, 30403, 40400, 100207
-## LoadOnDemand: 1
-## Title: Lib: DualSpec-1.0
-## Version: v1.24.0
-## X-Date: 2024-07-10T06:46:35Z
-## Notes: Adds spec switching support to individual AceDB-3.0 databases.
-## Author: Adirelle, Nebula
-## OptionalDeps: Ace3
-
-LibStub.lua
-LibDualSpec-1.0.lua
diff --git a/Libs/LibDualSpec-1.0/LibStub.lua b/Libs/LibDualSpec-1.0/LibStub.lua
deleted file mode 100644
index 0a41ac0..0000000
--- a/Libs/LibDualSpec-1.0/LibStub.lua
+++ /dev/null
@@ -1,30 +0,0 @@
--- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
--- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
-local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
-local LibStub = _G[LIBSTUB_MAJOR]
-
-if not LibStub or LibStub.minor < LIBSTUB_MINOR then
- LibStub = LibStub or {libs = {}, minors = {} }
- _G[LIBSTUB_MAJOR] = LibStub
- LibStub.minor = LIBSTUB_MINOR
-
- function LibStub:NewLibrary(major, minor)
- assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
- minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
-
- local oldminor = self.minors[major]
- if oldminor and oldminor >= minor then return nil end
- self.minors[major], self.libs[major] = minor, self.libs[major] or {}
- return self.libs[major], oldminor
- end
-
- function LibStub:GetLibrary(major, silent)
- if not self.libs[major] and not silent then
- error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
- end
- return self.libs[major], self.minors[major]
- end
-
- function LibStub:IterateLibraries() return pairs(self.libs) end
- setmetatable(LibStub, { __call = LibStub.GetLibrary })
-end
diff --git a/Libs/Libs.xml b/Libs/Libs.xml
index 7556987..5f8ccae 100644
--- a/Libs/Libs.xml
+++ b/Libs/Libs.xml
@@ -3,7 +3,6 @@
-
@@ -12,6 +11,5 @@
-