Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
Openarl committed Jan 30, 2017
2 parents 9728c1a + e9a4b95 commit 5295094
Show file tree
Hide file tree
Showing 16 changed files with 219 additions and 93 deletions.
41 changes: 34 additions & 7 deletions Classes/CalcsTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -350,13 +350,36 @@ function CalcsTabClass:BuildOutput()
self.itemCalculator = { self.calcs.getItemCalculator(self.build) }
end

-- Estimate the offensive and defensive power of all unallocated nodes
-- Controls the coroutine that calculations node power
function CalcsTabClass:BuildPower()
if self.powerBuildFlag then
self.powerBuildFlag = false
self.powerBuilder = coroutine.create(self.PowerBuilder)
end
if self.powerBuilder then
collectgarbage("stop") -- This is necessary to work around a bug in the JIT
coroutine.resume(self.powerBuilder, self)
if coroutine.status(self.powerBuilder) == "dead" then
self.powerBuilder = nil
end
collectgarbage("restart")
end
end

-- Estimate the offensive and defensive power of all unallocated nodes
function CalcsTabClass:PowerBuilder()
local calcFunc, calcBase = self:GetNodeCalculator()
local cache = { }
self.powerMax = { }
local newPowerMax = {
dps = 0,
def = 0
}
if not self.powerMax then
self.powerMax = newPowerMax
end
local start = GetTime()
for _, node in pairs(self.build.spec.nodes) do
node.power = wipeTable(node.power)
wipeTable(node.power)
if not node.alloc and node.modKey ~= "" then
if not cache[node.modKey] then
cache[node.modKey] = calcFunc({node})
Expand All @@ -370,12 +393,16 @@ function CalcsTabClass:BuildPower()
(output.LifeRegen - calcBase.LifeRegen) / 500 +
(output.EnergyShieldRegen - calcBase.EnergyShieldRegen) / 1000
if node.path then
self.powerMax.dps = m_max(self.powerMax.dps or 0, node.power.dps)
self.powerMax.def = m_max(self.powerMax.def or 0, node.power.def)
newPowerMax.dps = m_max(newPowerMax.dps, node.power.dps)
newPowerMax.def = m_max(newPowerMax.def, node.power.def)
end
end
end
self.powerBuildFlag = false
if coroutine.running() and GetTime() - start > 100 then
coroutine.yield()
start = GetTime()
end
end
self.powerMax = newPowerMax
end

function CalcsTabClass:GetNodeCalculator()
Expand Down
6 changes: 3 additions & 3 deletions Classes/CheckBoxControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ function CheckBoxClass:Draw(viewPort)
local tooltip = self:GetProperty("tooltip")
if tooltip then
main:AddTooltipLine(16, tooltip)
SetDrawLayer(nil, 100)
main:DrawTooltip(x, y, size, size, viewPort)
SetDrawLayer(nil, 0)
end
SetDrawLayer(nil, 100)
main:DrawTooltip(x, y, size, size, viewPort)
SetDrawLayer(nil, 0)
end
end

Expand Down
76 changes: 50 additions & 26 deletions Classes/ConfigTab.lua

Large diffs are not rendered by default.

