🛠️Configuration

This document describes all configuration options for the DevHub Truck robbery resource.

⚠️ REQUIRED STEPS BEFORE USE

1. pma-voice Configuration in server.cfg

Make sure that voice_enableRadioAnim in server.cfg is set to 0. If it doesn't exist, add to server.cfg:

setr voice_enableRadioAnim 0

2. pma-voice Export

Add this to the bottom of pma-voice/client/module/radio.lua:

exports("getRadioData", function()
    return radioData
end)

Shared Configuration (configs/shared.lua)

Reserved Channels System

Controls which radio frequencies are restricted to specific jobs or custom conditions.

Shared.ReservedChannels = {
    { jobs = { "police", "sheriff", "state" }, channels = { 909, 909.01, 909.02, 911 } },
    { jobs = { "police", "sheriff", "state", "ambulance" }, channels = { 912 } },
    { jobs = { "mechanic1" }, channels = { 913 } },
    { jobs = { "mechanic2" }, channels = { 914 } },
    { channels = { 915 }, handler = function(source, channel)
            local crimeJob = "xd"
            if crimeJob == "vagos" then 
                return true
            else 
                return false, "Access only for Vagos members"
            end
        end
    },
}
  • jobs: Array of job names that have access to the specified channels

  • channels: Array of frequency numbers that are reserved

  • handler: Optional custom function for advanced access control

    • Parameters: source (player ID), channel (frequency number)

    • Returns: boolean (access granted), optional string (denial message)

  • Usage: Add new entries to create job-specific radio channels

Example - Adding a new reserved channel for mechanics:

{ jobs = { "mechanic" }, channels = { 920, 920.01, 920.02 } },

Antenna Disable System

Configuration for the antenna hacking/disabling feature.

Shared.DisableSettings = {
    enabled = true,
    time = 60000 * 20, -- time in ms that antenna is disabled
    item = "dh_antenna_disabler", -- item required to disable antenna or you can set to false to do not require item
}
  • enabled: Enable/disable the antenna disabling feature

  • time: Duration in milliseconds that antenna remains disabled (default: 20 minutes)

  • item: Item name required to disable antenna

    • Set to false to allow disabling without an item

    • Default: "dh_antenna_disabler"


Antenna Debug Mode

Shows antenna coverage radius on the map for testing purposes.

Shared.AntennaDebug = false -- set to true to see antenna radius on map
  • AntennaDebug: Set to true to visualize antenna coverage areas on the map

  • Usage: Enable during setup to verify antenna placement and coverage


Antenna Locations

Defines all radio antenna locations across the map and their signal coverage.

Shared.AntennaLocations = {
    {prop = "reh_prop_reh_tablet_01a", coords = vector3(-1267.271, -2442.962, 14.603), rotation = vec3(118.426, -87.740, 122.140), radius = 1500.0},
    {prop = "reh_prop_reh_tablet_01a", coords = vector3(1369.801, -2325.915, 61.777), rotation = vec3(118.426, -87.740, 122.140), radius = 1650.0},
    -- ... more locations
}
  • prop: Prop model name for the antenna object

  • coords: vector3 coordinates (x, y, z) for antenna placement

  • rotation: vec3 rotation values (pitch, roll, yaw)

  • radius: Signal coverage radius in game units

  • Default Locations: 12 antennas strategically placed across the map

  • Coverage Areas:

    • Los Santos: 1300-1650 unit radius

    • Sandy Shores: 1350-2000 unit radius

    • Paleto Bay: 1200-3000 unit radius

Adding a New Antenna:

{
    prop = "reh_prop_reh_tablet_01a", 
    coords = vector3(x, y, z), 
    rotation = vec3(pitch, roll, yaw), 
    radius = 1500.0
},

Radio Item Name

Defines the inventory item name for the radio.

Shared.RadioItem = "radio" -- item name for radio, false to disable
  • RadioItem: Item name in your inventory system

  • Default: "radio"

  • Disable: Set to false to allow radio access without an item requirement


Client Configuration (configs/client.lua)

Radio Animations

Defines multiple animation options for holding and using the radio.

Config.Animations = {
    { -- Animation 1: Holding Radio (RPEmotes style)
        dict = "anim@male@holding_radio",
        anim = "holding_radio_clip",
        flags = 49,
        propModel = "prop_cs_hand_radio",
        bone = 28422,
        offsets = { x = 0.09, y = 0.03, z = 0.0, xRot = -70.0, yRot = 10.0, zRot = 290.0 },
    },
    { -- Animation 2: Reading (Phone style)
        dict = "cellphone@",
        anim = "cellphone_text_read_base",
        flags = 49,
        propModel = "prop_cs_hand_radio",
        bone = 28422,
        offsets = { x = 0.0, y = 0.0, z = 0.0, xRot = 0.0, yRot = 0.0, zRot = 0.0 },
    },
    { -- Animation 3: Generic Radio Chatter
        dict = "random@arrests",
        anim = "generic_radio_chatter",
        flags = 49,
        propModel = false,
        bone = 28422,
        offsets = { x = 0.0, y = 0.0, z = 0.0, xRot = 0.0, yRot = 0.0, zRot = 0.0 },
    },
    { -- Animation 4: Listening
        dict = "cellphone@",
        anim = "cellphone_call_listen_base",
        flags = 49,
        propModel = "prop_cs_hand_radio",
        bone = 28422,
        offsets = { x = 0.0, y = 0.0, z = 0.0, xRot = 0.0, yRot = 0.0, zRot = 0.0 },
    },
}
  • dict: Animation dictionary name

  • anim: Specific animation name within the dictionary

  • flags: Animation flags (49 = upperbody + loop)

  • propModel: Radio prop model (set to false for no prop)

  • bone: Bone ID for prop attachment (28422 = right hand)

  • offsets: Position and rotation offsets for the prop

    • x, y, z: Position offset

    • xRot, yRot, zRot: Rotation offset in degrees

  • Players can switch between animations in-game settings


