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
111 changes: 111 additions & 0 deletions spec/System/TestItemMods_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,117 @@ describe("TetsItemMods", function()
-- newBuild() takes care of resetting everything in setup()
end)

it("refreshes imported modifier ranges after crafting an affix", function()
local raw = [[
Item Class: Tinctures
Rarity: Magic
Potent Prismatic Tincture of Overpowering
--------
Quality: +24% (augmented)
Inflicts Mana Burn every 0.39 (augmented) Seconds
8 Second Cooldown when Deactivated
Intangibility: 5%
--------
Requirements:
Level: 68
--------
Item Level: 85
--------
{ Implicit Modifier — Damage, Elemental, Attack — 67% Increased }
100(70-100)% increased Elemental Damage with Melee Weapons
--------
{ Prefix Modifier "Potent" (Tier: 3) — 67% Increased }
35% increased effect — Unscalable Value
47(47-51)% increased Mana Burn rate
{ Suffix Modifier "of Overpowering" (Tier: 1) — Damage, Elemental, Attack — 67% Increased }
Melee Weapon Damage Penetrates 19(17-19)% Elemental Resistances
--------
Right click to activate. Only one Tincture in your belt can be active at a time. Mana Burn causes you to lose 1% of your maximum Mana per stack per second. Can be deactivated manually, or will automatically deactivate when you reach 0 Mana.
]]
for _, edit in ipairs({ "slider", "dropdown" }) do
for _, hasImplicit in ipairs({ true, false }) do
local tab = build.itemsTab
tab:CreateDisplayItemFromRaw(raw)
if not hasImplicit then
wipeTable(tab.displayItem.implicitModLines)
end
-- Saved items can retain the separately ranged line from advanced copy.
tab:CreateDisplayItemFromRaw(tab.displayItem:BuildRaw())
local ranges = tab.controls.displayItemRangeLine
local count = hasImplicit and 2 or 1
assert.are.equals(count, #ranges.list)
local affix = tab.controls.displayItemAffix1
if edit == "slider" then
affix.slider:SetVal(0.1)
else
affix:SetSel(1)
end
assert.are.equals(count - 1, #tab.displayItem.rangeLineList)
assert.are.equals(count - 1, #ranges.list)
ranges:SetSel(2)
if hasImplicit then
assert.are.equals(1, ranges.selIndex)
tab.controls.displayItemRangeSlider:SetVal(0)
assert.are.equals(0, tab.displayItem.rangeLineList[1].range)
else
assert.falsy(ranges:IsShown())
end
end
end
end)

it("shows local tincture effect without changing base rolls or character scaling", function()
local tab = build.itemsTab
tab:CreateDisplayItemFromRaw([[
Rarity: Magic
Prismatic Tincture
Crafted: true
Prefix: {range:0}TinctureEffectFasterToxicity1
Suffix: {range:1}TinctureElementalPenetration5
Quality: 24
Implicits: 1
{range:1}(70-100)% increased Elemental Damage with Melee Weapons
]])
local item = tab.displayItem
item:Craft()
tab:SetDisplayItem(item)
for _, roll in ipairs({ { 0, 17, 28 }, { 0.5, 18, 30 }, { 1, 19, 31 } }) do
item.suffixes[1].range = roll[1]
item:Craft()
local raw = item:BuildRaw()
local tooltip = new("Tooltip"):Tooltip()
tab:AddItemTooltip(tooltip, item)
local text = { }
for _, line in ipairs(tooltip.lines) do
table.insert(text, line.text or "")
end
text = table.concat(text, "\n")
assert.is_truthy(text:find("Melee Weapon Damage Penetrates " .. roll[3] .. "%% Elemental Resistances"))
assert.is_truthy(text:find("167%% increased Elemental Damage with Melee Weapons"))
assert.is_truthy(text:find("35%% increased effect"))
assert.are.equals(raw, item:BuildRaw())
assert.is_truthy(raw:find("Melee Weapon Damage Penetrates " .. roll[2] .. "%% Elemental Resistances"))
end
tab:AddDisplayItem()
tab.slots["Flask 1"].active = true
runCallback("OnFrame")
assert.are.equals(31, build.calcsTab.mainEnv.player.modDB.mods.ElementalPenetration[1].value)
build.configTab.input.customMods = "Tinctures applied to you have 20% increased effect"
build.configTab:BuildModList()
runCallback("OnFrame")
assert.are.equals(36, build.calcsTab.mainEnv.player.modDB.mods.ElementalPenetration[1].value)
local reloaded = new("Item"):Item(item:BuildRaw())
assert.are.equals(1.67, reloaded:GetTinctureEffect())
assert.are.equals(1.24, new("Item"):Item("Rarity: Magic\nPrismatic Tincture\nQuality: 24"):GetTinctureEffect())
assert.are.equals(1.35, new("Item"):Item("Rarity: Magic\nPrismatic Tincture\nQuality: 0\n35% increased effect"):GetTinctureEffect())
assert.are.equals(1.92, reloaded:GetTinctureEffect(20))
local penLine = reloaded.explicitModLines[3]
assert.is_truthy(itemLib.formatModLine(penLine):find("19%% Elemental Resistances"))
assert.is_truthy(itemLib.formatModLine(penLine, false, reloaded:GetTinctureEffect()):find("31%% Elemental Resistances"))
penLine.unscalable = true
assert.is_truthy(itemLib.formatModLine(penLine, false, reloaded:GetTinctureEffect()):find("19%% Elemental Resistances"))
end)

it("shows versioned reusable variant groups", function()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: Unique
Expand Down
7 changes: 7 additions & 0 deletions src/Classes/Item.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2046,6 +2046,13 @@ function ItemClass:BuildRaw()
return table.concat(rawLines, "\n")
end

-- The item preview uses local bonuses only; calculations also pass in character bonuses.
---@param effectInc number? Character tincture effect, in percent
---@return number
function ItemClass:GetTinctureEffect(effectInc)
return m_floor((1 + (self.tinctureData.effectInc + (effectInc or 0)) / 100) * (1 + (self.quality or 0) / 100) * 100) / 100
end

function ItemClass:BuildAndParseRaw()
local raw = self:BuildRaw()
self:ParseRaw(raw)
Expand Down
7 changes: 5 additions & 2 deletions src/Classes/ItemsTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,7 @@ holding Shift will put it in the second.]])
self.displayItem:Craft()
self:UpdateDisplayItemTooltip()
self:UpdateAffixControls()
self:UpdateDisplayItemRangeLines()
end)
drop.y = function()
return i == 1 and 0 or 24 + (prev.slider:IsShown() and 18 or 0)
Expand Down Expand Up @@ -939,6 +940,7 @@ holding Shift will put it in the second.]])
affix.range = verifyRange(range, index, drop)
self.displayItem:Craft()
self:UpdateDisplayItemTooltip()
self:UpdateDisplayItemRangeLines()
end)
slider.width = function()
return slider.divCount and 300 or 100
Expand Down Expand Up @@ -2478,8 +2480,8 @@ end

