[ESX][SNIPPET] Craft license plates in Cardealer job

Ok, first and foremost. I did NOT write any code here. I only used existing code from esx_mechanic to add crafting to the esx_vehicleshop Cardealer job.

Second, I will NOT help you edit your code. I’m way too busy IRL. If you don’t know how to edit code, DON’T DO IT!!

Third, for those of you that can edit, but maybe you’re still a bit new. DO NOT CLOSE YOUR FILES UNTIL YOU TEST. Just in case something doesn’t work for whatever reason, you will still be able to undo your edits. ALWAYS BACK UP YOUR RESOURCES BEFORE EDITING THEM!

The background for this is when I ran my server, CIVs were allowed to own businesses, including custom vehicle shops. I gave them the ability to craft license plates that can be used on purchased vehicles. This gave them a unique reason for other players to come to them rather than going to the public vehicle shop. I also made it so that the only way to get a custom plate was to purchase them from the car dealers.

This also creates a new item that you get when mining. Steel, which is needed to craft plates. The only place a miner could sell steel was to a car dealer and the only way a car dealer could get steel was to either go mining or buy it from other miners.

Ok, on to the instructions…
(also available here - https://github.com/Chip-W/esx_vehicleshop_craft_snippet)

LICENSE FOR USE

  • You may use this snippet and edit to your liking. Please PR any improvements.
  • I will not help to install or install this for you. If you don’t know how to edit code, DON’T.
  • I will delete any issues that do not show errors as I can not help without knowing what they are.

esx_vehicleshop_craft_snippet

  • Craft License Plates With Cardealer Job.
  • Requires two steel items to craft one licensplate item.
  • In some parts, it’s easier to replace an entire section than it is to just try and find the small area to change. Smart people will just be able to add in the proper code.

KNOWN BUGS

  • Marker is invisible until after a relog or when you start crafting. However, when invisible, the marker still works.
  • No other known bugs.

IMPORTANT NOTE

For this snippet to work properly, you will need three resources installed first.
THESE ARE REQUIRED!!

ESX_JOBS

Navigate to client/jobs/

MINER.LUA

Find:

	{
          name   = _U('m_diamond'),
          db_name= "diamond",
          max    = 50,
          add    = 1,
          drop   = 5
	}

Add a comma behind the } then press enter and paste:

        {
          name   = _U('m_steel'),
          db_name= "steel",
          max    = 30,
          add    = 1,
          drop   = 4
        }

I have steel set as more rare than diamonds, rarity is up to you

ESX_VEHICLESHOP

CONFIG.LUA

Find:

ResellVehicle = {
		Pos   = { x = -44.630, y = -1080.738, z = 25.683 },
		Size  = { x = 3.0, y = 3.0, z = 1.0 },
		Type  = 1,
}

Put a comma after the } press enter and paste this:

Craft = {
		Pos   = { x = -39.80, y = -1088.24, z = 25.50 },
		Size  = { x = 1.5, y = 1.5, z = 1.0 },
		Type  = 1,
}

These are default coords for esx_vehicleshop.

SERVER/MAIN.LUA

Find:

function PayRent(d, h, m)
	MySQL.Async.fetchAll('SELECT * FROM rented_vehicles', {}, function (result)
		for i=1, #result, 1 do
			local xPlayer = ESX.GetPlayerFromIdentifier(result[i].owner)

			-- message player if connected
			if xPlayer ~= nil then
				xPlayer.removeAccountMoney('bank', result[i].rent_price)
				TriggerClientEvent('esx:showNotification', xPlayer.source, _U('paid_rental', ESX.Math.GroupDigits(result[i].rent_price)))
			else -- pay rent either way
				MySQL.Sync.execute('UPDATE users SET bank = bank - @bank WHERE identifier = @identifier',
				{
					['@bank']       = result[i].rent_price,
					['@identifier'] = result[i].owner
				})
			end

			TriggerEvent('esx_addonaccount:getSharedAccount', 'society_cardealer', function(account)
				account.addMoney(result[i].rent_price)
			end)
		end
	end)
