So here are some notes on calculating time to strip armor. I think overall your analysis is pretty much on the right track, but there are a number of issues which this post will address.
Warning: math involved, though I'll summarize the conclusions at the bottom.Assumptions1. I know it's fairly common to assume the damage as going to a single block of armor, but it turns out, due to the inner/outer armor cell mechanic for Starsector, in practice armor degrades a lot more gracefully than what's implied by assuming a single block. 60% of the DPS goes toward the 9 inner cells, while 40% of the DPS goes toward the 12 outer cells. But the armor rating is based on the inner cells plus half of the outer cells, meaning it'll only "see" half of that 40% of the DPS that went to the outer cells. So the weapon does apply 100% of its damage to the armor cells, but the armor rating will go down by only 80% of the DPS. You can account for this by calculating for the inner and outer cells explicitly, or by setting the DPS to 80% until the armor rating is down to 20% of the base armor. At that point the inner cells are gone and 50% of each of the outer cells are left (which makes the armor rating 20% of the base armor). From there, you have 60% of the DPS go toward hull, while 20% of the DPS goes toward the remaining armor, until the armor is reduced to 0.
Mathematically, when the armor rating goes from 100% to 20%, the weapon has actually already taken off 100% of the base armor rating, just that 20% of it is "missing" due to the armor rating from the outer cells being halved. Then by setting the DPS to 20% when it's really 40% as the armor rating goes from 20% of base armor to 0, the weapon does an additional 40% of the base armor. So in the end the weapon really does 140% of the base armor rating to fully strip off the armor, as it should.
2. It turns out, yes projectile weapons can be approximated as beams, or more accurately, continuous weapons, with the same DPS and hit strength as the base weapon. (Even beams are not calculated continuously, but at 0.1 second intervals IIRC.) This can be seen by using my armor simulation Excel posted
here (which does account for inner/outer cells accurately as well as weapon damage type, assuming I coded it correctly). If you use whatever weapon hit strength and armor base value you want, and start with a very small weapon damage (which basically means a small step size), you'll find that every time you double that damage while leaving the weapon hit strength unchanged (i.e. doubling the step size), the number of "0" rows for hull damage (i.e. how long the weapon is hitting armor, until it breaks through and starts hitting hull) will pretty much be halved each time, to the limit of discretization anyway. For example, for 400 hit strength (energy damage), 500 armor rating, what you find for different values of the weapon damage are:
Weapon Damage : Number of steps (number of zeros) before hull is breached
3.125 : 280
6.25 : 140
12.5 : 70
25 : 35
50 : 17
100 : 9
200 : 4
400 : 2
(Side note: it's easy to count the number of zeros before hull is breached in Excel, you just need to type "=COUNTIF(H5:H557,0)" into any of the empty cells.)
In other words, when you calculate for the analytical, continuous case (i.e. step size ~0), as you increase the step size, the location where the formula crosses armor = 0 stays pretty consistent. In this case, at 400 damage, it would've predicted around 2.19 seconds, but of course that's not possible with discrete once-per-second hits so when calculating discrete 400-damage hits it'd say 2 (meaning on the 3rd one you start hitting hull). So it turns out, assuming it's continuous for derivation purposes is a pretty accurate assumption even when looking at projectiles. It's not exact, but it's pretty close for the most part. (Again, I didn't check for what if there are armor bonuses or anything, but this holds true for at least the base case.)
Problem DefinitionThis is where I think it gets a bit muddy. In this post you describe effective armor as e(A) = uA + v, but your derivation seems to define it the other way around, i.e. x is the effective armor and then you can define the actual armor phi(x) as phi(x) = alpha*x + beta. The definition should stay consistent, and I think this is where it runs into some problems.
For example, by defining actual armor phi(x) as alpha*x + beta, we have to then figure out what alpha and beta are (they are not the armor % bonus nor the added bonus, they're the inverse of that). Then in the derivation, you go from:
d(x) = H*B/(H + x)
to:
int (H + x)/alpha*H*B dx
However, you want to be careful with that differential. DPS is damage to the actual armor per second. But in this case, you defined x as the effective armor, meaning that you're integrating over the effective armor dx, rather than the actual armor dphi. If I understand your definitions correctly, then since phi(x) = alpha*x + beta, then dphi = alpha*dx, so:
DPS = dphi/dt (since phi is the actual armor) = alpha*dx/dt = H*B/(H + x)
==> dt = alpha * (H + x)/(H*B) dx
But you ended up with alpha in the denominator rather than the numerator later on. Fortunately since you're comparing ratios later on anyway the alphas will cancel out, so hope it doesn't matter. But it looks like the actual time calculations would be off if done in isolation. (That or I may have misunderstood your definition of variables.)
This is probably more of a writing style, but usually I'm more used to see inequalities written as "(variable) (inequality) (constant)", i.e. "x < 3" or "x > 3". Or, a convention where it's always written in one direction (i.e. always smaller < greater). In this case, 1 - M is a constant, so I would've written it as H/(H + x) <= 1 - M near the bottom of page 1. Also, using "d" as a function is usually discouraged due to confusion with the differential "d". That's more a matter of writing style though.
Also, the armor reduction bonus from Polarized Armor does [/i]not[/i] apply to the residual armor (i.e. the 0.05 after armor is stripped), or at least not in 0.95.1a-RC3 when I tested it. That residual armor is simply 5% of the base armor (including base armor modifying stuff like Heavy Armor) regardless of the hard flux level.
Result DerivationFor the sake of clarity, I think it's better to define x as the current armor. The reason is because then DPS is simply dx/dt, which simplifies a lot of things. So, start by defining a bunch of variables and parameters that'll be needed:
x = current armor
t = current time
T = total time for armor to be removed
W = weapon damage per second
H = weapon hit strength
A = base armor (i.e. initial starting armor when target is still pristine, which includes base armor affecting bonuses like Heavy Armor)
a = bonus % to base armor only for damage reduction purposes (for example, for Polarized Armor)
b = additional additive bonus to base armor only for damage reduction purposes (such as previously a +50 from Elite Impact Mitigation, though I don't think there are any such bonuses right now in the game)
M = maximum armor damage reduction (M = 0.85 by default, or 0.9 with Polarized Armor)
m = minimum damage reduction multiplier, which is 1 - M, i.e. 0.15 by default, or 0.1 with Polarized Armor; I prefer to think of this damage reduction bound in terms of "if H/(H+A) <= 0.15" rather than "if A/(H+A) >= 0.85", since I can then just
plug in substitute m when needed, so I prefer to work with m generally speaking
r = minimum effective armor fraction (r = 0.05, i.e. it always counts as the armor having at least 5% of its base armor when armor is (almost) stripped away)
c = (HM/m - b)/a, which is the value of the current armor at which the weapon starts doing more damage than the minimum damage multiplier m
All of these except for x and t are constants, i.e. are fixed numbers which are known at the beginning of the problem (except for T, which is what we're solving for).
So starting from the definition of DPS:
DPS = dx/dt = W * H/(H + ax + b)
==> (H + ax + b) dx = W * H dt
==> dt = (H + ax + b) / (W * H) dx
We can integrate both sides to find t, the time to strip the armor. Deriving it in this way allows us to integrate dx with the bounds (i.e. accounting for m and r, etc.) in terms of the base armor, which is much clearer:
t = a/(2WH) * x^2 + (H + b)/(WH) * x (...plus C harhar)
Now as far as I know, there aren't any additive armor bonuses for damage reduction purposes currently in the game, i.e. b = 0. Thus this simplifies down to:
t = [(a/2H)*x^2 + x]/W (plus C)
(For the sake of completeness, I'll note that DPS is actually a negative number, i.e. it's how much the armor decreases per second, but by convention it's considered a positive quantity. But we can just flip the sign by flipping the integration bounds and being careful about that, so it's not a problem.)
So that's the bulk of it, from here on out it's just accounting for all the messy bounds, inner/outer cells, and all that.
Possible CasesCase 1. Let's start with the trivial case, where the weapon hit strength is so low that the damage reduction will be equal or greater than the maximum damage reduction, even with stripped armor. Even though it's trivial, it's good at building up intuition for how the armor mechanics work. Take a vulcan cannon (500 frag DPS, hit strength 25 frag, or 6.25) hitting something with 1500 base armor (and thus 75 residual armor). Since its hit strength is so low, it'll always be doing the minimum amount of 15% regardless of the Onslaught's current armor value. This can be written as:
If H/(H + rA) <= m (Equivalently: if H <= rAm/M)
==> DPS = Wm
==> T (from x = A to x = 0.2A) = 0.8A/(Wm)
To account for inner/outer cells, the weapon damage W will really be 80% of it, so this boils down to:
==> T (from x = A to x = 0.2A) = A/(Wm)
At first this might seem a bit odd, that the time still boiled down to just the armor divided by the minimum damage. However, this is how long it takes to get the armor down to 20% of its original base rating. At this point, it'll display as the full base armor rating (i.e. if the ship had 1500 armor, at this point the game will display that a total of 1500 armor has been taken off, because it has), but in reality the armor rating is still at 300 due to the outer cells.
Now for what happens once armor is at 20% of the base value, this is when the inner armor cells are stripped but there are still some outer cells taking damage. At this point, the damage that hits the inner cells will hit hull instead, while the damage that hits the outer cells will continue hitting armor. It is the latter that needs to be reduced to 0 for the armor to be fully stripped. While 40% of the DPS is applied to the outer cells, it'll only count as 20% in terms of the armor rating. So:
T (from x = 0.2A to x = 0) = 0.2A/(0.2Wm) = A/(Wm)
So the total time it takes to strip off all armor is:
T (from x = A to x = 0) = 2A/(Wm)
This can be checked using the armor simulation Excel file. For example, if you set weapon damage to 500, weapon hit strength to 25 (note: since it's frag, the weapon hit strength for damage reduction is 6.25), weapon damage type to "Frag", and armor to 1500, then in this case, A = 1500, W = 125 (frag is only 25% vs armor), m = 0.15, W_h = 500, so:
T (from x = A to x = 0.2A) = A/(Wm) = 80
T (from x = A to x = 0) = 2A/(Wm) = 160
And indeed you'll see that it takes 80 steps for the inner cell armor to get reduced to 0 and for the weapon to start doing hull damage, and another 80 steps before the outer cell armor is reduced to 0.
Case 2. Next, let's take the case where the weapon hit strength is big enough to where it breaks above the minimum damage before the residual armor rA, but is such that at 20% of base armor, it's still doing less than the minimum damage reduction m. This can be written as:
If H/(H + rA) > m (Equivalently: if H > rAm/M)
and if H/(H + 0.2aA + b) <= m (Equivalently: if H <= (0.2aA + b)m/M)
Here, from max armor to 20% armor, the weapon is still doing the minimum damage of m (i.e. usually 15%), so everything is still the same as before, and so:
T (from x = A to x = 0.2A) = (0.8A)/(0.8Wm) = A/(Wm)
At this point, the weapon starts hitting hull, and only 20% of the DPS will go toward decreasing the armor rating. At some point, the DPS will start increasing above the minimum of m. This point is when the current armor x is such that:
H / (H + ax + b) = m
==> x = (HM/m - b)/a
For ease of writing, I'll define c to be this value of (HM/m - b)/a, because it's an important boundary point throughout this post, and I don't want to keep repeating it. It is the value of x below which the damage reduction calculation multiplier H/(H + ax + b) starts increasing above the minimum damage reduction multiplier of m. Note that b is often 0, but I'm including it for the sake of completeness. So:
T (from x = 0.2A to x = c) = (0.2A - c)/(0.2Wm)
Then from x = c to x = rA, the weapon is doing 20% of the quadratic damage to the armor. So (assuming b = 0):
T (from x = c to x = rA) = [(a/2H)*x^2 + x]/(0.2W) (from x = c to x = rA)
= [(a/2H)*c^2 + c]/(0.2W) - [(a/2H)*(rA)^2 + rA]/(0.2W)
Then from x = rA to x = 0, the weapon is doing 20% of its DPS damage with the damage reduction calculation counted as if the armor value were rA, even though it may be less than that. So the DPS is:
DPS (from x = rA to x = 0) = 0.2WH/(H + rA)
==> T (from x = rA to x = 0) = rA * (H + rA)/(0.2WH)
So, taking this all together:
T (from x = A to x = 0) = A/(Wm) + (0.2A - c)/(0.2Wm) + [(a/2H)*c^2 + c]/(0.2W) - [(a/2H)*(rA)^2 + rA]/(0.2W) + rA * (H + rA)/(0.2WH)
If you'd like to simplify, this ends up being:
T (from x = A to x = 0) = (5/W) * [0.4A/m - c/m + (a/2H)*c^2 + c + (1 - a/2)*(rA)^2 / H]
Case 3. Now, let's take the case where the weapon hit strength is big enough to where the weapon will be doing more than the minimum damage before the base armor reaches 20%, i.e. it starts doing more than the minimum damage m (usually 0.15) prior to the weapon hitting hull. But the weapon is still doing minimum damage at full base armor. This can be written as:
If H/(H + 0.2aA + b) > m (Equivalently: if H > (0.2aA + b)m/M)
and if H/(H + aA + b) <= m (Equivalently: if H <= (aA + b)m/M)
As with before, define the point c as the value of x below which the damage reduction calculation multiplier H/(H + ax + b) starts increasing above the minimum damage reduction multiplier of m. Then, from the beginning until x = c, the weapon is still doing the minimum damage:
T (from x = A to x = c) = (A - c)/(0.8Wm)
Then, we have the quadratic part from x = c to x = 0.2A, where, assuming b = 0:
T (from x = c to x = 0.2A) = [(a/2H)*x^2 + x]/W (from x = c to x = 0.2A)
= [(a/2H)*c^2 + c]/(0.8W) - [(a/2H)*0.2A*0.2A + 0.2A]/(0.8W)
At this point the weapon will start hitting hull, while still in the quadratic part. So, from x = 0.2A to x = rA (assuming b = 0):
T (from x = 0.2A to x = rA) = [(a/2H)*x^2 + x]/(0.2W) (from x = 0.2A to x = rA)
= [(a/2H)*0.2A*0.2A + 0.2A]/(0.2W) - [(a/2H)*(rA)^2 + rA]/(0.2W)
Then, as with before, from x = rA to x = 0, the weapon is doing damage as if x = rA, so as with before:
DPS (from x = rA to x = 0) = 0.2WH/(H + rA)
==> T (from x = rA to x = 0) = rA * (H + rA)/(0.2WH)
So, taking all this together:
T (from x = A to x = 0) = (A - c)/(0.8Wm) + [(a/2H)*c^2 + c]/(0.8W) - [(a/2H)*0.2A*0.2A + 0.2A]/(0.8W) + [(a/2H)*0.2A*0.2A + 0.2A]/(0.2W) - [(a/2H)*(rA)^2 + rA]/(0.2W) + rA * (H + rA)/(0.2WH)
You can probably simplify it (particularly since r = 0.05, and far as I know there's nothing that modifies that in the game), but I won't bother to here.
Case 4. This is the last case, where the weapon hit strength is so big that from the get-go, it's never as low as the minimum damage reduction multiplier m. This can be written as:
If H/(H + aA + b) > m (equivalently: if H > (aA + b)m/M)
Then we can proceed very similarly as Case 3, except now we don't have to worry about the beginning minimum damage section. Thus we start off directly with the quadratic case (assuming b = 0):
T (from x = A to x = 0.2A) = [(a/2H)*x^2 + x]/W (from x = A to x = 0.2A)
= [(a/2H)*A^2 + A]/(0.8W) - [(a/2H)*0.2A*0.2A + 0.2A]/(0.8W)
= [(a/2H)*0.96A^2 + 0.8A]/(0.8W)
= [(a/H)*0.6A^2 + A]/W
The rest is the same as in case 3. So, taking all this together:
T (from x = A to x = 0) = [(a/H)*0.6A^2 + A]/W + [(a/2H)*0.2A*0.2A + 0.2A]/(0.2W) - [(a/2H)*(rA)^2 + rA]/(0.2W) + rA * (H + rA)/(0.2WH)
SummarySo, to summarize, assuming my math is correct (which is always a dangerous assumption and is never guaranteed):
Case 1: If H <= rAm/M
then T = 2A/(Wm)
Case 2: If H > rAm/M and H <= (0.2aA + b)m/M (and assuming b = 0 due to quadratic section)
then T = (5/W) * [0.4A/m - c/m + (a/2H)*c^2 + c + (1 - a/2)*(rA)^2 / H]
Case 3: If H > (0.2aA + b)m/M and H <= (aA + b)m/M (and assuming b = 0 due to quadratic section)
then T = (A - c)/(0.8Wm) + [(a/2H)*c^2 + c]/(0.8W) - [(a/2H)*0.2A*0.2A + 0.2A]/(0.8W) + [(a/2H)*0.2A*0.2A + 0.2A]/(0.2W) - [(a/2H)*(rA)^2 + rA]/(0.2W) + rA * (H + rA)/(0.2WH)
Case 4: If H > (aA + b)m/M (and assuming b = 0 due to quadratic section)
then T = [(a/H)*0.6A^2 + A]/W + [(a/2H)*0.2A*0.2A + 0.2A]/(0.2W) - [(a/2H)*(rA)^2 + rA]/(0.2W) + rA * (H + rA)/(0.2WH)
These 4 cases are demonstrated in the attached graph, for 500 DPS, 1500 base armor, with minimum damage reduction multiplier 0.15. Note that the 4 cases are basically where the DPS starts going above the minimum damage reduction multiplier m. Case 1 = never, Case 2 = between 5% of base armor and 20% of base armor, Case 3 = between 20% of base armor and 100% of base amor, and Case 4 = above 100% of base armor.
Note that these cases are all defined in terms of the hit strength H relative to the base armor A. That makes it easier to get an intuitive feel for which case is applicable in a given situation.
-----
Now, regarding the hull damage while the armor rating goes from 20% to 0, you can follow the above analysis but now plugging in for hull damage during T from x = 0.2*A to 0 all the way through, or you can make a simple observation: during this period, the weapon does 20% of its DPS to armor, and 60% of its DPS to hull. Both are equally affected by the damage reduction calculation, so this proportion stays constant. So, this means that the weapon will do 60% of the base armor to hull during this time, subject to the difference between damage to armor and damage to hull as a multiplier (0.5 for HE, 1 for energy, 2 for kinetic, 4 for frag).
Taking the frag case, it means that the weapon will do 2.4x the base armor to hull, i.e. if the base armor were 1500, the weapon would do 3600 damage to hull during this time. Looking through the ship_data.csv, for all the ships, even if you add on Armored Weapon Mounts (+10% base armor) and Shield Shunt (+15% base armor), along with Heavy Armor (+150/300/400/500 base armor based on size), all of the ships will still have hull remaining after armor is stripped, except for the Dram and the Ox. So basically, this isn't something to be concerned about; you can almost always assume that the ship has enough hull to last through until the armor is gone. (In practice, this isn't true, because you could be hitting a fresh patch of armor when the ship has already taken hull damage through a hole in the armor on another part of the ship, but a ship taking damage from multiple directions is beyond the scope of this analysis.)
So this means that to calculate total time to kill, you can start with the time to fully strip armor above, and then start off the hull with already having taken some damage (60% of armor, modified by damage type), and then work from there. That makes the calculation a lot easier to do since you'll be working purely with damage to hull, assuming residual armor. (Until somebody wants to incorporate the effect of Combat Endurance's hull regen, anyway.)