# Starter Apartments

{% hint style="success" %}
Starter apartments let you automatically **assign a default apartment** to newly created characters and (optionally) **teleport** them inside right after creation.

This guide shows:

* how to configure starter apartments in `config.lua`
* where to call the server export to assign the apartment
* how to teleport the player after character creation (client export)
* examples for **ESX**, **qb-multicharacter**, and **qbx\_core**

✅ Works with **any framework** — you only need a place in your character creation flow where you can run the exports.
{% endhint %}

{% stepper %}
{% step %}

### Configure Starter Apartments (config.lua)

#### Create an Apartment Complex (required)

Starter apartments require an **apartment complex / building** (a “container” for starter units).

* Open the **Property Creator** (`/propertycreator`)
* Create an **Apartment Complex / Building**
* Save it
* Open your database and copy the **houseId / id** of the created complex
* Paste that value into `Config.StarterApartments.complexid`

{% hint style="info" %}
The complex ID is used as the parent building for the starter apartments.
{% endhint %}

#### Set your Starter Apartment configuration

```lua
Config.StarterApartments = { -- Instructions for implementing starter apartments in your multicharacter system can be found in [Dev Tools - Docs]/STARTER APARTMENTS.txt
    complexid = "509507963", -- You must create an apartment complex and enter the complex ID (houseId) from the database here
    apartmenttype = "SHELL", -- Apartment type: SHELL or IPL
    apartmentid = "rtx_housing_shell_1", -- Index from Config.HouseShells or Config.HouseIpls
    apartmenttheme = "modern", -- Theme used for IPL apartments only
    furnitureinside = true, -- Enable if players are allowed to place furniture inside the apartment
    wardrobe = true, -- Enable if the apartment includes a wardrobe
    storage = true, -- Enable if the apartment includes storage
    storagedata = {
        slots = 40,       -- Number of storage slots
        weight = 100000, -- Maximum storage weight (depends on your inventory system)
    },
    cantransfer = false, -- Enable if players are allowed to transfer the starter apartment
    cansell = false, -- Enable if players are allowed to sell the starter apartment
    sellprice = 0, -- Sell price (usually 0 for starter apartments)
    canlist = false, -- Enable if players are allowed to list the apartment on the market
}
```

**Quick notes**

* **SHELL:** `apartmentid` must exist in `shells.lua` (`Config.HouseShells`)
* **IPL:** `apartmentid` must exist in `ipls.lua` (`Config.HouseIpls`) and you can set `apartmenttheme`
* If you change/remove the interior later, do it carefully to avoid orphaned properties
  {% endstep %}

{% step %}

### Give Starter Apartment (server-side)

This is the **server export** you call once — right after a new character is created:

```lua
exports["rtx_housing"]:GiveStarterApartment(source)
```

#### When should I call it?

Call it only for **new characters** (first time creation). Most frameworks provide an `isNew` flag or similar logic.

#### ESX (es\_extended)

**File:** `es_extended/server/main.lua`\
**Function:** `loadESXPlayer` (or `LoadESXPlayer`, depends on version)

1. Find the function that loads the player
2. At the end of the function, after the player is fully loaded, add:

```lua
if isNew then
    exports["rtx_housing"]:GiveStarterApartment(playerId)
end
```

<details>

<summary><strong>Example code (ESX) — expanded snippet</strong></summary>

```lua
-- ... inside loadESXPlayer(...)

TriggerEvent("esx:playerLoaded", playerId, xPlayer, isNew)
xPlayer.triggerEvent("esx:playerLoaded", userData, isNew, userData.skin)

-- Give starter apartment only to new characters
if isNew then
    exports["rtx_housing"]:GiveStarterApartment(playerId)

    -- Optional: teleport after a short delay (recommended)
    Citizen.Wait(1500)
    exports["rtx_housing"]:TeleportPlayerToStartingApartment(playerId)
end
```

</details>

#### QBCore (qb-multicharacter)

**File:** `qb-multicharacter/server/main.lua`\
**Function:** `GiveStarterItems`

1. Find `GiveStarterItems`
2. Add the export at the end:

```lua
exports["rtx_housing"]:GiveStarterApartment(src)
```

