Biyei Scripts

Configuration

config.lua

public/framework.lua, public/inventory.lua, and public/dead.lua are the only files meant to be edited for a custom integration — see the auto-compatible "downed" detection note under Common Issues if you plan to swap Config.DeadDetection for your own check.

config.luaLua
Config = {}

-- =====================================================================
--  GENERAL
-- =====================================================================

-- Chat command that opens the radio menu.
Config.Command = 'radio'

-- Default key to open the menu (the player can rebind it in
-- Settings > Key Bindings). Leave as '' to disable it.
Config.OpenKey = ''

-- Lets you WALK while the radio menu is open.
-- The mouse still works to click buttons. As soon as you focus a text
-- field (frequency / sound search) movement locks so you can type, and
-- unlocks again when you leave the field.
--   true  = you can move around with the menu open.
--   false = the menu blocks movement (classic behaviour).
Config.CanWalkWhileUsing = true

-- UI and notifications language. Files live in locales/<code>.lua
Config.Locale = 'es'

-- =====================================================================
--  COLOR / THEME
--  A single color and the WHOLE interface (borders, backgrounds, glow,
--  slider, scrollbar, overlay...) is calculated from it. Accepts a 3 or
--  6 digit hex, with or without '#'.
-- =====================================================================
Config.Color = '#0098FF'

-- Allowed frequency range.
Config.MinFrequency = 1
Config.MaxFrequency = 999999

-- Decimal places allowed in the frequency (e.g. 1.1, 25.75). FiveM/pma-voice
-- support this.  0 = integers only.  1 = one decimal.  2 = two decimals...
Config.FrequencyDecimals = 1

-- Initial radio volume (0 - 100).
Config.DefaultVolume = 50

-- Text shown instead of the real name when anonymous mode is on.
-- A short id is appended to tell players apart.
Config.AnonymousPrefix = 'Anonimo'

-- =====================================================================
--  DEATH / INCAPACITATED
-- =====================================================================
-- true  = dying automatically disconnects you from the frequency and
--         closes the menu if you have it open.
-- false = you stay connected even if you die.
Config.DisconnectOnDead = true

-- true  = you can open the menu and join a frequency while downed.
-- false = the radio can't be used while downed/incapacitated.
Config.CanUseDead = false

-- Turns the "downed / incapacitated" detection on or off. All of its
-- logic lives in public/dead.lua (same pattern as framework.lua and
-- inventory.lua) so it's easy to replace with your own integration.
--   true  = use the automatic detection (natives + statebags + framework).
--   false = Dead.IsDead() always returns false (or put your own check here).
Config.DeadDetection = true

-- AUTO-COMPATIBLE "downed / incapacitated" detection. Besides the game's
-- natives (IsEntityDead / IsPlayerDead), these LocalPlayer.state statebags
-- are checked (true = downed). Covers wasabi_ambulance ('dead' / 'isDead' /
-- 'laststand'), qb-ambulancejob ('isdead' / 'inlaststand') and
-- esx_ambulancejob ('dead' / 'isDead') out of the box. Add or remove keys
-- to match your server.
Config.DeadStateBags = { 'dead', 'isDead', 'isdead', 'laststand', 'inlaststand' }

-- If you have wasabi_ambulance, its export
-- exports.wasabi_ambulance:isPlayerDead() is also checked automatically.

-- =====================================================================
--  REQUIRED ITEM
-- =====================================================================
-- true  = an item is required to open the menu and join a frequency
--         (and you get kicked out if you lose/drop it).
-- false = the radio works without any item.
Config.RequireItem = true

-- Item name in your inventory.
Config.ItemName = 'radio'

-- How often (ms) to check that you still have the item while on a
-- frequency. Only used if Config.RequireItem = true.
Config.ItemCheckInterval = 10000

-- Forces a specific inventory/framework instead of auto-detecting.
-- '' or 'auto' = detect only (recommended).
-- Inventory: 'ox_inventory' | 'qb-inventory' | 'qs-inventory' | 'origen_inventory'
-- Framework : 'qbox' | 'qbcore' | 'esx'
Config.ForceInventory = 'auto'
Config.ForceFramework = 'auto'

