Default Config

Here is the default configuration files in case you need it

config.lua
-- ############################################### --
-- ## ██╗  ██╗███████╗██████╗ ███████╗██╗   ██╗ ## --
-- ## ██║ ██╔╝██╔════╝██╔══██╗██╔════╝██║   ██║ ## --
-- ## █████╔╝ █████╗  ██║  ██║█████╗  ██║   ██║ ## --
-- ## ██╔═██╗ ██╔══╝  ██║  ██║██╔══╝  ╚██╗ ██╔╝ ## --
-- ## ██║  ██╗██║     ██████╔╝███████╗ ╚████╔╝  ## --
-- ## ╚═╝  ╚═╝╚═╝     ╚═════╝ ╚══════╝  ╚═══╝   ## --
-- ## KF Vehicle Shop                           ## --
-- ## Developed by KFDev                        ## --
-- ## DOCUMENATION: https://docs.kfdev.it/      ## --
-- ############################################### --

Config = {}

Config.Debug = false -- Enabled Debug mode and prints

Config.Locale = 'en' -- Default locale
Config.Locales = {}

Config.DefaultRoutingBucket = 0

-------------------
-- ##   IPLs   ## - -- ⚠️ WORK IN PROGRESS, USE BOB74_IPL INSTEAD ⚠️
-------------------
--[[
  Here you can set the IPLs that will be loaded on resource start
  The LoadIpls functions is only available if bob74_ipl resource is not started for a
  standalone version of the script. If you are using the bob74_ipl resource, please
  use that instead.
]]
-- Config.LoadIpls = GetResourceState('bob74_ipl') == 'started' and false or true -- Load IPLs from kf_ipl resource
-- Config.IPLsToLoad = { -- More IPLs can be added here and in the data/ipls.lua file
--   ['tuner_meet'] = true,
-- }

Config.VehiclesPlateText = ' KFSHOP ' -- Default plate text for the vehicles (1-8 characters)

