Skip to content

Releases: seikenxa/rf2-autocam

v1.5.0 - Incident signal + Live Cut manual replay

04 Jun 03:15

Choose a tag to compare

New

  • Incident signal. status.json now includes an incident boolean (true for incidenthold seconds after any detected incident, on both rF2 and LMU). The OBS Lua script gains incident_start / incident_end triggers — wire them to a banner or alert. It is independent of replay mode, so it fires even on LMU where replays cannot be plugin-driven.
  • Live Cut (livecut=1) — manual incident replay. Instead of auto-replaying, the camera cuts to the incident car and holds it for incidenthold seconds, and you decide when to replay.
    • rFactor 2: press your Instant Replay key to replay — the plugin seeks to the incident — and press it again to return to autocam. An on-screen prompt (Incident - press R for replay) tells you when one is ready.
    • Le Mans Ultimate: the plugin holds the live focus on the incident car; you use LMU's own native instant replay (press R, then click the LIVE marker on the seek bar to return). The on-screen prompt only shows while driving (LMU hides the message area in spectator view), so for a broadcast setup the camera cut to the incident car — and the OBS incident signal — is your cue. Set incidenthold to ~20 so the focus covers watching the replay.
    • Default livecut=0 keeps the previous automatic-replay behaviour.
  • replaykey=auto reads the sim's own Instant Replay key binding (rF2 Controller.JSON / LMU keyboard.json) so manual mode follows whatever key you use. Override with a hex virtual-key code if needed.
  • New ini keys: livecut (0), incidenthold (7), replaykey (auto).

Changes

  • lowinc / highinc defaults raised to 500 / 2000. The old 0.4 / 0.8 fired on virtually every contact — the actual contact-severity scale in current rF2/LMU is hundreds to thousands (roughly 500 = light contact, 2000+ = heavy, 3000+ = big crash). Thanks to Tony RZ for flagging this.
  • Player-driving detection now uses mControl == 0 (the local player actually in control) instead of mIsPlayer, which is unreliable on LMU — it stays set on your owned car even while spectating. Autocam now follows you switching between driving and spectating within a session, with no configuration.

Dev

  • Debug log (debug=1) gains imag / inc / lcf / orp / lo / hi / lc / pctl fields.

Install

Drop rf2autocam_x64.dll into ...\rFactor 2\Bin64\Plugins\ (or ...\Le Mans Ultimate\Plugins\). The same DLL works for both games. See the README for the LMU CustomPluginVariables.JSON entry.

v1.4.0 - Fix camera freeze after driving; practice/qualifying rotation

30 May 06:28

Choose a tag to compare

Fixes

  • Auto camera froze after taking control of a car (DRIVE). rF2 latches mReplayActive=true after the player drives and never clears it, which blocked all camera switching. The camera-commit path is now gated on our own incident replay (onreplay) instead of mReplayActive.
  • Camera could freeze on session change or race restart. A stale switch timer carried over from the previous session (e.g. a long practice into qualifying). UpdateScoring now self-heals when the session changes or the session clock resets.

Changes

  • Practice: camera now rotates through the cars on track in random order (no longer locked to P1), preferring cars not featured yet in the current cycle.
  • Qualifying: same rotation, but prioritises the action — a lead change (a new fastest lap takes P1) cuts immediately, followed by cars on pace for the overall best or beating the best sector 1.
  • Race camera selection unchanged (closest battle).

Dev

  • Debug log gains wtvN / rep / wpath fields (debug=1 only).

Install

Drop rf2autocam_x64.dll into ...\rFactor 2\Bin64\Plugins\.

v1.3.5 - Fix WantsToDisplayMessage check

28 May 22:40

Choose a tag to compare

Changes

Bug fix

  • WantsToDisplayMessage pointer comparisonmessage.mText == "" was comparing a char[128] buffer address against a string literal address (always false). Corrected to message.mText[0] == '\0'.

Known limitation

  • The "Auto camera: on/off" message does not appear in LMU. LMU appears not to implement the WantsToDisplayMessage InternalsPlugin callback. An alternative notification path for LMU is under investigation.

