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
8 changes: 7 additions & 1 deletion src/Classes/DropDownControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,22 @@ function DropDownClass:DrawSearchHighlights(label, searchInfo, x, y, width, heig
end


function DropDownClass:SelByValue(value, key)
function DropDownClass:SelByValue(value, key, callSelFunc)
for index, listVal in ipairs(self.list) do
if type(listVal) == "table" then
if listVal[key] == value then
self.selIndex = index
if callSelFunc and self.selFunc then
self.selFunc(index, self.list[index])
end
return
end
else
if listVal == value then
self.selIndex = index
if callSelFunc and self.selFunc then
self.selFunc(index, self.list[index])
end
return
end
end
Expand Down
21 changes: 20 additions & 1 deletion src/Classes/ImportTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1023,12 +1023,31 @@ function ImportTabClass:ImportItemsAndSkills(charData)
return charData -- For the wrapper
end

function ImportTabClass:ImportChakra(slotName, runeName)
local slot = self.build.itemsTab.runeSlots[slotName]
-- note that if the rune is not in ModRunes.lua, this will not select it
if slot then
slot:SelByValue(runeName, "name", true)
end
end

local rarityMap = { [0] = "NORMAL", "MAGIC", "RARE", "UNIQUE", [9] = "RELIC", [10] = "RELIC", [13] = "RARE" }
local slotMap = { ["Weapon"] = "Weapon 1", ["Offhand"] = "Weapon 2", ["Weapon2"] = "Weapon 1 Swap", ["Offhand2"] = "Weapon 2 Swap", ["Helm"] = "Helmet", ["BodyArmour"] = "Body Armour", ["Gloves"] = "Gloves", ["Boots"] = "Boots", ["Amulet"] = "Amulet", ["Ring"] = "Ring 1", ["Ring2"] = "Ring 2", ["Ring3"] = "Ring 3", ["Belt"] = "Belt", ["IncursionArmLeft"] = "Arm 2", ["IncursionArmRight"] = "Arm 1", ["IncursionLegLeft"] = "Leg 2", ["IncursionLegRight"] = "Leg 1" }

function ImportTabClass:ImportItem(itemData, slotName)
if not slotName then
if itemData.inventoryId == "PassiveJewels" then
-- monk martial artist rune tattoos
if itemData.inventoryId == "Chakra" then
-- TODO: should probably be exported from chakra slots table
-- API doesn't have slots directly, but has an x position similar to flasks
slotMap = {"Helmet Rune #1", "Body Armour Rune #1", "Body Armour Rune #2", "Gloves Rune #1", "Boots Rune #1"}
if slotMap[itemData.x + 1] and itemData.baseType then
slotName = slotMap[itemData.x + 1]
-- runes are imported differently as they're not items located in your inventory
self:ImportChakra(slotName, itemData.baseType)
return
end
elseif itemData.inventoryId == "PassiveJewels" then
slotName = "Jewel ".. self.build.latestTree.jewelSlots[itemData.x + 1]
elseif itemData.inventoryId == "Flask" then
if itemData.x > 1 then
Expand Down
2 changes: 1 addition & 1 deletion src/Classes/Item.lua
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality)
local runeData = data.itemMods.Runes[specVal]
if runeData then
for _, slotData in pairs(runeData) do
runeLevel = math.max(runeLevel, slotData.rank[1])
runeLevel = m_max(runeLevel, slotData.rank)
end
end
if runeLevel > 0 and (not self.requirements.runeLevel or runeLevel > self.requirements.runeLevel) then
Expand Down
179 changes: 173 additions & 6 deletions src/Classes/ItemsTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,11 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro
-- PoB Trader class initialization
self.tradeQuery = new("TradeQuery", self)

-- x offset for all of the left side item tab controls since they are
-- anchored to one another from top to bottom
local selectorsXOffset = 109
-- Set selector
self.controls.setSelect = new("DropDownControl", {"TOPLEFT",self,"TOPLEFT"}, {96, 8, 216, 20}, nil, function(index, value)
self.controls.setSelect = new("DropDownControl", {"TOPLEFT",self,"TOPLEFT"}, { selectorsXOffset, 8, 216, 20 }, nil, function(index, value)
self:SetActiveItemSet(self.itemSetOrderList[index])
self:AddUndoState()
end)
Expand All @@ -170,7 +173,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro
end)

