From d178bedc6e60dbea6725aa0e5f57ddb39ff92053 Mon Sep 17 00:00:00 2001 From: vaisest <4550061+vaisest@users.noreply.github.com> Date: Sun, 26 Jul 2026 23:45:48 +0300 Subject: [PATCH 1/4] Add support for 3.29 vestigial and intangibility parsing --- src/Classes/Item.lua | 11 ++++++++++- src/Classes/ItemsTab.lua | 7 ++++++- src/Data/Global.lua | 4 +++- src/Modules/ItemTools.lua | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Classes/Item.lua b/src/Classes/Item.lua index 67476cf1f8..41fb24d680 100644 --- a/src/Classes/Item.lua +++ b/src/Classes/Item.lua @@ -100,6 +100,7 @@ local lineFlags = { -- in poe2. this is currently only added as a hack for cane of kulemak and -- should be added based on mod tags after matching a mod in the future ["unveiled"] = true, + ["vestigial"] = true, } -- Special function to store unique instances of modifier on specific item slots @@ -690,6 +691,8 @@ function ItemClass:ParseRaw(raw, rarity, highQuality) end elseif specName == "CatalystQuality" then self.catalystQuality = specToNumber(specVal) + elseif specName == "Intangibility" then + self.intangibility = specToNumber(specVal) elseif specName == "Note" then self.note = specVal elseif specName == "Str" or specName == "Strength" or specName == "Dex" or specName == "Dexterity" or @@ -791,7 +794,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality) self.name = self.name:gsub(" %(.+%)","") end if not baseName then - baseName = line:gsub("^Superior ", ""):gsub("^Synthesised ","") + baseName = line:gsub("^Superior ", ""):gsub("^Synthesised ", ""):gsub("^Vestigial ", "") end if baseName == "Two-Toned Boots" then baseName = "Two-Toned Boots (Armour/Energy Shield)" @@ -1479,6 +1482,9 @@ function ItemClass:BuildRaw() end end end + if self.intangibility then + t_insert(rawLines, string.format("Intangibility: %d%%", self.intangibility)) + end if self.uniqueID then t_insert(rawLines, "Unique ID: " .. self.uniqueID) end @@ -1574,6 +1580,9 @@ function ItemClass:BuildRaw() if modLine.unscalable then line = "{unscalable}" .. line end + if modLine.vestigial then + line = "{vestigial}" .. line + end if modLine.variantList then local varSpec for varId in pairs(modLine.variantList) do diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 7171ea2db2..634ae3e625 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -4272,7 +4272,7 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode, maxWidth) end end end - + if item.catalyst and item.catalyst > 0 and item.catalyst <= #catalystQualityFormat and item.catalystQuality and item.catalystQuality > 0 then tooltip:AddLine(fontSizeBig, s_format(catalystQualityFormat[item.catalyst], item.catalystQuality), "FONTIN SC") tooltip:AddSeparator(10) @@ -4314,6 +4314,11 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode, maxWidth) tooltip:AddSeparator(10) end + if item.intangibility then + tooltip:AddLine(fontSizeBig, colorCodes.INTANGIBILITY .. s_format("Intangibility: ^7%d%%", item.intangibility), "FONTIN SC") + tooltip:AddSeparator(10) + end + -- Requirements self.build:AddRequirementsToTooltip(tooltip, item.requirements.level, item.requirements.strMod, item.requirements.dexMod, item.requirements.intMod, diff --git a/src/Data/Global.lua b/src/Data/Global.lua index 7a07f9a8e4..b33de85d79 100644 --- a/src/Data/Global.lua +++ b/src/Data/Global.lua @@ -57,7 +57,9 @@ colorCodes = { SAPBG = "^x261500", SCOURGE = "^xFF6E25", CRUCIBLE = "^xFFA500", - SPLITPERSONALITY = "^xFFD62A" + SPLITPERSONALITY = "^xFFD62A", + VESTIGIAL = "^xCBA5F1", + INTANGIBILITY = "^x9BF4BD", } colorCodes.STRENGTH = colorCodes.MARAUDER colorCodes.DEXTERITY = colorCodes.RANGER diff --git a/src/Modules/ItemTools.lua b/src/Modules/ItemTools.lua index 70331dad44..74c996fb9c 100644 --- a/src/Modules/ItemTools.lua +++ b/src/Modules/ItemTools.lua @@ -362,7 +362,7 @@ function itemLib.formatModLine(modLine, dbMode) line = line .. " ^1'" .. modLine.extra .. "'" end else - colorCode = (modLine.fractured and colorCodes.FRACTURED) or (modLine.crafted and colorCodes.CRAFTED) or (modLine.mutated and colorCodes.MUTATED) or (modLine.scourge and colorCodes.SCOURGE) or (modLine.custom and colorCodes.CUSTOM) or (modLine.crucible and colorCodes.CRUCIBLE) or colorCodes.MAGIC + colorCode = (modLine.fractured and colorCodes.FRACTURED) or (modLine.crafted and colorCodes.CRAFTED) or (modLine.mutated and colorCodes.MUTATED) or (modLine.scourge and colorCodes.SCOURGE) or (modLine.custom and colorCodes.CUSTOM) or (modLine.crucible and colorCodes.CRUCIBLE) or (modLine.vestigial and colorCodes.VESTIGIAL) or colorCodes.MAGIC end return colorCode..line end From 1b484dd3fdfff3e150adf0eb6dc94a723a43f808 Mon Sep 17 00:00:00 2001 From: vaisest <4550061+vaisest@users.noreply.github.com> Date: Wed, 29 Jul 2026 19:23:50 +0300 Subject: [PATCH 2/4] Also remove prefix from import typeline --- src/Classes/ImportTab.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index 39ffb7d081..03a2afadc0 100644 --- a/src/Classes/ImportTab.lua +++ b/src/Classes/ImportTab.lua @@ -1460,7 +1460,7 @@ function ImportTabClass:ImportItem(itemData, slotName, ignoreWeaponSwap) item.rarity = rarityMap[itemData.frameType] if #itemData.name > 0 then item.title = sanitiseText(itemData.name) - item.baseName = sanitiseText(itemData.typeLine):gsub("Synthesised ","") + item.baseName = sanitiseText(itemData.typeLine):gsub("Synthesised ", ""):gsub("^Vestigial ", "") item.name = item.title .. ", " .. item.baseName if item.baseName == "Two-Toned Boots" then -- Hack for Two-Toned Boots From 7c382429ed4ab83c88a75d99f8fe0c4efa692ccb Mon Sep 17 00:00:00 2001 From: vaisest <4550061+vaisest@users.noreply.github.com> Date: Thu, 30 Jul 2026 23:18:01 +0300 Subject: [PATCH 3/4] Fix trader parsing --- src/Classes/Item.lua | 2 + src/Classes/TradeQueryRequests.lua | 75 +++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/Classes/Item.lua b/src/Classes/Item.lua index 41fb24d680..a9462f0f71 100644 --- a/src/Classes/Item.lua +++ b/src/Classes/Item.lua @@ -693,6 +693,8 @@ function ItemClass:ParseRaw(raw, rarity, highQuality) self.catalystQuality = specToNumber(specVal) elseif specName == "Intangibility" then self.intangibility = specToNumber(specVal) + elseif specName == "Memory Strands" then + -- ignored elseif specName == "Note" then self.note = specVal elseif specName == "Str" or specName == "Strength" or specName == "Dex" or specName == "Dexterity" or diff --git a/src/Classes/TradeQueryRequests.lua b/src/Classes/TradeQueryRequests.lua index 4bdc5e3372..3bda7452a4 100644 --- a/src/Classes/TradeQueryRequests.lua +++ b/src/Classes/TradeQueryRequests.lua @@ -290,13 +290,86 @@ function TradeQueryRequestsClass:FetchResultBlock(url, callback) end local items = {} for _, trade_entry in pairs(response.result) do + local item = trade_entry.item + local t_insert = table.insert + + local rawLines = {} + t_insert(rawLines, "Rarity: " .. item.rarity) + -- item.name is empty when magic and full magic name is in typeLine but typeLine == baseType when rare. + if item.name ~= "" then + t_insert(rawLines, item.name) + end + t_insert(rawLines, item.typeLine) + -- note that PoB MUST parse these properties, or otherwise item + -- parsing will consider anything after a non-matching property + -- an explicit mod line + if item.properties then + for _, property in ipairs(item.properties) do + local name = escapeGGGString(property.name) + if property.values[1] then + t_insert(rawLines, string.format("%s: %s", name, property.values[1][1])) + else + t_insert(rawLines, name) + end + end + end + + if item.ilvl then + t_insert(rawLines, "Item Level: " .. item.ilvl) + end + if item.sockets then + local socketString = "" + local colours = {} + for _, socket in ipairs(item.sockets) do + table.insert(colours, socket.sColour) + end + socketString = table.concat(colours, "-") + t_insert(rawLines, "Sockets: " .. socketString) + end + + + -- TODO: crucible mods + for _, field in ipairs({ "enchantMods", "implicitMods", "scourgeMods", "explicitMods" }) do + if not item[field] then + item[field] = {} + end + end + + local function processLine(modLine) + local s = "" + for flagName, flag in pairs(modLine.flags or {}) do + if flag then + s = s .. string.format("{%s}", flagName) + end + end + return s .. escapeGGGString(modLine.description) + end + t_insert(rawLines, "Implicits: " .. (#item.enchantMods + #item.scourgeMods + #item.implicitMods)) + for _, modLine in ipairs(item.enchantMods) do + t_insert(rawLines, "{enchant}" .. processLine(modLine)) + end + for _, modLine in ipairs(item.scourgeMods) do + t_insert(rawLines, "{scourge}" .. processLine(modLine)) + end + for _, modLine in ipairs(item.implicitMods) do + t_insert(rawLines, processLine(modLine)) + end + for _, modLine in ipairs(item.explicitMods) do + t_insert(rawLines, processLine(modLine)) + end + if item.duplicated then + t_insert(rawLines, "Mirrored") + end + if item.corrupted then + t_insert(rawLines, "Corrupted") + end local pseudoMod = trade_entry.item.pseudoMods and trade_entry.item.pseudoMods[1] local pseudoModLine = pseudoMod and (pseudoMod.description or pseudoMod) table.insert(items, { amount = trade_entry.listing.price.amount, currency = trade_entry.listing.price.currency, priceType = trade_entry.listing.price.type, - item_string = escapeGGGString(common.base64.decode(trade_entry.item.extended.text)), + item_string = table.concat(rawLines, "\n"), whisper = trade_entry.listing.whisper, trader = trade_entry.listing.account.name, weight = pseudoModLine and pseudoModLine:match("Sum: (.+)") or "0", From 9f0861e57deac29992e2e28069610281caaf38c6 Mon Sep 17 00:00:00 2001 From: vaisest <4550061+vaisest@users.noreply.github.com> Date: Fri, 31 Jul 2026 19:49:50 +0300 Subject: [PATCH 4/4] Fix test --- spec/System/TestTradeQueryRequests_spec.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/System/TestTradeQueryRequests_spec.lua b/spec/System/TestTradeQueryRequests_spec.lua index fb3ffd9a57..f8e53ea5e7 100644 --- a/spec/System/TestTradeQueryRequests_spec.lua +++ b/spec/System/TestTradeQueryRequests_spec.lua @@ -204,8 +204,10 @@ Strict-Transport-Security: max-age=63115200; includeSubDomains; preload]] account = { name = "seller" }, }, item = { - extended = { text = "VGVzdCBJdGVt" }, pseudoMods = pseudoMods, + rarity = "Rare", + name = "Test Subject", + typeLine = "Astral Plate", }, } end