🎉 Driving School is released. Read more →
Paid Scripts
Housing
Integrations
Spawn Selector Scripts
Rm Spawnselector

Rainmad Spawnselector

In your cfg file please put the housing to '3'

Replace these files

client/editable.lua
setPlayerModel = function(gender)
    if gender == nil then
        gender = 0
    end
    local playerPed = PlayerPedId()
    local model = gender == 0 and "mp_m_freemode_01" or "mp_f_freemode_01"
    if not HasModelLoaded(model) then
        RequestModel(model)
        while not HasModelLoaded(model) do
            Citizen.Wait(100)
        end
    end
 
    SetPlayerModel(PlayerId(), model)
    SetPedComponentVariation(PlayerPedId(), 0, 0, 0, 2)
end
 
if framework == 'qb' then
    local qbHouses, qbApartments
    RegisterNetEvent('qb-houses:client:setHouseConfig', function(houseConfig)
        qbHouses = houseConfig
    end)
    RegisterNetEvent('housing:client:setHouseConfig', function(_, houseConfig)
        qbHouses = houseConfig
    end)
 
    RegisterNetEvent('qb-spawn:client:setupSpawns', function(cData, new, apps)
        locations = {}
        if not apps or not next(apps) and cfg['housing'] == '1' or cfg['housing'] == 2 then
            if not Apartments or not next(Apartments.Locations) then
                local dummy = require('@qbx_apartments.config.shared') or nil
                if not dummy or not next(dummy) then
                    print("APARTMENT CONFIG NOT IMPORTED PLEASE CHECK FXMANIFEST.LUA")
                else
                    qbApartments = dummy.locations
                end
            else
                qbApartments = Apartments.Locations
            end
        else
            if apps and next(apps) then
                qbApartments = apps
            end
        end
 
        if not new then
            while not QBCore do
                Wait(0)
            end
 
            QBCore.Functions.GetPlayerData(function(pd)
                locations[#locations + 1] = {
                    coords = pd.position,
                    label = cfg['locales']['last_location'],
                    id = -1,
                    type = 'last',
                }
            end)
 
            triggerCallback('spawnselector:server:getOwnedHouses', function(houses)
                if houses then
                    for i = 1, #houses do
                        if cfg['housing'] == '2' then
                            if not houses[i].apartment then
                                local houseData = json.decode(houses[i].door_data)
                                locations[#locations + 1] = {
                                    coords = vector3(houseData.x, houseData.y, houseData.z),
                                    label = ("%s - %s"):format(houses[i].street, houses[i].property_id),
                                    id = houses[i].property_id,
                                    type = 'house',
                                }
                            end
                        elseif cfg['housing'] == '3' then
                            local entry = houses[i].complex == 'Flat' and houses[i].data.flat.coords or houses[i].entry
                            locations[#locations + 1] = {
                                coords = vec3(entry.x, entry.y, entry.z),
                                label = houses[i].name,
                                id = houses[i].identifier,
                                type = 'house',
                            }
                        else
                            locations[#locations + 1] = {
                                coords = qbHouses[houses[i].house].coords.enter,
                                label = qbHouses[houses[i].house].adress,
                                id = houses[i].house,
                                type = 'house',
                            }
                        end
                    end
                end
            end, cData.citizenid)
 
            triggerCallback('spawnselector:server:getOwnedApartments', function(result)
                if result then
                    if cfg['housing'] == '1' then
                        for name, _ in pairs(qbApartments) do
                            if (name == result.type) then
                                locations[#locations + 1] = {
                                    coords = qbApartments[name].coords and qbApartments[name].coords.enter or
                                        qbApartments[name].enter,
                                    label = qbApartments[name].label,
                                    id = result.type,
                                    type = 'default',
                                }
                            end
                        end
                    else
                        for name, _ in pairs(qbApartments) do
                            if (name == result.apartment) then
                                locations[#locations + 1] = {
                                    coords = vector3(qbApartments[name].door.x, qbApartments[name].door.y,
                                        qbApartments[name].door.z),
                                    label = qbApartments[name].label,
                                    id = result.apartment,
                                    type = 'default',
                                }
                            end
                        end
                    end
                end
            end, cData.citizenid)
        elseif new then
            if not next(qbApartments) then
                locations[#locations + 1] = {
                    coords = cfg['newCharacterSpawnPoint'].coords,
                    label = cfg['newCharacterSpawnPoint'].label,
                    id = #locations + 1,
                    type = 'default',
                    backgroundColor = cfg['newCharacterSpawnPoint'].backgroundColor,
                    iconColor = cfg['newCharacterSpawnPoint'].iconColor,
                    iconName = cfg['newCharacterSpawnPoint'].iconName,
                }
            else
                for id, data in pairs(qbApartments) do
                    locations[#locations + 1] = {
                        coords = cfg['housing'] == '2' and qbApartments[id].door or
                            qbApartments[id].coords and qbApartments[id].coords.enter or qbApartments[id].enter,
                        label = qbApartments[id].label,
                        id = id,
                        type = 'apartment',
                    }
                end
            end
        end
 
        DoScreenFadeIn(200)
        TriggerServerEvent('QBCore:Server:OnPlayerLoaded')
        TriggerEvent('QBCore:Client:OnPlayerLoaded')
 
        Citizen.Wait(1000)
 
        if not cData or not cData.charinfo then
            cData = QBCore.Functions.GetPlayerData()
        end
 
        if new then
            setPlayerModel(cData and cData.charinfo and cData.charinfo.gender or nil)
        else
            TriggerEvent("illenium-appearance:client:reloadSkin", true)
            TriggerServerEvent('qb-clothes:loadPlayerSkin')
        end
 
        local playerJob = cData and cData.job and cData.job.name or nil
 
        startSpawnSelect(new, playerJob)
    end)
 
    RegisterNuiCallback('spawn', function(data, cb)
        cb(0)
 
        switchGameplayCam()
 
        local ped = PlayerPedId()
        if data.type == 'apartment' then
            if cfg['housing'] == '2' then
                TriggerServerEvent('ps-housing:server:createNewApartment', data.id)
            else
                TriggerServerEvent('apartments:server:CreateApartment', data.id, qbApartments[data.id].label)
            end
            FreezeEntityPosition(ped, false)
        elseif data.type == 'house' then
            if cfg['housing'] == '2' then
                TriggerServerEvent('ps-housing:server:enterProperty', tostring(data.id))
            elseif cfg['housing'] == '3' then
                SetEntityCoords(ped, data.coords.x, data.coords.y, data.coords.z)
            else
                TriggerEvent('housing:client:enterOwnedHouse', data.id)
                TriggerEvent('qb-houses:client:enterOwnedHouse', data.id)
            end
            TriggerServerEvent('qb-houses:server:SetInsideMeta', 0, false)
            TriggerServerEvent('qb-apartments:server:SetInsideMeta', 0, 0, false)
        elseif data.type == 'last' then
            local inside = {}
            QBCore.Functions.GetPlayerData(function(pd)
                RequestCollisionAtCoord(pd.position.x, pd.position.y, pd.position.z)
                while not HasCollisionLoadedAroundEntity(ped) do
                    Wait(0)
                end
                SetEntityCoords(ped, pd.position.x, pd.position.y, pd.position.z)
                SetEntityHeading(ped, pd.position.a)
                inside = pd.metadata['inside']
                if inside.house ~= nil then
                    local houseId = inside.house
                    TriggerEvent('qb-houses:client:LastLocationHouse', houseId)
                    TriggerEvent('housing:client:LastLocationHouse', houseId)
                elseif cfg['housing'] == '2' and inside.property_id ~= nil then
                    TriggerServerEvent('ps-housing:server:enterProperty', tostring(inside.property_id))
                elseif inside.apartment.apartmentType ~= nil or inside.apartment.apartmentId ~= nil then
                    local apartmentType = inside.apartment.apartmentType
                    local apartmentId = inside.apartment.apartmentId
                    TriggerEvent('qb-apartments:client:LastLocationHouse', apartmentType, apartmentId)
                end
            end)
        else
            local pos = cfg['locations'][data.id] and cfg['locations'][data.id].coords or nil
            if not pos then
                for k, v in pairs(locations) do
                    if v.id == data.id then
                        pos = v.coords
                    end
                end
            end
 
            TriggerServerEvent('qb-houses:server:SetInsideMeta', 0, false)
            TriggerServerEvent('qb-apartments:server:SetInsideMeta', 0, 0, false)
 
            RequestCollisionAtCoord(pos.x, pos.y, pos.z)
            while not HasCollisionLoadedAroundEntity(ped) do
                Wait(0)
            end
 
            SetEntityCoords(ped, pos.x, pos.y, pos.z)
            SetEntityHeading(ped, pos.w)
        end
 
        FreezeEntityPosition(ped, false)
    end)