-- Updates the range line dropdown and range slider for the current display item
function ItemsTabClass:UpdateDisplayItemRangeLines()
wipeTable(self.controls.displayItemRangeLine.list)
if self.displayItem and self.displayItem.rangeLineList[1] then
wipeTable(self.controls.displayItemRangeLine.list)
for _, modLine in ipairs(self.displayItem.rangeLineList) do
if (modLine.modId and modLine.newModId) or modLine.range then
t_insert(self.controls.displayItemRangeLine.list, { modLine = modLine, label = modLine.line })
Expand Down Expand Up @@ -4468,12 +4470,13 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode, maxWidth)
item.requirements.str or 0, item.requirements.dex or 0, item.requirements.int or 0)

-- Modifiers
local effectMod = base.tincture and item:GetTinctureEffect()
for _, modList in ipairs{item.enchantModLines, item.scourgeModLines, item.implicitModLines, item.explicitModLines, item.crucibleModLines} do
if modList[1] then
for _, modLine in ipairs(modList) do
local variantCount = item:GetModLineVariantCount(modLine)
if variantCount > 0 then
local formattedModLine = itemLib.formatModLine(modLine, dbMode)
local formattedModLine = itemLib.formatModLine(modLine, dbMode, effectMod)
if formattedModLine then
for _ = 1, variantCount do
tooltip:AddLine(fontSizeBig, formattedModLine, "FONTIN SC", modLine)
Expand Down
4 changes: 2 additions & 2 deletions src/Modules/CalcPerform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1870,13 +1870,13 @@ function calcs.perform(env, skipEHP)
local tinctureBuffsPerBase = {}

local function calcTinctureMods(item, baseName, buffModList, modList)
local tinctureEffectInc = effectInc + item.tinctureData.effectInc
local tinctureEffectInc = effectInc
if item.rarity == "MAGIC" then
tinctureEffectInc = tinctureEffectInc + effectIncMagic
end
-- Compute tincture effect multiplier.
-- Tincture effect multiplier is rounded to 2 decimal places before applying it.
local effectMod = math.floor((1 + (tinctureEffectInc) / 100) * (1 + (item.quality or 0) / 100) * 100) / 100
local effectMod = item:GetTinctureEffect(tinctureEffectInc)

-- same deal as flasks, go look at the comment there
if buffModList[1] then
Expand Down
19 changes: 16 additions & 3 deletions src/Modules/ItemTools.lua
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,23 @@ function itemLib.isModLineScalable(line, range, valueScalar)
return itemLib.applyRange(line, range, valueScalar, 1) ~= itemLib.applyRange(line, range, valueScalar, 2)
end

function itemLib.formatModLine(modLine, dbMode)
local shouldApplyRange = not dbMode and (modLine.range or modLine.corruptedRange)
---@param effectMod number? Display-only effect multiplier; leaves stored rolls unchanged
function itemLib.formatModLine(modLine, dbMode, effectMod)
local valueScalar = modLine.valueScalar
if effectMod and not dbMode and not modLine.unscalable and not modLine.extra then
-- The effect modifier itself must not be amplified, including crafted lines
-- which do not carry advanced-copy's unscalable marker.
for _, mod in ipairs(modLine.modList) do
if mod.name == "LocalEffect" or mod.name == "TinctureEffect" then
effectMod = 1
break
end
end
valueScalar = (valueScalar or 1) * effectMod
end
local shouldApplyRange = not dbMode and (modLine.range or modLine.corruptedRange or (effectMod and valueScalar))
local line = shouldApplyRange and itemLib.applyRange(modLine.line, modLine.range or main.defaultItemAffixQuality,
modLine.valueScalar, modLine.corruptedRange) or modLine.line
valueScalar, modLine.corruptedRange) or modLine.line
if line:match("^%+?0%%? ") or (line:match(" %+?0%%? ") and not line:match("0 to [1-9]")) or line:match(" 0%-0 ") or line:match(" 0 to 0 ") then -- Hack to hide 0-value modifiers
return
end
Expand Down
Loading