Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
28 changes: 20 additions & 8 deletions src/Classes/ItemsTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1585,14 +1585,14 @@ function ItemsTabClass:DeleteItem(item, deferUndoState)
end
end

local function copyAnointsAndEldritchImplicits(newItem, activeItemSet, items)
local newItemType = newItem.base.type
if activeItemSet[newItemType] then
local currentItem = activeItemSet[newItemType].selItemId and items[activeItemSet[newItemType].selItemId]
function ItemsTabClass:CopyAnointsAndEldritchImplicits(newItem, migrateEldritchImplicits, overwrite)
local newItemType = newItem.base.weapon and "Weapon 1" or newItem.base.type
if self.activeItemSet[newItemType] then
local currentItem = self.activeItemSet[newItemType].selItemId and self.items[self.activeItemSet[newItemType].selItemId]
-- if you don't have an equipped item that matches the type of the newItem, no need to do anything
if currentItem then
-- if the new item is anointable and does not have an anoint and your current respective item does, apply that anoint to the new item
if isAnointable(newItem) and #newItem.enchantModLines == 0 and activeItemSet[newItemType].selItemId > 0 then
if isAnointable(newItem) and (#newItem.enchantModLines == 0 or overwrite) and self.activeItemSet[newItemType].selItemId > 0 then
local currentAnoint = currentItem.enchantModLines
if currentAnoint and #currentAnoint == 1 then -- skip if amulet has more than one anoint e.g. Stranglegasp
newItem.enchantModLines = currentAnoint
Expand All @@ -1607,12 +1607,24 @@ local function copyAnointsAndEldritchImplicits(newItem, activeItemSet, items)
return
end
end
if main.migrateEldritchImplicits and isValueInTable(eldritchBaseTypes, newItem.base.type) and isValueInTable(eldritchRarities, newItem.rarity)
and #newItem.implicitModLines == 0 and not newItem.corrupted and (currentItem.cleansing or currentItem.tangle) and currentItem.implicitModLines then

local modifiableItem = not (newItem.corrupted or newItem.mirrored)
if migrateEldritchImplicits and isValueInTable(eldritchBaseTypes, newItem.base.type) and isValueInTable(eldritchRarities, newItem.rarity)
and (#newItem.implicitModLines == 0 or overwrite) and modifiableItem and (currentItem.cleansing or currentItem.tangle) and currentItem.implicitModLines then
newItem.implicitModLines = currentItem.implicitModLines
newItem.tangle = currentItem.tangle
newItem.cleansing = currentItem.cleansing
end

-- harvest and heist enchantments on modifiable body armour or weapons
if newItem.base.weapon or newItem.base.type == "Body Armour"
and (#newItem.enchantModLines == 0 or overwrite)
and self.activeItemSet[newItemType].selItemId > 0
and modifiableItem and currentItem.enchantModLines
then
newItem.enchantModLines = currentItem.enchantModLines
end

newItem:BuildAndParseRaw()
end
end
Expand All @@ -1622,7 +1634,7 @@ end
function ItemsTabClass:CreateDisplayItemFromRaw(itemRaw, normalise)
local newItem = new("Item", itemRaw)
if newItem.base then
copyAnointsAndEldritchImplicits(newItem, self.activeItemSet, self.items)
self:CopyAnointsAndEldritchImplicits(newItem, main.migrateEldritchImplicits, false)
if normalise then
newItem:NormaliseQuality()
newItem:BuildModList()
Expand Down
149 changes: 130 additions & 19 deletions src/Classes/TradeQuery.lua
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,22 @@ You can click this button to enter your POESESSID.
- You can only generate weighted searches for public leagues. (Generated searches can be modified
on trade site to work on other leagues and realms)]]

-- Fetches Box
-- Buyout selection
self.tradeTypes = {
"Instant buyout",
"Instant buyout and in person",
"In person (online in league)",
"In person (online)",
}

self.controls.tradeTypeSelection = new("DropDownControl", { "TOPLEFT", self.controls.poesessidButton, "BOTTOMLEFT" },
{ 0, row_vertical_padding, 188, row_height }, self.tradeTypes, function(index, value)
self.tradeTypeIndex = index
end)
-- remember previous choice
self.controls.tradeTypeSelection:SetSel(self.tradeTypeIndex or 1)

-- Fetches Box
self.maxFetchPerSearchDefault = 2
self.controls.fetchCountEdit = new("EditControl", {"TOPRIGHT", nil, "TOPRIGHT"}, {-12, 19, 154, row_height}, "", "Fetch Pages", "%D", 3, function(buf)
self.maxFetchPages = m_min(m_max(tonumber(buf) or self.maxFetchPerSearchDefault, 1), 10)
Expand Down Expand Up @@ -449,7 +464,7 @@ Highest Weight - Displays the order retrieved from trade]]
t_insert(slotTables, { slotName = self.itemsTab.sockets[nodeId].label, nodeId = nodeId })
end

