Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Support for automatically calculating Storm Rain DPS #6782

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from

Conversation

SonOfStone
Copy link

Implements #3158

I followed how explosive arrow fuse count was implemented since this seemed a very similar application. First PR so let me know if I am doing anything wrong.

Description of the problem being solved:

Calculates the DPS for storm rain with the below formula

a=average beam damage
x=arrow count (amount of arrows that are fired)
y=attack speed (how many attacks are performed in a second)
z=frequency (how many times beams fire per second)

DPS=(x * y * z) * a

Steps taken to verify a working solution:

Used two different gearsets to prove the dps calculation is correct

DPS=(6 * 3 * 2.5) * 100k ~ 4.5 mil
DPS=(4 * 3.5 * 3.75) * 200k ~ 10.5 mil

Link to a build that showcases this PR:

https://pobb.in/vuxKXMZ0sQpA

After screenshot:

https://prnt.sc/kZMFmKsombof
https://prnt.sc/YNJMnmkCIA0S

@Regisle
Copy link
Member

Regisle commented Oct 4, 2023

This is technically implemented as the config for num of overlapping beams, but if you wanted to calculate that automatically (which you cant really as not all the beams will overlap and hit the enemy), there are better ways of doing this. If you just dont apply it as a hittime override it will already factor in the attack speed, allowing you to do this entirely within the predamage func rather than having its own function

setting globalOutput.HitSpeed or globalOutput.SkillDPSMultiplier doesnt do much here as those are not displayed anywhere atm, I am planning on doing a proper display setup and breakdowns for SkillDPSMultiplier when I get time, but there are hundreds of sources of it, and this is not the best place to put it.

Also as there are other uses of dps multiplier this breaks support for some of the stuff so if you wanted to keep this layout I recommend doing activeSkill.skillData.dpsMultiplier = (activeSkill.skillData.dpsMultiplier or 1) * (projectiles * attackSpeed) instead of activeSkill.skillData.dpsMultiplier = (projectiles * attackSpeed) or 1

edit: you also need to fix the radius reliant on skill part 2, you also need to cap it at 100 arrows out at a time, as each beam will hit up to 4 times, and there can only be a maximum of 100 arrows out at a given time, so you need to take those into account, this means your damage numbers are off by atleast 4 times, for a low arrows/second count (due to getting 4 beam hits per arrow shot), and more if you go over the cap (eg beams fire every 0.4 seconds, so it takes 1.6 seconds to consume all the beams, so at even 62 arrows/second your already at the cap)

@SonOfStone
Copy link
Author

SonOfStone commented Oct 4, 2023

  1. I think I still need the attack speed in order to calculate arrows per second for the 100 arrow cap. Is there a way to access it inside the predamage function?

  2. I'll remove the SkillDPS Multiplier Breakdown since it is more complicated after taking into account the arrow cap and duration.

  3. I am not sure what "fix the radius reliant on skill part 2" means is it related to these lines and I need to add something for skillPart 3?

baseMods = {
		skill("radius", 10, { type = "SkillPart", skillPart = 1 }),
		skill("radiusLabel", "Arrow Explosion:", { type = "SkillPart", skillPart = 1 }),
		skill("radiusSecondary", 12, { type = "SkillPart", skillPart = 2 }),
		skill("radiusSecondaryLabel", "Beam Width:", { type = "SkillPart", skillPart = 2 }),
	},
  1. I think I have taken into account the max arrows and arrow duration here with the below formulas but I have nothing to check my work against. Also I am unsure if I need the math.floor around projectilesCap and attacksBeforeArrowFalloff, my logic was I cannot have a fraction of an attack or projectile.

DPS formula will now be
x=arrow count (minimum amount of arrows that are fired before arrows start disappearing or cap is hit) (DpsMultiplier)
z=frequency (how many times beams fire per second) (hitRate)
a=average beam damage

DPS= x * z * a

where x = min(100/arrowDuration, projectilesBeforeFalloff)

Some math examples:
Basic: https://prnt.sc/PKDJJ4l6zOGK
With Frequency buffs: https://prnt.sc/bxlB3pjCpWbU

		if activeSkill.skillPart == 3 then
			activeSkill.skillData.hitTimeOverride = activeSkill.skillData.hitFrequency / (1 + activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "StormRainBeamFrequency") / 100)
			local projectiles = activeSkill.actor.output.ProjectileCount or 1
			local attackSpeed = globalOutput.Speed

			-- Arrows pulse 4 times before expiring
			local arrowDuration = activeSkill.skillData.hitTimeOverride * 4
			-- Maximum amount of projectiles per second to calculate into dps (100 is max arrows out at one time)
			local projectilesPerSecondCap = math.floor(100 / arrowDuration)
			-- Number of attacks before arrows start to expire
			local attacksBeforeArrowFalloff = math.floor(arrowDuration * attackSpeed)
			local projectilesBeforeFalloff = projectiles * attacksBeforeArrowFalloff

			-- Use the lower amount of projectiles in the dps calculation
			activeSkill.skillData.dpsMultiplier = (activeSkill.skillData.dpsMultiplier or 1) * (math.min(projectilesBeforeFalloff, projectilesPerSecondCap) or 1)

@Paliak Paliak added the enhancement New feature, calculation, or mod label Oct 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature, calculation, or mod
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants