Accessible code
Shared = {
Locale = 'en',
Notify = {
duration = 5000, -- miliseconds
position = 'top-center' -- 'top' or 'top-right' or 'top-left' or 'bottom' or 'bottom-right' or 'bottom-left' or 'center-right' or 'center-left'
},
Logs = {
enabled = true,
webhook = '',
servername = 'Uniq Scripts',
color = 6579450,
icon_url = 'https://dunb17ur4ymx4.cloudfront.net/webstore/logos/248d77847b320034db12949cf577772b654daadd.png'
},
webhook = '', -- your discord channel webhook (logs & recorded camera history)
recordTime = 30, -- represents time of camera video recording in seconds
CopyLink = true, -- whether to copy video download link when playing video or not
AllowRotate = true, -- whether to allow camera owners to rotate cameras or not
Record = true, -- whether to allow camera recording or not (records are saved to your discord webhook)
HackProtection = 50000, -- price for protection from hackers (10% chance for hackers to hack the camera)
HackRadius = 1000, -- radius the hack device will search for (in meters)
HackCamera = { -- settings for hacking cameras
policeOnly = false,
policeJobs = { -- requried
['police'] = true
},
policeNotify = true, -- notify police about cameras being hacked
cameraDelay = 300000, -- delay for restoring all hacked cameras - ms
},
Keys = { -- https://docs.fivem.net/docs/game-references/controls/
finish = 191,
cancel = 194,
moveUp = 85,
moveDown = 48,
moveRight = 175,
moveLeft = 174,
moveForward = 172,
moveBack = 173,
rotateRight = 313,
rotateLeft = 312,
camera_rotateRight = 35,
camera_rotateLeft = 34,
camera_rotateUp = 32,
camera_rotateDown = 33,
record = 57
},
Items = {
camera = 'key',
tablet = 'lockpick',
hackdevice = 'hackdevice'
},
Tablet = {
dict = "amb@code_human_in_bus_passenger_idles@female@tablet@base",
anim = "base",
object = "prop_cs_tablet",
bone = 60309,
offset = vector3(0.03, 0.002, -0.0),
rotation = vector3(10.0, 160.0, 0.0)
},
Object = "prop_cctv_cam_01a", -- camera object | suggested: 'prop_cctv_cam_01b', 'prop_cctv_cam_01a'
RestrictedAreas = {
{
coords = vector3(123.45, -567.89, 30.0),
radius = 50.0,
name = "Police Station"
},
-- Add more restricted areas as needed
},
Camera = {
maxZoom = 50.0,
minZoom = 5.0,
zoomSpeed = 1.0,
nightVision = {
enabled = true,
toggleKey = 249, -- N key
timecycle = "secret_camera", -- Main night vision effect
thermalVision = false -- Set to true if you want thermal vision instead
}
}
}
-- Framework
-- your framework loading here (presetuped)
Locales['en'] = {
['camera'] = 'Camera',
['camera_record'] = 'Camera Record',
['camera_records'] = 'Camera Records',
['camera_record_for'] = 'This video record is for camera with ID',
['hack_device'] = 'Camera Hack Device',
-- ### Inputs ### --
['input.place_camera.title'] = 'Place Camera',
['input.place_camera.access.label'] = 'Camera Access',
['input.place_camera.access.description'] = 'Select the players who will have access to this camera, you can\'t edit this later',
['input.place_camera.name.label'] = 'Camera Name',
['input.place_camera.name.description'] = 'Unique name (label) for this camera',
['input.place_camera.name.placeholder'] = 'Camera Name 1',
['input.place_camera.security'] = 'Hackers Security',
['input.edit_camera.name.label'] = 'Edit Camera Name',
['input.edit_camera.name.new_name'] = 'New Camera Name',
['input.allowed_jobs'] = 'Allowed Jobs',
['input.allowed_jobs.description'] = 'Jobs that are allowed access to access this camera (optional)',
['input.allowed_jobs.update_access'] = 'Update Jobs Access',
['input.allowed_jobs.update_access.description'] = 'Update the access of jobs for this camera.',
['input.allowed_players.update_access'] = 'Update Players Access',
['input.allowed_players.update_access.description'] = 'Give camera access to selected players, players who already have camera access will remain.',
-- ### Inputs ### --
-- ### Buttons ### --
['btn_cancel'] = 'Cancel',
['btn_finish'] = 'Finish',
['btn_move_down'] = 'Move Down',
['btn_move_up'] = 'Move Up',
['btn_move_right'] = 'Move Right',
['btn_move_left'] = 'Move Left',
['btn_move_forward'] = 'Move Forward',
['btn_move_back'] = 'Move Back',
['btn_rotate_camera'] = 'Rotate Camera',
['btn_close_camera'] = 'Close Camera',
['btn_record'] = 'Record for %s seconds',
['btn_zoom_in'] = 'Zoom In',
['btn_zoom_out'] = 'Zoom Out',
['btn_night_vision'] = 'Toggle Night Vision',
-- ### Buttons ### --
-- ### Target ### --
['target.access_camera.label'] = 'Access The Camera',
['target.hack_camera.label'] = 'Hack The Camera',
-- ### Target ### --
-- ### Context Menu ### --
['context.camera_settings.label'] = 'Private Camera Settings',
['context.camera_settings.edit_name'] = 'Camera Name',
['context.camera_settings.edit_name.description'] = 'Edit name of this camera',
['context.camera_settings.camera_id'] = 'Camera ID',
['context.camera_settings.remove_camera'] = 'Remove Camera',
['context.camera_settings.remove_camera.description'] = 'Take off the camera from this place',
['context.camera_settings.remove_camera.sure'] = 'Are you sure you want to remove this camera?',
['context.camera_settings.manage_job_access'] = 'Manage Jobs Access',
['context.camera_settings.manage_job_access.description'] = 'Manage jobs access for this camera',
['context.camera_settings.manage_job_access.metadata_label'] = 'Current Access',
['context.camera_settings.manage_players_access'] = 'Give Access To Players',
['context.camera_settings.manage_players_access.description'] = 'Give camera access to selected players, players who already have camera access will remain',
['context.tablet.view_camera'] = 'Use Camera',
['context.tablet.view_camera.description'] = 'Take a live look on this camera',
['context.tablet.label'] = 'Cameras Tablet',
['context.tablet.waypoint.label'] = 'Set Waypoint',
['context.tablet.waypoint.description'] = 'Mark the camera location on the map',
['context.tablet.security.label'] = 'Hack Security',
['context.tablet.security.description'] = 'Purchase camera security from hackers - $%s (cash)',
['context.tablet.buy_security'] = 'Purchase Security',
['context.tablet.buy_security.sure'] = 'Are you sure you want to purchase security for this camera?',
['context.hack_camera.label'] = 'Hack Camera',
['context.hack_camera.sure'] = 'Are you sure you want to hack this camera?',
['context.access_camera.broken.title'] = 'Camera Broken',
['context.access_camera.broken.sure'] = 'This camera is broken, you have to repair it before you can access it. Do you want to repair it now?',
['context.video_records.title'] = 'Video Records',
['context.video_records.description'] = 'Take a look on all recorded videos with this camera',
['context.video_records.date'] = 'Date',
-- ### Context Menu ### --
-- ### Notify ### --
['notify.hack_camera.alreadyhacked'] = 'This camera is already hacked before, try again later',
['notify.hack_camera.canthackown'] = 'You can\'t hack the camera you have access to',
['notify.not_own'] = 'You don\'t own this camera',
['notify.not_access'] = 'You don\'t have access to this camera',
['notify.success_cancel'] = 'You have successfully canceled creating camera',
['notify.waypoint_set'] = 'The waypoint has been successfully marked on the map',
['notify.failed_repair'] = 'You failed to fix the camera',
['notify.failed_hack'] = 'You failed to hack the camera',
['notify.camera_created'] = 'Camera "%s" successfully created',
['notify.camera_deleted'] = 'Camera with ID %s successfully deleted',
['notify.camera_edited'] = 'The name of the camera with ID %s is successfully changed to "%s"',
['notify.not_enough_money'] = 'You don\'t have enough money (%s)',
['notify.already_secured'] = 'This camera is already secured',
['notify.success_secured'] = 'You have successfully secured a camera with ID %s',
['notify.recording_started'] = '%s seconds record started',
['notify.already_recording'] = 'You are already recording a video',
['notify.record_finished'] = 'Video successfully recorded and saved to the tablet',
['notify.record_link_copied'] = 'Recorded video download link successfully copied to clipboard',
['notify.camera_data_loaded'] = 'Camera successfully hacked & data loaded',
['notify.hack_camera.police_only'] = 'Only police officers can hack cameras',
['notify.hack_camera.police_notify'] = 'Someone is hacking the camera, the camera location is marked on the map',
['notify.access_updated'] = 'Access for camera ID %s successfully updated',
['notify.cant_hack_camera'] = 'This camera can\'t be hacked',
['notify.cant_place_restricted'] = 'Cannot place camera in restricted area: %s',
-- ### Notify ### --
-- ### Progress ### --
['progress.loading_data'] = 'Loading Camera Data',
-- ### Progress ### --
-- ### Logs ### --
['logs.cameras_setuped'] = 'All cameras have been successfully created',
['logs.camera_created'] = '**%s** created a new camera.\n- Camera Name: **%s**',
['logs.camera_deleted'] = '**%s** deleted a camera.\n- Camera ID: **#%s**',
['logs.camera_name_edited'] = '**%s** edited camera\'s name.\n- Camera ID: **#%s**\n- New Camera Name: **%s**',
['logs.bought_security'] = '**%s** bought security for camera with ID **#%s**',
['logs.recorded_video'] = '**%s** recorded a new video.\n- Camera ID: **#%s**\n- Video: **%s**'
-- ### Logs ### --
}
function sendNotify(title, description, type)
lib.notify({
title = title,
description = description,
duration = Shared.Notify.duration,
type = type,
position = Shared.Notify.position
})
end
RegisterNetEvent('cameras:notify', sendNotify)
function hackCamera(cameraId) -- you can change this to your desired minigame
if cameraId then
local playerCoords = GetEntityCoords(PlayerPedId())
local closestCameraId = GetClosestCameraId(playerCoords)
lib.callback('cameras:server:checkSecurity', false, function(hasSecurity)
if not hasSecurity then
local success = lib.skillCheck({'hard'}, {'w', 'a', 's', 'd'})
if success then
if lib.progressCircle({
duration = 5000,
label = L('progress.loading_data'),
position = 'middle',
useWhileDead = false,
canCancel = true,
disable = {
car = true,
},
}) then
Cameras[cameraId].hacked = true
Cameras[cameraId].broken = true
TriggerServerEvent('cameras:server:accessCamera', cameraId)
if Shared.HackCamera.policeNotify then
lib.callback('cameras:server:policeNotify', false, function() end, Cameras[closestCameraId].data.coords.x, Cameras[closestCameraId].data.coords.y)
end
sendNotify('', L('notify.camera_data_loaded'), 'success')
else end
else
sendNotify('', L('notify.failed_hack'), 'error')
removeTabletHands()
end
else
local success = lib.skillCheck({areaSize = 10, speedMultiplier = 4}, {'w', 'a', 's', 'd', 'g', 'h', 'k', 'j', 'l', 'f', 'r'})
if success then
Cameras[cameraId].hacked = true
Cameras[cameraId].broken = true
TriggerServerEvent('cameras:server:accessCamera', cameraId)
if Shared.HackCamera.policeNotify then
lib.callback('cameras:server:policeNotify', false, function() end, Cameras[closestCameraId].data.coords.x, Cameras[closestCameraId].data.coords.y)
end
sendNotify('', L('notify.camera_data_loaded'), 'success')
else
sendNotify('', L('notify.failed_hack'), 'error')
removeTabletHands()
end
end
end, cameraId)
else
sendNotify('', L('notify.cant_hack_camera'), 'error')
end
end
-- Discord Logs
local webhook = Shared.Logs.webhook
function logger(message)
if Shared.Logs.enabled then
if webhook ~= '' then
PerformHttpRequest(webhook, function(status) end, 'POST', json.encode({
username = cache.resource,
embeds = {{
color = Shared.Logs.color,
title = Shared.Logs.servername,
description = message,
footer = {
text = os.date(),
icon_url = Shared.Logs.icon_url
}
}}
}), { ['Content-Type'] = 'application/json' })
end
end
end
-- Usable Items - QB
QBCore.Functions.CreateUseableItem(Shared.Items.camera, function(source, item)
local Player = QBCore.Functions.GetPlayer(source)
if not Player.Functions.GetItemByName(item.name) then return end
TriggerClientEvent("cameras:createCamera", source)
end)
QBCore.Functions.CreateUseableItem(Shared.Items.tablet, function(source, item)
local Player = QBCore.Functions.GetPlayer(source)
if not Player.Functions.GetItemByName(item.name) then return end
TriggerClientEvent("cameras:accessTablet", source)
end)
QBCore.Functions.CreateUseableItem(Shared.Items.hackdevice, function(source, item)
local Player = QBCore.Functions.GetPlayer(source)
if not Player.Functions.GetItemByName(item.name) then return end
TriggerClientEvent("cameras:hackDevice", source)
end)
-- Usable Items - ESX
ESX.RegisterUsableItem(Shared.Items.camera, function(playerId)
local xPlayer = ESX.GetPlayerFromId(playerId)
if not xPlayer.hasItem(Shared.Items.camera) then return end
TriggerClientEvent("cameras:createCamera", playerId)
end)
ESX.RegisterUsableItem(Shared.Items.tablet, function(playerId)
local xPlayer = ESX.GetPlayerFromId(playerId)
if not xPlayer.hasItem(Shared.Items.tablet) then return end
TriggerClientEvent("cameras:accessTablet", playerId)
end)
ESX.RegisterUsableItem(Shared.Items.hackdevice, function(playerId)
local xPlayer = ESX.GetPlayerFromId(playerId)
if not xPlayer.hasItem(Shared.Items.hackdevice) then return end
TriggerClientEvent("cameras:hackDevice", playerId)
end)
Last updated