Skip to content

Commit 55dc4c7

Browse files
committed
Add support for enduring flask recovery to be displayed as life/es recovery
Works for life/mana flasks, life to es conversion and mana to life conversion. Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
1 parent 731c479 commit 55dc4c7

File tree

3 files changed

+107
-36
lines changed

3 files changed

+107
-36
lines changed

src/Classes/ItemsTab.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3198,6 +3198,11 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode)
31983198
t_insert(stats, s_format("^8Mana recovered: ^7%d ^8over ^7%.2fs", grad, manaDur))
31993199
end
32003200
end
3201+
if modDB:Flag(nil, "ManaFlaskAppliesToLife") then
3202+
if grad > 0 then
3203+
t_insert(stats, s_format("^8Life recovered: ^7%d ^8over ^7%.2fs", grad, manaDur))
3204+
end
3205+
end
32013206
end
32023207
else
32033208
if durInc ~= 0 then

src/Modules/CalcPerform.lua

Lines changed: 101 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,8 +1541,16 @@ function calcs.perform(env, avoidCache, fullDPSSkipEHP)
15411541
end
15421542
end
15431543

1544-
-- flask breakdown
15451544
local effectInc = modDB:Sum("INC", {actor = "player"}, "FlaskEffect")
1545+
local effectIncMagic = modDB:Sum("INC", {actor = "player"}, "MagicUtilityFlaskEffect")
1546+
local effectIncNonPlayer = modDB:Sum("INC", nil, "FlaskEffect")
1547+
local effectIncMagicNonPlayer = modDB:Sum("INC", nil, "MagicUtilityFlaskEffect")
1548+
local flasksApplyToMinion = env.minion and modDB:Flag(env.player.mainSkill.skillCfg, "FlasksApplyToMinion")
1549+
local quickSilverAppliesToAllies = env.minion and modDB:Flag(env.player.mainSkill.skillCfg, "QuickSilverAppliesToAllies")
1550+
local flaskTotalRateInc = modDB:Sum("INC", nil, "FlaskRecoveryRate")
1551+
local flaskDurInc = modDB:Sum("INC", nil, "FlaskDuration")
1552+
1553+
-- flask breakdown
15461554
if breakdown then
15471555
local chargesGenerated = modDB:Sum("BASE", nil, "FlaskChargesGenerated")
15481556
local usedFlasks = 0
@@ -1567,71 +1575,116 @@ function calcs.perform(env, avoidCache, fullDPSSkipEHP)
15671575
end
15681576

15691577
-- Merge flask modifiers
1570-
if env.mode_combat then
1571-
local effectIncMagic = modDB:Sum("INC", {actor = "player"}, "MagicUtilityFlaskEffect")
1572-
local effectIncNonPlayer = modDB:Sum("INC", nil, "FlaskEffect")
1573-
local effectIncMagicNonPlayer = modDB:Sum("INC", nil, "MagicUtilityFlaskEffect")
1578+
local function calcFlaskRecovery(type, item)
1579+
local out = {}
1580+
local lType = type:lower()
1581+
1582+
if not item.flaskData[lType.."EffectNotRemoved"] and not modDB:Flag(nil, type.."FlaskEffectNotRemoved") then
1583+
return out
1584+
end
1585+
1586+
local name = item.name
1587+
local base = item.flaskData[lType.."Base"]
1588+
local dur = item.flaskData.duration
1589+
local instPerc = item.flaskData.instantPerc
1590+
local flaskRecInc = modDB:Sum("INC", nil, "Flask"..type.."Recovery")
1591+
local flaskRecMore = modDB:More(nil, "Flask"..type.."Recovery")
1592+
local flaskRateInc = modDB:Sum("INC", nil, "Flask"..type.."RecoveryRate")
1593+
local flaskTotal = base * (1 - instPerc / 100) * (1 + flaskRecInc / 100) * flaskRecMore * (1 + flaskDurInc / 100)
1594+
local flaskDur = dur * (1 + flaskDurInc / 100) / (1 + flaskTotalRateInc / 100) / (1 + flaskRateInc / 100)
1595+
1596+
t_insert(out, modLib.createMod(type.."Recovery", "BASE", flaskTotal / flaskDur, name))
1597+
1598+
if (modDB:Flag(nil, type.."FlaskAppliesToEnergyShield")) then
1599+
t_insert(out, modLib.createMod("EnergyShieldRecovery", "BASE", flaskTotal / flaskDur, name))
1600+
end
1601+
1602+
if (modDB:Flag(nil, type.."FlaskAppliesToLife")) then
1603+
t_insert(out, modLib.createMod("LifeRecovery", "BASE", flaskTotal / flaskDur, name))
1604+
end
1605+
1606+
return out
1607+
end
1608+
1609+
local function mergeFlasks(flasks, onlyRecovery)
15741610
local flaskBuffs = { }
15751611
local flaskConditions = {}
15761612
local flaskBuffsPerBase = {}
15771613
local flaskBuffsNonPlayer = {}
15781614
local flaskBuffsPerBaseNonPlayer = {}
1579-
local flasksApplyToMinion = env.minion and modDB:Flag(env.player.mainSkill.skillCfg, "FlasksApplyToMinion")
1580-
local quickSilverAppliesToAllies = env.minion and modDB:Flag(env.player.mainSkill.skillCfg, "QuickSilverAppliesToAllies")
15811615