Config.Locations = {
  ['VehicleShop1'] = {
    RoutingBucket = nil, -- You can force a specific routing bucket. By default it will use the current player's routing bucket. Set to NIL to disable
    
    -------------------
    -- ## MARKERS ## --
    -------------------
    Markers = {
      EnterMarker = {
        Position = vector4(-1087.20, -1277.60, 5.84, 208.21), -- [[ Should be a vector4 since
        -- the last value is the heading which will be user to set the player rotation on exit ]]
        DrawDistance = 5.0,
        InteractDist = 2.0,
        InteractKey = 38, -- 38 = E
        Type = 2,
        Size = vector3(0.3, 0.3, 0.2),
        Text = 'Enter the Vehicle Shop',
        Color = {
          r = 255, 
          g = 255, 
          b = 255, 
          a = 200
        },
        Rotation = vector3(0, 180.0, 0),
        Rotate = false,
        Bounce = false,
        FaceCamera = true,
        TextureDict = nil,
        TextureName = nil,
        Blip = { -- Table or Nil to disable
          Sprite = 225,
          Color = 2,
          Scale = 0.7,
          Name = 'Enter Vehicle Shop',
        },
      },
      ExitMarker = {
        Position = vector4(-2220.60, 1160.06, -23.26, 216.48),
        DrawDistance = 5.0,
        InteractDist = 2.0,
        InteractKey = 38,
        Type = 2,
        Size = vector3(0.3, 0.3, 0.2),
        Text = 'Exit the vehicle shop',
        Color = {
          r = 255, 
          g = 255, 
          b = 255, 
          a = 200
        },
        Rotation = vector3(0, 180.0, 0),
        Rotate = false,
        Bounce = false,
        FaceCamera = true,
        TextureDict = nil,
        TextureName = nil,
        Blip = { -- Table or Nil/empty to disable
          Sprite = 225,
          Color = 1,
          Scale = 0.7,
          Name = 'Exit Vehicle Shop',
        },
      },
      ChangeVehicles = {
        Position = vector3(-2210.00, 1150.41, -23.26),
        DrawDistance = 10.0,
        InteractDist = 2.0,
        InteractKey = 38,
        Type = 36,
        Size = vector3(0.4, 0.4, 0.4),
        Text = 'Change Vehicles Catalogue',
        Color = {
          r = 222, 
          g = 70, 
          b = 20, 
          a = 200
        },
        Rotation = vector3(0, 0, 0),
        Rotate = false,
        Bounce = false,
        FaceCamera = true,
        TextureDict = nil,
        TextureName = nil,
        Blip = { -- Table or Nil/empty to disable
          Sprite = 225,
          Color = 1,
          Scale = 0.7,
          Name = 'Change Vehicles List',
        },
      }
    },

    -----------------------------
    -- ##  CATALOGUE NAMES  ## --
    -----------------------------
    Catalogues = {
      [1] = {
        name = 'page_1',
        label = 'Page 1',
        color = '#ff0000',
      },
      [2] = {
        name = 'page_2',
        label = 'Page 2',
        color = '#00ff00',
      },
      [3] = {
        name = 'page_3',
        label = 'Page 3',
        color = '#0000ff',
      },
    },

    ------------------
    -- ##  BLIP  ## --
    ------------------
    Blip = { -- Table or Nil to disable
      Sprite = 225,
      Color = 1,
      ShortRange = true,
      Scale = 0.7,
      Name = 'Vehicle Shop',
    },

    -----------------------------------------
    -- ##  VEHICLES SPAWNS (after buy)  ## --
    -----------------------------------------
    BoughtVehicleSpawns = {
      vector4(-1066.65, -1253.40, 5.88, 113.78),
      vector4(-1069.54, -1250.75, 5.75, 117.28),
      vector4(-1071.62, -1248.05, 5.60, 115.85),
      vector4(-1083.27, -1243.23, 5.08, 213.44),
    },

    ----------------------
    -- ##  POLYZONE  ## --
    ----------------------
    PolyZone = {
      Positions = {
        vector3(-2255.12, 962.27, -0.71),
        vector3(-2243.52, 1297.16, 26.22),
        vector3(-1779.32, 1283.67, -37.71),
        vector3(-1785.21, 949.93, -33.56),
      },
      MinZ = -45.0,
      MaxZ = -10.0,
      TeleportExitOnRelog = true,
    },

    -------------------------------
    -- ##  TEST DRIVE SPAWNS  ## --
    -------------------------------
    TestDrivePositions = {
      vector4(-2128.49, 1106.04, -27.37, 267.54),
      vector4(-2119.47, 1083.37, -27.35, 176.62),
      vector4(-2119.08, 1132.01, -27.37, 359.61),
      vector4(-2106.16, 1147.84, -27.36, 267.72),
      vector4(-2106.52, 1073.15, -27.35, 266.80),
    },

    -----------------------------------------
    -- ##  VEHICLES LIST and CATALOGUE  ## --
    -----------------------------------------
    Vehicles = {
      --[[ 
        Page System: You can set which vehicle will spawn in each "Page".
        This is useful to prevent memory overflow when loading a lot of custom vehicles

        Catalogue: The page number where the vehicle will be displayed. Use a maximum of
        30 vehicles per page to prevent memory overflow and long loading times.
      ]]
      ['adder_1'] = {
        Position = vector4(-2185.93, 1138.90, -24.26, 84.92),
        Catalogue = 'auto_prime',
      },
      ['kuruma_1'] = {
        Position = vector4(-2185.99, 1135.97, -24.26, 89.04),
        Catalogue = 'auto_prime',
      },
      ['bati'] = {
        Position = vector4(-2185.93, 1138.90, -24.26, 84.92),
        Catalogue = 'moto_prime',
      }
    },
  }
}

