ken

Risk of Rain 2 Mod - Sprint Double Bind

Runtime Assembly Hooking & Input Logic Injection

Overview

Risk of Rain 2 (RoR2) is a fast-paced roguelike with a strict keybinding constraint: the engine natively prevents players from assigning secondary keys to a single action.

This limitation became a major friction point with the discovery of the "Acrid Sprint Bug." By inputting a sprint command over 10 times per second while attacking, players can drastically increase Acrid’s attack speed and health regeneration. Attempting this manually with the default sprint key (Left Control) is not only difficult to sustain but also physically taxing on the wrist.

While the community often uses the mouse scroll wheel to trigger high-frequency inputs, RoR2 only allows binding Scroll Up natively. Binding it also overwrites the primary sprint key, making standard gameplay awkward. Typical workarounds like bloated mouse driver software or external macros require tedious setup and intrusive background processes.

Sprint Double Bind is a BepInEx plugin that bypasses these engine limitations. By hooking into the game’s runtime assembly, it allows players to assign an additional keybind to sprint and enables high-frequency inputs via both Scroll Up and Scroll Down. This restores gameplay flexibility while providing ergonomic access to the Acrid bug.

Core Functionality

Secondary Sprint Keybind

Allows an second sprint keybind to be set as a valid trigger for sprint toggling.

Sprint on Scroll

Adds toggles to enable sprint on Scroll Up and Down, enabling rapid sprint inputs.

Technical Implementation

The project utilizes BepInEx for assembly patching and MonoMod (via On.RoR2) to hook into the game’s internal classes.

A significant challenge was the disparity between Unity's Update() (input polling) and the game's FixedUpdate() (physics/state processing). To prevent dropped inputs, the mod implements a state-latching pattern:

01

Update()

Continuously polls Input.mouseScrollDelta and UnityInput

02

Flagging

If a valid input is detected, a _keyPressedThisFrame flag is raised

03

FixedUpdate()

The hook intercepts PlayerCharacterMasterController, checks the flag, and manually sets sprintInputPressReceived = true

The mod leverages the Risk of Options API as a soft dependency to expose configuration handles directly within the in-game settings. By implementing this provider, users can adjust mod options in real-time. This bypasses the friction of manual .cfg file editing and game restarts, providing a seamless live-configuration experience.

Risk of Options Screenshot
Ingame settings implemented through Risk of Options
FrameworkBepInEx / MonoMod
LanguageC# / .NET
Settings APIRisk of Options

Key Outcomes

01

Improved Accessibility

Implemented a secondary sprint bind that mirrors native behavior.

02

Seamless Integration

Utilized the Risk of Options API to provide a native-feeling UI, allowing users to configure binds within the game.

03

Published Mod

Deployed the mod to Thunderstore, managing the end-to-end release for public distribution.

Challenges & Solutions

Problem Non-Standard Sprint Logic

The game handles sprint states through a unique internal state machine, making it incompatible with standard input-handling methods.

Solution:

Analyzed existing mod implementations and collaborated with the modding community to identify the precise hooks required to toggle sprinting.

Problem Input Desync

Directly polling input within FixedUpdate led to missed inputs, as high-frequency events (like mouse-scroll ticks) often occurred between physics steps.

Solution:

Implemented a buffered input pattern: Update() captures and flags the input state, which is then consumed and reset during FixedUpdate(), ensuring frame-perfect reliability.

Future Work

Special Thanks

Kyryh for their PermaPing mod used as a reference.

@.score and @gchinchi for help in the RoR2 modding discord.