Skip to content

Installation ​

Requirements ​

  • A recent FiveM server artifact (uses entity state bags and Lua 5.4)

Nothing else is required. The NUI in html/ is plain HTML/CSS/JS with vendored fonts, so there is nothing to build.

Optional dependencies ​

Everything below is auto-detected. Start these resources before np_helicam.

KindResourcesWhat it adds
Frameworkqbx_core, qb-core, es_extendedJobs and duty for the air / ground / bolo roles, and callsigns (qb / qbx metadata.callsign)
Fuelox_fuel, LegacyFuel, cdn-fuel, ps-fuelFUEL % and endurance on the HUD. Without one, the native fuel level is used, and nothing is shown if it is 0
Notificationsnp_hud, ox_libUsed when Config.Notify.provider is 'np_hud' or 'ox_lib'. Otherwise the built-in Nimbus toasts
Evidencescreenshot-basicB (bookmark) also takes an evidence screenshot

Steps ​

  1. Put the resource in resources/ as np_helicam. The NUI callbacks use the resource name.
  2. Add it to server.cfg, after its optional dependencies:
    cfg
    ensure qbx_core          # or qb-core / es_extended, if you use one
    ensure ox_fuel           # optional
    ensure np_hud            # optional, for Config.Notify.provider = 'np_hud'
    ensure screenshot-basic  # optional, evidence screenshots
    ensure np_helicam
  3. Open config.lua and set at least:
    • Config.Helicopters: the models that have the camera
    • Config.Jobs: which jobs get the air, ground and bolo roles (framework servers)
    • Config.Callsigns: the air callsign, per model if you like
    • Config.Department and Config.Callsign: the text in the HUD header
  4. Optional: set the Discord webhook for mission reports (see below).

Start order

The framework bridge on the server re-detects when qbx_core, qb-core or es_extended starts after np_helicam. Fuel and notification providers are looked up when they are used. The safe order is still: dependencies first.

Roles ​

There are three roles. The server checks them on every action, and the client only uses its copy to show or hide UI.

RoleGrants
airOpen the camera, place / rename / delete markers, BOLO checks from ANPR, mission recording, crew share
groundThe F7 Air Support panel, the live feed, orbit requests, BOLO and share alerts
boloManage the BOLO list with /bolo (the role is set by Config.Bolo.commandJobs)

air and ground receive the marker list and can subscribe to the friendly-unit positions. Either role, or sitting in a camera heli, opens the F9 settings sheet. bolo is separate so that, for example, EMS keep the Air Support panel but can't flag plates.

With a framework ​

Config.Framework = 'auto' picks the first of qbx_core, qb-core, es_extended that is started. A player has a role when their job name is in Config.Jobs.air / .ground / .bolo:

lua
Config.Jobs = {
  air = { 'police', 'sheriff', 'lspd', 'bcso', 'sasp' },
  ground = { 'police', 'sheriff', 'lspd', 'bcso', 'sasp', 'ambulance' },
  bolo = { 'police', 'sheriff', 'lspd', 'bcso', 'sasp' },
  requireDuty = true,     -- qb / qbx: job.onduty must be true
  standaloneAllow = true,
}

ESX has no duty flag, so having the job counts as on duty. Job and duty changes are picked up through the framework events (QBCore:Server:OnJobUpdate, QBCore:Server:SetDuty, esx:setJob, …) and pushed to the client.

Standalone (ACE) ​

Without a framework, Config.Jobs.standaloneAllow = true gives everyone every role, like v1. To restrict it, set it to false and grant ACE permissions:

cfg
add_ace group.police np_helicam.air allow
add_ace group.police np_helicam.ground allow
add_ace group.police np_helicam.bolo allow

With standaloneAllow = false, only players with the ACE have the role. ACE is only consulted in standalone mode.

Config.CanUse ​

Config.CanUse(ped, heli) still exists. It runs on the client each time the camera opens and each time the searchlight or hover key is pressed outside the camera. Return false to deny:

lua
Config.CanUse = function(ped, heli)
  return GetVehicleLivery(heli) == 0 -- e.g. only the police livery
end

Client-side only

Config.CanUse is a UX gate, not a security boundary. The real gate is the role check on the server. Every server handler re-checks the role, the seat (for air actions) and rate limits. Clients write no state bags: the server validates what the operator sends and writes the bags itself.

Discord webhook ​

Finished mission reports can be posted to a Discord channel. The URL is a server convar, never part of config.lua, because that file is shared and is sent to every client:

cfg
set np_helicam_webhook "https://discord.com/api/webhooks/..."

It must start with https://. The post is an embed with the plain-text report, the duration, distance, event count and operator. Screenshots are not uploaded to Discord. See Operations → Mission recording.

Troubleshooting ​

SymptomFix
E does nothingCheck that the model is in Config.Helicopters (the lowercase spawn name, matched by model hash), that you sit in a seat in Config.CameraSeats, that you have the air role (job + duty, or ACE), and that Config.CanUse returns true. In the first second after joining, the role may not have arrived yet.
E, F7 or F9 conflicts with another scriptRebind it in Settings → Key Bindings → FiveM. Every action is a key mapping. The settings sheet uses F9 because qb-radialmenu binds F1.
F7 does nothingYou don't have the ground role. Check Config.Jobs.ground, duty, or the np_helicam.ground ACE. Without the role, F7 is silent on purpose.
F9 does nothingYou have neither the air nor the ground role and don't sit in a camera heli.
/bolo says "Not authorised."You don't have the role in Config.Bolo.commandJobs (default bolo: Config.Jobs.bolo, or the np_helicam.bolo ACE).
Minimap is in the wrong place after closing the camera or the Air Support panelAnother HUD (e.g. np_hud) placed the minimap. Set Config.ContextMap.restore to its layout, or have it listen for np_helicam:contextMap.
No FLIR right after opening the cameraFLIR warms up for Config.Thermal.warmupMs (8 s). The FLIR pill shows the percentage.
Grainy pictureConfig.Camera.cctvEffect is on (server-wide), or the player turned on CCTV grain in F9.
No fuel on the HUDNo fuel resource is started and the native fuel level is 0.
Hover won't engageYou are below Config.Hover.minAltitude (15 m) or faster than Config.Hover.maxEngageSpeed (12 m/s). Hover is a hold, not an autobrake.
B takes no screenshotscreenshot-basic is not started, or Config.Mission.screenshots is false. One screenshot per 5 s per player.
A searchlight stays lit after the operator leftThe server sweep turns it off within about 10 s once its operator is no longer in a camera seat with the air role. See Searchlight sync.

np_* FiveM resources