@@ -6975,10 +6975,89 @@ skills["MoltenStrike"] = {
69756975 projectile = true,
69766976 area = true,
69776977 },
6978+ {
6979+ name = "Average Balls Hitting",
6980+ melee = false,
6981+ projectile = true,
6982+ area = true,
6983+ },
69786984 },
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,
69797058 statMap = {
69807059 ["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 } })
69827061 },
69837062 },
69847063 baseFlags = {
@@ -6989,12 +7068,12 @@ skills["MoltenStrike"] = {
69897068 },
69907069 baseMods = {
69917070 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 } }),
69987077 flag("CannotSplit"),
69997078 },
70007079 qualityStats = {
@@ -7081,22 +7160,41 @@ skills["MoltenStrikeAltX"] = {
70817160 projectile = true,
70827161 area = true,
70837162 },
7163+ {
7164+ name = "Average Balls Hitting",
7165+ melee = false,
7166+ projectile = true,
7167+ area = true,
7168+ },
70847169 {
70857170 name = "Magma Balls (5th attack)",
70867171 melee = false,
70877172 projectile = true,
70887173 area = true,
70897174 },
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+ },
70907187 },
7188+ preDamageFunc = skills.MoltenStrike.preDamageFunc,
70917189 statMap = {
70927190 ["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 } })
70947192 },
70957193 ["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 } })
70977195 },
70987196 ["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 } })
71007198 },
71017199 },
71027200 baseFlags = {
@@ -7107,12 +7205,12 @@ skills["MoltenStrikeAltX"] = {
71077205 },
71087206 baseMods = {
71097207 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 } }),
71167214 flag("CannotSplit"),
71177215 },
71187216 qualityStats = {
0 commit comments