diff --git a/Classes/CalcsTab.lua b/Classes/CalcsTab.lua index 8f81939d..ac0080b4 100644 --- a/Classes/CalcsTab.lua +++ b/Classes/CalcsTab.lua @@ -372,7 +372,7 @@ function CalcsTabClass:BuildOutput() -- Retrieve calculator functions self.nodeCalculator = { self.calcs.getNodeCalculator(self.build) } - self.itemCalculator = { self.calcs.getItemCalculator(self.build) } + self.miscCalculator = { self.calcs.getMiscCalculator(self.build) } end -- Controls the coroutine that calculations node power @@ -382,7 +382,7 @@ function CalcsTabClass:BuildPower() self.powerBuilder = coroutine.create(self.PowerBuilder) end if self.powerBuilder then - collectgarbage("stop") -- This is necessary to work around a bug in the JIT + collectgarbage("stop") local res, errMsg = coroutine.resume(self.powerBuilder, self) if launch.devMode and not res then error(errMsg) @@ -440,8 +440,8 @@ function CalcsTabClass:GetNodeCalculator() return unpack(self.nodeCalculator) end -function CalcsTabClass:GetItemCalculator() - return unpack(self.itemCalculator) +function CalcsTabClass:GetMiscCalculator() + return unpack(self.miscCalculator) end function CalcsTabClass:CreateUndoState() diff --git a/Classes/ConfigTab.lua b/Classes/ConfigTab.lua index 8dd8900c..af8ac12b 100644 --- a/Classes/ConfigTab.lua +++ b/Classes/ConfigTab.lua @@ -64,12 +64,21 @@ local varList = { { var = "conditionCritRecently", type = "check", label = "Have you Crit Recently?", ifCond = "CritRecently", apply = function(val, modList, enemyModList) modList:NewMod("Misc", "LIST", { type = "Condition", var = "CritRecently" }, "Config", { type = "Condition", var = "Combat" }) end }, + { var = "conditionNonCritRecently", type = "check", label = "Have you dealt a Non-Crit Recently?", ifCond = "NonCritRecently", apply = function(val, modList, enemyModList) + modList:NewMod("Misc", "LIST", { type = "Condition", var = "NonCritRecently" }, "Config", { type = "Condition", var = "Combat" }) + end }, { var = "conditionKilledRecently", type = "check", label = "Have you Killed Recently?", ifCond = "KilledRecently", apply = function(val, modList, enemyModList) modList:NewMod("Misc", "LIST", { type = "Condition", var = "KilledRecently" }, "Config", { type = "Condition", var = "Combat" }) end }, { var = "conditionTotemsKilledRecently", type = "check", label = "Have your Totems Killed Recently?", ifCond = "TotemsKilledRecently", apply = function(val, modList, enemyModList) modList:NewMod("Misc", "LIST", { type = "Condition", var = "TotemsKilledRecently" }, "Config", { type = "Condition", var = "Combat" }) end }, + { var = "conditionFrozenEnemyRecently", type = "check", label = "Have you Frozen an Enemy Recently?", ifCond = "FrozenEnemyRecently", apply = function(val, modList, enemyModList) + modList:NewMod("Misc", "LIST", { type = "Condition", var = "FrozenEnemyRecently" }, "Config", { type = "Condition", var = "Combat" }) + end }, + { var = "conditionIgnitedEnemyRecently", type = "check", label = "Have you Ignited an Enemy Recently?", ifCond = "IgnitedEnemyRecently", apply = function(val, modList, enemyModList) + modList:NewMod("Misc", "LIST", { type = "Condition", var = "IgnitedEnemyRecently" }, "Config", { type = "Condition", var = "Combat" }) + end }, { var = "conditionBeenHitRecently", type = "check", label = "Have you been Hit Recently?", ifCond = "BeenHitRecently", apply = function(val, modList, enemyModList) modList:NewMod("Misc", "LIST", { type = "Condition", var = "BeenHitRecently" }, "Config", { type = "Condition", var = "Combat" }) end }, @@ -128,6 +137,9 @@ local varList = { { var = "conditionEnemyHindered", type = "check", label = "Is the enemy Hindered?", ifCond = "EnemyHindered", apply = function(val, modList, enemyModList) modList:NewMod("Misc", "LIST", { type = "Condition", var = "EnemyHindered" }, "Config", { type = "Condition", var = "Effective" }) end }, + { var = "conditionEnemyBlinded", type = "check", label = "Is the enemy Blinded?", tooltip = "In addition to allowing 'against Blinded Enemies' modifiers to apply,\nthis will lessen the enemy's chance to hit, and thereby increase your evade chance.", apply = function(val, modList, enemyModList) + modList:NewMod("Misc", "LIST", { type = "Condition", var = "EnemyBlinded" }, "Config", { type = "Condition", var = "Effective" }) + end }, { var = "conditionEnemyBurning", type = "check", label = "Is the enemy Burning?", ifCond = "EnemyBurning", apply = function(val, modList, enemyModList) modList:NewMod("Misc", "LIST", { type = "Condition", var = "EnemyBurning" }, "Config", { type = "Condition", var = "Effective" }) end }, @@ -179,13 +191,6 @@ local varList = { modList:NewMod("Misc", "LIST", { type = "EnemyCondition", var = "HitByLightningDamage" }, "Config") end }, } -if launch.enableFlasks then -- FIXME Flask release - t_insert(varList, { var = "enableFlask1", type = "check", label = "Flask 1", }) - t_insert(varList, { var = "enableFlask2", type = "check", label = "Flask 2", }) - t_insert(varList, { var = "enableFlask3", type = "check", label = "Flask 3", }) - t_insert(varList, { var = "enableFlask4", type = "check", label = "Flask 4", }) - t_insert(varList, { var = "enableFlask5", type = "check", label = "Flask 5", }) -end local ConfigTabClass = common.NewClass("ConfigTab", "UndoHandler", "ControlHost", "Control", function(self, build) self.UndoHandler() @@ -204,7 +209,7 @@ local ConfigTabClass = common.NewClass("ConfigTab", "UndoHandler", "ControlHost" local lastSection for _, varData in ipairs(varList) do if varData.section then - lastSection = common.New("SectionControl", {"TOPLEFT",self,"TOPLEFT"}, 0, 0, 350, 0, varData.section) + lastSection = common.New("SectionControl", {"TOPLEFT",self,"TOPLEFT"}, 0, 0, 360, 0, varData.section) lastSection.varControlList = { } lastSection.height = function(self) local height = 20 @@ -220,21 +225,21 @@ local ConfigTabClass = common.NewClass("ConfigTab", "UndoHandler", "ControlHost" else local control if varData.type == "check" then - control = common.New("CheckBoxControl", {"TOPLEFT",lastSection,"TOPLEFT"}, 224, 0, 18, nil, function(state) + control = common.New("CheckBoxControl", {"TOPLEFT",lastSection,"TOPLEFT"}, 234, 0, 18, nil, function(state) self.input[varData.var] = state self:AddUndoState() self:BuildModList() self.build.buildFlag = true end) elseif varData.type == "number" then - control = common.New("EditControl", {"TOPLEFT",lastSection,"TOPLEFT"}, 224, 0, 50, 18, "", nil, "^%-%d", 4, function(buf) + control = common.New("EditControl", {"TOPLEFT",lastSection,"TOPLEFT"}, 234, 0, 50, 18, "", nil, "^%-%d", 4, function(buf) self.input[varData.var] = tonumber(buf) self:AddUndoState() self:BuildModList() self.build.buildFlag = true end) elseif varData.type == "list" then - control = common.New("DropDownControl", {"TOPLEFT",lastSection,"TOPLEFT"}, 224, 0, 118, 16, varData.list, function(sel, selVal) + control = common.New("DropDownControl", {"TOPLEFT",lastSection,"TOPLEFT"}, 234, 0, 118, 16, varData.list, function(sel, selVal) self.input[varData.var] = selVal.val self:AddUndoState() self:BuildModList() diff --git a/Classes/DropDownControl.lua b/Classes/DropDownControl.lua index 1772b9bf..320a8c98 100644 --- a/Classes/DropDownControl.lua +++ b/Classes/DropDownControl.lua @@ -67,6 +67,9 @@ function DropDownClass:IsMouseOver() if not self:IsShown() then return false end + if self:GetMouseOverControl() then + return true + end local x, y = self:GetPos() local width, height = self:GetSize() local cursorX, cursorY = GetCursorPos() diff --git a/Classes/ItemSlotControl.lua b/Classes/ItemSlotControl.lua index 6e790655..61bbdad4 100644 --- a/Classes/ItemSlotControl.lua +++ b/Classes/ItemSlotControl.lua @@ -28,6 +28,20 @@ local ItemSlotClass = common.NewClass("ItemSlot", "DropDownControl", function(se self.items = { } self.slotName = slotName self.slotNum = tonumber(slotName:match("%d+")) + if slotName:match("Flask") then + self.controls.activate = common.New("CheckBoxControl", {"RIGHT",self,"LEFT"}, -2, 0, 20, nil, function(state) + self.active = state + itemsTab:AddUndoState() + itemsTab.build.buildFlag = true + end) + self.controls.activate.enabled = function() + return self.selItemId ~= 0 + end + self.controls.activate.tooltip = "Activate this flask." + self.labelOffset = -24 + else + self.labelOffset = -2 + end self.label = slotLabel or slotName self.nodeId = nodeId itemsTab.slots[slotName] = self @@ -57,8 +71,9 @@ end function ItemSlotClass:Draw(viewPort) local x, y = self:GetPos() local width, height = self:GetSize() - DrawString(x - 2, y + 2, "RIGHT_X", height - 4, "VAR", "^7"..self.label..":") + DrawString(x + self.labelOffset, y + 2, "RIGHT_X", height - 4, "VAR", "^7"..self.label..":") self.DropDownControl:Draw(viewPort) + self:DrawControls(viewPort) local highlight = false for _, control in pairs({self.itemsTab.controls.itemList, self.itemsTab.controls.uniqueDB, self.itemsTab.controls.rareDB}) do if control:IsShown() and control.selDragging and control.selDragActive and self.itemsTab:IsItemValidForSlot(control.selItem, self.slotName) then @@ -93,7 +108,7 @@ function ItemSlotClass:Draw(viewPort) if self.hoverSel then ttItem = self.itemsTab.list[self.items[self.hoverSel]] end - elseif self.selItemId and not self.itemsTab.selControl then + elseif self.selItemId and (not self.itemsTab.selControl or self.itemsTab.selControl == self.controls.activate) then ttItem = self.itemsTab.list[self.selItemId] end if ttItem then @@ -104,3 +119,14 @@ function ItemSlotClass:Draw(viewPort) end end end + +function ItemSlotClass:OnKeyDown(key) + if not self:IsShown() or not self:IsEnabled() then + return + end + local mOverControl = self:GetMouseOverControl() + if mOverControl and mOverControl == self.controls.activate then + return mOverControl:OnKeyDown(key) + end + return self.DropDownControl:OnKeyDown(key) +end \ No newline at end of file diff --git a/Classes/ItemsTab.lua b/Classes/ItemsTab.lua index 2cc8c59d..8f06959c 100644 --- a/Classes/ItemsTab.lua +++ b/Classes/ItemsTab.lua @@ -10,6 +10,9 @@ local ipairs = ipairs local t_insert = table.insert local t_remove = table.remove local s_format = string.format +local m_max = math.max +local m_min = math.min +local m_floor = math.floor local baseSlots = { "Weapon 1", "Weapon 2", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring 1", "Ring 2", "Belt" } if launch.enableFlasks then -- FIXME Flask release @@ -159,8 +162,13 @@ function ItemsTabClass:Load(xml, dbFileName) self.list[item.id] = item t_insert(self.orderList, item.id) elseif node.elem == "Slot" then - if self.slots[node.attrib.name or ""] then - self.slots[node.attrib.name].selItemId = tonumber(node.attrib.itemId) + local slot = self.slots[node.attrib.name or ""] + if slot then + slot.selItemId = tonumber(node.attrib.itemId) + if slot.controls.activate then + slot.active = node.attrib.active == "true" + slot.controls.activate.state = slot.active + end end end end @@ -182,7 +190,7 @@ function ItemsTabClass:Save(xml) end for name, slot in pairs(self.slots) do if slot.selItemId ~= 0 then - t_insert(xml, { elem = "Slot", attrib = { name = name, itemId = tostring(slot.selItemId) }}) + t_insert(xml, { elem = "Slot", attrib = { name = name, itemId = tostring(slot.selItemId), active = slot.active and "true" }}) end end self.modFlag = false @@ -527,10 +535,10 @@ function ItemsTabClass:AddItemTooltip(item, slot, dbMode) main:AddTooltipLine(16, s_format("^x7F7F7FQuality: "..data.colorCodes.MAGIC.."+%d%%", item.quality)) end if flaskData.lifeTotal then - main:AddTooltipLine(16, s_format("^x7F7F7FRecovers %s%d ^x7F7F7FLife over %s%.1f0 ^x7F7F7FSeconds", flaskData.lifeTotal ~= base.flask.life and data.colorCodes.MAGIC or "^7", flaskData.lifeTotal, flaskData.lifeDuration ~= base.flask.duration and data.colorCodes.MAGIC or "^7", flaskData.lifeDuration)) + main:AddTooltipLine(16, s_format("^x7F7F7FRecovers %s%d ^x7F7F7FLife over %s%.1f0 ^x7F7F7FSeconds", flaskData.lifeTotal ~= base.flask.life and data.colorCodes.MAGIC or "^7", flaskData.lifeTotal, flaskData.duration ~= base.flask.duration and data.colorCodes.MAGIC or "^7", flaskData.duration)) end if flaskData.manaTotal then - main:AddTooltipLine(16, s_format("^x7F7F7FRecovers %s%d ^x7F7F7FMana over %s%.1f0 ^x7F7F7FSeconds", flaskData.manaTotal ~= base.flask.mana and data.colorCodes.MAGIC or "^7", flaskData.manaTotal, flaskData.manaDuration ~= base.flask.duration and data.colorCodes.MAGIC or "^7", flaskData.manaDuration)) + main:AddTooltipLine(16, s_format("^x7F7F7FRecovers %s%d ^x7F7F7FMana over %s%.1f0 ^x7F7F7FSeconds", flaskData.manaTotal ~= base.flask.mana and data.colorCodes.MAGIC or "^7", flaskData.manaTotal, flaskData.duration ~= base.flask.duration and data.colorCodes.MAGIC or "^7", flaskData.duration)) end if not flaskData.lifeTotal and not flaskData.manaTotal then main:AddTooltipLine(16, s_format("^x7F7F7FLasts %s%.2f ^x7F7F7FSeconds", flaskData.duration ~= base.flask.duration and data.colorCodes.MAGIC or "^7", flaskData.duration)) @@ -602,45 +610,121 @@ function ItemsTabClass:AddItemTooltip(item, slot, dbMode) main:AddTooltipSeparator(14) -- Mod differences - local calcFunc, calcBase = self.build.calcsTab:GetItemCalculator() + local calcFunc, calcBase = self.build.calcsTab:GetMiscCalculator() if calcFunc then - self:UpdateSockets() - -- Build sorted list of slots to compare with - local compareSlots = { } - for slotName, slot in pairs(self.slots) do - local selItem = self.list[slot.selItemId] - if self:IsItemValidForSlot(item, slotName) and not slot.inactive then - t_insert(compareSlots, slot) - end - end - table.sort(compareSlots, function(a, b) - if a.selItemId ~= b.selItemId then - if item == self.list[a.selItemId] then - return true - elseif item == self.list[b.selItemId] then - return false + if base.flask then + -- Special handling for flasks + local stats = { } + local flaskData = item.flaskData + local modDB = self.build.calcsTab.mainEnv.modDB + local durInc = modDB:Sum("INC", nil, "FlaskDuration") + local effectInc = modDB:Sum("INC", nil, "FlaskEffect") + if item.base.flask.life or item.base.flask.mana then + local rateInc = modDB:Sum("INC", nil, "FlaskRecoveryRate") + local instantPerc = flaskData.instantPerc > 0 and m_min(flaskData.instantPerc + effectInc, 100) or 0 + if item.base.flask.life then + local lifeInc = modDB:Sum("INC", nil, "FlaskLifeRecovery") + local lifeRateInc = modDB:Sum("INC", nil, "FlaskLifeRecoveryRate") + local inst = flaskData.lifeBase * instantPerc / 100 * (1 + lifeInc / 100) * (1 + effectInc / 100) + local grad = flaskData.lifeBase * (1 - instantPerc / 100) * (1 + lifeInc / 100) * (1 + effectInc / 100) * (1 + durInc / 100) + local lifeDur = flaskData.duration * (1 + durInc / 100) / (1 + rateInc / 100) / (1 + lifeRateInc / 100) + if inst > 0 and grad > 0 then + t_insert(stats, s_format("^8Life recovered: ^7%d ^8(^7%d^8 instantly, plus ^7%d ^8over^7 %.2fs^8)", inst + grad, inst, grad, lifeDur)) + elseif inst + grad ~= flaskData.lifeTotal then + if inst > 0 then + t_insert(stats, s_format("^8Life recovered: ^7%d ^8instantly", inst)) + elseif grad > 0 then + t_insert(stats, s_format("^8Life recovered: ^7%d ^8over ^7%.2fs", grad, lifeDur)) + end + end + end + if item.base.flask.mana then + local manaInc = modDB:Sum("INC", nil, "FlaskManaRecovery") + local manaRateInc = modDB:Sum("INC", nil, "FlaskManaRecoveryRate") + local inst = flaskData.manaBase * instantPerc / 100 * (1 + manaInc / 100) * (1 + effectInc / 100) + local grad = flaskData.manaBase * (1 - instantPerc / 100) * (1 + manaInc / 100) * (1 + effectInc / 100) * (1 + durInc / 100) + local manaDur = flaskData.duration * (1 + durInc / 100) / (1 + rateInc / 100) / (1 + manaRateInc / 100) + if inst > 0 and grad > 0 then + t_insert(stats, s_format("^8Mana recovered: ^7%d ^8(^7%d^8 instantly, plus ^7%d ^8over^7 %.2fs^8)", inst + grad, inst, grad, manaDur)) + elseif inst + grad ~= flaskData.manaTotal then + if inst > 0 then + t_insert(stats, s_format("^8Mana recovered: ^7%d ^8instantly", inst)) + elseif grad > 0 then + t_insert(stats, s_format("^8Mana recovered: ^7%d ^8over ^7%.2fs", grad, manaDur)) + end + end + end + else + if durInc ~= 0 then + t_insert(stats, s_format("^8Flask effect duration: ^7%.1f0s", flaskData.duration * (1 + durInc / 100))) end end - local aNum = tonumber(a.slotName:match("%d+")) - local bNum = tonumber(b.slotName:match("%d+")) - if aNum and bNum then - return aNum < bNum - else - return a.slotName < b.slotName + local effectMod = 1 + (flaskData.effectInc + effectInc) / 100 + if effectMod ~= 1 then + t_insert(stats, s_format("^8Flask effect modifier: ^7%+d%%", effectMod * 100 - 100)) end - end) - - -- Add comparisons for each slot - for _, slot in pairs(compareSlots) do - local selItem = self.list[slot.selItemId] - local output = calcFunc(slot.slotName, item ~= selItem and item) + local usedInc = modDB:Sum("INC", nil, "FlaskChargesUsed") + if usedInc ~= 0 then + local used = m_floor(flaskData.chargesUsed * (1 + usedInc / 100)) + t_insert(stats, s_format("^8Charges used: ^7%d ^8of ^7%d ^8(^7%d ^8uses)", used, flaskData.chargesMax, m_floor(flaskData.chargesMax / used))) + end + local gainMod = flaskData.gainMod * (1 + modDB:Sum("INC", nil, "FlaskChargesGained") / 100) + if gainMod ~= 1 then + t_insert(stats, s_format("^8Charge gain modifier: ^7%+d%%", gainMod * 100 - 100)) + end + if stats[1] then + main:AddTooltipLine(14, "^7Effective flask stats:") + for _, stat in ipairs(stats) do + main:AddTooltipLine(14, stat) + end + end + local output = calcFunc({ toggleFlask = item }) local header - if item == selItem then - header = "^7Removing this item from "..slot.label.." will give you:" + if self.build.calcsTab.mainEnv.flasks[item] then + header = "^7Deactivating this flask will give you:" else - header = string.format("^7Equipping this item in %s%s will give you:", slot.label, selItem and " (replacing "..data.colorCodes[selItem.rarity]..selItem.name.."^7)" or "") + header = "^7Activating this flask will give you:" end self.build:AddStatComparesToTooltip(calcBase, output, header) + else + self:UpdateSockets() + -- Build sorted list of slots to compare with + local compareSlots = { } + for slotName, slot in pairs(self.slots) do + local selItem = self.list[slot.selItemId] + if self:IsItemValidForSlot(item, slotName) and not slot.inactive then + t_insert(compareSlots, slot) + end + end + table.sort(compareSlots, function(a, b) + if a.selItemId ~= b.selItemId then + if item == self.list[a.selItemId] then + return true + elseif item == self.list[b.selItemId] then + return false + end + end + local aNum = tonumber(a.slotName:match("%d+")) + local bNum = tonumber(b.slotName:match("%d+")) + if aNum and bNum then + return aNum < bNum + else + return a.slotName < b.slotName + end + end) + + -- Add comparisons for each slot + for _, slot in pairs(compareSlots) do + local selItem = self.list[slot.selItemId] + local output = calcFunc({ repSlotName = slot.slotName, repItem = item ~= selItem and item }) + local header + if item == selItem then + header = "^7Removing this item from "..slot.label.." will give you:" + else + header = string.format("^7Equipping this item in %s%s will give you:", slot.label, selItem and " (replacing "..data.colorCodes[selItem.rarity]..selItem.name.."^7)" or "") + end + self.build:AddStatComparesToTooltip(calcBase, output, header) + end end end diff --git a/Classes/PassiveTreeView.lua b/Classes/PassiveTreeView.lua index b2a6d6cc..45d628f9 100644 --- a/Classes/PassiveTreeView.lua +++ b/Classes/PassiveTreeView.lua @@ -575,25 +575,27 @@ function PassiveTreeViewClass:AddNodeTooltip(node, build) end -- Mod differences - local calcFunc, calcBase = build.calcsTab:GetNodeCalculator(build) + local calcFunc, calcBase = build.calcsTab:GetMiscCalculator(build) if calcFunc then main:AddTooltipSeparator(14) - local pathLength + local path = (node.alloc and node.depends) or self.tracePath or node.path or { } + local pathLength = #path + local pathNodes = { } + for _, node in pairs(path) do + pathNodes[node] = true + end local nodeOutput, pathOutput if node.alloc then -- Calculate the differences caused by deallocating this node and its dependants - pathLength = #node.depends - nodeOutput = calcFunc({node}, true) + nodeOutput = calcFunc({ removeNodes = { [node] = true } }) if pathLength > 1 then - pathOutput = calcFunc(node.depends, true) + pathOutput = calcFunc({ removeNodes = pathNodes }) end else - -- Calculated the differences caused by allocting this node and all nodes along the path to it - local path = self.tracePath or node.path or { } - pathLength = #path - nodeOutput = calcFunc({node}) + -- Calculated the differences caused by allocating this node and all nodes along the path to it + nodeOutput = calcFunc({ addNodes = { [node] = true } }) if pathLength > 1 then - pathOutput = calcFunc(path) + pathOutput = calcFunc({ addNodes = pathNodes }) end end local count = build:AddStatComparesToTooltip(calcBase, nodeOutput, node.alloc and "^7Unallocating this node will give you:" or "^7Allocating this node will give you:") diff --git a/Data/Uniques/flask.lua b/Data/Uniques/flask.lua index f5fc0e37..7fe083ac 100644 --- a/Data/Uniques/flask.lua +++ b/Data/Uniques/flask.lua @@ -5,8 +5,6 @@ return { [[ Blood of the Karui Sanctified Life Flask -Recovers 1460 Life over (2.86 to 2.50) seconds -Consumes 15 of 30 Charges on use Requires Level 50 (5-20)% increased Recovery Speed No Life Recovery Applies during Flask effect @@ -18,9 +16,8 @@ Doedre's Elixir Greater Mana Flask Variant: Pre 2.0.0 Variant: Current -Recovers 140 Mana over 5.60 seconds -Consumes (26 to 30) of 32 Charges on use Requires Level 12 +Implicits: 0 Removes 20% of your maximum Energy Shield on use You take 10% of your maximum Life as Chaos Damage on use You gain a Power Charge on use @@ -31,8 +28,6 @@ You gain an Endurance Charge on use ]],[[ Lavianga's Spirit Sanctified Mana Flask -Recovers (1365 to 1575) Mana over 7.00 seconds -Consumes 10 of 40 Charges on use Requires Level 50 (30-50)% increased Amount Recovered 100% increased Recovery Speed @@ -40,8 +35,6 @@ Your Skills have no Mana Cost during Flask effect ]],[[ Zerphi's Last Breath Grand Mana Flask -Recovers 210 Mana over 10.00 seconds -Consumes 12 of 30 Charges on use Requires Level 18 50% increased Charges used Skills used during Flask effect grant 800% of Mana Cost as Life @@ -53,9 +46,6 @@ Large Hybrid Flask Variant: Pre 1.1.0 Variant: Pre 2.2.0 Variant: Current -Recovers 140 Mana over 5.00 seconds -Recovers 510 Life over 5.00 seconds -Consumes 20 of 40 Charges on use Requires Level 30 (40-60)% increased Rarity of Items found during Flask effect {variant:1}(20-25)% increased Quantity of Items found during Flask effect @@ -66,9 +56,6 @@ Requires Level 30 ]],[[ The Writhing Jar Hallowed Hybrid Flask -Recovers (120 to 168) Mana over 5.00 seconds -Recovers (435 to 609) Life over 5.00 seconds -Consumes (16 to 18) of 40 Charges on use Requires Level 60 (75-65)% reduced Amount Recovered Instant Recovery @@ -79,8 +66,6 @@ Requires Level 60 [[ Atziri's Promise Amethyst Flask -Lasts 3.50 Seconds -Consumes 30 of 60 Charges on use +35% to Chaos Resistance Requires Level 68 2% of Chaos Damage Leeched as Life during Flask effect @@ -89,19 +74,16 @@ Gain (13-15)% of Elemental Damage as Extra Chaos Damage during effect ]],[[ Coruscating Elixir Ruby Flask -Lasts 4.00 Seconds -Consumes 30 of 60 Charges on use +50% to Fire Resistance +6% to maximum Fire Resistance Requires Level 18 +Implicits: 0 Chaos Damage does not bypass Energy Shield during effect Removes all but one Life on use Removed life is regenerated as Energy Shield over 2 seconds ]],[[ Dying Sun Ruby Flask -Lasts 4.00 Seconds -Consumes (27 to 33) of 60 Charges on use +50% to Fire Resistance +6% to maximum Fire Resistance Requires Level 68 @@ -113,8 +95,6 @@ Forbidden Taste Quartz Flask Variant: Pre 1.2.3 Variant: Current -Lasts 4.00 Seconds -Consumes 45 of 60 Charges on use 10% chance to Dodge Attacks 10% chance to Dodge Spell Damage Phasing @@ -127,10 +107,9 @@ Requires Level 27 ]],[[ Kiara's Determination Silver Flask -Lasts 2.50 Seconds -Consumes 40 of 60 Charges on use Onslaught Requires Level 22 +Implicits: 0 Immune to Freeze, Chill, Curses and Stuns during Flask Effect 50% reduced Duration ]],[[ @@ -138,10 +117,9 @@ Lion's Roar Granite Flask Variant: Pre 2.2.0 Variant: Current -Lasts 4.00 Seconds -Consumes 30 of 60 Charges on use +3000 to Armour Requires Level 27 +Implicits: 0 Adds Knockback during Flask effect 75% chance to cause Enemies to Flee on use {variant:1}(70 to 100)% increased Charges used @@ -153,8 +131,6 @@ Rotgut Quicksilver Flask Variant: Pre 2.2.0 Variant: Current -Lasts 4.00 Seconds -Consumes (30 to 40) of 50 Charges on use 40% increased Movement Speed Requires Level 40 {variant:1}(100-150)% increased Charges used @@ -169,8 +145,6 @@ Granite Flask Variant: Pre 1.3.0 Variant: Pre 2.5.0 Variant: Current -Lasts 4.00 Seconds -Consumes 30 of 60 Charges on use +3000 to Armour Requires Level 68 {variant:1}(30-40)% Chance to Block during Flask effect @@ -182,10 +156,9 @@ Requires Level 68 ]],[[ Sin's Rebirth Stibnite Flask -Lasts 5.00 Seconds -Consumes 10 of 30 Charges on use 100% increased Evasion Rating Requires Level 14 +Implicits: 2 Creates a Smoke Cloud on Use Gain Unholy Might during Flask Effect Immunity to Ignite during Flask effect @@ -195,8 +168,6 @@ Taste of Hate Sapphire Flask Variant: Pre 2.2.0 Variant: Current -Lasts 4.00 Seconds -Consumes 30 of 60 Charges on use +50% to Cold Resistance +6% to maximum Cold Resistance Requires Level 18 @@ -208,10 +179,9 @@ Gain (20-30)% of Physical Damage as Extra Cold Damage during effect ]],[[ The Overflowing Chalice Sulphur Flask -Lasts (4.40 to 4.80) Seconds -Consumes 20 of 60 Charges on use 40% increased Damage Requires Level 35 +Implicits: 2 Creates Consecrated Ground on Use 100% increased Charge Recovery (10-20)% increased Duration @@ -220,10 +190,9 @@ Gains no Charges during Effect of any Overflowing Chalice Flask ]],[[ The Sorrow of the Divine Sulphur Flask -Lasts (5.00 to 6.00) Seconds -Consumes 20 of 60 Charges on use 40% increased Damage Requires Level 35 +Implicits: 2 Creates Consecrated Ground on Use (25-50)% increased Duration Zealot's Oath during Flask effect @@ -238,8 +207,6 @@ Variant: Current (Penetration) Variant: Current (Spells) Variant: Current (Attacks) Variant: Current (Conversion) -Lasts 4.00 Seconds -Consumes (54 to 60) of 60 Charges on use +50% to Lightning Resistance +6% to maximum Lightning Resistance Requires Level 68 @@ -258,10 +225,9 @@ You are Shocked during Flask effect ]],[[ Witchfire Brew Stibnite Flask -Lasts 5.00 Seconds -Consumes 15 of 30 Charges on use 100% increased Evasion Rating Requires Level 48 +Implicits: 2 Creates a Smoke Cloud on Use 50% increased Charges used (50-70)% increased Damage Over Time during Flask Effect diff --git a/Modules/Build.lua b/Modules/Build.lua index fd86a816..3dd3616c 100644 --- a/Modules/Build.lua +++ b/Modules/Build.lua @@ -31,7 +31,7 @@ function buildMode:Init(dbFileName, buildName) self.anchorTopBarLeft = common.New("Control", nil, 4, 4, 0, 20) self.controls.back = common.New("ButtonControl", {"LEFT",self.anchorTopBarLeft,"RIGHT"}, 0, 0, 60, 20, "<< Back", function() if self.unsaved then - self:OpenSavePopup(false) + self:OpenSavePopup("LIST") else main:SetMode("LIST", self.dbFileName and self.buildName) end @@ -352,11 +352,11 @@ function buildMode:Init(dbFileName, buildName) self.abortSave = false end -function buildMode:CanExit() +function buildMode:CanExit(mode) if not self.unsaved then return true end - self:OpenSavePopup(true) + self:OpenSavePopup(mode) return false end @@ -408,7 +408,7 @@ function buildMode:OnFrame(inputEvents) inputEvents[id] = nil elseif event.key == "w" then if self.unsaved then - self:OpenSavePopup(false) + self:OpenSavePopup("LIST") else main:SetMode("LIST", self.dbFileName and self.buildName) end @@ -526,20 +526,27 @@ function buildMode:OnFrame(inputEvents) self:DrawControls(main.viewPort) end -function buildMode:OpenSavePopup(exit) - main:OpenPopup(280, 100, "Save Changes", { - common.New("LabelControl", nil, 0, 20, 0, 16, "^7This build has unsaved changes.\nDo you want to save them "..(exit and "before exiting?" or "now?")), +function buildMode:OpenSavePopup(mode) + local modeDesc = { + ["LIST"] = "now?", + ["EXIT"] = "before exiting?", + ["UPDATE"] = "before updating?", + } + main:OpenPopup(290, 100, "Save Changes", { + common.New("LabelControl", nil, 0, 20, 0, 16, "^7This build has unsaved changes.\nDo you want to save them "..modeDesc[mode]), common.New("ButtonControl", nil, -90, 70, 80, 20, "Save", function() main:ClosePopup() - self.actionOnSave = exit and "EXIT" or "LIST" + self.actionOnSave = mode self:SaveDBFile() end), common.New("ButtonControl", nil, 0, 70, 80, 20, "Don't Save", function() main:ClosePopup() - if exit then - Exit() - else + if mode == "LIST" then main:SetMode("LIST", self.dbFileName and self.buildName) + elseif mode == "EXIT" then + Exit() + elseif mode == "UPDATE" then + launch:ApplyUpdate(launch.updateAvailable) end end), common.New("ButtonControl", nil, 90, 70, 80, 20, "Cancel", function() @@ -702,9 +709,11 @@ function buildMode:SaveDBFile() file:write(xmlText) file:close() if self.actionOnSave == "LIST" then - main:SetMode("LIST", self.buildName) + main:SetMode("LIST", self.dbFileName and self.buildName) elseif self.actionOnSave == "EXIT" then Exit() + elseif self.actionOnSave == "UPDATE" then + launch:ApplyUpdate(launch.updateAvailable) end self.actionOnSave = nil end diff --git a/Modules/Calcs.lua b/Modules/Calcs.lua index d51c90b9..be4a5056 100644 --- a/Modules/Calcs.lua +++ b/Modules/Calcs.lua @@ -633,6 +633,7 @@ local function initEnv(build, mode) modDB:NewMod("BlockChance", "BASE", 15, "Base", { type = "Condition", var = "DualWielding" }) modDB:NewMod("LifeRegenPercent", "BASE", 4, "Base", { type = "Condition", var = "OnConsecratedGround" }) modDB:NewMod("Misc", "LIST", { type = "EnemyModifier", mod = modLib.createMod("DamageTaken", "INC", 50, "Shock") }, "Base", { type = "Condition", var = "EnemyShocked" }) + modDB:NewMod("Misc", "LIST", { type = "EnemyModifier", mod = modLib.createMod("HitChance", "MORE", -50, "Blind") }, "Base", { type = "Condition", var = "EnemyBlinded" }) -- Add bandit mods if build.banditNormal == "Alira" then @@ -678,32 +679,52 @@ local function initEnv(build, mode) end -- This function: --- 1. Merges modifiers for all items, optionally replacing one item +-- 1. Merges modifiers for all items -- 2. Builds a list of jewels with radius functions -- 3. Merges modifiers for all allocated passive nodes -- 4. Builds a list of active skills and their supports -- 5. Builds modifier lists for all active skills -local function mergeMainMods(env, repSlotName, repItem) +local function mergeMainMods(env, override) local build = env.build + override = override or { } + + -- Build list of passive nodes + local nodes + if override.addNodes or override.removeNodes then + nodes = { } + if override.addNodes then + for node in pairs(override.addNodes) do + nodes[node.id] = node + end + end + for _, node in pairs(build.spec.allocNodes) do + if not override.removeNodes or not override.removeNodes[node] then + nodes[node.id] = node + end + end + else + nodes = build.spec.allocNodes + end -- Build and merge item modifiers, and create list of radius jewels env.radiusJewelList = wipeTable(env.radiusJewelList) env.itemList = { } + env.flasks = { } env.modDB.conditions["UsingAllCorruptedItems"] = true for slotName, slot in pairs(build.itemsTab.slots) do local item - if slotName == repSlotName then - item = repItem + if slotName == override.repSlotName then + item = override.repItem else item = build.itemsTab.list[slot.selItemId] end if slot.nodeId then -- Slot is a jewel socket, check if socket is allocated - if not build.spec.allocNodes[slot.nodeId] then + if not nodes[slot.nodeId] then item = nil elseif item and item.jewelRadiusIndex then -- Jewel has a radius, add it to the list - local funcList = item.jewelFunc or { function(nodeMods, out, data) + local funcList = item.jewelFuncList or { function(nodeMods, out, data) -- Default function just tallies all stats in radius if nodeMods then for _, stat in pairs({"Str","Dex","Int"}) do @@ -727,12 +748,10 @@ local function mergeMainMods(env, repSlotName, repItem) end end if item and item.type == "Flask" then - if env.configInput["enableFlask"..slot.slotNum] then - -- FIXME dunno lol - env.modDB.conditions["UsingFlask"] = true - else - item = nil + if slot.active then + env.flasks[item] = true end + item = nil end env.itemList[slotName] = item if item then @@ -760,6 +779,14 @@ local function mergeMainMods(env, repSlotName, repItem) end end end + + if override.toggleFlask then + if env.flasks[override.toggleFlask] then + env.flasks[override.toggleFlask] = nil + else + env.flasks[override.toggleFlask] = true + end + end if env.mode == "MAIN" then -- Process extra skills granted by items @@ -844,7 +871,7 @@ local function mergeMainMods(env, repSlotName, repItem) end -- Build and merge modifiers for allocated passives - env.modDB:AddList(buildNodeModList(env, build.spec.allocNodes, true)) + env.modDB:AddList(buildNodeModList(env, nodes, true)) -- Determine main skill group if env.mode == "CALCS" then @@ -1015,6 +1042,15 @@ local function performCalcs(env) end end + -- Merge flask modifiers + if env.mode_combat then + local effectInc = modDB:Sum("INC", nil, "FlaskEffect") + for item in pairs(env.flasks) do + modDB.conditions["UsingFlask"] = true + modDB:ScaleAddList(item.modList, 1 + (effectInc + item.flaskData.effectInc) / 100) + end + end + -- Set conditions local condList = modDB.conditions if env.weaponData1.type == "Staff" then @@ -1538,7 +1574,7 @@ local function performCalcs(env) output.EvadeChance = 0 else local enemyAccuracy = round(calcVal(enemyDB, "Accuracy")) - output.EvadeChance = 100 - calcHitChance(output.Evasion, enemyAccuracy) + output.EvadeChance = 100 - calcHitChance(output.Evasion, enemyAccuracy) * calcMod(enemyDB, nil, "HitChance") if breakdown then breakdown.EvadeChance = { s_format("Enemy level: %d ^8(%s the Configuration tab)", env.enemyLevel, env.configInput.enemyLevel and "overridden from" or "can be overridden in"), @@ -2894,11 +2930,12 @@ end local calcs = { } --- Get calculator for tree node modifiers +-- Get fast calculator for adding tree node modifiers function calcs.getNodeCalculator(build) - return getCalculator(build, true, function(env, nodeList, remove) - -- Build and merge/unmerge modifiers for these nodes - local nodeModList = buildNodeModList(env, nodeList) + return getCalculator(build, true, function(env, nodeList) + -- Build and merge modifiers for these nodes + env.modDB:AddList(buildNodeModList(env, nodeList)) + --[[local nodeModList = buildNodeModList(env, nodeList) if remove then for _, mod in ipairs(nodeModList) do if mod.type == "LIST" or mod.type == "FLAG" then @@ -2916,15 +2953,14 @@ function calcs.getNodeCalculator(build) end else env.modDB:AddList(nodeModList) - end + end]] end) end --- Get calculator for item modifiers -function calcs.getItemCalculator(build) - return getCalculator(build, false, function(env, repSlotName, repItem) - -- Merge main mods, replacing the item in the given slot with the given item - mergeMainMods(env, repSlotName, repItem) +-- Get calculator for other changes (adding/removing nodes, items, gems, etc) +function calcs.getMiscCalculator(build) + return getCalculator(build, false, function(env, override) + mergeMainMods(env, override) end) end diff --git a/Modules/ItemTools.lua b/Modules/ItemTools.lua index 035bda8e..6a6727b6 100644 --- a/Modules/ItemTools.lua +++ b/Modules/ItemTools.lua @@ -450,45 +450,41 @@ function itemLib.buildItemModListForSlotNum(item, baseList, slotNum) local durationInc = sumLocal(modList, "Duration", "INC", 0) if item.base.flask.life or item.base.flask.mana then -- Recovery flask + flaskData.instantPerc = sumLocal(modList, "FlaskInstantRecovery", "BASE", 0) local recoveryMod = 1 + sumLocal(modList, "FlaskRecovery", "INC", 0) / 100 local rateMod = 1 + sumLocal(modList, "FlaskRecoveryRate", "INC", 0) / 100 - local instant = sumLocal(modList, "FlaskInstantRecovery", "BASE", 0) - local durBase = item.base.flask.duration * (1 + durationInc / 100) + flaskData.duration = item.base.flask.duration * (1 + durationInc / 100) / rateMod if item.base.flask.life then - local base = item.base.flask.life * (1 + item.quality / 100) * recoveryMod - local inst = base * instant / 100 - local grad = base * (1 - instant / 100) * (1 + durationInc / 100) - flaskData.lifeTotal = inst + grad - flaskData.lifeDuration = durBase / rateMod + flaskData.lifeBase = item.base.flask.life * (1 + item.quality / 100) * recoveryMod + flaskData.lifeInstant = flaskData.lifeBase * flaskData.instantPerc / 100 + flaskData.lifeGradual = flaskData.lifeBase * (1 - flaskData.instantPerc / 100) * (1 + durationInc / 100) + flaskData.lifeTotal = flaskData.lifeInstant + flaskData.lifeGradual end if item.base.flask.mana then - local base = item.base.flask.mana * (1 + item.quality / 100) * recoveryMod - local inst = base * instant / 100 - local grad = base * (1 - instant / 100) * (1 + durationInc / 100) - flaskData.manaTotal = inst + grad - flaskData.manaDuration = durBase / rateMod + flaskData.manaBase = item.base.flask.mana * (1 + item.quality / 100) * recoveryMod + flaskData.manaInstant = flaskData.manaBase * flaskData.instantPerc / 100 + flaskData.manaGradual = flaskData.manaBase * (1 - flaskData.instantPerc / 100) * (1 + durationInc / 100) + flaskData.manaTotal = flaskData.manaInstant + flaskData.manaGradual end else -- Utility flask - flaskData.duration = round(item.base.flask.duration * (1 + (durationInc + item.quality) / 100), 1) + flaskData.duration = item.base.flask.duration * (1 + (durationInc + item.quality) / 100) end - local extra = sumLocal(modList, "FlaskCharges", "BASE", 0) - local usedInc = sumLocal(modList, "FlaskChargesUsed", "INC", 0) - local gainedInc = sumLocal(modList, "FlaskChargeRecovery", "INC", 0) - flaskData.chargesMax = item.base.flask.chargesMax + extra - flaskData.chargesUsed = m_floor(item.base.flask.chargesUsed * (1 + usedInc / 100)) - flaskData.gainMod = 1 + gainedInc / 100 + flaskData.chargesMax = item.base.flask.chargesMax + sumLocal(modList, "FlaskCharges", "BASE", 0) + flaskData.chargesUsed = m_floor(item.base.flask.chargesUsed * (1 + sumLocal(modList, "FlaskChargesUsed", "INC", 0) / 100)) + flaskData.gainMod = 1 + sumLocal(modList, "FlaskChargeRecovery", "INC", 0) / 100 + flaskData.effectInc = sumLocal(modList, "FlaskEffect", "INC", 0) for _, value in ipairs(modList:Sum("LIST", nil, "Misc")) do if value.type == "FlaskData" then flaskData[value.key] = value.value end end elseif item.type == "Jewel" then - item.jewelFunc = nil + item.jewelFuncList = nil for _, value in ipairs(modList:Sum("LIST", nil, "Misc")) do if value.type == "JewelFunc" then - item.jewelFunc = item.jewelFunc or { } - t_insert(item.jewelFunc, value.func) + item.jewelFuncList = item.jewelFuncList or { } + t_insert(item.jewelFuncList, value.func) end end end diff --git a/Modules/Main.lua b/Modules/Main.lua index 604ed0cd..0f2ed897 100644 --- a/Modules/Main.lua +++ b/Modules/Main.lua @@ -126,7 +126,10 @@ function main:Init() self:OpenPopup(800, 250, "Update Available", { common.New("TextListControl", nil, 0, 20, 780, 190, nil, changeList), common.New("ButtonControl", nil, -45, 220, 80, 20, "Update", function() - launch:ApplyUpdate(launch.updateAvailable) + local ret = self:CallMode("CanExit", "UPDATE") + if ret == nil or ret == true then + launch:ApplyUpdate(launch.updateAvailable) + end main:ClosePopup() end), common.New("ButtonControl", nil, 45, 220, 80, 20, "Cancel", function() @@ -204,7 +207,7 @@ function main:Init() end function main:CanExit() - local ret = self:CallMode("CanExit") + local ret = self:CallMode("CanExit", "EXIT") if ret ~= nil then return ret else diff --git a/Modules/ModParser.lua b/Modules/ModParser.lua index d65ce81e..6bc95931 100644 --- a/Modules/ModParser.lua +++ b/Modules/ModParser.lua @@ -111,6 +111,7 @@ local modNameList = { -- Stun modifiers ["stun recovery"] = "StunRecovery", ["stun and block recovery"] = "StunRecovery", + ["block and stun recovery"] = "StunRecovery", ["stun threshold"] = "StunThreshold", ["block recovery"] = "BlockRecovery", ["enemy stun threshold"] = "EnemyStunThreshold", @@ -236,6 +237,8 @@ local modNameList = { ["effect"] = "FlaskEffect", ["effect of flasks"] = "FlaskEffect", ["amount recovered"] = "FlaskRecovery", + ["life recovered"] = "FlaskRecovery", + ["mana recovered"] = "FlaskRecovery", ["life recovery from flasks"] = "FlaskLifeRecovery", ["mana recovery from flasks"] = "FlaskManaRecovery", ["flask effect duration"] = "FlaskDuration", @@ -397,10 +400,13 @@ local modTagList = { ["if you've crit recently"] = { tag = { type = "Condition", var = "CritRecently" } }, ["if you've dealt a critical strike recently"] = { tag = { type = "Condition", var = "CritRecently" } }, ["if you haven't crit recently"] = { tag = { type = "Condition", var = "CritRecently", neg = true } }, + ["if you've dealt a non%-critical strike recently"] = { tag = { type = "Condition", var = "NonCritRecently" } }, ["if you've killed recently"] = { tag = { type = "Condition", var = "KilledRecently" } }, ["if you haven't killed recently"] = { tag = { type = "Condition", var = "KilledRecently", neg = true } }, ["if you or your totems have killed recently"] = { tag = { type = "Condition", varList = {"KilledRecently","TotemsKilledRecently"} } }, ["if you've killed a maimed enemy recently"] = { tagList = { { type = "Condition", var = "KilledRecently" }, { type = "Condition", var = "EnemyMaimed" } } }, + ["if you've frozen an enemy recently"] = { tag = { type = "Condition", var = "FrozenEnemyRecently" } }, + ["if you've ignited an enemy recently"] = { tag = { type = "Condition", var = "IgnitedEnemyRecently" } }, ["if you've been hit recently"] = { tag = { type = "Condition", var = "BeenHitRecently" } }, ["if you were hit recently"] = { tag = { type = "Condition", var = "BeenHitRecently" } }, ["if you were damaged by a hit recently"] = { tag = { type = "Condition", var = "BeenHitRecently" } }, @@ -428,6 +434,7 @@ local modTagList = { ["against bleeding enemies"] = { tag = { type = "Condition", var = "EnemyBleeding" }, flags = ModFlag.Hit }, ["against poisoned enemies"] = { tag = { type = "Condition", var = "EnemyPoisoned" }, flags = ModFlag.Hit }, ["against hindered enemies"] = { tag = { type = "Condition", var = "EnemyHindered" }, flags = ModFlag.Hit }, + ["against blinded enemies"] = { tag = { type = "Condition", var = "EnemyBlinded" }, flags = ModFlag.Hit }, ["against burning enemies"] = { tag = { type = "Condition", var = "EnemyBurning" }, flags = ModFlag.Hit }, ["against ignited enemies"] = { tag = { type = "Condition", var = "EnemyIgnited" }, flags = ModFlag.Hit }, ["against shocked enemies"] = { tag = { type = "Condition", var = "EnemyShocked" }, flags = ModFlag.Hit }, @@ -541,6 +548,9 @@ local specialModList = { ["your critical strike chance is lucky"] = { flag("CritChanceLucky") }, ["phasing"] = { mod("Misc", "LIST", { type = "Condition", var = "Phasing" }) }, ["onslaught"] = { mod("Misc", "LIST", { type = "Condition", var = "Onslaught" }) }, + ["creates a smoke cloud on use"] = { }, + ["creates chilled ground on use"] = { }, + ["creates consecrated ground on use"] = { }, -- Special item local modifiers ["no physical damage"] = { mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalMin" }), mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalMax" }), mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalDPS" }) }, ["all attacks with this weapon are critical strikes"] = { mod("Misc", "LIST", { type = "WeaponData", key = "critChance", value = 100 }) }, @@ -622,6 +632,7 @@ local specialModList = { ["non%-critical strikes deal (%d+)%% damage"] = function(num) return { mod("Damage", "MORE", -100+num, nil, ModFlag.Hit, { type = "Condition", var = "CriticalStrike", neg = true }) } end, ["ignited enemies burn (%d+)%% faster"] = function(num) return { mod("IgniteBurnRate", "INC", num) } end, ["enemies ignited by an attack burn (%d+)%% faster"] = function(num) return { mod("IgniteBurnRate", "INC", num, nil, ModFlag.Attack) } end, + ["gain unholy might during flask effect"] = { mod("Misc", "LIST", { type = "Condition", var = "UnholyMight" }, { type = "Condition", var = "UsingFlask" }) }, } local keystoneList = { -- List of keystones that can be found on uniques diff --git a/README.md b/README.md index c09655f9..bfb38659 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,11 @@ Head over to the [Releases](https://github.com/Openarl/PathOfBuilding/releases) ![ss3](https://cloud.githubusercontent.com/assets/19189971/18089780/f0ff234a-6f04-11e6-8c88-6193fe59a5c4.png) ## Changelog +### 1.2.41 - 2017/02/13 + * The program now shows the save prompt before updating if there are unsaved changes + * Added options to the Configuration tab for: Enemy Blinded, Dealt Non-Crit Recently, Ignited/Frozen an Enemy Recently + * Stat differences for allocating/deallocating passives will no longer be incorrect when certain radius jewels are used + ### 1.2.40 - 2017/02/11 * Movement Speed is now calculated and displayed in the sidebar and Calcs tab (in Other Defences) * Fixed display issue in the breakdown for ignite DPS @@ -436,7 +441,7 @@ Other changes: * More updates to 2.4.0 uniques * Re-nerfed Voidheart * Hypothermia now correctly affects hits only and not damage over time - * Fixed gems sometimes appearing to be deleted when another gem in the same socketGroup was removed + * Fixed gems sometimes appearing to be deleted when another gem in the same socket group was removed * Added flat elemental damage to ring, amulet and glove templates ### 1.0.25 - 2016/09/06 diff --git a/changelog.txt b/changelog.txt index cb9abbba..4393e017 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +VERSION[1.2.41][2017/02/12] + * The program now shows the save prompt before updating if there are unsaved changes + * Added options to the Configuration tab for: Enemy Blinded, Dealt Non-Crit Recently, Ignited/Frozen an Enemy Recently + * Stat differences for allocating/deallocating passives will no longer be incorrect when certain radius jewels are used VERSION[1.2.40][2017/02/11] * Movement Speed is now calculated and displayed in the sidebar and Calcs tab (in Other Defences) * Fixed display issue in the breakdown for ignite DPS @@ -330,7 +334,7 @@ VERSION[1.0.26][2016/09/09] * More updates to 2.4.0 uniques * Re-nerfed Voidheart * Hypothermia now correctly affects hits only and not damage over time - * Fixed gems sometimes appearing to be deleted when another gem in the same socketGroup was removed + * Fixed gems sometimes appearing to be deleted when another gem in the same socket group was removed * Added flat elemental damage to ring, amulet and glove templates VERSION[1.0.25][2016/09/06] * More updates to 2.4.0 uniques diff --git a/manifest.xml b/manifest.xml index ec9f73dc..f8000f93 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,37 +1,37 @@ - + - + - + - + - + - + - - + + - + @@ -42,15 +42,15 @@ - + - + - - - + + + @@ -90,7 +90,7 @@ - +