-------------------
-- ## 3D TEXT ## --
-------------------
Config.Draw3DTextDistance = 5.0 -- Distance to draw the 3D Text from the vehicle.
Config.Draw3DTextInteractDist = 2.0 -- Distance to interact with the vehicle. (It will pick the nearest)
Config.Draw3DTextScale = 0.4 -- Default scale for the 3D Text.
Config.Draw3DTextOffset = vector3(0.0, 0.0, 1.5) -- Offset for the 3D Text.
Config.Draw3DTextRowOffset = 0.1 -- Offset between rows of the 3D Text.

-------------------
-- ## KEYBINDS ## -
-------------------
Config.BuyVehicleKey = 38 -- Key to buy the vehicle. (Default: E)
Config.TestDriveKey = 47 -- Key to test drive the vehicle. (Default: G)
Config.TestDriveEndKey = 47 -- Key to end the test drive. (Default: G)

-------------------
-- ##  FADE  ## --
-------------------
Config.TeleportFade = true -- If True, the player will be teleported with a fade effect.
Config.TeleportFadeDuration = 500 -- Duration of the fade effect in milliseconds.

Config.SwitchVehiclesFade = true -- If True, the vehicle list will be switched with a fade effect.
Config.SwitchVehiclesFadeDuration = 500 -- Duration of the fade effect in milliseconds.

Config.TestDriveFade = true -- If True, the player will be teleported with a fade effect.
Config.TestDriveFadeDuration = 500 -- Duration of the fade effect in milliseconds.

--------------------------------
-- ##  VEHICLE TEST DRIVE  ## --
--------------------------------
Config.TestDriveEnabled = true -- If True, the player will be able to test drive the vehicle.
Config.TestDriveDuration = nil -- Duration of the test drive in milliseconds. (Nil or 0 to disable timer)
Config.EnableTestDriveMods = true -- If True, the player will be able to test the mods of the vehicle.
Config.DisableCollisions = true -- If True, the collisions will be disabled during the test drive.
Config.TestDriveInvincible = true -- If True, the vehicle will be invincible during the test drive.

--[[
  Here you can customize the payment functions that will be executed server-side when a player
  purchases a vehicle. The function must return a boolean value. You can create custom methods
  here and use its index as the payment method on the vehicles.lua file.
]]
Config.PayFunctions = {
  ['money'] = {
    text = '$',
    func = function(src, price)
      local ESX = exports['es_extended']:getSharedObject()
      local xPlayer = ESX.GetPlayerFromId(src)
      if xPlayer.getMoney() >= price then
        xPlayer.removeMoney(price)
        return true
      else
        return false
      end
    end,
  },
  ['bank'] = {
    text = '$',
    func = function(src, price)
      local ESX = exports['es_extended']:getSharedObject()
      local xPlayer = ESX.GetPlayerFromId(src)
      if xPlayer.getAccount('bank').money >= price then
        xPlayer.removeAccountMoney('bank', price)
        return true
      else
        return false
      end
    end,
  },
  ['black_money'] = {
    text = 'Black Money',
    func = function(src, price)
      local ESX = exports['es_extended']:getSharedObject()
      local xPlayer = ESX.GetPlayerFromId(src)
      if xPlayer.getAccount('black_money').money >= price then
        xPlayer.removeAccountMoney('black_money', price)
        return true
      else
        return false
      end
    end,
  },
  ['coin'] = {
    text = 'Coin',
    func = function(src, price)
      local itemQty = exports.ox_inventory:Search(src, 'count', 'coin')
      if itemQty >= price then
        exports.ox_inventory:RemoveItem(src, 'coin', price)
        return true
      else
        return false
      end
    end,
  }
}

Config.Use3DTextForMarkers = false -- If True, a 3D Text will be displayed when a player is near a marker, else a text ui will be displayed.