self.controls.sectionAnchor = new("LabelControl", {"LEFT", self.controls.poesessidButton, "LEFT"}, {0, 0, 0, 0}, "")
self.controls.sectionAnchor = new("LabelControl", {"LEFT", self.controls.tradeTypeSelection, "LEFT"}, {0, row_vertical_padding + row_height, 0, 0}, "")
top_pane_alignment_ref = {"TOPLEFT", self.controls.sectionAnchor, "TOPLEFT"}
local scrollBarShown = #slotTables > 21 -- clipping starts beyond this
-- dynamically hide rows that are above or below the scrollBar
Expand Down Expand Up @@ -486,6 +501,14 @@ Highest Weight - Displays the order retrieved from trade]]
return hideRowFunc(self, row_count)
end
row_count = row_count + 1
-- Watcher's Eye
self.slotTables[row_count] = { slotName = "Watcher's Eye", unique = true }
self:PriceItemRowDisplay(row_count, top_pane_alignment_ref, row_vertical_padding, row_height)
self.controls["name"..row_count].y = self.controls["name"..row_count].y + (row_height + row_vertical_padding)
self.controls["name"..row_count].shown = function()
return hideRowFunc(self, row_count) and self:findValidSlotForWatchersEye()
end
row_count = row_count + 1

local effective_row_count = row_count - ((scrollBarShown and #slotTables >= 19) and #slotTables-19 or 0) + 2 + 2 -- Two top menu rows, two bottom rows, slots after #19 overlap the other controls at the bottom of the pane
self.effective_rows_height = row_height * (effective_row_count - #slotTables + (18 - (#slotTables > 37 and 3 or 0))) -- scrollBar height, "18 - slotTables > 37" logic is fine tuning whitespace after last row
Expand Down Expand Up @@ -743,6 +766,17 @@ function TradeQueryClass:GetResultEvaluation(row_idx, result_index, calcFunc, ba
item.enchantModLines = { }
item:BuildAndParseRaw()
end

-- TODO:
-- if applicable: swap resistances

-- if applicable: apply same eldritch implicits or anoints as equipped
local migrateAnointsImplicits = true
if migrateAnointsImplicits then
self.itemsTab:CopyAnointsAndEldritchImplicits(item, true, true)
result.item_string = item:BuildRaw()
end

local output = self:ReduceOutput(calcFunc({ repSlotName = slotName, repItem = item }))
local weight = self.tradeQueryGenerator.WeightedRatioOutputs(baseOutput, output, self.statSortSelectionList)
result.evaluation = {{ output = output, weight = weight }}
Expand Down Expand Up @@ -870,12 +904,37 @@ function TradeQueryClass:addChaosEquivalentPriceToItems(items)
return outputItems
end

-- return valid slot for Watcher's Eye
-- Tries to first return an existing watcher's eye slot if possible
function TradeQueryClass:findValidSlotForWatchersEye()
for _, socket in pairs(self.itemsTab.sockets) do
if not socket.inactive and self.itemsTab.items[socket.selItemId].name:find("Watcher's Eye") then
return socket
end
end
local tmpWE=nil
for _,v in ipairs(data.uniques.generated) do
if v:find("Watcher's Eye") then
tmpWE= new("Item",v)
break
end
end
for _,v in pairs(self.itemsTab.sockets) do
if not v.inactive and self.itemsTab:IsItemValidForSlot(tmpWE,v.slotName,self.itemsTab.activeItemSet) then
return self.itemsTab.sockets[v.nodeId]
end
end
end

-- Method to generate pane elements for each item slot
function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, row_vertical_padding, row_height)
local controls = self.controls
local slotTbl = self.slotTables[row_idx]
local activeSlotRef = slotTbl.nodeId and self.itemsTab.activeItemSet[slotTbl.nodeId] or self.itemsTab.activeItemSet[slotTbl.slotName]
local activeSlot = slotTbl.nodeId and self.itemsTab.sockets[slotTbl.nodeId] or slotTbl.slotName and (self.itemsTab.slots[slotTbl.slotName] or slotTbl.fullName and self.itemsTab.slots[slotTbl.fullName]) -- fullName for Abyssal Sockets
local activeSlot = slotTbl.nodeId and self.itemsTab.sockets[slotTbl.nodeId] or
slotTbl.slotName and (self.itemsTab.slots[slotTbl.slotName] or
slotTbl.slotName == "Watcher's Eye" and self:findValidSlotForWatchersEye() or
slotTbl.fullName and self.itemsTab.slots[slotTbl.fullName]) -- fullName for Abyssal Sockets
local nameColor = slotTbl.unique and colorCodes.UNIQUE or "^7"
controls["name"..row_idx] = new("LabelControl", top_pane_alignment_ref, {0, row_idx*(row_height + row_vertical_padding), 100, row_height - 4}, nameColor..slotTbl.slotName)
controls["bestButton"..row_idx] = new("ButtonControl", { "LEFT", controls["name"..row_idx], "LEFT"}, {100 + 8, 0, 80, row_height}, "Find best", function()
Expand All @@ -893,6 +952,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
return
end
context.controls["priceButton"..context.row_idx].label = "Searching..."
self.lastQuery = query
self.tradeQueryRequests:SearchWithQueryWeightAdjusted(self.pbRealm, self.pbLeague, query,
function(items, errMsg)
if errMsg then
Expand Down Expand Up @@ -1013,7 +1073,16 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
local result = self.resultTbl[row_idx][pb_index]
local item = new("Item", result.item_string)
tooltip:Clear()
self.itemsTab:AddItemTooltip(tooltip, item, slotTbl)
if slotTbl.slotName == "Watcher's Eye" then
local firstValidSlot = self:findValidSlotForWatchersEye()
local currentItem = firstValidSlot.selItemId ~= 0 and self.itemsTab.items[firstValidSlot.selItemId]
local eyeEquipped = currentItem and currentItem.name:find("Watcher's Eye")
-- for watcher's eye we can compare to an already existing one, or
-- default to comparing with all active sockets
self.itemsTab:AddItemTooltip(tooltip, item, eyeEquipped and firstValidSlot or nil)
else
self.itemsTab:AddItemTooltip(tooltip, item, slotTbl)
end
addMegalomaniacCompareToTooltipIfApplicable(tooltip, pb_index)
tooltip:AddSeparator(10)
tooltip:AddLine(16, string.format("^7Price: %s %s", result.amount, result.currency))
Expand Down Expand Up @@ -1041,31 +1110,73 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
-- item.baseName is nil and throws error in the following AddItemTooltip func
-- if the item is unidentified
local item = new("Item", item_string)
self.itemsTab:AddItemTooltip(tooltip, item, slotTbl, true)
-- for watcher's eye we can compare to an already existing one, or
-- default to comparing with all active sockets
if slotTbl.slotName == "Watcher's Eye" then
local firstValidSlot = self:findValidSlotForWatchersEye()
local currentItem = firstValidSlot.selItemId ~= 0 and self.itemsTab.items[firstValidSlot.selItemId]
local eyeEquipped = currentItem and currentItem.name:find("Watcher's Eye")
self.itemsTab:AddItemTooltip(tooltip, item, eyeEquipped and firstValidSlot or nil, true)
else
self.itemsTab:AddItemTooltip(tooltip, item, slotTbl, true)
end
addMegalomaniacCompareToTooltipIfApplicable(tooltip, selected_result_index)
end
end
controls["importButton"..row_idx].enabled = function()
return self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]].item_string ~= nil
end
-- Whisper so we can copy to clipboard
controls["whisperButton"..row_idx] = new("ButtonControl", { "TOPLEFT", controls["importButton"..row_idx], "TOPRIGHT"}, {8, 0, 185, row_height}, function()
return self.totalPrice[row_idx] and "Whisper for " .. self.totalPrice[row_idx].amount .. " " .. self.totalPrice[row_idx].currency or "Whisper"
end, function()
Copy(self.resultTbl[row_idx][self.itemIndexTbl[row_idx]].whisper)
end)
controls["whisperButton"..row_idx].enabled = function()
return self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]].whisper ~= nil
end
controls["whisperButton"..row_idx].tooltipFunc = function(tooltip)
controls["whisperButton" .. row_idx] = new("ButtonControl",
{ "TOPLEFT", controls["importButton" .. row_idx], "TOPRIGHT" }, { 8, 0, 170, row_height }, function()
local itemResult = self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]]

