Skip to content

Fix #2525: clamp negative Cyclops power readout with no powercells#2748

Open
SkiLark1 wants to merge 1 commit into
SubnauticaNitrox:masterfrom
SkiLark1:fix/2525-cyclops-negative-charge
Open

Fix #2525: clamp negative Cyclops power readout with no powercells#2748
SkiLark1 wants to merge 1 commit into
SubnauticaNitrox:masterfrom
SkiLark1:fix/2525-cyclops-negative-charge

Conversation

@SkiLark1
Copy link
Copy Markdown

@SkiLark1 SkiLark1 commented May 18, 2026

Linked Issues / Context

Fixes #2525

Description of Change

Vanilla CyclopsHelmHUDManager.Update computes the displayed power percent as:

int num = Mathf.CeilToInt(subRoot.powerRelay.GetPower() / subRoot.powerRelay.GetMaxPower() * 100f);

With all powercells removed, GetMaxPower() returns 0, so 0f / 0f is NaN and Mathf.CeilToInt(NaN) is int.MinValue. The HUD then reads -2147483648% instead of 0%.

This state is normally unreachable in vanilla Subnautica because the engine auto-shuts when the player exits the helm, but Nitrox intentionally patches that out for MP reasons (see CyclopsMotorMode_SaveEngineStateAndPowerDown_Patch.cs). With auto-shutdown disabled, pulling all powercells at the helm exposes the divide-by-zero path.

The fix transpiles Update to clamp the Mathf.CeilToInt result with Mathf.Max(0, …), so the bad value never gets written and vanilla's own $"{num}%" formatting renders 0%. The clamp is a single insertion right after the uniquely-matchable Mathf.CeilToInt call.

Note: an earlier revision of this PR used a Postfix that overwrote the text after the fact. That approach wrote IntStringCache.GetStringForInt(0) = "0", which dropped the % sign that vanilla's $"{num}%" includes. The transpiler fixes the value at the source and lets vanilla's formatting run, producing the correct "0%". Thanks to the reviewer for pushing for the source-level fix.

The patch is registered in PatchesTranspilerTest so the IL match is covered by the test suite.

This patches a vanilla Subnautica bug (closed-source, can't be upstreamed), but the clamp is a no-op for all legitimate power values (0–100), so it has no effect in normal play.

Validation

Tested locally on Windows, Subnautica build 83031, Nitrox InDev master (bbf5124):

  1. Spawn a Cyclops via Developer → Give → Cyclops.
  2. Enter the cyclops, walk to the helm.
  3. Remove all 6 power cells.
  4. HUD power readout shows 0% (was -2147483648% before the fix).
  5. Insert a powercell back → shows a normal positive percent. Remove it again → back to 0%.

The transpiler is also covered by PatchesTranspilerTest.AllPatchesTranspilerSanity, which runs it against the real game IL and asserts it matches and inserts exactly 2 instructions.

PR Checklist


🤖 This code was created with the help of AI.

@dartasen dartasen added the Status: Waiting for reviews Pull Request is waiting for code review label May 18, 2026
@dartasen
Copy link
Copy Markdown
Member

What about transpiling patch the actual code, instead of adding a workaround ?

@dartasen dartasen added Status: Needs answers Pull Request needs answers from author and removed Status: Waiting for reviews Pull Request is waiting for code review labels May 20, 2026
…no powercells

Vanilla CyclopsHelmHUDManager.Update computes
    int num = Mathf.CeilToInt(powerRelay.GetPower() / powerRelay.GetMaxPower() * 100f);
With all powercells removed GetMaxPower() returns 0, so 0f/0f is NaN and
Mathf.CeilToInt(NaN) is int.MinValue, making the HUD read -2147483648%.

Transpile Update to clamp the CeilToInt result with Mathf.Max(0, ...) so
the bad value is never written and vanilla's own {num}% formatting
renders 0%. Registered in PatchesTranspilerTest so the IL match is
covered by the test suite.

Verified locally: spawn a Cyclops, enter, remove all 6 cells - HUD shows
0%. Insert and remove a cell again: readout behaves correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@SkiLark1 SkiLark1 force-pushed the fix/2525-cyclops-negative-charge branch from bac21c5 to 9b497e9 Compare May 21, 2026 17:12
@SkiLark1
Copy link
Copy Markdown
Author

What about transpiling patch the actual code, instead of adding a workaround ?

Pushed the transpiler version. It clamps the Mathf.CeilToInt result with Mathf.Max(0, ...) right after the call, so vanilla's own "{num}%" formatting renders 0% correctly. Added it to PatchesTranspilerTest too, and confirmed in-game the HUD reads 0% now.

Good call on doing it at the source. The old Postfix was dropping the % sign anyway, so this ended up cleaner all around.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Needs answers Pull Request needs answers from author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Charge on cyclops is negative after powering up engine without powercells present

2 participants