@@ -6975,10 +6975,89 @@ skills["MoltenStrike"] = {
6975
6975
projectile = true,
6976
6976
area = true,
6977
6977
},
6978
+ {
6979
+ name = "Average Balls Hitting",
6980
+ melee = false,
6981
+ projectile = true,
6982
+ area = true,
6983
+ },
6978
6984
},
6985
+ preDamageFunc = function(activeSkill, output, breakdown)
6986
+ local skillCfg = activeSkill.skillCfg
6987
+ local skillData = activeSkill.skillData
6988
+ local skillPart = activeSkill.skillPart
6989
+ local skillModList = activeSkill.skillModList
6990
+ local t_insert = table.insert
6991
+ local s_format = string.format
6992
+
6993
+ -- melee part doesn't need to calc balls
6994
+ if skillPart == 1 then
6995
+ return
6996
+ end
6997
+
6998
+ local enemyRadius = skillModList:Override(skillCfg, "EnemyRadius") or skillModList:Sum("BASE", skillCfg, "EnemyRadius")
6999
+ local ballRadius = output.AreaOfEffectRadius
7000
+ local innerRadius = output.AreaOfEffectRadiusSecondary
7001
+ local outerRadius = output.AreaOfEffectRadiusTertiary
7002
+
7003
+ -- logic adapted from MoldyDwarf's calculator
7004
+ local hitRange = enemyRadius + ballRadius - innerRadius
7005
+ local landingRange = outerRadius - innerRadius
7006
+ local overlapChance = math.min(1, hitRange / landingRange)
7007
+ output.OverlapChance = overlapChance * 100
7008
+
7009
+ if breakdown then
7010
+ breakdown.OverlapChance = { }
7011
+ t_insert(breakdown.OverlapChance, "Chance for individual balls to land on the enemy:")
7012
+ t_insert(breakdown.OverlapChance, "^8= (area where a ball can land on enemy) / (total area)")
7013
+ t_insert(breakdown.OverlapChance, "^8= (enemy radius + ball radius - min travel) / (max travel - min travel)")
7014
+ t_insert(breakdown.OverlapChance, s_format("^8= (^7%d^8 + ^7%d^8 - ^7%d) / (^7%d^8 - ^7%d)",
7015
+ enemyRadius, ballRadius, innerRadius, outerRadius, innerRadius))
7016
+ t_insert(breakdown.OverlapChance, s_format("^8=^7 %.2f^8%%", output.OverlapChance))
7017
+ end
7018
+
7019
+ local numProjectiles = skillModList:Sum("BASE", skillCfg, "ProjectileCount")
7020
+ local dpsMult = 1
7021
+ if skillPart == 3 or skillPart == 5 or skillPart == 6 then
7022
+ dpsMult = overlapChance * numProjectiles
7023
+
7024
+ if skillPart ~= 6 then
7025
+ if breakdown then
7026
+ breakdown.SkillDPSMultiplier = {}
7027
+ t_insert(breakdown.SkillDPSMultiplier, "DPS multiplier")
7028
+ t_insert(breakdown.SkillDPSMultiplier, "^8= number of projectiles * overlap chance")
7029
+ t_insert(breakdown.SkillDPSMultiplier, s_format("^8=^7 %d^8 *^7 %.3f^8", numProjectiles, overlapChance))
7030
+ t_insert(breakdown.SkillDPSMultiplier, s_format("^8=^7 %.3f", dpsMult))
7031
+ end
7032
+ else
7033
+ -- zenith: make an effective dpsMult for the weighted average of normal and 5th attack balls
7034
+ local gemQuality = activeSkill.activeEffect.quality
7035
+ local fifthAttackMulti = 1 + 8 + 0.1 * gemQuality
7036
+ local fifthAttackOverallMulti = fifthAttackMulti * overlapChance * (numProjectiles + 5)
7037
+ dpsMult = 0.8 * dpsMult + 0.2 * fifthAttackOverallMulti
7038
+
7039
+ if breakdown then
7040
+ breakdown.SkillDPSMultiplier = {}
7041
+ t_insert(breakdown.SkillDPSMultiplier, "Weighted average DPS multiplier for balls")
7042
+ t_insert(breakdown.SkillDPSMultiplier, "^8= (0.8 * balls dps) + (0.2 * 5th attack balls dps)")
7043
+ t_insert(breakdown.SkillDPSMultiplier, "^8= (0.8 * normal ball hit * overlap chance * number of projectiles) " ..
7044
+ "+ (0.2 * ball hit * 5th attack multiplier * overlap chance * (number of projectiles + 5))")
7045
+ t_insert(breakdown.SkillDPSMultiplier, "^8= ball hit * overlap chance * (0.8 * number of projectiles " ..
7046
+ "+ 0.2 * 5th attack multiplier * (number of projectiles + 5))")
7047
+ t_insert(breakdown.SkillDPSMultiplier, s_format("^8= ball hit * ^7%.3f ^8* (0.8 * ^7%d ^8+ 0.2 * ^7%.1f ^8* ^7%d^8)",
7048
+ overlapChance, numProjectiles, fifthAttackMulti, numProjectiles + 5))
7049
+ t_insert(breakdown.SkillDPSMultiplier, s_format("^8= ball hit * ^7 %.3f", dpsMult))
7050
+ end
7051
+ end
7052
+ end
7053
+ if dpsMult ~= 1 then
7054
+ skillData.dpsMultiplier = (skillData.dpsMultiplier or 1) * dpsMult
7055
+ output.SkillDPSMultiplier = (output.SkillDPSMultiplier or 1) * dpsMult
7056
+ end
7057
+ end,
6979
7058
statMap = {
6980
7059
["active_skill_hit_ailment_damage_with_projectile_+%_final"] = {
6981
- mod("Damage", "MORE", nil, bit.band(ModFlag.Hit, ModFlag.Ailment), 0, { type = "SkillPart", skillPart = 2 })
7060
+ mod("Damage", "MORE", nil, bit.band(ModFlag.Hit, ModFlag.Ailment), 0, { type = "SkillPart", skillPartList = { 2, 3 } })
6982
7061
},
6983
7062
},
6984
7063
baseFlags = {
@@ -6989,12 +7068,12 @@ skills["MoltenStrike"] = {
6989
7068
},
6990
7069
baseMods = {
6991
7070
skill("projectileSpeedAppliesToMSAreaOfEffect", true),
6992
- skill("radius", 9, { type = "SkillPart", skillPart = 2 }),
6993
- skill("radiusLabel", "Ball area:", { type = "SkillPart", skillPart = 2 }),
6994
- skill("radiusSecondary", 2, { type = "SkillPart", skillPart = 2 }),
6995
- skill("radiusSecondaryLabel", "Chain Minimum Distance:", { type = "SkillPart", skillPart = 2 }),
6996
- skill("radiusTertiary", 25, { type = "SkillPart", skillPart = 2 }),
6997
- skill("radiusTertiaryLabel", "Chain Maximum Distance:", { type = "SkillPart", skillPart = 2 }),
7071
+ skill("radius", 9, { type = "SkillPart", skillPartList = { 2, 3 } }),
7072
+ skill("radiusLabel", "Ball area:", { type = "SkillPart", skillPartList = { 2, 3 } }),
7073
+ skill("radiusSecondary", 2, { type = "SkillPart", skillPartList = { 2, 3 } }),
7074
+ skill("radiusSecondaryLabel", "Chain Minimum Distance:", { type = "SkillPart", skillPartList = { 2, 3 } }),
7075
+ skill("radiusTertiary", 25, { type = "SkillPart", skillPartList = { 2, 3 } }),
7076
+ skill("radiusTertiaryLabel", "Chain Maximum Distance:", { type = "SkillPart", skillPartList = { 2, 3 } }),
6998
7077
flag("CannotSplit"),
6999
7078
},
7000
7079
qualityStats = {
@@ -7081,22 +7160,41 @@ skills["MoltenStrikeAltX"] = {
7081
7160
projectile = true,
7082
7161
area = true,
7083
7162
},
7163
+ {
7164
+ name = "Average Balls Hitting",
7165
+ melee = false,
7166
+ projectile = true,
7167
+ area = true,
7168
+ },
7084
7169
{
7085
7170
name = "Magma Balls (5th attack)",
7086
7171
melee = false,
7087
7172
projectile = true,
7088
7173
area = true,
7089
7174
},
7175
+ {
7176
+ name = "Average Balls (5th attack)",
7177
+ melee = false,
7178
+ projectile = true,
7179
+ area = true,
7180
+ },
7181
+ {
7182
+ name = "Total Weighted Ball Average",
7183
+ melee = false,
7184
+ projectile = true,
7185
+ area = true,
7186
+ },
7090
7187
},
7188
+ preDamageFunc = skills.MoltenStrike.preDamageFunc,
7091
7189
statMap = {
7092
7190
["active_skill_hit_ailment_damage_with_projectile_+%_final"] = {
7093
- mod("Damage", "MORE", nil, bit.band(ModFlag.Hit, ModFlag.Ailment), 0, { type = "SkillPart", skillPartList = { 2, 3 } })
7191
+ mod("Damage", "MORE", nil, bit.band(ModFlag.Hit, ModFlag.Ailment), 0, { type = "SkillPart", skillPartList = { 2, 3, 4, 5, 6 } })
7094
7192
},
7095
7193
["molten_strike_every_5th_attack_projectiles_damage_+%_final"] = {
7096
- mod("Damage", "MORE", nil, bit.band(ModFlag.Hit, ModFlag.Ailment), 0, { type = "SkillPart", skillPart = 3 })
7194
+ mod("Damage", "MORE", nil, bit.band(ModFlag.Hit, ModFlag.Ailment), 0, { type = "SkillPart", skillPartList = { 4, 5 } })
7097
7195
},
7098
7196
["molten_strike_every_5th_attack_fire_X_additional_projectiles"] = {
7099
- mod("ProjectileCount", "BASE", nil, 0, 0, { type = "SkillPart", skillPart = 3 })
7197
+ mod("ProjectileCount", "BASE", nil, 0, 0, { type = "SkillPart", skillPartList = { 4, 5 } })
7100
7198
},
7101
7199
},
7102
7200
baseFlags = {
@@ -7107,12 +7205,12 @@ skills["MoltenStrikeAltX"] = {
7107
7205
},
7108
7206
baseMods = {
7109
7207
skill("projectileSpeedAppliesToMSAreaOfEffect", true),
7110
- skill("radius", 9, { type = "SkillPart", skillPartList = { 2, 3 } }),
7111
- skill("radiusLabel", "Ball area:", { type = "SkillPart", skillPartList = { 2, 3 } }),
7112
- skill("radiusSecondary", 2, { type = "SkillPart", skillPartList = { 2, 3 } }),
7113
- skill("radiusSecondaryLabel", "Chain Minimum Distance:", { type = "SkillPart", skillPartList = { 2, 3 } }),
7114
- skill("radiusTertiary", 25, { type = "SkillPart", skillPartList = { 2, 3 } }),
7115
- skill("radiusTertiaryLabel", "Chain Maximum Distance:", { type = "SkillPart", skillPartList = { 2, 3 } }),
7208
+ skill("radius", 9, { type = "SkillPart", skillPartList = { 2, 3, 4, 5, 6 } }),
7209
+ skill("radiusLabel", "Ball area:", { type = "SkillPart", skillPartList = { 2, 3, 4, 5, 6 } }),
7210
+ skill("radiusSecondary", 2, { type = "SkillPart", skillPartList = { 2, 3, 4, 5, 6 } }),
7211
+ skill("radiusSecondaryLabel", "Chain Minimum Distance:", { type = "SkillPart", skillPartList = { 2, 3, 4, 5, 6 } }),
7212
+ skill("radiusTertiary", 25, { type = "SkillPart", skillPartList = { 2, 3, 4, 5, 6 } }),
7213
+ skill("radiusTertiaryLabel", "Chain Maximum Distance:", { type = "SkillPart", skillPartList = { 2, 3, 4, 5, 6 } }),
7116
7214
flag("CannotSplit"),
7117
7215
},
7118
7216
qualityStats = {
0 commit comments