How to Build an ox_core Carwash Resource (the Fast Way)
A carwash is one of the best "first real resource" projects for a FiveM roleplay server. It touches almost everything you'll reuse later — a targeted interaction zone, a server-authoritative payment, a timed action with a progress bar, and a visible change to the player's vehicle. Build one well on the ox_overextended stack and you understand the patterns behind half the economy scripts on your server.
This guide walks the manual path first, then shows how to generate the same thing in seconds with myRP.build.
What a carwash resource actually needs
Strip away the fluff and a carwash is four moving parts:
- An interaction point — usually an
ox_targetbox zone at the carwash location so players get a contextual "Wash Vehicle" option only when they're in a vehicle inside the zone. - A server-side payment — the cost has to be charged through
ox_coremoney on the server, never the client. Client-side money checks are trivially exploitable. - A timed action with feedback — an
ox_libprogressBar(orprogressCircle) so the wash takes a few seconds and can be cancelled if the player drives off or gets out. - The actual wash — calling the GTA V native that resets the vehicle's dirt level so the car visibly comes out clean.
That's the whole contract. The hard part is wiring it together correctly and keeping the trust boundary on the server.
The manual approach
A correct manual build looks roughly like this.
1. Register the target zone (client). Add a box zone at the carwash with ox_target:
exports.ox_target:addBoxZone({
coords = vec3(26.5, -1392.0, 29.5),
size = vec3(6, 6, 4),
rotation = 20,
options = {
{
name = 'myrp_carwash',
icon = 'fa-solid fa-car',
label = 'Wash Vehicle',
canInteract = function()
return cache.vehicle ~= nil
end,
onSelect = function()
TriggerServerEvent('myrp_carwash:requestWash')
end,
},
},
})2. Validate and charge on the server. The server is the only place money is touched. Check the player can afford it, remove the funds, then tell the client to proceed:
RegisterNetEvent('myrp_carwash:requestWash', function()
local player = Ox.GetPlayer(source)
if not player then return end
local price = 150
if player.getAccount('money').balance < price then
return TriggerClientEvent('ox_lib:notify', source, {
type = 'error', description = 'Not enough cash',
})
end
player.removeAccountMoney('money', price, 'Carwash')
TriggerClientEvent('myrp_carwash:doWash', source)
end)3. Run the progress bar and clean the car (client). Only after the server confirms payment:
RegisterNetEvent('myrp_carwash:doWash', function()
if lib.progressBar({
duration = 6000,
label = 'Washing vehicle...',
canCancel = true,
disable = { move = true, car = true },
}) then
local veh = cache.vehicle
if veh then SetVehicleDirtLevel(veh, 0.0) end
end
end)4. Write the fxmanifest.lua. Declare the ox_lib dependency, the @ox_lib/init.lua shared import, and your client/server files in the right order.
None of this is exotic — but every step has a place to get it wrong: charging on the client, forgetting canCancel, mismatched event names, a manifest that loads ox_lib too late, or a dirt-level native that silently no-ops because you passed the wrong handle. A first-timer can easily lose an evening on it.
Generating it with myRP.build
myRP.build is a Windows desktop app that turns a plain-English description into a complete, ox-native resource written straight to your server — manifest, server, client, and config, with the trust boundary already in the right place. It targets ox_overextended exclusively, so you never get ESX or QBCore patterns bolted onto an ox server.
A prompt as simple as this is enough:
Build a carwash resource. Add an ox_target box zone at the Davis carwash. When a player in a vehicle interacts, charge $150 through ox_core on the server, run a 6-second ox_lib progress bar, then clean the vehicle. Cancel if they leave the car.
What you get back is the same four-part structure above — fxmanifest.lua with the ox_lib dependency, a server file that validates the player and removes money via ox_core, a client file with the ox_target zone and ox_lib progress bar, and a small config.lua for the location and price. Because it's written directly to your resources folder, you can ensure it and test it immediately, then tweak the config.
The point isn't to skip understanding the patterns — it's to stop hand-typing the same boilerplate every time you build the next ATM, fishing spot, or mechanic job. The patterns in this carwash repeat across your whole server.
If you want to try it on your own server, download myRP.build for Windows and point it at your resources folder, or read the docs first to see how generation and config work. Either way, your next economy script can be a one-paragraph prompt instead of a lost evening.