Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions spec/System/TestPyromanticPact_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
describe("TestPyromanticPact", function()
before_each(function()
newBuild()
end)

teardown(function()
-- newBuild() takes care of resetting everything in setup()
end)

local function withMods(customMods)
build.configTab.input.customMods = customMods
build.configTab:BuildModList()
runCallback("OnFrame")
return build.calcsTab.mainOutput
end

it("parses the Pyromantic Pact node", function()
local node = build.spec.nodes[13174]
assert.is_not_nil(node)
assert.True(node.modList:Flag(nil, "ManaReplacedByInfernalFlame"))
assert.True(node.modList:Flag(nil, "InfernalFlameInsteadOfManaCost"))
end)

it("replaces maximum Mana with twice as much maximum Infernal Flame", function()
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
local mana = withMods("").Mana
assert.True(mana > 0)
local output = withMods("Maximum Mana is replaced by twice as much Maximum Infernal Flame")
assert.are.equals(0, output.Mana)
assert.are.equals(mana * 2, output.MaximumInfernalFlame)
end)

it("turns Mana costs into Infernal Flame gained", function()
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
local manaCost = withMods("").ManaCost
assert.True(manaCost > 0)
local output = withMods("Gain Infernal Flame instead of spending Mana for Skill costs")
assert.are.equals(0, output.ManaCost)
assert.False(output.ManaHasCost)
assert.are.equals(manaCost, output.InfernalFlameCost)
assert.True(output.InfernalFlameHasCost)
end)

it("leaves Mana alone without Pyromantic Pact", function()
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
local output = withMods("")
assert.is_nil(output.MaximumInfernalFlame)
assert.is_nil(output.InfernalFlameCost)
end)
end)
13 changes: 3 additions & 10 deletions src/Data/ModCache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7774,10 +7774,7 @@ c["Gain Guard equal to 20% of missing Energy Shield for 4 seconds when you Dodge
c["Gain Guard equal to Current Runic Ward for 10 seconds when Effect ends"]={nil,"Guard equal to Current Runic Ward when Effect ends "}
c["Gain Guard equal to Current Runic Ward for 10 seconds when Effect ends Excess Life Recovery added as Guard for 10 seconds"]={nil,"Guard equal to Current Runic Ward when Effect ends Excess Life Recovery added as Guard "}
c["Gain Immunity to Physical Damage for 1.5 seconds on Rampage"]={nil,"Immunity to Physical Damage for 1.5 seconds on"}
c["Gain Infernal Flame instead of spending Mana for Skill costs"]={nil,"Infernal Flame instead of spending Mana for Skill costs "}
c["Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum"]={nil,"Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum "}
c["Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum Lose all Infernal Flame on reaching maximum Infernal Flame"]={nil,"Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum Lose all Infernal Flame on reaching maximum Infernal Flame "}
c["Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum Lose all Infernal Flame on reaching maximum Infernal Flame 25% of Infernal Flame lost per second if none was gained in the past 2 seconds"]={nil,"Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum Lose all Infernal Flame on reaching maximum Infernal Flame 25% of Infernal Flame lost per second if none was gained in the past 2 seconds "}
c["Gain Infernal Flame instead of spending Mana for Skill costs"]={{[1]={flags=0,keywordFlags=0,name="InfernalFlameInsteadOfManaCost",type="FLAG",value=true}},nil}
c["Gain Maddening Presence for 10 seconds when you Kill a Rare or Unique Enemy"]={{[1]={[1]={type="Condition",var="KilledUniqueEnemy"},flags=0,keywordFlags=0,name="EnemyModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="HasMaddeningPresence",type="FLAG",value=true}}}},nil}
c["Gain Onslaught for 4 seconds on Hit while at maximum Frenzy Charges"]={{[1]={[1]={stat="FrenzyCharges",thresholdStat="FrenzyChargesMax",type="StatThreshold"},[2]={type="Condition",var="HitRecently"},flags=0,keywordFlags=0,name="Onslaught",type="FLAG",value=true}},nil}
c["Gain Onslaught for 4 seconds when a Minion Dies"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="Condition:Onslaught",type="FLAG",value=true}}}}," when a Dies "}
Expand Down Expand Up @@ -8572,11 +8569,7 @@ c["Maximum Block chance is 75%"]={{[1]={flags=0,keywordFlags=0,name="BlockChance
c["Maximum Chance to Evade is 50%"]={{[1]={flags=0,keywordFlags=0,name="EvadeChanceMax",type="MAX",value=50}},nil}
c["Maximum Energy Shield cannot be Converted"]={{[1]={flags=0,keywordFlags=0,name="EnergyShieldCannotBeConverted",type="FLAG",value=true}},nil}
c["Maximum Life is 1"]={{[1]={flags=0,keywordFlags=0,name="Life",type="OVERRIDE",value=1}},nil}
c["Maximum Mana is replaced by twice as much Maximum Infernal Flame"]={nil,"Maximum Mana is replaced by twice as much Maximum Infernal Flame "}
c["Maximum Mana is replaced by twice as much Maximum Infernal Flame Gain Infernal Flame instead of spending Mana for Skill costs"]={nil,"Maximum Mana is replaced by twice as much Maximum Infernal Flame Gain Infernal Flame instead of spending Mana for Skill costs "}
c["Maximum Mana is replaced by twice as much Maximum Infernal Flame Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum"]={nil,"Maximum Mana is replaced by twice as much Maximum Infernal Flame Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum "}
c["Maximum Mana is replaced by twice as much Maximum Infernal Flame Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum Lose all Infernal Flame on reaching maximum Infernal Flame"]={nil,"Maximum Mana is replaced by twice as much Maximum Infernal Flame Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum Lose all Infernal Flame on reaching maximum Infernal Flame "}
c["Maximum Mana is replaced by twice as much Maximum Infernal Flame Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum Lose all Infernal Flame on reaching maximum Infernal Flame 25% of Infernal Flame lost per second if none was gained in the past 2 seconds"]={nil,"Maximum Mana is replaced by twice as much Maximum Infernal Flame Gain Infernal Flame instead of spending Mana for Skill costs Take maximum Life and Energy Shield as Fire Damage when Infernal Flame reaches maximum Lose all Infernal Flame on reaching maximum Infernal Flame 25% of Infernal Flame lost per second if none was gained in the past 2 seconds "}
c["Maximum Mana is replaced by twice as much Maximum Infernal Flame"]={{[1]={flags=0,keywordFlags=0,name="ManaReplacedByInfernalFlame",type="FLAG",value=true}},nil}
c["Maximum Physical Damage Reduction is 50%"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamageReductionMax",type="MAX",value=50}},nil}
c["Maximum Quality is 200%"]={{},nil}
c["Maximum Quality is 40%"]={{},nil}
Expand Down Expand Up @@ -10003,14 +9996,14 @@ c["Your speed is Unaffected by Slows while Sprinting"]={nil,"Your speed is Unaff
c["Your speed is Unaffected by Slows while Sprinting 10% less Movement and Skill Speed per Dodge Roll in the past 20 seconds"]={nil,"Your speed is Unaffected by Slows while Sprinting 10% less Movement and Skill Speed per Dodge Roll in the past 20 seconds "}
c["Your speed is unaffected by Slows"]={{[1]={flags=0,keywordFlags=0,name="UnaffectedBySlows",type="FLAG",value=true}},nil}
c["Your spells have 100% chance to Shock against Frozen Enemies"]={nil,"Your spells have 100% chance to Shock against Frozen Enemies "}
end)();(function()
c["Zealot's Oath"]={{[1]={flags=0,keywordFlags=0,name="Keystone",type="LIST",value="Zealot's Oath"},[2]={flags=0,keywordFlags=0,name="Condition:HaveZealot'sOath",type="FLAG",value=true}},nil}
c["Zealot's Oath during Effect"]={{[1]={[1]={type="Condition",var="UsingFlask"},flags=0,keywordFlags=0,name="ZealotsOath",type="FLAG",value=true}},nil}
c["additional Elemental Infusion of the same type"]={nil,"additional Elemental Infusion of the same type "}
c["additional Rune-only sockets:"]={{},nil}
c["as being boosted by Chilled Ground"]={nil,"as being boosted by Chilled Ground "}
c["as being boosted by Ignited Ground"]={nil,"as being boosted by Ignited Ground "}
c["as being boosted by Ignited, Shocked, and Chilled Ground"]={nil,"as being boosted by Ignited, Shocked, and Chilled Ground "}
end)();(function()
c["as being boosted by Shocked Ground"]={nil,"as being boosted by Shocked Ground "}
c["being Shapeshifted for at least 8 seconds"]={nil,"being Shapeshifted for at least 8 seconds "}
c["for 4 seconds, every 0.25 seconds while raised"]={nil,"for 4 seconds, every 0.25 seconds while raised "}
Expand Down
3 changes: 3 additions & 0 deletions src/Modules/BuildDisplayStats.lua
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ local displayStats = {
{ stat = "BrandAttachmentRangeMetre", label = "Attachment Range", fmt = ".1fm", flag = "brand" },
{ stat = "BrandTicks", label = "Activations per Brand", fmt = "d", flag = "brand" },
{ stat = "ManaCost", label = "Mana Cost", fmt = "d", color = colorCodes.MANA, pool = "ManaUnreserved", compPercent = true, lowerIsBetter = true, condFunc = function(v,o) return o.ManaHasCost end },
{ stat = "InfernalFlameCost", label = "Infernal Flame Gain", fmt = "d", color = colorCodes.FIRE, condFunc = function(v,o) return o.InfernalFlameHasCost end },
{ stat = "InfernalFlamePerSecondCost", label = "Infernal Flame per second", fmt = ".2f", color = colorCodes.FIRE, condFunc = function(v,o) return o.InfernalFlamePerSecondHasCost end },
{ stat = "ManaPercentCost", label = "Mana Cost", fmt = "d%%", color = colorCodes.MANA, pool = "ManaUnreservedPercent", compPercent = true, lowerIsBetter = true, condFunc = function(v,o) return o.ManaPercentHasCost end },
{ stat = "ManaPerSecondCost", label = "Mana Cost per second", fmt = ".2f", color = colorCodes.MANA, pool = "ManaUnreserved", compPercent = true, lowerIsBetter = true, condFunc = function(v,o) return o.ManaPerSecondHasCost end },
{ stat = "ManaPercentPerSecondCost", label = "Mana Cost per second", fmt = ".2f%%", color = colorCodes.MANA, pool = "ManaUnreservedPercent", compPercent = true, lowerIsBetter = true, condFunc = function(v,o) return o.ManaPercentPerSecondHasCost end },
Expand Down Expand Up @@ -168,6 +170,7 @@ local displayStats = {
{ stat = "LifeLeechGainPerHit", label = "Life Leech/Gain per Hit", fmt = ".1f", color = colorCodes.LIFE, compPercent = true },
{ },
{ stat = "Mana", label = "Total Mana", fmt = "d", color = colorCodes.MANA, compPercent = true, modNames = { "Mana" }, ignoredSections = { "Base from Gear", "Inc. from Tree" } },
{ stat = "MaximumInfernalFlame", label = "Max Infernal Flame", fmt = "d", color = colorCodes.FIRE, compPercent = true, condFunc = function(v,o) return v > 0 end },
{ stat = "Spec:ManaInc", label = "%Inc Mana from Tree", color = colorCodes.MANA, fmt = "d%%" },
{ stat = "ManaUnreserved", label = "Unreserved Mana", fmt = "d", color = colorCodes.MANA, condFunc = function(v,o) return v < o.Mana end, compPercent = true, warnFunc = function(v) return v < 0 and "Your unreserved Mana is negative" end, breakdown = "ManaReserved" },
{ stat = "ManaUnreservedPercent", label = "Unreserved Mana", fmt = "d%%", color = colorCodes.MANA, condFunc = function(v, o) return v < 100 end, breakdown = "ManaReserved" },
Expand Down
5 changes: 5 additions & 0 deletions src/Modules/CalcDefence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ function calcs.doActorLifeManaSpirit(actor, skipBreakdown)
local override = modDB:Override(nil, res)
output[res.."HasOverride"] = override ~= nil
output[res] = override or m_max(round((base * (1 - conv/100) + extra) * (1 + inc/100) * more + total), 1)
if res == "Mana" and modDB:Flag(nil, "ManaReplacedByInfernalFlame") then
-- Pyromantic Pact: maximum Mana is replaced by twice as much maximum Infernal Flame
output.MaximumInfernalFlame = output.Mana * 2
output.Mana = 0
end
if breakdown then
if inc ~= 0 or more ~= 1 or conv ~= 0 or extra ~= 0 or total ~= 0 then
breakdown[res][1] = s_format("%g ^8(base)", base)
Expand Down
14 changes: 14 additions & 0 deletions src/Modules/CalcOffence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2393,6 +2393,20 @@ function calcs.offence(env, actor, activeSkill)
end
end
end
-- Pyromantic Pact: Mana costs give Infernal Flame instead of spending Mana
if skillModList:Flag(skillCfg, "InfernalFlameInsteadOfManaCost") then
for _, cost in ipairs({ "Cost", "PerSecondCost" }) do
if output["Mana" .. cost] then
output["InfernalFlame" .. cost] = output["Mana" .. cost]
output["InfernalFlame" .. cost:gsub("Cost$", "HasCost")] = output["Mana" .. cost:gsub("Cost$", "HasCost")]
if breakdown then
breakdown["InfernalFlame" .. cost] = breakdown["Mana" .. cost]
end
output["Mana" .. cost] = 0
output["Mana" .. cost:gsub("Cost$", "HasCost")] = false
end
end
end
-- Eldritch Battery adds maximum Energy Shield to the Mana available for payable-cost damage.
output.ManaCostPayablePool = (output.ManaUnreserved or 0) + (modDB:Flag(nil, "EnergyShieldProtectsMana") and output.EnergyShield or 0)

Expand Down
3 changes: 3 additions & 0 deletions src/Modules/CalcSections.lua
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,8 @@ return {
{ label = "Spirit % Cost", color = colorCodes.SPIRIT, haveOutput = "SpiritPercentHasCost", { format = "{0:output:SpiritPercentCost}", { breakdown = "SpiritPercentCost" }, { modName = { "SpiritCost", "Cost", "SpiritCostNoMult" }, cfg = "skill" }, }, },
{ label = "Mana Cost", color = colorCodes.MANA, haveOutput = "ManaHasCost", { format = "{0:output:ManaCost}", { breakdown = "ManaCost" }, { modName = { "ManaCost", "Cost", "ManaCostNoMult" }, cfg = "skill" }, }, },
{ label = "Mana % Cost", color = colorCodes.MANA, haveOutput = "ManaPercentHasCost", { format = "{0:output:ManaPercentCost}", { breakdown = "ManaPercentCost" }, { modName = { "ManaCost", "Cost", "ManaCostNoMult" }, cfg = "skill" }, }, },
{ label = "Infernal Flame", color = colorCodes.FIRE, haveOutput = "InfernalFlameHasCost", { format = "{0:output:InfernalFlameCost}", { breakdown = "InfernalFlameCost" }, { modName = { "ManaCost", "Cost", "ManaCostNoMult" }, cfg = "skill" }, }, },
{ label = "Infernal Flame/s", color = colorCodes.FIRE, haveOutput = "InfernalFlamePerSecondHasCost", { format = "{2:output:InfernalFlamePerSecondCost}", { breakdown = "InfernalFlamePerSecondCost" }, { modName = { "ManaCost", "Cost", "ManaCostNoMult" }, cfg = "skill" }, }, },
{ label = "Mana per second", color = colorCodes.MANA, haveOutput = "ManaPerSecondHasCost", { format = "{2:output:ManaPerSecondCost}", { breakdown = "ManaPerSecondCost" }, { modName = { "ManaCost", "Cost", "ManaCostNoMult" }, cfg = "skill" }, }, },
{ label = "Mana % per second", color = colorCodes.MANA, haveOutput = "ManaPercentPerSecondHasCost", { format = "{2:output:ManaPercentPerSecondCost}", { breakdown = "ManaPercentPerSecondCost" }, { modName = { "ManaCost", "Cost", "ManaCostNoMult" }, cfg = "skill" }, }, },
{ label = "Life Cost", color = colorCodes.LIFE, haveOutput = "LifeHasCost", { format = "{0:output:LifeCost}", { breakdown = "LifeCost" }, { modName = { "LifeCost", "Cost", "LifeCostNoMult" }, cfg = "skill" }, }, },
Expand Down Expand Up @@ -1666,6 +1668,7 @@ return {
{ label = "Total Base", { format = "{0:mod:1}", { modName = "Mana", modType = "BASE" }, }, },
{ label = "Total Increased", { format = "{0:mod:1}%", { modName = "Mana", modType = "INC" }, }, },
{ label = "Total", { format = "{0:output:Mana}", { breakdown = "Mana" }, }, },
{ label = "Max Infernal Flame", haveOutput = "MaximumInfernalFlame", { format = "{0:output:MaximumInfernalFlame}", { modName = { "Mana" } }, }, },
{ label = "Reserved", { format = "{0:output:ManaReserved} ({0:output:ManaReservedPercent}%)", { breakdown = "ManaReserved" }, }, },
{ label = "Unreserved", { format = "{0:output:ManaUnreserved} ({0:output:ManaUnreservedPercent}%)" }, },
{ label = "Recovery", { format = "{1:output:ManaRegenRecovery} ({1:output:ManaRegenPercent}%)",
Expand Down
2 changes: 2 additions & 0 deletions src/Modules/ModParser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3443,6 +3443,8 @@ local specialModList = {
} end,
-- Witch -- Infernalist
["demonflame has no maximum"] = { mod("Multiplier:DemonFlameMaximum", "BASE", 999) },
["maximum mana is replaced by twice as much maximum infernal flame"] = { flag("ManaReplacedByInfernalFlame") },
["gain infernal flame instead of spending mana for skill costs"] = { flag("InfernalFlameInsteadOfManaCost") },
-- Druid -- Shaman
["enemies in your presence have exposure"] = {
mod("EnemyModifier", "LIST", { mod = mod("FireExposure", "BASE", 20, { type = "ActorCondition", actor = "enemy", var = "EnemyInPresence" }) }),
Expand Down