ATY Scripts Logo
ATY Scripts/Docs/Shell Creator/Shell Creator

Shell Creator

aty_shellcreator

In-game grid interior builder: design shell interiors on a 2 m grid from a modular kit (floors, walls, openings, stairs, ceilings, decor, lights, anchor points), preview them by walking through, publish them, and let other resources such as aty_housing use them as interiors. The asset companion aty_shellcreator_kit supplies the 3D pieces the builder places.

Version 1.0.0. Live-tested on QBCore. ESX and Qbox are supported through aty_lib but were not live-tested. Tested scope lists what was seen working in game and what was only checked with offline test harnesses.

Info

Resource name aty_shellcreator (companion asset: aty_shellcreator_kit)
Version 1.0.0 for both resources (kit data version 7)
Frameworks ESX / QBCore / Standalone (detected via aty_lib). Live-tested on QBCore only
Database MySQL through aty_lib. Tables are created and migrated automatically on start, no SQL file to import
Lua version Lua 5.4 (lua54 'yes'), fx_version 'cerulean', game 'gta5'
Sides Client + server (shared config, grid model and locales)
NUI Yes — Vue 3 + Pinia, pre-built into ui/ (shell library, editor panels, details, import and export dialogs)
Languages English (en), Turkish (tr), German (de), French (fr), Spanish (es) and Brazilian Portuguese (pt-br), selected with Config.Language; a missing key falls back to English
Grid Cell 2.0 m, storey height 3.2 m, wall and slab thickness 0.2 m. Default shell 20 x 20 cells (40 x 40 m), at most 32 x 32 cells (64 x 64 m), up to 6 levels including basements down to level -3
Third-party notices docs/LICENSES.md

Tested scope

Area Status
Resource start on QBCore with aty_lib Verified live: starts without errors, database migration runs, the kit is resolved and its hash is stored, ready is announced
Kit pieces in game Verified live during kit development: own floor, ceiling and wall pieces have collision, the own stair works, door leaves fit their frames and swing. The kit's own notes record an in-game collision probe on 2026-09-30. The current kit data version 7 (67 materials) was not re-checked piece by piece in game for this page
Console import and publish Verified live: sample interiors were created from JSON files with the console import command and published as revision 1
aty_housing registration Verified live: published shells were registered by aty_housing as sc_<id> interiors and cached in its aty_housing_built_shells table
Opening the builder from the aty_housing creator A defect was found live (the player was moved into an invisible editor bucket with no screen) and fixed. Re-tested in game after the fix: works
Implemented and checked with offline test harnesses, not yet verified in game Per-role permissions, multi-level builds and stairs, painting, undo and redo limits, prop budget, walk-through preview, drafts and autosave, revisions, members, import and export (share code and JSON), the 16 atmosphere presets, photo and plan thumbnails, coordinate-mode shells with teleporters and vehicle entry, the stay and restart watchdogs, shell visits for admins, and entering a property on a built shell end to end
ESX, Qbox Not live-tested. Supported through aty_lib, but nothing more is claimed. The framework admin check only knows qb-core and es_extended; on any other framework only the ACE permission applies

Dependencies

Dependency Required Notes
aty_lib Yes (declared in fxmanifest.lua) Framework, database, callback, notification, job and permission bridge. Must start first. Restarting aty_lib restarts every dependent resource, aty_shellcreator included. Requires aty_lib 1.3.9 or newer (the version released together with this one): it adds HasPermission (framework admins) and GetPlayerJob (job rules). With an older aty_lib only the ACE aty_shellcreator.admin and housing-ability rules match
aty_shellcreator_kit Yes, for building Not a declared dependency, so the resource starts without it, but then no kit is resolved: the builder is disabled and the console prints no usable shell kit - the builder stays disabled with the reason for every source tried. Players who open the manager get "No shell kit is installed. Start aty_shellcreator_kit." Start it before aty_shellcreator; it is also picked up when it starts later
es_extended or qb-core One of them Detected by aty_lib
oxmysql (or the database resource aty_lib detects) One of them Whatever aty_lib detects. Live-tested with oxmysql only
aty_housing Optional Uses published shells as property interiors. Its HasRealtorAbility export is only asked when a permission rule uses housingAbility. See aty_housing integration
screenshot-basic Optional (not required) Photo thumbnails of published shells. Without it (or with Config.Thumbnails.photo = 'off') no photo is taken; floor plan images do not need it. The state is checked when a thumbnail is requested, so start order does not matter
aty_clothing Optional This resource's code does not call it. Wardrobe anchors you place in a shell are handed to hosts such as aty_housing, which decide what a wardrobe opens
ox_target, qb-target or aty_interactions Optional Used through aty_lib for the optional target zone of coordinate-shell teleporters (Config.Teleporter.interact)
Inventory Not needed aty_shellcreator gives and takes no items. Every inventory that aty_lib supports works alongside it: aty_inventory, ox_inventory, qb-inventory, qs-inventory, ps-inventory, codem-inventory, tgiann-inventory, origen_inventory, gfx-inventory, esx_inventoryhud, ak47_inventory and ak47_qb_inventory. Live testing was done on aty_inventory only

Installation

  1. Copy the aty_shellcreator and aty_shellcreator_kit folders into your resources (for example [aty]/aty_shellcreator and [aty]/aty_shellcreator_kit).
  2. No SQL import. On every start the resource creates the tables it needs (CREATE TABLE IF NOT EXISTS) and adds missing columns itself. It never touches your framework's tables. If the database is unreachable the migration is retried three times (5 s, then 10 s apart); after that the console prints an error and the resource stays idle until you restart it. See Database for the table list.
  3. Add both resources to server.cfg in the order below.
  4. Give your administrators the permission (see Permissions).
  5. Check the job names and grades in Config.Permissions (default: the job realestate, grade 1 and 2).
  6. Edit shared/config.lua if needed (see Configuration) and restart the resource.
  7. In game, type /shellcreator and create your first shell.

On the first start with aty_shellcreator_kit, seven sample interiors are published as shells owned by the server: Bungalow - 2 bedrooms, Family house - 3 bedrooms, Empty Studio, Empty 1BR Apartment, Empty 2BR Apartment, Empty 3BR House and Empty Loft (Config.SampleShells, files in data/samples/). Each one is created once: a restart never duplicates it, and a sample you delete or rename is not created again. Set Config.SampleShells.enabled = false before the first start to skip them.

server.cfg

setr game_enableDynamicDoorCreation "true"   # door leaves: FiveM refuses to create them without it

ensure oxmysql
ensure qb-core               # or es_extended
ensure aty_lib               # always before any aty_* resource
ensure screenshot-basic      # optional, photo thumbnails
ensure aty_shellcreator_kit  # the 3D kit, before the builder
ensure aty_shellcreator
ensure aty_housing           # optional, after the builder

