⚙️Configuration
⚙️ Configuration Guide
SceneKits is easy to configure through two main files located in the config/ folder.
📁 Configuration Files
config/kits.lua
Commands, permissions, limits, and scene kits
config/translations.lua
UI text and notifications (for localization)
🎯 Basic Configuration (config/kits.lua)
config/kits.lua)Commands
Change command names to fit your server:
commands = {
spawn = 'sk_spawn', -- Open scene menu
clear = 'sk_clear', -- Delete all your scenes
purge = 'sk_purge', -- Purge nearby props
stats = 'sk_stats', -- Server statistics (admin)
debug = 'sk_debug', -- Debug tools (admin)
},Permissions
Define which jobs can access scene categories:
permissions = {
police = { 'police', 'sheriff', 'state' },
ems = { 'ambulance', 'ems' },
mech = { 'mechanic', 'tow' },
public = false, -- Everyone can access
},Match your framework's job names:
ESX: Check your database
jobstableQBCore: Check
qb-core/shared/jobs.luaQBox: Check
qbx_core/shared/jobs.lua
Server Limits
Control performance and player usage:
maxActivePerPlayer = 3, -- Scenes per player
maxGlobalScenes = 100, -- Total server scenes
autoExpireMinutes = 45, -- Auto-delete timer (0 = off)
debug = false, -- Debug mode
favoriteDisplay = true, -- Show favorites featureRecommended by server size:
Small (32)
2
30
Medium (64-128)
3
75
Large (128-256)
2
100
💻 Custom Framework -Standalone
SceneKits supports custom frameworks and standalone setups through the GetPlayerJob function.
For custom frameworks, ACE permissions, or standalone setups, edit the GetPlayerJob function in your config:
-- 💼 JOB SYSTEM CONFIGURATION
-- This function determines what job a player has. Edit it for custom frameworks.
-- Must return job string: 'police', 'sheriff', 'ambulance', 'ems', 'mechanic', or 'unemployed'
GetPlayerJob = function(source)
-- FOR QBCORE/QBOX USERS:
-- Note: QBox uses 'qb-core' export name, not 'qbx_core'
if GetResourceState('qbx_core') == 'started' or GetResourceState('qb-core') == 'started' then
local QBCore = exports['qb-core']:GetCoreObject()
local Player = QBCore and QBCore.Functions.GetPlayer(source)
if Player and Player.PlayerData and Player.PlayerData.job then
return Player.PlayerData.job.name or 'unemployed'
end
end
-- FOR ESX USERS:
if GetResourceState('es_extended') == 'started' then
local success, ESX = pcall(function() return exports['es_extended']:getSharedObject() end)
if success and ESX then
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer then
local job = (xPlayer.getJob and xPlayer.getJob()) or xPlayer.job
return (job and job.name) or 'unemployed'
end
end
end
-- FOR CUSTOM FRAMEWORKS (Standalone, etc.):
-- Uncomment and modify this section for your custom duty/job system:
--[[
local success, dutyInfo = pcall(function()
return exports['your-police-resource']:GetPlayerDutyInfo(source)
end)
if success and dutyInfo and dutyInfo.onDuty then
if dutyInfo.type == 'pd' or dutyInfo.type == 'police' then
return 'police'
elseif dutyInfo.type == 'ems' or dutyInfo.type == 'fire' then
return 'ambulance'
elseif dutyInfo.type == 'mech' then
return 'mechanic'
end
end
]]--
-- FOR ACE PERMISSION BASED:
-- Uncomment this if you want to use ACE permissions instead:
--[[
if IsPlayerAceAllowed(source, 'group.leo') then return 'police' end
if IsPlayerAceAllowed(source, 'group.ems') then return 'ambulance' end
if IsPlayerAceAllowed(source, 'group.mechanic') then return 'mechanic' end
]]--
-- Default: Everyone is unemployed (can only access public kits)
return 'unemployed'
end,🎨 Creating Custom Scene Kits
Basic Kit Structure
my_scene = {
label = 'Job — Scene Name',
description = "Brief description here",
allow = { 'police' }, -- or 'ems', 'mech', 'public'
objects = {
{hash = `prop_name`, offset = vector3(x, y, z), heading = 0.0},
{hash = `prop_name`, offset = vector3(x, y, z), heading = 0.0},
}
}Example: Simple Checkpoint
my_checkpoint = {
label = 'Police — My Checkpoint',
description = "Basic traffic checkpoint",
allow = { 'police' },
objects = {
{hash = `prop_mp_barrier_02b`, offset = vector3(0.0, 0.0, 0.0), heading = 0.0},
{hash = `prop_mp_cone_04`, offset = vector3(-2.0, -1.0, 0.0), heading = 0.0},
{hash = `prop_mp_cone_04`, offset = vector3(2.0, -1.0, 0.0), heading = 0.0},
{hash = `prop_worklight_02a`, offset = vector3(0.0, -2.0, 0.0), heading = 0.0},
}
}Tips:
Keep prop count under 15 for best performance
Use realistic spacing between objects
Test in-game before deploying
Find prop names using CodeWalker or online prop lists
🌍 Localization (config/translations.lua)
config/translations.lua)Change any text displayed in the UI:
return {
title = 'SceneKits',
main_menu_title = 'SceneKits',
note_scene_placed = 'Scene placed.',
note_placement_canceled = 'Placement canceled.',
-- Edit any text here...
}Example (Spanish):
title = 'SceneKits',
note_scene_placed = 'Escena colocada.',
note_placement_canceled = 'Colocación cancelada.',🔐 Admin Permissions
Admins need proper ACE permissions to access admin tools. This is configured in your server.cfg:
# Grant admin group access to SceneKits admin tools
add_ace group.admin scenekits.admin allow
# Add specific players to admin group (replace with actual license)
add_principal identifier.license:YOUR_LICENSE_HERE group.admin✅ Testing Your Configuration
After making changes:
Restart the resource:
restart 0bug_SceneKitsCheck console for any errors
Test in-game:
Open menu with
/sk_spawn(or your command)Spawn a scene to verify permissions
Check if limits work correctly
Monitor performance:
Use
/sk_statsto view active scenesAdjust limits if needed
🆘 Common Issues
"No permission for this kit"
Job names don't match your framework
Props not spawning
Invalid prop models for your server
Kit doesn't appear
Wrong allow category or syntax error
Command not working
Check spelling or try different command name
💾 Backup Reminder
Always backup your config files before making major changes:
config/kits.lua → config/kits.lua.backupLast updated