Releases: seikenxa/rf2-autocam
v1.5.0 - Incident signal + Live Cut manual replay
New
- Incident signal.
status.jsonnow includes anincidentboolean (true forincidentholdseconds after any detected incident, on both rF2 and LMU). The OBS Lua script gainsincident_start/incident_endtriggers — 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 forincidentholdseconds, 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
incidentsignal — is your cue. Setincidentholdto ~20 so the focus covers watching the replay. - Default
livecut=0keeps the previous automatic-replay behaviour.
replaykey=autoreads the sim's own Instant Replay key binding (rF2Controller.JSON/ LMUkeyboard.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/highincdefaults 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 ofmIsPlayer, 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) gainsimag/inc/lcf/orp/lo/hi/lc/pctlfields.
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
Fixes
- Auto camera froze after taking control of a car (DRIVE). rF2 latches
mReplayActive=trueafter 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 ofmReplayActive. - 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).
UpdateScoringnow 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/wpathfields (debug=1only).
Install
Drop rf2autocam_x64.dll into ...\rFactor 2\Bin64\Plugins\.
v1.3.5 - Fix WantsToDisplayMessage check
Changes
Bug fix
WantsToDisplayMessagepointer comparison —message.mText == ""was comparing achar[128]buffer address against a string literal address (alwaysfalse). Corrected tomessage.mText[0] == '\0'.
Known limitation
- The "Auto camera: on/off" message does not appear in LMU. LMU appears not to implement the
WantsToDisplayMessageInternalsPlugin 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
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
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
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
- In OBS: Tools → Scripts → + → select
autocam_obs.lua - Set
status.json pathin the script settings- Same-PC:
C:\...\rF2stream\status.json - Two-PC (network share):
\\game-pc\rF2stream\status.json
- Same-PC:
- 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_phase → formation |
| Green flag | game_phase → green |
| Safety car / FCY | game_phase → yellow |
| Red flag | game_phase → stopped |
| Race finished | game_phase → finished |
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, andgame_phasefields
v1.3.0 - Enhanced status.json for OBS integration
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_battleandsbs_activeare computed from existing internal state (pontosminbehind,obtime,maxsbs,sbscount) — no new tracking logic addedleadermaps to the existing internal P1 driver name already tracked for formation-lap walk-throughgame_phaseis derived frommGamePhase(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
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 betweenStartup()andStartSession() - Added named constants replacing bare magic numbers:
kNoLapTime(2147483640.0) — sentinel for no valid lap timekNoLapLimit(2147483640) — sentinel for time-based race (no lap limit)kCamTrackside(4) — trackside camera type index
- Moved
environmentAlreadySetfrompublictoprivate
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
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
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