diff --git a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua index 4965c4eec1..d323753e88 100644 --- a/src/Classes/TradeQuery.lua +++ b/src/Classes/TradeQuery.lua @@ -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) @@ -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.poesessidButton, "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 @@ -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 @@ -870,12 +893,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() @@ -893,6 +941,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 @@ -1013,7 +1062,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)) @@ -1041,7 +1099,16 @@ 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 @@ -1049,23 +1116,56 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro 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 = "" diff --git a/src/Classes/TradeQueryGenerator.lua b/src/Classes/TradeQueryGenerator.lua index 29772bead4..3959d63cfc 100644 --- a/src/Classes/TradeQueryGenerator.lua +++ b/src/Classes/TradeQueryGenerator.lua @@ -80,6 +80,7 @@ local tradeStatCategoryIndices = { ["Exarch"] = 3, ["Synthesis"] = 3, ["PassiveNode"] = 2, + ["WatchersEye"] = 2, } local influenceSuffixes = { "_shaper", "_elder", "_adjudicator", "_basilisk", "_crusader", "_eyrie"} @@ -406,6 +407,7 @@ function TradeQueryGeneratorClass:InitMods() ["Exarch"] = { }, ["Synthesis"] = { }, ["PassiveNode"] = { }, + ["WatchersEye"] = { }, } -- originates from: https://www.pathofexile.com/api/trade/data/stats @@ -464,6 +466,17 @@ function TradeQueryGeneratorClass:InitMods() end self:GenerateModData(clusterNotableMods, tradeQueryStatsParsed) + -- Watcher's Eye + local watchersEyeMods = {} + for _,v in pairs(data.uniqueMods["Watcher's Eye"]) do + if v.Id:find("SublimeVision") or v.Id:find("SummonArbalist") then + goto continue + end + watchersEyeMods[v.Id] = v.mod + watchersEyeMods[v.Id].type = "WatchersEye" + ::continue:: + end + self:GenerateModData(watchersEyeMods,tradeQueryStatsParsed,{ ["BaseJewel"] = true, ["AnyJewel"] = true },{["AnyJewel"]="AnyJewel"}) -- Base item implicit mods. A lot of this code is duplicated from generateModData(), but with important small logical flow changes to handle the format differences local subTypeState = { } local function updateRangeSubType(range, entry) @@ -727,6 +740,28 @@ function TradeQueryGeneratorClass:StartQuery(slot, options) calcNodesInsteadOfMods = true, } end + if options.special.itemName == "Watcher's Eye" then + special={ + queryExtra = { + name = "Watcher's Eye" + }, + queryFilters = { + type_filters = { + filters = { + category = { + option = "jewel" + }, + rarity = { + option = "unique" + } + } + } + }, + watchersEye = true + } + itemCategory = "AnyJewel" + itemCategoryQueryStr = "jewel" + end elseif slot.slotName:find("^Weapon %d") then if existingItem then if existingItem.type == "Shield" then @@ -874,6 +909,13 @@ function TradeQueryGeneratorClass:ExecuteQuery() self:GeneratePassiveNodeWeights(self.modData.PassiveNode) return end + if self.calcContext.special.watchersEye then + self:GenerateModWeights(self.modData.WatchersEye) + if self.calcContext.options.includeCorrupted then + self:GenerateModWeights(self.modData["Corrupted"]) + end + return + end self:GenerateModWeights(self.modData["Explicit"]) self:GenerateModWeights(self.modData["Implicit"]) if self.calcContext.options.includeCorrupted then @@ -891,6 +933,36 @@ function TradeQueryGeneratorClass:ExecuteQuery() end end +function TradeQueryGeneratorClass:addMoreWEMods() + local function getTableOfTradeModIds(tbl) + local tmpTable={} + for _,val in ipairs(tbl) do + table.insert(tmpTable,val.tradeModId) + end + return tmpTable + end + for _,skillGroup in ipairs(self.itemsTab.build.skillsTab.socketGroupList) do + for _,gem in ipairs(skillGroup.gemList) do + local tmpAura="" + if not gem.enabled then + goto continue + elseif gem.nameSpec:find("Vaal") and gem.enableGlobal2 then + tmpAura=gem.nameSpec:gsub("Vaal ",""):gsub("Impurity","Purity"):gsub("of","Of"):gsub(" ","") + elseif gem.gemData and gem.gemData.tags.aura or gem.fromItem then + tmpAura=gem.nameSpec:gsub("of","Of"):gsub(" ","") + else + goto continue + end + for id,mod in pairs(self.modData.WatchersEye) do + if id:find(tmpAura) and not isValueInTable(getTableOfTradeModIds(self.modWeights),mod.tradeMod.id) then + table.insert(self.modWeights,{invert=false,meanStatDiff=0,weight=0,tradeModId=mod.tradeMod.id}) + end + end + ::continue:: + end + end +end + function TradeQueryGeneratorClass:FinishQuery() -- Calc original item Stats without anoint or enchant, and use that diff as a basis for default min sum. local originalItem = self.calcContext.slot and self.itemsTab.items[self.calcContext.slot.selItemId] @@ -914,6 +986,10 @@ function TradeQueryGeneratorClass:FinishQuery() local originalOutput = originalItem and self.calcContext.calcFunc({ repSlotName = self.calcContext.slot.slotName, repItem = self.calcContext.testItem }) or self.calcContext.baseOutput local currentStatDiff = TradeQueryGeneratorClass.WeightedRatioOutputs(self.calcContext.baseOutput, originalOutput, self.calcContext.options.statWeights) * 1000 - (self.calcContext.baseStatValue or 0) + if self.calcContext.options.includeAllWEMods then + self:addMoreWEMods() + end + -- Sort by mean Stat diff rather than weight to more accurately prioritize stats that can contribute more table.sort(self.modWeights, function(a, b) if a.meanStatDiff == b.meanStatDiff then @@ -927,7 +1003,15 @@ function TradeQueryGeneratorClass:FinishQuery() -- This Stat diff value will generally be higher than the weighted sum of the same item, because the stats are all applied at once and can thus multiply off each other. -- So apply a modifier to get a reasonable min and hopefully approximate that the query will start out with small upgrades. local minWeight = megalomaniacSpecialMinWeight or currentStatDiff * 0.5 - + + -- what the trade site API uses for the above + self.tradeTypes = { + "securable", + "available", + "onlineleague", + "online", + } + local selectedTradeType = self.tradeTypes[self.tradeTypeIndex] -- Generate trade query str and open in browser local filters = 0 local queryTable = { @@ -940,7 +1024,7 @@ function TradeQueryGeneratorClass:FinishQuery() } } }, - status = { option = "available" }, + status = { option = selectedTradeType }, stats = { { type = "weight", @@ -1028,6 +1112,10 @@ function TradeQueryGeneratorClass:FinishQuery() } end + if options.account then + queryTable.query.filters.trade_filters.filters.account = {input = options.account} + end + if options.maxLevel and options.maxLevel > 0 then queryTable.query.filters.req_filters = { disabled = false, @@ -1116,9 +1204,12 @@ function TradeQueryGeneratorClass:RequestQuery(slot, context, statWeights, callb options.special = { itemName = context.slotTbl.slotName } end - controls.includeMirrored = new("CheckBoxControl", {"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Mirrored items:", function(state) end) - controls.includeMirrored.state = (self.lastIncludeMirrored == nil or self.lastIncludeMirrored == true) - updateLastAnchor(controls.includeMirrored) + -- these unique items cannot be mirrored + if not context.slotTbl.unique then + controls.includeMirrored = new("CheckBoxControl", {"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Mirrored items:", function(state) end) + controls.includeMirrored.state = (self.lastIncludeMirrored == nil or self.lastIncludeMirrored == true) + updateLastAnchor(controls.includeMirrored) + end if not isJewelSlot and not isAbyssalJewelSlot and includeScourge then controls.includeScourge = new("CheckBoxControl", {"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Scourge Mods:", function(state) end) @@ -1138,12 +1229,12 @@ function TradeQueryGeneratorClass:RequestQuery(slot, context, statWeights, callb updateLastAnchor(controls.includeEldritch) end - if isJewelSlot then + if isJewelSlot and context.slotTbl.slotName ~= "Watcher's Eye" then controls.jewelType = new("DropDownControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, { "Any", "Base", "Abyss" }, function(index, value) end) controls.jewelType.selIndex = self.lastJewelType or 1 controls.jewelTypeLabel = new("LabelControl", {"RIGHT",controls.jewelType,"LEFT"}, {-5, 0, 0, 16}, "Jewel Type:") updateLastAnchor(controls.jewelType) - elseif slot and not isAbyssalJewelSlot then + elseif slot and not isAbyssalJewelSlot and context.slotTbl.slotName ~= "Watcher's Eye" then controls.influence1 = new("DropDownControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, influenceDropdownNames, function(index, value) end) controls.influence1.selIndex = self.lastInfluence1 or 1 controls.influence1Label = new("LabelControl", {"RIGHT",controls.influence1,"LEFT"}, {-5, 0, 0, 16}, "Influence 1:") @@ -1213,9 +1304,18 @@ function TradeQueryGeneratorClass:RequestQuery(slot, context, statWeights, callb end popupHeight = popupHeight + 4 + if context.slotTbl.slotName == "Watcher's Eye" then + controls.includeAllWEMods = new("CheckBoxControl", {"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Include all Watcher's Eye mods:", function(state) end) + controls.includeAllWEMods.tooltipText = "Include mods that could not have a weight calculated for them at weight 0." + lastItemAnchor = controls.includeAllWEMods + popupHeight = popupHeight + 23 + end + controls.generateQuery = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {-45, -10, 80, 20}, "Execute", function() main:ClosePopup() + self.tradeTypeIndex = context.controls.tradeTypeSelection.selIndex + if controls.includeMirrored then self.lastIncludeMirrored, options.includeMirrored = controls.includeMirrored.state, controls.includeMirrored.state end @@ -1265,6 +1365,9 @@ function TradeQueryGeneratorClass:RequestQuery(slot, context, statWeights, callb if controls.links and controls.links.buf then options.links = tonumber(controls.links.buf) end + if controls.includeAllWEMods then + options.includeAllWEMods = controls.includeAllWEMods.state + end options.statWeights = statWeights self:StartQuery(slot, options) diff --git a/src/Classes/TradeQueryRequests.lua b/src/Classes/TradeQueryRequests.lua index e656fb5657..180050d106 100644 --- a/src/Classes/TradeQueryRequests.lua +++ b/src/Classes/TradeQueryRequests.lua @@ -285,8 +285,14 @@ function TradeQueryRequestsClass:FetchResultBlock(url, callback) table.insert(items, { amount = trade_entry.listing.price.amount, currency = trade_entry.listing.price.currency, + -- note: using these to travel to the hideout or for a + -- direct whisper is not allowed, even if they are provided + -- right here + -- hideout_token = trade_entry.listing.hideout_token, + -- whisper_token = trade_entry.listing.whisper_token, item_string = common.base64.decode(trade_entry.item.extended.text), whisper = trade_entry.listing.whisper, + trader = trade_entry.listing.account.name, weight = trade_entry.item.pseudoMods and trade_entry.item.pseudoMods[1]:match("Sum: (.+)") or "0", id = trade_entry.id }) diff --git a/src/Data/QueryMods.lua b/src/Data/QueryMods.lua index ba59ef34c0..1ec8a7e19c 100644 --- a/src/Data/QueryMods.lua +++ b/src/Data/QueryMods.lua @@ -72577,4 +72577,1330 @@ return { }, }, }, + ["WatchersEye"] = { + ["10058_ClarityReducedManaCost"] = { + ["AnyJewel"] = { + ["max"] = 5, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2445618239", + ["text"] = "+# to Total Mana Cost of Skills while affected by Clarity", + ["type"] = "explicit", + }, + }, + ["10063_ClarityReducedManaCostNonChannelled"] = { + ["AnyJewel"] = { + ["max"] = 5, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1853636813", + ["text"] = "Non-Channelling Skills have +# to Total Mana Cost while affected by Clarity", + ["type"] = "explicit", + }, + }, + ["10173_GraceChanceToDodge"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 12, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_4071658793", + ["text"] = "+#% chance to Suppress Spell Damage while affected by Grace", + ["type"] = "explicit", + }, + }, + ["10174_HasteChanceToDodgeSpells"] = { + ["AnyJewel"] = { + ["max"] = 8, + ["min"] = 5, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2170859717", + ["text"] = "+#% chance to Suppress Spell Damage while affected by Haste", + ["type"] = "explicit", + }, + }, + ["10452_MalevolenceUnaffectedByBleeding"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_4104891138", + ["text"] = "Unaffected by Bleeding while affected by Malevolence", + ["type"] = "explicit", + }, + }, + ["10456_PurityOfFireUnaffectedByBurningGround"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3308185931", + ["text"] = "Unaffected by Burning Ground while affected by Purity of Fire", + ["type"] = "explicit", + }, + }, + ["10461_PurityOfIceUnaffectedByChilledGround"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2647344903", + ["text"] = "Unaffected by Chilled Ground while affected by Purity of Ice", + ["type"] = "explicit", + }, + }, + ["10462_PurityOfLightningUnaffectedByConductivity"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1567542124", + ["text"] = "Unaffected by Conductivity while affected by Purity of Lightning", + ["type"] = "explicit", + }, + }, + ["10467_PurityOfElementsUnaffectedByElementalWeakness"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3223142064", + ["text"] = "Unaffected by Elemental Weakness while affected by Purity of Elements", + ["type"] = "explicit", + }, + }, + ["10468_GraceUnaffectedByEnfeeble"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2365917222", + ["text"] = "Unaffected by Enfeeble while affected by Grace", + ["type"] = "explicit", + }, + }, + ["10469_PurityOfFireUnaffectedByFlammability"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1173690938", + ["text"] = "Unaffected by Flammability while affected by Purity of Fire", + ["type"] = "explicit", + }, + }, + ["10471_PurityOfIceUnaffectedByFrostbite"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_4012281889", + ["text"] = "Unaffected by Frostbite while affected by Purity of Ice", + ["type"] = "explicit", + }, + }, + ["10475_MalevolenceUnaffectedByPoison"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_34059570", + ["text"] = "Unaffected by Poison while affected by Malevolence", + ["type"] = "explicit", + }, + }, + ["10481_PurityOfLightningUnaffectedByShockedGround"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2567659895", + ["text"] = "Unaffected by Shocked Ground while affected by Purity of Lightning", + ["type"] = "explicit", + }, + }, + ["10483_HasteUnaffectedByTemporalChains"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2806391472", + ["text"] = "Unaffected by Temporal Chains while affected by Haste", + ["type"] = "explicit", + }, + }, + ["10484_DeterminationUnaffectedByVulnerability"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3207781478", + ["text"] = "Unaffected by Vulnerability while affected by Determination", + ["type"] = "explicit", + }, + }, + ["10665_MalevolenceYourAilmentsDealDamageFaster"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3468843137", + ["text"] = "Damaging Ailments you inflict deal Damage #% faster while affected by Malevolence", + ["type"] = "explicit", + }, + }, + ["12_DeterminationReducedReflectedPhysicalDamage"] = { + ["AnyJewel"] = { + ["max"] = 75, + ["min"] = 50, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2255585376", + ["text"] = "#% of Physical Damage from your Hits cannot be Reflected while affected by Determination", + ["type"] = "explicit", + }, + }, + ["1740_ZealotryMaximumEnergyShieldPerSecondToMaximumEnergyShieldLeechRate"] = { + ["AnyJewel"] = { + ["max"] = 30, + ["min"] = 30, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2731416566", + ["text"] = "#% increased Maximum total Energy Shield Recovery per second from Leech while affected by Zealotry", + ["type"] = "explicit", + }, + }, + ["1741_ZealotryMaximumEnergyShieldPerSecondToMaximumEnergyShieldLeechRateOld"] = { + ["AnyJewel"] = { + ["max"] = 30, + ["min"] = 30, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2731416566", + ["text"] = "#% increased Maximum total Energy Shield Recovery per second from Leech while affected by Zealotry", + ["type"] = "explicit", + }, + }, + ["4557_HatredAdditionalCriticalStrikeChance"] = { + ["AnyJewel"] = { + ["max"] = 1.8, + ["min"] = 1.2, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2753985507", + ["text"] = "+#% to Critical Strike Chance while affected by Hatred", + ["type"] = "explicit", + }, + }, + ["4566_PurityOfElementsMaximumElementalResistances"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3234824465", + ["text"] = "+#% to all maximum Elemental Resistances while affected by Purity of Elements", + ["type"] = "explicit", + }, + }, + ["4584_DeterminationPhysicalDamageReduction"] = { + ["AnyJewel"] = { + ["max"] = 8, + ["min"] = 5, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1873457881", + ["text"] = "#% additional Physical Damage Reduction while affected by Determination", + ["type"] = "explicit", + }, + }, + ["4770_DeterminationAdditionalArmour"] = { + ["AnyJewel"] = { + ["max"] = 1000, + ["min"] = 600, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3742808908", + ["text"] = "+# to Armour while affected by Determination", + ["type"] = "explicit", + }, + }, + ["4867_PrecisionIncreasedAttackDamage"] = { + ["AnyJewel"] = { + ["max"] = 60, + ["min"] = 40, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2048747572", + ["text"] = "#% increased Attack Damage while affected by Precision", + ["type"] = "explicit", + }, + }, + ["4909_PrecisionIncreasedAttackSpeed"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3375743050", + ["text"] = "#% increased Attack Speed while affected by Precision", + ["type"] = "explicit", + }, + }, + ["5048_HatredPhysicalConvertedToCold"] = { + ["AnyJewel"] = { + ["max"] = 40, + ["min"] = 25, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_664849247", + ["text"] = "#% of Physical Damage Converted to Cold Damage while affected by Hatred", + ["type"] = "explicit", + }, + }, + ["5049_AngerPhysicalConvertedToFire"] = { + ["AnyJewel"] = { + ["max"] = 40, + ["min"] = 25, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3624529132", + ["text"] = "#% of Physical Damage Converted to Fire Damage while affected by Anger", + ["type"] = "explicit", + }, + }, + ["5050_WrathPhysicalConvertedToLightning"] = { + ["AnyJewel"] = { + ["max"] = 40, + ["min"] = 25, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2106756686", + ["text"] = "#% of Physical Damage Converted to Lightning Damage while affected by Wrath", + ["type"] = "explicit", + }, + }, + ["5226_GraceBlindEnemiesWhenHit"] = { + ["AnyJewel"] = { + ["max"] = 50, + ["min"] = 30, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2548097895", + ["text"] = "#% chance to Blind Enemies which Hit you while affected by Grace", + ["type"] = "explicit", + }, + }, + ["5236_DeterminationAdditionalBlock"] = { + ["AnyJewel"] = { + ["max"] = 8, + ["min"] = 5, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3692646597", + ["text"] = "+#% Chance to Block Attack Damage while affected by Determination", + ["type"] = "explicit", + }, + }, + ["5399_PrecisionCannotBeBlinded"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1653848515", + ["text"] = "Cannot be Blinded while affected by Precision", + ["type"] = "explicit", + }, + }, + ["5476_ZealotryCastSpeed"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2444534954", + ["text"] = "#% increased Cast Speed while affected by Zealotry", + ["type"] = "explicit", + }, + }, + ["5657_DisciplineAdditionalSpellBlock"] = { + ["AnyJewel"] = { + ["max"] = 8, + ["min"] = 5, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1313498929", + ["text"] = "+#% Chance to Block Spell Damage while affected by Discipline", + ["type"] = "explicit", + }, + }, + ["5680_GraceAdditionalChanceToEvade"] = { + ["AnyJewel"] = { + ["max"] = 8, + ["min"] = 5, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_969576725", + ["text"] = "+#% chance to Evade Attack Hits while affected by Grace", + ["type"] = "explicit", + }, + }, + ["5749_PurityOfElementsChaosResistance"] = { + ["AnyJewel"] = { + ["max"] = 50, + ["min"] = 30, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1138813382", + ["text"] = "+#% to Chaos Resistance while affected by Purity of Elements", + ["type"] = "explicit", + }, + }, + ["5806_PurityOfFireColdAndLightningTakenAsFire"] = { + ["AnyJewel"] = { + ["max"] = 20, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1723738042", + ["text"] = "#% of Cold and Lightning Damage taken as Fire Damage while affected by Purity of Fire", + ["type"] = "explicit", + }, + }, + ["5819_HatredIncreasedColdDamage"] = { + ["AnyJewel"] = { + ["max"] = 60, + ["min"] = 40, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1413864591", + ["text"] = "#% increased Cold Damage while affected by Hatred", + ["type"] = "explicit", + }, + }, + ["5854_ZealotryConsecratedGroundEnemyDamageTaken"] = { + ["AnyJewel"] = { + ["max"] = 10, + ["min"] = 8, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2434030180", + ["text"] = "Consecrated Ground you create while affected by Zealotry causes enemies to take #% increased Damage", + ["type"] = "explicit", + }, + }, + ["5857_ZealotryConsecratedGroundEffectLingersForMsAfterLeavingTheArea"] = { + ["AnyJewel"] = { + ["max"] = 2, + ["min"] = 2, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2163419452", + ["text"] = "Effects of Consecrated Ground you create while affected by Zealotry Linger for # seconds", + ["type"] = "explicit", + }, + }, + ["5926_ZealotryCriticalStrikeChanceAgainstEnemiesOnConsecratedGround"] = { + ["AnyJewel"] = { + ["max"] = 120, + ["min"] = 100, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_214835567", + ["text"] = "#% increased Critical Strike Chance against Enemies on Consecrated Ground while affected by Zealotry", + ["type"] = "explicit", + }, + }, + ["5946_WrathIncreasedCriticalStrikeChance"] = { + ["AnyJewel"] = { + ["max"] = 100, + ["min"] = 70, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3357049845", + ["text"] = "#% increased Critical Strike Chance while affected by Wrath", + ["type"] = "explicit", + }, + }, + ["5973_AngerIncreasedCriticalStrikeMultiplier"] = { + ["AnyJewel"] = { + ["max"] = 50, + ["min"] = 30, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3627458291", + ["text"] = "+#% to Critical Strike Multiplier while affected by Anger", + ["type"] = "explicit", + }, + }, + ["5974_PrecisionIncreasedCriticalStrikeMultiplier"] = { + ["AnyJewel"] = { + ["max"] = 30, + ["min"] = 20, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1817023621", + ["text"] = "+#% to Critical Strike Multiplier while affected by Precision", + ["type"] = "explicit", + }, + }, + ["5988_ZealotryCriticalStrikesPenetratesElementalResistances"] = { + ["AnyJewel"] = { + ["max"] = 10, + ["min"] = 8, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2091518682", + ["text"] = "Critical Strikes Penetrate #% of Enemy Elemental Resistances while affected by Zealotry", + ["type"] = "explicit", + }, + }, + ["6093_ClarityDamageTakenFromManaBeforeLife"] = { + ["AnyJewel"] = { + ["max"] = 10, + ["min"] = 6, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2383304564", + ["text"] = "#% of Damage taken from Mana before Life while affected by Clarity", + ["type"] = "explicit", + }, + }, + ["6111_ClarityDamageTakenGainedAsMana"] = { + ["AnyJewel"] = { + ["max"] = 20, + ["min"] = 15, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_380220671", + ["text"] = "#% of Damage taken while affected by Clarity Recouped as Mana", + ["type"] = "explicit", + }, + }, + ["6155_HasteDebuffsExpireFaster"] = { + ["AnyJewel"] = { + ["max"] = 20, + ["min"] = 15, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_207635700", + ["text"] = "Debuffs on you expire #% faster while affected by Haste", + ["type"] = "explicit", + }, + }, + ["6264_MalevolenceDamageOverTimeMultiplier"] = { + ["AnyJewel"] = { + ["max"] = 22, + ["min"] = 18, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2736708072", + ["text"] = "+#% to Damage over Time Multiplier while affected by Malevolence", + ["type"] = "explicit", + }, + }, + ["6434_DisciplineFasterStartOfRecharge"] = { + ["AnyJewel"] = { + ["max"] = 40, + ["min"] = 30, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1016185292", + ["text"] = "#% faster start of Energy Shield Recharge while affected by Discipline", + ["type"] = "explicit", + }, + }, + ["6437_DisciplineEnergyShieldPerHit"] = { + ["AnyJewel"] = { + ["max"] = 30, + ["min"] = 20, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3765507527", + ["text"] = "Gain # Energy Shield per Enemy Hit while affected by Discipline", + ["type"] = "explicit", + }, + }, + ["6442_WrathLightningDamageESLeech"] = { + ["AnyJewel"] = { + ["max"] = 1.5, + ["min"] = 1, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_121436064", + ["text"] = "#% of Lightning Damage is Leeched as Energy Shield while affected by Wrath", + ["type"] = "explicit", + }, + }, + ["6457_DisciplineEnergyShieldRecoveryRate"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_80470845", + ["text"] = "#% increased Energy Shield Recovery Rate while affected by Discipline", + ["type"] = "explicit", + }, + }, + ["6464_DisciplineEnergyShieldRegen"] = { + ["AnyJewel"] = { + ["max"] = 2.5, + ["min"] = 1.5, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_991194404", + ["text"] = "Regenerate #% of Energy Shield per Second while affected by Discipline", + ["type"] = "explicit", + }, + }, + ["6541_DeterminationReducedExtraDamageFromCrits"] = { + ["AnyJewel"] = { + ["max"] = 60, + ["min"] = 40, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_68410701", + ["text"] = "You take #% reduced Extra Damage from Critical Strikes while affected by Determination", + ["type"] = "explicit", + }, + }, + ["6557_PurityOfIceFireAndLightningTakenAsCold"] = { + ["AnyJewel"] = { + ["max"] = 20, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2189467271", + ["text"] = "#% of Fire and Lightning Damage taken as Cold Damage while affected by Purity of Ice", + ["type"] = "explicit", + }, + }, + ["6573_AngerIncreasedFireDamage"] = { + ["AnyJewel"] = { + ["max"] = 60, + ["min"] = 40, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3337107517", + ["text"] = "#% increased Fire Damage while affected by Anger", + ["type"] = "explicit", + }, + }, + ["6645_VitalityLifeRecoveryFromFlasks"] = { + ["AnyJewel"] = { + ["max"] = 70, + ["min"] = 50, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_362838683", + ["text"] = "#% increased Life Recovery from Flasks while affected by Vitality", + ["type"] = "explicit", + }, + }, + ["6728_ZealotryGainArcaneSurgeFor4SecondsWhenYouCreateConsecratedGround"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1919069577", + ["text"] = "Gain Arcane Surge for 4 seconds when you create Consecrated Ground while affected by Zealotry", + ["type"] = "explicit", + }, + }, + ["6792_HasteGainOnslaughtOnKill"] = { + ["AnyJewel"] = { + ["max"] = 4, + ["min"] = 4, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1424006185", + ["text"] = "You gain Onslaught for # seconds on Kill while affected by Haste", + ["type"] = "explicit", + }, + }, + ["6803_HasteGainPhasing"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1346311588", + ["text"] = "You have Phasing while affected by Haste", + ["type"] = "explicit", + }, + }, + ["7235_PurityOfIceImmuneToFreeze"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2720072724", + ["text"] = "Immune to Freeze while affected by Purity of Ice", + ["type"] = "explicit", + }, + }, + ["7238_PurityOfFireImmuneToIgnite"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_371612541", + ["text"] = "Immune to Ignite while affected by Purity of Fire", + ["type"] = "explicit", + }, + }, + ["7243_PurityOfLightningImmuneToShock"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_281949611", + ["text"] = "Immune to Shock while affected by Purity of Lightning", + ["type"] = "explicit", + }, + }, + ["7349_MalevolenceLifeAndEnergyShieldRecoveryRate"] = { + ["AnyJewel"] = { + ["max"] = 12, + ["min"] = 8, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3643449791", + ["text"] = "#% increased Recovery rate of Life and Energy Shield while affected by Malevolence", + ["type"] = "explicit", + }, + }, + ["7360_VitalityLifeGainPerHit"] = { + ["AnyJewel"] = { + ["max"] = 30, + ["min"] = 20, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_4259701244", + ["text"] = "Gain # Life per Enemy Hit while affected by Vitality", + ["type"] = "explicit", + }, + }, + ["7366_VitalityDamageLifeLeech"] = { + ["AnyJewel"] = { + ["max"] = 1.2, + ["min"] = 0.8, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3656959867", + ["text"] = "#% of Damage leeched as Life while affected by Vitality", + ["type"] = "explicit", + }, + }, + ["7373_AngerFireDamageLifeLeech"] = { + ["AnyJewel"] = { + ["max"] = 1.5, + ["min"] = 1, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2312747856", + ["text"] = "#% of Fire Damage Leeched as Life while affected by Anger", + ["type"] = "explicit", + }, + }, + ["7399_VitalityLifeRecoveryRate"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2690790844", + ["text"] = "#% increased Life Recovery Rate while affected by Vitality", + ["type"] = "explicit", + }, + }, + ["7409_VitalityFlatLifeRegen"] = { + ["AnyJewel"] = { + ["max"] = 140, + ["min"] = 100, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3489570622", + ["text"] = "Regenerate # Life per Second while affected by Vitality", + ["type"] = "explicit", + }, + }, + ["7416_VitalityPercentLifeRegen"] = { + ["AnyJewel"] = { + ["max"] = 1.5, + ["min"] = 1, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1165583295", + ["text"] = "Regenerate #% of Life per second while affected by Vitality", + ["type"] = "explicit", + }, + }, + ["7454_WrathIncreasedLightningDamage"] = { + ["AnyJewel"] = { + ["max"] = 60, + ["min"] = 40, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_418293304", + ["text"] = "#% increased Lightning Damage while affected by Wrath", + ["type"] = "explicit", + }, + }, + ["8188_WrathLightningDamageManaLeech"] = { + ["AnyJewel"] = { + ["max"] = 1.5, + ["min"] = 1, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2889601846", + ["text"] = "#% of Lightning Damage is Leeched as Mana while affected by Wrath", + ["type"] = "explicit", + }, + }, + ["8197_ClarityManaRecoveryRate"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_556659145", + ["text"] = "#% increased Mana Recovery Rate while affected by Clarity", + ["type"] = "explicit", + }, + }, + ["9174_ClarityManaAddedAsEnergyShield"] = { + ["AnyJewel"] = { + ["max"] = 10, + ["min"] = 6, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2831391506", + ["text"] = "Gain #% of Maximum Mana as Extra Maximum Energy Shield while affected by Clarity", + ["type"] = "explicit", + }, + }, + ["9237_HatredAddedColdDamage"] = { + ["AnyJewel"] = { + ["max"] = 87, + ["min"] = 73, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2643562209", + ["text"] = "Adds # to # Cold Damage while affected by Hatred", + ["type"] = "explicit", + }, + }, + ["9405_HasteCooldownRecoveryForMovementSkills"] = { + ["AnyJewel"] = { + ["max"] = 50, + ["min"] = 30, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3332055899", + ["text"] = "#% increased Cooldown Recovery Rate of Movement Skills used while affected by Haste", + ["type"] = "explicit", + }, + }, + ["9428_GraceIncreasedMovementSpeed"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3329402420", + ["text"] = "#% increased Movement Speed while affected by Grace", + ["type"] = "explicit", + }, + }, + ["9631_AngerPhysicalAddedAsFire"] = { + ["AnyJewel"] = { + ["max"] = 25, + ["min"] = 15, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_4245204226", + ["text"] = "Gain #% of Physical Damage as Extra Fire Damage while affected by Anger", + ["type"] = "explicit", + }, + }, + ["9634_WrathPhysicalAddedAsLightning"] = { + ["AnyJewel"] = { + ["max"] = 25, + ["min"] = 15, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_2255914633", + ["text"] = "Gain #% of Physical Damage as Extra Lightning Damage while affected by Wrath", + ["type"] = "explicit", + }, + }, + ["9656_PurityOfElementsTakePhysicalAsCold"] = { + ["AnyJewel"] = { + ["max"] = 12, + ["min"] = 8, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1710207583", + ["text"] = "#% of Physical Damage from Hits taken as Cold Damage while affected by Purity of Elements", + ["type"] = "explicit", + }, + }, + ["9657_PurityOfIceTakePhysicalAsIce"] = { + ["AnyJewel"] = { + ["max"] = 10, + ["min"] = 6, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1779027621", + ["text"] = "#% of Physical Damage from Hits taken as Cold Damage while affected by Purity of Ice", + ["type"] = "explicit", + }, + }, + ["9658_PurityOfElementsTakePhysicalAsFire"] = { + ["AnyJewel"] = { + ["max"] = 12, + ["min"] = 8, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1722775216", + ["text"] = "#% of Physical Damage from Hits taken as Fire Damage while affected by Purity of Elements", + ["type"] = "explicit", + }, + }, + ["9659_PurityOfFireTakePhysicalAsFire"] = { + ["AnyJewel"] = { + ["max"] = 10, + ["min"] = 6, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1798459983", + ["text"] = "#% of Physical Damage from Hits taken as Fire Damage while affected by Purity of Fire", + ["type"] = "explicit", + }, + }, + ["9660_PurityOfElementsTakePhysicalAsLightning"] = { + ["AnyJewel"] = { + ["max"] = 12, + ["min"] = 8, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_873224517", + ["text"] = "#% of Physical Damage from Hits taken as Lightning Damage while affected by Purity of Elements", + ["type"] = "explicit", + }, + }, + ["9661_PurityOfLightningTakePhysicalAsLightning"] = { + ["AnyJewel"] = { + ["max"] = 10, + ["min"] = 6, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_254131992", + ["text"] = "#% of Physical Damage from Hits taken as Lightning Damage while affected by Purity of Lightning", + ["type"] = "explicit", + }, + }, + ["9710_PrideChanceForDoubleDamage"] = { + ["AnyJewel"] = { + ["max"] = 12, + ["min"] = 8, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3371719014", + ["text"] = "#% chance to deal Double Damage while using Pride", + ["type"] = "explicit", + }, + }, + ["9711_PrideChanceToImpale"] = { + ["AnyJewel"] = { + ["max"] = 25, + ["min"] = 25, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_4173751044", + ["text"] = "#% chance to Impale Enemies on Hit with Attacks while using Pride", + ["type"] = "explicit", + }, + }, + ["9712_PrideIntimidateOnHit"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3772848194", + ["text"] = "Your Hits Intimidate Enemies for 4 seconds while you are using Pride", + ["type"] = "explicit", + }, + }, + ["9716_PrideIncreasedPhysicalDamage"] = { + ["AnyJewel"] = { + ["max"] = 60, + ["min"] = 40, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_576528026", + ["text"] = "#% increased Physical Damage while using Pride", + ["type"] = "explicit", + }, + }, + ["9718_PrideImpaleAdditionalHits"] = { + ["AnyJewel"] = { + ["max"] = 2, + ["min"] = 2, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1011863394", + ["text"] = "Impales you inflict last # additional Hits while using Pride", + ["type"] = "explicit", + }, + }, + ["9834_PrecisionFlaskChargeOnCrit"] = { + ["AnyJewel"] = { + ["max"] = 1, + ["min"] = 1, + }, + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3772841281", + ["text"] = "Gain a Flask Charge when you deal a Critical Strike while affected by Precision", + ["type"] = "explicit", + }, + }, + ["9845_ClarityRecoverManaOnSkillUse"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1699077932", + ["text"] = "#% chance to Recover 10% of Mana when you use a Skill while affected by Clarity", + ["type"] = "explicit", + }, + }, + ["9875_HatredColdPenetration"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1222888897", + ["text"] = "Damage Penetrates #% Cold Resistance while affected by Hatred", + ["type"] = "explicit", + }, + }, + ["9877_AngerFirePenetration"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_3111519953", + ["text"] = "Damage Penetrates #% Fire Resistance while affected by Anger", + ["type"] = "explicit", + }, + }, + ["9878_WrathLightningPenetration"] = { + ["AnyJewel"] = { + ["max"] = 15, + ["min"] = 10, + }, + ["sign"] = "", + ["specialCaseData"] = { + }, + ["tradeMod"] = { + ["id"] = "explicit.stat_1077131949", + ["text"] = "Damage Penetrates #% Lightning Resistance while affected by Wrath", + ["type"] = "explicit", + }, + }, + }, } \ No newline at end of file diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 01e7a590bc..877ebc5952 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -5671,6 +5671,27 @@ local specialModList = { ["nearby allies have (%d+)%% chance to block attack damage per (%d+) strength you have"] = function(block, _, str) return { mod("ExtraAura", "LIST", { onlyAllies = true, mod = mod("BlockChance", "BASE", block) }, { type = "PerStat", stat = "Str", div = tonumber(str) }), } end, + -- Watcher's Eye special cases + ["immune to ignite while affected by purity of fire"] = { flag("IgniteImmune", { type = "Condition", var = "AffectedByPurityofFire" }) }, + ["immune to freeze while affected by purity of ice"] = { flag("FreezeImmune", { type = "Condition", var = "AffectedByPurityofIce" }) }, + ["immune to shock while affected by purity of lightning"] = { flag("ShockImmune", { type = "Condition", var = "AffectedByPurityofLightning" }) }, + ["unaffected by vulnerability while affected by determination"] = { mod("CurseEffectOnSelf", "MORE", -100, { type = "SkillName", var = "Vulnerability" }, { type = "Condition", var = "AffectedByDetermination" }) }, + ["unaffected by enfeeble while affected by grace"] = { mod("CurseEffectOnSelf", "MORE", -100, { type = "SkillName", var = "Enfeeble" }, { type = "Condition", var = "AffectedByGrace" }) }, + ["unaffected by temporal chains while affected by haste"] = { mod("CurseEffectOnSelf", "MORE", -100, { type = "SkillName", skillName = "Temporal Chains" }, { type = "Condition", var = "AffectedByHaste" }) }, + ["unaffected by bleeding while affected by malevolence"] = { mod("SelfBleedEffect", "MORE", -100, { type = "Condition", var = "AffectedByMalevolence" }) }, + ["unaffected by poison while affected by malevolence"] = { mod("SelfPoisonEffect", "MORE", -100, { type = "Condition", var = "AffectedByMalevolence" }) }, + ["unaffected by elemental weakness while affected by purity of elements"] = { mod("CurseEffectOnSelf", "MORE", -100, { type = "SkillName", var = "Elemental Weakness" }, { type = "Condition", var = "AffectedByPurityofElements" }) }, + ["unaffected by flammability while affected by purity of fire"] = { mod("CurseEffectOnSelf", "MORE", -100, { type = "SkillName", var = "Flammability" }, { type = "Condition", var = "AffectedByPurityofFire" }) }, + ["unaffected by frostbite while affected by purity of ice"] = { mod("CurseEffectOnSelf", "MORE", -100, { type = "SkillName", var = "Frostbite" }, { type = "Condition", var = "AffectedByPurityofIce" }) }, + ["unaffected by conductivity while affected by purity of lightning"] = { mod("CurseEffectOnSelf", "MORE", -100, { type = "SkillName", var = "Conductivity" }, { type = "Condition", var = "AffectedByPurityofLightning" }) }, + ["your hits intimidate enemies for 4 seconds while you are using pride"] = { mod("EnemyModifier", "LIST", { mod = flag("Condition:Intimidated") }, { type = "Condition", var = "AffectedByPride" }) }, + ["(%d+)%% chance to blind enemies which hit you while affected by grace"] = function(num) return { mod("EnemyModifier","LIST",{mod=flag("Condition:Blinded")},{type="Condition",var="AffectedByGrace"}) } end, + ["debuffs on you expire (%d+)%% faster while affected by haste"] = function(num) return { mod("SelfDebuffExpirationRate", "BASE", num, {type = "Condition", var = "AffectedByHaste"}) } end, + ["(%d+)%% chance to recover 10%% of mana when you use a skill while affected by clarity"] = { mod("","", 0,{type="Condition",var="AffectedByClarity"})}, + ["effects of consecrated ground you create while affected by zealotry linger for 2 seconds"] = { mod("","", 0,{type="Condition",var="AffectedByZealotry"})}, + ["unaffected by shocked ground while affected by purity of lightning"] = { mod("","", 0,{type="Condition",var="AffectedByPurityofLightning"}) }, + ["unaffected by chilled ground while affected by purity of ice"] = { mod("","", 0,{type="Condition",var="AffectedByPurityofIce"}) }, + ["unaffected by burning ground while affected by purity of fire"] = { mod("","", 0,{type="Condition",var="AffectedByPurityofFire"}) }, ["physical skills have (%d+)%% increased duration per (%d+) intelligence"] = function(num1, _, num2) return { mod("Duration", "INC", num1, nil, nil, KeywordFlag.Physical, { type = "PerStat", stat = "Int", div = tonumber(num2) }) } end,