You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1780 lines
56 KiB

local _, addon = ...
local strmatch = string.match;
local gmatch = string.gmatch;
local After = C_Timer.After;
local unpack = unpack;
local FadeFrame = NarciFadeUI.Fade;
local outQuart = addon.EasingFunctions.outQuart;
local MAX_ROW = NarciConstants.Soulbinds.MaxRow or 8; --12
local FILE_PATH = "Interface\\AddOns\\Narcissus\\Art\\Modules\\CharacterFrame\\Soulbinds\\";
local CONDUIT_OFFSET = 60;
local CONDUIT_MAX_RANK = 14;
--[[
local QUALITY_COLORS = {
[0] = {0.5, 0.5, 0.5},
[1] = {0.8, 0.8, 0.8},
[2] = {0.57, 0.79, 0.40},
[3] = {0.17, 0.52, 0.87},
[4] = {0.64, 0.21, 0.93},
[5] = {0.5, 0.5, 0.5},
};
--]]
local QUALITY_COLORS = NarciAPI.GetItemQualityColorTable();
QUALITY_COLORS[1] = {0.8, 0.8, 0.8};
local C_Item = C_Item;
local C_Soulbinds = C_Soulbinds;
local GetSpellInfo = addon.TransitionAPI.GetSpellInfo;
local GetSpellTexture = addon.TransitionAPI.GetSpellTexture;
local MainFrame, NodesContainer, CollectionFrame, ConduitTooltip;
local function GetConduitItemQualityByRank(rank)
if rank == 0 then
return 1
elseif rank == 1 then
return 2
elseif rank <= 3 then
return 3
else
return 4
end
end
local function SetTextColorByQuality(text, quality, darker)
local r, g, b = unpack(QUALITY_COLORS[quality]);
if not r then
r, g, b = 0.8, 0.8, 0.8;
end
if darker then
text:SetTextColor(r, g, b);
else
text:SetTextColor(r*0.66, g*0.66, b*0.66);
end
end
local function SetConduitItemQualityColorByItemLevel(widget, itemLevel, isCurrentSpec)
local i;
if itemLevel < 158 then
i = 0;
elseif itemLevel <= 171 then
i = 1;
else
i = 2;
end
widget.Border:SetTexCoord(0.25 * i, 0.25 * (i + 1), 0, 1);
if isCurrentSpec then
widget.Border:SetVertexColor(1, 1, 1);
widget.Icon:SetVertexColor(1, 1, 1);
SetTextColorByQuality(widget.Name, i+2);
else
widget.Border:SetVertexColor(0.66, 0.66, 0.66);
widget.Icon:SetVertexColor(0.66, 0.66, 0.66);
SetTextColorByQuality(widget.Name, i+2, true);
end
end
-----------------------------------------------------------------------------------
local QueueFrame = NarciAPI.CreateProcessor();
local ReferenceTooltip = CreateFrame("GameTooltip", "NarciSoulbindsConduitReferenceTooltip", UIParent, "GameTooltipTemplate");
if ReferenceTooltip:HasScript("OnTooltipAddMoney") then --dragonflight
ReferenceTooltip:SetScript("OnTooltipAddMoney", nil);
end
if ReferenceTooltip:HasScript("OnTooltipCleared") then
ReferenceTooltip:SetScript("OnTooltipCleared", nil);
end
local DataProvider = {};
DataProvider.conduitItemIDs = {};
DataProvider.conduitNames = {};
function DataProvider:GetConduitItemLevel(rank)
if not rank or rank == 0 then
return 0;
else
return 135 + rank * 13;
end
end
function DataProvider:GetActiveCovenantID()
if not self.activeCovenantID then
self.activeCovenantID = C_Covenants.GetActiveCovenantID();
end
return self.activeCovenantID
end
function DataProvider:UpdateCovenantData()
self.activeCovenantID = C_Covenants.GetActiveCovenantID();
wipe(self.conduitItemIDs);
for conduitType = 0, 2 do
local data = C_Soulbinds.GetConduitCollection(conduitType);
if data then
local itemID, conduitID;
for i = 1, #data do
itemID = data[i].conduitItemID;
conduitID = data[i].conduitID;
if itemID then
self.conduitItemIDs[itemID] = conduitID;
end
end
end
end
end
function DataProvider:GetConduitName(conduitID, conduitItemID)
if not conduitID then return "" end;
if self.conduitNames[conduitID] then
return self.conduitNames[conduitID]
else
if not conduitItemID then
local collectionData = C_Soulbinds.GetConduitCollectionData(conduitID);
if collectionData then
conduitItemID = collectionData.conduitItemID;
end
end
if conduitItemID then
local name = C_Item.GetItemNameByID(conduitItemID);
if name and name ~= "" then
self.conduitNames[conduitID] = name;
return name
end
end
return ""
end
end
--/dump strmatch("|cFFFFFFFF10% sec|r. in to |cFFFFFFFF20% sec|r.", "|c%w%w%w%w%w%w%w%w([^|]+)")
--/dump string.gsub("|cFFFFFFFF10% sec|r. in to |cFFFFFFFF20% sec|r.", "|c%w%w%w%w%w%w%w%w([^|]+)", print)
function DataProvider:CacheConduitTooltip(conduitID, rank)
ReferenceTooltip:SetOwner(UIParent, "ANCHOR_NONE");
ReferenceTooltip:SetConduit(conduitID, rank);
end
function DataProvider:GetConduitDescription(conduitID, rank, numberOnly)
ReferenceTooltip:SetOwner(UIParent, "ANCHOR_NONE");
ReferenceTooltip:SetConduit(conduitID, rank);
if not self.referenceLine then
self.referenceLine = _G["NarciSoulbindsConduitReferenceTooltip".. "TextLeft5"];
end
if self.referenceLine then
local text = self.referenceLine:GetText();
if numberOnly and text then
local str = gmatch(text, "|c%w%w%w%w%w%w%w%w([^|]+)");
local effect1, effect2 = str(), str();
return effect1, effect2;
else
return text;
end
end
end
function DataProvider:GetConduitIDFromItemID(itemID)
if itemID then
return self.conduitItemIDs[tonumber(itemID)];
end
end
function DataProvider:GetKnownConduitItemLevel(itemID)
local conduitID = self:GetConduitIDFromItemID(itemID);
if conduitID then
local data = C_Soulbinds.GetConduitCollectionData(conduitID);
if data then
local rank = data.conduitRank;
local itemLevel = DataProvider:GetConduitItemLevel(rank);
local description = self:GetConduitDescription(conduitID, rank);
return true, itemLevel, description;
else
return true
end
end
end
function DataProvider:GetDefaultSoulbindID(covenantID)
--Blizzard_SoulbindsUtil.lua
local SOULBINDS_COVENANT_KYRIAN = 1;
local SOULBINDS_COVENANT_VENTHYR = 2;
local SOULBINDS_COVENANT_NIGHT_FAE = 3;
local SOULBINDS_COVENANT_NECROLORD = 4;
local soulbindDefaultIDs = {
[SOULBINDS_COVENANT_KYRIAN] = 7,
[SOULBINDS_COVENANT_VENTHYR] = 8,
[SOULBINDS_COVENANT_NIGHT_FAE] = 1,
[SOULBINDS_COVENANT_NECROLORD] = 4,
};
return soulbindDefaultIDs[covenantID]
end
function DataProvider:UpdateSpec()
self.specSetIDs = {};
local specIndex = GetSpecialization() or 1;
self.currentSpecID = GetSpecializationInfo(specIndex);
end
function DataProvider:IsCurrentSpec(specSetID)
if specSetID then
if self.specSetIDs[specSetID] == nil then
self.specSetIDs[specSetID] = C_SpecializationInfo.MatchesCurrentSpecSet(specSetID);
end
return self.specSetIDs[specSetID];
else
return false;
end
end
-----------------------------------------------------------------------------------
local ConduitNodeUtil = {};
ConduitNodeUtil.activeNodeFrames = {};
ConduitNodeUtil.nodePool = {};
ConduitNodeUtil.activeNodeIndexes = {};
function ConduitNodeUtil:ReleaseActiveNodes()
QueueFrame:Stop();
wipe(self.activeNodeIndexes);
for row, frame in pairs(self.activeNodeFrames) do
frame:Hide();
end
end
function ConduitNodeUtil:AcquireNodeFrame(row)
local frame = self.activeNodeFrames[row];
if not frame then
frame = CreateFrame("Frame", nil, MainFrame.AcitveNodesList, "NarciActiveConduitFrameTemplate");
self.activeNodeFrames[row] = frame;
end
frame:ClearAllPoints();
frame:SetPoint("TOPRIGHT", MainFrame, "TOPRIGHT", 0, -12 -24 * row);
frame:Show();
return frame;
end
function ConduitNodeUtil:SetUpActiveNodeFrame(conduitID, rank, spellID, conduitType, row)
local frame = self:AcquireNodeFrame(row);
frame:SetUp(conduitID, rank, spellID, conduitType, row);
end
function ConduitNodeUtil:SetUpEmptyNodeFrame(row, unlockLevel)
local frame = self:AcquireNodeFrame(row);
frame:SetFailureReason(row, unlockLevel);
end
function ConduitNodeUtil:BuildNodes(fullNodesData, isTreeActive)
self:ReleaseActiveNodes();
local IS_ROW_PROCESSED = {};
local numNodes;
if fullNodesData then
numNodes = #fullNodesData;
local node;
local nodeData;
for i = 1, numNodes do
node = self.nodePool[i];
nodeData = fullNodesData[i];
local row = nodeData.row;
if row + 1 <= MAX_ROW then
if not node then
node = CreateFrame("Button", nil, NodesContainer, "NarciConduitNodeButtonTemplate");
self.nodePool[i] = node;
end
if node:SetUp(nodeData, isTreeActive) then
tinsert(self.activeNodeIndexes, i);
end
node:Show();
if nodeData.state == 0 then --Unavailable
if not IS_ROW_PROCESSED[row] then
IS_ROW_PROCESSED[row] = true;
local unlockLevel = nodeData.failureRenownRequirement;
if unlockLevel then
self:SetUpEmptyNodeFrame(row, unlockLevel);
end
end
elseif nodeData.state == 3 then
end
end
end
else
numNodes = 1;
end
for i = numNodes + 1, #self.nodePool do
self.nodePool[i]:Hide();
end
end
function ConduitNodeUtil:PlayShine()
for i = 1, #self.activeNodeIndexes do
self.nodePool[ self.activeNodeIndexes[i] ]:Shine();
end
end
function ConduitNodeUtil:HighlightConduitByType(conduitType)
local node;
for i = 1, #self.activeNodeIndexes do
node = self.nodePool[ self.activeNodeIndexes[i] ];
if node.conduitType == conduitType then
node:Shine();
end
end
end
local ConduitCollectionUtil = {};
ConduitCollectionUtil.categoryButtons = {};
ConduitCollectionUtil.conduitButtons = {};
local function ConduitSortFunc(a, b)
if a.conduitSpecSetID == b.conduitSpecSetID then
if a.conduitRank ~= b.conduitRank then
return a.conduitRank > b.conduitRank;
end
return DataProvider:GetConduitName(a.conduitID) < DataProvider:GetConduitName(b.conduitID)
else
if DataProvider:IsCurrentSpec(a.conduitSpecSetID) then
if DataProvider:IsCurrentSpec(b.conduitSpecSetID) then
return a.conduitSpecSetID > b.conduitSpecSetID
else
return true
end
else
if DataProvider:IsCurrentSpec(b.conduitSpecSetID) then
return false
else
return a.conduitSpecSetID > b.conduitSpecSetID
end
end
end
end
function ConduitCollectionUtil:UpdateScrollRange()
local frame = MainFrame.ConduitCollection;
if self.numConduits == 0 then
frame:SetScrollRange(0);
return
end
local cb = self.categoryButtons;
if not cb or #cb < 3 then
return
end
local yTop = cb[1]:GetTop() or 0;
local M1 = yTop - (cb[2]:GetTop() or 0);
local M2 = yTop - (cb[3]:GetTop() or 0);
frame.scrollBar.onValueChangedFunc = function(endValue, delta, scrollBar, isTop, isBottom)
if endValue > M2 + 8 then
cb[1].Button:ResetAnchor();
cb[2].Button:ResetAnchor();
cb[3].Button:AnchorToTop();
elseif endValue > (M2 - 16) then
cb[1].Button:ResetAnchor();
cb[2].Button:AnchorToDrawer();
cb[3].Button:ResetAnchor();
elseif endValue > (M1 + 8) then
cb[1].Button:ResetAnchor();
cb[2].Button:AnchorToTop();
cb[3].Button:ResetAnchor();
elseif endValue > (M1 - 16) then
cb[1].Button:AnchorToDrawer();
cb[2].Button:ResetAnchor();
cb[3].Button:ResetAnchor();
elseif endValue > 8 then
cb[1].Button:AnchorToTop();
cb[2].Button:ResetAnchor();
cb[3].Button:ResetAnchor();
else
cb[1].Button:ResetAnchor();
cb[2].Button:ResetAnchor();
cb[3].Button:ResetAnchor();
end
end
local bottomButton;
if cb[3].Drawer:IsShown() then
bottomButton = self.bottomButton;
else
bottomButton = cb[3];
end
frame:SetScrollRange(yTop - bottomButton:GetBottom() - 192);
end
function ConduitCollectionUtil:BuildList()
local frame = MainFrame.ConduitCollection;
local buttons = self.conduitButtons;
local parentButtons = self.categoryButtons;
local button, parentButton;
local numConduits = 0;
local drawer;
local buttonHeight = 32;
local types = {2, 0, 1} --{1, 0, 2};
local categoryFrameLevel = frame.ScrollChild:GetFrameLevel() + 4;
for index = 1, 3 do
local conduitType = types[index];
local data = C_Soulbinds.GetConduitCollection(conduitType);
if data then
local numData = #data;
if numData > 0 then
table.sort(data, ConduitSortFunc);
parentButton = parentButtons[index];
if not parentButton then
parentButton = CreateFrame("Frame", nil, frame, "NarciConduitCollectionCategoryButtonTemplate");
parentButtons[index] = parentButton;
end
parentButton:ClearAllPoints();
parentButton.Button:SetFrameLevel(categoryFrameLevel);
if index == 1 then
parentButton:SetPoint("TOP", frame.ScrollChild, "TOP", -6, -6);
else
parentButton:SetPoint("TOP", drawer, "BOTTOM", 0, 0);
end
parentButton.Button:SetConduitType(conduitType);
parentButton.Button:SetDrawerHeight(numData * buttonHeight + 36);
drawer = parentButton.Drawer;
local d;
for i = 1, numData do
numConduits = numConduits + 1;
d = data[i];
button = buttons[numConduits];
if button then
button:SetParent(drawer);
else
button = CreateFrame("Button", nil, drawer, "NarciConduitCollectionConduitButtonTemplate");
buttons[numConduits] = button;
end
button:ClearAllPoints();
button:SetPoint("TOP", drawer, "TOP", 0, -buttonHeight * (i - 1) -26);
button:SetConduitFromData(d);
--DataProvider:CacheConduitTooltip(d.conduitID, d.conduitRank);
end
end
end
end
self.bottomButton = button;
self:UpdateScrollRange();
end
-----------------------------------------------------------------------------------
NarciConduitNodeButtonMixin = {};
--/script for i = 1, 15 do if NODES[i].row == 6 then print(NODES[i].conduitType) end end
function NarciConduitNodeButtonMixin:OnLoad()
self.ConduitBorder:SetTexture(FILE_PATH.."IconBorder", nil, nil, "LINEAR");
self.OnLoad = nil;
self:SetScript("OnLoad", nil);
end
function NarciConduitNodeButtonMixin:SetUp(nodeData, isTreeActive)
if nodeData then
self.nodeID = nodeData.ID;
local conduitType = nodeData.conduitType; --Fixed Node: conduitType = nil
self.conduitType = conduitType;
local row, column = nodeData.row, nodeData.column;
if not row and column then return end;
self:ClearAllPoints();
self:SetPoint("CENTER", MainFrame, "TOPLEFT", CONDUIT_OFFSET + 24*(column - 1), -24 -24 * row);
local spellID = nodeData.spellID;
local conduitID = nodeData.conduitID;
local conduitRank = nodeData.conduitRank;
self.conduitID = conduitID;
self.conduitRank = conduitRank;
self.isEnhanced = nodeData.socketEnhanced;
if conduitID ~= 0 and (conduitRank and conduitRank ~= 0) then
spellID = C_Soulbinds.GetConduitSpellID(conduitID, conduitRank);
self.Icon:SetTexture(GetSpellTexture(spellID));
if self.isEnhanced then
self.ConduitBorder:SetTexCoord(0.75, 1, 0, 1);
else
self.ConduitBorder:SetTexCoord(0.25, 0.5, 0, 1);
end
self.Highlight:SetTexCoord(0.5, 1, 0, 1);
self.Mask:SetTexture(FILE_PATH.."MaskOctagon");
elseif spellID ~= 0 then
self.Icon:SetTexture(nodeData.icon); --nodeData.icon
self.Mask:SetTexture(FILE_PATH.."MaskCircle");
self.ConduitBorder:SetTexCoord(0, 0.25, 0, 1);
self.Highlight:SetTexCoord(0, 0.5, 0, 1);
else
self.Icon:SetTexture(nil);
self.ConduitBorder:SetTexCoord(0.5, 0.75, 0, 1);
self.Highlight:SetTexCoord(0, 0, 0, 0);
end
self.spellID = spellID;
self.state = nodeData.state;
--Glow Animation
local Highlight = self.Highlight;
Highlight.Glow:Stop();
--If this node is active
if self.state == 3 then
self:SetParent(NodesContainer.ActiveNodesFrame);
self:UpdateVisual(true, isTreeActive);
Highlight.Glow.Delay:SetDuration(0.06 * row);
ConduitNodeUtil:SetUpActiveNodeFrame(conduitID, conduitRank, spellID, conduitType, row);
return true;
else
self:SetParent(NodesContainer.InactiveNodesFrame);
self:UpdateVisual(false, isTreeActive);
return false;
end
end
end
function NarciConduitNodeButtonMixin:UpdateVisual(isNodeSelected, isTreeActive)
if isNodeSelected then
self.Icon:SetDesaturation(0);
self.ConduitBorder:SetDesaturation(0);
else
self.Icon:SetDesaturation(1);
self.ConduitBorder:SetDesaturation(1);
end
if isTreeActive then
self.Icon:SetVertexColor(1, 1, 1);
self.ConduitBorder:SetVertexColor(1, 1, 1);
else
self.Icon:SetVertexColor(0.66, 0.66, 0.66);
self.ConduitBorder:SetVertexColor(0.66, 0.66, 0.66);
end
end
function NarciConduitNodeButtonMixin:Shine()
self.Highlight:Show();
self.Highlight.Glow:Play();
end
function NarciConduitNodeButtonMixin:ShowTooltip()
local tooltip = NarciGameTooltip;
tooltip:Hide();
if self.conduitID or self.spellID then
tooltip:SetOwner(self, "ANCHOR_NONE");
tooltip:SetPoint("TOPLEFT", self, "TOPRIGHT", 2, 0);
if self.conduitType then
if self.isEnhanced then
tooltip:SetEnhancedConduit(self.conduitID, self.conduitRank or 1);
else
tooltip:SetConduit(self.conduitID, self.conduitRank or 1);
end
elseif self.spellID then
tooltip:SetSpellByID(self.spellID);
end
tooltip:Show();
end
end
function NarciConduitNodeButtonMixin:HideTooltip()
local tooltip = NarciGameTooltip;
tooltip:Hide();
end
function NarciConduitNodeButtonMixin:OnEnter()
self:ShowTooltip();
end
function NarciConduitNodeButtonMixin:OnLeave()
self:HideTooltip();
end
function NarciConduitNodeButtonMixin:OnClick()
C_Soulbinds.SelectNode(self.nodeID);
end
NarciSoulbindsConduitFrameMixin = {};
function NarciSoulbindsConduitFrameMixin:SetNameAndIcon()
local name, _, icon = GetSpellInfo(self.spellID);
local hasName;
if name and name ~= "" then
self.Name:SetText(name);
hasName = true;
else
QueueFrame:Add(self, self.SetNameAndIcon);
end
return hasName;
end
function NarciSoulbindsConduitFrameMixin:SetUp(conduitID, rank, spellID, conduitType)
local quality = GetConduitItemQualityByRank(rank); --C_Soulbinds.GetConduitQuality(traitID, rank)
rank = DataProvider:GetConduitItemLevel(rank);
if not conduitType then
conduitType = 3;
end
self.ConduitTypeIcon:SetTexCoord(conduitType*0.25, conduitType*0.25 + 0.25, 0, 1);
local hasName;
if not spellID or spellID == 0 then
self.Name:SetText(EMPTY);
quality = 0;
hasName = true;
else
self.spellID = spellID;
self:SetNameAndIcon();
end
SetTextColorByQuality(self.Name, quality);
if not rank or rank == 0 then
rank = "";
end
self.ItemLevel:SetText(rank);
return hasName
end
function NarciSoulbindsConduitFrameMixin:SetFailureReason(row, requiredRenownLevel)
self.ConduitTypeIcon:SetTexCoord(0.75, 1, 0, 1);
self.ItemLevel:SetText("");
if row and requiredRenownLevel then
self.Name:SetText( string.format(COVENANT_SANCTUM_LEVEL, requiredRenownLevel) ); --COVENANT_SANCTUM_RENOWN_REWARD_DESC
self.Name:SetTextColor(0.5, 0.2, 0.2);
end
end
function NarciSoulbindsConduitFrameMixin:OnEnter()
end
function NarciSoulbindsConduitFrameMixin:OnLeave()
end
function NarciSoulbindsConduitFrameMixin:OnLoad()
end
------------------------------------------------------------------
NarciSoulbindsCharacterButtonMixin = {};
--Selcet a Soulbind
function NarciSoulbindsCharacterButtonMixin:SetSelected(state)
self:UnlockHighlight();
if state then
self.Texture:SetTexCoord(0.5, 1, 0, 0.5);
self.Highlight:SetTexCoord(0.5, 1, 0.5, 1);
self.isSelected = true;
else
self.Texture:SetTexCoord(0, 0.5, 0, 0.5);
self.Highlight:SetTexCoord(0, 0.5, 0.5, 1);
self.isSelected = nil;
end
end
function NarciSoulbindsCharacterButtonMixin:OnClick()
if self.soulbindID and self.soulbindID ~= MainFrame.soulbindID then
MainFrame:SelectTree(self.soulbindID);
self:LockHighlight();
end
end
function NarciSoulbindsCharacterButtonMixin:OnEnter(motion, isGamepad)
local tooltip = NarciGameTooltip;
tooltip:Hide();
if self.soulbindName then
tooltip:SetOwner(self, "ANCHOR_NONE");
tooltip:SetPoint("LEFT", self, "RIGHT", 8, 0);
tooltip:SetText(self.soulbindName, 1, 1, 1);
if isGamepad then
tooltip:FadeIn();
MainFrame:DisplayInactiveNodes(true);
else
tooltip:Show();
end
MainFrame:AutoHideTooltip(isGamepad);
end
end
function NarciSoulbindsCharacterButtonMixin:OnLeave()
NarciGameTooltip:Hide();
end
function NarciSoulbindsCharacterButtonMixin:OnMouseDown()
--self.Texture:SetSize(30, 30);
--self.Highlight:SetSize(30, 30);
self.Texture:SetPoint("CENTER", 1, 0);
self.Highlight:SetPoint("CENTER", 1, 0);
end
function NarciSoulbindsCharacterButtonMixin:OnMouseUp()
--self.Texture:SetSize(32, 32);
--self.Highlight:SetSize(32, 32);
self.Texture:SetPoint("CENTER", 0, 0);
self.Highlight:SetPoint("CENTER", 0, 0);
end
----------------------------------------------------------------------------
NarciConduitFlatButtonMixin = CreateFromMixins(NarciShewedRectButtonMixin);
function NarciConduitFlatButtonMixin:OnLoad()
self:SetHighlight(false);
end
function NarciConduitFlatButtonMixin:OnEnter()
self:SetHighlight(true);
local tooltip = NarciGameTooltip;
tooltip:Hide();
if self.conduitID or (self.spellID and self.spellID ~= 0) then
tooltip:SetOwner(self, "ANCHOR_NONE");
tooltip:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, -2);
if self.conduitID then
tooltip:SetConduit(self.conduitID, self.conduitRank or 1)
elseif self.spellID then
tooltip:SetSpellByID(self.spellID);
end
tooltip:Show();
else
tooltip:SetOwner(self, "ANCHOR_NONE");
tooltip:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, -2);
tooltip:SetText(EMPTY, 1, 0.82, 0);
tooltip:Show();
end
Narci_NavBar:PauseTimer(true);
end
function NarciConduitFlatButtonMixin:OnLeave()
self:SetHighlight(false);
local tooltip = NarciGameTooltip;
tooltip:Hide();
Narci_NavBar:PauseTimer(false);
end
function NarciConduitFlatButtonMixin:SetConduit(nodeData)
if not (nodeData and nodeData.conduitRank) then
self:SetEmptyConduit();
return
end
local rank = nodeData.conduitRank;
local spellID;
if rank == 0 then
spellID = nodeData.spellID;
self.conduitID = nil;
self.conduitRank = nil;
else
local conduitID = nodeData.conduitID;
spellID = C_Soulbinds.GetConduitSpellID(conduitID, rank);
self.conduitID = conduitID;
self.conduitRank = rank;
end
self.spellID = spellID;
if not spellID or spellID == 0 then
self:SetEmptyConduit();
return
else
self:Show();
end
local conduitType = nodeData.conduitType;
conduitType = conduitType or 3;
self.ConduitTypeIcon:Show();
self.ConduitTypeIcon:SetTexCoord(conduitType*0.25, conduitType*0.25 + 0.25, 0, 1);
self.UnlockLevel:Hide();
self:SetNameAndIcon();
end
function NarciConduitFlatButtonMixin:SetNameAndIcon()
local name, _, icon = GetSpellInfo(self.spellID);
local hasName;
if name and name ~= "" then
--self.Icon:SetTexture(icon);
self:SetIcon(icon);
hasName = true;
else
QueueFrame:Add(self, self.SetNameAndIcon);
end
return hasName;
end
function NarciConduitFlatButtonMixin:SetUnlockLevel(unlockLevel)
self:SetColorTexture(0.1, 0.1, 0.1);
self.ConduitTypeIcon:Hide();
self.UnlockLevel:SetText(unlockLevel);
self.UnlockLevel:Show();
self:Show();
end
function NarciConduitFlatButtonMixin:SetEmptyConduit()
self:ShowAlert();
self.ConduitTypeIcon:Hide();
self.UnlockLevel:Hide();
self:Show();
end
local function CreateTabs(frame)
local d = 0.08;
frame.Background:SetAlpha(0.9);
frame.Background:SetVertexColor(d, d, d);
end
NarciSoulbindsMixin = {};
local dynamicEvents = {"SOULBIND_ACTIVATED", "SOULBIND_NODE_UPDATED", "SOULBIND_PATH_CHANGED", "SOULBIND_NODE_LEARNED",
"ACTIVE_TALENT_GROUP_CHANGED",
};
function NarciSoulbindsMixin:OnLoad()
MainFrame = self;
local numRow = MAX_ROW;
local frameHeight = (numRow + 1) * 24;
self:SetHeight(frameHeight);
self.AcitveNodesList:SetHeight(frameHeight);
NodesContainer = self.ConduitNodesFrame;
self.ConduitNodesFrame:SetHeight(frameHeight);
self.ConduitNodesFrame:SetScript("OnEnter", function(frame)
self:DisplayInactiveNodes(true);
end);
self.ConduitNodesFrame:SetScript("OnLeave", function(frame)
if not frame:IsMouseOver() then
self:DisplayInactiveNodes(false);
end
end);
self.buttons = {};
-------------------------------------------
--Collection ScrollFrame
CollectionFrame = self.ConduitCollection;
local deltaRatio = 1;
local speedRatio = 0.2;
local positionFunc;
local buttonHeight = 60;
local range = 120;
NarciAPI_ApplySmoothScrollToScrollFrame(CollectionFrame, deltaRatio, speedRatio, positionFunc, buttonHeight, range);
ConduitTooltip = self.ConduitTooltip;
-------------------------------------------
self:RegisterForDrag("LeftButton");
--Static Events
self:RegisterEvent("PLAYER_ENTERING_WORLD");
self:RegisterEvent("COVENANT_CHOSEN");
for i = 1, #dynamicEvents do
self:RegisterEvent(dynamicEvents[i]);
end
CreateTabs(self.TabHolder);
CreateTabs = nil;
--Update Subtrate Height
if MAX_ROW and MAX_ROW > 8 then
self.Stone:SetTexture(FILE_PATH.."StoneLong");
self.StoneMask:SetTexture(FILE_PATH.."StoneMaskLong");
self.Stone:SetSize(136, 272 * 2);
end
self:SetScript("OnLoad", nil);
self.OnLoad = nil;
end
function NarciSoulbindsMixin:OnShow()
if self.soulbindID ~= C_Soulbinds.GetActiveSoulbindID() then
self.needsUpdate = true;
end
if self.needsUpdate then
self:SelectTree();
end
end
function NarciSoulbindsMixin:OnHide()
--[[
for i = 1, #dynamicEvents do
self:UnregisterEvent(dynamicEvents[i]);
end
--]]
self:AutoHideTooltip(false);
end
function NarciSoulbindsMixin:OnEvent(event, ...)
if event == "PLAYER_ENTERING_WORLD" then
self:UnregisterEvent(event);
DataProvider:UpdateSpec();
self:UpdateCovenantData();
self:SelectTree();
After(1, function()
self:RequestUpdate();
Narci_NavBar:RequestUpdate("all");
end)
elseif event == "COVENANT_CHOSEN" then
local newCovenantID = ...;
self:UpdateCovenantData(newCovenantID);
Narci_NavBar:RequestUpdate("soulbinds");
elseif event == "SOULBIND_ACTIVATED" then
self:RequestUpdate();
self:PlayShine();
Narci_NavBar:RequestUpdate("soulbinds");
elseif event == "SOULBIND_PATH_CHANGED" or event == "SOULBIND_NODE_UPDATED" then
self:RequestUpdate();
Narci_NavBar:RequestUpdate("soulbinds");
elseif event == "ACTIVE_TALENT_GROUP_CHANGED" then
DataProvider:UpdateSpec();
end
--print(event);
end
function NarciSoulbindsMixin:GetActiveConduit()
--DEBUG
local soulbindID = C_Soulbinds.GetActiveSoulbindID();
local data = C_Soulbinds.GetSoulbindData(soulbindID);
if not data or not data.tree then return end;
local nodes = data.tree.nodes;
local conduitType, conduitState;
for i = 1, #nodes do
conduitState = nodes[i].state;
if conduitState and conduitState == 3 then
conduitType = nodes[i].conduitType;
if conduitType then
print(C_Soulbinds.GetConduitSpellID(nodes[i].conduitID, nodes[i].conduitRank))
else
print(nodes[i].spellID);
end
end
end
end
function NarciSoulbindsMixin:UpdateCovenantData(newCovenantID)
local covenantID = newCovenantID or C_Covenants.GetActiveCovenantID();
if not covenantID or covenantID == 0 then
--Covenant Unselected
return
end
local data = C_Covenants.GetCovenantData(covenantID);
self.defaultSoulbindID = DataProvider:GetDefaultSoulbindID(covenantID);
if data then
self.covenantData = data;
self:CreateChoiceButtons(data.soulbindIDs);
end
DataProvider.activeCovenantID = covenantID;
DataProvider:UpdateCovenantData();
end
function NarciSoulbindsMixin:CreateChoiceButtons(soulbindIDs)
if not self.buttons then
self.buttons = {};
end
local numChoices = #soulbindIDs;
local gap = 4;
local button;
for i = 1, numChoices do
button = self.buttons[i];
if not button then
button = CreateFrame("Button", nil, self, "NarciSoulbindsCharacterButton");
button:SetFrameLevel(self:GetFrameLevel() + 3);
button:SetPoint("CENTER", self, "LEFT", 0, (16 + gap)*(numChoices - 1)/2 - (16 + gap)*(i - 1));
self.buttons[i] = button;
end
button.soulbindID = soulbindIDs[i];
local soulbindData = C_Soulbinds.GetSoulbindData(soulbindIDs[i]);
if soulbindData and soulbindData.name then
button.soulbindName = soulbindData.name;
end
soulbindData = nil;
if i == 1 then
button:SetSelected(true);
else
button:SetSelected(false);
end
end
end
function NarciSoulbindsMixin:GetPipe(index, row, col, effectiveCol)
if not self.pipePool then
self.pipePool = {};
end
local pipe = self.pipePool[index];
if not pipe then
pipe = self:CreateTexture(nil, "OVERLAY", "NarciSoulbindsPipeTextureTemplate");
self.pipePool[index] = pipe;
end
pipe:ClearAllPoints();
pipe:Show();
local offsetY = 0;
if col == 2 and effectiveCol and effectiveCol ~= 2 then
--Flip Texture
offsetY = -24;
col = effectiveCol;
end
pipe:SetPoint("TOP", self, "TOPLEFT", 60 + 24*(col - 2), 24*(1 - row) + offsetY);
return pipe
end
function NarciSoulbindsMixin:UpdatePipeline(structure)
if self.pipePool then
for _, pipe in pairs(self.pipePool) do
pipe:Hide();
end
end
local numTex = 0;
local numRow = #structure;
local numCol = 3;
local numNodesPerRow = {};
for row = 1, numRow do
local numNodes = 0;
for col = 1, numCol do
if structure[row][col] ~= 0 then
numNodes = numNodes + 1;
end
end
numNodesPerRow[row] = numNodes;
end
for row = 1, numRow - 1 do
local numNodes = numNodesPerRow[row];
for col = 1, numCol do
local nodeState = structure[row][col];
if nodeState ~= 0 then
local texOffsetY, nextNodeState;
local nextRowData = structure[row + 1];
if false and numNodes == 3 then
numTex = numTex + 1;
nextNodeState = nextRowData[col];
if nodeState == 2 and nextNodeState == 2 then
texOffsetY = 0.5;
else
texOffsetY = 0;
end
local pipe = self:GetPipe(numTex, row, col, col);
pipe:SetTexCoord(0.265625, 0.515625, texOffsetY, texOffsetY + 0.5);
else
if nextRowData[col] and nextRowData[col] ~= 0 then
numTex = numTex + 1;
nextNodeState = nextRowData[col];
if nodeState == 2 and nextNodeState == 2 then
texOffsetY = 0.5;
else
texOffsetY = 0;
end
local pipe = self:GetPipe(numTex, row, col, col);
pipe:SetTexCoord(0.265625, 0.515625, texOffsetY, texOffsetY + 0.5);
end
if numNodes == 1 or numNodesPerRow[row + 1] ~= 3 then
if nextRowData[col - 1] and nextRowData[col - 1] ~= 0 then
numTex = numTex + 1;
nextNodeState = nextRowData[col - 1];
if nodeState == 2 and nextNodeState == 2 then
texOffsetY = 0.5;
else
texOffsetY = 0;
end
local pipe = self:GetPipe(numTex, row, col - 1, 3);
if col == 2 then
pipe:SetTexCoord(0, 0.25, texOffsetY, texOffsetY + 0.5);
else
pipe:SetTexCoord(0.53125, 0.78125, texOffsetY + 0.5, texOffsetY);
end
end
if nextRowData[col + 1] and nextRowData[col + 1] ~= 0 then
numTex = numTex + 1;
nextNodeState = nextRowData[col + 1];
if nodeState == 2 and nextNodeState == 2 then
texOffsetY = 0.5;
else
texOffsetY = 0;
end
local pipe = self:GetPipe(numTex, row, col + 1, 1);
if col == 2 then
pipe:SetTexCoord(0.53125, 0.78125, texOffsetY, texOffsetY + 0.5);
else
pipe:SetTexCoord(0, 0.25, texOffsetY + 0.5, texOffsetY);
end
end
end
end
end
end
end
--[[
for i = 1, #structure do
print(unpack(structure[i]))
end
--]]
end
function NarciSoulbindsMixin:PlayShine()
if self:IsVisible() then
ConduitNodeUtil:PlayShine();
end
end
local function GetNullStructure()
local structure = {};
local numRow, numCol = MAX_ROW, 3;
for row = 1, numRow do
structure[row] = {};
for col = 1, numCol do
structure[row][col] = 0;
end
end
return structure
end
local atlasInfo = {
[1] = { --"Kyrian"
texture = "Interface\\Soulbinds\\SoulbindsShotsKyrian",
[13] = {603, 558, 0.00048828125, 0.294921875, 0.0009765625, 0.5458984375}, --Kleia
[18] = {578, 558, 0.2958984375, 0.578125, 0.0009765625, 0.5458984375}, --Mikanikos
[7] = {578, 558, 0.5791015625, 0.861328125, 0.0009765625, 0.5458984375}, --Pelagos
},
[2] = { --"Venthyr"
texture = "Interface\\Soulbinds\\SoulbindsShotsVenthyr",
[3] = {603, 558, 0.6064453125, 0.90087890625, 0.0009765625, 0.5458984375}, --Draven
[8] = {629, 558, 0.00048828125, 0.3076171875, 0.0009765625, 0.5458984375}, --Nadjia
[9] = {608, 558, 0.30859375, 0.60546875, 0.0009765625, 0.5458984375}, --Theotar
},
[3]={ --Night Fae
texture = "Interface\\Soulbinds\\SoulbindsShotsFey",
[1]={578, 558, 0.591309, 0.873535, 0.000976562, 0.545898}, --Niya
[2]={603, 558, 0.000488281, 0.294922, 0.000976562, 0.545898}, --Dreamweaver
[6]={603, 558, 0.295898, 0.590332, 0.000976562, 0.545898}, --Korayn
},
[4]={ --Necrolord
texture = "Interface\\Soulbinds\\SoulbindsShotsNecrolords",
[5] = {629, 558, 0.00048828125, 0.3076171875, 0.0009765625, 0.5458984375}, --Emeni
[4] = {572, 558, 0.5888671875, 0.8681640625, 0.0009765625, 0.5458984375}, --Marileth
[10] = {572, 558, 0.30859375, 0.587890625, 0.0009765625, 0.5458984375}, --Heirmir
},
}
function NarciSoulbindsMixin:SetPortrait(index, desaturated)
local covenantID = DataProvider:GetActiveCovenantID();
if not atlasInfo[covenantID] then return end;
self.Portrait:SetDesaturated(desaturated);
if index == atlasInfo.lastIndex then
return;
else
atlasInfo.lastIndex = index;
end
local data = atlasInfo[covenantID][index];
if data then
local width, height, left, right, top, bottom = unpack(data);
local ratio = 0.8;
local effectiveWidth = (self:GetHeight())*width/height * ratio;
self.Portrait:SetWidth(effectiveWidth);
self.Portrait:SetTexture(atlasInfo[covenantID].texture);
self.Portrait:SetTexCoord(left, left + (right - left)*ratio, top, bottom);
self.Portrait.ActivateAnim:Play();
end
end
function NarciSoulbindsMixin:SelectTree(soulbindID)
local data;
local activeSoulbindID = C_Soulbinds.GetActiveSoulbindID();
if not activeSoulbindID or activeSoulbindID == 0 then
--Thread of Fate Alt
Narci_NavBar:SetSkipCovenant(true);
return
end
soulbindID = soulbindID or activeSoulbindID;
if soulbindID == 0 then
soulbindID = self.defaultSoulbindID;
end
data = C_Soulbinds.GetSoulbindData(soulbindID);
if not data or not data.tree then
return
end
local nodes = data.tree.nodes;
if not nodes then return end;
self.needsUpdate = nil;
local node, conduitType, conduitState, spellID, conduitRank, traitID;
local isTreeActive = soulbindID == activeSoulbindID;
local structure = GetNullStructure();
Narci_NavBar:SetSoulbindName(data.name, isTreeActive);
for i = 1, #nodes do
node = nodes[i];
if structure[node.row + 1] then
conduitState = node.state;
if conduitState then
if conduitState == 3 then --Selected
structure[node.row + 1][node.column + 1] = 2;
else
structure[node.row + 1][node.column + 1] = 1;
end
end
end
end
--Node Links
self:UpdatePipeline(structure);
--Soulbinds Character Button
if self.buttons then
for i = 1, #self.buttons do
self.buttons[i]:SetSelected(self.buttons[i].soulbindID == activeSoulbindID);
end
end
if isTreeActive then
self.Stone:SetVertexColor(1, 1, 1);
else
self.Stone:SetVertexColor(0.66, 0.66, 0.66);
end
self:SetPortrait(soulbindID, soulbindID ~= activeSoulbindID);
self.ActivateButton:Update(not isTreeActive, soulbindID);
self.soulbindID = soulbindID;
ConduitNodeUtil:BuildNodes(nodes, isTreeActive);
end
function NarciSoulbindsMixin:RequestUpdate()
if self:IsVisible() then
self:SelectTree();
else
self.needsUpdate = true;
end
end
function NarciSoulbindsMixin:SelectTab(tabIndex)
if tabIndex == 2 then
self.AcitveNodesList:Hide();
self.ConduitCollection:Show();
ConduitCollectionUtil:BuildList();
else
self.AcitveNodesList:Show();
self.ConduitCollection:Hide();
end
end
local function AutoHideTooltip_OnUpdate(self, elapsed)
self.countdown = self.countdown + elapsed;
if self.countdown > 1 then
self:AutoHideTooltip(false);
NarciGameTooltip:FadeOut();
end
end
function NarciSoulbindsMixin:AutoHideTooltip(state)
if state then
self.countdown = 0;
self:SetScript("OnUpdate", AutoHideTooltip_OnUpdate);
else
self.countdown = nil;
self:SetScript("OnUpdate", nil);
end
end
function NarciSoulbindsMixin:DisplayInactiveNodes(state)
if state then
FadeFrame(self.ConduitNodesFrame.InactiveNodesFrame, 0.15, 1);
else
FadeFrame(self.ConduitNodesFrame.InactiveNodesFrame, 0.5, 0);
end
end
--------------------------------------------------------------------------------------------
NarciSoulbindsActivateButtonMixin = CreateFromMixins(NarciUIShimmerButtonMixin);
function NarciSoulbindsActivateButtonMixin:OnLoad()
self:Preload();
self:SetState(true);
local animFly = NarciAPI_CreateAnimationFrame(0.35);
animFly:SetScript("OnUpdate", function(frame, elapsed)
frame.total = frame.total + elapsed;
local offsetY = outQuart(frame.total, frame.fromY, frame.toY, frame.duration);
if frame.total >= frame.duration then
offsetY = frame.toY;
frame:Hide();
end
self:SetPoint("CENTER", animFly.relativeTo, animFly.relativePoint, animFly.offsetX, offsetY);
end);
function self:PlayFlyAnimation(direction)
if direction == animFly.direction then
return
else
animFly.direction = direction;
end
animFly:Hide();
local _, fromY, toY;
_, animFly.relativeTo, animFly.relativePoint, animFly.offsetX, fromY = self:GetPoint();
animFly.fromY = fromY;
local baseY = 28;
if direction > 0 then
toY = -12;
else
toY = -36;
end
toY = toY + baseY;
animFly.toY = toY;
local duration = (toY - fromY)/24 * 0.35;
if duration ~= 0 then
if toY < fromY then
duration = -duration;
end
animFly.duration = duration;
animFly:Show();
end
end
end
function NarciSoulbindsActivateButtonMixin:OnEnter()
local tooltip = NarciGameTooltip;
tooltip:Hide();
if self:IsEnabled() then
self:HoldShimmer();
elseif self.tooltipText then
tooltip:SetOwner(self, "ANCHOR_NONE");
tooltip:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, -4);
tooltip:SetText(self.tooltipText, 1, 0, 0);
tooltip:Show();
end
end
function NarciSoulbindsActivateButtonMixin:OnLeave()
--self:StopShimmer();
NarciGameTooltip:Hide();
if self:IsEnabled() then
self:PlayShimmer();
end
end
function NarciSoulbindsActivateButtonMixin:SetState(isEnabled)
if isEnabled then
self.ButtonText:SetTextColor(0, 0, 0);
self.ButtonText:SetShadowColor(1, 1, 1);
self.Background:SetDesaturation(0);
self.Background:SetVertexColor(1, 1, 1);
self:Enable();
self:PlayShimmer();
else
self.ButtonText:SetTextColor(0.5, 0.5, 0.5);
self.ButtonText:SetShadowColor(0, 0, 0);
self.Background:SetDesaturation(1);
self.Background:SetVertexColor(0.25, 0.25, 0.25);
self:Disable();
self:StopShimmer();
end
end
function NarciSoulbindsActivateButtonMixin:Toggle(visible)
if visible then
FadeFrame(self, 0.15, 1);
self:PlayFlyAnimation(1);
self.ButtonText:Show();
self.isVisible = visible;
else
FadeFrame(self, 0.15, 0);
self:PlayFlyAnimation(-1);
self.ButtonText:Hide();
self:StopShimmer();
self.isVisible = nil;
end
end
function NarciSoulbindsActivateButtonMixin:Check()
if not self.soulbindID then
self:Toggle(false);
return
end
local available, errorDescription = C_Soulbinds.CanActivateSoulbind(self.soulbindID);
if available then
self.tooltipText = nil;
else
self.tooltipText = errorDescription;
end
self:SetState(available);
end
function NarciSoulbindsActivateButtonMixin:Update(visible, soulbindID)
self.soulbindID = soulbindID;
self:Toggle(visible);
end
function NarciSoulbindsActivateButtonMixin:OnClick()
local soulbindID = self.soulbindID;
if soulbindID then
local available, errorDescription = C_Soulbinds.CanActivateSoulbind(soulbindID);
if available then
C_Soulbinds.ActivateSoulbind(self.soulbindID);
self:Toggle(false);
else
--print(errorDescription);
end
else
end
end
function NarciSoulbindsActivateButtonMixin:OnShow()
--UNIT_AREA_CHANGED --new event in 9.0.2 function????
self:Check();
self:RegisterEvent("PLAYER_UPDATE_RESTING");
end
function NarciSoulbindsActivateButtonMixin:OnHide()
self:UnregisterEvent("PLAYER_UPDATE_RESTING");
end
function NarciSoulbindsActivateButtonMixin:OnEvent(event, ...)
self:Check();
end
----------------------------------------------
--Conduit Collection
local GetMouseFocus = addon.TransitionAPI.GetMouseFocus;
local delayExecute = NarciAPI_CreateAnimationFrame(0.65);
delayExecute:SetScript("OnUpdate", function(self, elapsed)
self.total = self.total + elapsed;
if self.total >= self.duration then
self:Hide();
local widget = GetMouseFocus();
if widget and widget == self.lastFocus then
if widget.ShowBonusText then
widget:ShowBonusText();
end
end
end
end);
NarciConduitCollectionButtonMixin = {};
function NarciConduitCollectionButtonMixin:SetConduitFromData(conduitData)
self.conduitID = conduitData.conduitID;
self.conduitRank = conduitData.conduitRank;
self.conduitItemID = conduitData.conduitItemID;
self.ItemLevel:SetText(conduitData.conduitItemLevel);
SetConduitItemQualityColorByItemLevel(self, conduitData.conduitItemLevel, DataProvider:IsCurrentSpec(conduitData.conduitSpecSetID));
self:SetNameAndIcon();
end
function NarciConduitCollectionButtonMixin:SetNameAndIcon()
if not self.conduitID then return end;
local name = DataProvider:GetConduitName(self.conduitID, self.conduitItemID);
local icon = C_Item.GetItemIconByID(self.conduitItemID);
local hasName;
if name and name ~= "" and icon then
self.Name:SetText(name);
self.Icon:SetTexture(icon);
hasName = true;
else
QueueFrame:Add(self, self.SetNameAndIcon);
end
return hasName;
end
function NarciConduitCollectionButtonMixin:ShowTooltip()
delayExecute:Hide();
delayExecute.lastFocus = nil;
if not (self.conduitID and self.conduitRank) then
ConduitTooltip:Hide();
end;
ConduitTooltip:FadeInHighlight(self);
delayExecute.lastFocus = self;
delayExecute:Show();
end
function NarciConduitCollectionButtonMixin:ShowBonusText()
local id = self.conduitID;
local rank = self.conduitRank;
local effect = DataProvider:GetConduitDescription(id, rank, false);
if effect then
local textLeft, textRight;
for r = rank + 1, math.min(rank + 3, CONDUIT_MAX_RANK) do
local effect1, effect2 = DataProvider:GetConduitDescription(id, r, true);
local itemLevel = DataProvider:GetConduitItemLevel(r);
if effect1 and itemLevel then
if effect2 then
effect1 = effect1.." "..effect2;
end
end
if textLeft then
textLeft = textLeft .."\n"..itemLevel;
else
textLeft = itemLevel;
end
if textRight then
textRight = textRight .."\n"..effect1;
else
textRight = effect1;
end
end
ConduitTooltip:SetButtonTooltip(self, effect, textLeft, textRight);
return true;
else
QueueFrame:Add(self, self.ShowBonusText);
end
return false
end
function NarciConduitCollectionButtonMixin:OnEnter()
CollectionFrame:HighlightButton(self);
self:ShowTooltip();
SetCursor("Interface/CURSOR/Item.blp");
end
function NarciConduitCollectionButtonMixin:OnLeave()
CollectionFrame:HighlightButton();
NarciGameTooltip:Hide();
ConduitTooltip:Hide();
delayExecute:Hide();
ResetCursor();
end
--Conduit Category
NarciConduitCollectionCategoryButtonMixin = {};
function NarciConduitCollectionCategoryButtonMixin:ResetAnchor()
if not self.isDefaultAnchor then
self.isAnchorDrawer = nil;
self.isDefaultAnchor = true;
self.isAnchorTop = nil;
self:SetPoint("TOP", self:GetParent(), "TOP", 0, 0);
end
end
function NarciConduitCollectionCategoryButtonMixin:AnchorToTop()
if not self.isAnchorTop then
self.isAnchorDrawer = nil;
self.isAnchorTop = true;
self.isDefaultAnchor = nil;
self:SetPoint("TOP", CollectionFrame, "TOP", -6, 2);
end
end
function NarciConduitCollectionCategoryButtonMixin:AnchorToDrawer()
if not self.isAnchorDrawer then
self.isAnchorDrawer = true;
self.isAnchorTop = nil;
self.isDefaultAnchor = nil;
self:SetPoint("TOP", self:GetParent().Drawer, "BOTTOM", 0, 24);
end
end
function NarciConduitCollectionCategoryButtonMixin:SetConduitType(conduitType)
if not conduitType then
conduitType = 3;
end
self.conduitType = conduitType;
if conduitType == 0 then
self.ButtonText:SetText(CONDUIT_FINESSE);
elseif conduitType == 1 then
self.ButtonText:SetText(CONDUIT_POTENCY);
elseif conduitType == 2 then
self.ButtonText:SetText(CONDUIT_ENDURANCE);
elseif conduitType == 3 then
self.ButtonText:SetText("Unknown Type");
end
self.ConduitTypeIcon:SetTexCoord(conduitType*0.25, conduitType*0.25 + 0.25, 0, 1);
end
function NarciConduitCollectionCategoryButtonMixin:SetDrawerHeight(height)
height = math.max(height, 24);
self.expandedHeight = height;
self:SetExpanded(true);
end
function NarciConduitCollectionCategoryButtonMixin:SetExpanded(state)
self.isExpanded = state;
local Drawer = self:GetParent().Drawer
if state then
Drawer:Show();
Drawer:SetHeight(self.expandedHeight or 24);
self.ExpandMark:SetTexCoord(0, 0.5, 0, 1);
else
Drawer:Hide();
Drawer:SetHeight(24);
self.ExpandMark:SetTexCoord(0.5, 1, 0, 1);
end
end
function NarciConduitCollectionCategoryButtonMixin:OnMouseDown()
self.Background:SetPoint("CENTER", 1, -1);
end
function NarciConduitCollectionCategoryButtonMixin:OnMouseUp()
self.Background:SetPoint("CENTER", 0, 0);
end
function NarciConduitCollectionCategoryButtonMixin:OnClick()
self:SetExpanded(not self.isExpanded);
ConduitCollectionUtil:UpdateScrollRange();
end
function NarciConduitCollectionCategoryButtonMixin:OnEnter()
end
function NarciConduitCollectionCategoryButtonMixin:OnLeave()
end
----------------------------------------------
--Conduit Tooltip
local function AddComparisionByHyperlink(frame, link)
if not link then return end;
local itemID = strmatch(link, "item:(%d+):");
local isConduit, knownLevel, description = DataProvider:GetKnownConduitItemLevel(itemID);
if isConduit then
frame:AddLine(" ");
if knownLevel then
frame:AddDoubleLine("Known", knownLevel, 1, 1, 1, 1, 1, 1);
if description then
frame:AddLine(description, nil, nil, nil, true);
end
else
frame:AddLine("Unlearned", nil, nil, nil, true);
end
frame:Show();
end
end
local TooltipHooks = {};
TooltipHooks.hookedFrames = {
--[tooltip name] = hasHooked,
};
function TooltipHooks:Hook(tooltip)
local name = tooltip:GetName();
if self.hookedFrames[name] == nil then
self.hookedFrames[name] = true;
--Conduit Item
--[[
tooltip:HookScript("OnTooltipSetItem", function(frame)
local _, link = frame:GetItem();
AddComparisionByHyperlink(frame, link);
end);
--]]
--Conduit Collection
hooksecurefunc(tooltip, "SetConduit", function(frame, conduitID, currentRank)
--print("Current Rank: "..currentRank)
if not self.hookedFrames[name] then return end;
local hasHeader = false;
for rank = currentRank + 1, math.min(currentRank + 3, CONDUIT_MAX_RANK) do
local effect1, effect2 = DataProvider:GetConduitDescription(conduitID, rank, true);
local itemLevel = DataProvider:GetConduitItemLevel(rank);
if effect1 and itemLevel then
if not hasHeader then
hasHeader = true;
frame:AddDoubleLine("Effect", "Item Level", 0.5, 0.5, 0.5, 0.5, 0.5, 0.5);
end
if effect2 then
frame:AddDoubleLine(effect1.." "..effect2, itemLevel, 1, 1, 1, nil, nil, nil);
else
frame:AddDoubleLine(effect1, itemLevel, 1, 1, 1, nil, nil, nil);
end
end
end
end)
else
self.hookedFrames[name] = true;
end
end
function TooltipHooks:Unhook(tooltip)
local name = tooltip:GetName();
if self.hookedFrames[name] then
self.hookedFrames[name] = false;
end
end
--[[
hooksecurefunc(GameTooltip, "SetBagItem", function(frame, bag, slot)
local _, link = frame:GetItem();
AddComparisionByHyperlink(frame, link);
end)
--]]
TooltipHooks:Hook(NarciGameTooltip);
do
function addon.SettingFunctions.EnableConduitTooltip(state, db)
if state == nil then
state = db["ConduitTooltip"];
end
if state then
TooltipHooks:Hook(GameTooltip);
else
TooltipHooks:Unhook(GameTooltip);
end
end
end
--[[
column 0, 1, 2
row 0, 1, ..., 7
Enum.SoulbindNodeState:
0 Unavailable
1 Unselected
2 Selectable
3 Selected
Enum.SoulbindConduitType:
0 Finesse
1 Potency
2 Endurance
3 Flex
--]]