ATY Scripts Logo
ATY Scripts/Dokümanlar/Garage V2/Garage V2

Garage V2

aty_garage_v2

Full-featured multi-framework garage system: public/private/manageable/job/impound/lost-vehicle garages, pre-built IPL interior garages, park-in-place persistence, vehicle insurance, key sharing, shared-garage members, ps-housing house garages, and a police fine/impound workflow — all driven by a Vue NUI and the aty_lib framework bridge.

Info

Resource name aty_garage_v2
Frameworks ESX / QBCore / Qbox (via qbx_core qb-core compat bridge) — detected through aty_lib
Database MySQL (oxmysql/mysql-async, via aty_libmodules.ExecuteSql)

Dependencies

Dependency Required Notes
aty_lib Yes (declared in fxmanifest.lua) Framework bridge: getModules(), getUtils(), getShared() — SQL helper, callbacks (modules.RegisterCallback/TriggerCallback), notifications, identifiers, player job/gang lookup
qb-core / es_extended / qbx_core One of these Framework detected via Utils.Framework ('qb-core' or 'es_extended'); Qbox works through its qb-core compat layer
ox_target or qb-target Optional Only needed if Config.Interaction = 'target'. Auto-detected; falls back to marker mode if neither is running
ps-housing Optional Only needed if Config.Housing.enabled = true — reads its properties table for house garages
okokBilling / esx_billing / qb phone_invoices Optional Used by the police billing bridge (server/billing.lua) when Config.Police.billing = 'auto' (or a specific mode)

Installation

  1. Copy the aty_garage_v2 folder into your resources (e.g. [aty]/aty_garage_v2).

  2. No manual SQL import is required — on first start the resource runs CREATE TABLE IF NOT EXISTS statements itself (in server/main.lua) for all of its tables: aty_garages, aty_garage_ipls, aty_garage_vehmeta, aty_garage_members, aty_garage_keys, aty_garage_parked, aty_garage_fines, aty_garage_impounds. It also auto-migrates a few legacy columns (e.g. adds gang/gang_grade to aty_garages, stored_at/insurance_until/destroyed to aty_garage_vehmeta if missing). It reads/writes vehicle ownership from your framework's existing table: player_vehicles (QBCore) or owned_vehicles (ESX).

  3. Add to server.cfg, making sure aty_lib starts first:

    ensure aty_lib
    ensure aty_garage_v2
    
  4. Configure shared/config.lua (client + server visible) and server/config.lua (server-only — Discord webhook settings; never sent to clients).

  5. If using the pre-built IPL garages, verify/adjust the interior coordinates for your server with the /iploc and /iplhere diagnostic commands (see Commands), then place the actual menu/preview/spawn/zone points per IPL with /garageipl.

  6. Create garages in-game with /garageadmin (or the command configured in Config.AdminCommand).

Configuration

shared/config.lua — General

Option Type Default Description
Debug boolean false Debug flag (used sparingly in code)
Language string 'en' Active locale ('en' | 'tr'), loaded from locales/<lang>.lua; missing keys fall back to EN via locales/loader.lua

Interaction

Option Type Default Description
Interaction string 'target' 'marker' (3D marker + key prompt) or 'target' (ox_target/qb-target zones, auto-detected; falls back to marker if no target resource is running)
TargetIcons table { open, enter, store, buy, impound } FontAwesome icon per target action (keys: open, enter, store, buy, impound)
InteractionKey number 38 (E) Key to open/interact in marker mode
InteractionDistance number 3.0 Distance to open a garage menu / enter an IPL
StoreDistance number 8.0 Distance (in a vehicle) to store/park
MarkerDrawDistance number 15.0 Distance at which world markers are drawn

Admin

Option Type Default Description
AdminCommand string 'garageadmin' Command that opens the garage creation/admin menu
IplCommand string 'garageipl' Command that opens the IPL interior editor directly
QBPermission string/table { 'admin', 'god' } QBCore permission level(s) for AdminCommand/IplCommand (registered via QBCore.Commands.Add)
ESXGroup string/table { 'admin', 'superadmin' } ESX group(s) for the same commands (registered via ESX.RegisterCommand)
AdminAce string 'aty_garage.admin' Extra ace permission checked as a defense-in-depth layer on admin callbacks
AdminGroups table { admin = true, god = true, superadmin = true } Framework group names accepted by the internal isAdmin() check
PlaceholderVehicle string 'adder' Model shown while placing IPL "Vehicle Spawn" points in the editor

Vehicles & economy