end
 
if framework == 'esx' then
    local lastLocation, newChar = nil, false
 
    local qsHouses
    RegisterNetEvent('housing:client:setHouseConfig', function(_, houseConfig)
        qsHouses = houseConfig
    end)
 
    RegisterNetEvent('esx:playerLoaded', function(playerData, isNew, skin)
        locations = {}
        lastLocation = playerData.coords
 
        triggerCallback('spawnselector:server:getOwnedHouses', function(houses)
            if houses then
                for i = 1, #houses do
                    if cfg['housing'] == '3' then
                        local entry = houses[i].complex == 'Flat' and houses[i].data.flat.coords or houses[i].entry
                        locations[#locations + 1] = {
                            coords = vec3(entry.x, entry.y, entry.z),
                            label = houses[i].name,
                            id = houses[i].identifier,
                            type = 'house',
                        }
                    else
                        locations[#locations + 1] = {
                            coords = qsHouses[houses[i].house].coords,
                            label = qsHouses[houses[i].house].adress,
                            id = houses[i].house,
                            type = 'house',
                        }
                    end
                end
            end
        end, playerData.identifier)
 
        if not isNew then
            locations[#locations + 1] = {
                coords = lastLocation,
                label = cfg['locales']['last_location'],
                id = -1,
                type = 'last',
            }
        else
            locations[#locations + 1] = {
                coords = cfg['newCharacterSpawnPoint'].coords,
                label = cfg['newCharacterSpawnPoint'].label,
                id = #locations + 1,
                type = 'default',
                backgroundColor = cfg['newCharacterSpawnPoint'].backgroundColor,
                iconColor = cfg['newCharacterSpawnPoint'].iconColor,
                iconName = cfg['newCharacterSpawnPoint'].iconName,
            }
            newChar = true
        end
 
        skin.sex = playerData.sex == "m" and 0 or 1
        if isNew then
            setPlayerModel(skin.sex)
        else
            TriggerEvent("illenium-appearance:client:reloadSkin", true)
            TriggerEvent('skinchanger:loadSkin', skin)
        end
 
        local playerJob = playerData and playerData.job and playerData.job.name or nil
 
        startSpawnSelect(isNew, playerData.job.name)
    end)
 
    RegisterNuiCallback('spawn', function(data, cb)
        cb(0)
 
        switchGameplayCam()
 
        local ped = PlayerPedId()
        if data.type == 'last' then
            SetEntityCoords(ped, lastLocation.x, lastLocation.y, lastLocation.z)
            SetEntityHeading(ped, lastLocation.heading)
 
            -- qs-housing
            ESX.TriggerServerCallback('housing:server:getInside', function(inside)
                TriggerEvent('housing:client:lastLocationHouse', inside)
            end)
        elseif data.type == 'house' then
            if cfg['housing'] == '3' then
                SetEntityCoords(ped, data.coords.x, data.coords.y, data.coords.z)
            else
                TriggerEvent('housing:client:enterOwnedHouse', data.id)
            end
        else
            local pos = cfg['locations'][data.id].coords
 
            RequestCollisionAtCoord(pos.x, pos.y, pos.z)
            while not HasCollisionLoadedAroundEntity(ped) do
                Wait(0)
            end
 
            SetEntityCoords(ped, pos.x, pos.y, pos.z)
            SetEntityHeading(ped, pos.w)
        end
 
        -- esx_multicharacter (legacy)
        if newChar then
            TriggerEvent('esx_skin:openSaveableMenu')
        end
 
        FreezeEntityPosition(ped, false)
    end)