add_ace group.admin aty_shellcreator.admin allow

aty_shellcreator waits up to 10 seconds at start for aty_shellcreator_kit to begin starting, and resolves the kit again whenever the kit resource starts or stops. aty_housing notices aty_shellcreator starting or stopping at any time, so its position is not critical, but the order above is the tested one.

Admin permission

A player is a Shell Creator admin when either check says yes, framework first:

  1. The framework's own admin permission (Config.AdminPermission): qb-core permission levels in .qb (default { 'admin', 'god' }) or ESX groups in .esx (default { 'admin', 'superadmin' }), asked through aty_lib.
  2. The ACE permission Config.AdminAce (default aty_shellcreator.admin). It is also checked when the framework says the player is not an admin:
add_ace group.admin aty_shellcreator.admin allow
add_principal identifier.license:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx group.admin

On qb-core, group.admin is not a permission level: a player who is in group.admin but not in qbcore.admin or qbcore.god needs the ACE line above. The server console always counts as an admin. To use only ACE, set the lists in Config.AdminPermission to {}.

Kit resource

Start aty_shellcreator_kit before aty_shellcreator. The details are in Kit resource.

Database

All tables are created on start. Nothing here needs manual work; it is listed so you know what to include in backups.

Table Content
aty_shellcreator_shells One row per shell: title, description, owner, visibility, status, current revision, edit lock, world placement and teleporter settings
aty_shellcreator_revisions Published revisions of every shell (layout data)
aty_shellcreator_drafts Working copies per character, written by autosave
aty_shellcreator_members Per-shell members (editor or viewer role)
aty_shellcreator_snippets Saved clipboard snippets per character
aty_shellcreator_thumbs Photo and floor plan thumbnails
aty_shellcreator_returns Return points for builders and visitors, so a player is put back where they started
aty_shellcreator_log Audit log (opens, publishes, deletes, refused actions, unlocks, imports)
aty_shellcreator_meta Schema version and the kit hash used at the last boot

Notes:

  • The owner of a shell is the framework character id. Shells created from the console belong to the server (no owner).
  • Housekeeping runs at boot and every 6 hours: stale edit locks older than Config.Editor.lockTimeoutSeconds are cleared, drafts older than Config.Drafts.keepDays are removed, and audit rows older than Config.Log.retentionDays are removed.

Files that stay open for editing

When the resource is distributed as an escrowed asset, these stay readable and editable (upload-config.json):

