Skip to content

Commit 5587691

Browse files
committed
Add support for importing loadouts from build XML
Adds support for importing only loadouts (item sets, skill sets, tree specs, config sets) from a build XML to current build without overwriting anything else. Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
1 parent 4320038 commit 5587691

File tree

6 files changed

+317
-68
lines changed

6 files changed

+317
-68
lines changed

src/Classes/ConfigTab.lua

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -611,10 +611,12 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont
611611
self.controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, {0, 0, 18, 0}, 50, "VERTICAL", true)
612612
end)
613613

614-
function ConfigTabClass:Load(xml, fileName)
615-
self.activeConfigSetId = 1
616-
self.configSets = { }
617-
self.configSetOrderList = { 1 }
614+
function ConfigTabClass:Load(xml, fileName, appendConfigs)
615+
if not appendConfigs then
616+
self.activeConfigSetId = 0
617+
self.configSets = { }
618+
self.configSetOrderList = { }
619+
end
618620

619621
local function setInputAndPlaceholder(node, configSetId)
620622
if node.elem == "Input" then
@@ -660,24 +662,25 @@ function ConfigTabClass:Load(xml, fileName)
660662
if xml.empty then
661663
self:NewConfigSet(1, "Default")
662664
end
663-
for index, node in ipairs(xml) do
665+
for _, node in ipairs(xml) do
664666
if node.elem ~= "ConfigSet" then
665667
if not self.configSets[1] then
666668
self:NewConfigSet(1, "Default")
667669
end
668670
setInputAndPlaceholder(node, 1)
669671
else
670-
local configSetId = tonumber(node.attrib.id)
671-
self:NewConfigSet(configSetId, node.attrib.title or "Default")
672-
self.configSetOrderList[index] = configSetId
672+
local configSet = self:NewConfigSet(not appendConfigs and tonumber(node.attrib.id) or nil, node.attrib.title or "Default")
673+
t_insert(self.configSetOrderList, configSet.id)
673674
for _, child in ipairs(node) do
674-
setInputAndPlaceholder(child, configSetId)
675+
setInputAndPlaceholder(child, configSet.id)
675676
end
676677
end
677678
end
678679

679-
self:SetActiveConfigSet(tonumber(xml.attrib.activeConfigSet) or 1)
680-
self:ResetUndo()
680+
if not appendConfigs then
681+
self:SetActiveConfigSet(tonumber(xml.attrib.activeConfigSet) or 1)
682+
self:ResetUndo()
683+
end
681684
end
682685

683686
function ConfigTabClass:GetDefaultState(var, varType)

