Skip to main content

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
locations[#locations + 1] = {
coords = houses[i].complex == 'Apartment' and
vec3(houses[i].data.apartment.coords.x, houses[i].data.apartment.coords.y,
houses[i].data.apartment.coords.z) or
vec3(houses[i].entry.x, houses[i].entry.y, houses[i].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
locations[#locations + 1] = {
coords = houses[i].complex == 'Apartment' and
vec3(houses[i].data.apartment.coords.x, houses[i].data.apartment.coords.y,
houses[i].data.apartment.coords.z) or
vec3(houses[i].entry.x, houses[i].entry.y, houses[i].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:GetOwnedHomes(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