๐Ÿš— Garage

Access a comprehensive guide that includes a detailed installation process, examples of code, previews of configurations.

Garages use a different database than those from the Framework

INSTALLATION GUIDE

Step 0 - First Steps

Download is_garage from KeyMaster and install is_bridge & is_lib.

Step 1 - Configure Resources

You must read and configure the config.lua file in is_garage to meet your needs.

Step 2 - Import SQL

You can import the is_garage.sql file included with the received script or use the following command in the database

CREATE TABLE `is_garage` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `owner` longtext,
  `model` varchar(50),
  `hash` bigint(20),
  `vin` varchar(50),
  `plate` varchar(25),
  `status` longtext,
  `parked` longtext,
  `fuel` int(11),
  `engine` int(11),
  `body` int(11),
  `distance` float(10,2),
  `mods` longtext,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;

CREATE TABLE `is_garage_codes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(100),
  `code` varchar(100),
  `package` int(11),
  `count` int(11),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;

CREATE TABLE `is_garage_keys` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `identifier` varchar(100),
  `name` varchar(100),
  `vin` varchar(100),
  `favorite` tinyint(1),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;

ALTER TABLE `is_garage` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=84;
ALTER TABLE `is_garage_codes` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;
ALTER TABLE `is_garage_keys` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=66;

COMMIT;

Step 3 - Tebex Integration

Log in to your Tebex account, go to your project, and then:

  1. Open the Integrations tab and select Game Servers.

  2. If you don't have a created Server, click Connect Game Server and choose the PLUGIN connection type. Then, you'll need to specify the Server Name and click Select All next to Packages.

  3. If you have an existing Server, make sure it has the properties mentioned above.

  4. Click Edit on Your Server and then click Copy in the Secret Key tab.

  5. Then, in your server, go to server.cfg and insert this line, replacing yourKey with the copied key:

    setr sv_tebexSecret yourKey

Step 4 - Package Integration

Log in to your Tebex account, go to your project, and then:

  1. Go to the Packages tab and create your resource.

  2. Once you've done that, go to the package you created.

  3. The link to the page you are on should look like this: https://creator.tebex.io/packages/0000000, where the digits at the end of the link represent your package's ID - copy them.

  4. In your server, go to is_garage/config.lua and create a new table in cfg.Tebex.packages. It should look like the following:

    {id = 0, chars = 8}, -- id - Copied Package Id, chars - Maximum Characters in Plate
  5. Now, anyone with the specified resource will be able to use it in the game by referencing the transaction, tbx-xxxxxxxxx.

Step 5 - Converting Vehicles

To transfer your Vehicles from Old Garages, simply use the in-game command convertVehicles or the one set in config.lua, and then restart the script. After this, all vehicles from supported frameworks will be added to our Garage System.

Step 6 - Snippet for Vehicle Shops

QBCore

qb-vehicleshop -> client.lua

Search

{
    header = Lang:t('menus.freeuse_buy_header'),
    txt = Lang:t('menus.freeuse_buy_txt'),
    icon = 'fa-solid fa-hand-holding-dollar',
    params = {
        isServer = true,
        event = 'qb-vehicleshop:server:buyShowroomVehicle',
        args = {
            buyVehicle = Config.Shops[insideShop]['ShowroomVehicles'][ClosestVehicle].chosenVehicle
        }
    }
},
{
    header = Lang:t('menus.finance_header'),
    txt = Lang:t('menus.freeuse_finance_txt'),
    icon = 'fa-solid fa-coins',
    params = {
        event = 'qb-vehicleshop:client:openFinance',
        args = {
            price = getVehPrice(),
            buyVehicle = Config.Shops[insideShop]['ShowroomVehicles'][ClosestVehicle].chosenVehicle
        }
    }
},

Replace to

{
    header = Lang:t('menus.freeuse_buy_header'),
    txt = Lang:t('menus.freeuse_buy_txt'),
    icon = 'fa-solid fa-hand-holding-dollar',
    params = {
        isServer = true,
        event = 'qb-vehicleshop:server:buyShowroomVehicle',
        args = {
            buyVehicle = Config.Shops[insideShop]['ShowroomVehicles'][ClosestVehicle].chosenVehicle,
            shop = insideShop,
        }
    }
},
-- {
--     header = Lang:t('menus.finance_header'),
--     txt = Lang:t('menus.freeuse_finance_txt'),
--     icon = 'fa-solid fa-coins',
--     params = {
--         event = 'qb-vehicleshop:client:openFinance',
--         args = {
--             price = getVehPrice(),
--             buyVehicle = Config.Shops[insideShop]['ShowroomVehicles'][ClosestVehicle].chosenVehicle
--         }
--     }
-- },

qb-vehicleshop -> server.lua

Search

RegisterNetEvent('qb-vehicleshop:server:buyShowroomVehicle', function(vehicle)
    local src = source
    vehicle = vehicle.buyVehicle
    local pData = QBCore.Functions.GetPlayer(src)
    local cid = pData.PlayerData.citizenid
    local cash = pData.PlayerData.money['cash']
    local bank = pData.PlayerData.money['bank']
    local vehiclePrice = QBCore.Shared.Vehicles[vehicle]['price']
    local plate = GeneratePlate()

    if cash > tonumber(vehiclePrice) then
        MySQL.insert('INSERT INTO player_vehicles (license, citizenid, vehicle, hash, mods, plate, garage, state) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', {
            pData.PlayerData.license,
            cid,
            vehicle,
            GetHashKey(vehicle),
            '{}',
            plate,
            'pillboxgarage',
            0
        })
        TriggerClientEvent('QBCore:Notify', src, Lang:t('success.purchased'), 'success')
        TriggerClientEvent('qb-vehicleshop:client:buyShowroomVehicle', src, vehicle, plate)
        pData.Functions.RemoveMoney('cash', vehiclePrice, 'vehicle-bought-in-showroom')
    elseif bank > tonumber(vehiclePrice) then
        MySQL.insert('INSERT INTO player_vehicles (license, citizenid, vehicle, hash, mods, plate, garage, state) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', {
            pData.PlayerData.license,
            cid,
            vehicle,
            GetHashKey(vehicle),
            '{}',
            plate,
            'pillboxgarage',
            0
        })
        TriggerClientEvent('QBCore:Notify', src, Lang:t('success.purchased'), 'success')
        TriggerClientEvent('qb-vehicleshop:client:buyShowroomVehicle', src, vehicle, plate)
        pData.Functions.RemoveMoney('bank', vehiclePrice, 'vehicle-bought-in-showroom')
    else
        TriggerClientEvent('QBCore:Notify', src, Lang:t('error.notenoughmoney'), 'error')
    end
end)

Replace to

RegisterNetEvent('qb-vehicleshop:server:buyShowroomVehicle', function(data)
    local src = source

    local vehicle = data.buyVehicle
    local shop = data.shop
    local vehiclePrice = QBCore.Shared.Vehicles[vehicle]['price']
    local plate = GeneratePlate()

    local pData = QBCore.Functions.GetPlayer(src)
    local cash = pData.PlayerData.money['cash']
    local bank = pData.PlayerData.money['bank']

    if cash > tonumber(vehiclePrice) then
        pData.Functions.RemoveMoney('cash', vehiclePrice, 'vehicle-bought-in-showroom')
    elseif bank > tonumber(vehiclePrice) then
        pData.Functions.RemoveMoney('bank', vehiclePrice, 'vehicle-bought-in-showroom')
    else
        TriggerClientEvent('QBCore:Notify', src, Lang:t('error.notenoughmoney'), 'error')
        return
    end

    TriggerClientEvent('QBCore:Notify', src, Lang:t('success.purchased'), 'success')

    TriggerEvent("is_garage:createVehicle", {
        model = vehicle,
        hash = GetHashKey(vehicle),
        plate = plate,
        parked = {
            coords = Config.Shops[shop].VehicleSpawn,
            street = Config.Shops[shop].ShopLabel,
        },
    }, src)
end)

QBox

Go to qbx_vehicleshop/config/shared.lua and set finance.enable to false

qbx_vehicleshop -> server -> main.lua

Search

RegisterNetEvent('qbx_vehicleshop:server:buyShowroomVehicle', function(vehicleData)
    local src = source

    local shopId = getShopZone(src)
    local shop = sharedConfig.shops[shopId]
    if not shop then return end

    local vehicle = vehicleData.buyVehicle

    ---@diagnostic disable-next-line: param-type-mismatch
    if not checkVehicleList(vehicle, shopId) then
        return exports.qbx_core:Notify(src, locale('error.notallowed'), 'error')
    end

    local player = exports.qbx_core:GetPlayer(src)
    local vehiclePrice = coreVehicles[vehicle].price
    local currencyType = findChargeableCurrencyType(vehiclePrice, player.PlayerData.money.cash, player.PlayerData.money.bank)
    if not currencyType then
        return exports.qbx_core:Notify(src, locale('error.notenoughmoney'), 'error')
    end

    local vehicleId = qbx_vehicles:CreatePlayerVehicle({
        model = vehicle,
        citizenid = player.PlayerData.citizenid,
    })

    exports.qbx_core:Notify(src, locale('success.purchased'), 'success')


    spawnVehicle(src, {
        coords = shop.vehicleSpawn,
        vehicleId = vehicleId
    })

    player.Functions.RemoveMoney(currencyType, vehiclePrice, 'vehicle-bought-in-showroom')
end)

Replace to

RegisterNetEvent('qbx_vehicleshop:server:buyShowroomVehicle', function(vehicleData)
    local src = source

    local shopId = getShopZone(src)
    local shop = sharedConfig.shops[shopId]
    if not shop then return end

    local vehicle = vehicleData.buyVehicle

    ---@diagnostic disable-next-line: param-type-mismatch
    if not checkVehicleList(vehicle, shopId) then
        return exports.qbx_core:Notify(src, locale('error.notallowed'), 'error')
    end

    local player = exports.qbx_core:GetPlayer(src)
    local vehiclePrice = coreVehicles[vehicle].price
    local currencyType = findChargeableCurrencyType(vehiclePrice, player.PlayerData.money.cash, player.PlayerData.money.bank)
    if not currencyType then
        return exports.qbx_core:Notify(src, locale('error.notenoughmoney'), 'error')
    end

    TriggerEvent("is_garage:createVehicle", {
        model = vehicle,
        hash = GetHashKey(vehicle),
        plate = qbx.generateRandomPlate(),
        parked = {
            coords = shop.vehicleSpawn,
            street = shop.blip.label,
        },
    }, src)

    exports.qbx_core:Notify(src, locale('success.purchased'), 'success')

    player.Functions.RemoveMoney(currencyType, vehiclePrice, 'vehicle-bought-in-showroom')
end)

Last updated