Skip to content

fix(scp049): load the cooldown receiver in FinishingSense - #869

Merged
louis1706 merged 2 commits into
ExMod-Team:devfrom
Niruri:fix-scp049-sense-cooldown-receiver
Oct 19, 2026
Merged

louis1706 merged 2 commits into
ExMod-Team:devfrom
Niruri:fix-scp049-sense-cooldown-receiver

Conversation

@Niruri

@Niruri Niruri commented Oct 18, 2026

Copy link
Copy Markdown

Description

Describe the changes

Load Scp049SenseAbility.Cooldown before calling AbilityCooldown.Trigger(double) in the allowed branch emitted by FinishingSense3.

What is the current behavior?

When FinishingSense is patched, ServerProcessCmd can enter this branch with HasTarget == true. The generated IL currently pushes this (a Scp049SenseAbility) and ev.CooldownTime, then invokes AbilityCooldown.Trigger(double). The receiver is not an AbilityCooldown, so this call is incorrectly typed.

This was investigated after intermittent SCP-049 sense-related disconnects on an EXILED 9.15.2 server. The relevant production stack was:

Disconnecting connId=<redacted> to prevent exploits from an Exception in MessageHandler:
NullReferenceException: Object reference not set to an instance of an object
  Mirror.NetworkWriter.WriteBlittable[T]
  Mirror.NetworkWriter.WriteByte
  RecyclablePlayerIdReaderWriter.WriteRecyclablePlayerId
  Utils.Networking.ReferenceHubReaderWriter.WriteReferenceHub
  PlayerRoles.PlayableScps.Scp049.Scp049SenseAbility.ServerWriteRpc
  ...Scp049SenseAbility.ServerProcessCmd_Patch0
  PlayerRoles.Subroutines.SubroutineMessage.Apply

The server uses dynamic patching, and the affected game mode subscribes to Scp049.FinishingSense. The same missing field load exists in upstream dev. The invalid receiver was independently confirmed by invoking the framework's transpiler without loading the server's gameplay plugin. A clean client/server reproduction and the precise Mono dispatch behavior behind the observed stack have not yet been verified.

What is the new behavior?

The generated call now loads this.Cooldown as its receiver:

ldarg.0                   // allowed branch target
ldfld Scp049SenseAbility::Cooldown
ldloc ev
callvirt FinishingSenseEventArgs::get_CooldownTime()
callvirt AbilityCooldown::Trigger(double)

The event-provided duration is retained, and the allowed branch still enters before the receiver load.

Does this PR introduce a breaking change?

No. This is a one-instruction correction; no public API changes.

Other information

Validation:

  • Release build of Exiled.Events.csproj and its project dependencies using the official SL-References/Dev.zip: passed with 0 warnings and 0 errors.
  • Invoked the actual compiled FinishingSense3.Transpiler with a minimal IL fixture containing the real Cooldown and SubroutineBase.ServerSendRpc(bool) anchors.
  • The same check failed on the unmodified dev assembly and passed after this change. It checks that the single emitted Trigger(double) call loads an assignable receiver from this.Cooldown, retains ev.CooldownTime, and keeps the allowed branch label before the receiver load.
  • git diff --check: passed.
  • This is an emitted-IL check, not a live Unity/Mono server test. Live verification should cover an active target with IsAllowed = true, a subscriber changing CooldownTime, cancellation, and rapid/repeated sense input.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentations

Submission checklist

  • I have checked the project can be compiled
  • I have tested my changes and it worked as expected (emitted-IL regression check described above)

Patches (if there are any changes related to Harmony patches)

  • I have checked no IL patching errors in the console

Other

  • Still requires more testing (live Unity/Mono server verification)

@Niruri Niruri changed the title Fix invalid cooldown receiver in SCP-049 FinishingSense patch fix(scp049): load the cooldown receiver in FinishingSense Oct 18, 2026
@Niruri Niruri closed this Oct 18, 2026
@Niruri Niruri reopened this Oct 18, 2026
@Niruri
Niruri force-pushed the fix-scp049-sense-cooldown-receiver branch from 42d7db8 to 7d93a5f Compare October 18, 2026 08:06
@louis1706

Copy link
Copy Markdown

that look like a big skill issue nice spot

@Someone-193 Someone-193 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really niche bug. Sorry you had to deal with it

@louis1706
louis1706 merged commit 2fec73d into ExMod-Team:dev Oct 19, 2026
6 checks passed
@Niruri
Niruri deleted the fix-scp049-sense-cooldown-receiver branch October 19, 2026 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants