XyraLScripts
Installation guide

Phone

An iPhone-style smartphone with real calls, texts, maps, socials, 911 lines and 25+ apps. One resource, no SQL to import.

Requirements

Required

  • qbx_core or qb-core — the bridge detects which you run
  • ox_lib
  • oxmysql

Optional

  • pma-voice — powers call audio. Without it, calls connect but nobody can hear each other.
  • screenshot-basic — powers the camera.
  • xsound — only the Music app needs it.
  • A housing script — qbx_properties, ps-housing, qb-houses or bcs_housing. The Home app only shows when one is running.
  • A vehicle keys script — the valet and lent keys work with qbx_vehiclekeys, qb-vehiclekeys, Renewed-Vehiclekeys, wasabi_carlock, mk_vehiclekeys, jaksam's vehicles_keys and cd_garage.
  • ox_inventory is supported but not required.

Installation

  1. Drop the XS-Phone folder into your resources directory.
  2. No SQL import needed. Tables create themselves on first start. The file in sql/ is there only if you want to run it yourself.
  3. Add ensure XS-Phone to your server.cfg, after ox_lib, oxmysql, your framework and pma-voice.
  4. Set up the camera (see below), go through config.lua, then restart and open the phone.

Start order matters. XS-Phone has to start after ox_lib, oxmysql, your framework and pma-voice, or calls and callbacks fail on boot.

The phone item

Both frameworks already ship a phone item, and XS-Phone uses it as is — most servers can skip this step. Only add the item if your server doesn't have one, or skip items entirely with Item.enabled = false in the config.

ox_inventory, in data/items.lua:

['phone'] = {
    label = 'Phone',
    weight = 190,
    stack = false,
    consume = 0,
    client = { event = 'XS-Phone:client:use' },
},

On ox_inventory the client line is what opens the phone. If you kept your server's own phone item, add that line to it. The open key and /phone work either way.

qb-core, in shared/items.lua:

phone = { name = 'phone', label = 'Phone', weight = 190, type = 'item', image = 'phone.png', unique = true, useable = true, shouldClose = true, description = 'A smartphone' },

Camera

The camera uploads photos to a media host so they can show up in the gallery and on the socials. It uses fivemanage by default.

  1. Make a free account at fivemanage.com.
  2. Copy an image API token.
  3. Paste it into Config.Phone.Media.apiKey.

That is the whole setup. Until a key is set, the camera says so plainly and the server console prints the reason instead of failing silently.

Business lines

Every business in Config.Phone.Businesses is a real phone line. Calling the number rings a random on-duty worker for that job, and the caller only ever sees the business, never the worker's own number. If nobody is on duty, the business shows as closed and nobody answers.

Texts to a business land in a shared inbox in the Services app. Everyone on duty for that job sees it and replies as the business. None of it touches their own messages or recents.

911 and 912 are business lines with an emergency flag, pointing at your police and ambulance jobs. Change the numbers, labels and jobs to match your server. Give a business coords and it gets a GPS button in the Services app.

Garage and keys

The Garage reads player_vehicles, which both frameworks use, and works with qb-garages, Qbox garages and jg-advancedgarages. Different table? Change Garage.table.

  • Valet — players pay to have a parked car brought to them. With Valet.drive = true a valet drives it over on the roads.
  • Remote — find, lock, unlock, honk, flash and start a car that's out, from up to Remote.range metres away.
  • Keys — players lend a key to a contact for an hour, a day or until they take it back. Lent keys show in the Wallet.

Car pictures come from FiveM's own vehicle pictures. Add-on cars without one get a drawing instead, or set Garage.images = '' to turn pictures off.

Home and bills

The Home app shows up on its own when qbx_properties, ps-housing, qb-houses or bcs_housing is running. Players lock and unlock, give and take keys, and see who rang the doorbell. Locking depends on the housing script: qbx_properties has no locks of its own, and bcs_housing keys stay in its own menu.

Bills and fines show in the Wallet. The phone reads the phone_invoices table that qb-phone used and creates it if you don't have one, so /fine and other billing scripts that write there just work. okokBilling and peleg-billing work too. Paid bills go into the job's account on Renewed-Banking, qb-banking, okokBanking, tgg-banking, wasabi_banking, fd_banking or qb-management.

Config

Everything lives in config.lua and is commented in plain language. The ones most servers touch:

  • Businesses — your job list for the Services app and the 911 and 912 lines.
  • AppNames — rename Chirp, Prism, Sparks and the rest if you want your own branding.
  • OpenKey — the default is the backtick key.
  • Media — your fivemanage key, and which hosts photos may be imported from.
  • Garage — the vehicles table, the valet price, the remote and lent keys.
  • Maps.Places — the places everyone sees on the map.
  • News.jobs — the jobs that can write for Weazel News.
  • Home.housing — only if your housing script runs under a different name.

Exports

-- server
exports['XS-Phone']:GetNumber(source)
exports['XS-Phone']:Notify(source, { app = 'mail', title = '...', body = '...' })
exports['XS-Phone']:SendMessage('BANK', number, 'You were paid $2,500.')
exports['XS-Phone']:SendMail(number, { from = 'cityhall@ls.mail', subject = '...', body = '...' })
exports['XS-Phone']:CreateBill(source or citizenid, amount, 'mechanic', 'Engine rebuild')

-- client
exports['XS-Phone']:IsPhoneOpen()

SendMail delivers to whatever mail account is logged in on that player's phone. No account, no delivery — it returns false. CreateBill puts a bill in their Wallet, and paying it sends the money to that job.

Troubleshooting

"You don't have a phone"

The item is not in your inventory config, or its name does not match Config.Phone.Item.name. Both frameworks ship a phone item that works as is, so most servers can leave this alone, or set Item.enabled to false to skip the item entirely.

Using the phone item does nothing on ox_inventory

The item is missing its client event. Add client = { event = 'XS-Phone:client:use' } to the phone item in ox_inventory's data/items.lua.

Photos won't save

Your fivemanage API key is missing or wrong. Paste an image API token into Config.Phone.Media.apiKey. The server console prints the actual reason when an upload fails.

Calls connect but there is no audio

pma-voice is missing or outdated. Calls route through it, so it has to be started before XS-Phone.

The Garage app is empty

Your server uses a different vehicles table. Point Config.Phone.Garage.table at it. It reads player_vehicles by default and handles builds that store the model as a hash.

Cars show as out when they're parked

Your garage script marks parked cars in a different column. Set Config.Phone.Garage.stateFrom to that column.

There is no Home app

None of the supported housing scripts is running. If yours runs under a different resource name, set Config.Phone.Home.housing.

News or Crypto is missing

Both are in the App Store. New phones come with News already installed.

Nobody can write news

Add your reporter job to Config.Phone.News.jobs.

The Music app won't play anything

xsound is not installed. Music is the only app that needs it — everything else works without it.

Updating

Going to 2.0? Replace the whole folder, including config.lua, then copy your own settings into the new one. A lot of the config is new.

  1. Keep a copy of your edited config.lua.
  2. Replace the resource folder and merge your config back.
  3. Restart the resource. Any new tables are created automatically.

Support

Open an issue on GitHub, or ask in the Discord.