Installation

3 min readUpdated 2 days ago

Overview

ML Radio adds handset radios on pma-voice with antenna-based signal coverage, jammers, hackable towers, job-gated broadcast stations, speaker zones and placeable stereos. It persists placed infrastructure to the database and integrates with the inventory through ml_bridge.

Quick Start

  1. Download from CFX Portal
  2. Extract to your resources folder as ml_radio
  3. Add to server.cfg:
server.cfg
1ensure oxmysql
2ensure ox_lib
3ensure pma-voice
4ensure ml_bridge
5ensure xsound      # optional - station and stereo audio
6ensure ml_radio
Load Order

ml_radio must start AFTER ml_bridge and pma-voice.

Dual Channel Needs The Bundled pma-voice

The download ships a pma-voice folder next to ml_radio. It is pma-voice with a second radio channel added, which is what lets the handset talk on one frequency while monitoring another. Install it in place of your current pma-voice, or port the setSecondRadioChannel export into your own copy. On stock pma-voice the dual channel switches itself off, prints one warning and everything else runs unchanged. README_ML_RADIO.md in that folder lists what was changed.

Database

Tables are created automatically on first start:

Table | Purpose

ml_radio_antennas | Player-placed antennas: position, health, lockout

ml_radio_fixed_antennas | Fixed tower state overrides: health, lockout

ml_radio_disruptors | Placed jammers: position, power, health

ml_radio_data | Key/value store, currently placed stereos

Per-player radio state rides on the item itself as metadata, not in a table, so a handset keeps its frequencies, callsign and charge when it changes hands.

_INSTALL/sql.sql creates the first three by hand for anyone who prefers that. ml_radio_fixed_antennas is always created at runtime.

Item Registration

Register the following items in your inventory system. Ready-to-paste definitions ship in _INSTALL/items.lua, and _INSTALL/ox_items.txt is pre-formatted for ox_inventory/data/items.lua:

  • radio: Handset
  • radio_jammer: Placeable jamming tower
  • radio_antenna_small / radio_antenna_medium / radio_antenna_large - Placeable antennas
  • boombox: Placeable stereo
  • batteria_stilo: Battery, recharges handsets and jammers
  • electronic_kit / metal_scrap - Repair materials
  • hacking_device: Required to hack antennas

Handset and consumable names live in Config.Items. Antenna and jammer names live with their models in Config.Antenna.tiers and Config.Jammer.tiers.

Props Ship With The Script

The custom tower model used by the large antenna and the fixed towers is streamed from the resource itself. Everything else uses base-game props. Nothing extra to install.

Verify

After starting, the console prints the resource banner and the fixed towers load. In game: use a radio item from your inventory, tune a frequency near a tower and the signal bars read above zero.

  • Radio opens but nobody hears voice - check that pma-voice is running and started before ml_radio.
  • Stations and boomboxes play no music - xsound is missing or Config.Broadcast.streamingProvider = 'none'. Voice radio is unaffected.
  • Using the item does nothing - the item is not registered in your inventory, or its name does not match Config.Items.radios.
  • "No signal" everywhere - signal starts at Config.Signal.baseSignalWithoutAntenna = 0; coverage comes from fixed towers and placed antennas. Check the tower coords are loaded.
  • Nothing posts to Discord - the webhooks in server/config_server.lua ship empty; fill in real URLs.