frameworks/client.lua
if config.framework ~= 'esx' then return end
ESX = exports['es_extended']:getSharedObject()
local framework = {}
return framework
client/cartheif.lua
local utils = require('src/client/utils')
local carthief = {}
local vehicleEntity = nil
function carthief.init()
local vehicle = config.vehicles[math.random(#config.vehicles)]
local location = config.locations[math.random(#config.locations)]
vehicleEntity = utils.createVehicle(vehicle, location.xyz, location[4])
SetVehicleDoorsLocked(vehicleEntity, 2)
utils.debug('Created vehicle: ' .. vehicle)
local blip = utils.createRuteBlip(location.xyz)
ESX.ShowNotification('Kolla din GPS så ser du vart bilen du ska sno befinner sig.')
local gpsDuration = config.gpsDuration
local trackingActive = false
local networkId = NetworkGetNetworkIdFromEntity(vehicleEntity)
CreateThread(function()
while true do
if not DoesEntityExist(vehicleEntity) then
break;
end
Wait(0)
end
main.inmission = false
RemoveBlip(blip)
TriggerServerEvent('vnrp_Carthief:removecooldown')
end)
local function startGPSTracking()
trackingActive = true
TriggerServerEvent('vnrp_carthief:startTracking', networkId)
local coords = GetEntityCoords(vehicleEntity)
local streetName = GetStreetNameFromHashKey(GetStreetNameAtCoord(coords.x, coords.y, coords.z))
exports["lb-phone"]:SendCompanyMessage('police', ('Bilstöld: Någon bryter sig just nu in i en bil på adressen %s'):format(streetName), true)
CreateThread(function()
while trackingActive do
local playerPed = PlayerPedId()
local isInDriverSeat = false
if DoesEntityExist(vehicleEntity) then
isInDriverSeat = GetPedInVehicleSeat(vehicleEntity, -1) == playerPed
else
trackingActive = false
main.inmission = false
TriggerServerEvent('vnrp_Carthief:removecooldown')
TriggerServerEvent('vnrp_carthief:stopTracking', networkId)
lib.hideTextUI()
break
end
if isInDriverSeat then
local mins = math.floor(gpsDuration / 60)
local secs = gpsDuration % 60
lib.showTextUI(('GPS-spårning: %02d:%02d kvar'):format(mins, secs), {
position = "top-center",
icon = 'map-pin',
iconColor = '#00FF00',
style = {
backgroundColor = '#324142',
borderRadius = 8,
padding = '5px 10px'
}
})
Wait(1000)
gpsDuration = gpsDuration - 1
if gpsDuration <= 0 then
trackingActive = false
TriggerServerEvent('vnrp_carthief:stopTracking', networkId)
lib.hideTextUI()
if DoesEntityExist(vehicleEntity) then
carthief.leave()
end
break
end
else
lib.showTextUI('GPS-spårning: Pausad (du måste sitta i förarsätet)', {
position = "top-center",
icon = 'car',
iconColor = '#FF0000',
style = {
backgroundColor = '#324142',
borderRadius = 8,
padding = '5px 10px'
}
})
Wait(1000)
end
end
lib.hideTextUI()
end)
end
exports.ox_target:addLocalEntity(vehicleEntity, {
{
name = 'carthief_breakin',
label = 'Bryt dig in',
icon = 'fa-solid fa-screwdriver-wrench',
distance = 2.5,
canInteract = function(entity, coords, distance, data, name)
local driverDoor = GetEntityBoneIndexByName(entity, 'door_dside_f')
if driverDoor == -1 then
driverDoor = GetEntityBoneIndexByName(entity, 'door_pside_f')
end
if driverDoor ~= -1 then
local doorPos = GetWorldPositionOfEntityBone(entity, driverDoor)
local playerPos = GetEntityCoords(PlayerPedId())
return #(doorPos - playerPos) < 1.2
end
return false
end,
onSelect = function(data)
if lib.skillCheck({'easy', 'easy', 'easy'}, {'w', 'a', 's', 'd'}) then
ESX.ShowNotification('Du lyckades bryta dig in!')
SetVehicleDoorsLocked(vehicleEntity, 1)
SetVehicleAlarm(vehicleEntity, true)
StartVehicleAlarm(vehicleEntity)
exports.ox_target:removeLocalEntity(vehicleEntity, 'carthief_breakin')
startGPSTracking()
else
ESX.ShowNotification('Du misslyckades och verktyget gick sönder!')
SetVehicleAlarm(vehicleEntity, true)
StartVehicleAlarm(vehicleEntity)
end
RemoveBlip(blip)
end
}
})
end
function carthief.leave()
ESX.ShowNotification('Bra jobbat, GPS-spårningen är nu bortkopplad. Se till att tappa polisen och ta dig till den angivna platsen för din betalning.')
local leaveLocation = config.leaveLocations[math.random(#config.leaveLocations)]
local blip = utils.createRuteBlip(leaveLocation.xyz)
local npcPed = nil
local npcSpawned = false
CreateThread(function()
while not npcSpawned do
local playerCoords = GetEntityCoords(PlayerPedId())
local dist = #(playerCoords - leaveLocation.xyz)
if dist < 100.0 then
npcSpawned = true
npcPed = utils.createPed(config.ped.model, leaveLocation.xyz, config.ped.anim.dict, config.ped.anim.name)
utils.debug('Created npc: ' .. config.ped.model)
end
Wait(1000)
end
end)
lib.zones.box({
coords = leaveLocation.xyz,
size = vec3(10, 10, 10),
rotation = leaveLocation.w or 0,
debug = false,
inside = function()
if DoesEntityExist(vehicleEntity) then
lib.showTextUI('[E] Lämna fordonet', {
position = "top-center",
icon = 'car',
style = {
backgroundColor = '#324142',
borderRadius = 6,
padding = '7px 15px'
}
})
else
lib.hideTextUI()
end
end,
onEnter = function()
end,
onExit = function()
lib.hideTextUI()
end
})
local function handleLeave()
if IsControlJustPressed(0, 38) then
local playerPed = PlayerPedId()
if IsPedInVehicle(playerPed, vehicleEntity, false) then
TaskLeaveVehicle(playerPed, vehicleEntity, 0)
Wait(2000)
DeleteVehicle(vehicleEntity)
vehicleEntity = nil
if not npcPed then
npcPed = utils.createPed(config.ped.model, leaveLocation.xyz, config.ped.anim.dict, config.ped.anim.name)
end
local price = math.random(config.price.min, config.price.max)
RemoveBlip(blip)
exports.ox_target:addLocalEntity(npcPed, {
{
name = 'carthief_npc',
label = 'Prata med kontakt',
icon = 'fa-solid fa-comment',
distance = 2.5,
onSelect = function(data)
exports.vnrp_dialog:showDialog({
ped = npcPed,
dialog = {
{
id = 'carthief',
job = 'Bilstöld',
name = config.ped.name,
text = ('Tjena igen lilbro, jävligt bra jobbat med stölden. Har ett extremt bra erbjudande till dig, antigen tar du %s kr eller så kör vi dubbel eller inget :D'):format(price),
buttons = {
{
label = 'Jag är bettingtorsk, jag dubblar!',
close = true,
onSelect = function()
main.inmission = false
local random = math.random(1, 2)
if random == 1 then
ESX.TriggerServerCallback('vnrp_carthief:getReward', function(res)
local newPrice = (price * 2)
ESX.ShowNotification('Du vann och fick ' .. newPrice .. ' kr!')
end, (price * 2))
else
ESX.TriggerServerCallback('vnrp_carthief:getReward', function(res)
ESX.ShowNotification('HAHA, du fick inget. Men tack för bilen :)')
end)
end
exports.ox_target:removeLocalEntity(npcPed, 'carthief_npc')
DeletePed(npcPed)
end
},
{
label = 'Nej jag är en feg fitta, ge mig pengarna!',
close = true,
onSelect = function()
ESX.TriggerServerCallback('vnrp_carthief:getReward', function(res)
ESX.ShowNotification('Du fick ' .. price .. ' kr!')
end, price)
exports.ox_target:removeLocalEntity(npcPed, 'carthief_npc')
DeletePed(npcPed)
end,
},
},
},
}
})
end
}
})
else
ESX.ShowNotification('Du måste vara i det stulna fordonet!')
end
end
end
Citizen.CreateThread(function()
while true do
local playerCoords = GetEntityCoords(PlayerPedId())
local dist = #(playerCoords - leaveLocation.xyz)
if dist < 10.0 then
handleLeave()
end
if not DoesEntityExist(vehicleEntity) then
break
end
Wait(0)
end
end)
end
return carthief
client/main.lua
local utils = require('src.client.utils')
local carthief = require('src/client/carthief')
local policeBlip = nil
main = {
inmission = false
}
CreateThread(function()
while not ESX.IsPlayerLoaded() do
Wait(0)
end
utils.createBlip(config.ped.coords.xyz)
local ped = utils.createPed(config.ped.model, config.ped.coords, config.ped.anim.dict, config.ped.anim.name)
utils.debug('Ped Loaded')
while not exports.ox_target do
Wait(0)
end
exports.ox_target:addLocalEntity(ped, {
{
name = "carthief",
label = ('Prata med %s'):format(config.ped.name),
icon = "fa-solid fa-car",
distance = 2.5,
onSelect = function()
if not exports.vnrp_semiwl:HasKrim() then
return ESX.ShowNotification('Du är inte kriminell')
end
if main.inmission then
return ESX.ShowNotification('Du har redan ett pågående uppdrag? Trög eller? Ja det är du!')
end
ESX.TriggerServerCallback('vnrp_carthief:canStart', function(res)
if not res.success then
ESX.ShowNotification(res.message)
else
exports.vnrp_dialog:showDialog({
ped = ped,
dialog = {
{
id = 'carthief',
job = 'Bilstöld',
name = config.ped.name,
text = 'Tjena, är du sugen på att sno en bil åt mig?',
buttons = {
{
label = 'Ja gärna!',
close = true,
onSelect = function()
main.inmission = true
carthief.init()
end
},
{
label = 'Nej tack, jag vill inte.',
close = true,
onSelect = function()
TriggerServerEvent('vnrp_Carthief:removecooldown')
end
},
},
},
}
})
end
end)
end
},
})
end)
RegisterNetEvent('vnrp_carthief:updatePoliceBlip')
AddEventHandler('vnrp_carthief:updatePoliceBlip', function(coords)
if ESX.GetPlayerData().job.name and ESX.GetPlayerData().job.name == 'police' then
if not policeBlip then
policeBlip = AddBlipForCoord(coords.x, coords.y, coords.z)
SetBlipSprite(policeBlip, 161)
SetBlipColour(policeBlip, 1)
SetBlipScale(policeBlip, 1.2)
SetBlipAsShortRange(policeBlip, false)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("Stöldfordon (Live)")
EndTextCommandSetBlipName(policeBlip)
else
SetBlipCoords(policeBlip, coords.x, coords.y, coords.z)
end
end
end)
RegisterNetEvent('vnrp_carthief:removePoliceBlip')
AddEventHandler('vnrp_carthief:removePoliceBlip', function()
if policeBlip then
RemoveBlip(policeBlip)
policeBlip = nil
end
end)
client/utils.lua
local utils = {}
function utils.debug(msg)
if(not config.debug) then return end
end
function utils.createBlip(coords)
local blip = AddBlipForCoord(coords)
SetBlipSprite(blip, 126)
SetBlipColour(blip, 3)
SetBlipScale(blip, 0.8)
SetBlipAsShortRange(blip, false)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString(config.ped.name)
EndTextCommandSetBlipName(blip)
return blip
end
function utils.createRuteBlip(coords)
local routeBlip = AddBlipForCoord(coords)
SetBlipRoute(routeBlip, true)
SetBlipColour(routeBlip, 46)
SetBlipRouteColour(routeBlip, 46)
EndTextCommandSetBlipName(routeBlip)
return routeBlip
end
function utils.createVehicle(model, coords, heading)
local modelHash = type(model) == 'string' and GetHashKey(model) or model
RequestModel(modelHash)
while not HasModelLoaded(modelHash) do
Wait(0)
end
local vehicle = CreateVehicle(modelHash, coords.x, coords.y, coords.z, heading, true, false)
SetEntityAsMissionEntity(vehicle, true, true)
return vehicle
end
function utils.createPed(model, coords, animDict, animName)
local modelHash = type(model) == 'string' and GetHashKey(model) or model
if not IsModelValid(modelHash) then
return nil
end
RequestModel(modelHash)
while not HasModelLoaded(modelHash) do
Wait(0)
end
local ped = CreatePed(4, modelHash, coords.x, coords.y, coords.z, coords.w or 0.0, false, false)
if animDict and animName then
RequestAnimDict(animDict)
while not HasAnimDictLoaded(animDict) do
Wait(0)
end
TaskPlayAnim(ped, animDict, animName, 1.0, -1, -1, 1, 0, 0, 0, 0)
end
SetEntityInvincible(ped, true)
SetBlockingOfNonTemporaryEvents(ped, true)
-- Clean up model memory
SetModelAsNoLongerNeeded(modelHash)
return ped
end
return utils
config.lua
config = config or {}
config.framework = 'auto_detect'
config.debug = true
config.price = {
min = 15250,
max = 20000
}
config.policeCount = 5
config.gpsDuration = 500
config.ped = {
model = 'g_m_m_casrn_01',
coords = vector4(276.1453552246094, -343.3414306640625, 44.91979217529297, 340.7944641113281),
name = 'Bilstöld',
anim = {
dict = 'mini@strip_club@idles@bouncer@base',
name = 'base'
}
}
config.vehicles = {
'audirs6tk',
'm3kean',
'rmodm4gts',
'850sw',
'volvo145'
}
config.locations = {
vector4(293.96380615234375, -346.1685180664063, 44.9198112487793, 68.42893981933594),
vector4(296.19549560546875, -339.5173950195313, 44.9198112487793, 70.66112518310547),
vector4(298.1001586914063, -333.0532836914063, 44.91981506347656, 67.3129653930664)
}
config.leaveLocations = {
vector4(416.215087890625, 6468.71875, 28.84889030456543, 45.15995025634765),
vector4(2201.113525390625, 5610.3837890625, 53.4927749633789, 344.3866882324219),
vector4(1970.52880859375, 5168.52685546875, 47.63904571533203, 128.43716430664065),
}
shared/main.lua
local utils = require('src/client/utils')
if config.framework == 'auto_detect' then
if(GetResourceState('es_extended') == 'started') then
config.framework = 'esx'
elseif(GetResourceState('qb-core') == 'started') then
config.framework = 'qb'
else
return utils.debug('Unable to detect framework')
end
utils.debug('Detected framework: ' .. config.framework)
end
kolla på koden och fixa en framework/**/server.lua och en src/server/*.lua