Garages
Garages
Properties can store vehicles. There are two flavours: a garage point (a spot that opens a store/retrieve menu) and a full IPL garage (a walk-in garage interior with your cars physically parked and displayed across floors).
Garage capacity
Each property has garageSlots (default Config.PropertyDefaults.garageSlots =
2). Fitting a garage can be charged via Config.FeaturePricing.garage, and the
minimum is floored for employee-set fit-outs.
Garage points (store / retrieve)
A garage point is placed in the world (the placement previews a ghost vehicle,
Config.GaragePreviewVehicle = sultan).
- Drive up / walk to the garage point.
- Choose Store vehicle (parks your current car) or pick a listed vehicle to retrieve it.
- An empty garage tells you so; a full garage respects the slot cap.
Vehicle display names come from Config.VehicleList in
shared/config_vehicles.lua:
Config.VehicleList = {
-- [`spawnname`] = "Display Name",
['sultan'] = 'Karin Sultan',
}IPL garages (physical, multi-floor)
For a richer experience, a property can use an IPL garage, a real garage interior you walk into, with your vehicles physically parked and displayed.
- Entering plays a short garage entry cutscene/camera, then reveals the interior with your cars parked on display.
- Vehicles are laid out across floors/pages, retrieve by walking up to the car, and drive out through the garage exit.
- IPL garages are priced up with
Config.Garage.IplPriceMult(2.0) relative to a standard garage.
Config.Garage = {
IplPriceMult = 2.0, -- price multiplier for IPL-mode garages
}IPL garages reuse the same instancing model as other IPL/shell interiors, each occupant is in their own routing bucket, so your parked cars are yours alone.
Setting up a garage
- Add a garage to a property from the creation wizard (garage slots field) or place a garage point afterward.
- The wizard's garage placement previews a vehicle ghost so you can align the parking spot.
External garage resources
By default the [E] at a garage point opens the built-in menu. You can hand it to a garage resource you already run instead:
-- shared/garage.lua
Config.Garage = {
IplPriceMult = 2.0,
UseExternal = true,
-- 'auto' | 'kartik-garages' | 'op-garages' | 'jg-advancedgarages'
Provider = 'auto',
}UseExternal = trueswitches the garage point over to the provider.Provider = 'auto'uses whichever supported garage resource is started. If several are running, it picks the first alphabetically and prints a warning in the console. Set a name to pin one.- If no provider is running, the built-in menu is used, so the key always works.
- The property still decides access and the slot cap before the handoff. A player without access gets nothing, and parking into a full garage is refused.
Vehicles parked this way are saved with garage = 'kp_prop_<propertyId>' and
state = 'garage'.
Making your garage script understand property garages
A stock garage script doesn't know what kp_prop_12 is, so a car parked at home
looks lost. The external garage API exports
fix that without touching our tables:
-- in your garage resource (server)
if exports['kartik-properties']:IsPropertyGarage(vehicle.garage) then
local g = exports['kartik-properties']:GetPropertyGarage(vehicle.garage)
garageLabel = g.label -- "Mirror Park #4"
garageCoords = g.coords -- { x, y, z, w }
end
-- list a player's home garages next to the public ones
for _, g in ipairs(exports['kartik-properties']:GetPropertyGarages(cid)) do
addGarage(g.garageId, g.label, g.coords)
endAdding another provider
Providers are small client files in bridge/garage/client/. Copy one and register
it under the resource's name:
local RES = 'my-garages'
KPGarage = KPGarage or {}
KPGarage.providers = KPGarage.providers or {}
KPGarage.providers[RES] = {
resource = RES,
Available = function() return GetResourceState(RES) == 'started' end,
-- ctx = { garageId, label, coords = {x,y,z,w}, used, slots, canPark }
Open = function(ctx)
exports[RES]:OpenGarage(ctx.garageId, ctx.coords)
end,
-- called instead of Open when the player is in a vehicle
Park = function(ctx, vehicle)
exports[RES]:StoreVehicle(ctx.garageId, vehicle)
end,
}