Skip to main content
The Frequency minigame is the only one in cc_minigames that requires the server. Two players collaborate: a viewer sees a target waveform, and a tuner adjusts probe frequency and amplitude until both axes are within tolerance, then both hold for holdSeconds to win. The server holds the canonical state and ticks the hold-timer at 100 ms — neither client can spoof a “locked” frame to fake a win.

Server export

FrequencyStart returns a promise that resolves with the success boolean. From inside a server thread you can also Citizen.Await(p) to block on it.

Per-difficulty defaults

Server export reference

Cross-resource event

When a session ends, the server fires:
This is a regular Lua event (server-local, not net), so any other server resource can AddEventHandler it and react when a frequency session resolves — useful when the server resource that started the session was in a different lifecycle than the one that needs to react to the result.

What happens on the wire

1

Server picks targets, seeds probes off-target

targetFreq and targetAmp are randomized within their bounds. probeFreq and probeAmp are re-rolled until they’re at least 25% off-target on each axis, so the game never spawns already-locked.
2

Server fans out the join event

Both clients receive cc_minigames:cl:frequency:join carrying the token and their assigned role. Each client runs the local Frequency minigame export.
3

Tuner inputs go to the server

A/D/W/S on the tuner client fire cc_minigames:sv:frequency:input with { axis, dir }. Server clamps and applies the step. Viewer inputs are silently ignored.
4

Server ticks at 100 ms

On each tick: drift advances the target on harder tiers, the timer counts down, and the hold-meter accumulates while both axes are within tolerance and decays 1.5× faster when out. State is broadcast to both clients.
5

Hold target met → success

When holdMs reaches holdSeconds × 1000, the server fires cc_minigames:cl:frequency:finish to both clients with success = true, resolves the promise, and emits cc_minigames:sv:frequency:finished for cross-resource listeners.
6

Anything else → fail

Time limit hit, either player escapes the local minigame, or either player drops — the session resolves false with the same fan-out.

Variants

Embedding the viewer in a DUI

A common heist setup: the viewer’s waveform is on a wall-mounted CRT prop, the tuner is a player at a console nearby. Use the DUI session helper for the viewer side and pass viewerEmbed = true so the server doesn’t try to push a fullscreen NUI to that player.
The server’s per-tick state events are forwarded into the DUI automatically because the DUI session registered its sessionToken.

Test it solo

For visual debugging without a partner the local /minigame command bypasses the server session entirely and renders both halves in one card:
This drives a fake state loop in the NUI — useful for tuning visuals or layout without two clients.