# lb-phone

1. Navigate to the **lb-phone/config/config.lua** and find the `Config.ServerSideSpawn` option - set to **true**

```lua
Config.ServerSideSpawn = true
```

2. Navigate to the **lb-phone/server/custom/frameworks/YOUR\_FRAMEWORK/vehicles.lua** and replace the entire file

<details>

<summary><strong>esx</strong></summary>

```lua
if Config.Framework ~= "esx" then
    return
end

while not ESX do
    Wait(500)
    debugprint("Vehicles: Waiting for ESX to load")
end

function GetPlayerVehicles(source)
    local toSend = {}
    local vehicles = MySQL.query.await("SELECT * FROM owned_vehicles WHERE owner = ? ", { GetIdentifier(source) })

    for i = 1, #vehicles do
        local vehicle = vehicles[i] or {}

        local impounded = false
        local garageName, garageCoords = vehicle.garage and exports['vms_garagesv2']:getGarageInfo(vehicle.garage)

        vehicle.stored = not vehicle.garage

        if vehicle.impound_date and vehicle.impound_data then
            impounded = true
            vehicle.stored = false
            vehicle.pound = garageName
            local impoundInfo = json.decode(vehicle.impound_data)
            vehicle.impoundReason = impoundInfo and {
                reason = impoundInfo.fine_title,
                price = impoundInfo.fine_amount,
                impounder = impoundInfo.impounded_by
            }
        end

        local location = garageName or "out"
        if impounded and vehicle.pound then
            location = vehicle.pound
        end

        local newCar = {
            plate = vehicle.plate,
            type = vehicle.type == "vehicle" and "car" or vehicle.type,
            location = location,
            impounded = impounded,
            statistics = {},
            impoundReason = vehicle.impoundReason
        }

        local vehicleMods = json.decode(vehicle.vehicle)
        if vehicleMods then
            if vehicleMods.engineHealth then
                newCar.statistics.engine = math.floor(vehicleMods.engineHealth / 10 + 0.5)
            end
            if vehicleMods.bodyHealth then
                newCar.statistics.body = math.floor(vehicleMods.bodyHealth / 10 + 0.5)
            end
            if vehicleMods.fuelLevel then
                newCar.statistics.fuel = math.floor(vehicleMods.fuelLevel + 0.5)
            end
        end
        
        newCar.model = vehicleMods.model

        toSend[#toSend+1] = newCar
    end

    return toSend
end

function GetVehicle(source, plate)
    local vehicle = MySQL.single.await("SELECT * FROM owned_vehicles WHERE `owner` = ? AND `plate` = ? AND `garage` IS NOT NULL", {
        GetIdentifier(source),
        plate
    })
    
    if not vehicle then
        return
    end

    if vehicle then
        TriggerEvent('vms_garagesv2:vehicleTakenByPhone', vehicle.garage, vehicle.garageSpotID)
    end

    MySQL.update("UPDATE owned_vehicles SET `garage` = NULL, `garageSpotID` = NULL WHERE plate = ?", { plate })

    vehicle.model = json.decode(vehicle.vehicle).model

    return vehicle
end

```

</details>

<details>

<summary><strong>qb</strong></summary>

{% hint style="danger" %}

## READ BEFORE CHANGES

If you are using the **owned\_vehicles** table instead of **player\_vehicles**, use the **ESX** file, but be sure to change from `Config.Framework ~= "esx"` to `Config.Framework ~= "qbox"` in the first line.
{% endhint %}

