Скрипты системы топлива FiveM: реалистичная заправка транспортных средств
Добавьте работающий топливный механизм на ваш сервер FiveM. АЗС, канистры, электромобили и лучшие топливные скрипты для QBCore, ESX и standalone.
Agency Scripts
Основатель и ведущий разработчик Agency Scripts
Механика расхода топлива
Реалистичная система топлива добавляет важный уровень погружения и создает естественный денежный слив, помогающий балансировать экономику сервера. Основной механизм , отслеживание уровня топлива каждого транспортного средства как числа с плавающей точкой от 0 до 100, которое уменьшается в зависимости от работы двигателя и стиля вождения. Уровень топлива хранится с помощью entity state bags с Entity(vehicle).state.fuel чтобы значение сохранялось на всех клиентах и сохранялось при смене сетевого владельца. Рассчитывайте скорость потребления за тик на основе текущих оборотов двигателя транспортного средства, полученных через GetVehicleCurrentRpm , положение дроссельной заслонки от GetControlNormal и множитель расхода топлива, зависящий от класса транспортного средства. Спортивные и супер-кары должны расходовать топливо значительно быстрее экономичных автомобилей, в то время как грузовики и внедорожники занимают промежуточное положение. Применяйте дополнительные модификаторы расхода для агрессивного стиля вождения, такого как резкое ускорение, высокая постоянная скорость и торможение двигателем. Когда топливо заканчивается, постепенно снижайте максимальную скорость автомобиля с помощью SetVehicleMaxSpeed для имитации прерывистого глохания двигателя, а не мгновенного его отключения, давая игроку несколько критических секунд, чтобы безопасно остановиться.
-- 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)
UI автозаправки и заправка
Опыт на автозаправочной станции должен быть отточенным и интуитивным благодаря хорошо продуманному интерфейсу NUI. Когда игрок паркуется рядом с топливным насосом в пределах заданного радиуса, отображается подсказка для взаимодействия. При взаимодействии открывается интерфейс заправки, который показывает текущий уровень топлива в виде шкалы или индикатора прогресса, емкость бака транспортного средства, цену за литр в зависимости от текущего типа топлива и опции для полной заправки или заправки на определенную сумму в долларах. Анимация заправки должна воспроизводиться как на персонаже игрока, который стоит рядом с транспортным средством, держа топливный пистолет, используя TaskPlayAnim и саму топливную колонку, если вы используете кастомный проп. Топливо должно заполняться постепенно в реальном времени, а не мгновенно, создавая небольшую задержку, которая добавляет реализма и предотвращает быструю заправку во время погони. Показывайте общую стоимость в реальном времени по мере заправки и снимайте оплату только когда игрок перестаёт заправлять или бак полный. Поддерживайте несколько типов топлива на премиальных станциях: обычный бензин по стандартной цене, премиум-топливо с небольшим приростом производительности и более высокой ценой, а также дизель для грузовиков и промышленных машин с отдельными колонками.
Канистра и экстренная заправка
Остановка из-за нехватки топлива на трассе , реалистичный сценарий, который ваша система должна корректно обрабатывать, не заставляя игрока покидать транспорт. Реализуйте предмет канистры, который можно купить на заправках или в хозяйственных магазинах и заправить на любом насосе. Канистра должна функционировать как используемый предмет в инвентаре с метаданными, отслеживающими текущий уровень топлива, обычно вмещая 10-20 литров. При использовании канистры рядом с пустым транспортом воспроизводится анимация заливки, и топливо переносится из канистры в бак. Канистра должна иметь вес в системе инвентаря пропорционально количеству топлива, делая полную канистру тяжелее пустой. Добавьте механику вызова дорожной помощи через встроенный телефон, которая отправляет NPC или игрока с эвакуатором и услугой доставки топлива за плату. Для погружения игроки должны иметь возможность перекачивать топливо из других транспортных средств с помощью шланга, передавая топливо между машинами с затратами времени и риском быть пойманными.
-- 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)
Поддержка электромобилей
Современные ролевые серверы всё чаще используют электромобили, которым нужна параллельная инфраструктура зарядки. Электромобили не должны потреблять бензин, вместо этого расходуя заряд батареи, который функционирует аналогично индикатору топлива, но расходуется с другой скоростью. Потребление электромобилей должно быть ниже на километр, чем у бензиновых, отражая их реальное преимущество в эффективности, но зарядка должна занимать больше времени, чем заправка бензином, создавая другой игровой ритм. Размещайте зарядные станции в выбранных местах по карте, не обязательно на традиционных автозаправках, чтобы создать уникальные маршруты для владельцев электромобилей. Реализуйте UI зарядки, показывающий текущий процент заряда, предполагаемое время до полной зарядки и стоимость за киловатт-час. Добавьте опцию быстрой зарядки на премиальных станциях, которая заполняет батарею вдвое быстрее по двойной цене за единицу. Для конфигурации транспортных средств классифицируйте электромобили по их хэшу модели и храните тип транспортного средства в конфиге, чтобы система автоматически определяла, нуждается ли транспорт в бензине или электричестве. Поддерживайте гибридные автомобили, которые могут использовать оба типа топлива, переключаясь между электрическим режимом на низких скоростях и бензиновым на шоссе, потребляя оба ресурса с пониженной индивидуальной скоростью.
Экономика динамического ценообразования топлива
Динамическая система ценообразования делает топливную экономику живой и создаёт интересные экономические решения для игроков. Базируйте цены на топливо на настраиваемой ставке, которая колеблется в зависимости от механики спроса и предложения. Отслеживайте общий объём топлива, купленного на всех станциях за скользящие временные окна: при высоком потреблении цены постепенно растут, при снижении , падают для привлечения клиентов. Реализуйте ценообразование по станциям, где удалённые станции в Blaine County берут больше из-за транспортных расходов, а городские конкурируют с меньшей маржой. Позвольте игрокам-владельцам АЗС устанавливать собственные цены в пределах минимального и максимального диапазона, заданного конфигом сервера, создавая реальную ценовую конкуренцию. Владелец станции покупает оптовое топливо у NPC-поставщика по оптовой цене и устанавливает розничную цену с наценкой, которая становится его доходом. Добавьте сезонные или событийные скачки цен, когда топливо дорожает во время серверных событий с высокой активностью транспорта, таких как гонки или ограбления, создавая экономические волны, влияющие на всех игроков и стимулирующие экономию или стратегические закупки топлива перед ожидаемым ростом цен.
Автозаправка как бизнес
Преобразование автозаправочных станций в бизнесы, управляемые игроками, добавляет полный экономический цикл в систему топлива. Владелец станции управляет запасами, заказывая поставки топлива у оптового поставщика, поддерживает оборудование, оплачивая ремонт и модернизацию насосов, и нанимает других игроков в качестве операторов насосов, которые получают почасовую оплату. Реализуйте панель управления станцией, доступную только владельцу, которая отображает ежедневный объем продаж, доход, маржу прибыли, текущие запасы топлива в подземных резервуарах и учет посещаемости сотрудников. Станция должна иметь физический подземный резервуар с ограниченной емкостью, который истощается по мере заправки клиентов, требуя от владельца планировать визиты грузовиков с топливом, которые занимают время на доставку и требуют предоплаты. Добавьте магазин внутри станции, где владелец может хранить товары повседневного спроса, такие как закуски, напитки и базовые принадлежности, которые клиенты могут покупать вместе с топливом, создавая дополнительный источник дохода. Позвольте улучшать саму станцию, добавляя дополнительные насосные места для обслуживания большего числа клиентов одновременно, устанавливая оборудование для автомойки за дополнительную плату или добавляя станции зарядки электромобилей для привлечения рынка электромобилей. Отслеживайте репутацию станции на основе справедливости цен, времени доступности и удовлетворенности клиентов, чтобы станции с лучшей репутацией выделялись на карте и привлекали больше посетителей.
Интеграция HUD и индикатор топлива
Индикатор топлива , это постоянный элемент HUD, который игроки видят постоянно, поэтому он должен быть визуально чистым и ненавязчивым, при этом передавать важную информацию с первого взгляда. Разработайте минималистичный индикатор топлива, расположенный рядом со спидометром или в углу экрана, показывающий текущий уровень топлива в виде полукругового индикатора, вертикальной шкалы или простого процента. Используйте цветовую кодировку: зелёный , уровень топлива выше 50%, жёлтый , умеренный уровень от 20% до 50%, красный , критически низкий уровень ниже 20%. Когда топливо опускается ниже 15%, запускайте периодический звуковой сигнал низкого топлива и мигание индикатора, чтобы игрок не забыл заправиться. Показывайте примерный оставшийся пробег, рассчитываемый делением оставшегося топлива на средний расход за последние несколько минут езды. Полностью скрывайте индикатор топлива, когда игрок пешком, чтобы уменьшить загромождение HUD, и плавно показывайте его при посадке в транспорт. Для игроков, предпочитающих минималистичный HUD, предложите настройку полного скрытия индикатора с показом только временного уведомления при достижении настраиваемого порога топлива. Интегрируйте индикатор с другими элементами HUD транспорта, такими как спидометр и состояние двигателя, для создания цельной приборной панели.
Производительность и синхронизация
Топливная система работает непрерывно на каждом клиенте, управляющем транспортом, поэтому оптимизация производительности критична. Используйте интервал обновления расхода в 1000 миллисекунд вместо обновления на каждом кадре, так как изменения топлива происходят достаточно медленно, и обновления раз в секунду визуально неотличимы от обновлений на каждом кадре, при этом потребляя примерно в 60 раз меньше ресурсов. Храните значения топлива в entity state bags, а не в пользовательских сетевых событиях, так как state bags оптимизированы для часто меняющихся значений и синхронизируются только при изменении. При сохранении топлива в базе данных для сохранения между перезапусками сервера объединяйте все обновления топлива транспортных средств в один запрос, выполняемый каждые 60 секунд, вместо записи каждого изменения отдельно. Используйте сетевой ID транспортного средства как ключ для отслеживания топлива и очищайте данные о топливе для несуществующих транспортных средств, чтобы избежать раздувания базы данных. Обрабатывайте крайний случай, когда транспорт меняет сетевого владельца во время заправки, проверяя владельца перед применением изменений топлива и используя серверную валидацию всех платежей. Для станций с большим количеством клиентов одновременно реализуйте систему очереди, которая не позволяет двум игрокам одновременно использовать один и тот же насос, показывая визуальный индикатор занятости.