Option Type Default Description
SharedGarages boolean false If true, a vehicle can be taken out directly from any garage regardless of where it was stored
Warp boolean true Auto-warp the player into the vehicle after spawn
VisuallyDamageCars boolean true Re-apply visual damage on spawn
DefaultCapacity number 25 Default garage vehicle capacity
Bring.enabled boolean true Enable "bring vehicle from another garage" (used when SharedGarages = false)
Bring.price number 1500 Fee charged to bring a vehicle
Bring.account string 'bank' Account charged for Bring
Owned.account string 'bank' Account used for private garage purchase/sale
Owned.maxHourlyFee number 100 Cap on the hourly fee an owner can set on their private garage
Owned.sellRefundPercent number 50 Refund percentage when a private garage is sold
JobPlatePrefix string 'JOB' Plate prefix used for job fleet vehicles
Lost.retrieveFee number 2500 Fee to retrieve a "lost" vehicle (not impounded, not destroyed) into a normal garage
Lost.account string 'bank' Account charged for Lost retrieval

Integration hooks

Option Type Default Description
Integrations.getFuel function | nil nil Override fuel read (falls back to aty_lib bridge default); errors are caught with pcall
Integrations.setFuel function | nil nil Override fuel write
Integrations.onVehicleSpawned function | nil nil Called (veh, plate, props) after a vehicle is spawned from a garage
Integrations.onVehicleStored function | nil nil Called (veh, plate, props) right before a stored vehicle's entity is deleted

Event hooks (Config.Hooks, client-side)

Every hook is optional (nil = disabled) and pcall-protected. Each one also fires a Lua event aty_garage_v2:hook:<name> with the same arguments, so other resources can listen with AddEventHandler without editing the config.

Hook Arguments Fired when
onMenuOpen (garage) The garage menu opens
onMenuClose (garage) The garage menu closes
onIplEnter (garage) The player enters an IPL interior
onIplExit (garage) The player exits an IPL interior
onLockpickStart (veh, plate) A lockpick attempt starts (after server validation)
onLockpickSuccess (veh, plate) The lock is picked successfully
onLockpickFail (veh, plate, broke) The attempt fails (broke = lockpick item broke)
onLockpickAlert (coords, plate, veh) Police alert roll passes (Lockpick.alertChance) — wire to your dispatch script, e.g. exports['ps-dispatch']:CarJacking(veh)
onVehicleTaken (veh, plate, props) A vehicle is taken out and spawned
onVehicleStored (veh, plate, props) A vehicle is stored (entity still exists)

Example — dispatch alert without touching the config, from any resource:

AddEventHandler('aty_garage_v2:hook:onLockpickAlert', function(coords, plate, veh)
    exports['ps-dispatch']:CarJacking(veh)
end)

Housing (ps-housing)

Option Type Default Description
Housing.enabled boolean true Enable dynamic house garages generated from ps-housing's properties.garage_data
Housing.script string 'ps-housing' Only 'ps-housing' is currently supported
Housing.capacity number 10 Capacity of each house garage
Housing.rescanInterval number (ms) 300000 Periodic re-scan interval of the properties table
Housing.blip boolean false Whether to show a map blip for house garages

Insurance & vehicle recovery

Option Type Default Description
Insurance.enabled boolean true Enable per-vehicle insurance purchase
Insurance.account string 'bank' Account charged for insurance
Insurance.price number 5000 Policy price
Insurance.durationDays number 7 Policy duration in days (re-purchase extends it)
Insurance.claimFee number 1000 Fee to recover an insured, destroyed vehicle
Insurance.allowUninsured boolean true Whether an uninsured destroyed vehicle can still be recovered (for uninsuredFee)
Insurance.uninsuredFee number 15000 Fee to recover an uninsured destroyed vehicle
Insurance.cancelRefundPercent number 50 Refund percentage (of remaining policy value) on cancellation

Preview camera

Option Type Default Description
Preview.enabled boolean true Enable the vehicle preview camera in garage menus
Preview.dof boolean false Depth-of-field (blur background, keep vehicle sharp)
Preview.camOffset vector3 vec3(4.2, 3.6, 1.5) Camera offset from the previewed vehicle
Preview.fov number 45.0 Camera field of view

Blips

Option Type Default Description
Blip.show boolean true Show garage blips on the map
Blip.sprite number 357 Blip sprite ID
Blip.color number 3 Blip color ID
Blip.size number 0.8 Blip scale
Blip.toggleCommand string 'garageblips' Client command to toggle blip visibility per player (preference persisted in a resource KVP)

