[#1636][6.20] Repair drones erroneously round down repair amount due to integer division - Fix coming.

Ask here if you experience technical problems with X4: Foundations.

Moderator: Moderators for English X Forum

Mookau
XWiki Moderator
XWiki Moderator
Posts: 172
Joined: Tue, 8. Sep 20, 05:31
x4

[#1636][6.20] Repair drones erroneously round down repair amount due to integer division - Fix coming.

Post by Mookau »

OS: Linux
Version: 6.20
Language: English
Modified: No
Game Start: Budgeted Custom (or Any)

Problem:
Due to the relevant script accidentally leaves the repair rate value as an integer, the repair rate for repair drones only increases by 50MJs at a time.

A ship with a single repair drone should repair exactly 10x faster than the same ship with 0 - However for specific drone amounts and crew skill values, this isn't the case.
For a ship with any number of drones, the repair amount is rounded down to the nearest 50 MJ.

How to Reproduce:
Start a new game using one of the custom start options.
Add a ship with a 0 star pilot and no crew and no repair drones.
Add an identical ship with a 0 star pilot and no crew, but with 1 repair drone.
Damage each ship somewhere below 64% hull so that it can repair, noting the current hull value in MJ.
Note the increase after each repair tick.

The ship with 0 drones will repair at a rate of 7MJ/tick.
The ship with 1 drones will repair at a rate of 50MJ/tick.

The ship with 1 drone should be repairing at 70MJ/tick. It is repairing 29% slower than it should be.

Notes:
This bug can lose up to 49% of the expected repair rate given specific conditions.

Save:
The following save is from a custom creative game, the player is positioned in front of a damaged ship with 1 repair drone, a 0 star pilot, and no crew. You can note the repair amounts as it's health ticks up.
https://drive.google.com/file/d/167FLLm ... sp=sharing

There are also other ships in the save scattered around that I used to test.
The ships with 1 drone and 5 star pilots should repair at 210MJ/tick (compared to 21 of their 0 drone counterparts), but they only repair at a rate of 200MJ/tick.
Unfortunately only the ones with 1 drone will exhibit the bug, as those with increments of 5 (every other ship) end up with expected values ending in 50.

Research:

The offending lines of code is in the engineer.ai script.

I'll give an example of 2 drones, and a crew with 0 skill.

Code: Select all

<set_value name="$repairratefactor" exact="0" />
This line sets the repair rate factor to "0" to begin with.

Code: Select all

<set_value name="$repairratefactor" operation="add" exact="$unitamounts.{$i} * $i" />
Then this line adds the number of drones to the repair rate factor. So for our 2 drones example:
repairratefactor = 0 + number of drones
repairratefactor = 2

Code: Select all

<set_value name="$repairratefactor" operation="add" exact="$repairratefactor * $repairmodifier / 25" comment="crew speeds up repair by up to 400% (meaning a fifth of the normal repair time)" />
This line adds the contribution of the repair drones we calculated above to the ship's repair modifier (calculated based on the ship's crew skill) - this is where things go awry.

repairmodifier is defined elsewhere in the script as: "crewskill + 10" with a cap of 100.

So for a 0 star crew, repairmodifier equals 10.
Also rembering that repairratefactor is currenty 2, we have:

repairratefactor = 2 + 2 * 10 / 25

If we simplify it one step we get:
repairratefactor = 2 + (20 / 25)

This seems like it should equal to "2 + 0.8" or "2.8", the problem here is that everything we have dealt with up until now has been an integer (whole number).
When (most) programming languages do math with integers, they throw away anything after the decimal place when dividing one integer by another.
So what happens here is that the "0.8" becomes just a "0", so we get "2 + 0" = "2"
Our crew have effectively contributed nothing! - Admittedly they sucked, but they should still count.

The final repair value in MJ is calculated as the repairratefactor at this step * 50.
So what we get is "2 * 50" or 100MJ repair rate.
When we should have had "50 * 2.8" or 140MJ repair rate.
We have lost a whole 40MJ of repair rate per tick!

Solution 1:
Simply replace the line:

Code: Select all

<set_value name="$repairratefactor" exact="0" />
With:

Code: Select all

<set_value name="$repairratefactor" exact="0f" />
The "f" after the 0 here tells the programming language to treat this a float instead of an integer, allowing for decimal places. Since this value is what we add to in each step, it remains a float the whole way through.

Solution 2:
Simply replace the line:

Code: Select all

<set_value name="$repairratefactor" operation="add" exact="$repairratefactor * $repairmodifier / 25" comment="crew speeds up repair by up to 400% (meaning a fifth of the normal repair time)" />
With:

Code: Select all

<set_value name="$repairratefactor" operation="add" exact="$repairratefactor * $repairmodifier / 25f" comment="crew speeds up repair by up to 400% (meaning a fifth of the normal repair time)" />
The "f" after the 25 here does the same thing as solution 1, but at a different step of the process. The result is the same.


Why doesn't this happen when you have 0 repair drones?
Because of these lines:

Code: Select all

        <do_else>
          <!-- if no builds are underway, repair 10 times more slowly than with just one mk1 drone -->
          <set_value name="$repairratefactor" exact="0.1"/>
The developer comments in this code give away what is happening - If there are no repair drones, the game tells it that the resulting repair rate should be 1/10th of the rate if it just had a single repair drone.
The reason that this fixes the problem is that instead of setting the the value of repairrate as either "0" or the number of drones - which are both whole numbers (and therefore integers) - it is given as "0.1" which is implicitly a float.
Because it is implicit it doesn't need the "f" afterwards for the programming language to know that decimal places are important.
PV_
Posts: 441
Joined: Sun, 4. Sep 22, 20:57
x4

Re: [#1636][6.20] Repair drones erroneously round down repair amount due to integer division.

Post by PV_ »

Good job! Very explanatory, even for those who never dove inside script files.
By any chance, may you've also seen why repairing from low hull values is faster than when hull is slightly dented? I often board carriers and auxiliary ships and if they get heavy damage they (especially auxiliary ships cuz of more repair drones) get ridiculous amount of repairing. Basically before boarding pods finish their sticking to the hull Atlas E capable of self-repairing from like 20% to 75%, and then repairing slows down.
Another example is M frigates with repair drones. Falx, for example, may restore their hull from <50% to 100% in a matter of few seconds, while barely scratched chassis will be under repair for ages.
Mookau
XWiki Moderator
XWiki Moderator
Posts: 172
Joined: Tue, 8. Sep 20, 05:31
x4

Re: [#1636][6.20] Repair drones erroneously round down repair amount due to integer division.

Post by Mookau »

PV_ wrote: Tue, 9. Jan 24, 11:17 Good job! Very explanatory, even for those who never dove inside script files.
By any chance, may you've also seen why repairing from low hull values is faster than when hull is slightly dented? I often board carriers and auxiliary ships and if they get heavy damage they (especially auxiliary ships cuz of more repair drones) get ridiculous amount of repairing. Basically before boarding pods finish their sticking to the hull Atlas E capable of self-repairing from like 20% to 75%, and then repairing slows down.
Another example is M frigates with repair drones. Falx, for example, may restore their hull from <50% to 100% in a matter of few seconds, while barely scratched chassis will be under repair for ages.
It's likely the behaviour you see is intended.

A barely scratched ship often won't repair at all. Ships will repair to a certain hull% based on crew skill, the higher the crew skill, the higher the hull% they will repair to. Once the repairs cause the hull to pass that threshold, they stop repairs. For a low skilled crew, this will be as low as 64%.

In the first example, the crew skill of the ship is contributing to the repair rate, and as you progress the boarding operation, they have less crew skill to add to the repair rate, so it slows down.

In the second example, M ships repair faster because they have less hull. The repair rate is not dependent on size or max hull amount. A ship with 5 repair drones and a 5 star crew will receive 1250 MJ every 10 to 11 seconds whether it's M or XL - this could repair quite a large portion of a frigate's health, but only small fraction of a carrier's health.
PV_
Posts: 441
Joined: Sun, 4. Sep 22, 20:57
x4

Re: [#1636][6.20] Repair drones erroneously round down repair amount due to integer division.

Post by PV_ »

Mookau wrote: Tue, 9. Jan 24, 12:01 A barely scratched ship often won't repair at all. Ships will repair to a certain hull% based on crew skill, the higher the crew skill, the higher the hull% they will repair to. Once the repairs cause the hull to pass that threshold, they stop repairs. For a low skilled crew, this will be as low as 64%.
Yeah, heard that too and that looks like a real thing, but threshold by the crew isn't anyhow mentioned in the math above. Are there any additional checks over flat "adds"?
Mookau wrote: Tue, 9. Jan 24, 12:01In the second example, M ships repair faster because they have less hull. The repair rate is not dependent on size or max hull amount. A ship with 5 repair drones and a 5 star crew will receive 1250 MJ every 10 to 11 seconds whether it's M or XL - this could repair quite a large portion of a frigate's health, but only small fraction of a carrier's health.
Here is one a bit tricky script I suppose. Repairing is extremely slow for hull above ~50% with even high skilled crew. When it drops down to below 50% then hull quickly gets repaired to 100%, literally. And that is barely may be explained with listed formulas. :gruebel: 50% is an approximate threshold. I'd say 30-60% is more precise range.
j.harshaw
EGOSOFT
EGOSOFT
Posts: 2202
Joined: Mon, 23. Nov 15, 18:02

Re: [#1636][6.20] Repair drones erroneously round down repair amount due to integer division.

Post by j.harshaw »

Nice catch. Looks like this particular issue has been overlooked for a while. Fixed here now. Should be in a future update.

Return to “X4: Foundations - Technical Support”