Jixryo Trail Cams
Trail cameras strapped to trees or set on steel poles, with SIM cards, motion detection checked by the server, photos, a live feed, alerts on the phone and the tablet, department cameras for the police, and a Staff tab.
Version 1.3.0 Updated See it on its script page
On this page
Jixryo Trail Cams puts real trail cameras in the world. Buy one, strap it to a tree or drive a steel pole into open ground, slot a SIM card, and the camera watches its cone for animals, people and vehicles. Nearby players' games report what is really inside it; the server checks every report, names the species or the vehicle itself, records the sighting and sends the alert to the camera's owner. The TrailCam app shows your cameras as live feeds, the sightings as a photo wall, your alert settings and, for staff, every camera in the city. It comes as two resources: jixryo_trailcam (the cameras) and jixryo_trailcam_app (the TrailCam tablet, the lb-phone app and the app on the Jixryo Tablet).
What players get
- Two cameras, each its own item, modelled on a cellular trail camera. The Ranger sees 14 m across 110 degrees. The Cellular Pro sees 20 m across 100 degrees, and its solar panel makes the battery last longer. On a tree the camera hangs on a strap fitted to the trunk: each game measures the trunk and shows the small, medium or large strap.
- Placement. A ghost of the camera follows your aim with its detection cone, and a panel shows the mount, the pole and the SIM card, which way it faces, how high it sits and whether it is in reach and far enough from other cameras. Trunks, posts and walls take a strap; open ground takes the pole item. Tree mounts can be fine-tuned with the game's 3D gizmo. Then the work: wrap the strap round the trunk and cinch it, or drive the pole in (it sinks as you hammer) and screw the camera onto its bracket. Every step is an animation with a progress bar and a skill check, a slip can be retried twice, and nothing is taken from you until the camera is up. Up to 5 cameras per player, within 6 m of you, no higher than 2.5 m up a trunk, at least 20 m from any other camera.
- SIM cards. A camera reports through its SIM. Without one it still sits there, but no sightings, alerts, photos or live feed get through. Placing a camera puts a SIM from your pockets in; the owner takes it out or puts one in later. Anyone else can pry it out through a hard skill check: the camera's last act is a photo of them and an alert to the owner.
- The status light blinks slow green while the camera watches, fast green while it arms, amber on a low battery and red without a SIM, and goes dark when the battery dies. At night the four IR windows glow red when it fires.
- The close-up. "Look at the screen" moves your view in to the camera's own screen: its battery, signal or NO SIM, when it last fired and the time; the panel beside it says the same in words. Anyone can read it; only the owner sees the camera's name.
- Motion detection. A new camera waits 45 seconds before it starts watching. Games within 60 m scan its cone every 1.5 seconds for distance, field of view and line of sight; the server re-checks the reporter's position and every cooldown, records one event per camera every 20 seconds at most, and keeps the newest 60.
- Photos are taken when you capture one: the snapshot button in a camera's live feed. A sighting on its own records what was seen and sends the notification without touching anyone's screen. Photos upload to Fivemanage when a key is set, otherwise they are resized to 1280 by 720 and stored in the database; lists only carry thumbnails, and the newest 20 photos per camera are kept.
- Live view. A full-screen feed from the lens with the camera and area, battery, signal, night and time pills, the heading, the zoom and the key hints. Scroll zooms, the right mouse button toggles night vision, the left takes a snapshot, the arrows switch between your cameras. A session lasts 5 minutes at most, your character stands still, and taking damage, a dead battery or a destroyed camera cuts the feed with a SIGNAL LOST banner.
- Alerts. Nothing pops up over the game. Motion and camera health arrive as a notification on lb-phone (with the photo when photos are hosted, and a Watch live button), on the TrailCam tablet while it is open, and in the Jixryo Tablet's notifications. Each player picks which kinds they get in the app's settings.
- Battery. It drains 1.4 percent per real hour (about three days a cell), 0.15 percent per trigger and 1 percent per minute watched; the Cellular Pro drains at 0.6 of that. Swap it with the battery item. The low alert fires at 20 percent, once per battery.
- Destructible. One shot or swing wrecks a camera, and it hangs off its strap.
What staff get
- Police cameras. On-duty officers of any job of type
leoset department cameras with the Surveillance Cam from the armory. A department camera belongs to the department, not the officer: every on-duty officer of it sees it in the tablet and the phone app, gets its alerts, watches it live, takes it down and swaps its battery. It runs on the department network with no SIM, is named PD-01, PD-02 and so on, sees 22 m across 100 degrees, and nobody outside the department can take it or pry it open. Up to 30 per department. - The Staff tab, for players with the
godoradminACE: every camera in the city with search, filters, photos, a staff live view (no battery drain, no snapshots, works without a SIM), teleport, GPS, recharge, repair and remove, returning the camera, its pole and its SIM to the owner when asked (never for a department camera). Every action is re-checked on the server and written to the console with the staff member's name and citizen ID. - Sounds. The game's own menu sounds on hovers and clicks in the app, in the live feed and while placing; players switch them off in the app's settings.
- Known limit, from the README: props are local to each game, so destruction is reported by whoever saw it, and the reporter must be within range of the camera.
Install
What it replaces. Nothing by name. It does not use Jixryo Core.
Order. The cameras depend on ox_lib, oxmysql, qbx_core, ox_inventory and ox_target; the app depends on ox_lib and the cameras. Optional: screenshot-basic (photos), lb-phone (the phone app), the Jixryo Tablet (TrailCam as an app on it). The optional ones are picked up whenever they start.
server.cfg ensure ox_lib ensure oxmysql ensure qbx_core ensure ox_inventory ensure ox_target ensure jixryo_trailcam ensure jixryo_trailcam_appItems. Add these to
ox_inventory/data/items.luaand copyIMAGES/*.pngtoox_inventory/web/images/.lua ['jixryo_trailcam'] = { label = 'Ranger Trail Camera', weight = 900, stack = true, close = true, description = 'Straps to a tree or a pole and reports to the TrailCam app. Sees 14 m.', client = { image = 'jixryo_trailcam.png' } }, ['jixryo_trailcam_pro'] = { label = 'Cellular Pro Trail Camera', weight = 1100, stack = true, close = true, description = 'Long-range cellular trail camera with a solar panel. Sees 20 m, and the battery lasts longer.', client = { image = 'jixryo_trailcam_pro.png' } }, ['jixryo_trailcam_police'] = { label = 'Surveillance Cam', weight = 1100, stack = true, close = true, description = 'Department surveillance camera. On-duty police only; every on-duty officer can watch it.', client = { image = 'jixryo_trailcam_police.png' } }, ['jixryo_trailcam_pole'] = { label = 'Trail Cam Pole', weight = 1500, stack = true, close = true, description = 'A steel post with a bracket. Mounts a trail camera in open ground.', client = { image = 'jixryo_trailcam_pole.png' } }, ['jixryo_trailcam_sim'] = { label = 'Trail Cam SIM Card', weight = 10, stack = true, close = true, description = 'Lets a trail camera reach the TrailCam app. Goes in when you mount one.', client = { image = 'jixryo_trailcam_sim.png' } }, ['jixryo_trailcam_battery'] = { label = 'Trail Cam Battery', weight = 250, stack = true, close = true, description = 'A fresh battery for a deployed trail camera.', client = { image = 'jixryo_trailcam_battery.png' } }, ['jixryo_trailcam_tablet'] = { label = 'TrailCam Tablet', weight = 600, stack = false, close = true, description = 'Shows what your trail cameras see: feeds, sightings and alerts.', client = { image = 'jixryo_trailcam_tablet.png' } },The shop. The README puts the cameras, pole, SIM, battery and tablet in the gg_hunting script's Hunting Lodge menu (
Config.Shop["hunting_menu"]ingg_hunting/shared/config.lua), with the cost and level yours to tune. Put the Surveillance Cam, batteries and poles in your police armory, for example an ox_inventory shop limited to the police job.lua {item = 'jixryo_trailcam', cost = 750, level = 2}, {item = 'jixryo_trailcam_pro', cost = 1600, level = 4}, {item = 'jixryo_trailcam_pole', cost = 120, level = 2}, {item = 'jixryo_trailcam_sim', cost = 75, level = 2}, {item = 'jixryo_trailcam_battery', cost = 50, level = 2}, {item = 'jixryo_trailcam_tablet', cost = 400, level = 1},Database. Nothing to run. The tables
jixryo_trailcam_cameras,jixryo_trailcam_eventsandjixryo_trailcam_settingsmake themselves on start, and older installs are upgraded: cameras placed before 1.3.0 become Rangers with a SIM card in them, and their stakes become poles.sql/install.sqlis a reference copy.Hosted photos, optional: put your Fivemanage image API key in
server.cfgas the convar below (the same key lb-phone uses for images). Without it, photos are stored in the database.server.cfg set jixryo_trailcam_fivemanage "<your Fivemanage image key>"The phone app, optional: players install TrailCam from the lb-phone app store, or
Config.DefaultAppin the app'sconfig.luapreinstalls it. The tablet needs no install, only the item.The Jixryo Tablet. With
jixryo_tabletrunning and the Jixryo Tablet switch in the app'sconfig.luaon (its default), TrailCam is an app on that tablet and the tablet item brings it out straight onto TrailCam. Off, or without that resource, the item opens TrailCam's own tablet.Staff, optional: the Staff tab is for the ACE permissions in
Config.admin.aces(god,admin). If your server does not grant them already:add_ace group.admin admin allow.The app's page ships built in
ui/dist; after editing it,cd custom-apps/jixryo_trailcam_app/ui && npm install && npm run build.Props. The cameras, straps and pole stream from
stream/with 2K textures; a 4K edition sits ineditions/4kto copy over them (about four times the video memory, and FiveM warns about oversized assets). A missing camera model falls back toprop_cctv_cam_04a.Restart the whole server the first time, so every resource sees the new items and every game downloads the props.
How other scripts' calls behave
- It answers as itself only. The cameras' exports live under
jixryo_trailcam, the tablet's underjixryo_trailcam_app; nothing is provided under another name. - qbx_core. Players by source and citizen ID, the job's type and duty for department cameras,
CreateUseableItemfor every camera item and the tablet, andGetJobsfor a department's display name. Going on or off duty refreshes which police cameras are yours. - ox_inventory. Items are taken and given back with
RemoveItem,AddItem,CanCarryItemandGetItemCount. - ox_target. Each camera prop gets its options: Look at the screen, Take the camera down, Swap the battery, Insert or take out the SIM card, Pry the SIM card out.
- screenshot-basic takes every photo; without it, snapshots are refused with a message and motion photos are skipped.
- lb-phone and lb-tablet. The app registers with
AddCustomAppon each that runs (lb-tablet is off by default), pushes withSendCustomAppMessage, and sends alerts withSendNotification, with a Watch live button that opens the feed. - The Jixryo Tablet. The app registers with
AddApp(idjixryo_trailcam, "TrailCam",ui/dist/app.html), pushes withSendAppMessage, notifies quietly withNotify, and opens the tablet onto itself withOpen. - Fivemanage. With the key set, the server asks for presigned upload links and stores only links whose host is
fivemanage.comorfmapi.net. - The world reaches every game through
jixryo_trailcam:client:cameraAdded,cameraRemovedandcameraUpdated; the payloads never carry the owner.
Its own API
Client exports of jixryo_trailcam:
| Export | What it does |
|---|---|
startLiveView(camId, staff?) | Opens the feed on a camera; staff asks for the staff view, which the server checks. Returns true, or false and why |
stopLiveView() | Closes the feed |
isLive() | Whether a feed is open |
getLiveState() | { camId, label, staff } of the open feed, or nil |
vehicleName(model) | "Bravado Bison" for a vehicle model hash, or nil |
alertText(alert) | The text of an alert, as the notifications word it |
placeNames(x, y, z) | The zone and street names of a point |
playSound(key), setUiSounds(on), getUiSounds() | The app's sounds and the player's on or off choice |
Client exports of jixryo_trailcam_app:
| Export | What it does |
|---|---|
openTablet() | Brings out TrailCam's own tablet |
closeTablet() | Puts it away |
Events:
| Event | Direction | What it carries |
|---|---|---|
jixryo_trailcam:client:cameraAdded, cameraRemoved, cameraUpdated | to every game | a camera placed, taken away, or its light or wreck state changed |
jixryo_trailcam:client:newEvent, eventPhoto | to the camera's audience | a sighting or system event recorded; a photo attached to one |
jixryo_trailcam:client:alert | to the camera's audience, by their settings | the notification: kind, camera, label, model, coordinates, thumbnail link |
jixryo_trailcam:client:cameraStatus | to the camera's audience | destroyed, taken or nosim |
jixryo_trailcam:client:capture | to one player | the server borrows your screen for a motion photo (off by default) |
jixryo_trailcam:client:useCamera, useTablet | to one player | the item was used |
jixryo_trailcam:client:liveState | local, core to app | a feed started or ended, and why |
jixryo_trailcam:server:motionReport, cameraDestroyed, exitLive, captureDecline, photoUploaded, photoData | from a game | a report the server checks before anything is recorded |
The app's calls go through 28 server callbacks named jixryo_trailcam:server:<name> (placing, picking up, retiring, SIM cards, the battery, the close-up, the cameras and events, photos, settings, live view and the staff tools); they are not an API, and the server checks every one.
Commands and keybinds
There are no slash commands. One key mapping is registered: trailcam_watch, K by default, rebound in Settings, Key Bindings, FiveM. It only does something with Config.alerts.screen on.
| Key | Who | What it does |
|---|---|---|
| Using a camera item | its holder, on foot | Starts placing |
| Placing: scroll, Up and Down, V, E, Esc | the placer | Rotate, tilt, view through the lens, place (tree mounts go on to the gizmo), cancel |
| Gizmo: left mouse, Tab, right mouse held, V, Enter, Esc | the placer | Drag an axis, switch move and rotate, look around, view through the lens, mount it here, back |
| X while the camera goes up, E in skill checks | the placer | Stop (nothing is taken); hit the checks |
| Third eye: Look at the screen | anyone | The close-up; Esc, Backspace or a step away leaves it |
| Third eye: Swap the battery, Insert or take out the SIM card | the owner, or the department on duty | What they say |
| Third eye: Pry the SIM card out | anyone else | A hard skill check, then the SIM into your pocket and a photo of you to the owner |
| Third eye: Take the camera down | the owner (anyone, with Config.security.stealable) | Unstraps it, or unscrews it and pulls the pole |
| Live feed: scroll, right mouse, left mouse, Left and Right, Esc or Backspace | the viewer | Zoom, night vision, snapshot (not in staff view), switch camera, exit |
| K | anyone, with the on-screen card on | Watch the camera from the newest card |
| TrailCam tablet: Q and E, Esc | its holder | Previous and next tab; close a photo or a question, then put the tablet away |
| Using the tablet item | its holder | Brings out TrailCam's tablet, or the Jixryo Tablet on TrailCam |
Configuration
jixryo_trailcam/config.lua:
| Key | Default | What it does |
|---|---|---|
items | battery jixryo_trailcam_battery, pole jixryo_trailcam_pole, sim jixryo_trailcam_sim, tablet jixryo_trailcam_tablet | The items; tablet nil turns the tablet item off |
appResource | jixryo_trailcam_app | The app resource that turns alerts into notifications |
models | ranger (14 m, 110 degrees, drain 1.0), pro (20 m, 100 degrees, drain 0.6), police (22 m, 100 degrees, drain 0.5, department) | Each camera's item, model, lens, light, IR and screen positions, reach, field of view and drain |
defaultModel, fallbackModel | ranger; prop_cctv_cam_04a | Cameras from before 1.3.0; the prop used when a model is not streamed |
pole | mountHeight 1.06, plateDepth 0.0125, sinkStart 0.27 | The pole's geometry |
strap | radii 0.10, 0.18, 0.30 | The three strap sizes |
placement | gizmo true, maxOwned 5, maxDistance 6.0, maxHeight 2.5, minSpacing 20.0, previewAlpha 170, showCone true, allowPreview true, the strap, pole and screw steps with their seconds and checks, skillKeys e, retries 2 | Placement limits, the ghost and the work |
sim | required true, stealable true, pry 6 s medium, medium, hard, swap 3 s | SIM cards |
lights | enabled true, range 35.0, ir true | The status light and the IR glow |
inspect | enabled true, distance 2.5, seconds 20 | The close-up |
detection | enabled true, activationRange 60.0, losCheck true, armSeconds 45, interval 1500, clientThrottle 8000, entityMemory 45000, animals, people, vehicles true | Motion detection |
events | perCamCooldown 20, historyLimit 60, photoWaitSeconds 4, notifyDefaults all on | Events and alerts |
photos | enabled true, borrowScreens false, perCamCooldown 25, perPlayerCooldown 12, maxCaptureSpeed 8.0, keepPhotos 20, 1280 by 720 at 0.72, thumbnails 320 by 180 at 0.6, maxBytes 700 KiB, maxThumbBytes 60 KiB, upload convar, presign URL, allowed hosts | Photos and where they go |
battery | enabled true, drainPerHour 1.4, liveDrainPerMinute 1.0, perEventDrain 0.15, lowThreshold 20 | The battery |
live | fov 50, minFov 20, maxFov 70, zoomStep 4, maxSessionSeconds 300, nightvision true, autoNightFrom 20, autoNightTo 6, freezeViewer true, timecycle scanline_cam_cheap at 0.3, snapshotCooldown 3 | The feed |
sounds | enabled true, the game's frontend sounds | Hover, click, back, tick, error and shutter |
alerts | screen false, seconds 8, watchKey K | The optional on-screen card |
admin | aces god, admin, returnItemByDefault true | The Staff tab |
security | stealable false, destructible true, refundDestroyed false, notifyOnTamper true, allowRemoteRetire true | Ownership and tampering |
police | enabled true, jobType leo, requireDuty true, maxCameras 30, labelPrefix PD | Department cameras |
jixryo_trailcam_app/config.lua:
| Key | Default | What it does |
|---|---|---|
LBPhone, LBTablet | true, false | Register the app on lb-phone and lb-tablet |
| The Jixryo Tablet switch | true | TrailCam as an app on the Jixryo Tablet, and the tablet item opens it there |
Tablet | enabled true, blur true, prop_cs_tablet in the left hand, the bus passenger tablet animation | TrailCam's own tablet |
Identifier, Name, Description, Developer, DefaultApp | jixryo_trailcam, TrailCam, Jixryo, false | The app store listing |
ReopenAfterLive | true | Reopen the device on that camera when you exit a feed on purpose |
Alerts | phone true, tablet true | Where alerts arrive |
Security
- Identity comes from the source. Ownership is checked by citizen ID, and a department camera by the caller's police job and duty.
- Distances are re-checked on the server, every number is range-checked, every string clamped and UTF-8 safe, and all SQL is parameterised.
- Every callback and event is rate limited. Placement and SIM changes hold in-flight locks, and removing a camera takes it out of memory before any database wait, so two players can never both get the item back.
- Items move once. Placement takes the camera and the pole only when the work is done and gives everything back if anything after that fails. A SIM always leaves the camera before it reaches a pocket.
- Event text is the server's. Nothing a client types is stored or shown to other players; species and vehicles are named from the model hash.
- Photos are accepted only for a capture session the server opened, from that player, within 20 seconds, as a JPEG within the size limits or as a link on an allowed host.
- Nothing leaks. World payloads never include a camera's owner, and the close-up shows a camera's name only to its owner. Live view needs your own camera or the department's, a SIM, a live battery, and refuses while you drive; the battery is charged from the server's clock, not the client's.
- Staff callbacks re-check the ACE on every call, are rate limited, and write an audit line to the console.
Tests
There is no luarun suite for the cameras or the app. The repository has a contracts check, dev-tools/luacheck/contracts.mjs, that cross-checks every name crossing a boundary between the cameras, the app, their pages and the dev mock. Run on 2026-10-31 it reported ALL CONTRACTS MATCH: 28 server callbacks, 6 client-to-server events, 7 of 10 server-to-client events handled (newEvent, eventPhoto and cameraStatus are consumed by the app's pushes), 7 HUD actions, 7 live phases, 24 app page calls, 5 pushes, and 9 of 10 core exports used by the app.
node dev-tools/luacheck/contracts.mjs .Check it in game
- Start with the items added. The console shows the cameras loaded and any columns added to an older install.
- Use a Ranger on foot near a tree: the ghost follows your aim with its cone, the panel shows the mount and the SIM, E places it, the gizmo opens, Enter mounts it. The strap wraps and cinches through the progress bars and skill checks, and the camera is up with "starts watching in 45 seconds".
- Use another on open ground with a pole in your pockets: the pole sinks as you hammer, then the camera screws onto its bracket.
- Look at the screen with the third eye: the view moves in to the camera's own screen with battery, signal and the time. Esc leaves it.
- Walk a second player, an animal or a car through the cone after 45 seconds: a notification on the phone or the tablet names what was seen, and the status light blinks.
- Open the TrailCam tablet with its item: your cameras as feeds, the sightings, the settings. Open a live feed, zoom, toggle night vision, take a snapshot; the photo lands on the wall. Shoot the camera: SIGNAL LOST.
- As a second player, pry the SIM out: the owner gets the alert and a photo of you, and the light turns red.
- As staff, the Staff tab lists every camera; teleport to one, recharge it, repair the wrecked one, remove one with the item returned to its owner. The console shows each action with your name.