Blur (menu background)

Option Type Default Description
Blur.enabled boolean true Enable frosted-glass background blur in the NUI (captured via screenshot-basic + GLSL, not the native blur)
Blur.interval number (ms) 350 Recapture interval — lower = livelier but costs more performance
Blur.settleDelay number (ms) 250 Delay before the first capture after the menu opens (lets the camera settle)

Mileage

Option Type Default Description
Mileage.enabled boolean true Enable client→server mileage tracking/sync
Mileage.syncInterval number (ms) 60000 Client sync interval

Park-in-place

Option Type Default Description
ParkInPlace.enabled boolean true Store vehicles in the world at the spot they were parked instead of despawning them
ParkInPlace.parkRadius number 30.0 Max distance from the garage center a vehicle may be parked
ParkInPlace.spawnDistance number 60.0 Distance at which a nearby player triggers the entity to (re)spawn
ParkInPlace.deleteDistance number 85.0 Distance beyond which the entity is deleted (all players out of range)
ParkInPlace.checkInterval number (ms) 4000 Server-side distance check interval

Police / fines / impound

Option Type Default Description
Police.jobs table { police = true, sheriff = true } Jobs allowed to use fine/impound features
Police.fineKey number 47 (G) Key to open the fine/impound prompt near a parked vehicle
Police.interactDistance number 4.0 Distance for the fine/impound prompt
Police.minFine / Police.maxFine number 50 / 10000 Allowed fine amount range
Police.payAccount string 'bank' Internal collection account (used when no external billing succeeds)
Police.reasons table 4 presets (Illegal Parking 250, Blocking Traffic 400, Abandoned Vehicle 600, Parking on Sidewalk 300) Preset reasons shown in the fine/impound menu (amount editable)
Police.impound.searchRadius number 18.0 Radius to find a target vehicle for impound
Police.impound.defaultEarlyFee number 1500 Fee to release before the set release date
Police.impound.defaultLateFee number 1000 Fee to release after the set release date (normal)
Police.impound.minFee / maxFee number 0 / 100000 Allowed impound fee range
Police.impound.maxDays number 30 Max days in the future for the release date
Police.billing string 'auto' 'auto' (tries okokBilling → esx_billing → qb phone_invoices → internal), or force one of 'okokbilling', 'esx_billing', 'qb', 'internal', 'custom'
Police.society table { name = 'police', account = 'society_police', label = 'LSPD' } Society info passed to the billing bridge
Police.customBill function | nil nil Custom billing hook used when Police.billing = 'custom'; return true if billed externally

IPL interiors — fully in-game, DB-backed

IPL interiors are no longer defined in config (shared/ipls.lua was removed). They live entirely in the aty_garage_ipls table and are created/edited in-game via the IPL editor (/garageipl → dropdown → + Create New Interior). Each record holds its own IPL names to load (ipl_names), interior start point (teleport), menu/enter coordinates, and vehicle spawn slots — all garages sharing an IPL id share those interior points. On first start, known legacy ids (impexp_mid, impexp_large, eclipse_10car, lom_bank) get their ipl_names/teleport seeded automatically if empty.

server/config.lua — Discord logging (server-only, never sent to clients)

Option Type Default Description
Config.Logs.enabled boolean true Master switch for Discord webhook logging
Config.Logs.console boolean true Also print every logged event to the server console
Config.Logs.botName string 'ATY Garage' Webhook embed username
Config.Logs.webhook string (set) Default webhook URL used when a category has none set
Config.Logs.webhooks table (all categories set) Per-category webhook override: vehicle, economy, impound, admin
Config.Logs.colors table blue/green/red/yellow Embed color per category

Security note: the shipped server/config.lua currently has a live Discord webhook URL filled in for the default and every category. Since this file only lives server-side it isn't leaked to clients, but you should still replace it with your own server's webhook(s) (or blank them out) before going live — the checked-in URL should be treated as compromised.

Exports

