NR_DJ

A feature-rich DJ booth script that integrates with xSound to play YouTube music at configurable locations with job/gang restrictions, volume control, and playback history.

Features

Dependencies

Resource Description Required
qbx_core or qb-core Core framework Yes
ox_lib UI library (context menus, input dialogs, notifications) Yes
ox_target Interaction system Yes
xsound 3D sound system for YouTube audio Yes

Installation

Step 1: Download

Download NR_DJ from your Tebex purchase and extract it to your resources folder:

server/
  └── resources/
      └── [nightrider]/
          └── NR_DJ/

Step 2: server.cfg

Add the resource to your server configuration. xsound must start before NR_DJ:

ensure xsound
ensure ox_lib
ensure ox_target
ensure qbx_core
ensure NR_DJ

Step 3: Configuration

Edit config.lua to add your DJ booth locations. Configure job/gang restrictions, audio ranges, and default volumes as needed.

Step 4: Restart

Restart your server to load the resource.

⚠️ Important

xsound must be started before NR_DJ in your server.cfg. Without xsound, no audio will play.

How It Works

1. Approaching a Booth

Player walks up to a configured DJ booth location. ox_target shows a "DJ Booth" interaction option. The option only appears if the player has the required job/gang (if configured).

2. Opening the Menu

Player uses third eye (ox_target) to interact. A context menu opens showing current song status with the song title, timestamp, and playback status.

3. Playing a Song

Select "Play Song" from the menu. An input dialog prompts for a YouTube URL — full URL, short URL, or just the video ID. The song starts playing for all players in range.

4. Song History

"History" option shows previously played songs. Click any song to replay it instantly. History persists for the resource session.

5. Playback Controls

6. Audio Experience

Music plays in 3D space from the booth's soundLoc position. Volume fades based on distance, and players beyond the configured radius cannot hear the music.

Configuration

General Settings

Config.Debug = false  -- Enable debug mode (visual markers, console logs)
Config.Language = 'en'  -- Locale language

DJ Booth Location Structure

{
    name = "Booth Name",        -- Descriptive name
    enableBooth = true,         -- Enable/disable this location

    -- Access Control
    job = "public",             -- "public", specific job, or table of jobs
    gang = nil,                 -- nil, specific gang, or table of gangs

    -- Location Settings
    coords = vec3(x, y, z),    -- Interaction point (ox_target zone)
    soundLoc = vec3(x, y, z),  -- Where sound originates from

    -- Audio Settings
    DefaultVolume = 0.15,       -- Starting volume (0.0 - 1.0)
    radius = 60,                -- Hearing distance in GTA units

    -- Optional Prop
    prop = {
        model = "prop_dj_deck_01",
        coords = vec4(x, y, z, heading)
    },
}

Example: Public Booth

{
    name = "Nightclub",
    enableBooth = true,
    job = "public",
    gang = nil,
    coords = vec3(119.52, -1299.95, 29.22),
    soundLoc = vec3(119.52, -1299.95, 29.22),
    DefaultVolume = 0.15,
    radius = 60,
    prop = {
        model = "prop_dj_deck_01",
        coords = vec4(119.52, -1299.95, 29.22, 180.0)
    },
}

Example: Job-Locked Booth

{
    name = "Police Station",
    enableBooth = true,
    job = "police",
    gang = nil,
    coords = vec3(441.0, -982.0, 30.68),
    soundLoc = vec3(441.0, -982.0, 30.68),
    DefaultVolume = 0.10,
    radius = 40,
    prop = nil,
}

Example: Gang-Locked Booth

{
    name = "Gang Hideout",
    enableBooth = true,
    job = nil,
    gang = "ballas",
    coords = vec3(100.0, -1900.0, 21.0),
    soundLoc = vec3(100.0, -1900.0, 21.0),
    DefaultVolume = 0.20,
    radius = 50,
    prop = nil,
}

Example: Multiple Jobs Allowed

