Release 1.3.11

- Added options to delete data before importing a character
- Changed Wither to show secondary duration
- Local inc. Accuracy is now multiplicative with global
This commit is contained in:
Openarl
2017-02-26 23:03:54 +10:00
parent e89b023d21
commit d08cbf7e84
18 changed files with 273 additions and 61 deletions

View File

@@ -504,6 +504,9 @@ return {
}, },
} },
{ 1, "MiscEffects", 1, "Other Effects", data.colorCodes.OFFENCE, {
--[[{ label = "Life Leech Rate", flag = "leechLife", { format = "{1:output:LifeLeechRate}", { breakdown = "LifeLeechRate" }, }, },
{ label = "ES Leech Rate", flag = "leechES", { format = "{1:output:EnergyShieldLeechRate}", { breakdown = "EnergyShieldLeechRate" }, }, },
{ label = "Mana Leech Rate", flag = "leechMana", { format = "{1:output:ManaLeechRate}", { breakdown = "ManaLeechRate" }, }, },]]
{ label = "Chance to Shock", flag = "shock", { format = "{0:output:ShockChance}%",
{ breakdown = "MainHand.ShockChance" },
{ breakdown = "OffHand.ShockChance" },

View File

@@ -635,6 +635,8 @@ local function initEnv(build, mode, override)
modDB:NewMod("Damage", "MORE", 4, "Base", { type = "Multiplier", var = "FrenzyCharge" })
modDB:NewMod("EnduranceChargesMax", "BASE", 3, "Base")
modDB:NewMod("ElementalResist", "BASE", 4, "Base", { type = "Multiplier", var = "EnduranceCharge" })
modDB:NewMod("MaxLifeLeechRate", "BASE", 20, "Base")
modDB:NewMod("MaxManaLeechRate", "BASE", 20, "Base")
modDB:NewMod("ActiveTrapLimit", "BASE", 3, "Base")
modDB:NewMod("ActiveMineLimit", "BASE", 5, "Base")
modDB:NewMod("ActiveTotemLimit", "BASE", 1, "Base")
@@ -1652,6 +1654,14 @@ local function performCalcs(env)
end
end
-- Leech caps
if modDB:Sum("FLAG", nil, "GhostReaver") then
output.MaxEnergyShieldLeechRate = output.EnergyShield * modDB:Sum("BASE", nil, "MaxLifeLeechRate") / 100
else
output.MaxLifeLeechRate = output.Life * modDB:Sum("BASE", nil, "MaxLifeLeechRate") / 100
end
output.MaxManaLeechRate = output.Mana * modDB:Sum("BASE", nil, "MaxManaLeechRate") / 100
-- Other defences: block, dodge, stun recovery/avoidance
do
output.MovementSpeedMod = calcMod(modDB, nil, "MovementSpeed")
@@ -2195,6 +2205,8 @@ local function performCalcs(env)
for pass = 1, 2 do
-- Pass 1 is critical strike damage, pass 2 is non-critical strike
condList["CriticalStrike"] = (pass == 1)
local lifeLeechTotal = 0
local manaLeechTotal = 0
for _, damageType in ipairs(dmgTypeList) do
local min, max
if skillFlags.hit and canDeal[damageType] then
@@ -2253,9 +2265,17 @@ local function performCalcs(env)
breakdown[damageType.."EffMult"] = effMultBreakdown(damageType, resist, pen, taken, effMult)
end
end
if breakdown then
if breakdown then
t_insert(breakdown[damageType], s_format("= %d to %d", min, max))
end
local lifeLeech = modDB:Sum("BASE", cfg, "DamageLifeLeech", damageType.."LifeLeech", isElemental[damageType] and "ElementalLifeLeech" or nil) + enemyDB:Sum("BASE", nil, "SelfDamageLifeLeech") / 100
if lifeLeech > 0 then
lifeLeechTotal = lifeLeechTotal + (min + max) / 2 * lifeLeech / 100
end
local manaLeech = modDB:Sum("BASE", cfg, "DamageManaLeech", damageType.."ManaLeech", isElemental[damageType] and "ElementalManaLeech" or nil) + enemyDB:Sum("BASE", nil, "SelfDamageManaLeech") / 100
if manaLeech > 0 then
manaLeechTotal = manaLeechTotal + (min + max) / 2 * manaLeech / 100
end
else
min, max = 0, 0
if breakdown then
@@ -2278,6 +2298,29 @@ local function performCalcs(env)
totalHitMax = totalHitMax + max
end
end
if pass == 1 then
if modDB:Sum("FLAG", cfg, "InstantLifeLeech") then
output.LifeLeechInstant = (output.LifeLeechInstant or 0) + lifeLeechTotal * output.CritChance / 100
else
output.LifeLeech = (output.LifeLeech or 0) + lifeLeechTotal * output.CritChance / 100
end
if modDB:Sum("FLAG", cfg, "InstantManaLeech") then
output.ManaLeechInstant = (output.ManaLeechInstant or 0) + manaLeechTotal * output.CritChance / 100
else
output.ManaLeech = (output.ManaLeech or 0) + manaLeechTotal * output.CritChance / 100
end
else
if modDB:Sum("FLAG", cfg, "InstantLifeLeech") then
output.LifeLeechInstant = (output.LifeLeechInstant or 0) + lifeLeechTotal * (1 - output.CritChance / 100)
else
output.LifeLeech = (output.LifeLeech or 0) + lifeLeechTotal * (1 - output.CritChance / 100)
end
if modDB:Sum("FLAG", cfg, "InstantManaLeech") then
output.ManaLeechInstant = (output.ManaLeechInstant or 0) + manaLeechTotal * (1 - output.CritChance / 100)
else
output.ManaLeech = (output.ManaLeech or 0) + manaLeechTotal * (1 - output.CritChance / 100)
end
end
end
output.TotalMin = totalHitMin
output.TotalMax = totalHitMax
@@ -2289,6 +2332,15 @@ local function performCalcs(env)
enemyDB.conditions.HitByLightningDamage = output.LightningHitAverage > 0
end
-- Calculate leech
local hitRate = output.HitChance / 100 * (globalOutput.HitSpeed or globalOutput.Speed) * (skillData.dpsMultiplier or 1)
output.LifeLeechDuration = (output.LifeLeech or 0) / (modDB:Sum("FLAG", nil, "GhostReaver") and globalOutput.EnergyShield or globalOutput.Life) / 0.02
output.LifeLeechInstances = output.LifeLeechDuration * hitRate
output.LifeLeechInstantRate = (output.LifeLeechInstant or 0) * hitRate
output.ManaLeechDuration = (output.ManaLeech or 0) / globalOutput.Mana / 0.02
output.ManaLeechInstances = output.ManaLeechDuration * hitRate
output.ManaLeechInstantRate = (output.ManaLeechInstant or 0) * hitRate
-- Calculate average damage and final DPS
output.AverageHit = (totalHitMin + totalHitMax) / 2 * (1 - output.CritChance / 100) + (totalCritMin + totalCritMax) / 2 * output.CritChance / 100
output.AverageDamage = output.AverageHit * output.HitChance / 100
@@ -2317,6 +2369,12 @@ local function performCalcs(env)
combineStat("CritMultiplier", "AVERAGE")
combineStat("AverageDamage", "DPS")
combineStat("TotalDPS", "DPS")
combineStat("LifeLeechDuration", "DPS")
combineStat("LifeLeechInstances", "DPS")
combineStat("LifeLeechInstantRate", "DPS")
combineStat("ManaLeechDuration", "DPS")
combineStat("ManaLeechInstances", "DPS")
combineStat("ManaLeechInstantRate", "DPS")
if skillFlags.bothWeaponAttack then
if breakdown then
breakdown.AverageDamage = { }
@@ -2355,6 +2413,57 @@ local function performCalcs(env)
t_insert(breakdown.TotalDPS, s_format("= %.1f", output.TotalDPS))
end
-- Calculate leech rates
if modDB:Sum("FLAG", nil, "GhostReaver") then
output.EnergyShieldLeechRate = output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.EnergyShield * 0.02 * calcMod(modDB, skillCfg, "LifeLeechRate"), output.MaxEnergyShieldLeechRate)
else
output.LifeLeechRate = output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.Life * 0.02 * calcMod(modDB, skillCfg, "LifeLeechRate"), output.MaxLifeLeechRate)
end
output.ManaLeechRate = output.ManaLeechInstantRate + m_min(output.ManaLeechInstances * output.Mana * 0.02 * calcMod(modDB, skillCfg, "ManaLeechRate"), output.MaxManaLeechRate)
skillFlags.leechES = (output.EnergyShieldLeechRate or 0) > 0
skillFlags.leechLife = (output.LifeLeechRate or 0) > 0
skillFlags.leechMana = output.ManaLeechRate > 0
if breakdown then
local function leechBreakdown(instant, instances, pool, rate, max, dur)
local out = { }
if instant > 0 then
t_insert(out, s_format("Instant Leech per second: %.1f", instant))
end
if instances > 0 then
t_insert(out, "Rate per instance:")
t_insert(out, s_format("%d ^8(size of leech destination pool)", pool))
t_insert(out, "x 0.02 ^8(base leech rate is 2% per second)")
local rateMod = calcMod(modDB, skillCfg, rate)
if rateMod ~= 1 then
t_insert(out, s_format("x %.2f ^8(leech rate modifier)", rateMod))
end
t_insert(out, s_format("= %.1f ^8per second", pool * 0.02 * rateMod))
t_insert(out, "Maximum leech rate against one target:")
t_insert(out, s_format("%.1f", pool * 0.02 * rateMod))
t_insert(out, s_format("x %.1f ^8(average instances)", instances))
local total = pool * 0.02 * rateMod * instances
t_insert(out, s_format("= %.1f ^8per second", total))
if total <= max then
t_insert(out, s_format("Time to reach max: %.1fs", dur))
end
t_insert(out, s_format("Leech rate cap: %.1f", max))
if total > max then
t_insert(out, s_format("Time to reach cap: %.1fs", dur / total * max))
end
end
return out
end
if skillFlags.leechES then
breakdown.EnergyShieldLeechRate = leechBreakdown(output.LifeLeechInstantRate, output.LifeLeechInstances, output.EnergyShield, "LifeLeechRate", output.MaxEnergyShieldLeechRate, output.LifeLeechDuration)
end
if skillFlags.leechLife then
breakdown.LifeLeechRate = leechBreakdown(output.LifeLeechInstantRate, output.LifeLeechInstances, output.Life, "LifeLeechRate", output.MaxLifeLeechRate, output.LifeLeechDuration)
end
if skillFlags.leechMana then
breakdown.ManaLeechRate = leechBreakdown(output.ManaLeechInstantRate, output.ManaLeechInstances, output.Mana, "ManaLeechRate", output.MaxManaLeechRate, output.ManaLeechDuration)
end
end
-- Calculate skill DOT components
local dotCfg = {
skillName = skillCfg.skillName,

View File

@@ -517,6 +517,10 @@ function itemLib.buildItemModListForSlotNum(item, baseList, slotNum)
weaponData[value.key] = value.value
end
end
weaponData.AccuracyInc = sumLocal(modList, "Accuracy", "INC", 0)
if weaponData.AccuracyInc > 0 then
modList:NewMod("Accuracy", "MORE", weaponData.AccuracyInc, item.modSource, { type = "Condition", var = (slotNum == 1) and "MainHandAttack" or "OffHandAttack" })
end
for _, mod in ipairs(modList) do
-- Convert accuracy modifiers to local
if mod.name == "Accuracy" and mod.flags == 0 and mod.keywordFlags == 0 and not mod.tagList[1] then

View File

@@ -19,6 +19,7 @@ local formList = {
["^(%d+)%% less"] = "LESS",
["^([%+%-][%d%.]+)%%?"] = "BASE",
["^([%+%-][%d%.]+)%%? to"] = "BASE",
["^([%+%-][%d%.]+)%%? of"] = "BASE",
["^([%+%-][%d%.]+)%%? base"] = "BASE",
["^([%+%-]?[%d%.]+)%%? additional"] = "BASE",
["^you gain ([%d%.]+)"] = "BASE",
@@ -143,7 +144,7 @@ local modNameList = {
["maximum endurance charges"] = "EnduranceChargesMax",
["endurance charge duration"] = "EnduranceChargesDuration",
["endurance, frenzy and power charge duration"] = { "PowerChargesDuration", "FrenzyChargesDuration", "EnduranceChargesDuration" },
-- On hit/kill effects
-- On hit/kill/leech effects
["life gained on kill"] = "LifeOnKill",
["mana gained on kill"] = "ManaOnKill",
["life gained for each enemy hit by attacks"] = { "LifeOnHit", flags = ModFlag.Attack },
@@ -155,6 +156,10 @@ local modNameList = {
["energy shield gained for each enemy hit by attacks"] = { "EnergyShieldOnHit", flags = ModFlag.Attack },
["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 },
["life leeched per second"] = "LifeLeechRate",
["mana leeched per second"] = "ManaLeechRate",
["maximum life per second to maximum life leech rate"] = "MaxLifeLeechRate",
["maximum mana per second to maximum mana leech rate"] = "MaxLifeLeechRate",
-- Projectile modifiers
["projectile"] = "ProjectileCount",
["projectiles"] = "ProjectileCount",
@@ -267,6 +272,7 @@ local modFlagList = {
["with axes"] = { flags = ModFlag.Axe },
["with bows"] = { flags = ModFlag.Bow },
["with claws"] = { flags = ModFlag.Claw },
["dealt with claws"] = { flags = ModFlag.Claw },
["with daggers"] = { flags = ModFlag.Dagger },
["with maces"] = { flags = ModFlag.Mace },
["with staves"] = { flags = ModFlag.Staff },
@@ -343,6 +349,7 @@ local preFlagList = {
-- List of modifier tags
local modTagList = {
["on enemies"] = { },
[" on critical strike"] = { tag = { type = "Condition", var = "CriticalStrike" } },
-- Multipliers
["per power charge"] = { tag = { type = "Multiplier", var = "PowerCharge" } },
["per frenzy charge"] = { tag = { type = "Multiplier", var = "FrenzyCharge" } },
@@ -447,6 +454,7 @@ local modTagList = {
["against enemies on low life"] = { tag = { type = "Condition", var = "EnemyLowLife" }, flags = ModFlag.Hit },
["against enemies that are on low life"] = { tag = { type = "Condition", var = "EnemyLowLife" }, flags = ModFlag.Hit },
["against rare and unique enemies"] = { tag = { type = "Condition", var = "EnemyRareOrUnique" }, flags = ModFlag.Hit },
["against cursed enemies"] = { tag = { type = "Condition", var = "EnemyCursed" }, flags = ModFlag.Hit },
["against bleeding enemies"] = { tag = { type = "Condition", var = "EnemyBleeding" }, flags = ModFlag.Hit },
["against poisoned enemies"] = { tag = { type = "Condition", var = "EnemyPoisoned" }, flags = ModFlag.Hit },
["against hindered enemies"] = { tag = { type = "Condition", var = "EnemyHindered" }, flags = ModFlag.Hit },
@@ -484,7 +492,7 @@ local specialModList = {
["30%% chance to dodge attacks%. 50%% less armour and energy shield, 30%% less chance to block spells and attacks"] = { mod("AttackDodgeChance", "BASE", 30), mod("Armour", "MORE", -50), mod("EnergyShield", "MORE", -50), mod("BlockChance", "MORE", -30), mod("SpellBlockChance", "MORE", -30) },
["maximum life becomes 1, immune to chaos damage"] = { flag("ChaosInoculation") },
["life regeneration is applied to energy shield instead"] = { flag("ZealotsOath") },
["life leech applies instantly%. life regeneration has no effect%."] = { flag("VaalPact"), flag("NoLifeRegen") },
["life leech applies instantly%. life regeneration has no effect%."] = { flag("InstantLifeLeech"), flag("NoLifeRegen") },
["deal no non%-fire damage"] = { flag("DealNoPhysical"), flag("DealNoLightning"), flag("DealNoCold"), flag("DealNoChaos") },
["(%d+)%% of physical, cold and lightning damage converted to fire damage"] = function(num) return { mod("PhysicalDamageConvertToFire", "BASE", num), mod("LightningDamageConvertToFire", "BASE", num), mod("ColdDamageConvertToFire", "BASE", num) } end,
["removes all mana%. spend life instead of mana for skills"] = { mod("Mana", "MORE", -100), flag("BloodMagic") },
@@ -500,6 +508,7 @@ local specialModList = {
}
end,
["projectile attacks deal up to 50%% more damage to targets at the start of their movement, dealing less damage to targets as the projectile travels farther"] = { flag("PointBlank") },
["life leech is applied to energy shield instead"] = { flag("GhostReaver") },
-- Ascendancy notables
["movement skills cost no mana"] = { mod("ManaCost", "MORE", -100, nil, 0, KeywordFlag.Movement) },
["projectiles have (%d+)%% additional chance to pierce targets at the start of their movement, losing this chance as the projectile travels farther"] = function(num) return { mod("PierceChance", "BASE", num, { type = "DistanceRamp", ramp = {{10,1},{120,0}} }) } end,
@@ -529,6 +538,7 @@ local specialModList = {
["you and nearby allies have (%d+)%% increased movement speed"] = function(num) return { mod("MovementSpeed", "INC", num) } end,
["skills from your helmet penetrate (%d+)%% elemental resistances"] = function(num) return { mod("ElementalPenetration", "BASE", num, { type = "SocketedIn", slotName = "Helmet" }) } end,
["skills from your gloves have (%d+)%% increased area of effect"] = function(num) return { mod("AreaRadius", "INC", num, { type = "SocketedIn", slotName = "Gloves" }) } end,
["skills from your boots leech (%d+)%% of damage as life"] = function(num) return { mod("DamageLifeLeech", "BASE", num, { type = "SocketedIn", slotName = "Boots" }) } end,
["(%d+)%% less totem damage per totem"] = function(num) return { mod("Damage", "MORE", -num, nil, 0, KeywordFlag.Totem, { type = "PerStat", stat = "ActiveTotemLimit", div = 1 }) } end,
["poison you inflict with critical strikes deals (%d+)%% more damage"] = function(num) return { mod("PoisonDamageOnCrit", "MORE", 100) } end,
["bleeding you inflict on maimed enemies deals (%d+)%% more damage"] = function(num) return { mod("Damage", "MORE", num, nil, 0, KeywordFlag.Bleed, { type = "Condition", var = "EnemyMaimed"}) } end,
@@ -678,6 +688,9 @@ local specialModList = {
["grants level (%d+) (.+) curse aura during flask effect"] = function(num, _, skill) return { mod("ExtraCurse", "LIST", { name = gemNameLookup[skill:gsub(" skill","")] or "Unknown", level = num }, { type = "Condition", var = "UsingFlask" }) } end,
["passives in radius can be allocated without being connected to your tree"] = { mod("Misc", "LIST", { type = "JewelData", key = "intuitiveLeap", value = true }) },
["your hits inflict decay, dealing (%d+) chaos damage per second for 10 seconds"] = function(num) return { mod("Misc", "LIST", { type = "SkillData", key = "decay", value = num, merge = "MAX" }) } end,
["leech applies instantly on critical strike"] = { flag("InstantLifeLeech", { type = "Condition", var = "CriticalStrike" }), flag("InstantManaLeech", { type = "Condition", var = "CriticalStrike" }) },
["leech applies instantly during flask effect"] = { flag("InstantLifeLeech", { type = "Condition", var = "UsingFlask" }), flag("InstantManaLeech", { type = "Condition", var = "UsingFlask" }) },
["life leech from hits with this weapon applies instantly"] = { flag("InstantLifeLeech", { type = "Condition", var = "XHandAttack" }) },
}
local keystoneList = {
-- List of keystones that can be found on uniques
@@ -726,6 +739,9 @@ local convTypes = {
["converted to cold damage"] = "ConvertToCold",
["converted to fire damage"] = "ConvertToFire",
["converted to chaos damage"] = "ConvertToChaos",
["leeched as life and mana"] = "Leech",
["leeched as life"] = "LifeLeech",
["leeched as mana"] = "ManaLeech",
}
local dmgTypes = {
["physical"] = "Physical",