Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,9 @@ Loadouts can be selected from the dropdown in the top middle of the screen. Sele

3) If there is only one set for a set type (except passive tree), e.g. "Default" config set, it will be assigned to all existing loadouts.

The "New Loadout" option allows the user to create all four sets from a single popup for convenience.
The "New Loadout" option allows the user to create all four sets from a single popup for convenience. If you check the current active sets option, it will make a new loadout by copying all the active sets and giving them the new name.
The "Sync" option is a backup option to force the UI to update in case the user has changed this data behind the scenes.
All options that allow you to enter a name only support exact name match, although you can technically add an identifier in the name, but be careful of giving multiple loadouts the same identifier. Things will get krangled quickly.


---[Party Tab]
Expand Down
117 changes: 117 additions & 0 deletions spec/System/TestLoadouts_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
describe("TestLoadouts", function()
before_each(function()
newBuild()

build.itemsTab:CreateDisplayItemFromRaw([[Dialla's Malefaction
Sage's Robe
Energy Shield: 95
EnergyShieldBasePercentile: 0
Variant: Pre 3.19.0
Variant: Current
Selected Variant: 2
Sage's Robe
Quality: 20
Sockets: R-G-B-B-B-B
LevelReq: 37
Implicits: 0
Gems can be Socketed in this Item ignoring Socket Colour
{variant:1}Gems Socketed in Red Sockets have +1 to Level
{variant:2}Gems Socketed in Red Sockets have +2 to Level
{variant:1}Gems Socketed in Green Sockets have +10% to Quality
{variant:2}Gems Socketed in Green Sockets have +30% to Quality
{variant:1}Gems Socketed in Blue Sockets gain 25% increased Experience
{variant:2}Gems Socketed in Blue Sockets gain 100% increased Experience
Has no Attribute Requirements]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
end)

teardown(function()
-- newBuild() takes care of resetting everything in setup()
end)

local function getSelectedLoadout(treeId, itemIndex, itemId, skillIndex, skillId, configIndex, configId)
local selectedLoadout = {
treeId = treeId,
itemIndex = itemIndex,
itemId = itemId,
skillIndex = skillIndex,
skillId = skillId,
configIndex = configIndex,
configId = configId,
}
return selectedLoadout
end

it("Test -- Default loadout exists on new build", function()
assert.are.equals(1, #build.controls.buildLoadouts.existingLoadoutsList)
assert.are.equals("Default", build.controls.buildLoadouts.existingLoadoutsList[1])
end)

it("Test New Loadout -- Default selected, fromExistingSets false", function()
build:NewLoadout(false, "New Loadout 1", getSelectedLoadout(1, 1, 1, 1, 1, 1, 1))
build:SyncLoadouts()

assert.are.equals(2, #build.controls.buildLoadouts.existingLoadoutsList)
assert.are.equals("Default", build.controls.buildLoadouts.existingLoadoutsList[1])
assert.are.equals("New Loadout 1", build.controls.buildLoadouts.existingLoadoutsList[2])

assert.are.equals(1, build.itemsTab.itemSets[1]["Body Armour"].selItemId)
assert.are.equals(0, build.itemsTab.itemSets[2]["Body Armour"].selItemId) -- Dialla's not copied over, new empty set
end)

it("Test New Loadout -- Default selected, fromExistingSets true", function()
build:NewLoadout(true, "New Loadout 1", getSelectedLoadout(1, 1, 1, 1, 1, 1, 1))
build:SyncLoadouts()

assert.are.equals(2, #build.controls.buildLoadouts.existingLoadoutsList)
assert.are.equals("Default", build.controls.buildLoadouts.existingLoadoutsList[1])
assert.are.equals("New Loadout 1", build.controls.buildLoadouts.existingLoadoutsList[2])

assert.are.equals(1, build.itemsTab.itemSets[1]["Body Armour"].selItemId)
assert.are.equals(1, build.itemsTab.itemSets[2]["Body Armour"].selItemId) -- Dialla's copied over successfully
end)

it("Test Copy Loadout -- Default selected", function()
build:CopyLoadout("New Loadout 1", getSelectedLoadout(1, 1, 1, 1, 1, 1, 1))
build:SyncLoadouts()

assert.are.equals(2, #build.controls.buildLoadouts.existingLoadoutsList)
assert.are.equals("Default", build.controls.buildLoadouts.existingLoadoutsList[1])
assert.are.equals("New Loadout 1", build.controls.buildLoadouts.existingLoadoutsList[2])

assert.are.equals(1, build.itemsTab.itemSets[1]["Body Armour"].selItemId)
assert.are.equals(1, build.itemsTab.itemSets[2]["Body Armour"].selItemId) -- Dialla's copied over successfully
end)

it("Test Rename Loadout -- Default selected", function()
build:RenameLoadout("New Loadout 1", getSelectedLoadout(1, 1, 1, 1, 1, 1, 1))
build:SyncLoadouts()

assert.are.equals(1, #build.controls.buildLoadouts.existingLoadoutsList)
assert.are.equals("New Loadout 1", build.controls.buildLoadouts.existingLoadoutsList[1])
end)

it("Test Delete Loadout -- Default selected after creating New Loadout 1", function()
build:NewLoadout(false, "New Loadout 1", getSelectedLoadout(1, 1, 1, 1, 1, 1, 1))
build:SyncLoadouts()

build:DeleteLoadout(getSelectedLoadout(1, 1, 1, 1, 1, 1, 1))
build:SyncLoadouts()

assert.are.equals(1, #build.controls.buildLoadouts.existingLoadoutsList)
assert.are.equals("New Loadout 1", build.controls.buildLoadouts.existingLoadoutsList[1])
end)

it("Test Delete Loadout -- New Loadout 1 selected", function()
build:NewLoadout(false, "New Loadout 1", getSelectedLoadout(1, 1, 1, 1, 1, 1, 1))
build:SyncLoadouts()

build:DeleteLoadout(getSelectedLoadout(2, 2, 2, 2, 2, 2, 2))
build:SyncLoadouts()

assert.are.equals(1, #build.controls.buildLoadouts.existingLoadoutsList)
assert.are.equals("Default", build.controls.buildLoadouts.existingLoadoutsList[1])
assert.are.equals(1, build.itemsTab.itemSets[1]["Body Armour"].selItemId) -- make sure items weren't somehow affected
end)
end)
27 changes: 24 additions & 3 deletions src/Classes/ConfigSetListControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ local m_max = math.max
local ConfigSetListClass = newClass("ConfigSetListControl", "ListControl", function(self, anchor, rect, configTab)
self.ListControl(anchor, rect, 16, "VERTICAL", true, configTab.configSetOrderList)
self.configTab = configTab
self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function()
local configSet = configTab.configSets[self.selValue]
self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function(id) -- id is for Loadouts using copy.onClick()
local configSet = configTab.configSets[id or self.selValue]
local newConfigSet = copyTable(configSet)
newConfigSet.id = 1
while configTab.configSets[newConfigSet.id] do
newConfigSet.id = newConfigSet.id + 1
end
configTab.configSets[newConfigSet.id] = newConfigSet
self:RenameSet(newConfigSet, true)
if not id then
self:RenameSet(newConfigSet, true)
else
return newConfigSet
end
end)
self.controls.copy.enabled = function()
return self.selValue ~= nil
Expand Down Expand Up @@ -103,6 +107,23 @@ function ConfigSetListClass:OnSelDelete(index, configSetId)
end
end

-- bypass confirmation popup, used by Loadouts
function ConfigSetListClass:DeleteById(index, configSetId, sync)
if #self.list > 1 then
t_remove(self.list, index)
self.configTab.configSets[configSetId] = nil
self.selIndex = nil
self.selValue = nil
if configSetId == self.configTab.activeConfigSetId then
self.configTab:SetActiveConfigSet(self.list[m_max(1, index - 1)])
end
self.configTab:AddUndoState()
if sync then
self.configTab.build:SyncLoadouts()
end
end
end

function ConfigSetListClass:OnSelKeyDown(index, configSetId, key)
if key == "F2" then
self:RenameSet(self.configTab.configSets[configSetId])
Expand Down
28 changes: 25 additions & 3 deletions src/Classes/ItemSetListControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ local s_format = string.format
local ItemSetListClass = newClass("ItemSetListControl", "ListControl", function(self, anchor, rect, itemsTab)
self.ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemSetOrderList)
self.itemsTab = itemsTab
self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function()
local newSet = copyTable(itemsTab.itemSets[self.selValue])
self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function(id) -- id is for Loadouts using copy.onClick()
local newSet = copyTable(itemsTab.itemSets[id or self.selValue])
newSet.id = 1
while itemsTab.itemSets[newSet.id] do
newSet.id = newSet.id + 1
end
itemsTab.itemSets[newSet.id] = newSet
self:RenameSet(newSet, true)
if not id then
self:RenameSet(newSet, true)
else
return newSet
end
end)
self.controls.copy.enabled = function()
return self.selValue ~= nil
Expand Down Expand Up @@ -133,6 +137,24 @@ function ItemSetListClass:OnSelDelete(index, itemSetId)
end
end

-- bypass confirmation popup, used by Loadouts
function ItemSetListClass:DeleteById(index, itemSetId, sync)
local itemSet = self.itemsTab.itemSets[itemSetId]
if #self.list > 1 then
t_remove(self.list, index)
self.itemsTab.itemSets[itemSetId] = nil
self.selIndex = nil
self.selValue = nil
if itemSetId == self.itemsTab.activeItemSetId then
self.itemsTab:SetActiveItemSet(self.list[m_max(1, index - 1)])
end
self.itemsTab:AddUndoState()
if sync then
self.itemsTab.build:SyncLoadouts()
end
end
end

function ItemSetListClass:OnSelKeyDown(index, itemSetId, key)
local itemSet = self.itemsTab.itemSets[itemSetId]
if key == "F2" then
Expand Down
36 changes: 30 additions & 6 deletions src/Classes/PassiveSpecListControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ local m_max = math.max
local PassiveSpecListClass = newClass("PassiveSpecListControl", "ListControl", function(self, anchor, rect, treeTab)
self.ListControl(anchor, rect, 16, "VERTICAL", true, treeTab.specList)
self.treeTab = treeTab
self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function()
local newSpec = new("PassiveSpec", treeTab.build, self.selValue.treeVersion)
newSpec.title = self.selValue.title
newSpec.jewels = copyTable(self.selValue.jewels)
newSpec:RestoreUndoState(self.selValue:CreateUndoState())
self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function(spec) -- spec is for Loadouts using copy.onClick()
local selValue = spec or self.selValue
local newSpec = new("PassiveSpec", treeTab.build, selValue.treeVersion)
newSpec.title = selValue.title
newSpec.jewels = copyTable(selValue.jewels)
newSpec:RestoreUndoState(selValue:CreateUndoState())
newSpec:BuildClusterJewelGraphs()
self:RenameSpec(newSpec, "Copy Tree", true)
if not spec then
self:RenameSpec(newSpec, "Copy Tree", true)
else
return newSpec
end
end)
self.controls.copy.enabled = function()
return self.selValue ~= nil
Expand Down Expand Up @@ -110,6 +115,25 @@ function PassiveSpecListClass:OnSelDelete(index, spec)
end
end

-- bypass confirmation popup, used by Loadouts
function PassiveSpecListClass:DeleteByIndex(index, sync)
if #self.list > 1 then
t_remove(self.list, index)
self.selIndex = nil
self.selValue = nil
if index == self.treeTab.activeSpec then
self.treeTab:SetActiveSpec(1)
else
self.treeTab.activeSpec = isValueInArray(self.list, self.treeTab.build.spec)
end
self.treeTab.modFlag = true
self:UpdateItemsTabPassiveTreeDropdown()
if sync then
self.treeTab.build:SyncLoadouts()
end
end
end

function PassiveSpecListClass:OnSelKeyDown(index, spec, key)
if key == "F2" then
self:RenameSpec(spec, "Rename Tree")
Expand Down
27 changes: 24 additions & 3 deletions src/Classes/SkillSetListControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ local s_format = string.format
local SkillSetListClass = newClass("SkillSetListControl", "ListControl", function(self, anchor, rect, skillsTab)
self.ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.skillSetOrderList)
self.skillsTab = skillsTab
self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function()
local skillSet = skillsTab.skillSets[self.selValue]
self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function(id) -- id is for Loadouts using copy.onClick()
local skillSet = skillsTab.skillSets[id or self.selValue]
local newSkillSet = copyTable(skillSet, true)
newSkillSet.socketGroupList = { }
for socketGroupIndex, socketGroup in pairs(skillSet.socketGroupList) do
Expand All @@ -28,7 +28,11 @@ local SkillSetListClass = newClass("SkillSetListControl", "ListControl", functio
newSkillSet.id = newSkillSet.id + 1
end
skillsTab.skillSets[newSkillSet.id] = newSkillSet
self:RenameSet(newSkillSet, true)
if not id then
self:RenameSet(newSkillSet, true)
else
return newSkillSet
end
end)
self.controls.copy.enabled = function()
return self.selValue ~= nil
Expand Down Expand Up @@ -113,6 +117,23 @@ function SkillSetListClass:OnSelDelete(index, skillSetId)
end
end

-- bypass confirmation popup, used by Loadouts
function SkillSetListClass:DeleteById(index, skillSetId, sync)
if #self.list > 1 then
t_remove(self.list, index)
self.skillsTab.skillSets[skillSetId] = nil
self.selIndex = nil
self.selValue = nil
if skillSetId == self.skillsTab.activeSkillSetId then
self.skillsTab:SetActiveSkillSet(self.list[m_max(1, index - 1)])
end
self.skillsTab:AddUndoState()
if sync then
self.skillsTab.build:SyncLoadouts()
end
end
end

function SkillSetListClass:OnSelKeyDown(index, skillSetId, key)
if key == "F2" then
self:RenameSet(self.skillsTab.skillSets[skillSetId])
Expand Down
Loading