```lua
if Config.Framework ~= "qb" then
    return
end

while not QB do
    Wait(500)
    debugprint("Vehicles: Waiting for QB to load")
end

function GetPlayerVehicles(source)
    local toSend = {}
    local vehicles = MySQL.query.await("SELECT * FROM player_vehicles WHERE citizenid = ?", { GetIdentifier(source) })

    for i = 1, #vehicles do
        local vehicle = vehicles[i] or {}

        local impounded = false
        local garageName, garageCoords = vehicle.garage and exports['vms_garagesv2']:getGarageInfo(vehicle.garage)

        vehicle.stored = not vehicle.garage

        if vehicle.impound_date and vehicle.impound_data then
            impounded = true
            vehicle.stored = false
            vehicle.pound = garageName
            local impoundInfo = json.decode(vehicle.impound_data)
            vehicle.impoundReason = impoundInfo and {
                reason = impoundInfo.fine_title,
                price = impoundInfo.fine_amount,
                impounder = impoundInfo.impounded_by
            }
        end

        local location = garageName or "out"
        if impounded and vehicle.pound then
            location = vehicle.pound
        end

        local newCar = {
            plate = vehicle.plate,
            type = vehicle.type == "vehicle" and "car" or vehicle.type,
            location = location,
            impounded = impounded,
            statistics = {},
            impoundReason = vehicle.impoundReason
        }

        local vehicleMods = json.decode(vehicle.mods)
        if vehicleMods then
            if vehicleMods.engineHealth then
                newCar.statistics.engine = math.floor(vehicleMods.engineHealth / 10 + 0.5)
            end
            if vehicleMods.bodyHealth then
                newCar.statistics.body = math.floor(vehicleMods.bodyHealth / 10 + 0.5)
            end
            if vehicleMods.fuelLevel then
                newCar.statistics.fuel = math.floor(vehicleMods.fuelLevel + 0.5)
            end
        end

        newCar.model = vehicleMods.model

        toSend[#toSend+1] = newCar
    end

    return toSend
end

function GetVehicle(source, plate)
    local vehicle = MySQL.single.await("SELECT * FROM player_vehicles WHERE `citizenid` = ? AND `plate` = ? AND `garage` IS NOT NULL", {
        GetIdentifier(source),
        plate
    })
    
    if not vehicle then
        return
    end

    if vehicle then
        TriggerEvent('vms_garagesv2:vehicleTakenByPhone', vehicle.garage, vehicle.garageSpotID)
    end

    MySQL.update("UPDATE player_vehicles SET `garage` = NULL, `garageSpotID` = NULL WHERE plate = ?", { plate })

    vehicle.model = json.decode(vehicle.mods).model

    return vehicle
end
```

</details>

<details>

<summary><strong>qbox</strong></summary>

{% hint style="danger" %}

## READ BEFORE CHANGES

If you are using the **owned\_vehicles** table instead of **player\_vehicles**, use the **ESX** file, but be sure to change from `Config.Framework ~= "esx"` to `Config.Framework ~= "qbox"` in the first line.
{% endhint %}

```lua
if Config.Framework ~= "qbox" then
    return
end

while not QB do
    Wait(500)
    debugprint("Vehicles: Waiting for QBox to load")
end

function GetPlayerVehicles(source)
    local toSend = {}
    local vehicles = MySQL.query.await("SELECT * FROM player_vehicles WHERE citizenid = ?", { GetIdentifier(source) })

    for i = 1, #vehicles do
        local vehicle = vehicles[i] or {}

        local impounded = false
        local garageName, garageCoords = vehicle.garage and exports['vms_garagesv2']:getGarageInfo(vehicle.garage)

        vehicle.stored = not vehicle.garage

        if vehicle.impound_date and vehicle.impound_data then
            impounded = true
            vehicle.stored = false
            vehicle.pound = garageName
            local impoundInfo = json.decode(vehicle.impound_data)
            vehicle.impoundReason = impoundInfo and {
                reason = impoundInfo.fine_title,
                price = impoundInfo.fine_amount,
                impounder = impoundInfo.impounded_by
            }
        end

        local location = garageName or "out"
        if impounded and vehicle.pound then
            location = vehicle.pound
        end

        local newCar = {
            plate = vehicle.plate,
            type = vehicle.type == "vehicle" and "car" or vehicle.type,
            location = location,
            impounded = impounded,
            statistics = {},
            impoundReason = vehicle.impoundReason
        }

        local vehicleMods = json.decode(vehicle.mods)
        if vehicleMods then
            if vehicleMods.engineHealth then
                newCar.statistics.engine = math.floor(vehicleMods.engineHealth / 10 + 0.5)
            end
            if vehicleMods.bodyHealth then
                newCar.statistics.body = math.floor(vehicleMods.bodyHealth / 10 + 0.5)
            end
            if vehicleMods.fuelLevel then
                newCar.statistics.fuel = math.floor(vehicleMods.fuelLevel + 0.5)
            end
        end

        newCar.model = vehicleMods.model

        toSend[#toSend+1] = newCar
    end

    return toSend
end

function GetVehicle(source, plate)
    local vehicle = MySQL.single.await("SELECT * FROM player_vehicles WHERE `citizenid` = ? AND `plate` = ? AND `garage` IS NOT NULL", {
        GetIdentifier(source),
        plate
    })
    
    if not vehicle then
        return
    end

    if vehicle then
        TriggerEvent('vms_garagesv2:vehicleTakenByPhone', vehicle.garage, vehicle.garageSpotID)
    end

    MySQL.update("UPDATE player_vehicles SET `garage` = NULL, `garageSpotID` = NULL WHERE plate = ?", { plate })

    vehicle.model = json.decode(vehicle.mods).model

    return vehicle
end
```

</details>

3. Navigate to the **lb-phone/server/apps/framework/garage.lua** and replace the entire file

<details>

