> For the complete documentation index, see [llms.txt](https://uniqers-scripts-docs.gitbook.io/uniqers-scripts-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://uniqers-scripts-docs.gitbook.io/uniqers-scripts-docs/uniqers-spawn.md).

# uniqers-spawn

<figure><img src="/files/hy3wVyUAkUtMzMR0NW5R" alt=""><figcaption></figcaption></figure>

<figure><img src="https://dunb17ur4ymx4.cloudfront.net/wysiwyg/1302793/8d1a45373067aa1b6bfeae1aae2fce36dac934d2.jpg" alt=""><figcaption></figcaption></figure>

## 📖 Uniqers-Spawn: Installation & Configuration Guide

Welcome to the official installation guide for Uniqers-Spawn. Please carefully follow the instructions corresponding to your server's framework.

### 🟢 QBCore / QBus / Custom QBCore Frameworks

#### Step 1: Remove Old Spawn Scripts

Stop or delete `qb-spawn` or any other spawn script you are currently using.

#### Step 2: Update Apartments

Navigate to `qb-apartments/client/main.lua`. To integrate both the first spawn and normal spawn functionality ensuring compatibility with jobs, gangs, houses, and apartments, replace the relevant spawn UI code with the following:

Lua

```
RegisterNetEvent('apartments:client:setupSpawnUI', function(cData)
    QBCore.Functions.TriggerCallback('apartments:GetOwnedApartment', function(result)
        if result then
            TriggerEvent('qb-spawn:client:setupSpawns', cData, false, nil)
            TriggerEvent('qb-spawn:client:openUI', true)
            TriggerEvent("apartments:client:SetHomeBlip", result.type)
        elseif Apartments.Starting then
            TriggerEvent('qb-spawn:client:setupSpawns', cData, true, Apartments.Locations)
            TriggerEvent('qb-spawn:client:openUI', true)
        else
            TriggerEvent('qb-spawn:client:setupSpawns', cData, false, nil)
            TriggerEvent('qb-spawn:client:openUI', true)
        end
    end, cData.citizenid)
end)
```

#### Step 3: Add Spawn Locations for Gangs & Jobs

Open `[qb]\qb-core\shared\gangs.lua` and `[qb]\qb-core\shared\jobs.lua` to add `spawnlocations` to your configurations.

For Gangs (`gangs.lua`):

Lua

```
ballas = {
    label = 'Ballas',
    grades = {
        ['0'] = { name = 'Recruit' },
        ['1'] = { name = 'Enforcer' },
        ['2'] = { name = 'Shot Caller' },
        ['3'] = { name = 'Boss', isboss = true },
    },
    spawnlocations = {
        [1] = {x = 469.34469, y = -982.1764, z = 26.273393}
    },
},    
```

For Jobs (`jobs.lua`):

Lua

```
police = {
    label = 'Law Enforcement',
    type = 'leo',
    defaultDuty = true,
    offDutyPay = false,
    grades = {
        ['0'] = { name = 'Recruit', payment = 50 },
        ['1'] = { name = 'Officer', payment = 75 },
        ['2'] = { name = 'Sergeant', payment = 100 },
        ['3'] = { name = 'Lieutenant', payment = 125 },
        ['4'] = { name = 'Chief', isboss = true, payment = 150 },
    },
    spawnlocations = {
        [1] = {x = 469.34469, y = -982.1764, z = 26.273393}
    },
},
```

#### Step 4: Configure Apartment Locations

Open `qb-apartments/config.lua` and update your `Apartments.Locations` table:

Lua

```
Apartments.Locations = {
    ["apartment1"] = {
        name = "apartment1",
        label = "South Rockford Drive",
        image = "img/imgap1.png",
        price = "FREE",
        description = "Information about the hotel can be written here.",
        maplocation = "img/imgap1.jpg",
        coords = {
            enter = vector4(-667.02, -1105.24, 14.63, 242.32),
            camcoords = vector4(-691.7783, -1098.214, 27.575319, 263.03857),
        },
        polyzoneBoxData = {
            heading = 245,
            minZ = 13.5,
            maxZ = 16.0,
            debug = false,
            length = 1,
            width = 3,
            distance = 2.0,
            created = false
        }
    },
    ["apartment2"] = {
        name = "apartment2",
        label = "Morningwood Blvd",
        image = "img/imgap2.png",
        price = "FREE",
        description = "Information about the hotel can be written here.",
        maplocation = "img/imgap2.jpg",
        coords = {
            enter = vector4(-1288.52, -430.51, 35.15, 124.81),
            camcoords = vector4(-1260.244, -423.0414, 45.239257, 101.14539),
        },
        polyzoneBoxData = {
            heading = 124,
            minZ = 34.0,
            maxZ = 37.0,
            debug = false,
            length = 1,
            width = 3,
            distance = 2.0,
            created = false
        }
    },
    ["apartment3"] = {
        name = "apartment3",
        label = "Integrity Way",
        image = "img/imgap3.png",
        price = "FREE",
        description = "Information about the hotel can be written here.",
        maplocation = "img/imgap3.jpg",
        coords = {
            enter = vector4(269.73, -640.75, 42.02, 249.07),
            camcoords = vector4(245.81562, -622.9107, 58.348945, 228.84838),
        },
        polyzoneBoxData = {
            heading = 250,
            minZ = 40,
            maxZ = 43.5,
            debug = false,
            length = 1,
            width = 1,
            distance = 2.0,
            created = false
        }
    },
    ["apartment4"] = {
        name = "apartment4",
        label = "Tinsel Towers",
        image = "img/imgap4.png",
        price = "FREE",
        description = "Information about the hotel can be written here.",
        maplocation = "img/imgap4.jpg",
        coords = {
            enter = vector4(-619.29, 37.69, 43.59, 181.03),
            camcoords = vector4(-586.6358, 8.9766902, 63.2192, 358.14163),
        },
        polyzoneBoxData = {
            heading = 180,
            minZ = 41.0,
            maxZ = 45.5,
            debug = false,
            length = 1,
            width = 2,
            distance = 2.0,
            created = false
        }
    },
    ["apartment5"] = {
        name = "apartment5",
        label = "Fantastic Plaza",
        image = "img/imgap5.png",
        price = "FREE",
        description = "Information about the hotel can be written here.",
        maplocation = "img/imgap5.jpg",
        coords = {
            enter = vector4(291.517, -1078.674, 29.405, 270.75),
            camcoords = vector4(313.55181, -1087.797, 52.274063, 68.456321),
        },
        polyzoneBoxData = {
            heading = 270,
            minZ = 28.5,
            maxZ = 31.0,
            debug = false,
            length = 1,
            width = 2,
            distance = 2.0,
            created = false
        }
    },
}
```

> Note: If you are using custom apartments, you can utilize `FirstLoadAP()`. If you are using custom character creation codes, utilize `FirstLoad()` inside your config.

### 🔵 ESX / Old ESX / Custom ESX Frameworks

#### Step 1: Remove Old Scripts

Stop or delete your current spawn script.

#### Step 2: Compatibility Notice

By default, ESX does not include native apartment, gang, or house scripts. If you are using custom scripts for these features and wish to integrate them with this spawn script, please contact our support team for compatibility patches.

#### Step 3: Multicharacter Integration

If you are using a multicharacter script, replace the existing spawn triggers with the following logic. (If you do not use multicharacter, apply this where your character originally spawns):

Client-Side Event:

Lua

```
TriggerEvent('qb-spawn:client:setupSpawns', Player, false, nil)
TriggerEvent('qb-spawn:client:openUI', true)
```

Server-Side Trigger (if needed from server):

Lua

```
TriggerClientEvent('qb-spawn:client:setupSpawns', src, Player, false, nil)
TriggerClientEvent('qb-spawn:client:openUI', src, true)
```

Your characters will now be fully integrated with the spawn system.

#### Step 4: Custom Character Creation

Because Uniqers-Spawn bypasses standard ESX apartment logic for new characters, players will spawn at a designated creation location. You can trigger your custom character creation UI via the `FirstLoad()` function in the config:

Lua

```
function FirstLoad() 
    
end
```

> Place your custom character script events inside this function. If you are using a specific custom apartment system for ESX, contact us and we can implement it for you.

### 🟣 QBX Framework (Qbox)

#### Step 1: Remove Old Scripts

Stop or delete `qbx_spawn` or any other spawn script you are currently using. Note that QBX natively lacks house scripts; if you use third-party housing, contact us for integration.

#### Step 2: QBX Core Integration (`qbx_core`)

To allow your players to trigger the script after selecting or creating a character, update the following in `qbx_core`:

Step 2.1: Modify `onSelect` Navigate to `qbx_core/client/character.lua` (Around Line 318). Update the existing character loading logic with the Uniqers-Spawn check:

Lua

```
onSelect = function()
    DoScreenFadeOut(10)
    lib.callback.await('qbx_core:server:loadCharacter', false, character.citizenid)
    if GetResourceState('qbx_apartments'):find('start') then
        TriggerEvent('apartments:client:setupSpawnUI', character.citizenid)
    elseif GetResourceState('uniqers-spawn'):find('start') then 
        TriggerEvent('qb-spawn:client:setupSpawns', character.citizenid)
        TriggerEvent('qb-spawn:client:openUI', true)
    elseif GetResourceState('qbx_spawn'):find('start') then
        TriggerEvent('qb-spawn:client:setupSpawns', character.citizenid)
        TriggerEvent('qb-spawn:client:openUI', true)
    else
        spawnLastLocation()
    end
    destroyPreviewCam()
end
```

Step 2.2: Modify `createCharacter` Navigate to `qbx_core/client/character.lua` (Around Line 215). Update the default spawn check for new characters:

Lua

```
if GetResourceState('uniqers-spawn') == 'missing' and GetResourceState('qbx_spawn') == 'missing' then
    spawnDefault()
else
    if config.characters.startingApartment then
        TriggerEvent('apartments:client:setupSpawnUI', newData)
    else
        TriggerEvent('qbx_core:client:spawnNoApartments')
    end
end
```

#### Step 3: QBX Properties Integration (`qbx_properties`)

To completely disable QBX's default board UI and route the apartment list directly to your script's screen, apply this step:

Navigate to `qbx_properties/client/apartments.lua` (Around Line 206). Completely clear the `apartments:client:setupSpawnUI` event content and change it to trigger your interface directly:

Lua

```
RegisterNetEvent('apartments:client:setupSpawnUI', function(cData)
    TriggerEvent('qb-spawn:client:setupSpawns', cData, true, nil)
    TriggerEvent('qb-spawn:client:openUI', true)
end)
```

#### Step 4: Uniqers Spawn Configuration (`config.lua`)

Since the QBX apartment system uses numerical IDs instead of names, the table index structure must be a numerical string. Update your `config.lua` settings:

Lua

```
UniqersSpawn.QBX = true
UniqersSpawn.ApartmentStyle = "qbx-apartment"

UniqersSpawn.QBApartments = {
    ["1"] = {
        name = "1",
        label = "Del Perro Heights Apt",
        image = "img/imgap1.png",
        price = "FREE",
        description = "Enjoy ocean views far away from tourists and bums on Del Perro Beach.",
        coords = {
            enter = vector4(-1447.35, -537.84, 34.74, 120.0),
            camcoords = vector4(-1467.0, -537.0, 45.0, 250.0),
        }
    },
    ["2"] = {
        name = "2",
        label = "Del Perro Heights Apt",
        image = "img/imgap2.png",
        price = "FREE",
        description = "Luxury Del Perro Heights apartment complex! For all you voyeurs out there!",
        coords = {
            enter = vector4(-1447.35, -537.84, 34.74, 120.0),
            camcoords = vector4(-1467.0, -537.0, 45.0, 250.0),
        }
    },
    ["3"] = {
        name = "3",
        label = "4 Integrity Way Apt",
        image = "img/imgap3.png",
        price = "FREE",
        description = "This is such an promosing neighborhood, you can literally see the construction from your window!",
        coords = {
            enter = vector4(-59.4, -616.29, 37.36, 180.0),
            camcoords = vector4(-80.0, -616.0, 50.0, 270.0),
        }
    },
    ["4"] = {
        name = "4",
        label = "4 Integrity Way Apt",
        image = "img/imgap4.png",
        price = "FREE",
        description = "An apartment so expansive, all your friends will immediately know how much you paid for it.",
        coords = {
            enter = vector4(-47.52, -585.86, 37.95, 180.0),
            camcoords = vector4(-80.0, -585.0, 50.0, 270.0),
        }
    },
    ["5"] = {
        name = "5",
        label = "Richard Majestic Apt",
        image = "img/imgap5.png",
        price = "FREE",
        description = "This breathtaking luxury condo is a stone's throw from AKAN Records and a Sperm Donor Clinic.",
        coords = {
            enter = vector4(-936.15, -378.91, 38.96, 30.0),
            camcoords = vector4(-950.0, -360.0, 50.0, 210.0),
        }
    },
    ["6"] = {
        name = "6",
        label = "Tinsel Towers Apt",
        image = "img/imgap1.png",
        price = "FREE",
        description = "A picture-perfect lateral living experience in one of Los Santos most sought-after tower blocks.",
        coords = {
            enter = vector4(-614.58, 46.52, 43.59, 180.0),
            camcoords = vector4(-630.0, 60.0, 55.0, 250.0),
        }
    }
}
```

#### Step 5: Jobs & Gangs Update for QBX

Just like QBCore, append `spawnlocations` to your gang and job tables in `[qbx]\qbx_core\shared\gangs.lua` and `jobs.lua`:

For Gangs (`gangs.lua`):

Lua

```
['lostmc'] = {
    label = 'The Lost MC',
    grades = {
        [0] = {name = 'Recruit'},
        [1] = {name = 'Enforcer'},
        [2] = {name = 'Shot Caller'},
        [3] = {name = 'Boss', isboss = true, bankAuth = true},
    },
    spawnlocations = {
        [1] = {x = 469.34469, y = -982.1764, z = 26.273393}
    },
},
```

For Jobs (`jobs.lua`):

Lua

```
['police'] = {
    label = 'LSPD',
    type = 'leo',
    defaultDuty = true,
    offDutyPay = false,
    grades = {
        [0] = {name = 'Recruit', payment = 50},
        [1] = {name = 'Officer', payment = 75},
        [2] = {name = 'Sergeant', payment = 100},
        [3] = {name = 'Lieutenant', payment = 125},
        [4] = {name = 'Chief', isboss = true, bankAuth = true, payment = 150},
    },
    spawnlocations = {
        [1] = {x = 469.34469, y = -982.1764, z = 26.273393}
    },
},
```

#### Step 6: Server Properties Update

Navigate to `qbx_properties/server/property.lua` and paste the following event:

Lua

```
RegisterNetEvent('uniqers:qbx:login:apart', function(cid)
    local src = source
    local property = MySQL.single.await('SELECT * FROM properties WHERE owner = ?', {cid})
    local id = property.id
    local propertyCoords = json.decode(property.coords)
    propertyCoords = vec3(propertyCoords.x, propertyCoords.y, propertyCoords.z)
    
    local player = exports.qbx_core:GetPlayerByCitizenId(cid)
    citizenid[src] = player.PlayerData.citizenid
    local interactions = {}
    local isInteriorShell = tonumber(property.interior) ~= nil
    local stashes = json.decode(property.stash_options)
    
    for i = 1, #stashes do    
        local stashCoords = isInteriorShell and CalculateOffsetCoords(propertyCoords, stashes[i].coords) or stashes[i].coords    
        interactions[#interactions+1] = {        
            type = 'stash',        
            coords = vec3(stashCoords.x, stashCoords.y, stashCoords.z)    
        }    
        exports.ox_inventory:RegisterStash(string.format('qbx_properties_%s', property.property_name), string.format('Property: %s', property.property_name), stashes[i].slots, stashes[i].maxWeight, property.owner)
    end
    
    if isInteriorShell then    
        TriggerClientEvent('qbx_properties:client:createInterior', src, tonumber(property.interior), vec3(propertyCoords.x, propertyCoords.y, propertyCoords.z - ShellUndergroundOffset))
    end
    
    local interactData = json.decode(property.interact_options)
    for i = 1, #interactData do    
        local coords = isInteriorShell and CalculateOffsetCoords(propertyCoords, interactData[i].coords) or interactData[i].coords    
        interactions[#interactions+1] = {        
            type = interactData[i].type,        
            coords = vec3(coords.x, coords.y, coords.z)    
        }    
        if interactData[i].type == 'exit' then        
            SetEntityCoords(GetPlayerPed(src), coords.x, coords.y, coords.z, false, false, false, false)    
        end
    end
    
    local decorations = json.decode(property.decorations)
    for i = 1, #decorations do    
        decorations[i].coords = CalculateOffsetCoords(propertyCoords, decorations[i].coords) or vec3(decorations[i].coords.x, decorations[i].coords.y, decorations[i].coords.z)
    end
    
    TriggerClientEvent('qbx_properties:client:loadDecorations', src, decorations)
    enteredProperty[src] = id
    insideProperty[id] = insideProperty[id] or {}
    insideProperty[id][#insideProperty[id] + 1] = src
    
    for i = 1, #insideProperty[id] do    
        TriggerClientEvent('qbx_properties:client:concealPlayers', insideProperty[id][i], insideProperty[id])
    end
    
    TriggerClientEvent('qbx_properties:client:updateInteractions', src, interactions, type(property.rent_interval) == 'number')
end)
```

### 🏗️ 0r-Apartment Integration (Optional)

If you are running the `0r-apartment` resource, open your `0r-apartment` config file and integrate the variables for each apartment as shown in the template below:

Variable Requirements:

Lua

```
name = 1, 
image = "img/imgap4.png",
price = "FREE",
description = "Information about the hotel can be written here.",
maplocation = "img/imgap4.jpg",
coords = {
    enter = vector4(-619.29, 37.69, 43.59, 181.03),
    camcoords = vector4(-586.6358, 8.9766902, 63.2192, 358.14163),
},
```

Full Implementation Example:

Lua

```
[1] = {    
    name = 1,    
    label = "Shelly Apart",	
    image = "img/imgap4.png",	
    price = "FREE",	
    description = "Information about the hotel can be written here.",	
    maplocation = "img/imgap4.jpg",    
    tint = 55,    
    coords = { 
        enter = vec4(278.6257, -1118.3618, 29.4197, 179.6273), 
        camcoords = vector4(-586.6358, 8.9766902, 63.2192, 358.14163) 
    },    
    blip = {        
        active = true,        
        title = "Shelly Apart #1",        
        sprite = 476,        
        color = 2,        
        scale = 0.8,        
        coords = vec3(278.202209, -1124.268188, 29.380981)    
    },
},  
```

### Support & Updates & Questions <a href="#support-and-updates-and-questions" id="support-and-updates-and-questions"></a>

![https://discord.gg/MyrGhbf9tM](https://uniqers-scripts-docs.gitbook.io/~gitbook/image?url=https%3A%2F%2F1436200110-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FZO8XqahJMWr9lDZTL9c1%252Fuploads%252F6U1vJg05XehtFcmGXsMW%252F3670325.png%3Falt%3Dmedia%26token%3D603ba3cd-283e-42c5-a0e2-13d33fefb5bd\&width=768\&dpr=4\&quality=100\&sign=80843ce\&sv=2)

<https://discord.gg/MyrGhbf9tM>
