Integrating any radar
Wire tDetector to any radar resource — including encrypted ones you cannot edit — with state bags, events, exports, or the bridge resource.
Integration answers one question, asked on the transmitting player's machine: is my radar keyed up right now? Everything else — range, bands, strength, arrows, sound — tDetector already does.
tRadar, wk_wars2x, seeker_dual, rs9000 and ProLaser4 are configured out of the
box, with ready-made exports under Install → Patch your radar on the tDetector index
page. For anything else, stop at the first row that fits.
| Radar edited? | Survives a radar update? | Use when | |
|---|---|---|---|
| Export | Usually yes | No | The radar already exports something, or you can edit it |
| State bag | No | Yes | The radar publishes its state into a bag. Best for an escrowed radar |
| Event | No | Yes | The radar fires an on/off event — last resort |
| Bridge resource | No | Yes | The answer needs real logic |
Try the bare name first. A name on its own is probed against the exports radars
actually use — GetDetectorSignature, IsRadarActive, IsRadarOn, GetRadarState,
IsTransmitting.
Config.radarResources = { "tRadar", "my_radar" }A miss is tried once, remembered, and cleared when that resource restarts — so patching a radar and restarting it is enough.
1. Export
tDetector calls the function once per Config.radarStateInterval. Naming export means
that export only, skipping the probe order.
Config.radarResources = {
{ resource = "my_radar", export = "RadarIsOn", band = "k" },
}| Export | Return |
|---|---|
GetDetectorSignature() | false/nil when idle, or { band = "ka", frequency = 34.712, mode = "instant", range = 150.0 }. All four fields optional. |
IsRadarActive() | true while powered and transmitting. |
Neither needs an fxmanifest.lua entry. GetDetectorSignature() may also return a bare
band string, read as a state bag value is; a table carrying
active = false or transmitting = false reads as idle whatever else is in it. A
frequency outside its band is dropped, and a range of zero or less is unreported.
Constant-on and instant-on
mode = "instant" lights the I/O badge and holds the alert for a few seconds. The
field is case-insensitive and trimmed — "instant-on", "i/o", "pulse", "burst"
and "trigger" all read as instant-on, as does instant = true. Say nothing and you get
"constant".
How far your radar reaches
range is optional, in metres: how far your radar can clock an ordinary car. It is
heard out to range × Config.detectionRatio. Without it, every radar is heard at the
flat Config.detectionRange. The server rejects an absurd value and each receiving
client clamps the reach to Config.detectionRangeMax.
An edited radar export is fragile
An export you added to someone else's resource is gone the next time you update it, and it fails silently — no error, no log line, nothing on screen. Put it in a bridge resource instead.
2. State bag
Needs no changes to the radar. A radar that draws its own NUI usually already publishes its state into a bag.
Config.radarResources = {
{ resource = "their_radar", statebag = "radarTransmitting" },
{ resource = "veh_radar", statebag = { key = "on", bag = "vehicle" }, band = "k" },
}bag is "player" (default), "vehicle" or "global".
What the value may be
| Value | Read as |
|---|---|
true | Transmitting, on the band from your config entry |
"ka" / "k" / "x" / "laser" | Transmitting, on that band |
{ band = "ka", frequency = 34.712, mode = "instant", range = 150.0 } | Transmitting, all four carried through |
| Anything else | Idle |
That last row is strict: "off" and "standby" read as idle, and so does a misspelled
band.
State bags are read fresh every time, so they cannot drift out of sync.
3. Event
Needs no changes to the radar. tDetector latches onto an event the radar already
fires, subscribing with both RegisterNetEvent and AddEventHandler.
Config.radarResources = {
{ resource = "old_radar", event = { on = "rdr:on", off = "rdr:off" }, band = "ka" },
-- or one event whose payload says what happened
{ resource = "old_radar", event = "rdr:stateChanged" },
}The payload is read like a state bag value, and one that reads as idle clears the latch — which is what makes the one-event form work both ways. An edge with no payload at all means "transmitting on the configured band and mode".
4. The bridge resource
bridge/tdetector_bridge/ is a resource you copy out and edit, for when the answer
needs logic config cannot express. Copy it into resources, ensure it between your
radar and tDetector, name it in Config.radarResources, and fill in its one
isTransmitting() function — three worked examples are commented out above it. Return
false when idle, or true / { band = ... } / the full signature table.
Keep it cheap: it runs once per Config.radarStateInterval, so no loops over players,
no waits, no blocking natives. A mistake in it is reported once and then reports idle.
Diagnosing it: /tDetSources
Per entry, in the F8 client console: the resource and whether it is started; the
mechanism; which export names answered, are not present, or were not tried;
the exact bag and key, present or ABSENT; which events are subscribed and whether the
latch is set; and whether the source is transmitting right now, with band, frequency,
mode and reach. The same problems print once at startup on the server console.
The closing line matters most. Nothing transmitting while your radar is keyed up
means the wiring is wrong — work back up this page. Transmitting but others see no
alert means this side is right: run tdetector_diag on the server console and read its
radar sync section, which says how many radars the server believes in and whether a
radar resource is running at all. If the server believes the radar, the remaining causes
are range and sensitivity.
/tDetSources test runs a 12-second sweep on your own display, in a vehicle with the
detector on. If it looks right, every missing alert is a wiring problem.
When a radar exposes nothing at all
An escrowed radar with no export, no state bag and no event is unreachable, bridge included. Paste this to its author:
Could you add a client export so radar-detector resources can tell when the unit is transmitting?
exports('IsRadarActive', function() return <powered AND transmitting> end)is enough. It needs nofxmanifest.luaentry, it is read-only, and it changes nothing about how the radar behaves. A state bag carrying the same boolean works too.
Reference: the entry shapes
Config.radarResources = {
"wk_wars2x", -- default probe order
{ resource = "my_radar", export = "RadarIsOn", band = "k" }, -- one named export
{ resource = "io_radar", export = "RadarIsOn", band = "ka", mode = "instant" },
{ resource = "their_radar", statebag = "radarTransmitting" },
{ resource = "veh_radar", statebag = { key = "on", bag = "vehicle" } },
{ resource = "old_radar", event = { on = "rdr:on", off = "rdr:off" } },
{ resource = "old_radar", event = "rdr:stateChanged" },
}| Field | Meaning |
|---|---|
resource | The resource name as it appears in your resources folder |
band | "ka", "k", "x" or "laser", case-insensitive. A fallback only; a radar naming its own band overrides it. Defaults to "ka" — K and X share a band with civilian falses. |
mode | "constant" or "instant". Also a fallback the radar's report overrides. |
export / statebag / event | Exactly one. Omit all three for the default probe order. |
probes | Export names to try in order instead of the default list. export takes precedence. |
Entries are probed in order and the first transmitting wins, so put your primary radar at the top.
Optional: let the server corroborate the claim
The report reaching the server is a claim a modified client could make. tDetector
checks it two ways: at least one name in Config.radarResources must be started, and
if a radar can answer for itself it is asked and its answer wins.
That second check is a server-side export, worth adding only if your radar knows server-side who is transmitting. Most do not, and leaving it out changes nothing.
-- A SERVER script in your radar resource. GetPlayerRadarState is read identically.
exports('IsPlayerRadarTransmitting', function(src)
-- true | false | nil ("I have no record of that player")
return transmittingBySource[src]
end)nil falls back to the resource-running check. Only false refuses a claim, including
after an alert is already up. A bridge is client-side, so it is accepted on the first
check alone.
Next steps
- Troubleshooting — when the wiring is right and alerts still do not appear.
- Configuration — the range and band values every source is measured against.
Radar Detector
Still stuck? Support can answer it directly.
Was this page helpful?
TIMMYG Studios