Skip to Content
Resourcesqb-interior Reference

qb-interior

qb-interior is a shell spawner. Each export creates a single interior shell object at coordinates you pass in, freezes it, fades the screen, and teleports the player inside. It returns the handles it created plus the offsets of the shell’s points of interest, so the caller can place its own markers and clean up afterwards.

It does not own housing, apartments, or robbery logic. Those live in qb-houses, qb-apartments, and qb-houserobbery, which call these exports to get a room to put the player in.

The manifest at the commit linked above declares version 1.2.0.

Dependencies and start order

The manifest declares no dependency entry and loads only client/main.lua and client/optional.lua. It sets this_is_a_map 'yes' and registers stream/starter_shells_k4mb1.ytyp as a DLC_ITYP_REQUEST data file, so the bundled archetypes are available to the game.

Because it is a streaming resource, start it early, before the housing and robbery resources that call into it.

What is bundled and what is not

This is the part most setups get wrong.

client/main.lua spawns models that ship in the repository’s own stream/ folder, for example furnitured_midapart, shell_v16low, shell_v16mid, shell_trevor, shell_trailer, shell_lester, shell_ranch, container_shell, modernhotel_shell, shell_frankaunt, shell_michael, shell_office1, shell_store1, shell_warehouse1.

client/optional.lua defines well over a hundred further exports that request models such as shell_medium2, shell_banham, k4_mansion_shell, luxury_housing1_k4mb1, and k4mb1_house1_shell. None of those model files are in this repository. They come from separate K4MB1 packages that a server owner has to obtain and stream themselves.

Calling an optional.lua export without the matching stream assets means HasModelLoaded never returns true, and the export loops on Wait(1000) while the screen stays faded out. Verify which model a given export requests before wiring it into a menu.

Exports

All exports are client side.

Generic shell creation

exports['qb-interior']:CreateShell(spawn, exitXYZH, model)
ParameterTypeMeaning
spawnvector3 or table with x, y, zWorld position the shell object is created at
exitXYZHtable with x, y, z, hOffset from spawn where the player is placed, plus a heading
modelstring or hashArchetype to request

Returns a two element array: { objects, POIOffsets }. objects is an array of created entity handles. POIOffsets is a table whose exit field holds the offset you passed in.

Named shell helpers

Each named export wraps CreateShell with a fixed model and a fixed exit offset, so the caller only supplies spawn. The ones backed by bundled models are:

ExportModel
CreateApartmentFurnishedfurnitured_midapart
CreateFurniMidfurnitured_midapart
CreateHouseRobberyfurnitured_midapart
CreateApartmentShellshell_v16low
CreateTier1Houseshell_v16mid
CreateTrevorsShellshell_trevor
CreateCaravanShellshell_trailer
CreateLesterShellshell_lester
CreateRanchShellshell_ranch
CreateContainercontainer_shell
CreateFurniMotelModernmodernhotel_shell
CreateFranklinAuntshell_frankaunt
CreateMichaelshell_michael
CreateOffice1shell_office1
CreateStore1shell_store1
CreateWarehouse1shell_warehouse1

CreateApartmentFurnished is the only one that adds extra points of interest. It sets clothes, stash, and logout offsets on the returned POIOffsets table, and if the client has received qb-interior:client:SetNewState with true, it fires qb-clothes:client:CreateFirstCharacter 750 ms after the shell appears.

CreateGarageMed requests the model shell_garagemed. The bundled stream folder contains shell_garagem.ydr. Confirm the archetype name your own build actually provides before relying on that export.

Cleanup

exports['qb-interior']:DespawnInterior(objects, cb)

Iterates the handle array returned by a create export, deletes each entity that still exists, then invokes cb. Call this whenever the player leaves, and on resource stop, otherwise shells stay in the world.

Integration example

-- client side local currentShell local function EnterPlayerHouse(houseCoords) local result = exports['qb-interior']:CreateTier1House(houseCoords) currentShell = result[1] local offsets = result[2] -- offsets.exit is relative to houseCoords, so build absolute coords for your own marker local exitCoords = vector3( houseCoords.x + offsets.exit.x, houseCoords.y + offsets.exit.y, houseCoords.z + offsets.exit.z ) TriggerEvent('myresource:client:registerExitZone', exitCoords) end local function LeavePlayerHouse() if not currentShell then return end exports['qb-interior']:DespawnInterior(currentShell, function() currentShell = nil end) end

Events

qb-interior:client:SetNewState(bool) is a client event. Set it to true before calling CreateApartmentFurnished for a brand new character, so the first-character clothing flow runs. The resource resets the flag to false itself after firing.

Troubleshooting

SymptomLikely cause
Screen stays black after enteringThe requested model never loaded. Either the archetype is not streamed, or you called an optional.lua export whose K4MB1 package you do not own
Shell appears but the player is outside itThe exitXYZH offset does not match the model. Use the named helper for that model rather than raw CreateShell
Old shells pile up in the worldDespawnInterior was never called, or the caller lost the handle array. Store the array from the create call
Players see each other’s interiorsShells are plain world objects at real coordinates. Separate them yourself, for example with far apart spawn coordinates or a routing bucket. See OneSync and scope

Proposed manual smoke test

Not yet executed. On staging:

  1. Call one bundled shell export and confirm the fade completes and the player lands inside.
  2. Confirm the returned offsets place your exit marker at the real doorway.
  3. Call DespawnInterior and confirm the object is gone with GetGamePool('CObject').
  4. Restart the resource while a shell is spawned and confirm no orphan object remains.

Sources