local ADDON_NAME , Internal = ...
local L = Internal.L
local GetActiveCovenantID = C_Covenants.GetActiveCovenantID
local GetCovenantData = C_Covenants.GetCovenantData
local ActivateSoulbind = C_Soulbinds.ActivateSoulbind
local GetActiveSoulbindID = C_Soulbinds.GetActiveSoulbindID
local GetSoulbindData = C_Soulbinds.GetSoulbindData
local GetSoulbindNode = C_Soulbinds.GetNode
local SelectSoulbindNode = C_Soulbinds.SelectNode
local HelpTipBox_Anchor = Internal.HelpTipBox_Anchor ;
local HelpTipBox_SetText = Internal.HelpTipBox_SetText ;
local function CompareSets ( a , b )
if a.soulbindID ~= b.soulbindID then
return false
end
if not tCompare ( a.nodes , b.nodes , 10 ) then
return false
end
if type ( a.restrictions ) ~= type ( b.restrictions ) and not tCompare ( a.restrictions , b.restrictions , 10 ) then
return false
end
return true
end
--[[ SOULBIND DROPDOWN ]]
BtWLoadoutsSoulbindDropDownMixin = { }
function BtWLoadoutsSoulbindDropDownMixin : OnShow ( )
if not self.initialized then
UIDropDownMenu_Initialize ( self , self.Init ) ;
self.initialized = true
end
end
function BtWLoadoutsSoulbindDropDownMixin : Init ( level , menuList )
local info = UIDropDownMenu_CreateInfo ( ) ;
local selected = self : GetValue ( ) ;
info.func = function ( button , arg1 , arg2 , checked )
self : SetValue ( button , arg1 , arg2 , checked )
end
if ( level or 1 ) == 1 then
if self.includeNone then
info.text = L [ " None " ] ;
info.checked = selected == nil ;
UIDropDownMenu_AddButton ( info , level ) ;
end
for covenantID = 1 , 4 do
local covenantData = GetCovenantData ( covenantID )
info.text = covenantData.name ;
info.hasArrow , info.menuList = true , covenantData.ID ;
info.keepShownOnClick = true ;
info.notCheckable = true ;
UIDropDownMenu_AddButton ( info , level ) ;
end
else
local covenantData = GetCovenantData ( menuList )
for _ , soulbindID in ipairs ( covenantData.soulbindIDs ) do
local soulbindData = GetSoulbindData ( soulbindID )
info.text = soulbindData.name ;
info.arg1 = soulbindData.ID ;
info.checked = selected == soulbindData.ID ;
UIDropDownMenu_AddButton ( info , level ) ;
end
end
end
function BtWLoadoutsSoulbindDropDownMixin : GetValue ( )
end
function BtWLoadoutsSoulbindDropDownMixin : SetValue ( button , classIndex , classFile , checked )
end
--[[ SET HANDLING ]]
local function UpdateSetFilters ( set )
set.filters = set.filters or { }
local filters = set.filters
wipe ( filters )
Internal.UpdateRestrictionFilters ( set )
filters.soulbind = set.soulbindID
local soulbindData = GetSoulbindData ( set.soulbindID )
filters.covenant = soulbindData.covenantID
set.filters = filters
return set
end
local function RefreshSet ( set )
local nodes = set.nodes or { }
local conduits = set.conduits or { }
wipe ( nodes )
wipe ( conduits )
local soulbindData = GetSoulbindData ( set.soulbindID )
for _ , node in ipairs ( soulbindData.tree . nodes ) do
if node.state == Enum.SoulbindNodeState . Selected then
nodes [ node.ID ] = true
end
local conduitID = C_Soulbinds.GetInstalledConduitID ( node.ID )
if conduitID ~= 0 then
conduits [ node.ID ] = conduitID
end
end
set.nodes = nodes
set.conduits = conduits
set.classID = select ( 3 , UnitClass ( " player " ) )
return UpdateSetFilters ( set )
end
local function AddSet ( )
local soulbindID = GetActiveSoulbindID ( )
if soulbindID == 0 then
soulbindID = 7 -- Default to pelagos because why not
end
local soulbindData = GetSoulbindData ( soulbindID )
return Internal.AddSet ( " soulbinds " , RefreshSet ( {
soulbindID = soulbindID ,
name = format ( L [ " New %s Set " ] , soulbindData.name ) ,
useCount = 0 ,
nodes = { } ,
} ) )
end
local function DeleteSet ( id )
Internal.DeleteSet ( BtWLoadoutsSets.soulbinds , id ) ;
if type ( id ) == " table " then
id = id.setID ;
end
for _ , set in pairs ( BtWLoadoutsSets.profiles ) do
if type ( set ) == " table " then
for index , setID in ipairs ( set.soulbinds ) do
if setID == id then
table.remove ( set.soulbinds , index )
end
end
end
end
local frame = BtWLoadoutsFrame.Soulbinds ;
local set = frame.set ;
if set.setID == id then
frame.set = nil
BtWLoadoutsFrame : Update ( ) ;
end
end
local function GetSet ( id )
if type ( id ) == " table " then
return id ;
elseif id < 0 then -- Fake a soulbind set
local set = GetSoulbindData ( math.abs ( id ) )
set.soulbindID = set.ID
set.setID = - set.ID
set.ID = nil
return set
else
return BtWLoadoutsSets.soulbinds [ id ]
end
end
local function GetSets ( id , ... )
if id ~= nil then
return GetSet ( id ) , GetSets ( ... ) ;
end
end
-- In General, For Player, For Player Spec
local function SetIsValid ( set )
set = GetSet ( set ) ;
local soulbindData = GetSoulbindData ( set.soulbindID )
local playerCovenantID = GetActiveCovenantID ( )
return true , ( soulbindData.covenantID == playerCovenantID )
end
local function GetByName ( name )
return Internal.GetSetByName ( " soulbinds " , name , SetIsValid )
end
local function IsSetActive ( set , ignoreConduits )
if set.soulbindID then
local covenantID = GetActiveCovenantID ( )
if covenantID then
local soulbindID = GetActiveSoulbindID ( )
local soulbindData = GetSoulbindData ( set.soulbindID )
-- The target soulbind is unlocked, is for the players covenant, so is valid for the character
if soulbindData.unlocked and soulbindData.covenantID == covenantID then
if set.soulbindID ~= soulbindID then
return false
end
if set.nodes then
for nodeID in pairs ( set.nodes ) do
local node = GetSoulbindNode ( nodeID )
if node.state ~= Enum.SoulbindNodeState . Selected and node.state ~= Enum.SoulbindNodeState . Unavailable then
return false
end
end
if set.conduits and not ignoreConduits then
for nodeID , conduitID in pairs ( set.conduits ) do
local node = GetSoulbindNode ( nodeID )
if C_Soulbinds.GetInstalledConduitID ( nodeID ) ~= conduitID and node.state ~= Enum.SoulbindNodeState . Unavailable then
return false
end
end
end
end
end
end
end
return true ;
end
local function IsSetConduitsActive ( set )
if set.conduits and next ( set.conduits ) then
for nodeID , conduitID in pairs ( set.conduits ) do
local node = GetSoulbindNode ( nodeID )
if node and node.state ~= Enum.SoulbindNodeState . Unavailable and C_Soulbinds.GetInstalledConduitID ( nodeID ) ~= conduitID then
return false
end
end
end
return true ;
end
local function CombineSets ( result , state , ... )
result = result or { } ;
local classID = select ( 3 , UnitClass ( " player " ) )
local covenantID = GetActiveCovenantID ( )
if covenantID then
for i = 1 , select ( ' # ' , ... ) do
local set = select ( i , ... ) ;
local soulbindData = GetSoulbindData ( set.soulbindID )
if soulbindData.covenantID == covenantID and soulbindData.unlocked and ( set.classID == nil or set.classID == classID ) and Internal.AreRestrictionsValidForPlayer ( set.restrictions ) then
result.soulbindID = set.soulbindID
result.nodes = set.nodes
result.conduits = set.conduits
end
end
if state and state.blockers and not IsSetActive ( result ) then
local conduitsActive = IsSetConduitsActive ( result )
if not conduitsActive then
state.blockers [ Internal.GetForgeOfBondsBlocker ( ) ] = IsSetActive ( result , true )
end
-- If the conduits are already set we wont need to go to a forge so we may need a tome or rested area
-- If we need to swap conduits but allowPartial has been set we may need a tome or rested area
if not C_Soulbinds.CanSwitchActiveSoulbindTreeBranch ( ) and ( conduitsActive or state.allowPartial ) then
state.blockers [ Internal.GetRestedTomeBlocker ( ) ] = true
end
state.blockers [ Internal.GetCombatBlocker ( ) ] = true
state.blockers [ Internal.GetMythicPlusBlocker ( ) ] = true
state.blockers [ Internal.GetJailersChainBlocker ( ) ] = true
end
end
return result ;
end
local function ActivateSet ( set , state )
local complete = true ;
if not IsSetActive ( set ) then
local soulbindData = GetSoulbindData ( set.soulbindID )
if C_Soulbinds.GetActiveSoulbindID ( ) ~= set.soulbindID then
Internal.LogMessage ( " Switching soulbind to %s " , soulbindData.name )
ActivateSoulbind ( set.soulbindID )
end
if set.nodes and C_Soulbinds.CanSwitchActiveSoulbindTreeBranch ( ) then
for nodeID in pairs ( set.nodes ) do
local node = GetSoulbindNode ( nodeID )
if node.state ~= Enum.SoulbindNodeState . Selected and node.state ~= Enum.SoulbindNodeState . Unavailable then
Internal.LogMessage ( " Switching soulbind tree node to %d " , nodeID )
SelectSoulbindNode ( nodeID )
complete = false
end
end
local socketedAny = false
if set.conduits and C_Soulbinds.CanModifySoulbind ( ) then
for nodeID , conduitID in pairs ( set.conduits ) do
local node = GetSoulbindNode ( nodeID )
if C_Soulbinds.GetInstalledConduitID ( nodeID ) ~= conduitID and node.state ~= Enum.SoulbindNodeState . Unavailable then
Internal.LogMessage ( " Socket conduit %d into node %d " , conduitID , nodeID )
C_Soulbinds.ModifyNode ( nodeID , conduitID , Enum.SoulbindConduitTransactionType . Install )
socketedAny = true
end
end
end
if socketedAny then
C_Soulbinds.CommitPendingConduitsInSoulbind ( set.soulbindID )
complete = false
end
end
end
return complete
end
local function CheckErrors ( errorState , set )
set = GetSet ( set )
if not Internal.AreRestrictionsValidFor ( set.restrictions , errorState.specID ) then
return L [ " Incompatible Restrictions " ]
end
end
local genericSoulbindSets = { }
for covenantID = 1 , 4 do
local covenantData = GetCovenantData ( covenantID )
for index , soulbindID in ipairs ( covenantData.soulbindIDs ) do
local soulbindData = GetSoulbindData ( soulbindID )
genericSoulbindSets [ # genericSoulbindSets + 1 ] = UpdateSetFilters ( {
setID = - soulbindData.ID ,
name = soulbindData.name ,
soulbindID = soulbindData.ID ,
covenantID = covenantID ,
order = - 20 + ( index * 4 + covenantID ) ,
} )
end
end
-- Initializes the set dropdown menu for the Loadouts page
local function SetDropDownInit ( self , set , index )
local temp = { }
for _ , set in pairs ( genericSoulbindSets ) do
temp [ set.setID ] = set
end
for _ , set in pairs ( BtWLoadoutsSets.soulbinds ) do
if type ( set ) == " table " then
temp [ set.setID ] = set
end
end
self : SetSelected ( index and set.soulbinds [ index ] or nil )
self : SetSets ( temp )
self : SetFilters ( BtWLoadoutsFilters.soulbinds )
self : SetCategories ( BtWLoadoutsCategories.soulbinds )
self : SetIncludeNone ( index ~= nil )
self : OnItemClick ( function ( self , setID )
local index = index or ( # set.soulbinds + 1 )
if set.soulbinds [ index ] then
local subset = GetSet ( set.soulbinds [ index ] ) ;
subset.useCount = ( subset.useCount or 1 ) - 1 ;
end
if setID == " none " then
table.remove ( set.soulbinds , index ) ;
elseif setID == " new " then
local subset = AddSet ( ) ;
set.soulbinds [ index ] = subset.setID ;
BtWLoadoutsFrame.Soulbinds . set = subset ;
PanelTemplates_SetTab ( BtWLoadoutsFrame , BtWLoadoutsFrame.Soulbinds : GetID ( ) ) ;
BtWLoadoutsHelpTipFlags [ " TUTORIAL_CREATE_TALENT_SET " ] = true ;
else -- Change to a specific set
set.soulbinds [ index ] = setID ;
end
if set.soulbinds [ index ] then
local subset = GetSet ( set.soulbinds [ index ] ) ;
subset.useCount = ( subset.useCount or 0 ) + 1 ;
end
self : SetSelected ( set.soulbinds [ index ] )
CloseDropDownMenus ( )
BtWLoadoutsFrame : Update ( ) ;
end )
end
Internal.AddLoadoutSegment ( {
id = " soulbinds " ,
name = L [ " Soulbinds " ] ,
events = " SOULBIND_ACTIVATED " ,
add = AddSet ,
get = GetSets ,
getByName = GetSets ,
combine = CombineSets ,
isActive = IsSetActive ,
activate = ActivateSet ,
dropdowninit = SetDropDownInit ,
checkerrors = CheckErrors ,
export = function ( set )
return {
version = 1 ,
name = set.name ,
soulbindID = set.soulbindID ,
nodes = set.nodes ,
restrictions = set.restrictions ,
}
end ,
import = function ( source , version , name , ... )
assert ( version == 1 )
local soulbindID = source.soulbindID or ...
return Internal.AddSet ( " soulbinds " , UpdateSetFilters ( {
soulbindID = soulbindID ,
name = name or source.name ,
useCount = 0 ,
nodes = source.nodes ,
restrictions = source.restrictions ,
} ) )
end ,
getByValue = function ( set )
-- If the nodes is missing then we just want the faux set
if set.nodes == nil then
return GetSet ( - set.soulbindID )
else
return Internal.GetSetByValue ( BtWLoadoutsSets.soulbinds , set , CompareSets )
end
end ,
verify = function ( source , ... )
local soulbindID = source.soulbindID or ...
if not soulbindID or not GetSoulbindData ( soulbindID ) then
return false , L [ " Invalid soulbind " ]
end
if source.nodes ~= nil and type ( source.nodes ) ~= " table " then
return false , L [ " Invalid nodes " ]
end
if source.restrictions ~= nil and type ( source.restrictions ) ~= " table " then
return false , L [ " Missing restrictions " ]
end
-- @TODO verify talent ids?
return true
end ,
} )
-- [[ TAB UI ]]
local function GetConduitName ( conduitType )
if conduitType == Enum.SoulbindConduitType . Potency then
return CONDUIT_POTENCY ;
elseif conduitType == Enum.SoulbindConduitType . Endurance then
return CONDUIT_ENDURANCE ;
elseif conduitType == Enum.SoulbindConduitType . Finesse then
return CONDUIT_FINESSE ;
end
end
local function GetConduitEmblemAtlas ( conduitType )
if conduitType == Enum.SoulbindConduitType . Potency then
return " Soulbinds_Tree_Conduit_Icon_Attack " ;
elseif conduitType == Enum.SoulbindConduitType . Endurance then
return " Soulbinds_Tree_Conduit_Icon_Protect " ;
elseif conduitType == Enum.SoulbindConduitType . Finesse then
return " Soulbinds_Tree_Conduit_Icon_Utility " ;
end
end
local function GetConduitIconScale ( conduitType )
if conduitType == Enum.SoulbindConduitType . Potency then
return 1.0 ;
elseif conduitType == Enum.SoulbindConduitType . Endurance then
return 1.0 ;
elseif conduitType == Enum.SoulbindConduitType . Finesse then
return 1.0 ;
end
end
local conduits = {
{ -- Stalwart Guardian
conduitID = 5 ,
conduitType = 2 ,
conduitSpecSetID = 168 ,
covenantID = 0 ,
conduitItemID = 180842 ,
} ,
{ -- Brutal Vitality
conduitID = 7 ,
conduitType = 2 ,
conduitSpecSetID = 168 ,
covenantID = 0 ,
conduitItemID = 180844 ,
} ,
{ -- Inspiring Presence
conduitID = 8 ,
conduitType = 0 ,
conduitSpecSetID = 168 ,
covenantID = 0 ,
conduitItemID = 180847 ,
} ,
{ -- Safeguard
conduitID = 9 ,
conduitType = 0 ,
conduitSpecSetID = 168 ,
covenantID = 0 ,
conduitItemID = 180896 ,
} ,
{ -- Fueled by Violence
conduitID = 10 ,
conduitType = 2 ,
conduitSpecSetID = 42 ,
covenantID = 0 ,
conduitItemID = 180932 ,
} ,
{ -- Ashen Juggernaut
conduitID = 11 ,
conduitType = 1 ,
conduitSpecSetID = 168 ,
covenantID = 0 ,
conduitItemID = 180933 ,
} ,
{ -- Crash the Ramparts
conduitID = 12 ,
conduitType = 1 ,
conduitSpecSetID = 40 ,
covenantID = 0 ,
conduitItemID = 180935 ,
} ,
{ -- Cacophonous Roar
conduitID = 13 ,
conduitType = 0 ,
conduitSpecSetID = 168 ,
covenantID = 0 ,
conduitItemID = 180943 ,
} ,
{ -- Merciless Bonegrinder
conduitID = 14 ,
conduitType = 1 ,
conduitSpecSetID = 40 ,
covenantID = 0 ,
conduitItemID = 180944 ,
} ,
{ -- Harm Denial
conduitID = 15 ,
conduitType = 2 ,
conduitSpecSetID = 164 ,
covenantID = 0 ,
conduitItemID = 181373 ,
} ,
{ -- Inner Fury
conduitID = 16 ,
conduitType = 1 ,
conduitSpecSetID = 26 ,
covenantID = 0 ,
conduitItemID = 181376 ,
} ,
{ -- Unrelenting Cold
conduitID = 17 ,
conduitType = 1 ,
conduitSpecSetID = 22 ,
covenantID = 0 ,
conduitItemID = 181383 ,
} ,
{ -- Shivering Core
conduitID = 18 ,
conduitType = 1 ,
conduitSpecSetID = 22 ,
covenantID = 0 ,
conduitItemID = 181389 ,
} ,
{ -- Calculated Strikes
conduitID = 19 ,
conduitType = 1 ,
conduitSpecSetID = 26 ,
covenantID = 0 ,
conduitItemID = 181435 ,
} ,
{ -- Icy Propulsion
conduitID = 20 ,
conduitType = 1 ,
conduitSpecSetID = 22 ,
covenantID = 0 ,
conduitItemID = 181455 ,
} ,
{ -- Ice Bite
conduitID = 21 ,
conduitType = 1 ,
conduitSpecSetID = 22 ,
covenantID = 0 ,
conduitItemID = 181461 ,
} ,
{ -- Coordinated Offensive
conduitID = 22 ,
conduitType = 1 ,
conduitSpecSetID = 26 ,
covenantID = 0 ,
conduitItemID = 181462 ,
} ,
{ -- Winter's Protection
conduitID = 23 ,
conduitType = 0 ,
conduitSpecSetID = 162 ,
covenantID = 0 ,
conduitItemID = 181464 ,
} ,
{ -- Xuen's Bond
conduitID = 24 ,
conduitType = 1 ,
conduitSpecSetID = 26 ,
covenantID = 0 ,
conduitItemID = 181465 ,
} ,
{ -- Grounding Breath
conduitID = 25 ,
conduitType = 2 ,
conduitSpecSetID = 164 ,
covenantID = 0 ,
conduitItemID = 181466 ,
} ,
{ -- Flow of Time
conduitID = 26 ,
conduitType = 0 ,
conduitSpecSetID = 162 ,
covenantID = 0 ,
conduitItemID = 181467 ,
} ,
{ -- Indelible Victory
conduitID = 27 ,
conduitType = 2 ,
conduitSpecSetID = 168 ,
covenantID = 0 ,
conduitItemID = 181469 ,
} ,
{ -- Jade Bond
conduitID = 28 ,
conduitType = 1 ,
conduitSpecSetID = 25 ,
covenantID = 0 ,
conduitItemID = 181495 ,
} ,
{ -- Grounding Surge
conduitID = 29 ,
conduitType = 0 ,
conduitSpecSetID = 162 ,
covenantID = 0 ,
conduitItemID = 181498 ,
} ,
{ -- Infernal Cascade
conduitID = 30 ,
conduitType = 1 ,
conduitSpecSetID = 23 ,
covenantID = 0 ,
conduitItemID = 181504 ,
} ,
{ -- Resplendent Mist
conduitID = 31 ,
conduitType = 1 ,
conduitSpecSetID = 25 ,
covenantID = 0 ,
conduitItemID = 181505 ,
} ,
{ -- Master Flame
conduitID = 32 ,
conduitType = 1 ,
conduitSpecSetID = 23 ,
covenantID = 0 ,
conduitItemID = 181506 ,
} ,
{ -- Fortifying Ingredients
conduitID = 33 ,
conduitType = 2 ,
conduitSpecSetID = 164 ,
covenantID = 0 ,
conduitItemID = 181508 ,
} ,
{ -- Arcane Prodigy
conduitID = 34 ,
conduitType = 1 ,
conduitSpecSetID = 21 ,
covenantID = 0 ,
conduitItemID = 181509 ,
} ,
{ -- Lingering Numbness
conduitID = 35 ,
conduitType = 0 ,
conduitSpecSetID = 164 ,
covenantID = 0 ,
conduitItemID = 181510 ,
} ,
{ -- Nether Precision
conduitID = 36 ,
conduitType = 1 ,
conduitSpecSetID = 21 ,
covenantID = 0 ,
conduitItemID = 181511 ,
} ,
{ -- Dizzying Tumble
conduitID = 37 ,
conduitType = 0 ,
conduitSpecSetID = 164 ,
covenantID = 0 ,
conduitItemID = 181512 ,
} ,
{ -- Discipline of the Grove
conduitID = 38 ,
conduitType = 1 ,
conduitSpecSetID = 162 ,
covenantID = 3 ,
conduitItemID = 181539 ,
} ,
{ -- Gift of the Lich
conduitID = 39 ,
conduitType = 1 ,
conduitSpecSetID = 162 ,
covenantID = 4 ,
conduitItemID = 181553 ,
} ,
{ -- Ire of the Ascended
conduitID = 40 ,
conduitType = 1 ,
conduitSpecSetID = 162 ,
covenantID = 1 ,
conduitItemID = 181600 ,
} ,
{ -- Swift Transference
conduitID = 41 ,
conduitType = 0 ,
conduitSpecSetID = 164 ,
covenantID = 0 ,
conduitItemID = 181624 ,
} ,
{ -- Tumbling Technique
conduitID = 42 ,
conduitType = 0 ,
conduitSpecSetID = 164 ,
covenantID = 0 ,
conduitItemID = 181640 ,
} ,
{ -- Siphoned Malice
conduitID = 43 ,
conduitType = 1 ,
conduitSpecSetID = 162 ,
covenantID = 2 ,
conduitItemID = 181639 ,
} ,
{ -- Rising Sun Revival
conduitID = 44 ,
conduitType = 1 ,
conduitSpecSetID = 25 ,
covenantID = 0 ,
conduitItemID = 181641 ,
} ,
{ -- Cryo-Freeze
conduitID = 45 ,
conduitType = 2 ,
conduitSpecSetID = 162 ,
covenantID = 0 ,
conduitItemID = 181698 ,
} ,
{ -- Scalding Brew
conduitID = 46 ,
conduitType = 1 ,
conduitSpecSetID = 24 ,
covenantID = 0 ,
conduitItemID = 181700 ,
} ,
{ -- Celestial Effervescence
conduitID = 47 ,
conduitType = 2 ,
conduitSpecSetID = 24 ,
covenantID = 0 ,
conduitItemID = 181705 ,
} ,
{ -- Diverted Energy
conduitID = 48 ,
conduitType = 2 ,
conduitSpecSetID = 162 ,
covenantID = 0 ,
conduitItemID = 181707 ,
} ,
{ -- Unnerving Focus
conduitID = 49 ,
conduitType = 2 ,
conduitSpecSetID = 42 ,
covenantID = 0 ,
conduitItemID = 181709 ,
} ,
{ -- Depths of Insanity
conduitID = 50 ,
conduitType = 1 ,
conduitSpecSetID = 41 ,
covenantID = 0 ,
conduitItemID = 181712 ,
} ,
{ -- Magi's Brand
conduitID = 51 ,
conduitType = 1 ,
conduitSpecSetID = 21 ,
covenantID = 0 ,
conduitItemID = 181734 ,
} ,
{ -- Hack and Slash
conduitID = 52 ,
conduitType = 1 ,
conduitSpecSetID = 41 ,
covenantID = 0 ,
conduitItemID = 181735 ,
} ,
{ -- Flame Accretion
conduitID = 53 ,
conduitType = 1 ,
conduitSpecSetID = 23 ,
covenantID = 0 ,
conduitItemID = 181736 ,
} ,
{ -- Nourishing Chi
conduitID = 54 ,
conduitType = 1 ,
conduitSpecSetID = 25 ,
covenantID = 0 ,
conduitItemID = 181737 ,
} ,
{ -- Artifice of the Archmage
conduitID = 55 ,
conduitType = 1 ,
conduitSpecSetID = 21 ,
covenantID = 0 ,
conduitItemID = 181738 ,
} ,
{ -- Evasive Stride
conduitID = 56 ,
conduitType = 2 ,
conduitSpecSetID = 24 ,
covenantID = 0 ,
conduitItemID = 181740 ,
} ,
{ -- Walk with the Ox
conduitID = 57 ,
conduitType = 1 ,
conduitSpecSetID = 24 ,
covenantID = 0 ,
conduitItemID = 181742 ,
} ,
{ -- Incantation of Swiftness
conduitID = 58 ,
conduitType = 0 ,
conduitSpecSetID = 162 ,
covenantID = 0 ,
conduitItemID = 181756 ,
} ,
{ -- Strike with Clarity
conduitID = 59 ,
conduitType = 1 ,
conduitSpecSetID = 164 ,
covenantID = 1 ,
conduitItemID = 181759 ,
} ,
{ -- Bone Marrow Hops
conduitID = 60 ,
conduitType = 1 ,
conduitSpecSetID = 164 ,
covenantID = 4 ,
conduitItemID = 181770 ,
} ,
{ -- Tempest Barrier
conduitID = 61 ,
conduitType = 2 ,
conduitSpecSetID = 162 ,
covenantID = 0 ,
conduitItemID = 181769 ,
} ,
{ -- Imbued Reflections
conduitID = 62 ,
conduitType = 1 ,
conduitSpecSetID = 164 ,
covenantID = 2 ,
conduitItemID = 181774 ,
} ,
{ -- Way of the Fae
conduitID = 63 ,
conduitType = 1 ,
conduitSpecSetID = 164 ,
covenantID = 3 ,
conduitItemID = 181775 ,
} ,
{ -- Vicious Contempt
conduitID = 64 ,
conduitType = 1 ,
conduitSpecSetID = 41 ,
covenantID = 0 ,
conduitItemID = 181776 ,
} ,
{ -- Eternal Hunger
conduitID = 65 ,
conduitType = 1 ,
conduitSpecSetID = 7 ,
covenantID = 0 ,
conduitItemID = 181786 ,
} ,
{ -- Translucent Image
conduitID = 66 ,
conduitType = 2 ,
conduitSpecSetID = 166 ,
covenantID = 0 ,
conduitItemID = 181826 ,
} ,
{ -- Move with Grace
conduitID = 67 ,
conduitType = 0 ,
conduitSpecSetID = 166 ,
covenantID = 0 ,
conduitItemID = 181827 ,
} ,
{ -- Chilled Resilience
conduitID = 68 ,
conduitType = 0 ,
conduitSpecSetID = 43 ,
covenantID = 0 ,
conduitItemID = 181834 ,
} ,
{ -- Clear Mind
conduitID = 69 ,
conduitType = 0 ,
conduitSpecSetID = 166 ,
covenantID = 0 ,
conduitItemID = 181837 ,
} ,
{ -- Spirit Drain
conduitID = 70 ,
conduitType = 0 ,
conduitSpecSetID = 43 ,
covenantID = 0 ,
conduitItemID = 181836 ,
} ,
{ -- Charitable Soul
conduitID = 71 ,
conduitType = 2 ,
conduitSpecSetID = 166 ,
covenantID = 0 ,
conduitItemID = 181838 ,
} ,
{ -- Light's Inspiration
conduitID = 72 ,
conduitType = 2 ,
conduitSpecSetID = 166 ,
covenantID = 0 ,
conduitItemID = 181840 ,
} ,
{ -- Power Unto Others
conduitID = 73 ,
conduitType = 0 ,
conduitSpecSetID = 166 ,
covenantID = 0 ,
conduitItemID = 181842 ,
} ,
{ -- Reinforced Shell
conduitID = 74 ,
conduitType = 2 ,
conduitSpecSetID = 43 ,
covenantID = 0 ,
conduitItemID = 181841 ,
} ,
{ -- Shining Radiance
conduitID = 75 ,
conduitType = 1 ,
conduitSpecSetID = 31 ,
covenantID = 0 ,
conduitItemID = 181843 ,
} ,
{ -- Pain Transformation
conduitID = 76 ,
conduitType = 1 ,
conduitSpecSetID = 31 ,
covenantID = 0 ,
conduitItemID = 181844 ,
} ,
{ -- Exaltation
conduitID = 77 ,
conduitType = 1 ,
conduitSpecSetID = 31 ,
covenantID = 0 ,
conduitItemID = 181845 ,
} ,
{ -- Lasting Spirit
conduitID = 78 ,
conduitType = 1 ,
conduitSpecSetID = 32 ,
covenantID = 0 ,
conduitItemID = 181847 ,
} ,
{ -- Accelerated Cold
conduitID = 79 ,
conduitType = 1 ,
conduitSpecSetID = 6 ,
covenantID = 0 ,
conduitItemID = 181848 ,
} ,
{ -- Withering Plague
conduitID = 80 ,
conduitType = 1 ,
conduitSpecSetID = 5 ,
covenantID = 0 ,
conduitItemID = 181866 ,
} ,
{ -- Swift Penitence
conduitID = 81 ,
conduitType = 1 ,
conduitSpecSetID = 31 ,
covenantID = 0 ,
conduitItemID = 181867 ,
} ,
{ -- Focused Mending
conduitID = 82 ,
conduitType = 1 ,
conduitSpecSetID = 32 ,
covenantID = 0 ,
conduitItemID = 181942 ,
} ,
{ -- Eradicating Blow
conduitID = 83 ,
conduitType = 1 ,
conduitSpecSetID = 6 ,
covenantID = 0 ,
conduitItemID = 181943 ,
} ,
{ -- Resonant Words
conduitID = 84 ,
conduitType = 1 ,
conduitSpecSetID = 32 ,
covenantID = 0 ,
conduitItemID = 181944 ,
} ,
{ -- Mental Recovery
conduitID = 85 ,
conduitType = 0 ,
conduitSpecSetID = 166 ,
covenantID = 0 ,
conduitItemID = 181962 ,
} ,
{ -- Blood Bond
conduitID = 86 ,
conduitType = 2 ,
conduitSpecSetID = 5 ,
covenantID = 0 ,
conduitItemID = 181963 ,
} ,
{ -- Courageous Ascension
conduitID = 87 ,
conduitType = 1 ,
conduitSpecSetID = 166 ,
covenantID = 1 ,
conduitItemID = 181974 ,
} ,
{ -- Hardened Bones
conduitID = 88 ,
conduitType = 2 ,
conduitSpecSetID = 43 ,
covenantID = 0 ,
conduitItemID = 181975 ,
} ,
{ -- Embrace Death
conduitID = 89 ,
conduitType = 1 ,
conduitSpecSetID = 7 ,
covenantID = 0 ,
conduitItemID = 181980 ,
} ,
{ -- Festering Transfusion
conduitID = 90 ,
conduitType = 1 ,
conduitSpecSetID = 166 ,
covenantID = 4 ,
conduitItemID = 181981 ,
} ,
{ -- Everfrost
conduitID = 91 ,
conduitType = 1 ,
conduitSpecSetID = 6 ,
covenantID = 0 ,
conduitItemID = 181982 ,
} ,
{ -- Astral Protection
conduitID = 92 ,
conduitType = 2 ,
conduitSpecSetID = 13 ,
covenantID = 0 ,
conduitItemID = 182105 ,
} ,
{ -- Refreshing Waters
conduitID = 93 ,
conduitType = 2 ,
conduitSpecSetID = 13 ,
covenantID = 0 ,
conduitItemID = 182106 ,
} ,
{ -- Vital Accretion
conduitID = 94 ,
conduitType = 2 ,
conduitSpecSetID = 13 ,
covenantID = 0 ,
conduitItemID = 182107 ,
} ,
{ -- Thunderous Paws
conduitID = 95 ,
conduitType = 0 ,
conduitSpecSetID = 13 ,
covenantID = 0 ,
conduitItemID = 182108 ,
} ,
{ -- Totemic Surge
conduitID = 96 ,
conduitType = 0 ,
conduitSpecSetID = 13 ,
covenantID = 0 ,
conduitItemID = 182109 ,
} ,
{ -- Crippling Hex
conduitID = 97 ,
conduitType = 0 ,
conduitSpecSetID = 13 ,
covenantID = 0 ,
conduitItemID = 182110 ,
} ,
{ -- Spiritual Resonance
conduitID = 98 ,
conduitType = 0 ,
conduitSpecSetID = 13 ,
covenantID = 0 ,
conduitItemID = 182111 ,
} ,
{ -- Fleeting Wind
conduitID = 99 ,
conduitType = 0 ,
conduitSpecSetID = 43 ,
covenantID = 0 ,
conduitItemID = 182113 ,
} ,
{ -- Pyroclastic Shock
conduitID = 100 ,
conduitType = 1 ,
conduitSpecSetID = 11 ,
covenantID = 0 ,
conduitItemID = 182125 ,
} ,
{ -- Fae Fermata
conduitID = 101 ,
conduitType = 1 ,
conduitSpecSetID = 166 ,
covenantID = 3 ,
conduitItemID = 182129 ,
} ,
{ -- High Voltage
conduitID = 102 ,
conduitType = 1 ,
conduitSpecSetID = 11 ,
covenantID = 0 ,
conduitItemID = 182126 ,
} ,
{ -- Shake the Foundations
conduitID = 103 ,
conduitType = 1 ,
conduitSpecSetID = 11 ,
covenantID = 0 ,
conduitItemID = 182127 ,
} ,
{ -- Call of Flame
conduitID = 104 ,
conduitType = 1 ,
conduitSpecSetID = 11 ,
covenantID = 0 ,
conduitItemID = 182128 ,
} ,
{ -- Shattered Perceptions
conduitID = 105 ,
conduitType = 1 ,
conduitSpecSetID = 166 ,
covenantID = 2 ,
conduitItemID = 182130 ,
} ,
{ -- Unending Grip
conduitID = 106 ,
conduitType = 0 ,
conduitSpecSetID = 43 ,
covenantID = 0 ,
conduitItemID = 182132 ,
} ,
{ -- Haunting Apparitions
conduitID = 107 ,
conduitType = 1 ,
conduitSpecSetID = 33 ,
covenantID = 0 ,
conduitItemID = 182131 ,
} ,
{ -- Insatiable Appetite
conduitID = 108 ,
conduitType = 2 ,
conduitSpecSetID = 43 ,
covenantID = 0 ,
conduitItemID = 182133 ,
} ,
{ -- Unruly Winds
conduitID = 109 ,
conduitType = 1 ,
conduitSpecSetID = 12 ,
covenantID = 0 ,
conduitItemID = 182134 ,
} ,
{ -- Focused Lightning
conduitID = 110 ,
conduitType = 1 ,
conduitSpecSetID = 12 ,
covenantID = 0 ,
conduitItemID = 182135 ,
} ,
{ -- Magma Fist
conduitID = 111 ,
conduitType = 1 ,
conduitSpecSetID = 12 ,
covenantID = 0 ,
conduitItemID = 182137 ,
} ,
{ -- Chilled to the Core
conduitID = 112 ,
conduitType = 1 ,
conduitSpecSetID = 12 ,
covenantID = 0 ,
conduitItemID = 182136 ,
} ,
{ -- Mind Devourer
conduitID = 113 ,
conduitType = 1 ,
conduitSpecSetID = 33 ,
covenantID = 0 ,
conduitItemID = 182138 ,
} ,
{ -- Rabid Shadows
conduitID = 114 ,
conduitType = 1 ,
conduitSpecSetID = 33 ,
covenantID = 0 ,
conduitItemID = 182139 ,
} ,
{ -- Dissonant Echoes
conduitID = 115 ,
conduitType = 1 ,
conduitSpecSetID = 33 ,
covenantID = 0 ,
conduitItemID = 182140 ,
} ,
{ -- Holy Oration
conduitID = 116 ,
conduitType = 1 ,
conduitSpecSetID = 32 ,
covenantID = 0 ,
conduitItemID = 182141 ,
} ,
{ -- Embrace of Earth
conduitID = 117 ,
conduitType = 1 ,
conduitSpecSetID = 4 ,
covenantID = 0 ,
conduitItemID = 182142 ,
} ,
{ -- Swirling Currents
conduitID = 118 ,
conduitType = 1 ,
conduitSpecSetID = 4 ,
covenantID = 0 ,
conduitItemID = 182143 ,
} ,
{ -- Heavy Rainfall
conduitID = 119 ,
conduitType = 1 ,
conduitSpecSetID = 4 ,
covenantID = 0 ,
conduitItemID = 182145 ,
} ,
{ -- Nature's Focus
conduitID = 120 ,
conduitType = 1 ,
conduitSpecSetID = 4 ,
covenantID = 0 ,
conduitItemID = 182144 ,
} ,
{ -- Meat Shield
conduitID = 121 ,
conduitType = 2 ,
conduitSpecSetID = 5 ,
covenantID = 0 ,
conduitItemID = 182187 ,
} ,
{ -- Unleashed Frenzy
conduitID = 122 ,
conduitType = 1 ,
conduitSpecSetID = 6 ,
covenantID = 0 ,
conduitItemID = 182201 ,
} ,
{ -- Debilitating Malady
conduitID = 123 ,
conduitType = 1 ,
conduitSpecSetID = 5 ,
covenantID = 0 ,
conduitItemID = 182203 ,
} ,
{ -- Convocation of the Dead
conduitID = 124 ,
conduitType = 1 ,
conduitSpecSetID = 7 ,
covenantID = 0 ,
conduitItemID = 182206 ,
} ,
{ -- Lingering Plague
conduitID = 125 ,
conduitType = 1 ,
conduitSpecSetID = 7 ,
covenantID = 0 ,
conduitItemID = 182208 ,
} ,
{ -- Impenetrable Gloom
conduitID = 126 ,
conduitType = 1 ,
conduitSpecSetID = 43 ,
covenantID = 2 ,
conduitItemID = 182288 ,
} ,
{ -- Brutal Grasp
conduitID = 127 ,
conduitType = 1 ,
conduitSpecSetID = 43 ,
covenantID = 4 ,
conduitItemID = 182292 ,
} ,
{ -- Proliferation
conduitID = 128 ,
conduitType = 1 ,
conduitSpecSetID = 43 ,
covenantID = 1 ,
conduitItemID = 182295 ,
} ,
{ -- Divine Call
conduitID = 129 ,
conduitType = 2 ,
conduitSpecSetID = 30 ,
covenantID = 0 ,
conduitItemID = 182304 ,
} ,
{ -- Fel Defender
conduitID = 130 ,
conduitType = 2 ,
conduitSpecSetID = 8 ,
covenantID = 0 ,
conduitItemID = 182316 ,
} ,
{ -- Viscous Ink
conduitID = 131 ,
conduitType = 2 ,
conduitSpecSetID = 8 ,
covenantID = 0 ,
conduitItemID = 182318 ,
} ,
{ -- Shattered Restoration
conduitID = 132 ,
conduitType = 2 ,
conduitSpecSetID = 8 ,
covenantID = 0 ,
conduitItemID = 182317 ,
} ,
{ -- Shielding Words
conduitID = 133 ,
conduitType = 2 ,
conduitSpecSetID = 30 ,
covenantID = 0 ,
conduitItemID = 182307 ,
} ,
{ -- Felfire Haste
conduitID = 134 ,
conduitType = 0 ,
conduitSpecSetID = 8 ,
covenantID = 0 ,
conduitItemID = 182324 ,
} ,
{ -- Ravenous Consumption
conduitID = 135 ,
conduitType = 0 ,
conduitSpecSetID = 8 ,
covenantID = 0 ,
conduitItemID = 182325 ,
} ,
{ -- Enfeebled Mark
conduitID = 137 ,
conduitType = 1 ,
conduitSpecSetID = 163 ,
covenantID = 1 ,
conduitItemID = 182321 ,
} ,
{ -- Demonic Parole
conduitID = 138 ,
conduitType = 0 ,
conduitSpecSetID = 8 ,
covenantID = 0 ,
conduitItemID = 182330 ,
} ,
{ -- Empowered Release
conduitID = 139 ,
conduitType = 1 ,
conduitSpecSetID = 163 ,
covenantID = 2 ,
conduitItemID = 182331 ,
} ,
{ -- Spirit Attunement
conduitID = 140 ,
conduitType = 1 ,
conduitSpecSetID = 163 ,
covenantID = 3 ,
conduitItemID = 182335 ,
} ,
{ -- Golden Path
conduitID = 141 ,
conduitType = 2 ,
conduitSpecSetID = 30 ,
covenantID = 0 ,
conduitItemID = 182336 ,
} ,
{ -- Pure Concentration
conduitID = 142 ,
conduitType = 0 ,
conduitSpecSetID = 30 ,
covenantID = 0 ,
conduitItemID = 182338 ,
} ,
{ -- Necrotic Barrage
conduitID = 143 ,
conduitType = 1 ,
conduitSpecSetID = 163 ,
covenantID = 4 ,
conduitItemID = 182339 ,
} ,
{ -- Fel Celerity
conduitID = 144 ,
conduitType = 0 ,
conduitSpecSetID = 167 ,
covenantID = 0 ,
conduitItemID = 182340 ,
} ,
{ -- Lost in Darkness
conduitID = 145 ,
conduitType = 0 ,
conduitSpecSetID = 8 ,
covenantID = 0 ,
conduitItemID = 182344 ,
} ,
{ -- Elysian Dirge
conduitID = 146 ,
conduitType = 1 ,
conduitSpecSetID = 13 ,
covenantID = 1 ,
conduitItemID = 182345 ,
} ,
{ -- Tumbling Waves
conduitID = 147 ,
conduitType = 1 ,
conduitSpecSetID = 13 ,
covenantID = 4 ,
conduitItemID = 182346 ,
} ,
{ -- Essential Extraction
conduitID = 148 ,
conduitType = 1 ,
conduitSpecSetID = 13 ,
covenantID = 3 ,
conduitItemID = 182347 ,
} ,
{ -- Lavish Harvest
conduitID = 149 ,
conduitType = 1 ,
conduitSpecSetID = 13 ,
covenantID = 2 ,
conduitItemID = 182348 ,
} ,
{ -- Relentless Onslaught
conduitID = 150 ,
conduitType = 1 ,
conduitSpecSetID = 9 ,
covenantID = 0 ,
conduitItemID = 182368 ,
} ,
{ -- Dancing with Fate
conduitID = 151 ,
conduitType = 1 ,
conduitSpecSetID = 9 ,
covenantID = 0 ,
conduitItemID = 182383 ,
} ,
{ -- Serrated Glaive
conduitID = 152 ,
conduitType = 1 ,
conduitSpecSetID = 9 ,
covenantID = 0 ,
conduitItemID = 182384 ,
} ,
{ -- Growing Inferno
conduitID = 153 ,
conduitType = 1 ,
conduitSpecSetID = 8 ,
covenantID = 0 ,
conduitItemID = 182385 ,
} ,
{ -- Piercing Verdict
conduitID = 154 ,
conduitType = 1 ,
conduitSpecSetID = 168 ,
covenantID = 1 ,
conduitItemID = 182440 ,
} ,
{ -- Marksman's Advantage
conduitID = 157 ,
conduitType = 2 ,
conduitSpecSetID = 163 ,
covenantID = 0 ,
conduitItemID = 182441 ,
} ,
{ -- Veteran's Repute
conduitID = 158 ,
conduitType = 1 ,
conduitSpecSetID = 168 ,
covenantID = 4 ,
conduitItemID = 182442 ,
} ,
{ -- Light's Barding
conduitID = 159 ,
conduitType = 0 ,
conduitSpecSetID = 30 ,
covenantID = 0 ,
conduitItemID = 182448 ,
} ,
{ -- Resolute Barrier
conduitID = 160 ,
conduitType = 2 ,
conduitSpecSetID = 167 ,
covenantID = 0 ,
conduitItemID = 182449 ,
} ,
{ -- Wrench Evil
conduitID = 161 ,
conduitType = 0 ,
conduitSpecSetID = 30 ,
covenantID = 0 ,
conduitItemID = 182456 ,
} ,
{ -- Accrued Vitality
conduitID = 162 ,
conduitType = 2 ,
conduitSpecSetID = 167 ,
covenantID = 0 ,
conduitItemID = 182460 ,
} ,
{ -- Echoing Blessings
conduitID = 163 ,
conduitType = 0 ,
conduitSpecSetID = 30 ,
covenantID = 0 ,
conduitItemID = 182461 ,
} ,
{ -- Expurgation
conduitID = 164 ,
conduitType = 1 ,
conduitSpecSetID = 29 ,
covenantID = 0 ,
conduitItemID = 182462 ,
} ,
{ -- Harrowing Punishment
conduitID = 165 ,
conduitType = 1 ,
conduitSpecSetID = 168 ,
covenantID = 2 ,
conduitItemID = 182463 ,
} ,
{ -- Harmony of the Tortollan
conduitID = 166 ,
conduitType = 2 ,
conduitSpecSetID = 163 ,
covenantID = 0 ,
conduitItemID = 182464 ,
} ,
{ -- Truth's Wake
conduitID = 167 ,
conduitType = 1 ,
conduitSpecSetID = 29 ,
covenantID = 0 ,
conduitItemID = 182465 ,
} ,
{ -- Shade of Terror
conduitID = 168 ,
conduitType = 0 ,
conduitSpecSetID = 167 ,
covenantID = 0 ,
conduitItemID = 182466 ,
} ,
{ -- Mortal Combo
conduitID = 169 ,
conduitType = 1 ,
conduitSpecSetID = 40 ,
covenantID = 0 ,
conduitItemID = 182468 ,
} ,
{ -- Rejuvenating Wind
conduitID = 170 ,
conduitType = 2 ,
conduitSpecSetID = 163 ,
covenantID = 0 ,
conduitItemID = 182469 ,
} ,
{ -- Demonic Momentum
conduitID = 171 ,
conduitType = 0 ,
conduitSpecSetID = 167 ,
covenantID = 0 ,
conduitItemID = 182470 ,
} ,
{ -- Soul Furnace
conduitID = 172 ,
conduitType = 1 ,
conduitSpecSetID = 10 ,
covenantID = 0 ,
conduitItemID = 182471 ,
} ,
{ -- Resilience of the Hunter
conduitID = 173 ,
conduitType = 2 ,
conduitSpecSetID = 163 ,
covenantID = 0 ,
conduitItemID = 182476 ,
} ,
{ -- Corrupting Leer
conduitID = 174 ,
conduitType = 1 ,
conduitSpecSetID = 37 ,
covenantID = 0 ,
conduitItemID = 182478 ,
} ,
{ -- Reversal of Fortune
conduitID = 175 ,
conduitType = 0 ,
conduitSpecSetID = 163 ,
covenantID = 0 ,
conduitItemID = 182480 ,
} ,
{ -- Templar's Vindication
conduitID = 176 ,
conduitType = 1 ,
conduitSpecSetID = 29 ,
covenantID = 0 ,
conduitItemID = 182559 ,
} ,
{ -- Enkindled Spirit
conduitID = 177 ,
conduitType = 1 ,
conduitSpecSetID = 27 ,
covenantID = 0 ,
conduitItemID = 182582 ,
} ,
{ -- Cheetah's Vigor
conduitID = 178 ,
conduitType = 0 ,
conduitSpecSetID = 163 ,
covenantID = 0 ,
conduitItemID = 182584 ,
} ,
{ -- Demon Muzzle
conduitID = 179 ,
conduitType = 2 ,
conduitSpecSetID = 10 ,
covenantID = 0 ,
conduitItemID = 182598 ,
} ,
{ -- Roaring Fire
conduitID = 180 ,
conduitType = 2 ,
conduitSpecSetID = 10 ,
covenantID = 0 ,
conduitItemID = 182604 ,
} ,
{ -- Tactical Retreat
conduitID = 181 ,
conduitType = 0 ,
conduitSpecSetID = 163 ,
covenantID = 0 ,
conduitItemID = 182605 ,
} ,
{ -- Virtuous Command
conduitID = 182 ,
conduitType = 1 ,
conduitSpecSetID = 29 ,
covenantID = 0 ,
conduitItemID = 182608 ,
} ,
{ -- Ferocious Appetite
conduitID = 183 ,
conduitType = 1 ,
conduitSpecSetID = 44 ,
covenantID = 0 ,
conduitItemID = 182610 ,
} ,
{ -- Resplendent Light
conduitID = 184 ,
conduitType = 1 ,
conduitSpecSetID = 27 ,
covenantID = 0 ,
conduitItemID = 182622 ,
} ,
{ -- One With the Beast
conduitID = 185 ,
conduitType = 1 ,
conduitSpecSetID = 44 ,
covenantID = 0 ,
conduitItemID = 182621 ,
} ,
{ -- Show of Force
conduitID = 186 ,
conduitType = 1 ,
conduitSpecSetID = 42 ,
covenantID = 0 ,
conduitItemID = 182624 ,
} ,
{ -- Repeat Decree
conduitID = 187 ,
conduitType = 1 ,
conduitSpecSetID = 8 ,
covenantID = 1 ,
conduitItemID = 182646 ,
} ,
{ -- Sharpshooter's Focus
conduitID = 188 ,
conduitType = 1 ,
conduitSpecSetID = 14 ,
covenantID = 0 ,
conduitItemID = 182648 ,
} ,
{ -- Brutal Projectiles
conduitID = 189 ,
conduitType = 1 ,
conduitSpecSetID = 14 ,
covenantID = 0 ,
conduitItemID = 182649 ,
} ,
{ -- Destructive Reverberations
conduitID = 190 ,
conduitType = 1 ,
conduitSpecSetID = 168 ,
covenantID = 3 ,
conduitItemID = 182651 ,
} ,
{ -- Disturb the Peace
conduitID = 191 ,
conduitType = 0 ,
conduitSpecSetID = 168 ,
covenantID = 0 ,
conduitItemID = 182656 ,
} ,
{ -- Deadly Chain
conduitID = 192 ,
conduitType = 1 ,
conduitSpecSetID = 14 ,
covenantID = 0 ,
conduitItemID = 182657 ,
} ,
{ -- Focused Light
conduitID = 193 ,
conduitType = 1 ,
conduitSpecSetID = 27 ,
covenantID = 0 ,
conduitItemID = 182667 ,
} ,
{ -- Untempered Dedication
conduitID = 194 ,
conduitType = 1 ,
conduitSpecSetID = 27 ,
covenantID = 0 ,
conduitItemID = 182675 ,
} ,
{ -- Vengeful Shock
conduitID = 195 ,
conduitType = 1 ,
conduitSpecSetID = 28 ,
covenantID = 0 ,
conduitItemID = 182681 ,
} ,
{ -- Punish the Guilty
conduitID = 196 ,
conduitType = 1 ,
conduitSpecSetID = 28 ,
covenantID = 0 ,
conduitItemID = 182677 ,
} ,
{ -- Resolute Defender
conduitID = 197 ,
conduitType = 2 ,
conduitSpecSetID = 28 ,
covenantID = 0 ,
conduitItemID = 182684 ,
} ,
{ -- Increased Scrutiny
conduitID = 198 ,
conduitType = 1 ,
conduitSpecSetID = 8 ,
covenantID = 2 ,
conduitItemID = 182685 ,
} ,
{ -- Powerful Precision
conduitID = 199 ,
conduitType = 1 ,
conduitSpecSetID = 14 ,
covenantID = 0 ,
conduitItemID = 182686 ,
} ,
{ -- Brooding Pool
conduitID = 200 ,
conduitType = 1 ,
conduitSpecSetID = 8 ,
covenantID = 4 ,
conduitItemID = 182706 ,
} ,
{ -- Rolling Agony
conduitID = 201 ,
conduitType = 1 ,
conduitSpecSetID = 37 ,
covenantID = 0 ,
conduitItemID = 182736 ,
} ,
{ -- Focused Malignancy
conduitID = 202 ,
conduitType = 1 ,
conduitSpecSetID = 37 ,
covenantID = 0 ,
conduitItemID = 182743 ,
} ,
{ -- Withering Bolt
conduitID = 203 ,
conduitType = 1 ,
conduitSpecSetID = 37 ,
covenantID = 0 ,
conduitItemID = 182747 ,
} ,
{ -- Borne of Blood
conduitID = 204 ,
conduitType = 1 ,
conduitSpecSetID = 39 ,
covenantID = 0 ,
conduitItemID = 182748 ,
} ,
{ -- Carnivorous Stalkers
conduitID = 205 ,
conduitType = 1 ,
conduitSpecSetID = 39 ,
covenantID = 0 ,
conduitItemID = 182750 ,
} ,
{ -- Tyrant's Soul
conduitID = 206 ,
conduitType = 1 ,
conduitSpecSetID = 39 ,
covenantID = 0 ,
conduitItemID = 182751 ,
} ,
{ -- Fel Commando
conduitID = 207 ,
conduitType = 1 ,
conduitSpecSetID = 39 ,
covenantID = 0 ,
conduitItemID = 182752 ,
} ,
{ -- Duplicitous Havoc
conduitID = 208 ,
conduitType = 1 ,
conduitSpecSetID = 38 ,
covenantID = 0 ,
conduitItemID = 182754 ,
} ,
{ -- Royal Decree
conduitID = 209 ,
conduitType = 2 ,
conduitSpecSetID = 28 ,
covenantID = 0 ,
conduitItemID = 182753 ,
} ,
{ -- The Long Summer
conduitID = 210 ,
conduitType = 1 ,
conduitSpecSetID = 30 ,
covenantID = 3 ,
conduitItemID = 182767 ,
} ,
{ -- Ashen Remains
conduitID = 211 ,
conduitType = 1 ,
conduitSpecSetID = 38 ,
covenantID = 0 ,
conduitItemID = 182755 ,
} ,
{ -- Combusting Engine
conduitID = 212 ,
conduitType = 1 ,
conduitSpecSetID = 38 ,
covenantID = 0 ,
conduitItemID = 182769 ,
} ,
{ -- Righteous Might
conduitID = 213 ,
conduitType = 1 ,
conduitSpecSetID = 30 ,
covenantID = 4 ,
conduitItemID = 182770 ,
} ,
{ -- Infernal Brand
conduitID = 214 ,
conduitType = 1 ,
conduitSpecSetID = 38 ,
covenantID = 0 ,
conduitItemID = 182772 ,
} ,
{ -- Hallowed Discernment
conduitID = 215 ,
conduitType = 1 ,
conduitSpecSetID = 30 ,
covenantID = 2 ,
conduitItemID = 182777 ,
} ,
{ -- Ringing Clarity
conduitID = 216 ,
conduitType = 1 ,
conduitSpecSetID = 30 ,
covenantID = 1 ,
conduitItemID = 182778 ,
} ,
{ -- Soul Tithe
conduitID = 217 ,
conduitType = 1 ,
conduitSpecSetID = 167 ,
covenantID = 1 ,
conduitItemID = 182960 ,
} ,
{ -- Fatal Decimation
conduitID = 218 ,
conduitType = 1 ,
conduitSpecSetID = 167 ,
covenantID = 4 ,
conduitItemID = 182961 ,
} ,
{ -- Catastrophic Origin
conduitID = 219 ,
conduitType = 1 ,
conduitSpecSetID = 167 ,
covenantID = 2 ,
conduitItemID = 182962 ,
} ,
{ -- Soul Eater
conduitID = 220 ,
conduitType = 1 ,
conduitSpecSetID = 167 ,
covenantID = 3 ,
conduitItemID = 182964 ,
} ,
{ -- Kilrogg's Cunning
conduitID = 221 ,
conduitType = 0 ,
conduitSpecSetID = 167 ,
covenantID = 0 ,
conduitItemID = 183044 ,
} ,
{ -- Diabolic Bloodstone
conduitID = 222 ,
conduitType = 2 ,
conduitSpecSetID = 167 ,
covenantID = 0 ,
conduitItemID = 183076 ,
} ,
{ -- Echoing Call
conduitID = 223 ,
conduitType = 1 ,
conduitSpecSetID = 44 ,
covenantID = 0 ,
conduitItemID = 183132 ,
} ,
{ -- Strength of the Pack
conduitID = 224 ,
conduitType = 1 ,
conduitSpecSetID = 20 ,
covenantID = 0 ,
conduitItemID = 183167 ,
} ,
{ -- Reverberation
conduitID = 225 ,
conduitType = 1 ,
conduitSpecSetID = 165 ,
covenantID = 1 ,
conduitItemID = 183492 ,
} ,
{ -- Stinging Strike
conduitID = 226 ,
conduitType = 1 ,
conduitSpecSetID = 20 ,
covenantID = 0 ,
conduitItemID = 183184 ,
} ,
{ -- Sudden Fractures
conduitID = 227 ,
conduitType = 1 ,
conduitSpecSetID = 165 ,
covenantID = 4 ,
conduitItemID = 183493 ,
} ,
{ -- Septic Shock
conduitID = 228 ,
conduitType = 1 ,
conduitSpecSetID = 165 ,
covenantID = 3 ,
conduitItemID = 183494 ,
} ,
{ -- Lashing Scars
conduitID = 229 ,
conduitType = 1 ,
conduitSpecSetID = 165 ,
covenantID = 2 ,
conduitItemID = 183495 ,
} ,
{ -- Nimble Fingers
conduitID = 230 ,
conduitType = 2 ,
conduitSpecSetID = 165 ,
covenantID = 0 ,
conduitItemID = 183496 ,
} ,
{ -- Recuperator
conduitID = 231 ,
conduitType = 2 ,
conduitSpecSetID = 165 ,
covenantID = 0 ,
conduitItemID = 183497 ,
} ,
{ -- Cloaked in Shadows
conduitID = 232 ,
conduitType = 2 ,
conduitSpecSetID = 165 ,
covenantID = 0 ,
conduitItemID = 183498 ,
} ,
{ -- Quick Decisions
conduitID = 233 ,
conduitType = 0 ,
conduitSpecSetID = 165 ,
covenantID = 0 ,
conduitItemID = 183499 ,
} ,
{ -- Fade to Nothing
conduitID = 234 ,
conduitType = 0 ,
conduitSpecSetID = 165 ,
covenantID = 0 ,
conduitItemID = 183500 ,
} ,
{ -- Rushed Setup
conduitID = 235 ,
conduitType = 0 ,
conduitSpecSetID = 165 ,
covenantID = 0 ,
conduitItemID = 183501 ,
} ,
{ -- Prepared for All
conduitID = 236 ,
conduitType = 0 ,
conduitSpecSetID = 165 ,
covenantID = 0 ,
conduitItemID = 183502 ,
} ,
{ -- Poisoned Katar
conduitID = 237 ,
conduitType = 1 ,
conduitSpecSetID = 34 ,
covenantID = 0 ,
conduitItemID = 183503 ,
} ,
{ -- Well-Placed Steel
conduitID = 238 ,
conduitType = 1 ,
conduitSpecSetID = 34 ,
covenantID = 0 ,
conduitItemID = 183504 ,
} ,
{ -- Maim, Mangle
conduitID = 239 ,
conduitType = 1 ,
conduitSpecSetID = 34 ,
covenantID = 0 ,
conduitItemID = 183505 ,
} ,
{ -- Lethal Poisons
conduitID = 240 ,
conduitType = 1 ,
conduitSpecSetID = 34 ,
covenantID = 0 ,
conduitItemID = 183506 ,
} ,
{ -- Triple Threat
conduitID = 241 ,
conduitType = 1 ,
conduitSpecSetID = 35 ,
covenantID = 0 ,
conduitItemID = 183507 ,
} ,
{ -- Ambidexterity
conduitID = 242 ,
conduitType = 1 ,
conduitSpecSetID = 35 ,
covenantID = 0 ,
conduitItemID = 183508 ,
} ,
{ -- Sleight of Hand
conduitID = 243 ,
conduitType = 1 ,
conduitSpecSetID = 35 ,
covenantID = 0 ,
conduitItemID = 183509 ,
} ,
{ -- Count the Odds
conduitID = 244 ,
conduitType = 1 ,
conduitSpecSetID = 35 ,
covenantID = 0 ,
conduitItemID = 183510 ,
} ,
{ -- Deeper Daggers
conduitID = 245 ,
conduitType = 1 ,
conduitSpecSetID = 36 ,
covenantID = 0 ,
conduitItemID = 183511 ,
} ,
{ -- Planned Execution
conduitID = 246 ,
conduitType = 1 ,
conduitSpecSetID = 36 ,
covenantID = 0 ,
conduitItemID = 183512 ,
} ,
{ -- Stiletto Staccato
conduitID = 247 ,
conduitType = 1 ,
conduitSpecSetID = 36 ,
covenantID = 0 ,
conduitItemID = 183513 ,
} ,
{ -- Perforated Veins
conduitID = 248 ,
conduitType = 1 ,
conduitSpecSetID = 36 ,
covenantID = 0 ,
conduitItemID = 183514 ,
} ,
{ -- Controlled Destruction
conduitID = 249 ,
conduitType = 1 ,
conduitSpecSetID = 23 ,
covenantID = 0 ,
conduitItemID = 183197 ,
} ,
{ -- Withering Ground
conduitID = 250 ,
conduitType = 1 ,
conduitSpecSetID = 43 ,
covenantID = 3 ,
conduitItemID = 183199 ,
} ,
{ -- Deadly Tandem
conduitID = 251 ,
conduitType = 1 ,
conduitSpecSetID = 20 ,
covenantID = 0 ,
conduitItemID = 183202 ,
} ,
{ -- Flame Infusion
conduitID = 252 ,
conduitType = 1 ,
conduitSpecSetID = 20 ,
covenantID = 0 ,
conduitItemID = 183396 ,
} ,
{ -- Bloodletting
conduitID = 253 ,
conduitType = 1 ,
conduitSpecSetID = 44 ,
covenantID = 0 ,
conduitItemID = 183402 ,
} ,
{ -- Tough as Bark
conduitID = 254 ,
conduitType = 2 ,
conduitSpecSetID = 48 ,
covenantID = 0 ,
conduitItemID = 183464 ,
} ,
{ -- Ursine Vigor
conduitID = 255 ,
conduitType = 2 ,
conduitSpecSetID = 48 ,
covenantID = 0 ,
conduitItemID = 183465 ,
} ,
{ -- Innate Resolve
conduitID = 256 ,
conduitType = 2 ,
conduitSpecSetID = 48 ,
covenantID = 0 ,
conduitItemID = 183466 ,
} ,
{ -- Tireless Pursuit
conduitID = 257 ,
conduitType = 0 ,
conduitSpecSetID = 48 ,
covenantID = 0 ,
conduitItemID = 183467 ,
} ,
{ -- Born Anew
conduitID = 258 ,
conduitType = 0 ,
conduitSpecSetID = 48 ,
covenantID = 0 ,
conduitItemID = 183468 ,
} ,
{ -- Front of the Pack
conduitID = 259 ,
conduitType = 0 ,
conduitSpecSetID = 48 ,
covenantID = 0 ,
conduitItemID = 183469 ,
} ,
{ -- Born of the Wilds
conduitID = 260 ,
conduitType = 0 ,
conduitSpecSetID = 48 ,
covenantID = 0 ,
conduitItemID = 183470 ,
} ,
{ -- Stellar Inspiration
conduitID = 261 ,
conduitType = 1 ,
conduitSpecSetID = 15 ,
covenantID = 0 ,
conduitItemID = 183476 ,
} ,
{ -- Precise Alignment
conduitID = 262 ,
conduitType = 1 ,
conduitSpecSetID = 15 ,
covenantID = 0 ,
conduitItemID = 183477 ,
} ,
{ -- Fury of the Skies
conduitID = 263 ,
conduitType = 1 ,
conduitSpecSetID = 15 ,
covenantID = 0 ,
conduitItemID = 183478 ,
} ,
{ -- Umbral Intensity
conduitID = 264 ,
conduitType = 1 ,
conduitSpecSetID = 15 ,
covenantID = 0 ,
conduitItemID = 183479 ,
} ,
{ -- Taste for Blood
conduitID = 265 ,
conduitType = 1 ,
conduitSpecSetID = 16 ,
covenantID = 0 ,
conduitItemID = 183480 ,
} ,
{ -- Incessant Hunter
conduitID = 266 ,
conduitType = 1 ,
conduitSpecSetID = 16 ,
covenantID = 0 ,
conduitItemID = 183481 ,
} ,
{ -- Sudden Ambush
conduitID = 267 ,
conduitType = 1 ,
conduitSpecSetID = 16 ,
covenantID = 0 ,
conduitItemID = 183482 ,
} ,
{ -- Carnivorous Instinct
conduitID = 268 ,
conduitType = 1 ,
conduitSpecSetID = 16 ,
covenantID = 0 ,
conduitItemID = 183483 ,
} ,
{ -- Unchecked Aggression
conduitID = 269 ,
conduitType = 1 ,
conduitSpecSetID = 17 ,
covenantID = 0 ,
conduitItemID = 183484 ,
} ,
{ -- Savage Combatant
conduitID = 270 ,
conduitType = 1 ,
conduitSpecSetID = 17 ,
covenantID = 0 ,
conduitItemID = 183485 ,
} ,
{ -- Well-Honed Instincts
conduitID = 271 ,
conduitType = 2 ,
conduitSpecSetID = 48 ,
covenantID = 0 ,
conduitItemID = 183486 ,
} ,
{ -- Layered Mane
conduitID = 272 ,
conduitType = 2 ,
conduitSpecSetID = 17 ,
covenantID = 0 ,
conduitItemID = 183487 ,
} ,
{ -- Unstoppable Growth
conduitID = 273 ,
conduitType = 1 ,
conduitSpecSetID = 18 ,
covenantID = 0 ,
conduitItemID = 183488 ,
} ,
{ -- Flash of Clarity
conduitID = 274 ,
conduitType = 1 ,
conduitSpecSetID = 18 ,
covenantID = 0 ,
conduitItemID = 183489 ,
} ,
{ -- Floral Recycling
conduitID = 275 ,
conduitType = 1 ,
conduitSpecSetID = 18 ,
covenantID = 0 ,
conduitItemID = 183490 ,
} ,
{ -- Ready for Anything
conduitID = 276 ,
conduitType = 1 ,
conduitSpecSetID = 18 ,
covenantID = 0 ,
conduitItemID = 183491 ,
} ,
{ -- Deep Allegiance
conduitID = 277 ,
conduitType = 1 ,
conduitSpecSetID = 48 ,
covenantID = 1 ,
conduitItemID = 183471 ,
} ,
{ -- Evolved Swarm
conduitID = 278 ,
conduitType = 1 ,
conduitSpecSetID = 48 ,
covenantID = 4 ,
conduitItemID = 183472 ,
} ,
{ -- Conflux of Elements
conduitID = 279 ,
conduitType = 1 ,
conduitSpecSetID = 48 ,
covenantID = 3 ,
conduitItemID = 183473 ,
} ,
{ -- Endless Thirst
conduitID = 280 ,
conduitType = 1 ,
conduitSpecSetID = 48 ,
covenantID = 2 ,
conduitItemID = 183474 ,
} ,
{ -- Unnatural Malice
conduitID = 281 ,
conduitType = 1 ,
conduitSpecSetID = 8 ,
covenantID = 3 ,
conduitItemID = 183463 ,
} ,
{ -- Ambuscade
conduitID = 282 ,
conduitType = 0 ,
conduitSpecSetID = 163 ,
covenantID = 0 ,
conduitItemID = 184587 ,
} ,
{ -- Condensed Anima Sphere
conduitID = 283 ,
conduitType = 2 ,
conduitSpecSetID = 2 ,
covenantID = 0 ,
conduitItemID = 187506 ,
} ,
{ -- Adaptive Armor Fragment
conduitID = 284 ,
conduitType = 1 ,
conduitSpecSetID = 1 ,
covenantID = 0 ,
conduitItemID = 187507 ,
} ,
}
local conduitsByID = { }
local conduitsByItemID = { }
for _ , conduit in ipairs ( conduits ) do
conduit.conduitRank = 11
conduit.conduitItemLevel = 278
local specIDs = C_SpecializationInfo.GetSpecIDs ( conduit.conduitSpecSetID )
if # specIDs == 1 then
conduit.conduitSpecName = select ( 2 , GetSpecializationInfoByID ( specIDs [ 1 ] ) )
end
conduitsByID [ conduit.conduitID ] = conduit
conduitsByItemID [ conduit.conduitItemID ] = conduit
end
local function GetConduitByID ( itemID )
return conduitsByID [ itemID ]
end
local function GetConduitByItemID ( itemID )
return conduitsByItemID [ itemID ]
end
local function CheckConduitCovenant ( conduitData , covenantID )
return conduitData.covenantID == 0 or conduitData.covenantID == covenantID
end
local function CheckConduitClass ( conduitData , classID )
local specIDs = C_SpecializationInfo.GetSpecIDs ( conduitData.conduitSpecSetID )
if conduitData.conduitID == 284 then -- Tank only conduit
local classInfo = C_CreatureInfo.GetClassInfo ( classID )
for _ , specID in ipairs ( specIDs ) do
local classFile = select ( 6 , GetSpecializationInfoByID ( specID ) )
if classInfo.classFile == classFile then
conduitData.conduitSpecName = select ( 2 , GetSpecializationInfoByID ( specID ) )
return true
end
end
return false
end
if # specIDs == 0 or # specIDs > 4 then
return true
end
local classInfo = C_CreatureInfo.GetClassInfo ( classID )
local classFile = select ( 6 , GetSpecializationInfoByID ( specIDs [ 1 ] ) )
return classInfo.classFile == classFile
end
local function GetConduitCollection ( classID , covenantID , conduitType )
local results = { }
if classID ~= nil then
for _ , conduit in ipairs ( conduits ) do
if conduit.conduitType == conduitType and CheckConduitCovenant ( conduit , covenantID ) and CheckConduitClass ( conduit , classID ) then
results [ # results + 1 ] = conduit
end
end
end
return results
end
local ConduitTypeCollapsed = { }
BtWLoadoutsConduitListCategoryButtonMixin = { } ;
function BtWLoadoutsConduitListCategoryButtonMixin : Init ( conduitType , collapsed )
local name = self.Container . Name ;
name : SetText ( GetConduitName ( conduitType ) ) ;
name : SetWidth ( name : GetStringWidth ( ) + 40 ) ;
local icon = self.Container . ConduitIcon ;
icon : SetAtlas ( GetConduitEmblemAtlas ( conduitType ) ) ;
icon : SetScale ( GetConduitIconScale ( conduitType ) ) ;
icon : SetPoint ( " LEFT " , name , " RIGHT " , - 40 , - 1 ) ;
self.collapsed = collapsed ;
self : SetCollapsedVisuals ( collapsed ) ;
end
function BtWLoadoutsConduitListCategoryButtonMixin : OnEnter ( )
for index , texture in ipairs ( self.Container . Hovers ) do
texture : Show ( ) ;
end
end
function BtWLoadoutsConduitListCategoryButtonMixin : OnLeave ( )
for index , texture in ipairs ( self.Container . Hovers ) do
texture : Hide ( ) ;
end
GameTooltip_Hide ( ) ;
end
function BtWLoadoutsConduitListCategoryButtonMixin : OnMouseDown ( )
self.Container : AdjustPointsOffset ( 1 , - 1 ) ;
end
function BtWLoadoutsConduitListCategoryButtonMixin : OnMouseUp ( )
self.Container : AdjustPointsOffset ( - 1 , 1 ) ;
end
function BtWLoadoutsConduitListCategoryButtonMixin : SetCollapsedVisuals ( collapsed )
if collapsed then
self.Container . ExpandableIcon : SetAtlas ( " Soulbinds_Collection_CategoryHeader_Expand " , TextureKitConstants.UseAtlasSize ) ;
else
self.Container . ExpandableIcon : SetAtlas ( " Soulbinds_Collection_CategoryHeader_Collapse " , TextureKitConstants.UseAtlasSize ) ;
end
end
function BtWLoadoutsConduitListCategoryButtonMixin : SetCollapsed ( collapsed )
local changed = self.collapsed ~= collapsed ;
if not changed then
return ;
end
self.collapsed = collapsed ;
PlaySound ( SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF ) ;
self : SetCollapsedVisuals ( collapsed ) ;
end
BtWLoadoutsConduitListConduitButtonMixin = { } ;
BtWLoadoutsConduitListConduitButtonMixin.State = {
Uninstalled = 1 ,
Installed = 2 ,
Pending = 3 ,
}
function BtWLoadoutsConduitListConduitButtonMixin : OnLoad ( )
self : RegisterForDrag ( " LeftButton " ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : Init ( owner , conduitData )
self.owner = owner
self.conduitData = conduitData ;
local itemID = conduitData.conduitItemID ;
local item = Item : CreateFromItemID ( itemID ) ;
local itemCallback = function ( )
self.ConduitName : SetSize ( 150 , 30 ) ;
self.ConduitName : SetText ( item : GetItemName ( ) ) ;
self.ConduitName : SetHeight ( self.ConduitName : GetStringHeight ( ) ) ;
local yOffset = self.ConduitName : GetNumLines ( ) > 1 and - 6 or 0 ;
self.ConduitName : ClearAllPoints ( ) ;
self.ConduitName : SetPoint ( " BOTTOMLEFT " , self.Icon , " RIGHT " , 10 , yOffset ) ;
self.ConduitName : SetWidth ( 150 ) ;
self.ItemLevel : SetPoint ( " TOPLEFT " , self.ConduitName , " BOTTOMLEFT " , 0 , 0 ) ;
self.ItemLevel : SetText ( conduitData.conduitItemLevel ) ;
end ;
item : ContinueOnItemLoad ( itemCallback ) ;
local icon = item : GetItemIcon ( ) ;
self.Icon : SetTexture ( icon ) ;
self.Icon2 : SetTexture ( icon ) ;
self.IconPulse : SetTexture ( icon ) ;
local conduitQuality = C_Soulbinds.GetConduitQuality ( conduitData.conduitID , conduitData.conduitRank ) ;
local color = ITEM_QUALITY_COLORS [ conduitQuality ] ;
local r , g , b = color.r , color.g , color.b ;
self.IconOverlay : SetVertexColor ( r , g , b ) ;
self.IconOverlay2 : SetVertexColor ( r , g , b ) ;
self.IconOverlayDark : SetVertexColor ( 0 , 0 , 0 ) ;
self.ConduitName : SetTextColor ( r , g , b ) ;
local conduitSpecName = conduitData.conduitSpecName ;
if conduitSpecName then
local specIDs = C_SpecializationInfo.GetSpecIDs ( conduitData.conduitSpecSetID ) ;
self.Spec . Icon : SetTexture ( select ( 4 , GetSpecializationInfoByID ( specIDs [ 1 ] ) ) ) ;
self.Spec : SetScript ( " OnEnter " , function ( )
GameTooltip : SetOwner ( self.Spec , " ANCHOR_RIGHT " ) ;
GameTooltip_AddHighlightLine ( GameTooltip , conduitSpecName ) ;
GameTooltip : Show ( ) ;
end ) ;
self.Spec : SetScript ( " OnLeave " , function ( )
GameTooltip_Hide ( ) ;
end ) ;
self.Spec : Show ( ) ;
else
self.Spec : Hide ( ) ;
self.Spec : SetScript ( " OnEnter " , nil ) ;
self.Spec : SetScript ( " OnLeave " , nil ) ;
end
self : Update ( ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : OnEvent ( event , ... )
if event == " CURSOR_CHANGED " then
local cursorType , itemID = GetCursorInfo ( )
local pending = cursorType == " item " and itemID == self.conduitData . conduitItemID ;
self.PendingBackground : SetShown ( pending ) ;
end
end
function BtWLoadoutsConduitListConduitButtonMixin : OnShow ( )
FrameUtil.RegisterFrameForEvents ( self , {
" CURSOR_CHANGED " ,
} ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : OnHide ( )
FrameUtil.UnregisterFrameForEvents ( self , {
" CURSOR_CHANGED " ,
} ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : MatchesID ( conduitID )
return self.conduitData . conduitID == conduitID ;
end
function BtWLoadoutsConduitListConduitButtonMixin : UpdateVisuals ( state )
local installed = state == BtWLoadoutsConduitListConduitButtonMixin.State . Installed ;
local pending = state == BtWLoadoutsConduitListConduitButtonMixin.State . Pending ;
local dark = installed or pending ;
self.ConduitName : SetAlpha ( dark and .5 or 1 ) ;
self.ItemLevel : SetAlpha ( dark and .2 or 1 ) ;
self.IconOverlayDark : SetShown ( dark ) ;
self.IconDark : SetShown ( dark ) ;
self.Pending : SetShown ( pending ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : Update ( )
self : UpdateVisuals ( self : GetState ( ) ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : GetState ( )
if self.owner and self.conduitData then
local installed = self.owner : IsConduitSlotted ( self.conduitData . conduitID )
if installed then
return BtWLoadoutsConduitListConduitButtonMixin.State . Installed ;
end
end
-- local soulbindID = Soulbinds.GetOpenSoulbindID();
-- local conduitID = self.conduitData.conduitID;
-- local pendingInstallNodeID = C_Soulbinds.FindNodeIDPendingInstall(soulbindID, conduitID);
-- if pendingInstallNodeID > 0 then
-- return BtWLoadoutsConduitListConduitButtonMixin.State.Pending;
-- end
-- local pendingUninstallNodeID = C_Soulbinds.FindNodeIDPendingUninstall(soulbindID, conduitID);
-- if pendingUninstallNodeID > 0 then
-- return BtWLoadoutsConduitListConduitButtonMixin.State.Uninstalled;
-- end
-- local installed = C_Soulbinds.IsConduitInstalledInSoulbind(soulbindID, conduitID);
-- if installed then
-- return BtWLoadoutsConduitListConduitButtonMixin.State.Installed;
-- end
return BtWLoadoutsConduitListConduitButtonMixin.State . Uninstalled ;
end
function BtWLoadoutsConduitListConduitButtonMixin : OnClick ( buttonName )
if buttonName == " LeftButton " then
local linked = false ;
if IsModifiedClick ( " CHATLINK " ) then
local link = C_Soulbinds.GetConduitHyperlink ( self.conduitData . conduitID , self.conduitData . conduitRank ) ;
linked = HandleModifiedItemClick ( link ) ;
end
if not linked then
self : CreateCursor ( ) ;
end
elseif buttonName == " RightButton " then
--@TODO highlight conduit within tree?
end
end
function BtWLoadoutsConduitListConduitButtonMixin : OnDragStart ( )
self : CreateCursor ( ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : CreateCursor ( )
SetCursorVirtualItem ( self.conduitData . conduitItemID , Enum.UICursorType . ConduitCollectionItem ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : OnEnter ( )
for index , texture in ipairs ( self.Hovers ) do
texture : Show ( ) ;
end
GameTooltip : SetOwner ( self.Icon , " ANCHOR_RIGHT " , 178 , 0 ) ;
if IsModifiedClick ( " SHIFT " ) then
GameTooltip : SetEnhancedConduit ( self.conduitData . conduitID , self.conduitData . conduitRank ) ;
else
GameTooltip : SetConduit ( self.conduitData . conduitID , self.conduitData . conduitRank ) ;
end
GameTooltip : Show ( ) ;
end
function BtWLoadoutsConduitListConduitButtonMixin : OnLeave ( )
if self.conduitOnSpellLoadCb then
self.conduitOnSpellLoadCb ( ) ;
self.conduitOnSpellLoadCb = nil ;
end
GameTooltip_Hide ( ) ;
for index , texture in ipairs ( self.Hovers ) do
texture : Hide ( ) ;
end
end
BtWLoadoutsConduitListSectionMixin = { }
function BtWLoadoutsConduitListSectionMixin : OnLoad ( )
self.CategoryButton : SetScript ( " OnClick " , function ( button , buttonName , down )
local newCollapsed = self.Container : IsShown ( ) ;
self : GetElementData ( ) . collapsed = newCollapsed ;
self : SetCollapsed ( newCollapsed ) ;
end ) ;
self.pool = CreateFramePool ( " BUTTON " , self.Container , " BtWLoadoutsConduitListConduitButtonTemplate " ) ;
end
function BtWLoadoutsConduitListSectionMixin : Init ( owner , elementData )
self.pool : ReleaseAll ( ) ;
self.owner = owner
local conduitDatas = CopyTable ( elementData.conduitDatas ) ;
self.conduitType = elementData.conduitType ;
local frames = { } ;
local count = # conduitDatas ;
local function FactoryFunction ( index )
if index > count then
return nil ;
end
local frame = self.pool : Acquire ( ) ;
table.insert ( frames , frame ) ;
frame : SetPoint ( " LEFT " , self.Container , " LEFT " , 0 , 0 ) ;
frame : SetPoint ( " RIGHT " , self.Container , " RIGHT " , 0 , 0 ) ;
frame : Show ( ) ;
return frame ;
end
local direction , stride , x , y , paddingX , paddingY = GridLayoutMixin.Direction . TopLeftToBottomRight , 1 , 0 , 1 , 0 , 0 ;
local anchor = AnchorUtil.CreateAnchor ( " TOPLEFT " , self.Container , " TOPLEFT " ) ;
local layout = AnchorUtil.CreateGridLayout ( direction , stride , paddingX , paddingY ) ;
AnchorUtil.GridLayoutFactoryByCount ( FactoryFunction , count , anchor , layout ) ;
self.CategoryButton : Init ( self.conduitType , elementData.collapsed ) ;
self : SetCollapsed ( elementData.collapsed ) ;
if self.currentContinuable then
self.currentContinuable : Cancel ( ) ;
end
self.currentContinuable = ContinuableContainer : Create ( ) ;
for index , conduitData in ipairs ( conduitDatas ) do
if not conduitData.conduitSpecName then
conduitData.sortingCategory = 1 ;
else
conduitData.sortingCategory = 2 ;
end
conduitData.item = Item : CreateFromItemID ( conduitData.conduitItemID ) ;
self.currentContinuable : AddContinuable ( conduitData.item ) ;
end
self.currentContinuable : ContinueOnLoad ( function ( )
local sorter = function ( lhs , rhs )
if lhs.sortingCategory == rhs.sortingCategory then
if ( not lhs.conduitSpecName or not rhs.conduitSpecName ) or lhs.conduitSpecName == rhs.conduitSpecName then
if lhs.conduitRank ~= rhs.conduitRank then
return lhs.conduitRank > rhs.conduitRank ;
end
return lhs.item : GetItemName ( ) < rhs.item : GetItemName ( ) ;
else
return lhs.conduitSpecName < rhs.conduitSpecName ;
end
else
return lhs.sortingCategory < rhs.sortingCategory ;
end
end ;
table.sort ( conduitDatas , sorter ) ;
for index , conduitData in ipairs ( conduitDatas ) do
frames [ index ] : Init ( self.owner , conduitData ) ;
end
local newConduitData = elementData.newConduitData ;
if newConduitData then
elementData.newConduitData = nil ;
self : PlayUpdateAnim ( newConduitData ) ;
end
end ) ;
end
function BtWLoadoutsConduitListSectionMixin : Update ( )
for conduitButton in self.pool : EnumerateActive ( ) do
conduitButton : Update ( ) ;
end
end
function BtWLoadoutsConduitListSectionMixin : FindConduitButton ( conduitID )
for conduitButton in self.pool : EnumerateActive ( ) do
if conduitButton : MatchesID ( conduitID ) then
return conduitButton ;
end
end
end
function BtWLoadoutsConduitListSectionMixin : IsCollapsed ( )
return self : GetElementData ( ) . collapsed ;
end
function BtWLoadoutsConduitListSectionMixin : SetCollapsed ( collapsed )
ConduitTypeCollapsed [ self.conduitType ] = collapsed
self.CategoryButton : SetCollapsed ( collapsed ) ;
local shown = not collapsed ;
self.Container : SetShown ( shown ) ;
self.Spacer : SetShown ( shown ) ;
self : Layout ( ) ;
end
BtWLoadoutsConduitListMixin = { }
function BtWLoadoutsConduitListMixin : OnLoad ( )
local buttonHeight = 42 ;
local topSpacer = 10 ;
local bottomSpacer = 5 ;
local catButtonExtent = 23 ;
local containerOffset = 5 ;
local expandedExtent = catButtonExtent + topSpacer + bottomSpacer + containerOffset ;
local collapsedExtent = catButtonExtent + topSpacer ;
local view = CreateScrollBoxListLinearView ( ) ;
view : SetElementExtentCalculator ( function ( dataIndex , elementData )
if elementData.collapsed then
return collapsedExtent ;
else
return ( # elementData.conduitDatas * buttonHeight ) + expandedExtent ;
end
end ) ;
if Internal.IsDragonflight ( ) then
view : SetElementInitializer ( " BtWLoadoutsConduitListSectionTemplate " , function ( list , elementData )
list : Init ( self.owner , elementData ) ;
end ) ;
else
view : SetElementInitializer ( " EventFrame " , " BtWLoadoutsConduitListSectionTemplate " , function ( list , elementData )
list : Init ( self.owner , elementData ) ;
end ) ;
end
ScrollUtil.InitScrollBoxListWithScrollBar ( self.ScrollBox , self.ScrollBar , view ) ;
ScrollUtil.AddResizableChildrenBehavior ( self.ScrollBox ) ;
end
function BtWLoadoutsConduitListMixin : Init ( owner , classID , covenantID )
if self.classID == classID and self.covenantID == covenantID then
return
end
self.owner = owner
self.classID = classID
self.covenantID = covenantID
local conduitTypes = {
Enum.SoulbindConduitType . Endurance ,
Enum.SoulbindConduitType . Finesse ,
Enum.SoulbindConduitType . Potency ,
} ;
local listDatas = { } ;
for i , conduitType in ipairs ( conduitTypes ) do
local conduitDatas = GetConduitCollection ( classID , covenantID , conduitType ) ;
if # conduitDatas > 0 then
table.insert ( listDatas , { conduitDatas = conduitDatas , conduitType = conduitType , collapsed = ConduitTypeCollapsed [ conduitType ] } ) ;
end
end
local dataProvider = CreateDataProvider ( listDatas ) ;
self.ScrollBox : SetDataProvider ( dataProvider ) ;
end
function BtWLoadoutsConduitListMixin : Update ( )
self.ScrollBox : ForEachFrame ( function ( list )
list : Update ( ) ;
end ) ;
end
BtWLoadoutsSoulbindNodeMixin = { }
function BtWLoadoutsSoulbindNodeMixin : Init ( owner , node )
self.owner = owner
self.node = node
self.Icon : SetTexture ( node.icon )
if node.conduitType ~= nil then
local atlas = GetConduitEmblemAtlas ( node.conduitType ) ;
self.Emblem : Show ( )
self.EmblemBg : Show ( )
self.Emblem : SetAtlas ( atlas ) ;
self.EmblemBg : SetAtlas ( atlas )
self.EmblemBg : SetVertexColor ( 0 , 0 , 0 ) ;
self.Icon : Hide ( ) ;
self.Ring : SetAtlas ( " Soulbinds_Tree_Conduit_Ring " , false ) ;
self.MouseOverlay : SetAtlas ( " Soulbinds_Tree_Conduit_Ring " , false ) ;
else
self.Emblem : Hide ( )
self.EmblemBg : Hide ( )
self.Icon : Show ( ) ;
self.Ring : SetAtlas ( " Soulbinds_Tree_Ring " , false ) ;
self.MouseOverlay : SetAtlas ( " Soulbinds_Tree_Ring " , false ) ;
end
end
function BtWLoadoutsSoulbindNodeMixin : SetSelected ( selected )
if not selected then
self.Icon : SetDesaturated ( false ) ;
self.IconOverlay : Show ( ) ;
self.Ring : SetDesaturated ( true ) ;
self.MouseOverlay : SetDesaturated ( true ) ;
else
self.Icon : SetDesaturated ( false ) ;
self.IconOverlay : Hide ( ) ;
self.Ring : SetDesaturated ( false ) ;
self.MouseOverlay : SetDesaturated ( false ) ;
end
end
function BtWLoadoutsSoulbindNodeMixin : SetConduit ( conduitID )
if conduitID and conduitID ~= 0 then
local conduit = GetConduitByID ( conduitID )
local spellID = C_Soulbinds.GetConduitSpellID ( conduit.conduitID , conduit.conduitRank )
self.Icon : SetTexture ( GetSpellTexture ( spellID ) )
self.Icon : Show ( )
self.conduit = conduit
else
self.Icon : SetShown ( self.node . conduitType == nil )
self.conduit = nil
end
end
function BtWLoadoutsSoulbindNodeMixin : OnClick ( button )
local node = self.node
if node.conduitType ~= nil then
local cursorType , itemID = GetCursorInfo ( )
local conduit = cursorType == " item " and GetConduitByItemID ( itemID )
if conduit then
if conduit.conduitType == node.conduitType then
if self.owner : SetNodeConduit ( node.ID , conduit.conduitID ) then
ClearCursor ( )
end
-- self:SetConduit(node.ID)
end
return
end
end
if button == " LeftButton " then
self.owner : ToggleNode ( node.ID )
else
if node.conduitType ~= nil then
self.owner : SetNodeConduit ( node.ID , nil )
-- self:SetConduit(nil)
end
end
end
function BtWLoadoutsSoulbindNodeMixin : OnEnter ( )
self.MouseOverlay : Show ( ) ;
if self.node . spellID ~= 0 then
GameTooltip : SetOwner ( self , " ANCHOR_RIGHT " ) ;
GameTooltip : SetSpellByID ( self.node . spellID ) ;
GameTooltip : Show ( ) ;
elseif self.conduit then
GameTooltip : SetOwner ( self , " ANCHOR_RIGHT " ) ;
if IsModifiedClick ( " SHIFT " ) then
GameTooltip : SetEnhancedConduit ( self.conduit . conduitID , self.conduit . conduitRank ) ;
else
GameTooltip : SetConduit ( self.conduit . conduitID , self.conduit . conduitRank ) ;
end
GameTooltip : Show ( ) ;
end
end
function BtWLoadoutsSoulbindNodeMixin : OnLeave ( )
self.MouseOverlay : Hide ( ) ;
GameTooltip : Hide ( ) ;
end
local SoulbindTreeLinkDirections = {
Vertical = 1 ,
Converge = 2 ,
Diverge = 3 ,
} ;
BtWLoadoutsSoulbindTreeNodeLinkMixin = { }
function BtWLoadoutsSoulbindTreeNodeLinkMixin : Init ( direction , angle )
if direction == SoulbindTreeLinkDirections.Vertical then
self.Background : SetAtlas ( " Soulbinds_Tree_Connector_Vertical " , true ) ;
self.FillMask : SetAtlas ( " Soulbinds_Tree_Connector_Vertical_Mask " , true ) ;
elseif direction == SoulbindTreeLinkDirections.Converge then
self.Background : SetAtlas ( " Soulbinds_Tree_Connector_Diagonal_Close " , true ) ;
self.FillMask : SetAtlas ( " Soulbinds_Tree_Connector_Diagonal_Close_Mask " , true ) ;
elseif direction == SoulbindTreeLinkDirections.Diverge then
self.Background : SetAtlas ( " Soulbinds_Tree_Connector_Diagonal_Far " , true ) ;
self.FillMask : SetAtlas ( " Soulbinds_Tree_Connector_Diagonal_Far_Mask " , true ) ;
end
self : RotateTextures ( angle ) ;
end
function BtWLoadoutsSoulbindTreeNodeLinkMixin : OnHide ( )
self.FlowAnim1 : Stop ( ) ;
self.FlowAnim2 : Stop ( ) ;
self.FlowAnim3 : Stop ( ) ;
self.FlowAnim4 : Stop ( ) ;
self.FlowAnim5 : Stop ( ) ;
self.FlowAnim6 : Stop ( ) ;
end
function BtWLoadoutsSoulbindTreeNodeLinkMixin : Reset ( )
self : SetState ( Enum.SoulbindNodeState . Unselected ) ;
end
function BtWLoadoutsSoulbindTreeNodeLinkMixin : SetState ( state )
self.state = state ;
if state == Enum.SoulbindNodeState . Unselected or state == Enum.SoulbindNodeState . Unavailable then
self : DesaturateHierarchy ( 1 ) ;
for _ , foreground in ipairs ( self.foregrounds ) do
foreground : SetShown ( false ) ;
end
self.FlowAnim1 : Stop ( ) ;
self.FlowAnim2 : Stop ( ) ;
self.FlowAnim3 : Stop ( ) ;
self.FlowAnim4 : Stop ( ) ;
self.FlowAnim5 : Stop ( ) ;
self.FlowAnim6 : Stop ( ) ;
elseif state == Enum.SoulbindNodeState . Selectable then
self : DesaturateHierarchy ( 0 ) ;
for _ , foreground in ipairs ( self.foregrounds ) do
foreground : SetShown ( true ) ;
foreground : SetVertexColor ( .3 , .3 , .3 ) ;
end
self.FlowAnim1 : Play ( ) ;
self.FlowAnim2 : Play ( ) ;
self.FlowAnim3 : Play ( ) ;
self.FlowAnim4 : Play ( ) ;
self.FlowAnim5 : Play ( ) ;
self.FlowAnim6 : Play ( ) ;
elseif state == Enum.SoulbindNodeState . Selected then
self : DesaturateHierarchy ( 0 ) ;
for _ , foreground in ipairs ( self.foregrounds ) do
foreground : SetShown ( true ) ;
foreground : SetVertexColor ( .192 , .686 , .941 ) ;
end
self.FlowAnim1 : Play ( ) ;
self.FlowAnim2 : Play ( ) ;
self.FlowAnim3 : Play ( ) ;
self.FlowAnim4 : Play ( ) ;
self.FlowAnim5 : Play ( ) ;
self.FlowAnim6 : Play ( ) ;
end
end
function BtWLoadoutsSoulbindTreeNodeLinkMixin : GetState ( )
return self.state ;
end
BtWLoadoutsSoulbindsMixin = { }
function BtWLoadoutsSoulbindsMixin : OnLoad ( )
self.RestrictionsDropDown : SetSupportedTypes ( " spec " , " race " )
self.RestrictionsDropDown : SetScript ( " OnChange " , function ( )
self : Update ( )
end )
self.temp = { }
self.tempConduits = { } -- Conduits for different classes for currently selected soulbind
self.nodes = CreateFramePool ( " BUTTON " , self.Scroll : GetScrollChild ( ) , " BtWLoadoutsSoulbindNodeTemplate " ) ;
self.links = CreateFramePool ( " FRAME " , self.Scroll , " BtWLoadoutsSoulbindTreeNodeLinkTemplate " ) ;
self.nodesByID = { }
end
function BtWLoadoutsSoulbindsMixin : OnShow ( )
if not self.initialized then
UIDropDownMenu_SetWidth ( self.SoulbindDropDown , 170 ) ;
UIDropDownMenu_JustifyText ( self.SoulbindDropDown , " LEFT " ) ;
self.SoulbindDropDown . GetValue = function ( )
if self.set then
return self.set . soulbindID
end
end
self.SoulbindDropDown . SetValue = function ( _ , _ , arg1 )
CloseDropDownMenus ( ) ;
local set = self.set ;
if set then
local soulbindID = set.soulbindID
local classID = set.classID
local temp = self.temp ;
local tempConduits = self.tempConduits
if classID then
if tempConduits [ classID ] then
wipe ( tempConduits [ classID ] ) ;
else
tempConduits [ classID ] = { } ;
end
for nodeID , conduitID in pairs ( set.conduits ) do
tempConduits [ classID ] [ nodeID ] = conduitID
end
end
if temp [ soulbindID ] then
wipe ( temp [ soulbindID ] . nodes ) ;
else
temp [ soulbindID ] = { nodes = { } } ;
end
for nodeID in pairs ( set.nodes ) do
temp [ soulbindID ] . nodes [ nodeID ] = true ;
end
temp [ soulbindID ] . conduits = tempConduits
soulbindID = arg1 ;
set.soulbindID = soulbindID ;
wipe ( set.nodes ) ;
wipe ( set.conduits ) ;
if temp [ soulbindID ] then
for nodeID in pairs ( temp [ soulbindID ] . nodes ) do
set.nodes [ nodeID ] = true ;
end
self.tempConduits = temp [ soulbindID ] . conduits
if self.tempConduits [ classID ] then
for nodeID , conduitID in pairs ( self.tempConduits [ classID ] ) do
set.conduits [ nodeID ] = conduitID
end
end
else
self.tempConduits = { }
end
self : Update ( )
end
end
self.ClassDropDown . includeNone = true ;
UIDropDownMenu_SetWidth ( self.ClassDropDown , 203 ) ;
UIDropDownMenu_JustifyText ( self.ClassDropDown , " LEFT " ) ;
self.ClassDropDown . GetValue = function ( )
if self.set then
return self.set . classID
end
end
self.ClassDropDown . SetValue = function ( _ , _ , arg1 )
CloseDropDownMenus ( ) ;
local set = self.set ;
if set then
local classID = set.classID
local tempConduits = self.tempConduits
if classID then
if tempConduits [ classID ] then
wipe ( tempConduits [ classID ] ) ;
else
tempConduits [ classID ] = { } ;
end
for nodeID , conduitID in pairs ( set.conduits ) do
tempConduits [ classID ] [ nodeID ] = conduitID ;
end
end
classID = arg1
set.classID = classID
wipe ( set.conduits ) ;
if classID then
if tempConduits [ classID ] then
for nodeID , conduitID in pairs ( tempConduits [ classID ] ) do
set.conduits [ nodeID ] = conduitID ;
end
end
end
self : Update ( )
end
end
self.initialized = true ;
end
end
function BtWLoadoutsSoulbindsMixin : ChangeSet ( set )
self.set = set
self : Update ( )
end
function BtWLoadoutsSoulbindsMixin : UpdateSetName ( value )
if self.set and self.set . name ~= not value then
self.set . name = value ;
self : Update ( ) ;
end
end
function BtWLoadoutsSoulbindsMixin : OnButtonClick ( button )
CloseDropDownMenus ( )
if button.isAdd then
BtWLoadoutsHelpTipFlags [ " TUTORIAL_NEW_SET " ] = true ;
self.Name : ClearFocus ( )
self : ChangeSet ( AddSet ( ) )
C_Timer.After ( 0 , function ( )
self.Name : HighlightText ( )
self.Name : SetFocus ( )
end )
elseif button.isDelete then
local set = self.set
if set.useCount > 0 then
StaticPopup_Show ( " BTWLOADOUTS_DELETEINUSESET " , set.name , nil , {
set = set ,
func = DeleteSet ,
} )
else
StaticPopup_Show ( " BTWLOADOUTS_DELETESET " , set.name , nil , {
set = set ,
func = DeleteSet ,
} )
end
elseif button.isRefresh then
local set = self.set ;
RefreshSet ( set )
self : Update ( )
elseif button.isExport then
local set = self.set ;
self : GetParent ( ) : SetExport ( Internal.Export ( " soulbinds " , set.setID ) )
elseif button.isActivate then
local set = self.set ;
Internal.ActivateProfile ( {
soulbinds = { set.setID }
} ) ;
end
end
function BtWLoadoutsSoulbindsMixin : OnSidebarItemClick ( button )
CloseDropDownMenus ( )
if button.isHeader then
button.collapsed [ button.id ] = not button.collapsed [ button.id ]
self : Update ( )
else
if IsModifiedClick ( " SHIFT " ) then
local set = GetSet ( button.id ) ;
Internal.ActivateProfile ( {
soulbinds = { button.id }
} ) ;
else
self.Name : ClearFocus ( ) ;
self : ChangeSet ( GetSet ( button.id ) )
end
end
end
function BtWLoadoutsSoulbindsMixin : OnSidebarItemDoubleClick ( button )
CloseDropDownMenus ( )
if button.isHeader then
return
end
local set = GetSet ( button.id ) ;
Internal.ActivateProfile ( {
soulbinds = { button.id }
} ) ;
end
function BtWLoadoutsSoulbindsMixin : OnSidebarItemDragStart ( button )
CloseDropDownMenus ( )
if button.isHeader then
return
end
local icon = " INV_Misc_QuestionMark " ;
local set = GetSet ( button.id ) ;
local command = format ( " /btwloadouts activate soulbinds %d " , button.id ) ;
if set.specID then
icon = select ( 4 , GetSpecializationInfoByID ( set.specID ) ) ;
end
if command then
local macroId ;
local numMacros = GetNumMacros ( ) ;
for i = 1 , numMacros do
if GetMacroBody ( i ) : trim ( ) == command then
macroId = i ;
break ;
end
end
if not macroId then
if numMacros == MAX_ACCOUNT_MACROS then
print ( L [ " Cannot create any more macros " ] ) ;
return ;
end
if InCombatLockdown ( ) then
print ( L [ " Cannot create macros while in combat " ] ) ;
return ;
end
macroId = CreateMacro ( set.name , icon , command , false ) ;
else
-- Rename the macro while not in combat
if not InCombatLockdown ( ) then
icon = select ( 2 , GetMacroInfo ( macroId ) )
EditMacro ( macroId , set.name , icon , command )
end
end
if macroId then
PickupMacro ( macroId ) ;
end
end
end
function BtWLoadoutsSoulbindsMixin : SetSoulbind ( soulbindID )
if self.soulbind and self.soulbind . ID == soulbindID then
return
end
local soulbind = GetSoulbindData ( soulbindID )
local nodes = soulbind.tree . nodes
local nodesByID = { }
for _ , node in ipairs ( nodes ) do
nodesByID [ node.ID ] = node
end
for _ , node in ipairs ( nodes ) do
for _ , parentID in ipairs ( node.parentNodeIDs ) do
local parent = nodesByID [ parentID ]
if not parent.childNodeIDs then
parent.childNodeIDs = { }
end
parent.childNodeIDs [ # parent.childNodeIDs + 1 ] = node.ID
end
end
soulbind.tree . nodesByID = nodesByID
self.soulbind = soulbind
end
function BtWLoadoutsSoulbindsMixin : GetSoulbind ( )
return self.soulbind
end
function BtWLoadoutsSoulbindsMixin : ToggleNode ( nodeID )
local nodes = self.set and self.set . nodes
self : SetNodeEnabled ( nodeID , not nodes [ nodeID ] )
end
function BtWLoadoutsSoulbindsMixin : SetNodeEnabled ( nodeID , enabled )
local set = self.set
if set then
local nodes = set.nodes
local soulbindData = self : GetSoulbind ( )
local nodesByID = soulbindData.tree . nodesByID
local targetNode = nodesByID [ nodeID ]
while targetNode.childNodeIDs and # targetNode.childNodeIDs == 1 do
local childID = targetNode.childNodeIDs [ 1 ]
local child = nodesByID [ childID ]
if # child.parentNodeIDs ~= 1 then
break
end
targetNode = child
end
if enabled then
for _ , node in pairs ( nodesByID ) do
if node.row == targetNode.row then
nodes [ node.ID ] = nil
end
end
end
nodes [ targetNode.ID ] = enabled and true or nil
while # targetNode.parentNodeIDs == 1 do
local parentID = targetNode.parentNodeIDs [ 1 ]
targetNode = nodesByID [ parentID ]
if not targetNode.childNodeIDs or # targetNode.childNodeIDs ~= 1 then
break
end
if enabled then
for _ , node in pairs ( nodesByID ) do
if node.row == targetNode.row then
nodes [ node.ID ] = nil
end
end
end
nodes [ targetNode.ID ] = enabled and true or nil
end
self : Update ( )
end
end
function BtWLoadoutsSoulbindsMixin : IsNodeEnabled ( nodeID )
local nodes = self.set and self.set . nodes
return nodes [ nodeID ] and true or false
end
function BtWLoadoutsSoulbindsMixin : SetNodeConduit ( nodeID , conduitID )
if not self.set or self.set . classID == nil then
return false
end
if conduitID ~= nil then
local conduit = GetConduitByID ( conduitID )
if not CheckConduitClass ( conduit , self.set . classID ) then
return false
end
end
local conduits = self.set . conduits
for nodeID , nodeConduitID in pairs ( conduits ) do
if conduitID == nodeConduitID then
conduits [ nodeID ] = nil
end
end
conduits [ nodeID ] = conduitID
self : Update ( )
return true
end
function BtWLoadoutsSoulbindsMixin : IsConduitSlotted ( conduitID )
local conduits = self.set and self.set . conduits
for _ , nodeConduitID in pairs ( conduits ) do
if conduitID == nodeConduitID then
return true
end
end
return false
end
function BtWLoadoutsSoulbindsMixin : Update ( )
self : GetParent ( ) : SetTitle ( L [ " Soulbinds " ] ) ;
local sidebar = BtWLoadoutsFrame.Sidebar
sidebar : SetSupportedFilters ( " covenant " , " spec " , " class " , " role " , " race " )
sidebar : SetSets ( BtWLoadoutsSets.soulbinds )
sidebar : SetCollapsed ( BtWLoadoutsCollapsed.soulbinds )
sidebar : SetCategories ( BtWLoadoutsCategories.soulbinds )
sidebar : SetFilters ( BtWLoadoutsFilters.soulbinds )
sidebar : SetSelected ( self.set )
sidebar : Update ( )
self.set = sidebar : GetSelected ( )
local set = self.set
local showingNPE = BtWLoadoutsFrame : SetNPEShown ( set == nil , L [ " Soulbinds " ] , L [ " Create soulbind trees for switching between soulbind paths, leave rows blank to not skip them. Conduits are not affected. " ] )
self : GetParent ( ) . ExportButton : SetEnabled ( true )
self : GetParent ( ) . DeleteButton : SetEnabled ( true ) ;
if not showingNPE then
local soulbindID = set.soulbindID ;
self : SetSoulbind ( soulbindID )
local soulbindData = self : GetSoulbind ( )
UpdateSetFilters ( set )
sidebar : Update ( )
set.restrictions = set.restrictions or { }
self.RestrictionsDropDown : SetSelections ( set.restrictions )
self.RestrictionsDropDown : SetLimitations ( " class " , set.classID )
self.RestrictionsButton : SetEnabled ( true ) ;
if not self.Name : HasFocus ( ) then
self.Name : SetText ( set.name or " " ) ;
end
-- UIDropDownMenu_SetSelectedValue(self.SoulbindDropDown, soulbindID);
UIDropDownMenu_SetText ( self.SoulbindDropDown , soulbindData.name ) ;
UIDropDownMenu_EnableDropDown ( self.SoulbindDropDown ) ;
if not set.conduits then
set.conduits = { }
end
local selected = set.nodes ;
local conduits = set.conduits ;
self.nodes : ReleaseAll ( )
self.links : ReleaseAll ( )
wipe ( self.nodesByID )
for _ , node in ipairs ( soulbindData.tree . nodes ) do
local nodeFrame = self.nodes : Acquire ( )
nodeFrame : SetFrameLevel ( 6 )
nodeFrame : SetPoint ( " TOP " , ( node.column - 1 ) * ( nodeFrame : GetWidth ( ) + 30 ) , - node.row * ( nodeFrame : GetHeight ( ) + 24 ) - 17 )
nodeFrame : Init ( self , node )
nodeFrame : SetConduit ( conduits [ node.ID ] )
nodeFrame : SetSelected ( selected [ node.ID ] )
nodeFrame : Show ( )
self.nodesByID [ node.ID ] = nodeFrame
end
for _ , linkFromFrame in pairs ( self.nodesByID ) do
if linkFromFrame.node . row > 0 then
for _ , parentID in ipairs ( linkFromFrame.node . parentNodeIDs ) do
local linkToFrame = self.nodesByID [ parentID ]
local linkFrame = self.links : Acquire ( )
linkFrame : SetFrameLevel ( 2 )
local toColumn = linkToFrame.node . column ;
local fromColumn = linkFromFrame.node . column ;
local offset = toColumn - fromColumn ;
if offset < 0 then
linkFrame : SetPoint ( " BOTTOMRIGHT " , linkFromFrame , " CENTER " ) ;
linkFrame : SetPoint ( " TOPLEFT " , linkToFrame , " CENTER " ) ;
elseif offset > 0 then
linkFrame : SetPoint ( " BOTTOMLEFT " , linkFromFrame , " CENTER " ) ;
linkFrame : SetPoint ( " TOPRIGHT " , linkToFrame , " CENTER " ) ;
else
linkFrame : SetPoint ( " BOTTOM " , linkFromFrame , " CENTER " ) ;
linkFrame : SetPoint ( " TOP " , linkToFrame , " CENTER " ) ;
end
local direction ;
local diagonal = toColumn ~= fromColumn ;
if diagonal then
direction = SoulbindTreeLinkDirections.Converge
else
direction = SoulbindTreeLinkDirections.Vertical ;
end
local quarter = ( math.pi * 0.5 ) ;
local angle = RegionUtil.CalculateAngleBetween ( linkToFrame , linkFromFrame ) - quarter ;
linkFrame : Init ( direction , angle ) ;
linkFrame : SetState ( ( selected [ linkToFrame.node . ID ] and selected [ linkFromFrame.node . ID ] ) and Enum.SoulbindNodeState . Selected or Enum.SoulbindNodeState . Unselected ) ;
linkFrame : Show ( ) ;
end
end
end
if set.classID then
local classInfo = C_CreatureInfo.GetClassInfo ( set.classID )
local classColor = C_ClassColor.GetClassColor ( classInfo.classFile )
UIDropDownMenu_SetText ( self.ClassDropDown , classColor : WrapTextInColorCode ( classInfo.className ) ) ;
else
UIDropDownMenu_SetText ( self.ClassDropDown , L [ " None " ] ) ;
end
UIDropDownMenu_EnableDropDown ( self.ClassDropDown ) ;
self.ConduitList : Init ( self , set.classID , soulbindData.covenantID )
self.ConduitList : Update ( )
local playerClassID = select ( 3 , UnitClass ( " player " ) )
local playerCovenantID = GetActiveCovenantID ( )
local playerSoulbindID = GetActiveSoulbindID ( )
self : GetParent ( ) . RefreshButton : SetEnabled ( soulbindID == playerSoulbindID )
self : GetParent ( ) . ActivateButton : SetEnabled ( soulbindData.covenantID == playerCovenantID and soulbindData.unlocked and ( set.classID == nil or set.classID == playerClassID ) ) ;
local helpTipBox = self : GetParent ( ) . HelpTipBox ;
helpTipBox : Hide ( ) ;
else
local soulbindID = GetActiveSoulbindID ( )
if soulbindID == 0 then
soulbindID = 7 -- Default to pelagos because why not
end
local soulbindData = GetSoulbindData ( soulbindID )
self.Name : SetText ( format ( L [ " New %s Set " ] , soulbindData.name ) ) ;
self.nodes : ReleaseAll ( )
self.links : ReleaseAll ( )
for _ , node in ipairs ( soulbindData.tree . nodes ) do
local nodeFrame = self.nodes : Acquire ( )
nodeFrame : SetFrameLevel ( 6 )
nodeFrame : SetPoint ( " TOP " , self.Inset , " TOP " , ( node.column - 1 ) * ( nodeFrame : GetWidth ( ) + 30 ) , - node.row * ( nodeFrame : GetHeight ( ) + 12 ) - 17 )
nodeFrame : Init ( self , node )
nodeFrame : SetSelected ( false )
nodeFrame : Show ( )
self.nodesByID [ node.ID ] = nodeFrame
end
local helpTipBox = self : GetParent ( ) . HelpTipBox ;
helpTipBox : Hide ( ) ;
end
end
function BtWLoadoutsSoulbindsMixin : SetEnabled ( value )
BtWLoadoutsTabFrame_SetEnabled ( self , value )
end
function BtWLoadoutsSoulbindsMixin : SetSetByID ( setID )
self.set = GetSet ( setID )
end