Aiming Animation

Special animation used when player is aiming with a weapon while using radio.

Config.AimingAnim = {
    dict = "arrest",
    anim = "radio_chatter",
    flags = 49,
    propModel = false,
    bone = 28422,
    offsets = { x = 0.0, y = 0.0, z = 0.0, xRot = 0.0, yRot = 0.0, zRot = 0.0 },
}
  • Same structure as regular animations

  • No prop model by default for compatibility with weapon aiming

  • Automatically activates when player aims while radio is open


Translation Configuration (configs/translation.lua)

Customize all user-facing text in the resource. Full multi-language support.

Tuning Minigame Translations

Shared.Lang = {
    ['tuning_signal_tuning'] = "SIGNAL TUNING",
    ['tuning_description'] = "STABILIZE THE DISTORTED FREQUENCY SIGNAL",
    ['tuning_instructions'] = "Match your signal to the ghost reference line...",
    -- ... more tuning translations
}

Items Configuration (items/items.lua)

Add these items to your inventory system:

Radio Item

-- ESX Example
['radio'] = {
    label = 'Radio',
    weight = 1,
    stack = false,
    close = true,
    description = 'A portable radio communication device'
}

Antenna Disabler Item

-- ESX Example
['dh_antenna_disabler'] = {
    label = 'Antenna Disabler',
    weight = 1,
    stack = true,
    close = true,
    description = 'Device to temporarily disable radio antennas'
}

Item Images:

  • items/dh_antenna_disabler.png - Provided in the resource

  • Add to your inventory images folder


Customization Examples

Creating Job-Specific Channels

Add multiple job groups with shared access:

Shared.ReservedChannels = {
    -- Emergency Services (Police + EMS)
    { jobs = { "police", "sheriff", "ambulance" }, channels = { 911, 911.01, 911.02 } },
    
    -- Police Only
    { jobs = { "police", "sheriff", "state" }, channels = { 909, 909.1, 909.2 } },
    
    -- Medical Only
    { jobs = { "ambulance", "doctor" }, channels = { 912 } },
    
    -- Mechanics
    { jobs = { "mechanic" }, channels = { 913, 913.1 } },
    
    -- Government
    { jobs = { "government", "mayor" }, channels = { 920 } },
}

Custom Access Handler Example

Create advanced access control based on custom logic:

{ 
    channels = { 915, 916, 917 }, 
    handler = function(source, channel)
        local xPlayer = ESX.GetPlayerFromId(source)
        
        -- Check gang affiliation
        local gang = xPlayer.getGang() -- Your gang system
        
        if gang == "vagos" and channel == 915 then
            return true
        elseif gang == "ballas" and channel == 916 then
            return true
        elseif gang == "families" and channel == 917 then
            return true
        else
            return false, "This channel is restricted to gang members"
        end
    end
},

Making Radio Accessible Without Item

Allow all players to use radio without needing the item:

Shared.RadioItem = false  -- Disable item requirement

Advanced Configuration

Frequency Range

The radio supports frequencies from 0.00 to 9999.99 MHz.


Signal Strength System

Signal strength is calculated based on:

  1. Distance from nearest antenna

  2. Antenna radius configuration

  3. Whether antenna is disabled

Signal Levels:

  • 5 bars: Within optimal range (< 50% of radius)

  • 3-4 bars: Medium range (50-75% of radius)

  • 1-2 bars: Weak signal (75-100% of radius)

  • 0 bars: No signal (outside radius or antenna disabled)


UI Customization

Players can customize their radio interface:

  • Wallpaper: None or Custom

  • Background Opacity: Adjustable transparency

  • Radio Volume: Individual volume control

  • Button Click Volume: UI sound control

  • HUD Display: Toggle on/off

  • Radio Scale: Size adjustment

  • HUD Scale: HUD size adjustment

  • Position: Drag and reposition UI elements

  • Animation: Choose from available animations


Troubleshooting

Radio not opening:

  • Verify player has the radio item (if Shared.RadioItem is set)

  • Check F8 console for Lua errors

  • Check if resource is started: /ensure devhub_radio

No signal everywhere:

  • Enable Shared.AntennaDebug = true to visualize coverage

  • Verify antenna coordinates are valid

  • Ensure antenna props are spawning correctly

Reserved channels not working:

  • Verify job names match your framework's job names exactly

  • Check player's job with /job or similar command

  • Review server console for access denial messages

  • Test custom handler functions with debug prints

Antenna hacking not working:

  • Verify player has dh_antenna_disabler item

  • Check if Shared.DisableSettings.enabled is true

  • Ensure minigame scripts are loaded

  • Look for errors during antenna interaction


Last updated