Skip to content

GameInput

Bartholomew Ho edited this page Nov 9, 2026 · 1 revision

GameInput

Feeds the game's own controls, as a controller would: the driving controls, the menus' sticks, and the controller's buttons held. It can also let the game play on with no controller at all. This is how a keyboard-and-mouse mod drives the car and works the menus.

Thread: any thread.

Example

W and S are gas and brake, A and D steer, and E shifts up.

using FH2;
using FH2ModPlatform;

public sealed class KeyboardDriving : Mod
{
    private bool _eWasDown;

    public override ModInfo Info => new("KeyboardDriving", "1.0.0");

    protected override void OnInit()
    {
        _ = Menus.IsReady;   // GameInput starts with Menus

        Game.Tick += () =>
        {
            GameInput.SetDriving(DrivingControl.Gas, GameWindow.IsKeyDown(0x57) ? 1 : 0);    // W
            GameInput.SetDriving(DrivingControl.Brake, GameWindow.IsKeyDown(0x53) ? 1 : 0);  // S
            float steer = (GameWindow.IsKeyDown(0x44) ? 1 : 0) - (GameWindow.IsKeyDown(0x41) ? 1 : 0);   // D, A
            GameInput.SetDriving(DrivingControl.Steer, steer);

            bool e = GameWindow.IsKeyDown(0x45);   // E
            if (e && !_eWasDown) GameInput.PressDriving(DrivingControl.ShiftUp);
            _eWasDown = e;
        };
    }
}
Imports FH2
Imports FH2ModPlatform

Public Class KeyboardDriving
    Inherits [Mod]

    Private _eWasDown As Boolean

    Public Overrides ReadOnly Property Info As ModInfo
        Get
            Return New ModInfo("KeyboardDriving", "1.0.0")
        End Get
    End Property

    Protected Overrides Sub OnInit()
        Dim ready = Menus.IsReady   ' GameInput starts with Menus

        AddHandler Game.Tick,
            Sub()
                GameInput.SetDriving(DrivingControl.Gas, If(GameWindow.IsKeyDown(&H57), 1.0F, 0.0F))    ' W
                GameInput.SetDriving(DrivingControl.Brake, If(GameWindow.IsKeyDown(&H53), 1.0F, 0.0F))  ' S
                Dim steer = If(GameWindow.IsKeyDown(&H44), 1.0F, 0.0F) - If(GameWindow.IsKeyDown(&H41), 1.0F, 0.0F)   ' D, A
                GameInput.SetDriving(DrivingControl.Steer, steer)

                Dim e = GameWindow.IsKeyDown(&H45)   ' E
                If e AndAlso Not _eWasDown Then GameInput.PressDriving(DrivingControl.ShiftUp)
                _eWasDown = e
            End Sub
    End Sub
End Class

Members

Driving

Member What it does
CanDrive (property, bool) True once the driving controls can be fed (the game's input code is as expected).
DrivingControlsOn (property, bool) True while the game takes driving input: not on a race's results, in a cutscene, in photo mode or in a menu. As of the last input frame.
SetDriving(DrivingControl control, float value) (method) Adds value to a driving control for as long as you leave it set (set 0 to stop). 1 is a pedal pressed fully or a stick pushed all the way. The controller's own value is added to it, and the total is kept within -1..1.
SetDrivingAtLeast(DrivingControl control, float value) (method) Keeps the control at least at value (set 0 to stop). Meant for the look controls, where a stick let go means "ahead".
ClearDriving() (method) Stops feeding every driving control.
PressDriving(DrivingControl control) (method) One press of a button control (shift up, rewind, map...), as the controller's. Each place in the game that asks for it within a moment sees it pressed once, unless one of them takes it for itself.
LastAsked(DrivingControl control) (method, returns long) When the game last asked for the control, as Environment.TickCount64. The look controls are asked for while a driving camera looks where the stick points.

Menus

Member What it does
SetMenu(MenuControl control, float value) (method) Adds value (-1..1) to one of the menus' sticks, for as long as you leave it set.

Buttons and controllers

Member What it does
HeldButtons (property, PadButtons, get/set) Controller buttons held for the game, as if on the controller, until you change it. What reads the buttons themselves (the radio's d-pad, the tile grids, FH2 ANNA) sees them held, pressed and let go.
HeldXInputButtons (property, ushort, get/set) XInput button bits (0x1 d-pad up ... 0x8000 Y) held only where the controller's raw state is read, not for the game's own buttons. Extra Options and its plugins read them there.
AnyControllerConnected (property, bool) True if a controller is connected to the game.
PlayWithoutController (property, bool, get/set) ⚠️ Not tested much in the game yet. True: the game plays on without a controller, for a mod that is the controller (the keyboard). With no controller there, the title screen signs in without one, "Controller disconnected" isn't shown, the game doesn't pause for it, and photo mode starts. Plugging a controller in pairs it again as usual.

Debugging

Member What it does
Trace (property, bool, get/set) Set to true before the game starts: platform.log then gets each input check that answers anything but 0 (which control, the answer, and where it was asked from), at most every 400 ms each. For finding out what a screen reads. Slows the game a little.
InputFrame (property, uint) Counts the game's input updates (once a frame). 0 until GameInput has started.

Related types

DrivingControl (enum)

The driving controls you can feed.

Value Meaning
Gas, Brake The pedals, 0..1.
Steer -1 left .. 1 right.
Handbrake, ShiftUp, ShiftDown, Clutch The other driving controls.
LookAhead, LookBack, LookLeft, LookRight The right stick, for the driving cameras: up (ahead), back, left, right.
PhotoMode, Camera, Rewind, Map Photo mode, the camera button, rewind, and the map. Button controls: use PressDriving.
Interact The HUD's prompts ("Enter garage"): X with an automatic gearbox, View with a manual one.

MenuControl (enum)

The menus' analog controls.

Value Meaning
LayerRight, LayerUp Design editor > Edit layer: move, size, spin or skew the layer (right +, up +).
CameraRight, CameraUp The garage's camera, turned by the right stick (right +, up +).

PadButtons (flags enum)

The controller's buttons, as the game keeps them. Combine them with | (C#) or Or (VB).

None, DPadUp, DPadDown, DPadLeft, DPadRight, Start, View, LeftStick, RightStick, LB, RB, A, B, X, Y.

Notes

  • GameInput starts with Menus. It switches itself on the first time a mod reads Menus.IsReady or subscribes to Menus.Frame. If no mod does, nothing you feed reaches the game.
  • What you feed goes straight to the game's own controls. Driving values only count while the game takes driving input (not in photo mode or a menu). The menu sticks only count in the menus.
  • SetDriving and SetMenu stay set until you change them. Set the value back to 0 (or call ClearDriving) when your key is let go.
  • SetDrivingAtLeast is applied only while it's set to something other than 0, so it never pulls steering from -1 to 0.
  • HeldButtons stays held until you set it again. Set PadButtons.None to let go.
  • If your mod is a hosted mod and it's reloaded, everything it fed (driving, menu sticks, held buttons) is cleared, and the new copy feeds its own.
  • Unsupported game build: if the game's input code isn't as expected, CanDrive stays false and platform.log says "GameInput: no driving controls". If held buttons can't be fed, platform.log says "GameInput: no held buttons". The parts for playing without a controller each switch off on their own if they don't match.
  • Trace is only read when GameInput starts, so set it in OnInit, before Menus is first used.

See also

Clone this wiki locally