--[[
  Here you can customize the textui that will be displayed when the player
  uses a marker.
]]
Config.TextUI = {
  Show = function(text, key)
    exports['j-textui']:displayTextUI(text, key)
  end,
  Hide = function() 
    exports['j-textui']:hideTextUI()
  end,
}

--[[
  Here you can customize the notifications. By default, it will use the esx:showNotification event
]]
Config.ClientNotify = function(text, type, length, title)
  TriggerEvent('esx:showNotification', text, type, length, title)
  -- QBCore.Functions.Notify(text, type, length, title)
end

Config.ServerNotify = function(src, text, type, length, title)
  if tonumber(src) then -- If triggered by server
    TriggerClientEvent('esx:showNotification', src, text, type, length, title)
  end
  -- QBCore.Functions.Notify(text, type, length, title)
end

--[[
  Here you can customize the 3D Text that will be displayed when the player
  is near a vehicle in the shop.
]]
Config.DrawText3D = function(text, position, scale_factor, options)
  local x, y, z = position.x, position.y, position.z
  local onScreen, _x, _y = World3dToScreen2d(x, y, z)
  local p = GetGameplayCamCoords()
  local distance = GetDistanceBetweenCoords(p.x, p.y, p.z, x, y, z, 1)
  local scale = (1 / distance) * 2
  local fov = (1 / GetGameplayCamFov()) * 100
  local scale = scale * fov * scale_factor
  local color = options.color or {r = 255, g = 255, b = 255, a = 255}
  local dropShadow = options.dropShadow or true
  local dropShadowSettings = options.dropShadow or {a = 0, b = 0, c = 0, d = 0, e = 255}
  local outline = options.outline or true
  local center = options.center or true
  local font = options.font or 0
  local edge = options.edge or {a = 2, b = 0, c = 0, d = 0, e = 150}
  local proportional = options.proportional or 1
  if onScreen then
      SetTextScale(0.0, scale)
      SetTextFont(font)
      SetTextProportional(proportional)
      SetTextColour(color.r, color.g, color.b, color.a or 255)
      SetTextEdge(edge.a, edge.b, edge.c, edge.d, edge.e)
      if dropShadow then
        SetTextDropShadow()
        SetTextDropshadow(dropShadowSettings.a, dropShadowSettings.b, dropShadowSettings.c, dropShadowSettings.d, dropShadowSettings.e)
      end
      if outline then
        SetTextOutline()
      end
      SetTextEntry("STRING")
      SetTextCentre(center)
      AddTextComponentString(text)
      DrawText(_x, _y)
  end
end

--[[
  Here you can customize the 2D Text that will be displayed when the player
  is near a vehicle in the shop.
]]
Config.DrawText2D = function(x, y, text, scale, options)
  local scale = scale or 0.35
  local font = options.font or 4
  local color = options.color or {r = 255, g = 255, b = 255, a = 255}
  local dropShadow = options.dropShadow or true
  local dropShadowSettings = options.dropShadow or {a = 0, b = 0, c = 0, d = 0, e = 255}
  local outline = options.outline or true
  local center = options.center or true
  local edge = options.edge or {a = 2, b = 0, c = 0, d = 0, e = 150}
  local proportional = options.proportional or 1

  SetTextFont(font)
  SetTextProportional(proportional)
  SetTextScale(scale, scale)
  SetTextColour(color.r, color.g, color.b, color.a)
  if dropShadow then
    SetTextDropShadow()
    SetTextDropshadow(dropShadowSettings.a, dropShadowSettings.b, dropShadowSettings.c, dropShadowSettings.d, dropShadowSettings.e)
  end
  if outline then
    SetTextOutline()
  end
  SetTextEdge(edge.a, edge.b, edge.c, edge.d, edge.e)
  SetTextEntry("STRING")
  AddTextComponentString(text)
  DrawText(x, y)
end