Path Why
fxmanifest.lua, shared/config.lua Configuration
server/api.lua, client/api.lua The open integration API (exports, events, hooks)
locales/*.lua and locales/ui/*.lua Translate or reword any text, including the builder panels
docs/*.md Documentation

This list is the escrow edition. The open edition (a separate download of the same resource) is not protected: its Lua files are readable and editable as well.

data/*.json (the base decor catalogue and the starting templates in data/templates/*.json) are plain data files, not Lua. In the escrow edition all other Lua files are protected. The UI source code and the development tools are not part of the package; the pre-built panel is in ui/. For aty_shellcreator_kit the open files are fxmanifest.lua, kit.json and LICENSE.md.

Configuration

Everything is set in shared/config.lua. The file is read when the resource starts: restart aty_shellcreator after every change. Distances are metres unless stated, and durations say their unit in the option name. Every key is read on both sides unless noted; the server re-checks everything the client sends.

Core

Option Type Default Description
Config.Debug boolean false Verbose console output
Config.Language string 'en' 'en', 'tr', 'de', 'fr', 'es' or 'pt-br'. Missing keys fall back to English
Config.Command string 'shellcreator' Chat command that opens the shell library. Also the name of the server console command (see Commands)
Config.ExitCommand string 'shellcreatorexit' Emergency command: closes the editor or preview, restores the character and releases focus
Config.AdminPermission table { qb = { 'admin', 'god' }, esx = { 'admin', 'superadmin' } } Framework admin permission, checked first. {} skips the framework check on that framework
Config.AdminAce string 'aty_shellcreator.admin' ACE permission, the last-resort admin check
Config.HideOthers boolean false true = non-admins never see other users' shells (owners and members still see theirs)
Config.RequireDuty boolean false true = job criteria in Config.Permissions only count while the player is on duty
Config.Kit string 'auto' 'auto', 'aty_shellcreator_kit' or 'base_temp'. See Kit resource
Config.SampleShells table { enabled = true, list = { 'bungalow_2bed', 'family_3bed', 'empty_studio', 'empty_1br', 'empty_2br', 'empty_house_3bed', 'empty_loft' } } Sample interiors in data/samples/<key>.json, published once with the own kit (same checks as the console import). A published sample is remembered in aty_shellcreator_meta (sample:<key>), so it is never created twice; a shell that already has the sample's title is adopted instead. enabled = false = never; remove a key from list to skip that sample. Nothing is seeded with the temporary base_temp kit
Config.KitExtensions table {} RESERVED, not read by any code in this version. Leave it empty
Config.CustomTextures table { enabled = false, slots = { walls = {}, floors = {} } } RESERVED, not read by any code in this version. Leave it off
Config.Doors.system boolean true Register built door leaves with the game's door system
Config.Doors.enableDynamicDoors boolean true The server sets the replicated convar game_enableDynamicDoorCreation to "true" at start when server.cfg does not. Without it FiveM refuses to create door leaves. Keep the setr line in server.cfg anyway
Config.Log.retentionDays number 180 Audit log rows older than this are removed

Permissions

Config.Permissions holds one rule per capability. The rule syntax and every default are described in Permissions.

Grid and budget

Option Type Default Description
Config.Grid.defaultSize table { w = 20, d = 20 } Size of a new shell in cells (2 m each), even numbers
Config.Grid.minSize table { w = 4, d = 4 } Smallest size in cells
Config.Grid.maxSize table { w = 32, d = 32 } Largest size in cells (64 x 64 m)
Config.Grid.defaultLevels number 1 Levels of a new shell
Config.Grid.maxLevels number 6 Total levels including basements
Config.Grid.minLevel number -3 Lowest basement level index
Config.Budget.maxProps number 800 Runtime props per shell (the config comment gives the range 50 to 1500)
Config.Budget.warnAt number 0.85 Share of the prop budget at which the editor warns
Config.Budget.maxDecor number 400 Decor items per shell
Config.Budget.maxDecorPerCell number 8 Decor items per cell
Config.Budget.maxDecorPerFace number 6 Decor items per wall face
Config.Budget.maxLights number 32 Lights per shell
Config.Budget.maxAnchors number 24 Anchor points per shell

A shell that goes over the prop, light or decor caps cannot be published.

Editor

Option Type Default Description
Config.Editor.bucketBase number 400000 Routing bucket of an editing player = bucketBase + server id. Keep it clear of other scripts (the comment names aty_housing at 100000+ and 200000+, aty_garage_v2 at 700000+)
Config.Editor.origin table { x = -2800.0, y = -4600.0, z = 1100.0 } Where the builder works in the world. Not checked in game for map geometry: change it if the surroundings clip
Config.Editor.keepInput boolean false Keep game input while the editor panel has focus. Gizmo sessions always keep it
Config.Editor.historySize number 200 Undo steps (20 to 1000)
Config.Editor.historyBytes number 4194304 Memory cap of the undo history
Config.Editor.autosaveSeconds number 30 Draft write interval while there are unsaved changes (15 to 300)
Config.Editor.heartbeatSeconds number 20 Session heartbeat to the server
Config.Editor.lockTimeoutSeconds number 90 A shell lock without heartbeat expires after this long
Config.Editor.opBatchMs number 700 How long edits are batched before they go to the server
Config.Editor.maxOpsPerBatch number 64 Edits per batch
Config.Editor.maxBatchBytes number 16384 Bytes per batch
Config.Editor.pasteMaxCells number 256 Largest region the clipboard pastes
Config.Editor.spawnPerFrame number 32 Props spawned per frame while the editor builds the view
Config.Editor.edgePick number 0.6 Distance from an edge that selects it
Config.Editor.previewKeyHoldMs number 600 How long Backspace must be held to leave the preview
Config.Editor.maxSessionMinutes number 240 Session cap in minutes; 0 = none
Config.Editor.idleMinutes number 20 No edits and no camera input for this long: autosave and close
Config.Revisions table { keep = 20, pinnedMax = 5, noteMax = 128 } Revisions kept per shell, pinned revisions that survive pruning, note length
Config.Drafts table { keepDays = 30, maxPerCharacter = 10 } Draft retention and per-character cap
Config.Snippets table { maxPerCharacter = 30, maxCells = 256 } Saved snippets per character and the largest snippet

Shortcuts

Config.Shortcuts holds the default editor shortcut per action; players can rebind them in the editor's settings. Config.ReservedKeys lists keys that other resources commonly map (1 to 9, F1, F2, F3, F5, F6, F8, F11, T, Tab, B, Y, X, G, K, M, L, U, N, H, I, Z, Alt, CapsLock); these are not offered for editor shortcuts. The defaults are listed under Key bindings.

Storage (coordinate shells)

Option Type Default Description
Config.Storage.origin table { x = -2000.0, y = -5200.0, z = 1000.0 } Origin of the slot grid where coordinate-mode shells without their own world position are placed. Not checked in game for map geometry
Config.Storage.spacing number 96.0 Distance between slots. Must be at least the largest shell extent (64 m) plus 32 m
Config.Storage.columns number 16 Slots per row; rows grow towards -Y

Changing these after coordinate shells exist moves them; the server prints an error at boot when it detects it, and also when two coordinate shells overlap.

Runtime (spawning shells for players)

Option Type Default Description
Config.Runtime.spawnRadius number 40.0 Coordinate shells build when the player is this close
Config.Runtime.despawnMargin number 20.0 Extra distance before they are removed
Config.Runtime.lingerSeconds number 8 How long a coordinate shell stays built after the player has moved out of range
Config.Runtime.checkMs number 1000 How often the client checks its distance to coordinate shells
Config.Runtime.jumpDistance number 50.0 A move between two checks larger than this triggers an immediate check of coordinate shells (for example after a teleport)
Config.Runtime.batchPerFrame number 20 Props spawned per frame
Config.Runtime.lodDist number 250 Draw distance of built props
Config.Runtime.modelTimeoutMs number 10000 Wait for models to load
Config.Runtime.payloadTimeoutMs number 12000 Wait for the shell data from the server
Config.Runtime.maxClientProps number 2000 Props one client keeps built across shells
Config.Runtime.cacheShells number 12 Shells cached on the client
Config.Runtime.serverCacheShells number 50 Shells cached on the server
Config.Runtime.kvpCache boolean true Cache shell data in the client's key-value store
Config.Runtime.kvpMaxBytes number 262144 Size cap of that cache
Config.Runtime.freezeVehicles boolean true Freeze vehicles this client controls inside a shell that is about to be removed, so they do not fall
Config.Runtime.fallbackSpawn table { x = -1035.71, y = -2731.87, z = 12.86, w = 0.0 } Where a player is put when the shell they were in is gone

A new published revision reaches players already inside a shell on their next entry; there is no live respawn.

Network and rate limits

Option Type Default Description
Config.Net.latentBps number 131072 Bandwidth of latent uploads (bytes per second)
Config.Net.uploadChunk number 16000 Upload chunk size
Config.Net.thumbMaxBytes number 180000 Largest photo thumbnail
Config.Net.planMaxBytes number 60000 Largest plan thumbnail
Config.Net.importMaxBytes number 524288 Largest import
Config.Net.layoutMaxBytes number 524288 Largest stored layout
Config.RateLimits.defaultMs number 300 Minimum gap between two calls of the same kind without its own rule
Config.RateLimits.ops table { perSecond = 6, burst = 12, perMinute = 2400 } Edit batches per player
Config.RateLimits.query number 2 Query rate
Config.RateLimits.payloadPerMinute number 20 Shell data requests per player and minute
Config.RateLimits.payloadPerShellPerMinute number 5 Shell data requests per player, shell and minute
Config.RateLimits.openSeconds number 3 Gap between two editor opens
Config.RateLimits.saveSeconds number 10 Gap between two saves
Config.RateLimits.importPerMinute number 3 Imports per minute
Config.RateLimits.teleportSeconds number 2 Gap between two teleporter uses
Config.RateLimits.moveSeconds number 5 Gap between two shell moves

Thumbnails, atmosphere and lights

Option Type Default Description
Config.Thumbnails.photo string 'auto' 'auto' takes a photo when screenshot-basic runs; 'off' never does
Config.Thumbnails.width, .height number 480, 270 Photo size
Config.Thumbnails.quality number 0.8 Photo compression quality
Config.Thumbnails.planSize number 512 Floor plan image size
Config.Thumbnails.yaw, .pitch, .fov number 45.0, 38.0, 40.0 Camera angle of the photo
Config.Thumbnails.fill number 0.8 How much of the frame the shell fills
Config.Thumbnails.settleMs number 600 Wait before the photo is taken
Config.Atmosphere.presets table 16 presets Ids: neutral, warm, cool, dim, night, neon, clinical, industrial, luxury, vintage, noir, sunset, foggy, bright, cinematic, dark. Each has a label key, a timecycle modifier name, a strength and optionally an hour or weather override. Names the running game build does not know are skipped
Config.Atmosphere.default string 'neutral' Preset of a new shell
Config.Atmosphere.weathers table { 'EXTRASUNNY', 'CLEAR', 'CLOUDS', 'OVERCAST', 'FOGGY' } Weather locks a builder can choose
Config.Atmosphere.defaultHour number 12 Clock lock inside a shell
Config.Atmosphere.defaultWeather string 'EXTRASUNNY' Weather lock inside a shell
Config.Atmosphere.noRain boolean true No rain inside a shell
Config.Atmosphere.pauseEvents table { enter = {}, leave = {} } Client events to fire when a player enters or leaves a shell, to pause and resume a weather or time sync script, for example { { event = 'qb-weathersync:client:DisableSync' } }
Config.Lights.maxDrawn number 24 Lights drawn at once on one client
Config.Lights.drawDistance number 30.0 Light draw distance
Config.Lights.defaultRange number 6.0 Range of a new light
Config.Lights.defaultIntensity number 1.5 Intensity of a new light

Teleporter (coordinate shells)

Option Type Default Description
Config.Teleporter.enabled boolean true false turns every shell teleporter off
Config.Teleporter.interact string 'both' 'marker', 'target' or 'both'; a shell's own teleporter setting wins
Config.Teleporter.key string 'E' Default key of the aty_sc_use key mapping
Config.Teleporter.drawDistance number 20.0 The ring marker shows within this distance
Config.Teleporter.interactDistance number 1.8 The prompt works within this distance
Config.Teleporter.standStillMs number 500 The player must stand still this long before the prompt appears
Config.Teleporter.fadeMs number 400 Screen fade time
Config.Teleporter.instanceBucketBase number 500000 Routing bucket of a per-player instance = base + server id
Config.Teleporter.marker table { type = 25, size = { x = 1.1, y = 1.1, z = 1.1 }, color = { 105, 255, 236, 110 } } Ring marker style
Config.Teleporter.watchdogSeconds number 5 Interval of the server check for players standing inside a restricted coordinate shell without access

Restricted teleporters. A teleporter whose access is not everyone is restricted. Its entry point is sent only to players who may use it (admins, players with a live grant, and players who pass the access rule: jobs, ACE, members or the canUseTeleporter hook, cached for 30 seconds). Everyone else receives the shell with entry = false and restricted = true: no ring, no prompt, no coordinates. The list is re-sent to a player whose right changes (job, ACE, grant, membership). The exit inside a shell always works.

The server also guards the shell itself. Every watchdogSeconds it checks the players in the default routing bucket: a player standing inside a restricted coordinate shell without a grant is moved back to the teleporter entry by the server (the vehicle they sit in is moved with them), so a modified client cannot stay inside. Admins, players with a grant (a teleporter entry grants the shell to the driver and every passenger of the vehicle) and players in a per-player instance are not moved. Each intrusion is written to the shell's audit log (at most once a minute per player and shell).

Commands

Every command is registered unrestricted and checked on the server; a player without the right gets a notification, nothing happens.

Command Where Description
/shellcreator Player Opens the shell library (manager). Needs the open capability
/shellcreator edit <id> Player Opens shell <id> in the editor
/shellcreator view <id> Player Opens shell <id> read-only
/shellcreator tp <id> Player, admins Visits shell <id>. /shellcreator tp without an id returns from the visit
/shellcreatorexit Player Emergency exit: closes the editor or preview, restores the character, releases focus
shellcreator kit Server console Prints the active kit id, version, source, hash, grid, tint count, model count and decor count
shellcreator rebake [id] Server console Clears the shell data cache and rebakes the current revision of one shell or all published shells, with timings
shellcreator validate [id] Server console Prints the publish validation result (error and warning codes) of one shell or all
shellcreator unlock <id> Server console Clears the edit lock of a shell and closes the editor session holding it
shellcreator purge <id> Server console Permanently deletes a shell that is already in the deleted state
shellcreator import <file> [title] Server console Creates a shell owned by the server from a JSON file inside the aty_shellcreator resource folder (an exported layout, or an object with title, description, tags, visibility and layout) and publishes it. The same import and publish checks run as in the in-game dialog. A shell with the same title is never created twice
shellcreator republish <id> <file> Server console Publishes the layout in such a JSON file as a new revision of an existing shell; its id, title, owner, tags and revision history stay. Refused while the shell is open in the editor

The command names follow Config.Command and Config.ExitCommand. The subcommands of the console version are ignored when typed by a player; a player typing /shellcreator kit simply opens the library.

Key bindings

Key bindings are registered with FiveM and can be rebound by every player under Settings, Key Bindings, FiveM.

Binding Default What it does
aty_sc_use E (Config.Teleporter.key) Use a shell entrance or exit. Acts only at a teleporter, never while the editor is open or a panel has focus
+aty_sc_preview_exit BACKSPACE (hold) Leave the walk-through preview; hold for Config.Editor.previewKeyHoldMs
+aty_sc_gizmo_toggle R Switch the move and rotate handles of the gizmo
+aty_sc_gizmo_select MOUSE_LEFT Drag a gizmo handle

Inside the editor the defaults of Config.Shortcuts apply:

Action Key Action Key
Select Q Rotate R
Floor F Rotate left / right [ / ]
Wall C Undo / redo Ctrl+Z / Ctrl+Y
Opening O Copy / cut / paste Ctrl+C / Ctrl+X / Ctrl+V
Stair J Duplicate Ctrl+D
Paint P Mirror X / Y Ctrl+M / Ctrl+Shift+M
Decor V Level up / down PageUp / PageDown

| Light | ; | View mode | \ | | Anchor | , | Reset view | Home | | Room | . | Plan view | End | | Measure | / | Preview | Insert | | Demolish | Delete | Leave preview | Backspace | | Frame | Ctrl+F | | |

Mouse wheel while placing. When the active tool is placing something, the wheel turns it instead of zooming:

Placing Wheel Shift + wheel
Floor or ceiling decor, anchors (spawn, exit and the other types) 15° a notch, on the 15° grid 5° a notch, on the 5° grid
Stairs, a pasted region A quarter turn (90°) a notch Same

Wheel up turns the item left (counter-clockwise). R still turns 90° and Shift+R turns 15°. Ctrl + wheel zooms the camera while you place.

The wheel zooms the camera again in these cases: while a gizmo is editing an item, in demolish mode, when no item is armed for placement, for wall-only decor (it keeps the wall face heading), in the opening tool, in read-only sessions, in the walk-through preview, and during the thumbnail photo.

Outlines. Only decor items that are hovered or selected and currently visible get the engine outline. Nothing is outlined in the preview, during the photo, while the editor is loading or closing, or for items on a level the view hides. Lights and anchors are marked with wire boxes, not outlines.

Permissions

Config.Permissions has one rule per capability. A rule is 'admin', 'everyone', 'nobody', or a table. Admins (see Admin permission) pass every rule. A table rule passes when any listed criterion matches:

Criterion Meaning
jobs = { [job] = minGrade } The player has that job at that grade or higher (aty_lib job lookup). With onDuty = true on the rule, or Config.RequireDuty = true, the player must also be on duty
ace = 'name' The player holds that ACE permission
housingAbility = 'name' aty_housing reports that realtor ability for the player (its HasRealtorAbility export). false when aty_housing is not started
owner = true Counts only in checks on one specific shell: the player owns it

Defaults (job realestate; grades are the minimum grade):

Capability Default What it allows
open realestate 1 Open the shell library
create realestate 1 Create shells
editOwn realestate 1 Edit own shells (as owner, or as a member with the editor role)
editAny admin Edit any shell
publish realestate 2 Publish a revision
deleteOwn realestate 2 Archive or delete own shells
deleteAny admin Archive, delete or restore any shell
viewAll realestate 1 See public shells of other users
moveCoords admin Place or move a coordinate-mode shell in the world
teleporters admin Configure shell teleporters
import admin Import a shell from JSON or a share code
export realestate 2 Export a shell
revisions realestate 2 Browse, restore and pin revisions
members realestate 2 Manage the member list of an own shell (the shell owner, or an admin)
forceUnlock admin Take over a shell locked by another editor
purge admin Permanently delete a deleted shell

Shells are designed by admins and realtors; there are no player-owned shells by default. Other rule values are supported by the code but only the defaults are described as intended.

How a shell is seen by a player:

  • Admins, the owner and members always see it.
  • Otherwise, with Config.HideOthers = true nobody else sees it.
  • With Config.HideOthers = false, a public shell is visible with viewAll, a team shell is visible to players holding open whose job equals the shell's team job, and a private shell is visible only to owner, members and admins.
  • A deleted shell is visible only to admins and its owner.

A player's capabilities are cached for 10 seconds, so a job change can take up to 10 seconds to apply. Every action is checked again on the server. Refused actions are written to the audit log, at most one row per player and action per minute.

Kit resource

aty_shellcreator_kit holds the 3D pieces the builder places. It has no scripts: its fxmanifest.lua streams the models and textures (stream/) and ships kit.json, the list the builder reads. Everything in it is original ATY work (see its LICENSE.md); kit.json only names three base-game models by name, which every GTA V client already has: two door leaves (door_house1, door_studio) and a pillar decor item. Stairs, railing, frames and window inserts are own models.

What kit.json (kit version 7) defines:

Item Count or value
Grid Cell 2.0 m, storey 3.2 m, wall 0.2 m, slab 0.2 m
Materials 67: 32 wall, 25 floor, 10 ceiling
Part groups Floor and ceiling plates, walls in 8 shapes (full, half, low, arch, door, window, wide, hatch), 8 wall skins, 3 corner fillers, 13 door leaves (11 own, 1.30 x 2.30 m, plus the 2 base-game leaves above), 4 opening frames (wide, wide glass, arch glass, hatch glass), 8 window designs (each with a glass and an opaque variant), 3 stair styles (wood, dark, concrete), 1 stairwell railing, void
Own decor 1 entry (a pillar). Base-game decor from data/decor_base.json is merged in (includeDecorBase), 111 built-in fit-out entries in the base catalogue (ceiling lights, bathroom fixtures, fitted kitchen units, shelving, office, wall art). 100 of the 111 show a picture icon in the editor (the same thumbnails aty_housing uses for its Decor Studio catalogue, shipped in data/thumbs/kit/); the other 11 show a category glyph. Living furniture is not shell decor: with aty_housing it comes as the property's furniture set (Decor Studio furniture)
Tints None (tints.count = 0); anchor models are not part of this kit version

Config.Kit chooses the source:

Value Behaviour
'auto' (default) Use aty_shellcreator_kit when it is started and its kit.json validates; otherwise fall back to base_temp
'aty_shellcreator_kit' Only the kit resource. If it is missing or invalid the builder stays disabled
'base_temp' Only the temporary base-game kit. This is a development-only kit and is not shipped: data/kits/base_temp.json is excluded from the package, so on a purchased copy it does not exist and the builder stays disabled without the kit resource

Config.KitExtensions is RESERVED for kits that extend the base kit; nothing reads it in this version.

A change of the kit while the server runs re-resolves the kit and fires the local event aty_shellcreator:kitChanged. Published shells are rebaked lazily on their next request, because the data hash includes the kit hash. A kit changed between restarts is detected at boot, and shell statistics are refreshed in the background.

Every player downloads the kit's stream files on connect. A client that is missing models answers models_missing when a shell is spawned and the shell does not build.

The kit's LICENSE.md states: copyright 2026 ATY, all rights reserved; every model, texture and archetype file is original, procedurally generated ATY work with no third-party or Rockstar textures or models included.

Exports

Server exports are called as exports.aty_shellcreator:<Name>(...). Every server export answers from memory unless marked "may yield"; before the resource is ready they return the value in brackets.

Server exports

Export Returns Description
ListShells(filter?) array [] Shells as items. filter = { status = 'published' (default) | 'archived' | 'draft' | 'any', owner, tag, coordMode }. Item: id, uid, title, status, rev, hash, tags, stats = { area, rooms, levels, props }, anchors, bounds = { min, max, radius }, hasPhoto, planLevels, updatedAt, deleted, broken. Deleted shells are never listed. broken means the current revision cannot be read
GetShell(id) item or nil The item plus settings, owner_name, created_at, description. Works for deleted shells too, so a stored sc_<id> can be resolved
GetShellPayload(id, rev?) table or nil Baked shell data for hosts that spawn shells themselves. May yield
GetShellAnchors(id, rev?) anchor set or nil Anchors of the current or the given revision. Other revisions may yield
GetShellPlan(id, level) table or nil Floor plan data of the current revision. May yield
GetShellThumb(id, kind, level?) data URI or nil kind is 'photo' or 'plan'. May yield, cached for 5 minutes
ContainsPoint(id, point, margin?) boolean point ({ x, y, z } or array) is above an occupied cell of the current revision, within that level's clear height plus the margin. The vertical margin is capped at half a slab, so a roof counts as outside. false when unknown
GetShellMask(id) table or nil The occupancy mask ContainsPoint reads, { levels = [{ l, minX, minY, w, d, bits }], cell, storey, clear, slab }, for hosts that mirror the check on the client
GetWorldPlacement(id) { x, y, z, h } or nil World placement of a coordinate-mode shell
CanEdit(src, id) boolean Whether the player may edit that shell
GetPolicy(src, id) table or nil The player's policy for that shell: view, edit, publish, delete, restore, move, teleporter, export, revisions, members, unlock, purge, owner, member, admin
OpenEditor(src, id?) true or false, key, text Opens the editor for that player. Without an id it opens the shell library. With an id the server checks the kit, the shell, the permission and the canOpen hook, then the player's client runs its normal open flow. text is the refusal in this resource's language
IsEditing(src) shell id or nil The shell the player is editing
GetKit() table or nil { id, version, hash, capabilities, tints } of the active kit
RegisterHook(name, fn) hook id or nil See Hooks
RemoveHook(id) boolean Removes a hook

Anchor format: each anchor is { id, floor = { x, y, z, h }, ped = { x, y, z + 1.0, h }, label } in shell-local metres. ped is the standing-ped reading: place a ped with SetEntityCoords(ped, x, y, z - 1.0). An anchor set is { spawn, exit, stash = {...}, wardrobe = {...}, bed = {...}, kitchen = {...}, garage = {...}, custom = {...} }.

-- list published shells and read one
local shells = exports.aty_shellcreator:ListShells({ tag = 'apartment' })
for _, s in ipairs(shells) do
    print(s.id, s.title, s.stats.area, s.stats.rooms)
end

local shell = exports.aty_shellcreator:GetShell(2)
local anchors = exports.aty_shellcreator:GetShellAnchors(2)
if anchors and anchors.spawn then
    print('spawn at', anchors.spawn.floor.x, anchors.spawn.floor.y, anchors.spawn.floor.z)
end

-- open the builder for a player
local ok, key, text = exports.aty_shellcreator:OpenEditor(source, 2)
if not ok then print('refused:', key, text) end

Client exports

Hosted shells: the host resource owns the routing bucket and the teleport; aty_shellcreator builds the props.

Export Returns Description
SpawnShell(id, opts) handle, or false, reason[, missingModels] Builds a shell. opts = { origin = vector3 or { x, y, z }, heading = 0.0, rev = nil (current published), timeoutMs = 15000 (one deadline for data, models and collision, 1000 to 60000), hash = nil (a known data hash lets a cached copy skip the server round trip) }. Yields. Reasons: sc_invalid_input, sc_not_ready, sc_no_permission, sc_not_found, sc_shell_broken (from the server), sc_payload_timeout, models_missing, prop_cap, pool_full, models_timeout, create_refused, cancelled. Parts the client cannot create (slow, refused or missing models, door leaves without game_enableDynamicDoorCreation) do not stop the shell while the spawn point has a floor: they are printed once and retried in the background (see notSpawned and issue of GetHandleInfo)
DespawnShell(handle) boolean Removes the shell
MoveShell(handle, origin, heading) boolean Moves a built shell
GetHandleAnchors(handle) table or nil Anchor set in world space. Each anchor is { floor = vector4, ped = vector4 (z + 1.0), label, id }
GetHandleInfo(handle) table or nil { handle, id, rev, hash, owner, state, origin, heading, props, doors = { doorKey... }, notSpawned, issue }
IsInsideShell() handle, shellId, roomIndex or nil The shell the local player is in
GetCurrentRoom() { handle, id, room = { id, name, area } } or nil The room the local player is in
SetDoorLocked(handle, doorKey, locked) boolean Lock or unlock a door leaf
SetRoomLights(handle, roomId | nil, on) boolean Switch the lights of one room, or of the whole shell with nil
OpenEditor(id?) boolean Asks the server to open the editor (true = asked, permission is checked there); no id opens the shell library. false while an editor is already active or opening
IsEditorActive() boolean Whether the local player is in the editor

A handle keeps the revision it was built with; a newer published revision is used by the next SpawnShell. Under the client prop cap, coordinate shells farther away are removed first. Handles are removed when the resource that created them stops.

-- client: build a shell at a spot and walk the ped to its spawn anchor
local handle, reason = exports.aty_shellcreator:SpawnShell(2, {
    origin = vector3(-3500.0, -3500.0, 900.0), heading = 0.0,
})
if not handle then
    print('could not build shell:', reason)
    return
end
local a = exports.aty_shellcreator:GetHandleAnchors(handle)
if a and a.spawn then
    SetEntityCoords(PlayerPedId(), a.spawn.ped.x, a.spawn.ped.y, a.spawn.ped.z - 1.0)
end
-- later
exports.aty_shellcreator:DespawnShell(handle)

Events

Server events are local events (TriggerEvent). Listen with AddEventHandler only, never RegisterNetEvent, so a client can never fake them.

Server events

Event Arguments When
aty_shellcreator:ready none Boot finished. Re-query and register your hooks again
aty_shellcreator:shellChanged id, info info.kind is published, archived, deleted, restored, renamed, moved, teleporter, purged or thumbnail; info.rev is the current revision
aty_shellcreator:editorOpened src, id A player opened the editor on a shell
aty_shellcreator:editorClosed src, id, mode The session ended
aty_shellcreator:kitChanged kitHash The active kit changed while the server runs
AddEventHandler('aty_shellcreator:shellChanged', function(id, info)
    if info.kind == 'published' then
        print(('shell %d now at revision %s'):format(id, tostring(info.rev)))
    end
end)

Client events

Event Arguments When
aty_shellcreator:client:enteredShell handle, id The local player entered a built shell
aty_shellcreator:client:leftShell handle, id The local player left it
aty_shellcreator:client:handlesLost handles Fired synchronously while this resource stops, with every handle that is about to disappear. Set flags only and act in your own thread; the ped is frozen when inside
aty_shellcreator:client:editorOpened id The local editor opened
aty_shellcreator:client:editorClosed id The local editor closed

Other aty_shellcreator:client:* and aty_shellcreator:server:* net events (openManager, openEditor, payload, index, indexDelta, forceExit, forceClose, editorLoad, upload) are internal to the resource. Use the exports instead of triggering them.

Hooks

Register a hook with exports.aty_shellcreator:RegisterHook(name, fn). Hooks are removed when the registering resource stops, so register them again on aty_shellcreator:ready. A hook that can veto returns false, message (the message is shown to the player, at most 128 characters); anything else allows.

Hook Data Behaviour when your function errors
canOpen { source, shellId, charId } Allows (fails open)
canPublish { source, shellId, charId, stats } Allows (fails open)
canArchive { source, shellId, force } Refuses, unless force is set (admins only)
canDelete { source, shellId, force } Refuses, unless force is set (admins only)
canUseTeleporter { source, shellId, direction } Refuses (fails closed)
usage { shellId } Return { resource, count, label }; shown in the manager and the details view. A failing or malformed hook is skipped
onPublished { shellId, rev } Notification only, runs in its own thread
onDeleted { shellId, rev } Notification only, runs in its own thread
-- refuse to archive or delete a shell your resource still uses
local function inUse(data)
    if countMyUses(data.shellId) > 0 then
        return false, 'Used by my resource'
    end
end

local function register()
    exports.aty_shellcreator:RegisterHook('canArchive', inUse)
    exports.aty_shellcreator:RegisterHook('canDelete', inUse)
end
register()
AddEventHandler('aty_shellcreator:ready', register)

aty_housing integration

aty_housing is optional. When both run, every shell published in the Shell Creator becomes a housing shell interior named sc_<id>. This is handled by aty_housing (server/built_shells.lua) through the exports, events and hooks above; this resource needs nothing extra.

The interface follows the integration. The builder asks the server whether aty_housing is started and shows housing-specific parts only while it runs: the housing wording in the guide and the details tabs, the host export format, and the housingAbility chip of the permission rules. Without aty_housing the same places use generic wording about "host scripts" that read published shells through the exports, and the housing-only options are hidden. The state updates live when aty_housing starts or stops; nothing has to be configured.

What aty_housing takes from a published shell:

From the shell Used for
spawn and exit anchors Where a player appears when entering, and the inside exit. A shell with no spawn anchor gets a fallback point at the grid origin and a warning in the housing health check
stash anchors Property stashes (the first is the main stash; more become extra stashes, limited by Config.Stashes.max in aty_housing)
wardrobe, bed, kitchen anchors Living points, mapped through Config.BuiltShells.fixtures (default wardrobe to wardrobe, bed to bed, kitchen to stove)
Tags apartment, house, trailer The listing type (Config.BuiltShells.typeTag)
Stats and thumbnails Area, rooms, levels, props and the photo and floor plan gallery of a listing
Bounds and occupancy mask The inside check and the point check for captured points and furniture (ContainsPoint)

The interior is built on the client at Config.ShellSpawn of aty_housing through SpawnShell, in the property's own routing bucket. That spawn point is marked in aty_housing as not verified in game: change it if a shell clips into anything.

The Config.BuiltShells block of aty_housing (shared/config.lua) controls the integration:

Option Default Description
enabled 'auto' 'auto' uses the Shell Creator when it runs and stays quiet otherwise; true does the same but a missing resource is an error in the console and the admin health check; false never
resource 'aty_shellcreator' Resource name of the Shell Creator
planImages true Show the photo and floor plans in the listing gallery
typeTag { apartment = 'apartment', house = 'house', trailer = 'trailer' } Shell tag to listing type
fixtures { wardrobe = 'wardrobe', bed = 'bed', kitchen = 'stove' } Anchor type to living point type; false = anchors give no living points
containsMargin 0.5 Metres around the shell's floor cells that still count as inside
radiusPad 2.0 Metres added to the shell's bounding radius
spawnTimeoutMs 15000 How long a client waits for the shell to build (1000 to 60000)
blockDelete true Refuse archiving or deleting a shell that properties use. An admin can force it
blockEditorInside true Refuse opening the Shell Creator while the player is inside a property or on a creator visit
notifyUpdate true Players inside hear once that a new version was published; it applies when the property is empty again
notifyOwners true Owners and tenants are notified when their interior is archived, deleted or broken
thumbCacheSeconds 300 How long photo and floor plan images are cached on the server

Behaviour to know:

  • aty_housing registers the canArchive, canDelete, usage and canOpen hooks. The manager shows how many properties use a shell.
  • A shell that disappears (stopped, archived, deleted, purged, broken, unpublished) stays registered as unavailable, so its properties show "interior unavailable" instead of vanishing. Entering is refused, and such a property cannot be bought until the interior is back.
  • aty_housing keeps the last known copy of every shell in its own table aty_housing_built_shells, so labels and points survive while aty_shellcreator is not running.
  • A new revision does not change a property while someone is inside; it applies on the next entry.
  • Publish a shell, then pick it under built shells in the aty_housing property creator. The creator can also open the builder for a shell (OpenEditor).

Features

Builders (realtors and admins)

  • Build on a 2 m grid with 3.2 m storeys: up to 6 levels including basements, shells of up to 64 x 64 m.
  • Tools for floors, walls in 8 shapes, openings (doors, windows, wide openings), stairs, ceilings, painting (material and surface), decor, lights, anchor points, room naming and atmosphere, and a measure tool.
  • Mouse-wheel rotation while placing decor, anchors, stairs and pasted regions (15° a notch, Shift 5°; Ctrl + wheel zooms), see Key bindings.
  • Select, copy, cut, paste, duplicate and mirror regions; rotate; deep undo and redo; save regions as snippets and paste them into other shells.
  • Start from a blank shell or one of seven templates: studio, one bedroom, two bedroom, office, shop, garage and warehouse.
  • Prop, decor and light budgets with a live warning; publishing is blocked when a cap is exceeded.
  • Publish validation with errors (no spawn point, spawn or exit not on a real floor or with less than 2.0 m headroom, over the caps, layout integrity, no real floor, empty title) and warnings (for example door swings over stairs or decor, perimeter openings or glass).
  • Walk-through preview of the built shell before publishing.
  • 16 atmosphere presets with clock and weather locks, per shell and per room.
  • Orbit, plan and fly camera, level views, and an automatic photo and floor plan per level when you publish.
  • Autosaved drafts, revision history with notes and pinned revisions, restore a revision as a draft.
  • Share a shell as JSON or a share code; import by pasting one (the import checks size, grid version and kit keys, and reports what was replaced or dropped).
  • Optional shell members (editor or viewer) so a colleague can work on your shell.

Admins

  • Edit, publish, archive, delete, restore and permanently delete any shell.
  • Visit any shell with /shellcreator tp <id> and return with /shellcreator tp.
  • Take over a locked shell, or clear a stale lock from the console.
  • Place coordinate-mode shells in the world with teleporter entrances (marker and optional target zone, per-player or shared instance, optional vehicle entry for the driver, restricted access with an intrusion watchdog).
  • Import shells from files with the console import command; run validate, rebake and kit for diagnostics.
  • Audit log of opens, publishes, deletions, unlocks, imports and refused actions.

Server owners

  • No SQL import; tables are created and migrated on start.
  • Permissions per capability by job and grade, ACE, duty state, or the housing realtor ability; hide other users' shells.
  • Per-shell prop, decor, light and anchor caps and a global client prop cap to protect performance.
  • Rate limits on every call, server-side re-validation of every edit, a server-authoritative editor lock and draft storage.
  • Every value the client sends is checked on the server; the client can never send models or prop lists.
  • Open integration API (exports, events, hooks) for your own scripts, and an interface in English, Turkish, German, French, Spanish and Brazilian Portuguese.

Languages

Language Config.Language Files
English (default, fallback) 'en' locales/en.lua, locales/ui/en.lua
Turkish 'tr' locales/tr.lua, locales/ui/tr.lua
German 'de' locales/de.lua, locales/ui/de.lua
French 'fr' locales/fr.lua, locales/ui/fr.lua
Spanish 'es' locales/es.lua, locales/ui/es.lua
Brazilian Portuguese 'pt-br' locales/pt-br.lua, locales/ui/pt-br.lua

To switch, set Config.Language in shared/config.lua to the code in the second column and restart the resource. Server messages and the interface follow that setting. A key that is missing in the chosen language is shown in English.

Troubleshooting

Problem Solution
Console: no usable shell kit - the builder stays disabled, or players get "No shell kit is installed. Start aty_shellcreator_kit." Add ensure aty_shellcreator_kit before ensure aty_shellcreator, check the folder name is exactly aty_shellcreator_kit, and run shellcreator kit in the console. The error line names the reason for every kit source that was tried
Doorways without door leaves; F8 not spawned (doors_disabled): aty_sc_door_... FiveM refuses to create door leaves unless setr game_enableDynamicDoorCreation "true" is set. Config.Doors.enableDynamicDoors = true (default) sets it when the resource starts; add the line to server.cfg to make it permanent. The rest of the shell spawns without the leaves
Config.Kit = ... is not a kit source in the console Use 'auto', 'aty_shellcreator_kit' or 'base_temp'. 'base_temp' does not exist in a purchased copy
/shellcreator says "You are not allowed to do that." The player lacks the open capability. Give them the job and grade of Config.Permissions.open, or add the ACE line. Job changes can take up to 10 seconds to apply
Admin cannot do admin-only things Check Config.AdminPermission for your framework and the ACE line add_ace group.admin aty_shellcreator.admin allow plus the add_principal. On qb-core group.admin is not a permission level. On a framework other than qb-core and es_extended only ACE works
A shell stays locked after a crash The lock expires after Config.Editor.lockTimeoutSeconds (90 s) without a heartbeat. To clear it at once, run shellcreator unlock <id> in the console or use an admin account
Stuck in the editor, preview or with a panel on screen Type /shellcreatorexit (or the name in Config.ExitCommand)
A shell does not build for a player, models_missing The kit's stream files did not reach the client. Check aty_shellcreator_kit is started and not blocked in your stream setup, and have the player reconnect
Shell does not build: prop_cap or pool_full The client hit Config.Runtime.maxClientProps or the game object pool limit. Lower Config.Budget.maxProps for new shells or reduce how many shells are built at once
models_timeout or sc_payload_timeout Slow client or heavy server. Raise Config.Runtime.modelTimeoutMs / payloadTimeoutMs, or the host's own timeout (Config.BuiltShells.spawnTimeoutMs in aty_housing)
Publish is refused Open the validation list in the editor. Common causes: no spawn anchor, spawn or exit not on a floor or without headroom, a cap exceeded, empty title. Run shellcreator validate <id> for the codes
A shell card is marked broken Its current revision cannot be read. Restore an older revision as a draft and publish it; until then GetShellPayload returns nil and aty_housing treats the interior as unavailable
No photo thumbnails Install and start screenshot-basic, and keep Config.Thumbnails.photo at 'auto'. Floor plan images do not need it
A property in aty_housing says "interior unavailable" The shell is stopped, archived, deleted or broken. Start aty_shellcreator, restore or republish the shell, or check the reason in the aty_housing admin health check
Weather or time is wrong inside shells Your weather sync script is fighting the shell's locks. Pause it with Config.Atmosphere.pauseEvents
Console: Config.Storage changed ... coordinate shells moved or coordinate shells ... overlap Restore the previous Config.Storage values, or move one of the overlapping shells
Database errors at start Check oxmysql (or your database resource) and the connection string; the migration retries three times, then the resource stays idle until restarted

Known limitations

  • Only the parts listed as verified in Tested scope were seen working in game. Everything else is implemented and checked with offline test harnesses only.
  • Only QBCore was used for live tests. ESX and Qbox are untested; on a framework other than qb-core or es_extended the framework admin check is skipped and only ACE applies.
  • No player-owned shells in this version: by default only admins and realtors design shells. The permission rules can be loosened, but that setup is not tested.
  • A newly published revision reaches players already inside a shell on their next entry; there is no live respawn.
  • Config.Editor.origin and Config.Storage.origin were chosen far from the map and are not verified against map geometry in game. Move them if the surroundings clip or the area is not empty on your server.
  • Config.KitExtensions and Config.CustomTextures are RESERVED and have no effect in this version. The current kit has no colour tints and no anchor models.
  • Photo thumbnails need screenshot-basic.
  • Each shell is limited by the budget caps and, per client, by Config.Runtime.maxClientProps.
  • Shell names and descriptions are free text typed by builders; the interface texts are available in English, Turkish, German, French, Spanish and Brazilian Portuguese.
  • Job-based rules need the job lookup of aty_lib; without it only admin, ACE and housing-ability criteria can match.
  • The seven sample shells (Config.SampleShells) are plain grid layouts made with the own kit; the two furnished houses get their furniture from aty_housing furniture sets (matched by title), not from the layout.

Third-party notices

Third-party components shipped with or required by these resources are listed in LICENSES.md: the Outfit typeface (SIL Open Font License 1.1, text in docs/OFL.txt), Vue and Pinia (MIT) bundled into the pre-built UI, and the separately installed resources aty_lib, aty_shellcreator_kit, aty_housing, aty_clothing and screenshot-basic. aty_shellcreator ships no Rockstar Games assets and no third-party shell, MLO or housing code. The kit's own licence statement is in aty_shellcreator_kit/LICENSE.md.

ATY Scripts LogoATY SCRIPTS

Crafting highly optimized FiveM scripts for QBCore & ESX. Maximum performance, precision code, zero lag.

Join Community

Partner

Official partners with Tebex. Secure checkout and Cfx.re Keymaster integration.

Legal

Not affiliated with Rockstar Games, Cfx.re, FiveM, or Take-Two Interactive. Purchases bound by Tebex Terms of Service.

© 2026 ATY SCRIPTS. All rights reserved.