Skip to content

Reloading and debugging

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

Reloading without restarting the game

Hosted mods and scripts can be rebuilt and swapped in while the game runs. NativeAOT mods can't, which is one more reason to develop hosted and ship NativeAOT.

Three ways to reload:

  • On every build: turn on MODS > Installed mods > Platform.NET > Reload .NET mods when rebuilt. With <FH2ModsDir> set in your project, dotnet build copies the mod into the game and it restarts straight away. Scripts reload when you save them.
  • From the console: type reload MyMod. Leave out the name to reload every hosted mod and start any new ones.
  • From a key: bind Reload .NET mods on the Mods page.

What happens in a reload

  1. The old copy's Unloading token is cancelled and its OnUnload() runs. Stop your threads and timers there.
  2. The old copy's hooks are switched off, and its Game.Tick handlers, ANNA entries and other FH2 registrations are removed.
  3. The new copy's OnInit() runs, with IsReload set to true.
protected override void OnInit()
{
    new Thread(() =>
    {
        while (!Unloading.IsCancellationRequested)
        {
            // ...
            Unloading.WaitHandle.WaitOne(1000);   // sleeps, but wakes up for a reload
        }
    }) { IsBackground = true }.Start();
}

protected override void OnUnload() => _file?.Dispose();

What a reload can't change

The platform can't remove things a mod added, so:

  • Settings, pages, title-screen entries, hotkeys and commands the new copy adds with the same key keep their place and call the new code.
  • Ones it adds for the first time only show from the next launch.
  • Ones it no longer adds stay until the game restarts, and do nothing.
  • Text and database edits take effect at the next launch, because the game reads them once.

The old copy stays in memory until the game closes, so reloading is for development, not for players.

The console

Press ~ (the key left of 1) to open or close it. It shows platform.log as it's written, with failures in red and warnings in yellow. It also has a prompt:

Type To
list list every mod's commands
MyMod speed run your mod's speed command
reload MyMod reload a hosted mod
mods list the hosted mods
cls, help clear the screen, show help

The console is a separate program (fh2-mods\dotnet\FH2Console.exe), so closing it can't close the game.

Logging

  • Log("...") writes a line to platform.log, tagged with your mod's name.
  • Console.WriteLine, Trace.WriteLine and Debug.WriteLine go there too. They're safe to call anywhere, hooks included.

Watching values

Add a command, then type it in the console:

AddCommand("speed", "my car's speed", _ => $"{Player.Car?.SpeedKmh:F0} km/h");

Or show values over the game while you drive with DebugOverlay.

Breakpoints

Attach Visual Studio to azimuth.exe (Debug > Attach to Process), with code type Managed (.NET Core, .NET 5+). Hosted mods load with their .pdb, so breakpoints in your code are hit in the running game, after reloads too.

A breakpoint pauses the game's thread. Don't stop on one in Game.Tick while you're racing.

Clone this wiki locally