Mecânica do Consumo de Combustível
Um sistema de combustível realista adiciona uma camada essencial de imersão e cria um dissipador natural de dinheiro que ajuda a equilibrar a economia do seu servidor. A mecânica central envolve rastrear o nível de combustível de cada veículo como um valor de ponto flutuante entre 0 e 100, diminuindo-o com base na atividade do motor e no comportamento de direção. Armazene o nível de combustível usando sacos de estado de entidade com Entity(vehicle).state.fuel para que o valor persista em todos os clientes e sobreviva às mudanças de propriedade da rede. Calcule a taxa de consumo por tick com base na RPM atual do veículo obtida através de GetVehicleCurrentRpm, na posição do acelerador de GetControlNormal e no multiplicador de consumo específico da classe do veículo. Os carros esportivos e supercarros devem consumir combustível significativamente mais rápido do que os veículos econômicos, enquanto os caminhões e os SUVs ficam em algum ponto intermediário. Aplique modificadores de consumo adicionais para comportamentos de direção agressivos, como aceleração rápida, altas velocidades sustentadas e frenagem com motor. Quando o combustível chegar a zero, reduza gradualmente a velocidade máxima do veículo usando SetVehicleMaxSpeed para simular estalos em vez de desligar o motor instantaneamente, dando ao jogador alguns segundos críticos para parar com segurança.
-- Client-side fuel consumption thread
local fuelConsumptionRate = 0.0
CreateThread(function()
while true do
local ped = PlayerPedId()
local vehicle = GetVehiclePedIsIn(ped, false)
if vehicle ~= 0 and GetPedInVehicleSeat(vehicle, -1) == ped then
local engineOn = GetIsVehicleEngineRunning(vehicle)
if engineOn then
local rpm = GetVehicleCurrentRpm(vehicle)
local speed = GetEntitySpeed(vehicle) * 3.6 -- km/h
local classMultiplier = Config.ClassConsumption[GetVehicleClass(vehicle)] or 1.0
-- Base consumption + RPM factor + speed factor
fuelConsumptionRate = (Config.BaseConsumption
+ (rpm * Config.RpmFactor)
+ (speed * Config.SpeedFactor)
) * classMultiplier
local currentFuel = Entity(vehicle).state.fuel or 100.0
local newFuel = math.max(0.0, currentFuel - fuelConsumptionRate)
Entity(vehicle).state:set('fuel', newFuel, true)
-- Engine stall when empty
if newFuel <= 0 then
SetVehicleUndriveable(vehicle, true)
SetVehicleEngineOn(vehicle, false, true, true)
elseif newFuel <= 5.0 then
-- Sputtering effect
SetVehicleMaxSpeed(vehicle, 30.0 * (newFuel / 5.0))
end
end
end
Wait(1000) -- Update every second
end
end)Interface do posto de gasolina e reabastecimento
A experiência no posto de gasolina deve ser refinada e intuitiva por meio de uma interface NUI bem projetada. Quando um jogador estaciona perto de uma bomba de combustível dentro de um raio definido, exibe um prompt de interação. Após a interação, abra uma interface de reabastecimento que mostra o nível atual de combustível como um medidor ou barra de progresso, a capacidade do tanque do veículo, o preço por litro com base no tipo de combustível atual e opções para abastecer completamente ou bombear uma quantia específica em dólares. A animação de reabastecimento deve ser reproduzida tanto no personagem do jogador, que está ao lado do veículo segurando um suporte de bico de combustível usando TaskPlayAnim, quanto na própria bomba de combustível, se você usar uma configuração de suporte personalizada. O combustível deve ser abastecido gradualmente em tempo real, em vez de saltar instantaneamente para cheio, criando uma breve espera que adiciona realismo e evita que os jogadores reabasteçam rapidamente durante as perseguições. Mostre o custo operacional total atualizado ao vivo como bombas de combustível e deduza o pagamento somente quando o jogador parar de bombear ou o tanque estiver cheio. Suporta vários tipos de combustível em postos premium: combustível normal sem chumbo a preço padrão, combustível premium que proporciona um pequeno aumento de desempenho e custa mais, e diesel para caminhões e veículos industriais que usa bombas separadas.
Jerry Can e reabastecimento de emergência
Ficar sem combustível na rodovia é um cenário realista que seu sistema deve lidar normalmente, sem forçar o jogador a abandonar o veículo. Implemente um galão que possa ser comprado em postos de gasolina ou lojas de ferragens e abastecido em qualquer bomba. O galão deve funcionar como um item de inventário utilizável com metadados rastreando seu nível de enchimento atual, normalmente contendo de 10 a 20 litros. Quando um jogador usa um galão perto de um veículo vazio, reproduza uma animação de derramamento e transfira o combustível da lata para o tanque do veículo. O galão deve ter peso no sistema de estoque proporcional à quantidade de combustível que contém, tornando uma lata cheia mais pesada que uma vazia. Adicione um mecânico onde a assistência rodoviária pode ser chamada através do telefone do jogo, despachando um NPC ou um caminhão de reboque operado pelo jogador com um serviço de entrega de combustível mediante o pagamento de uma taxa. Para imersão, os jogadores devem ser capazes de extrair combustível de outros veículos usando uma mangueira, transferindo combustível entre veículos à custa de tempo e do risco de serem pegos em flagrante.
-- Jerry can usage handler
RegisterNetEvent('fuel:useJerryCan')
AddEventHandler('fuel:useJerryCan', function(slot)
local src = source
local ped = GetPlayerPed(src)
local coords = GetEntityCoords(ped)
-- Find nearest vehicle
local nearbyVehicle = GetClosestVehicle(coords, 3.0)
if not nearbyVehicle or nearbyVehicle == 0 then
return notify(src, 'No vehicle nearby.', 'error')
end
-- Get jerry can metadata
local canData = exports.ox_inventory:GetSlot(src, slot)
if not canData or not canData.metadata or not canData.metadata.fuel then
return notify(src, 'Jerry can is empty.', 'error')
end
local canFuel = canData.metadata.fuel
local vehicleFuel = Entity(nearbyVehicle).state.fuel or 0.0
local maxTransfer = math.min(canFuel, 100.0 - vehicleFuel)
if maxTransfer <= 0 then
return notify(src, 'Vehicle tank is already full.', 'error')
end
-- Transfer fuel
Entity(nearbyVehicle).state:set('fuel', vehicleFuel + maxTransfer, true)
-- Update jerry can metadata
local remainingFuel = canFuel - maxTransfer
if remainingFuel <= 0 then
exports.ox_inventory:SetMetadata(src, slot, { fuel = 0, label = 'Empty Jerry Can' })
else
exports.ox_inventory:SetMetadata(src, slot, { fuel = remainingFuel })
end
notify(src, ('Transferred %.1f liters to the vehicle.'):format(maxTransfer), 'success')
end)Suporte para veículos elétricos
Os servidores de roleplay modernos apresentam cada vez mais veículos elétricos que precisam de uma infraestrutura de carregamento paralela. Os veículos eléctricos não devem consumir gasolina e, em vez disso, drenar um nível de carga da bateria que funciona de forma idêntica ao indicador de combustível, mas que se esgota a uma taxa diferente. O consumo de veículos elétricos deve ser menor por quilómetro do que os veículos a gasolina, refletindo a sua vantagem de eficiência no mundo real, mas o carregamento deve demorar mais do que bombear gasolina, criando um ritmo de jogo diferente. Coloque estações de carregamento em locais selecionados no mapa, não necessariamente em postos de gasolina tradicionais, para criar padrões de viagem distintos para proprietários de veículos elétricos. Implemente uma IU de cobrança que mostre a porcentagem de cobrança atual, o tempo estimado para carga completa e o custo por quilowatt-hora. Adicione uma opção de carregamento rápido em estações premium que enche a bateria na metade do tempo e com o dobro do custo por unidade. Para a configuração do veículo, classifique os EVs pelo hash do modelo e armazene o tipo de veículo na sua configuração para que o sistema detecte automaticamente se um veículo precisa de gasolina ou eletricidade. Apoiar veículos híbridos que possam utilizar ambos os tipos de combustível, alternando entre o modo elétrico em baixas velocidades e a gasolina em velocidades de rodovia, consumindo ambos os recursos a taxas individuais reduzidas.
Economia Dinâmica de Preços de Combustível
Um sistema de preços dinâmico dá vida à economia de combustível e cria decisões econômicas interessantes para os jogadores. Baseie os preços dos combustíveis em uma taxa configurável que flutua com base na mecânica de oferta e demanda. Acompanhe o total de combustível adquirido em todos os postos em janelas de tempo contínuo e, quando o consumo é alto, os preços sobem gradualmente. Quando o consumo cai, os preços diminuem para atrair mais clientes. Implemente preços específicos para estações onde as estações remotas no condado de Blaine cobram mais devido aos custos de transporte, enquanto as estações urbanas competem com margens mais baixas. Permitir postos de gasolina de propriedade do jogador onde o proprietário pode definir seus próprios preços de combustível dentro de uma faixa mínima e máxima definida pela configuração do servidor, criando uma competição genuína de preços entre os operadores dos postos. O dono do posto compra combustível no atacado de um NPC fornecedor a granel e marca até seu preço de varejo, sendo a margem de lucro sua renda. Adicione aumentos de preços sazonais ou baseados em eventos onde os custos de combustível aumentam durante eventos de servidor que envolvem alta atividade de veículos, como corridas ou assaltos, criando efeitos econômicos que afetam todos os jogadores e incentivam a conservação ou compras estratégicas de combustível antes dos aumentos de preços previstos.
Posto de gasolina como negócio
Transformar postos de gasolina em negócios operados por jogadores acrescenta um ciclo econômico completo ao sistema de combustível. O proprietário do posto gerencia o estoque solicitando entregas de combustível de um fornecedor atacadista, mantém o equipamento pagando por reparos e atualizações nas bombas e cuida da equipe contratando outros jogadores como atendentes das bombas que ganham salários por hora. Implementar um painel de gerenciamento de postos acessível apenas ao proprietário que exiba diariamente o volume de vendas, receitas, margens de lucro, estoque atual de combustível nos tanques subterrâneos e registros de frequência dos funcionários. A estação deve ter um tanque físico subterrâneo com capacidade limitada que se esgota à medida que os clientes reabastecem, exigindo que o proprietário agende visitas de caminhões de entrega que demoram para chegar e custam dinheiro antecipadamente. Adicione um componente de loja dentro do posto onde o proprietário pode estocar itens de conveniência como lanches, bebidas e suprimentos básicos que os clientes podem comprar junto com o combustível, criando um fluxo de receita adicional. Permitir atualizações na própria estação, como adicionar compartimentos de bombas adicionais para atender mais clientes simultaneamente, instalar equipamentos de lavagem de carros por uma taxa de serviço extra ou adicionar estações de carregamento de veículos elétricos para conquistar o mercado de veículos elétricos. Rastreie a reputação das estações com base na justiça dos preços, na disponibilidade, no tempo de atividade e na satisfação do cliente, para que as estações com melhor reputação apareçam destacadas no mapa e atraiam mais tráfego.
Integração HUD e medidor de combustível
O medidor de combustível é um elemento persistente do HUD que os jogadores verão constantemente, por isso deve ser visualmente limpo e não intrusivo, ao mesmo tempo que transmite informações essenciais rapidamente. Projete um indicador de combustível mínimo que fique próximo ao velocímetro ou em um canto da tela, mostrando o nível de combustível atual como um medidor semicircular, uma barra vertical ou uma simples leitura de porcentagem. Use o código de cores onde o verde indica um nível de combustível saudável acima de 50%, o amarelo sinaliza combustível moderado entre 20-50% e o vermelho alerta sobre combustível criticamente baixo abaixo de 20%. Quando o combustível cair abaixo de 15%, acione um aviso sonoro periódico de pouco combustível e pisque o medidor para garantir que o player não fique vazio acidentalmente. Apresenta a distância restante estimada com base na taxa de consumo atual, calculada dividindo o combustível restante pelo consumo médio por quilómetro nos últimos minutos de condução. Oculte totalmente o medidor de combustível quando o jogador estiver a pé para reduzir a confusão do HUD e apague-o suavemente quando ele entrar em um veículo. Para jogadores que preferem um HUD mínimo, ofereça uma configuração para ocultar totalmente o medidor de combustível e mostrá-lo apenas como uma notificação temporária quando o combustível cair abaixo de um limite configurável. Integre o medidor com outros elementos do HUD do veículo, como velocímetro e integridade do motor, para criar uma experiência coesa no painel do veículo.
Desempenho e sincronização
O sistema de combustível funciona continuamente em cada cliente que dirige um veículo, portanto a otimização do desempenho é crítica. Use um intervalo de atualização de consumo de 1.000 milissegundos em vez de executar a cada frame tick, pois as mudanças de combustível são graduais o suficiente para que as atualizações por segundo sejam visualmente indistinguíveis das atualizações por quadro, usando cerca de 60 vezes menos poder de processamento. Armazene valores de combustível em bolsas de estado de entidade em vez de eventos de rede personalizados, uma vez que as bolsas de estado são otimizadas para valores que mudam frequentemente e só sincronizam quando o valor realmente muda. Ao economizar combustível no banco de dados para persistência nas reinicializações do servidor, agrupe todas as atualizações de combustível do veículo em uma única consulta executada a cada 60 segundos, em vez de escrever individualmente cada vez que o combustível de um veículo muda. Use o ID de rede do veículo como chave para rastreamento de combustível e limpe os dados de combustível armazenados de veículos que não existem mais para evitar o inchaço do banco de dados. Lide com o caso extremo em que um veículo altera a propriedade da rede durante o reabastecimento, verificando a propriedade antes de aplicar as alterações de combustível e usando a validação do lado do servidor para todas as transações de pagamento. Para estações com muitos clientes simultâneos, implemente um sistema de fila que evite que dois jogadores utilizem a mesma bomba simultaneamente, ao mesmo tempo que mostra um indicador visual de que a bomba está em uso.