-- Price Items
self.controls.priceDisplayItem = new("ButtonControl", {"TOPLEFT",self,"TOPLEFT"}, {96, 32, 310, 20}, "Trade for these items", function()
self.controls.priceDisplayItem = new("ButtonControl", {"TOPLEFT",self,"TOPLEFT"}, { selectorsXOffset, 32, 310, 20 }, "Trade for these items", function()
self.tradeQuery:PriceItem()
end)
self.controls.priceDisplayItem.tooltipFunc = function(tooltip)
Expand All @@ -179,12 +182,70 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro
tooltip:AddLine(16, "^7similar or better items for this build")
end

-- list of runes that fit the martial artist slots, and which have global
-- effects
local runeList = { helmet = {}, ["body armour"] = {}, gloves = {}, boots = {} }

for name, runeMods in pairs(data.itemMods.Runes) do
for slot, mod in pairs(runeMods) do
if mod.type == "Rune" and not mod.localMod and (runeList[slot] or (slot == "armour")) then
local rune = {mods = {}}

for _, line in ipairs(mod) do
local modList, extra = modLib.parseMod(line)
t_insert(rune, line)
for _, mod in ipairs(modList or {}) do
t_insert(rune.mods, mod)
end
end

rune.name = name
rune.label = mod[1]
rune.order = mod.statOrder[1]
rune.req = mod.rank
rune.group = #mod
rune.limit = mod.limit

if slot == "armour" then
for _, v in pairs(runeList) do
table.insert(v, rune)
end
else
table.insert(runeList[slot], rune)
end
end
end
end

for _, v in pairs(runeList) do
local sortKeys = {"req", "order", "group"}
table.sort(v, function(a, b)
for _, key in ipairs(sortKeys) do
if a[key] > b[key] then
return true
elseif a[key] < b[key] then
return false
end
end
return false
-- if a.order == b.order then
-- return a.req > b.req
-- elseif a.group == b.group then
-- return a.order < b.order
-- else
-- return a.group < b.group
-- end
end)
table.insert(v, 1, { label = "None", mods = {}, order = -1, group = -1, req = 1 })
end

-- Item slots
self.slots = { }
self.orderedSlots = { }
self.slotOrder = { }
self.runeSlots = { }
self.initSockets = true
self.slotAnchor = new("Control", {"TOPLEFT",self,"TOPLEFT"}, {96, 76, 310, 0})
self.slotAnchor = new("Control", {"TOPLEFT",self,"TOPLEFT"}, {selectorsXOffset, 76, 310, 0})
local prevSlot = self.slotAnchor
local function addSlot(slot)
prevSlot = slot
Expand All @@ -205,6 +266,65 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro
parentSlot.jewelSocketList[i] = jewel
end
end
local function addRuneSockets()
-- TODO: use game data for this from chakra slots table
local slots = { { type = "Helmet", n = 1 }, { type = "Body Armour", n = 2 }, { type = "Gloves", n = 1 }, { type = "Boots", n = 1 } }
for _, slot in ipairs(slots) do
for i = 1, slot.n do
local slotName = s_format("%s Rune #%d", slot.type, i)
local label = slotName:gsub(" Armour", ""):gsub("#", "")

local runeSlot = new("DropDownControl", { "TOPLEFT", prevSlot, "BOTTOMLEFT" }, {0, 2, 310, 20}, runeList[slot.type:lower()], function (_, value)
self.activeItemSet[slotName] = { runeName = value.name }
self.build.buildFlag = true
end)
runeSlot.anchor.collapse = true

runeSlot.tooltipFunc = function(tooltip, mode, index, rune)
tooltip:Clear()
if rune.label ~= "None" then
tooltip:AddLine(16, "^7" .. rune.name)

if rune.limit then
tooltip:AddLine(14, "^7" .. s_format("Limited to: %d", rune.limit))
end

if rune.req > 1 then
tooltip:AddLine(14, "^7" .. s_format("Requires: Level %d", rune.req))
end
for _, line in ipairs(rune) do
-- skip bonded lines as monks cannot use these
if not line:match("^Bonded:") then
tooltip:AddLine(14, colorCodes.MAGIC .. line)
end
end
-- Adding Comparison
local compLines = { type = "Rune" }
for _, line in ipairs(rune) do
t_insert(compLines, line)
end
local calcFunc = self.build.calcsTab:GetMiscCalculator()
local outputBase = calcFunc()
local outputNew = calcFunc({ repSlotName = slotName, repItem = rune })
self.build:AddStatComparesToTooltip(tooltip, outputBase, outputNew,
"\n^7Adding this mod will give: ")
end
end

self.controls[slotName .. " Label"] = new("LabelControl", { "RIGHT", runeSlot, "LEFT" },
{ -2, 0, 16, 16 },
s_format("^7%s:", label))

prevSlot = runeSlot
t_insert(self.controls, runeSlot)
self.runeSlots[slotName] = runeSlot
runeSlot.shown = function()
return self.build.calcsTab.mainEnv.modDB:Flag(nil, "SocketRunesOnCharacter")
end
end

end
end
for index, slotName in ipairs(baseSlots) do
local slot = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName)
addSlot(slot)
Expand Down Expand Up @@ -243,21 +363,26 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro
end
end

