From f17fc54e6b285019dc530d575cfa05045c5691d8 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 25 Oct 2022 13:51:13 +0200 Subject: [PATCH 01/83] feat(esx_skin): update player weight on spawn This updates the max weight on join, if a player has a bag. --- [esx]/esx_skin/client/main.lua | 7 +++++++ [esx]/esx_skin/server/main.lua | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/[esx]/esx_skin/client/main.lua b/[esx]/esx_skin/client/main.lua index cc49fbc8..3640626c 100644 --- a/[esx]/esx_skin/client/main.lua +++ b/[esx]/esx_skin/client/main.lua @@ -1,6 +1,13 @@ local lastSkin, cam, isCameraActive local firstSpawn, zoomOffset, camOffset, heading, skinLoaded = true, 0.0, 0.0, 90.0, false +RegisterNetEvent('esx:playerLoaded') +AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) + if ESX.IsPlayerLoaded() then + TriggerServerEvent('esx_skin:setWeight', skin) + end +end) + function OpenMenu(submitCb, cancelCb, restrict) local playerPed = PlayerPedId() diff --git a/[esx]/esx_skin/server/main.lua b/[esx]/esx_skin/server/main.lua index ff133355..73f47cd0 100644 --- a/[esx]/esx_skin/server/main.lua +++ b/[esx]/esx_skin/server/main.lua @@ -19,6 +19,22 @@ AddEventHandler('esx_skin:save', function(skin) }) end) +RegisterServerEvent('esx_skin:setWeight') +AddEventHandler('esx_skin:setWeight', function(skin) + local xPlayer = ESX.GetPlayerFromId(source) + + if not ESX.GetConfig().OxInventory then + local defaultMaxWeight = ESX.GetConfig().MaxWeight + local backpackModifier = Config.BackpackWeight[skin.bags_1] + + if backpackModifier then + xPlayer.setMaxWeight(defaultMaxWeight + backpackModifier) + else + xPlayer.setMaxWeight(defaultMaxWeight) + end + end +end) + RegisterServerEvent('esx_skin:responseSaveSkin') AddEventHandler('esx_skin:responseSaveSkin', function(skin) local xPlayer = ESX.GetPlayerFromId(source) From 3fb93998e6376213ad9fba47dd44469e7245568f Mon Sep 17 00:00:00 2001 From: bitpredator <67551273+bitpredator@users.noreply.github.com> Date: Sun, 27 Nov 2022 11:38:52 +0100 Subject: [PATCH 02/83] feat:(Italian language translation) --- [esx_addons]/esx_taxijob/locales/it.lua | 57 +++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 [esx_addons]/esx_taxijob/locales/it.lua diff --git a/[esx_addons]/esx_taxijob/locales/it.lua b/[esx_addons]/esx_taxijob/locales/it.lua new file mode 100644 index 00000000..5d97f45c --- /dev/null +++ b/[esx_addons]/esx_taxijob/locales/it.lua @@ -0,0 +1,57 @@ +Locales['it'] = { + -- cloakroom + ['cloakroom_menu'] = 'guardaroba', + ['cloakroom_prompt'] = 'premi [E] per accedere al guardaroba.', + ['wear_citizen'] = 'abbigliamento cittadino', + ['wear_work'] = 'abiti da lavoro', + + -- garage + ['spawner_prompt'] = 'premi [E] per accedere al garage.', + ["vehicle_spawned"] = "generato con successo un ~b~Taxi!", + ['store_veh'] = 'premi [E] per depositare il veicolo', + ['spawn_veh'] = 'genera veicolo', + ['spawnpoint_blocked'] = 'un veicolo blocca lo spawnpoint!', + ['only_taxi'] = 'puoi depositare solo taxi.', + ['empty_garage'] = 'nessun veicolo nel garage!', + + ['taking_service'] = 'prendi servizio: Taxi/Uber', + ['full_service'] = 'servizio completo: ', + ['amount_invalid'] = 'importo non valido', + ['press_to_open'] = 'premi [E] per accedere al menu', + ['billing'] = 'fattura', + ['billing_sent'] = 'la fattura è stata registrata!', + ['invoice_amount'] = 'importo fattura', + ['no_players_near'] = 'nessun giocatore nelle vicinanze', + ['start_job'] = 'inizia / interrompi la guida di lavori NPC', + ['drive_search_pass'] = 'guida alla ricerca di passeggeri', + ['customer_found'] = 'hai trovato un cliente avvicinati a lui', + ['client_unconcious'] = 'il tuo cliente è ~r~incosciente, cercane un altro', + ['arrive_dest'] = 'sei arrivato a destinazione', + ['take_me_to_near'] = 'portami a %s, vicino a %s', + ['take_me_to'] = 'portami a %s', + ['close_to_client'] = 'sei troppo lontano dal cliente, avvicinati a lui', + ['return_to_veh'] = 'torna al tuo veicolo per continuare la missione', + ['must_in_taxi'] = 'devi essere in un taxi per iniziare la missione', + ['must_in_vehicle'] = 'devi essere in un veicolo per iniziare la missione', + ['not_in_taxi'] = 'Hai lasciato il taxi mentre eri in missione!', + ['have_earned'] = 'hai guadagnato $%s', + ['comp_earned'] = '- la tua azienda ha guadagnato $%s \n - hai guadagnato $%s', + ['deposit_stock'] = 'deposito', + ['take_stock' ] = 'prendi', + ['empty_stock'] = 'deposito vuoto!', + ['empty_your_inventory'] = 'Svuota il tuo inventario!' , + ['boss_actions'] = 'Azioni del capo', + ['mission_complete'] = 'missione completata', + ['quantity' ] = 'quantità', + ['quantity_invalid'] = 'questa quantità non è valida!', + ['inventory'] = 'inventario', + ['taxi_client'] = 'cliente taxi', + ['have_withdrawn'] = 'hai prelevato x%s %s', + ['have_deposited'] = 'hai depositato x%s %s', + ['player_cannot_hold'] = '~r~non hai abbastanza spazio libero nel tuo inventario!', + ['blip_taxi'] = 'Downtown Cab Co.', + ['phone_taxi' ] = ' downtown Cab Co.', + ['taxi' ] = 'taxi', + ['taxi_stock'] = 'deposito dei taxi', + ['menu_return'] = 'Ritorno' + } \ No newline at end of file From 33e1bb331cdc62f9ec5eab300a8ebaa44c6ba5f1 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 27 Nov 2022 21:16:46 +0100 Subject: [PATCH 03/83] fix(esx_skin): removed if statement --- [esx]/esx_skin/client/main.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/[esx]/esx_skin/client/main.lua b/[esx]/esx_skin/client/main.lua index 3640626c..086a8cdf 100644 --- a/[esx]/esx_skin/client/main.lua +++ b/[esx]/esx_skin/client/main.lua @@ -3,9 +3,7 @@ local firstSpawn, zoomOffset, camOffset, heading, skinLoaded = true, 0.0, 0.0, 9 RegisterNetEvent('esx:playerLoaded') AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) - if ESX.IsPlayerLoaded() then - TriggerServerEvent('esx_skin:setWeight', skin) - end + TriggerServerEvent('esx_skin:setWeight', skin) end) function OpenMenu(submitCb, cancelCb, restrict) From 9a196c3012e356ebd49993e139a9e04a165e4d0c Mon Sep 17 00:00:00 2001 From: Csoki Date: Sun, 27 Nov 2022 21:24:53 +0100 Subject: [PATCH 04/83] esx_garage: update 'hu' locales --- [esx_addons]/esx_garage/locales/hu.lua | 8 ++++---- [esx_addons]/esx_garage/server/main.lua | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/[esx_addons]/esx_garage/locales/hu.lua b/[esx_addons]/esx_garage/locales/hu.lua index 0e5d3d3f..727b4a19 100644 --- a/[esx_addons]/esx_garage/locales/hu.lua +++ b/[esx_addons]/esx_garage/locales/hu.lua @@ -1,15 +1,15 @@ Locales["hu"] = { ["parking_blip_name"] = 'Garázs', ["Impound_blip_name"] = 'Lefoglaltak', - ["access_parking"] = 'Nyomd meg az [E] gombot a parkoló eléréshez.', + ["access_parking"] = 'Nyomd meg az [E] gombot a parkoló megtekintéséhez.', ["access_Impound"] = 'Nyomd meg az [E] gombot a lefoglaltak megtekintéséhez.', ["park_veh"] = 'Nyomd meg az [E] gombot a jármű parkolásához.', ["not_owning_veh"] = 'Ez a jármű nem a te tulajdonod!', - ['veh_released'] = 'Jármű sikeresen kivéve.', + ['veh_released'] = 'Sikeresen kivetted a járművet.', ['veh_Impound_released'] = 'Jármű sikeresen kiváltva a legfolalásból.', ['veh_stored'] = 'Jármű sikeresen tárolva', - ['veh_impounded'] = 'Lefoglalt jármű', - ['no_veh_parking'] = 'Nincsenek itt tárolt járművek-', + ['veh_impounded'] = 'Lefoglalt jármű megjelölve a térképen', + ['no_veh_parking'] = 'Nincsenek itt tárolt járművek.', ['no_veh_impounded'] = 'Nincs lefoglalt jármű.', ['no_veh_Impound'] = 'nincs lefoglalt járműved.', ['veh_model'] = 'Model', diff --git a/[esx_addons]/esx_garage/server/main.lua b/[esx_addons]/esx_garage/server/main.lua index f22dcf3e..5c5683cb 100644 --- a/[esx_addons]/esx_garage/server/main.lua +++ b/[esx_addons]/esx_garage/server/main.lua @@ -38,7 +38,6 @@ AddEventHandler('esx_garage:setImpound', function(Impound, vehicleProps) }) xPlayer.showNotification(TranslateCap('veh_impounded')) - end) From a6a411a93acf82a58fa16226eb51c209ea27be0f Mon Sep 17 00:00:00 2001 From: Csoki Date: Sun, 27 Nov 2022 21:29:20 +0100 Subject: [PATCH 05/83] es_extended: add missing locales - tpm --- [esx]/es_extended/client/main.lua | 4 ++-- [esx]/es_extended/locales/en.lua | 1 + [esx]/es_extended/locales/hu.lua | 7 ++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/[esx]/es_extended/client/main.lua b/[esx]/es_extended/client/main.lua index b613f741..dbda6dd3 100644 --- a/[esx]/es_extended/client/main.lua +++ b/[esx]/es_extended/client/main.lua @@ -611,12 +611,12 @@ AddEventHandler("esx:tpm", function() -- If we can't find the coords, set the coords to the old ones. -- We don't unpack them before since they aren't in a loop and only called once. SetPedCoordsKeepVehicle(ped, oldCoords['x'], oldCoords['y'], oldCoords['z'] - 1.0) - ESX.ShowNotification('Successfully Teleported', true, false, 140) + ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) end -- If Z coord was found, set coords in found coords. SetPedCoordsKeepVehicle(ped, x, y, groundZ) - ESX.ShowNotification('Successfully Teleported', true, false, 140) + ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) end end) end) diff --git a/[esx]/es_extended/locales/en.lua b/[esx]/es_extended/locales/en.lua index 30fa36c7..dfe8e9fb 100644 --- a/[esx]/es_extended/locales/en.lua +++ b/[esx]/es_extended/locales/en.lua @@ -108,6 +108,7 @@ Locales['en'] = { ['command_giveammo_noweapon_found'] = '%s does not have that weapon', ['command_giveammo_weapon'] = 'Weapon name', ['command_giveammo_ammo'] = 'Ammo Quantity', + ['tpm_success'] = 'Successfully Teleported', -- Locale settings ['locale_digit_grouping_symbol'] = ',', diff --git a/[esx]/es_extended/locales/hu.lua b/[esx]/es_extended/locales/hu.lua index abd4ffa6..bcbf2f3a 100644 --- a/[esx]/es_extended/locales/hu.lua +++ b/[esx]/es_extended/locales/hu.lua @@ -105,9 +105,10 @@ Locales["hu"] = { ["commanderror_invalidcommand"] = "Érvénytelen parancs - /%s", ["commanderror_invalidplayerid"] = "Megadott játékos nem online.", ["commandgeneric_playerid"] = "Játékos Szerver Id", - ['command_giveammo_noweapon_found'] = '%s does not have that weapon', - ['command_giveammo_weapon'] = 'Weapon name', - ['command_giveammo_ammo'] = 'Ammo Quantity', + ['command_giveammo_noweapon_found'] = 'Nincs ilyen fegyvered: %s', + ['command_giveammo_weapon'] = 'Fegyver név', + ['command_giveammo_ammo'] = 'Lőszer mennyiség', + ['tpm_success'] = 'Sikeres teleportálás', -- Locale settings ["locale_digit_grouping_symbol"] = ",", From b98de6c2c4368954ead082895af7ad4dabef6323 Mon Sep 17 00:00:00 2001 From: Csoki Date: Sun, 27 Nov 2022 21:34:19 +0100 Subject: [PATCH 06/83] es_extended: refactor esx:GetVehicleType event --- [esx]/es_extended/client/main.lua | 32 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/[esx]/es_extended/client/main.lua b/[esx]/es_extended/client/main.lua index dbda6dd3..f53c3539 100644 --- a/[esx]/es_extended/client/main.lua +++ b/[esx]/es_extended/client/main.lua @@ -711,26 +711,22 @@ AddEventHandler("esx:freezePlayer", function(input) end) RegisterNetEvent("esx:GetVehicleType", function(Model, Request) - local Model = Model - local VehicleType = GetVehicleClassFromName(Model) - local type = "automobile" - if VehicleType == 15 then - type = "heli" - elseif VehicleType == 16 then - type = "plane" - elseif VehicleType == 14 then - type = "boat" - elseif VehicleType == 11 then - type = "trailer" - elseif VehicleType == 21 then - type = "train" - elseif VehicleType == 13 or VehicleType == 8 then - type = "bike" - end if Model == `submersible` or Model == `submersible2` then - type = "submarine" + return TriggerServerEvent("esx:ReturnVehicleType", "submarine", Request) end - TriggerServerEvent("esx:ReturnVehicleType", type, Request) + + local VehicleType = GetVehicleClassFromName(Model) + local types = { + [8] = "bike", + [11] = "trailer", + [13] = "bike", + [14] = "boat", + [15] = "heli", + [16] = "plane", + [21] = "train", + } + + TriggerServerEvent("esx:ReturnVehicleType", types[VehicleType] or "automobile", Request) end) From bedefd7b5c6792046997a154964807a750c8e733 Mon Sep 17 00:00:00 2001 From: Csoki Date: Sun, 27 Nov 2022 21:58:04 +0100 Subject: [PATCH 07/83] es_extended: noclip # add missing locales # refactor noclip methods (thread only if noclip enabled) # format code --- [esx]/es_extended/client/main.lua | 267 ++++++++++++++---------------- [esx]/es_extended/locales/en.lua | 5 + [esx]/es_extended/locales/hu.lua | 5 + 3 files changed, 138 insertions(+), 139 deletions(-) diff --git a/[esx]/es_extended/client/main.lua b/[esx]/es_extended/client/main.lua index f53c3539..e857b077 100644 --- a/[esx]/es_extended/client/main.lua +++ b/[esx]/es_extended/client/main.lua @@ -537,158 +537,147 @@ AddEventHandler("esx:tpm", function() local GetVehiclePedIsIn = GetVehiclePedIsIn ESX.TriggerServerCallback("esx:isUserAdmin", function(admin) - if admin then - local blipMarker = GetFirstBlipInfoId(8) - if not DoesBlipExist(blipMarker) then - ESX.ShowNotification('No Waypoint Set.', true, false, 140) - return 'marker' + if not admin then + return + end + local blipMarker = GetFirstBlipInfoId(8) + if not DoesBlipExist(blipMarker) then + ESX.ShowNotification(TranslateCap('tpm_nowaypoint'), true, false, 140) + return 'marker' + end + + -- Fade screen to hide how clients get teleported. + DoScreenFadeOut(650) + while not IsScreenFadedOut() do + Wait(0) + end + + local ped, coords = ESX.PlayerData.ped, GetBlipInfoIdCoord(blipMarker) + local vehicle = GetVehiclePedIsIn(ped, false) + local oldCoords = GetEntityCoords(ped) + + -- Unpack coords instead of having to unpack them while iterating. + -- 825.0 seems to be the max a player can reach while 0.0 being the lowest. + local x, y, groundZ, Z_START = coords['x'], coords['y'], 850.0, 950.0 + local found = false + FreezeEntityPosition(vehicle > 0 and vehicle or ped, true) + + for i = Z_START, 0, -25.0 do + local z = i + if (i % 2) ~= 0 then + z = Z_START - i end - - -- Fade screen to hide how clients get teleported. - DoScreenFadeOut(650) - while not IsScreenFadedOut() do - Wait(0) + + NewLoadSceneStart(x, y, z, x, y, z, 50.0, 0) + local curTime = GetGameTimer() + while IsNetworkLoadingScene() do + if GetGameTimer() - curTime > 1000 then + break + end + Wait(0) end - - local ped, coords = ESX.PlayerData.ped, GetBlipInfoIdCoord(blipMarker) - local vehicle = GetVehiclePedIsIn(ped, false) - local oldCoords = GetEntityCoords(ped) - - -- Unpack coords instead of having to unpack them while iterating. - -- 825.0 seems to be the max a player can reach while 0.0 being the lowest. - local x, y, groundZ, Z_START = coords['x'], coords['y'], 850.0, 950.0 - local found = false - if vehicle > 0 then - FreezeEntityPosition(vehicle, true) - else - FreezeEntityPosition(ped, true) + NewLoadSceneStop() + SetPedCoordsKeepVehicle(ped, x, y, z) + + while not HasCollisionLoadedAroundEntity(ped) do + RequestCollisionAtCoord(x, y, z) + if GetGameTimer() - curTime > 1000 then + break + end + Wait(0) end - - for i = Z_START, 0, -25.0 do - local z = i - if (i % 2) ~= 0 then - z = Z_START - i - end - - NewLoadSceneStart(x, y, z, x, y, z, 50.0, 0) - local curTime = GetGameTimer() - while IsNetworkLoadingScene() do - if GetGameTimer() - curTime > 1000 then - break - end - Wait(0) - end - NewLoadSceneStop() - SetPedCoordsKeepVehicle(ped, x, y, z) - - while not HasCollisionLoadedAroundEntity(ped) do - RequestCollisionAtCoord(x, y, z) - if GetGameTimer() - curTime > 1000 then - break - end - Wait(0) - end - - -- Get ground coord. As mentioned in the natives, this only works if the client is in render distance. - found, groundZ = GetGroundZFor_3dCoord(x, y, z, false) - if found then - Wait(0) - SetPedCoordsKeepVehicle(ped, x, y, groundZ) - break - end - Wait(0) + + -- Get ground coord. As mentioned in the natives, this only works if the client is in render distance. + found, groundZ = GetGroundZFor_3dCoord(x, y, z, false) + if found then + Wait(0) + SetPedCoordsKeepVehicle(ped, x, y, groundZ) + break end - - -- Remove black screen once the loop has ended. - DoScreenFadeIn(650) - if vehicle > 0 then - FreezeEntityPosition(vehicle, false) - else - FreezeEntityPosition(ped, false) - end - - if not found then - -- If we can't find the coords, set the coords to the old ones. - -- We don't unpack them before since they aren't in a loop and only called once. - SetPedCoordsKeepVehicle(ped, oldCoords['x'], oldCoords['y'], oldCoords['z'] - 1.0) - ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) - end - - -- If Z coord was found, set coords in found coords. - SetPedCoordsKeepVehicle(ped, x, y, groundZ) + Wait(0) + end + + -- Remove black screen once the loop has ended. + DoScreenFadeIn(650) + FreezeEntityPosition(vehicle > 0 and vehicle or ped, false) + + if not found then + -- If we can't find the coords, set the coords to the old ones. + -- We don't unpack them before since they aren't in a loop and only called once. + SetPedCoordsKeepVehicle(ped, oldCoords['x'], oldCoords['y'], oldCoords['z'] - 1.0) ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) end + + -- If Z coord was found, set coords in found coords. + SetPedCoordsKeepVehicle(ped, x, y, groundZ) + ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) end) end) local noclip = false +local noclip_pos = vector3(0, 0, 70) +local heading = 0 + +local function noclipThread() + while noclip do + SetEntityCoordsNoOffset(ESX.PlayerData.ped, noclip_pos.x, noclip_pos.y, noclip_pos.z, 0, 0, 0) + + if IsControlPressed(1, 34) then + heading = heading + 1.5 + if heading > 360 then + heading = 0 + end + + SetEntityHeading(ESX.PlayerData.ped, heading) + end + + if IsControlPressed(1, 9) then + heading = heading - 1.5 + if heading < 0 then + heading = 360 + end + + SetEntityHeading(ESX.PlayerData.ped, heading) + end + + if IsControlPressed(1, 8) then + noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 1.0, 0.0) + end + + if IsControlPressed(1, 32) then + noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, -1.0, 0.0) + end + + if IsControlPressed(1, 27) then + noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 0.0, 1.0) + end + + if IsControlPressed(1, 173) then + noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 0.0, -1.0) + end + Wait(0) + end +end + RegisterNetEvent("esx:noclip") AddEventHandler("esx:noclip", function(input) ESX.TriggerServerCallback("esx:isUserAdmin", function(admin) - if admin then - local player = PlayerId() - - local msg = "disabled" - if(noclip == false)then - noclip_pos = GetEntityCoords(ESX.PlayerData.ped, false) - end - - noclip = not noclip - - if(noclip)then - msg = "enabled" - end - - TriggerEvent("chatMessage", "Noclip has been ^2^*" .. msg) - end - end) -end) - - local heading = 0 - CreateThread(function() - while true do - local Sleep = 1500 - - if(noclip)then - Sleep = 0 - SetEntityCoordsNoOffset(ESX.PlayerData.ped, noclip_pos.x, noclip_pos.y, noclip_pos.z, 0, 0, 0) - - if(IsControlPressed(1, 34))then - heading = heading + 1.5 - if(heading > 360)then - heading = 0 - end - - SetEntityHeading(ESX.PlayerData.ped, heading) - end - - if(IsControlPressed(1, 9))then - heading = heading - 1.5 - if(heading < 0)then - heading = 360 - end - - SetEntityHeading(ESX.PlayerData.ped, heading) - end - - if(IsControlPressed(1, 8))then - noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 1.0, 0.0) - end - - if(IsControlPressed(1, 32))then - noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, -1.0, 0.0) - end - - if(IsControlPressed(1, 27))then - noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 0.0, 1.0) - end - - if(IsControlPressed(1, 173))then - noclip_pos = GetOffsetFromEntityInWorldCoords(ESX.PlayerData.ped, 0.0, 0.0, -1.0) - end + if not admin then + return end - Wait(Sleep) - end + + if not noclip then + noclip_pos = GetEntityCoords(ESX.PlayerData.ped, false) + heading = GetEntityHeading(ESX.PlayerData.ped) + end + + noclip = not noclip + if noclip then + CreateThread(noclipThread) + end + + ESX.ShowNotification(TranslateCap('noclip_message', noclip and "enabled" or "disabled"), true, false, 140) + end) end) RegisterNetEvent("esx:killPlayer") @@ -705,7 +694,7 @@ AddEventHandler("esx:freezePlayer", function(input) SetPlayerInvincible(player, true) elseif input == 'unfreeze' then SetEntityCollision(ESX.PlayerData.ped, true) - FreezeEntityPosition(ESX.PlayerData.ped, false) + FreezeEntityPosition(ESX.PlayerData.ped, false) SetPlayerInvincible(player, false) end end) diff --git a/[esx]/es_extended/locales/en.lua b/[esx]/es_extended/locales/en.lua index dfe8e9fb..e480153f 100644 --- a/[esx]/es_extended/locales/en.lua +++ b/[esx]/es_extended/locales/en.lua @@ -108,8 +108,13 @@ Locales['en'] = { ['command_giveammo_noweapon_found'] = '%s does not have that weapon', ['command_giveammo_weapon'] = 'Weapon name', ['command_giveammo_ammo'] = 'Ammo Quantity', + ['tpm_nowaypoint'] = 'No Waypoint Set.', ['tpm_success'] = 'Successfully Teleported', + ['noclip_message'] = 'Noclip has been %s', + ['enabled'] = '~g~enabled~s~', + ['disabled'] = '~r~disabled~s~', + -- Locale settings ['locale_digit_grouping_symbol'] = ',', ['locale_currency'] = '£%s', diff --git a/[esx]/es_extended/locales/hu.lua b/[esx]/es_extended/locales/hu.lua index bcbf2f3a..f909601a 100644 --- a/[esx]/es_extended/locales/hu.lua +++ b/[esx]/es_extended/locales/hu.lua @@ -108,8 +108,13 @@ Locales["hu"] = { ['command_giveammo_noweapon_found'] = 'Nincs ilyen fegyvered: %s', ['command_giveammo_weapon'] = 'Fegyver név', ['command_giveammo_ammo'] = 'Lőszer mennyiség', + ['tpm_nowaypoint'] = 'Nincs kijelölve pozíció!', ['tpm_success'] = 'Sikeres teleportálás', + ['noclip_message'] = 'Noclip %s', + ['enabled'] = '~g~engedélyezve~s~', + ['disabled'] = '~r~letiltva~s~', + -- Locale settings ["locale_digit_grouping_symbol"] = ",", ["locale_currency"] = "$%s", From 43e388739e9304e6da4c02d32dbd8ffafdf81bb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AL1=C6=8EN?= <72218928+johnsoul777@users.noreply.github.com> Date: Mon, 28 Nov 2022 03:03:32 +0100 Subject: [PATCH 08/83] New update in spanish New update in spanish --- [esx]/esx_multicharacter/locales/es.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/[esx]/esx_multicharacter/locales/es.lua b/[esx]/esx_multicharacter/locales/es.lua index f43622e2..4bef70ed 100644 --- a/[esx]/esx_multicharacter/locales/es.lua +++ b/[esx]/esx_multicharacter/locales/es.lua @@ -1,15 +1,18 @@ Locales["es"] = { ["male"] = "Hombre", ["female"] = "Mujer", - ["delete_label"] = "¿Quieres borrar a %s %s?", ["select_char"] = "Seleccionar personaje", - ["select_char_description"] = "Select a character to play as.", + ["select_char_description"] = "Selecciona un personaje para jugar.", ["create_char"] = "Crear nuevo personaje", ["char_play"] = "Jugar este personaje", + ["char_play_description"] = "Continúe hacia la ciudad.", ["char_disabled"] = "Este personaje está deshabilitado", + ["char_disabled_description"] = "Este personaje es inutilizable.", ["char_delete"] = "Borrar este personaje", - ["cancel"] = "Cancelar", - ["confirm"] = "Confirmar", + ["char_delete_description"] = "Eliminar permanentemente este personaje.", + ["character"] = "Personaje: %s", + ["return"] = "Volver", + ["return_description"] = "Volver a la selección de personajes.", ["command_setslots"] = "Establecer el numero de espacios de un jugador", ["command_remslots"] = "Elimina espacios multipersonaje de un jugador", ["command_enablechar"] = "Habilita el personaje de un jugador", From a3d7b381d28078d5c6fdb94b389a2a89a3f89520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AL1=C6=8EN?= <72218928+johnsoul777@users.noreply.github.com> Date: Mon, 28 Nov 2022 03:13:04 +0100 Subject: [PATCH 09/83] Last update in spanish Last update in spanish --- [esx_addons]/esx_lscustom/locales/es.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/[esx_addons]/esx_lscustom/locales/es.lua b/[esx_addons]/esx_lscustom/locales/es.lua index 9906d613..a21c1999 100644 --- a/[esx_addons]/esx_lscustom/locales/es.lua +++ b/[esx_addons]/esx_lscustom/locales/es.lua @@ -268,9 +268,9 @@ Locales['es'] = { ['stickers'] = 'calcomanías', -- Xenon Colors - ['mintgreen'] = 'Mint Green', - ['goldenshower'] = 'Golden Shower', - ['ponypink'] = 'Pony Pink', - ['hotpink'] = 'Hot Pink', - ['blacklight'] = 'Blacklight', + ['mintgreen'] = 'Menta verde', + ['goldenshower'] = 'Baño de oro', + ['ponypink'] = 'Poni rosa', + ['hotpink'] = 'Rosa caliente', + ['blacklight'] = 'Luz negra', } From d4500ad09b5387601a829c8e7261f7f852390a2b Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Mon, 28 Nov 2022 16:35:04 +0800 Subject: [PATCH 10/83] context implementation --- [esx_addons]/esx_shops/client/main.lua | 60 +++++++++++--------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/[esx_addons]/esx_shops/client/main.lua b/[esx_addons]/esx_shops/client/main.lua index da3a15e4..1d12688d 100644 --- a/[esx_addons]/esx_shops/client/main.lua +++ b/[esx_addons]/esx_shops/client/main.lua @@ -2,49 +2,39 @@ local hasAlreadyEnteredMarker, lastZone local currentAction, currentActionMsg, currentActionData = nil, nil, {} function OpenShopMenu(zone) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-shopping-basket", title = TranslateCap('shop') } + } + for i=1, #Config.Zones[zone].Items, 1 do local item = Config.Zones[zone].Items[i] - table.insert(elements, { - label = ('%s - %s'):format(item.label, TranslateCap('shop_item', ESX.Math.GroupDigits(item.price))), + elements[#elements+1] = { + icon = "fas fa-shopping-basket", + title = ('%s - %s'):format(item.label, TranslateCap('shop_item', ESX.Math.GroupDigits(item.price))), itemLabel = item.label, - item = item.name, - price = item.price, - - -- menu properties - value = 1, - type = 'slider', - min = 1, - max = 100 - }) + item = item.name, + price = item.price + } end - ESX.UI.Menu.CloseAll() + ESX.OpenContext("right", elements, function(menu,element) + local elements2 = { + {unselectable = true, icon = "fas fa-shopping-basket", title = element.title}, + {icon = "fas fa-shopping-basket", title = "Amount", input = true, inputType = "number", inputPlaceholder = "Amount you want to buy", inputMin = 1, inputMax = 25}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'shop', { - title = TranslateCap('shop'), - align = 'bottom-left', - elements = elements - }, function(data, menu) - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'shop_confirm', { - title = TranslateCap('shop_confirm', data.current.value, data.current.itemLabel, ESX.Math.GroupDigits(data.current.price * data.current.value)), - align = 'bottom-left', - elements = { - {label = TranslateCap('no'), value = 'no'}, - {label = TranslateCap('yes'), value = 'yes'} - }}, function(data2, menu2) - if data2.current.value == 'yes' then - TriggerServerEvent('esx_shops:buyItem', data.current.item, data.current.value, zone) - end - - menu2.close() - end, function(data2, menu2) - menu2.close() + ESX.OpenContext("right", elements2, function(menu2,element2) + local amount = menu2.eles[2].inputValue + ESX.CloseContext() + TriggerServerEvent('esx_shops:buyItem', element.item, amount, zone) + end, function(menu) + currentAction = 'shop_menu' + currentActionMsg = TranslateCap('press_menu') + currentActionData = {zone = zone} end) - end, function(data, menu) - menu.close() - + end, function(menu) currentAction = 'shop_menu' currentActionMsg = TranslateCap('press_menu') currentActionData = {zone = zone} From 7b7d4db48aa8fd736da2706e5b2bfc7970a8e483 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Tue, 29 Nov 2022 17:34:52 +0800 Subject: [PATCH 11/83] remove is menu open check --- [esx_addons]/esx_billing/client/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx_addons]/esx_billing/client/main.lua b/[esx_addons]/esx_billing/client/main.lua index ec15c725..66ae67d5 100644 --- a/[esx_addons]/esx_billing/client/main.lua +++ b/[esx_addons]/esx_billing/client/main.lua @@ -27,7 +27,7 @@ function ShowBillsMenu() end RegisterCommand('showbills', function() - if not isDead and not ESX.UI.Menu.IsOpen('default', GetCurrentResourceName(), 'billing') then + if not isDead then ShowBillsMenu() end end, false) From 429b454116773b815d32a93cf1b5753bea9c172d Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Tue, 29 Nov 2022 17:56:12 +0800 Subject: [PATCH 12/83] min/max config option --- [esx_addons]/esx_drugs/config.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/[esx_addons]/esx_drugs/config.lua b/[esx_addons]/esx_drugs/config.lua index 6f789f4a..27409d0e 100644 --- a/[esx_addons]/esx_drugs/config.lua +++ b/[esx_addons]/esx_drugs/config.lua @@ -31,3 +31,10 @@ Config.Marker = { Size = vector3(1.5,1.5,1.0), Type = 1, } + +-- min amount of Config.DrugDealerItems to sell +-- max amount of Config.DrugDealerItems to sell +Config.SellMenu = { + Min = 1, + Max = 50 +} From 0fca847965cf69237f1a06cc153f2324db247b9f Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Tue, 29 Nov 2022 17:57:15 +0800 Subject: [PATCH 13/83] context implementation --- [esx_addons]/esx_drugs/client/main.lua | 87 +++++++++++--------------- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/[esx_addons]/esx_drugs/client/main.lua b/[esx_addons]/esx_drugs/client/main.lua index fda69166..77cd648d 100644 --- a/[esx_addons]/esx_drugs/client/main.lua +++ b/[esx_addons]/esx_drugs/client/main.lua @@ -21,7 +21,6 @@ CreateThread(function() inZoneDrugShop = false if menuOpen then menuOpen=false - ESX.UI.Menu.CloseAll() end end @@ -62,36 +61,39 @@ CreateThread(function () end) function OpenDrugShop() - ESX.UI.Menu.CloseAll() - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-cannabis", title = TranslateCap('dealer_title')} + } menuOpen = true for k, v in pairs(ESX.GetPlayerData().inventory) do local price = Config.DrugDealerItems[v.name] if price and v.count > 0 then - table.insert(elements, { - label = ('%s - %s'):format(v.label, TranslateCap('dealer_item', ESX.Math.GroupDigits(price))), + elements[#elements+1] = { + icon = "fas fa-shopping-basket", + title = ('%s - %s'):format(v.label, TranslateCap('dealer_item', ESX.Math.GroupDigits(price))), name = v.name, price = price, - - -- menu properties - type = 'slider', - value = 1, - min = 1, - max = v.count - }) + } end end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'drug_shop', { - title = TranslateCap('dealer_title'), - align = 'top-left', - elements = elements - }, function(data, menu) - TriggerServerEvent('esx_drugs:sellDrug', data.current.name, data.current.value) - end, function(data, menu) - menu.close() + ESX.OpenContext("right", elements, function(menu,element) + local elements2 = { + {unselectable = true, icon = "fas fa-shopping-basket", title = element.title}, + {icon = "fas fa-shopping-basket", title = "Amount", input = true, inputType = "number", inputPlaceholder = "Amount you want to sell", inputMin = Config.SellMenu.Min, inputMax = Config.SellMenu.Max}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local amount = menu2.eles[2].inputValue + ESX.CloseContext() + TriggerServerEvent('esx_drugs:sellDrug', element.name, amount) + end, function(menu) + menuOpen = false + end) + end, function(menu) menuOpen = false end) end @@ -99,7 +101,7 @@ end AddEventHandler('onResourceStop', function(resource) if resource == GetCurrentResourceName() then if menuOpen then - ESX.UI.Menu.CloseAll() + ESX.CloseContext() end end end) @@ -109,39 +111,20 @@ function OpenBuyLicenseMenu(licenseName) local license = Config.LicensePrices[licenseName] local elements = { - { - label = TranslateCap('license_no'), - value = 'no' - }, - - { - label = ('%s - %s'):format(license.label, TranslateCap('dealer_item', ESX.Math.GroupDigits(license.price))), - value = licenseName, - price = license.price, - licenseName = license.label - } + {unselectable = true, title = TranslateCap('purchase_license')}, + {title = ('%s - %s'):format(license.label, TranslateCap('dealer_item', ESX.Math.GroupDigits(license.price))), value = licenseName, price = license.price, licenseName = license.label} } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'license_shop', { - title = TranslateCap('license_title'), - align = 'top-left', - elements = elements - }, function(data, menu) - - if data.current.value ~= 'no' then - ESX.TriggerServerCallback('esx_drugs:buyLicense', function(boughtLicense) - if boughtLicense then - ESX.ShowNotification(TranslateCap('license_bought', data.current.licenseName, ESX.Math.GroupDigits(data.current.price))) - else - ESX.ShowNotification(TranslateCap('license_bought_fail', data.current.licenseName)) - end - end, data.current.value) - else - menu.close() - end - - end, function(data, menu) - menu.close() + ESX.OpenContext("right", elements, function(menu,element) + ESX.TriggerServerCallback('esx_drugs:buyLicense', function(boughtLicense) + if boughtLicense then + ESX.CloseContext() + ESX.ShowNotification(TranslateCap('license_bought', element.licenseName, ESX.Math.GroupDigits(element.price))) + else + ESX.ShowNotification(TranslateCap('license_bought_fail', element.licenseName)) + end + end, element.value) + end, function(menu) menuOpen = false end) end From e0c211d7dd5a882a896b1bad6a823a292a811dae Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:21:36 +0800 Subject: [PATCH 14/83] context implemenation --- [esx_addons]/esx_ambulancejob/client/job.lua | 142 +++++++++---------- 1 file changed, 70 insertions(+), 72 deletions(-) diff --git a/[esx_addons]/esx_ambulancejob/client/job.lua b/[esx_addons]/esx_ambulancejob/client/job.lua index 36d5ab70..68c16e78 100644 --- a/[esx_addons]/esx_ambulancejob/client/job.lua +++ b/[esx_addons]/esx_ambulancejob/client/job.lua @@ -11,63 +11,59 @@ end) function OpenAmbulanceActionsMenu() - local elements = {{label = TranslateCap('cloakroom'), value = 'cloakroom'}} + local elements = { + {unselectable = true, icon = "fas fa-shirt", title = "Ambulance Actions"}, + {icon = "fas fa-shirt", title = TranslateCap('cloakroom'), value = 'cloakroom'} + } if Config.EnablePlayerManagement and ESX.PlayerData.job.grade_name == 'boss' then - table.insert(elements, {label = TranslateCap('boss_actions'), value = 'boss_actions'}) + elements[#elements+1] = { + icon = "fas fa-ambulance", + title = TranslateCap('boss_actions'), + value = 'boss_actions' + } end - ESX.UI.Menu.CloseAll() - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'ambulance_actions', { - title = TranslateCap('ambulance'), - align = 'top-left', - elements = elements - }, function(data, menu) - if data.current.value == 'cloakroom' then + ESX.OpenContext("right", elements, function(menu,element) + if element.value == 'cloakroom' then OpenCloakroomMenu() - elseif data.current.value == 'boss_actions' then + elseif element.value == 'boss_actions' then TriggerEvent('esx_society:openBossMenu', 'ambulance', function(data, menu) menu.close() end, {wash = false}) end - end, function(data, menu) - menu.close() end) end function OpenMobileAmbulanceActionsMenu() - ESX.UI.Menu.CloseAll() + local elements = { + {unselectable = true, icon = "fas fa-ambulance", title = TranslateCap('ambulance')}, + {icon = "fas fa-ambulance", title = TranslateCap('ems_menu'), value = "citizen_interaction"} + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'mobile_ambulance_actions', { - title = TranslateCap('ambulance'), - align = 'top-left', - elements = { - {label = TranslateCap('ems_menu'), value = 'citizen_interaction'} - }}, function(data, menu) - if data.current.value == 'citizen_interaction' then - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction', { - title = TranslateCap('ems_menu_title'), - align = 'top-left', - elements = { - {label = TranslateCap('ems_menu_revive'), value = 'revive'}, - {label = TranslateCap('ems_menu_small'), value = 'small'}, - {label = TranslateCap('ems_menu_big'), value = 'big'}, - {label = TranslateCap('ems_menu_putincar'), value = 'put_in_vehicle'}, - {label = TranslateCap('ems_menu_search'), value = 'search'} - }}, function(data, menu) + ESX.OpenContext("right", elements, function(menu,element) + if element.value == "citizen_interaction" then + local elements2 = { + {unselectable = true, icon = "fas fa-ambulance", title = element.title}, + {icon = "fas fa-syringe", title = TranslateCap('ems_menu_revive'), value = "revive"}, + {icon = "fas fa-bandage", title = TranslateCap('ems_menu_small'), value = "small"}, + {icon = "fas fa-bandage", title = TranslateCap('ems_menu_big'), value = "big"}, + {icon = "fas fa-car", title = TranslateCap('ems_menu_putincar'), value = "put_in_vehicle"}, + {icon = "fas fa-syringe", title = TranslateCap('ems_menu_search'), value = "search"}, + } + + ESX.OpenContext("right", elements2, function(menu2,element2) if isBusy then return end - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if data.current.value == 'search' then + if element2.value == 'search' then TriggerServerEvent('esx_ambulancejob:svsearch') elseif closestPlayer == -1 or closestDistance > 1.0 then ESX.ShowNotification(TranslateCap('no_players')) else - if data.current.value == 'revive' then + if element2.value == 'revive' then revivePlayer(closestPlayer) - elseif data.current.value == 'small' then + elseif element2.value == 'small' then ESX.TriggerServerCallback('esx_ambulancejob:getItemAmount', function(quantity) if quantity > 0 then local closestPlayerPed = GetPlayerPed(closestPlayer) @@ -94,8 +90,7 @@ function OpenMobileAmbulanceActionsMenu() end end, 'bandage') - elseif data.current.value == 'big' then - + elseif element2.value == 'big' then ESX.TriggerServerCallback('esx_ambulancejob:getItemAmount', function(quantity) if quantity > 0 then local closestPlayerPed = GetPlayerPed(closestPlayer) @@ -121,18 +116,12 @@ function OpenMobileAmbulanceActionsMenu() ESX.ShowNotification(TranslateCap('not_enough_medikit')) end end, 'medikit') - - elseif data.current.value == 'put_in_vehicle' then + elseif element2.value == 'put_in_vehicle' then TriggerServerEvent('esx_ambulancejob:putInVehicle', GetPlayerServerId(closestPlayer)) end end - end, function(data, menu) - menu.close() end) end - - end, function(data, menu) - menu.close() end) end @@ -328,7 +317,7 @@ end) AddEventHandler('esx_ambulancejob:hasExitedMarker', function(hospital, part, partNum) if not isInShopMenu then - ESX.UI.Menu.CloseAll() + ESX.CloseContext() end ESX.HideUI() CurrentAction = nil @@ -411,14 +400,14 @@ AddEventHandler('esx_ambulancejob:putInVehicle', function() end) function OpenCloakroomMenu() - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'cloakroom', { - title = TranslateCap('cloakroom'), - align = 'top-left', - elements = { - {label = TranslateCap('ems_clothes_civil'), value = 'citizen_wear'}, - {label = TranslateCap('ems_clothes_ems'), value = 'ambulance_wear'}, - }}, function(data, menu) - if data.current.value == 'citizen_wear' then + local elements = { + {unselectable = true, icon = "fas fa-shirt", title = TranslateCap('cloakroom')}, + {icon = "fas fa-shirt", title = TranslateCap('ems_clothes_civil'), value = "citizen_wear"}, + {icon = "fas fa-shirt", title = TranslateCap('ems_clothes_ems'), value = "ambulance_wear"}, + } + + ESX.OpenContext("right", elements, function(menu,element) + if element.value == "citizen_wear" then ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) TriggerEvent('skinchanger:loadSkin', skin) isOnDuty = false @@ -432,7 +421,7 @@ function OpenCloakroomMenu() print("[^2INFO^7] Off Duty") end end) - elseif data.current.value == 'ambulance_wear' then + elseif element.value == "ambulance_wear" then ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) if skin.sex == 0 then TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_male) @@ -450,29 +439,38 @@ function OpenCloakroomMenu() end end) end - - menu.close() - end, function(data, menu) - menu.close() end) end function OpenPharmacyMenu() - ESX.UI.Menu.CloseAll() + local elements = { + {unselectable = true, icon = "fas fa-pills", title = TranslateCap('pharmacy_menu_title')} + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'pharmacy', { - title = TranslateCap('pharmacy_menu_title'), - align = 'top-left', - elements = { - {label = TranslateCap('pharmacy_take', TranslateCap('medikit')), item = 'medikit', type = 'slider', value = 1, min = 1, max = 100}, - {label = TranslateCap('pharmacy_take', TranslateCap('bandage')), item = 'bandage', type = 'slider', value = 1, min = 1, max = 100} - }}, function(data, menu) - if Config.Debug then - print("[^2INFO^7] Attempting to Give Item - ^5" .. tostring(data.current.item) .. "^7") - end - TriggerServerEvent('esx_ambulancejob:giveItem', data.current.item, data.current.value) - end, function(data, menu) - menu.close() + for k,v in pairs(Config.PharmacyItems) do + elements[#elements+1] = { + icon = "fas fa-pills", + title = v.title, + item = v.item + } + end + + ESX.OpenContext("right", elements, function(menu,element) + local elements2 = { + {unselectable = true, icon = "fas fa-pills", title = element.title}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to buy.."}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local amount = menu2.eles[2].inputValue + if Config.Debug then + print("[^2INFO^7] Attempting to Give Item - ^5" .. tostring(element.item) .. "^7") + end + TriggerServerEvent('esx_ambulancejob:giveItem', element.item, amount) + end, function(menu) + OpenPharmacyMenu() + end) end) end From 805cc7ad3a6f60f47f0d2f6a20ac49e9d1913b47 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:22:06 +0800 Subject: [PATCH 15/83] context implementation --- [esx_addons]/esx_ambulancejob/client/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/[esx_addons]/esx_ambulancejob/client/main.lua b/[esx_addons]/esx_ambulancejob/client/main.lua index 68772db2..a9a46264 100644 --- a/[esx_addons]/esx_ambulancejob/client/main.lua +++ b/[esx_addons]/esx_ambulancejob/client/main.lua @@ -100,7 +100,7 @@ end) function OnPlayerDeath() isDead = true - ESX.UI.Menu.CloseAll() + ESX.CloseContext() ClearTimecycleModifier() SetTimecycleModifier("REDMIST_blend") SetTimecycleModifierStrength(0.7) @@ -115,7 +115,7 @@ end RegisterNetEvent('esx_ambulancejob:useItem') AddEventHandler('esx_ambulancejob:useItem', function(itemName) - ESX.UI.Menu.CloseAll() + ESX.CloseContext() if itemName == 'medikit' then local lib, anim = 'anim@heists@narcotics@funding@gang_idle', 'gang_chatting_idle01' -- TODO better animations From e3671ef0ce1c52bee1b5e45a8c5968d45e304050 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:22:57 +0800 Subject: [PATCH 16/83] context implementation --- .../esx_ambulancejob/client/vehicle.lua | 167 +++++++++--------- 1 file changed, 83 insertions(+), 84 deletions(-) diff --git a/[esx_addons]/esx_ambulancejob/client/vehicle.lua b/[esx_addons]/esx_ambulancejob/client/vehicle.lua index 05ea2719..a11ec9ce 100644 --- a/[esx_addons]/esx_ambulancejob/client/vehicle.lua +++ b/[esx_addons]/esx_ambulancejob/client/vehicle.lua @@ -2,16 +2,15 @@ local spawnedVehicles = {} function OpenVehicleSpawnerMenu(type, hospital, part, partNum) local playerCoords = GetEntityCoords(PlayerPedId()) + local elements = { + {unselectable = true, icon = "fas fa-car", title = TranslateCap('garage_title')}, + {icon = "fas fa-car", title = TranslateCap('garage_storeditem'), action = 'garage'}, + {icon = "fas fa-car", title = TranslateCap('garage_storeitem'), action = 'store_garage'}, + {icon = "fas fa-car", title = TranslateCap('garage_buyitem'), action = 'buy_vehicle'} + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle', { - title = TranslateCap('garage_title'), - align = 'top-left', - elements = { - {label = TranslateCap('garage_storeditem'), action = 'garage'}, - {label = TranslateCap('garage_storeitem'), action = 'store_garage'}, - {label = TranslateCap('garage_buyitem'), action = 'buy_vehicle'} - }}, function(data, menu) - if data.current.action == 'buy_vehicle' then + ESX.OpenContext("right", elements, function(menu,element) + if element.action == "buy_vehicle" then local shopElements = {} local authorizedVehicles = Config.AuthorizedVehicles[type][ESX.PlayerData.job.grade_name] local shopCoords = Config.Hospitals[hospital][part][partNum].InsideShop @@ -21,23 +20,30 @@ function OpenVehicleSpawnerMenu(type, hospital, part, partNum) if IsModelInCdimage(vehicle.model) then local vehicleLabel = GetLabelText(GetDisplayNameFromVehicleModel(vehicle.model)) - table.insert(shopElements, { - label = ('%s - %s'):format(vehicleLabel, TranslateCap('shop_item', ESX.Math.GroupDigits(vehicle.price))), + shopElements[#shopElements+1] = { + icon = 'fas fa-car', + title = ('%s - %s'):format(vehicleLabel, TranslateCap('shop_item', ESX.Math.GroupDigits(vehicle.price))), name = vehicleLabel, model = vehicle.model, price = vehicle.price, props = vehicle.props, type = type - }) + } end end if #shopElements > 0 then OpenShopMenu(shopElements, playerCoords, shopCoords) + else + ESX.ShowNotification(TranslateCap('garage_notauthorized')) end + else + ESX.ShowNotification(TranslateCap('garage_notauthorized')) end - elseif data.current.action == 'garage' then - local garage = {} + elseif element.action == "garage" then + local garage = { + {unselectable = true, icon = "fas fa-car", title = "Garage"} + } ESX.TriggerServerCallback('esx_vehicleshop:retrieveJobVehicles', function(jobVehicles) if #jobVehicles > 0 then @@ -56,42 +62,37 @@ function OpenVehicleSpawnerMenu(type, hospital, part, partNum) label = label .. ('%s'):format(TranslateCap('garage_notstored')) end - table.insert(garage, { - label = label, + garage[#garage+1] = { + icon = 'fas fa-car', + title = label, stored = v.stored, model = props.model, plate = props.plate - }) + } allVehicleProps[props.plate] = props end end if #garage > 0 then - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_garage', { - title = TranslateCap('garage_title'), - align = 'top-left', - elements = garage - }, function(data2, menu2) - if data2.current.stored == 1 then + ESX.OpenContext("right", garage, function(menuG,elementG) + if elementG.stored == 1 then local foundSpawn, spawnPoint = GetAvailableVehicleSpawnPoint(hospital, part, partNum) if foundSpawn then - menu2.close() + ESX.CloseContext() - ESX.Game.SpawnVehicle(data2.current.model, spawnPoint.coords, spawnPoint.heading, function(vehicle) - local vehicleProps = allVehicleProps[data2.current.plate] + ESX.Game.SpawnVehicle(elementG.model, spawnPoint.coords, spawnPoint.heading, function(vehicle) + local vehicleProps = allVehicleProps[elementG.plate] ESX.Game.SetVehicleProperties(vehicle, vehicleProps) - TriggerServerEvent('esx_vehicleshop:setJobVehicleState', data2.current.plate, false) + TriggerServerEvent('esx_vehicleshop:setJobVehicleState', elementG.plate, false) ESX.ShowNotification(TranslateCap('garage_released')) end) end else ESX.ShowNotification(TranslateCap('garage_notavailable')) end - end, function(data2, menu2) - menu2.close() end) else ESX.ShowNotification(TranslateCap('garage_empty')) @@ -100,11 +101,9 @@ function OpenVehicleSpawnerMenu(type, hospital, part, partNum) ESX.ShowNotification(TranslateCap('garage_empty')) end end, type) - elseif data.current.action == 'store_garage' then + elseif element.action == "store_garage" then StoreNearbyVehicle(playerCoords) end - end, function(data, menu) - menu.close() end) end @@ -198,72 +197,72 @@ end function OpenShopMenu(elements, restoreCoords, shopCoords) local playerPed = PlayerPedId() isInShopMenu = true + ESX.OpenContext("right", elements, function(menu,element) + local elements2 = { + {unselectable = true, icon = "fas fa-car", title = element.title}, + {icon = "fas fa-eye", title = "View", value = "view"} + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop', { - title = TranslateCap('vehicleshop_title'), - align = 'top-left', - elements = elements - }, function(data, menu) - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop_confirm', { - title = TranslateCap('vehicleshop_confirm', data.current.name, data.current.price), - align = 'top-left', - elements = { - {label = TranslateCap('confirm_no'), value = 'no'}, - {label = TranslateCap('confirm_yes'), value = 'yes'} - }}, function(data2, menu2) - if data2.current.value == 'yes' then - local newPlate = exports['esx_vehicleshop']:GeneratePlate() - local vehicle = GetVehiclePedIsIn(playerPed, false) - local props = ESX.Game.GetVehicleProperties(vehicle) - props.plate = newPlate + ESX.OpenContext("right", elements2, function(menu2,element2) + if element2.value == "view" then + DeleteSpawnedVehicles() + WaitForVehicleToLoad(element.model) - ESX.TriggerServerCallback('esx_ambulancejob:buyJobVehicle', function(bought) - if bought then - ESX.ShowNotification(TranslateCap('vehicleshop_bought', data.current.name, ESX.Math.GroupDigits(data.current.price))) + ESX.Game.SpawnLocalVehicle(element.model, shopCoords, 0.0, function(vehicle) + table.insert(spawnedVehicles, vehicle) + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + FreezeEntityPosition(vehicle, true) + SetModelAsNoLongerNeeded(element.model) + if element.props then + ESX.Game.SetVehicleProperties(vehicle, element.props) + end + end) + + local elements3 = { + {unselectable = true, icon = "fas fa-car", title = element.title}, + {icon = "fas fa-check-double", title = "Buy", value = "buy"}, + {icon = "fas fa-eye", title = "Stop Viewing", value = "stop"} + } + + ESX.OpenContext("right", elements3, function(menu3,element3) + if element3.value == 'stop' then isInShopMenu = false - ESX.UI.Menu.CloseAll() + ESX.CloseContext() DeleteSpawnedVehicles() FreezeEntityPosition(playerPed, false) SetEntityVisible(playerPed, true) ESX.Game.Teleport(playerPed, restoreCoords) - else - ESX.ShowNotification(TranslateCap('vehicleshop_money')) - menu2.close() + elseif element3.value == "buy" then + local newPlate = exports['esx_vehicleshop']:GeneratePlate() + local vehicle = GetVehiclePedIsIn(playerPed, false) + local props = ESX.Game.GetVehicleProperties(vehicle) + props.plate = newPlate + + ESX.TriggerServerCallback('esx_ambulancejob:buyJobVehicle', function (bought) + if bought then + ESX.ShowNotification(TranslateCap('vehicleshop_bought', element.name, ESX.Math.GroupDigits(element.price))) + + isInShopMenu = false + ESX.CloseContext() + DeleteSpawnedVehicles() + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + + ESX.Game.Teleport(playerPed, restoreCoords) + else + ESX.ShowNotification(TranslateCap('vehicleshop_money')) + ESX.CloseContext() + end + end, props, element.type) end - end, props, data.current.type) - else - menu2.close() - end - end, function(data2, menu2) - menu2.close() - end) - end, function(data, menu) - isInShopMenu = false - ESX.UI.Menu.CloseAll() - - DeleteSpawnedVehicles() - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - - ESX.Game.Teleport(playerPed, restoreCoords) - end, function(data, menu) - DeleteSpawnedVehicles() - WaitForVehicleToLoad(data.current.model) - - ESX.Game.SpawnLocalVehicle(data.current.model, shopCoords, 0.0, function(vehicle) - table.insert(spawnedVehicles, vehicle) - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - SetModelAsNoLongerNeeded(data.current.model) - - if data.current.props then - ESX.Game.SetVehicleProperties(vehicle, data.current.props) + end) end end) end) +end WaitForVehicleToLoad(elements[1].model) ESX.Game.SpawnLocalVehicle(elements[1].model, shopCoords, 0.0, function(vehicle) From 77863a229b5943292f209c2188b22391ac21aed9 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:29:16 +0800 Subject: [PATCH 17/83] context implementation, replace whole --- [esx_addons]/esx_ambulancejob/client/vehicle.lua | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/[esx_addons]/esx_ambulancejob/client/vehicle.lua b/[esx_addons]/esx_ambulancejob/client/vehicle.lua index a11ec9ce..b2edd04a 100644 --- a/[esx_addons]/esx_ambulancejob/client/vehicle.lua +++ b/[esx_addons]/esx_ambulancejob/client/vehicle.lua @@ -264,19 +264,6 @@ function OpenShopMenu(elements, restoreCoords, shopCoords) end) end - WaitForVehicleToLoad(elements[1].model) - ESX.Game.SpawnLocalVehicle(elements[1].model, shopCoords, 0.0, function(vehicle) - table.insert(spawnedVehicles, vehicle) - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - SetModelAsNoLongerNeeded(elements[1].model) - - if elements[1].props then - ESX.Game.SetVehicleProperties(vehicle, elements[1].props) - end - end) -end - CreateThread(function() while true do sleep = 1500 From bf7bc4401b4c55a99ac7e0ca6ef8380993ae6603 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:35:49 +0800 Subject: [PATCH 18/83] add pharmacy items into config for better user friendlyness --- [esx_addons]/esx_ambulancejob/config.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/[esx_addons]/esx_ambulancejob/config.lua b/[esx_addons]/esx_ambulancejob/config.lua index 5efa5a64..833983e3 100644 --- a/[esx_addons]/esx_ambulancejob/config.lua +++ b/[esx_addons]/esx_ambulancejob/config.lua @@ -35,6 +35,17 @@ Config.RespawnPoints = { {coords = vector3(1836.03, 3670.99, 34.28), heading = 296.06} -- Sandy Shores } +Config.PharmacyItems = { + { + title = "Medikit", + item = "medikit" + }, + { + title = "Bandage", + item = "bandage" + }, +} + Config.Hospitals = { CentralLosSantos = { From 7282e0f8cf2dd463680cadbdaf2508643aa5bb65 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 19:54:39 +0800 Subject: [PATCH 19/83] context implementation --- [esx_addons]/esx_boat/client/main.lua | 212 +++++++++++++------------- 1 file changed, 105 insertions(+), 107 deletions(-) diff --git a/[esx_addons]/esx_boat/client/main.lua b/[esx_addons]/esx_boat/client/main.lua index d4e6440c..1a9cd519 100644 --- a/[esx_addons]/esx_boat/client/main.lua +++ b/[esx_addons]/esx_boat/client/main.lua @@ -5,97 +5,96 @@ function OpenBoatShop(shop) isInShopMenu = true local playerPed = PlayerPedId() - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-ship", title = TranslateCap('boat_shop')} + } for k,v in ipairs(Config.Vehicles) do - table.insert(elements, { - label = ('%s - $%s'):format(v.label, ESX.Math.GroupDigits(v.price)), + elements[#elements+1] = { + icon = "fas fa-ship", + title = ('%s - $%s'):format(v.label, ESX.Math.GroupDigits(v.price)), name = v.label, model = v.model, price = v.price, props = v.props or nil - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'boat_shop', { - title = TranslateCap('boat_shop'), - align = 'top-left', - elements = elements - }, function (data, menu) - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'boat_shop_confirm', { - title = TranslateCap('boat_shop_confirm', data.current.name, ESX.Math.GroupDigits(data.current.price)), - align = 'top-left', - elements = { - {label = TranslateCap('confirm_no'), value = 'no'}, - {label = TranslateCap('confirm_yes'), value = 'yes'} - }}, function (data2, menu2) - if data2.current.value == 'yes' then - local plate = exports['esx_vehicleshop']:GeneratePlate() - local vehicle = GetVehiclePedIsIn(playerPed, false) - local props = ESX.Game.GetVehicleProperties(vehicle) - props.plate = plate + ESX.OpenContext("right", elements, function(menu,element) + local elements2 = { + {unselectable = true, icon = "fas fa-ship", title = element.title}, + {icon = "fas fa-eye", title = "View", val = "view"} + } - ESX.TriggerServerCallback('esx_boat:buyBoat', function(bought) - if bought then - ESX.ShowNotification(TranslateCap('boat_shop_bought', data.current.name, ESX.Math.GroupDigits(data.current.price))) + ESX.OpenContext("right", elements2, function(menu2,element2) + if element2.val == "view" then + DeleteSpawnedVehicles() - DeleteSpawnedVehicles() - isInShopMenu = false - ESX.UI.Menu.CloseAll() + ESX.Game.SpawnLocalVehicle(element.model, shop.Inside, shop.Inside.w, function (vehicle) + table.insert(spawnedVehicles, vehicle) + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + FreezeEntityPosition(vehicle, true) - CurrentAction = 'boat_shop' - CurrentActionMsg = TranslateCap('boat_shop_open') - - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - SetEntityCoords(playerPed, shop.Outside.x, shop.Outside.y, shop.Outside.z) - else - ESX.ShowNotification(TranslateCap('boat_shop_nomoney')) - menu2.close() + if element.props then + ESX.Game.SetVehicleProperties(vehicle, element.props) end - end, props) - else - menu2.close() - end - end, function (data2, menu2) - menu2.close() - end) - end, function (data, menu) - menu.close() - isInShopMenu = false - DeleteSpawnedVehicles() + local elements3 = { + {unselectable = true, icon = "fas fa-ship", title = element.title}, + {icon = "fas fa-check-double", title = "Buy", value = "buy"}, + {icon = "fas fa-eye", title = "Stop Viewing", value = "stop"} + } + + ESX.OpenContext("right", elements3, function(menu3,element3) + if element3.value == "buy" then + local plate = exports['esx_vehicleshop']:GeneratePlate() + local vehicle = GetVehiclePedIsIn(playerPed, false) + local props = ESX.Game.GetVehicleProperties(vehicle) + props.plate = plate + + ESX.TriggerServerCallback('esx_boat:buyBoat', function(bought) + if bought then + ESX.ShowNotification(TranslateCap('boat_shop_bought', element.name, ESX.Math.GroupDigits(element.price))) + + DeleteSpawnedVehicles() + isInShopMenu = false + ESX.CloseContext() + + CurrentAction = 'boat_shop' + CurrentActionMsg = TranslateCap('boat_shop_open') + + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + SetEntityCoords(playerPed, shop.Outside.x, shop.Outside.y, shop.Outside.z) + else + ESX.ShowNotification(TranslateCap('boat_shop_nomoney')) + ESX.CloseContext() + end + end, props) + elseif element3.value == "stop" then + isInShopMenu = false + DeleteSpawnedVehicles() + + CurrentAction = 'boat_shop' + CurrentActionMsg = TranslateCap('boat_shop_open') + + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + SetEntityCoords(playerPed, shop.Outside.x, shop.Outside.y, shop.Outside.z) + ESX.CloseContext() + end + end) + end) + end + end, function(menu) + isInShopMenu = false + CurrentAction = 'boat_shop' + CurrentActionMsg = TranslateCap('boat_shop_open') + end) + end, function(menu) + isInShopMenu = false CurrentAction = 'boat_shop' CurrentActionMsg = TranslateCap('boat_shop_open') - - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - SetEntityCoords(playerPed, shop.Outside.x, shop.Outside.y, shop.Outside.z) - end, function (data, menu) - DeleteSpawnedVehicles() - - ESX.Game.SpawnLocalVehicle(data.current.model, shop.Inside, shop.Inside.w, function (vehicle) - table.insert(spawnedVehicles, vehicle) - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - - if data.current.props then - ESX.Game.SetVehicleProperties(vehicle, data.current.props) - end - end) - end) - - -- spawn first vehicle - DeleteSpawnedVehicles() - - ESX.Game.SpawnLocalVehicle(Config.Vehicles[1].model, shop.Inside, shop.Inside.w, function (vehicle) - table.insert(spawnedVehicles, vehicle) - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - - if Config.Vehicles[1].props then - ESX.Game.SetVehicleProperties(vehicle, Config.Vehicles[1].props) - end end) end @@ -105,24 +104,22 @@ function OpenBoatGarage(garage) ESX.ShowNotification(TranslateCap('garage_noboats')) else -- get all available boats - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-ship", title = TranslateCap('garage')} + } for i=1, #ownedBoats, 1 do ownedBoats[i] = json.decode(ownedBoats[i]) - table.insert(elements, { - label = getVehicleLabelFromHash(ownedBoats[i].model), + elements[#elements+1] = { + icon = "fas fa-ship", + title = getVehicleLabelFromHash(ownedBoats[i].model), vehicleProps = ownedBoats[i] - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'boat_garage', { - title = TranslateCap('garage'), - align = 'top-left', - elements = elements - }, function (data, menu) - -- make sure the spawn point isn't blocked + ESX.OpenContext("right", elements, function(menu,element) local playerPed = PlayerPedId() - local vehicleProps = data.current.vehicleProps + local vehicleProps = element.vehicleProps if ESX.Game.IsSpawnPointClear(garage.SpawnPoint, 4.0) then TriggerServerEvent('esx_boat:takeOutVehicle', vehicleProps.plate) @@ -133,13 +130,11 @@ function OpenBoatGarage(garage) ESX.Game.SetVehicleProperties(vehicle, vehicleProps) end) - menu.close() + ESX.CloseContext() else ESX.ShowNotification(TranslateCap('garage_blocked')) end - end, function (data, menu) - menu.close() - + end, function(menu) CurrentAction = 'garage_out' CurrentActionMsg = TranslateCap('garage_open') end) @@ -148,33 +143,36 @@ function OpenBoatGarage(garage) end function OpenLicenceMenu(shop) - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'boat_license', { - title = TranslateCap('license_menu'), - align = 'top-left', - elements = { - {label = TranslateCap('license_buy_no'), value = 'no'}, - {label = TranslateCap('license_buy_yes', ESX.Math.GroupDigits(Config.LicensePrice)), value = 'yes'} - }}, function (data, menu) - if data.current.value == 'yes' then + local elements = { + {unselectable = true, icon = "fas fa-ship", title = TranslateCap('license_menu')}, + {icon = "fas fa-ship", title = "Purchase Boat License"} + } + + ESX.OpenContext("right", elements, function(menu,element) + local elements2 = { + {unselectable = true, icon = "fas fa-ship", title = element.title}, + {icon = "fas fa-check-double", title = TranslateCap('license_buy_yes'), val = "yes"}, + {icon = "fas fa-window-close", title = TranslateCap('license_buy_no'), val = "no"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) ESX.TriggerServerCallback('esx_boat:buyBoatLicense', function (boughtLicense) if boughtLicense then ESX.ShowNotification(TranslateCap('license_bought', ESX.Math.GroupDigits(Config.LicensePrice))) - menu.close() + ESX.CloseContext() OpenBoatShop(shop) -- parse current shop else ESX.ShowNotification(TranslateCap('license_nomoney')) end end) - else - CurrentAction = 'boat_shop' + end, function(menu) + CurrentAction = 'boat_shop' CurrentActionMsg = TranslateCap('boat_shop_open') - menu.close() - end - end, function (data, menu) - CurrentAction = 'boat_shop' + end) + end, function(menu) + CurrentAction = 'boat_shop' CurrentActionMsg = TranslateCap('boat_shop_open') - menu.close() end) end From 649ca301a6cf32e8a0fcc97f93396be464f1b2f5 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 20:12:13 +0800 Subject: [PATCH 20/83] complete context implementation --- [esx_addons]/esx_bankerjob/client/main.lua | 108 +++++++++++++-------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/[esx_addons]/esx_bankerjob/client/main.lua b/[esx_addons]/esx_bankerjob/client/main.lua index 8097c310..a4d8a732 100644 --- a/[esx_addons]/esx_bankerjob/client/main.lua +++ b/[esx_addons]/esx_bankerjob/client/main.lua @@ -72,40 +72,54 @@ function OpenCustomersMenu() ESX.OpenContext("right", elements2, function(menu2,element2) local customer = element.data if element2.value == "deposit" then - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'customer_deposit_amount', { - title = TranslateCap('amount') - }, function(data2, menu2) - local amount = tonumber(data2.value) + local elements = { + {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('amount')}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = "Amount to bill.."}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } - if amount == nil then - ESX.ShowNotification(TranslateCap('invalid_amount')) - else - menu2.close() - TriggerServerEvent('esx_bankerjob:customerDeposit', customer.source, amount) - ESX.ShowNotification("You have deposited $"..amount.." into "..element.title.."s account.") - OpenCustomersMenu() + ESX.OpenContext("right", elements, function(menu,element) + if element.val == "confirm" then + local amount = tonumber(menu.eles[2].inputValue) + + if amount == nil then + ESX.ShowNotification(TranslateCap('invalid_amount')) + else + ESX.CloseContext() + TriggerServerEvent('esx_bankerjob:customerDeposit', customer.source, amount) + ESX.ShowNotification("You have deposited $"..amount.." into "..element.title.."s account.") + OpenCustomersMenu() + end end - end, function(data2, menu2) - menu2.close() - OpenCustomersMenu() + end, function(menu) + CurrentAction = 'bank_actions_menu' + CurrentActionMsg = TranslateCap('press_input_context_to_open_menu') + CurrentActionData = {} end) elseif element2.value == "withdraw" then - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'customer_withdraw_amount', { - title = TranslateCap('amount') - }, function(data2, menu2) - local amount = tonumber(data2.value) + local elements = { + {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('amount')}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = "Amount to bill.."}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } - if amount == nil then - ESX.ShowNotification(TranslateCap('invalid_amount')) - else - menu2.close() - TriggerServerEvent('esx_bankerjob:customerWithdraw', customer.source, amount) - ESX.ShowNotification("You have withdrawn $"..amount.." from "..element.title.."s account.") - OpenCustomersMenu() + ESX.OpenContext("right", elements, function(menu,element) + if element.val == "confirm" then + local amount = tonumber(menu.eles[2].inputValue) + + if amount == nil then + ESX.ShowNotification(TranslateCap('invalid_amount')) + else + ESX.CloseContext() + TriggerServerEvent('esx_bankerjob:customerWithdraw', customer.source, amount) + ESX.ShowNotification("You have withdrawn $"..amount.." from "..element.title.."s account.") + OpenCustomersMenu() + end end - end, function(data2, menu2) - menu2.close() - OpenCustomersMenu() + end, function(menu) + CurrentAction = 'bank_actions_menu' + CurrentActionMsg = TranslateCap('press_input_context_to_open_menu') + CurrentActionData = {} end) end end, function(menu) @@ -122,26 +136,34 @@ function OpenCustomersMenu() end function CreateBillingDialog() - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'billing', { - title = TranslateCap('bill_amount') - }, function(data, menu) - local amount = tonumber(data.value) + local elements = { + {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('bill_amount')}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = "Amount to bill.."}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } - if amount == nil then - ESX.ShowNotification(TranslateCap('invalid_amount')) - else - menu.close() + ESX.OpenContext("right", elements, function(menu,element) + if element.val == "confirm" then + local amount = tonumber(menu.eles[2].inputValue) - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - - if closestPlayer == -1 or closestDistance > 5.0 then - ESX.ShowNotification(TranslateCap('no_player_nearby')) + if amount == nil then + ESX.ShowNotification(TranslateCap('invalid_amount')) else - TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_banker', 'Bank', amount) + ESX.CloseContext() + + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + + if closestPlayer == -1 or closestDistance > 5.0 then + ESX.ShowNotification(TranslateCap('no_player_nearby')) + else + TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_banker', 'Bank', amount) + end end end - end, function(data, menu) - menu.close() + end, function(menu) + CurrentAction = 'bank_actions_menu' + CurrentActionMsg = TranslateCap('press_input_context_to_open_menu') + CurrentActionData = {} end) end From 847a0d73b9f33bedd7855930584f77a7709caf29 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 20:14:08 +0800 Subject: [PATCH 21/83] update hasExitedMarker (context) --- [esx_addons]/esx_boat/client/marker.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx_addons]/esx_boat/client/marker.lua b/[esx_addons]/esx_boat/client/marker.lua index 81038fb3..94ff319e 100644 --- a/[esx_addons]/esx_boat/client/marker.lua +++ b/[esx_addons]/esx_boat/client/marker.lua @@ -68,7 +68,7 @@ end) AddEventHandler('esx_boat:hasExitedMarker', function() if not isInShopMenu then - ESX.UI.Menu.CloseAll() + ESX.CloseContext() end CurrentAction = nil From 90fd8dd22ec48424f71a94975a1a6d0a0c580037 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 20:17:59 +0800 Subject: [PATCH 22/83] complete context implementation --- [esx_addons]/esx_clotheshop/client/main.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/[esx_addons]/esx_clotheshop/client/main.lua b/[esx_addons]/esx_clotheshop/client/main.lua index 4cff1f30..6c6d5d40 100644 --- a/[esx_addons]/esx_clotheshop/client/main.lua +++ b/[esx_addons]/esx_clotheshop/client/main.lua @@ -33,18 +33,18 @@ function OpenShopMenu() ESX.OpenContext("right", elements2, function(menu2,element2) if element2.value == "yes" then - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'outfit_name', { - title = TranslateCap('name_outfit') - }, function(data3, menu3) - menu3.close() + local elements3 = { + {unselectable = true, icon = "fas fa-shirt", title = TranslateCap('name_outfit')}, + {title = "Outfit Name", input = true, inputType = "text", inputPlaceholder = "Outfit name in wardrobe.."}, + {icon = "fas fa-check-circle", title = "Confirm", value = "confirm"} + } + ESX.OpenContext("right", elements3, function(menu3,element3) TriggerEvent('skinchanger:getSkin', function(skin) ESX.CloseContext() - TriggerServerEvent('esx_clotheshop:saveOutfit', data3.value, skin) + TriggerServerEvent('esx_clotheshop:saveOutfit', menu3.eles[2].inputValue, skin) ESX.ShowNotification(TranslateCap('saved_outfit')) end) - end, function(data3, menu3) - menu3.close() end) elseif element2.value == "no" then ESX.CloseContext() From 724ac6920ccc3e35b56bffbfe0aee71d7d6b653d Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 20:21:08 +0800 Subject: [PATCH 23/83] context implementation --- [esx_addons]/esx_jobs/client/main.lua | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/[esx_addons]/esx_jobs/client/main.lua b/[esx_addons]/esx_jobs/client/main.lua index ecdc9baf..721742de 100644 --- a/[esx_addons]/esx_jobs/client/main.lua +++ b/[esx_addons]/esx_jobs/client/main.lua @@ -27,17 +27,14 @@ RegisterNetEvent('esx:setJob',function(job) end) function OpenMenu() - ESX.UI.Menu.CloseAll() + local elements = { + {unselectable = true, icon = "fas fa-shirt", title = TranslateCap('cloakroom')}, + {icon = "fas fa-shirt", title = TranslateCap('job_wear'), value = "job_wear"}, + {icon = "fas fa-shirt", title = TranslateCap('citizen_wear'), value = "citizen_wear"}, + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'cloakroom', - { - title = TranslateCap('cloakroom'), - elements = { - {label = TranslateCap('job_wear'), value = 'job_wear'}, - {label = TranslateCap('citizen_wear'), value = 'citizen_wear'} - } - }, function(data, menu) - if data.current.value == 'citizen_wear' then + ESX.OpenContext("right", elements, function(menu,element) + if element.value == "citizen_wear" then onDuty = false ESX.ShowNotification(TranslateCap('offduty'),"success") ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) @@ -49,7 +46,7 @@ function OpenMenu() end) end) end) - elseif data.current.value == 'job_wear' then + elseif element.value == "job_wear" then onDuty = true ESX.ShowNotification(TranslateCap('onduty'), "success") ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) @@ -68,10 +65,6 @@ function OpenMenu() end end) end - - menu.close() - end, function(data, menu) - menu.close() end) end From 131a9fcd8c37df50a6efc1963db8da96b1010747 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 20:55:09 +0800 Subject: [PATCH 24/83] context implementation --- [esx_addons]/esx_mechanicjob/client/main.lua | 312 ++++++++----------- 1 file changed, 136 insertions(+), 176 deletions(-) diff --git a/[esx_addons]/esx_mechanicjob/client/main.lua b/[esx_addons]/esx_mechanicjob/client/main.lua index 723fe067..bb5b9d66 100644 --- a/[esx_addons]/esx_mechanicjob/client/main.lua +++ b/[esx_addons]/esx_mechanicjob/client/main.lua @@ -54,44 +54,41 @@ end function OpenMechanicActionsMenu() local elements = { - {label = TranslateCap('vehicle_list'), value = 'vehicle_list'}, - {label = TranslateCap('work_wear'), value = 'cloakroom'}, - {label = TranslateCap('civ_wear'), value = 'cloakroom2'}, - {label = TranslateCap('deposit_stock'), value = 'put_stock'}, - {label = TranslateCap('withdraw_stock'), value = 'get_stock'} + {unselectable = true, icon = "fas fa-gear", title = TranslateCap('mechanic')}, + {icon = "fas fa-car", title = TranslateCap('vehicle_list'), value = 'vehicle_list'}, + {icon = "fas fa-shirt", title = TranslateCap('work_wear'), value = 'cloakroom'}, + {icon = "fas fa-shirt", title = TranslateCap('civ_wear'), value = 'cloakroom2'}, + {icon = "fas fa-box", title = TranslateCap('deposit_stock'), value = 'put_stock'}, + {icon = "fas fa-box", title = TranslateCap('withdraw_stock'), value = 'get_stock'} } if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name == 'boss' then - table.insert(elements, {label = TranslateCap('boss_actions'), value = 'boss_actions'}) + elements[#elements+1] = { + icon = 'fas fa-boss', + title = TranslateCap('boss_actions'), + value = 'boss_actions' + } end - ESX.UI.Menu.CloseAll() - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'mechanic_actions', { - title = TranslateCap('mechanic'), - align = 'top-left', - elements = elements - }, function(data, menu) - if data.current.value == 'vehicle_list' then + ESX.OpenContext("right", elements, function(menu,element) + if element.value == 'vehicle_list' then if Config.EnableSocietyOwnedVehicles then - - local elements = {} + local elements2 = { + {unselectable = true, icon = "fas fa-car", title = TranslateCap('service_vehicle')} + } ESX.TriggerServerCallback('esx_society:getVehiclesInGarage', function(vehicles) for i=1, #vehicles, 1 do - table.insert(elements, { - label = GetDisplayNameFromVehicleModel(vehicles[i].model) .. ' [' .. vehicles[i].plate .. ']', + elements2[#elements2+1] = { + icon = 'fas fa-car', + title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. ' [' .. vehicles[i].plate .. ']', value = vehicles[i] - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_spawner', { - title = TranslateCap('service_vehicle'), - align = 'top-left', - elements = elements - }, function(data, menu) - menu.close() - local vehicleProps = data.current.value + ESX.OpenContext("right", elements2, function(menu2,element2) + ESX.CloseContext() + local vehicleProps = element.value ESX.Game.SpawnVehicle(vehicleProps.model, Config.Zones.VehicleSpawnPoint.Pos, 270.0, function(vehicle) ESX.Game.SetVehicleProperties(vehicle, vehicleProps) @@ -100,38 +97,35 @@ function OpenMechanicActionsMenu() end) TriggerServerEvent('esx_society:removeVehicleFromGarage', 'mechanic', vehicleProps) - end, function(data, menu) - menu.close() end) end, 'mechanic') - else - - local elements = { - {label = TranslateCap('flat_bed'), value = 'flatbed'}, - {label = TranslateCap('tow_truck'), value = 'towtruck2'} + local elements2 = { + {unselectable = true, icon = "fas fa-car", title = TranslateCap('service_vehicle')}, + {icon = "fas fa-truck", title = TranslateCap('flat_bed'), value = 'flatbed'}, + {icon = "fas fa-truck", title = TranslateCap('tow_truck'), value = 'towtruck2'} } if Config.EnablePlayerManagement and ESX.PlayerData.job and (ESX.PlayerData.job.grade_name == 'boss' or ESX.PlayerData.job.grade_name == 'chief' or ESX.PlayerData.job.grade_name == 'experimente') then - table.insert(elements, {label = 'SlamVan', value = 'slamvan3'}) + elements2[#elements2+1] = { + icon = 'fas fa-truck', + title = 'Slamvan', + value = 'slamvan3' + } end - ESX.UI.Menu.CloseAll() - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'spawn_vehicle', { - title = TranslateCap('service_vehicle'), - align = 'top-left', - elements = elements - }, function(data, menu) + ESX.OpenContext("right", elements2, function(menu2,element2) if Config.MaxInService == -1 then - ESX.Game.SpawnVehicle(data.current.value, Config.Zones.VehicleSpawnPoint.Pos, 90.0, function(vehicle) + ESX.CloseContext() + ESX.Game.SpawnVehicle(element2.value, Config.Zones.VehicleSpawnPoint.Pos, 90.0, function(vehicle) local playerPed = PlayerPedId() TaskWarpPedIntoVehicle(playerPed, vehicle, -1) end) else ESX.TriggerServerCallback('esx_service:enableService', function(canTakeService, maxInService, inServiceCount) if canTakeService then - ESX.Game.SpawnVehicle(data.current.value, Config.Zones.VehicleSpawnPoint.Pos, 90.0, function(vehicle) + ESX.CloseContext() + ESX.Game.SpawnVehicle(element2.value, Config.Zones.VehicleSpawnPoint.Pos, 90.0, function(vehicle) local playerPed = PlayerPedId() TaskWarpPedIntoVehicle(playerPed, vehicle, -1) end) @@ -140,16 +134,10 @@ function OpenMechanicActionsMenu() end end, 'mechanic') end - - menu.close() - end, function(data, menu) - menu.close() - OpenMechanicActionsMenu() end) - end - elseif data.current.value == 'cloakroom' then - menu.close() + elseif element.value == 'cloakroom' then + ESX.CloseContext() ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) if skin.sex == 0 then TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_male) @@ -157,27 +145,24 @@ function OpenMechanicActionsMenu() TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_female) end end) - elseif data.current.value == 'cloakroom2' then - menu.close() + elseif element.value == 'cloakroom2' then + ESX.CloseContext() ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) TriggerEvent('skinchanger:loadSkin', skin) end) - - elseif Config.OxInventory and (data.current.value == 'put_stock' or data.current.value == 'get_stock') then + elseif Config.OxInventory and (element.value == 'put_stock' or element.value == 'get_stock') then exports.ox_inventory:openInventory('stash', 'society_mechanic') - return ESX.UI.Menu.CloseAll() - elseif data.current.value == 'put_stock' then + return ESX.CloseContext() + elseif element.value == 'put_stock' then OpenPutStocksMenu() - elseif data.current.value == 'get_stock' then + elseif element.value == 'get_stock' then OpenGetStocksMenu() - elseif data.current.value == 'boss_actions' then + elseif element.value == 'boss_actions' then TriggerEvent('esx_society:openBossMenu', 'mechanic', function(data, menu) menu.close() end) end - end, function(data, menu) - menu.close() - + end, function(menu) CurrentAction = 'mechanic_actions_menu' CurrentActionMsg = TranslateCap('open_actions') CurrentActionData = {} @@ -187,29 +172,21 @@ end function OpenMechanicHarvestMenu() if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name ~= 'recrue' then local elements = { - {label = TranslateCap('gas_can'), value = 'gaz_bottle'}, - {label = TranslateCap('repair_tools'), value = 'fix_tool'}, - {label = TranslateCap('body_work_tools'), value = 'caro_tool'} + {unselectable = true, icon = "fas fa-gear", title = "Mechanic Harvest Menu"}, + {icon = "fas fa-gear", title = TranslateCap('gas_can'), value = 'gaz_bottle'}, + {icon = "fas fa-gear", title = TranslateCap('repair_tools'), value = 'fix_tool'}, + {icon = "fas fa-gear", title = TranslateCap('body_work_tools'), value = 'caro_tool'} } - ESX.UI.Menu.CloseAll() - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'mechanic_harvest', { - title = TranslateCap('harvest'), - align = 'top-left', - elements = elements - }, function(data, menu) - menu.close() - - if data.current.value == 'gaz_bottle' then + ESX.OpenContext("right", elements, function(menu,element) + if element.value == 'gaz_bottle' then TriggerServerEvent('esx_mechanicjob:startHarvest') - elseif data.current.value == 'fix_tool' then + elseif element.value == 'fix_tool' then TriggerServerEvent('esx_mechanicjob:startHarvest2') - elseif data.current.value == 'caro_tool' then + elseif element.value == 'caro_tool' then TriggerServerEvent('esx_mechanicjob:startHarvest3') end - end, function(data, menu) - menu.close() + end, function(menu) CurrentAction = 'mechanic_harvest_menu' CurrentActionMsg = TranslateCap('harvest_menu') CurrentActionData = {} @@ -222,30 +199,21 @@ end function OpenMechanicCraftMenu() if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name ~= 'recrue' then local elements = { - {label = TranslateCap('blowtorch'), value = 'blow_pipe'}, - {label = TranslateCap('repair_kit'), value = 'fix_kit'}, - {label = TranslateCap('body_kit'), value = 'caro_kit'} + {unselectable = true, icon = "fas fa-gear", title = "Mechanic Craft Menu"}, + {icon = "fas fa-gear", title = TranslateCap('blowtorch'), value = 'blow_pipe'}, + {icon = "fas fa-gear", title = TranslateCap('repair_kit'), value = 'fix_kit'}, + {icon = "fas fa-gear", title = TranslateCap('body_kit'), value = 'caro_kit'} } - ESX.UI.Menu.CloseAll() - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'mechanic_craft', { - title = TranslateCap('craft'), - align = 'top-left', - elements = elements - }, function(data, menu) - menu.close() - - if data.current.value == 'blow_pipe' then + ESX.OpenContext("right", elements, function(menu,element) + if element.value == 'blow_pipe' then TriggerServerEvent('esx_mechanicjob:startCraft') - elseif data.current.value == 'fix_kit' then + elseif element.value == 'fix_kit' then TriggerServerEvent('esx_mechanicjob:startCraft2') - elseif data.current.value == 'caro_kit' then + elseif element.value == 'caro_kit' then TriggerServerEvent('esx_mechanicjob:startCraft3') end - end, function(data, menu) - menu.close() - + end, function(menu) CurrentAction = 'mechanic_craft_menu' CurrentActionMsg = TranslateCap('craft_menu') CurrentActionData = {} @@ -256,27 +224,29 @@ function OpenMechanicCraftMenu() end function OpenMobileMechanicActionsMenu() - ESX.UI.Menu.CloseAll() + local elements = { + {unselectable = true, icon = "fas fa-gear", title = TranslateCap('mechanic')}, + {icon = "fas fa-gear", title = TranslateCap('billing'), value = 'billing'}, + {icon = "fas fa-gear", title = TranslateCap('hijack'), value = 'hijack_vehicle'}, + {icon = "fas fa-gear", title = TranslateCap('repair'), value = 'fix_vehicle'}, + {icon = "fas fa-gear", title = TranslateCap('clean'), value = 'clean_vehicle'}, + {icon = "fas fa-gear", title = TranslateCap('imp_veh'), value = 'del_vehicle'}, + {icon = "fas fa-gear", title = TranslateCap('flat_bed'), value = 'dep_vehicle'}, + {icon = "fas fa-gear", title = TranslateCap('place_objects'), value = 'object_spawner'} + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'mobile_mechanic_actions', { - title = TranslateCap('mechanic'), - align = 'top-left', - elements = { - {label = TranslateCap('billing'), value = 'billing'}, - {label = TranslateCap('hijack'), value = 'hijack_vehicle'}, - {label = TranslateCap('repair'), value = 'fix_vehicle'}, - {label = TranslateCap('clean'), value = 'clean_vehicle'}, - {label = TranslateCap('imp_veh'), value = 'del_vehicle'}, - {label = TranslateCap('flat_bed'), value = 'dep_vehicle'}, - {label = TranslateCap('place_objects'), value = 'object_spawner'} - }}, function(data, menu) + ESX.OpenContext("right", elements, function(menu,element) if isBusy then return end - if data.current.value == 'billing' then - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'billing', { - title = TranslateCap('invoice_amount') - }, function(data, menu) - local amount = tonumber(data.value) + if element.value == "billing" then + local elements2 = { + {unselectable = true, icon = "fas fa-scroll", title = element.title}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = "Amount to bill.."}, + {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local amount = tonumber(menu2.eles[2].inputValue) if amount == nil or amount < 0 then ESX.ShowNotification(TranslateCap('amount_invalid'), "error") @@ -289,10 +259,8 @@ function OpenMobileMechanicActionsMenu() TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_mechanic', TranslateCap('mechanic'), amount) end end - end, function(data, menu) - menu.close() end) - elseif data.current.value == 'hijack_vehicle' then + elseif element.value == "hijack_vehicle" then local playerPed = PlayerPedId() local vehicle = ESX.Game.GetVehicleInDirection() local coords = GetEntityCoords(playerPed) @@ -318,7 +286,7 @@ function OpenMobileMechanicActionsMenu() else ESX.ShowNotification(TranslateCap('no_vehicle_nearby')) end - elseif data.current.value == 'fix_vehicle' then + elseif element.value == "fix_vehicle" then local playerPed = PlayerPedId() local vehicle = ESX.Game.GetVehicleInDirection() local coords = GetEntityCoords(playerPed) @@ -346,7 +314,7 @@ function OpenMobileMechanicActionsMenu() else ESX.ShowNotification(TranslateCap('no_vehicle_nearby')) end - elseif data.current.value == 'clean_vehicle' then + elseif element.value == "clean_vehicle" then local playerPed = PlayerPedId() local vehicle = ESX.Game.GetVehicleInDirection() local coords = GetEntityCoords(playerPed) @@ -371,7 +339,7 @@ function OpenMobileMechanicActionsMenu() else ESX.ShowNotification(TranslateCap('no_vehicle_nearby')) end - elseif data.current.value == 'del_vehicle' then + elseif element.value == "del_vehicle" then local playerPed = PlayerPedId() if IsPedSittingInAnyVehicle(playerPed) then @@ -393,7 +361,7 @@ function OpenMobileMechanicActionsMenu() ESX.ShowNotification(TranslateCap('must_near')) end end - elseif data.current.value == 'dep_vehicle' then + elseif element.value == "dep_vehicle" then local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, true) @@ -459,7 +427,7 @@ function OpenMobileMechanicActionsMenu() else ESX.ShowNotification(TranslateCap('imp_flatbed')) end - elseif data.current.value == 'object_spawner' then + elseif element.value == "object_spawner" then local playerPed = PlayerPedId() if IsPedSittingInAnyVehicle(playerPed) then @@ -467,14 +435,14 @@ function OpenMobileMechanicActionsMenu() return end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'mobile_mechanic_actions_spawn', { - title = TranslateCap('objects'), - align = 'top-left', - elements = { - {label = TranslateCap('roadcone'), value = 'prop_roadcone02a'}, - {label = TranslateCap('toolbox'), value = 'prop_toolchest_01'} - }}, function(data2, menu2) - local model = data2.current.value + local elements2 = { + {unselectable= true, icon = "fas fa-object", title = TranslateCap('objects')}, + {icon = "fas fa-object", title = TranslateCap('roadcone'), value = 'prop_roadcone02a'}, + {icon = "fas fa-object", title = TranslateCap('toolbox'), value = 'prop_toolchest_01'} + } + + ESX.OpenContext("right", elements2, function(menuObj,elementObj) + local model = elementObj.value local coords = GetEntityCoords(playerPed) local forward = GetEntityForwardVector(playerPed) local x, y, z = table.unpack(coords + forward * 1.0) @@ -489,100 +457,92 @@ function OpenMobileMechanicActionsMenu() SetEntityHeading(obj, GetEntityHeading(playerPed)) PlaceObjectOnGroundProperly(obj) end) - end, function(data2, menu2) - menu2.close() end) end - end, function(data, menu) - menu.close() end) end function OpenGetStocksMenu() ESX.TriggerServerCallback('esx_mechanicjob:getStockItems', function(items) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-box", title = TranslateCap('mechanic_stock')} + } for i=1, #items, 1 do - table.insert(elements, { - label = 'x' .. items[i].count .. ' ' .. items[i].label, + elements[#elements+1] = { + icon = 'fas fa-box', + title = 'x' .. items[i].count .. ' ' .. items[i].label, value = items[i].name - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'stocks_menu', { - title = TranslateCap('mechanic_stock'), - align = 'top-left', - elements = elements - }, function(data, menu) - local itemName = data.current.value + ESX.OpenContext("right", elements, function(menu,element) + local itemName = element.value - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_get_item_count', { - title = TranslateCap('quantity') - }, function(data2, menu2) - local count = tonumber(data2.value) + local elements2 = { + {unselectable = true, icon = "fas fa-box", title = element.title}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to deposit.."}, + {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local count = tonumber(menu2.eles[2].inputValue) if count == nil then ESX.ShowNotification(TranslateCap('invalid_quantity')) else - menu2.close() - menu.close() + ESX.CloseContext() TriggerServerEvent('esx_mechanicjob:getStockItem', itemName, count) Wait(1000) OpenGetStocksMenu() end - end, function(data2, menu2) - menu2.close() end) - end, function(data, menu) - menu.close() end) end) end function OpenPutStocksMenu() ESX.TriggerServerCallback('esx_mechanicjob:getPlayerInventory', function(inventory) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-box", title = TranslateCap('inventory')} + } for i=1, #inventory.items, 1 do local item = inventory.items[i] if item.count > 0 then - table.insert(elements, { - label = item.label .. ' x' .. item.count, + elements[#elements+1] = { + icon = 'fas fa-box', + title = item.label .. ' x' .. item.count, type = 'item_standard', value = item.name - }) + } end end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'stocks_menu', { - title = TranslateCap('inventory'), - align = 'top-left', - elements = elements - }, function(data, menu) - local itemName = data.current.value + ESX.OpenContext("right", elements, function(menu,element) + local itemName = element.value - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_put_item_count', { - title = TranslateCap('quantity') - }, function(data2, menu2) - local count = tonumber(data2.value) + local elements2 = { + {unselectable = true, icon = "fas fa-box", title = element.title}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to withdraw.."}, + {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local count = tonumber(menu2.eles[2].inputValue) if count == nil then ESX.ShowNotification(TranslateCap('invalid_quantity')) else - menu2.close() - menu.close() + ESX.CloseContext() TriggerServerEvent('esx_mechanicjob:putStockItems', itemName, count) Wait(1000) OpenPutStocksMenu() end - end, function(data2, menu2) - menu2.close() end) - end, function(data, menu) - menu.close() end) end) end @@ -738,7 +698,7 @@ AddEventHandler('esx_mechanicjob:hasExitedMarker', function(zone) end CurrentAction = nil - ESX.UI.Menu.CloseAll() + ESX.CloseContext() end) AddEventHandler('esx_mechanicjob:hasEnteredEntityZone', function(entity) From 5b357be9dc00833aec1d9db85e3428570a6d600a Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 21:01:42 +0800 Subject: [PATCH 25/83] fix typo --- [esx_addons]/esx_mechanicjob/client/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/[esx_addons]/esx_mechanicjob/client/main.lua b/[esx_addons]/esx_mechanicjob/client/main.lua index bb5b9d66..bb085d7d 100644 --- a/[esx_addons]/esx_mechanicjob/client/main.lua +++ b/[esx_addons]/esx_mechanicjob/client/main.lua @@ -481,7 +481,7 @@ function OpenGetStocksMenu() local elements2 = { {unselectable = true, icon = "fas fa-box", title = element.title}, - {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to deposit.."}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to withdraw.."}, {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} } @@ -526,7 +526,7 @@ function OpenPutStocksMenu() local elements2 = { {unselectable = true, icon = "fas fa-box", title = element.title}, - {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to withdraw.."}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to deposit.."}, {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} } From e070b83afd683caffab9c09c451e7994af8c3a59 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 21:20:58 +0800 Subject: [PATCH 26/83] complete context implementation --- [esx_addons]/esx_taxijob/client/main.lua | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/[esx_addons]/esx_taxijob/client/main.lua b/[esx_addons]/esx_taxijob/client/main.lua index e1161b45..7c363578 100644 --- a/[esx_addons]/esx_taxijob/client/main.lua +++ b/[esx_addons]/esx_taxijob/client/main.lua @@ -322,24 +322,24 @@ function OpenGetStocksMenu() ESX.OpenContext("right", elements, function(menu,element) local itemName = element.value - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_get_item_count', { - title = TranslateCap('quantity') - }, function(data2, menu2) - local count = tonumber(data2.value) + local elements2 = { + {unselectable = true, icon = "fas fa-box", title = element.title}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to withdraw.."}, + {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local count = tonumber(menu2.eles[2].inputValue) if count == nil then ESX.ShowNotification(TranslateCap('quantity_invalid')) else - menu2.close() ESX.CloseContext() - - -- todo: refresh on callback TriggerServerEvent('esx_taxijob:getStockItem', itemName, count) + Wait(1000) OpenGetStocksMenu() end - end, function(data2, menu2) - menu2.close() end) end) end, function(menu) @@ -370,24 +370,24 @@ function OpenPutStocksMenu() ESX.OpenContext("right", elements, function(menu,element) local itemName = element.value - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_put_item_count', { - title = TranslateCap('quantity') - }, function(data2, menu2) - local count = tonumber(data2.value) + local elements2 = { + {unselectable = true, icon = "fas fa-box", title = element.title}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to deposit.."}, + {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local count = tonumber(menu2.eles[2].inputValue) if count == nil then ESX.ShowNotification(TranslateCap('quantity_invalid')) - else - menu2.close() + else ESX.CloseContext() - -- todo: refresh on callback TriggerServerEvent('esx_taxijob:putStockItems', itemName, count) Wait(1000) OpenPutStocksMenu() end - end, function(data2, menu2) - menu2.close() end) end) end, function(menu) From 6f4de63488fe3919f2f30be54ab24de769af1f2f Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 21:21:26 +0800 Subject: [PATCH 27/83] fix invalid quantity when depositing items into storage --- [esx_addons]/esx_taxijob/server/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx_addons]/esx_taxijob/server/main.lua b/[esx_addons]/esx_taxijob/server/main.lua index 2bd43059..42307181 100644 --- a/[esx_addons]/esx_taxijob/server/main.lua +++ b/[esx_addons]/esx_taxijob/server/main.lua @@ -104,7 +104,7 @@ AddEventHandler('esx_taxijob:putStockItems', function(itemName, count) TriggerEvent('esx_addoninventory:getSharedInventory', 'society_taxi', function(inventory) local item = inventory.getItem(itemName) - if item.count > 0 then + if sourceItem.count >= count and count > 0 then xPlayer.removeInventoryItem(itemName, count) inventory.addItem(itemName, count) xPlayer.showNotification(TranslateCap('have_deposited', count, item.label)) From 3f54a18bc5fa538db5253e2e69e830a14daa959e Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Thu, 1 Dec 2022 21:36:16 +0800 Subject: [PATCH 28/83] forgot sourceItem --- [esx_addons]/esx_taxijob/server/main.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/[esx_addons]/esx_taxijob/server/main.lua b/[esx_addons]/esx_taxijob/server/main.lua index 42307181..9bfdc4f9 100644 --- a/[esx_addons]/esx_taxijob/server/main.lua +++ b/[esx_addons]/esx_taxijob/server/main.lua @@ -99,7 +99,8 @@ end) RegisterNetEvent('esx_taxijob:putStockItems') AddEventHandler('esx_taxijob:putStockItems', function(itemName, count) local xPlayer = ESX.GetPlayerFromId(source) - + local sourceItem = xPlayer.getInventoryItem(itemName) + if xPlayer.job.name == 'taxi' then TriggerEvent('esx_addoninventory:getSharedInventory', 'society_taxi', function(inventory) local item = inventory.getItem(itemName) From eb983f1206fa14f9e715f393e1d382d083db72c9 Mon Sep 17 00:00:00 2001 From: Benzo <102178921+Benzo00@users.noreply.github.com> Date: Sun, 4 Dec 2022 04:44:23 +0100 Subject: [PATCH 29/83] refactor(es_extended) removing getshared event --- [esx]/es_extended/client/common.lua | 6 ------ 1 file changed, 6 deletions(-) diff --git a/[esx]/es_extended/client/common.lua b/[esx]/es_extended/client/common.lua index c3fc1c36..26020ace 100644 --- a/[esx]/es_extended/client/common.lua +++ b/[esx]/es_extended/client/common.lua @@ -1,9 +1,3 @@ -AddEventHandler('esx:getSharedObject', function(cb) - local Invoke = GetInvokingResource() - print(('[^3WARNING^7] ^5%s^7 used ^5esx:getSharedObject^7, this method is deprecated and should not be used! Refer to ^5https://docs.esx-framework.org/tutorials/sharedevent^7 for more info!'):format(Invoke)) - cb(ESX) -end) - exports('getSharedObject', function() return ESX end) From e3b3314706c9034cc4b084e7993df764d1ab922c Mon Sep 17 00:00:00 2001 From: Benzo <102178921+Benzo00@users.noreply.github.com> Date: Sun, 4 Dec 2022 04:44:43 +0100 Subject: [PATCH 30/83] refactor(es_extended) removing getshared event --- [esx]/es_extended/server/common.lua | 5 ----- 1 file changed, 5 deletions(-) diff --git a/[esx]/es_extended/server/common.lua b/[esx]/es_extended/server/common.lua index 199491b8..0d595045 100644 --- a/[esx]/es_extended/server/common.lua +++ b/[esx]/es_extended/server/common.lua @@ -14,11 +14,6 @@ Core.Pickups = {} Core.PickupId = 0 Core.PlayerFunctionOverrides = {} -AddEventHandler('esx:getSharedObject', function(cb) - local Invoke = GetInvokingResource() - print(('[^3WARNING^7] ^5%s^7 used ^5esx:getSharedObject^7, this method is deprecated and should not be used, On 30/11/2022 esx:getSharedObject will come to EOL and be fully removed! Refer to ^5https://docs.esx-framework.org/tutorials/sharedevent^7 for more info!'):format(Invoke)) - cb(ESX) -end) exports('getSharedObject', function() return ESX From 9f072f99cf50fa140948bbd5891ae8c4be3b3926 Mon Sep 17 00:00:00 2001 From: TheFantomas <117121911+TheFantomas@users.noreply.github.com> Date: Sun, 4 Dec 2022 12:16:28 +0100 Subject: [PATCH 31/83] Update cs.lua and dont translate some things --- [esx]/es_extended/locales/cs.lua | 545 +++++++++++++++++++------------ 1 file changed, 338 insertions(+), 207 deletions(-) diff --git a/[esx]/es_extended/locales/cs.lua b/[esx]/es_extended/locales/cs.lua index b338d3fa..7186ef8b 100644 --- a/[esx]/es_extended/locales/cs.lua +++ b/[esx]/es_extended/locales/cs.lua @@ -1,228 +1,359 @@ Locales['cs'] = { -- Inventory - ['inventory'] = 'inventář %s / %s', - ['use'] = 'použít', - ['give'] = 'dát', - ['remove'] = 'zahodit', - ['return'] = 'zpět', - ['give_to'] = 'dát', - ['amount'] = 'množství', - ['giveammo'] = 'dát munici', - ['amountammo'] = 'množství munice', - ['noammo'] = 'nemáte dostatek munice!', - ['gave_item'] = 'dali jste %sx %s %s', - ['received_item'] = 'obdrželi jste %sx %s od %s', - ['gave_weapon'] = 'dal jsi %s hráči %s', - ['gave_weapon_ammo'] = 'dal jsi ~o~%sx %s za %s to %s', - ['gave_weapon_withammo'] = 'dal jwi %s s ~o~%sx %s to %s', - ['gave_weapon_hasalready'] = '%s již má %s', - ['gave_weapon_noweapon'] = '%s nemá tuhle zbraň', - ['received_weapon'] = 'obdrzel jsi %s od %s', - ['received_weapon_ammo'] = 'obdrzel jsi ~o~%sx %s za tvůj %s od %s', - ['received_weapon_withammo'] = 'obdzel jsi %s s ~o~%sx %s od %s', - ['received_weapon_hasalready'] = '%s se pokusil ti dat %s, ale jiz tento predmet jednou mas', - ['received_weapon_noweapon'] = '%s se pokusil ti dat naboje pro %s, ale tuhle zbran nemas', - ['gave_account_money'] = 'dali jste $%s (%s) %s', - ['received_account_money'] = 'obdrželi jste $%s (%s) od %s', - ['amount_invalid'] = 'neplatné množství', - ['players_nearby'] = 'žádní hráči poblíž', - ['ex_inv_lim'] = 'akce není možná, překročen limit inventáře pro %s', - ['imp_invalid_quantity'] = 'akce není možná, neplatný počet', - ['imp_invalid_amount'] = 'akce není možná, neplatné množství', - ['threw_standard'] = 'vyhodil jsi %sx %s', - ['threw_account'] = 'vyhodil jsi $%s %s', - ['threw_weapon'] = 'vzhodil jsi %s', - ['threw_weapon_ammo'] = 'vyhodil jsi %s s ~o~%sx %s', - ['threw_weapon_already'] = 'jiz stejnou zbraan mas', - ['threw_cannot_pickup'] = 'tohle nemuzes sebrat, protoze tvuj inventar je plny', - ['threw_pickup_prompt'] = 'stiskni E po zvednuti', + ['inventory'] = 'Inventář ( Váha %s / %s )', + ['use'] = 'Použít', + ['give'] = 'Darovat', + ['remove'] = 'Odhodit', + ['return'] = 'Vrátit', + ['give_to'] = 'Darováno', + ['amount'] = 'Počet', + ['giveammo'] = 'Podat náboje', + ['amountammo'] = 'Počet nábojů', + ['noammo'] = 'Nedostatek!', + ['gave_item'] = 'Daroval %sx %s pro %s', + ['received_item'] = 'Získáno %sx %s od %s', + ['gave_weapon'] = 'Předání %s pro %s', + ['gave_weapon_ammo'] = 'Darování ~o~%sx %s do %s pro %s', + ['gave_weapon_withammo'] = 'Darování %s s ~o~%sx %s pro %s', + ['gave_weapon_hasalready'] = '%s již vlastní %s', + ['gave_weapon_noweapon'] = '%s nemá tuto zbraň', + ['received_weapon'] = 'Obdrženo %s od %s', + ['received_weapon_ammo'] = 'Obdrženo ~o~%sx %s pro zbraň %s od %s', + ['received_weapon_withammo'] = 'Obdrženo %s s ~o~%sx %s od %s', + ['received_weapon_hasalready'] = '%s se snažil darovat %s, ale již tuto zbraň máš', + ['received_weapon_noweapon'] = '%s se snažil ti dát náboje %s, ale nemáš potřebnou zbrań', + ['gave_account_money'] = 'Darováno $%s (%s) pro %s', + ['received_account_money'] = 'Získáno $%s (%s) od %s', + ['amount_invalid'] = 'Špatné množství', + ['players_nearby'] = 'Žádný hráč není poblíž', + ['ex_inv_lim'] = 'Nelze sebrat,protože máš plné kapsy %s', + ['imp_invalid_quantity'] = 'Neplatné množství', + ['imp_invalid_amount'] = 'Nelze provést, neplatné množství', + ['threw_standard'] = 'Zahozeno %sx %s', + ['threw_account'] = 'Zahozeno $%s %s', + ['threw_weapon'] = 'Zahozeno %s', + ['threw_weapon_ammo'] = 'Zahozeno %s s ~o~%sx %s', + ['threw_weapon_already'] = 'Již vlastníš tuto zbraň', + ['threw_cannot_pickup'] = 'Kapsy máš plné, nemůžeš sebrat!', + ['threw_pickup_prompt'] = 'Zmáčkni E pro sebrání!', -- Key mapping - ['keymap_showinventory'] = 'zobrazit inventar', + ['keymap_showinventory'] = 'Otevřít inventář', -- Salary related - ['received_salary'] = 'obdrželi jste výplatu: $%s', - ['received_help'] = 'obdrželi jste sociální dávku: $%s', - ['company_nomoney'] = 'společnost u které jste zaměstananí nemá peníze na váš plat', - ['received_paycheck'] = 'obdržena výplata', - ['bank'] = 'bankovní účet', - ['account_bank'] = 'banka', - ['account_black_money'] = 'spinave penize', - ['account_money'] = 'kapesne', + ['received_salary'] = 'Obdržel jsi: $%s', + ['received_help'] = 'Obdržel jsi svůj podíl: $%s', + ['company_nomoney'] = 'Firma kde pracujete je příliš chudá, aby vám zaplatila', + ['received_paycheck'] = 'Obdržena platba', + ['bank'] = 'Banka', + ['account_bank'] = 'V bance', + ['account_black_money'] = 'Špináve peníze', + ['account_money'] = 'V kapse', - ['act_imp'] = 'akce není možná', - ['in_vehicle'] = 'nemůže nic dát osobě ve vozidle', + ['act_imp'] = 'Nelze provést', + ['in_vehicle'] = 'Nelze provést, hráč je v autě', -- Commands - ['command_car'] = 'spawn an vehicle', - ['command_car_car'] = 'vehicle spawn name or hash', - ['command_cardel'] = 'delete vehicle in proximity', - ['command_cardel_radius'] = 'optional, delete every vehicle within the specified radius', - ['command_clear'] = 'clear chat', - ['command_clearall'] = 'clear chat for all players', - ['command_clearinventory'] = 'clear player inventory', - ['command_clearloadout'] = 'clear a player loadout', - ['command_giveaccountmoney'] = 'give account money', - ['command_giveaccountmoney_account'] = 'valid account name', - ['command_giveaccountmoney_amount'] = 'amount to add', - ['command_giveaccountmoney_invalid'] = 'invalid account name', - ['command_giveitem'] = 'give an item to a player', - ['command_giveitem_item'] = 'item name', - ['command_giveitem_count'] = 'item count', - ['command_giveweapon'] = 'give a weapon to a player', - ['command_giveweapon_weapon'] = 'weapon name', - ['command_giveweapon_ammo'] = 'ammo count', - ['command_giveweapon_hasalready'] = 'player already has that weapon', - ['command_giveweaponcomponent'] = 'give weapon component', - ['command_giveweaponcomponent_component'] = 'component name', - ['command_giveweaponcomponent_invalid'] = 'invalid weapon component', - ['command_giveweaponcomponent_hasalready'] = 'player already has that weapon component', - ['command_giveweaponcomponent_missingweapon'] = 'player does not have that weapon', - ['command_save'] = 'save a player to database', - ['command_saveall'] = 'save all players to database', - ['command_setaccountmoney'] = 'set account money for a player', - ['command_setaccountmoney_amount'] = 'amount of money to set', - ['command_setcoords'] = 'teleport to coordinates', - ['command_setcoords_x'] = 'x axis', - ['command_setcoords_y'] = 'y axis', - ['command_setcoords_z'] = 'z axis', - ['command_setjob'] = 'set job for a player', - ['command_setjob_job'] = 'job name', - ['command_setjob_grade'] = 'job grade', - ['command_setjob_invalid'] = 'the job, grade or both are invalid', - ['command_setgroup'] = 'set player group', - ['command_setgroup_group'] = 'group name', - ['commanderror_argumentmismatch'] = 'argument count mismatch (passed %s, wanted %s)', - ['commanderror_argumentmismatch_number'] = 'argument #%s type mismatch (passed string, wanted number)', - ['commanderror_invaliditem'] = 'invalid item name', - ['commanderror_invalidweapon'] = 'invalid weapon', - ['commanderror_console'] = 'that command can not be run from console', - ['commanderror_invalidcommand'] = '/%s is not an valid command!', - ['commanderror_invalidplayerid'] = 'there is no player online matching that server id', - ['commandgeneric_playerid'] = 'player id', - ['command_giveammo_noweapon_found'] = '%s does not have that weapon', - ['command_giveammo_weapon'] = 'Weapon name', - ['command_giveammo_ammo'] = 'Ammo Quantity', + ['command_bring'] = 'Přivolat si hráče k sobě', + ['command_car'] = 'Spawnout vozidlo', + ['command_car_car'] = 'Zadej jméno vozidla nebo spawnname', + ['command_cardel'] = 'Odstranění vozidla v okolí', + ['command_cardel_radius'] = 'Odstranění vozidla v určeném dosahu', + ['command_clear'] = 'Vymazat text v chatu', + ['command_clearall'] = 'Vymazat chet pro všechny hráče', + ['command_clearinventory'] = 'Vymazat všechny věci z invetáře hráče', + ['command_clearloadout'] = 'Vymazat všechny zbraně z inventáře hráče', + ['command_freeze'] = 'Zmrazit hráče', + ['command_unfreeze'] = 'Odmrazit hráče', + ['command_giveaccountmoney'] = 'Poslat peníze na účet ', + ['command_giveaccountmoney_account'] = 'Převést peníze na účet', + ['command_giveaccountmoney_amount'] = 'Částka k poslání', + ['command_giveaccountmoney_invalid'] = 'Neplátné jméno', + ['command_giveitem'] = 'Darovat věc hráči', + ['command_giveitem_item'] = 'Název věci', + ['command_giveitem_count'] = 'Množství', + ['command_giveweapon'] = 'Dát zbraň hráči', + ['command_giveweapon_weapon'] = 'Název zbraně', + ['command_giveweapon_ammo'] = 'Množství náboje', + ['command_giveweapon_hasalready'] = 'Hráč již má tuto zbraň', + ['command_giveweaponcomponent'] = 'Darovat přídavek na zbraň', + ['command_giveweaponcomponent_component'] = 'Název zbraně', + ['command_giveweaponcomponent_invalid'] = 'Špatné jméno přídavku', + ['command_giveweaponcomponent_hasalready'] = 'Hráč již má tento přídavek', + ['command_giveweaponcomponent_missingweapon'] = 'Hráč nemá tuto zbrań', + ['command_goto'] = 'Teleportování sebe k hráči', + ['command_kill'] = 'Zabití hráče', + ['command_save'] = 'Uložení dat hráče', + ['command_saveall'] = 'Uložení veškerých dat hráče', + ['command_setaccountmoney'] = 'Nastavení určeného počtu peněz', + ['command_setaccountmoney_amount'] = 'Počet peněz', + ['command_setcoords'] = 'Teleportování na určené souřadnice', + ['command_setcoords_x'] = 'Hodnota X', + ['command_setcoords_y'] = 'Hodnota Y', + ['command_setcoords_z'] = 'Hodnota Z', + ['command_setjob'] = 'Nastavit práci hráči', + ['command_setjob_job'] = 'Název práce', + ['command_setjob_grade'] = 'Pozice ve firmě', + ['command_setjob_invalid'] = 'Špatné zadání práce,hodnosti nebo i obou hodnot', + ['command_setgroup'] = 'Nastavení práv hráči', + ['command_setgroup_group'] = 'Název skupiny', + ['commanderror_argumentmismatch'] = 'Chybný počet hodnot (správně %s, potřebných %s)', + ['commanderror_argumentmismatch_number'] = 'Chybně zadaná hodnot #%s (správně, špatně)', + ['commanderror_invaliditem'] = 'Špatný předmět', + ['commanderror_invalidweapon'] = 'Špatná zbraň', + ['commanderror_console'] = 'příkaz nelze být zpracován v konzoli', + ['commanderror_invalidcommand'] = 'Špatný příakz - /%s', + ['commanderror_invalidplayerid'] = 'Hráč není dostupný', + ['commandgeneric_playerid'] = 'Id hráče', + ['command_giveammo_noweapon_found'] = '%s nemá tuto zbraň', + ['command_giveammo_weapon'] = 'Název zbraně', + ['command_giveammo_ammo'] = 'Počet nábojů', -- Locale settings - ['locale_digit_grouping_symbol'] = ' ', - ['locale_currency'] = '$%s', + ['locale_digit_grouping_symbol'] = ',', + ['locale_currency'] = '£%s', -- Weapons - ['weapon_knife'] = 'nuz', - ['weapon_nightstick'] = 'policejni obusek', - ['weapon_hammer'] = 'kladivo', - ['weapon_bat'] = 'basseballka', - ['weapon_golfclub'] = 'gollfova hul', - ['weapon_crowbar'] = 'pacidlo', - ['weapon_pistol'] = 'pistole', - ['weapon_combatpistol'] = 'utocna pistole', - ['weapon_appistol'] = 'ap pistole', - ['weapon_pistol50'] = 'pistole .50', - ['weapon_microsmg'] = 'micro smg', - ['weapon_smg'] = 'smg', - ['weapon_assaultsmg'] = 'utocne smg', - ['weapon_assaultrifle'] = 'utocna puska', - ['weapon_carbinerifle'] = 'carbine puska', - ['weapon_advancedrifle'] = 'pokrocily puska', - ['weapon_mg'] = 'mg', - ['weapon_combatmg'] = 'utocne mg', - ['weapon_pumpshotgun'] = 'pumpovana brokovnice', - ['weapon_sawnoffshotgun'] = 'upilovana brokovnice', - ['weapon_assaultshotgun'] = 'utocna brokovnice', - ['weapon_bullpupshotgun'] = 'bullpup brokovnice', - ['weapon_stungun'] = 'tazer', - ['weapon_sniperrifle'] = 'sniperka', - ['weapon_heavysniper'] = 'tezka sniperka', - ['weapon_grenadelauncher'] = 'launcher granatu', - ['weapon_rpg'] = 'raketomet', - ['weapon_minigun'] = 'minigun', - ['weapon_grenade'] = 'granat', - ['weapon_stickybomb'] = 'lepkava bomba', - ['weapon_smokegrenade'] = 'kourovy granat', - ['weapon_bzgas'] = 'bz gas', - ['weapon_molotov'] = 'molotov koktejl', - ['weapon_fireextinguisher'] = 'hasicak', - ['weapon_petrolcan'] = 'kanystr', - ['weapon_ball'] = 'koule', - ['weapon_snspistol'] = 'sns pistole', - ['weapon_bottle'] = 'lahev', - ['weapon_gusenberg'] = 'gusenberguv zametac', - ['weapon_specialcarbine'] = 'specialni karabina', - ['weapon_heavypistol'] = 'tezka pistole', - ['weapon_bullpuprifle'] = 'bullpup puska', - ['weapon_dagger'] = 'dyka', - ['weapon_vintagepistol'] = 'velmi stara pistole', - ['weapon_firework'] = 'ohnostroj', - ['weapon_musket'] = 'musketa', - ['weapon_heavyshotgun'] = 'tezka brokovnice', - ['weapon_marksmanrifle'] = 'puska strelce', - ['weapon_hominglauncher'] = 'navadeci launcher', - ['weapon_proxmine'] = 'mina na blizko', - ['weapon_snowball'] = 'snehova koule', - ['weapon_flaregun'] = 'svetlice', - ['weapon_combatpdw'] = 'utocne pdw', - ['weapon_marksmanpistol'] = 'pistole strelce', - ['weapon_knuckle'] = 'knuckledusters', - ['weapon_hatchet'] = 'sekerka', - ['weapon_railgun'] = 'vlakovy launcher', - ['weapon_machete'] = 'maceta', - ['weapon_machinepistol'] = 'kulomet', - ['weapon_switchblade'] = 'vystrelovaci nuz', - ['weapon_revolver'] = 'tezky revolver', - ['weapon_dbshotgun'] = 'dvouhlavnova brokovnice', - ['weapon_compactrifle'] = 'kompaktni puska', - ['weapon_autoshotgun'] = 'automaticka brokovnice', - ['weapon_battleaxe'] = 'bojova sekera', - ['weapon_compactlauncher'] = 'kompaktni launcher', - ['weapon_minismg'] = 'mini smg', - ['weapon_pipebomb'] = 'dymkova bomba', - ['weapon_poolcue'] = 'kulecnikove tago', - ['weapon_wrench'] = 'klic na trubky', - ['weapon_flashlight'] = 'baterka', - ['gadget_parachute'] = 'padak', - ['weapon_flare'] = 'svetlice', - ['weapon_doubleaction'] = 'dvojhlavnovy revolver', + + -- Melee + ['weapon_dagger'] = 'Dýka', + ['weapon_bat'] = 'Baseballová pálka', + ['weapon_battleaxe'] = 'Bitevní sekera', + ['weapon_bottle'] = 'Rozbitá lahve', + ['weapon_crowbar'] = 'Páčidlo', + ['weapon_flashlight'] = 'Baterka', + ['weapon_golfclub'] = 'Golfová hůl', + ['weapon_hammer'] = 'Kladivo', + ['weapon_hatchet'] = 'Sekera', + ['weapon_knife'] = 'Nůž', + ['weapon_knuckle'] = 'Boxer', + ['weapon_machete'] = 'Mačeta', + ['weapon_nightstick'] = 'Policejní obušek', + ['weapon_wrench'] = 'Francouzský klíč', + ['weapon_poolcue'] = 'Kulečníkové tágo', + ['weapon_stone_hatchet'] = 'Kamenná sekera', + ['weapon_switchblade'] = 'Vystřelovací nůž', + + -- Handguns + ['weapon_appistol'] = 'AP pistol', + ['weapon_ceramicpistol'] = 'Ceramic pistol', + ['weapon_combatpistol'] = 'Combat pistol', + ['weapon_doubleaction'] = 'Double-Action Revolver', + ['weapon_navyrevolver'] = 'Navy Revolver', + ['weapon_flaregun'] = 'Flaregun', + ['weapon_gadgetpistol'] = 'Gadget Pistol', + ['weapon_heavypistol'] = 'Heavy Pistol', + ['weapon_revolver'] = 'Heavy Revolver', + ['weapon_revolver_mk2'] = 'Heavy Revolver MK2', + ['weapon_marksmanpistol'] = 'Marksman Pistol', + ['weapon_pistol'] = 'Pistol', + ['weapon_pistol_mk2'] = 'Pistol MK2', + ['weapon_pistol50'] = 'Pistol .50', + ['weapon_snspistol'] = 'SNS Pistol', + ['weapon_snspistol_mk2'] = 'SNS Pistol MK2', + ['weapon_stungun'] = 'Taser', + ['weapon_raypistol'] = 'Up-N-Atomizer', + ['weapon_vintagepistol'] = 'Vintage Pistol', + + -- Shotguns + ['weapon_assaultshotgun'] = 'Assault Shotgun', + ['weapon_autoshotgun'] = 'Auto Shotgun', + ['weapon_bullpupshotgun'] = 'Bullpup Shotgun', + ['weapon_combatshotgun'] = 'Combat Shotgun', + ['weapon_dbshotgun'] = 'Double Barrel Shotgun', + ['weapon_heavyshotgun'] = 'Heavy Shotgun', + ['weapon_musket'] = 'Musket', + ['weapon_pumpshotgun'] = 'Pump Shotgun', + ['weapon_pumpshotgun_mk2'] = 'Pump Shotgun MK2', + ['weapon_sawnoffshotgun'] = 'Sawed Off Shotgun', + + -- SMG & LMG + ['weapon_assaultsmg'] = 'Assault SMG', + ['weapon_combatmg'] = 'Combat MG', + ['weapon_combatmg_mk2'] = 'Combat MG MK2', + ['weapon_combatpdw'] = 'Combat PDW', + ['weapon_gusenberg'] = 'Gusenberg Sweeper', + ['weapon_machinepistol'] = 'Machine Pistol', + ['weapon_mg'] = 'MG', + ['weapon_microsmg'] = 'Micro SMG', + ['weapon_minismg'] = 'Mini SMG', + ['weapon_smg'] = 'SMG', + ['weapon_smg_mk2'] = 'SMG MK2', + ['weapon_raycarbine'] = 'Unholy Hellbringer', + + -- Rifles + ['weapon_advancedrifle'] = 'Advanced Rifle', + ['weapon_assaultrifle'] = 'Assault Rifle', + ['weapon_assaultrifle_mk2'] = 'Assault Rifle MK2', + ['weapon_bullpuprifle'] = 'Bullpup Rifle', + ['weapon_bullpuprifle_mk2'] = 'Bullpup Rifle MK2', + ['weapon_carbinerifle'] = 'Carbine Rifle', + ['weapon_carbinerifle_mk2'] = 'Carbine Rifle MK2', + ['weapon_compactrifle'] = 'Compact Rifle', + ['weapon_militaryrifle'] = 'Military Rifle', + ['weapon_specialcarbine'] = 'Special Carbine', + ['weapon_specialcarbine_mk2'] = 'Special Carbine MK2', + + -- Sniper + ['weapon_heavysniper'] = 'Heavy Sniper', + ['weapon_heavysniper_mk2'] = 'Heavy Sniper MK2', + ['weapon_marksmanrifle'] = 'Marksman Rifle', + ['weapon_marksmanrifle_mk2'] = 'Marksman Rifle MK2', + ['weapon_sniperrifle'] = 'Sniper Rifle', + + -- Heavy / Launchers + ['weapon_compactlauncher'] = 'Compact Launcher', + ['weapon_firework'] = 'Firework Launcher', + ['weapon_grenadelauncher'] = 'Grenade Launcher', + ['weapon_hominglauncher'] = 'Homing Launcher', + ['weapon_minigun'] = 'Minigun', + ['weapon_railgun'] = 'Railgun', + ['weapon_rpg'] = 'Rocket Launcher', + ['weapon_rayminigun'] = 'Widowmaker', + + -- Criminal Enterprises DLC + ['weapon_metaldetector'] = 'Detektor kovu', + ['weapon_precisionrifle'] = 'Precision Rifle', + ['weapon_tactilerifle'] = 'Service Carbine', + + -- Thrown + ['weapon_ball'] = 'Míček', + ['weapon_bzgas'] = 'Smrtící slzný plyn', + ['weapon_flare'] = 'Světlice', + ['weapon_grenade'] = 'Granát', + ['weapon_petrolcan'] = 'Kanistr', + ['weapon_hazardcan'] = 'Hazardous Jerrycan', + ['weapon_molotov'] = 'Molotův koktejl', + ['weapon_proxmine'] = 'Pohybová mina', + ['weapon_pipebomb'] = 'Trubková bomba', + ['weapon_snowball'] = 'Sněhová koule', + ['weapon_stickybomb'] = 'C4', + ['weapon_smokegrenade'] = 'Slzný plyn', + + -- Special + ['weapon_fireextinguisher'] = 'Hasící přístroj', + ['weapon_digiscanner'] = 'Skener', + ['weapon_garbagebag'] = 'Odpadkový pytel', + ['weapon_handcuffs'] = 'Pouta', + ['gadget_nightvision'] = 'Noční vidění', + ['gadget_parachute'] = 'Padák', -- Weapon Components - ['component_clip_default'] = 'zakladni rukojet', - ['component_clip_extended'] = 'prodloucena rukojet', + ['component_knuckle_base'] = 'base Model', + ['component_knuckle_pimp'] = 'the Pimp', + ['component_knuckle_ballas'] = 'the Ballas', + ['component_knuckle_dollar'] = 'the Hustler', + ['component_knuckle_diamond'] = 'the Rock', + ['component_knuckle_hate'] = 'the Hater', + ['component_knuckle_love'] = 'the Lover', + ['component_knuckle_player'] = 'the Player', + ['component_knuckle_king'] = 'the King', + ['component_knuckle_vagos'] = 'the Vagos', + + ['component_luxary_finish'] = 'luxary Weapon Finish', + + ['component_handle_default'] = 'default Handle', + ['component_handle_vip'] = 'vIP Handle', + ['component_handle_bodyguard'] = 'bodyguard Handle', + + ['component_vip_finish'] = 'vIP Finish', + ['component_bodyguard_finish'] = 'bodyguard Finish', + + ['component_camo_finish'] = 'digital Camo', + ['component_camo_finish2'] = 'brushstroke Camo', + ['component_camo_finish3'] = 'woodland Camo', + ['component_camo_finish4'] = 'skull Camo', + ['component_camo_finish5'] = 'sessanta Nove Camo', + ['component_camo_finish6'] = 'perseus Camo', + ['component_camo_finish7'] = 'leopard Camo', + ['component_camo_finish8'] = 'zebra Camo', + ['component_camo_finish9'] = 'geometric Camo', + ['component_camo_finish10'] = 'boom Camo', + ['component_camo_finish11'] = 'patriotic Camo', + + ['component_camo_slide_finish'] = 'digital Slide Camo', + ['component_camo_slide_finish2'] = 'brushstroke Slide Camo', + ['component_camo_slide_finish3'] = 'woodland Slide Camo', + ['component_camo_slide_finish4'] = 'skull Slide Camo', + ['component_camo_slide_finish5'] = 'sessanta Nove Slide Camo', + ['component_camo_slide_finish6'] = 'perseus Slide Camo', + ['component_camo_slide_finish7'] = 'leopard Slide Camo', + ['component_camo_slide_finish8'] = 'zebra Slide Camo', + ['component_camo_slide_finish9'] = 'geometric Slide Camo', + ['component_camo_slide_finish10'] = 'boom Slide Camo', + ['component_camo_slide_finish11'] = 'patriotic Slide Camo', + + ['component_clip_default'] = 'default Magazine', + ['component_clip_extended'] = 'extended Magazine', ['component_clip_drum'] = 'drum Magazine', - ['component_clip_box'] = 'krabice s naboji', - ['component_flashlight'] = 'baterka', - ['component_scope'] = 'zamerovac', - ['component_scope_advanced'] = 'pokrocily zamerovac', - ['component_suppressor'] = 'tlumic', - ['component_grip'] = 'rukojet', - ['component_luxary_finish'] = 'luxusni vzhled zbrane', + ['component_clip_box'] = 'box Magazine', + + ['component_scope_holo'] = 'holographic Scope', + ['component_scope_small'] = 'small Scope', + ['component_scope_medium'] = 'medium Scope', + ['component_scope_large'] = 'large Scope', + ['component_scope'] = 'mounted Scope', + ['component_scope_advanced'] = 'advanced Scope', + ['component_ironsights'] = 'ironsights', + + ['component_suppressor'] = 'suppressor', + ['component_compensator'] = 'compensator', + + ['component_muzzle_flat'] = 'flat Muzzle Brake', + ['component_muzzle_tactical'] = 'tactical Muzzle Brake', + ['component_muzzle_fat'] = 'fat-End Muzzle Brake', + ['component_muzzle_precision'] = 'precision Muzzle Brake', + ['component_muzzle_heavy'] = 'heavy Duty Muzzle Brake', + ['component_muzzle_slanted'] = 'slanted Muzzle Brake', + ['component_muzzle_split'] = 'split-End Muzzle Brake', + ['component_muzzle_squared'] = 'squared Muzzle Brake', + + ['component_flashlight'] = 'flashlight', + ['component_grip'] = 'grip', + + ['component_barrel_default'] = 'default Barrel', + ['component_barrel_heavy'] = 'heavy Barrel', + + ['component_ammo_tracer'] = 'tracer Ammo', + ['component_ammo_incendiary'] = 'incendiary Ammo', + ['component_ammo_hollowpoint'] = 'hollowpoint Ammo', + ['component_ammo_fmj'] = 'fMJ Ammo', + ['component_ammo_armor'] = 'armor Piercing Ammo', + ['component_ammo_explosive'] = 'armor Piercing Incendiary Ammo', + + ['component_shells_default'] = 'default Shells', + ['component_shells_incendiary'] = 'dragons Breath Shells', + ['component_shells_armor'] = 'steel Buckshot Shells', + ['component_shells_hollowpoint'] = 'flechette Shells', + ['component_shells_explosive'] = 'explosive Slug Shells', -- Weapon Ammo - ['ammo_rounds'] = 'naboj(e)', - ['ammo_shells'] = 'patrona(y)', - ['ammo_charge'] = 'naboj(e)', - ['ammo_petrol'] = 'galonu paliva', - ['ammo_firework'] = 'ohnostroj(e)', - ['ammo_rockets'] = 'raketa(y)', - ['ammo_grenadelauncher'] = 'granat(y)', - ['ammo_grenade'] = 'granat(y)', - ['ammo_stickybomb'] = 'bomba(y)', - ['ammo_pipebomb'] = 'bomba(y)', - ['ammo_smokebomb'] = 'bomba(y)', - ['ammo_molotov'] = 'koktejl(y)', - ['ammo_proxmine'] = 'mina(y)', - ['ammo_bzgas'] = 'kanystr(y)', - ['ammo_ball'] = 'koule', - ['ammo_snowball'] = 'snehova(e) koule', - ['ammo_flare'] = 'svetlice', - ['ammo_flaregun'] = 'svetlice', + ['ammo_rounds'] = 'round(s)', + ['ammo_shells'] = 'shell(s)', + ['ammo_charge'] = 'charge', + ['ammo_petrol'] = 'gallons of fuel', + ['ammo_firework'] = 'firework(s)', + ['ammo_rockets'] = 'rocket(s)', + ['ammo_grenadelauncher'] = 'grenade(s)', + ['ammo_grenade'] = 'grenade(s)', + ['ammo_stickybomb'] = 'bomb(s)', + ['ammo_pipebomb'] = 'bomb(s)', + ['ammo_smokebomb'] = 'bomb(s)', + ['ammo_molotov'] = 'cocktail(s)', + ['ammo_proxmine'] = 'mine(s)', + ['ammo_bzgas'] = 'can(s)', + ['ammo_ball'] = 'ball(s)', + ['ammo_snowball'] = 'snowball(s)', + ['ammo_flare'] = 'flare(s)', + ['ammo_flaregun'] = 'flare(s)', -- Weapon Tints - ['tint_default'] = 'zakladni skin', - ['tint_green'] = 'zeleny skin', - ['tint_gold'] = 'zlaty skin', - ['tint_pink'] = 'ruzovy skin', - ['tint_army'] = 'armadni skin', - ['tint_lspd'] = 'modry skin', - ['tint_orange'] = 'oranzovy skin', - ['tint_platinum'] = 'platinovy skin', + ['tint_default'] = 'default skin', + ['tint_green'] = 'green skin', + ['tint_gold'] = 'gold skin', + ['tint_pink'] = 'pink skin', + ['tint_army'] = 'army skin', + ['tint_lspd'] = 'blue skin', + ['tint_orange'] = 'orange skin', + ['tint_platinum'] = 'platinum skin', } From 88a32d6a6c50fd4da4a79deaa6b8032643937df1 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Mon, 5 Dec 2022 15:02:14 +0800 Subject: [PATCH 32/83] full context implementation --- [esx_addons]/esx_taxijob/client/main.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/[esx_addons]/esx_taxijob/client/main.lua b/[esx_addons]/esx_taxijob/client/main.lua index 7c363578..afb3b56e 100644 --- a/[esx_addons]/esx_taxijob/client/main.lua +++ b/[esx_addons]/esx_taxijob/client/main.lua @@ -238,15 +238,18 @@ function OpenMobileTaxiActionsMenu() ESX.OpenContext("right", elements, function(menu,element) if element.value == "billing" then - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'billing', { - title = TranslateCap('invoice_amount') - }, function(data, menu) + local elements2 = { + {unselectable = true, icon = "fas fa-taxi", title = element.title}, + {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = "Amount to bill.."}, + {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} + } - local amount = tonumber(data.value) + ESX.OpenContext("right", elements2, function(menu2,element2) + local amount = tonumber(menu2.eles[2].inputValue) if amount == nil then ESX.ShowNotification(TranslateCap('amount_invalid')) else - menu.close() + ESX.CloseContext() local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() if closestPlayer == -1 or closestDistance > 3.0 then ESX.ShowNotification(TranslateCap('no_players_near')) @@ -256,8 +259,6 @@ function OpenMobileTaxiActionsMenu() ESX.ShowNotification(TranslateCap('billing_sent')) end end - end, function(data, menu) - menu.close() end) elseif element.value == "start_job" then if OnJob then From d5888d3ff09079eec7d589877a66c617b1a30d16 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Mon, 5 Dec 2022 15:12:03 +0800 Subject: [PATCH 33/83] remove is menu open check --- [esx]/es_extended/client/main.lua | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/[esx]/es_extended/client/main.lua b/[esx]/es_extended/client/main.lua index b613f741..5c35d413 100644 --- a/[esx]/es_extended/client/main.lua +++ b/[esx]/es_extended/client/main.lua @@ -250,9 +250,7 @@ if not Config.OxInventory then ESX.UI.ShowInventoryItemNotification(true, item, count) end - if ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then - ESX.ShowInventory() - end + ESX.ShowInventory() end) RegisterNetEvent('esx:removeInventoryItem') @@ -269,9 +267,7 @@ if not Config.OxInventory then ESX.UI.ShowInventoryItemNotification(false, item, count) end - if ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then - ESX.ShowInventory() - end + ESX.ShowInventory() end) RegisterNetEvent('esx:addWeapon') @@ -463,7 +459,7 @@ end if not Config.OxInventory and Config.EnableDefaultInventory then RegisterCommand('showinv', function() - if not ESX.PlayerData.dead and not ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then + if not ESX.PlayerData.dead then ESX.ShowInventory() end end) From 25b1660fef3aa3363e9a61ae1aee8ac6510a91d2 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Mon, 5 Dec 2022 15:12:46 +0800 Subject: [PATCH 34/83] inventory context implementation --- [esx]/es_extended/client/functions.lua | 248 ++++++++++++------------- 1 file changed, 122 insertions(+), 126 deletions(-) diff --git a/[esx]/es_extended/client/functions.lua b/[esx]/es_extended/client/functions.lua index d59e240c..3be7d9c7 100644 --- a/[esx]/es_extended/client/functions.lua +++ b/[esx]/es_extended/client/functions.lua @@ -1088,22 +1088,26 @@ end function ESX.ShowInventory() local playerPed = ESX.PlayerData.ped - local elements, currentWeight = {}, 0 + local elements = { + {unselectable = true, icon = 'fas fa-box', title = 'Player Inventory'} + } + local currentWeight = 0 for i=1, #(ESX.PlayerData.accounts) do if ESX.PlayerData.accounts[i].money > 0 then - local formattedMoney = TranslateCap('locale_currency', ESX.Math.GroupDigits(ESX.PlayerData.accounts[i].money)) + local formattedMoney = _U('locale_currency', ESX.Math.GroupDigits(ESX.PlayerData.accounts[i].money)) local canDrop = ESX.PlayerData.accounts[i].name ~= 'bank' - table.insert(elements, { - label = ('%s: %s'):format(ESX.PlayerData.accounts[i].label, formattedMoney), + elements[#elements+1] = { + icon = 'fas fa-money-bill-wave', + title = ('%s: %s'):format(ESX.PlayerData.accounts[i].label, formattedMoney), count = ESX.PlayerData.accounts[i].money, type = 'item_account', value = ESX.PlayerData.accounts[i].name, usable = false, rare = false, canRemove = canDrop - }) + } end end @@ -1111,15 +1115,16 @@ function ESX.ShowInventory() if v.count > 0 then currentWeight = currentWeight + (v.weight * v.count) - table.insert(elements, { - label = ('%s x%s'):format(v.label, v.count), + elements[#elements+1] = { + icon = 'fas fa-box', + title = ('%s x%s'):format(v.label, v.count), count = v.count, type = 'item_standard', value = v.name, usable = v.usable, rare = v.rare, canRemove = v.canRemove - }) + } end end @@ -1135,8 +1140,9 @@ function ESX.ShowInventory() label = v.label end - table.insert(elements, { - label = label, + elements[#elements+1] = { + icon = 'fas fa-gun', + title = label, count = 1, type = 'item_weapon', value = v.name, @@ -1145,76 +1151,80 @@ function ESX.ShowInventory() ammo = ammo, canGiveAmmo = (v.ammo ~= nil), canRemove = true - }) + } end end - ESX.UI.Menu.CloseAll() + elements[#elements+1] = { + unselectable = true, + icon = "fas fa-weight", + title = "Current Weight: "..currentWeight + } + + ESX.CloseContext() - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'inventory', { - title = TranslateCap('inventory', currentWeight, ESX.PlayerData.maxWeight), - align = 'bottom-right', - elements = elements - }, function(data, menu) - menu.close() + ESX.OpenContext("right", elements, function(menu,element) local player, distance = ESX.Game.GetClosestPlayer() - elements = {} - if data.current.usable then - table.insert(elements, { - label = TranslateCap('use'), + elements2 = {} + + if element.usable then + elements2[#elements2+1] = { + icon = "fas fa-utensils", + title = _U('use'), action = 'use', - type = data.current.type, - value = data.current.value - }) + type = element.type, + value = element.value + } end - if data.current.canRemove then + if element.canRemove then if player ~= -1 and distance <= 3.0 then - table.insert(elements, { - label = TranslateCap('give'), + elements2[#elements2+1] = { + icon = "fas fa-hands", + title = _U('give'), action = 'give', - type = data.current.type, - value = data.current.value - }) + type = element.type, + value = element.value + } end - table.insert(elements, { - label = TranslateCap('remove'), + elements2[#elements2+1] = { + icon = "fas fa-trash", + title = _U('remove'), action = 'remove', - type = data.current.type, - value = data.current.value - }) + type = element.type, + value = element.value + } end - if data.current.type == 'item_weapon' and data.current.canGiveAmmo and data.current.ammo > 0 and player ~= -1 and - distance <= 3.0 then - table.insert(elements, { - label = TranslateCap('giveammo'), + if element.type == 'item_weapon' and element.canGiveAmmo and element.ammo > 0 and player ~= -1 and distance <= 3.0 then + elements2[#elements2+1] = { + icon = "fas fa-gun", + title = _U('giveammo'), action = 'give_ammo', - type = data.current.type, - value = data.current.value - }) + type = element.type, + value = element.value + } end - table.insert(elements, { - label = TranslateCap('return'), + elements2[#elements2+1] = { + icon = "fas fa-arrow-left", + title = _U('return'), action = 'return' - }) + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'inventory_item', { - title = data.current.label, - align = 'bottom-right', - elements = elements - }, function(data1, menu1) - local item, type = data1.current.value, data1.current.type + ESX.OpenContext("right", elements2, function(menu2,element2) + local item, type = element2.value, element2.type - if data1.current.action == 'give' then + if element2.action == "give" then local playersNearby = ESX.Game.GetPlayersInArea(GetEntityCoords(playerPed), 3.0) if #playersNearby > 0 then local players = {} - elements = {} + elements3 = { + {unselectable = true, icon = "fas fa-users", title = "Nearby Players"} + } for k, playerNearby in ipairs(playersNearby) do players[GetPlayerServerId(playerNearby)] = true @@ -1222,19 +1232,15 @@ function ESX.ShowInventory() ESX.TriggerServerCallback('esx:getPlayerNames', function(returnedPlayers) for playerId, playerName in pairs(returnedPlayers) do - table.insert(elements, { - label = playerName, + elements3[#elements3+1] = { + icon = "fas fa-user", + title = playerName, playerId = playerId - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'give_item_to', { - title = TranslateCap('give_to'), - align = 'bottom-right', - elements = elements - }, function(data2, menu2) - local selectedPlayer, selectedPlayerId = GetPlayerFromServerId(data2.current.playerId), - data2.current.playerId + ESX.OpenContext("right", elements3, function(menu3,element3) + local selectedPlayer, selectedPlayerId = GetPlayerFromServerId(element3.playerId), element3.playerId playersNearby = ESX.Game.GetPlayersInArea(GetEntityCoords(playerPed), 3.0) playersNearby = ESX.Table.Set(playersNearby) @@ -1244,80 +1250,75 @@ function ESX.ShowInventory() if IsPedOnFoot(selectedPlayerPed) and not IsPedFalling(selectedPlayerPed) then if type == 'item_weapon' then TriggerServerEvent('esx:giveInventoryItem', selectedPlayerId, type, item, nil) - menu2.close() - menu1.close() + ESX.CloseContext() else - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), - 'inventory_item_count_give', { - title = TranslateCap('amount') - }, function(data3, menu3) - local quantity = tonumber(data3.value) + local elementsG = { + {unselectable = true, icon = "fas fa-trash", title = element.title}, + {icon = "fas fa-tally", title = "Amount.", input = true, inputType = "number", inputPlaceholder = "Amount to give..", inputMin = 1, inputMax = 1000}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } - if quantity and quantity > 0 and data.current.count >= quantity then - TriggerServerEvent('esx:giveInventoryItem', selectedPlayerId, type, - item, quantity) - menu3.close() - menu2.close() - menu1.close() - else - ESX.ShowNotification(TranslateCap('amount_invalid')) - end - end, function(data3, menu3) - menu3.close() - end) + ESX.OpenContext("right", elementsG, function(menuG,elementG) + local quantity = tonumber(menuG.eles[2].inputValue) + + if quantity and quantity > 0 and element.count >= quantity then + TriggerServerEvent('esx:giveInventoryItem', selectedPlayerId, type, item, quantity) + ESX.CloseContext() + else + ESX.ShowNotification(_U('amount_invalid')) + end + end) end else - ESX.ShowNotification(TranslateCap('in_vehicle')) + ESX.ShowNotification(_U('in_vehicle')) end else - ESX.ShowNotification(TranslateCap('players_nearby')) - menu2.close() + ESX.ShowNotification(_U('players_nearby')) + ESX.CloseContext() end - end, function(data2, menu2) - menu2.close() end) end, players) - else - ESX.ShowNotification(TranslateCap('players_nearby')) end - elseif data1.current.action == 'remove' then + elseif element2.action == "remove" then if IsPedOnFoot(playerPed) and not IsPedFalling(playerPed) then local dict, anim = 'weapons@first_person@aim_rng@generic@projectile@sticky_bomb@', 'plant_floor' ESX.Streaming.RequestAnimDict(dict) if type == 'item_weapon' then - menu1.close() + ESX.CloseContext() TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false) RemoveAnimDict(dict) Wait(1000) TriggerServerEvent('esx:removeInventoryItem', type, item) else - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'inventory_item_count_remove', { - title = TranslateCap('amount') - }, function(data2, menu2) - local quantity = tonumber(data2.value) + local elementsR = { + {unselectable = true, icon = "fas fa-trash", title = element.title}, + {icon = "fas fa-tally", title = "Amount.", input = true, inputType = "number", inputPlaceholder = "Amount to remove..", inputMin = 1, inputMax = 1000}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } - if quantity and quantity > 0 and data.current.count >= quantity then - menu2.close() - menu1.close() + ESX.OpenContext("right", elementsR, function(menuR,elementR) + local quantity = tonumber(menuR.eles[2].inputValue) + + if quantity and quantity > 0 and element.count >= quantity then + ESX.CloseContext() TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false) RemoveAnimDict(dict) Wait(1000) TriggerServerEvent('esx:removeInventoryItem', type, item, quantity) else - ESX.ShowNotification(TranslateCap('amount_invalid')) + ESX.ShowNotification(_U('amount_invalid')) end - end, function(data2, menu2) - menu2.close() end) end end - elseif data1.current.action == 'use' then + elseif element2.action == "use" then + ESX.CloseContext() TriggerServerEvent('esx:useItem', item) - elseif data1.current.action == 'return' then - ESX.UI.Menu.CloseAll() + elseif element2.action == "return" then + ESX.CloseContext() ESX.ShowInventory() - elseif data1.current.action == 'give_ammo' then + elseif element2.action == "give_ammo" then local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() local closestPed = GetPlayerPed(closestPlayer) local pedAmmo = GetAmmoInPedWeapon(playerPed, joaat(item)) @@ -1325,42 +1326,37 @@ function ESX.ShowInventory() if IsPedOnFoot(closestPed) and not IsPedFalling(closestPed) then if closestPlayer ~= -1 and closestDistance < 3.0 then if pedAmmo > 0 then - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'inventory_item_count_give', { - title = TranslateCap('amountammo') - }, function(data2, menu2) - local quantity = tonumber(data2.value) + local elementsGA = { + {unselectable = true, icon = "fas fa-trash", title = element.title}, + {icon = "fas fa-tally", title = "Amount.", input = true, inputType = "number", inputPlaceholder = "Amount to give..", inputMin = 1, inputMax = 1000}, + {icon = "fas fa-check-double", title = "Confirm", val = "confirm"} + } + + ESX.OpenContext("right", elementsGA, function(menuGA,elementGA) + local quantity = tonumber(menuGA.eles[2].inputValue) if quantity and quantity > 0 then if pedAmmo >= quantity then - TriggerServerEvent('esx:giveInventoryItem', GetPlayerServerId(closestPlayer), - 'item_ammo', item, quantity) - menu2.close() - menu1.close() + TriggerServerEvent('esx:giveInventoryItem', GetPlayerServerId(closestPlayer), 'item_ammo', item, quantity) + ESX.CloseContext() else - ESX.ShowNotification(TranslateCap('noammo')) + ESX.ShowNotification(_U('noammo')) end else - ESX.ShowNotification(TranslateCap('amount_invalid')) + ESX.ShowNotification(_U('amount_invalid')) end - end, function(data2, menu2) - menu2.close() end) else - ESX.ShowNotification(TranslateCap('noammo')) + ESX.ShowNotification(_U('noammo')) end else - ESX.ShowNotification(TranslateCap('players_nearby')) + ESX.ShowNotification(_U('players_nearby')) end else - ESX.ShowNotification(TranslateCap('in_vehicle')) + ESX.ShowNotification(_U('in_vehicle')) end end - end, function(data1, menu1) - ESX.UI.Menu.CloseAll() - ESX.ShowInventory() end) - end, function(data, menu) - menu.close() end) end From 04ebf295f607b97a608452164c176de855651dc5 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Mon, 5 Dec 2022 15:13:46 +0800 Subject: [PATCH 35/83] remove closeall func --- [esx]/esx_multicharacter/client/main.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/[esx]/esx_multicharacter/client/main.lua b/[esx]/esx_multicharacter/client/main.lua index 69365dee..ca6f89ac 100644 --- a/[esx]/esx_multicharacter/client/main.lua +++ b/[esx]/esx_multicharacter/client/main.lua @@ -35,7 +35,6 @@ if ESX.GetConfig().Multichar then RenderScriptCams(true, false, 1, true, true) SetCamCoord(cam, offset.x, offset.y, offset.z) PointCamAtCoord(cam, Config.Spawn.x, Config.Spawn.y, Config.Spawn.z + 1.3) - ESX.UI.Menu.CloseAll() ESX.UI.HUD.SetDisplay(0.0) StartLoop() ShutdownLoadingScreen() From fa8b7d6068d6c713d77f0634def1033ce05d5764 Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Mon, 5 Dec 2022 15:16:40 +0800 Subject: [PATCH 36/83] fix _U to TranslateCap --- [esx]/es_extended/client/functions.lua | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/[esx]/es_extended/client/functions.lua b/[esx]/es_extended/client/functions.lua index 3be7d9c7..77ac0dc5 100644 --- a/[esx]/es_extended/client/functions.lua +++ b/[esx]/es_extended/client/functions.lua @@ -1095,7 +1095,7 @@ function ESX.ShowInventory() for i=1, #(ESX.PlayerData.accounts) do if ESX.PlayerData.accounts[i].money > 0 then - local formattedMoney = _U('locale_currency', ESX.Math.GroupDigits(ESX.PlayerData.accounts[i].money)) + local formattedMoney = TranslateCap('locale_currency', ESX.Math.GroupDigits(ESX.PlayerData.accounts[i].money)) local canDrop = ESX.PlayerData.accounts[i].name ~= 'bank' elements[#elements+1] = { @@ -1171,7 +1171,7 @@ function ESX.ShowInventory() if element.usable then elements2[#elements2+1] = { icon = "fas fa-utensils", - title = _U('use'), + title = TranslateCap('use'), action = 'use', type = element.type, value = element.value @@ -1182,7 +1182,7 @@ function ESX.ShowInventory() if player ~= -1 and distance <= 3.0 then elements2[#elements2+1] = { icon = "fas fa-hands", - title = _U('give'), + title = TranslateCap('give'), action = 'give', type = element.type, value = element.value @@ -1191,7 +1191,7 @@ function ESX.ShowInventory() elements2[#elements2+1] = { icon = "fas fa-trash", - title = _U('remove'), + title = TranslateCap('remove'), action = 'remove', type = element.type, value = element.value @@ -1201,7 +1201,7 @@ function ESX.ShowInventory() if element.type == 'item_weapon' and element.canGiveAmmo and element.ammo > 0 and player ~= -1 and distance <= 3.0 then elements2[#elements2+1] = { icon = "fas fa-gun", - title = _U('giveammo'), + title = TranslateCap('giveammo'), action = 'give_ammo', type = element.type, value = element.value @@ -1210,7 +1210,7 @@ function ESX.ShowInventory() elements2[#elements2+1] = { icon = "fas fa-arrow-left", - title = _U('return'), + title = TranslateCap('return'), action = 'return' } @@ -1265,15 +1265,15 @@ function ESX.ShowInventory() TriggerServerEvent('esx:giveInventoryItem', selectedPlayerId, type, item, quantity) ESX.CloseContext() else - ESX.ShowNotification(_U('amount_invalid')) + ESX.ShowNotification(TranslateCap('amount_invalid')) end end) end else - ESX.ShowNotification(_U('in_vehicle')) + ESX.ShowNotification(TranslateCap('in_vehicle')) end else - ESX.ShowNotification(_U('players_nearby')) + ESX.ShowNotification(TranslateCap('players_nearby')) ESX.CloseContext() end end) @@ -1307,7 +1307,7 @@ function ESX.ShowInventory() Wait(1000) TriggerServerEvent('esx:removeInventoryItem', type, item, quantity) else - ESX.ShowNotification(_U('amount_invalid')) + ESX.ShowNotification(TranslateCap('amount_invalid')) end end) end @@ -1340,20 +1340,20 @@ function ESX.ShowInventory() TriggerServerEvent('esx:giveInventoryItem', GetPlayerServerId(closestPlayer), 'item_ammo', item, quantity) ESX.CloseContext() else - ESX.ShowNotification(_U('noammo')) + ESX.ShowNotification(TranslateCap('noammo')) end else - ESX.ShowNotification(_U('amount_invalid')) + ESX.ShowNotification(TranslateCap('amount_invalid')) end end) else - ESX.ShowNotification(_U('noammo')) + ESX.ShowNotification(TranslateCap('noammo')) end else - ESX.ShowNotification(_U('players_nearby')) + ESX.ShowNotification(TranslateCap('players_nearby')) end else - ESX.ShowNotification(_U('in_vehicle')) + ESX.ShowNotification(TranslateCap('in_vehicle')) end end end) From 14b852dee1e7be7960da76ea6248413eca5ae57f Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Mon, 5 Dec 2022 15:26:49 +0800 Subject: [PATCH 37/83] closecontext func --- [esx_addons]/esx_shops/client/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx_addons]/esx_shops/client/main.lua b/[esx_addons]/esx_shops/client/main.lua index 1d12688d..f2077b0f 100644 --- a/[esx_addons]/esx_shops/client/main.lua +++ b/[esx_addons]/esx_shops/client/main.lua @@ -49,7 +49,7 @@ end) AddEventHandler('esx_shops:hasExitedMarker', function(zone) currentAction = nil - ESX.UI.Menu.CloseAll() + ESX.CloseContext() end) -- Create Blips From b55a603e4a432c828b5115d5a2d9d0813b522dd8 Mon Sep 17 00:00:00 2001 From: bitpredator <67551273+bitpredator@users.noreply.github.com> Date: Tue, 6 Dec 2022 16:54:16 +0100 Subject: [PATCH 38/83] feat:(Italian language for esx_skin) --- [esx]/esx_skin/locales/it.lua | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 [esx]/esx_skin/locales/it.lua diff --git a/[esx]/esx_skin/locales/it.lua b/[esx]/esx_skin/locales/it.lua new file mode 100644 index 00000000..dbf84c6d --- /dev/null +++ b/[esx]/esx_skin/locales/it.lua @@ -0,0 +1,6 @@ +Locales['it'] = { + ['skin_menu'] = 'Menu Skin', + ['use_rotate_view'] = 'usa ~INPUT_FRONTEND_LS~ e ~INPUT_CHARACTER_WHEEL~ per ruotare la visuale.', + ['skin'] = 'cambia skin', + ['saveskin'] = 'salvare la skin', +} From 1248c0a5cdbec9a0e57784d2850b74a91c6836d6 Mon Sep 17 00:00:00 2001 From: bitpredator <67551273+bitpredator@users.noreply.github.com> Date: Tue, 6 Dec 2022 17:18:32 +0100 Subject: [PATCH 39/83] feat:(Italian language for esx_skin) From 3f5a090125ed47856d2c136b69dd679c437af86f Mon Sep 17 00:00:00 2001 From: wobozkyng <42249669+wobozkyng@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:55:48 +0700 Subject: [PATCH 40/83] refactor(es_extended\client\main.lua): entity check VehicleProperties Statebag handler --- [esx]/es_extended/client/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/[esx]/es_extended/client/main.lua b/[esx]/es_extended/client/main.lua index b613f741..5d6ac860 100644 --- a/[esx]/es_extended/client/main.lua +++ b/[esx]/es_extended/client/main.lua @@ -203,8 +203,8 @@ AddStateBagChangeHandler('VehicleProperties', nil, function(bagName, key, value) local NetId = value.NetId local Vehicle = NetworkGetEntityFromNetworkId(NetId) local Tries = 0 - while not DoesEntityExist(Vehicle) do - local Vehicle = NetworkGetEntityFromNetworkId(NetId) + while Vehicle == 0 do + Vehicle = NetworkGetEntityFromNetworkId(NetId) Wait(100) Tries = Tries + 1 if Tries > 300 then From 4416953334311baafa3afa2df20f1c7600b5a5a0 Mon Sep 17 00:00:00 2001 From: iSentrie Date: Thu, 8 Dec 2022 19:03:11 +0200 Subject: [PATCH 41/83] allow set account to 0 too pretty sure i was done this fix, but someone tend to undo fixes and have broken code over and over again --- [esx]/es_extended/server/classes/player.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx]/es_extended/server/classes/player.lua b/[esx]/es_extended/server/classes/player.lua index 73634829..ffdb18c6 100644 --- a/[esx]/es_extended/server/classes/player.lua +++ b/[esx]/es_extended/server/classes/player.lua @@ -187,7 +187,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) return end - if money > 0 then + if money >= 0 then local account = self.getAccount(accountName) if account then From 51280a094c9b813225cb27037f21607ef964a09e Mon Sep 17 00:00:00 2001 From: Mycroft Date: Fri, 9 Dec 2022 01:07:53 +0000 Subject: [PATCH 42/83] refactor(es_extended): Server sided Coord Saving this is as thread less design that allows both xPlayer.coords and xPlayer.getCoords to correctly function, aswell as removing the need for the client to trigger a server event this is once again, a change that **requires** Onesync **infinity** --- [esx]/es_extended/client/main.lua | 21 ---------------- [esx]/es_extended/server/classes/player.lua | 28 +++++++++++++++++---- [esx]/es_extended/server/main.lua | 2 +- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/[esx]/es_extended/client/main.lua b/[esx]/es_extended/client/main.lua index b613f741..6d46a79d 100644 --- a/[esx]/es_extended/client/main.lua +++ b/[esx]/es_extended/client/main.lua @@ -438,27 +438,6 @@ function StartServerSyncLoops() end end) end - - -- sync current player coords with server - CreateThread(function() - local previousCoords = vector3(ESX.PlayerData.coords.x, ESX.PlayerData.coords.y, ESX.PlayerData.coords.z) - - while ESX.PlayerLoaded do - local playerPed = PlayerPedId() - if ESX.PlayerData.ped ~= playerPed then ESX.SetPlayerData('ped', playerPed) end - - if DoesEntityExist(ESX.PlayerData.ped) then - local playerCoords = GetEntityCoords(ESX.PlayerData.ped) - local distance = #(playerCoords - previousCoords) - - if distance > 1 then - previousCoords = playerCoords - TriggerServerEvent('esx:updateCoords') - end - end - Wait(1500) - end - end) end if not Config.OxInventory and Config.EnableDefaultInventory then diff --git a/[esx]/es_extended/server/classes/player.lua b/[esx]/es_extended/server/classes/player.lua index 73634829..8f3eb8e9 100644 --- a/[esx]/es_extended/server/classes/player.lua +++ b/[esx]/es_extended/server/classes/player.lua @@ -1,3 +1,9 @@ +local SetTimeout = SetTimeout +local GetPlayerPed = GetPlayerPed +local DoesEntityExist = DoesEntityExist +local GetEntityCoords = GetEntityCoords +local GetEntityHeading = GetEntityHeading + function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, weight, job, loadout, name, coords) local targetOverrides = Config.PlayerFunctionOverride and Core.PlayerFunctionOverrides[Config.PlayerFunctionOverride] or {} @@ -31,7 +37,6 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, end function self.setCoords(coords) - self.updateCoords(coords) local Ped = GetPlayerPed(self.source) local vector = type(coords) == "vector4" and coords or type(coords) == "vector3" and vector4(coords, 0.0) or vec(coords.x, coords.y, coords.z, coords.heading or 0.0) @@ -40,10 +45,23 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, end function self.updateCoords() - local Ped = GetPlayerPed(self.source) - local coords = GetEntityCoords(Ped) - local heading = GetEntityHeading(Ped) - self.coords = {x = ESX.Math.Round(coords.x, 1), y = ESX.Math.Round(coords.y, 1), z = ESX.Math.Round(coords.z, 1), heading = ESX.Math.Round(heading or 0.0, 1)} + SetTimeout(1000,function() + local Ped = GetPlayerPed(self.source) + if DoesEntityExist(Ped) then + local coords = GetEntityCoords(Ped) + local distance = #(coords - vector3(self.coords.x, self.coords.y, self.coords.z)) + if distance > 1.5 then + local heading = GetEntityHeading(Ped) + self.coords = { + x = coords.x, + y = coords.y, + z = coords.z, + heading = heading or 0.0 + } + end + end + self.updateCoords() + end) end function self.getCoords(vector) diff --git a/[esx]/es_extended/server/main.lua b/[esx]/es_extended/server/main.lua index 87ffeb71..ddfb98dd 100644 --- a/[esx]/es_extended/server/main.lua +++ b/[esx]/es_extended/server/main.lua @@ -317,7 +317,7 @@ function loadESXPlayer(identifier, playerId, isNew) else exports.ox_inventory:setPlayerInventory(xPlayer, userData.inventory) end - + xPlayer.updateCoords() xPlayer.triggerEvent('esx:registerSuggestions', Core.RegisteredCommands) print(('[^2INFO^0] Player ^5"%s"^0 has connected to the server. ID: ^5%s^7'):format(xPlayer.getName(), playerId)) end From bdd56329c791d09f03099e5860516ffc22b79d09 Mon Sep 17 00:00:00 2001 From: Mycroft Date: Fri, 9 Dec 2022 18:15:15 +0000 Subject: [PATCH 43/83] tweak(es_extended): remove unused event handler --- [esx]/es_extended/server/main.lua | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/[esx]/es_extended/server/main.lua b/[esx]/es_extended/server/main.lua index ddfb98dd..00c871ba 100644 --- a/[esx]/es_extended/server/main.lua +++ b/[esx]/es_extended/server/main.lua @@ -359,16 +359,6 @@ AddEventHandler('esx:playerLogout', function(playerId, cb) TriggerClientEvent("esx:onPlayerLogout", playerId) end) -RegisterNetEvent('esx:updateCoords') -AddEventHandler('esx:updateCoords', function() - local source = source - local xPlayer = ESX.GetPlayerFromId(source) - - if xPlayer then - xPlayer.updateCoords() - end -end) - if not Config.OxInventory then RegisterNetEvent('esx:updateWeaponAmmo') AddEventHandler('esx:updateWeaponAmmo', function(weaponName, ammoCount) From 227532d4b663b98839dec0047aaf818b03d75f97 Mon Sep 17 00:00:00 2001 From: Mycroft Date: Fri, 9 Dec 2022 22:17:47 +0000 Subject: [PATCH 44/83] fix(es_extended): dont spawn vehicle if non-existant --- [esx]/es_extended/client/main.lua | 45 +++++++++++++++------------- [esx]/es_extended/server/onesync.lua | 40 ++++++++++++++----------- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/[esx]/es_extended/client/main.lua b/[esx]/es_extended/client/main.lua index 6d46a79d..34ba5d47 100644 --- a/[esx]/es_extended/client/main.lua +++ b/[esx]/es_extended/client/main.lua @@ -690,28 +690,33 @@ AddEventHandler("esx:freezePlayer", function(input) end) RegisterNetEvent("esx:GetVehicleType", function(Model, Request) + local ReturnedType = "automobile" local Model = Model - local VehicleType = GetVehicleClassFromName(Model) - local type = "automobile" - if VehicleType == 15 then - type = "heli" - elseif VehicleType == 16 then - type = "plane" - elseif VehicleType == 14 then - type = "boat" - elseif VehicleType == 11 then - type = "trailer" - elseif VehicleType == 21 then - type = "train" - elseif VehicleType == 13 or VehicleType == 8 then - type = "bike" - end - if Model == `submersible` or Model == `submersible2` then - type = "submarine" - end - TriggerServerEvent("esx:ReturnVehicleType", type, Request) -end) + local IsValidModel = IsModelInCdimage(Model) + if IsValidModel == true or IsValidModel == 1 then + local VehicleType = GetVehicleClassFromName(Model) + if VehicleType == 15 then + ReturnedType = "heli" + elseif VehicleType == 16 then + ReturnedType = "plane" + elseif VehicleType == 14 then + ReturnedType = "boat" + elseif VehicleType == 11 then + ReturnedType = "trailer" + elseif VehicleType == 21 then + ReturnedType = "train" + elseif VehicleType == 13 or VehicleType == 8 then + ReturnedType = "bike" + end + if Model == `submersible` or Model == `submersible2` then + ReturnedType = "submarine" + end + else + ReturnedType = false + end + TriggerServerEvent("esx:ReturnVehicleType", ReturnedType, Request) +end) local DoNotUse = { 'essentialmode', diff --git a/[esx]/es_extended/server/onesync.lua b/[esx]/es_extended/server/onesync.lua index 67a629d1..2ede0ff2 100644 --- a/[esx]/es_extended/server/onesync.lua +++ b/[esx]/es_extended/server/onesync.lua @@ -61,23 +61,29 @@ end ---@param heading number ---@param Properties table ---@param cb function -function ESX.OneSync.SpawnVehicle(model, coords, heading, Properties, cb) - model = type(model) == 'string' and joaat(model) or model - Properties = Properties or {} - local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) - TriggerClientEvent("esx:requestModel", -1, model) - CreateThread(function() - local xPlayer = ESX.OneSync.GetClosestPlayer(vector, 200) - ESX.GetVehicleType(model, xPlayer.id, function(Type) - local SpawnedEntity = CreateVehicleServerSetter(model, Type, vector, heading) - Wait(250) - local NetworkId = NetworkGetNetworkIdFromEntity(SpawnedEntity) - Properties.NetId = NetworkId - Entity(SpawnedEntity).state:set('VehicleProperties', Properties, true) - cb(NetworkId) - end) - end) -end + function ESX.OneSync.SpawnVehicle(model, coords, heading, Properties, cb) + local veh_model = type(model) == 'string' and joaat(model) or model + Properties = Properties or {} + local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z) + TriggerClientEvent("esx:requestModel", -1, model) + CreateThread(function() + local xPlayer = ESX.OneSync.GetClosestPlayer(vector, 300) + ESX.GetVehicleType(veh_model, xPlayer.id, function(Type) + if Type then + local SpawnedEntity = CreateVehicleServerSetter(veh_model, Type, vector, heading) + local NetworkId = NetworkGetNetworkIdFromEntity(SpawnedEntity) + while not DoesEntityExist(SpawnedEntity) do + Wait(100) + end + Properties.NetId = NetworkId + Entity(SpawnedEntity).state:set('VehicleProperties', Properties, true) + cb(NetworkId) + else + print(('[^1ERROR^7] Tried to spawn invalid vehicle - ^5%s^7!'):format(model)) + end + end) + end) + end ---@param model number|string From 8b466eb2b27a766401b3bf869c89f21b51dc07bc Mon Sep 17 00:00:00 2001 From: Amir_Lynx <60301485+AmirLynx@users.noreply.github.com> Date: Wed, 14 Dec 2022 17:40:03 +0330 Subject: [PATCH 45/83] refactor(esx_lscustom\server):fix nil table values --- [esx_addons]/esx_lscustom/server/main.lua | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/[esx_addons]/esx_lscustom/server/main.lua b/[esx_addons]/esx_lscustom/server/main.lua index a2f41376..9c0912ac 100644 --- a/[esx_addons]/esx_lscustom/server/main.lua +++ b/[esx_addons]/esx_lscustom/server/main.lua @@ -4,10 +4,10 @@ local Customs = {} RegisterNetEvent('esx_lscustom:startModing', function(props, netId) local src = tostring(source) if Customs[src] then - Customs[src][props.plate] = {props = props, netId = netId} + Customs[src][tostring(props.plate)] = {props = props, netId = netId} else Customs[src] = {} - Customs[src][props.plate] = {props = props, netId = netId} + Customs[src][tostring(props.plate)] = {props = props, netId = netId} end end) @@ -25,7 +25,7 @@ AddEventHandler('esx:playerDropped', function(src) for k,v in pairs(Customs[src]) do local entity = NetworkGetEntityFromNetworkId(v.netId) if DoesEntityExist(entity) then - if players > 0 then + if playersCount > 0 then TriggerClientEvent('esx_lscustom:restoreMods', -1, v.netId, v.props) else DeleteEntity(entity) @@ -70,16 +70,25 @@ AddEventHandler('esx_lscustom:buyMod', function(price) end) RegisterServerEvent('esx_lscustom:refreshOwnedVehicle') -AddEventHandler('esx_lscustom:refreshOwnedVehicle', function(vehicleProps) +AddEventHandler('esx_lscustom:refreshOwnedVehicle', function(vehicleProps, netId) + local src = tostring(source) local xPlayer = ESX.GetPlayerFromId(source) - MySQL.single('SELECT vehicle FROM owned_vehicles WHERE plate = ?', {vehicleProps.plate}, function(result) if result then local vehicle = json.decode(result.vehicle) if vehicleProps.model == vehicle.model then MySQL.update('UPDATE owned_vehicles SET vehicle = ? WHERE plate = ?', {json.encode(vehicleProps), vehicleProps.plate}) - Customs[tostring(source)][tostring(vehicleProps.plate)].props = props + if Customs[src] then + if Customs[src][tostring(vehicleProps.plate)] then + Customs[src][tostring(vehicleProps.plate)].props = vehicleProps + else + Customs[src][tostring(vehicleProps.plate)] = {props = vehicleProps, netId = netId} + end + else + Customs[src] = {} + Customs[src][tostring(vehicleProps.plate)] = {props = vehicleProps, netId = netId} + end else print(('[^3WARNING^7] Player ^5%s^7 Attempted To upgrade with mismatching vehicle model'):format(xPlayer.source)) end From 27462c40449acee9680e0b8c83927ceac07b170c Mon Sep 17 00:00:00 2001 From: Amir_Lynx <60301485+AmirLynx@users.noreply.github.com> Date: Wed, 14 Dec 2022 17:41:30 +0330 Subject: [PATCH 46/83] refactor(esx_lscustom\config):Missed vehicle price --- [esx_addons]/esx_lscustom/config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx_addons]/esx_lscustom/config.lua b/[esx_addons]/esx_lscustom/config.lua index 3ed2514d..c8983ed5 100644 --- a/[esx_addons]/esx_lscustom/config.lua +++ b/[esx_addons]/esx_lscustom/config.lua @@ -472,7 +472,7 @@ Config.Menus = { label = TranslateCap('transmission'), parent = 'upgrades', modType = 13, - price = {13.95, 20.93, 46.51} + price = {13.95, 20.93, 46.51, 63.55} }, modSuspension = { label = TranslateCap('suspension'), From 45f4db04ab4573a2bfbf4a8e2f36bd5b711f1e67 Mon Sep 17 00:00:00 2001 From: Amir_Lynx <60301485+AmirLynx@users.noreply.github.com> Date: Wed, 14 Dec 2022 17:42:01 +0330 Subject: [PATCH 47/83] refactor(esx_lscustom\client):Fixed netid --- [esx_addons]/esx_lscustom/client/main.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/[esx_addons]/esx_lscustom/client/main.lua b/[esx_addons]/esx_lscustom/client/main.lua index c5c79fd6..fefc6934 100644 --- a/[esx_addons]/esx_lscustom/client/main.lua +++ b/[esx_addons]/esx_lscustom/client/main.lua @@ -14,7 +14,7 @@ RegisterNetEvent('esx_lscustom:installMod') AddEventHandler('esx_lscustom:installMod', function() local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) myCar = ESX.Game.GetVehicleProperties(vehicle) - TriggerServerEvent('esx_lscustom:refreshOwnedVehicle', myCar) + TriggerServerEvent('esx_lscustom:refreshOwnedVehicle', myCar, NetworkGetNetworkIdFromEntity(vehicle)) end) RegisterNetEvent('esx_lscustom:restoreMods', function(netId, props) @@ -79,8 +79,8 @@ function OpenLSMenu(elems, menuName, menuTitle, parent) if data.current.label == TranslateCap('by_default') or string.match(data.current.label, TranslateCap('installed')) then ESX.ShowNotification(TranslateCap('already_own', data.current.label)) - myCar = ESX.Game.GetVehicleProperties(vehicle) - TriggerServerEvent('esx_lscustom:refreshOwnedVehicle', myCar) + myCar = ESX.Game.GetVehicleProperties(vehicle) + TriggerServerEvent('esx_lscustom:refreshOwnedVehicle', myCar, NetworkGetNetworkIdFromEntity(vehicle)) else local vehiclePrice = 50000 From 13281e60530d2fc558cf77508ad3920ea0452a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=20Gerg=C5=91?= <69343477+Rav3n95@users.noreply.github.com> Date: Thu, 15 Dec 2022 13:44:25 +0100 Subject: [PATCH 48/83] fix text ui again --- [esx]/esx_textui/TextUI.lua | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/[esx]/esx_textui/TextUI.lua b/[esx]/esx_textui/TextUI.lua index f63fcfcc..b70709f9 100644 --- a/[esx]/esx_textui/TextUI.lua +++ b/[esx]/esx_textui/TextUI.lua @@ -1,21 +1,19 @@ Debug = ESX.GetConfig().EnableDebug -local IsShowing = false +local isShowing = false ---@param message string ----@param Type string -local function TextUI(message, type) - IsShowing = true +---@param typ string +local function TextUI(message, typ) + isShowing = true SendNUIMessage({ action = 'show', message = message and message or 'ESX-TextUI', - type = type == 0 and "info" or type + type = type(typ) == "string" and typ or 'info' }) end local function HideUI() - if not IsShowing then - return - end - IsShowing = false + if not isShowing then return end + isShowing = false SendNUIMessage({ action = 'hide' }) From 213c68e3ee5d43b66d0fd933a5870861cadface9 Mon Sep 17 00:00:00 2001 From: Csoki Date: Thu, 15 Dec 2022 13:52:14 +0100 Subject: [PATCH 49/83] fix: setVehicleProps --- [esx]/es_extended/client/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx]/es_extended/client/functions.lua b/[esx]/es_extended/client/functions.lua index d59e240c..51b56020 100644 --- a/[esx]/es_extended/client/functions.lua +++ b/[esx]/es_extended/client/functions.lua @@ -877,7 +877,7 @@ function ESX.Game.SetVehicleProperties(vehicle, props) if props.extras ~= nil then for extraId, enabled in pairs(props.extras) do - SetVehicleExtra(vehicle, tonumber(extraId), enabled and 0 or 0) + SetVehicleExtra(vehicle, tonumber(extraId), enabled and 1 or 0) end end From 82c83cf884ed6e4b12e137df32dfc5ef70490a46 Mon Sep 17 00:00:00 2001 From: Csoki Date: Thu, 15 Dec 2022 13:59:03 +0100 Subject: [PATCH 50/83] esx_banking: remove unused xPlayer and event handle only if peds enabled --- [esx_addons]/esx_banking/server/main.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/[esx_addons]/esx_banking/server/main.lua b/[esx_addons]/esx_banking/server/main.lua index d4a34243..e61f7ee4 100644 --- a/[esx_addons]/esx_banking/server/main.lua +++ b/[esx_addons]/esx_banking/server/main.lua @@ -22,10 +22,11 @@ AddEventHandler('onResourceStop', function(resourceName) if Config.EnablePeds then BANK.DeletePeds() end end) -AddEventHandler('esx:playerLoaded', function(playerId, xPlayer) - if not Config.EnablePeds then return end - TriggerClientEvent('esx_banking:PedHandler', playerId, netIdTable) -end) +if Config.EnablePeds then + AddEventHandler('esx:playerLoaded', function(playerId) + TriggerClientEvent('esx_banking:PedHandler', playerId, netIdTable) + end) +end -- event RegisterServerEvent('esx_banking:doingType') From c26c2036a5294106e3fe6b086963cb89a650ac4a Mon Sep 17 00:00:00 2001 From: Csoki Date: Thu, 15 Dec 2022 14:07:13 +0100 Subject: [PATCH 51/83] fix: 'no object by ID' warning --- [esx_addons]/esx_banking/client/main.lua | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/[esx_addons]/esx_banking/client/main.lua b/[esx_addons]/esx_banking/client/main.lua index e87c5d55..a4c29f1e 100644 --- a/[esx_addons]/esx_banking/client/main.lua +++ b/[esx_addons]/esx_banking/client/main.lua @@ -197,11 +197,14 @@ RegisterNetEvent('esx_banking:closebanking', function() CloseUi() end) -RegisterNetEvent('esx_banking:PedHandler', function(netIdTable) - local npc - for i = 1, #netIdTable do - npc = NetworkGetEntityFromNetworkId(netIdTable[i]) - TaskStartScenarioInPlace(npc, Config.Peds[i].Scenario, 0, true) +local function loadNPC(index, netID) + CreateThread(function() + while not NetworkDoesEntityExistWithNetworkId(netID) do + Wait(1) + end + local npc = NetworkGetEntityFromNetworkId(netID) + + TaskStartScenarioInPlace(npc, Config.Peds[index].Scenario, 0, true) SetEntityProofs(npc, true, true, true, true, true, true, true, true) SetBlockingOfNonTemporaryEvents(npc, true) FreezeEntityPosition(npc, true) @@ -209,6 +212,12 @@ RegisterNetEvent('esx_banking:PedHandler', function(netIdTable) SetPedCanRagdoll(npc, false) SetEntityAsMissionEntity(npc, true, true) SetEntityDynamic(npc, false) + end) +end + +RegisterNetEvent('esx_banking:PedHandler', function(netIdTable) + for i = 1, #netIdTable do + loadNPC(i, netIdTable[i]) end end) From 702b64fe835f7d1c2d1845c7287fe90330a8ddce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AL1=C6=8EN?= <72218928+johnsoul777@users.noreply.github.com> Date: Thu, 15 Dec 2022 15:57:24 +0100 Subject: [PATCH 52/83] Create es.lua --- [esx_addons]/esx_property/es.lua | 217 +++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 [esx_addons]/esx_property/es.lua diff --git a/[esx_addons]/esx_property/es.lua b/[esx_addons]/esx_property/es.lua new file mode 100644 index 00000000..1a6e2bf5 --- /dev/null +++ b/[esx_addons]/esx_property/es.lua @@ -0,0 +1,217 @@ +Locales['es'] = { + --- CCTV Strings ------ + + ["take_picture"] = "Tomar foto", + ["rot_left_right"] = "Izquierda/Derecha", + ["rot_up_down"] = "Arriba/Abajo", + ["zoom"] = "Zoom +/-", + ["zoom_level"] = "Nivel de Zoom: %s %%", + ["night_vision"] = "Alternar Visión Nocturna", + ["clipboard"] = "Enlace copiado al ~b~Portapapeles", + ["picture_taken"] = "¡Foto tomada!", + ["please_wait"] = "Espere antes de tomar otra ~b~Foto", + ["exit"] = "Salir", + + --- Furniture Strings ------ + + ["height"] = "Altura", + ["rotate"] = "Rotación", + ["place"] = "Colocar mueble", + ["delete_furni"] = "Borrar", + ["confirm_buy"] = "¿Quieres comprar %s?", + ["price"] = "Precio: $%s", + ["yes"] = "Si", + ["no"] = "No", + ["action"] = "¡ Tu %s ~b~%s~s~ !", + ["bought_furni"] = "¡ Has ~g~comprado~s~ un ~b~%s~s~ !", + ["edited_furni"] = "¡ Has editado ~b~%s~s~ !", + ["cannot_buy"] = "¡~r~No puedes~s~ comprar esto!", + ["cannot_edit"] = "¡Usted ~r~no puede~s~ editar esto!", + ["store_title"] = "Tienda - %s", + ["back"] = "Volver", + ["edit_title"] = "Edición - %s", + ["move_title"] = "Mover", + ["delete_confirm"] = "¡Borrado ~b~%s~s~!", + ["delete_error"] = "No se puede borrar ~b~%s~s~!", + ["owned_furni"] = "Mobiliario propio", + ["menu_stores"] = "Tiendas de muebles", + ["menu_stores_desc"] = "Comprar mueble", + ["menu_reset"] = "Reiniciar", + ["menu_reset_desc"] = "Limpia todos los muebles", + ["menu_edit"] = "Editar", + ["menu_edit_desc"] = "Mover y/o Eliminar muebles", + ["furni_command"] = "muebles", + ["furni_command_desc"] = "Abrir menú de muebles", + ["furni_command_permission"] = "~r~No~s~ puede acceder a este menú.", + ["furni_reset_success"] = "¡Todos los muebles reiniciados!", + ["furni_cannot_afford"] = "¡Usted no puede permitirse el lujo de hacer esto!", + ["furni_reset_error"] = "~r~No puede~s~ ¡Restablecer esta propiedad!", + ["furni_management"] = "Administrar muebles", + + --------- Key Strings --------------- + + ["you_granted"] = 'Se le han otorgado llaves a ~b~%s~s~.', + ["already_has"] = "¡Este jugador ya tiene llaves!", + ["do_not_own"] = 'Usted ~r~no~s~ es dueño de esta propiedad.', + ["key_revoked"] = 'Su llave de acceso a ~b~%s~s~. ha sido ~r~revocada~s~', + ["no_keys"] = "¡Este jugador no tiene llaves!", + ["nearby"] = "Jugadores cercanos", + ["gave_key"] = "Entrega de llaves a %s!", + ["key_cannot_give"] = "No puedes darle a este jugador una ~r~Llave", + ["remove_title"] = "Eliminar llaves del jugador", + ["key_revoke_success"] = "Revocación de llaves de ~b~%s~s~.", + ["key_revoke_error"] = "No puede ~b~quitar~s~ las ~r~llave~s~ a esta persona", + ["key_management"] = "Gestión de llaves", + ["key_management_desc"] = "Controlar el acceso a la propiedad.", + ["give_keys"] = "Dar llaves", + ["remove_keys"] = "Quitar llaves", + + --------- Real Estate Strings --------------- + + ["office_blip"] = "Oficina de %s", + ["actions"] = "Acciones Inmobiliarias", + ["property_create"] = "Crear propiedad", + ["property_manage"] = "Administrar propiedades", + ["realestate_command"] = "realestatequickmenu", + ["realestate_command_desc"] = "(ESX Property) Abrir acciones rápidas inmobiliarias", + ["enter_office"] = "~b~Entrando~a~la oficina.", + ["enter_office_error"] = "¡Usted ~r~no puede~s~ entrar en la oficina!", + ["exit_office"] = "~b~Saliendo~s~ de la oficina.", + ["exit_office_error"] = "¡Usted ~r~no puede~s~ salir de la oficina!", + ["realestate_textui"] = "Presione ~b~[E]~s~ para acceder ~b~%s", + + ------------Command Strings------------------------------- + + ["refresh_name"] = "property:refresh", + ["refresh_desc"] = "Actualizar al estado de inicio del servidor", + ["save_name"] = "property:save", + ["save_desc"] = "Forzar guardar propiedades", + ["create_name"] = "property:create", + ["create_desc"] = "Crear una nueva propiedad", + ["admin_name"] = "property:admin", + ["admin_desc"] = "Administrar/ver todas las propiedades", + + ---------- Property Actions Menu ------------------------- + + ["knocking"] = "Alguien Está ~b~Llamando~s~ A La Puerta.", + ["name_edit"] = "Editar nombre de propiedad", + ["name"] = "Nombre", + ["confirm"] = "Confirmar", + ["name_edit_success"] = "Ha establecido el nombre de la propiedad a ~b~%s~s~.", + ["name_edit_error"] = "No puede establecer el nombre de la propiedad a ~r~%s~s~.", + ["door_locked"] = "Puerta: cerrada", + ["door_unlocked"] = "Puerta: abierta", + ["name_manage"] = "Administrar nombre", + ["name_manage_desc"] = "Establezca el nombre de la propiedad.", + ["sell_title"] = "Vender", + ["sell_desc"] = "Vender esta propiedad por $%s", + ["raid_title"] = "Redada", + ["raid_desc"] = "Forzar la entrada a la propiedad.", + ["cctv_title"] = "CCTV", + ["cctv_desc"] = "Compruebe el circuito cerrado de televisión.", + ["inventory_title"] = "Inventario", + ["inventory_desc"] = "Cambiar la posición del inventario de propiedad.", + ["wardrobe_title"] = "Armario", + ["wardrobe_desc"] = "Cambiar la posición del armario de la propiedad.", + ["furniture_title"] = "Muebles", + ["furniture_desc"] = "Cambiar Posición de Mobiliario de Propiedad.", + ["enter_title"] = "Entrar", + ["knock_title"] = "Tocar la puerta", + ["buy_title"] = "Comprar", + ["buy_desc"] = "Compre esta propiedad por $%s", + ["sellplayer_title"] = "Vender al jugador", + ["sellplayer_desc"] = "Vender esta propiedad por $%s", + ["view_title"] = "Vista previa del interior", + ["exit_title"] = "Salir", + ["property_editing_error"] = "Actualmente está editando la propiedad.", + ["unlock_error"] = "No puede ~b~desbloquear~s~ esta propiedad", + ["lock_error"] = "No puede ~bloquear~a~ esta propiedad", + ["prep_raid"] = "¡~b~Preparando~s~ Redada!", + ["raiding"] = "Asaltando...", + ["cancel_raiding"] = "¡Redada ~r~Cancelada~s~!", + ["cannot_raid"] = "No puedes ~b~Asaltar~s~ esta propiedad.", + ["storage_pos_textui"] = "Presione ~b~[G]~s~ para establecer la posición del inventario", + ["storage_pos_success"] = "Posición del ~b~Inventario~s~ establecida.", + ["storage_pos_error"] = "~r~No se puede~s~ establecer la posición de ~b~inventario~s~.", + ["wardrobe_pos_textui"] = "Presione ~b~[G]~s~ para establecer la posición del Armario", + ["wardrobe_pos_success"] = "Posición del ~b~Armario~s~ establecida.", + ["wardrobe_pos_error"] = "~r~No se puede~s~ establecer la posición de ~b~armario~s~.", + ["please_finish"] = "Finalice la configuración de posición de ~b~%s~s~", + ["cannot_afford"] = "¡Usted no puede comprar esta propiedad!", + ["select_player"] = "Seleccionar jugador", + ["cannot_sell"] = "¡No se puede vender a este jugador!", + ["knock_on_door"] = "Llamando a la puerta...", + ["nobody_home"] = "Parece que nadie está en casa...", + + ---------- General Strings ---------------- + + ["enabled"] = "Activado", + ["disabled"] = "Desactivado", + ["exiting"] = "Saliendo de la propiedad...", + ["entering"] = "Entrando a la propiedad...", + ["shell_disabled"] = "¡Este interior usa shells, que están deshabilitados!", + ["access_textui"] = "Pulsa ~b~[E]~s~ para acceder ~b~%s", + ["raid_notify_error"] = "Necesitas ~b~ %sx %s~s~ para poder asaltar!", + ["raid_notify_success"] = "¡Su propiedad está siendo actualmente ~b~Asaltada!", + + --------------- Garage Strings -------------- + + ["store_success"] = "Vehículo ~b~¡Almacenado!", + ["store_error"] = "¡No puede almacenar este vehículo!", + ["property_garage"] = "Garaje de propiedad", + ["retriving_notify"] = "Sacando ~b~%s~s~ ...", + ["cannot_access"] = "¡No puede acceder a este garaje!", + ["store_textui"] = "Pulsa ~b~[E]~s~ para almacenar ~b~%s", + ["garage_not_enabled"] = 'Garaje No Habilitado En Esta Propiedad.', + ["cannot_access_property"] = '~r~No puede~s~ Acceder a esta propiedad.', + + ----------------- Creation Menu Strings ---------------- + + ["menu_title"] = "Creación de propiedad", + ["element_title1"] = "Número de calle", + ["element_description1"] = "Establezca el número de calle de la propiedad.", + ["element_title2"] = "Precio", + ["element_description2"] = "Fijar el Precio de la Propiedad.", + ["element_title3"] = "Interior", + ["element_description3"] = "Seleccione un interior para la propiedad", + ["element_title4"] = "Garaje", + ["element_description4"] = "(Opcional) Administrar la configuración del garaje", + ["element_title5"] = "CCTV", + ["element_description5"] = "(Opcional) Administrar la configuración de CCTV", + ["element_title6"] = "Entrada", + ["element_description6"] = "Establezca la ubicación de entrada de la propiedad.", + ["element_create_title"] = "Crear propiedad", + ["element_create_desc_1"] = "¡Complete todas las entradas requeridas!", + ["entrance_set_title"] = "Entrada establecida.", + ["entrance_set_description"] = "Entrada: %s, %s, %s", + ["interior_set_title"] = "Interior seleccionado.", + ["interior_set_description"] = "Selected: %s", + ["ipl_title"] = "Interiores IPL", + ["types_title"] = "Tipos de interiores", + ["ipl_description"] = "Interiores nativos de GTA, Hecho por R*", + ["shell_title"] = "Interiores personalizados", + ["shell_description"] = "Interiores personalizados, hechos por Ti", + ["cctv_settings"] = "Ajustes CCTV", + ["garage_settings"] = "Configuración del garaje", + ["toggle_title"] = "Alternar uso", + ["toggle_description"] = "Estado actual: %s", + ["cctv_set_title"] = "Establecer angulo de CCTV", + ["cctv_set_description"] = "Establece el angulo de las cámaras para tus direcciones de Cámaras", + ["back_description"] = "Volver a la creación de propiedad.", + ["garage_set_title"] = "Establecer posición de garaje", + ["garage_set_description"] = "Establece la posición del garaje de la propiedad.", + ["garage_textui"] = "Presione ~b~[E]~s~ para establecer la posición", + ["cctv_textui_1"] = "Presione ~b~[E]~s~ para establecer el ángulo", + ["cctv_textui_2"] = "Presione ~b~[E]~s~ para establecer la rotación máxima a la derecha", + ["cctv_textui_3"] = "Presione ~b~[E]~s~ para establecer la rotación máxima a la izquierda", + ["create_success"] = "¡Propiedad creada!", + ["missing_data"] = "¡Complete todas las entradas requeridas!", + + -- Saving Translations + ["server_restart"] = "Reinicio del servidor", + ["server_shutdown"] = "Apagado del servidor", + ["manual_save"] = "Guardado manual (solicitado por %s)", + ["resource_stop"] = "Detención de recurso", + ["force_save"] = "Forzar guardado (solicitado por %s)", + ["interval_saving"] = "Intervalo de Guardado" +} From ca0c535ea944cfc70c6a2bf9f223294338600123 Mon Sep 17 00:00:00 2001 From: Csoki Date: Thu, 15 Dec 2022 20:44:38 +0100 Subject: [PATCH 53/83] refactor: es_extended weapon functions --- [esx]/es_extended/common/functions.lua | 50 ++++++++++++++------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/[esx]/es_extended/common/functions.lua b/[esx]/es_extended/common/functions.lua index 2282e630..b3074c8a 100644 --- a/[esx]/es_extended/common/functions.lua +++ b/[esx]/es_extended/common/functions.lua @@ -4,6 +4,16 @@ for i = 48, 57 do table.insert(Charset, string.char(i)) end for i = 65, 90 do table.insert(Charset, string.char(i)) end for i = 97, 122 do table.insert(Charset, string.char(i)) end +local weaponsByName = {} +local weaponsByHash = {} + +CreateThread(function() + for index, weapon in pairs(Config.Weapons) do + weaponsByName[weapon.name] = index + weaponsByHash[joaat(weapon.name)] = weapon + end +end) + function ESX.GetRandomString(length) math.randomseed(GetGameTimer()) @@ -17,19 +27,16 @@ end function ESX.GetWeapon(weaponName) weaponName = string.upper(weaponName) - for k,v in ipairs(Config.Weapons) do - if v.name == weaponName then - return k, v - end - end + assert(weaponsByName[weaponName], "Invalid weapon name!") + + local index = weaponsByName[weaponName] + return index, Config.Weapons[index] end function ESX.GetWeaponFromHash(weaponHash) - for k,v in ipairs(Config.Weapons) do - if joaat(v.name) == weaponHash then - return v - end - end + weaponHash = type(weaponHash) == "string" and joaat(weaponHash) or weaponHash + + return weaponsByHash[weaponHash] end function ESX.GetWeaponList() @@ -39,24 +46,21 @@ end function ESX.GetWeaponLabel(weaponName) weaponName = string.upper(weaponName) - for k,v in ipairs(Config.Weapons) do - if v.name == weaponName then - return v.label - end - end + assert(weaponsByName[weaponName], "Invalid weapon name!") + + local index = weaponsByName[weaponName] + return Config.Weapons[index].label or "" end function ESX.GetWeaponComponent(weaponName, weaponComponent) weaponName = string.upper(weaponName) - local weapons = Config.Weapons - for k,v in ipairs(Config.Weapons) do - if v.name == weaponName then - for k2,v2 in ipairs(v.components) do - if v2.name == weaponComponent then - return v2 - end - end + assert(weaponsByName[weaponName], "Invalid weapon name!") + local weapon = Config.Weapons[weaponsByName[weaponName]] + + for _, component in ipairs(weapon.components) do + if component.name == weaponComponent then + return component end end end From 44a0021b7bfeb35b8faef0b83656ec4a8f796613 Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Fri, 16 Dec 2022 09:21:19 +0530 Subject: [PATCH 54/83] fix: Moved checks to if xPlayer isn't nil --- [esx]/esx_identity/server/main.lua | 42 ++++++++++++++---------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/[esx]/esx_identity/server/main.lua b/[esx]/esx_identity/server/main.lua index 08ed89c9..f15671d7 100644 --- a/[esx]/esx_identity/server/main.lua +++ b/[esx]/esx_identity/server/main.lua @@ -373,29 +373,27 @@ else ESX.RegisterServerCallback('esx_identity:registerIdentity', function(source, cb, data) local xPlayer = ESX.GetPlayerFromId(source) - - if not checkNameFormat(data.firstname) then - xPlayer.showNotification(TranslateCap('invalid_firstname_format'), "error") - return cb(false) - end - if not checkNameFormat(data.lastname) then - xPlayer.showNotification(TranslateCap('invalid_lastname_format'), "error") - return cb(false) - end - if not checkSexFormat(data.sex) then - xPlayer.showNotification(TranslateCap('invalid_sex_format'), "error") - return cb(false) - end - if not checkDOBFormat(data.dateofbirth) then - xPlayer.showNotification(TranslateCap('invalid_dob_format'), "error") - return cb(false) - end - if not checkHeightFormat(data.height) then - xPlayer.showNotification(TranslateCap('invalid_height_format'), "error") - return cb(false) - end - if xPlayer then + if not checkNameFormat(data.firstname) then + xPlayer.showNotification(TranslateCap('invalid_firstname_format'), "error") + return cb(false) + end + if not checkNameFormat(data.lastname) then + xPlayer.showNotification(TranslateCap('invalid_lastname_format'), "error") + return cb(false) + end + if not checkSexFormat(data.sex) then + xPlayer.showNotification(TranslateCap('invalid_sex_format'), "error") + return cb(false) + end + if not checkDOBFormat(data.dateofbirth) then + xPlayer.showNotification(TranslateCap('invalid_dob_format'), "error") + return cb(false) + end + if not checkHeightFormat(data.height) then + xPlayer.showNotification(TranslateCap('invalid_height_format'), "error") + return cb(false) + end if alreadyRegistered[xPlayer.identifier] then xPlayer.showNotification(TranslateCap('already_registered'), "error") return cb(false) From 9a5bef10999f0f89a0b8c57067d40dc72cd1d43d Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Fri, 16 Dec 2022 09:34:45 +0530 Subject: [PATCH 55/83] Update main.lua --- [esx]/esx_identity/server/main.lua | 42 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/[esx]/esx_identity/server/main.lua b/[esx]/esx_identity/server/main.lua index f15671d7..5b15086d 100644 --- a/[esx]/esx_identity/server/main.lua +++ b/[esx]/esx_identity/server/main.lua @@ -373,27 +373,27 @@ else ESX.RegisterServerCallback('esx_identity:registerIdentity', function(source, cb, data) local xPlayer = ESX.GetPlayerFromId(source) - if xPlayer then - if not checkNameFormat(data.firstname) then - xPlayer.showNotification(TranslateCap('invalid_firstname_format'), "error") - return cb(false) - end - if not checkNameFormat(data.lastname) then - xPlayer.showNotification(TranslateCap('invalid_lastname_format'), "error") - return cb(false) - end - if not checkSexFormat(data.sex) then - xPlayer.showNotification(TranslateCap('invalid_sex_format'), "error") - return cb(false) - end - if not checkDOBFormat(data.dateofbirth) then - xPlayer.showNotification(TranslateCap('invalid_dob_format'), "error") - return cb(false) - end - if not checkHeightFormat(data.height) then - xPlayer.showNotification(TranslateCap('invalid_height_format'), "error") - return cb(false) - end + if not checkNameFormat(data.firstname) then + TriggerClientEvent('esx:showNotification',source,(TranslateCap('invalid_firstname_format'), "error") + return cb(false) + end + if not checkNameFormat(data.lastname) then + TriggerClientEvent('esx:showNotification',source,TranslateCap('invalid_lastname_format'), "error") + return cb(false) + end + if not checkSexFormat(data.sex) then + TriggerClientEvent('esx:showNotification',source,TranslateCap('invalid_sex_format'), "error") + return cb(false) + end + if not checkDOBFormat(data.dateofbirth) then + TriggerClientEvent('esx:showNotification',source,TranslateCap('invalid_dob_format'), "error") + return cb(false) + end + if not checkHeightFormat(data.height) then + TriggerClientEvent('esx:showNotification',source,TranslateCap('invalid_height_format'), "error") + return cb(false) + end + if xPlayer then if alreadyRegistered[xPlayer.identifier] then xPlayer.showNotification(TranslateCap('already_registered'), "error") return cb(false) From bdcd53307af660c287455d197788727e3b1f883e Mon Sep 17 00:00:00 2001 From: Alessandro Alterno <28725795+lexinor@users.noreply.github.com> Date: Fri, 16 Dec 2022 10:38:05 +0100 Subject: [PATCH 56/83] Changed PK in vehicle_sold --- [SQL]/legacy.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/[SQL]/legacy.sql b/[SQL]/legacy.sql index 4fb035d1..b68e02e2 100644 --- a/[SQL]/legacy.sql +++ b/[SQL]/legacy.sql @@ -709,11 +709,13 @@ INSERT INTO `vehicle_categories` (`name`, `label`) VALUES -- CREATE TABLE `vehicle_sold` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, `client` varchar(50) NOT NULL, `model` varchar(50) NOT NULL, `plate` varchar(50) NOT NULL, `soldby` varchar(50) NOT NULL, - `date` varchar(50) NOT NULL + `date` varchar(50) NOT NULL, + PRIMARY KEY (`id`) ) ENGINE=InnoDB; -- From a9562d97d47a118ce9a7f910f0fc2a4cdba4a037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=20Gerg=C5=91?= <69343477+Rav3n95@users.noreply.github.com> Date: Fri, 16 Dec 2022 16:44:22 +0100 Subject: [PATCH 57/83] fix typo --- [esx]/esx_identity/server/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx]/esx_identity/server/main.lua b/[esx]/esx_identity/server/main.lua index 5b15086d..b9513cee 100644 --- a/[esx]/esx_identity/server/main.lua +++ b/[esx]/esx_identity/server/main.lua @@ -374,7 +374,7 @@ else ESX.RegisterServerCallback('esx_identity:registerIdentity', function(source, cb, data) local xPlayer = ESX.GetPlayerFromId(source) if not checkNameFormat(data.firstname) then - TriggerClientEvent('esx:showNotification',source,(TranslateCap('invalid_firstname_format'), "error") + TriggerClientEvent('esx:showNotification',source,TranslateCap('invalid_firstname_format'), "error") return cb(false) end if not checkNameFormat(data.lastname) then From 9c3c225b11da9f40011ab639dec00670be543508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=20Gerg=C5=91?= <69343477+Rav3n95@users.noreply.github.com> Date: Fri, 16 Dec 2022 17:20:54 +0100 Subject: [PATCH 58/83] refactor playerclass --- [esx]/es_extended/server/classes/player.lua | 1085 ++++++++++--------- 1 file changed, 566 insertions(+), 519 deletions(-) diff --git a/[esx]/es_extended/server/classes/player.lua b/[esx]/es_extended/server/classes/player.lua index 39e303cf..14b1eb9a 100644 --- a/[esx]/es_extended/server/classes/player.lua +++ b/[esx]/es_extended/server/classes/player.lua @@ -1,400 +1,425 @@ -local SetTimeout = SetTimeout -local GetPlayerPed = GetPlayerPed -local DoesEntityExist = DoesEntityExist -local GetEntityCoords = GetEntityCoords -local GetEntityHeading = GetEntityHeading - function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, weight, job, loadout, name, coords) local targetOverrides = Config.PlayerFunctionOverride and Core.PlayerFunctionOverrides[Config.PlayerFunctionOverride] or {} - - local self = {} + local xPlayer = { + accounts = accounts, + coords = coords, + group = group, + identifier = identifier, + inventory = inventory, + job = job, + loadout = loadout, + name = name, + playerId = playerId, + source = playerId, + ped = GetPlayerPed(playerId), + variables = {}, + weight = weight, + maxWeight = Config.MaxWeight, + license = Config.Multichar and 'license'.. identifier:sub(identifier:find(':'), identifier:len()) or 'license:'..identifier, - self.accounts = accounts - self.coords = coords - self.group = group - self.identifier = identifier - self.inventory = inventory - self.job = job - self.loadout = loadout - self.name = name - self.playerId = playerId - self.source = playerId - self.variables = {} - self.weight = weight - self.maxWeight = Config.MaxWeight - if Config.Multichar then self.license = 'license'.. identifier:sub(identifier:find(':'), identifier:len()) else self.license = 'license:'..identifier end + triggerEvent = function (self, eventName, ...) + TriggerClientEvent(eventName, self.playerId, ...) + end, - ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) - - Player(self.source).state:set("identifier", self.identifier, true) - Player(self.source).state:set("license", self.license, true) - Player(self.source).state:set("job", self.job, true) - Player(self.source).state:set("group", self.group, true) - Player(self.source).state:set("name", self.name, true) - - function self.triggerEvent(eventName, ...) - TriggerClientEvent(eventName, self.source, ...) - end - - function self.setCoords(coords) - local Ped = GetPlayerPed(self.source) - local vector = type(coords) == "vector4" and coords or type(coords) == "vector3" and vector4(coords, 0.0) or - vec(coords.x, coords.y, coords.z, coords.heading or 0.0) - SetEntityCoords(Ped, vector.xyz, false, false, false, false) - SetEntityHeading(Ped, vector.w) - end - - function self.updateCoords() - SetTimeout(1000,function() - local Ped = GetPlayerPed(self.source) - if DoesEntityExist(Ped) then - local coords = GetEntityCoords(Ped) - local distance = #(coords - vector3(self.coords.x, self.coords.y, self.coords.z)) - if distance > 1.5 then - local heading = GetEntityHeading(Ped) - self.coords = { - x = coords.x, - y = coords.y, - z = coords.z, - heading = heading or 0.0 - } + updatePed = function(self) + SetTimeout(1000,function() + if self.ped ~= GetPlayerPed(self.playerId) then + self.ped = GetPlayerPed(self.playerId) + self:triggerEvent('esx:updatePed', self.ped) + TriggerEvent('esx:updatePed', self.playerId, self.ped) + Player(self.playerId).state:set("ped", self.ped, true) end - end - self.updateCoords() - end) - end + self:updatePed() + end) + end, - function self.getCoords(vector) - if vector then - return vector3(self.coords.x, self.coords.y, self.coords.z) - else - return self.coords - end - end + getPed = function(self) + return self.ped + end, - function self.kick(reason) - DropPlayer(self.source, reason) - end + setCoords = function(self, coord) + local vector = type(coord) == "vector4" and coord or type(coord) == "vector3" and vector4(coord, 0.0) or + vec(coord.x, coord.y, coord.z, coord.w or 0.0) + SetEntityCoords(self.ped, vector.x, vector.y, vector.z, false, false, false, false) + SetEntityHeading(self.ped, vector.w) + end, - function self.setMoney(money) - money = ESX.Math.Round(money) - self.setAccountMoney('money', money) - end + updateCoords = function(self) + SetTimeout(1000,function() + if DoesEntityExist(self.ped) then + local coord = GetEntityCoords(self.ped) + local distance = #(coord - vector3(self.coords.x, self.coords.y, self.coords.z)) + if distance > 1.5 then + local heading = GetEntityHeading(self.ped) + self.coords = { + x = coords.x, + y = coords.y, + z = coords.z, + heading = heading or 0.0 + } + end + end + self:updateCoords() + end) + end, - function self.getMoney() - return self.getAccount('money').money - end + getCoords = function(self, vector) + return vector and vector3(self.coords.x, self.coords.y, self.coords.z) or self.coords + end, - function self.addMoney(money, reason) - money = ESX.Math.Round(money) - self.addAccountMoney('money', money, reason) - end - - function self.removeMoney(money, reason) - money = ESX.Math.Round(money) - self.removeAccountMoney('money', money, reason) - end - - function self.getIdentifier() - return self.identifier - end - - function self.setGroup(newGroup) - ExecuteCommand(('remove_principal identifier.%s group.%s'):format(self.license, self.group)) - self.group = newGroup - Player(self.source).state:set("group", self.group, true) - ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) - end - - function self.getGroup() - return self.group - end - - function self.set(k, v) - self.variables[k] = v - Player(self.source).state:set(k, v, true) - end - - function self.get(k) - return self.variables[k] - end - - function self.getAccounts(minimal) - if minimal then - local minimalAccounts = {} + kick = function(self, reason) + DropPlayer(self.playerId, reason) + end, + getAccount = function(self, account) for i=1, #self.accounts do - minimalAccounts[self.accounts[i].name] = self.accounts[i].money + if self.accounts[i].name == account then + return self.accounts[i] + end + end + end, + + getAccounts = function(self, minimal) + if minimal then + local minimalAccounts = {} + + for i=1, #self.accounts do + minimalAccounts[self.accounts[i].name] = self.accounts[i].money + end + + return minimalAccounts + else + return self.accounts + end + end, + + setAccountMoney = function(self, accountName, amount, reason) + reason = reason or 'unknown' + if not tonumber(amount) then + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) + return + end + if amount >= 0 then + local account = self:getAccount(accountName) + + if account then + amount = account.round and ESX.Math.Round(amount) or amount + self.accounts[account.index].money = amount + self:triggerEvent('esx:setAccountMoney', account) + TriggerEvent('esx:setAccountMoney', self.playerId, accountName, amount, reason) + else + print(('[^1ERROR^7] Tried To Set Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + end + else + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) + end + end, + + addAccountMoney = function(self, accountName, amount, reason) + reason = reason or 'Unknown' + if not tonumber(amount) then + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) + return + end + if amount > 0 then + local account = self:getAccount(accountName) + if account then + amount = account.round and ESX.Math.Round(amount) or amount + self.accounts[account.index].money += amount + self:triggerEvent('esx:setAccountMoney', account) + TriggerEvent('esx:addAccountMoney', self.playerId, accountName, amount, reason) + else + print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + end + else + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) + end + end, + + removeAccountMoney = function(self, accountName, amount, reason) + reason = reason or 'Unknown' + if not tonumber(amount) then + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) + return + end + if amount > 0 then + local account = self:getAccount(accountName) + + if account then + amount = account.round and ESX.Math.Round(amount) or amount + self.accounts[account.index].money -= amount + self:triggerEvent('esx:setAccountMoney', account) + TriggerEvent('esx:removeAccountMoney', self.playerId, accountName, amount, reason) + else + print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + end + else + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) + end + end, + + setMoney = function (self, amount) + amount = ESX.Math.Round(amount) + self:setAccountMoney('money', amount) + end, + + getMoney = function(self) + return self:getAccount('money').money + end, + + addMoney = function(self, amount, reason) + amount = ESX.Math.Round(amount) + self:addAccountMoney('money', amount, reason) + end, + + removeMoney = function(self, amount, reason) + amount = ESX.Math.Round(amount) + self:removeAccountMoney('money', amount, reason) + end, + + getGroup = function(self) + return self.group + end, + + setGroup = function(self, newGroup) + ExecuteCommand(('remove_principal identifier.%s group.%s'):format(self.license, self.group)) + self.group = newGroup + Player(self.playerId).state:set("group", self.group, true) + ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) + end, + + getIdentifier = function(self) + return self.identifier + end, + + set = function(self, key, value) + self.variables[key] = value + Player(self.playerId).state:set(key, value, true) + end, + + get = function(self, key) + return self.variables[key] + end, + + getJob = function(self) + return self.job + end, + + setJob = function(self, jobName, grade) + grade = tostring(grade) + local lastJob = json.decode(json.encode(self.job)) + + if ESX.DoesJobExist(jobName, grade) then + local jobObject, gradeObject = ESX.Jobs[jobName], ESX.Jobs[jobName].grades[grade] + + self.job.id = jobObject.id + self.job.name = jobObject.name + self.job.label = jobObject.label + + self.job.grade = tonumber(grade) + self.job.grade_name = gradeObject.name + self.job.grade_label = gradeObject.label + self.job.grade_salary = gradeObject.salary + + if gradeObject.skin_male then + self.job.skin_male = json.decode(gradeObject.skin_male) + else + self.job.skin_male = {} + end + + if gradeObject.skin_female then + self.job.skin_female = json.decode(gradeObject.skin_female) + else + self.job.skin_female = {} + end + + TriggerEvent('esx:setJob', self.playerId, self.job, lastJob) + self:triggerEvent('esx:setJob', self.job) + Player(self.playerId).state:set("job", self.job, true) + else + print(('[es_extended] [^3WARNING^7] Ignoring invalid ^5:setJob()^7 usage for ID: ^5%s^7, Job: ^5%s^7'):format(self.playerId, job)) + end + end, + + getName = function(self) + return self.name + end, + + setName = function(self, newName) + self.name = newName + Player(self.playerId).state:set("name", newName, true) + end, + + getWeight = function(self) + return self.weight + end, + + getMaxWeight = function(self) + return self.maxWeight + end, + + setMaxWeight = function(self, newWeight) + self.maxWeight = newWeight + Player(self.playerId).state:set("maxWeight", newWeight, true) + self:triggerEvent('esx:setMaxWeight', newWeight) + end, + + getInventory = function(self, minimal) + if minimal then + local minimalInventory = {} + + for _, v in ipairs(self.inventory) do + if v.count > 0 then + minimalInventory[v.name] = v.count + end + end + + return minimalInventory end - return minimalAccounts - else - return self.accounts - end - end + return self.inventory + end, - function self.getAccount(account) - for i=1, #self.accounts do - if self.accounts[i].name == account then - return self.accounts[i] + getInventoryItem = function(self, item, metadata) + for _,v in ipairs(self.inventory) do + if v.name == item then + return v + end end - end - end + end, - function self.getInventory(minimal) - if minimal then - local minimalInventory = {} + addInventoryItem = function(self, itemName, count, metadata, slot) + local item = self:getInventoryItem(itemName) - for k, v in ipairs(self.inventory) do - if v.count > 0 then - minimalInventory[v.name] = v.count + if item then + count = ESX.Math.Round(count) + item.count = item.count + count + self.weight = self.weight + (item.weight * count) + TriggerEvent('esx:onAddInventoryItem', self.playerId, item.name, item.count) + self:triggerEvent('esx:addInventoryItem', item.name, item.count) + Player(self.playerId).state:set("weight", self.weight, true) + end + end, + + removeInventoryItem = function(self, itemName, count, metadata, slot) + local item = self:getInventoryItem(itemName) + + if item then + count = ESX.Math.Round(count) + local newCount = item.count - count + + if newCount >= 0 then + item.count = newCount + self.weight = self.weight - (item.weight * count) + TriggerEvent('esx:onRemoveInventoryItem', self.playerId, item.name, item.count) + self:triggerEvent('esx:removeInventoryItem', item.name, item.count) + Player(self.playerId).state:set("weight", self.weight, true) + end + end + end, + + setInventoryItem = function(self, itemName, count, metadata) + local item = self:getInventoryItem(itemName) + + if item and count >= 0 then + count = ESX.Math.Round(count) + + if count > item.count then + self:addInventoryItem(item.name, count - item.count) + else + self:removeInventoryItem(item.name, item.count - count) + end + end + end, + + canCarryItem = function(self, itemName, count, metadata) + if ESX.Items[itemName] then + local currentWeight, itemWeight = self.weight, ESX.Items[itemName].weight + local newWeight = currentWeight + (itemWeight * count) + + return newWeight <= self.maxWeight + else + print(('[^3WARNING^7] Item ^5"%s"^7 was used but does not exist!'):format(itemName)) + end + end, + + canSwapItem = function(self, firstItem, firstItemCount, testItem, testItemCount) + local firstItemObject = self:getInventoryItem(firstItem) + local testItemObject = self:getInventoryItem(testItem) + + if firstItemObject.count >= firstItemCount then + local weightWithoutFirstItem = ESX.Math.Round(self.weight - (firstItemObject.weight * firstItemCount)) + local weightWithTestItem = ESX.Math.Round(weightWithoutFirstItem + (testItemObject.weight * testItemCount)) + + return weightWithTestItem <= self.maxWeight + end + + return false + end, + + hasItem = function(self, itemName, metadata) + for _, v in ipairs(self.inventory) do + if (v.name == itemName) and (v.count >= 1) then + return v, v.count end end - return minimalInventory - end + return false + end, - return self.inventory - end + getLoadout = function(self, minimal) + if minimal then + local minimalLoadout = {} - function self.getJob() - return self.job - end + for _, v in ipairs(self.loadout) do + minimalLoadout[v.name] = {ammo = v.ammo} + if v.tintIndex > 0 then minimalLoadout[v.name].tintIndex = v.tintIndex end - function self.getLoadout(minimal) - if minimal then - local minimalLoadout = {} + if #v.components > 0 then + local components = {} - for k,v in ipairs(self.loadout) do - minimalLoadout[v.name] = {ammo = v.ammo} - if v.tintIndex > 0 then minimalLoadout[v.name].tintIndex = v.tintIndex end + for _, component in ipairs(v.components) do + if component ~= 'clip_default' then + components[#components + 1] = component + end + end - if #v.components > 0 then - local components = {} - - for k2,component in ipairs(v.components) do - if component ~= 'clip_default' then - components[#components + 1] = component + if #components > 0 then + minimalLoadout[v.name].components = components end end + end - if #components > 0 then - minimalLoadout[v.name].components = components - end + return minimalLoadout + else + return self.loadout + end + end, + + hasWeapon = function(self, weaponName) + for _, v in ipairs(self.loadout) do + if v.name == weaponName then + return true end end - return minimalLoadout - else - return self.loadout - end - end + return false + end, - function self.getName() - return self.name - end - - function self.setName(newName) - self.name = newName - Player(self.source).state:set("name", self.name, true) - end - - function self.setAccountMoney(accountName, money, reason) - reason = reason or 'unknown' - if not tonumber(money) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - return - end - if money >= 0 then - local account = self.getAccount(accountName) - - if account then - money = account.round and ESX.Math.Round(money) or money - self.accounts[account.index].money = money - - self.triggerEvent('esx:setAccountMoney', account) - TriggerEvent('esx:setAccountMoney', self.source, accountName, money, reason) - else - print(('[^1ERROR^7] Tried To Set Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + getWeapon = function(self, weaponName) + for k,v in ipairs(self.loadout) do + if v.name == weaponName then + return k, v + end end - else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - end - end + end, - function self.addAccountMoney(accountName, money, reason) - reason = reason or 'Unknown' - if not tonumber(money) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - return - end - if money > 0 then - local account = self.getAccount(accountName) - if account then - money = account.round and ESX.Math.Round(money) or money - self.accounts[account.index].money += money - - self.triggerEvent('esx:setAccountMoney', account) - TriggerEvent('esx:addAccountMoney', self.source, accountName, money, reason) - else - print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) - end - else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - end - end - - function self.removeAccountMoney(accountName, money, reason) - reason = reason or 'Unknown' - if not tonumber(money) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - return - end - if money > 0 then - local account = self.getAccount(accountName) - - if account then - money = account.round and ESX.Math.Round(money) or money - self.accounts[account.index].money -= money - - self.triggerEvent('esx:setAccountMoney', account) - TriggerEvent('esx:removeAccountMoney', self.source, accountName, money, reason) - else - print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) - end - else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) - end - end - - function self.getInventoryItem(name, metadata) - for k,v in ipairs(self.inventory) do - if v.name == name then - return v - end - end - end - - function self.addInventoryItem(name, count, metadata, slot) - local item = self.getInventoryItem(name) - - if item then - count = ESX.Math.Round(count) - item.count = item.count + count - self.weight = self.weight + (item.weight * count) - - TriggerEvent('esx:onAddInventoryItem', self.source, item.name, item.count) - self.triggerEvent('esx:addInventoryItem', item.name, item.count) - end - end - - function self.removeInventoryItem(name, count, metadata, slot) - local item = self.getInventoryItem(name) - - if item then - count = ESX.Math.Round(count) - local newCount = item.count - count - - if newCount >= 0 then - item.count = newCount - self.weight = self.weight - (item.weight * count) - - TriggerEvent('esx:onRemoveInventoryItem', self.source, item.name, item.count) - self.triggerEvent('esx:removeInventoryItem', item.name, item.count) - end - end - end - - function self.setInventoryItem(name, count, metadata) - local item = self.getInventoryItem(name) - - if item and count >= 0 then - count = ESX.Math.Round(count) - - if count > item.count then - self.addInventoryItem(item.name, count - item.count) - else - self.removeInventoryItem(item.name, item.count - count) - end - end - end - - function self.getWeight() - return self.weight - end - - function self.getMaxWeight() - return self.maxWeight - end - - function self.canCarryItem(name, count, metadata) - if ESX.Items[name] then - local currentWeight, itemWeight = self.weight, ESX.Items[name].weight - local newWeight = currentWeight + (itemWeight * count) - - return newWeight <= self.maxWeight - else - print(('[^3WARNING^7] Item ^5"%s"^7 was used but does not exist!'):format(name)) - end - end - - function self.canSwapItem(firstItem, firstItemCount, testItem, testItemCount) - local firstItemObject = self.getInventoryItem(firstItem) - local testItemObject = self.getInventoryItem(testItem) - - if firstItemObject.count >= firstItemCount then - local weightWithoutFirstItem = ESX.Math.Round(self.weight - (firstItemObject.weight * firstItemCount)) - local weightWithTestItem = ESX.Math.Round(weightWithoutFirstItem + (testItemObject.weight * testItemCount)) - - return weightWithTestItem <= self.maxWeight - end - - return false - end - - function self.setMaxWeight(newWeight) - self.maxWeight = newWeight - self.triggerEvent('esx:setMaxWeight', self.maxWeight) - end - - function self.setJob(job, grade) - grade = tostring(grade) - local lastJob = json.decode(json.encode(self.job)) - - if ESX.DoesJobExist(job, grade) then - local jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade] - - self.job.id = jobObject.id - self.job.name = jobObject.name - self.job.label = jobObject.label - - self.job.grade = tonumber(grade) - self.job.grade_name = gradeObject.name - self.job.grade_label = gradeObject.label - self.job.grade_salary = gradeObject.salary - - if gradeObject.skin_male then - self.job.skin_male = json.decode(gradeObject.skin_male) - else - self.job.skin_male = {} + addWeapon = function(self, weaponName, ammo) + if self:hasWeapon(weaponName) then + print(('[^1ERROR^7] Player already has this weapon ^5%s'):format(weaponName)) + return end - if gradeObject.skin_female then - self.job.skin_female = json.decode(gradeObject.skin_female) - else - self.job.skin_female = {} - end - - TriggerEvent('esx:setJob', self.source, self.job, lastJob) - self.triggerEvent('esx:setJob', self.job) - Player(self.source).state:set("job", self.job, true) - else - print(('[es_extended] [^3WARNING^7] Ignoring invalid ^5.setJob()^7 usage for ID: ^5%s^7, Job: ^5%s^7'):format(self.source, job)) - end - end - - function self.addWeapon(weaponName, ammo) - if not self.hasWeapon(weaponName) then local weaponLabel = ESX.GetWeaponLabel(weaponName) table.insert(self.loadout, { @@ -405,177 +430,199 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, tintIndex = 0 }) - GiveWeaponToPed(GetPlayerPed(self.source), joaat(weaponName), ammo, false, false) - self.triggerEvent('esx:addInventoryItem', weaponLabel, false, true) - end - end + GiveWeaponToPed(self.ped, joaat(weaponName), ammo, false, false) + self:triggerEvent('esx:addInventoryItem', weaponLabel, false, true) + end, - function self.addWeaponComponent(weaponName, weaponComponent) - local loadoutNum, weapon = self.getWeapon(weaponName) - - if weapon then - local component = ESX.GetWeaponComponent(weaponName, weaponComponent) - - if component then - if not self.hasWeaponComponent(weaponName, weaponComponent) then - self.loadout[loadoutNum].components[#self.loadout[loadoutNum].components + 1] = weaponComponent - local componentHash = ESX.GetWeaponComponent(weaponName, weaponComponent).hash - GiveWeaponComponentToPed(GetPlayerPed(self.source), joaat(weaponName), componentHash) - self.triggerEvent('esx:addInventoryItem', component.label, false, true) - end + hasWeaponComponent = function(self, weaponName, weaponComponent) + local loadoutNum, weapon = self:getWeapon(weaponName) + if not weapon then + print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) + return false end - end - end - function self.addWeaponAmmo(weaponName, ammoCount) - local loadoutNum, weapon = self.getWeapon(weaponName) - - if weapon then - weapon.ammo = weapon.ammo + ammoCount - SetPedAmmo(GetPlayerPed(self.source), joaat(weaponName), weapon.ammo) - end - end - - function self.updateWeaponAmmo(weaponName, ammoCount) - local loadoutNum, weapon = self.getWeapon(weaponName) - - if weapon then - weapon.ammo = ammoCount - end - end - - function self.setWeaponTint(weaponName, weaponTintIndex) - local loadoutNum, weapon = self.getWeapon(weaponName) - - if weapon then - local weaponNum, weaponObject = ESX.GetWeapon(weaponName) - - if weaponObject.tints and weaponObject.tints[weaponTintIndex] then - self.loadout[loadoutNum].tintIndex = weaponTintIndex - self.triggerEvent('esx:setWeaponTint', weaponName, weaponTintIndex) - self.triggerEvent('esx:addInventoryItem', weaponObject.tints[weaponTintIndex], false, true) - end - end - end - - function self.getWeaponTint(weaponName) - local loadoutNum, weapon = self.getWeapon(weaponName) - - if weapon then - return weapon.tintIndex - end - - return 0 - end - - function self.removeWeapon(weaponName) - local weaponLabel - - for k,v in ipairs(self.loadout) do - if v.name == weaponName then - weaponLabel = v.label - - for k2,v2 in ipairs(v.components) do - self.removeWeaponComponent(weaponName, v2) - end - - table.remove(self.loadout, k) - break - end - end - - if weaponLabel then - self.triggerEvent('esx:removeWeapon', weaponName) - self.triggerEvent('esx:removeInventoryItem', weaponLabel, false, true) - end - end - - function self.removeWeaponComponent(weaponName, weaponComponent) - local loadoutNum, weapon = self.getWeapon(weaponName) - - if weapon then - local component = ESX.GetWeaponComponent(weaponName, weaponComponent) - - if component then - if self.hasWeaponComponent(weaponName, weaponComponent) then - for k,v in ipairs(self.loadout[loadoutNum].components) do - if v == weaponComponent then - table.remove(self.loadout[loadoutNum].components, k) - break - end - end - - self.triggerEvent('esx:removeWeaponComponent', weaponName, weaponComponent) - self.triggerEvent('esx:removeInventoryItem', component.label, false, true) - end - end - end - end - - function self.removeWeaponAmmo(weaponName, ammoCount) - local loadoutNum, weapon = self.getWeapon(weaponName) - - if weapon then - weapon.ammo = weapon.ammo - ammoCount - self.triggerEvent('esx:setWeaponAmmo', weaponName, weapon.ammo) - end - end - - function self.hasWeaponComponent(weaponName, weaponComponent) - local loadoutNum, weapon = self.getWeapon(weaponName) - - if weapon then - for k,v in ipairs(weapon.components) do + for _, v in ipairs(weapon.components) do if v == weaponComponent then return true end end - return false + end, + + addWeaponComponent = function(self, weaponName, weaponComponent) + local loadoutNum, weapon = self:getWeapon(weaponName) + if not weapon then + print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) + return + end + + local component = ESX.GetWeaponComponent(weaponName, weaponComponent) + if not component then + print(('[^1ERROR^7] Weapon component not exist ^5%s'):format(weaponComponent)) + return + end + + if not self:hasWeaponComponent(weaponName, weaponComponent) then + print(('[^1ERROR^7] Player not owning this component ^5%s'):format(weaponComponent)) + return + end + + self.loadout[loadoutNum].components[#self.loadout[loadoutNum].components + 1] = weaponComponent + local componentHash = ESX.GetWeaponComponent(weaponName, weaponComponent).hash + GiveWeaponComponentToPed(self.ped, joaat(weaponName), componentHash) + self:triggerEvent('esx:addInventoryItem', component.label, false, true) + end, + + addWeaponAmmo = function(self, weaponName, ammoCount) + local loadoutNum, weapon = self:getWeapon(weaponName) + + if not weapon then + print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) + return + end + + weapon.ammo = weapon.ammo + ammoCount + SetPedAmmo(self.ped, joaat(weaponName), weapon.ammo) + end, + + updateWeaponAmmo = function(self, weaponName, ammoCount) + local loadoutNum, weapon = self:getWeapon(weaponName) + + if not weapon then + print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) + return + end + + weapon.ammo = ammoCount + end, + + setWeaponTint = function(self, weaponName, weaponTintIndex) + local loadoutNum, weapon = self:getWeapon(weaponName) + + if not weapon then + print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) + return + end + + local weaponNum, weaponObject = ESX.GetWeapon(weaponName) + + if weaponObject.tints and weaponObject.tints[weaponTintIndex] then + self.loadout[loadoutNum].tintIndex = weaponTintIndex + self:triggerEvent('esx:setWeaponTint', weaponName, weaponTintIndex) + self:triggerEvent('esx:addInventoryItem', weaponObject.tints[weaponTintIndex], false, true) + end + end, + + getWeaponTint = function(self, weaponName) + local loadoutNum, weapon = self:getWeapon(weaponName) + + if not weapon then + print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) + return 0 + end + + return weapon.tintIndex + end, + + removeWeapon = function(self, weaponName) + local weaponLabel + + for k,v in ipairs(self.loadout) do + if v.name == weaponName then + weaponLabel = v.label + + for _, key in ipairs(v.components) do + self:removeWeaponComponent(weaponName, key) + end + + table.remove(self.loadout, k) + break + end + end + + if weaponLabel then + self:triggerEvent('esx:removeWeapon', weaponName) + self:triggerEvent('esx:removeInventoryItem', weaponLabel, false, true) + end + end, + + removeWeaponComponent = function(self, weaponName, weaponComponent) + local loadoutNum, weapon = self:getWeapon(weaponName) + + if not weapon then + print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) + return + end + + local component = ESX.GetWeaponComponent(weaponName, weaponComponent) + if not component then + print(('[^1ERROR^7] Weapon component not exist ^5%s'):format(weaponComponent)) + return + end + + if not self:hasWeaponComponent(weaponName, weaponComponent) then + print(('[^1ERROR^7] Player not owning this component ^5%s'):format(weaponComponent)) + return + end + + for k,v in ipairs(self.loadout[loadoutNum].components) do + if v == weaponComponent then + table.remove(self.loadout[loadoutNum].components, k) + break + end + end + + self:triggerEvent('esx:removeWeaponComponent', weaponName, weaponComponent) + self:triggerEvent('esx:removeInventoryItem', component.label, false, true) + end, + + removeWeaponAmmo = function(self, weaponName, ammoCount) + local loadoutNum, weapon = self:getWeapon(weaponName) + + if not weapon then + print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) + return + end + weapon.ammo = weapon.ammo - ammoCount + self:triggerEvent('esx:setWeaponAmmo', weaponName, weapon.ammo) + end, + + showNotification = function(self, msg) + self:triggerEvent('esx:showNotification', msg) + end, + + showHelpNotification = function(self, msg, thisFrame, beep, duration) + self:triggerEvent('esx:showHelpNotification', msg, thisFrame, beep, duration) + end + } + + ExecuteCommand(('add_principal identifier.%s group.%s'):format(xPlayer.license, xPlayer.group)) + + -- StateBag + local stateBag = Player(xPlayer.playerId).state + stateBag:set("identifier", xPlayer.identifier, true) + stateBag:set("license", xPlayer.license, true) + stateBag:set("job", xPlayer.job, true) + stateBag:set("group", xPlayer.group, true) + stateBag:set("name", xPlayer.name, true) + stateBag:set("ped", xPlayer.ped, true) + stateBag:set("weight", xPlayer.weight, true) + stateBag:set("maxWeight", xPlayer.maxWeight, true) + + local tempxPlayer = {} + for fnName, fn in pairs(xPlayer) do + if type(fn) == "function" then + tempxPlayer[fnName] = function(...) + return fn(xPlayer, ...) + end else - return false + tempxPlayer[fnName] = fn end - end - - function self.hasWeapon(weaponName) - for k,v in ipairs(self.loadout) do - if v.name == weaponName then - return true - end - end - - return false - end - - function self.hasItem(item, metadata) - for k,v in ipairs(self.inventory) do - if (v.name == item) and (v.count >= 1) then - return v, v.count - end - end - - return false - end - - function self.getWeapon(weaponName) - for k,v in ipairs(self.loadout) do - if v.name == weaponName then - return k, v - end - end - end - - function self.showNotification(msg) - self.triggerEvent('esx:showNotification', msg) - end - - function self.showHelpNotification(msg, thisFrame, beep, duration) - self.triggerEvent('esx:showHelpNotification', msg, thisFrame, beep, duration) - end + end for fnName,fn in pairs(targetOverrides) do - self[fnName] = fn(self) + tempxPlayer[fnName] = fn(tempxPlayer) end - return self + return tempxPlayer end From 88b5aee197d5f3021d24d9ce2f657cceab9d6a83 Mon Sep 17 00:00:00 2001 From: wobozkyng <42249669+wobozkyng@users.noreply.github.com> Date: Sun, 18 Dec 2022 20:54:33 +0700 Subject: [PATCH 59/83] fix(es_extended/client/functions.lua): fix swapped SetVehicleExtra enabled parameter --- [esx]/es_extended/client/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx]/es_extended/client/functions.lua b/[esx]/es_extended/client/functions.lua index ec083a9a..83489795 100644 --- a/[esx]/es_extended/client/functions.lua +++ b/[esx]/es_extended/client/functions.lua @@ -877,7 +877,7 @@ function ESX.Game.SetVehicleProperties(vehicle, props) if props.extras ~= nil then for extraId, enabled in pairs(props.extras) do - SetVehicleExtra(vehicle, tonumber(extraId), enabled and 1 or 0) + SetVehicleExtra(vehicle, tonumber(extraId), enabled and 0 or 1) end end From 024a1a424732f33ca58a4b0da4fdca008349a00f Mon Sep 17 00:00:00 2001 From: IT-Kewai <44037081+ITKewai@users.noreply.github.com> Date: Sun, 18 Dec 2022 15:09:18 +0100 Subject: [PATCH 60/83] esx_identity: fix NUI not loading on low-end pc --- [esx]/esx_identity/client/main.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/[esx]/esx_identity/client/main.lua b/[esx]/esx_identity/client/main.lua index e3d6becc..0671c876 100644 --- a/[esx]/esx_identity/client/main.lua +++ b/[esx]/esx_identity/client/main.lua @@ -44,7 +44,10 @@ if not Config.UseDeferrals then RegisterNetEvent('esx_identity:showRegisterIdentity', function() TriggerEvent('esx_skin:resetFirstSpawn') - + while not ready do + print('Waiting for esx_identity NUI..') + Wait(100) + end if not ESX.PlayerData.dead then setGuiState(true) end end) @@ -66,4 +69,4 @@ if not Config.UseDeferrals then end end, data) end) -end \ No newline at end of file +end From ea22899afd63654fb80b3fde5d460418689bf79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=20Gerg=C5=91?= Date: Mon, 19 Dec 2022 14:23:28 +0100 Subject: [PATCH 61/83] Disable few hud component --- [esx]/es_extended/config.lua | 20 ++++++++++---------- [esx_addons]/esx_status/config.lua | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/[esx]/es_extended/config.lua b/[esx]/es_extended/config.lua index a72b3f64..caf9a794 100644 --- a/[esx]/es_extended/config.lua +++ b/[esx]/es_extended/config.lua @@ -19,7 +19,7 @@ Config.Accounts = { Config.StartingAccountMoney = {bank = 50000} Config.EnableSocietyPayouts = false -- pay from the society account that the player is employed at? Requirement: esx_society -Config.EnableHud = true -- enable the default hud? Display current job and accounts (black, bank & cash) +Config.EnableHud = false -- enable the default hud? Display current job and accounts (black, bank & cash) Config.MaxWeight = 24 -- the max inventory weight without backpack Config.PaycheckInterval = 7 * 60000 -- how often to recieve pay checks in milliseconds Config.EnableDebug = false -- Use Debug options? @@ -36,19 +36,19 @@ Config.DisableNPCDrops = false -- stops NPCs from dropping weapons on Config.DisableWeaponWheel = false -- Disables default weapon wheel Config.DisableAimAssist = false -- disables AIM assist (mainly on controllers) Config.RemoveHudCommonents = { - [1] = false, --WANTED_STARS, - [2] = false, --WEAPON_ICON - [3] = false, --CASH - [4] = false, --MP_CASH + [1] = true, --WANTED_STARS, + [2] = true, --WEAPON_ICON + [3] = true, --CASH + [4] = true, --MP_CASH [5] = false, --MP_MESSAGE - [6] = false, --VEHICLE_NAME - [7] = false,-- AREA_NAME - [8] = false,-- VEHICLE_CLASS - [9] = false, --STREET_NAME + [6] = true, --VEHICLE_NAME + [7] = true,-- AREA_NAME + [8] = true,-- VEHICLE_CLASS + [9] = true, --STREET_NAME [10] = false, --HELP_TEXT [11] = false, --FLOATING_HELP_TEXT_1 [12] = false, --FLOATING_HELP_TEXT_2 - [13] = false, --CASH_CHANGE + [13] = true, --CASH_CHANGE [14] = false, --RETICLE [15] = false, --SUBTITLE_TEXT [16] = false, --RADIO_STATIONS diff --git a/[esx_addons]/esx_status/config.lua b/[esx_addons]/esx_status/config.lua index 7f86d835..4120ac64 100644 --- a/[esx_addons]/esx_status/config.lua +++ b/[esx_addons]/esx_status/config.lua @@ -3,4 +3,4 @@ Config = {} Config.StatusMax = 1000000 Config.TickTime = 1000 Config.UpdateInterval = 30000 -Config.Display = true -- Enable the esx_status bars (disable if you are using another HUD) +Config.Display = false -- Enable the esx_status bars (disable if you are using another HUD) From c1e344e9b517c3a1d0652827ef8c598d3bb7d6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=20Gerg=C5=91?= Date: Mon, 19 Dec 2022 14:30:47 +0100 Subject: [PATCH 62/83] Fuck property --- .gitignore | 1 + [esx_addons]/esx_property/properties.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..1946e67e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +[esx_addons]/esx_property/properties.json \ No newline at end of file diff --git a/[esx_addons]/esx_property/properties.json b/[esx_addons]/esx_property/properties.json index a99deb4e..77915851 100644 --- a/[esx_addons]/esx_property/properties.json +++ b/[esx_addons]/esx_property/properties.json @@ -1 +1 @@ -[{"Locked":false,"Price":25000,"Entrance":{"z":28.57,"y":6206.16,"x":-467.88},"furniture":[],"plysinside":[],"Keys":[],"Owned":false,"Owner":"","OwnerName":"","setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":90.71163940429688,"maxright":-88.02642059326172,"enabled":true,"rot":{"z":2.7542073726654,"y":2.7045992112562097e-8,"x":-9.43104267120361}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1076 Procopio Dr","Interior":"low-end"},{"Locked":false,"Price":25000,"Entrance":{"z":29.07,"y":6260.23,"x":-448.02},"furniture":[],"plysinside":[],"Keys":[],"Owned":false,"Owner":"","OwnerName":"","setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-113.61099243164064,"maxright":70.65039825439453,"enabled":true,"rot":{"z":162.9940643310547,"y":-0.0,"x":3.75689458847045}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1075 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":27.96,"y":6314.13,"x":-407.35},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-54.77568435668945,"maxright":135.13072204589845,"enabled":true,"rot":{"z":-138.95835876464845,"y":-0.0,"x":-1.16786921024322}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1074 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":28.86,"y":6341.62,"x":-368.23},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-51.56189727783203,"maxright":132.70008850097657,"enabled":true,"rot":{"z":-139.94163513183598,"y":-0.0,"x":-2.56643605232238}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1073 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.52,"y":6400.88,"x":-272.61},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-65.34387969970703,"maxright":123.2501983642578,"enabled":true,"rot":{"z":-152.39810180664066,"y":-0.0,"x":-7.54235982894897}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1071 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.48,"y":6414.46,"x":-246.14},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-148.38644409179688,"maxright":38.33782577514648,"enabled":true,"rot":{"z":128.27305603027345,"y":4.379791960218428e-7,"x":-12.92249584197998}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1071 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.22,"y":6445.48,"x":-229.63},"furniture":[],"plysinside":[],"Price":27500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-135.48313903808598,"maxright":48.30059432983398,"enabled":true,"rot":{"z":137.8870849609375,"y":2.1444458297992242e-7,"x":-5.53862285614013}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1070 Procopio Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":28.89,"y":6551.76,"x":-130.8},"furniture":[],"plysinside":[],"Price":27500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-46.79578399658203,"maxright":138.85032653808598,"enabled":true,"rot":{"z":-134.93411254882813,"y":1.0691521623584777e-7,"x":3.44796895980834}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1067 Procopio Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.11,"y":6637.3,"x":-41.72},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-56.39479827880859,"maxright":129.07382202148438,"enabled":true,"rot":{"z":-144.0503692626953,"y":-1.3340336835199196e-8,"x":-0.24611411988735}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1065 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.72,"y":6654.13,"x":-9.62},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-68.07413482666016,"maxright":116.67019653320313,"enabled":true,"rot":{"z":-155.01153564453126,"y":-1.068413766347477e-7,"x":-2.71219563484191}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1064 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.86,"y":6207.33,"x":-356.82},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-45.94052505493164,"maxright":135.7574005126953,"enabled":true,"rot":{"z":-133.8831787109375,"y":-0.0,"x":-2.77191710472106}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1034 Paleto Blvd","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.87,"y":6252.75,"x":-379.92},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":42.09032440185547,"maxright":-131.2773895263672,"enabled":true,"rot":{"z":-40.4444465637207,"y":4.32035335506953e-7,"x":-8.85426330566406}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1034 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":31.91,"y":6326.99,"x":-302.19},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":133.55870056152345,"maxright":-42.54082870483398,"enabled":true,"rot":{"z":44.16030502319336,"y":-9.440947223993136e-7,"x":-25.26673126220703}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1047 Paleto Blvd","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.9,"y":6225.21,"x":-347.3},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-43.60107040405273,"maxright":134.7738800048828,"enabled":true,"rot":{"z":-137.5096435546875,"y":-0.0,"x":-1.57497417926788}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1043 Paleto Blvd","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":32.26,"y":6557.45,"x":-15.3},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":43.89247512817383,"maxright":-133.83499145507813,"enabled":true,"rot":{"z":-45.87245941162109,"y":-0.0,"x":-11.80154037475586}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1059 Paleto Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":32.1,"y":6568.19,"x":4.43},"furniture":[],"plysinside":[],"Price":27500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-139.30752563476566,"maxright":44.53319549560547,"enabled":true,"rot":{"z":129.4863433837891,"y":2.144746105159357e-7,"x":-5.62087059020996}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1061 Paleto Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":31.84,"y":6596.46,"x":31.0},"furniture":[],"plysinside":[],"Price":27500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-43.43285751342773,"maxright":-159.96804809570313,"enabled":true,"rot":{"z":-94.7632293701172,"y":-0.0,"x":-5.83577966690063}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1061 Paleto Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.9,"y":4642.33,"x":1725.06},"furniture":[],"plysinside":[],"Price":12500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-63.00457000732422,"y":-0.0,"x":-6.35934734344482}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2016 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.39,"y":4658.22,"x":1674.01},"furniture":[],"plysinside":[],"Price":12500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":91.53390502929688,"y":2.7858778395284394e-8,"x":-16.72389602661132}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2015 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.68,"y":4677.34,"x":1718.91},"furniture":[],"plysinside":[],"Price":7500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-93.13695526123049,"y":-0.0,"x":-29.83987236022949}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2014 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.09,"y":4689.52,"x":1682.85},"furniture":[],"plysinside":[],"Price":7500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":91.7155303955078,"y":-0.0,"x":-6.32857131958007}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2013 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":41.03,"y":4739.5,"x":1664.0},"furniture":[],"plysinside":[],"Price":10000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":110.03758239746094,"y":-0.0,"x":-18.96443367004394}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2011 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":32.23,"y":3920.59,"x":1880.27},"furniture":[],"plysinside":[],"Price":10000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-77.30774688720703,"y":-0.0,"x":-14.36374378204345}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"3012 Niland Ave","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":32.48,"y":3914.59,"x":1846.06},"furniture":[],"plysinside":[],"Price":9000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":103.60260009765624,"y":-2.1725810483985698e-7,"x":-10.75266551971435}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"3013 Niland Ave","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":36.08,"y":3913.8,"x":1803.57},"furniture":[],"plysinside":[],"Price":11500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-76.59026336669922,"y":-0.0,"x":-20.23343658447265}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"3013 Marina Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":33.45,"y":3657.13,"x":1435.31},"furniture":[],"plysinside":[],"Price":11500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":95.02767944335938,"y":-0.0,"x":-5.87784767150878}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"3025 Lesbos Ln","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":43.5,"y":2607.8,"x":471.15},"furniture":[],"plysinside":[],"Price":12500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-166.2356719970703,"y":-0.0,"x":-20.86568069458007}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"4018 Route 68","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.28,"y":3087.1,"x":181.03},"furniture":[],"plysinside":[],"Price":7500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-93.07178497314452,"y":-0.0,"x":-11.2086534500122}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"4013 Joshua Rd","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.50999999999999,"y":-593.38,"x":1386.22},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-127.72049713134766,"y":-0.0,"x":-9.48588275909423}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7340 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.52,"y":-569.49,"x":1388.94},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-69.5700912475586,"y":-0.0,"x":-9.84068393707275}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7341 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.71,"y":-555.82,"x":1373.19},"furniture":[],"plysinside":[],"Price":4500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-114.24230194091796,"y":-0.0,"x":-12.52571487426757}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7341 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.72999999999999,"y":-606.62,"x":1367.33},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-177.74884033203126,"y":-0.0,"x":-10.93433380126953}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7340 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.72,"y":-597.26,"x":1341.64},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":62.37366104125976,"y":-0.0,"x":-17.39539337158203}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7339 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":72.91,"y":-546.97,"x":1348.31},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-27.96370315551757,"y":4.342483350683324e-7,"x":-10.56496334075927}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7342 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":72.27,"y":-583.06,"x":1323.3},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":152.2796173095703,"y":4.441767487151084e-7,"x":-16.03893852233886}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7339 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":71.46,"y":-535.91,"x":1328.57},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-111.59012603759766,"y":-0.00000144736395,"x":-53.85140228271484}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7342 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":70.75,"y":-574.08,"x":1301.02},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":164.71957397460938,"y":4.6078031346041828e-7,"x":-22.11302947998047}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7339 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":70.47999999999999,"y":-527.3,"x":1303.1},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-19.26140213012695,"y":4.363083689895575e-7,"x":-11.92860603332519}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7342 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":56.84,"y":-729.5,"x":996.89},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":125.62109375,"y":-0.0,"x":-58.0705451965332}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7322 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.24,"y":-716.31,"x":979.11},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":131.13587951660157,"y":-0.0,"x":-15.06083393096923}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7320 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.5,"y":-701.3,"x":970.88},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":170.76788330078126,"y":3.3350637806961464e-9,"x":-0.14884614944458}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7320 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.47,"y":-669.85,"x":960.15},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":115.8887939453125,"y":4.346124455878453e-7,"x":-10.81925582885742}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7319 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.45,"y":-653.51,"x":943.45},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":38.34314727783203,"y":0.00000168464464,"x":-59.54927444458008}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7319 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":58.26,"y":-627.65,"x":980.25},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-144.15000915527345,"y":-0.0,"x":-36.16230392456055}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7318 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.26,"y":-639.71,"x":928.82},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":137.4777984619141,"y":-0.0,"x":-15.65773868560791}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7317 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.47,"y":-615.51,"x":902.95},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":46.20460510253906,"y":-0.00000160100864,"x":-57.77318572998047}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7317 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.47,"y":-608.21,"x":886.77},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":138.07872009277345,"y":-8.718344588487525e-7,"x":-11.68268966674804}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7316 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.18,"y":-583.65,"x":861.7},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-176.59844970703126,"y":-0.0,"x":-3.38041257858276}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7316 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.01,"y":-562.66,"x":844.12},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":12.50613498687744,"y":-2.1754524937023245e-7,"x":-11.14390087127685}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7312 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":56.95,"y":-532.68,"x":850.25},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":85.02394104003906,"y":-5.362977262279856e-8,"x":-5.74017667770385}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7314 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":56.74,"y":-508.98,"x":861.51},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":46.49221038818359,"y":0.00000154111978,"x":-56.35844421386719}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7313 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.11000000000001,"y":-497.87,"x":878.44},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":44.91729354858398,"y":-0.0,"x":-64.80823516845703}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7313 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":58.46,"y":-489.76,"x":906.46},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":19.29909515380859,"y":-0.0,"x":-14.44456386566162}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7311 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":60.1,"y":-477.8,"x":921.78},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-8.25692367553711,"y":-0.0,"x":-19.33738899230957}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7311 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":60.57,"y":-463.17,"x":944.54},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-55.23443603515625,"y":-8.953837777880835e-7,"x":-17.53591918945312}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7309 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":61.81,"y":-451.65,"x":967.16},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":33.32376480102539,"y":8.936335120779404e-7,"x":-17.17726707458496}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7309 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.06000000000001,"y":-433.03,"x":987.57},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":34.80197525024414,"y":8.771137913754501e-7,"x":-13.24740600585937}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7307 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":64.36999999999999,"y":-423.38,"x":1010.38},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":123.14452362060549,"y":-4.402644719903037e-7,"x":-14.16050624847412}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7307 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":65.36,"y":-408.36,"x":1028.78},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":41.270263671875,"y":-4.386202476780454e-7,"x":-13.28245830535888}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7305 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":67.25,"y":-378.13,"x":1060.52},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":54.3464241027832,"y":-8.817532943794504e-7,"x":-14.47243404388427}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7305 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.52,"y":-469.3,"x":1014.67},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-144.52737426757813,"y":-9.047982416632294e-7,"x":-19.33366966247558}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7306 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":61.16,"y":-502.36,"x":970.55},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-107.44925689697266,"y":-0.0,"x":-8.07564449310302}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7308 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":59.64,"y":-518.94,"x":945.9},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":119.70294189453124,"y":-0.0,"x":-61.49639892578125}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7310 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":58.81,"y":-526.05,"x":924.39},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-151.43536376953126,"y":-0.0,"x":-17.66978073120117}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7312 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.53,"y":-540.58,"x":893.24},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-69.45809936523438,"y":-9.24586970540986e-7,"x":-22.57007217407226}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7312 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.39,"y":-569.56,"x":919.7},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":28.74713134765625,"y":4.412431167111208e-7,"x":-14.65564727783203}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7312 Nikola Ave","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":58.75,"y":-541.93,"x":965.25},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":32.70853805541992,"y":-4.381802227726439e-7,"x":-13.03651428222656}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7310 Nikola Ave","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":59.71,"y":-525.76,"x":987.84},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":30.89822769165039,"y":9.366781910102872e-7,"x":-24.28778457641601}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7310 Nikola Ave","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":60.01,"y":-510.98,"x":1006.48},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-65.29899597167969,"y":-0.0,"x":-16.08703422546386}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7308 Nikola Ave","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.1,"y":-498.06,"x":1046.29},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":144.13137817382813,"y":9.091479000744585e-7,"x":-20.10037040710449}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7306 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.32,"y":-470.58,"x":1051.04},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":76.4620132446289,"y":-0.0,"x":-11.98972129821777}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7306 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":65.28,"y":-448.93,"x":1056.24},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":162.82366943359376,"y":-0.0,"x":-8.78071689605712}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7306 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":64.67999999999999,"y":-484.37,"x":1090.46},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-102.9858856201172,"y":-4.4310172597761268e-7,"x":-15.54805183410644}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7344 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":66.33999999999999,"y":-464.52,"x":1098.58},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-15.62946987152099,"y":2.17306606487e-7,"x":-10.81984233856201}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7346 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":66.81,"y":-438.69,"x":1099.44},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":179.49822998046876,"y":-0.0,"x":-11.32894706726074}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7346 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":66.58,"y":-411.33,"x":1101.06},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-93.88529205322266,"y":-5.391471091797939e-8,"x":-8.21971225738525}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7348 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":67.97,"y":-391.27,"x":1114.44},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-112.49811553955078,"y":-0.0,"x":-24.5419979095459}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7348 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":69.03999999999999,"y":-429.86,"x":1262.35},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":112.37248229980468,"y":-2.144359569911103e-7,"x":-5.51487922668457}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7345 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":69.53999999999999,"y":-458.06,"x":1265.74},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":94.98734283447266,"y":-0.0,"x":-14.86165904998779}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7945 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":69.21,"y":-480.18,"x":1259.51},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":125.15465545654296,"y":-0.0,"x":-10.50986766815185}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7343 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.92999999999999,"y":-494.1,"x":1251.53},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":63.34117126464844,"y":-0.0,"x":-16.31183433532715}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7343 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.36999999999999,"y":-515.5,"x":1250.9},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":77.79755401611328,"y":-0.0,"x":-17.28229522705078}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7343 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.67999999999999,"y":-566.43,"x":1241.53},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":130.3302459716797,"y":-0.0,"x":-22.43321228027343}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7338 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.8,"y":-601.65,"x":1240.54},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":91.53223419189452,"y":-1.3435412782314417e-8,"x":-6.82489442825317}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7338 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.58999999999999,"y":-620.99,"x":1250.79},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Price":40000,"Owner":"","OwnerName":"","setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":27.77294158935547,"y":-2.145688853261163e-7,"x":-5.87094974517822}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7336 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":67.14,"y":-648.63,"x":1265.69},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-152.5341949462891,"y":-0.0,"x":-14.65502071380615}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7333 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":65.05,"y":-683.53,"x":1270.98},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-171.3050994873047,"y":-0.0,"x":-12.5356969833374}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7333 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.93,"y":-702.82,"x":1264.75},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":58.4541015625,"y":0.00000175048376,"x":-12.71638584136962}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7328 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":59.98,"y":-725.27,"x":1229.58},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-88.46087646484375,"y":-0.0,"x":-11.09668827056884}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7328 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":59.82,"y":-696.93,"x":1223.0},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-81.23240661621094,"y":-0.0,"x":-17.37718200683593}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7328 Mirror Park Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":62.71,"y":-669.31,"x":1221.46},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-164.38833618164066,"y":-0.0,"x":-11.55613040924072}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7333 Mirror Park Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":65.46,"y":-620.26,"x":1207.46},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-87.679443359375,"y":1.3399391818325056e-8,"x":-5.38702487945556}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7336 Mirror Park Blvd","Interior":"mid-end"},{"Locked":false,"Price":40000,"Entrance":{"z":67.08,"y":-598.41,"x":1203.75},"furniture":[],"setName":"","Owned":false,"Owner":"","garage":{"enabled":false},"cctv":{"enabled":false,"maxright":-20,"maxleft":80,"rot":{"x":-16.58763313293457,"y":-0.0,"z":3.90023970603942}},"Keys":[],"Interior":"mid-end","positions":{"Storage":{"x":343.86859130859377,"y":-1001.140380859375,"z":-99.19619750976563},"Wardrobe":{"x":350.74249267578127,"y":-994.2987060546875,"z":-99.14720153808594}},"Name":"7338 Mirror Park Blvd","plysinside":[]},{"Locked":false,"Price":40000,"Entrance":{"z":68.16,"y":-575.59,"x":1201.01},"furniture":[],"setName":"","Owned":false,"Owner":"","garage":{"enabled":false},"cctv":{"enabled":false,"maxright":-20,"maxleft":80,"rot":{"x":-20.23956108093261,"y":9.099596240957908e-7,"z":-37.31895446777344}},"Keys":[],"Interior":"mid-end","positions":{"Storage":{"x":343.86859130859377,"y":-1001.140380859375,"z":-99.19619750976563},"Wardrobe":{"x":350.74249267578127,"y":-994.2987060546875,"z":-99.14720153808594}},"Name":"7338 Mirror Park Blvd","plysinside":[]}] \ No newline at end of file +[{"cctv":{"rot":{"z":2.7542073726654,"y":2.7045992112562097e-8,"x":-9.43104267120361},"maxright":-88.02642059326172,"maxleft":90.71163940429688,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":28.57,"y":6206.16,"x":-467.88},"Interior":"low-end","OwnerName":"","Owned":false,"Locked":false,"setName":"","Name":"1076 Procopio Dr","Keys":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":162.9940643310547,"y":-0.0,"x":3.75689458847045},"maxright":70.65039825439453,"maxleft":-113.61099243164064,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":29.07,"y":6260.23,"x":-448.02},"Interior":"low-end","OwnerName":"","Owned":false,"Locked":false,"setName":"","Name":"1075 Procopio Dr","Keys":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-138.95835876464845,"y":-0.0,"x":-1.16786921024322},"maxright":135.13072204589845,"maxleft":-54.77568435668945,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":27.96,"y":6314.13,"x":-407.35},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1074 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-139.94163513183598,"y":-0.0,"x":-2.56643605232238},"maxright":132.70008850097657,"maxleft":-51.56189727783203,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":28.86,"y":6341.62,"x":-368.23},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1073 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-152.39810180664066,"y":-0.0,"x":-7.54235982894897},"maxright":123.2501983642578,"maxleft":-65.34387969970703,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.52,"y":6400.88,"x":-272.61},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1071 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":128.27305603027345,"y":4.379791960218428e-7,"x":-12.92249584197998},"maxright":38.33782577514648,"maxleft":-148.38644409179688,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.48,"y":6414.46,"x":-246.14},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1071 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":137.8870849609375,"y":2.1444458297992242e-7,"x":-5.53862285614013},"maxright":48.30059432983398,"maxleft":-135.48313903808598,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":30.22,"y":6445.48,"x":-229.63},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1070 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":27500},{"cctv":{"rot":{"z":-134.93411254882813,"y":1.0691521623584777e-7,"x":3.44796895980834},"maxright":138.85032653808598,"maxleft":-46.79578399658203,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":28.89,"y":6551.76,"x":-130.8},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1067 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":27500},{"cctv":{"rot":{"z":-144.0503692626953,"y":-1.3340336835199196e-8,"x":-0.24611411988735},"maxright":129.07382202148438,"maxleft":-56.39479827880859,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.11,"y":6637.3,"x":-41.72},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1065 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-155.01153564453126,"y":-1.068413766347477e-7,"x":-2.71219563484191},"maxright":116.67019653320313,"maxleft":-68.07413482666016,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.72,"y":6654.13,"x":-9.62},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1064 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-133.8831787109375,"y":-0.0,"x":-2.77191710472106},"maxright":135.7574005126953,"maxleft":-45.94052505493164,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.86,"y":6207.33,"x":-356.82},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1034 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-40.4444465637207,"y":4.32035335506953e-7,"x":-8.85426330566406},"maxright":-131.2773895263672,"maxleft":42.09032440185547,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.87,"y":6252.75,"x":-379.92},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1034 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":44.16030502319336,"y":-9.440947223993136e-7,"x":-25.26673126220703},"maxright":-42.54082870483398,"maxleft":133.55870056152345,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":31.91,"y":6326.99,"x":-302.19},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1047 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-137.5096435546875,"y":-0.0,"x":-1.57497417926788},"maxright":134.7738800048828,"maxleft":-43.60107040405273,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.9,"y":6225.21,"x":-347.3},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1043 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-45.87245941162109,"y":-0.0,"x":-11.80154037475586},"maxright":-133.83499145507813,"maxleft":43.89247512817383,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":32.26,"y":6557.45,"x":-15.3},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1059 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":129.4863433837891,"y":2.144746105159357e-7,"x":-5.62087059020996},"maxright":44.53319549560547,"maxleft":-139.30752563476566,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":32.1,"y":6568.19,"x":4.43},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1061 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":27500},{"cctv":{"rot":{"z":-94.7632293701172,"y":-0.0,"x":-5.83577966690063},"maxright":-159.96804809570313,"maxleft":-43.43285751342773,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":31.84,"y":6596.46,"x":31.0},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1061 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":27500},{"cctv":{"rot":{"z":-63.00457000732422,"y":-0.0,"x":-6.35934734344482},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.9,"y":4642.33,"x":1725.06},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2016 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":12500},{"cctv":{"rot":{"z":91.53390502929688,"y":2.7858778395284394e-8,"x":-16.72389602661132},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.39,"y":4658.22,"x":1674.01},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2015 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":12500},{"cctv":{"rot":{"z":-93.13695526123049,"y":-0.0,"x":-29.83987236022949},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.68,"y":4677.34,"x":1718.91},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2014 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":7500},{"cctv":{"rot":{"z":91.7155303955078,"y":-0.0,"x":-6.32857131958007},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.09,"y":4689.52,"x":1682.85},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2013 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":7500},{"cctv":{"rot":{"z":110.03758239746094,"y":-0.0,"x":-18.96443367004394},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":41.03,"y":4739.5,"x":1664.0},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2011 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":10000},{"cctv":{"rot":{"z":-77.30774688720703,"y":-0.0,"x":-14.36374378204345},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":32.23,"y":3920.59,"x":1880.27},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"3012 Niland Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":10000},{"cctv":{"rot":{"z":103.60260009765624,"y":-2.1725810483985698e-7,"x":-10.75266551971435},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":32.48,"y":3914.59,"x":1846.06},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"3013 Niland Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":9000},{"cctv":{"rot":{"z":-76.59026336669922,"y":-0.0,"x":-20.23343658447265},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":36.08,"y":3913.8,"x":1803.57},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"3013 Marina Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":11500},{"cctv":{"rot":{"z":95.02767944335938,"y":-0.0,"x":-5.87784767150878},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":33.45,"y":3657.13,"x":1435.31},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"3025 Lesbos Ln","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":11500},{"cctv":{"rot":{"z":-166.2356719970703,"y":-0.0,"x":-20.86568069458007},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":43.5,"y":2607.8,"x":471.15},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"4018 Route 68","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":12500},{"cctv":{"rot":{"z":-93.07178497314452,"y":-0.0,"x":-11.2086534500122},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.28,"y":3087.1,"x":181.03},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"4013 Joshua Rd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":7500},{"cctv":{"rot":{"z":-127.72049713134766,"y":-0.0,"x":-9.48588275909423},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.50999999999999,"y":-593.38,"x":1386.22},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7340 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-69.5700912475586,"y":-0.0,"x":-9.84068393707275},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.52,"y":-569.49,"x":1388.94},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7341 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-114.24230194091796,"y":-0.0,"x":-12.52571487426757},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.71,"y":-555.82,"x":1373.19},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7341 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":4500},{"cctv":{"rot":{"z":-177.74884033203126,"y":-0.0,"x":-10.93433380126953},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.72999999999999,"y":-606.62,"x":1367.33},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7340 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":62.37366104125976,"y":-0.0,"x":-17.39539337158203},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.72,"y":-597.26,"x":1341.64},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7339 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-27.96370315551757,"y":4.342483350683324e-7,"x":-10.56496334075927},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":72.91,"y":-546.97,"x":1348.31},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7342 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":152.2796173095703,"y":4.441767487151084e-7,"x":-16.03893852233886},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":72.27,"y":-583.06,"x":1323.3},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7339 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-111.59012603759766,"y":-0.00000144736395,"x":-53.85140228271484},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":71.46,"y":-535.91,"x":1328.57},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7342 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":164.71957397460938,"y":4.6078031346041828e-7,"x":-22.11302947998047},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":70.75,"y":-574.08,"x":1301.02},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7339 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-19.26140213012695,"y":4.363083689895575e-7,"x":-11.92860603332519},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":70.47999999999999,"y":-527.3,"x":1303.1},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7342 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":125.62109375,"y":-0.0,"x":-58.0705451965332},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":56.84,"y":-729.5,"x":996.89},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7322 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":131.13587951660157,"y":-0.0,"x":-15.06083393096923},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.24,"y":-716.31,"x":979.11},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7320 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":170.76788330078126,"y":3.3350637806961464e-9,"x":-0.14884614944458},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.5,"y":-701.3,"x":970.88},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7320 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":115.8887939453125,"y":4.346124455878453e-7,"x":-10.81925582885742},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.47,"y":-669.85,"x":960.15},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7319 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":38.34314727783203,"y":0.00000168464464,"x":-59.54927444458008},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.45,"y":-653.51,"x":943.45},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7319 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-144.15000915527345,"y":-0.0,"x":-36.16230392456055},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":58.26,"y":-627.65,"x":980.25},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7318 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":137.4777984619141,"y":-0.0,"x":-15.65773868560791},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.26,"y":-639.71,"x":928.82},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7317 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":46.20460510253906,"y":-0.00000160100864,"x":-57.77318572998047},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.47,"y":-615.51,"x":902.95},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7317 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":138.07872009277345,"y":-8.718344588487525e-7,"x":-11.68268966674804},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.47,"y":-608.21,"x":886.77},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7316 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-176.59844970703126,"y":-0.0,"x":-3.38041257858276},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.18,"y":-583.65,"x":861.7},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7316 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":12.50613498687744,"y":-2.1754524937023245e-7,"x":-11.14390087127685},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.01,"y":-562.66,"x":844.12},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7312 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":85.02394104003906,"y":-5.362977262279856e-8,"x":-5.74017667770385},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":56.95,"y":-532.68,"x":850.25},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7314 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":46.49221038818359,"y":0.00000154111978,"x":-56.35844421386719},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":56.74,"y":-508.98,"x":861.51},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7313 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":44.91729354858398,"y":-0.0,"x":-64.80823516845703},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.11000000000001,"y":-497.87,"x":878.44},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7313 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":19.29909515380859,"y":-0.0,"x":-14.44456386566162},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":58.46,"y":-489.76,"x":906.46},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7311 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-8.25692367553711,"y":-0.0,"x":-19.33738899230957},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":60.1,"y":-477.8,"x":921.78},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7311 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-55.23443603515625,"y":-8.953837777880835e-7,"x":-17.53591918945312},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":60.57,"y":-463.17,"x":944.54},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7309 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":33.32376480102539,"y":8.936335120779404e-7,"x":-17.17726707458496},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":61.81,"y":-451.65,"x":967.16},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7309 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":34.80197525024414,"y":8.771137913754501e-7,"x":-13.24740600585937},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":63.06000000000001,"y":-433.03,"x":987.57},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7307 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":123.14452362060549,"y":-4.402644719903037e-7,"x":-14.16050624847412},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":64.36999999999999,"y":-423.38,"x":1010.38},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7307 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":41.270263671875,"y":-4.386202476780454e-7,"x":-13.28245830535888},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":65.36,"y":-408.36,"x":1028.78},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7305 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":54.3464241027832,"y":-8.817532943794504e-7,"x":-14.47243404388427},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":67.25,"y":-378.13,"x":1060.52},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7305 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-144.52737426757813,"y":-9.047982416632294e-7,"x":-19.33366966247558},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":63.52,"y":-469.3,"x":1014.67},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7306 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-107.44925689697266,"y":-0.0,"x":-8.07564449310302},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":61.16,"y":-502.36,"x":970.55},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7308 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":119.70294189453124,"y":-0.0,"x":-61.49639892578125},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":59.64,"y":-518.94,"x":945.9},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7310 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-151.43536376953126,"y":-0.0,"x":-17.66978073120117},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":58.81,"y":-526.05,"x":924.39},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7312 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-69.45809936523438,"y":-9.24586970540986e-7,"x":-22.57007217407226},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.53,"y":-540.58,"x":893.24},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7312 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":28.74713134765625,"y":4.412431167111208e-7,"x":-14.65564727783203},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.39,"y":-569.56,"x":919.7},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7312 Nikola Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":32.70853805541992,"y":-4.381802227726439e-7,"x":-13.03651428222656},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":58.75,"y":-541.93,"x":965.25},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7310 Nikola Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":30.89822769165039,"y":9.366781910102872e-7,"x":-24.28778457641601},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":59.71,"y":-525.76,"x":987.84},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7310 Nikola Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-65.29899597167969,"y":-0.0,"x":-16.08703422546386},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":60.01,"y":-510.98,"x":1006.48},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7308 Nikola Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":144.13137817382813,"y":9.091479000744585e-7,"x":-20.10037040710449},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":63.1,"y":-498.06,"x":1046.29},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7306 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":76.4620132446289,"y":-0.0,"x":-11.98972129821777},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":63.32,"y":-470.58,"x":1051.04},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7306 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":162.82366943359376,"y":-0.0,"x":-8.78071689605712},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":65.28,"y":-448.93,"x":1056.24},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7306 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-102.9858856201172,"y":-4.4310172597761268e-7,"x":-15.54805183410644},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":64.67999999999999,"y":-484.37,"x":1090.46},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7344 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-15.62946987152099,"y":2.17306606487e-7,"x":-10.81984233856201},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":66.33999999999999,"y":-464.52,"x":1098.58},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7346 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":179.49822998046876,"y":-0.0,"x":-11.32894706726074},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":66.81,"y":-438.69,"x":1099.44},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7346 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-93.88529205322266,"y":-5.391471091797939e-8,"x":-8.21971225738525},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":66.58,"y":-411.33,"x":1101.06},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7348 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-112.49811553955078,"y":-0.0,"x":-24.5419979095459},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":67.97,"y":-391.27,"x":1114.44},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7348 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":112.37248229980468,"y":-2.144359569911103e-7,"x":-5.51487922668457},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":69.03999999999999,"y":-429.86,"x":1262.35},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7345 East Mirror Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":94.98734283447266,"y":-0.0,"x":-14.86165904998779},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":69.53999999999999,"y":-458.06,"x":1265.74},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7945 East Mirror Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":125.15465545654296,"y":-0.0,"x":-10.50986766815185},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":69.21,"y":-480.18,"x":1259.51},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7343 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":63.34117126464844,"y":-0.0,"x":-16.31183433532715},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.92999999999999,"y":-494.1,"x":1251.53},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7343 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":77.79755401611328,"y":-0.0,"x":-17.28229522705078},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.36999999999999,"y":-515.5,"x":1250.9},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7343 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":130.3302459716797,"y":-0.0,"x":-22.43321228027343},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.67999999999999,"y":-566.43,"x":1241.53},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7338 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":91.53223419189452,"y":-1.3435412782314417e-8,"x":-6.82489442825317},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.8,"y":-601.65,"x":1240.54},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7338 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":27.77294158935547,"y":-2.145688853261163e-7,"x":-5.87094974517822},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.58999999999999,"y":-620.99,"x":1250.79},"Interior":"mid-end","OwnerName":"","Owned":false,"Locked":false,"setName":"","Name":"7336 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-152.5341949462891,"y":-0.0,"x":-14.65502071380615},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":67.14,"y":-648.63,"x":1265.69},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7333 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-171.3050994873047,"y":-0.0,"x":-12.5356969833374},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":65.05,"y":-683.53,"x":1270.98},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7333 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":58.4541015625,"y":0.00000175048376,"x":-12.71638584136962},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":63.93,"y":-702.82,"x":1264.75},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7328 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-88.46087646484375,"y":-0.0,"x":-11.09668827056884},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":59.98,"y":-725.27,"x":1229.58},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7328 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-81.23240661621094,"y":-0.0,"x":-17.37718200683593},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":59.82,"y":-696.93,"x":1223.0},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7328 Mirror Park Blvd","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-164.38833618164066,"y":-0.0,"x":-11.55613040924072},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":62.71,"y":-669.31,"x":1221.46},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7333 Mirror Park Blvd","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-87.679443359375,"y":1.3399391818325056e-8,"x":-5.38702487945556},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":65.46,"y":-620.26,"x":1207.46},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7336 Mirror Park Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":3.90023970603942,"y":-0.0,"x":-16.58763313293457},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":67.08,"y":-598.41,"x":1203.75},"Interior":"mid-end","plysinside":[],"Locked":false,"setName":"","Name":"7338 Mirror Park Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-37.31895446777344,"y":9.099596240957908e-7,"x":-20.23956108093261},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.16,"y":-575.59,"x":1201.01},"Interior":"mid-end","plysinside":[],"Locked":false,"setName":"","Name":"7338 Mirror Park Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000}] \ No newline at end of file From ad8c7e9d28e6550b72a63ff171b1c6785fbe2526 Mon Sep 17 00:00:00 2001 From: Benzo <102178921+Benzo00@users.noreply.github.com> Date: Mon, 19 Dec 2022 18:02:05 +0100 Subject: [PATCH 63/83] preparing for esx_hud --- [esx]/es_extended/config.lua | 2 +- [esx_addons]/esx_status/config.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/[esx]/es_extended/config.lua b/[esx]/es_extended/config.lua index a72b3f64..50c57ea3 100644 --- a/[esx]/es_extended/config.lua +++ b/[esx]/es_extended/config.lua @@ -19,7 +19,7 @@ Config.Accounts = { Config.StartingAccountMoney = {bank = 50000} Config.EnableSocietyPayouts = false -- pay from the society account that the player is employed at? Requirement: esx_society -Config.EnableHud = true -- enable the default hud? Display current job and accounts (black, bank & cash) +Config.EnableHud = false -- enable the default hud? Display current job and accounts (black, bank & cash) Config.MaxWeight = 24 -- the max inventory weight without backpack Config.PaycheckInterval = 7 * 60000 -- how often to recieve pay checks in milliseconds Config.EnableDebug = false -- Use Debug options? diff --git a/[esx_addons]/esx_status/config.lua b/[esx_addons]/esx_status/config.lua index 7f86d835..4120ac64 100644 --- a/[esx_addons]/esx_status/config.lua +++ b/[esx_addons]/esx_status/config.lua @@ -3,4 +3,4 @@ Config = {} Config.StatusMax = 1000000 Config.TickTime = 1000 Config.UpdateInterval = 30000 -Config.Display = true -- Enable the esx_status bars (disable if you are using another HUD) +Config.Display = false -- Enable the esx_status bars (disable if you are using another HUD) From 6ffecabaf2be7ab2883f8c77fc03f266a2596cfd Mon Sep 17 00:00:00 2001 From: Benzo <102178921+Benzo00@users.noreply.github.com> Date: Mon, 19 Dec 2022 20:52:58 +0100 Subject: [PATCH 64/83] esx_basicneeds rework -Kuuzoo --- [esx_addons]/esx_basicneeds/client/main.lua | 65 ++++++++++----------- [esx_addons]/esx_basicneeds/config.lua | 12 ++-- [esx_addons]/esx_basicneeds/locales/de.lua | 7 ++- [esx_addons]/esx_basicneeds/locales/en.lua | 5 +- [esx_addons]/esx_basicneeds/server/main.lua | 32 +++++----- 5 files changed, 59 insertions(+), 62 deletions(-) diff --git a/[esx_addons]/esx_basicneeds/client/main.lua b/[esx_addons]/esx_basicneeds/client/main.lua index 7ed21927..fc6d4543 100644 --- a/[esx_addons]/esx_basicneeds/client/main.lua +++ b/[esx_addons]/esx_basicneeds/client/main.lua @@ -6,7 +6,6 @@ AddEventHandler('esx_basicneeds:resetStatus', function() TriggerEvent('esx_status:set', 'thirst', 500000) end) - RegisterNetEvent('esx_basicneeds:healPlayer') AddEventHandler('esx_basicneeds:healPlayer', function() -- restore hunger & thirst @@ -27,11 +26,10 @@ AddEventHandler('esx:onPlayerSpawn', function(spawn) TriggerEvent('esx_basicneeds:resetStatus') end - IsDead = false + IsDead = false end) AddEventHandler('esx_status:loaded', function(status) - TriggerEvent('esx_status:registerStatus', 'hunger', 1000000, '#CFAD0F', function(status) return Config.Visible end, function(status) @@ -43,7 +41,6 @@ AddEventHandler('esx_status:loaded', function(status) end, function(status) status.remove(75) end) - end) AddEventHandler('esx_status:onTick', function(data) @@ -74,11 +71,18 @@ AddEventHandler('esx_basicneeds:isEating', function(cb) cb(IsAnimated) end) -RegisterNetEvent('esx_basicneeds:onEat') -AddEventHandler('esx_basicneeds:onEat', function(prop_name) +RegisterNetEvent('esx_basicneeds:onUse') +AddEventHandler('esx_basicneeds:onUse', function(type, prop_name) if not IsAnimated then - prop_name = prop_name or 'prop_cs_burger_01' + local anim = {dict = 'mp_player_inteat@burger', name = 'mp_player_int_eat_burger_fp', settings = {8.0, -8, -1, 49, 0, 0, 0, 0}} IsAnimated = true + if type == 'food' then + prop_name = prop_name or 'prop_cs_burger_01' + anim = {dict = 'mp_player_inteat@burger', name = 'mp_player_int_eat_burger_fp', settings = {8.0, -8, -1, 49, 0, 0, 0, 0}} + elseif type == 'drink' then + prop_name = prop_name or 'prop_ld_flow_bottle' + anim = {dict = 'mp_player_intdrink', name = 'loop_bottle', settings = {1.0, -1.0, 2000, 0, 1, true, true, true}} + end CreateThread(function() local playerPed = PlayerPedId() @@ -87,9 +91,9 @@ AddEventHandler('esx_basicneeds:onEat', function(prop_name) local boneIndex = GetPedBoneIndex(playerPed, 18905) AttachEntityToEntity(prop, playerPed, boneIndex, 0.12, 0.028, 0.001, 10.0, 175.0, 0.0, true, true, false, true, 1, true) - ESX.Streaming.RequestAnimDict('mp_player_inteat@burger', function() - TaskPlayAnim(playerPed, 'mp_player_inteat@burger', 'mp_player_int_eat_burger_fp', 8.0, -8, -1, 49, 0, 0, 0, 0) - RemoveAnimDict('mp_player_inteat@burger') + ESX.Streaming.RequestAnimDict(anim.dict, function() + TaskPlayAnim(playerPed, anim.dict, anim.name, anim.settings[1], anim.settings[2], anim.settings[3], anim.settings[4], anim.settings[5], anim.settings[6], anim.settings[7], anim.settings[8]) + RemoveAnimDict(anim.dict) Wait(3000) IsAnimated = false @@ -97,33 +101,28 @@ AddEventHandler('esx_basicneeds:onEat', function(prop_name) DeleteObject(prop) end) end) - end end) +-- Backwards compatibility +RegisterNetEvent('esx_basicneeds:onEat') +AddEventHandler('esx_basicneeds:onEat', function(prop_name) + local Invoke = GetInvokingResource() + print(('[^3WARNING^7] ^5%s^7 used ^5esx_basicneeds:onEat^7, this method is deprecated and should not be used! Refer to ^5https://docs.esx-framework.org/tutorials/basicneeds^7 for more info!'):format(Invoke)) + + if not prop_name then + prop_name = 'prop_cs_burger_01' + end + TriggerEvent('esx_basicneeds:onUse', 'food', prop_name) +end) + RegisterNetEvent('esx_basicneeds:onDrink') AddEventHandler('esx_basicneeds:onDrink', function(prop_name) - if not IsAnimated then - prop_name = prop_name or 'prop_ld_flow_bottle' - IsAnimated = true + local Invoke = GetInvokingResource() + print(('[^3WARNING^7] ^5%s^7 used ^5esx_basicneeds:onDrink^7, this method is deprecated and should not be used! Refer to ^5https://docs.esx-framework.org/tutorials/basicneeds^7 for more info!'):format(Invoke)) - CreateThread(function() - local playerPed = PlayerPedId() - local x,y,z = table.unpack(GetEntityCoords(playerPed)) - local prop = CreateObject(joaat(prop_name), x, y, z + 0.2, true, true, true) - local boneIndex = GetPedBoneIndex(playerPed, 18905) - AttachEntityToEntity(prop, playerPed, boneIndex, 0.12, 0.028, 0.001, 10.0, 175.0, 0.0, true, true, false, true, 1, true) - - ESX.Streaming.RequestAnimDict('mp_player_intdrink', function() - TaskPlayAnim(playerPed, 'mp_player_intdrink', 'loop_bottle', 1.0, -1.0, 2000, 0, 1, true, true, true) - RemoveAnimDict('mp_player_intdrink') - - Wait(3000) - IsAnimated = false - ClearPedSecondaryTask(playerPed) - DeleteObject(prop) - end) - end) - - end + if not prop_name then + prop_name = 'prop_ld_flow_bottle' + end + TriggerEvent('esx_basicneeds:onUse', 'drink', prop_name) end) diff --git a/[esx_addons]/esx_basicneeds/config.lua b/[esx_addons]/esx_basicneeds/config.lua index 973caacf..a577e68b 100644 --- a/[esx_addons]/esx_basicneeds/config.lua +++ b/[esx_addons]/esx_basicneeds/config.lua @@ -2,15 +2,17 @@ Config = {} Config.Locale = GetConvar('esx:locale', 'en') Config.Visible = true -Config.Food = { +Config.Items = { ["bread"] = { + type = "food", + prop= "prop_cs_burger_01", status = 200000, remove = true - } -} - -Config.Drinks = { + }, + ["water"] = { + type = "drink", + prop = "prop_ld_flow_bottle", status = 100000, remove = true } diff --git a/[esx_addons]/esx_basicneeds/locales/de.lua b/[esx_addons]/esx_basicneeds/locales/de.lua index 041b447a..93584e37 100644 --- a/[esx_addons]/esx_basicneeds/locales/de.lua +++ b/[esx_addons]/esx_basicneeds/locales/de.lua @@ -1,4 +1,5 @@ Locales['de'] = { - ['used_bread'] = 'du hast 1x Brot gegessen', - ['used_water'] = 'du hast 1x Wasser getrunken', -} \ No newline at end of file + ['used_food'] = 'Du hast 1x %s gegessen.', + ['used_drink'] = 'Du hast 1x %s getrunken.', + ['got_healed'] = 'Du wurdest geheilt.' +} diff --git a/[esx_addons]/esx_basicneeds/locales/en.lua b/[esx_addons]/esx_basicneeds/locales/en.lua index a84b4c38..a994b1bf 100644 --- a/[esx_addons]/esx_basicneeds/locales/en.lua +++ b/[esx_addons]/esx_basicneeds/locales/en.lua @@ -1,4 +1,5 @@ Locales['en'] = { - ['used_eat'] = 'you have used 1x %s', - ['used_drink'] = 'you have used 1x %s', + ['used_food'] = 'You have eaten 1x %s', + ['used_drink'] = 'You have drinked 1x %s', + ['got_healed'] = 'You have been healed.' } diff --git a/[esx_addons]/esx_basicneeds/server/main.lua b/[esx_addons]/esx_basicneeds/server/main.lua index 7ecd02f3..a4eaf01d 100644 --- a/[esx_addons]/esx_basicneeds/server/main.lua +++ b/[esx_addons]/esx_basicneeds/server/main.lua @@ -1,34 +1,28 @@ CreateThread(function() - for k,v in pairs(Config.Food) do + for k,v in pairs(Config.Items) do ESX.RegisterUsableItem(k, function(source) local xPlayer = ESX.GetPlayerFromId(source) if v.remove then xPlayer.removeInventoryItem(k,1) end - TriggerClientEvent("esx_status:add",source,"hunger",v.status) - TriggerClientEvent('esx_basicneeds:onEat',source) - xPlayer.showNotification(TranslateCap('used_eat', ESX.GetItemLabel(k))) - end) - end -end) - -CreateThread(function() - for k,v in pairs(Config.Drinks) do - ESX.RegisterUsableItem(k, function(source) - local xPlayer = ESX.GetPlayerFromId(source) - if v.remove then - xPlayer.removeInventoryItem(k,1) + if v.type == "food" then + TriggerClientEvent("esx_status:add", source, "hunger", v.status) + TriggerClientEvent('esx_basicneeds:onUse', source, v.type) + xPlayer.showNotification(TranslateCap('used_food', ESX.GetItemLabel(k))) + elseif v.type == "drink" then + TriggerClientEvent("esx_status:add", source, "thirst", v.status) + TriggerClientEvent('esx_basicneeds:onUse', source, v.type) + xPlayer.showNotification(TranslateCap('used_drink', ESX.GetItemLabel(k))) + else + print(string.format('^1[ERROR]^0 %s has no correct type defined.', k)) end - TriggerClientEvent("esx_status:add",source,"thirst",v.status) - TriggerClientEvent('esx_basicneeds:onDrink',source) - xPlayer.showNotification(TranslateCap('used_drink', ESX.GetItemLabel(k))) end) - end + end end) ESX.RegisterCommand('heal', 'admin', function(xPlayer, args, showError) args.playerId.triggerEvent('esx_basicneeds:healPlayer') - args.playerId.showNotification('You have been healed.') + args.playerId.showNotification(TranslateCap('got_healed')) end, true, {help = 'Heal a player, or yourself - restores thirst, hunger and health.', validate = true, arguments = { {name = 'playerId', help = 'the player id', type = 'player'} }}) From 1e4f2293c27f853b07704d6e918cb3ac9802dc6f Mon Sep 17 00:00:00 2001 From: Taavi <97351942+Taavi-AU@users.noreply.github.com> Date: Tue, 20 Dec 2022 21:52:30 +0800 Subject: [PATCH 65/83] context implementation (policejob) (#758) --- [esx_addons]/esx_policejob/client/main.lua | 544 +++++++++--------- [esx_addons]/esx_policejob/client/vehicle.lua | 176 +++--- 2 files changed, 338 insertions(+), 382 deletions(-) diff --git a/[esx_addons]/esx_policejob/client/main.lua b/[esx_addons]/esx_policejob/client/main.lua index 6ba8daa9..0115ba9c 100644 --- a/[esx_addons]/esx_policejob/client/main.lua +++ b/[esx_addons]/esx_policejob/client/main.lua @@ -50,30 +50,38 @@ function OpenCloakroomMenu() local grade = ESX.PlayerData.job.grade_name local elements = { - {label = TranslateCap('citizen_wear'), value = 'citizen_wear'}, - {label = TranslateCap('bullet_wear'), uniform = 'bullet_wear'}, - {label = TranslateCap('gilet_wear'), uniform = 'gilet_wear'}, - {label = TranslateCap('police_wear'), uniform = grade} + {unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom")}, + {icon = "fas fa-shirt", title = TranslateCap('citizen_wear'), value = 'citizen_wear'}, + {icon = "fas fa-shirt", title = TranslateCap('bullet_wear'), uniform = 'bullet_wear'}, + {icon = "fas fa-shirt", title = TranslateCap('gilet_wear'), uniform = 'gilet_wear'}, + {icon = "fas fa-shirt", title = TranslateCap('police_wear'), uniform = grade} } if Config.EnableCustomPeds then for k,v in ipairs(Config.CustomPeds.shared) do - table.insert(elements, {label = v.label, value = 'freemode_ped', maleModel = v.maleModel, femaleModel = v.femaleModel}) + elements[#elements+1] = { + icon = "fas fa-shirt", + title = v.label, + value = 'freemode_ped', + maleModel = v.maleModel, + femaleModel = v.femaleModel + } end for k,v in ipairs(Config.CustomPeds[grade]) do - table.insert(elements, {label = v.label, value = 'freemode_ped', maleModel = v.maleModel, femaleModel = v.femaleModel}) + elements[#elements+1] = { + icon = "fas fa-shirt", + title = v.label, + value = 'freemode_ped', + maleModel = v.maleModel, + femaleModel = v.femaleModel + } end end - ESX.UI.Menu.CloseAll() - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'cloakroom', { - title = TranslateCap('cloakroom'), - align = 'top-left', - elements = elements - }, function(data, menu) + ESX.OpenContext("right", elements, function(menu,element) cleanPlayer(playerPed) + local data = {current = element} if data.current.value == 'citizen_wear' then if Config.EnableCustomPeds then @@ -194,9 +202,7 @@ function OpenCloakroomMenu() end) end) end - end, function(data, menu) - menu.close() - + end, function(menu) CurrentAction = 'menu_cloakroom' CurrentActionMsg = TranslateCap('open_cloackroom') CurrentActionData = {} @@ -207,28 +213,24 @@ function OpenArmoryMenu(station) local elements if Config.OxInventory then exports.ox_inventory:openInventory('stash', {id = 'society_police', owner = station}) - return ESX.UI.Menu.CloseAll() + return ESX.CloseContext() else elements = { - {label = TranslateCap('buy_weapons'), value = 'buy_weapons'} + {unselectable = true, icon = "fas fa-gun", title = TranslateCap('armory')}, + {icon = "fas fa-gun", title = TranslateCap('buy_weapons'), value = 'buy_weapons'} + } if Config.EnableArmoryManagement then - table.insert(elements, {label = TranslateCap('get_weapon'), value = 'get_weapon'}) - table.insert(elements, {label = TranslateCap('put_weapon'), value = 'put_weapon'}) - table.insert(elements, {label = TranslateCap('remove_object'), value = 'get_stock'}) - table.insert(elements, {label = TranslateCap('deposit_object'), value = 'put_stock'}) + table.insert(elements, {icon = "fas fa-gun", title = TranslateCap('get_weapon'), value = 'get_weapon'}) + table.insert(elements, {icon = "fas fa-gun", title = TranslateCap('put_weapon'), value = 'put_weapon'}) + table.insert(elements, {icon = "fas fa-box", title = TranslateCap('remove_object'), value = 'get_stock'}) + table.insert(elements, {icon = "fas fa-box", title = TranslateCap('deposit_object'), value = 'put_stock'}) end end - ESX.UI.Menu.CloseAll() - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory', { - title = TranslateCap('armory'), - align = 'top-left', - elements = elements - }, function(data, menu) - + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} if data.current.value == 'get_weapon' then OpenGetWeaponMenu() elseif data.current.value == 'put_weapon' then @@ -240,10 +242,7 @@ function OpenArmoryMenu(station) elseif data.current.value == 'get_stock' then OpenGetStocksMenu() end - - end, function(data, menu) - menu.close() - + end, function(menu) CurrentAction = 'menu_armory' CurrentActionMsg = TranslateCap('open_armory') CurrentActionData = {station = station} @@ -251,39 +250,41 @@ function OpenArmoryMenu(station) end function OpenPoliceActionsMenu() - ESX.UI.Menu.CloseAll() + local elements = { + {unselectable = true, icon = "fas fa-police", title = "Police"}, + {icon = "fas fa-user", title = TranslateCap('citizen_interaction'), value = 'citizen_interaction'}, + {icon = "fas fa-car", title = TranslateCap('vehicle_interaction'), value = 'vehicle_interaction'}, + {icon = "fas fa-object", title = TranslateCap('object_spawner'), value = 'object_spawner'} + } + + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'police_actions', { - title = 'Police', - align = 'top-left', - elements = { - {label = TranslateCap('citizen_interaction'), value = 'citizen_interaction'}, - {label = TranslateCap('vehicle_interaction'), value = 'vehicle_interaction'}, - {label = TranslateCap('object_spawner'), value = 'object_spawner'} - }}, function(data, menu) if data.current.value == 'citizen_interaction' then - local elements = { - {label = TranslateCap('id_card'), value = 'identity_card'}, - {label = TranslateCap('search'), value = 'search'}, - {label = TranslateCap('handcuff'), value = 'handcuff'}, - {label = TranslateCap('drag'), value = 'drag'}, - {label = TranslateCap('put_in_vehicle'), value = 'put_in_vehicle'}, - {label = TranslateCap('out_the_vehicle'), value = 'out_the_vehicle'}, - {label = TranslateCap('fine'), value = 'fine'}, - {label = TranslateCap('unpaid_bills'), value = 'unpaid_bills'} + local elements2 = { + {unselectable = true, icon = "fas fa-user", title = element.title}, + {icon = "fas fa-idkyet", title = TranslateCap('id_card'), value = 'identity_card'}, + {icon = "fas fa-idkyet", title = TranslateCap('search'), value = 'search'}, + {icon = "fas fa-idkyet", title = TranslateCap('handcuff'), value = 'handcuff'}, + {icon = "fas fa-idkyet", title = TranslateCap('drag'), value = 'drag'}, + {icon = "fas fa-idkyet", title = TranslateCap('put_in_vehicle'), value = 'put_in_vehicle'}, + {icon = "fas fa-idkyet", title = TranslateCap('out_the_vehicle'), value = 'out_the_vehicle'}, + {icon = "fas fa-idkyet", title = TranslateCap('fine'), value = 'fine'}, + {icon = "fas fa-idkyet", title = TranslateCap('unpaid_bills'), value = 'unpaid_bills'} } if Config.EnableLicenses then - table.insert(elements, {label = TranslateCap('license_check'), value = 'license'}) + elements2[#elements2+1] = { + icon = "fas fa-scroll", + title = TranslateCap('license_check'), + value = 'license' + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction', { - title = TranslateCap('citizen_interaction'), - align = 'top-left', - elements = elements - }, function(data2, menu2) + ESX.OpenContext("right", elements2, function(menu2,element2) local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() if closestPlayer ~= -1 and closestDistance <= 3.0 then + local data2 = {current = element2} local action = data2.current.value if action == 'identity_card' then @@ -308,33 +309,36 @@ function OpenPoliceActionsMenu() else ESX.ShowNotification(TranslateCap('no_players_nearby')) end - end, function(data2, menu2) - menu2.close() + end, function(menu) + OpenPoliceActionsMenu() end) elseif data.current.value == 'vehicle_interaction' then - local elements = {} + local elements3 = { + {unselectable = true, icon = "fas fa-car", title = element.title} + } local playerPed = PlayerPedId() local vehicle = ESX.Game.GetVehicleInDirection() if DoesEntityExist(vehicle) then - table.insert(elements, {label = TranslateCap('vehicle_info'), value = 'vehicle_infos'}) - table.insert(elements, {label = TranslateCap('pick_lock'), value = 'hijack_vehicle'}) - table.insert(elements, {label = TranslateCap('impound'), value = 'impound'}) + elements3[#elements3+1] = {icon = "fas fa-car", title = TranslateCap('vehicle_info'), value = 'vehicle_infos'} + elements3[#elements3+1] = {icon = "fas fa-car", title = TranslateCap('pick_lock'), value = 'hijack_vehicle'} + elements3[#elements3+1] = {icon = "fas fa-car", title = TranslateCap('impound'), value = 'impound'} end - table.insert(elements, {label = TranslateCap('search_database'), value = 'search_database'}) - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_interaction', { - title = TranslateCap('vehicle_interaction'), - align = 'top-left', - elements = elements - }, function(data2, menu2) + elements3[#elements3+1] = { + icon = "fas fa-scroll", + title = TranslateCap('search_database'), + value = 'search_database' + } + + ESX.OpenContext("right", elements3, function(menu3,element3) + local data2 = {current = element3} local coords = GetEntityCoords(playerPed) vehicle = ESX.Game.GetVehicleInDirection() action = data2.current.value if action == 'search_database' then - LookupVehicle() + LookupVehicle(element3) elseif DoesEntityExist(vehicle) then if action == 'vehicle_infos' then local vehicleData = ESX.Game.GetVehicleProperties(vehicle) @@ -350,7 +354,6 @@ function OpenPoliceActionsMenu() ESX.ShowNotification(TranslateCap('vehicle_unlocked')) end elseif action == 'impound' then - -- is the script busy? if currentTask.busy then return end @@ -362,10 +365,9 @@ function OpenPoliceActionsMenu() currentTask.task = ESX.SetTimeout(10000, function() ClearPedTasks(playerPed) ImpoundVehicle(vehicle) - Wait(100) -- sleep the entire script to let stuff sink back to reality + Wait(100) end) - -- keep track of that vehicle! CreateThread(function() while currentTask.busy do Wait(1000) @@ -384,21 +386,21 @@ function OpenPoliceActionsMenu() else ESX.ShowNotification(TranslateCap('no_vehicles_nearby')) end - - end, function(data2, menu2) - menu2.close() + end, function(menu) + OpenPoliceActionsMenu() end) - elseif data.current.value == 'object_spawner' then - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction', { - title = TranslateCap('traffic_interaction'), - align = 'top-left', - elements = { - {label = TranslateCap('cone'), model = 'prop_roadcone02a'}, - {label = TranslateCap('barrier'), model = 'prop_barrier_work05'}, - {label = TranslateCap('spikestrips'), model = 'p_ld_stinger_s'}, - {label = TranslateCap('box'), model = 'prop_boxpile_07d'}, - {label = TranslateCap('cash'), model = 'hei_prop_cash_crate_half_full'} - }}, function(data2, menu2) + elseif data.current.value == "object_spawner" then + local elements4 = { + {unselectable = true, icon = "fas fa-object", title = element.title}, + {icon = "fas fa-cone", title = TranslateCap('cone'), model = 'prop_roadcone02a'}, + {icon = "fas fa-cone", title = TranslateCap('barrier'), model = 'prop_barrier_work05'}, + {icon = "fas fa-cone", title = TranslateCap('spikestrips'), model = 'p_ld_stinger_s'}, + {icon = "fas fa-cone", title = TranslateCap('box'), model = 'prop_boxpile_07d'}, + {icon = "fas fa-cone", title = TranslateCap('cash'), model = 'hei_prop_cash_crate_half_full'} + } + + ESX.OpenContext("right", elements4, function(menu4,element4) + local data2 = {current = element4} local playerPed = PlayerPedId() local coords, forward = GetEntityCoords(playerPed), GetEntityForwardVector(playerPed) local objectCoords = (coords + forward * 1.0) @@ -407,46 +409,40 @@ function OpenPoliceActionsMenu() SetEntityHeading(obj, GetEntityHeading(playerPed)) PlaceObjectOnGroundProperly(obj) end) - end, function(data2, menu2) - menu2.close() + end, function(menu) + OpenPoliceActionsMenu() end) end - end, function(data, menu) - menu.close() end) end function OpenIdentityCardMenu(player) ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(data) local elements = { - {label = TranslateCap('name', data.name)}, - {label = TranslateCap('job', ('%s - %s'):format(data.job, data.grade))} + {icon = "fas fa-user", title = TranslateCap('name', data.name)}, + {icon = "fas fa-user", title = TranslateCap('job', ('%s - %s'):format(data.job, data.grade))} } if Config.EnableESXIdentity then - table.insert(elements, {label = TranslateCap('sex', TranslateCap(data.sex))}) - table.insert(elements, {label = TranslateCap('dob', data.dob)}) - table.insert(elements, {label = TranslateCap('height', data.height)}) + elements[#elements+1] = {icon = "fas fa-user", title = TranslateCap('sex', TranslateCap(data.sex))} + elements[#elements+1] = {icon = "fas fa-user", title = TranslateCap('sex', TranslateCap(data.sex))} + elements[#elements+1] = {icon = "fas fa-user", title = TranslateCap('height', data.height)} end if Config.EnableESXOptionalneeds and data.drunk then - table.insert(elements, {label = TranslateCap('bac', data.drunk)}) + elements[#elements+1] = {title = TranslateCap('bac', data.drunk)} end if data.licenses then - table.insert(elements, {label = TranslateCap('license_label')}) + elements[#elements+1] = {title = TranslateCap('license_label')} for i=1, #data.licenses, 1 do - table.insert(elements, {label = data.licenses[i].label}) + elements[#elements+1] = {title = data.licenses[i].label} end end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction', { - title = TranslateCap('citizen_interaction'), - align = 'top-left', - elements = elements - }, nil, function(data, menu) - menu.close() + ESX.OpenContext("right", elements, nil, function(menu) + OpenPoliceActionsMenu() end) end, GetPlayerServerId(player)) end @@ -454,21 +450,23 @@ end function OpenBodySearchMenu(player) if Config.OxInventory then exports.ox_inventory:openInventory('player', GetPlayerServerId(player)) - return ESX.UI.Menu.CloseAll() + return ESX.CloseContext() end ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(data) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-user", title = TranslateCap('search')} + } for i=1, #data.accounts, 1 do if data.accounts[i].name == 'black_money' and data.accounts[i].money > 0 then - table.insert(elements, { - label = TranslateCap('confiscate_dirty', ESX.Math.Round(data.accounts[i].money)), + elements[#elements+1] = { + icon = "fas fa-money", + title = TranslateCap('confiscate_dirty', ESX.Math.Round(data.accounts[i].money)), value = 'black_money', itemType = 'item_account', amount = data.accounts[i].money - }) - + } break end end @@ -476,78 +474,72 @@ function OpenBodySearchMenu(player) table.insert(elements, {label = TranslateCap('guns_label')}) for i=1, #data.weapons, 1 do - table.insert(elements, { - label = TranslateCap('confiscate_weapon', ESX.GetWeaponLabel(data.weapons[i].name), data.weapons[i].ammo), + elements[#elements+1] = { + icon = "fas fa-gun", + title = TranslateCap('confiscate_weapon', ESX.GetWeaponLabel(data.weapons[i].name), data.weapons[i].ammo), value = data.weapons[i].name, itemType = 'item_weapon', amount = data.weapons[i].ammo - }) + } end - table.insert(elements, {label = TranslateCap('inventory_label')}) + elements[#elements+1] = {title = TranslateCap('inventory_label')} for i=1, #data.inventory, 1 do if data.inventory[i].count > 0 then - table.insert(elements, { - label = TranslateCap('confiscate_inv', data.inventory[i].count, data.inventory[i].label), + elements[#elements+1] = { + icon = "fas fa-box", + title = TranslateCap('confiscate_inv', data.inventory[i].count, data.inventory[i].label), value = data.inventory[i].name, itemType = 'item_standard', amount = data.inventory[i].count - }) + } end end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'body_search', { - title = TranslateCap('search'), - align = 'top-left', - elements = elements - }, function(data, menu) + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} if data.current.value then TriggerServerEvent('esx_policejob:confiscatePlayerItem', GetPlayerServerId(player), data.current.itemType, data.current.value, data.current.amount) OpenBodySearchMenu(player) end - end, function(data, menu) - menu.close() end) end, GetPlayerServerId(player)) end function OpenFineMenu(player) - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'fine', { - title = TranslateCap('fine'), - align = 'top-left', - elements = { - {label = TranslateCap('traffic_offense'), value = 0}, - {label = TranslateCap('minor_offense'), value = 1}, - {label = TranslateCap('average_offense'), value = 2}, - {label = TranslateCap('major_offense'), value = 3} - }}, function(data, menu) + local elements = { + {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('fine')}, + {icon = "fas fa-scroll", title = TranslateCap('traffic_offense'), value = 0}, + {icon = "fas fa-scroll", title = TranslateCap('minor_offense'), value = 1}, + {icon = "fas fa-scroll", title = TranslateCap('average_offense'), value = 2}, + {icon = "fas fa-scroll", title = TranslateCap('major_offense'), value = 3} + } + + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} OpenFineCategoryMenu(player, data.current.value) - end, function(data, menu) - menu.close() end) end function OpenFineCategoryMenu(player, category) ESX.TriggerServerCallback('esx_policejob:getFineList', function(fines) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('fine')} + } for k,fine in ipairs(fines) do - table.insert(elements, { - label = ('%s %s'):format(fine.label, TranslateCap('armory_item', ESX.Math.GroupDigits(fine.amount))), + elements[#elements+1] = { + icon = "fas fa-scroll", + title = ('%s %s'):format(fine.label, TranslateCap('armory_item', ESX.Math.GroupDigits(fine.amount))), value = fine.id, amount = fine.amount, fineLabel = fine.label - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'fine_category', { - title = TranslateCap('fine'), - align = 'top-left', - elements = elements - }, function(data, menu) - menu.close() - + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} if Config.EnablePlayerManagement then TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), 'society_police', TranslateCap('fine_total', data.current.fineLabel), data.current.amount) else @@ -557,65 +549,63 @@ function OpenFineCategoryMenu(player, category) ESX.SetTimeout(300, function() OpenFineCategoryMenu(player, category) end) - end, function(data, menu) - menu.close() end) end, category) end -function LookupVehicle() - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'lookup_vehicle', { - title = TranslateCap('search_database_title'), - }, function(data, menu) +function LookupVehicle(elementF) + local elements = { + {unselectable = true, icon = "fas fa-car", title = elementF.title}, + {title = "Enter Plate", input = true, inputType = "text", inputPlaceholder = "ABC 123"}, + {icon = "fas fa-check-double", title = "Lookup Plate", value = "lookup"} + } + + ESX.OpenContext("right", elements, function(menu,element) + local data = {value = menu.eles[2].inputValue} local length = string.len(data.value) if not data.value or length < 2 or length > 8 then ESX.ShowNotification(TranslateCap('search_database_error_invalid')) else ESX.TriggerServerCallback('esx_policejob:getVehicleInfos', function(retrivedInfo) - local elements = {{label = TranslateCap('plate', retrivedInfo.plate)}} - menu.close() + local elements = { + {unselectable = true, icon = "fas fa-car", title = element.title}, + {unselectable = true, icon = "fas fa-car", title = TranslateCap('plate', retrivedInfo.plate)} + } if not retrivedInfo.owner then - table.insert(elements, {label = TranslateCap('owner_unknown')}) + elements[#elements+1] = {unselectable = true, icon = "fas fa-user", title = TranslateCap('owner_unknown')} else - table.insert(elements, {label = TranslateCap('owner', retrivedInfo.owner)}) + elements[#elements+1] = {unselectable = true, icon = "fas fa-user", title = TranslateCap('owner', retrivedInfo.owner)} end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_infos', { - title = TranslateCap('vehicle_info'), - align = 'top-left', - elements = elements - }, nil, function(data2, menu2) - menu2.close() + ESX.OpenContext("right", elements, nil, function(menu) + OpenPoliceActionsMenu() end) end, data.value) - end - end, function(data, menu) - menu.close() end) end function ShowPlayerLicense(player) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('license_revoke')} + } ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(playerData) if playerData.licenses then for i=1, #playerData.licenses, 1 do if playerData.licenses[i].label and playerData.licenses[i].type then - table.insert(elements, { - label = playerData.licenses[i].label, + elements[#elements+1] = { + icon = "fas fa-scroll", + title = playerData.licenses[i].label, type = playerData.licenses[i].type - }) + } end end end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'manage_license', { - title = TranslateCap('license_revoke'), - align = 'top-left', - elements = elements, - }, function(data, menu) + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} ESX.ShowNotification(TranslateCap('licence_you_revoked', data.current.label, playerData.name)) TriggerServerEvent('esx_policejob:message', GetPlayerServerId(player), TranslateCap('license_revoked', data.current.label)) @@ -624,85 +614,77 @@ function ShowPlayerLicense(player) ESX.SetTimeout(300, function() ShowPlayerLicense(player) end) - end, function(data, menu) - menu.close() end) - end, GetPlayerServerId(player)) end function OpenUnpaidBillsMenu(player) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('unpaid_bills')} + } ESX.TriggerServerCallback('esx_billing:getTargetBills', function(bills) for k,bill in ipairs(bills) do - table.insert(elements, { - label = ('%s - %s'):format(bill.label, TranslateCap('armory_item', ESX.Math.GroupDigits(bill.amount))), + elements[#elements+1] = { + unselectable = true, + icon = "fas fa-scroll", + title = ('%s - %s'):format(bill.label, TranslateCap('armory_item', ESX.Math.GroupDigits(bill.amount))), billId = bill.id - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'billing', { - title = TranslateCap('unpaid_bills'), - align = 'top-left', - elements = elements - }, nil, function(data, menu) - menu.close() - end) + ESX.OpenContext("right", elements, nil, nil) end, GetPlayerServerId(player)) end function OpenVehicleInfosMenu(vehicleData) ESX.TriggerServerCallback('esx_policejob:getVehicleInfos', function(retrivedInfo) - local elements = {{label = TranslateCap('plate', retrivedInfo.plate)}} + local elements = { + {unselectable = true, icon = "fas fa-car", title = TranslateCap('vehicle_info')}, + {icon = "fas fa-car", title = TranslateCap('plate', retrivedInfo.plate)} + + } if not retrivedInfo.owner then - table.insert(elements, {label = TranslateCap('owner_unknown')}) + elements[#elements+1] = {unselectable = true, icon = "fas fa-user", title = TranslateCap('owner_unknown')} else - table.insert(elements, {label = TranslateCap('owner', retrivedInfo.owner)}) + elements[#elements+1] = {unselectable = true, icon = "fas fa-user", title = TranslateCap('owner', retrivedInfo.owner)} end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_infos', { - title = TranslateCap('vehicle_info'), - align = 'top-left', - elements = elements - }, nil, function(data, menu) - menu.close() - end) + ESX.OpenContext("right", elements, nil, nil) end, vehicleData.plate) end function OpenGetWeaponMenu() ESX.TriggerServerCallback('esx_policejob:getArmoryWeapons', function(weapons) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-gun", title = TranslateCap('get_weapon_menu')} + } for i=1, #weapons, 1 do if weapons[i].count > 0 then - table.insert(elements, { - label = 'x' .. weapons[i].count .. ' ' .. ESX.GetWeaponLabel(weapons[i].name), + elements[#elements+1] = { + icon = "fas fa-gun", + title = 'x' .. weapons[i].count .. ' ' .. ESX.GetWeaponLabel(weapons[i].name), value = weapons[i].name - }) + } end end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory_get_weapon', { - title = TranslateCap('get_weapon_menu'), - align = 'top-left', - elements = elements - }, function(data, menu) - menu.close() - + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} ESX.TriggerServerCallback('esx_policejob:removeArmoryWeapon', function() + ESX.CloseContext() OpenGetWeaponMenu() end, data.current.value) - end, function(data, menu) - menu.close() end) end) end function OpenPutWeaponMenu() - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-gun", title = TranslateCap('put_weapon_menu')} + } local playerPed = PlayerPedId() local weaponList = ESX.GetWeaponList() @@ -710,30 +692,27 @@ function OpenPutWeaponMenu() local weaponHash = joaat(weaponList[i].name) if HasPedGotWeapon(playerPed, weaponHash, false) and weaponList[i].name ~= 'WEAPON_UNARMED' then - table.insert(elements, { - label = weaponList[i].label, + elements[#elements+1] = { + icon = "fas fa-gun", + title = weaponList[i].label, value = weaponList[i].name - }) + } end end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory_put_weapon', { - title = TranslateCap('put_weapon_menu'), - align = 'top-left', - elements = elements - }, function(data, menu) - menu.close() - + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} ESX.TriggerServerCallback('esx_policejob:addArmoryWeapon', function() + ESX.CloseContext() OpenPutWeaponMenu() end, data.current.value, true) - end, function(data, menu) - menu.close() end) end function OpenBuyWeaponsMenu() - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-gun", title = TranslateCap('armory_weapontitle')} + } local playerPed = PlayerPedId() for k,v in ipairs(Config.AuthorizedWeapons[ESX.PlayerData.job.grade_name]) do @@ -757,15 +736,16 @@ function OpenBuyWeaponsMenu() end end - table.insert(components, { - label = label, + components[#components+1] = { + icon = "fas fa-gun", + title = label, componentLabel = component.label, hash = component.hash, name = component.name, price = v.components[i], hasComponent = hasComponent, componentNum = i - }) + } end end end @@ -782,21 +762,19 @@ function OpenBuyWeaponsMenu() end end - table.insert(elements, { - label = label, + elements[#elements+1] = { + icon = "fas fa-gun", + title = label, weaponLabel = weapon.label, name = weapon.name, components = components, price = v.price, hasWeapon = hasWeapon - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory_buy_weapons', { - title = TranslateCap('armory_weapontitle'), - align = 'top-left', - elements = elements - }, function(data, menu) + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} if data.current.hasWeapon then if #data.current.components > 0 then OpenWeaponComponentShop(data.current.components, data.current.name, menu) @@ -815,17 +793,13 @@ function OpenBuyWeaponsMenu() end end, data.current.name, 1) end - end, function(data, menu) - menu.close() end) end function OpenWeaponComponentShop(components, weaponName, parentShop) - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory_buy_weapons_components', { - title = TranslateCap('armory_componenttitle'), - align = 'top-left', - elements = components - }, function(data, menu) + + ESX.OpenContext("right", components, function(menu,element) + local data = {current = element} if data.current.hasComponent then ESX.ShowNotification(TranslateCap('armory_hascomponent')) else @@ -843,96 +817,94 @@ function OpenWeaponComponentShop(components, weaponName, parentShop) end end, weaponName, 2, data.current.componentNum) end - end, function(data, menu) - menu.close() end) end function OpenGetStocksMenu() ESX.TriggerServerCallback('esx_policejob:getStockItems', function(items) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-box", title = TranslateCap('police_stock')} + } for i=1, #items, 1 do - table.insert(elements, { - label = 'x' .. items[i].count .. ' ' .. items[i].label, + elements[#elements+1] = { + icon = "fas fa-box", + title = 'x' .. items[i].count .. ' ' .. items[i].label, value = items[i].name - }) + } end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'stocks_menu', { - title = TranslateCap('police_stock'), - align = 'top-left', - elements = elements - }, function(data, menu) + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} local itemName = data.current.value - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_get_item_count', { - title = TranslateCap('quantity') - }, function(data2, menu2) + local elements2 = { + {unselectable = true, icon = "fas fa-box", title = element.title}, + {title = TranslateCap('quantity'), input = true, inputType = "number", inputMin = 1, inputMax = 150, inputPlaceholder = "Amount to withdraw.."}, + {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local data2 = {value = menu2.eles[2].inputValue} local count = tonumber(data2.value) if not count then ESX.ShowNotification(TranslateCap('quantity_invalid')) else - menu2.close() - menu.close() + ESX.CloseContext() TriggerServerEvent('esx_policejob:getStockItem', itemName, count) Wait(300) OpenGetStocksMenu() end - end, function(data2, menu2) - menu2.close() end) - end, function(data, menu) - menu.close() end) end) end function OpenPutStocksMenu() ESX.TriggerServerCallback('esx_policejob:getPlayerInventory', function(inventory) - local elements = {} + local elements = { + {unselectable = true, icon = "fas fa-box", title = TranslateCap('inventory')} + } for i=1, #inventory.items, 1 do local item = inventory.items[i] if item.count > 0 then - table.insert(elements, { - label = item.label .. ' x' .. item.count, + elements[#elements+1] = { + icon = "fas fa-box", + title = item.label .. ' x' .. item.count, type = 'item_standard', value = item.name - }) + } end end - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'stocks_menu', { - title = TranslateCap('inventory'), - align = 'top-left', - elements = elements - }, function(data, menu) + ESX.OpenContext("right", elements, function(menu,element) + local data = {current = element} local itemName = data.current.value - ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_put_item_count', { - title = TranslateCap('quantity') - }, function(data2, menu2) + local elements2 = { + {unselectable = true, icon = "fas fa-box", title = element.title}, + {title = TranslateCap('quantity'), input = true, inputType = "number", inputMin = 1, inputMax = 150, inputPlaceholder = "Amount to withdraw.."}, + {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} + } + + ESX.OpenContext("right", elements2, function(menu2,element2) + local data2 = {value = menu2.eles[2].inputValue} local count = tonumber(data2.value) if not count then ESX.ShowNotification(TranslateCap('quantity_invalid')) else - menu2.close() - menu.close() + ESX.CloseContext() TriggerServerEvent('esx_policejob:putStockItems', itemName, count) Wait(300) OpenPutStocksMenu() end - end, function(data2, menu2) - menu2.close() end) - end, function(data, menu) - menu.close() end) end) end @@ -993,7 +965,7 @@ end) AddEventHandler('esx_policejob:hasExitedMarker', function(station, part, partNum) if not isInShopMenu then - ESX.UI.Menu.CloseAll() + ESX.CloseContext() end CurrentAction = nil @@ -1437,7 +1409,7 @@ ESX.RegisterInput("police:interact", "(ESX PoliceJob) Interact", "keyboard", "E" elseif CurrentAction == 'delete_vehicle' then ESX.Game.DeleteVehicle(CurrentActionData.vehicle) elseif CurrentAction == 'menu_boss_actions' then - ESX.UI.Menu.CloseAll() + ESX.CloseContext() TriggerEvent('esx_society:openBossMenu', 'police', function(data, menu) menu.close() diff --git a/[esx_addons]/esx_policejob/client/vehicle.lua b/[esx_addons]/esx_policejob/client/vehicle.lua index 34b19e5e..34841a25 100644 --- a/[esx_addons]/esx_policejob/client/vehicle.lua +++ b/[esx_addons]/esx_policejob/client/vehicle.lua @@ -3,16 +3,15 @@ local spawnedVehicles = {} function OpenVehicleSpawnerMenu(type, station, part, partNum) local playerCoords = GetEntityCoords(PlayerPedId()) + local elements = { + {unselectable = true, icon = "fas fa-car", title = TranslateCap('garage_title')}, + {icon = "fas fa-car", title = TranslateCap('garage_storeditem'), action = 'garage'}, + {icon = "fas fa-car", title = TranslateCap('garage_storeitem'), action = 'store_garage'}, + {icon = "fas fa-car", title = TranslateCap('garage_buyitem'), action = 'buy_vehicle'} + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle', { - title = TranslateCap('garage_title'), - align = 'top-left', - elements = { - {label = TranslateCap('garage_storeditem'), action = 'garage'}, - {label = TranslateCap('garage_storeitem'), action = 'store_garage'}, - {label = TranslateCap('garage_buyitem'), action = 'buy_vehicle'} - }}, function(data, menu) - if data.current.action == 'buy_vehicle' then + ESX.OpenContext("right", elements, function(menu,element) + if element.action == "buy_vehicle" then local shopElements = {} local shopCoords = Config.PoliceStations[station][part][partNum].InsideShop local authorizedVehicles = Config.AuthorizedVehicles[type][ESX.PlayerData.job.grade_name] @@ -23,14 +22,15 @@ function OpenVehicleSpawnerMenu(type, station, part, partNum) if IsModelInCdimage(vehicle.model) then local vehicleLabel = GetLabelText(GetDisplayNameFromVehicleModel(vehicle.model)) - table.insert(shopElements, { - label = ('%s - %s'):format(vehicleLabel, TranslateCap('shop_item', ESX.Math.GroupDigits(vehicle.price))), + shopElements[#shopElements+1] = { + icon = 'fas fa-car', + title = ('%s - %s'):format(vehicleLabel, TranslateCap('shop_item', ESX.Math.GroupDigits(vehicle.price))), name = vehicleLabel, model = vehicle.model, price = vehicle.price, props = vehicle.props, type = type - }) + } end end @@ -45,8 +45,10 @@ function OpenVehicleSpawnerMenu(type, station, part, partNum) else ESX.ShowNotification(TranslateCap('garage_notauthorized')) end - elseif data.current.action == 'garage' then - local garage = {} + elseif element.action == "garage" then + local garage = { + {unselectable = true, icon = "fas fa-car", title = "Garage"} + } ESX.TriggerServerCallback('esx_vehicleshop:retrieveJobVehicles', function(jobVehicles) if #jobVehicles > 0 then @@ -65,42 +67,37 @@ function OpenVehicleSpawnerMenu(type, station, part, partNum) label = label .. ('%s'):format(TranslateCap('garage_notstored')) end - table.insert(garage, { - label = label, + garage[#garage+1] = { + icon = 'fas fa-car', + title = label, stored = v.stored, model = props.model, plate = props.plate - }) + } allVehicleProps[props.plate] = props end end if #garage > 0 then - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_garage', { - title = TranslateCap('garage_title'), - align = 'top-left', - elements = garage - }, function(data2, menu2) - if data2.current.stored == 1 then + ESX.OpenContext("right", garage, function(menuG,elementG) + if elementG.stored == 1 then local foundSpawn, spawnPoint = GetAvailableVehicleSpawnPoint(station, part, partNum) if foundSpawn then - menu2.close() + ESX.CloseContext() - ESX.Game.SpawnVehicle(data2.current.model, spawnPoint.coords, spawnPoint.heading, function(vehicle) - local vehicleProps = allVehicleProps[data2.current.plate] + ESX.Game.SpawnVehicle(elementG.model, spawnPoint.coords, spawnPoint.heading, function(vehicle) + local vehicleProps = allVehicleProps[elementG.plate] ESX.Game.SetVehicleProperties(vehicle, vehicleProps) - TriggerServerEvent('esx_vehicleshop:setJobVehicleState', data2.current.plate, false) + TriggerServerEvent('esx_vehicleshop:setJobVehicleState', elementG.plate, false) ESX.ShowNotification(TranslateCap('garage_released')) end) end else ESX.ShowNotification(TranslateCap('garage_notavailable')) end - end, function(data2, menu2) - menu2.close() end) else ESX.ShowNotification(TranslateCap('garage_empty')) @@ -109,11 +106,9 @@ function OpenVehicleSpawnerMenu(type, station, part, partNum) ESX.ShowNotification(TranslateCap('garage_empty')) end end, type) - elseif data.current.action == 'store_garage' then + elseif element.action == "store_garage" then StoreNearbyVehicle(playerCoords) end - end, function(data, menu) - menu.close() end) end @@ -207,85 +202,74 @@ end function OpenShopMenu(elements, restoreCoords, shopCoords) local playerPed = PlayerPedId() isInShopMenu = true + ESX.OpenContext("right", elements, function(menu,element) + local elements2 = { + {unselectable = true, icon = "fas fa-car", title = element.title}, + {icon = "fas fa-eye", title = "View", value = "view"} + } - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop', { - title = TranslateCap('vehicleshop_title'), - align = 'top-left', - elements = elements - }, function(data, menu) - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop_confirm', { - title = TranslateCap('vehicleshop_confirm', data.current.name, data.current.price), - align = 'top-left', - elements = { - {label = TranslateCap('confirm_no'), value = 'no'}, - {label = TranslateCap('confirm_yes'), value = 'yes'} - }}, function(data2, menu2) - if data2.current.value == 'yes' then - local newPlate = exports['esx_vehicleshop']:GeneratePlate() - local vehicle = GetVehiclePedIsIn(playerPed, false) - local props = ESX.Game.GetVehicleProperties(vehicle) - props.plate = newPlate + ESX.OpenContext("right", elements2, function(menu2,element2) + if element2.value == "view" then + DeleteSpawnedVehicles() + WaitForVehicleToLoad(element.model) - ESX.TriggerServerCallback('esx_policejob:buyJobVehicle', function (bought) - if bought then - ESX.ShowNotification(TranslateCap('vehicleshop_bought', data.current.name, ESX.Math.GroupDigits(data.current.price))) + ESX.Game.SpawnLocalVehicle(element.model, shopCoords, 0.0, function(vehicle) + table.insert(spawnedVehicles, vehicle) + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + FreezeEntityPosition(vehicle, true) + SetModelAsNoLongerNeeded(element.model) + if element.props then + ESX.Game.SetVehicleProperties(vehicle, element.props) + end + end) + + local elements3 = { + {unselectable = true, icon = "fas fa-car", title = element.title}, + {icon = "fas fa-check-double", title = "Buy", value = "buy"}, + {icon = "fas fa-eye", title = "Stop Viewing", value = "stop"} + } + + ESX.OpenContext("right", elements3, function(menu3,element3) + if element3.value == 'stop' then isInShopMenu = false - ESX.UI.Menu.CloseAll() + ESX.CloseContext() + DeleteSpawnedVehicles() FreezeEntityPosition(playerPed, false) SetEntityVisible(playerPed, true) ESX.Game.Teleport(playerPed, restoreCoords) - else - ESX.ShowNotification(TranslateCap('vehicleshop_money')) - menu2.close() + elseif element3.value == "buy" then + local newPlate = exports['esx_vehicleshop']:GeneratePlate() + local vehicle = GetVehiclePedIsIn(playerPed, false) + local props = ESX.Game.GetVehicleProperties(vehicle) + props.plate = newPlate + + ESX.TriggerServerCallback('esx_policejob:buyJobVehicle', function (bought) + if bought then + ESX.ShowNotification(TranslateCap('vehicleshop_bought', element.name, ESX.Math.GroupDigits(element.price))) + + isInShopMenu = false + ESX.CloseContext() + DeleteSpawnedVehicles() + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + + ESX.Game.Teleport(playerPed, restoreCoords) + else + ESX.ShowNotification(TranslateCap('vehicleshop_money')) + ESX.CloseContext() + end + end, props, element.type) end - end, props, data.current.type) - else - menu2.close() - end - end, function(data2, menu2) - menu2.close() - end) - end, function(data, menu) - isInShopMenu = false - ESX.UI.Menu.CloseAll() - - DeleteSpawnedVehicles() - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - - ESX.Game.Teleport(playerPed, restoreCoords) - end, function(data, menu) - DeleteSpawnedVehicles() - WaitForVehicleToLoad(data.current.model) - - ESX.Game.SpawnLocalVehicle(data.current.model, shopCoords, 0.0, function(vehicle) - table.insert(spawnedVehicles, vehicle) - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - SetModelAsNoLongerNeeded(data.current.model) - - if data.current.props then - ESX.Game.SetVehicleProperties(vehicle, data.current.props) + end) end end) end) - - WaitForVehicleToLoad(elements[1].model) - ESX.Game.SpawnLocalVehicle(elements[1].model, shopCoords, 0.0, function(vehicle) - table.insert(spawnedVehicles, vehicle) - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - SetModelAsNoLongerNeeded(elements[1].model) - - if elements[1].props then - ESX.Game.SetVehicleProperties(vehicle, elements[1].props) - end - end) end + CreateThread(function() while true do Wait(0) From d0d2c841867e77afe91d9b19fce1920c9a9d1402 Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Tue, 20 Dec 2022 23:07:36 +0530 Subject: [PATCH 66/83] Update UI for canClose function --- [esx]/esx_context/index.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/[esx]/esx_context/index.html b/[esx]/esx_context/index.html index fa50034e..5d15770d 100644 --- a/[esx]/esx_context/index.html +++ b/[esx]/esx_context/index.html @@ -352,8 +352,11 @@ } function Close() { - $.post(`https://${GetParentResourceName()}/closed`) - Closed() + $.post(`https://${GetParentResourceName()}/closed`,(retVal)=>{ + if(retVal){ + Closed() + } + }) } window.addEventListener("message", (e) => { @@ -437,4 +440,4 @@ - \ No newline at end of file + From 54088abcb6bebf368c344680d7ffa689f4c8abbb Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Tue, 20 Dec 2022 23:10:06 +0530 Subject: [PATCH 67/83] Add canClose function to context menu Added a canClose parameter so that the user cannot close the menu by pressing ESC instead has to be force closed via code. --- [esx]/esx_context/main.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/[esx]/esx_context/main.lua b/[esx]/esx_context/main.lua index 5a879643..8a2769c9 100644 --- a/[esx]/esx_context/main.lua +++ b/[esx]/esx_context/main.lua @@ -12,10 +12,11 @@ function Post(fn,...) }) end -function Open(position,eles,onSelect,onClose) +function Open(position,eles,onSelect,onClose,canClose) activeMenu = { position = position, eles = eles, + canClose = canClose, onSelect = onSelect, onClose = onClose } @@ -74,11 +75,11 @@ end) -- NUI Callbacks -- [ closed | selected | changed ] -RegisterNUICallback("closed",function() - if not activeMenu then - return +RegisterNUICallback("closed",function(data,cb) + if not activeMenu or (activeMenu and not activeMenu.canClose) then + return cb(false) end - + cb(true) Closed() end) @@ -266,4 +267,4 @@ if Debug then exports["esx_context"]:Open(position,eles,onSelect,onClose) end) -end \ No newline at end of file +end From cf24e7212dab838d9e7ed3ab0ad92f36e41bc2c3 Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Tue, 20 Dec 2022 23:13:09 +0530 Subject: [PATCH 68/83] Update Multicharacter to fix issue of closing context menu --- [esx]/esx_multicharacter/client/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/[esx]/esx_multicharacter/client/main.lua b/[esx]/esx_multicharacter/client/main.lua index 69365dee..67def6fa 100644 --- a/[esx]/esx_multicharacter/client/main.lua +++ b/[esx]/esx_multicharacter/client/main.lua @@ -164,7 +164,7 @@ if ESX.GetConfig().Multichar then elseif Action.action == "return" then SelectCharacterMenu(Characters, slots) end - end, nil, true) + end, nil, false) end function SelectCharacterMenu(Characters, slots) @@ -212,7 +212,7 @@ if ESX.GetConfig().Multichar then SetPedAoBlobRendering(playerPed, true) ResetEntityAlpha(playerPed) end - end, nil, true) + end, nil, false) end RegisterNetEvent('esx_multicharacter:SetupUI') AddEventHandler('esx_multicharacter:SetupUI', function(data, slots) From c59f654755aa5e40a8808e75adb5b0ed9825bfce Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Tue, 20 Dec 2022 23:26:09 +0530 Subject: [PATCH 69/83] Remove Unused code --- [esx_addons]/esx_banking/client/main.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/[esx_addons]/esx_banking/client/main.lua b/[esx_addons]/esx_banking/client/main.lua index e87c5d55..be960269 100644 --- a/[esx_addons]/esx_banking/client/main.lua +++ b/[esx_addons]/esx_banking/client/main.lua @@ -115,7 +115,6 @@ local function StartThread() local atm = GetClosestObjectOfType(_GetEntityCoords, 8.0, Config.AtmModels[i], false) if atm ~= 0 then local atmOffset = GetOffsetFromEntityInWorldCoords(atm, 0.0, -0.7, 0.0) - local atmHeading = GetEntityHeading(atm) local atmDistance = #(_GetEntityCoords - atmOffset) if not isInAtmMarker and atmDistance <= 1.5 then isInAtmMarker = true @@ -242,4 +241,4 @@ AddEventHandler('onResourceStop', function(resource) if isInMenu then CloseUi() end -end) \ No newline at end of file +end) From ccfa9195e0684c8e72221b8f488915d590875c52 Mon Sep 17 00:00:00 2001 From: paarbo <35691223+paarbo@users.noreply.github.com> Date: Wed, 21 Dec 2022 11:38:30 +0000 Subject: [PATCH 70/83] Translated bank related labels --- [SQL]/legacy.sql | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/[SQL]/legacy.sql b/[SQL]/legacy.sql index b68e02e2..ff923035 100644 --- a/[SQL]/legacy.sql +++ b/[SQL]/legacy.sql @@ -1003,20 +1003,20 @@ INSERT INTO `fine_types` (label, amount, category) VALUES -- INSERT INTO `addon_account` (name, label, shared) VALUES - ('society_banker','Banque',1), - ('bank_savings','Livret Bleu',0) + ('society_banker','Bank',1), + ('bank_savings','Savings account',0) ; INSERT INTO `jobs` (name, label) VALUES - ('banker','Banquier') + ('banker','Banker') ; INSERT INTO `job_grades` (job_name, grade, name, label, salary, skin_male, skin_female) VALUES - ('banker',0,'advisor','Conseiller',10,'{}','{}'), - ('banker',1,'banker','Banquier',20,'{}','{}'), - ('banker',2,'business_banker',"Banquier d\'affaire",30,'{}','{}'), - ('banker',3,'trader','Trader',40,'{}','{}'), - ('banker',4,'boss','Patron',0,'{}','{}') + ('banker',0,'advisor','Consultant',10,'{}','{}'), + ('banker',1,'banker','Banker',20,'{}','{}'), + ('banker',2,'business_banker',"Investment banker",30,'{}','{}'), + ('banker',3,'trader','Broker',40,'{}','{}'), + ('banker',4,'boss','Boss',0,'{}','{}') ; -- From bfbaea5d9034145c451c996aafccffe9acf02997 Mon Sep 17 00:00:00 2001 From: bitpredator <67551273+bitpredator@users.noreply.github.com> Date: Wed, 21 Dec 2022 18:24:25 +0100 Subject: [PATCH 71/83] fix:(Italian language correction) in the Italian translation some strings were not present --- it.lua | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 it.lua diff --git a/it.lua b/it.lua new file mode 100644 index 00000000..d75a6e53 --- /dev/null +++ b/it.lua @@ -0,0 +1,30 @@ +Locales['it'] = { + ['male'] = "Maschio", + ['female'] = "Femmina", + ['delete_label'] = "Cancella %s %s?", + ['select_char'] = "Seleziona Personaggio", + ["select_char_description"] = "Seleziona il personaggio con cui vuoi giocare.", + ['create_char'] = "Crea un nuovo personaggio", + ['char_play'] = "Gioca questo personaggio", + ['char_disabled'] = "Questo personaggio è disabilitato", + ['char_delete'] = "Cancella questo personaggio", + ['cancel'] = "Annulla", + ['confirm'] = "Conferma", + ['command_setslots'] = "Imposta il numero di slot di personaggi di un giocatore", + ['command_remslots'] = "Rimuovi il numero di slot di personaggi di un giocatore", + ['command_enablechar'] = "Abilita un personaggio di un giocatore", + ['command_disablechar'] = "Disabilita un personaggio di un giocatore", + ['command_charslot'] = "Numero dello slot del personaggio", + ['command_identifier'] = "Identifier del giocatore", + ['command_slots'] = "# di slot", + ['slotsadd'] = "Hai aggiunto %s slot a %s", + ['slotsedit'] = "Hai impostato %s slot a %s", + ['slotsrem'] = "Hai rimosso gli slot a %s", + ['charenabled'] = "Hai abilitato il %s° personaggio di %s", + ['chardisabled'] = "Hai disabilitato il %s° personaggio di %s", + ['charnotfound'] = "Il personaggio %s di %s non esiste", + ['return_description'] ="Ritorna alla selezione dei personaggi" , + ['char_play_description'] ="continua a giocare con questo personaggio", + ['char_delete_description'] = "elimina il personaggio selezionato", + ['return'] = "ritorna indietro", +} From d719a5366656ae0eea37da8fa1973478af0e0b56 Mon Sep 17 00:00:00 2001 From: TheFarFantomas <120812953+TheFarFantomas@users.noreply.github.com> Date: Wed, 21 Dec 2022 21:12:38 +0100 Subject: [PATCH 72/83] Update esx_multicharacter dependencies --- [esx]/esx_multicharacter/fxmanifest.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx]/esx_multicharacter/fxmanifest.lua b/[esx]/esx_multicharacter/fxmanifest.lua index 83f55093..05a7f1b0 100644 --- a/[esx]/esx_multicharacter/fxmanifest.lua +++ b/[esx]/esx_multicharacter/fxmanifest.lua @@ -5,7 +5,7 @@ description 'Official Multicharacter System For ESX Legacy' version '1.8.5' lua54 'yes' -dependencies {'es_extended', 'esx_menu_default', 'esx_identity', 'esx_skin'} +dependencies {'es_extended', 'esx_context', 'esx_identity', 'esx_skin'} shared_scripts {'@es_extended/imports.lua', '@es_extended/locale.lua', 'locales/*.lua', 'config.lua'} From 634a5c740f0ab70b031c4a5dae931b1b304fcc59 Mon Sep 17 00:00:00 2001 From: Gellipapa Date: Thu, 22 Dec 2022 00:52:49 +0100 Subject: [PATCH 73/83] Revert "refactor playerclass and default hud settings" --- .gitignore | 1 - [esx]/es_extended/config.lua | 18 +- [esx]/es_extended/server/classes/player.lua | 1085 +++++++++---------- [esx_addons]/esx_property/properties.json | 2 +- 4 files changed, 529 insertions(+), 577 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1946e67e..00000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -[esx_addons]/esx_property/properties.json \ No newline at end of file diff --git a/[esx]/es_extended/config.lua b/[esx]/es_extended/config.lua index caf9a794..50c57ea3 100644 --- a/[esx]/es_extended/config.lua +++ b/[esx]/es_extended/config.lua @@ -36,19 +36,19 @@ Config.DisableNPCDrops = false -- stops NPCs from dropping weapons on Config.DisableWeaponWheel = false -- Disables default weapon wheel Config.DisableAimAssist = false -- disables AIM assist (mainly on controllers) Config.RemoveHudCommonents = { - [1] = true, --WANTED_STARS, - [2] = true, --WEAPON_ICON - [3] = true, --CASH - [4] = true, --MP_CASH + [1] = false, --WANTED_STARS, + [2] = false, --WEAPON_ICON + [3] = false, --CASH + [4] = false, --MP_CASH [5] = false, --MP_MESSAGE - [6] = true, --VEHICLE_NAME - [7] = true,-- AREA_NAME - [8] = true,-- VEHICLE_CLASS - [9] = true, --STREET_NAME + [6] = false, --VEHICLE_NAME + [7] = false,-- AREA_NAME + [8] = false,-- VEHICLE_CLASS + [9] = false, --STREET_NAME [10] = false, --HELP_TEXT [11] = false, --FLOATING_HELP_TEXT_1 [12] = false, --FLOATING_HELP_TEXT_2 - [13] = true, --CASH_CHANGE + [13] = false, --CASH_CHANGE [14] = false, --RETICLE [15] = false, --SUBTITLE_TEXT [16] = false, --RADIO_STATIONS diff --git a/[esx]/es_extended/server/classes/player.lua b/[esx]/es_extended/server/classes/player.lua index 14b1eb9a..39e303cf 100644 --- a/[esx]/es_extended/server/classes/player.lua +++ b/[esx]/es_extended/server/classes/player.lua @@ -1,425 +1,400 @@ +local SetTimeout = SetTimeout +local GetPlayerPed = GetPlayerPed +local DoesEntityExist = DoesEntityExist +local GetEntityCoords = GetEntityCoords +local GetEntityHeading = GetEntityHeading + function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, weight, job, loadout, name, coords) local targetOverrides = Config.PlayerFunctionOverride and Core.PlayerFunctionOverrides[Config.PlayerFunctionOverride] or {} - local xPlayer = { - accounts = accounts, - coords = coords, - group = group, - identifier = identifier, - inventory = inventory, - job = job, - loadout = loadout, - name = name, - playerId = playerId, - source = playerId, - ped = GetPlayerPed(playerId), - variables = {}, - weight = weight, - maxWeight = Config.MaxWeight, - license = Config.Multichar and 'license'.. identifier:sub(identifier:find(':'), identifier:len()) or 'license:'..identifier, + + local self = {} - triggerEvent = function (self, eventName, ...) - TriggerClientEvent(eventName, self.playerId, ...) - end, + self.accounts = accounts + self.coords = coords + self.group = group + self.identifier = identifier + self.inventory = inventory + self.job = job + self.loadout = loadout + self.name = name + self.playerId = playerId + self.source = playerId + self.variables = {} + self.weight = weight + self.maxWeight = Config.MaxWeight + if Config.Multichar then self.license = 'license'.. identifier:sub(identifier:find(':'), identifier:len()) else self.license = 'license:'..identifier end - updatePed = function(self) - SetTimeout(1000,function() - if self.ped ~= GetPlayerPed(self.playerId) then - self.ped = GetPlayerPed(self.playerId) - self:triggerEvent('esx:updatePed', self.ped) - TriggerEvent('esx:updatePed', self.playerId, self.ped) - Player(self.playerId).state:set("ped", self.ped, true) + ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) + + Player(self.source).state:set("identifier", self.identifier, true) + Player(self.source).state:set("license", self.license, true) + Player(self.source).state:set("job", self.job, true) + Player(self.source).state:set("group", self.group, true) + Player(self.source).state:set("name", self.name, true) + + function self.triggerEvent(eventName, ...) + TriggerClientEvent(eventName, self.source, ...) + end + + function self.setCoords(coords) + local Ped = GetPlayerPed(self.source) + local vector = type(coords) == "vector4" and coords or type(coords) == "vector3" and vector4(coords, 0.0) or + vec(coords.x, coords.y, coords.z, coords.heading or 0.0) + SetEntityCoords(Ped, vector.xyz, false, false, false, false) + SetEntityHeading(Ped, vector.w) + end + + function self.updateCoords() + SetTimeout(1000,function() + local Ped = GetPlayerPed(self.source) + if DoesEntityExist(Ped) then + local coords = GetEntityCoords(Ped) + local distance = #(coords - vector3(self.coords.x, self.coords.y, self.coords.z)) + if distance > 1.5 then + local heading = GetEntityHeading(Ped) + self.coords = { + x = coords.x, + y = coords.y, + z = coords.z, + heading = heading or 0.0 + } end - self:updatePed() - end) - end, + end + self.updateCoords() + end) + end - getPed = function(self) - return self.ped - end, + function self.getCoords(vector) + if vector then + return vector3(self.coords.x, self.coords.y, self.coords.z) + else + return self.coords + end + end - setCoords = function(self, coord) - local vector = type(coord) == "vector4" and coord or type(coord) == "vector3" and vector4(coord, 0.0) or - vec(coord.x, coord.y, coord.z, coord.w or 0.0) - SetEntityCoords(self.ped, vector.x, vector.y, vector.z, false, false, false, false) - SetEntityHeading(self.ped, vector.w) - end, + function self.kick(reason) + DropPlayer(self.source, reason) + end - updateCoords = function(self) - SetTimeout(1000,function() - if DoesEntityExist(self.ped) then - local coord = GetEntityCoords(self.ped) - local distance = #(coord - vector3(self.coords.x, self.coords.y, self.coords.z)) - if distance > 1.5 then - local heading = GetEntityHeading(self.ped) - self.coords = { - x = coords.x, - y = coords.y, - z = coords.z, - heading = heading or 0.0 - } - end - end - self:updateCoords() - end) - end, + function self.setMoney(money) + money = ESX.Math.Round(money) + self.setAccountMoney('money', money) + end - getCoords = function(self, vector) - return vector and vector3(self.coords.x, self.coords.y, self.coords.z) or self.coords - end, + function self.getMoney() + return self.getAccount('money').money + end - kick = function(self, reason) - DropPlayer(self.playerId, reason) - end, + function self.addMoney(money, reason) + money = ESX.Math.Round(money) + self.addAccountMoney('money', money, reason) + end + + function self.removeMoney(money, reason) + money = ESX.Math.Round(money) + self.removeAccountMoney('money', money, reason) + end + + function self.getIdentifier() + return self.identifier + end + + function self.setGroup(newGroup) + ExecuteCommand(('remove_principal identifier.%s group.%s'):format(self.license, self.group)) + self.group = newGroup + Player(self.source).state:set("group", self.group, true) + ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) + end + + function self.getGroup() + return self.group + end + + function self.set(k, v) + self.variables[k] = v + Player(self.source).state:set(k, v, true) + end + + function self.get(k) + return self.variables[k] + end + + function self.getAccounts(minimal) + if minimal then + local minimalAccounts = {} - getAccount = function(self, account) for i=1, #self.accounts do - if self.accounts[i].name == account then - return self.accounts[i] - end - end - end, - - getAccounts = function(self, minimal) - if minimal then - local minimalAccounts = {} - - for i=1, #self.accounts do - minimalAccounts[self.accounts[i].name] = self.accounts[i].money - end - - return minimalAccounts - else - return self.accounts - end - end, - - setAccountMoney = function(self, accountName, amount, reason) - reason = reason or 'unknown' - if not tonumber(amount) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) - return - end - if amount >= 0 then - local account = self:getAccount(accountName) - - if account then - amount = account.round and ESX.Math.Round(amount) or amount - self.accounts[account.index].money = amount - self:triggerEvent('esx:setAccountMoney', account) - TriggerEvent('esx:setAccountMoney', self.playerId, accountName, amount, reason) - else - print(('[^1ERROR^7] Tried To Set Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) - end - else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) - end - end, - - addAccountMoney = function(self, accountName, amount, reason) - reason = reason or 'Unknown' - if not tonumber(amount) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) - return - end - if amount > 0 then - local account = self:getAccount(accountName) - if account then - amount = account.round and ESX.Math.Round(amount) or amount - self.accounts[account.index].money += amount - self:triggerEvent('esx:setAccountMoney', account) - TriggerEvent('esx:addAccountMoney', self.playerId, accountName, amount, reason) - else - print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) - end - else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) - end - end, - - removeAccountMoney = function(self, accountName, amount, reason) - reason = reason or 'Unknown' - if not tonumber(amount) then - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) - return - end - if amount > 0 then - local account = self:getAccount(accountName) - - if account then - amount = account.round and ESX.Math.Round(amount) or amount - self.accounts[account.index].money -= amount - self:triggerEvent('esx:setAccountMoney', account) - TriggerEvent('esx:removeAccountMoney', self.playerId, accountName, amount, reason) - else - print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) - end - else - print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, amount)) - end - end, - - setMoney = function (self, amount) - amount = ESX.Math.Round(amount) - self:setAccountMoney('money', amount) - end, - - getMoney = function(self) - return self:getAccount('money').money - end, - - addMoney = function(self, amount, reason) - amount = ESX.Math.Round(amount) - self:addAccountMoney('money', amount, reason) - end, - - removeMoney = function(self, amount, reason) - amount = ESX.Math.Round(amount) - self:removeAccountMoney('money', amount, reason) - end, - - getGroup = function(self) - return self.group - end, - - setGroup = function(self, newGroup) - ExecuteCommand(('remove_principal identifier.%s group.%s'):format(self.license, self.group)) - self.group = newGroup - Player(self.playerId).state:set("group", self.group, true) - ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group)) - end, - - getIdentifier = function(self) - return self.identifier - end, - - set = function(self, key, value) - self.variables[key] = value - Player(self.playerId).state:set(key, value, true) - end, - - get = function(self, key) - return self.variables[key] - end, - - getJob = function(self) - return self.job - end, - - setJob = function(self, jobName, grade) - grade = tostring(grade) - local lastJob = json.decode(json.encode(self.job)) - - if ESX.DoesJobExist(jobName, grade) then - local jobObject, gradeObject = ESX.Jobs[jobName], ESX.Jobs[jobName].grades[grade] - - self.job.id = jobObject.id - self.job.name = jobObject.name - self.job.label = jobObject.label - - self.job.grade = tonumber(grade) - self.job.grade_name = gradeObject.name - self.job.grade_label = gradeObject.label - self.job.grade_salary = gradeObject.salary - - if gradeObject.skin_male then - self.job.skin_male = json.decode(gradeObject.skin_male) - else - self.job.skin_male = {} - end - - if gradeObject.skin_female then - self.job.skin_female = json.decode(gradeObject.skin_female) - else - self.job.skin_female = {} - end - - TriggerEvent('esx:setJob', self.playerId, self.job, lastJob) - self:triggerEvent('esx:setJob', self.job) - Player(self.playerId).state:set("job", self.job, true) - else - print(('[es_extended] [^3WARNING^7] Ignoring invalid ^5:setJob()^7 usage for ID: ^5%s^7, Job: ^5%s^7'):format(self.playerId, job)) - end - end, - - getName = function(self) - return self.name - end, - - setName = function(self, newName) - self.name = newName - Player(self.playerId).state:set("name", newName, true) - end, - - getWeight = function(self) - return self.weight - end, - - getMaxWeight = function(self) - return self.maxWeight - end, - - setMaxWeight = function(self, newWeight) - self.maxWeight = newWeight - Player(self.playerId).state:set("maxWeight", newWeight, true) - self:triggerEvent('esx:setMaxWeight', newWeight) - end, - - getInventory = function(self, minimal) - if minimal then - local minimalInventory = {} - - for _, v in ipairs(self.inventory) do - if v.count > 0 then - minimalInventory[v.name] = v.count - end - end - - return minimalInventory + minimalAccounts[self.accounts[i].name] = self.accounts[i].money end - return self.inventory - end, + return minimalAccounts + else + return self.accounts + end + end - getInventoryItem = function(self, item, metadata) - for _,v in ipairs(self.inventory) do - if v.name == item then - return v - end + function self.getAccount(account) + for i=1, #self.accounts do + if self.accounts[i].name == account then + return self.accounts[i] end - end, + end + end - addInventoryItem = function(self, itemName, count, metadata, slot) - local item = self:getInventoryItem(itemName) + function self.getInventory(minimal) + if minimal then + local minimalInventory = {} - if item then - count = ESX.Math.Round(count) - item.count = item.count + count - self.weight = self.weight + (item.weight * count) - TriggerEvent('esx:onAddInventoryItem', self.playerId, item.name, item.count) - self:triggerEvent('esx:addInventoryItem', item.name, item.count) - Player(self.playerId).state:set("weight", self.weight, true) - end - end, - - removeInventoryItem = function(self, itemName, count, metadata, slot) - local item = self:getInventoryItem(itemName) - - if item then - count = ESX.Math.Round(count) - local newCount = item.count - count - - if newCount >= 0 then - item.count = newCount - self.weight = self.weight - (item.weight * count) - TriggerEvent('esx:onRemoveInventoryItem', self.playerId, item.name, item.count) - self:triggerEvent('esx:removeInventoryItem', item.name, item.count) - Player(self.playerId).state:set("weight", self.weight, true) - end - end - end, - - setInventoryItem = function(self, itemName, count, metadata) - local item = self:getInventoryItem(itemName) - - if item and count >= 0 then - count = ESX.Math.Round(count) - - if count > item.count then - self:addInventoryItem(item.name, count - item.count) - else - self:removeInventoryItem(item.name, item.count - count) - end - end - end, - - canCarryItem = function(self, itemName, count, metadata) - if ESX.Items[itemName] then - local currentWeight, itemWeight = self.weight, ESX.Items[itemName].weight - local newWeight = currentWeight + (itemWeight * count) - - return newWeight <= self.maxWeight - else - print(('[^3WARNING^7] Item ^5"%s"^7 was used but does not exist!'):format(itemName)) - end - end, - - canSwapItem = function(self, firstItem, firstItemCount, testItem, testItemCount) - local firstItemObject = self:getInventoryItem(firstItem) - local testItemObject = self:getInventoryItem(testItem) - - if firstItemObject.count >= firstItemCount then - local weightWithoutFirstItem = ESX.Math.Round(self.weight - (firstItemObject.weight * firstItemCount)) - local weightWithTestItem = ESX.Math.Round(weightWithoutFirstItem + (testItemObject.weight * testItemCount)) - - return weightWithTestItem <= self.maxWeight - end - - return false - end, - - hasItem = function(self, itemName, metadata) - for _, v in ipairs(self.inventory) do - if (v.name == itemName) and (v.count >= 1) then - return v, v.count + for k, v in ipairs(self.inventory) do + if v.count > 0 then + minimalInventory[v.name] = v.count end end - return false - end, + return minimalInventory + end - getLoadout = function(self, minimal) - if minimal then - local minimalLoadout = {} + return self.inventory + end - for _, v in ipairs(self.loadout) do - minimalLoadout[v.name] = {ammo = v.ammo} - if v.tintIndex > 0 then minimalLoadout[v.name].tintIndex = v.tintIndex end + function self.getJob() + return self.job + end - if #v.components > 0 then - local components = {} + function self.getLoadout(minimal) + if minimal then + local minimalLoadout = {} - for _, component in ipairs(v.components) do - if component ~= 'clip_default' then - components[#components + 1] = component - end - end - - if #components > 0 then - minimalLoadout[v.name].components = components - end - end - end - - return minimalLoadout - else - return self.loadout - end - end, - - hasWeapon = function(self, weaponName) - for _, v in ipairs(self.loadout) do - if v.name == weaponName then - return true - end - end - - return false - end, - - getWeapon = function(self, weaponName) for k,v in ipairs(self.loadout) do - if v.name == weaponName then - return k, v + minimalLoadout[v.name] = {ammo = v.ammo} + if v.tintIndex > 0 then minimalLoadout[v.name].tintIndex = v.tintIndex end + + if #v.components > 0 then + local components = {} + + for k2,component in ipairs(v.components) do + if component ~= 'clip_default' then + components[#components + 1] = component + end + end + + if #components > 0 then + minimalLoadout[v.name].components = components + end end end - end, - addWeapon = function(self, weaponName, ammo) - if self:hasWeapon(weaponName) then - print(('[^1ERROR^7] Player already has this weapon ^5%s'):format(weaponName)) - return + return minimalLoadout + else + return self.loadout + end + end + + function self.getName() + return self.name + end + + function self.setName(newName) + self.name = newName + Player(self.source).state:set("name", self.name, true) + end + + function self.setAccountMoney(accountName, money, reason) + reason = reason or 'unknown' + if not tonumber(money) then + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + return + end + if money >= 0 then + local account = self.getAccount(accountName) + + if account then + money = account.round and ESX.Math.Round(money) or money + self.accounts[account.index].money = money + + self.triggerEvent('esx:setAccountMoney', account) + TriggerEvent('esx:setAccountMoney', self.source, accountName, money, reason) + else + print(('[^1ERROR^7] Tried To Set Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + end + else + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + end + end + + function self.addAccountMoney(accountName, money, reason) + reason = reason or 'Unknown' + if not tonumber(money) then + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + return + end + if money > 0 then + local account = self.getAccount(accountName) + if account then + money = account.round and ESX.Math.Round(money) or money + self.accounts[account.index].money += money + + self.triggerEvent('esx:setAccountMoney', account) + TriggerEvent('esx:addAccountMoney', self.source, accountName, money, reason) + else + print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + end + else + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + end + end + + function self.removeAccountMoney(accountName, money, reason) + reason = reason or 'Unknown' + if not tonumber(money) then + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + return + end + if money > 0 then + local account = self.getAccount(accountName) + + if account then + money = account.round and ESX.Math.Round(money) or money + self.accounts[account.index].money -= money + + self.triggerEvent('esx:setAccountMoney', account) + TriggerEvent('esx:removeAccountMoney', self.source, accountName, money, reason) + else + print(('[^1ERROR^7] Tried To Set Add To Invalid Account ^5%s^0 For Player ^5%s^0!'):format(accountName, self.playerId)) + end + else + print(('[^1ERROR^7] Tried To Set Account ^5%s^0 For Player ^5%s^0 To An Invalid Number -> ^5%s^7'):format(accountName, self.playerId, money)) + end + end + + function self.getInventoryItem(name, metadata) + for k,v in ipairs(self.inventory) do + if v.name == name then + return v + end + end + end + + function self.addInventoryItem(name, count, metadata, slot) + local item = self.getInventoryItem(name) + + if item then + count = ESX.Math.Round(count) + item.count = item.count + count + self.weight = self.weight + (item.weight * count) + + TriggerEvent('esx:onAddInventoryItem', self.source, item.name, item.count) + self.triggerEvent('esx:addInventoryItem', item.name, item.count) + end + end + + function self.removeInventoryItem(name, count, metadata, slot) + local item = self.getInventoryItem(name) + + if item then + count = ESX.Math.Round(count) + local newCount = item.count - count + + if newCount >= 0 then + item.count = newCount + self.weight = self.weight - (item.weight * count) + + TriggerEvent('esx:onRemoveInventoryItem', self.source, item.name, item.count) + self.triggerEvent('esx:removeInventoryItem', item.name, item.count) + end + end + end + + function self.setInventoryItem(name, count, metadata) + local item = self.getInventoryItem(name) + + if item and count >= 0 then + count = ESX.Math.Round(count) + + if count > item.count then + self.addInventoryItem(item.name, count - item.count) + else + self.removeInventoryItem(item.name, item.count - count) + end + end + end + + function self.getWeight() + return self.weight + end + + function self.getMaxWeight() + return self.maxWeight + end + + function self.canCarryItem(name, count, metadata) + if ESX.Items[name] then + local currentWeight, itemWeight = self.weight, ESX.Items[name].weight + local newWeight = currentWeight + (itemWeight * count) + + return newWeight <= self.maxWeight + else + print(('[^3WARNING^7] Item ^5"%s"^7 was used but does not exist!'):format(name)) + end + end + + function self.canSwapItem(firstItem, firstItemCount, testItem, testItemCount) + local firstItemObject = self.getInventoryItem(firstItem) + local testItemObject = self.getInventoryItem(testItem) + + if firstItemObject.count >= firstItemCount then + local weightWithoutFirstItem = ESX.Math.Round(self.weight - (firstItemObject.weight * firstItemCount)) + local weightWithTestItem = ESX.Math.Round(weightWithoutFirstItem + (testItemObject.weight * testItemCount)) + + return weightWithTestItem <= self.maxWeight + end + + return false + end + + function self.setMaxWeight(newWeight) + self.maxWeight = newWeight + self.triggerEvent('esx:setMaxWeight', self.maxWeight) + end + + function self.setJob(job, grade) + grade = tostring(grade) + local lastJob = json.decode(json.encode(self.job)) + + if ESX.DoesJobExist(job, grade) then + local jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade] + + self.job.id = jobObject.id + self.job.name = jobObject.name + self.job.label = jobObject.label + + self.job.grade = tonumber(grade) + self.job.grade_name = gradeObject.name + self.job.grade_label = gradeObject.label + self.job.grade_salary = gradeObject.salary + + if gradeObject.skin_male then + self.job.skin_male = json.decode(gradeObject.skin_male) + else + self.job.skin_male = {} end + if gradeObject.skin_female then + self.job.skin_female = json.decode(gradeObject.skin_female) + else + self.job.skin_female = {} + end + + TriggerEvent('esx:setJob', self.source, self.job, lastJob) + self.triggerEvent('esx:setJob', self.job) + Player(self.source).state:set("job", self.job, true) + else + print(('[es_extended] [^3WARNING^7] Ignoring invalid ^5.setJob()^7 usage for ID: ^5%s^7, Job: ^5%s^7'):format(self.source, job)) + end + end + + function self.addWeapon(weaponName, ammo) + if not self.hasWeapon(weaponName) then local weaponLabel = ESX.GetWeaponLabel(weaponName) table.insert(self.loadout, { @@ -430,199 +405,177 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, tintIndex = 0 }) - GiveWeaponToPed(self.ped, joaat(weaponName), ammo, false, false) - self:triggerEvent('esx:addInventoryItem', weaponLabel, false, true) - end, + GiveWeaponToPed(GetPlayerPed(self.source), joaat(weaponName), ammo, false, false) + self.triggerEvent('esx:addInventoryItem', weaponLabel, false, true) + end + end - hasWeaponComponent = function(self, weaponName, weaponComponent) - local loadoutNum, weapon = self:getWeapon(weaponName) - if not weapon then - print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) - return false - end + function self.addWeaponComponent(weaponName, weaponComponent) + local loadoutNum, weapon = self.getWeapon(weaponName) - for _, v in ipairs(weapon.components) do - if v == weaponComponent then - return true + if weapon then + local component = ESX.GetWeaponComponent(weaponName, weaponComponent) + + if component then + if not self.hasWeaponComponent(weaponName, weaponComponent) then + self.loadout[loadoutNum].components[#self.loadout[loadoutNum].components + 1] = weaponComponent + local componentHash = ESX.GetWeaponComponent(weaponName, weaponComponent).hash + GiveWeaponComponentToPed(GetPlayerPed(self.source), joaat(weaponName), componentHash) + self.triggerEvent('esx:addInventoryItem', component.label, false, true) end end - return false - end, + end + end - addWeaponComponent = function(self, weaponName, weaponComponent) - local loadoutNum, weapon = self:getWeapon(weaponName) - if not weapon then - print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) - return - end - - local component = ESX.GetWeaponComponent(weaponName, weaponComponent) - if not component then - print(('[^1ERROR^7] Weapon component not exist ^5%s'):format(weaponComponent)) - return - end - - if not self:hasWeaponComponent(weaponName, weaponComponent) then - print(('[^1ERROR^7] Player not owning this component ^5%s'):format(weaponComponent)) - return - end - - self.loadout[loadoutNum].components[#self.loadout[loadoutNum].components + 1] = weaponComponent - local componentHash = ESX.GetWeaponComponent(weaponName, weaponComponent).hash - GiveWeaponComponentToPed(self.ped, joaat(weaponName), componentHash) - self:triggerEvent('esx:addInventoryItem', component.label, false, true) - end, - - addWeaponAmmo = function(self, weaponName, ammoCount) - local loadoutNum, weapon = self:getWeapon(weaponName) - - if not weapon then - print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) - return - end + function self.addWeaponAmmo(weaponName, ammoCount) + local loadoutNum, weapon = self.getWeapon(weaponName) + if weapon then weapon.ammo = weapon.ammo + ammoCount - SetPedAmmo(self.ped, joaat(weaponName), weapon.ammo) - end, + SetPedAmmo(GetPlayerPed(self.source), joaat(weaponName), weapon.ammo) + end + end - updateWeaponAmmo = function(self, weaponName, ammoCount) - local loadoutNum, weapon = self:getWeapon(weaponName) - - if not weapon then - print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) - return - end + function self.updateWeaponAmmo(weaponName, ammoCount) + local loadoutNum, weapon = self.getWeapon(weaponName) + if weapon then weapon.ammo = ammoCount - end, + end + end - setWeaponTint = function(self, weaponName, weaponTintIndex) - local loadoutNum, weapon = self:getWeapon(weaponName) - - if not weapon then - print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) - return - end + function self.setWeaponTint(weaponName, weaponTintIndex) + local loadoutNum, weapon = self.getWeapon(weaponName) + if weapon then local weaponNum, weaponObject = ESX.GetWeapon(weaponName) if weaponObject.tints and weaponObject.tints[weaponTintIndex] then self.loadout[loadoutNum].tintIndex = weaponTintIndex - self:triggerEvent('esx:setWeaponTint', weaponName, weaponTintIndex) - self:triggerEvent('esx:addInventoryItem', weaponObject.tints[weaponTintIndex], false, true) + self.triggerEvent('esx:setWeaponTint', weaponName, weaponTintIndex) + self.triggerEvent('esx:addInventoryItem', weaponObject.tints[weaponTintIndex], false, true) end - end, - - getWeaponTint = function(self, weaponName) - local loadoutNum, weapon = self:getWeapon(weaponName) - - if not weapon then - print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) - return 0 - end - - return weapon.tintIndex - end, - - removeWeapon = function(self, weaponName) - local weaponLabel - - for k,v in ipairs(self.loadout) do - if v.name == weaponName then - weaponLabel = v.label - - for _, key in ipairs(v.components) do - self:removeWeaponComponent(weaponName, key) - end - - table.remove(self.loadout, k) - break - end - end - - if weaponLabel then - self:triggerEvent('esx:removeWeapon', weaponName) - self:triggerEvent('esx:removeInventoryItem', weaponLabel, false, true) - end - end, - - removeWeaponComponent = function(self, weaponName, weaponComponent) - local loadoutNum, weapon = self:getWeapon(weaponName) - - if not weapon then - print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) - return - end - - local component = ESX.GetWeaponComponent(weaponName, weaponComponent) - if not component then - print(('[^1ERROR^7] Weapon component not exist ^5%s'):format(weaponComponent)) - return - end - - if not self:hasWeaponComponent(weaponName, weaponComponent) then - print(('[^1ERROR^7] Player not owning this component ^5%s'):format(weaponComponent)) - return - end - - for k,v in ipairs(self.loadout[loadoutNum].components) do - if v == weaponComponent then - table.remove(self.loadout[loadoutNum].components, k) - break - end - end - - self:triggerEvent('esx:removeWeaponComponent', weaponName, weaponComponent) - self:triggerEvent('esx:removeInventoryItem', component.label, false, true) - end, - - removeWeaponAmmo = function(self, weaponName, ammoCount) - local loadoutNum, weapon = self:getWeapon(weaponName) - - if not weapon then - print(('[^1ERROR^7] Weapon not exist ^5%s'):format(weaponName)) - return - end - weapon.ammo = weapon.ammo - ammoCount - self:triggerEvent('esx:setWeaponAmmo', weaponName, weapon.ammo) - end, - - showNotification = function(self, msg) - self:triggerEvent('esx:showNotification', msg) - end, - - showHelpNotification = function(self, msg, thisFrame, beep, duration) - self:triggerEvent('esx:showHelpNotification', msg, thisFrame, beep, duration) end - } - - ExecuteCommand(('add_principal identifier.%s group.%s'):format(xPlayer.license, xPlayer.group)) - - -- StateBag - local stateBag = Player(xPlayer.playerId).state - stateBag:set("identifier", xPlayer.identifier, true) - stateBag:set("license", xPlayer.license, true) - stateBag:set("job", xPlayer.job, true) - stateBag:set("group", xPlayer.group, true) - stateBag:set("name", xPlayer.name, true) - stateBag:set("ped", xPlayer.ped, true) - stateBag:set("weight", xPlayer.weight, true) - stateBag:set("maxWeight", xPlayer.maxWeight, true) - - local tempxPlayer = {} - for fnName, fn in pairs(xPlayer) do - if type(fn) == "function" then - tempxPlayer[fnName] = function(...) - return fn(xPlayer, ...) - end - else - tempxPlayer[fnName] = fn - end - end - - for fnName,fn in pairs(targetOverrides) do - tempxPlayer[fnName] = fn(tempxPlayer) end - return tempxPlayer + function self.getWeaponTint(weaponName) + local loadoutNum, weapon = self.getWeapon(weaponName) + + if weapon then + return weapon.tintIndex + end + + return 0 + end + + function self.removeWeapon(weaponName) + local weaponLabel + + for k,v in ipairs(self.loadout) do + if v.name == weaponName then + weaponLabel = v.label + + for k2,v2 in ipairs(v.components) do + self.removeWeaponComponent(weaponName, v2) + end + + table.remove(self.loadout, k) + break + end + end + + if weaponLabel then + self.triggerEvent('esx:removeWeapon', weaponName) + self.triggerEvent('esx:removeInventoryItem', weaponLabel, false, true) + end + end + + function self.removeWeaponComponent(weaponName, weaponComponent) + local loadoutNum, weapon = self.getWeapon(weaponName) + + if weapon then + local component = ESX.GetWeaponComponent(weaponName, weaponComponent) + + if component then + if self.hasWeaponComponent(weaponName, weaponComponent) then + for k,v in ipairs(self.loadout[loadoutNum].components) do + if v == weaponComponent then + table.remove(self.loadout[loadoutNum].components, k) + break + end + end + + self.triggerEvent('esx:removeWeaponComponent', weaponName, weaponComponent) + self.triggerEvent('esx:removeInventoryItem', component.label, false, true) + end + end + end + end + + function self.removeWeaponAmmo(weaponName, ammoCount) + local loadoutNum, weapon = self.getWeapon(weaponName) + + if weapon then + weapon.ammo = weapon.ammo - ammoCount + self.triggerEvent('esx:setWeaponAmmo', weaponName, weapon.ammo) + end + end + + function self.hasWeaponComponent(weaponName, weaponComponent) + local loadoutNum, weapon = self.getWeapon(weaponName) + + if weapon then + for k,v in ipairs(weapon.components) do + if v == weaponComponent then + return true + end + end + + return false + else + return false + end + end + + function self.hasWeapon(weaponName) + for k,v in ipairs(self.loadout) do + if v.name == weaponName then + return true + end + end + + return false + end + + function self.hasItem(item, metadata) + for k,v in ipairs(self.inventory) do + if (v.name == item) and (v.count >= 1) then + return v, v.count + end + end + + return false + end + + function self.getWeapon(weaponName) + for k,v in ipairs(self.loadout) do + if v.name == weaponName then + return k, v + end + end + end + + function self.showNotification(msg) + self.triggerEvent('esx:showNotification', msg) + end + + function self.showHelpNotification(msg, thisFrame, beep, duration) + self.triggerEvent('esx:showHelpNotification', msg, thisFrame, beep, duration) + end + + for fnName,fn in pairs(targetOverrides) do + self[fnName] = fn(self) + end + + return self end diff --git a/[esx_addons]/esx_property/properties.json b/[esx_addons]/esx_property/properties.json index 77915851..a99deb4e 100644 --- a/[esx_addons]/esx_property/properties.json +++ b/[esx_addons]/esx_property/properties.json @@ -1 +1 @@ -[{"cctv":{"rot":{"z":2.7542073726654,"y":2.7045992112562097e-8,"x":-9.43104267120361},"maxright":-88.02642059326172,"maxleft":90.71163940429688,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":28.57,"y":6206.16,"x":-467.88},"Interior":"low-end","OwnerName":"","Owned":false,"Locked":false,"setName":"","Name":"1076 Procopio Dr","Keys":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":162.9940643310547,"y":-0.0,"x":3.75689458847045},"maxright":70.65039825439453,"maxleft":-113.61099243164064,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":29.07,"y":6260.23,"x":-448.02},"Interior":"low-end","OwnerName":"","Owned":false,"Locked":false,"setName":"","Name":"1075 Procopio Dr","Keys":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-138.95835876464845,"y":-0.0,"x":-1.16786921024322},"maxright":135.13072204589845,"maxleft":-54.77568435668945,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":27.96,"y":6314.13,"x":-407.35},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1074 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-139.94163513183598,"y":-0.0,"x":-2.56643605232238},"maxright":132.70008850097657,"maxleft":-51.56189727783203,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":28.86,"y":6341.62,"x":-368.23},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1073 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-152.39810180664066,"y":-0.0,"x":-7.54235982894897},"maxright":123.2501983642578,"maxleft":-65.34387969970703,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.52,"y":6400.88,"x":-272.61},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1071 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":128.27305603027345,"y":4.379791960218428e-7,"x":-12.92249584197998},"maxright":38.33782577514648,"maxleft":-148.38644409179688,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.48,"y":6414.46,"x":-246.14},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1071 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":137.8870849609375,"y":2.1444458297992242e-7,"x":-5.53862285614013},"maxright":48.30059432983398,"maxleft":-135.48313903808598,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":30.22,"y":6445.48,"x":-229.63},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1070 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":27500},{"cctv":{"rot":{"z":-134.93411254882813,"y":1.0691521623584777e-7,"x":3.44796895980834},"maxright":138.85032653808598,"maxleft":-46.79578399658203,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":28.89,"y":6551.76,"x":-130.8},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1067 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":27500},{"cctv":{"rot":{"z":-144.0503692626953,"y":-1.3340336835199196e-8,"x":-0.24611411988735},"maxright":129.07382202148438,"maxleft":-56.39479827880859,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.11,"y":6637.3,"x":-41.72},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1065 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-155.01153564453126,"y":-1.068413766347477e-7,"x":-2.71219563484191},"maxright":116.67019653320313,"maxleft":-68.07413482666016,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.72,"y":6654.13,"x":-9.62},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1064 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-133.8831787109375,"y":-0.0,"x":-2.77191710472106},"maxright":135.7574005126953,"maxleft":-45.94052505493164,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.86,"y":6207.33,"x":-356.82},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1034 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-40.4444465637207,"y":4.32035335506953e-7,"x":-8.85426330566406},"maxright":-131.2773895263672,"maxleft":42.09032440185547,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.87,"y":6252.75,"x":-379.92},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1034 Procopio Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":44.16030502319336,"y":-9.440947223993136e-7,"x":-25.26673126220703},"maxright":-42.54082870483398,"maxleft":133.55870056152345,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":31.91,"y":6326.99,"x":-302.19},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1047 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-137.5096435546875,"y":-0.0,"x":-1.57497417926788},"maxright":134.7738800048828,"maxleft":-43.60107040405273,"enabled":true},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":30.9,"y":6225.21,"x":-347.3},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"1043 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":-45.87245941162109,"y":-0.0,"x":-11.80154037475586},"maxright":-133.83499145507813,"maxleft":43.89247512817383,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":32.26,"y":6557.45,"x":-15.3},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1059 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":25000},{"cctv":{"rot":{"z":129.4863433837891,"y":2.144746105159357e-7,"x":-5.62087059020996},"maxright":44.53319549560547,"maxleft":-139.30752563476566,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":32.1,"y":6568.19,"x":4.43},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1061 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":27500},{"cctv":{"rot":{"z":-94.7632293701172,"y":-0.0,"x":-5.83577966690063},"maxright":-159.96804809570313,"maxleft":-43.43285751342773,"enabled":true},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":31.84,"y":6596.46,"x":31.0},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"1061 Paleto Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":27500},{"cctv":{"rot":{"z":-63.00457000732422,"y":-0.0,"x":-6.35934734344482},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.9,"y":4642.33,"x":1725.06},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2016 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":12500},{"cctv":{"rot":{"z":91.53390502929688,"y":2.7858778395284394e-8,"x":-16.72389602661132},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.39,"y":4658.22,"x":1674.01},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2015 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":12500},{"cctv":{"rot":{"z":-93.13695526123049,"y":-0.0,"x":-29.83987236022949},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.68,"y":4677.34,"x":1718.91},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2014 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":7500},{"cctv":{"rot":{"z":91.7155303955078,"y":-0.0,"x":-6.32857131958007},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.09,"y":4689.52,"x":1682.85},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2013 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":7500},{"cctv":{"rot":{"z":110.03758239746094,"y":-0.0,"x":-18.96443367004394},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":41.03,"y":4739.5,"x":1664.0},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"2011 Grapeseed Main St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":10000},{"cctv":{"rot":{"z":-77.30774688720703,"y":-0.0,"x":-14.36374378204345},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":32.23,"y":3920.59,"x":1880.27},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"3012 Niland Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":10000},{"cctv":{"rot":{"z":103.60260009765624,"y":-2.1725810483985698e-7,"x":-10.75266551971435},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":32.48,"y":3914.59,"x":1846.06},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"3013 Niland Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":9000},{"cctv":{"rot":{"z":-76.59026336669922,"y":-0.0,"x":-20.23343658447265},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":36.08,"y":3913.8,"x":1803.57},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"3013 Marina Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":11500},{"cctv":{"rot":{"z":95.02767944335938,"y":-0.0,"x":-5.87784767150878},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":33.45,"y":3657.13,"x":1435.31},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"3025 Lesbos Ln","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":11500},{"cctv":{"rot":{"z":-166.2356719970703,"y":-0.0,"x":-20.86568069458007},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":43.5,"y":2607.8,"x":471.15},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"4018 Route 68","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":12500},{"cctv":{"rot":{"z":-93.07178497314452,"y":-0.0,"x":-11.2086534500122},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Entrance":{"z":42.28,"y":3087.1,"x":181.03},"Interior":"low-end","Keys":[],"Locked":false,"setName":"","Name":"4013 Joshua Rd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":7500},{"cctv":{"rot":{"z":-127.72049713134766,"y":-0.0,"x":-9.48588275909423},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.50999999999999,"y":-593.38,"x":1386.22},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7340 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-69.5700912475586,"y":-0.0,"x":-9.84068393707275},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.52,"y":-569.49,"x":1388.94},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7341 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-114.24230194091796,"y":-0.0,"x":-12.52571487426757},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.71,"y":-555.82,"x":1373.19},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7341 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":4500},{"cctv":{"rot":{"z":-177.74884033203126,"y":-0.0,"x":-10.93433380126953},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.72999999999999,"y":-606.62,"x":1367.33},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7340 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":62.37366104125976,"y":-0.0,"x":-17.39539337158203},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":73.72,"y":-597.26,"x":1341.64},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7339 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-27.96370315551757,"y":4.342483350683324e-7,"x":-10.56496334075927},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":72.91,"y":-546.97,"x":1348.31},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7342 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":152.2796173095703,"y":4.441767487151084e-7,"x":-16.03893852233886},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":72.27,"y":-583.06,"x":1323.3},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7339 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-111.59012603759766,"y":-0.00000144736395,"x":-53.85140228271484},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":71.46,"y":-535.91,"x":1328.57},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7342 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":164.71957397460938,"y":4.6078031346041828e-7,"x":-22.11302947998047},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":70.75,"y":-574.08,"x":1301.02},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7339 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":-19.26140213012695,"y":4.363083689895575e-7,"x":-11.92860603332519},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":70.47999999999999,"y":-527.3,"x":1303.1},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7342 Nikola Pl","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":45000},{"cctv":{"rot":{"z":125.62109375,"y":-0.0,"x":-58.0705451965332},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":56.84,"y":-729.5,"x":996.89},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7322 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":131.13587951660157,"y":-0.0,"x":-15.06083393096923},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.24,"y":-716.31,"x":979.11},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7320 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":170.76788330078126,"y":3.3350637806961464e-9,"x":-0.14884614944458},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.5,"y":-701.3,"x":970.88},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7320 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":115.8887939453125,"y":4.346124455878453e-7,"x":-10.81925582885742},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.47,"y":-669.85,"x":960.15},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7319 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":38.34314727783203,"y":0.00000168464464,"x":-59.54927444458008},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.45,"y":-653.51,"x":943.45},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7319 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-144.15000915527345,"y":-0.0,"x":-36.16230392456055},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":58.26,"y":-627.65,"x":980.25},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7318 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":137.4777984619141,"y":-0.0,"x":-15.65773868560791},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.26,"y":-639.71,"x":928.82},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7317 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":46.20460510253906,"y":-0.00000160100864,"x":-57.77318572998047},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.47,"y":-615.51,"x":902.95},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7317 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":138.07872009277345,"y":-8.718344588487525e-7,"x":-11.68268966674804},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.47,"y":-608.21,"x":886.77},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7316 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-176.59844970703126,"y":-0.0,"x":-3.38041257858276},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.18,"y":-583.65,"x":861.7},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7316 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":12.50613498687744,"y":-2.1754524937023245e-7,"x":-11.14390087127685},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.01,"y":-562.66,"x":844.12},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7312 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":85.02394104003906,"y":-5.362977262279856e-8,"x":-5.74017667770385},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":56.95,"y":-532.68,"x":850.25},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7314 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":46.49221038818359,"y":0.00000154111978,"x":-56.35844421386719},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":56.74,"y":-508.98,"x":861.51},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7313 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":44.91729354858398,"y":-0.0,"x":-64.80823516845703},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.11000000000001,"y":-497.87,"x":878.44},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7313 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":19.29909515380859,"y":-0.0,"x":-14.44456386566162},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":58.46,"y":-489.76,"x":906.46},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7311 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-8.25692367553711,"y":-0.0,"x":-19.33738899230957},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":60.1,"y":-477.8,"x":921.78},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7311 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-55.23443603515625,"y":-8.953837777880835e-7,"x":-17.53591918945312},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":60.57,"y":-463.17,"x":944.54},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7309 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":33.32376480102539,"y":8.936335120779404e-7,"x":-17.17726707458496},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":61.81,"y":-451.65,"x":967.16},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7309 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":34.80197525024414,"y":8.771137913754501e-7,"x":-13.24740600585937},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":63.06000000000001,"y":-433.03,"x":987.57},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7307 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":123.14452362060549,"y":-4.402644719903037e-7,"x":-14.16050624847412},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":64.36999999999999,"y":-423.38,"x":1010.38},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7307 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":41.270263671875,"y":-4.386202476780454e-7,"x":-13.28245830535888},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":65.36,"y":-408.36,"x":1028.78},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7305 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":54.3464241027832,"y":-8.817532943794504e-7,"x":-14.47243404388427},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":67.25,"y":-378.13,"x":1060.52},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7305 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-144.52737426757813,"y":-9.047982416632294e-7,"x":-19.33366966247558},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":63.52,"y":-469.3,"x":1014.67},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7306 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-107.44925689697266,"y":-0.0,"x":-8.07564449310302},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":61.16,"y":-502.36,"x":970.55},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7308 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":119.70294189453124,"y":-0.0,"x":-61.49639892578125},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":59.64,"y":-518.94,"x":945.9},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7310 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-151.43536376953126,"y":-0.0,"x":-17.66978073120117},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":58.81,"y":-526.05,"x":924.39},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7312 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-69.45809936523438,"y":-9.24586970540986e-7,"x":-22.57007217407226},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.53,"y":-540.58,"x":893.24},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7312 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":28.74713134765625,"y":4.412431167111208e-7,"x":-14.65564727783203},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":57.39,"y":-569.56,"x":919.7},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7312 Nikola Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":32.70853805541992,"y":-4.381802227726439e-7,"x":-13.03651428222656},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":58.75,"y":-541.93,"x":965.25},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7310 Nikola Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":30.89822769165039,"y":9.366781910102872e-7,"x":-24.28778457641601},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":59.71,"y":-525.76,"x":987.84},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7310 Nikola Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-65.29899597167969,"y":-0.0,"x":-16.08703422546386},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":60.01,"y":-510.98,"x":1006.48},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7308 Nikola Ave","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":144.13137817382813,"y":9.091479000744585e-7,"x":-20.10037040710449},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":63.1,"y":-498.06,"x":1046.29},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7306 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":76.4620132446289,"y":-0.0,"x":-11.98972129821777},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":63.32,"y":-470.58,"x":1051.04},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7306 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":162.82366943359376,"y":-0.0,"x":-8.78071689605712},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":65.28,"y":-448.93,"x":1056.24},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7306 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-102.9858856201172,"y":-4.4310172597761268e-7,"x":-15.54805183410644},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":64.67999999999999,"y":-484.37,"x":1090.46},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7344 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-15.62946987152099,"y":2.17306606487e-7,"x":-10.81984233856201},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":66.33999999999999,"y":-464.52,"x":1098.58},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7346 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":179.49822998046876,"y":-0.0,"x":-11.32894706726074},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":66.81,"y":-438.69,"x":1099.44},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7346 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-93.88529205322266,"y":-5.391471091797939e-8,"x":-8.21971225738525},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":66.58,"y":-411.33,"x":1101.06},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7348 Bridge St","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":-112.49811553955078,"y":-0.0,"x":-24.5419979095459},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":67.97,"y":-391.27,"x":1114.44},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7348 West Mirror Drive","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":112.37248229980468,"y":-2.144359569911103e-7,"x":-5.51487922668457},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":69.03999999999999,"y":-429.86,"x":1262.35},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7345 East Mirror Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":94.98734283447266,"y":-0.0,"x":-14.86165904998779},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":69.53999999999999,"y":-458.06,"x":1265.74},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7945 East Mirror Dr","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":125.15465545654296,"y":-0.0,"x":-10.50986766815185},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":69.21,"y":-480.18,"x":1259.51},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7343 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":63.34117126464844,"y":-0.0,"x":-16.31183433532715},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.92999999999999,"y":-494.1,"x":1251.53},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7343 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":77.79755401611328,"y":-0.0,"x":-17.28229522705078},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.36999999999999,"y":-515.5,"x":1250.9},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7343 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":130.3302459716797,"y":-0.0,"x":-22.43321228027343},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.67999999999999,"y":-566.43,"x":1241.53},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7338 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":91.53223419189452,"y":-1.3435412782314417e-8,"x":-6.82489442825317},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.8,"y":-601.65,"x":1240.54},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7338 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":27.77294158935547,"y":-2.145688853261163e-7,"x":-5.87094974517822},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.58999999999999,"y":-620.99,"x":1250.79},"Interior":"mid-end","OwnerName":"","Owned":false,"Locked":false,"setName":"","Name":"7336 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-152.5341949462891,"y":-0.0,"x":-14.65502071380615},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":67.14,"y":-648.63,"x":1265.69},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7333 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-171.3050994873047,"y":-0.0,"x":-12.5356969833374},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":65.05,"y":-683.53,"x":1270.98},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7333 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":58.4541015625,"y":0.00000175048376,"x":-12.71638584136962},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":63.93,"y":-702.82,"x":1264.75},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7328 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-88.46087646484375,"y":-0.0,"x":-11.09668827056884},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":59.98,"y":-725.27,"x":1229.58},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7328 East Mirror Dr","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-81.23240661621094,"y":-0.0,"x":-17.37718200683593},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":59.82,"y":-696.93,"x":1223.0},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7328 Mirror Park Blvd","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-164.38833618164066,"y":-0.0,"x":-11.55613040924072},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":62.71,"y":-669.31,"x":1221.46},"Interior":"mid-end","Owned":false,"Locked":false,"setName":"","Name":"7333 Mirror Park Blvd","plysinside":[],"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-87.679443359375,"y":1.3399391818325056e-8,"x":-5.38702487945556},"maxright":-20,"maxleft":80,"enabled":false},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Entrance":{"z":65.46,"y":-620.26,"x":1207.46},"Interior":"mid-end","Keys":[],"Locked":false,"setName":"","Name":"7336 Mirror Park Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"plysinside":[],"Price":40000},{"cctv":{"rot":{"z":3.90023970603942,"y":-0.0,"x":-16.58763313293457},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":67.08,"y":-598.41,"x":1203.75},"Interior":"mid-end","plysinside":[],"Locked":false,"setName":"","Name":"7338 Mirror Park Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000},{"cctv":{"rot":{"z":-37.31895446777344,"y":9.099596240957908e-7,"x":-20.23956108093261},"maxright":-20,"maxleft":80,"enabled":false},"Keys":[],"Entrance":{"z":68.16,"y":-575.59,"x":1201.01},"Interior":"mid-end","plysinside":[],"Locked":false,"setName":"","Name":"7338 Mirror Park Blvd","Owned":false,"furniture":[],"Owner":"","garage":{"enabled":false,"StoredVehicles":[]},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Price":40000}] \ No newline at end of file +[{"Locked":false,"Price":25000,"Entrance":{"z":28.57,"y":6206.16,"x":-467.88},"furniture":[],"plysinside":[],"Keys":[],"Owned":false,"Owner":"","OwnerName":"","setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":90.71163940429688,"maxright":-88.02642059326172,"enabled":true,"rot":{"z":2.7542073726654,"y":2.7045992112562097e-8,"x":-9.43104267120361}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1076 Procopio Dr","Interior":"low-end"},{"Locked":false,"Price":25000,"Entrance":{"z":29.07,"y":6260.23,"x":-448.02},"furniture":[],"plysinside":[],"Keys":[],"Owned":false,"Owner":"","OwnerName":"","setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-113.61099243164064,"maxright":70.65039825439453,"enabled":true,"rot":{"z":162.9940643310547,"y":-0.0,"x":3.75689458847045}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1075 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":27.96,"y":6314.13,"x":-407.35},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-54.77568435668945,"maxright":135.13072204589845,"enabled":true,"rot":{"z":-138.95835876464845,"y":-0.0,"x":-1.16786921024322}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1074 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":28.86,"y":6341.62,"x":-368.23},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-51.56189727783203,"maxright":132.70008850097657,"enabled":true,"rot":{"z":-139.94163513183598,"y":-0.0,"x":-2.56643605232238}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1073 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.52,"y":6400.88,"x":-272.61},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-65.34387969970703,"maxright":123.2501983642578,"enabled":true,"rot":{"z":-152.39810180664066,"y":-0.0,"x":-7.54235982894897}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1071 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.48,"y":6414.46,"x":-246.14},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-148.38644409179688,"maxright":38.33782577514648,"enabled":true,"rot":{"z":128.27305603027345,"y":4.379791960218428e-7,"x":-12.92249584197998}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1071 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.22,"y":6445.48,"x":-229.63},"furniture":[],"plysinside":[],"Price":27500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-135.48313903808598,"maxright":48.30059432983398,"enabled":true,"rot":{"z":137.8870849609375,"y":2.1444458297992242e-7,"x":-5.53862285614013}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1070 Procopio Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":28.89,"y":6551.76,"x":-130.8},"furniture":[],"plysinside":[],"Price":27500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-46.79578399658203,"maxright":138.85032653808598,"enabled":true,"rot":{"z":-134.93411254882813,"y":1.0691521623584777e-7,"x":3.44796895980834}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1067 Procopio Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.11,"y":6637.3,"x":-41.72},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-56.39479827880859,"maxright":129.07382202148438,"enabled":true,"rot":{"z":-144.0503692626953,"y":-1.3340336835199196e-8,"x":-0.24611411988735}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1065 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.72,"y":6654.13,"x":-9.62},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-68.07413482666016,"maxright":116.67019653320313,"enabled":true,"rot":{"z":-155.01153564453126,"y":-1.068413766347477e-7,"x":-2.71219563484191}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1064 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.86,"y":6207.33,"x":-356.82},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-45.94052505493164,"maxright":135.7574005126953,"enabled":true,"rot":{"z":-133.8831787109375,"y":-0.0,"x":-2.77191710472106}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1034 Paleto Blvd","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.87,"y":6252.75,"x":-379.92},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":42.09032440185547,"maxright":-131.2773895263672,"enabled":true,"rot":{"z":-40.4444465637207,"y":4.32035335506953e-7,"x":-8.85426330566406}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1034 Procopio Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":31.91,"y":6326.99,"x":-302.19},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":133.55870056152345,"maxright":-42.54082870483398,"enabled":true,"rot":{"z":44.16030502319336,"y":-9.440947223993136e-7,"x":-25.26673126220703}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1047 Paleto Blvd","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":30.9,"y":6225.21,"x":-347.3},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-43.60107040405273,"maxright":134.7738800048828,"enabled":true,"rot":{"z":-137.5096435546875,"y":-0.0,"x":-1.57497417926788}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"1043 Paleto Blvd","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":32.26,"y":6557.45,"x":-15.3},"furniture":[],"plysinside":[],"Price":25000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":43.89247512817383,"maxright":-133.83499145507813,"enabled":true,"rot":{"z":-45.87245941162109,"y":-0.0,"x":-11.80154037475586}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1059 Paleto Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":32.1,"y":6568.19,"x":4.43},"furniture":[],"plysinside":[],"Price":27500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-139.30752563476566,"maxright":44.53319549560547,"enabled":true,"rot":{"z":129.4863433837891,"y":2.144746105159357e-7,"x":-5.62087059020996}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1061 Paleto Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":31.84,"y":6596.46,"x":31.0},"furniture":[],"plysinside":[],"Price":27500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":-43.43285751342773,"maxright":-159.96804809570313,"enabled":true,"rot":{"z":-94.7632293701172,"y":-0.0,"x":-5.83577966690063}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"1061 Paleto Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.9,"y":4642.33,"x":1725.06},"furniture":[],"plysinside":[],"Price":12500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-63.00457000732422,"y":-0.0,"x":-6.35934734344482}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2016 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.39,"y":4658.22,"x":1674.01},"furniture":[],"plysinside":[],"Price":12500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":91.53390502929688,"y":2.7858778395284394e-8,"x":-16.72389602661132}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2015 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.68,"y":4677.34,"x":1718.91},"furniture":[],"plysinside":[],"Price":7500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-93.13695526123049,"y":-0.0,"x":-29.83987236022949}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2014 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.09,"y":4689.52,"x":1682.85},"furniture":[],"plysinside":[],"Price":7500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":91.7155303955078,"y":-0.0,"x":-6.32857131958007}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2013 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":41.03,"y":4739.5,"x":1664.0},"furniture":[],"plysinside":[],"Price":10000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":110.03758239746094,"y":-0.0,"x":-18.96443367004394}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"2011 Grapeseed Main St","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":32.23,"y":3920.59,"x":1880.27},"furniture":[],"plysinside":[],"Price":10000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-77.30774688720703,"y":-0.0,"x":-14.36374378204345}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"3012 Niland Ave","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":32.48,"y":3914.59,"x":1846.06},"furniture":[],"plysinside":[],"Price":9000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":103.60260009765624,"y":-2.1725810483985698e-7,"x":-10.75266551971435}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"3013 Niland Ave","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":36.08,"y":3913.8,"x":1803.57},"furniture":[],"plysinside":[],"Price":11500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-76.59026336669922,"y":-0.0,"x":-20.23343658447265}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"3013 Marina Dr","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":33.45,"y":3657.13,"x":1435.31},"furniture":[],"plysinside":[],"Price":11500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":95.02767944335938,"y":-0.0,"x":-5.87784767150878}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"3025 Lesbos Ln","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":43.5,"y":2607.8,"x":471.15},"furniture":[],"plysinside":[],"Price":12500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-166.2356719970703,"y":-0.0,"x":-20.86568069458007}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"4018 Route 68","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":42.28,"y":3087.1,"x":181.03},"furniture":[],"plysinside":[],"Price":7500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-93.07178497314452,"y":-0.0,"x":-11.2086534500122}},"positions":{"Wardrobe":{"z":-99.00859832763672,"y":-1003.45947265625,"x":259.9942932128906}},"Name":"4013 Joshua Rd","Interior":"low-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.50999999999999,"y":-593.38,"x":1386.22},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-127.72049713134766,"y":-0.0,"x":-9.48588275909423}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7340 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.52,"y":-569.49,"x":1388.94},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-69.5700912475586,"y":-0.0,"x":-9.84068393707275}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7341 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.71,"y":-555.82,"x":1373.19},"furniture":[],"plysinside":[],"Price":4500,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-114.24230194091796,"y":-0.0,"x":-12.52571487426757}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7341 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.72999999999999,"y":-606.62,"x":1367.33},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-177.74884033203126,"y":-0.0,"x":-10.93433380126953}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7340 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":73.72,"y":-597.26,"x":1341.64},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":62.37366104125976,"y":-0.0,"x":-17.39539337158203}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7339 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":72.91,"y":-546.97,"x":1348.31},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-27.96370315551757,"y":4.342483350683324e-7,"x":-10.56496334075927}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7342 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":72.27,"y":-583.06,"x":1323.3},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":152.2796173095703,"y":4.441767487151084e-7,"x":-16.03893852233886}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7339 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":71.46,"y":-535.91,"x":1328.57},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-111.59012603759766,"y":-0.00000144736395,"x":-53.85140228271484}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7342 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":70.75,"y":-574.08,"x":1301.02},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":164.71957397460938,"y":4.6078031346041828e-7,"x":-22.11302947998047}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7339 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":70.47999999999999,"y":-527.3,"x":1303.1},"furniture":[],"plysinside":[],"Price":45000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-19.26140213012695,"y":4.363083689895575e-7,"x":-11.92860603332519}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7342 Nikola Pl","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":56.84,"y":-729.5,"x":996.89},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":125.62109375,"y":-0.0,"x":-58.0705451965332}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7322 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.24,"y":-716.31,"x":979.11},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":131.13587951660157,"y":-0.0,"x":-15.06083393096923}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7320 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.5,"y":-701.3,"x":970.88},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":170.76788330078126,"y":3.3350637806961464e-9,"x":-0.14884614944458}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7320 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.47,"y":-669.85,"x":960.15},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":115.8887939453125,"y":4.346124455878453e-7,"x":-10.81925582885742}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7319 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.45,"y":-653.51,"x":943.45},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":38.34314727783203,"y":0.00000168464464,"x":-59.54927444458008}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7319 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":58.26,"y":-627.65,"x":980.25},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-144.15000915527345,"y":-0.0,"x":-36.16230392456055}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7318 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.26,"y":-639.71,"x":928.82},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":137.4777984619141,"y":-0.0,"x":-15.65773868560791}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7317 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.47,"y":-615.51,"x":902.95},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":46.20460510253906,"y":-0.00000160100864,"x":-57.77318572998047}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7317 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.47,"y":-608.21,"x":886.77},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":138.07872009277345,"y":-8.718344588487525e-7,"x":-11.68268966674804}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7316 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.18,"y":-583.65,"x":861.7},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-176.59844970703126,"y":-0.0,"x":-3.38041257858276}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7316 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.01,"y":-562.66,"x":844.12},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":12.50613498687744,"y":-2.1754524937023245e-7,"x":-11.14390087127685}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7312 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":56.95,"y":-532.68,"x":850.25},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":85.02394104003906,"y":-5.362977262279856e-8,"x":-5.74017667770385}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7314 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":56.74,"y":-508.98,"x":861.51},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":46.49221038818359,"y":0.00000154111978,"x":-56.35844421386719}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7313 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.11000000000001,"y":-497.87,"x":878.44},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":44.91729354858398,"y":-0.0,"x":-64.80823516845703}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7313 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":58.46,"y":-489.76,"x":906.46},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":19.29909515380859,"y":-0.0,"x":-14.44456386566162}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7311 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":60.1,"y":-477.8,"x":921.78},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-8.25692367553711,"y":-0.0,"x":-19.33738899230957}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7311 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":60.57,"y":-463.17,"x":944.54},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-55.23443603515625,"y":-8.953837777880835e-7,"x":-17.53591918945312}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7309 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":61.81,"y":-451.65,"x":967.16},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":33.32376480102539,"y":8.936335120779404e-7,"x":-17.17726707458496}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7309 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.06000000000001,"y":-433.03,"x":987.57},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":34.80197525024414,"y":8.771137913754501e-7,"x":-13.24740600585937}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7307 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":64.36999999999999,"y":-423.38,"x":1010.38},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":123.14452362060549,"y":-4.402644719903037e-7,"x":-14.16050624847412}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7307 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":65.36,"y":-408.36,"x":1028.78},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":41.270263671875,"y":-4.386202476780454e-7,"x":-13.28245830535888}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7305 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":67.25,"y":-378.13,"x":1060.52},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":54.3464241027832,"y":-8.817532943794504e-7,"x":-14.47243404388427}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7305 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.52,"y":-469.3,"x":1014.67},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-144.52737426757813,"y":-9.047982416632294e-7,"x":-19.33366966247558}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7306 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":61.16,"y":-502.36,"x":970.55},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-107.44925689697266,"y":-0.0,"x":-8.07564449310302}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7308 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":59.64,"y":-518.94,"x":945.9},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":119.70294189453124,"y":-0.0,"x":-61.49639892578125}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7310 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":58.81,"y":-526.05,"x":924.39},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-151.43536376953126,"y":-0.0,"x":-17.66978073120117}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7312 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.53,"y":-540.58,"x":893.24},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-69.45809936523438,"y":-9.24586970540986e-7,"x":-22.57007217407226}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7312 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":57.39,"y":-569.56,"x":919.7},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":28.74713134765625,"y":4.412431167111208e-7,"x":-14.65564727783203}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7312 Nikola Ave","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":58.75,"y":-541.93,"x":965.25},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":32.70853805541992,"y":-4.381802227726439e-7,"x":-13.03651428222656}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7310 Nikola Ave","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":59.71,"y":-525.76,"x":987.84},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":30.89822769165039,"y":9.366781910102872e-7,"x":-24.28778457641601}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7310 Nikola Ave","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":60.01,"y":-510.98,"x":1006.48},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-65.29899597167969,"y":-0.0,"x":-16.08703422546386}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7308 Nikola Ave","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.1,"y":-498.06,"x":1046.29},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":144.13137817382813,"y":9.091479000744585e-7,"x":-20.10037040710449}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7306 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.32,"y":-470.58,"x":1051.04},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":76.4620132446289,"y":-0.0,"x":-11.98972129821777}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7306 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":65.28,"y":-448.93,"x":1056.24},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":162.82366943359376,"y":-0.0,"x":-8.78071689605712}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7306 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":64.67999999999999,"y":-484.37,"x":1090.46},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-102.9858856201172,"y":-4.4310172597761268e-7,"x":-15.54805183410644}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7344 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":66.33999999999999,"y":-464.52,"x":1098.58},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-15.62946987152099,"y":2.17306606487e-7,"x":-10.81984233856201}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7346 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":66.81,"y":-438.69,"x":1099.44},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":179.49822998046876,"y":-0.0,"x":-11.32894706726074}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7346 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":66.58,"y":-411.33,"x":1101.06},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-93.88529205322266,"y":-5.391471091797939e-8,"x":-8.21971225738525}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7348 Bridge St","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":67.97,"y":-391.27,"x":1114.44},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-112.49811553955078,"y":-0.0,"x":-24.5419979095459}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7348 West Mirror Drive","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":69.03999999999999,"y":-429.86,"x":1262.35},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":112.37248229980468,"y":-2.144359569911103e-7,"x":-5.51487922668457}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7345 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":69.53999999999999,"y":-458.06,"x":1265.74},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":94.98734283447266,"y":-0.0,"x":-14.86165904998779}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7945 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":69.21,"y":-480.18,"x":1259.51},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":125.15465545654296,"y":-0.0,"x":-10.50986766815185}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7343 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.92999999999999,"y":-494.1,"x":1251.53},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":63.34117126464844,"y":-0.0,"x":-16.31183433532715}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7343 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.36999999999999,"y":-515.5,"x":1250.9},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":77.79755401611328,"y":-0.0,"x":-17.28229522705078}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7343 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.67999999999999,"y":-566.43,"x":1241.53},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":130.3302459716797,"y":-0.0,"x":-22.43321228027343}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7338 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.8,"y":-601.65,"x":1240.54},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":91.53223419189452,"y":-1.3435412782314417e-8,"x":-6.82489442825317}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7338 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":68.58999999999999,"y":-620.99,"x":1250.79},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Price":40000,"Owner":"","OwnerName":"","setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":27.77294158935547,"y":-2.145688853261163e-7,"x":-5.87094974517822}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7336 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":67.14,"y":-648.63,"x":1265.69},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-152.5341949462891,"y":-0.0,"x":-14.65502071380615}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7333 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":65.05,"y":-683.53,"x":1270.98},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-171.3050994873047,"y":-0.0,"x":-12.5356969833374}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7333 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":63.93,"y":-702.82,"x":1264.75},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":58.4541015625,"y":0.00000175048376,"x":-12.71638584136962}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7328 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":59.98,"y":-725.27,"x":1229.58},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-88.46087646484375,"y":-0.0,"x":-11.09668827056884}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7328 East Mirror Dr","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":59.82,"y":-696.93,"x":1223.0},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-81.23240661621094,"y":-0.0,"x":-17.37718200683593}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7328 Mirror Park Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":62.71,"y":-669.31,"x":1221.46},"furniture":[],"plysinside":[],"garage":{"enabled":false,"StoredVehicles":[]},"Owner":"","Price":40000,"setName":"","Keys":[],"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-164.38833618164066,"y":-0.0,"x":-11.55613040924072}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7333 Mirror Park Blvd","Interior":"mid-end"},{"Locked":false,"Owned":false,"Entrance":{"z":65.46,"y":-620.26,"x":1207.46},"furniture":[],"plysinside":[],"Price":40000,"Owner":"","Keys":[],"setName":"","garage":{"enabled":false,"StoredVehicles":[]},"cctv":{"maxleft":80,"maxright":-20,"enabled":false,"rot":{"z":-87.679443359375,"y":1.3399391818325056e-8,"x":-5.38702487945556}},"positions":{"Wardrobe":{"z":-99.14720153808594,"y":-994.2987060546876,"x":350.7424926757813}},"Name":"7336 Mirror Park Blvd","Interior":"mid-end"},{"Locked":false,"Price":40000,"Entrance":{"z":67.08,"y":-598.41,"x":1203.75},"furniture":[],"setName":"","Owned":false,"Owner":"","garage":{"enabled":false},"cctv":{"enabled":false,"maxright":-20,"maxleft":80,"rot":{"x":-16.58763313293457,"y":-0.0,"z":3.90023970603942}},"Keys":[],"Interior":"mid-end","positions":{"Storage":{"x":343.86859130859377,"y":-1001.140380859375,"z":-99.19619750976563},"Wardrobe":{"x":350.74249267578127,"y":-994.2987060546875,"z":-99.14720153808594}},"Name":"7338 Mirror Park Blvd","plysinside":[]},{"Locked":false,"Price":40000,"Entrance":{"z":68.16,"y":-575.59,"x":1201.01},"furniture":[],"setName":"","Owned":false,"Owner":"","garage":{"enabled":false},"cctv":{"enabled":false,"maxright":-20,"maxleft":80,"rot":{"x":-20.23956108093261,"y":9.099596240957908e-7,"z":-37.31895446777344}},"Keys":[],"Interior":"mid-end","positions":{"Storage":{"x":343.86859130859377,"y":-1001.140380859375,"z":-99.19619750976563},"Wardrobe":{"x":350.74249267578127,"y":-994.2987060546875,"z":-99.14720153808594}},"Name":"7338 Mirror Park Blvd","plysinside":[]}] \ No newline at end of file From d9ad6d9d53ec199acbfc71e26fddac18ea089a30 Mon Sep 17 00:00:00 2001 From: MoskalykA <100430077+MoskalykA@users.noreply.github.com> Date: Thu, 22 Dec 2022 16:10:08 +0100 Subject: [PATCH 74/83] refactor: jquery removal and formatting --- [esx]/esx_loadingscreen/css/index.css | 132 +++++++++++++------------- [esx]/esx_loadingscreen/index.html | 39 ++++---- [esx]/esx_loadingscreen/js/index.js | 18 ++-- 3 files changed, 95 insertions(+), 94 deletions(-) diff --git a/[esx]/esx_loadingscreen/css/index.css b/[esx]/esx_loadingscreen/css/index.css index 9520df8e..6cb39671 100644 --- a/[esx]/esx_loadingscreen/css/index.css +++ b/[esx]/esx_loadingscreen/css/index.css @@ -12,102 +12,106 @@ * This copyright should appear in every part of the project code */ -html,body { - - margin: 0; - padding: 0; - font-family: 'Quicksand', sans-serif; - overflow: hidden; - +html, +body { + margin: 0; + padding: 0; + font-family: "Quicksand", sans-serif; + overflow: hidden; } #esx_intro { - - z-index: 2; - + z-index: 2; } #esx_loop { - - z-index: 1; - + z-index: 1; } #loading_txt { + bottom: 5%; + left: 50%; + margin-left: -80px; + position: absolute; + z-index: 999; - bottom: 5%; - left: 50%; - margin-left: -80px; - position: absolute; - z-index: 999; - - -webkit-animation: fadein 5s; - -moz-animation: fadein 5s; - -ms-animation: fadein 5s; - -o-animation: fadein 5s; - animation: fadein 5s; - + -webkit-animation: fadein 5s; + -moz-animation: fadein 5s; + -ms-animation: fadein 5s; + -o-animation: fadein 5s; + animation: fadein 5s; } p { - - color: white; - font-size: 32px; - + color: white; + font-size: 32px; } .text_thing:after { - content: ' .'; - animation: dots 2s steps(5, end) infinite; + content: " ."; + animation: dots 2s steps(5, end) infinite; } @keyframes dots { - 0%, 20% { - color: rgba(0,0,0,0); - text-shadow: - .25em 0 0 rgba(0,0,0,0), - .5em 0 0 rgba(0,0,0,0); - } - 40% { - color: white; - text-shadow: - .25em 0 0 rgba(0,0,0,0), - .5em 0 0 rgba(0,0,0,0); - } - 60% { - text-shadow: - .25em 0 0 white, - .5em 0 0 rgba(0,0,0,0); - } - 80%, 100% { - text-shadow: - .25em 0 0 white, - .5em 0 0 white; - } + 0%, + 20% { + color: rgba(0, 0, 0, 0); + text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0); + } + 40% { + color: white; + text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0); + } + 60% { + text-shadow: 0.25em 0 0 white, 0.5em 0 0 rgba(0, 0, 0, 0); + } + 80%, + 100% { + text-shadow: 0.25em 0 0 white, 0.5em 0 0 white; + } } - @keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } + from { + opacity: 0; + } + to { + opacity: 1; + } } @-moz-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } + from { + opacity: 0; + } + to { + opacity: 1; + } } @-webkit-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } + from { + opacity: 0; + } + to { + opacity: 1; + } } @-ms-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } + from { + opacity: 0; + } + to { + opacity: 1; + } } @-o-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } + from { + opacity: 0; + } + to { + opacity: 1; + } } diff --git a/[esx]/esx_loadingscreen/index.html b/[esx]/esx_loadingscreen/index.html index ced82440..212b9e7e 100644 --- a/[esx]/esx_loadingscreen/index.html +++ b/[esx]/esx_loadingscreen/index.html @@ -1,28 +1,25 @@ - - - + - - + - - - + +
-
-

Loading

-
+
+

Loading

+
- - + +
- - - - \ No newline at end of file + + diff --git a/[esx]/esx_loadingscreen/js/index.js b/[esx]/esx_loadingscreen/js/index.js index 955be242..e2312b4a 100644 --- a/[esx]/esx_loadingscreen/js/index.js +++ b/[esx]/esx_loadingscreen/js/index.js @@ -10,13 +10,13 @@ // If you redistribute this software, you must link to ORIGINAL repository at https://github.com/esx-framework/esx-reborn // This copyright should appear in every part of the project code -$(document).ready(function(){ - const introTag = document.getElementById('esx_intro'); - const loopTag = document.getElementById('esx_loop'); +document.addEventListener("DOMContentLoaded", () => { + const introTag = document.getElementById("esx_intro"); + const loopTag = document.getElementById("esx_loop"); - introTag.onended = (event) => { - introTag.style.display = "none"; - loopTag.loop = true; // true - loopTag.play() - }; -}) + introTag.onended = () => { + introTag.style.display = "none"; + loopTag.loop = true; // true + loopTag.play(); + }; +}); From f71dcae72a8d8c92a1aa8d8a6e080d68157630b9 Mon Sep 17 00:00:00 2001 From: bitpredator <67551273+bitpredator@users.noreply.github.com> Date: Fri, 23 Dec 2022 13:18:58 +0100 Subject: [PATCH 75/83] fix:(boat license missing) --- [SQL]/legacy.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/[SQL]/legacy.sql b/[SQL]/legacy.sql index 4fb035d1..95924e9e 100644 --- a/[SQL]/legacy.sql +++ b/[SQL]/legacy.sql @@ -329,7 +329,8 @@ INSERT INTO `licenses` (`type`, `label`) VALUES ('drive', 'Drivers License'), ('drive_bike', 'Motorcycle License'), ('drive_truck', 'Commercial Drivers License'), -('weed_processing', 'Weed Processing License'); +('weed_processing', 'Weed Processing License'), +('boat', 'Boat License'); -- -------------------------------------------------------- From b3b3b19e8b3572789882744435486eaf5dd98f80 Mon Sep 17 00:00:00 2001 From: Mycroft Date: Fri, 23 Dec 2022 20:45:23 +0000 Subject: [PATCH 76/83] fix(esx_lscustoms): Sync VehicleProperties State to owned vehicles --- [esx_addons]/esx_lscustom/client/main.lua | 7 +++---- [esx_addons]/esx_lscustom/server/main.lua | 7 ++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/[esx_addons]/esx_lscustom/client/main.lua b/[esx_addons]/esx_lscustom/client/main.lua index b5273d1b..6a3374cc 100644 --- a/[esx_addons]/esx_lscustom/client/main.lua +++ b/[esx_addons]/esx_lscustom/client/main.lua @@ -2,9 +2,7 @@ local Vehicles, myCar = {}, {} local lsMenuIsShowed, HintDisplayed, isInLSMarker = false, false, false RegisterNetEvent('esx:playerLoaded') -AddEventHandler('esx:playerLoaded', function(xPlayer) - ESX.PlayerLoaded = true - ESX.PlayerData = xPlayer +AddEventHandler('esx:playerLoaded', function() ESX.TriggerServerCallback('esx_lscustom:getVehiclesPrices', function(vehicles) Vehicles = vehicles end) @@ -13,8 +11,9 @@ end) RegisterNetEvent('esx_lscustom:installMod') AddEventHandler('esx_lscustom:installMod', function() local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) + local NetId = NetworkGetNetworkIdFromEntity(vehicle) myCar = ESX.Game.GetVehicleProperties(vehicle) - TriggerServerEvent('esx_lscustom:refreshOwnedVehicle', myCar) + TriggerServerEvent('esx_lscustom:refreshOwnedVehicle', myCar, NetId) end) RegisterNetEvent('esx_lscustom:restoreMods', function(netId, props) diff --git a/[esx_addons]/esx_lscustom/server/main.lua b/[esx_addons]/esx_lscustom/server/main.lua index 5879b7dc..94aafe25 100644 --- a/[esx_addons]/esx_lscustom/server/main.lua +++ b/[esx_addons]/esx_lscustom/server/main.lua @@ -70,7 +70,7 @@ AddEventHandler('esx_lscustom:buyMod', function(price) end) RegisterServerEvent('esx_lscustom:refreshOwnedVehicle') -AddEventHandler('esx_lscustom:refreshOwnedVehicle', function(vehicleProps) +AddEventHandler('esx_lscustom:refreshOwnedVehicle', function(vehicleProps, netId) local xPlayer = ESX.GetPlayerFromId(source) MySQL.single('SELECT vehicle FROM owned_vehicles WHERE plate = ?', {vehicleProps.plate}, @@ -80,6 +80,11 @@ AddEventHandler('esx_lscustom:refreshOwnedVehicle', function(vehicleProps) if vehicleProps.model == vehicle.model then MySQL.update('UPDATE owned_vehicles SET vehicle = ? WHERE plate = ?', {json.encode(vehicleProps), vehicleProps.plate}) Customs[tostring(source)][tostring(vehicleProps.plate)].props = vehicleProps + local veh = NetworkGetEntityFromNetworkId(netId) + local Veh_State = Entity(veh).state.VehicleProperties + if Veh_State then + Entity(veh).state:set("VehicleProperties", vehicleProps, true) + end else print(('[^3WARNING^7] Player ^5%s^7 Attempted To upgrade with mismatching vehicle model'):format(xPlayer.source)) end From 471e19fb538add0b99dbac446a17f3ee941b58fb Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Mon, 26 Dec 2022 16:14:37 +0530 Subject: [PATCH 77/83] refactor: Pass character data to client --- [esx]/es_extended/server/main.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/[esx]/es_extended/server/main.lua b/[esx]/es_extended/server/main.lua index 87ffeb71..715680ac 100644 --- a/[esx]/es_extended/server/main.lua +++ b/[esx]/es_extended/server/main.lua @@ -308,6 +308,10 @@ function loadESXPlayer(identifier, playerId, isNew) maxWeight = xPlayer.getMaxWeight(), money = xPlayer.getMoney(), sex = xPlayer.get("sex") or "m", + firstName = xPlayer.get("firstName") or "John", + lastName = xPlayer.get("lastName") or "Doe, + dateofbirth = xPlayer.get("dateofbirth") or "01/01/2000", + height = xPlayer.get("height") or 120, dead = false }, isNew, userData.skin) From a92e8456fe8e21e567358db90a29218f99353d28 Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Mon, 26 Dec 2022 17:15:55 +0530 Subject: [PATCH 78/83] Update main.lua --- [esx]/es_extended/server/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[esx]/es_extended/server/main.lua b/[esx]/es_extended/server/main.lua index 715680ac..c5a61e85 100644 --- a/[esx]/es_extended/server/main.lua +++ b/[esx]/es_extended/server/main.lua @@ -309,7 +309,7 @@ function loadESXPlayer(identifier, playerId, isNew) money = xPlayer.getMoney(), sex = xPlayer.get("sex") or "m", firstName = xPlayer.get("firstName") or "John", - lastName = xPlayer.get("lastName") or "Doe, + lastName = xPlayer.get("lastName") or "Doe", dateofbirth = xPlayer.get("dateofbirth") or "01/01/2000", height = xPlayer.get("height") or 120, dead = false From 46de4fcb2ca12ef914228de48a3cff1a607ecedd Mon Sep 17 00:00:00 2001 From: TheFarFantomas Date: Tue, 27 Dec 2022 17:10:15 +0100 Subject: [PATCH 79/83] refactor(es_extended/client/main.lua): Remove unused variables and some comments --- [esx]/es_extended/client/main.lua | 102 +++++++++++++++--------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/[esx]/es_extended/client/main.lua b/[esx]/es_extended/client/main.lua index b613f741..570ec5a1 100644 --- a/[esx]/es_extended/client/main.lua +++ b/[esx]/es_extended/client/main.lua @@ -1,5 +1,5 @@ local pickups = {} -local PlayerBank, PlayerMoney = 0,0 + CreateThread(function() while not Config.Multichar do Wait(0) @@ -52,71 +52,71 @@ AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin) while ESX.PlayerData.ped == nil do Wait(20) end - -- enable PVP if Config.EnablePVP then SetCanAttackFriendly(ESX.PlayerData.ped, true, false) NetworkSetFriendlyFireOption(true) end - CreateThread(function() - local SetPlayerHealthRechargeMultiplier = SetPlayerHealthRechargeMultiplier - local BlockWeaponWheelThisFrame = BlockWeaponWheelThisFrame - local DisableControlAction = DisableControlAction - local IsPedArmed = IsPedArmed - local SetPlayerLockonRangeOverride = SetPlayerLockonRangeOverride - local DisablePlayerVehicleRewards = DisablePlayerVehicleRewards - local RemoveAllPickupsOfType = RemoveAllPickupsOfType - local HideHudComponentThisFrame = HideHudComponentThisFrame - local PlayerId = PlayerId() - local DisabledComps = {} - for i=1, #(Config.RemoveHudCommonents) do - if Config.RemoveHudCommonents[i] then - DisabledComps[#DisabledComps + 1] = i - end - end - while true do - local Sleep = true + CreateThread(function() + local SetPlayerHealthRechargeMultiplier = SetPlayerHealthRechargeMultiplier + local BlockWeaponWheelThisFrame = BlockWeaponWheelThisFrame + local DisableControlAction = DisableControlAction + local IsPedArmed = IsPedArmed + local SetPlayerLockonRangeOverride = SetPlayerLockonRangeOverride + local DisablePlayerVehicleRewards = DisablePlayerVehicleRewards + local RemoveAllPickupsOfType = RemoveAllPickupsOfType + local HideHudComponentThisFrame = HideHudComponentThisFrame + local PlayerId = PlayerId() + local DisabledComps = {} + for i=1, #(Config.RemoveHudCommonents) do + if Config.RemoveHudCommonents[i] then + DisabledComps[#DisabledComps + 1] = i + end + end - if Config.DisableHealthRegeneration then - Sleep = false - SetPlayerHealthRechargeMultiplier(PlayerId, 0.0) - end + while true do + local Sleep = true - if Config.DisableWeaponWheel then - Sleep = false - BlockWeaponWheelThisFrame() - DisableControlAction(0, 37,true) - end + if Config.DisableHealthRegeneration then + Sleep = false + SetPlayerHealthRechargeMultiplier(PlayerId, 0.0) + end - if Config.DisableAimAssist then - Sleep = false - if IsPedArmed(ESX.PlayerData.ped, 4) then - SetPlayerLockonRangeOverride(PlayerId, 2.0) - end - end + if Config.DisableWeaponWheel then + Sleep = false + BlockWeaponWheelThisFrame() + DisableControlAction(0, 37,true) + end - if Config.DisableVehicleRewards then - Sleep = false - DisablePlayerVehicleRewards(PlayerId) + if Config.DisableAimAssist then + Sleep = false + if IsPedArmed(ESX.PlayerData.ped, 4) then + SetPlayerLockonRangeOverride(PlayerId, 2.0) end + end + + if Config.DisableVehicleRewards then + Sleep = false + DisablePlayerVehicleRewards(PlayerId) + end - if Config.DisableNPCDrops then - Sleep = false - RemoveAllPickupsOfType(0xDF711959) -- carbine rifle - RemoveAllPickupsOfType(0xF9AFB48F) -- pistol - RemoveAllPickupsOfType(0xA9355DCD) -- pumpshotgun - end + if Config.DisableNPCDrops then + Sleep = false + RemoveAllPickupsOfType(0xDF711959) + RemoveAllPickupsOfType(0xF9AFB48F) + RemoveAllPickupsOfType(0xA9355DCD) + end - if #DisabledComps > 0 then - Sleep = false - for i=1, #(DisabledComps) do - HideHudComponentThisFrame(DisabledComps[i]) - end + if #DisabledComps > 0 then + Sleep = false + for i=1, #(DisabledComps) do + HideHudComponentThisFrame(DisabledComps[i]) end + end Wait(Sleep and 1500 or 0) - end - end) + end + end) if Config.EnableHud then for i=1, #(ESX.PlayerData.accounts) do From d214b902e5ab21150a1484b0c8576dfbd312317b Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Wed, 28 Dec 2022 11:18:50 +0530 Subject: [PATCH 80/83] fix: Backwards compatibility for closing context menu --- [esx]/esx_context/main.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/[esx]/esx_context/main.lua b/[esx]/esx_context/main.lua index 8a2769c9..0a0567d7 100644 --- a/[esx]/esx_context/main.lua +++ b/[esx]/esx_context/main.lua @@ -13,6 +13,9 @@ function Post(fn,...) end function Open(position,eles,onSelect,onClose,canClose) + if canClose == nil then + canClose = true + end activeMenu = { position = position, eles = eles, From 19f0365b57230e1346dfc144c985940a82282653 Mon Sep 17 00:00:00 2001 From: Tony Stark <76168122+tony-stark-17@users.noreply.github.com> Date: Wed, 28 Dec 2022 11:32:33 +0530 Subject: [PATCH 81/83] fix: Changed it to the same as the main so now issues in merge --- [esx]/esx_context/main.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/[esx]/esx_context/main.lua b/[esx]/esx_context/main.lua index 0a0567d7..6c16fc7d 100644 --- a/[esx]/esx_context/main.lua +++ b/[esx]/esx_context/main.lua @@ -13,9 +13,7 @@ function Post(fn,...) end function Open(position,eles,onSelect,onClose,canClose) - if canClose == nil then - canClose = true - end + local canClose = canClose == nil and true or canClose activeMenu = { position = position, eles = eles, From d5956944ba716a44ebfd2236d1e06182c48ea3fb Mon Sep 17 00:00:00 2001 From: wobozkyng <42249669+wobozkyng@users.noreply.github.com> Date: Wed, 28 Dec 2022 13:52:13 +0700 Subject: [PATCH 82/83] adding delete character confirmation --- [esx]/esx_multicharacter/client/main.lua | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/[esx]/esx_multicharacter/client/main.lua b/[esx]/esx_multicharacter/client/main.lua index c37bf0f7..a6f36f0f 100644 --- a/[esx]/esx_multicharacter/client/main.lua +++ b/[esx]/esx_multicharacter/client/main.lua @@ -140,6 +140,24 @@ if ESX.GetConfig().Multichar then }) end + function CharacterDeleteConfirmation(Characters, slots, SelectedCharacter, value) + local elements = { + {title = 'Delete Confirmation', icon = "fa-solid fa-users", description = 'Are you sure removing selected character?', unselectable = true}, + {title = TranslateCap('char_delete'), icon ="fa-solid fa-xmark", description = 'Yes, I am sure removing selected character', action = 'delete', value = value}, + {title = TranslateCap('return'), unselectable = false, icon = "fa-solid fa-arrow-left", description = 'No, return to character options', action = "return"} + } + + ESX.OpenContext("left", elements, function(element, Action) + if Action.action == "delete" then + ESX.CloseContext() + TriggerServerEvent('esx_multicharacter:DeleteCharacter', Action.value) + spawned = false + elseif Action.action == "return" then + CharacterOptions(Characters, slots, SelectedCharacter) + end + end, nil, false) + end + function CharacterOptions(Characters, slots, SelectedCharacter) local elements = {{title = TranslateCap('character', Characters[SelectedCharacter.value].firstname .. " ".. Characters[SelectedCharacter.value].lastname),icon = "fa-regular fa-user", unselectable = true}, {title = TranslateCap('return'), unselectable = false,icon = "fa-solid fa-arrow-left",description = TranslateCap('return_description'), action = "return"}} @@ -157,9 +175,7 @@ if ESX.GetConfig().Multichar then ESX.CloseContext() TriggerServerEvent('esx_multicharacter:CharacterChosen', Action.value, false) elseif Action.action == "delete" then - ESX.CloseContext() - TriggerServerEvent('esx_multicharacter:DeleteCharacter', Action.value) - spawned = false + CharacterDeleteConfirmation(Characters, slots, SelectedCharacter, Action.value) elseif Action.action == "return" then SelectCharacterMenu(Characters, slots) end From de1fb18c796a06434cf134b9175367f81a915eb5 Mon Sep 17 00:00:00 2001 From: wobozkyng <42249669+wobozkyng@users.noreply.github.com> Date: Wed, 28 Dec 2022 17:17:36 +0700 Subject: [PATCH 83/83] adding english translation for delchar confirm text --- [esx]/esx_multicharacter/client/main.lua | 6 +++--- [esx]/esx_multicharacter/locales/en.lua | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/[esx]/esx_multicharacter/client/main.lua b/[esx]/esx_multicharacter/client/main.lua index a6f36f0f..de34e7c3 100644 --- a/[esx]/esx_multicharacter/client/main.lua +++ b/[esx]/esx_multicharacter/client/main.lua @@ -142,9 +142,9 @@ if ESX.GetConfig().Multichar then function CharacterDeleteConfirmation(Characters, slots, SelectedCharacter, value) local elements = { - {title = 'Delete Confirmation', icon = "fa-solid fa-users", description = 'Are you sure removing selected character?', unselectable = true}, - {title = TranslateCap('char_delete'), icon ="fa-solid fa-xmark", description = 'Yes, I am sure removing selected character', action = 'delete', value = value}, - {title = TranslateCap('return'), unselectable = false, icon = "fa-solid fa-arrow-left", description = 'No, return to character options', action = "return"} + {title = TranslateCap('char_delete_confirmation'), icon = "fa-solid fa-users", description = TranslateCap('char_delete_confirmation_description'), unselectable = true}, + {title = TranslateCap('char_delete'), icon ="fa-solid fa-xmark", description = TranslateCap('char_delete_yes_description'), action = 'delete', value = value}, + {title = TranslateCap('return'), unselectable = false, icon = "fa-solid fa-arrow-left", description = TranslateCap('char_delete_no_description'), action = "return"} } ESX.OpenContext("left", elements, function(element, Action) diff --git a/[esx]/esx_multicharacter/locales/en.lua b/[esx]/esx_multicharacter/locales/en.lua index 64491ee2..d796ec32 100644 --- a/[esx]/esx_multicharacter/locales/en.lua +++ b/[esx]/esx_multicharacter/locales/en.lua @@ -10,6 +10,10 @@ Locales["en"] = { ["char_disabled_description"] = "This Character Is Unusable.", ["char_delete"] = "Delete", ["char_delete_description"] = "Permanently Remove This Character.", + ["char_delete_confirmation"] = "Delete Confirmation", + ["char_delete_confirmation_description"] = "Are you sure removing selected character?", + ["char_delete_yes_description"] = "Yes, I am sure removing selected character", + ["char_delete_no_description"] = "No, return to character options", ["character"] = "Character: %s", ["return"] = "Return", ["return_description"] = "Return To Character Selection.",