end
server/editable.lua
if framework == 'qb' then
    registerCallback('spawnselector:server:getOwnedHouses', function(_, cb, cid)
        if cid ~= nil then
            local query = 'SELECT * FROM player_houses WHERE citizenid = ?'
            if cfg.housing == '2' then query = 'SELECT * FROM properties WHERE owner_citizenid = ?' end
            if cfg.housing == '3' then
                local houses = exports.bcs_housing:GetOwnedHomeKeys(cid)
                if houses[1] ~= nil then
                    cb(houses)
                else
                    cb(false)
                end
            else
                local houses = sql.sync.query(query, { cid })
                if houses[1] ~= nil then
                    cb(houses)
                else
                    cb(false)
                end
            end
        else
            cb(false)
        end
    end)
 
    registerCallback('spawnselector:server:getOwnedApartments', function(_, cb, cid)
        if cfg['housing'] == '1' then
            if cid ~= nil then
                local result = MySQL.query.await('SELECT * FROM apartments WHERE citizenid = ?', { cid })
                if result[1] ~= nil then
                    return cb(result[1])
                end
                return cb(nil)
            else
                local src = source
                local Player = QBCore.Functions.GetPlayer(src)
                local result = MySQL.query.await('SELECT * FROM apartments WHERE citizenid = ?',
                    { Player.PlayerData.citizenid })
                if result[1] ~= nil then
                    return cb(result[1])
                end
                return cb(nil)
            end
        elseif cfg['housing'] == '3' then
            return cb(nil)
        else
            if cid ~= nil then
                local result = MySQL.query.await(
                    'SELECT * FROM properties WHERE owner_citizenid = ? AND apartment IS NOT NULL AND apartment <> ""',
                    { cid })
                if result[1] ~= nil then
                    return cb(result[1])
                end
                return cb(nil)
            else
                local src = source
                local Player = QBCore.Functions.GetPlayer(src)
                local result = MySQL.query.await(
                    'SELECT * FROM properties WHERE owner_citizenid = ? AND apartment IS NOT NULL AND apartment <> ""',
                    { Player.PlayerData.citizenid })
                if result[1] ~= nil then
                    return cb(result[1])
                end
                return cb(nil)
            end
        end
    end)
elseif framework == 'esx' then
    registerCallback('spawnselector:server:getOwnedHouses', function(_, cb, cid)
        if GetResourceState("qs-housing") == "missing" or GetResourceState('bcs_housing') == 'missing' then
            return cb(false)
        end
        if cid ~= nil then
            if cfg.housing == '3' then
                local houses = exports.bcs_housing:GetOwnedHomes(cid)
                if houses[1] ~= nil then
                    cb(houses)
                else
                    cb(false)
                end
            else
                local houses = sql.sync.query('SELECT * FROM player_houses WHERE citizenid = ?', { cid })
                if houses[1] ~= nil then
                    cb(houses)
                else
                    cb(false)
                end
            end
        else
            cb(false)
        end
    end)
end