1582-
for item in pairs(env.flasks) do
1616+
for item in pairs(flasks) do
15831617
flaskBuffsPerBase[item.baseName] = flaskBuffsPerBase[item.baseName] or {}
15841618
flaskBuffsPerBaseNonPlayer[item.baseName] = flaskBuffsPerBaseNonPlayer[item.baseName] or {}
1585-
flaskConditions["UsingFlask"] = true
1586-
if item.base.flask.life then
1587-
flaskConditions["UsingLifeFlask"] = true
1588-
end
1589-
if item.base.flask.mana then
1590-
flaskConditions["UsingManaFlask"] = true
1591-
end
1592-
flaskConditions["Using"..item.baseName:gsub("%s+", "")] = true
15931619

1594-
local flaskEffectInc = item.flaskData.effectInc
1595-
local flaskEffectIncNonPlayer = flaskEffectInc
1596-
if item.rarity == "MAGIC" and not (flaskConditions["UsingLifeFlask"] or flaskConditions["UsingManaFlask"]) then
1620+
local flaskEffectInc = effectInc + item.flaskData.effectInc
1621+
local flaskEffectIncNonPlayer = effectIncNonPlayer + flaskEffectInc
1622+
if item.rarity == "MAGIC" and not (item.base.flask.life or item.base.flask.mana) then
15971623
flaskEffectInc = flaskEffectInc + effectIncMagic
15981624
flaskEffectIncNonPlayer = effectIncNonPlayer + effectIncMagicNonPlayer
15991625
end
16001626

1627+
flaskConditions["UsingFlask"] = true
1628+
flaskConditions["Using"..item.baseName:gsub("%s+", "")] = true
1629+
1630+
local buffMods = {}
1631+
local modList = {}
1632+
if onlyRecovery then
1633+
if item.base.flask.life then
1634+
flaskConditions["UsingLifeFlask"] = true
1635+
for _, mod in ipairs(calcFlaskRecovery("Life", item)) do
1636+
t_insert(buffMods, mod)
1637+
end
1638+
end
1639+
if item.base.flask.mana then
1640+
flaskConditions["UsingManaFlask"] = true
1641+
for _, mod in ipairs(calcFlaskRecovery("Mana", item)) do
1642+
t_insert(buffMods, mod)
1643+
end
1644+
end
1645+
else
1646+
buffMods = item.buffModList
1647+
modList = item.modList
1648+
end
1649+
16011650
-- Avert thine eyes, lest they be forever scarred
1602-
-- I have no idea how to determine which buff is applied by a given flask,
1651+
-- I have no idea how to determine which buff is applied by a given flask,
16031652
-- so utility flasks are grouped by base, unique flasks are grouped by name, and magic flasks by their modifiers
1604-
local effectMod = 1 + (effectInc + flaskEffectInc) / 100
1605-
local effectModNonPlayer = 1 + (effectIncNonPlayer + flaskEffectIncNonPlayer) / 100
1606-
if item.buffModList[1] then
1653+
local effectMod = 1 + (flaskEffectInc) / 100
1654+
local effectModNonPlayer = 1 + (flaskEffectIncNonPlayer) / 100
1655+
if buffMods[1] then
16071656
local srcList = new("ModList")
1608-
srcList:ScaleAddList(item.buffModList, effectMod)
1609-
mergeBuff(srcList, flaskBuffs, item.baseName)
1610-
mergeBuff(srcList, flaskBuffsPerBase[item.baseName], item.baseName)
1657+
local baseName = item.baseName
1658+
if item.base.flask.life or item.base.flask.mana then
1659+
baseName = "LifeManaFlask"
1660+
end
1661+
srcList:ScaleAddList(buffMods, effectMod)
1662+
mergeBuff(srcList, flaskBuffs, baseName)
1663+
mergeBuff(srcList, flaskBuffsPerBase[item.baseName], baseName)
16111664
if (flasksApplyToMinion or quickSilverAppliesToAllies) then
16121665
srcList = new("ModList")
1613-
srcList:ScaleAddList(item.buffModList, effectModNonPlayer)
1614-
mergeBuff(srcList, flaskBuffsNonPlayer, item.baseName)
1615-
mergeBuff(srcList, flaskBuffsPerBaseNonPlayer[item.baseName], item.baseName)
1666+
srcList:ScaleAddList(buffMods, effectModNonPlayer)
1667+
mergeBuff(srcList, flaskBuffsNonPlayer, baseName)
1668+
mergeBuff(srcList, flaskBuffsPerBaseNonPlayer[item.baseName], baseName)
16161669
end
16171670
end
1618-
if item.modList[1] then
1671+
if modList[1] then
16191672
local srcList = new("ModList")
1620-
srcList:ScaleAddList(item.modList, effectMod)
1673+
srcList:ScaleAddList(modList, effectMod)
16211674
local key
16221675
if item.rarity == "UNIQUE" then
16231676
key = item.title
16241677
else
16251678
key = ""
1626-
for _, mod in ipairs(item.modList) do
1679+
for _, mod in ipairs(modList) do
16271680
key = key .. modLib.formatModParams(mod) .. "&"
16281681
end
16291682
end
16301683
mergeBuff(srcList, flaskBuffs, key)
16311684
mergeBuff(srcList, flaskBuffsPerBase[item.baseName], key)
16321685
if (flasksApplyToMinion or quickSilverAppliesToAllies) then
16331686
srcList = new("ModList")
1634-
srcList:ScaleAddList(item.modList, effectModNonPlayer)
1687+
srcList:ScaleAddList(modList, effectModNonPlayer)
16351688
mergeBuff(srcList, flaskBuffsNonPlayer, key)
16361689
mergeBuff(srcList, flaskBuffsPerBaseNonPlayer[item.baseName], key)
16371690
end
@@ -1655,7 +1708,7 @@ function calcs.perform(env, avoidCache, fullDPSSkipEHP)
16551708
minionModDB:AddList(buffModList)
16561709
end
16571710
else -- Not all flasks apply to minions. Check if some flasks need to be selectively applied
1658-
if quickSilverAppliesToAllies and flaskBuffsPerBaseNonPlayer["Quicksilver Flask"] then
1711+
if quickSilverAppliesToAllies and flaskBuffsPerBaseNonPlayer["Quicksilver Flask"] then
16591712
local minionModDB = env.minion.modDB
16601713
minionModDB.conditions["UsingQuicksilverFlask"] = flaskConditions["UsingQuicksilverFlask"]
16611714
minionModDB.conditions["UsingFlask"] = flaskConditions["UsingFlask"]
@@ -1667,8 +1720,14 @@ function calcs.perform(env, avoidCache, fullDPSSkipEHP)
16671720
end
16681721
end
16691722

