diff --git a/README.md b/README.md index 914792b..11739fc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,36 @@ # msk_vehicleItems - Give or Delete Vehicles with Command or Item +Give or Delete Vehicles with Command or Item + +**PLATE is OPTIONAL** + +## Ingame Command Usage ## + +/giveveh +/giveveh +/giveveh +/giveveh + +> Example: /giveveh 1 car zentorno "LS 1234" +> Example: /giveveh 1 boat zentorno "LS 1234" +> Example: /giveveh 1 aircraft zentorno "LS 1234" +> Example: /giveveh 1 helicopter zentorno "LS 1234" + +/delveh + +> Example: /delveh "LS 1234" + +## Console Command Usage ## + +_giveveh +_giveveh +_giveveh +_giveveh + +> Example: _giveveh 1 car zentorno LS 1234 +> Example: _giveveh 1 boat zentorno LS 1234 +> Example: _giveveh 1 aircraft zentorno LS 1234 +> Example: _giveveh 1 helicopter zentorno LS 1234 + +_delveh + +> Example: _delveh LS 1234 \ No newline at end of file diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..9f8e9b6 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.0 \ No newline at end of file diff --git a/client.lua b/client.lua new file mode 100644 index 0000000..d8565ca --- /dev/null +++ b/client.lua @@ -0,0 +1,102 @@ +ESX = nil +if Config.ESX.version:match('1.2') then + Citizen.CreateThread(function() + while ESX == nil do + TriggerEvent(Config.ESX.getSharedObject, function(obj) ESX = obj end) + Citizen.Wait(0) + end + end) +elseif Config.ESX.version:match('legacy') then + ESX = exports["es_extended"]:getSharedObject() +end + +local Charset = {} +for i = 65, 90 do table.insert(Charset, string.char(i)) end +for i = 97, 122 do table.insert(Charset, string.char(i)) end + +RegisterNetEvent('msk_vehicleItems:giveVehicle') +AddEventHandler('msk_vehicleItems:giveVehicle', function(item, veh) + local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + + ESX.Game.SpawnVehicle(veh.model, playerCoords, 0.0, function(vehicle) + if DoesEntityExist(vehicle) then + SetEntityVisible(vehicle, false, false) + SetEntityCollision(vehicle, false) + + local vehicleProps = ESX.Game.GetVehicleProperties(vehicle) + vehicleProps.plate = genPlate() + TriggerServerEvent('msk_vehicleItems:setVehicle', item, vehicleProps, veh.categorie) + ESX.Game.DeleteVehicle(vehicle) + end + end) +end) + +RegisterNetEvent('msk_vehicleItems:giveVehicleCommand') +AddEventHandler('msk_vehicleItems:giveVehicleCommand', function(target, categorie, model, plate, console) + local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + local newPlate + local carExist = false + + if plate then + newPlate = plate + else + newPlate = genPlate() + end + + ESX.Game.SpawnVehicle(model, playerCoords, 0.0, function(vehicle) + if DoesEntityExist(vehicle) then + carExist = true + SetEntityVisible(vehicle, false, false) + SetEntityCollision(vehicle, false) + + local vehicleProps = ESX.Game.GetVehicleProperties(vehicle) + vehicleProps.plate = newPlate + TriggerServerEvent('msk_vehicleItems:setVehicleCommand', target, categorie, model, newPlate, vehicleProps, console) + ESX.Game.DeleteVehicle(vehicle) + debug('Vehicle registered') + end + end) + + Wait(2000) + if not carExist then + Config.Notification(source, 'client', nil, Translation[Config.Locale]['clientCommand'] .. model .. Translation[Config.Locale]['clientCommand2']) + end +end) + +function genPlate() + local plate + if Config.Plate.format:match('XXX XXX') then + plate = string.upper(GetRandomLetter(3)) .. ' ' .. math.random(001, 999) + elseif Config.Plate.format:match('XX XXXX') then + if Config.Plate.enablePrefix then + plate = Config.Plate.prefix .. ' ' .. math.random(0001, 9999) + else + plate = string.upper(GetRandomLetter(2)) .. ' ' .. math.random(0001, 9999) + end + end + + return plate +end + +function GetRandomLetter(length) + Wait(0) + if length > 0 then + return GetRandomLetter(length - 1) .. Charset[math.random(1, #Charset)] + else + return '' + end +end + +function debug(msg, msg2, msg3) + if Config.Debug then + if msg3 then + print(msg, msg2, msg3) + elseif not msg3 and msg2 then + print(msg, msg2) + else + print(msg) + end + end +end \ No newline at end of file diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..92d5a84 --- /dev/null +++ b/config.lua @@ -0,0 +1,52 @@ +Config = {} +---------------------------------------------------------------- +Config.Locale = 'de' +Config.VersionChecker = false +Config.Debug = true + +Config.ESX = { + version = 'legacy', -- Set '1.2' or 'legacy' + getSharedObject = 'esx:getSharedObject' -- Only needed if version set to '1.2' +} +---------------------------------------------------------------- +-- !!! This function is clientside AND serverside !!! +-- Look for type == 'client' and type == 'server' +Config.Notification = function(src, type, xPlayer, message) -- xPlayer = ESX.GetPlayerFromId(src) + if type == 'client' then -- clientside + ESX.ShowNotification(message) -- replace this with your Notify + elseif type == 'server' then -- serverside + xPlayer.showNotification(message) -- replace this with your Notify + end +end +---------------------------------------------------------------- +Config.MySQL = { + type = 'type', -- Type Column + stored = 'stored', -- Stored Column +} + +Config.AdminGroups = {'superadmin', 'admin'} -- You can set multiple groups +-- Ingame Commands +Config.Command = 'giveveh' -- Read the Readme.md for Command Usage +Config.Command2 = 'delveh' -- Read the Readme.md for Command Usage +-- Console Commands +Config.ConsoleCommand = '_giveveh' -- Read the Readme.md for Command Usage +Config.ConsoleCommand2 = '_delveh' -- Read the Readme.md for Command Usage + +Config.Plate = { + format = 'XXX XXX', -- 'XXX XXX' or 'XX XXXX' + + enablePrefix = true, -- Set to false if you want Random Letters + prefix = 'PX' -- Only if format = 'XX XXXX' // Looks like 'PX 1234' +} +---------------------------------------------------------------- +-- You can give Player an Item and they can use the Item to get a Vehicle +Config.Vehicles = { + ["zentorno"] = { -- Item Name + model = 'zentorno', -- Vehicle Name + categorie = 'car' -- Vehicle Categorie + }, + ["seashark"] = { -- Item Name + model = 'seashark', -- Vehicle Name + categorie = 'boat' -- Vehicle Categorie + }, +} \ No newline at end of file diff --git a/fxmanifest.lua b/fxmanifest.lua new file mode 100644 index 0000000..99b697c --- /dev/null +++ b/fxmanifest.lua @@ -0,0 +1,27 @@ +fx_version 'adamant' +games { 'gta5' } + +author 'Musiker15 - MSK Scripts' +name 'msk_vehicleItems' +description 'Give or Delete Vehicles with Command or Item' +version '1.0' + +lua54 'yes' + +escrow_ignore { + 'config.lua', +} + +shared_scripts { + 'config.lua', + 'translation.lua' +} + +client_scripts { + 'client.lua', +} + +server_scripts { + '@mysql-async/lib/MySQL.lua', + 'server.lua' +} \ No newline at end of file diff --git a/server.lua b/server.lua new file mode 100644 index 0000000..94e2d7b --- /dev/null +++ b/server.lua @@ -0,0 +1,194 @@ +ESX = nil +if Config.ESX.version:match('1.2') then + TriggerEvent(Config.ESX.getSharedObject, function(obj) ESX = obj end) +elseif Config.ESX.version:match('legacy') then + ESX = exports["es_extended"]:getSharedObject() +end + +for k, veh in pairs(Config.Vehicles) do + ESX.RegisterUsableItem(k, function(source) + local xPlayer = ESX.GetPlayerFromId(source) + + xPlayer.triggerEvent('msk_vehicleItems:giveVehicle', k, veh) + end) +end + +RegisterServerEvent('msk_vehicleItems:setVehicle') +AddEventHandler('msk_vehicleItems:setVehicle', function(item, props, vehicleType) + local src = source + local xPlayer = ESX.GetPlayerFromId(src) + local data = MySQL.Sync.fetchAll('SELECT * FROM owned_vehicles WHERE plate = @plate', { + ["@plate"] = props.plate + }) + + if data[1] then + Config.Notification(src, 'server', xPlayer, Translation[Config.Locale]['item_already_exist']) -- Plate already exist + else + MySQL.Async.execute('INSERT INTO owned_vehicles (owner, plate, vehicle, stored, type) VALUES (@owner, @plate, @vehicle, @stored, @type)', { + ['@owner'] = xPlayer.identifier, + ['@plate'] = props.plate, + ['@vehicle'] = json.encode(props), + ['@stored'] = 1, + ['type'] = vehicleType + }) + + xPlayer.removeInventoryItem(item, 1) + Config.Notification(src, 'server', xPlayer, Translation[Config.Locale]['item_success']) + end +end) + +-- Ingame Commands +ESX.RegisterCommand(Config.Command, Config.AdminGroups, function(xPlayer, args, showError) + xPlayer.triggerEvent('msk_vehicleItems:giveVehicleCommand', args.player, args.type, args.vehicle, args.plate) + end, false, {help = 'Give someone a Vehicle', arguments = { + {name = 'player', help = 'PlayerID', type = 'player'}, + {name = 'type', help = 'Categorie', type = 'string'}, + {name = 'vehicle', help = 'Vehiclename', type = 'string'}, + {name = 'plate', help = '"Plate" (optional)', type = 'string'} +}}) + +ESX.RegisterCommand(Config.Command2, Config.AdminGroups, function(xPlayer, args, showError) + if args.plate then + MySQL.Async.execute('DELETE FROM owned_vehicles WHERE plate = @plate', { + ['@plate'] = args.plate + }, function(result) + if result == 1 then + debug('Deleted', args.plate) + Config.Notification(src, 'server', xPlayer, Translation[Config.Locale]['deleted'] .. args.plate .. Translation[Config.Locale]['deleted2']) + else + debug('Error while deleting', args.plate) + Config.Notification(src, 'server', xPlayer, Translation[Config.Locale]['delete_failed'] .. args.plate .. Translation[Config.Locale]['delete_failed2']) + end + end) + end + end, false, {help = 'Delete a Vehicle from Database', arguments = { + {name = 'plate', help = '"Plate"', type = 'string'} +}}) + +-- Console Commands +RegisterCommand(Config.ConsoleCommand, function(source, args, rawCommand) + if (source == 0) then + local playerID = args[1] + + if args[1] and args[2] and args[3] and args[4] then + local plate = args[4] + + if #args > 4 then + for i=5, #args do + plate = plate.." "..args[i] + end + end + plate = string.upper(plate) + + TriggerClientEvent('msk_vehicleItems:giveVehicleCommand', playerID, playerID, args[2], args[3], plate, true) + elseif args[1] and args[2] and args[3] then + TriggerClientEvent('msk_vehicleItems:giveVehicleCommand', playerID, playerID, args[2], args[3], nil, true) + else + print('^1SYNTAX ERROR: ^5_giveveh ^0| Plate is optional') + end + end +end) + +RegisterCommand(Config.ConsoleCommand2, function(source, args, rawCommand) + if (source == 0) then + if args[1] then + local plate = args[1] + + if #args > 1 then + for i=2, #args do + plate = plate.." "..args[i] + end + end + plate = string.upper(plate) + + MySQL.Async.execute('DELETE FROM owned_vehicles WHERE plate = @plate', { + ['@plate'] = plate + }, function(result) + if result == 1 then + debug('Deleted', plate) + else + debug('Error while deleting', plate) + end + end) + else + print('^1SYNTAX ERROR: ^5_delveh ') + end + end +end) + +RegisterServerEvent('msk_vehicleItems:setVehicleCommand') +AddEventHandler('msk_vehicleItems:setVehicleCommand', function(xTarget, categorie, model, plate, props, console) + local src = source + local xPlayer = ESX.GetPlayerFromId(src) + local data = MySQL.Sync.fetchAll('SELECT * FROM owned_vehicles WHERE plate = @plate', { + ["@plate"] = plate + }) + if console then + xTarget = ESX.GetPlayerFromId(xTarget) + end + + if data[1] then + debug(Translation[Config.Locale]['vehicle_already_exist'] .. plate .. Translation[Config.Locale]['vehicle_already_exist2']) + if xPlayer and not console then + Config.Notification(src, 'server', xPlayer, Translation[Config.Locale]['vehicle_already_exist'] .. plate .. Translation[Config.Locale]['vehicle_already_exist2']) + end + else + MySQL.Async.execute('INSERT INTO owned_vehicles (owner, plate, vehicle, stored, type) VALUES (@owner, @plate, @vehicle, @stored, @type)', { + ['@owner'] = xTarget.identifier, + ['@plate'] = plate, + ['@vehicle'] = json.encode(props), + ['@stored'] = 1, + ['type'] = categorie + }) + + debug(Translation[Config.Locale]['vehicle_successfully_added'] .. model .. Translation[Config.Locale]['vehicle_successfully_added2'] .. plate .. Translation[Config.Locale]['vehicle_successfully_added2'] .. xTarget.source .. Translation[Config.Locale]['vehicle_successfully_added2']) + if xPlayer and not console then + Config.Notification(src, 'server', xPlayer, Translation[Config.Locale]['vehicle_successfully_added'] .. model .. Translation[Config.Locale]['vehicle_successfully_added2'] .. plate .. Translation[Config.Locale]['vehicle_successfully_added2'] .. xTarget.source .. Translation[Config.Locale]['vehicle_successfully_added2']) + + if xPlayer.source == xTarget.source then + Config.Notification(src, 'server', xPlayer, Translation[Config.Locale]['got_vehicle'] .. model .. Translation[Config.Locale]['got_vehicle2'] .. plate .. Translation[Config.Locale]['got_vehicle3']) + end + end + + if xPlayer and console then + Config.Notification(src, 'server', xPlayer, Translation[Config.Locale]['got_vehicle'] .. model .. Translation[Config.Locale]['got_vehicle2'] .. plate .. Translation[Config.Locale]['got_vehicle3']) + end + end +end) + +function debug(msg, msg2, msg3) + if Config.Debug then + if msg3 then + print(msg, msg2, msg3) + elseif not msg3 and msg2 then + print(msg, msg2) + else + print(msg) + end + end +end + +---- GitHub Updater ---- +function GetCurrentVersion() + return GetResourceMetadata(GetCurrentResourceName(), "version") +end + +local CurrentVersion = GetCurrentVersion() +local resourceName = "^4["..GetCurrentResourceName().."]^0" + +if Config.VersionChecker then + PerformHttpRequest('https://raw.githubusercontent.com/Musiker15/msk_vehicleItems/main/VERSION', function(Error, NewestVersion, Header) + print("###############################") + if CurrentVersion == NewestVersion then + print(resourceName .. '^2 ✓ Resource is Up to Date^0 - ^5Current Version: ^2' .. CurrentVersion .. '^0') + elseif CurrentVersion ~= NewestVersion then + print(resourceName .. '^1 ✗ Resource Outdated. Please Update!^0 - ^5Current Version: ^1' .. CurrentVersion .. '^0') + print('^5Newest Version: ^2' .. NewestVersion .. '^0 - ^6Download here: ^9https://github.com/Musiker15/msk_vehicleItems/releases/tag/v'.. NewestVersion .. '^0') + end + print("###############################") + end) +else + print("###############################") + print(resourceName .. '^2 ✓ Resource loaded^0') + print("###############################") +end \ No newline at end of file diff --git a/translation.lua b/translation.lua new file mode 100644 index 0000000..8e80cd4 --- /dev/null +++ b/translation.lua @@ -0,0 +1,52 @@ +Translation = {} +---------------------------------------------------------------- +Translation = { + ['de'] = { + ['clientCommand'] = 'Das Fahrzeug ~y~', -- client.lua + ['clientCommand2'] = '~s~ existiert nicht', -- client.lua + + ['item_already_exist'] = 'Dein Fahrzeug konnte nicht zugestellt werden.', + ['item_success'] = 'Dein Fahrzeug wurde zu einer Garage geliefert.', + + ['deleted'] = 'Das Fahrzeug mit dem Kennzeichen ~y~', + ['deleted2'] = '~s~ wurde gelöscht', + ['delete_failed'] = 'Das Fahrzeug mit dem Kennzeichen ~y~', + ['delete_failed2'] = '~s~ konnte nicht gelöscht werden.', + + ['vehicle_already_exist'] = 'Das Fahrzeug mit dem Kennzeichen ~y~', + ['vehicle_already_exist2'] = '~s~ existiert bereits.', + + ['vehicle_successfully_added'] = 'Das Fahrzeug ~y~', + ['vehicle_successfully_added2'] = '~s~ mit dem Kennzeichen ~y~', + ['vehicle_successfully_added3'] = '~s~ wurde an ID ~y~', + ['vehicle_successfully_added4'] = '~s~ geliefert.', + + ['got_vehicle'] = 'Du hast das Fahrzeug ~y~', + ['got_vehicle2'] = '~s~ mit dem Kennezichen ~y~', + ['got_vehicle3'] = '~s~ erhalten.', + }, + ['en'] = { + ['clientCommand'] = 'The vehicle ~y~', -- client.lua + ['clientCommand2'] = '~s~ does not exist.', -- client.lua + + ['item_already_exist'] = 'Your vehicle could not be delivered.', + ['item_success'] = 'Your vehicle has been delivered to a garage.', + + ['deleted'] = 'The vehicle with the license plate ~y~', + ['deleted2'] = '~s~ was deleted.', + ['delete_failed'] = 'The vehicle with the license plate ~y~', + ['delete_failed2'] = '~s~ could not be deleted.', + + ['vehicle_already_exist'] = 'The vehicle with the license plate ~y~', + ['vehicle_already_exist2'] = '~s~ does already exist.', + + ['vehicle_successfully_added'] = 'the vehicle ~y~', + ['vehicle_successfully_added2'] = '~s~ with the license plate ~y~', + ['vehicle_successfully_added3'] = '~s~ was delivered to ID ~y~', + ['vehicle_successfully_added4'] = '~s~.', + + ['got_vehicle'] = 'You received the vehicle ~y~', + ['got_vehicle2'] = '~s~ with the license plate ~y~', + ['got_vehicle3'] = '~s~.', + }, +} \ No newline at end of file