src/Classes/ImportTab.lua

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,24 @@ You can get this from your web browser's cookies while logged into the Path of E
314314
self.build:Init(self.build.dbFileName, self.build.buildName, self.importCodeXML, false, self.importCodeSite and self.controls.importCodeIn.buf or nil)
315315
self.build.viewMode = "TREE"
316316
end)
317+
elseif self.controls.importCodeMode.selIndex == 3 then
318+
local controls = { }
319+
t_insert(controls, new("LabelControl", nil, {0, 20, 0, 16}, colorCodes.WARNING.."Warning:^7 Importing many loadouts into the same build"))
320+
t_insert(controls, new("LabelControl", nil, {0, 36, 0, 16}, "may cause performance issues. Use with caution."))
321+
t_insert(controls, new("LabelControl", nil, {0, 64, 0, 16}, "^7Prefix for imported loadouts:"))
322+
controls.prefix = new("EditControl", nil, {0, 84, 350, 20}, "Imported - ", nil, nil, 50)
323+
controls.import = new("ButtonControl", nil, {-45, 114, 80, 20}, "Import", function()
324+
local prefix = controls.prefix.buf
325+
if prefix == "" then
326+
prefix = "Imported - "
327+
end
328+
main:ClosePopup()
329+
self.build:ImportLoadouts(self.importCodeXML, prefix)
330+
end)
331+
t_insert(controls, new("ButtonControl", nil, {45, 114, 80, 20}, "Cancel", function()
332+
main:ClosePopup()
333+
end))
334+
main:OpenPopup(380, 144, "Import Loadouts", controls, "import")
317335
else
318336
self.build:Shutdown()
319337
self.build:Init(false, "Imported build", self.importCodeXML, false, self.importCodeSite and self.controls.importCodeIn.buf or nil)
@@ -331,7 +349,7 @@ You can get this from your web browser's cookies while logged into the Path of E
331349
self.controls.importCodeState.label = function()
332350
return self.importCodeDetail or ""
333351
end
334-
self.controls.importCodeMode = new("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 160, 20}, { "Import to this build", "Import to a new build" })
352+
self.controls.importCodeMode = new("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 160, 20}, { "Import to this build", "Import to a new build", "Import loadouts only" })
335353
self.controls.importCodeMode.enabled = function()
336354
return self.build.dbFileName and self.importCodeValid
337355
end
@@ -1214,4 +1232,4 @@ function ImportTabClass:SetPredefinedBuildName()
12141232
local charData = charSelect.list[charSelect.selIndex].char
12151233
local charName = charData.name
12161234
main.predefinedBuildName = accountName.." - "..charName
1217-
end
1235+
end

src/Classes/ItemsTab.lua

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -958,15 +958,24 @@ holding Shift will put it in the second.]])
958958
self.lastSlot = self.slots[baseSlots[#baseSlots]]
959959
end)
960960

961-
function ItemsTabClass:Load(xml, dbFileName)
962-
self.activeItemSetId = 0
963-
self.itemSets = { }
964-
self.itemSetOrderList = { }
965-
self.tradeQuery.statSortSelectionList = { }
961+
function ItemsTabClass:Load(xml, dbFileName, appendItems)
962+
if not appendItems then
963+
self.activeItemSetId = 0
964+
self.itemSets = { }
965+
self.itemSetOrderList = { }
966+
self.tradeQuery.statSortSelectionList = { }
967+
end
968+
969+
local itemIdMap = { }
970+
local itemSetIdMap = { }
966971
for _, node in ipairs(xml) do
967972
if node.elem == "Item" then
968973
local item = new("Item", "")
969-
item.id = tonumber(node.attrib.id)
974+
local itemId = tonumber(node.attrib.id)
975+
if not appendItems then
976+
item.id = itemId
977+
end
978+
970979
item.variant = tonumber(node.attrib.variant)
971980
if node.attrib.variantAlt then
972981
item.hasAltVariant = true
@@ -1009,8 +1018,13 @@ function ItemsTabClass:Load(xml, dbFileName)
10091018
end
10101019
if item.base then
10111020
item:BuildModList()
1012-
self.items[item.id] = item
1013-
t_insert(self.itemOrderList, item.id)
1021+
if appendItems then
1022+
self:AddItem(item, true)
1023+
itemIdMap[itemId] = item.id
1024+
else
1025+
self.items[item.id] = item
1026+
t_insert(self.itemOrderList, item.id)
1027+
end
10141028
end
10151029
-- Below is OBE and left for legacy compatibility (all Slots are part of ItemSets now)
10161030
elseif node.elem == "Slot" then
@@ -1023,14 +1037,22 @@ function ItemsTabClass:Load(xml, dbFileName)
10231037
end
10241038
end
10251039
elseif node.elem == "ItemSet" then
1026-
local itemSet = self:NewItemSet(tonumber(node.attrib.id))
1040+
local oldItemSetId = tonumber(node.attrib.id)
1041+
local itemSet = self:NewItemSet(not appendItems and oldItemSetId or nil)
1042+
if appendItems then
1043+
itemSetIdMap[oldItemSetId] = itemSet.id
1044+
end
10271045
itemSet.title = node.attrib.title
10281046
itemSet.useSecondWeaponSet = node.attrib.useSecondWeaponSet == "true"
10291047
for _, child in ipairs(node) do
10301048
if child.elem == "Slot" then
10311049
local slotName = child.attrib.name or ""
10321050
if itemSet[slotName] then
1033-
itemSet[slotName].selItemId = tonumber(child.attrib.itemId)
1051+
local itemId = tonumber(child.attrib.itemId)
1052+
if appendItems and itemIdMap[itemId] then
1053+
itemId = itemIdMap[itemId]
1054+
end
1055+
itemSet[slotName].selItemId = itemId
10341056
itemSet[slotName].active = child.attrib.active == "true"
10351057
itemSet[slotName].pbURL = child.attrib.itemPbURL or ""
10361058
end
@@ -1051,16 +1073,20 @@ function ItemsTabClass:Load(xml, dbFileName)
10511073
end
10521074
end
10531075
end
1054-
if not self.itemSetOrderList[1] then
1055-
self.activeItemSet = self:NewItemSet(1)
1056-
self.activeItemSet.useSecondWeaponSet = xml.attrib.useSecondWeaponSet == "true"
1057-
self.itemSetOrderList[1] = 1
1058-
end
1059-
self:SetActiveItemSet(tonumber(xml.attrib.activeItemSet) or 1)
1060-
if xml.attrib.showStatDifferences then
1061-
self.showStatDifferences = xml.attrib.showStatDifferences == "true"
1076+
if not appendItems then
1077+
if not self.itemSetOrderList[1] then
1078+
self.activeItemSet = self:NewItemSet(1)
1079+
self.activeItemSet.useSecondWeaponSet = xml.attrib.useSecondWeaponSet == "true"
1080+
self.itemSetOrderList[1] = 1
1081+
end
1082+
self:SetActiveItemSet(tonumber(xml.attrib.activeItemSet) or 1)
1083+
if xml.attrib.showStatDifferences then
1084+
self.showStatDifferences = xml.attrib.showStatDifferences == "true"
1085+
end
1086+
self:ResetUndo()
1087+
else
1088+
return itemIdMap, itemSetIdMap
10621089
end
1063-
self:ResetUndo()
10641090
end
10651091

10661092
function ItemsTabClass:Save(xml)

src/Classes/SkillsTab.lua

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -374,33 +374,36 @@ function SkillsTabClass:LoadSkill(node, skillSetId)
374374
t_insert(self.skillSets[skillSetId].socketGroupList, socketGroup)
375375
end
376376

377-
function SkillsTabClass:Load(xml, fileName)
378-
self.activeSkillSetId = 0
379-
self.skillSets = { }
380-
self.skillSetOrderList = { }
381-
-- Handle legacy configuration settings when loading `defaultGemLevel`
382-
if xml.attrib.matchGemLevelToCharacterLevel == "true" then
383-
self.controls.defaultLevel:SelByValue("characterLevel", "gemLevel")
384-
elseif type(xml.attrib.defaultGemLevel) == "string" and tonumber(xml.attrib.defaultGemLevel) == nil then
385-
self.controls.defaultLevel:SelByValue(xml.attrib.defaultGemLevel, "gemLevel")
386-
else
387-
self.controls.defaultLevel:SelByValue("normalMaximum", "gemLevel")
388-
end
389-
self.defaultGemLevel = self.controls.defaultLevel:GetSelValueByKey("gemLevel")
390-
self.defaultGemQuality = m_max(m_min(tonumber(xml.attrib.defaultGemQuality) or 0, 23), 0)
391-
self.controls.defaultQuality:SetText(self.defaultGemQuality or "")
392-
if xml.attrib.sortGemsByDPS then
393-
self.sortGemsByDPS = xml.attrib.sortGemsByDPS == "true"
394-
end
395-
self.controls.sortGemsByDPS.state = self.sortGemsByDPS
396-
if xml.attrib.showAltQualityGems then
397-
self.showAltQualityGems = xml.attrib.showAltQualityGems == "true"
398-
end
399-
self.controls.showAltQualityGems.state = self.showAltQualityGems
400-
self.controls.showSupportGemTypes:SelByValue(xml.attrib.showSupportGemTypes or "ALL", "show")
401-
self.controls.sortGemsByDPSFieldControl:SelByValue(xml.attrib.sortGemsByDPSField or "CombinedDPS", "type")
402-
self.showSupportGemTypes = self.controls.showSupportGemTypes:GetSelValueByKey("show")
403-
self.sortGemsByDPSField = self.controls.sortGemsByDPSFieldControl:GetSelValueByKey("type")
377+
function SkillsTabClass:Load(xml, fileName, appendSkills)
378+
if not appendSkills then
379+
self.activeSkillSetId = 0
380+
self.skillSets = { }
381+
self.skillSetOrderList = { }
382+
-- Handle legacy configuration settings when loading `defaultGemLevel`
383+
if xml.attrib.matchGemLevelToCharacterLevel == "true" then
384+
self.controls.defaultLevel:SelByValue("characterLevel", "gemLevel")
385+
elseif type(xml.attrib.defaultGemLevel) == "string" and tonumber(xml.attrib.defaultGemLevel) == nil then
386+
self.controls.defaultLevel:SelByValue(xml.attrib.defaultGemLevel, "gemLevel")
387+
else
388+
self.controls.defaultLevel:SelByValue("normalMaximum", "gemLevel")
389+
end
390+
self.defaultGemLevel = self.controls.defaultLevel:GetSelValueByKey("gemLevel")
391+
self.defaultGemQuality = m_max(m_min(tonumber(xml.attrib.defaultGemQuality) or 0, 23), 0)
392+
self.controls.defaultQuality:SetText(self.defaultGemQuality or "")
393+
if xml.attrib.sortGemsByDPS then
394+
self.sortGemsByDPS = xml.attrib.sortGemsByDPS == "true"
395+
end
396+
self.controls.sortGemsByDPS.state = self.sortGemsByDPS
397+
if xml.attrib.showAltQualityGems then
398+
self.showAltQualityGems = xml.attrib.showAltQualityGems == "true"
399+
end
400+
self.controls.showAltQualityGems.state = self.showAltQualityGems
401+
self.controls.showSupportGemTypes:SelByValue(xml.attrib.showSupportGemTypes or "ALL", "show")
402+
self.controls.sortGemsByDPSFieldControl:SelByValue(xml.attrib.sortGemsByDPSField or "CombinedDPS", "type")
403+
self.showSupportGemTypes = self.controls.showSupportGemTypes:GetSelValueByKey("show")
404+
self.sortGemsByDPSField = self.controls.sortGemsByDPSFieldControl:GetSelValueByKey("type")
405+
end
406+
404407
for _, node in ipairs(xml) do
405408
if node.elem == "Skill" then
406409
-- Old format, initialize skill sets if needed
@@ -412,16 +415,18 @@ function SkillsTabClass:Load(xml, fileName)
412415
end
413416

414417
if node.elem == "SkillSet" then
415-
local skillSet = self:NewSkillSet(tonumber(node.attrib.id))
418+
local skillSet = self:NewSkillSet(not appendSkills and tonumber(node.attrib.id) or nil)
416419
skillSet.title = node.attrib.title
417420
t_insert(self.skillSetOrderList, skillSet.id)
418421
for _, subNode in ipairs(node) do
419422
self:LoadSkill(subNode, skillSet.id)
420423
end
421424
end
422425
end
423-
self:SetActiveSkillSet(tonumber(xml.attrib.activeSkillSet) or 1)
424-
self:ResetUndo()
426+
if not appendSkills then
427+
self:SetActiveSkillSet(tonumber(xml.attrib.activeSkillSet) or 1)
428+
self:ResetUndo()
429+
end
425430
end
426431

427432
function SkillsTabClass:Save(xml)

src/Classes/TreeTab.lua

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,11 @@ function TreeTabClass:GetSpecList()
456456
return newSpecList
457457
end
458458

459-
function TreeTabClass:Load(xml, dbFileName)
460-
self.specList = { }
459+
function TreeTabClass:Load(xml, dbFileName, appendSpecs)
460+
if not appendSpecs then
461+
self.specList = { }
462+
end
463+
461464
if xml.elem == "Spec" then
462465
-- Import single spec from old build
463466
self.specList[1] = new("PassiveSpec", self.build, defaultTreeVersion)
@@ -473,16 +476,19 @@ function TreeTabClass:Load(xml, dbFileName)
473476
main:OpenMessagePopup("Unknown Passive Tree Version", "The build you are trying to load uses an unrecognised version of the passive skill tree.\nYou may need to update the program before loading this build.")
474477
return true
475478
end
479+
476480
local newSpec = new("PassiveSpec", self.build, node.attrib.treeVersion or defaultTreeVersion)
477481
newSpec:Load(node, dbFileName)
478482
t_insert(self.specList, newSpec)
479483
end
480484
end
481485
end
482-
if not self.specList[1] then
483-
self.specList[1] = new("PassiveSpec", self.build, latestTreeVersion)
486+
if not appendSpecs then
487+
if not self.specList[1] then
488+
self.specList[1] = new("PassiveSpec", self.build, latestTreeVersion)
489+
end
490+
self:SetActiveSpec(tonumber(xml.attrib.activeSpec) or 1)
484491
end
485-
self:SetActiveSpec(tonumber(xml.attrib.activeSpec) or 1)
486492
end
487493

488494
function TreeTabClass:PostLoad()

0 commit comments

Comments
 (0)