Stable, versioned entry point for other Project Zomboid mods to feed their vehicles into Better Vehicle Dynamics (BVD). Register typed Lua tables instead of editing fragile sandbox strings.
BVD (created on load; safe to BVD = BVD or {} before use).BVD.API_VERSION → number. Currently 1. Bumped only on a breaking change to the documented surface, with a deprecation period.error(). Bad input is rejected with a single [BVD.API] WARNING: log line — a misbehaving pack can only reduce its own coverage, never break another mod's file load.hp → engine force and mass_kg → mass are applied at world start, and only while the Reference power & weight sandbox option is enabled and the BVD Java component is installed. Registration always succeeds for a well-formed entry even if PZ never loads that script — it simply no-ops at apply time.BVD = BVD or {}
Events.OnGameBoot.Add(function()
BVD.registerVehicle("MyMod.ExampleRoadster", {
hp = 240, -- number > 0, applied as engine force
mass_kg = 1450, -- number > 0, applied as vehicle mass
cargo = 260, -- accepted + validated, RESERVED (not applied in API v1)
})
end)
scriptName is the PZ vehicle script full type (e.g. "MyMod.ExampleRoadster"). Returns the stored entry on success, or nil if the entry was skipped (a single warning is logged).
BVD.registerVehicles({
["MyMod.ExampleRoadster"] = { hp = 240, mass_kg = 1450 },
["MyMod.ExampleHauler"] = { hp = 180, mass_kg = 3200 },
})
Each entry is validated independently; a bad one is skipped without affecting the others.
For "here is my whole table" — convenience wrapper:
BVD.registerPack("mymod_vehicles", {
["MyMod.ExampleRoadster"] = { hp = 240, mass_kg = 1450 },
}, {
check = function() return true end, -- optional; should this pack apply?
priority = 0, -- optional; higher applied last (wins conflicts)
source = "mymod", -- optional; informational log tag
})
Lower-level form (inline table or a require-path to a data module that returns { [fullType] = entry }):
BVD.Packs.register("mymod_vehicles", {
data = "MyMod_VehicleData", -- or an inline table
check = function() return true end,
priority = 0,
source = "bundled",
})
Pack registration is idempotent on name: the first registration for a name wins; a duplicate name is ignored with one info line. Pick a unique, namespaced pack name.
local data = BVD.getVehicleData("MyMod.ExampleRoadster") -- table | nil
local all = BVD.getRegisteredVehicles() -- live table; DO NOT mutate
local v = BVD.API_VERSION -- number