>
Tutorial 2026-04-07

Desenvolvimento de Jobs de Táxi e Transporte em FiveM

OntelMonke

OntelMonke

Admin & Developer na Agency Scripts

Arquitetura do sistema de trabalho de táxi

Um sistema de trabalho de táxi é um recurso fundamental para qualquer servidor de RPG que deseja oferecer aos jogadores um trabalho de nível básico acessível com interação genuína do jogador. Ao contrário de muitos outros trabalhos que podem parecer enfadonhos e repetitivos, um sistema de táxi bem projetado cria encontros orgânicos de roleplay enquanto os motoristas pegam passageiros, negociam tarifas e navegam pela cidade sob pressão de tempo. A arquitetura se divide em dois modos distintos: transporte de jogador para jogador, onde passageiros reais solicitam caronas, e modo de missão NPC, onde o sistema gera locais de embarque e desembarque para jogo solo fora dos horários de pico. Ambos os modos compartilham o mesmo mecanismo de cálculo de tarifas, interface de usuário do taxímetro e sistema de gerenciamento de veículos. A principal decisão de projeto é usar um sistema de despacho centralizado, onde as solicitações de viagem vão para uma fila compartilhada visível para todos os motoristas em serviço, ou um sistema baseado em proximidade, onde o motorista mais próximo tem prioridade. A maioria das implementações bem-sucedidas utiliza uma abordagem híbrida com um quadro de despacho que mostra todas as solicitações pendentes, mas destaca as próximas, dando aos motoristas a liberdade de escolher seus trabalhos e ao mesmo tempo garantindo que os passageiros sejam recolhidos rapidamente.

Implementação de taxímetro

O taxímetro é o coração do sistema tarifário e precisa parecer autêntico e, ao mesmo tempo, permanecer transparente tanto para o motorista quanto para o passageiro. Um medidor adequado rastreia dois componentes: uma tarifa básica cobrada no início de cada viagem e uma tarifa por distância que aumenta à medida que o veículo se move. Alguns servidores também adicionam uma taxa de tempo de espera que cobra uma taxa menor por segundo quando o táxi está parado, simulando a prática real de cobrar pelo tempo gasto no trânsito. O medidor deve ser visível tanto para o motorista quanto para qualquer passageiro no veículo através de um elemento NUI persistente posicionado no canto da tela. Aqui está uma implementação de medidor do lado do cliente que calcula a tarifa com base na distância percorrida:

local meterActive = false
local currentFare = 0.0
local lastPosition = nil
local baseFare = 50
local ratePerMile = 15
local waitRatePerSecond = 0.5
local totalDistance = 0.0

function StartMeter()
    meterActive = true
    currentFare = baseFare
    totalDistance = 0.0
    lastPosition = GetEntityCoords(PlayerPedId())

    SendNUIMessage({action = 'showMeter', fare = currentFare, distance = 0.0})

    CreateThread(function()
        while meterActive do
            Wait(500)
            local currentPos = GetEntityCoords(PlayerPedId())
            local speed = GetEntitySpeed(PlayerPedId())

            if speed > 1.0 then
                local dist = #(currentPos - lastPosition)
                totalDistance = totalDistance + dist
                local miles = totalDistance / 1609.34
                currentFare = baseFare + (miles * ratePerMile)
            else
                currentFare = currentFare + (waitRatePerSecond * 0.5)
            end

            lastPosition = currentPos

            SendNUIMessage({
                action = 'updateMeter',
                fare = math.floor(currentFare),
                distance = math.floor(totalDistance),
                speed = math.floor(speed * 2.236936)
            })
        end
    end)
end

function StopMeter()
    meterActive = false
    local finalFare = math.floor(currentFare)
    SendNUIMessage({action = 'stopMeter', fare = finalFare})
    return finalFare
end

O componente NUI do medidor deve ser compacto, mas legível, mostrando a tarifa atual de forma destacada, juntamente com a distância percorrida e a tarifa atual aplicada. Use uma fonte monoespaçada para a exibição da tarifa para imitar a aparência de um taxímetro real e adicione uma animação sutil cada vez que a tarifa aumenta para fornecer feedback visual de que o taxímetro está funcionando. Considere adicionar um recurso de estimativa de tarifa que calcule o custo aproximado com base na distância em linha reta até o destino antes do início da viagem, para que os passageiros possam decidir se desejam prosseguir.