No gameplay changes

This release contains no changes to camera selection logic or autocam behaviour.

v1.3.3 - Fix: playerDriving check refined to mPitState

26 May 21:15

Choose a tag to compare

v1.3.3 - Fix: playerDriving check now uses mPitState

Fixes a regression introduced in v1.3.2 where autocam was suspended even
while the player was waiting in the pit box before going out on track.

In rF2, WantsToViewVehicle is still called during that window, so watching
other cars from the garage was possible before - and should remain possible.

Change: playerDriving check is now mIsPlayer AND mFinishStatus==0 AND mPitState==0

mPitState==0 means the car is physically on track (not in pit lane, pit box, or garage).

Behaviour:
Active lap on track => playerDriving true, camera switching suspended
Waiting in pit/garage => playerDriving false, autocam active
DNF / finished => playerDriving false, autocam active
Spectator => playerDriving false, autocam active

v1.3.2 - Safety: suspend camera when player is driving

26 May 21:06

Choose a tag to compare

v1.3.2 - Safety: suspend camera switching while player is driving

Bug fix: In LMU, the REST API could forcibly switch the camera away from the player while driving. In rF2, enabling autocam had a 15-20 second delay before first switch.

Plugin changes:

  • playerDriving detection (mIsPlayer and mFinishStatus == 0)
  • Camera selection and REST API calls skipped while driving
  • Autocam resumes automatically on DNF or spectator entry
  • First-switch delay removed when toggling ON
  • HUD message now shown in LMU on toggle
  • status.json: new player_driving field

OBS Lua script changes:

  • player_driving_start trigger (false to true)
  • player_driving_end trigger (true to false, DNF or spectator)

v1.3.1 - OBS Lua script for race-event automation

26 May 05:09

Choose a tag to compare

v1.3.1 — OBS Lua script for race-event automation

Adds obs-script/autocam_obs.lua — an OBS Lua script that reads status.json
from the plugin and fires configurable OBS actions (scene switch, source show/hide,
media playback) whenever race events occur.

Setup

  1. In OBS: Tools → Scripts → + → select autocam_obs.lua
  2. Set status.json path in the script settings
    • Same-PC: C:\...\rF2stream\status.json
    • Two-PC (network share): \\game-pc\rF2stream\status.json
  3. Configure actions per trigger — all settings are optional, leave blank to skip

Triggers

Trigger Fires when…
Replay started / ended on_replay changes
Battle started / ended in_battle changes
Side-by-side started / ended sbs_active changes
Leader changed leader field changes
Formation lap game_phaseformation
Green flag game_phasegreen
Safety car / FCY game_phaseyellow
Red flag game_phasestopped
Race finished game_phasefinished

Per-trigger actions

Setting Description
Switch scene OBS scene to activate
Show sources Comma-separated source names to make visible
Hide sources Comma-separated source names to hide
Trigger media source Media Source to restart/play
Auto-restore after N sec Reverses show↔hide automatically (0 = off)

Example: replay scene with auto-return

  • Replay started → Switch scene: Replay, Show: Replay Overlay
  • Replay ended → Switch scene: Live, Hide: Replay Overlay

Example: leader-change banner (auto-hide after 5 s)

  • Leader changed → Show: Leader Banner, Auto-restore: 5

Notes

  • First poll establishes a silent baseline — no triggers fire on OBS startup
  • Two-PC setups: UNC paths (\\game-pc\rF2stream\status.json) work natively
  • No extra software required beyond OBS itself
  • Requires rf2-autocam v1.3.0 or later for in_battle, sbs_active, leader, and game_phase fields

v1.3.0 - Enhanced status.json for OBS integration

26 May 05:00

Choose a tag to compare

v1.3.0 — Enhanced status.json for OBS integration

Extends status.json with four new fields that enable richer OBS Lua script automation — scene switching, overlays, and audio triggers based on race events.

New status.json fields

