Garages
Property garages are stored in world_housing_garages and opened through a detected garage script. Housing owns the world interaction (ox_lib zones). External garage resources are only used for open / store / backend via their public events or exports.
Feature flag: Config.Features.garages.
Architecture
- Player places (or re-places) access + spawn points near the house.
- Housing writes one row per property in
world_housing_garages. - The active provider registers backend identity if needed (
housing_{housingId}). - Housing creates a client sphere zone at the access coords (
InteractDistance). - [E] on foot opens the garage; [E] in a vehicle stores it — forwarded to the provider.
Place / replace → DB (one garage per housing_id)
→ Provider Register / Update (backend only)
→ Housing ox_lib zone (world interact)
→ Open / store via provider export or eventqbx_garages is not supported: it has no safe unregister / replace API for client zones without patching that resource.
Flow
- Owner buys the GARAGE upgrade in Housing Central (requires a compatible provider).
- Placement starts automatically (or via Create garage action).
- Step 1 — Stand at the interaction point → [E] (access marker, Z offset −0.9).
- Step 2 — Stand where vehicles should spawn, face exit → [E] (preview vehicle).
- [ENTER] confirms · [BACKSPACE] cancels.
- Stay within
Config.Garage.MaxDistanceFromHouseof the house exterior.
TextUI stays visible for the whole placement (including after leaving the interior).
Replacing a garage
Placing again on the same property updates the existing garage (it does not stack a second one):
- DB row for that
housing_idis updated; duplicates are removed. - Housing removes the old zone and creates one at the new access coords.
- Provider
Updateruns (backend sync only — no second world interact from housing).
Shared garage
SHARED_GARAGE unlocks shared vehicle access for keyholders with the GARAGE privilege. It only appears when the active provider supports shared garages (cd_garage, RxGarages).
Supported providers
Detection order when Config.Garage.System = "auto" (first started resource wins):
| Resource | Shared | Client zones | Register / Update | Open / store |
|---|---|---|---|---|
qb-garages | no | yes | Syncs house garage data (addHouseGarage) | setHouseGarage + OpenHouseGarage / store bridge |
jg-advancedgarages | no | yes | Validation only | open-garage / store-vehicle events |
cd_garage | yes | yes | PropertyGarage:Create once per property; update does not re-Create | PropertyGarage:Open / PropertyGarage:StoreVehicle |
okokGarage | no | yes | DB row replace by garagename | OpenPrivateGarageMenu / StoreVehiclePrivate |
rcore_garage | no | yes | Validation only | OpenGarageOnSpot / StoreMyVehicle |
zerio-garage | no | yes | Validation only | Server open/store → Zerio exports |
RxGarages | yes | yes | Validation only | OpenGarage / ParkVehicle exports |
vms_garagesv2 | no | yes | registerHousingGarage | enterHouseGarage |
All kept providers use housing client zones (needsClientZones = true). Players interact with the housing zone, not a second marker owned by the garage script (when the provider allows that).
Force a provider (or leave auto detection):
Config.Garage.System = "auto" -- or a provider name from the table aboveConfig
Config.Garage = {
System = "auto",
MaxDistanceFromHouse = 40.0,
InteractDistance = 5.0,
DetectOrder = {
"qb-garages",
"jg-advancedgarages",
"cd_garage",
"okokGarage",
"rcore_garage",
"zerio-garage",
"RxGarages",
"vms_garagesv2",
},
}| Option | Description |
|---|---|
System | "auto" or a resource name from the table above |
MaxDistanceFromHouse | Max distance from house while placing |
InteractDistance | Housing zone radius for open / park after creation |
DetectOrder | Priority list for auto detection |
Parking / opening
- Walk to the housing access zone → ox_lib TextUI (
GARAGE_ZONE_HINT) → E to open or park. - Garage id / name pattern:
housing_{housingId}. - Access check:
HasHousingAccess(stateId, housingId, "GARAGE")(owners always pass); also requires the GARAGE upgrade.
Garage limit (VEHICLES)
Property creator stores a Garage Limit in property_settings.VEHICLES. That value is property metadata only; the housing garage adapters do not currently enforce a max vehicle count when parking. Limits, if any, come from the active garage script itself.
Export
local garage = exports["prp-housing-v2"]:GetClosestGarage()
-- or exports["prp-housing-v2"]:GetClosestGarage(coords)Returns the nearest garage the player may use (or closest without access check when skip flag is used internally). Integrate from vehicle scripts as needed.
Editable providers
Adapter files live in server/garage/providers/*.lua. Client zone + open/store routing: client/garage/zones.lua. Shared detection meta: shared/garage/provider.lua. All are covered by escrow_ignore — see Editable files.