Controlling drive-by shooting on a FiveM server
SetPlayerCanDoDriveBy(PlayerId(), false) turns off aiming and shooting from vehicles for the local player; it is a toggle, not a per-frame call. For driver-only rules, check GetPedInVehicleSeat(vehicle, -1) and flip the toggle when the player changes seat. Finer rules, such as weapon allow lists or speed limits, disable the vehicle aim and attack controls (68, 69, 70, 91, 92) per frame. Mounted guns are separate: use DisableVehicleWeapon. Back it up on the server with a weaponDamageEvent check.
Drive-bys are the fastest way to turn a roleplay chase into a one-sided shooting gallery. A driver who can steer at full speed while emptying an SMG out of the window has no reason to ever stop the car, and police chases stop being about driving. Most servers do not want drive-bys gone entirely, they want them fair: passengers can shoot, drivers drive.

#What counts as a drive-by
In GTA terms a drive-by is any aiming or shooting a ped does while seated in a vehicle: leaning out of a car window with a pistol, firing an SMG from a motorbike, or shooting from a boat. The native reference for SetPlayerCanDoDriveBy notes that it also covers the middle-finger taunt, since that uses the same in-vehicle aiming system.
Two things look similar but are not drive-bys:
- Vehicle weapons, such as the mounted guns on armed vans, jeeps and helicopters, or the cannon on a tank. These belong to the vehicle and are handled with vehicle weapon natives.
- Shooting while standing on a vehicle, for example from the back of a truck bed while not seated. That is normal on-foot shooting.
Decide which you want before writing code. "No drive-bys" on a roleplay server almost always means "drivers may not shoot"; on a PvP server it might mean the opposite.
#Turning drive-bys off completely
The simplest rule is one call. The native is a toggle for the player, so run it once when the player spawns rather than in a per-frame loop.
AddEventHandler('playerSpawned', function()
SetPlayerCanDoDriveBy(PlayerId(), false)
end)
CreateThread(function()
SetPlayerCanDoDriveBy(PlayerId(), false)
end)The second block covers the resource being restarted while players are already in the game. Frameworks with their own spawn events (esx:playerLoaded, QBCore:Client:OnPlayerLoaded) work just as well; the point is to set it once per session and after anything that might reset the player.
#Blocking drivers, allowing passengers
The common roleplay rule checks the seat. The driver's seat index is -1; passengers are 0 and up. Poll a few times a second and flip the toggle only when the answer changes.
local allowed = true
local function setDriveBy(state)
if state ~= allowed then
allowed = state
SetPlayerCanDoDriveBy(PlayerId(), state)
end
end
CreateThread(function()
while true do
local ped = PlayerPedId()
local vehicle = GetVehiclePedIsIn(ped, false)
if vehicle ~= 0 and GetPedInVehicleSeat(vehicle, -1) == ped then
setDriveBy(false)
else
setDriveBy(true)
end
Wait(250)
end
end)A quarter of a second is fast enough that nobody can shuffle into the driver's seat and fire before the rule catches up, and slow enough to cost nothing. If you also block seat shuffling, that window disappears entirely.
#Weapon allow lists and speed limits
The toggle is all or nothing. For finer rules, leave drive-bys enabled and disable the in-vehicle aim and fire controls on frames where the rule says no.
| Index | Control | Default key |
|---|---|---|
| 68 | INPUT_VEH_AIM | Right mouse |
| 69 | INPUT_VEH_ATTACK | Left mouse |
| 70 | INPUT_VEH_ATTACK2 | Right mouse |
| 91 | INPUT_VEH_PASSENGER_AIM | Right mouse |
| 92 | INPUT_VEH_PASSENGER_ATTACK | Left mouse |
Vehicle combat controls
This example lets passengers shoot only pistols and SMGs, and blocks everyone above 80 km/h:
local ALLOWED_GROUPS = {
[`GROUP_PISTOL`] = true,
[`GROUP_SMG`] = true,
}
local MAX_SPEED = 80.0 / 3.6 -- km/h to m/s
local function blockVehicleCombat()
DisableControlAction(0, 68, true)
DisableControlAction(0, 69, true)
DisableControlAction(0, 70, true)
DisableControlAction(0, 91, true)
DisableControlAction(0, 92, true)
end
CreateThread(function()
while true do
local ped = PlayerPedId()
local vehicle = GetVehiclePedIsIn(ped, false)
if vehicle == 0 then
Wait(500)
else
local weapon = GetSelectedPedWeapon(ped)
local group = GetWeapontypeGroup(weapon)
local tooFast = GetEntitySpeed(vehicle) > MAX_SPEED
if not ALLOWED_GROUPS[group] or tooFast then
blockVehicleCombat()
end
Wait(0)
end
end
end)The loop only runs every frame while the player is inside a vehicle and sleeps otherwise. Weapon groups come from the Group field in weapons.meta, so an add-on SMG with GROUP_SMG is allowed automatically. Note that the machine guns in vanilla GTA are in GROUP_MG, not GROUP_SMG, so they stay blocked here.
Combining this with the driver-only rule from the previous section is straightforward: turn the toggle off for drivers and run the control loop for passengers.
#Disabling mounted vehicle weapons
Armed vehicles have their own weapons, named VEHICLE_WEAPON_..., for example VEHICLE_WEAPON_TANK, VEHICLE_WEAPON_TURRET_INSURGENT and VEHICLE_WEAPON_PLAYER_BUZZARD. SetPlayerCanDoDriveBy is about hand-held weapons, so handle mounted guns separately. DisableVehicleWeapon(disabled, weaponHash, vehicle, owner) turns a specific one off for a specific ped.
local BLOCKED = {
`VEHICLE_WEAPON_TANK`,
`VEHICLE_WEAPON_PLAYER_BUZZARD`,
`VEHICLE_WEAPON_TURRET_INSURGENT`,
`VEHICLE_WEAPON_TURRET_TECHNICAL`,
}
CreateThread(function()
local lastVehicle = 0
while true do
local ped = PlayerPedId()
local vehicle = GetVehiclePedIsIn(ped, false)
if vehicle ~= 0 and vehicle ~= lastVehicle and DoesVehicleHaveWeapons(vehicle) then
for i = 1, #BLOCKED do
DisableVehicleWeapon(true, BLOCKED[i], vehicle, ped)
end
end
lastVehicle = vehicle
Wait(500)
end
end)Most roleplay servers simply do not allow armed vehicles to be spawned or bought, which is the more robust fix. The native is useful when a vehicle is needed for its looks, a police Insurgent for example, without its turret.
#Middle-finger taunts and unarmed drive-bys
Because the same system drives the in-vehicle taunt, disabling drive-bys also stops players flipping each other off from a car. If you want the taunt but not the guns, use the control-based approach and only block while a weapon is selected (GetSelectedPedWeapon(ped) ~= WEAPON_UNARMED). The ped config flag reference also lists flag 123 as DisableUnarmedDrivebys, which targets the unarmed side on its own.
#Backing it up on the server
Everything above runs on the client, so a modified client can ignore it. With OneSync the server can see who is in which seat, and weaponDamageEvent fires before damage is applied, which is enough to reject hits from drivers.
AddEventHandler('weaponDamageEvent', function(sender, data)
local ped = GetPlayerPed(sender)
if ped == 0 then return end
local vehicle = GetVehiclePedIsIn(ped, false)
if vehicle ~= 0 and GetPedInVehicleSeat(vehicle, -1) == ped then
CancelEvent()
print(('[driveby] blocked damage from driver %s (%s)'):format(GetPlayerName(sender), sender))
end
end)Log before you punish. Ramming, explosions and a few edge cases involving vehicle weapons can produce damage events from drivers that are not drive-bys, so watch the log for a week before turning it into an automatic kick. The wider pattern is in server-side weapon validation.
#Testing each rule
Drive-by rules are easy to get subtly wrong, because the same player moves between seats, vehicles and weapons constantly. Walk through these with a second player:
- Driver, pistol drawn. Aim with right mouse. Nothing should happen, and no shots should fire with left mouse.
- Passenger, same pistol. Aiming and shooting should work. Swap seats with the driver and confirm the rules follow the seat, not the person.
- Passenger, blocked weapon. Select a rifle or machine gun and confirm it cannot fire from the car.
- Speed limit. Accelerate past the limit as a passenger and confirm shooting stops, then slows back under it.
- Motorbike. Ride alone and with a pillion to see what your bike rule does.
- Armed vehicle. Enter a vehicle with a mounted gun and confirm the turret is disabled for the seats you blocked.
- Server log. Check the server console for
[driveby]lines from the test, which proves the server-side check sees drivers correctly.
If step 1 fails but the others pass, another resource is probably calling SetPlayerCanDoDriveBy(PlayerId(), true) after yours. Search your resources for the native; old framework scripts and HUDs sometimes set it on spawn.
#Roleplay rules that work alongside the script
- Write it in the rules. Players accept a script that enforces a written rule far better than one that silently blocks them.
- Give passengers a reason to exist. Drive-by rules make a second person in the car valuable, which is good for group roleplay.
- Think about police. Some servers let police passengers return fire but not civilians; that is a job check around the same code.
- Pair it with aiming rules. First-person-only aiming in vehicles is a popular companion setting, covered in forcing first-person aiming.
Questions
How do I disable drive-by in FiveM?
SetPlayerCanDoDriveBy(PlayerId(), false) on the client once per session. It is a toggle, so it does not need to run every frame.How do I let passengers shoot but not drivers?
GetPedInVehicleSeat(vehicle, -1) is the player's ped and toggle SetPlayerCanDoDriveBy off for drivers and on for everyone else.Which controls are used for shooting from a vehicle?
How do I disable the guns on armed vehicles?
DisableVehicleWeapon(true, weaponHash, vehicle, ped) with the vehicle weapon's hash, such as VEHICLE_WEAPON_TANK, or do not allow armed vehicles to be spawned.Can a cheater bypass a drive-by script?
weaponDamageEvent that cancels damage coming from a player sitting in the driver's seat.Ready to pick a map?
Twelve themes on three base map styles, $8 each, instant download.
Relevant to what you just read
Look it up while you work
The reference tables this guide leans on, free and without an account.
- All 921 vehicle spawn namesEvery vanilla model with a picture, its display name, its class and the hash CreateVehicle takes.