diff --git a/Classes/ConfigTab.lua b/Classes/ConfigTab.lua index 78a72cb92..edee53420 100644 --- a/Classes/ConfigTab.lua +++ b/Classes/ConfigTab.lua @@ -112,6 +112,9 @@ local varList = { { var = "conditionEnemyShocked", type = "check", label = "Is the enemy Shocked?", tooltip = "In addition to allowing any 'against Shocked Enemies' modifiers to apply,\nthis will apply Shock's Damage Taken modifier to the enemy.", apply = function(val, modList, enemyModList) modList:NewMod("Misc", "LIST", { type = "Condition", var = "EnemyShocked" }, "Config", { type = "Condition", var = "Effective" }) end }, + { var = "conditionEnemyIntimidated", type = "check", label = "Is the enemy Intimidated?", tooltip = "This adds the following modifiers:\n10% increased Damage Taken by enemy", apply = function(val, modList, enemyModList) + enemyModList:NewMod("DamageTaken", "INC", 10, "Intimidate") + end }, { var = "conditionEnemyCoveredInAsh", type = "check", label = "Is the enemy covered in Ash?", tooltip = "This adds the following modifiers:\n20% less enemy Movement Speed\n20% increased Fire Damage Taken by enemy", apply = function(val, modList, enemyModList) enemyModList:NewMod("FireDamageTaken", "INC", 20, "Ash") end }, diff --git a/Classes/PassiveTreeView.lua b/Classes/PassiveTreeView.lua index bbe8c98d7..81cc5c4fa 100644 --- a/Classes/PassiveTreeView.lua +++ b/Classes/PassiveTreeView.lua @@ -425,7 +425,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) DrawImage(self.highlightRing, scrX - size, scrY - size, size * 2, size * 2) SetDrawLayer(nil, 0) end - if node == hoverNode and (node.type ~= "socket" or not IsKeyDown("SHIFT") or self.traceMode) then + if node == hoverNode and (node.type ~= "socket" or not IsKeyDown("SHIFT")) then -- Draw tooltip SetDrawLayer(nil, 10) local size = m_floor(hoverNode.size * scale) @@ -527,10 +527,11 @@ function PassiveTreeViewClass:AddNodeTooltip(node, build) else main:AddTooltipLine(24, "^7"..node.dn..(launch.devMode and IsKeyDown("ALT") and " ["..node.id.."]" or "")) end + main:AddTooltipSeparator(14) if socket:IsEnabled() then - main:AddTooltipSeparator(14) main:AddTooltipLine(14, "^x80A080Tip: Right click this socket to go to the items page and choose the jewel for this socket.") end + main:AddTooltipLine(14, "^x80A080Tip: Hold Shift to hide this tooltip.") return end @@ -604,8 +605,8 @@ function PassiveTreeViewClass:AddNodeTooltip(node, build) end -- Pathing distance + main:AddTooltipSeparator(14) if node.path and #node.path > 0 then - main:AddTooltipSeparator(14) if self.traceMode and isValueInArray(self.tracePath, node) then main:AddTooltipLine(14, "^7"..#self.tracePath .. " nodes in trace path") else @@ -617,6 +618,9 @@ function PassiveTreeViewClass:AddNodeTooltip(node, build) end end end + if node.type == "socket" then + main:AddTooltipLine(14, "^x80A080Tip: Hold Shift to hide this tooltip.") + end if node.depends and #node.depends > 1 then main:AddTooltipSeparator(14) main:AddTooltipLine(14, "^7"..#node.depends .. " points gained from unallocating these nodes") diff --git a/Data/Gems/sup_int.lua b/Data/Gems/sup_int.lua index 078dfd0e9..2eb09c3f2 100644 --- a/Data/Gems/sup_int.lua +++ b/Data/Gems/sup_int.lua @@ -228,40 +228,40 @@ gems["Cast while Channelling"] = { mod("Damage", "INC", 0.5, 0, 0, nil), --"damage_+%" = 0.5 }, levelMods = { - --[1] = "cast_while_channelling_time_ms" + [1] = skill("timeOverride", nil, { type = "SkillType", skillType = SkillType.TriggerableSpell }), --"cast_while_channelling_time_ms" [2] = mod("Damage", "MORE", nil, 0, 0, { type = "SkillType", skillType = SkillType.TriggerableSpell }), --"support_cast_while_channelling_triggered_skill_damage_+%_final" }, levels = { - [1] = { 450, 0, }, - [2] = { 440, 0, }, - [3] = { 440, 1, }, - [4] = { 430, 1, }, - [5] = { 430, 2, }, - [6] = { 420, 2, }, - [7] = { 420, 3, }, - [8] = { 410, 3, }, - [9] = { 410, 4, }, - [10] = { 400, 4, }, - [11] = { 400, 5, }, - [12] = { 390, 5, }, - [13] = { 390, 6, }, - [14] = { 380, 6, }, - [15] = { 380, 7, }, - [16] = { 370, 7, }, - [17] = { 370, 8, }, - [18] = { 360, 8, }, - [19] = { 360, 9, }, - [20] = { 350, 9, }, - [21] = { 350, 10, }, - [22] = { 340, 10, }, - [23] = { 340, 11, }, - [24] = { 330, 11, }, - [25] = { 330, 12, }, - [26] = { 320, 12, }, - [27] = { 320, 13, }, - [28] = { 310, 13, }, - [29] = { 310, 14, }, - [30] = { 300, 14, }, + [1] = { 0.45, 0, }, + [2] = { 0.44, 0, }, + [3] = { 0.44, 1, }, + [4] = { 0.43, 1, }, + [5] = { 0.43, 2, }, + [6] = { 0.42, 2, }, + [7] = { 0.42, 3, }, + [8] = { 0.41, 3, }, + [9] = { 0.41, 4, }, + [10] = { 0.4, 4, }, + [11] = { 0.4, 5, }, + [12] = { 0.39, 5, }, + [13] = { 0.39, 6, }, + [14] = { 0.38, 6, }, + [15] = { 0.38, 7, }, + [16] = { 0.37, 7, }, + [17] = { 0.37, 8, }, + [18] = { 0.36, 8, }, + [19] = { 0.36, 9, }, + [20] = { 0.35, 9, }, + [21] = { 0.35, 10, }, + [22] = { 0.34, 10, }, + [23] = { 0.34, 11, }, + [24] = { 0.33, 11, }, + [25] = { 0.33, 12, }, + [26] = { 0.32, 12, }, + [27] = { 0.32, 13, }, + [28] = { 0.31, 13, }, + [29] = { 0.31, 14, }, + [30] = { 0.3, 14, }, }, } gems["Chance to Ignite"] = { diff --git a/Data/New.lua b/Data/New.lua index c127885fe..dc1bbbe25 100644 --- a/Data/New.lua +++ b/Data/New.lua @@ -579,6 +579,7 @@ You can only Socket Corrupted Gems in this item {variant:19}Unwavering Stance {variant:20}Vaal Pact {variant:21}Zealot's Oath +Corrupted ]],[[ The Red Dream Crimson Jewel diff --git a/Modules/Calcs.lua b/Modules/Calcs.lua index ca380f0a0..380707a8a 100644 --- a/Modules/Calcs.lua +++ b/Modules/Calcs.lua @@ -1818,20 +1818,25 @@ local function performCalcs(env) -- Calculate attack/cast speed do local baseSpeed - if isAttack then - if skillData.castTimeOverridesAttackTime then - -- Skill is overriding weapon attack speed - baseSpeed = 1 / skillData.castTime * (1 + (env.weaponData1.AttackSpeedInc or 0) / 100) + if skillData.timeOverride then + output.Time = skillData.timeOverride + output.Speed = 1 / output.Time + else + if isAttack then + if skillData.castTimeOverridesAttackTime then + -- Skill is overriding weapon attack speed + baseSpeed = 1 / skillData.castTime * (1 + (env.weaponData1.AttackSpeedInc or 0) / 100) + else + baseSpeed = env.weaponData1.attackRate or 1 + end else - baseSpeed = env.weaponData1.attackRate or 1 + baseSpeed = 1 / (skillData.castTime or 1) + end + output.Speed = baseSpeed * calcMod(modDB, skillCfg, "Speed") + output.Time = 1 / output.Speed + if breakdown then + simpleBreakdown(baseSpeed, skillCfg, "Speed") end - else - baseSpeed = 1 / (skillData.castTime or 1) - end - output.Speed = baseSpeed * calcMod(modDB, skillCfg, "Speed") - output.Time = 1 / output.Speed - if breakdown then - simpleBreakdown(baseSpeed, skillCfg, "Speed") end end @@ -1992,7 +1997,7 @@ local function performCalcs(env) output.TotalMax = totalMax -- Update enemy hit-by-damage-type conditions - enemyDB.conditions.HitByFireDamage = output.FireAverage > 0 + enemyDB.conditions.HitByFireDamage = output.FireAverage > 0 enemyDB.conditions.HitByColdDamage = output.ColdAverage > 0 enemyDB.conditions.HitByLightningDamage = output.LightningAverage > 0 @@ -2150,7 +2155,7 @@ local function performCalcs(env) if output.CritEffect ~= 1 then t_insert(breakdown.BleedDPS, s_format("x %.3f ^8(crit effect modifier)", output.CritEffect)) end - t_insert(breakdown.BleedDPS, "x 0.2 ^8(bleed deals 20% per second)") + t_insert(breakdown.BleedDPS, "x 0.1 ^8(bleed deals 10% per second)") t_insert(breakdown.BleedDPS, s_format("= %.1f", baseVal, 1)) t_insert(breakdown.BleedDPS, "Bleed DPS:") dotBreakdown(breakdown.BleedDPS, baseVal, inc, more, effMult, output.BleedDPS) @@ -2567,7 +2572,7 @@ function calcs.buildOutput(build, mode) output.CombatList = table.concat(combatList, ", ") output.CurseList = table.concat(curseList, ", ") - infoDump(env) + --infoDump(env) end return env diff --git a/Modules/Common.lua b/Modules/Common.lua index 69d3da681..8ae71ae69 100644 --- a/Modules/Common.lua +++ b/Modules/Common.lua @@ -15,7 +15,7 @@ local s_format = string.format common = { } -- External libraries -common.curl = require("lcurl") +common.curl = require("lcurl.safe") common.xml = require("xml") common.base64 = require("base64") diff --git a/Modules/ItemTools.lua b/Modules/ItemTools.lua index 4ded54c87..ff9d80875 100644 --- a/Modules/ItemTools.lua +++ b/Modules/ItemTools.lua @@ -356,6 +356,8 @@ function itemLib.buildItemModListForSlotNum(item, baseList, slotNum) end elseif tag.type == "SocketedIn" then tag.slotName = slotName + elseif tag.type == "Condition" and tag.var == "XHandAttack" then + tag.var = (slotNum == 1) and "MainHandAttack" or "OffHandAttack" end end if add then diff --git a/Modules/ModParser.lua b/Modules/ModParser.lua index e416cd164..7c6b21e04 100644 --- a/Modules/ModParser.lua +++ b/Modules/ModParser.lua @@ -20,7 +20,7 @@ local formList = { ["^([%+%-][%d%.]+)%%?"] = "BASE", ["^([%+%-][%d%.]+)%%? to"] = "BASE", ["^([%+%-][%d%.]+)%%? base"] = "BASE", - ["^([%+%-]?[%d%.]+)%% additional"] = "BASE", + ["^([%+%-]?[%d%.]+)%%? additional"] = "BASE", ["^you gain ([%d%.]+)"] = "BASE", ["^([%+%-]?%d+)%% chance"] = "CHANCE", ["^([%+%-]?%d+)%% additional chance"] = "CHANCE", @@ -145,6 +145,8 @@ local modNameList = { ["energy shield gained for each enemy hit by your attacks"] = { "EnergyShieldOnHit", flags = ModFlag.Attack }, ["life and mana gained for each enemy hit"] = { "LifeOnHit", "ManaOnHit", flags = ModFlag.Attack }, -- Projectile modifiers + ["projectile"] = "ProjectileCount", + ["projectiles"] = "ProjectileCount", ["pierce chance"] = "PierceChance", ["of projectiles piercing"] = "PierceChance", ["of arrows piercing"] = { "PierceChance", flags = ModFlag.Bow }, @@ -187,6 +189,8 @@ local modNameList = { ["physical weapon damage"] = { "PhysicalDamage", flags = ModFlag.Weapon }, ["physical melee damage"] = { "PhysicalDamage", flags = ModFlag.Melee }, ["melee physical damage"] = { "PhysicalDamage", flags = ModFlag.Melee }, + ["projectile damage"] = { "Damage", flags = ModFlag.Projectile }, + ["projectile attack damage"] = { "Damage", flags = bor(ModFlag.Projectile, ModFlag.Attack) }, ["bow damage"] = { "Damage", flags = ModFlag.Bow }, ["wand damage"] = { "Damage", flags = ModFlag.Wand }, ["wand physical damage"] = { "PhysicalDamage", flags = ModFlag.Wand }, @@ -194,7 +198,6 @@ local modNameList = { ["damage over time"] = { "Damage", flags = ModFlag.Dot }, ["physical damage over time"] = { "PhysicalDamage", flags = ModFlag.Dot }, ["burning damage"] = { "FireDamage", flags = ModFlag.Dot }, - ["righteous fire damage"] = { "Damage", tag = { type = "SkillName", skillName = "Righteous Fire" } }, -- Parser mis-interprets this one (Righteous/Fire Damage instead of Righteous Fire/Damage) -- Crit/accuracy/speed modifiers ["critical strike chance"] = "CritChance", ["critical strike multiplier"] = "CritMultiplier", @@ -257,7 +260,6 @@ local modFlagList = { ["with melee attacks"] = { flags = ModFlag.Melee }, ["on melee hit"] = { flags = ModFlag.Melee }, ["with poison"] = { keywordFlags = KeywordFlag.Poison }, - ["projectile"] = { flags = ModFlag.Projectile }, ["area"] = { flags = ModFlag.Area }, ["mine"] = { keywordFlags = KeywordFlag.Mine }, ["with mines"] = { keywordFlags = KeywordFlag.Mine }, @@ -290,6 +292,8 @@ local preFlagList = { ["^minions deal "] = { keywordFlags = KeywordFlag.Minion }, ["^attacks used by totems have "] = { keywordFlags = KeywordFlag.Totem }, ["^spells cast by totems have "] = { keywordFlags = KeywordFlag.Totem }, + ["^attacks with this weapon "] = { tag = { type = "Condition", var = "XHandAttack" } }, + ["^attacks with this weapon have "] = { tag = { type = "Condition", var = "XHandAttack" } }, ["^attacks have "] = { flags = ModFlag.Attack }, ["^melee attacks have "] = { flags = ModFlag.Melee }, ["^left ring slot: "] = { tag = { type = "SlotNumber", num = 1 } }, @@ -343,6 +347,7 @@ local modTagList = { ["if all worn items are corrupted"] = { tag = { type = "Condition", var = "UsingAllCorruptedItems" } }, ["with main hand"] = { tag = { type = "Condition", var = "MainHandAttack" } }, ["with off hand"] = { tag = { type = "Condition", var = "OffHandAttack" } }, + ["with this weapon"] = { tag = { type = "Condition", var = "XHandAttack" } }, -- The X is replaced when the item modifiers are generated -- Player status conditions ["when on low life"] = { tag = { type = "Condition", var = "LowLife" } }, ["while on low life"] = { tag = { type = "Condition", var = "LowLife" } }, @@ -558,7 +563,8 @@ local specialModList = { ["critical strike chance is increased by uncapped lightning resistance"] = { mod("CritChance", "INC", 1, { type = "PerStat", stat = "LightningResistTotal", div = 1 }) }, ["critical strikes deal no damage"] = { flag("NoCritDamage") }, ["enemies chilled by you take (%d+)%% increased burning damage"] = function(num) return { mod("Misc", "LIST", { type = "EnemyModifier", mod = mod("BurningDamageTaken", "INC", num) }, { type = "Condition", var = "EnemyChilled" }) } end, - ["attacks with this weapon penetrate (%d+)%% elemental resistances"] = function(num) return { mod("ElementalPenetration", "BASE", num, nil, ModFlag.Weapon) } end, + ["attacks with this weapon penetrate (%d+)%% elemental resistances"] = function(num) return { mod("ElementalPenetration", "BASE", num, { type = "Condition", var = "XHandAttack" }) } end, + ["attacks with this weapon deal double damage to chilled enemies"] = { mod("Damage", "MORE", 100, nil, ModFlag.Hit, { type = "Condition", var = "XHandAttack" }, { type = "Condition", var = "EnemyChilled" }) }, ["(%d+)%% of maximum life converted to energy shield"] = function(num) return { mod("LifeConvertToEnergyShield", "BASE", num) } end, } local keystoneList = { @@ -641,10 +647,11 @@ end local function getSimpleConv(src, dst, type, factor) return function(nodeMods, out, data) if nodeMods then - local nodeVal = nodeMods:Sum(type, nil, src) - if nodeVal ~= 0 then - out:NewMod(src, type, -nodeVal, "Tree:Jewel") - out:NewMod(dst, type, nodeVal * factor, "Tree:Jewel") + for _, mod in ipairs(nodeMods) do + if mod.name == src and mod.type == type then + out:NewMod(src, type, -mod.value, "Tree:Jewel", mod.flags, mod.keywordFlags, unpack(mod.tagList)) + out:NewMod(dst, type, mod.value * factor, "Tree:Jewel", mod.flags, mod.keywordFlags, unpack(mod.tagList)) + end end end end @@ -762,7 +769,7 @@ local function scan(line, patternList, plain) return bestMatch[1], bestMatch[2], bestMatch[3] end -local function parseMod(line) +local function parseMod(line, order) -- Check if this is a special modifier local specialMod, specialLine, cap = scan(line, specialModList) if specialMod and #specialLine == 0 then @@ -803,14 +810,16 @@ local function parseMod(line) end end - -- Scan for modifier name - local modName - modName, line = scan(line, modNameList, true) - - -- Scan for skill name - local skillTag + -- Scan for modifier name and skill name + local modName, skillTag + if order == 1 then + modName, line = scan(line, modNameList, true) + end skillTag, line = scan(line, skillNameList, true) - + if order == 2 then + modName, line = scan(line, modNameList, true) + end + -- Scan for flags if one hasn't been found already if not modFlag then modFlag, line = scan(line, modFlagList, true) @@ -917,7 +926,11 @@ local unsupported = { } local count = 0 return function(line) if not cache[line] then - cache[line] = { parseMod(line) } + local modList, extra = parseMod(line, 1) + if modList and extra then + modList, extra = parseMod(line, 2) + end + cache[line] = { modList, extra } --[[if not cache[line][1] then local form = line:gsub("[%+%-]?%d+%.?%d*","{num}") if not unsupported[form] then diff --git a/README.md b/README.md index dfef1f953..908533875 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,8 @@ Welcome to Path of Building, an offline build planner for Path of Exile! * Also calculates life/mana reservations * Shows a summary of character stats in the side bar, as well as a detailed calcs breakdown tab which can show you how the stats were derived * Supports most skills, support gems, passives and item modifiers - * Throughout the program, supported modifiers will show in blue and unsupported ones in white + * Throughout the program, supported modifiers will show in blue and unsupported ones in red * Most minion skill are unsupported at present (except for golems, which can provide buffs to you) - * Trigger gems are generally unsupported (Cast on Crit, etc) * No support for flasks yet * Passive skill tree planner: * Support for jewels including most radius/conversion jewels @@ -49,6 +48,18 @@ 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.27 - 2016/12/21 + * Cast when Channelling now overrides the cast rate of the triggered skill, allowing the DPS of that skill + to be calculated correctly + * Added an option to the Configuration tab to enable the Intimidate debuff on the enemy + * Jewel tooltips on the passive tree can now be hidden by holding Shift + * Corrected a display issue in the breakdown for Bleed that showed the wrong percentage of base damage + * Energised Armour now correctly converts the ES-from-Shield node in the Mind Barrier cluster + * Many skill-specific modifiers (such as helmet enchants) that weren't previously recognised should now be working + * New installer versions are available, and are recommended if you need to install the program again + * The new standalone install no longer forces an update check when run for the first time, and will never ask for + administrator privileges to update itself (as currently happens when certain files need to be updated) + ### 1.2.26 - 2016/12/14 * The sidebar now displays a DPS or Average Hit total that factors in Poison * Added support for the Bone Nova skill granted by Uul-Netol's Embrace diff --git a/changelog.txt b/changelog.txt index a697dbfe1..2570fa7b5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,14 @@ +VERSION[1.2.27][2016/12/21] + * Cast when Channelling now overrides the cast rate of the triggered skill, allowing the DPS of that skill + to be calculated correctly + * Added an option to the Configuration tab to enable the Intimidate debuff on the enemy + * Jewel tooltips on the passive tree can now be hidden by holding Shift + * Corrected a display issue in the breakdown for Bleed that showed the wrong percentage of base damage + * Energised Armour now correctly converts the ES-from-Shield node in the Mind Barrier cluster + * Many skill-specific modifiers (such as helmet enchants) that weren't previously recognised should now be working + * New installer versions are available, and are recommended if you need to install the program again + * The new standalone install no longer forces an update check when run for the first time, and will never ask for + administrator privileges to update itself (as currently happens when certain files need to be updated) VERSION[1.2.26][2016/12/14] * The sidebar now displays a DPS or Average Hit total that factors in Poison * Added support for the Bone Nova skill granted by Uul-Netol's Embrace diff --git a/manifest.xml b/manifest.xml index 584c92e87..50235bb47 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,20 +1,20 @@ - + - + - + @@ -31,7 +31,7 @@ - + @@ -44,24 +44,24 @@ - + - + - + - + - + - + @@ -99,9 +99,9 @@ - + - + @@ -138,7 +138,7 @@ - + diff --git a/runtime-win32.zip b/runtime-win32.zip index 3a68c12bd..20a3eba78 100644 Binary files a/runtime-win32.zip and b/runtime-win32.zip differ diff --git a/tree.zip b/tree.zip index 4ae434265..fe08c5159 100644 Binary files a/tree.zip and b/tree.zip differ