--[[
  Here you can customize the help text that will be displayed when the player
  is near a vehicle in the shop. By default, it will use the BeginTextCommandDisplayHelp native
]]
Config.DrawHelpText = function(text)
  AddTextEntry('KF_VEHICLE_SHOP_HELP', text)
  BeginTextCommandDisplayHelp('KF_VEHICLE_SHOP_HELP')
  EndTextCommandDisplayHelp(0, false, true, -1)
end

--[[
  Confirmation Dialog that will be displayed when the player is about to buy a vehicle.
  By default, it will use the OX_Lib AlertDialog.
  Should return a boolean value.
]]
Config.ConfirmationDialog = function(title, text, options)
  
  local buttonLabels = options.labels or {
    confirm = Lang['confirm'],
    cancel = Lang['cancel'],
  }

  local alertDialog = lib.alertDialog({
    header = title,
    content = text,
    size = 'md',
    centered = true,
    cancel = true,
    labels = {
      confirm = Lang['confirm'],
      cancel = Lang['cancel'],
    }
  })

  if alertDialog == 'confirm' then
    return true
  end
  return false
end

--[[
  Here you can customize the vehicle assignment function after the payment is done.
  By default, it will put the vehicle in the player's owner vehicles.
]]
Config.GiveVehicle = function(src, identifier, vehicle, vehicleHandle)
  local given = MySQL.Sync.execute('INSERT INTO owned_vehicles (owner, plate, vehicle, stored) VALUES (@owner, @plate, @vehicle, @stored)', {
    ['@owner'] = identifier,
    ['@plate'] = vehicle.plate,
    ['@vehicle'] = json.encode(vehicle.properties),
    ['@stored'] = 0,
  })

  if given > 0 then
    return true
  end
  return false
end

--[[
  Here you can customize the player identifier that should be used
  By default, it will use the ESX to get the player identifier.
]]
Config.GetPlayerIdentifier = function(src)
  local ESX = exports['es_extended']:getSharedObject()
  local xPlayer = ESX.GetPlayerFromId(src)
  if xPlayer then
    return xPlayer.getIdentifier()
  end
  return nil
end

--[[
  Player Loaded method used to check if the player is loaded.
  By default, it will use the ESX IsPlayerLoaded method.
]]
Config.PlayerLoaded = function(src)
  local ESX = exports['es_extended']:getSharedObject()
  return ESX.IsPlayerLoaded(src)
end

--[[
  Get Vehicle Properties method used to get the vehicle properties (Client-Side).
  By default, it will use the ESX GetVehicleProperties method.
]]
Config.GetVehicleProperties = function(vehicle)
  local ESX = exports['es_extended']:getSharedObject()
  local vProps = ESX.Game.GetVehicleProperties(vehicle)
  return vProps
end