end

After, paste:

local function Craft(source)
	SetTimeout(4000, function()

		if PlayersCrafting[source] == true then
			local xPlayer = ESX.GetPlayerFromId(source)
			local SteelQuantity = xPlayer.getInventoryItem('steel').count

			if SteelQuantity <= 0 then
				TriggerClientEvent('esx:showNotification', source, _U('not_enough_steel'))
			else
				xPlayer.removeInventoryItem('steel', 2)
				xPlayer.addInventoryItem('licenseplate', 1)
				Craft(source)
			end
		end

	end)
end

RegisterServerEvent('esx_vehicleshop:startCraft')
AddEventHandler('esx_sidealership:startCraft', function()
	local _source = source
	PlayersCrafting[_source] = true
	TriggerClientEvent('esx:showNotification', _source, _U('assembling_license_plate'))
	Craft(_source)
end)

RegisterServerEvent('esx_vehicleshop:stopCraft')
AddEventHandler('esx_sidealership:stopCraft', function()
	local _source = source
	PlayersCrafting[_source] = false
end)

CLIENT/MAIN.LUA

find:

Citizen.CreateThread(function ()
	while ESX == nil do
		TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
		Citizen.Wait(0)
	end

	Citizen.Wait(10000)

	ESX.TriggerServerCallback('esx_vehicleshop:getCategories', function (categories)
		Categories = categories
	end)

	ESX.TriggerServerCallback('esx_vehicleshop:getVehicles', function (vehicles)
		Vehicles = vehicles
	end)

	if Config.EnablePlayerManagement then
		if ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.ShopEntering.Type = 1

			if ESX.PlayerData.job.grade_name == 'boss' then
				Config.Zones.BossActions.Type = 1
			end

		else
			Config.Zones.ShopEntering.Type = -1
			Config.Zones.BossActions.Type  = -1
		end
	end
end)

RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer)
	ESX.PlayerData = xPlayer

	if Config.EnablePlayerManagement then
		if ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.ShopEntering.Type = 1

			if ESX.PlayerData.job.grade_name == 'boss' then
				Config.Zones.BossActions.Type = 1
			end

		else
			Config.Zones.ShopEntering.Type = -1
			Config.Zones.BossActions.Type  = -1
		end
	end
end)

Replace with:

Citizen.CreateThread(function ()
	while ESX == nil do
		TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
		Citizen.Wait(0)
	end

	Citizen.Wait(10000)

	ESX.TriggerServerCallback('esx_vehicleshop:getCategories', function (categories)
		Categories = categories
	end)

	ESX.TriggerServerCallback('esx_vehicleshop:getVehicles', function (vehicles)
		Vehicles = vehicles
	end)

	if Config.EnablePlayerManagement then
		if ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.ShopEntering.Type = 1

			if ESX.PlayerData.job.grade_name == 'boss' then
				Config.Zones.BossActions.Type = 1
			end

		elseif ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.Craft.Type = 1

		else
			Config.Zones.ShopEntering.Type = -1
			Config.Zones.Craft.Type 	   = -1
			Config.Zones.BossActions.Type  = -1
		end
	end
end)

RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer)
	ESX.PlayerData = xPlayer

	if Config.EnablePlayerManagement then
		if ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.ShopEntering.Type = 1

			if ESX.PlayerData.job.grade_name == 'boss' then
				Config.Zones.BossActions.Type = 1
			end

		elseif ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.Craft.Type = 1

		else
			Config.Zones.ShopEntering.Type = -1
			Config.Zones.Craft.Type 	   = -1
			Config.Zones.BossActions.Type  = -1
		end
	end
end)

Find:

