Documentation

Setup

Install and configure Wheel Pop.

#Standalone Installation

  1. Install and start the latest zyke_lib.
  2. Download Wheel Pop and keep the folder name zyke_wheelpop.
  3. Add the item definitions from extras/items to your inventory and copy the included images.
  4. Configure shared/unlocked/config.lua.
  5. Add the resources to server.cfg in this order:
cfg
ensure zyke_lib
ensure zyke_wheelpop

Realistic Vehicles and Vehicle Terrain are not required.

The default items are:

ItemPurpose
wheel_scannerOpens the wheel integrity overview.
vehicle_wheelStores a picked-up loose wheel and its fitment metadata.
tirekitRepairs the nearest damaged or failed wheel.

#Using All Three Resources

When Realistic Vehicles is also started, it combines the missing-wheel penalty with engine-damage torque handling. Vehicle Terrain coordinates its handling baseline through optional exports. Each resource can run on its own and shares handling data when used together.

Use this order when installing all three:

cfg
ensure zyke_lib
ensure zyke_vehicleterrain
ensure zyke_wheelpop
ensure zyke_realisticvehicles

#Persistence

Wheel state is replicated through the wheelLoss vehicle state bag. GetWheelLossData(vehicle) and SetWheelLossData(vehicle, data) save and restore both failed-wheel entries and per-wheel integrity.

The state bag keeps the data synchronized while the vehicle exists. Owned vehicles need the framework property integration below to retain it after parking, despawning, or restarting the server.

Use this standalone zykeWheelLoss integration when running Wheel Pop without Realistic Vehicles.

If both resources are installed, do not add both property integrations. Follow the Realistic Vehicles persistence setup instead; its zykeRealisticVehicles payload already includes Wheel Pop data.

#ESX

Open es_extended/client/functions.lua.

Reference points:

Add zykeWheelLoss to the table returned by ESX.Game.GetVehicleProperties:

diff
         modWindows = GetVehicleMod(vehicle, 46),
         modLivery = GetVehicleMod(vehicle, 48) == -1 and GetVehicleLivery(vehicle) or GetVehicleMod(vehicle, 48),
         modLightbar = GetVehicleMod(vehicle, 49),
+        zykeWheelLoss = exports["zyke_wheelpop"]:GetWheelLossData(vehicle),
     }
 end

Apply it in ESX.Game.SetVehicleProperties after ESX restores props.tyreBurst, before the function closes:

diff
     if props.tyreBurst ~= nil then
         for k, v in pairs(props.tyreBurst) do
             if v then
                 k = tonumber(k)
                 if k then
                     SetVehicleTyreBurst(vehicle, k, true, 1000.0)
                 end
             end
         end
     end
+
+    if (props.zykeWheelLoss ~= nil) then
+        exports["zyke_wheelpop"]:SetWheelLossData(vehicle, props.zykeWheelLoss)
+    end
 end

#QBCore

Open qb-core/client/functions.lua.

Reference points:

Add zykeWheelLoss to the table returned by QBCore.Functions.GetVehicleProperties:

diff
             modLivery = modLivery,
             modKit49 = GetVehicleMod(vehicle, 49),
             liveryRoof = GetVehicleRoofLivery(vehicle),
+            zykeWheelLoss = exports["zyke_wheelpop"]:GetWheelLossData(vehicle),
         }
     else
         return
     end
 end

Apply it in QBCore.Functions.SetVehicleProperties after the existing vehicle properties, before the outer end:

diff
         if props.liveryRoof then
             SetVehicleRoofLivery(vehicle, props.liveryRoof)
         end
+        if (props.zykeWheelLoss ~= nil) then
+            exports["zyke_wheelpop"]:SetWheelLossData(vehicle, props.zykeWheelLoss)
+        end
     end
 end

#Qbox / ox_lib

Open ox_lib/resource/vehicleProperties/client.lua.

Reference points:

Add zykeWheelLoss to the table returned by lib.getVehicleProperties:

diff
             tyres = damage.tyres,
             bulletProofTyres = GetVehicleTyresCanBurst(vehicle),
             driftTyres = gameBuild >= 2372 and GetDriftTyresEnabled(vehicle),
+            zykeWheelLoss = exports["zyke_wheelpop"]:GetWheelLossData(vehicle),
             -- no setters?
             -- leftHeadlight = GetIsLeftVehicleHeadlightDamaged(vehicle),

Apply it in lib.setVehicleProperties after fixVehicle, before the final return:

diff
     if fixVehicle then
         SetVehicleFixed(vehicle)
     end
+
+    if (props.zykeWheelLoss ~= nil) then
+        exports["zyke_wheelpop"]:SetWheelLossData(vehicle, props.zykeWheelLoss)
+    end

     return not NetworkGetEntityIsNetworked(vehicle) or NetworkGetEntityOwner(vehicle) == cache.playerId
 end

For Qbox persistence, also add the property to watchedKeys in qbx_core/client/vehicle-persistence.lua:

diff
 local watchedKeys = {
     'bodyHealth',
     'engineHealth',
     'tankHealth',
     'fuelLevel',
     'oilLevel',
     'dirtLevel',
     'windows',
     'doors',
     'tyres',
+    'zykeWheelLoss',
 }

Finally, copy the changed property into the stored vehicle properties in qbx_core/server/vehicle-persistence.lua before SaveVehicle:

diff
     if diff.tyres then
         props.tyres = diff.tyres ~= 'deleted' and diff.tyres or nil
     end
+
+    if diff.zykeWheelLoss then
+        props.zykeWheelLoss = diff.zykeWheelLoss ~= 'deleted' and diff.zykeWheelLoss or nil
+    end

     exports.qbx_vehicles:SaveVehicle(vehicle, {
         props = props,
     })