This resource does not currently register any of its own exports(...) (client or server). All feature access goes through:

  • NUI ⇄ server callbacks via modules.RegisterCallback / modules.TriggerCallback (see Events below for the full callback list — these are internal to the resource's own UI, not meant to be called from other resources).
  • The aty_garage_v2:refreshHouseGarages server event (see Events) as the one documented integration point for ps-housing.

It consumes exports from its dependencies: exports.aty_lib:getModules()/getUtils()/getShared(), and optionally exports['qb-target'] / exports.ox_target and exports['okokBilling']:CreateCustomInvoice(...).

Events

Public integration hook

Event Side Direction Description
aty_garage_v2:refreshHouseGarages Server Trigger into this resource Fire this from ps-housing (or any script) after a house's garage data changes to force an immediate rescan + broadcast, instead of waiting for Housing.rescanInterval

Internal client/server sync (not intended for external use)

Event Side Description
aty_garage_v2:getGarages, getVehicles, takeVehicle, storeVehicle, transferVehicle, getImpoundGarages, issueFine, beginImpound, impoundVehicle, bringVehicle, getLostVehicles, locateVehicle, retrieveLostVehicle, buyInsurance, cancelInsurance, giveKeys, getKeyHolders, revokeKeys, favoriteVehicle, isAdmin, getAdminData, buyGarage, saveGarage, deleteGarage, getIplList, saveIplCoords, sellGarage, transferOwnedGarage, getManageGarage, ejectVehicle, getPurchaseInfo, saveManageGarage, getGarageMembers, addGarageMember, removeGarageMember Server (modules.RegisterCallback) NUI-driven request/response callbacks used by the resource's own client code
aty_garage_v2:client:setGarages Client (RegisterNetEvent) Server pushes the player's currently visible garage list
aty_garage_v2:client:openAdmin Client (RegisterNetEvent) Fired by the server-registered AdminCommand once the framework permission check passes; opens the admin UI
aty_garage_v2:client:openIplEditor Client (RegisterNetEvent) Fired by the server-registered IplCommand; opens the IPL editor UI
aty_garage_v2:client:receiveKeys / aty_garage_v2:client:removeKeys Client (RegisterNetEvent) Notifies a player they were given/revoked persistent keys to a plate
aty_garage_v2:vehicleDestroyed Server (RegisterNetEvent), triggered by client Client reports a park-in-place vehicle exploded, so the server marks it destroyed in aty_garage_vehmeta
aty_garage_v2:server:syncMileage Server (RegisterNetEvent), triggered by client Rate-limited (max once/10s, capped at 30 miles/sync) mileage delta sync
aty_garage_v2:targetReady Client (AddEventHandler/TriggerEvent, local only) Internal signal that target-mode detection finished, used to register target zones/global-vehicle options
QBCore:Client:OnJobUpdate, esx:setJob, QBCore:Client:OnGangUpdate, QBCore:Client:OnPlayerLoaded, esx:playerLoaded Client (listened to, not emitted) Trigger a garage-list refresh on job/gang change or player load

Commands

Command Side Default restriction Description
/garageadmin (Config.AdminCommand) Client (registered server-side) QBCore perms Config.QBPermission (admin, god) / ESX groups Config.ESXGroup (admin, superadmin) Opens the garage creation/admin menu
/garageipl (Config.IplCommand) Client (registered server-side) Same as above Opens the IPL interior editor directly
/garageblips (Config.Blip.toggleCommand) Client None (any player) Toggles the player's own garage blip visibility; preference stored in a resource KVP
/impound Client None enforced at command level; internally requires Config.Police.jobs Opens the impound/fine flow for the vehicle you're in, or the nearest one
/garagedebug Client Admin only Prints interaction mode, target detection, garage count, and the nearest garage's distance/coords to F8
/garageprobe Client Admin only Places a bare test target zone to verify ox_target/qb-target renders options
/iploc [id] [x y z] Client Admin only Loads an IPL and teleports you to its start point (or a candidate x y z) to verify interior coordinates
/iplhere Client Admin only Prints your current coords + interior id to F8 (for picking interior points)

The four diagnostic commands (/garagedebug, /garageprobe, /iploc, /iplhere) are admin-gated: each verifies the caller via the server aty_garage_v2:isAdmin callback (same isAdmin() used everywhere else — ACE Config.AdminAce, framework permissions, or Config.AdminGroups) before running. Non-admins get a "no permission" notification and the command does nothing.

Features

  • Multiple garage types: public, private (purchasable/manageable), job fleet, impound, and "lost vehicle" garages.
  • Framework-agnostic (ESX / QBCore / Qbox) via aty_lib, including job-grade and QBCore gang-grade access locks per garage (ESX has no standard gang system, so job is used instead for gang-style access).
  • Pre-built IPL interior garages (Import/Export mid & large, Eclipse Blvd 10-car, Underground/Lom Bank) with a dedicated in-game editor for menu/preview/spawn/zone points, a showroom of spawned display vehicles, and world-side vehicle spawn slots.
  • Park-in-place persistence: vehicles stay physically parked where stored (frozen/invincible display entity), streamed in/out server-side based on player proximity, and survive restarts via the aty_garage_parked table.
  • Vehicle insurance with configurable policy price/duration, and a "Lost Vehicles" recovery flow for destroyed vehicles (insured claim fee vs. uninsured recovery fee) as well as plain lost (not destroyed, not impounded) vehicles.
  • Persistent key sharing (aty_garage_keys) so another player can take/store a plate without transferring ownership, plus revocation.
  • Shared/manageable garage members (aty_garage_members) for co-owned private garages.
  • Dynamic ps-housing house garages generated from the properties table (never written to aty_garages), periodically rescanned and instantly refreshable via aty_garage_v2:refreshHouseGarages.
  • ox_target / qb-target support with automatic detection and marker-mode fallback.
  • Discord webhook logging split into vehicle, economy, impound, and admin categories, queued to respect Discord rate limits.
  • Vue NUI with category tabs, capacity indicator, and a cinematic vehicle preview camera with optional depth-of-field and a periodically-recaptured frosted blur background.
  • Anti-dupe protections: per-plate operation locks (plateLock) and per-player/action rate limiting (rateOk) around take/store/transfer flows.
  • Vehicle mileage tracking with a rate-limited client→server sync.
  • Police fine and impound workflow for park-in-place vehicles, with configurable reasons/fees/impound duration and a billing bridge that tries okokBillingesx_billing → QBCore phone_invoices → internal collection (or a custom hook).

Troubleshooting

Problem Solution
Garages don't appear / menu won't open Run /garagedebug to check interaction mode, target detection, and the nearest garage's distance/coords. Confirm aty_lib started before aty_garage_v2 in server.cfg.
Target option shows no interaction / no marker If Config.Interaction = 'target' but neither ox_target nor qb-target is running, the resource falls back to marker mode automatically — check /garagedebug output for ox=/qb= resource state. Use /garageprobe to test whether the running target resource renders options at all.
No IPL interiors in the garage/editor dropdown Interiors are DB-backed. Create one in-game: /garageipl → dropdown → + Create New Interior (enter an ID, label, and the IPL names to load, then pick the coordinates). Legacy ids are seeded on first start.
IPL teleport lands in an empty void The teleport (Interior Start Point) of that IPL record doesn't line up with the interior. Re-pick it in the IPL editor, or use /iploc <id> <x> <y> <z> to test candidate coordinates.
House garages missing for a player Check Config.Housing.enabled = true, Config.Housing.script = 'ps-housing', that ps-housing is running, and that the properties row has a non-empty garage_data and a matching owner_citizenid. Trigger aty_garage_v2:refreshHouseGarages server-side to force a rescan instead of waiting for Housing.rescanInterval.
Fines/impound don't bill externally Set Config.Police.billing to a specific mode to isolate the issue, or check that okokBilling/esx_billing is actually started (GetResourceState) or that the phone_invoices table exists for the 'qb' mode. 'auto' silently falls back to internal collection if all external attempts fail.
No Discord logs arriving Check server/config.luaConfig.Logs.enabled and that webhook/webhooks[category] is a valid URL (replace the shipped example webhook with your own). Run the server-console-only /garagelogtest command to confirm delivery, and check Config.Logs.console output for the resolved settings.
Vehicle stuck as "destroyed" / can't retrieve Open the Lost Vehicles menu: insured vehicles pay Insurance.claimFee, uninsured ones pay Insurance.uninsuredFee only if Insurance.allowUninsured = true — otherwise the vehicle cannot be recovered by design.
/iploc, /iplhere, /garagedebug, /garageprobe do nothing for a player Working as intended — these diagnostics are admin only (verified via the server aty_garage_v2:isAdmin callback). Grant the player admin (ACE Config.AdminAce, framework admin/god/superadmin, or Config.AdminGroups) to use them.
ATY Scripts LogoATY SCRIPTS

QBCore & ESX için yüksek optimizasyonlu FiveM scriptleri üretiyoruz. Maksimum performans, hassas kod, sıfır gecikme.

Topluluğa Katıl

Partner

Tebex resmi partneri. Güvenli ödeme ve Cfx.re Keymaster entegrasyonu.

Yasal

Rockstar Games, Cfx.re, FiveM veya Take-Two Interactive ile bağlantılı değildir. Satın alımlar Tebex Hizmet Şartları'na tabidir.

© 2026 ATY SCRIPTS. Tüm hakları saklıdır.