function OpenPutStocksMenu()
	ESX.TriggerServerCallback('esx_vehicleshop:getPlayerInventory', function (inventory)
		local elements = {}

		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,
					type = 'item_standard',
					value = item.name
				})
			end
		end

		ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'stocks_menu',
		{
			title    = _U('inventory'),
			align    = 'top-left',
			elements = elements
		}, function (data, menu)
			local itemName = data.current.value

			ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_put_item_count', {
				title = _U('amount')
			}, function (data2, menu2)
				local count = tonumber(data2.value)

				if count == nil then
					ESX.ShowNotification(_U('quantity_invalid'))
				else
					TriggerServerEvent('esx_vehicleshop:putStockItems', itemName, count)
					menu2.close()
					menu.close()
					OpenPutStocksMenu()
				end

			end, function (data2, menu2)
				menu2.close()
			end)

		end, function (data, menu)
			menu.close()
		end)
	end)
end

Below, paste:

function OpenLicensePlateCraftMenu()
	if Config.EnablePlayerManagement then
		if ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.Craft.Type = 1
		else
			Config.Zones.Craft.Type = -1
		end
		
		local elements = {
			{label = _U('licenseplate'),  value = 'license_plate'}
		}

		ESX.UI.Menu.CloseAll()

		ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'license_plate_craft', {
			title    = _U('craft'),
			align    = 'top-left',
			elements = elements
		}, function(data, menu)
			if data.current.value == 'license_plate' then
				menu.close()
				TriggerServerEvent('esx_vehicleshop:startCraft')
			end

		end, function(data, menu)
			menu.close()

			CurrentAction     = 'license_plate_menu'
			CurrentActionMsg  = _U('craft_menu')
			CurrentActionData = {}
		end)

	else
		ESX.ShowNotification(_U('not_experienced_enough'))
	end
end

Find:

RegisterNetEvent('esx:setJob')
AddEventHandler('esx:setJob', function (job)
	ESX.PlayerData.job = job

	if Config.EnablePlayerManagement then
		if ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.ShopEntering.Type = 1

			if ESX.PlayerData.job.grade_name == 'boss' then
				Config.Zones.BossActions.Type = 1
			end

		else
			Config.Zones.ShopEntering.Type = -1
			Config.Zones.BossActions.Type  = -1
		end
	end
end)

Replace with:

RegisterNetEvent('esx:setJob')
AddEventHandler('esx:setJob', function (job)
	ESX.PlayerData.job = job

	if Config.EnablePlayerManagement then
		if ESX.PlayerData.job.name == 'cardealer' then
			Config.Zones.ShopEntering.Type = 1

			if ESX.PlayerData.job.grade_name == 'boss' then
				Config.Zones.BossActions.Type = 1
			end
		elseif ESX.PlayerData.job.name == 'cardealer' then
			   Config.Zones.Craft.Type = 1
		else
			Config.Zones.ShopEntering.Type = -1
			Config.Zones.Craft.Type 	   = -1
			Config.Zones.BossActions.Type  = -1
		end
	end
end)

Find:

	elseif zone == 'BossActions' and Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.name == 'cardealer' and ESX.PlayerData.job.grade_name == 'boss' then

		CurrentAction     = 'boss_actions_menu'
		CurrentActionMsg  = _U('shop_menu')
		CurrentActionData = {}

	end

Above, paste:

	elseif zone == 'Craft' and Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.name == 'cardealer' then
		CurrentAction     = 'license_plate_craft_menu'
		CurrentActionMsg  = _U('craft_menu')
		CurrentActionData = {}

Find:

AddEventHandler('esx_vehicleshop:hasExitedMarker', function (zone)
	if not IsInShopMenu then
		ESX.UI.Menu.CloseAll()
	end

	CurrentAction = nil
end)

Replace with:

AddEventHandler('esx_vehicleshop:hasExitedMarker', function (zone)
	if not IsInShopMenu then
		ESX.UI.Menu.CloseAll()
	-- Craft License Plate
	elseif zone == 'Craft' then
		TriggerServerEvent('esx_vehicleshop:stopCraft')
	end

	CurrentAction = nil
end)

Find:

