diff --git a/resources/[defaultmaps]/dtpl_carrental/fxmanifest.lua b/resources/[defaultmaps]/dtpl_carrental/fxmanifest.lua deleted file mode 100644 index 3f6cd83fa..000000000 --- a/resources/[defaultmaps]/dtpl_carrental/fxmanifest.lua +++ /dev/null @@ -1,5 +0,0 @@ -fx_version 'cerulean' -games { 'gta5' } -author 'DTPL 3D <3d@dtpl.cz>' -description 'Touchdown Car Rental' -version '1.0.1' \ No newline at end of file diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/_dtplcarrent.ymf b/resources/[defaultmaps]/dtpl_carrental/stream/_dtplcarrent.ymf deleted file mode 100644 index 09455cc04..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/_dtplcarrent.ymf and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark.ydr deleted file mode 100644 index 988372a9c..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark.ydr and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark2.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark2.ydr deleted file mode 100644 index c59c70d28..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark2.ydr and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.cwproj b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.cwproj deleted file mode 100644 index 56a850537..000000000 --- a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.cwproj +++ /dev/null @@ -1,21 +0,0 @@ - - New CodeWalker Project - - - dtpl_carrent.ymap - hei_ap1_03_strm_2.ymap - - - dtpl_carrent.ytyp - - - - - - - - - - - - \ No newline at end of file diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ymap b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ymap deleted file mode 100644 index 227126a09..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ymap and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ytyp b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ytyp deleted file mode 100644 index b4a05fb3e..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ytyp and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_col.ybn b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_col.ybn deleted file mode 100644 index 948502977..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_col.ybn and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_doors.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_doors.ydr deleted file mode 100644 index 27b3f519e..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_doors.ydr and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_shell.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_shell.ydr deleted file mode 100644 index d4b8571ce..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_shell.ydr and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_txd.ytd b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_txd.ytd deleted file mode 100644 index 009ab9940..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_txd.ytd and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_9.ybn b/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_9.ybn deleted file mode 100644 index 4207679a8..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_9.ybn and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_strm_2.ymap b/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_strm_2.ymap deleted file mode 100644 index 5582fdd2f..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_strm_2.ymap and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/hi@hei_ap1_03_0.ybn b/resources/[defaultmaps]/dtpl_carrental/stream/hi@hei_ap1_03_0.ybn deleted file mode 100644 index b3e47d5a1..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/hi@hei_ap1_03_0.ybn and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03+hi.ytd b/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03+hi.ytd deleted file mode 100644 index 12fdf6366..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03+hi.ytd and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03.ytd b/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03.ytd deleted file mode 100644 index 6bb9bad95..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03.ytd and /dev/null differ diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/rental_light.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/rental_light.ydr deleted file mode 100644 index 74042c980..000000000 Binary files a/resources/[defaultmaps]/dtpl_carrental/stream/rental_light.ydr and /dev/null differ diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/client/client.lua b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/client/client.lua index 4104bbc54..cd1de2d6d 100644 --- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/client/client.lua +++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/client/client.lua @@ -9,6 +9,8 @@ local PlyInCarCam = false local bcamstate = false local carCam = false local onRec = false +local isRecording = false +local isDashcamRecording = false -- for prop and ped local propNetID = nil @@ -767,22 +769,88 @@ RegisterNetEvent('spy-bodycam:client:deleteDecoyPed',function(plyId) end) RegisterNetEvent('spy-bodycam:client:startRec',function(webhook,serviceUsed) - SendNUIMessage({ - action = "toggle_record", - hook = webhook, - service = serviceUsed, - recTiming = Config.RecordTime, - }) - if Config.ForceViewCam then - SetTimecycleModifier(Config.CameraEffect.bodycam) - SetTimecycleModifierStrength(0.5) - CreateThread(function() - onRec = true - while onRec do - SetFollowPedCamViewMode(4) - Wait(0) - end - end) + if isRecording then + SendNUIMessage({action = "cancel_rec_force"}) + isRecording = false + NotifyPlayer('Recording stopped!', 'success', 2500) + + if Config.ForceViewCam then + onRec = false + SetFollowPedCamViewMode(1) + SetTimecycleModifier('default') + SetTimecycleModifierStrength(1.0) + end + else + SendNUIMessage({ + action = "toggle_record", + hook = webhook, + service = serviceUsed, + recTiming = Config.RecordTime, + }) + isRecording = true + NotifyPlayer('Recording started!', 'success', 2500) + + if Config.ForceViewCam then + SetTimecycleModifier(Config.CameraEffect.bodycam) + SetTimecycleModifierStrength(0.5) + CreateThread(function() + onRec = true + while onRec do + SetFollowPedCamViewMode(4) + Wait(0) + end + end) + end + end +end) + +RegisterNetEvent('spy-bodycam:client:startDashcamRec', function(webhook, serviceUsed, netId) + if isDashcamRecording then + SendNUIMessage({action = "stop_dashcam_recording"}) + isDashcamRecording = false + NotifyPlayer('Dashcam recording stopped!', 'success', 2500) + + if Config.ForceViewCam then + onRec = false + SetFollowPedCamViewMode(1) + SetTimecycleModifier('default') + SetTimecycleModifierStrength(1.0) + end + else + local veh = NetworkGetEntityFromNetworkId(netId) + if not DoesEntityExist(veh) then + NotifyPlayer('Vehicle not found!', 'error', 2500) + return + end + + -- Get vehicle info for recording overlay + local carPlate = GetVehicleNumberPlateText(veh) + local carName = GetVehDisplayName(GetEntityModel(veh)) + + -- Send message to NUI to start recording + SendNUIMessage({ + action = "toggle_dashcam_record", + hook = webhook, + service = serviceUsed, + recTiming = Config.RecordTime, + vehicleId = netId, + vehiclePlate = carPlate, + vehicleName = carName + }) + isDashcamRecording = true + NotifyPlayer('Dashcam recording started!', 'success', 2500) + + if Config.ForceViewCam then + SetTimecycleModifier(Config.CameraEffect.dashcam) + SetTimecycleModifierStrength(0.5) + CreateThread(function() + onRec = true + while onRec do + SetFollowPedCamViewMode(4) + Wait(0) + end + end) + end end end) @@ -805,6 +873,39 @@ RegisterNetEvent('spy-bodycam:client:refreshRecords',function(records,isBoss) }) end) +-- Register hotkeys for recording if enabled in config +if Config.EnableRecordingHotkeys then + -- Bodycam recording hotkey + RegisterKeyMapping('bodycamrecord', 'Start/Stop bodycam recording', 'keyboard', Config.RecordHotkey) + RegisterCommand('bodycamrecord', function() + if bcamstate then -- Only if bodycam is active + TriggerServerEvent('spy-bodycam:server:toggleRecording') + else + NotifyPlayer('Bodycam not activated!', 'error', 2500) + end + end) + + -- Dashcam recording hotkey + RegisterKeyMapping('dashcamrecord', 'Start/Stop dashcam recording', 'keyboard', Config.DashcamHotkey) + RegisterCommand('dashcamrecord', function() + if IsPedInAnyVehicle(cache.ped, false) then + local veh = GetVehiclePedIsIn(cache.ped, false) + if isCarAuth(veh) then + local netId = NetworkGetNetworkIdFromEntity(veh) + if GlobalState.CarsOnBodycam[netId] then + TriggerServerEvent('spy-bodycam:server:toggleDashcamRecording', netId) + else + NotifyPlayer('Dashcam not activated in this vehicle!', 'error', 2500) + end + else + NotifyPlayer('Vehicle not authorized for dashcam!', 'error', 2500) + end + else + NotifyPlayer('You need to be in a vehicle to use dashcam!', 'error', 2500) + end + end) +end + RegisterKeyMapping('bodycamexit', 'Exit bodycam spectate', 'keyboard', Config.ExitCamKey) RegisterCommand('bodycamexit', function() if PlyInCam or PlyInCarCam then @@ -827,7 +928,7 @@ RegisterNUICallback('videoLog', function(data, cb) local videoUrl = data.vidurl local pos = GetEntityCoords(cache.ped) local s1, s2 = GetStreetNameAtCoord(pos.x, pos.y, pos.z) - TriggerServerEvent('spy-bodycam:server:logVideoDetails', videoUrl,GetStreetNameFromHashKey(s1)) + TriggerServerEvent('spy-bodycam:server:logVideoDetails', videoUrl, GetStreetNameFromHashKey(s1), data.isDashcam) end end) @@ -1041,6 +1142,7 @@ function PlayWatchAnim(ped,isNet) Citizen.Wait(10) end local prop = CreateObject(tabletprop, x, y, z + 0.2, isNet, true, false) + AttachEntityToEntity(prop, ped, GetPedBoneIndex(ped, 28422), -0.05, 0.0, 0.0, 0.0, 0.0, 0.0, AttachEntityToEntity(prop, ped, GetPedBoneIndex(ped, 28422), -0.05, 0.0, 0.0, 0.0, 0.0, 0.0, true, true, false, true, 1, true) local animDict = 'amb@code_human_in_bus_passenger_idles@female@tablet@idle_a' RequestAnimDict(animDict) @@ -1221,3 +1323,5 @@ function HasItemsCheck(itemname) end + + diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/config.lua b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/config.lua index cb9ef331b..58580fbcf 100644 --- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/config.lua +++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/config.lua @@ -21,10 +21,13 @@ Config.Dependency = { UseProgress = 'qb', -- qb | ox | esx UseMenu = 'qb', -- qb | ox | esx UseNotify = 'qb', -- qb | ox | esx - UseAppearance = 'illenium', -- qb | illenium | false + UseAppearance = 'illenium', -- qb | illenium | false } Config.ExitCamKey = 'BACK' +Config.RecordHotkey = 'F9' -- Hotkey for bodycam recording +Config.DashcamHotkey = 'F10' -- Hotkey for dashcam recording +Config.EnableRecordingHotkeys = true -- Enable/disable hotkey functionality Config.CameraEffect = { bodycam = 'Island_CCTV_ChannelFuzz', @@ -119,4 +122,4 @@ Config.VehCamOffset = { -- 19: Military -- 20: Commercial -- 21: Trains --- 22: Open Wheel \ No newline at end of file +-- 22: Open Wheel diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/server/server.lua b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/server/server.lua index bf4ee74dc..77f6024a3 100644 --- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/server/server.lua +++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/server/server.lua @@ -161,13 +161,70 @@ Citizen.CreateThread(function() end end) -RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetName) +-- Handle bodycam recording toggle +RegisterNetEvent('spy-bodycam:server:toggleRecording', function() + local src = source + if PlayerOnBodycam[src] then + local defwebhook + if Upload.ServiceUsed == 'discord' then + local jobKey + if Config.Framework == 'qb' then + local Player = QBCore.Functions.GetPlayer(src) + jobKey = Player.PlayerData.job.name + else + local xPlayer = ESX.GetPlayerFromId(src) + jobKey = xPlayer.getJob().name + end + if Upload.JobUploads[jobKey] then + defwebhook = Upload.JobUploads[jobKey].webhook + else + defwebhook = Upload.DefaultUploads.webhook + end + elseif Upload.ServiceUsed == 'fivemanage' or Upload.ServiceUsed == 'fivemerr' then + defwebhook = Upload.Token + end + TriggerClientEvent('spy-bodycam:client:startRec', src, defwebhook, Upload.ServiceUsed) + else + NotifyPlayerSv('Bodycam not turned on!', 'error', 3000, src) + end +end) + +-- Handle dashcam recording toggle +RegisterNetEvent('spy-bodycam:server:toggleDashcamRecording', function(netId) + local src = source + if CarsOnBodycam[netId] then + local defwebhook + if Upload.ServiceUsed == 'discord' then + local jobKey + if Config.Framework == 'qb' then + local Player = QBCore.Functions.GetPlayer(src) + jobKey = Player.PlayerData.job.name + else + local xPlayer = ESX.GetPlayerFromId(src) + jobKey = xPlayer.getJob().name + end + if Upload.JobUploads[jobKey] then + defwebhook = Upload.JobUploads[jobKey].webhook + else + defwebhook = Upload.DefaultUploads.webhook + end + elseif Upload.ServiceUsed == 'fivemanage' or Upload.ServiceUsed == 'fivemerr' then + defwebhook = Upload.Token + end + TriggerClientEvent('spy-bodycam:client:startDashcamRec', src, defwebhook, Upload.ServiceUsed, netId) + else + NotifyPlayerSv('Dashcam not turned on!', 'error', 3000, src) + end +end) + +RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl, streetName, isDashcam) local src = source local offName local offJob local offRank local jobKey local date = os.date('%Y-%m-%d') + local recordType = isDashcam and "dashcam" or "bodycam" if Config.Framework == 'qb' then local Player = QBCore.Functions.GetPlayer(src) @@ -184,12 +241,13 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN end ---SQL UPLOAD - MySQL.Async.execute('INSERT INTO spy_bodycam (job, videolink, street, date, playername) VALUES (@job, @videolink, @street, @date, @playername)', { + MySQL.Async.execute('INSERT INTO spy_bodycam (job, videolink, street, date, playername, recordtype) VALUES (@job, @videolink, @street, @date, @playername, @recordtype)', { ['@job'] = jobKey, ['@videolink'] = videoUrl, ['@street'] = streetName, ['@date'] = date, - ['@playername'] = offName + ['@playername'] = offName, + ['@recordtype'] = recordType }, function(rowsChanged) end) if Upload.DiscordLogs.Enabled then @@ -204,7 +262,7 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN end local embedData = { { - title = Upload.DiscordLogs.Title, + title = Upload.DiscordLogs.Title .. (isDashcam and " (Dashcam)" or " (Bodycam)"), color = 16761035, fields = { { name = "Name:", value = offName, inline = false }, @@ -212,7 +270,7 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN { name = "Job Rank:", value = offRank, inline = false }, }, footer = { - text = "Date: " .. os.date("!%Y-%m-%d %H:%M:%S", os.time()), + text = "Date: " .. os.date("!%Y-%m-%d %H:%M:%S", os.time()), icon_url = "https://i.imgur.com/CuSyeZT.png", }, author = author @@ -370,4 +428,3 @@ AddEventHandler('onResourceStart', function(resourceName) checkForUpdates() end end) - diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/index.html b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/index.html index 23ade29bb..d7463b4dd 100644 --- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/index.html +++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/index.html @@ -79,9 +79,18 @@ + +
+
+
+ DASHCAM RECORDING +
+
Police Cruiser - ABC123
+
00:00
+
- \ No newline at end of file + diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/js/app.js b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/js/app.js index ff0b16b3d..929f4db9f 100644 --- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/js/app.js +++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/js/app.js @@ -1,7 +1,10 @@ import { GameView } from './gameview.js'; const gameview = new GameView(); let isRecording = false; +let isDashcamRecording = false; let recordingTimeout; +let dashcamRecordingTimeout; +let dashcamTimer; $(document).ready(function () { $('.overlayCont').hide(); @@ -10,6 +13,7 @@ $(document).ready(function () { $('.recCont').hide(); $('.askMain').hide(); $('.vidplaycont').hide(); + $('#dashcam-recording-ui').hide(); const beepSound = document.getElementById('beep-sound'); const offSound = document.getElementById('off-sound'); @@ -98,7 +102,7 @@ $(document).ready(function () { startRecording(data.hook, data.service); recordingTimeout = setTimeout(() => { if (isRecording) { - // Stop recording automatically after 30 seconds + // Stop recording automatically after configured time isRecording = false; $('.HeadText').html('' + 'Recording Stopped'); setTimeout(() => { @@ -118,6 +122,53 @@ $(document).ready(function () { stopRecording(); } } + if (data.action === 'toggle_dashcam_record') { + clearTimeout(dashcamRecordingTimeout); + if (!isDashcamRecording) { + // Start dashcam recording + isDashcamRecording = true; + $('#dashcam-recording-ui').show(); + $('#dashcam-vehicle-info').text(`${data.vehicleName} - ${data.vehiclePlate}`); + + // Start a timer for the dashcam recording + let seconds = 0; + dashcamTimer = setInterval(() => { + seconds++; + const mins = Math.floor(seconds / 60); + const secs = seconds % 60; + $('#dashcam-timer').text(`${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`); + }, 1000); + + // Start recording using the existing function + startRecording(data.hook, data.service, data.recTiming, true); + + // Auto-stop after the configured time + dashcamRecordingTimeout = setTimeout(() => { + if (isDashcamRecording) { + isDashcamRecording = false; + $('#dashcam-recording-ui').hide(); + clearInterval(dashcamTimer); + stopRecording(true); + } + }, data.recTiming * 1000); + } else { + // Stop dashcam recording + isDashcamRecording = false; + $('#dashcam-recording-ui').hide(); + clearTimeout(dashcamRecordingTimeout); + clearInterval(dashcamTimer); + stopRecording(true); + } + } + if (data.action === 'stop_dashcam_recording') { + if (isDashcamRecording) { + isDashcamRecording = false; + $('#dashcam-recording-ui').hide(); + clearTimeout(dashcamRecordingTimeout); + clearInterval(dashcamTimer); + stopRecording(true); + } + } if (data.action === 'cancel_rec_force') { if (isRecording) { // Force stop recording @@ -129,6 +180,13 @@ $(document).ready(function () { }, 1000); stopRecording(); } + if (isDashcamRecording) { + isDashcamRecording = false; + $('#dashcam-recording-ui').hide(); + clearTimeout(dashcamRecordingTimeout); + clearInterval(dashcamTimer); + stopRecording(true); + } } // RECORDS SHOWING @@ -138,16 +196,18 @@ $(document).ready(function () { if (Array.isArray(data.recordData) && data.recordData.length > 0) { $.each(data.recordData, function (index, record) { + var recordType = record.recordtype || 'bodycam'; + var recordIcon = recordType === 'dashcam' ? 'fa-car' : 'fa-video'; var camBox = $( `
${record.playername} [${record.street}]
-
Date: ${record.date}
+
${recordType.toUpperCase()} | Date: ${record.date}
- ${data.isBoss ? `
` : ''} + ${data.isBoss ? `
` : ''}
` @@ -166,16 +226,18 @@ $(document).ready(function () { $('.recInnerScroll').empty(); if (Array.isArray(data.recordData) && data.recordData.length > 0) { $.each(data.recordData, function (index, record) { + var recordType = record.recordtype || 'bodycam'; + var recordIcon = recordType === 'dashcam' ? 'fa-car' : 'fa-video'; var camBox = $( `
${record.playername} [${record.street}]
-
Date: ${record.date}
+
${recordType.toUpperCase()} | Date: ${record.date}
- ${data.isBoss ? `
` : ''} + ${data.isBoss ? `
` : ''}
` @@ -196,7 +258,7 @@ $(document).ready(function () { function updateVisibility(searchText) { $('.camBox').each(function () { var camTitleText = $(this).find('.camTitle').text().toLowerCase(); - var camDescDate = $(this).find('.camDesc').text().trim().replace('Date: ', ''); + var camDescDate = $(this).find('.camDesc').text().trim().replace(/.*Date: /, ''); if ((searchText === '' || camTitleText.includes(searchText)) && ($(this).css('display') !== 'none' || camDescDate === $('.selectedDate').val()) ) { @@ -220,7 +282,7 @@ $(document).ready(function () { $('.selectedDate').on('change', function () { var selectedDate = $(this).val(); $('.camBox').each(function () { - var camDescDate = $(this).find('.camDesc').text().trim().replace('Date: ', ''); + var camDescDate = $(this).find('.camDesc').text().trim().replace(/.*Date: /, ''); if (selectedDate === '') { $(this).show(); } else if (selectedDate === camDescDate) { @@ -235,7 +297,7 @@ $(document).ready(function () { $(document).on('click', '.camDelete', function () { const camBox = $(this).closest('.camBox'); - deleteUrl = camBox.find('.camShow').data('stored'); + deleteUrl = $(this).data('url'); $('.askMain').fadeIn(); }); @@ -287,7 +349,7 @@ let mediaRecorder; let audioStream; const canvasElement = document.querySelector('canvas'); -async function uploadBlob(videoBlob, hook, service) { +async function uploadBlob(videoBlob, hook, service, isDashcam = false) { $.post(`https://${GetParentResourceName()}/exitBodyCam`, '{}'); const formData = new FormData(); try { @@ -306,7 +368,8 @@ async function uploadBlob(videoBlob, hook, service) { } responseData = await response.json(); $.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({ - vidurl: responseData.url + vidurl: responseData.url, + isDashcam: isDashcam })); } else if (service === 'fivemerr') { formData.append('file', videoBlob, 'video.webm'); @@ -322,7 +385,8 @@ async function uploadBlob(videoBlob, hook, service) { } responseData = await response.json(); $.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({ - vidurl: responseData.url + vidurl: responseData.url, + isDashcam: isDashcam })); } else if (service === 'discord') { formData.append('file', videoBlob, 'video.webm'); @@ -335,7 +399,8 @@ async function uploadBlob(videoBlob, hook, service) { } responseData = await response.json(); $.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({ - vidurl: responseData.attachments[0].url + vidurl: responseData.attachments[0].url, + isDashcam: isDashcam })); } } catch (error) { @@ -353,15 +418,16 @@ async function startMicrophoneCapture() { } } -async function startRecording(hook, service) { +async function startRecording(hook, service, recordTime, isDashcam = false) { audioStream = await startMicrophoneCapture(); - if (!isRecording){ + if (!isRecording && !isDashcamRecording) { if (audioStream) { audioStream.getAudioTracks().forEach(track => track.stop()); } - return + return; } - console.log('Video Recording Started'); + + console.log(isDashcam ? 'Dashcam Recording Started' : 'Bodycam Recording Started'); const gameView = gameview.createGameView(canvasElement); const canvasStream = canvasElement.captureStream(30); @@ -379,7 +445,7 @@ async function startRecording(hook, service) { mediaRecorder.onstop = async () => { const videoBlob = new Blob(videoChunks, { type: 'video/webm' }); if (videoBlob.size > 0) { - uploadBlob(videoBlob, hook, service); + uploadBlob(videoBlob, hook, service, isDashcam); } if (audioStream) { audioStream.getAudioTracks().forEach(track => track.stop()); @@ -387,8 +453,15 @@ async function startRecording(hook, service) { }; } -function stopRecording() { +function stopRecording(isDashcam = false) { if (mediaRecorder && mediaRecorder.state === 'recording') { mediaRecorder.stop(); } -} \ No newline at end of file + + if (isDashcam) { + isDashcamRecording = false; + $('#dashcam-recording-ui').hide(); + } else { + isRecording = false; + } +} diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/style.css b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/style.css index 8aa3d53f0..63e98b69d 100644 --- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/style.css +++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/style.css @@ -448,4 +448,57 @@ color: rgba(255, 255, 255, 0.26); font-size: 3rem; font-family: "Fjalla One", sans-serif; -} \ No newline at end of file +} + +/* Dashcam Recording UI */ +#dashcam-recording-ui { + position: absolute; + top: 20px; + left: 20px; + background-color: rgba(0, 0, 0, 0.7); + color: white; + padding: 15px; + border-radius: 5px; + font-family: "Play", sans-serif; + display: none; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); + border: 1px solid rgba(255, 0, 0, 0.3); + min-width: 250px; +} + +.dashcam-header { + display: flex; + align-items: center; + margin-bottom: 10px; + font-weight: bold; + font-size: 16px; +} + +#dashcam-vehicle-info { + font-size: 14px; + margin-bottom: 5px; + color: #f0f0f0; +} + +#dashcam-timer { + font-size: 20px; + font-weight: bold; + color: #ff3333; + text-align: center; +} + +.dashcam-recording-indicator { + width: 12px; + height: 12px; + background-color: red; + border-radius: 50%; + display: inline-block; + margin-right: 10px; + animation: blink 1s infinite; +} + +@keyframes blink { + 0% { opacity: 1; } + 50% { opacity: 0; } + 100% { opacity: 1; } +}