Sistema de missão de coleta de NPC

As missões NPC mantêm os motoristas de táxi ocupados quando não há passageiros reais suficientes no servidor. O sistema gera locais aleatórios de coleta e entrega a partir de uma lista selecionada de pontos de interesse ao redor do mapa, cria um NPC no local de coleta e orienta o motorista durante todo o ciclo tarifário. A qualidade da experiência da missão do NPC depende muito dos dados de localização: usar apenas coordenadas aleatórias produz coletas não naturais no meio do nada, portanto, manter uma lista selecionada manualmente de locais realistas, como hospitais, restaurantes, hotéis e shopping centers, faz com que as missões pareçam genuínas. Aqui está a lógica do lado do servidor para gerar e despachar missões NPC:

local MissionLocations = {
    {coords = vector3(-240.49, -987.78, 29.29), label = 'Pillbox Medical Center'},
    {coords = vector3(228.28, -790.70, 30.58), label = 'Legion Square'},
    {coords = vector3(-1044.57, -2739.76, 13.85), label = 'Los Santos Airport'},
    {coords = vector3(126.19, -1282.72, 29.27), label = 'Strawberry Avenue'},
    {coords = vector3(-556.18, -196.17, 38.22), label = 'Rockford Hills'},
    {coords = vector3(1159.56, -314.45, 69.21), label = 'Vinewood Hills'},
    {coords = vector3(-1222.08, -906.82, 12.32), label = 'Del Perro Pier'},
    {coords = vector3(373.58, 325.71, 103.57), label = 'Downtown Vinewood'},
}