if not itemResult then return "" end

local price = self.totalPrice[row_idx] and
self.totalPrice[row_idx].amount .. " " .. self.totalPrice[row_idx].currency

if itemResult.whisper then
return price and "Whisper for " .. price or "Whisper"
else
return price and "Search for " .. price or "Search"
end

end, function()
local itemResult = self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]]
if itemResult.whisper then
Copy(itemResult.whisper)
else
local exactQuery = dkjson.decode(self.lastQuery)
-- use trade sum to get the specific item. both min and max
-- weight fields seem to be inconsistent. making the minimum
-- e.g. exactly 172.3 as on the result item does not always work
exactQuery.query.stats[1].value = { min = floor(itemResult.weight, 1) - 0.1, max = round(itemResult.weight, 1) + 0.1 }
-- also apply trader name. this should make false positives
-- extremely unlikely. this doesn't seem to take up a filter
-- slot
exactQuery.query.filters.trade_filters = { filters = { account = itemResult.trader } }

local exactQueryStr = dkjson.encode(exactQuery)

self.tradeQueryRequests:SearchWithQuery(self.pbRealm, self.pbLeague, exactQueryStr, function(_, _)
end, {callbackQueryId = function(queryId)
local url = self.hostName.."trade/search/"..self.pbLeague.."/"..queryId
Copy(url)
OpenURL(url)
end})
end
end)

controls["whisperButton" .. row_idx].tooltipFunc = function(tooltip)
tooltip:Clear()
if self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]].item_string then
tooltip.center = true
tooltip:AddLine(16, "Copies the item purchase whisper to the clipboard")
end
tooltip.center = true
local itemResult = self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]]
local text = itemResult.whisper and "Copies the item purchase whisper to the clipboard" or
"Opens the search page to show the item"
tooltip:AddLine(16, text)
end
end

-- Method to update the Total Price string sum of all items
function TradeQueryClass:GetTotalPriceString()
local text = ""
Expand Down
Loading