1670-
-- Merge keystones again to catch any that were added by flasks
1671-
mergeKeystones(env)
1723+
if env.mode_combat then
1724+
-- This needs to be done in 2 steps to account for effects affecting life recovery from flasks
1725+
-- For example Sorrow of the Divine and buffs (like flask recovery watchers eye)
1726+
mergeFlasks(env.flasks, false)
1727+
1728+
-- Merge keystones again to catch any that were added by flasks
1729+
mergeKeystones(env)
1730+
end
16721731

16731732
-- Calculate attributes and life/mana pools
16741733
doActorAttribsConditions(env, env.player)
@@ -2261,6 +2320,12 @@ function calcs.perform(env, avoidCache, fullDPSSkipEHP)
22612320
end
22622321
end
22632322

2323+
if env.mode_combat then
2324+
-- This needs to be done in 2 steps to account for effects affecting life recovery from flasks
2325+
-- For example Sorrow of the Divine and buffs (like flask recovery watchers eye)
2326+
mergeFlasks(env.flasks, true)
2327+
end
2328+
22642329
-- Check for extra curses
22652330
for dest, modDB in pairs({[curses] = modDB, [minionCurses] = env.minion and env.minion.modDB}) do
22662331
for _, value in ipairs(modDB:List(nil, "ExtraCurse")) do

src/Modules/ModParser.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,7 @@ local specialModList = {
19171917
mod("ManaConvertToArmour", "BASE", num),
19181918
} end,
19191919
["life recovery from flasks also applies to energy shield"] = { flag("LifeFlaskAppliesToEnergyShield") },
1920+
["non%-instant mana recovery from flasks is also recovered as life"] = { flag("ManaFlaskAppliesToLife") },
19201921
["life leech effects recover energy shield instead while on full life"] = { flag("ImmortalAmbition", { type = "Condition", var = "FullLife" }, { type = "Condition", var = "LeechingLife" }) },
19211922
["shepherd of souls"] = { mod("Damage", "MORE", -30, { type = "SkillType", skillType = SkillType.Vaal, neg = true }) },
19221923
["adds (%d+) to (%d+) attack physical damage to melee skills per (%d+) dexterity while you are unencumbered"] = function(_, min, max, dex) return { -- Hollow Palm 3 suffixes

0 commit comments

Comments
 (0)