diff --git a/Classes/CalcsTab.lua b/Classes/CalcsTab.lua index ac0080b4..e55a8458 100644 --- a/Classes/CalcsTab.lua +++ b/Classes/CalcsTab.lua @@ -341,6 +341,11 @@ function CalcsTabClass:CheckFlag(obj) end end end + if obj.haveOutput then + if not self.calcsOutput[obj.haveOutput] or self.calcsOutput[obj.haveOutput] == 0 then + return + end + end return true end diff --git a/Data/Gems/act_dex.lua b/Data/Gems/act_dex.lua index cdb2b8e4..3335acce 100644 --- a/Data/Gems/act_dex.lua +++ b/Data/Gems/act_dex.lua @@ -2835,8 +2835,8 @@ gems["Poacher's Mark"] = { [2] = skill("duration", nil), --"base_skill_effect_duration" [3] = mod("AreaOfEffect", "INC", nil), --"base_skill_area_of_effect_+%" [4] = mod("Evasion", "MORE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse"}), --"evasion_rating_+%_final_from_poachers_mark" - [5] = mod("LifeOnHit", "BASE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Curse" }), --"life_granted_when_hit_by_attacks" - [6] = mod("ManaOnHit", "BASE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Curse" }), --"mana_granted_when_hit_by_attacks" + [5] = mod("SelfLifeOnHit", "BASE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Curse" }), --"life_granted_when_hit_by_attacks" + [6] = mod("SelfManaOnHit", "BASE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Curse" }), --"mana_granted_when_hit_by_attacks" --[7] = "chance_to_grant_frenzy_charge_on_death_%" }, levels = { diff --git a/Data/Gems/act_int.lua b/Data/Gems/act_int.lua index c7cb24cf..3915c762 100644 --- a/Data/Gems/act_int.lua +++ b/Data/Gems/act_int.lua @@ -220,8 +220,8 @@ gems["Assassin's Mark"] = { [2] = skill("duration", nil), --"base_skill_effect_duration" [3] = mod("AreaOfEffect", "INC", nil), --"base_skill_area_of_effect_+%" [4] = mod("SelfExtraCritChance", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), --"additional_chance_to_take_critical_strike_%" - [5] = mod("LifeOnKill", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), --"life_granted_when_killed" - [6] = mod("ManaOnKill", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), --"mana_granted_when_killed" + [5] = mod("SelfLifeOnKill", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), --"life_granted_when_killed" + [6] = mod("SelfManaOnKill", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), --"mana_granted_when_killed" --[7] = "chance_to_grant_power_charge_on_death_%" }, levels = { @@ -3415,6 +3415,59 @@ gems["Raise Spectre"] = { spell = true, minion = true, unsupported = true, + color = 3, + baseFlags = { + }, + skillTypes = { [2] = true, [9] = true, [21] = true, [17] = true, [18] = true, [19] = true, [26] = true, [36] = true, [49] = true, }, + baseMods = { + skill("castTime", 0.85), + --"base_number_of_spectres_allowed" = 1 + --"active_skill_minion_movement_velocity_+%_final" = 55 + --"movement_velocity_cap" = -89 + --"damage_taken_+%_from_arrow_traps_final" = -90 + --"minion_elemental_resistance_%" = 30 + }, + qualityMods = { + --"minion_movement_speed_+%" = 1 + }, + levelMods = { + [1] = skill("manaCost", nil), + --[2] = "active_skill_minion_damage_+%_final" + --[3] = "active_skill_minion_life_+%_final" + --[4] = "active_skill_minion_energy_shield_+%_final" + }, + levels = { + [1] = { 21, -30, -20, -20, }, + [2] = { 23, -25, -19, -19, }, + [3] = { 24, -21, -18, -18, }, + [4] = { 26, -17, -17, -17, }, + [5] = { 27, -14, -16, -16, }, + [6] = { 28, -11, -15, -15, }, + [7] = { 29, -8, -14, -14, }, + [8] = { 30, -6, -13, -13, }, + [9] = { 31, -4, -12, -12, }, + [10] = { 32, -2, -11, -11, }, + [11] = { 33, 0, -10, -10, }, + [12] = { 34, 1, -9, -9, }, + [13] = { 35, 2, -8, -8, }, + [14] = { 36, 3, -7, -7, }, + [15] = { 37, 4, -6, -6, }, + [16] = { 38, 5, -5, -5, }, + [17] = { 39, 6, -4, -4, }, + [18] = { 40, 7, -3, -3, }, + [19] = { 41, 8, -2, -2, }, + [20] = { 42, 10, 0, 0, }, + [21] = { 43, 12, 2, 2, }, + [22] = { 44, 14, 4, 4, }, + [23] = { 44, 16, 6, 6, }, + [24] = { 45, 18, 8, 8, }, + [25] = { 46, 20, 10, 10, }, + [26] = { 47, 22, 12, 12, }, + [27] = { 48, 24, 14, 14, }, + [28] = { 49, 26, 16, 16, }, + [29] = { 50, 28, 18, 18, }, + [30] = { 51, 30, 20, 20, }, + }, } gems["Raise Zombie"] = { intelligence = true, @@ -3422,6 +3475,56 @@ gems["Raise Zombie"] = { spell = true, minion = true, unsupported = true, + color = 3, + baseFlags = { + }, + skillTypes = { [2] = true, [9] = true, [21] = true, [17] = true, [18] = true, [19] = true, [26] = true, [36] = true, [49] = true, }, + baseMods = { + skill("castTime", 0.85), + --"base_number_of_zombies_allowed" = 3 + --"active_skill_minion_damage_+%_final" = 0 + --"display_minion_monster_type" = 1 + }, + qualityMods = { + mod("MinionLife", "INC", 1), --"minion_maximum_life_+%" = 1 + --"minion_movement_speed_+%" = 1 + }, + levelMods = { + [1] = skill("manaCost", nil), + --[2] = "display_minion_monster_level" + }, + levels = { + [1] = { 10, 2, }, + [2] = { 11, 3, }, + [3] = { 12, 5, }, + [4] = { 13, 8, }, + [5] = { 14, 12, }, + [6] = { 16, 16, }, + [7] = { 18, 20, }, + [8] = { 21, 24, }, + [9] = { 24, 28, }, + [10] = { 26, 32, }, + [11] = { 28, 36, }, + [12] = { 30, 40, }, + [13] = { 31, 44, }, + [14] = { 32, 48, }, + [15] = { 33, 52, }, + [16] = { 34, 56, }, + [17] = { 35, 60, }, + [18] = { 36, 64, }, + [19] = { 37, 67, }, + [20] = { 38, 70, }, + [21] = { 38, 72, }, + [22] = { 38, 74, }, + [23] = { 38, 76, }, + [24] = { 39, 78, }, + [25] = { 40, 80, }, + [26] = { 40, 82, }, + [27] = { 41, 84, }, + [28] = { 42, 86, }, + [29] = { 42, 88, }, + [30] = { 42, 90, }, + }, } gems["Righteous Fire"] = { intelligence = true, @@ -4162,6 +4265,54 @@ gems["Summon Raging Spirit"] = { duration = true, fire = true, unsupported = true, + color = 3, + baseFlags = { + }, + skillTypes = { [2] = true, [9] = true, [12] = true, [21] = true, [17] = true, [18] = true, [19] = true, [26] = true, [36] = true, [49] = true, [33] = true, }, + baseMods = { + skill("castTime", 0.5), + skill("duration", 5), --"base_skill_effect_duration" = 5000 + --"base_number_of_raging_spirits_allowed" = 20 + --"active_skill_minion_added_damage_+%_final" = -30 + }, + qualityMods = { + --"minion_movement_speed_+%" = 1 + }, + levelMods = { + [1] = skill("manaCost", nil), + }, + levels = { + [1] = { 4, }, + [2] = { 4, }, + [3] = { 5, }, + [4] = { 5, }, + [5] = { 6, }, + [6] = { 6, }, + [7] = { 6, }, + [8] = { 7, }, + [9] = { 7, }, + [10] = { 8, }, + [11] = { 8, }, + [12] = { 9, }, + [13] = { 9, }, + [14] = { 10, }, + [15] = { 10, }, + [16] = { 10, }, + [17] = { 11, }, + [18] = { 11, }, + [19] = { 11, }, + [20] = { 12, }, + [21] = { 12, }, + [22] = { 13, }, + [23] = { 13, }, + [24] = { 13, }, + [25] = { 14, }, + [26] = { 14, }, + [27] = { 14, }, + [28] = { 15, }, + [29] = { 15, }, + [30] = { 15, }, + }, } gems["Summon Skeletons"] = { intelligence = true, @@ -4170,6 +4321,57 @@ gems["Summon Skeletons"] = { minion = true, duration = true, unsupported = true, + color = 3, + baseFlags = { + }, + skillTypes = { [2] = true, [9] = true, [12] = true, [21] = true, [17] = true, [18] = true, [19] = true, [26] = true, [36] = true, [49] = true, }, + baseMods = { + skill("castTime", 0.8), + --"number_of_melee_skeletons_to_summon" = 2 + skill("duration", 20), --"base_skill_effect_duration" = 20000 + --"active_skill_minion_added_damage_+%_final" = -50 + --"display_minion_monster_type" = 2 + }, + qualityMods = { + mod("Damage", "INC", 1, 0, 0, nil), --"damage_+%" = 1 + }, + levelMods = { + [1] = skill("manaCost", nil), + --[2] = "base_number_of_skeletons_allowed" + --[3] = "display_minion_monster_level" + }, + levels = { + [1] = { 6, 4, 10, }, + [2] = { 7, 4, 13, }, + [3] = { 8, 4, 16, }, + [4] = { 9, 4, 19, }, + [5] = { 10, 4, 22, }, + [6] = { 11, 4, 25, }, + [7] = { 12, 4, 28, }, + [8] = { 12, 4, 32, }, + [9] = { 13, 5, 36, }, + [10] = { 14, 5, 40, }, + [11] = { 15, 5, 44, }, + [12] = { 15, 5, 47, }, + [13] = { 16, 5, 50, }, + [14] = { 17, 5, 53, }, + [15] = { 17, 5, 56, }, + [16] = { 18, 6, 59, }, + [17] = { 19, 6, 62, }, + [18] = { 20, 6, 64, }, + [19] = { 20, 6, 66, }, + [20] = { 21, 6, 68, }, + [21] = { 21, 6, 70, }, + [22] = { 22, 6, 72, }, + [23] = { 22, 6, 74, }, + [24] = { 22, 6, 76, }, + [25] = { 23, 6, 78, }, + [26] = { 23, 6, 80, }, + [27] = { 24, 6, 82, }, + [28] = { 24, 6, 84, }, + [29] = { 25, 6, 86, }, + [30] = { 25, 6, 88, }, + }, } gems["Vaal Summon Skeletons"] = { intelligence = true, @@ -4179,6 +4381,58 @@ gems["Vaal Summon Skeletons"] = { minion = true, duration = true, unsupported = true, + color = 3, + baseFlags = { + }, + skillTypes = { [2] = true, [9] = true, [12] = true, [21] = true, [17] = true, [18] = true, [19] = true, [26] = true, [43] = true, }, + baseMods = { + skill("castTime", 0.8), + --"number_of_leader_skeletons_to_summon" = 1 + skill("duration", 20), --"base_skill_effect_duration" = 20000 + --"display_minion_monster_type" = 2 + }, + qualityMods = { + mod("Damage", "INC", 1, 0, 0, nil), --"damage_+%" = 1 + }, + levelMods = { + --[1] = "number_of_melee_skeletons_to_summon" + --[2] = "number_of_archer_skeletons_to_summon" + --[3] = "number_of_mage_skeletons_to_summon" + --[4] = "base_number_of_skeletons_allowed" + --[5] = "display_minion_monster_level" + }, + levels = { + [1] = { 14, 2, 0, 17, 10, }, + [2] = { 15, 2, 0, 18, 13, }, + [3] = { 15, 3, 0, 19, 16, }, + [4] = { 16, 3, 0, 20, 19, }, + [5] = { 16, 4, 0, 21, 22, }, + [6] = { 17, 4, 0, 22, 25, }, + [7] = { 17, 5, 0, 23, 28, }, + [8] = { 18, 5, 0, 24, 32, }, + [9] = { 18, 5, 1, 25, 36, }, + [10] = { 18, 6, 1, 26, 40, }, + [11] = { 18, 6, 2, 27, 44, }, + [12] = { 19, 6, 2, 28, 47, }, + [13] = { 19, 6, 3, 29, 50, }, + [14] = { 20, 6, 3, 30, 53, }, + [15] = { 20, 7, 3, 31, 56, }, + [16] = { 20, 7, 4, 32, 59, }, + [17] = { 20, 8, 4, 33, 62, }, + [18] = { 21, 8, 4, 34, 64, }, + [19] = { 21, 8, 5, 35, 66, }, + [20] = { 21, 9, 5, 36, 68, }, + [21] = { 22, 9, 5, 37, 70, }, + [22] = { 22, 9, 6, 38, 72, }, + [23] = { 22, 10, 6, 39, 74, }, + [24] = { 23, 10, 6, 40, 76, }, + [25] = { 23, 10, 7, 41, 78, }, + [26] = { 23, 11, 7, 42, 80, }, + [27] = { 24, 11, 7, 43, 82, }, + [28] = { 24, 11, 8, 44, 84, }, + [29] = { 25, 11, 8, 45, 86, }, + [30] = { 25, 12, 8, 46, 88, }, + }, } gems["Tempest Shield"] = { intelligence = true, diff --git a/Data/Uniques/bow.lua b/Data/Uniques/bow.lua index b9f2559d..4c665800 100644 --- a/Data/Uniques/bow.lua +++ b/Data/Uniques/bow.lua @@ -113,7 +113,7 @@ Adds (8-12) to (16-24) Physical Damage (14-20)% increased Attack Speed (14-20)% increased Totem Life (14-20)% increased Totem Placement speed -Can summon 1 additional Siege Ballista Totem per 200 Dexterity +Can have 1 additional Siege Ballista Totem per 200 Dexterity Adds 1 to 3 Physical Damage to Attacks per 25 Dexterity ]],[[ Lioneye's Glare diff --git a/Data/Uniques/shield.lua b/Data/Uniques/shield.lua index d5a76d28..72fc804e 100644 --- a/Data/Uniques/shield.lua +++ b/Data/Uniques/shield.lua @@ -101,7 +101,7 @@ Requires Level 17, 46 Str 0.5% of Life Regenerated per Second 15% increased Area of Effect for Skills used by Totems {variant:1}1% of Damage Leeched as Life for Skills used by Totems -{variant:2}0.5% of Damage dealt by Totems is Leeched to you as Life +{variant:2}0.5% of Damage dealt by your Totems is Leeched to you as Life ]],[[ Tukohama's Fortress Ebony Tower Shield diff --git a/Modules/Build.lua b/Modules/Build.lua index 364750fd..d885dcfc 100644 --- a/Modules/Build.lua +++ b/Modules/Build.lua @@ -268,16 +268,22 @@ function buildMode:Init(dbFileName, buildName) { stat = "LifeUnreserved", label = "Unreserved Life", fmt = "d", condFunc = function(v,o) return v < o.Life end, compPercent = true }, { stat = "LifeUnreservedPercent", label = "Unreserved Life", fmt = "d%%", condFunc = function(v,o) return v < 100 end }, { stat = "LifeRegen", label = "Life Regen", fmt = ".1f" }, + { stat = "LifeLeechGainRate", label = "Life Leech/On Hit Rate", fmt = ".1f", compPercent = true }, + { stat = "LifeLeechGainPerHit", label = "Life Leech/Gain per Hit", fmt = ".1f", compPercent = true }, { }, { stat = "Mana", label = "Total Mana", fmt = "d", compPercent = true }, { stat = "Spec:ManaInc", label = "%Inc Mana from Tree", fmt = "d%%" }, { stat = "ManaUnreserved", label = "Unreserved Mana", fmt = "d", condFunc = function(v,o) return v < o.Mana end, compPercent = true }, { stat = "ManaUnreservedPercent", label = "Unreserved Mana", fmt = "d%%", condFunc = function(v,o) return v < 100 end }, { stat = "ManaRegen", label = "Mana Regen", fmt = ".1f" }, + { stat = "ManaLeechGainRate", label = "Mana Leech/On Hit Rate", fmt = ".1f", compPercent = true }, + { stat = "ManaLeechGainPerHit", label = "Mana Leech/Gain per Hit", fmt = ".1f", compPercent = true }, { }, { stat = "EnergyShield", label = "Energy Shield", fmt = "d", compPercent = true }, { stat = "Spec:EnergyShieldInc", label = "%Inc ES from Tree", fmt = "d%%" }, { stat = "EnergyShieldRegen", label = "Energy Shield Regen", fmt = ".1f" }, + { stat = "EnergyShieldLeechGainRate", label = "ES Leech/On Hit Rate", fmt = ".1f", compPercent = true }, + { stat = "EnergyShieldLeechGainPerHit", label = "ES Leech/Gain per Hit", fmt = ".1f", compPercent = true }, { stat = "Evasion", label = "Evasion rating", fmt = "d", compPercent = true }, { stat = "Spec:EvasionInc", label = "%Inc Evasion from Tree", fmt = "d%%" }, { stat = "EvadeChance", label = "Evade Chance", fmt = "d%%" }, diff --git a/Modules/CalcSections.lua b/Modules/CalcSections.lua index 26a76644..25514ee4 100644 --- a/Modules/CalcSections.lua +++ b/Modules/CalcSections.lua @@ -503,21 +503,114 @@ return { { modName = "Duration", cfg = "decay" }, }, }, } }, +{ 1, "LeechGain", 1, "Leech & Gain on Hit", data.colorCodes.OFFENCE, { + { label = "Life Leech Cap", flag = "leechLife", { format = "{1:output:MaxLifeLeechRate}", + { breakdown = "MaxLifeLeechRate" }, + { modName = "MaxLifeLeechRate" }, + }, }, + { label = "Life Leech Rate", flag = "leechLife", notFlag = "showAverage", { format = "{1:output:LifeLeechRate}", + { breakdown = "LifeLeech" }, + { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Totem modifiers", flag = "totem", modName = { "DamageLifeLeechToPlayer" }, modType = "BASE", cfg = "skill" }, + { label = "Enemy modifiers", modName = { "SelfDamageLifeLeech" }, modType = "BASE", enemy = true }, + }, }, + { label = "Life Leech per Hit", flagList = { "leechLife", "showAverage" }, { format = "{1:output:LifeLeechPerHit}", + { breakdown = "LifeLeech" }, + { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Totem modifiers", flag = "totem", modName = { "DamageLifeLeechToPlayer" }, modType = "BASE", cfg = "skill" }, + { label = "Enemy modifiers", modName = { "SelfDamageLifeLeech" }, modType = "BASE", enemy = true }, + }, }, + { label = "Life Gain Rate", notFlag = "showAverage", haveOutput = "LifeOnHitRate", { format = "{1:output:LifeOnHitRate}", + { label = "Player modifiers", notFlag = "attack", modName = "LifeOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = { "SelfLifeOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, + }, }, + { label = "Life Gain per Hit", flag = "showAverage", haveOutput = "LifeOnHit", { format = "{1:output:LifeOnHit}", + { label = "Player modifiers", notFlag = "attack", modName = "LifeOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = { "SelfLifeOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, + }, }, + { label = "ES Leech Cap", flag = "leechES", { format = "{1:output:MaxEnergyShieldLeechRate}", + { breakdown = "MaxEnergyShieldLeechRate" }, + { modName = "MaxLifeLeechRate" }, + }, }, + { label = "ES Leech Rate", flag = "leechES", notFlag = "showAverage", { format = "{1:output:EnergyShieldLeechRate}", + { breakdown = "EnergyShieldLeech" }, + { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Totem modifiers", flag = "totem", modName = { "DamageLifeLeechToPlayer" }, modType = "BASE", cfg = "skill" }, + { label = "Enemy modifiers", modName = { "SelfDamageLifeLeech" }, modType = "BASE", enemy = true }, + }, }, + { label = "ES Leech per Hit", flagList = { "leechES", "showAverage" }, { format = "{1:output:EnergyShieldLeechPerHit}", + { breakdown = "EnergyShieldLeech" }, + { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Totem modifiers", flag = "totem", modName = { "DamageLifeLeechToPlayer" }, modType = "BASE", cfg = "skill" }, + { label = "Enemy modifiers", modName = { "SelfDamageLifeLeech" }, modType = "BASE", enemy = true }, + }, }, + { label = "ES Gain Rate", notFlag = "showAverage", haveOutput = "EnergyShieldOnHitRate", { format = "{1:output:EnergyShieldOnHitRate}", + { label = "Player modifiers", notFlag = "attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = { "SelfEnergyShieldOnHit" }, modType = "BASE", enemy = true }, + }, }, + { label = "ES Gain per Hit", flag = "showAverage", haveOutput = "EnergyShieldOnHit", { format = "{1:output:EnergyShieldOnHit}", + { label = "Player modifiers", notFlag = "attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = { "SelfEnergyShieldOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, + }, }, + { label = "Mana Leech Cap", flag = "leechMana", { format = "{1:output:MaxManaLeechRate}", + { breakdown = "MaxManaLeechRate" }, + { modName = "MaxManaLeechRate" }, + }, }, + { label = "Mana Leech Rate", flag = "leechMana", notFlag = "showAverage", { format = "{1:output:ManaLeechRate}", + { breakdown = "ManaLeech" }, + { label = "Player modifiers", notFlag = "attack", modName = { "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = { "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = { "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = { "SelfDamageManaLeech" }, modType = "BASE", cfg = "skill", enemy = true }, + }, }, + { label = "Mana Leech per Hit", flagList = { "leechMana", "showAverage" }, { format = "{1:output:ManaLeechPerHit}", + { breakdown = "ManaLeech" }, + { label = "Player modifiers", notFlag = "attack", modName = { "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = { "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = { "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = { "SelfDamageManaLeech" }, modType = "BASE", enemy = true }, + }, }, + { label = "Mana Gain Rate", notFlag = "showAverage", haveOutput = "ManaOnHitRate", { format = "{1:output:ManaOnHitRate}", + { label = "Player modifiers", notFlag = "attack", modName = "ManaOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = { "SelfManaOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, + }, }, + { label = "Mana Gain per Hit", flag = "showAverage", haveOutput = "ManaOnHit", { format = "{1:output:ManaOnHit}", + { label = "Player modifiers", notFlag = "attack", modName = "ManaOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = { "SelfManaOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, + }, }, +} }, { 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" }, + { breakdown = "MainHand.ShockChance" }, + { breakdown = "OffHand.ShockChance" }, { breakdown = "ShockChance" }, { label = "Player modifiers", modName = "EnemyShockChance", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfShockChance", enemy = true }, }, }, { label = "Shock Dur. Mod", flag = "shock", { format = "x {2:output:ShockDurationMod}", - { breakdown = "MainHand.ShockDPS" }, - { breakdown = "OffHand.ShockDPS" }, - { breakdown = "ShockDPS" }, + { breakdown = "MainHand.ShockDPS" }, + { breakdown = "OffHand.ShockDPS" }, + { breakdown = "ShockDPS" }, { label = "Player modifiers", modName = "EnemyShockDuration", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfShockDuration", enemy = true }, }, }, diff --git a/Modules/Calcs.lua b/Modules/Calcs.lua index e3607182..26667178 100644 --- a/Modules/Calcs.lua +++ b/Modules/Calcs.lua @@ -1815,10 +1815,31 @@ local function performCalcs(env) -- Leech caps if modDB:Sum("FLAG", nil, "GhostReaver") then output.MaxEnergyShieldLeechRate = output.EnergyShield * modDB:Sum("BASE", nil, "MaxLifeLeechRate") / 100 + if breakdown then + breakdown.MaxEnergyShieldLeechRate = { + s_format("%d ^8(maximum energy shield)", output.EnergyShield), + s_format("x %d%% ^8(percenage of life to maximum leech rate)", modDB:Sum("BASE", nil, "MaxLifeLeechRate")), + s_format("= %.1f", output.MaxEnergyShieldLeechRate) + } + end else output.MaxLifeLeechRate = output.Life * modDB:Sum("BASE", nil, "MaxLifeLeechRate") / 100 + if breakdown then + breakdown.MaxLifeLeechRate = { + s_format("%d ^8(maximum life)", output.Life), + s_format("x %d%% ^8(percenage of life to maximum leech rate)", modDB:Sum("BASE", nil, "MaxLifeLeechRate")), + s_format("= %.1f", output.MaxLifeLeechRate) + } + end end output.MaxManaLeechRate = output.Mana * modDB:Sum("BASE", nil, "MaxManaLeechRate") / 100 + if breakdown then + breakdown.MaxManaLeechRate = { + s_format("%d ^8(maximum mana)", output.Mana), + s_format("x %d%% ^8(percenage of mana to maximum leech rate)", modDB:Sum("BASE", nil, "MaxManaLeechRate")), + s_format("= %.1f", output.MaxManaLeechRate) + } + end -- Other defences: block, dodge, stun recovery/avoidance do @@ -1881,13 +1902,13 @@ local function performCalcs(env) local skillData = env.mainSkill.skillData local skillFlags = env.mainSkill.skillFlags local skillCfg = env.mainSkill.skillCfg - if env.mainSkill.skillFlags.attack then + if skillFlags.attack then env.mode_skillType = "ATTACK" else env.mode_skillType = "SPELL" end - if env.mainSkill.skillData.showAverage then - env.mode_average = true + if skillData.showAverage then + skillFlags.showAverage = true else skillFlags.notAverage = true end @@ -2363,6 +2384,10 @@ local function performCalcs(env) -- Calculate hit damage for each damage type local totalHitMin, totalHitMax = 0, 0 local totalCritMin, totalCritMax = 0, 0 + output.LifeLeech = 0 + output.LifeLeechInstant = 0 + output.ManaLeech = 0 + output.ManaLeechInstant = 0 for pass = 1, 2 do -- Pass 1 is critical strike damage, pass 2 is non-critical strike condList["CriticalStrike"] = (pass == 1) @@ -2429,13 +2454,26 @@ local function performCalcs(env) 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 + if skillFlags.mine or skillFlags.trap or skillFlags.totem then + if not modDB:Sum("FLAG", cfg, "CannotLeechLife") then + local lifeLeech = modDB:Sum("BASE", cfg, "DamageLifeLeechToPlayer") + if lifeLeech > 0 then + lifeLeechTotal = lifeLeechTotal + (min + max) / 2 * lifeLeech / 100 + end + end + else + if not modDB:Sum("FLAG", cfg, "CannotLeechLife") then + local lifeLeech = modDB:Sum("BASE", cfg, "DamageLifeLeech", damageType.."DamageLifeLeech", isElemental[damageType] and "ElementalDamageLifeLeech" or nil) + enemyDB:Sum("BASE", nil, "SelfDamageLifeLeech") / 100 + if lifeLeech > 0 then + lifeLeechTotal = lifeLeechTotal + (min + max) / 2 * lifeLeech / 100 + end + end + if not modDB:Sum("FLAG", cfg, "CannotLeechMana") then + local manaLeech = modDB:Sum("BASE", cfg, "DamageManaLeech", damageType.."DamageManaLeech", isElemental[damageType] and "ElementalDamageManaLeech" or nil) + enemyDB:Sum("BASE", nil, "SelfDamageManaLeech") / 100 + if manaLeech > 0 then + manaLeechTotal = manaLeechTotal + (min + max) / 2 * manaLeech / 100 + end + end end else min, max = 0, 0 @@ -2459,28 +2497,16 @@ 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 + local portion = (pass == 1) and (output.CritChance / 100) or (1 - output.CritChance / 100) + if modDB:Sum("FLAG", cfg, "InstantLifeLeech") then + output.LifeLeechInstant = output.LifeLeechInstant + lifeLeechTotal * portion 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 + output.LifeLeech = output.LifeLeech + lifeLeechTotal * portion + end + if modDB:Sum("FLAG", cfg, "InstantManaLeech") then + output.ManaLeechInstant = output.ManaLeechInstant + manaLeechTotal * portion + else + output.ManaLeech = output.ManaLeech + manaLeechTotal * portion end end output.TotalMin = totalHitMin @@ -2493,14 +2519,29 @@ 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 + + -- Calculate leech + output.LifeLeechDuration = output.LifeLeech / (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.LifeLeechInstantRate = output.LifeLeechInstant * hitRate + output.ManaLeechDuration = output.ManaLeech / globalOutput.Mana / 0.02 output.ManaLeechInstances = output.ManaLeechDuration * hitRate - output.ManaLeechInstantRate = (output.ManaLeechInstant or 0) * hitRate + output.ManaLeechInstantRate = output.ManaLeechInstant * hitRate + + -- Calculate gain on hit + if skillFlags.mine or skillFlags.trap or skillFlags.totem then + output.LifeOnHit = 0 + output.EnergyShieldOnHit = 0 + output.ManaOnHit = 0 + else + output.LifeOnHit = modDB:Sum("BASE", skillCfg, "LifeOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfLifeOnHit") + output.EnergyShieldOnHit = modDB:Sum("BASE", skillCfg, "EnergyShieldOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfEnergyShieldOnHit") + output.ManaOnHit = modDB:Sum("BASE", skillCfg, "ManaOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfManaOnHit") + end + output.LifeOnHitRate = output.LifeOnHit * hitRate + output.EnergyShieldOnHitRate = output.EnergyShieldOnHit * hitRate + output.ManaOnHitRate = output.ManaOnHit * hitRate -- Calculate average damage and final DPS output.AverageHit = (totalHitMin + totalHitMax) / 2 * (1 - output.CritChance / 100) + (totalCritMin + totalCritMax) / 2 * output.CritChance / 100 @@ -2533,10 +2574,18 @@ local function performCalcs(env) combineStat("TotalDPS", "DPS") combineStat("LifeLeechDuration", "DPS") combineStat("LifeLeechInstances", "DPS") + combineStat("LifeLeechInstant", "DPS") combineStat("LifeLeechInstantRate", "DPS") combineStat("ManaLeechDuration", "DPS") combineStat("ManaLeechInstances", "DPS") + combineStat("ManaLeechInstant", "DPS") combineStat("ManaLeechInstantRate", "DPS") + combineStat("LifeOnHit", "DPS") + combineStat("LifeOnHitRate", "DPS") + combineStat("EnergyShieldOnHit", "DPS") + combineStat("EnergyShieldOnHitRate", "DPS") + combineStat("ManaOnHit", "DPS") + combineStat("ManaOnHitRate", "DPS") if skillFlags.bothWeaponAttack then if breakdown then breakdown.AverageDamage = { } @@ -2551,7 +2600,7 @@ local function performCalcs(env) end end if env.mode == "CALCS" then - if env.mode_average then + if skillData.showAverage then output.DisplayDamage = s_format("%.1f average damage", output.AverageDamage) else output.DisplayDamage = s_format("%.1f DPS", output.TotalDPS) @@ -2577,52 +2626,88 @@ local function performCalcs(env) -- 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) + output.LifeLeechRate = 0 + output.LifeLeechPerHit = 0 + output.EnergyShieldLeechInstanceRate = output.EnergyShield * 0.02 * calcMod(modDB, skillCfg, "LifeLeechRate") + output.EnergyShieldLeechRate = output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.EnergyShieldLeechInstanceRate, output.MaxEnergyShieldLeechRate) + output.EnergyShieldLeechPerHit = m_min(output.EnergyShieldLeechInstanceRate, output.MaxEnergyShieldLeechRate) * output.LifeLeechDuration + output.LifeLeechInstant else - output.LifeLeechRate = output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.Life * 0.02 * calcMod(modDB, skillCfg, "LifeLeechRate"), output.MaxLifeLeechRate) + output.LifeLeechInstanceRate = output.Life * 0.02 * calcMod(modDB, skillCfg, "LifeLeechRate") + output.LifeLeechRate = output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.LifeLeechInstanceRate, output.MaxLifeLeechRate) + output.LifeLeechPerHit = m_min(output.LifeLeechInstanceRate, output.MaxLifeLeechRate) * output.LifeLeechDuration + output.LifeLeechInstant + output.EnergyShieldLeechRate = 0 + output.EnergyShieldLeechPerHit = 0 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 + output.ManaLeechInstanceRate = output.Mana * 0.02 * calcMod(modDB, skillCfg, "ManaLeechRate") + output.ManaLeechRate = output.ManaLeechInstantRate + m_min(output.ManaLeechInstances * output.ManaLeechInstanceRate, output.MaxManaLeechRate) + output.ManaLeechPerHit = m_min(output.ManaLeechInstanceRate, output.MaxManaLeechRate) * output.ManaLeechDuration + output.ManaLeechInstant + skillFlags.leechES = output.EnergyShieldLeechRate > 0 + skillFlags.leechLife = output.LifeLeechRate > 0 skillFlags.leechMana = output.ManaLeechRate > 0 + if skillData.showAverage then + output.LifeLeechGainPerHit = output.LifeLeechPerHit + output.LifeOnHit + output.EnergyShieldLeechGainPerHit = output.EnergyShieldLeechPerHit + output.EnergyShieldOnHit + output.ManaLeechGainPerHit = output.ManaLeechPerHit + output.ManaOnHit + else + output.LifeLeechGainRate = output.LifeLeechRate + output.LifeOnHitRate + output.EnergyShieldLeechGainRate = output.EnergyShieldLeechRate + output.EnergyShieldOnHitRate + output.ManaLeechGainRate = output.ManaLeechRate + output.ManaOnHitRate + end if breakdown then - local function leechBreakdown(instant, instances, pool, rate, max, dur) + local function leechBreakdown(instant, instantRate, 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)) + if skillData.showAverage then + if instant > 0 then + t_insert(out, s_format("Instant Leech: %.1f", instant)) 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)) + if instances > 0 then + t_insert(out, "Total leeched 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("x %.2fs ^8(instance duration)", dur)) + t_insert(out, s_format("= %.1f", pool * 0.02 * rateMod * 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)) + else + if instantRate > 0 then + t_insert(out, s_format("Instant Leech per second: %.1f", instantRate)) + 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 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) + breakdown.LifeLeech = leechBreakdown(output.LifeLeechInstant, output.LifeLeechInstantRate, output.LifeLeechInstances, output.Life, "LifeLeechRate", output.MaxLifeLeechRate, output.LifeLeechDuration) + end + if skillFlags.leechES then + breakdown.EnergyShieldLeech = leechBreakdown(output.LifeLeechInstant, output.LifeLeechInstantRate, output.LifeLeechInstances, output.EnergyShield, "LifeLeechRate", output.MaxEnergyShieldLeechRate, output.LifeLeechDuration) end if skillFlags.leechMana then - breakdown.ManaLeechRate = leechBreakdown(output.ManaLeechInstantRate, output.ManaLeechInstances, output.Mana, "ManaLeechRate", output.MaxManaLeechRate, output.ManaLeechDuration) + breakdown.ManaLeech = leechBreakdown(output.ManaLeechInstant, output.ManaLeechInstantRate, output.ManaLeechInstances, output.Mana, "ManaLeechRate", output.MaxManaLeechRate, output.ManaLeechDuration) end end @@ -2816,6 +2901,7 @@ local function performCalcs(env) skillFlags.duration = true if not env.mainSkill.bleedCfg then env.mainSkill.bleedCfg = { + skillName = skillCfg.skillName, slotName = skillCfg.slotName, flags = bor(band(skillCfg.flags, ModFlag.SourceMask), ModFlag.Dot, skillData.dotIsSpell and ModFlag.Spell or 0), keywordFlags = bor(skillCfg.keywordFlags, KeywordFlag.Bleed) @@ -2868,6 +2954,7 @@ local function performCalcs(env) skillFlags.duration = true if not env.mainSkill.poisonCfg then env.mainSkill.poisonCfg = { + skillName = skillCfg.skillName, slotName = skillCfg.slotName, flags = bor(band(skillCfg.flags, ModFlag.SourceMask), ModFlag.Dot, skillData.dotIsSpell and ModFlag.Spell or 0), keywordFlags = bor(skillCfg.keywordFlags, KeywordFlag.Poison) @@ -2896,7 +2983,7 @@ local function performCalcs(env) local durationMod = calcMod(modDB, dotCfg, "Duration") * calcMod(enemyDB, nil, "SelfPoisonDuration") globalOutput.PoisonDuration = durationBase * durationMod * debuffDurationMult output.PoisonDamage = output.PoisonDPS * globalOutput.PoisonDuration - if env.mode_average then + if skillData.showAverage then output.TotalPoisonAverageDamage = output.HitChance / 100 * output.PoisonChance / 100 * output.PoisonDamage else output.TotalPoisonDPS = output.HitChance / 100 * output.PoisonChance / 100 * output.PoisonDamage * (globalOutput.HitSpeed or globalOutput.Speed) * (skillData.dpsMultiplier or 1) @@ -2955,6 +3042,7 @@ local function performCalcs(env) skillFlags.ignite = true if not env.mainSkill.igniteCfg then env.mainSkill.igniteCfg = { + skillName = skillCfg.skillName, slotName = skillCfg.slotName, flags = bor(band(skillCfg.flags, ModFlag.SourceMask), ModFlag.Dot, skillData.dotIsSpell and ModFlag.Spell or 0), keywordFlags = skillCfg.keywordFlags, @@ -2980,7 +3068,7 @@ local function performCalcs(env) globalOutput.IgniteDuration = 4 * (1 + incDur / 100) * moreDur / burnRateMod * debuffDurationMult if skillFlags.igniteCanStack then output.IgniteDamage = output.IgniteDPS * globalOutput.IgniteDuration - if env.mode_average then + if skillData.showAverage then output.TotalIgniteAverageDamage = output.HitChance / 100 * output.IgniteChance / 100 * output.IgniteDamage else output.TotalIgniteDPS = output.HitChance / 100 * output.IgniteChance / 100 * output.IgniteDamage * (globalOutput.HitSpeed or globalOutput.Speed) * (skillData.dpsMultiplier or 1) @@ -3106,7 +3194,7 @@ local function performCalcs(env) combineStat("PoisonChance", "AVERAGE") combineStat("PoisonDPS", "CHANCE", "PoisonChance") combineStat("PoisonDamage", "CHANCE", "PoisonChance") - if env.mode_average then + if skillData.showAverage then combineStat("TotalPoisonAverageDamage", "DPS") else combineStat("TotalPoisonDPS", "DPS") @@ -3115,7 +3203,7 @@ local function performCalcs(env) combineStat("IgniteDPS", "CHANCE", "IgniteChance") if skillFlags.igniteCanStack then combineStat("IgniteDamage", "CHANCE", "IgniteChance") - if env.mode_average then + if skillData.showAverage then combineStat("TotalIgniteAverageDamage", "DPS") else combineStat("TotalIgniteDPS", "DPS") @@ -3171,10 +3259,10 @@ local function performCalcs(env) end -- Calculate combined DPS estimate, including DoTs - local baseDPS = output[(env.mode_average and "AverageDamage") or "TotalDPS"] + output.TotalDot + local baseDPS = output[(skillData.showAverage and "AverageDamage") or "TotalDPS"] + output.TotalDot output.CombinedDPS = baseDPS if skillFlags.poison then - if env.mode_average then + if skillData.showAverage then output.CombinedDPS = output.CombinedDPS + output.TotalPoisonAverageDamage output.WithPoisonAverageDamage = baseDPS + output.TotalPoisonAverageDamage else @@ -3184,7 +3272,7 @@ local function performCalcs(env) end if skillFlags.ignite then if skillFlags.igniteCanStack then - if env.mode_average then + if skillData.showAverage then output.CombinedDPS = output.CombinedDPS + output.TotalIgniteAverageDamage output.WithIgniteAverageDamage = baseDPS + output.TotalIgniteAverageDamage else @@ -3345,9 +3433,11 @@ function calcs.buildOutput(build, mode) local specCfg = { source = "Tree" } - for _, stat in pairs({"Life", "Mana", "Armour", "Evasion", "EnergyShield"}) do - output["Spec:"..stat.."Inc"] = env.modDB:Sum("INC", specCfg, stat) - end + output["Spec:LifeInc"] = env.modDB:Sum("INC", specCfg, "Life") + output["Spec:ManaInc"] = env.modDB:Sum("INC", specCfg, "Mana") + output["Spec:ArmourInc"] = env.modDB:Sum("INC", specCfg, "Armour", "ArmourAndEvasion") + output["Spec:EvasionInc"] = env.modDB:Sum("INC", specCfg, "Evasion", "ArmourAndEvasion") + output["Spec:EnergyShieldInc"] = env.modDB:Sum("INC", specCfg, "EnergyShield") env.conditionsUsed = { } local function addCond(var, mod) diff --git a/Modules/ItemTools.lua b/Modules/ItemTools.lua index e976ca78..9650223e 100644 --- a/Modules/ItemTools.lua +++ b/Modules/ItemTools.lua @@ -532,8 +532,12 @@ function itemLib.buildItemModListForSlotNum(item, baseList, slotNum) 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 + -- Convert accuracy, L/MGoH and PAD Leech modifiers to local + if ( + (mod.name == "Accuracy" and mod.flags == 0) or + ((mod.name == "LifeOnHit" or mod.name == "ManaOnHit") and mod.flags == ModFlag.Attack) or + ((mod.name == "PhysicalDamageLifeLeech" or mod.name == "PhysicalDamageManaLeech") and mod.flags == ModFlag.Attack) + ) and mod.keywordFlags == 0 and not mod.tagList[1] then mod.tagList[1] = { type = "Condition", var = (slotNum == 1) and "MainHandAttack" or "OffHandAttack" } end end diff --git a/Modules/ModParser.lua b/Modules/ModParser.lua index 2accd191..29086696 100644 --- a/Modules/ModParser.lua +++ b/Modules/ModParser.lua @@ -114,7 +114,7 @@ local modNameList = { ["to avoid being chilled"] = "AvoidChilled", ["to avoid being ignited"] = "AvoidIgnite", ["to avoid elemental status ailments"] = { "AvoidShock", "AvoidFrozen", "AvoidChilled", "AvoidIgnite" }, - ["damage is taken from mana before life"] = { "DamageTakenFromManaBeforeLife" }, + ["damage is taken from mana before life"] = "DamageTakenFromManaBeforeLife", -- Stun modifiers ["stun recovery"] = "StunRecovery", ["stun and block recovery"] = "StunRecovery", @@ -167,7 +167,7 @@ local modNameList = { ["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", + ["maximum mana per second to maximum mana leech rate"] = "MaxManaLeechRate", -- Projectile modifiers ["projectile"] = "ProjectileCount", ["projectiles"] = "ProjectileCount", @@ -221,6 +221,7 @@ local modNameList = { ["wand damage"] = { "Damage", flags = ModFlag.Wand }, ["wand physical damage"] = { "PhysicalDamage", flags = ModFlag.Wand }, ["claw physical damage"] = { "PhysicalDamage", flags = ModFlag.Claw }, + ["sword physical damage"] = { "PhysicalDamage", flags = ModFlag.Sword }, ["damage over time"] = { "Damage", flags = ModFlag.Dot }, ["physical damage over time"] = { "PhysicalDamage", flags = ModFlag.Dot }, ["burning damage"] = { "FireDamage", flags = ModFlag.Dot }, @@ -602,6 +603,7 @@ local specialModList = { ["can have up to (%d+) additional remote mines? placed at a time"] = function(num) return { mod("ActiveMineLimit", "BASE", num) } end, ["can have up to (%d+) additional totems? summoned at a time"] = function(num) return { mod("ActiveTotemLimit", "BASE", num) } end, ["enemies can have 1 additional curse"] = { mod("EnemyCurseLimit", "BASE", 1) }, + ["([%d%.]+)%% of damage dealt by y?o?u?r? ?totems is leeched to you as life"] = function(num) return { mod("DamageLifeLeechToPlayer", "BASE", num, nil, 0, KeywordFlag.Totem) } end, -- Other modifiers ["cannot be stunned"] = { mod("AvoidStun", "BASE", 100) }, ["cannot be shocked"] = { mod("AvoidShock", "BASE", 100) }, @@ -739,6 +741,11 @@ local specialModList = { mod("ColdPenetration", "BASE", num, { type = "Condition", var = "UncappedColdResistIsHighest" }), mod("FirePenetration", "BASE", num, { type = "Condition", var = "UncappedFireResistIsHighest" }), } end, + ["can [hs][au][vm][em]o?n? 1 additional siege ballista totem per (%d+) dexterity"] = function(num) return { mod("ActiveTotemLimit", "BASE", 1, { type = "SkillName", skillName = "Siege Ballista" }, { type = "PerStat", stat = "Dex", div = num }) } end, + ["cannot leech life"] = { flag("CannotLeechLife") }, + ["cannot leech mana"] = { flag("CannotLeechMana") }, + ["cannot leech when on low life"] = { flag("CannotLeechLife", { type = "Condition", var = "LowLife" }), flag("CannotLeechMana", { type = "Condition", var = "LowLife" }) }, + ["cannot leech life from critical strikes"] = { flag("CannotLeechLife", { type = "Condition", var = "CriticalStrike" }) }, } local keystoneList = { -- List of keystones that can be found on uniques diff --git a/README.md b/README.md index 0ed62cbd..5129b0bf 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,18 @@ 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.3.24 - 2017/04/05 +This update adds support for Life/Mana Leech and Life/Mana/ES Gain on Hit: + * All sources of Leech and Gain on Hit are supported, including "Damage dealt by your Totems is Leeched to you" + * For skills with a known hit rate (i.e skills that show DPS instead of Average Damage), the combined rate of recovery + from Leech and Gain on Hit is displayed in the sidebar + * For other skills, the total amount leeched/gained from one hit is displayed instead + * Detailed breakdowns of Leech and Gain on Hit can be found in the new "Leech & Gain on Hit" section in the Calcs tab + Other changes: + * Added support for the additional Siege Ballista totems modifier on Iron Commander + * The "%Inc Armour from Tree" and "%Inc Evasion from Tree" sidebar stats now include "increased Evasion Rating and Armour" + * Various minor tweaks and fixes + ### 1.3.23 - 2017/03/31 * Helmets and Boots can now be enchanted via the new "Apply Enchantment..." button that appears when viewing the item * Added support for more helmet enchants; the vast majority of them should now work diff --git a/changelog.txt b/changelog.txt index 2e741de9..aeed9398 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,14 @@ +VERSION[1.3.24][2017/04/05] +This update adds support for Life/Mana Leech and Life/Mana/ES Gain on Hit: + * All sources of Leech and Gain on Hit are supported, including "Damage dealt by your Totems is Leeched to you" + * For skills with a known hit rate (i.e skills that show DPS instead of Average Damage), the combined rate of recovery + from Leech and Gain on Hit is displayed in the sidebar + * For other skills, the total amount leeched/gained from one hit is displayed instead + * Detailed breakdowns of Leech and Gain on Hit can be found in the new "Leech & Gain on Hit" section in the Calcs tab + Other changes: + * Added support for the additional Siege Ballista totems modifier on Iron Commander + * The "%Inc Armour from Tree" and "%Inc Evasion from Tree" sidebar stats now include "increased Evasion Rating and Armour" + * Various minor tweaks and fixes VERSION[1.3.23][2017/03/31] * Helmets and Boots can now be enchanted via the new "Apply Enchantment..." button that appears when viewing the item * Added support for more helmet enchants; the vast majority of them should now work diff --git a/manifest.xml b/manifest.xml index 3a08565f..f82bcee7 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,18 +1,18 @@ - + - + - + @@ -42,15 +42,15 @@ - + - - + + - + - + @@ -60,8 +60,8 @@ - - + + @@ -91,7 +91,7 @@ - + @@ -101,13 +101,13 @@ - + - + diff --git a/runtime-win32.zip b/runtime-win32.zip index edbdd50f..9c8339bc 100644 Binary files a/runtime-win32.zip and b/runtime-win32.zip differ