-- =====================================================================
--  RADIO TALKING ANIMATIONS
--  - dict/anim : applied to pma-voice (exports['pma-voice']:setRadioTalkAnim).
--  - prop      : model attached to the hand while transmitting (optional).
--  - propOptions: how the prop is attached to the ped's bone.
--      offset/rot = vector3, bone = bone index.
-- =====================================================================
Config.Animations = {
  {
    id    = 'hombro',
    label = 'Al hombro',
    desc  = 'Lapel mic: hand to the shoulder.',
    dict  = 'random@arrests',
    anim  = 'generic_radio_chatter',
    prop  = 'prop_cs_hand_radio',
    propOptions = {
      offset = vector3(0.055, 0.055, 0.035),
      rot    = vector3(-103.000, 0.000, 0.000),
      bone   = 60309,
    },
  },
  {
    id    = 'boca',
    label = 'Boca',
    desc  = 'Holds the radio up to the mouth.',
    dict  = 'anim@male@holding_radio',
    anim  = 'holding_radio_clip',
    prop  = 'prop_cs_hand_radio',
    propOptions = {
      offset = vector3(0.0750, 0.0230, -0.0230),
      rot    = vector3(-90.0000, 0.0, -59.9999),
      bone   = 28422,
    },
  },
  {
    id    = 'oreja',
    label = 'En la oreja',
    desc  = 'Brings the radio up to the ear.',
    dict  = 'cellphone@str',
    anim  = 'cellphone_call_listen_a',
    prop  = 'prop_cs_hand_radio',
    propOptions = {
      offset = vector3(-0.01, -0.01, 0.02),
      rot    = vector3(0.0, 0.0, 0.0),
      bone   = 28422,
    },
  },
}

-- Default animation selected (id from the list above).
Config.DefaultAnimation = 'boca'

-- =====================================================================
--  "RADIO IN HAND" ANIMATION  (while the menu is open)
--  INDEPENDENT from the talking animations above: it only plays while
--  the menu is open and makes the ped hold the radio and look at it,
--  phone-style. Starting to transmit hands off to the pma-voice
--  animation, and releasing PTT brings this one back.
-- =====================================================================
Config.HoldAnimation = {
  -- true = enable / false = disable this animation.
  enabled = true,

  dict  = 'cellphone@',
  enter = 'cellphone_text_in',        -- entry (played once). '' = no entry.
  idle  = 'cellphone_text_read_base', -- loop while the menu is open.

  -- Prop attached to the hand (optional; '' to attach none).
  prop       = 'prop_cs_hand_radio',
  propBone   = 28422,
  propOffset = vector3(0.0, 0.0, 0.0),
  propRot    = vector3(0.0, 0.0, 0.0),
}

-- =====================================================================
--  SOUNDS
--  Files live in the biyei_radio/sound/ folder (NOT inside web/) so
--  rebuilding the UI never deletes them.
--
--  - start  : played when you START transmitting / receiving.
--  - finish : (optional) played when you RELEASE / end transmitting.
--
--  The player picks one of these in the radio menu.
-- =====================================================================
Config.Sounds = {
  { id = 'beep',         label = 'Beep',          start = 'beep.mp3' },
  { id = 'bipbip',       label = 'Bip-bip',       start = 'bipbip.mp3' },
  { id = 'chiclkin',     label = 'Click',         start = 'chiclkin.mp3' },
  { id = 'connect',      label = 'Conexion',      start = 'connect.mp3' },
  { id = 'error',        label = 'Error',         start = 'error.mp3' },
  { id = 'militar',      label = 'Militar',       start = 'militar.mp3' },
  { id = 'notification', label = 'Notificacion',  start = 'notification.mp3' },
  { id = 'police',       label = 'Policia',       start = 'police.mp3' },
  { id = 'pop',          label = 'Pop',           start = 'pop.mp3' },
  { id = 'tin',          label = 'Tin',           start = 'tin.mp3' },
  { id = 'turconorolas', label = 'Motorola',      start = 'turconorolas.mp3' },
}

-- Default sound selected (id from the list above, or '' for none).
Config.DefaultSound = 'beep'

--- Rounds a frequency to Config.FrequencyDecimals and validates it against
--- the allowed range. Returns a number or nil. (shared client/server)
function Config.NormalizeFrequency(v)
  v = tonumber(v)
  if not v then return nil end
  local p = math.max(0, math.floor(Config.FrequencyDecimals or 0))
  local m = 10 ^ p
  v = math.floor(v * m + 0.5) / m
  if v < Config.MinFrequency or v > Config.MaxFrequency then return nil end
  return v
end

-- =====================================================================
--  Character name resolution (framework) and item checking (inventory)
--  now live in the public/ folder so each server can adapt them without
--  touching the rest of the resource:
--    public/framework.lua -> auto-detect QBox / QBCore / ESX
--    public/inventory.lua -> auto-detect ox / qb / qs / origen inventory
--    public/dead.lua      -> auto-detect "downed / incapacitated"
-- =====================================================================