Field Type Description
in_battle boolean true when the tightest on-track gap is within the onboarddiff threshold — same condition used internally for onboard camera trigger
sbs_active boolean true when two or more cars are running side-by-side within sbsdist meters at the same track position
leader string Driver name of the current P1 (session leader) — useful for detecting lead changes
game_phase string Race phase: garage / warmup / formation / green / yellow (safety car / FCY) / stopped (red flag) / finished

Example output

{
  driver:       Verstappen,
  position:     3,
  camera:       trackside,
  on_replay:    false,
  autocam:      true,
  session_type: race,
  game_phase:   green,
  time_display: 01:23:45,
  gap_to_next:  0.312,
  in_battle:    true,
  sbs_active:   false,
  leader:       Hamilton
}

OBS automation possibilities

Trigger Field to watch
Replay scene switch on_replay true/false
Battle overlay in_battle true/false
Side-by-side graphic sbs_active true/false
Lead change banner leader value changes
Safety car overlay game_phase == yellow
Post-race endcard game_phase == finished

Implementation notes

  • in_battle and sbs_active are computed from existing internal state (pontosminbehind, obtime, maxsbs, sbscount) — no new tracking logic added
  • leader maps to the existing internal P1 driver name already tracked for formation-lap walk-through
  • game_phase is derived from mGamePhase (rF2/LMU API field) and stored as a member variable set each scoring update
  • No changes to existing fields; fully backwards compatible

v1.2.0 - Code refactoring

26 May 03:46

Choose a tag to compare

v1.2.0 - Refactoring: improved code structure and readability

No functional changes. This release improves maintainability and readability of the codebase.

Phase 1 — Constants & cleanup

  • Extracted ResetSessionState() to eliminate ~25 lines of duplicate reset logic shared between Startup() and StartSession()
  • Added named constants replacing bare magic numbers:
    • kNoLapTime (2147483640.0) — sentinel for no valid lap time
    • kNoLapLimit (2147483640) — sentinel for time-based race (no lap limit)
    • kCamTrackside (4) — trackside camera type index
  • Moved environmentAlreadySet from public to private

Phase 2 — UpdateScoring() split

  • Broke 390-line UpdateScoring() into focused private methods:
Method Lines Responsibility
ScanVehicles() 28 Prelist pass: leader, best lap, allfinished
SelectCameraQualifying() 38 Practice / qualifying camera logic
SelectCameraRace() 124 Race camera logic (SBS, pit, last lap)
DetectIncidents() 60 mResultsStream incident detection
ResolveTargetVehicle() 38 needpos → needveh + camera type
WriteSessionOutputs() 69 Time string, file writes, debug log
  • UpdateScoring() reduced from ~390 to 73 lines (orchestration only)

Verified on

  • rF2 (via WantsToViewVehicle)
  • LMU (via REST API)

v1.1.1

26 May 02:05

Choose a tag to compare

Bug fixes

  • LMU: Ctrl+A toggle now works — LMU does not call the \CheckHWControl\ callback, so the hotkey was silently ignored. Added fallback key detection in \UpdateScoring\ so the toggle works in both rF2 and LMU.

The same
f2autocam_x64.dll\ works for both games — no separate build needed.

v1.0.1 — Incident replay loop fix

25 May 01:19

Choose a tag to compare

Bug Fixes

Incident replay firing on loop (fix for lowinc/highinc workaround)

The full mResultsStream buffer was re-scanned on every UpdateScoring call (2×/sec).
After a replay triggered and reset pincsize to 0, the same incident text remained in the
buffer and was immediately re-detected, causing the replay to fire again and again in a loop.

Fix: only the newly appended portion of the stream is scanned on each call.
Previously-processed events are never re-examined. The default lowinc/highinc values
(0.4 / 0.8) now work as intended — the lowinc=40000 workaround is no longer needed.

Toggle hotkey default restored to Ctrl+A

The default autokey value was inadvertently changed to 0xBE (Ctrl+.) in v1.0.0.
Restored to 0x41 (Ctrl+A) to match the original plugin default that existing users expect.


Full changelog: v1.0.0...v1.0.1