diff --git a/Classes/ConfigTab.lua b/Classes/ConfigTab.lua index edee5342..2f6ceaf7 100644 --- a/Classes/ConfigTab.lua +++ b/Classes/ConfigTab.lua @@ -17,6 +17,7 @@ local varList = { { var = "conditionFullLife", type = "check", label = "Are you always on Full Life?", tooltip = "You will automatically be considered to be on Full Life if you have Chaos Innoculation,\nbut you can use this option to force it if necessary.", apply = function(val, modList, enemyModList) modList:NewMod("Misc", "LIST", { type = "Condition", var = "FullLife" }, "Config") end }, + { var = "igniteMode", type = "list", label = "Ignite calculation mode:", tooltip = "Controls how the base damage for ignite is calculated:\nAverage Damage: Ignite is based on the average damage dealt, factoring in crits and non-crits.\nCrit Damage: Ignite is based on crit damage only.", list = {{val="AVERAGE",label="Average Damage"},{val="CRIT",label="Crit Damage"}} }, { section = "When In Combat" }, { var = "usePowerCharges", type = "check", label = "Do you use Power Charges?" }, { var = "useFrenzyCharges", type = "check", label = "Do you use Frenzy Charges?" }, @@ -166,7 +167,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, 300, 0, varData.section) + lastSection = common.New("SectionControl", {"TOPLEFT",self,"TOPLEFT"}, 0, 0, 350, 0, varData.section) lastSection.varControlList = { } lastSection.height = function(self) local height = 20 @@ -195,6 +196,13 @@ local ConfigTabClass = common.NewClass("ConfigTab", "UndoHandler", "ControlHost" self:BuildModList() self.build.buildFlag = true end) + elseif varData.type == "list" then + control = common.New("DropDownControl", {"TOPLEFT",lastSection,"TOPLEFT"}, 216, 0, 126, 16, varData.list, function(sel, selVal) + self.input[varData.var] = selVal.val + self:AddUndoState() + self:BuildModList() + self.build.buildFlag = true + end) end if varData.ifNode then control.shown = function() @@ -206,7 +214,7 @@ local ConfigTabClass = common.NewClass("ConfigTab", "UndoHandler", "ControlHost" else control.tooltip = varData.tooltip end - t_insert(self.controls, common.New("LabelControl", {"RIGHT",control,"LEFT"}, -4, 2, 0, 14, "^7"..varData.label)) + t_insert(self.controls, common.New("LabelControl", {"RIGHT",control,"LEFT"}, -4, 0, 0, 14, "^7"..varData.label)) self.varControls[varData.var] = control t_insert(self.controls, control) t_insert(lastSection.varControlList, control) @@ -259,6 +267,8 @@ function ConfigTabClass:UpdateControls() control:SetText(tostring(self.input[var] or "")) elseif control._className == "CheckBoxControl" then control.state = self.input[var] + elseif control._className == "DropDownControl" then + control:SelByValue(self.input[var]) end end end @@ -288,7 +298,8 @@ function ConfigTabClass:Draw(viewPort, inputEvents) local y = 14 for _, varControl in ipairs(section.varControlList) do if varControl:IsShown() then - varControl.y = y + local width, height = varControl:GetSize() + varControl.y = y + (18 - height) / 2 y = y + 20 end end @@ -301,7 +312,7 @@ function ConfigTabClass:Draw(viewPort, inputEvents) end col = col + 1 end - section.x = 10 + (col - 1) * 310 + section.x = 10 + (col - 1) * 360 section.y = colY[col] colY[col] = colY[col] + height + 18 end diff --git a/Data/Gems/act_dex.lua b/Data/Gems/act_dex.lua index 0b95b1c3..6e5217a2 100644 --- a/Data/Gems/act_dex.lua +++ b/Data/Gems/act_dex.lua @@ -278,6 +278,20 @@ gems["Blade Vortex"] = { spell = true, area = true, duration = true, + parts = { + { + name = "0 Blades", + }, + { + name = "5 Blades", + }, + { + name = "10 Blades", + }, + { + name = "20 Blades", + }, + }, color = 2, baseFlags = { spell = true, @@ -298,8 +312,15 @@ gems["Blade Vortex"] = { --"is_area_damage" = ? --"skill_can_add_multiple_charges_per_action" = ? --"action_ignores_crit_tracking" = ? - skill("showAverage", true), --"base_skill_show_average_damage_instead_of_dps" = ? + nil, --"base_skill_show_average_damage_instead_of_dps" = ? skill("deliciouslyOverpowered", true), + mod("Damage", "MORE", 150, ModFlag.Spell, 0, { type = "SkillPart", skillPart = 2 }), + mod("Damage", "MORE", 300, ModFlag.Spell, 0, { type = "SkillPart", skillPart = 3 }), + mod("Damage", "MORE", 600, ModFlag.Spell, 0, { type = "SkillPart", skillPart = 4 }), + skill("hitTimeOverride", 0.6, { type = "SkillPart", skillPart = 1 }), + skill("hitTimeOverride", 0.4, { type = "SkillPart", skillPart = 2 }), + skill("hitTimeOverride", 0.3, { type = "SkillPart", skillPart = 3 }), + skill("hitTimeOverride", 0.2, { type = "SkillPart", skillPart = 4 }), }, qualityMods = { mod("AreaRadius", "INC", 0.5), --"base_skill_area_of_effect_+%" = 0.5 diff --git a/Modules/Build.lua b/Modules/Build.lua index 0c14ecbc..3423adbf 100644 --- a/Modules/Build.lua +++ b/Modules/Build.lua @@ -228,6 +228,7 @@ function buildMode:Init(dbFileName, buildName) { mod = "AverageHit", label = "Average Hit", fmt = ".1f", compPercent = true }, { mod = "Speed", label = "Attack Rate", fmt = ".2f", compPercent = true, flag = "attack" }, { mod = "Speed", label = "Cast Rate", fmt = ".2f", compPercent = true, flag = "spell" }, + { mod = "HitSpeed", label = "Hit Rate", fmt = ".2f" }, { mod = "CritChance", label = "Crit Chance", fmt = ".2f%%" }, { mod = "CritMultiplier", label = "Crit Multiplier", fmt = "d%%", pc = true, condFunc = function(v,o) return o.CritChance > 0 end }, { mod = "HitChance", label = "Hit Chance", fmt = "d%%", flag = "attack" }, diff --git a/Modules/CalcSections.lua b/Modules/CalcSections.lua index af6a3150..3021b3b2 100644 --- a/Modules/CalcSections.lua +++ b/Modules/CalcSections.lua @@ -77,10 +77,10 @@ return { }, { label = "Hit Damage", textSize = 12, { format = "{0:output:TotalMin} to {0:output:TotalMax}", }, - { format = "{0:output:PhysicalMin} to {0:output:PhysicalMax}", { breakdown = "Physical" }, { label = "Conversions", modName = { "SkillPhysicalDamageConvertToLightning", "SkillPhysicalDamageConvertToCold", "SkillPhysicalDamageConvertToFire", "SkillPhysicalDamageConvertToChaos", "PhysicalDamageConvertToLightning", "PhysicalDamageConvertToCold", "PhysicalDamageConvertToFire", "PhysicalDamageConvertToChaos", "PhysicalDamageGainAsLightning", "PhysicalDamageGainAsCold", "PhysicalDamageGainAsFire", "PhysicalDamageGainAsChaos" }, modType = "BASE", skill = true }, }, - { format = "{0:output:LightningMin} to {0:output:LightningMax}", { breakdown = "Lightning" }, { label = "Conversions", modName = { "LightningDamageConvertToCold", "LightningDamageConvertToFire", "LightningDamageConvertToChaos", "LightningDamageGainAsCold", "LightningDamageGainAsFire", "LightningDamageGainAsChaos" }, modType = "BASE", skill = true }, }, - { format = "{0:output:ColdMin} to {0:output:ColdMax}", { breakdown = "Cold" }, { label = "Conversions", modName = { "SkillColdDamageConvertToFire", "ColdDamageConvertToFire", "ColdDamageConvertToChaos", "ColdDamageGainAsFire", "ColdDamageGainAsChaos" }, modType = "BASE", skill = true }, }, - { format = "{0:output:FireMin} to {0:output:FireMax}", { breakdown = "Fire" }, { label = "Conversions", modName = { "FireDamageConvertToChaos", "FireDamageGainAsChaos" }, modType = "BASE", skill = true }, }, + { format = "{0:output:PhysicalMin} to {0:output:PhysicalMax}", { breakdown = "Physical" }, { label = "Conversions", modName = { "SkillPhysicalDamageConvertToLightning", "SkillPhysicalDamageConvertToCold", "SkillPhysicalDamageConvertToFire", "SkillPhysicalDamageConvertToChaos", "PhysicalDamageConvertToLightning", "PhysicalDamageConvertToCold", "PhysicalDamageConvertToFire", "PhysicalDamageConvertToChaos", "PhysicalDamageGainAsLightning", "PhysicalDamageGainAsCold", "PhysicalDamageGainAsFire", "PhysicalDamageGainAsChaos" }, modType = "BASE", cfg = "skill" }, }, + { format = "{0:output:LightningMin} to {0:output:LightningMax}", { breakdown = "Lightning" }, { label = "Conversions", modName = { "LightningDamageConvertToCold", "LightningDamageConvertToFire", "LightningDamageConvertToChaos", "LightningDamageGainAsCold", "LightningDamageGainAsFire", "LightningDamageGainAsChaos" }, modType = "BASE", cfg = "skill" }, }, + { format = "{0:output:ColdMin} to {0:output:ColdMax}", { breakdown = "Cold" }, { label = "Conversions", modName = { "SkillColdDamageConvertToFire", "ColdDamageConvertToFire", "ColdDamageConvertToChaos", "ColdDamageGainAsFire", "ColdDamageGainAsChaos" }, modType = "BASE", cfg = "skill" }, }, + { format = "{0:output:FireMin} to {0:output:FireMax}", { breakdown = "Fire" }, { label = "Conversions", modName = { "FireDamageConvertToChaos", "FireDamageGainAsChaos" }, modType = "BASE", cfg = "skill" }, }, { format = "{0:output:ChaosMin} to {0:output:ChaosMax}", { breakdown = "Chaos" }, }, }, { label = "Average Hit", { format = "{1:output:AverageHit}", { breakdown = "AverageHit" }, }, }, diff --git a/Modules/Calcs.lua b/Modules/Calcs.lua index 380707a8..49f25647 100644 --- a/Modules/Calcs.lua +++ b/Modules/Calcs.lua @@ -1838,6 +1838,10 @@ local function performCalcs(env) simpleBreakdown(baseSpeed, skillCfg, "Speed") end end + if skillData.hitTimeOverride then + output.HitTime = skillData.hitTimeOverride + output.HitSpeed = 1 / output.HitTime + end end -- Calculate crit chance, crit multiplier, and their combined effect @@ -2004,7 +2008,7 @@ local function performCalcs(env) -- Calculate average damage and final DPS output.AverageHit = (totalMin + totalMax) / 2 * output.CritEffect output.AverageDamage = output.AverageHit * output.HitChance / 100 - output.TotalDPS = output.AverageDamage * output.Speed * (skillData.dpsMultiplier or 1) + output.TotalDPS = output.AverageDamage * (output.HitSpeed or output.Speed) * (skillData.dpsMultiplier or 1) if env.mode == "CALCS" then if env.mode_average then output.DisplayDamage = s_format("%.1f average damage", output.AverageDamage) @@ -2028,12 +2032,12 @@ local function performCalcs(env) } breakdown.TotalDPS = { s_format("%.1f ^8(average damage)", output.AverageDamage), - s_format("x %.2f ^8(attack rate)", output.Speed), + output.HitSpeed and s_format("x %.2f ^8(hit rate)", output.HitSpeed) or s_format("x %.2f ^8(attack rate)", output.Speed), } else breakdown.TotalDPS = { s_format("%.1f ^8(average hit)", output.AverageDamage), - s_format("x %.2f ^8(cast rate)", output.Speed), + output.HitSpeed and s_format("x %.2f ^8(hit rate)", output.HitSpeed) or s_format("x %.2f ^8(cast rate)", output.Speed), } end if skillData.dpsMultiplier then @@ -2251,6 +2255,7 @@ local function performCalcs(env) if modDB:Sum("FLAG", skillCfg, "CannotIgnite") then output.IgniteChance = 0 else + local igniteMode = env.configInput.igniteMode or "AVERAGE" output.IgniteChance = m_min(100, modDB:Sum("BASE", skillCfg, "EnemyIgniteChance") + enemyDB:Sum("BASE", nil, "SelfIgniteChance")) local sourceDmg = 0 if canDeal.Fire and not modDB:Sum("FLAG", skillCfg, "FireCannotIgnite") then @@ -2259,7 +2264,7 @@ local function performCalcs(env) if canDeal.Cold and modDB:Sum("FLAG", skillCfg, "ColdCanIgnite") then sourceDmg = sourceDmg + output.ColdAverage end - if canDeal.Fire and output.IgniteChance > 0 and sourceDmg > 0 then + if canDeal.Fire and (output.IgniteChance > 0 or igniteMode == "CRIT") and sourceDmg > 0 then skillFlags.ignite = true local dotCfg = { slotName = skillCfg.slotName, @@ -2267,7 +2272,12 @@ local function performCalcs(env) keywordFlags = skillCfg.keywordFlags, } env.mainSkill.igniteCfg = dotCfg - local baseVal = sourceDmg * output.CritEffect * 0.2 + local baseVal + if igniteMode == "CRIT" then + baseVal = sourceDmg * output.CritMultiplier * 0.2 + else + baseVal = sourceDmg * output.CritEffect * 0.2 + end local effMult = 1 if env.mode_effective then local resist = output["EnemyFireResist"] @@ -2285,11 +2295,18 @@ local function performCalcs(env) output.IgniteDuration = 4 * (1 + incDur / 100) * debuffDurationMult if breakdown then breakdown.IgniteDPS = { + s_format("Ignite mode: %s ^8(can be changed in the Configuration tab)", igniteMode == "CRIT" and "Crit Damage" or "Average Damage"), "Base damage:", - s_format("%.1f ^8(average non-crit damage from sources)", sourceDmg) + s_format("%.1f ^8(average non-crit damage from sources)", sourceDmg), } - if output.CritEffect ~= 1 then - t_insert(breakdown.IgniteDPS, s_format("x %.3f ^8(crit effect modifier)", output.CritEffect)) + if igniteMode == "CRIT" then + if output.CritMultiplier ~= 1 then + t_insert(breakdown.IgniteDPS, s_format("x %.2f ^8(crit multiplier)", output.CritMultiplier)) + end + else + if output.CritEffect ~= 1 then + t_insert(breakdown.IgniteDPS, s_format("x %.3f ^8(crit effect modifier)", output.CritEffect)) + end end t_insert(breakdown.IgniteDPS, "x 0.2 ^8(ignite deals 20% per second)") t_insert(breakdown.IgniteDPS, s_format("= %.1f", baseVal, 1)) @@ -2387,7 +2404,7 @@ local function performCalcs(env) output.CombinedDPS = output.CombinedDPS + output.PoisonChance / 100 * output.PoisonDamage output.WithPoisonAverageHit = output.CombinedDPS else - output.CombinedDPS = output.CombinedDPS + output.PoisonChance / 100 * output.PoisonDamage * output.Speed + output.CombinedDPS = output.CombinedDPS + output.PoisonChance / 100 * output.PoisonDamage * (output.HitSpeed or output.Speed) output.WithPoisonDPS = output.CombinedDPS end end diff --git a/README.md b/README.md index 90853387..5c769931 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,12 @@ 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.28 - 2016/12/22 + * Added skill parts to Blade Vortex to enable calculation of DPS with different blade counts + * Blade Vortex now has a hit rate override which replaces the cast rate when calculating the skill's DPS + * This will allow you to see the skill's true DPS at a given blade count + * The calculation of Ignite base damage can now be controlled using a new option in the Configuration tab + ### 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 diff --git a/changelog.txt b/changelog.txt index 2570fa7b..deb55fa6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,8 @@ +VERSION[1.2.28][2016/12/22] + * Added skill parts to Blade Vortex to enable calculation of DPS with different blade counts + * Blade Vortex now has a hit rate override which replaces the cast rate when calculating the skill's DPS + * This will allow you to see the skill's true DPS at a given blade count + * The calculation of Ignite base damage can now be controlled using a new option in the Configuration tab 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 diff --git a/manifest.xml b/manifest.xml index 50235bb4..19a9cf8f 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,20 +1,20 @@ - + - + - + @@ -42,10 +42,10 @@ - + - - + + @@ -56,7 +56,7 @@ - +