RegisterNetEvent('taxi:server:requestNPCMission', function()
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player or Player.PlayerData.job.name ~= 'taxi' then return end

    local pickup = MissionLocations[math.random(#MissionLocations)]
    local dropoff = MissionLocations[math.random(#MissionLocations)]

    while pickup.label == dropoff.label do
        dropoff = MissionLocations[math.random(#MissionLocations)]
    end

    local estimatedDistance = #(pickup.coords - dropoff.coords)
    local basePay = 50
    local distancePay = math.floor(estimatedDistance / 1609.34 * 15)
    local totalPay = basePay + distancePay

    TriggerClientEvent('taxi:client:startNPCMission', src, {
        pickup = pickup,
        dropoff = dropoff,
        estimatedPay = totalPay,
        npcModel = Config.NPCModels[math.random(#Config.NPCModels)],
        missionId = 'TAXI-' .. os.time() .. '-' .. math.random(1000, 9999)
    })
end)

No lado do cliente, crie o NPC no local de coleta com uma animação de espera, adicione um sinal para guiar o motorista e reproduza uma animação de entrada do veículo quando o motorista chegar. Durante a viagem, o NPC deve usar comportamentos naturais, como olhar ao redor e ocasionalmente comentar sobre a direção através de balões de bate-papo. Quando o veículo chega ao destino, o NPC sai e a tarifa é paga automaticamente através de um evento no servidor. Adicione variedade gerando ocasionalmente missões especiais com pagamentos mais elevados, como transferências de aeroporto ou clientes VIP que exigem uma condução cuidadosa e sem colisões.

Cálculo de tarifas e preços dinâmicos

Além do cálculo básico baseado na distância, um sistema tarifário sofisticado leva em conta a hora do dia, as condições do trânsito e o tipo de veículo. Implemente preços dinâmicos durante horários de pico no servidor, quando muitos jogadores estão online e a demanda de táxi excede a oferta. O multiplicador de pico deve ser comunicado de forma transparente aos passageiros antes de confirmarem a viagem, para que não haja surpresas no final. Você pode calcular a demanda dinamicamente rastreando a proporção de solicitações de viagem pendentes em relação aos motoristas disponíveis. Aqui está um mecanismo de cálculo de tarifa que incorpora estas variáveis:

function CalculateFare(pickupCoords, dropoffCoords, vehicleClass)
    local distance = #(pickupCoords - dropoffCoords)
    local miles = distance / 1609.34

    local rates = Config.FareRates
    local baseFare = rates.base
    local perMile = rates.perMile

    -- Vehicle class multiplier
    local classMultiplier = {
        [0] = 0.8,   -- Compacts (budget)
        [1] = 1.0,   -- Sedans (standard)
        [2] = 1.0,   -- SUVs
        [3] = 1.2,   -- Coupes (comfort)
        [18] = 1.5,  -- Super (luxury)
    }
    local vehMultiplier = classMultiplier[vehicleClass] or 1.0

    -- Time-of-day multiplier (night premium)
    local hour = GetClockHours()
    local timeMultiplier = 1.0
    if hour >= 22 or hour <= 5 then
        timeMultiplier = 1.3  -- 30% night surcharge
    end

    -- Surge pricing based on demand
    local surgeMultiplier = GetCurrentSurgeMultiplier()

    local totalFare = (baseFare + (miles * perMile)) * vehMultiplier * timeMultiplier * surgeMultiplier

    return {
        total = math.floor(totalFare),
        breakdown = {
            base = baseFare,
            distance = math.floor(miles * perMile),
            vehicleClass = vehMultiplier,
            nightSurcharge = timeMultiplier > 1.0,
            surgeActive = surgeMultiplier > 1.0,
            surgeRate = surgeMultiplier
        }
    }
end

Exiba o detalhamento da tarifa ao passageiro quando ele solicitar uma viagem, para que ele entenda o que está pagando. Se o preço dinâmico estiver ativo, mostre o multiplicador claramente com um indicador de cor diferente na IU. Esta transparência cria confiança entre motoristas e passageiros e reduz disputas sobre valores de tarifas. Permita que os passageiros selecionem sua classe de veículo preferida no momento da reserva, com opções econômicas usando carros compactos e opções de luxo usando sedãs ou SUVs de alta qualidade com tarifas premium.

Exibição de rota e navegação GPS

Fornecer orientação visual de rota torna a experiência do táxi mais tranquila para motoristas novos e experientes. FiveM fornece o SetNewWaypoint nativo para roteamento GPS básico, mas uma abordagem mais refinada desenha a rota diretamente no minimapa e, opcionalmente, renderiza um caminho 3D no mundo. Use a função SetBlipRoute nas mensagens de destino para ativar o caminho GPS integrado e aprimorá-lo com mensagens personalizadas nos principais pontos de referência ao longo da rota. Para benefício do passageiro, exiba o tempo estimado de chegada e a distância restante na IU do medidor, atualizando em tempo real conforme o veículo avança. Veja como configurar o sistema de exibição de rota com rastreamento de waypoint:

local routeBlip = nil
local checkpointBlips = {}

function SetTaxiRoute(destination, checkpoints)
    ClearTaxiRoute()

    routeBlip = AddBlipForCoord(destination.x, destination.y, destination.z)
    SetBlipSprite(routeBlip, 198)
    SetBlipColour(routeBlip, 5)
    SetBlipScale(routeBlip, 1.0)
    SetBlipRoute(routeBlip, true)
    SetBlipRouteColour(routeBlip, 5)
    BeginTextCommandSetBlipName('STRING')
    AddTextComponentSubstringPlayerName('Destination')
    EndTextCommandSetBlipName(routeBlip)

    if checkpoints then
        for i, cp in ipairs(checkpoints) do
            local cpBlip = AddBlipForCoord(cp.x, cp.y, cp.z)
            SetBlipSprite(cpBlip, 1)
            SetBlipColour(cpBlip, 3)
            SetBlipScale(cpBlip, 0.6)
            table.insert(checkpointBlips, cpBlip)
        end
    end
end

function ClearTaxiRoute()
    if routeBlip then
        SetBlipRoute(routeBlip, false)
        RemoveBlip(routeBlip)
        routeBlip = nil
    end
    for _, blip in ipairs(checkpointBlips) do
        RemoveBlip(blip)
    end
    checkpointBlips = {}
end

function UpdateETADisplay(destination)
    CreateThread(function()
        while routeBlip do
            Wait(2000)
            local pos = GetEntityCoords(PlayerPedId())
            local remaining = #(pos - destination)
            local speed = GetEntitySpeed(PlayerPedId())

            local etaSeconds = speed > 2.0 and (remaining / speed) or 0
            local etaMinutes = math.floor(etaSeconds / 60)

            SendNUIMessage({
                action = 'updateETA',
                distance = math.floor(remaining),
                eta = etaMinutes > 0 and (etaMinutes .. ' min') or 'Arriving'
            })
        end
    end)
end

Para uma camada extra de imersão, implemente um sistema de classificação onde os passageiros avaliam sua viagem com base em fatores como tempo de viagem comparado à estimativa, número de colisões durante a viagem e se o motorista seguiu as leis de trânsito. Exiba a classificação média do motorista em seu perfil de táxi para que os passageiros possam vê-la antes de aceitar a corrida, criando um incentivo para que os motoristas prestem um bom serviço.

Sistema de dicas e classificações de motorista

Um sistema de gorjetas adiciona uma mecânica social gratificante que incentiva os motoristas a prestar um serviço excelente. Depois que a tarifa for paga e o passageiro sair do veículo, exiba um aviso de gorjeta ao passageiro com opções predefinidas como 10%, 15%, 20% ou um valor personalizado. A gorjeta vai diretamente para o motorista, além da tarifa base e qualquer comissão da empresa de táxi. Acompanhe dicas cumulativas por motorista no banco de dados para criar tabelas de classificação e desbloquear bônus para os pilotos mais bem avaliados. No lado do servidor, processe as gorjetas através do mesmo sistema de transação das tarifas para garantir consistência e evitar duplicação. Os motoristas que mantêm uma classificação alta e uma média de gorjetas ao longo do tempo podem desbloquear vantagens como acesso a veículos premium, taxas de comissão reduzidas da empresa ou prioridade na fila de despacho. Combine o sistema de gorjetas com um sistema de revisão onde os passageiros deixam uma breve revisão de texto visível para o motorista, criando um ciclo de feedback que melhora a qualidade geral do serviço de táxi no servidor.

Solicitações de embarque e passeio

O quadro de despacho é o ponto central onde os motoristas de táxi encontram seu próximo emprego. Construa-o como um painel NUI acessível a partir da sede da empresa de táxi ou através de uma tecla de atalho durante o serviço. O quadro deve exibir todas as solicitações de viagem pendentes classificadas por proximidade, com cada entrada mostrando o nome do passageiro, local de retirada, destino, tarifa estimada e distância estimada. Quando um motorista aceita um trabalho, remova-o do quadro para todos os outros motoristas e inicie uma contagem regressiva, caso o motorista não chegue à coleta no prazo, o trabalho retorna ao quadro e o motorista recebe uma penalidade de confiabilidade. Para o lado voltado para o passageiro, crie um aplicativo ou comando de telefone simples que permita solicitar uma viagem especificando sua localização e destino atuais. A solicitação entra na fila de despacho e o passageiro recebe atualizações conforme o motorista aceita e se aproxima. Implemente um sistema de cancelamento com uma pequena taxa para cancelamentos tardios para evitar que os passageiros solicitem e cancelem viagens repetidamente, o que desperdiça o tempo do motorista e cria uma experiência frustrante.

Sistema de Gestão de Veículos e Frota

Um sistema de táxi completo necessita de um gerenciamento adequado de veículos para que os motoristas utilizem veículos adequados e a empresa mantenha sua frota. Crie um sistema de check-out de veículos na garagem de táxis onde os motoristas selecionam os veículos disponíveis da empresa. Cada veículo deve ter um contador de quilometragem rastreado, nível de combustível e status de condição, e os motoristas são responsáveis ​​por devolver os veículos em condições aceitáveis ​​ou enfrentar deduções de reparos de seus ganhos. A garagem deve estocar diferentes níveis de veículos: sedãs econômicos para tarifas padrão, SUVs confortáveis ​​para serviço premium e veículos de luxo para reservas VIP. Acompanhe as estatísticas de uso de cada veículo, incluindo o total de tarifas concluídas, receitas geradas e custos de manutenção. Implementar um sistema de consumo de combustível que exija que os motoristas reabasteçam nos postos de gasolina durante o seu turno, acrescentando um custo operacional realista que os motoristas experientes aprendam a gerir de forma eficiente. No final do turno, o motorista devolve o veículo à garagem, seus ganhos totais são calculados menos a comissão da empresa e quaisquer custos com danos ao veículo, e o pagamento líquido é depositado em sua conta bancária. Esse ciclo completo cria uma experiência de trabalho realista que reflete as operações reais da empresa de táxi.

Partilhar este artigo

Pronto para melhorar o teu servidor?

Explora os nossos scripts FiveM premium na loja Agency Scripts ou junta-te à nossa comunidade no Discord para suporte e atualizações.