diff --git a/resources/[carscripts]/qb-vehicle-tracker/client/client.lua b/resources/[carscripts]/qb-vehicle-tracker/client/client.lua index 8830e9711..7357a5ed4 100644 --- a/resources/[carscripts]/qb-vehicle-tracker/client/client.lua +++ b/resources/[carscripts]/qb-vehicle-tracker/client/client.lua @@ -296,30 +296,42 @@ end) RegisterNetEvent('qb_vehicle_tracker:client:locateTracker', function(serialNumber) if serialNumber == nil then uiNotify(locale('vt_not_placed'), 'error') return end - lib.callback('qb_vehicle_tracker:getTrackedVehicleBySerial', false, function(veh, vehCoords, trackerName) + lib.callback('qb_vehicle_tracker:getTrackedVehicleBySerial', false, function(veh, vehCoords, trackerName, isLastKnown) if veh == nil then uiNotify(locale('vt_unable_connect'), 'error') return end - local blip = AddBlipForCoord(vehCoords.x , vehCoords.y, 0.0) + local blip = AddBlipForCoord(vehCoords.x, vehCoords.y, 0.0) SetBlipSprite(blip, 161) - SetBlipColour(blip, 1) + SetBlipColour(blip, isLastKnown and 3 or 1) -- Use yellow for last known position, red for current SetBlipAlpha(blip, 250) SetBlipDisplay(blip, 2) SetBlipScale(blip, 2.5) PulseBlip(blip) SetBlipAsShortRange(blip, false) BeginTextCommandSetBlipName('STRING') - AddTextComponentSubstringPlayerName(trackerName or ('Tracker ' .. veh)) + + local blipName = trackerName or ('Tracker ' .. veh) + if isLastKnown then + blipName = blipName .. " (Last Known)" + end + + AddTextComponentSubstringPlayerName(blipName) EndTextCommandSetBlipName(blip) - SetNewWaypoint(vehCoords.x , vehCoords.y) + SetNewWaypoint(vehCoords.x, vehCoords.y) trackedVehicles[serialNumber] = blip playSound('10_SEC_WARNING', 'HUD_MINI_GAME_SOUNDSET') - uiNotify(locale('vt_connection_success'), 'success') + + if isLastKnown then + uiNotify(locale('vt_last_known_position') or "Showing last known position of vehicle", 'info') + else + uiNotify(locale('vt_connection_success'), 'success') + end end, serialNumber) end) + -- New events for advanced scanner features RegisterNetEvent('qb_vehicle_tracker:client:locateTrackerOwner', function(vehiclePlate) -- Determine which skill check difficulty to use based on player job diff --git a/resources/[carscripts]/qb-vehicle-tracker/locales/en.json b/resources/[carscripts]/qb-vehicle-tracker/locales/en.json index 8578907d2..da6eecc39 100644 --- a/resources/[carscripts]/qb-vehicle-tracker/locales/en.json +++ b/resources/[carscripts]/qb-vehicle-tracker/locales/en.json @@ -41,5 +41,7 @@ "vt_trace_failed": "Failed to trace the signal", "vt_phone_not_found": "Could not extract phone number from the tracker", "vt_phone_found": "Phone number extracted: ", - "vt_phone_extraction_failed": "Failed to extract phone number" + "vt_phone_extraction_failed": "Failed to extract phone number", + "vt_last_known_position":"Showing last known position of vehicle" + } \ No newline at end of file diff --git a/resources/[carscripts]/qb-vehicle-tracker/server/server.lua b/resources/[carscripts]/qb-vehicle-tracker/server/server.lua index 70a9aae4f..87220f39e 100644 --- a/resources/[carscripts]/qb-vehicle-tracker/server/server.lua +++ b/resources/[carscripts]/qb-vehicle-tracker/server/server.lua @@ -3,7 +3,7 @@ local config = require 'config' -- Database functions local function deleteOldTrackers() - return MySQL.query.await('DELETE FROM `vehicle_trackers` WHERE startedAt < (NOW() - INTERVAL 7 DAY)') + return true end local function addTracker(serialNumber, vehiclePlate, owner, name, phoneNumber) @@ -16,7 +16,7 @@ local function deleteTracker(vehiclePlate) end local function getTracker(serialNumber) - return MySQL.single.await('SELECT `serialNumber`, `vehiclePlate`, `name`, `phoneNumber`, `owner` FROM `vehicle_trackers` WHERE `serialNumber` = ? LIMIT 1', { serialNumber }) + return MySQL.single.await('SELECT `serialNumber`, `vehiclePlate`, `name`, `phoneNumber`, `owner`, `lastKnownX`, `lastKnownY`, `lastKnownZ`, `lastUpdated` FROM `vehicle_trackers` WHERE `serialNumber` = ? LIMIT 1', { serialNumber }) end local function isTracked(vehiclePlate) @@ -32,6 +32,12 @@ local function updateTrackerName(serialNumber, name) { name, serialNumber }) end +-- New function to update tracker position +local function updateTrackerPosition(serialNumber, coords) + return MySQL.prepare.await('UPDATE `vehicle_trackers` SET `lastKnownX` = ?, `lastKnownY` = ?, `lastKnownZ` = ? WHERE `serialNumber` = ?', + { coords.x, coords.y, coords.z, serialNumber }) +end + -- Utility functions local function getRandomSerialNumber() return lib.string.random('...........') @@ -88,7 +94,7 @@ end) -- Event Handler AddEventHandler('onResourceStart', function(resourceName) if GetCurrentResourceName() == resourceName then - deleteOldTrackers() + -- deleteOldTrackers() -- Comment out to prevent deletion after 7 days end end) @@ -99,15 +105,30 @@ lib.callback.register('qb_vehicle_tracker:getTrackedVehicleBySerial', function(_ local tracker = getTracker(serialNumber) if not tracker then return end + -- Try to find the vehicle in the world local vehicleNetworkID = getVehicleNetworkIdByPlate(tracker.vehiclePlate) - if not vehicleNetworkID then return end - - local vehicleEntity = NetworkGetEntityFromNetworkId(vehicleNetworkID) - if not DoesEntityExist(vehicleEntity) then return end - - local vehCoords = GetEntityCoords(vehicleEntity) - - return tracker.vehiclePlate, vector2(vehCoords.x, vehCoords.y), tracker.name + + -- If vehicle is found in the world + if vehicleNetworkID then + local vehicleEntity = NetworkGetEntityFromNetworkId(vehicleNetworkID) + if DoesEntityExist(vehicleEntity) then + local vehCoords = GetEntityCoords(vehicleEntity) + + -- Update the last known position in the database + updateTrackerPosition(serialNumber, vehCoords) + + return tracker.vehiclePlate, vector2(vehCoords.x, vehCoords.y), tracker.name + end + end + + -- If vehicle is not found in the world, check if we have a last known position + if tracker.lastKnownX and tracker.lastKnownY then + -- Return the last known position + return tracker.vehiclePlate, vector2(tracker.lastKnownX, tracker.lastKnownY), tracker.name, true -- true indicates this is a last known position + end + + -- No current or last known position available + return nil end) lib.callback.register('qb_vehicle_tracker:isVehicleTracked', function(source, vehiclePlate) @@ -128,6 +149,13 @@ lib.callback.register('qb_vehicle_tracker:placeTracker', function(source, vehicl if not addTracker(serialNumber, trim(vehiclePlate), Player.PlayerData.citizenid, defaultName, phoneNumber) then return false end + -- Try to get initial position + local vehicle = lib.getClosestVehicle(GetEntityCoords(GetPlayerPed(source)), 3.0, true) + if vehicle and DoesEntityExist(vehicle) then + local vehCoords = GetEntityCoords(vehicle) + updateTrackerPosition(serialNumber, vehCoords) + end + Player.Functions.RemoveItem(config.trackerItem, 1, slot) TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items[config.trackerItem], 'remove') @@ -182,7 +210,7 @@ lib.callback.register('qb_vehicle_tracker:updateTrackerName', function(source, s return updateTrackerName(serialNumber, name) end) --- New callbacks for advanced scanner features +-- Callbacks for advanced scanner features lib.callback.register('qb_vehicle_tracker:getTrackerOwnerLocation', function(source, vehiclePlate) if type(vehiclePlate) ~= "string" then return nil end @@ -227,3 +255,24 @@ lib.callback.register('qb_vehicle_tracker:getTrackerOwnerPhone', function(source return tracker.phoneNumber end) + +-- Add this thread to periodically update positions of all tracked vehicles +CreateThread(function() + while true do + Wait(300000) -- Update every 5 minutes + + -- Get all tracked vehicles + local trackers = MySQL.query.await('SELECT `serialNumber`, `vehiclePlate` FROM `vehicle_trackers`') + + for _, tracker in ipairs(trackers) do + local vehicleNetworkID = getVehicleNetworkIdByPlate(tracker.vehiclePlate) + if vehicleNetworkID then + local vehicleEntity = NetworkGetEntityFromNetworkId(vehicleNetworkID) + if DoesEntityExist(vehicleEntity) then + local vehCoords = GetEntityCoords(vehicleEntity) + updateTrackerPosition(tracker.serialNumber, vehCoords) + end + end + end + end +end) diff --git a/resources/[inventory]/qs-inventory/html/images/lighter.png b/resources/[inventory]/qs-inventory/html/images/lighter.png index 319fe9a3d..7873a795c 100644 Binary files a/resources/[inventory]/qs-inventory/html/images/lighter.png and b/resources/[inventory]/qs-inventory/html/images/lighter.png differ