54 changes: 38 additions & 16 deletions Classes/ImportTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ local ImportTabClass = common.NewClass("ImportTab", "ControlHost", "Control", fu
self.controls.accountNameGo.enabled = function()
return self.controls.accountName.buf:match("%S")
end
self.controls.accountNameTip = common.New("LabelControl", {"TOPLEFT",self.controls.accountName,"BOTTOMLEFT"}, 0, 4, 0, 14, "^7Note: the account name must have the correct capitalisation, or the character import will fail.")

-- Stage: input POESESSID
self.controls.sessionHeader = common.New("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, 6, 40, 200, 14)
Expand Down Expand Up @@ -205,22 +204,45 @@ function ImportTabClass:DownloadCharacterList()
self.charImportMode = "GETACCOUNTNAME"
return
end
self.charImportStatus = "Character list successfully retrieved."
self.charImportMode = "SELECTCHAR"
main.lastAccountName = accountName
if sessionID then
main.accountSessionIDs[accountName] = sessionID
end
wipeTable(self.controls.charSelect.list)
for i, char in ipairs(charList) do
t_insert(self.controls.charSelect.list, {
val = char,
label = string.format("%s: Level %d %s in %s", char.name or "?", char.level or 0, char.class or "?", char.league or "?")
})
--ConPrintTable(charList)
if #charList == 0 then
self.charImportStatus = data.colorCodes.NEGATIVE.."The account has no characters to import."
self.charImportMode = "GETACCOUNTNAME"
return
end
table.sort(self.controls.charSelect.list, function(a,b)
return a.val.name:lower() < b.val.name:lower()
end)
-- GGG's character API has an issue where for /get-characters the account name is not case-sensitive, but for /get-passive-skills and /get-items it is.
-- This workaround grabs the profile page and extracts the correct account name from one of the URLs.
launch:DownloadPage("https://www.pathofexile.com/account/view-profile/"..accountName, function(page, errMsg)
if errMsg then
self.charImportStatus = data.colorCodes.NEGATIVE.."Error retrieving character list, try again ("..errMsg:gsub("\n"," ")..")"
self.charImportMode = "GETACCOUNTNAME"
return
end
local realAccountName = page:match("/account/view%-profile/([^/]+)/characters")
if not realAccountName then
self.charImportStatus = data.colorCodes.NEGATIVE.."Failed to retrieve character list."
self.charImportMode = "GETSESSIONID"
return
end
self.controls.accountName:SetText(realAccountName)
accountName = realAccountName
self.charImportStatus = "Character list successfully retrieved."
self.charImportMode = "SELECTCHAR"
main.lastAccountName = accountName
if sessionID then
main.accountSessionIDs[accountName] = sessionID
end
wipeTable(self.controls.charSelect.list)
for i, char in ipairs(charList) do
t_insert(self.controls.charSelect.list, {
val = char,
label = string.format("%s: Level %d %s in %s", char.name or "?", char.level or 0, char.class or "?", char.league or "?")
})
end
table.sort(self.controls.charSelect.list, function(a,b)
return a.val.name:lower() < b.val.name:lower()
end)
end, sessionID and "POESESSID="..sessionID)
end, sessionID and "POESESSID="..sessionID)
end

Expand Down
3 changes: 2 additions & 1 deletion Classes/PassiveSpec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ local PassiveSpecClass = common.NewClass("PassiveSpec", "UndoHandler", function(
self.nodes = { }
for _, treeNode in ipairs(self.tree.nodes) do
self.nodes[treeNode.id] = setmetatable({
linked = { }
linked = { },
power = { }
}, treeNode.meta)
end
for id, node in pairs(self.nodes) do
Expand Down
9 changes: 5 additions & 4 deletions Classes/PassiveTreeView.lua
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,11 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
SetDrawColor(1, 1, 1)
end

if self.showHeatMap then
-- Build the power numbers if needed
build.calcsTab:BuildPower()
end

-- Draw the nodes
for nodeId, node in pairs(spec.nodes) do
-- Determine the base and overlay images for this node based on type and state
Expand Down Expand Up @@ -360,10 +365,6 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
SetDrawColor(0.5, 0.5, 0.5)
end
if self.showHeatMap then
if build.calcsTab.powerBuildFlag then
-- Build the power numbers if needed
build.calcsTab:BuildPower()
end
if not node.alloc and node.type ~= "classStart" and node.type ~= "ascendClassStart" then
-- Calculate color based on DPS and defensive powers
local dps = m_max(node.power.dps or 0, 0)
Expand Down
2 changes: 1 addition & 1 deletion Data/Uniques/gloves.lua
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ Energy Shield: 24
Requires Level 51, 40 Str, 40 Int
Adds (30-36 to 44-50) Cold Damage to Attacks
(12 to 16)% increased maximum Life
(40 to 50)% to Cold Resistance
+(40 to 50)% to Cold Resistance
25% increased Freeze Duration on Enemies
Your Hits can only Kill Frozen enemies
]],
Expand Down
12 changes: 7 additions & 5 deletions Launch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ function launch:OnSubError(errMsg)
end

function launch:OnSubFinished(...)
if self.subScriptType == "UPDATE" then
local type = self.subScriptType
self.subScriptType = nil
if type == "UPDATE" then
local ret = (...)
self.updateAvailable = ret
if self.updateChecking then
Expand All @@ -203,14 +205,14 @@ function launch:OnSubFinished(...)
end
self.updateChecking = false
end
elseif self.subScriptType == "DOWNLOAD" then
local errMsg = PCall(self.downloadCallback, ...)
elseif type == "DOWNLOAD" then
local callback = self.downloadCallback
self.downloadCallback = nil
local errMsg = PCall(callback, ...)
if errMsg then
self:ShowErrMsg("In download callback: %s", errMsg)
end
self.downloadCallback = nil
end
self.subScriptType = nil
end

function launch:DownloadPage(url, callback, cookies)
Expand Down
2 changes: 1 addition & 1 deletion Modules/Build.lua
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ function buildMode:Init(dbFileName, buildName)
local start = GetTime()
SetProfiling(true)
for i = 1, 10 do
self.calcsTab:BuildPower(self)
self.calcsTab:PowerBuilder()
end
SetProfiling(false)
ConPrintf("Power build time: %d msec", GetTime() - start)
Expand Down
2 changes: 1 addition & 1 deletion Modules/CalcSections.lua
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ return {
{ label = "Total Increased", { format = "{0:mod:1}%", { modName = { "Damage", "FireDamage", "ElementalDamage" }, modType = "INC", cfg = "ignite" }, }, },
{ label = "Total More", { format = "{0:mod:1}%", { modName = { "Damage", "FireDamage", "ElementalDamage" }, modType = "MORE", cfg = "ignite" }, }, },
{ label = "Effective DPS Mod", flag = "effective", { format = "x {3:output:IgniteEffMult}", { breakdown = "IgniteEffMult" }, { label = "Enemy modifiers", modName = { "FireResist", "ElementalResist", "DamageTaken", "DotTaken", "FireDamageTaken", "BurningDamageTaken", "ElementalDamageTaken" }, enemy = true }, }, },
{ label = "Ignite DPS", { format = "{1:output:IgniteDPS}", { breakdown = "IgniteDPS" }, }, },
{ label = "Ignite DPS", { format = "{1:output:IgniteDPS}", { breakdown = "IgniteDPS" }, { modName = { "IgniteBurnRate" }, cfg = "skill" }, }, },
{ label = "Ignite Duration", { format = "{2:output:IgniteDuration}s", { breakdown = "IgniteDuration" }, { label = "Player modifiers", modName = "EnemyIgniteDuration", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfIgniteDuration", enemy = true }, }, },
{ label = "Dmg. per Ignite", flag = "igniteCanStack", { format = "{1:output:IgniteDamage}", { breakdown = "IgniteDamage" }, }, },
} },
Expand Down
49 changes: 41 additions & 8 deletions Modules/Calcs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
-- Module: Calcs
-- Performs all the offense and defense calculations.
-- Here be dragons!
-- This file is 2700 lines long, over half of which is in one function...
-- This file is 2800 lines long, over half of which is in one function...
--

local pairs = pairs
Expand Down Expand Up @@ -1277,14 +1277,17 @@ local function performCalcs(env)
end
return out
end
dotBreakdown = function(out, baseVal, inc, more, effMult, total)
dotBreakdown = function(out, baseVal, inc, more, rate, effMult, total)
t_insert(out, s_format("%.1f ^8(base damage per second)", baseVal))
if inc ~= 0 then
t_insert(out, s_format("x %.2f ^8(increased/reduced)", 1 + inc/100))
end
if more ~= 1 then
t_insert(out, s_format("x %.2f ^8(more/less)", more))
end
if rate and rate ~= 1 then
t_insert(out, s_format("x %.2f ^8(rate modifier)", rate))
end
if effMult ~= 1 then
t_insert(out, s_format("x %.3f ^8(effective DPS modifier)", effMult))
end
Expand Down Expand Up @@ -2170,7 +2173,7 @@ local function performCalcs(env)
output.TotalDot = output.TotalDot + total
if breakdown then
breakdown[damageType.."Dot"] = { }
dotBreakdown(breakdown[damageType.."Dot"], baseVal, inc, more, effMult, total)
dotBreakdown(breakdown[damageType.."Dot"], baseVal, inc, more, nil, effMult, total)
end
end
end
Expand Down Expand Up @@ -2312,7 +2315,7 @@ local function performCalcs(env)
t_insert(breakdown.BleedDPS, "x 0.1 ^8(bleed deals 10% per second)")
t_insert(breakdown.BleedDPS, s_format("= %.1f", baseVal))
t_insert(breakdown.BleedDPS, "Bleed DPS:")
dotBreakdown(breakdown.BleedDPS, baseVal, inc, more, effMult, output.BleedDPS)
dotBreakdown(breakdown.BleedDPS, baseVal, inc, more, nil, effMult, output.BleedDPS)
if output.BleedDuration ~= 5 then
breakdown.BleedDuration = {
"5.00s ^8(base duration)"
Expand Down Expand Up @@ -2373,7 +2376,7 @@ local function performCalcs(env)
t_insert(breakdown.PoisonDPS, "x 0.08 ^8(poison deals 8% per second)")
t_insert(breakdown.PoisonDPS, s_format("= %.1f", baseVal, 1))
t_insert(breakdown.PoisonDPS, "Poison DPS:")
dotBreakdown(breakdown.PoisonDPS, baseVal, inc, more, effMult, output.PoisonDPS)
dotBreakdown(breakdown.PoisonDPS, baseVal, inc, more, nil, effMult, output.PoisonDPS)
if output.PoisonDuration ~= 2 then
breakdown.PoisonDuration = {
s_format("%.2fs ^8(base duration)", durationBase)
Expand Down Expand Up @@ -2439,9 +2442,10 @@ local function performCalcs(env)
end
local inc = modDB:Sum("INC", dotCfg, "Damage", "FireDamage", "ElementalDamage")
local more = round(modDB:Sum("MORE", dotCfg, "Damage", "FireDamage", "ElementalDamage"), 2)
output.IgniteDPS = baseVal * (1 + inc/100) * more * effMult
local burnRateMod = calcMod(modDB, skillCfg, "IgniteBurnRate")
output.IgniteDPS = baseVal * (1 + inc/100) * more * burnRateMod * effMult
local incDur = modDB:Sum("INC", dotCfg, "EnemyIgniteDuration") + enemyDB:Sum("INC", nil, "SelfIgniteDuration")
output.IgniteDuration = 4 * (1 + incDur / 100) * debuffDurationMult
output.IgniteDuration = 4 * (1 + incDur / 100) / burnRateMod * debuffDurationMult
if modDB:Sum("FLAG", nil, "IgniteCanStack") then
output.IgniteDamage = output.IgniteDPS * output.IgniteDuration
skillFlags.igniteCanStack = true
Expand All @@ -2450,7 +2454,7 @@ local function performCalcs(env)
t_insert(breakdown.IgniteDPS, "x 0.2 ^8(ignite deals 20% per second)")
t_insert(breakdown.IgniteDPS, s_format("= %.1f", baseVal, 1))
t_insert(breakdown.IgniteDPS, "Ignite DPS:")
dotBreakdown(breakdown.IgniteDPS, baseVal, inc, more, effMult, output.IgniteDPS)
dotBreakdown(breakdown.IgniteDPS, baseVal, inc, more, burnRateMod, effMult, output.IgniteDPS)
if skillFlags.igniteCanStack then
breakdown.IgniteDamage = {
s_format("%.1f ^8(damage per second)", output.IgniteDPS),
Expand All @@ -2465,6 +2469,9 @@ local function performCalcs(env)
if incDur ~= 0 then
t_insert(breakdown.IgniteDuration, s_format("x %.2f ^8(increased/reduced duration)", 1 + incDur/100))
end
if burnRateMod ~= 1 then
t_insert(breakdown.IgniteDuration, s_format("/ %.2f ^8(rate modifier)", burnRateMod))
end
if debuffDurationMult ~= 1 then
t_insert(breakdown.IgniteDuration, s_format("/ %.2f ^8(debuff expires slower/faster)", 1 / debuffDurationMult))
end
Expand Down Expand Up @@ -2725,6 +2732,32 @@ function calcs.buildOutput(build, mode)
for _, stat in pairs({"Life", "Mana", "Armour", "Evasion", "EnergyShield"}) do
output["Spec:"..stat.."Inc"] = env.modDB:Sum("INC", specCfg, stat)
end

env.conditionsUsed = { }
local function addCond(var, mod)
if not env.conditionsUsed[var] then
env.conditionsUsed[var] = { }
end
t_insert(env.conditionsUsed[var], mod)
end
for _, db in ipairs{env.modDB, env.enemyDB} do
for modName, modList in pairs(db.mods) do
for _, mod in ipairs(modList) do
for _, tag in ipairs(mod.tagList) do
if tag.type == "Condition" then
if tag.varList then
for _, var in ipairs(tag.varList) do
addCond(var, mod)
end
else
addCond(tag.var, mod)
end
end
end
end
end
end
ConPrintTable(env.conditionsUsed)
elseif mode == "CALCS" then
local buffList = { }
local combatList = { }
Expand Down
5 changes: 5 additions & 0 deletions Modules/ModParser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ local modTagList = {
["while using a flask"] = { tag = { type = "Condition", var = "UsingFlask" } },
["during flask effect"] = { tag = { type = "Condition", var = "UsingFlask" } },
["while on consecrated ground"] = { tag = { type = "Condition", var = "OnConsecratedGround" } },
["on burning ground"] = { tag = { type = "Condition", var = "OnBurningGround" } },
["on chilled ground"] = { tag = { type = "Condition", var = "OnChilledGround" } },
["on shocked ground"] = { tag = { type = "Condition", var = "OnShockedGround" } },
["while ignited"] = { tag = { type = "Condition", var = "PlayerIgnited" } },
["while frozen"] = { tag = { type = "Condition", var = "PlayerFrozen" } },
["while shocked"] = { tag = { type = "Condition", var = "PlayerShocked" } },
Expand Down Expand Up @@ -582,6 +585,8 @@ local specialModList = {
["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,
["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,
}
local keystoneList = {
-- List of keystones that can be found on uniques
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.36 - 2017/01/31
* Condition toggles in the Configuration tab will now only appear if the condition is actually used by the build
* Added support for "Ignited Enemies Burn faster" modifiers
* Added options to the Configuration tab for "Are you on Shocked/Burning/Chilled Ground"
* Character imports will now work even if the capitalisation of the account name is incorrect

### 1.2.35 - 2017/01/29
With this update, the way the program handles the calculation of crit damage has been improved.
Damage for crits and non-crits are now calculated and tallied separately, and combined later, instead of only
Expand Down
5 changes: 5 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
VERSION[1.2.36][2017/01/31]
* Condition toggles in the Configuration tab will now only appear if the condition is actually used by the build
* Added support for "Ignited Enemies Burn faster" modifiers
* Added options to the Configuration tab for "Are you on Shocked/Burning/Chilled Ground"
* Character imports will now work even if the capitalisation of the account name is incorrect
VERSION[1.2.35][2017/01/29]
With this update, the way the program handles the calculation of crit damage has been improved.
Damage for crits and non-crits are now calculated and tallied separately, and combined later, instead of only
Expand Down
Loading

0 comments on commit 5295094

Please sign in to comment.