<details>

<summary><strong>Example code (qb-multicharacter) — expanded snippet</strong></summary>

```lua
local function GiveStarterItems(source)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)

    for _, v in pairs(QBCore.Shared.StarterItems) do
        local info = {}
        -- ... existing starter items logic ...
        exports['qb-inventory']:AddItem(src, v.item, v.amount, false, info, 'qb-multicharacter:GiveStarterItems')
    end

    -- Give starter apartment
    exports["rtx_housing"]:GiveStarterApartment(src)
end
```

</details>

#### QBox / qbx\_core

**File:** `qbx_core/server/character.lua`\
**Function:** `giveStarterItems`

Add at the end of the function:

```lua
exports["rtx_housing"]:GiveStarterApartment(source)
```

<details>

<summary><strong>Example code (qbx_core) — expanded snippet</strong></summary>

```lua
local function giveStarterItems(source)
    if GetResourceState('ox_inventory') == 'missing' then return end

    while not exports.ox_inventory:GetInventory(source) do
        Wait(100)
    end

    for i = 1, #starterItems do
        local item = starterItems[i]
        if item.metadata and type(item.metadata) == 'function' then
            exports.ox_inventory:AddItem(source, item.name, item.amount, item.metadata(source))
        else
            exports.ox_inventory:AddItem(source, item.name, item.amount, item.metadata)
        end
    end

    -- Give starter apartment
    exports["rtx_housing"]:GiveStarterApartment(source)
end
```

</details>
{% endstep %}

{% step %}

### Teleport player to Starter Apartment (client-side)

This is the **client export** you can call after character creation / skin creation:

```lua
exports["rtx_housing"]:TeleportPlayerToStartingApartment()
```

#### Recommended usage

* Call it **after** the character is created and spawned
* If you call teleport too early, the player may not be fully initialized

#### ESX Multicharacter (example)

<details>

<summary><strong>Example code (esx_multicharacter) — teleport after skin creator</strong></summary>

```lua
function Multicharacter:LoadSkinCreator(skin)
    TriggerEvent("skinchanger:loadSkin", skin, function()
        exports["rtx_housing"]:TeleportPlayerToStartingApartment()

        DoScreenFadeIn(600)
        SetPedAoBlobRendering(self.playerPed, true)
        ResetEntityAlpha(self.playerPed)

        TriggerEvent("esx_skin:openSaveableMenu", function()
            Multicharacter.finishedCreation = true
        end, function()
            Multicharacter.finishedCreation = true
        end)
    end)
end
```

</details>

#### qb-multicharacter (example)

**File:** `qb-multicharacter/client/main.lua`

<details>

<summary><strong>Example code (qb-multicharacter) — teleport on spawn event</strong></summary>

```lua
RegisterNetEvent('qb-multicharacter:client:closeNUIdefault', function()
    -- ... existing spawn logic ...

    TriggerEvent('qb-clothes:client:CreateFirstCharacter')

    -- Teleport to starter apartment
    exports["rtx_housing"]:TeleportPlayerToStartingApartment()
end)
```

</details>

#### qbx\_core (example)

<details>

<summary><strong>Example code (qbx_core) — teleport on spawn event</strong></summary>

```lua
RegisterNetEvent('qbx_core:client:spawnNoApartments', function()
    -- ... existing spawn logic ...

    TriggerEvent('qb-clothes:client:CreateFirstCharacter')

    -- Teleport to starter apartment
    exports["rtx_housing"]:TeleportPlayerToStartingApartment()
end)
```

</details>
{% endstep %}

{% step %}

### Global explanation (for any framework)

You only need two things:

#### Give the apartment (server-side)

Call once for new characters:

```lua
exports["rtx_housing"]:GiveStarterApartment(source)
```

#### Teleport (client-side)

Call after character/spawn is finished:

```lua
exports["rtx_housing"]:TeleportPlayerToStartingApartment()
```

✅ This works for **any framework**.\
Just place these calls into the correct “new character created” and “player spawned” moments.

***

### Need help?

If you want, **we can implement the integration for you**.\
Contact us on Discord: <https://discord.gg/rtxdev>
{% endstep %}
{% endstepper %}