addRuneSockets()

-- Passive tree dropdown controls
self.controls.specSelect = new("DropDownControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, {0, 8, 216, 20}, nil, function(index, value)
if self.build.treeTab.specList[index] then
self.build.modFlag = true
self.build.treeTab:SetActiveSpec(index)
end
end)
self.controls.specSelect.anchor.collapse = true
self.controls.specSelect.enabled = function()
return #self.controls.specSelect.list > 1
end
prevSlot = self.controls.specSelect
self.controls.specButton = new("ButtonControl", {"LEFT",prevSlot,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function()
self.build.treeTab:OpenSpecManagePopup()
end)
self.controls.specButton.anchor.collapse = true
self.controls.specLabel = new("LabelControl", {"RIGHT",prevSlot,"LEFT"}, {-2, 0, 0, 16}, "^7Passive tree:")
self.controls.specLabel.anchor.collapse = true

self.sockets = { }
local socketOrder = { }
Expand Down Expand Up @@ -678,9 +803,17 @@ holding Shift will put it in the second.]])
drop.tooltipFunc = function(tooltip, mode, index, value)
tooltip:Clear()
if value.lines and value.lines[1] ~= "None" then
tooltip:AddLine(14, "^7"..value.name)
tooltip:AddLine(16, "^7" .. value.name)

if value.lines and value.lines.limit then
tooltip:AddLine(14, "^7" .. s_format("Limited to: %d", value.lines.limit))
end

if value.req > 1 then
tooltip:AddLine(14, "^7" .. s_format("Requires: Level %d", value.req))
end
for _, line in ipairs(value.lines) do
tooltip:AddLine(14, "^7"..line)
tooltip:AddLine(14, colorCodes.MAGIC .. line)
end
-- Adding Comparison
local compLines = { type = "Rune" }
Expand Down Expand Up @@ -1128,6 +1261,13 @@ function ItemsTabClass:Load(xml, dbFileName)
itemSet[slotName].active = child.attrib.active == "true"
itemSet[slotName].pbURL = child.attrib.itemPbURL or ""
end
elseif child.elem == "RuneSlot" then
local slotName = child.attrib.slotName or ""
local slot = itemSet[slotName]
if slot then
local runeName = child.attrib.runeName or "None"
slot.runeName = runeName
end
elseif child.elem == "SocketIdURL" then
local id = tonumber(child.attrib.nodeId)
itemSet[id] = { pbURL = child.attrib.itemPbURL or "" }
Expand Down Expand Up @@ -1220,6 +1360,11 @@ function ItemsTabClass:Save(xml)
end
end
end
for slotName, _ in pairs(self.runeSlots) do
local runeName = (itemSet[slotName] and itemSet[slotName].runeName) or "None"
local node = { elem = "RuneSlot", attrib = { slotName = slotName, runeName = runeName } }
t_insert(child, node)
end
t_insert(xml, child)
end
if self.tradeQuery.statSortSelectionList then
Expand Down Expand Up @@ -1393,6 +1538,9 @@ function ItemsTabClass:CreateItemSet(itemSetId, name)
itemSet[slotName] = { selItemId = 0 }
end
end
for slotName, _ in pairs(self.runeSlots) do
itemSet[slotName] = { runeName = "None" }
end
self.itemSets[itemSet.id] = itemSet
return itemSet
end
Expand Down Expand Up @@ -1460,6 +1608,15 @@ function ItemsTabClass:SetActiveItemSet(itemSetId, deferSync)
end
end
end
for slotName, slot in pairs(self.runeSlots) do
if prevSet then
-- Update the previous set
prevSet[slotName] = { runeName = slot:GetSelValue().name }
end
-- Equip incoming set's rune
local currentRune = curSet[slotName] and curSet[slotName].runeName or "None"
slot:SelByValue(currentRune, "name", true)
end
self.build.buildFlag = true
self:PopulateSlots()
if not deferSync then
Expand Down Expand Up @@ -1888,7 +2045,17 @@ local runeModLines = { { name = "None", label = "None", lines = { "None" }, orde
for name, runeMods in pairs(data.itemMods.Runes) do
-- Some runes have multiple mod lines; insert each as separate entry
for slotType, runeMod in pairs(runeMods) do
t_insert(runeModLines, { name = name, label = runeMod[1], lines = runeMod, req = runeMod.rank[1], order = runeMod.statOrder[1], slot = slotType, type = runeMod.type, group = #runeMod })
t_insert(runeModLines,
{
name = name,
label = runeMod[1],
lines = runeMod,
req = runeMod.rank,
order = runeMod.statOrder[1],
slot = slotType,
type = runeMod.type,
group = #runeMod
})
end
end
table.sort(runeModLines, function(a, b)
Expand Down
Loading
Loading