local HasAlreadyEnteredMarker, OnJob, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, CurrentActionData = false, false, false, false, false, {} local CurrentCustomer, CurrentCustomerBlip, DestinationBlip, targetCoords, LastZone, CurrentAction, CurrentActionMsg, lastSelectedNPC RegisterNetEvent('esx:playerLoaded') AddEventHandler('esx:playerLoaded', function(xPlayer) ESX.PlayerData = xPlayer ESX.PlayerLoaded = true end) RegisterNetEvent('esx:onPlayerLogout') AddEventHandler('esx:onPlayerLogout', function() ESX.PlayerLoaded = false ESX.PlayerData = {} end) RegisterNetEvent('esx:setJob') AddEventHandler('esx:setJob', function(job) ESX.PlayerData.job = job end) function DrawSub(msg, time) ClearPrints() BeginTextCommandPrint('STRING') AddTextComponentSubstringPlayerName(msg) EndTextCommandPrint(time, 1) end function ShowLoadingPromt(msg, time, type) CreateThread(function() Wait(0) BeginTextCommandBusyspinnerOn('STRING') AddTextComponentSubstringPlayerName(msg) EndTextCommandBusyspinnerOn(type) Wait(time) BusyspinnerOff() end) end function GetRandomWalkingNPC() local search = {} local peds = GetGamePool("CPed") for i = 1, #peds, 1 do if IsPedHuman(peds[i]) and IsPedWalking(peds[i]) and not IsPedAPlayer(peds[i]) then if peds[i] ~= lastSelectedNPC then search[#search+1] = peds[i] end end end if #search > 0 then local selectedNPC = search[math.random(#search)] lastSelectedNPC = selectedNPC return selectedNPC else return nil end end function ClearCurrentMission() if DoesBlipExist(CurrentCustomerBlip) then RemoveBlip(CurrentCustomerBlip) end if DoesBlipExist(DestinationBlip) then RemoveBlip(DestinationBlip) end CurrentCustomer = nil CurrentCustomerBlip = nil DestinationBlip = nil IsNearCustomer = false CustomerIsEnteringVehicle = false CustomerEnteredVehicle = false targetCoords = nil end function StartTaxiJob() ShowLoadingPromt(TranslateCap('taking_service'), 5000, 3) ClearCurrentMission() OnJob = true end function StopTaxiJob() local playerPed = PlayerPedId() if IsPedInAnyVehicle(playerPed, false) and CurrentCustomer ~= nil then local vehicle = GetVehiclePedIsIn(playerPed, false) TaskLeaveVehicle(CurrentCustomer, vehicle, 0) if CustomerEnteredVehicle then TaskGoStraightToCoord(CurrentCustomer, targetCoords.x, targetCoords.y, targetCoords.z, 1.0, -1, 0.0, 0.0) end end ClearCurrentMission() OnJob = false DrawSub(TranslateCap('mission_complete'), 5000) end function OpenCloakroom() local elements = { {unselectable = true, icon = "fas fa-shirt", title = TranslateCap('cloakroom_menu')}, {icon = "fas fa-shirt", title = TranslateCap('wear_citizen'), value = "wear_citizen"}, {icon = "fas fa-shirt", title = TranslateCap('wear_work'), value = "wear_work"}, } ESX.OpenContext("right", elements, function(menu,element) if element.value == "wear_citizen" then ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) TriggerEvent('skinchanger:loadSkin', skin) end) elseif element.value == "wear_work" then ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) if skin.sex == 0 then TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_male) else TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_female) end end) end end, function(menu) CurrentAction = 'cloakroom' CurrentActionMsg = TranslateCap('cloakroom_prompt') CurrentActionData = {} end) end function OpenVehicleSpawnerMenu() local elements = { {unselectable = true, icon = "fas fa-car", title = TranslateCap('spawn_veh')} } if Config.EnableSocietyOwnedVehicles then ESX.TriggerServerCallback('esx_society:getVehiclesInGarage', function(vehicles) for i = 1, #vehicles, 1 do elements[#elements+1] = { icon = "fas fa-car", title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. ' [' .. vehicles[i].plate .. ']', value = vehicles[i] } end ESX.OpenContext("right", elements, function(menu,element) if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then ESX.ShowNotification(TranslateCap('spawnpoint_blocked')) return end local vehicleProps = element.value ESX.TriggerServerCallback("esx_taxijob:SpawnVehicle", function() return end, vehicleProps.model, vehicleProps) TriggerServerEvent('esx_society:removeVehicleFromGarage', 'taxi', vehicleProps) ESX.CloseContext() end, function(menu) CurrentAction = 'vehicle_spawner' CurrentActionMsg = TranslateCap('spawner_prompt') CurrentActionData = {} end) end, 'taxi') else -- not society vehicles if #Config.AuthorizedVehicles == 0 then ESX.ShowNotification(TranslateCap('empty_authorized_vehicles_table'), "error") return end ESX.OpenContext("right", Config.AuthorizedVehicles, function(menu,element) if not element.model or string.len(element.model) == 0 then ESX.ShowNotification(TranslateCap('unknow_model'), "error") return end if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then ESX.ShowNotification(TranslateCap('spawnpoint_blocked')) return end ESX.TriggerServerCallback("esx_taxijob:SpawnVehicle", function() ESX.ShowNotification(TranslateCap('vehicle_spawned', element.title), "success") end, element.model, {plate = "TAXI JOB"}) ESX.CloseContext() end, function(menu) CurrentAction = 'vehicle_spawner' CurrentActionMsg = TranslateCap('spawner_prompt') CurrentActionData = {} end) end end function DeleteJobVehicle() local playerPed = PlayerPedId() if Config.EnableSocietyOwnedVehicles then local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) TriggerServerEvent('esx_society:putVehicleInGarage', 'taxi', vehicleProps) ESX.Game.DeleteVehicle(CurrentActionData.vehicle) else if IsInAuthorizedVehicle() then ESX.Game.DeleteVehicle(CurrentActionData.vehicle) if Config.MaxInService ~= -1 then TriggerServerEvent('esx_service:disableService', 'taxi') end else ESX.ShowNotification(TranslateCap('only_taxi')) end end end function OpenTaxiActionsMenu() local elements = { {unselectable = true, icon = "fas fa-taxi", title = TranslateCap('taxi')}, {icon = "fas fa-box",title = TranslateCap('deposit_stock'),value = 'put_stock'}, {icon = "fas fa-box", title = TranslateCap('take_stock'), value = 'get_stock'} } if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == 'boss' then elements[#elements+1] = { icon = "fas fa-wallet", title = TranslateCap('boss_actions'), value = "boss_actions" } end ESX.OpenContext("right", elements, function(menu,element) if Config.OxInventory and (element.value == 'put_stock' or element.value == 'get_stock') then exports.ox_inventory:openInventory('stash', 'society_taxi') return ESX.CloseContext() elseif element.value == 'put_stock' then OpenPutStocksMenu() elseif element.value == 'get_stock' then OpenGetStocksMenu() elseif element.value == 'boss_actions' then TriggerEvent('esx_society:openBossMenu', 'taxi', function(data, menu) menu.close() end) end end, function(menu) CurrentAction = 'taxi_actions_menu' CurrentActionMsg = TranslateCap('press_to_open') CurrentActionData = {} end) end function OpenMobileTaxiActionsMenu() local elements = { {unselectable = true, icon = "fas fa-taxi", title = TranslateCap('taxi')}, {icon = "fas fa-scroll", title = TranslateCap('billing'), value = "billing"}, {icon = "fas fa-taxi", title = TranslateCap('start_job'), value = "start_job"}, } ESX.OpenContext("right", elements, function(menu,element) if element.value == "billing" then local elements2 = { {unselectable = true, icon = "fas fa-taxi", title = element.title}, {title = TranslateCap('amount'), input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = TranslateCap('bill_amount')}, {icon = "fas fa-check-double", title = TranslateCap('confirm'), value = "confirm"} } ESX.OpenContext("right", elements2, function(menu2,element2) local amount = tonumber(menu2.eles[2].inputValue) if amount == nil then ESX.ShowNotification(TranslateCap('amount_invalid')) else ESX.CloseContext() local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() if closestPlayer == -1 or closestDistance > 3.0 then ESX.ShowNotification(TranslateCap('no_players_near')) else TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_taxi', 'Taxi', amount) ESX.ShowNotification(TranslateCap('billing_sent')) end end end) elseif element.value == "start_job" then if OnJob then ESX.CloseContext() StopTaxiJob() else if ESX.PlayerData.job ~= nil and ESX.PlayerData.job.name == 'taxi' then local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then if tonumber(ESX.PlayerData.job.grade) >= 3 then ESX.CloseContext() StartTaxiJob() else if IsInAuthorizedVehicle() then ESX.CloseContext() StartTaxiJob() else ESX.ShowNotification(TranslateCap('must_in_taxi')) end end else if tonumber(ESX.PlayerData.job.grade) >= 3 then ESX.ShowNotification(TranslateCap('must_in_vehicle')) else ESX.ShowNotification(TranslateCap('must_in_taxi')) end end end end end end) end function IsInAuthorizedVehicle() local playerPed = PlayerPedId() local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) for i = 1, #Config.AuthorizedVehicles, 1 do if Config.AuthorizedVehicles[i].model and vehModel == joaat(Config.AuthorizedVehicles[i].model) then return true end end return false end function OpenGetStocksMenu() ESX.TriggerServerCallback('esx_taxijob:getStockItems', function(items) local elements = { {unselectable = true, icon = "fas fa-box", title = TranslateCap('taxi_stock')} } for i = 1, #items, 1 do elements[#elements+1] = { icon = "fas fa-box", title = 'x' .. items[i].count .. ' ' .. items[i].label, value = items[i].name } end ESX.OpenContext("right", elements, function(menu,element) local itemName = element.value local elements2 = { {unselectable = true, icon = "fas fa-box", title = element.title}, {title = TranslateCap('amount'), input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = TranslateCap('withdraw_amount')}, {icon = "fas fa-check-double", title = TranslateCap('confirm'), value = "confirm"} } ESX.OpenContext("right", elements2, function(menu2,element2) local count = tonumber(menu2.eles[2].inputValue) if count == nil then ESX.ShowNotification(TranslateCap('quantity_invalid')) else ESX.CloseContext() TriggerServerEvent('esx_taxijob:getStockItem', itemName, count) Wait(1000) OpenGetStocksMenu() end end) end) end, function(menu) CurrentAction = 'taxi_actions_menu' CurrentActionMsg = TranslateCap('press_to_open') CurrentActionData = {} end) end function OpenPutStocksMenu() ESX.TriggerServerCallback('esx_taxijob:getPlayerInventory', function(inventory) local elements = { {unselectable = true, icon = "fas fa-box", title = TranslateCap('inventory')} } for i = 1, #inventory.items, 1 do local item = inventory.items[i] if item.count > 0 then elements[#elements+1] = { icon = "fas fa-box", title = item.label .. ' x' .. item.count, type = 'item_standard', value = item.name } end end ESX.OpenContext("right", elements, function(menu,element) local itemName = element.value local elements2 = { {unselectable = true, icon = "fas fa-box", title = element.title}, {title = TranslateCap('amount'), input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = TranslateCap('deposit_amount')}, {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} } ESX.OpenContext("right", elements2, function(menu2,element2) local count = tonumber(menu2.eles[2].inputValue) if count == nil then ESX.ShowNotification(TranslateCap('quantity_invalid')) else ESX.CloseContext() -- todo: refresh on callback TriggerServerEvent('esx_taxijob:putStockItems', itemName, count) Wait(1000) OpenPutStocksMenu() end end) end) end, function(menu) CurrentAction = 'taxi_actions_menu' CurrentActionMsg = TranslateCap('press_to_open') CurrentActionData = {} end) end AddEventHandler('esx_taxijob:hasEnteredMarker', function(zone) if zone == 'VehicleSpawner' then CurrentAction = 'vehicle_spawner' CurrentActionMsg = TranslateCap('spawner_prompt') CurrentActionData = {} elseif zone == 'VehicleDeleter' then local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then CurrentAction = 'delete_vehicle' CurrentActionMsg = TranslateCap('store_veh') CurrentActionData = { vehicle = vehicle } end elseif zone == 'TaxiActions' then CurrentAction = 'taxi_actions_menu' CurrentActionMsg = TranslateCap('press_to_open') CurrentActionData = {} elseif zone == 'Cloakroom' then CurrentAction = 'cloakroom' CurrentActionMsg = TranslateCap('cloakroom_prompt') CurrentActionData = {} end end) AddEventHandler('esx_taxijob:hasExitedMarker', function(zone) ESX.CloseContext() CurrentAction = nil end) RegisterNetEvent('esx_phone:loaded') AddEventHandler('esx_phone:loaded', function(phoneNumber, contacts) local specialContact = { name = TranslateCap('phone_taxi'), number = 'taxi', base64Icon = 'data:image/png;base64,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' } TriggerEvent('esx_phone:addSpecialContact', specialContact.name, specialContact.number, specialContact.base64Icon) end) -- Create Blips CreateThread(function() local blip = AddBlipForCoord(Config.Zones.TaxiActions.Pos.x, Config.Zones.TaxiActions.Pos.y, Config.Zones.TaxiActions.Pos.z) SetBlipSprite(blip, 198) SetBlipDisplay(blip, 4) SetBlipScale(blip, 1.0) SetBlipColour(blip, 5) SetBlipAsShortRange(blip, true) BeginTextCommandSetBlipName('STRING') AddTextComponentSubstringPlayerName(TranslateCap('blip_taxi')) EndTextCommandSetBlipName(blip) end) -- Enter / Exit marker events, and draw markers CreateThread(function() while true do local sleep = 1500 if ESX.PlayerData.job and ESX.PlayerData.job.name == 'taxi' then local coords = GetEntityCoords(PlayerPedId()) local isInMarker, currentZone = false for k, v in pairs(Config.Zones) do local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) local distance = #(coords - zonePos) if v.Type ~= -1 and distance < Config.DrawDistance then sleep = 0 DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) end if distance < v.Size.x then isInMarker, currentZone = true, k end end if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then HasAlreadyEnteredMarker, LastZone = true, currentZone TriggerEvent('esx_taxijob:hasEnteredMarker', currentZone) end if not isInMarker and HasAlreadyEnteredMarker then HasAlreadyEnteredMarker = false TriggerEvent('esx_taxijob:hasExitedMarker', LastZone) end end Wait(sleep) end end) -- Taxi Job CreateThread(function() while true do local Sleep = 1500 if OnJob then Sleep = 0 local playerPed = PlayerPedId() if CurrentCustomer == nil then DrawSub(TranslateCap('drive_search_pass'), 5000) if IsPedInAnyVehicle(playerPed, false) and OnJob then Wait(5000) CurrentCustomer = GetRandomWalkingNPC() if CurrentCustomer ~= nil then CurrentCustomerBlip = AddBlipForEntity(CurrentCustomer) SetBlipAsFriendly(CurrentCustomerBlip, true) SetBlipColour(CurrentCustomerBlip, 2) SetBlipCategory(CurrentCustomerBlip, 3) SetBlipRoute(CurrentCustomerBlip, true) SetEntityAsMissionEntity(CurrentCustomer, true, false) ClearPedTasksImmediately(CurrentCustomer) SetBlockingOfNonTemporaryEvents(CurrentCustomer, true) local standTime = GetRandomIntInRange(60000, 180000) TaskStandStill(CurrentCustomer, standTime) ESX.ShowNotification(TranslateCap('customer_found')) end end else if IsPedFatallyInjured(CurrentCustomer) then ESX.ShowNotification(TranslateCap('client_unconcious')) if DoesBlipExist(CurrentCustomerBlip) then RemoveBlip(CurrentCustomerBlip) end if DoesBlipExist(DestinationBlip) then RemoveBlip(DestinationBlip) end SetEntityAsMissionEntity(CurrentCustomer, false, true) CurrentCustomer, CurrentCustomerBlip, DestinationBlip, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, targetCoords = nil, nil, nil, false, false, false, nil end if IsPedInAnyVehicle(playerPed, false) then local vehicle = GetVehiclePedIsIn(playerPed, false) local playerCoords = GetEntityCoords(playerPed) local customerCoords = GetEntityCoords(CurrentCustomer) local customerDistance = #(playerCoords - customerCoords) if IsPedSittingInVehicle(CurrentCustomer, vehicle) then if CustomerEnteredVehicle then local targetDistance = #(playerCoords - targetCoords) if targetDistance <= 10.0 then TaskLeaveVehicle(CurrentCustomer, vehicle, 0) ESX.ShowNotification(TranslateCap('arrive_dest')) TaskGoStraightToCoord(CurrentCustomer, targetCoords.x, targetCoords.y, targetCoords.z, 1.0, -1, 0.0, 0.0) SetEntityAsMissionEntity(CurrentCustomer, false, true) TriggerServerEvent('esx_taxijob:success') RemoveBlip(DestinationBlip) local function scope(customer) ESX.SetTimeout(60000, function() DeletePed(customer) end) end scope(CurrentCustomer) CurrentCustomer, CurrentCustomerBlip, DestinationBlip, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, targetCoords = nil, nil, nil, false, false, false, nil end if targetCoords then DrawMarker(36, targetCoords.x, targetCoords.y, targetCoords.z + 1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 234, 223, 72, 155, false, false, 2, true, nil, nil, false) end else RemoveBlip(CurrentCustomerBlip) CurrentCustomerBlip = nil targetCoords = Config.JobLocations[GetRandomIntInRange(1, #Config.JobLocations)] local distance = #(playerCoords - targetCoords) while distance < Config.MinimumDistance do Wait(0) targetCoords = Config.JobLocations[GetRandomIntInRange(1, #Config.JobLocations)] distance = #(playerCoords - targetCoords) end local street = table.pack(GetStreetNameAtCoord(targetCoords.x, targetCoords.y, targetCoords.z)) local msg = nil if street[2] ~= 0 and street[2] ~= nil then msg = string.format(TranslateCap('take_me_to_near', GetStreetNameFromHashKey(street[1]), GetStreetNameFromHashKey(street[2]))) else msg = string.format(TranslateCap('take_me_to', GetStreetNameFromHashKey(street[1]))) end ESX.ShowNotification(msg) DestinationBlip = AddBlipForCoord(targetCoords.x, targetCoords.y, targetCoords.z) BeginTextCommandSetBlipName('STRING') AddTextComponentSubstringPlayerName('Destination') EndTextCommandSetBlipName(DestinationBlip) SetBlipRoute(DestinationBlip, true) CustomerEnteredVehicle = true end else DrawMarker(36, customerCoords.x, customerCoords.y, customerCoords.z + 1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 234, 223, 72, 155, false, false, 2, true, nil, nil, false) if not CustomerEnteredVehicle then if customerDistance <= 40.0 then if not IsNearCustomer then ESX.ShowNotification(TranslateCap('close_to_client')) IsNearCustomer = true end end if customerDistance <= 20.0 then if not CustomerIsEnteringVehicle then ClearPedTasksImmediately(CurrentCustomer) local maxSeats, freeSeat = GetVehicleMaxNumberOfPassengers(vehicle) for i = maxSeats - 1, 0, -1 do if IsVehicleSeatFree(vehicle, i) then freeSeat = i break end end if freeSeat then TaskEnterVehicle(CurrentCustomer, vehicle, -1, freeSeat, 2.0, 0) CustomerIsEnteringVehicle = true end end end end end else DrawSub(TranslateCap('return_to_veh'), 5000) end end end Wait(Sleep) end end) CreateThread(function() while OnJob do Wait(10000) if ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade < 3 then if not IsInAuthorizedVehicle() then ClearCurrentMission() OnJob = false ESX.ShowNotification(TranslateCap('not_in_taxi')) end end end end) -- Key Controls CreateThread(function() while true do local sleep = 1500 if CurrentAction and not ESX.PlayerData.dead then sleep = 0 ESX.ShowHelpNotification(CurrentActionMsg) if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == 'taxi' then if CurrentAction == 'taxi_actions_menu' then OpenTaxiActionsMenu() elseif CurrentAction == 'cloakroom' then OpenCloakroom() elseif CurrentAction == 'vehicle_spawner' then OpenVehicleSpawnerMenu() elseif CurrentAction == 'delete_vehicle' then DeleteJobVehicle() end CurrentAction = nil end end Wait(sleep) end end) RegisterCommand('taximenu', function() if not ESX.PlayerData.dead and Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.name == 'taxi' then OpenMobileTaxiActionsMenu() end end, false) RegisterKeyMapping('taximenu', 'Open Taxi Menu', 'keyboard', 'f6')