|
| 1 | +# NewStarGP Telemetry Mod — Force Feedback (FFB) Planning |
| 2 | + |
| 3 | +## Status |
| 4 | +Drafting phase only. No implementation changes yet. |
| 5 | + |
| 6 | +## Goals |
| 7 | +- Add steering wheel integration for NewStarGP telemetry output. |
| 8 | +- Use telemetry to drive force feedback (FFB) on supported wheels. |
| 9 | +- Feed a virtual Xbox gamepad via ViGEm from wheel input. |
| 10 | +- Keep architecture extensible for multiple wheel backends. |
| 11 | + |
| 12 | +## Confirmed Constraints |
| 13 | +- Work resides under `NewStarGP-TelemetryMod` submodule in this repository. |
| 14 | +- Branch: `ffb`. |
| 15 | +- **Do not modify `TelemetryExtractor`** at this stage. |
| 16 | + - `TelemetryExtractor` is intended to remain generic/non-game-specific. |
| 17 | +- Consume telemetry after plugin enhancement (game-specific enrichment such as tire data). |
| 18 | +- Runtime tuning must be exposed via **BepInEx config** (live adjustable via config UI). |
| 19 | +- Moza-first implementation priority. |
| 20 | + |
| 21 | +## Dependencies |
| 22 | +- Virtual gamepad: `Nefarius.VigemClient` (NuGet) |
| 23 | +- Wheel input fallback path (later): SharpDX / DirectInput |
| 24 | +- Primary wheel SDK (v1): Moza C# SDK |
| 25 | + - Present in branch under `libs/moza/x64/MOZA_API_CSharp.dll` |
| 26 | +- Moza examples/docs in repo: |
| 27 | + - `libs/moza/example` |
| 28 | + - `libs/moza_cpp/docsEng/index.html` |
| 29 | + |
| 30 | +## High-Level Architecture |
| 31 | + |
| 32 | +### Data Flow |
| 33 | +1. `TelemetryExtractor` produces base telemetry (unchanged). |
| 34 | +2. Plugin enriches telemetry with game-specific fields (tires, survival points, etc.). |
| 35 | +3. Enhanced telemetry is published to a runtime-accessible state store. |
| 36 | +4. Wheel runtime consumes enhanced telemetry each update and: |
| 37 | + - maps wheel inputs to virtual Xbox controller state |
| 38 | + - computes FFB torque/effects and sends to wheel backend |
| 39 | + |
| 40 | +### Lifecycle |
| 41 | +Create one long-lived runtime service as part of plugin lifecycle: |
| 42 | +- initialize once on plugin startup |
| 43 | +- update every plugin tick / frame |
| 44 | +- dispose once on plugin unload |
| 45 | + |
| 46 | +## Proposed Components (Draft) |
| 47 | + |
| 48 | +### Runtime |
| 49 | +- `Runtime/WheelIntegrationRuntime.cs` |
| 50 | + - Orchestrates provider initialization, per-frame update, and disposal. |
| 51 | +- `Runtime/TelemetryStateStore.cs` |
| 52 | + - Holds latest enhanced telemetry snapshot (thread-safe access). |
| 53 | + |
| 54 | +### Contracts |
| 55 | +- `Contracts/IWheelInputProvider.cs` |
| 56 | +- `Contracts/IWheelFfbProvider.cs` |
| 57 | +- `Contracts/IVirtualGamepadOutput.cs` |
| 58 | + |
| 59 | +### Moza Backend |
| 60 | +- `Moza/MozaSdkAdapter.cs` |
| 61 | + - Single boundary around vendor SDK calls. |
| 62 | +- `Moza/MozaWheelInputProvider.cs` |
| 63 | +- `Moza/MozaWheelFfbProvider.cs` |
| 64 | + |
| 65 | +### Virtual Controller |
| 66 | +- `Output/VigemXboxGamepadOutput.cs` |
| 67 | + |
| 68 | +### FFB Model |
| 69 | +- `Ffb/FfbModel.cs` |
| 70 | + - Converts enhanced telemetry into FFB command(s) |
| 71 | + - Applies thresholds, cooldowns, gains, smoothing, clamping |
| 72 | + |
| 73 | +### Models |
| 74 | +- `Models/WheelInputState.cs` |
| 75 | +- `Models/VirtualPadState.cs` |
| 76 | +- `Models/FfbCommand.cs` |
| 77 | + |
| 78 | +### Config |
| 79 | +- `Config/WheelConfig.cs` |
| 80 | + - BepInEx `ConfigEntry<T>` bindings and ranges |
| 81 | + |
| 82 | +## BepInEx Runtime Config (Draft) |
| 83 | +All values should be editable at runtime through BepInEx config UI. |
| 84 | + |
| 85 | +### `Wheel/General` |
| 86 | +- `Enabled` (bool, default `true`) |
| 87 | +- `Backend` (string, default `Moza`) |
| 88 | +- `RequireX64` (bool, default `true`) |
| 89 | + |
| 90 | +### `Wheel/FFB` |
| 91 | +- `OverallStrength` (float, default `1.0`, range `0.0..2.0`) |
| 92 | +- `MaxTorque` (float, default `1.0`) |
| 93 | +- `BumpThreshold` (float, default `0.15`) |
| 94 | +- `BumpScale` (float, default `0.35`) |
| 95 | +- `BumpCooldownMs` (int, default `60`) |
| 96 | +- `CForceDampingScale` (float, default `0.4`) |
| 97 | +- `SmoothingAlpha` (float, default `0.25`, range `0..1`) |
| 98 | + |
| 99 | +### `Wheel/Input` |
| 100 | +- `SteerDeadzone` (float) |
| 101 | +- `SteerSaturation` (float) |
| 102 | + |
| 103 | +## FFB Behavior Plan (v1) |
| 104 | + |
| 105 | +### 1) Tire Impact Impulses |
| 106 | +- Generate small directional impulses from left/right tire impact signals. |
| 107 | +- Apply a threshold to ignore minor bumps. |
| 108 | +- Apply cooldown to avoid rapid repeated impulses. |
| 109 | + |
| 110 | +### 2) CForce-Based Resistance |
| 111 | +- Use CForce to increase directional resistance (damping/friction-like feel). |
| 112 | +- Scale by configurable gain. |
| 113 | + |
| 114 | +### 3) Global Strength |
| 115 | +- Multiply total FFB by `Wheel/FFB/OverallStrength`. |
| 116 | +- Clamp final torque to `MaxTorque`. |
| 117 | + |
| 118 | +### 4) Smoothing |
| 119 | +- Apply lightweight smoothing to reduce jitter/chatter. |
| 120 | + |
| 121 | +## Input Mapping Plan (v1) |
| 122 | +- Wheel steer axis -> virtual gamepad left-stick X (deadzone removal + rescale). |
| 123 | +- Basic pedal mapping to triggers where available. |
| 124 | +- Button/paddle mapping can be expanded later. |
| 125 | + |
| 126 | +## Platform and Safety |
| 127 | +- Assume game process is x64; verify at runtime. |
| 128 | +- If required SDK/controller init fails, disable wheel integration gracefully (no plugin crash). |
| 129 | +- Ensure clean teardown/disposal on unload. |
| 130 | + |
| 131 | +## Deferred / Low Priority |
| 132 | +- Tire slip behavior causing temporary wheel loosening. |
| 133 | +- Roll/pitch angular velocity collision heuristics. |
| 134 | +- DirectInput backend parity. |
| 135 | + |
| 136 | +## Open Questions |
| 137 | +1. Exact Moza SDK C# method signatures for init/poll/ffb/dispose. |
| 138 | +2. Required call frequency/threading constraints from Moza docs. |
| 139 | +3. Final telemetry field names for left/right tire impacts and CForce. |
| 140 | +4. Preferred location for `plan.md` if not repository root. |
| 141 | + |
| 142 | +## Suggested Implementation Phases |
| 143 | +1. Skeleton runtime + config entries (no active FFB) |
| 144 | +2. Moza input polling + ViGEm output mapping |
| 145 | +3. Add CForce resistance effect |
| 146 | +4. Add tire impulse effects with threshold/cooldown |
| 147 | +5. Tune defaults and safety clamps |
| 148 | +6. Add DirectInput backend later behind same interfaces |
| 149 | + |
| 150 | +--- |
| 151 | + |
| 152 | +Owner note: This file is intentionally planning-only and should be updated before implementation begins. |
0 commit comments