Config.GeneratePlate = function()
  local plateFormat = 'AAA 000'
  local allowedChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
  local plate = ''

  for i = 1, 3 do
    local random = math.random(1, #allowedChars)
    plate = plate .. allowedChars:sub(random, random)
  end

  plate = plate .. ' '

  for i = 1, 3 do
    local random = math.random(1, #allowedChars)
    plate = plate .. allowedChars:sub(random, random)
  end

  return plate
end

Config.Locales = {
  ['it'] = {
    ['vehicles_catalogue_title'] = 'Catalogo Veicoli',
    ['current_catalogue'] = 'Catalogo Attuale',
    ['previous_catalogue'] = 'Catalogo Precedente',
    ['next_catalogue'] = 'Prossimo Catalogo',
    ['catalogue'] = 'Visualizza catalogo',
    ['price'] = 'Prezzo',
    ['vehicle_seats'] = 'Posti',
    ['press_e_to_buy'] = 'Premi ~g~[E]~w~ per acquistare il veicolo',
    ['press_g_to_testdrive'] = 'Premi ~g~[G]~w~ per provare il veicolo',
    ['press_h_to_try_mods'] = 'Premi ~g~[H]~w~ per provare le modifiche',
    ['test_drive_active'] = 'Stai effettuando un Test Drive',
    ['test_drive_end'] = 'Premi ~input_detonate~ per terminare il test drive',
    ['error_give_vehicle'] = 'Errore durante l\'acquisto del veicolo',
    ['error_not_enough_money'] = 'Non hai abbastanza soldi per acquistare questo veicolo',
    ['confirm'] = 'Conferma',
    ['cancel'] = 'Annulla',
    ['buy_confirmation_title'] = 'Conferma acquisto',
    ['confirm_buy_text'] = 'Sei sicuro di voler acquistare il veicolo per',
    ['confirm_pay_amount'] = 'Conferma, paga',
    ['vehicle_bought_title'] = 'Veicolo Acquistato',
    ['vehicle_bought'] = 'Veicolo acquistato con successo',
  },
  ['en'] = {
    ['vehicles_catalogue_title'] = 'Vehicles Catalogue',
    ['current_catalogue'] = 'Current Catalogue',
    ['previous_catalogue'] = 'Previous Catalogue',
    ['next_catalogue'] = 'Next Catalogue',
    ['catalogue'] = 'View catalogue',
    ['price'] = 'Price',
    ['vehicle_seats'] = 'Seats',
    ['press_e_to_buy'] = 'Press ~g~[E]~w~ to buy the vehicle',
    ['press_g_to_testdrive'] = 'Press ~g~[G]~w~ to test drive the vehicle',
    ['press_h_to_try_mods'] = 'Press ~g~[H]~w~ to try the mods',
    ['test_drive_active'] = 'You are test driving a vehicle',
    ['test_drive_end'] = 'Press ~input_detonate~ to end the test drive',
    ['error_give_vehicle'] = 'Error while giving the vehicle',
    ['error_not_enough_money'] = 'You don\'t have enough money to buy this vehicle',
    ['confirm'] = 'Confirm',
    ['cancel'] = 'Cancel',
    ['buy_confirmation_title'] = 'Buy Confirmation',
    ['confirm_buy_text'] = 'Are you sure you want to buy the vehicle for',
    ['confirm_pay_amount'] = 'Confirm, pay',
    ['vehicle_bought_title'] = 'Vehicle Bought',
    ['vehicle_bought'] = 'Vehicle bought successfully',
  }
}
data/vehicles.lua
-- ############################################### --
-- ## ██╗  ██╗███████╗██████╗ ███████╗██╗   ██╗ ## --
-- ## ██║ ██╔╝██╔════╝██╔══██╗██╔════╝██║   ██║ ## --
-- ## █████╔╝ █████╗  ██║  ██║█████╗  ██║   ██║ ## --
-- ## ██╔═██╗ ██╔══╝  ██║  ██║██╔══╝  ╚██╗ ██╔╝ ## --
-- ## ██║  ██╗██║     ██████╔╝███████╗ ╚████╔╝  ## --
-- ## ╚═╝  ╚═╝╚═╝     ╚═════╝ ╚══════╝  ╚═══╝   ## --
-- ## Developed by KFDev                        ## --
-- ## DOCUMENATION: https://docs.kfdev.it/      ## --
-- ############################################### --

Config.Vehicles = {
  --[[
    You can create the same vehicle with different prices and payment methods.
    Just add a new entry with a different key index (The text between the []).
    The key index must be unique otherwise the vehicle will be overwritten by the last entry.
  ]]

  ['kuruma_1'] = {
    model = 'kuruma',
    label = 'Karin Kuruma',
    price = 50000,
    payMethod = 'money',
    category = 'Sports',
  },

  ['adder_1'] = {
    model = 'adder',
    label = 'Bravado Adder',
    price = 100000,
    payMethod = 'coin',
    category = 'Sports',
  },

  ['bati'] = {
    model = 'bati',
    label = 'Pegassi Bati 801',
    price = 20000,
    payMethod = 'money',
    category = 'Motorcycles',
  },
}

Last updated