{
    name = "Staff Room",
    enableBooth = true,
    job = {"police", "ambulance", "mechanic"},
    gang = nil,
    coords = vec3(300.0, -580.0, 43.26),
    soundLoc = vec3(300.0, -580.0, 43.26),
    DefaultVolume = 0.12,
    radius = 35,
    prop = nil,
}

Booth Identification System

Each booth is identified by: (job or gang) + zoneNum

Example Identifier
Public booth #1 public1
Police booth #3 police3
Ballas booth #2 ballas2

This allows multiple booths with different access levels. Song history is stored per booth identifier and persists until resource restart.

Audio Settings

Volume System

Config Value Menu Display xSound Value
DefaultVolume = 0.15 15% 0.15
DefaultVolume = 0.50 50% 0.50

Recommended Volume Levels

Venue Type Volume Range
Nightclubs 0.15 - 0.25
Bars 0.10 - 0.15
Outdoor events 0.20 - 0.30
Background music 0.05 - 0.10

Radius & Distance

Venue Size Radius
Small room 25
Medium venue 50
Large outdoor area 100
Entire block 150

Sound Location vs Interaction Point

coords = vec3(x, y, z)    -- Where player clicks (ox_target zone)
soundLoc = vec3(x, y, z) -- Where audio emanates from

Usually these are the same, but you can offset soundLoc for better audio positioning (e.g., center of dance floor vs booth location).

YouTube URL Formats

The following formats are supported:

-- Full URL
https://www.youtube.com/watch?v=dQw4w9WgXcQ

-- Short URL
https://youtu.be/dQw4w9WgXcQ

-- Video ID only
dQw4w9WgXcQ

The script auto-corrects partial URLs by prepending https://www.youtube.com/watch?v=. Live streams are automatically detected — they show "LIVE" instead of a timestamp.

Props & Visual Elements

DJ Equipment Props

Prop Description
prop_dj_deck_01 Standard DJ deck
prop_speaker_01 Large speaker
prop_speaker_02 Small speaker
prop_speaker_03 Floor speaker
prop_studio_light_01 Stage light

Set prop = nil to disable props for a booth. Props are purely cosmetic.

Localization

The script supports full localization. Edit Config.Locale in config.lua:

Config.Locale = {
    ['en'] = {
        target = {
            dj_booth = "DJ Booth",
        },
        menu = {
            play = "Play Song",
            youtube_url = "Enter YouTube URL",
            history = "Song History",
            no_song = "No Song Playing",
            cur_playing = "Currently Playing",
            cur_paused = "Currently Paused",
        },
        notify = {
            load_link = "Loading song: ",
            new_volume = "Volume set to: ",
        },
    }
}

Add new languages by copying the ['en'] block and translating strings.

Advanced Features

Dynamic Booth Creation

Add booths at runtime using the export:

exports['NR_DJ']:AddLocation({
    name = "New Venue",
    enableBooth = true,
    job = "public",
    gang = nil,
    coords = vec3(100.0, 200.0, 30.0),
    soundLoc = vec3(100.0, 200.0, 30.0),
    DefaultVolume = 0.15,
    radius = 50,
    prop = nil,
})

This broadcasts to all clients and creates the booth immediately.

Song Timestamp Display

🔊 (02:45/04:30)  -- Playing
🔇 (02:45/04:30)  -- Paused
LIVE              -- Live stream

YouTube Thumbnails

The menu automatically shows video thumbnails extracted from the YouTube URL.

Performance

Metric Value
Resmon impact ~0.00ms (idle), ~0.01ms (menu open)
Network traffic Minimal (event-based synchronization)
Memory usage ~1.2 MB
xSound load Depends on active songs (handled by xSound)
Threads 1 (debug markers if enabled)

Troubleshooting

No sound playing

ox_target not showing

Menu not opening

Volume not working

Props not spawning

History not saving

Multiple booths interfering

Best Practices

Support

For paid script support, open a ticket in our Discord server for priority assistance.