Citizen.CreateThread(function()
	while true do
		Citizen.Wait(10)

		if CurrentAction == nil then
			Citizen.Wait(500)
		else

			ESX.ShowHelpNotification(CurrentActionMsg)

			if IsControlJustReleased(0, Keys['E']) then
				if CurrentAction == 'shop_menu' then
					OpenShopMenu()
				elseif CurrentAction == 'reseller_menu' then
					OpenResellerMenu()
				elseif CurrentAction == 'give_back_vehicle' then

					ESX.TriggerServerCallback('esx_vehicleshop:giveBackVehicle', function(isRentedVehicle)
						if isRentedVehicle then
							ESX.Game.DeleteVehicle(CurrentActionData.vehicle)
							ESX.ShowNotification(_U('delivered'))
						else
							ESX.ShowNotification(_U('not_rental'))
						end
					end, ESX.Math.Trim(GetVehicleNumberPlateText(CurrentActionData.vehicle)))

				elseif CurrentAction == 'resell_vehicle' then

					ESX.TriggerServerCallback('esx_vehicleshop:resellVehicle', function(vehicleSold)

						if vehicleSold then
							ESX.Game.DeleteVehicle(CurrentActionData.vehicle)
							ESX.ShowNotification(_U('vehicle_sold_for', CurrentActionData.label, ESX.Math.GroupDigits(CurrentActionData.price)))
						else
							ESX.ShowNotification(_U('not_yours'))
						end

					end, CurrentActionData.plate, CurrentActionData.model)

				elseif CurrentAction == 'boss_actions_menu' then
					OpenBossActionsMenu()
				end

				CurrentAction = nil
			end
		end
	end
end)

Replace with:

Citizen.CreateThread(function()
	while true do
		Citizen.Wait(10)

		if CurrentAction == nil then
			Citizen.Wait(500)
		else

			ESX.ShowHelpNotification(CurrentActionMsg)

			if IsControlJustReleased(0, Keys['E']) then
				if CurrentAction == 'shop_menu' then
					OpenShopMenu()
				elseif CurrentAction == 'reseller_menu' then
					OpenResellerMenu()
				elseif CurrentAction == 'give_back_vehicle' then

					ESX.TriggerServerCallback('esx_vehicleshop:giveBackVehicle', function(isRentedVehicle)
						if isRentedVehicle then
							ESX.Game.DeleteVehicle(CurrentActionData.vehicle)
							ESX.ShowNotification(_U('delivered'))
						else
							ESX.ShowNotification(_U('not_rental'))
						end
					end, ESX.Math.Trim(GetVehicleNumberPlateText(CurrentActionData.vehicle)))

				elseif CurrentAction == 'resell_vehicle' then

					ESX.TriggerServerCallback('esx_vehicleshop:resellVehicle', function(vehicleSold)

						if vehicleSold then
							ESX.Game.DeleteVehicle(CurrentActionData.vehicle)
							ESX.ShowNotification(_U('vehicle_sold_for', CurrentActionData.label, ESX.Math.GroupDigits(CurrentActionData.price)))
						else
							ESX.ShowNotification(_U('not_yours'))
						end

					end, CurrentActionData.plate, CurrentActionData.model)

				elseif CurrentAction == 'boss_actions_menu' then
					OpenBossActionsMenu()

				elseif CurrentAction == 'license_plate_craft_menu' then
					OpenLicensePlateCraftMenu()
				end

				CurrentAction = nil
			end
		end
	end
end)

LOCALES/EN.LUA

If using another language, you will need to translate and add to your language file

Find:

  ['customer_date']           = 'date',

Below, add:

  ['assembling_license_plate']  = 'assembling License Plate',
  ['not_enough_steel']        = 'you don\'t have enough steel',
  ['craft_menu']              = 'press ~INPUT_CONTEXT~ to craft license plates.',
  ['licenseplate']            = 'license Plate',
  ['craft']                   = 'craft License Plate',

DONE

6 Likes

I tried adding this, when clicking “craft plate” nothing happends. its like its not triggering.