<summary>Garage</summary>

```lua
local function IsVehicleOut(plate, vehicles)
    if not vehicles then
        vehicles = GetAllVehicles()
    end

    for i = 1, #vehicles do
        local vehicle = vehicles[i]
        if DoesEntityExist(vehicle) and GetVehicleNumberPlateText(vehicle):gsub("%s+", "") == plate:gsub("%s+", "") then
            return true, vehicle
        end
    end

    return false
end

BaseCallback("garage:findCar", function(source, phoneNumber, plate)
    local out, vehicle = IsVehicleOut(plate)

    if out and vehicle then
        return GetEntityCoords(vehicle)
    end

    local query = 'SELECT `garage` FROM owned_vehicles WHERE `plate` = ?'
    if Config.Framework == 'qb' or Config.Framework == 'qbox' then
        query = 'SELECT `garage` FROM player_vehicles WHERE `plate` = ?'
    end
    local vehicle = MySQL.single.await(query, { plate })
    if vehicle and vehicle.garage then
        local garageName, garageCoords = exports['vms_garagesv2']:getGarageInfo(vehicle.garage)
        return garageCoords
    end

    SendNotification(phoneNumber, {
        source = source,
        app = "Garage",
        title = L("BACKEND.GARAGE.VALET"),
        content = L("BACKEND.GARAGE.COULDNT_FIND"),
    })

    return false
end)

BaseCallback("garage:getVehicles", function(source, phoneNumber)
    local vehicles = GetPlayerVehicles(source)
    local allVehicles = #vehicles > 0 and GetAllVehicles() or {}

    for i = 1, #vehicles do
        if IsVehicleOut(vehicles[i].plate, allVehicles) then
            vehicles[i].location = "out"
        end
    end

    return vehicles
end)

BaseCallback("garage:valetVehicle", function(source, phoneNumber, plate, coords, heading)
    if IsVehicleOut(plate) then
        SendNotification(phoneNumber, {
            app = "Garage",
            title = L("BACKEND.GARAGE.VALET"),
            content = L("BACKEND.GARAGE.ALREADY_OUT"),
        })
        return
    end

    if Config.Valet.Price and GetBalance(source) < Config.Valet.Price then
        SendNotification(phoneNumber, {
            app = "Garage",
            title = L("BACKEND.GARAGE.VALET"),
            content = L("BACKEND.GARAGE.NO_MONEY"),
        })
        return
    end

    local vehicleData = GetVehicle(source, plate)
    if not vehicleData then
        return
    end

    if Config.Valet.Price and not RemoveMoney(source, Config.Valet.Price) then
        SendNotification(phoneNumber, {
            app = "Garage",
            title = L("BACKEND.GARAGE.VALET"),
            content = L("BACKEND.GARAGE.NO_MONEY"),
        })
        return
    end

    SendNotification(phoneNumber, {
        app = "Garage",
        title = L("BACKEND.GARAGE.VALET"),
        content = L("BACKEND.GARAGE.ON_WAY"),
    })

    if not Config.ServerSideSpawn then
        GiveVehicleKey(source, plate)
        return vehicleData
    end

    local vehicle = CreateServerVehicle(vehicleData.model, coords, heading)
    if not vehicle then
        AddMoney(source, Config.Valet.Price)
        debugprint("Failed to create vehicle")
        return
    end

    if Config.Framework == 'qb' or Config.Framework == 'qbox' then
        Entity(vehicle).state:set("VehicleProperties", json.decode(vehicleData.mods), true)
    else
        Entity(vehicle).state:set("VehicleProperties", json.decode(vehicleData.vehicle), true)
    end
    vehicleData.vehNetId = NetworkGetNetworkIdFromEntity(vehicle)

    if Config.Valet.Drive then
        local ped = CreateServerPed(Config.Valet.Model, coords + vector3(0.0, 1.0, 1.0), heading)
        if not ped then
            AddMoney(source, Config.Valet.Price)
            DeleteEntity(vehicle)
            debugprint("Failed to create ped")
            return
        end
        vehicleData.pedNetId = NetworkGetNetworkIdFromEntity(ped)
    end
    
    if vehicleData.vehNetId then
        local str = 'UPDATE owned_vehicles SET netid = ? WHERE plate = ?'
        if Config.Framework == 'qb' then
            str = 'UPDATE player_vehicles SET netid = ? WHERE plate = ?'
        end
        MySQL.Sync.execute(str, { vehicleData.vehNetId, plate })
    end

    Entity(vehicle).state.plate = plate

    GiveVehicleKey(source, plate, vehicle)

    return vehicleData
end)
```

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.vames-store.com/assets/vms_garagesv2/compatibility/phones/lb-phone.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
