Skip to main content

Download

LonexDiscordAPI is available via GitHub.
  1. Visit the repository: https://github.com/LonexLabs/LonexDiscordAPI
  2. Click Code → Download ZIP
Or, clone the repository using Git:
git clone https://github.com/LonexLabs/LonexDiscordAPI.git
Once downloaded, extract the files if you used the ZIP option.

Discord Bot Setup

LonexDiscordAPI requires a Discord bot to function correctly. Create a Discord Application
  1. Go to the Discord Developer Portal
  2. Click New Application
  3. Give your application a name and create it
Create the Bot
  1. Open your application
  2. Navigate to the Bot tab
  3. Click Create Bot
Enable Privileged Gateway Intents Under the Privileged Gateway Intents section, enable:
  • Server Members Intent
  • Presence Intent
Save your changes. Copy the Bot Token
  1. In the Bot section, click Reset Token (if needed)
  2. Copy the token - you’ll need this later.
    Note: Keep this token secret. Do not share it.
Invite the Bot to Your Server Invite the bot to your Discord server with the following permissions:
  • Manage Roles
  • Manage Nicknames
  • View Channels
  • Move Members (only required if using voice channel features)
Important Role Hierarchy Notice
Discord bots can only manage roles that are below their highest role.
Make sure:
  • The bot has its own role
  • The bot’s role is placed above any roles you want it to manage
If this is not configured correctly, role-related features will not work.

Installing LonexDiscordAPI

Resource Installation
  1. Place the resource in your server’s resources folder
  2. Ensure the folder name is exactly:
    LonexDiscordAPI
⚠️ The resource will not work if the folder name is changed. Server Configuration Add the following lines to your server.cfg:
# Required configuration
set lonex_discord_token "YOUR_BOT_TOKEN"
set lonex_discord_guild "YOUR_GUILD_ID"

# Required for permission system: Allow resource to modify ACE permissions
add_ace resource.LonexDiscordAPI command allow
add_ace resource.LonexDiscordAPI command.add_principal allow
add_ace resource.LonexDiscordAPI command.remove_principal allow

# Execute the permissions config (for ACE group definitions)
exec @LonexDiscordAPI/lonexperms.cfg

ensure LonexDiscordAPI
Configuration Values
  • YOUR_BOT_TOKEN → The bot token copied from the Discord Developer Portal
  • YOUR_GUILD_ID → Your Discord server ID (enable Developer Mode in Discord to copy this)

Configuration Guide

This guide explains all configuration options available in config.lua.

General Settings

Config.Debug = false
Config.LogLevel = 'info'
Config.LogCacheRefresh = false
Config.CheckUpdates = true
OptionTypeDefaultDescription
DebugbooleanfalseEnable debug mode for verbose logging
LogLevelstring'info'Log level: 'error', 'warn', 'info', 'debug'
LogCacheRefreshbooleanfalseLog when guild/roles cache refreshes (set false to reduce console spam)
CheckUpdatesbooleantrueCheck GitHub for new releases on startup

Force Default Ped

Forces all players to spawn as a specific ped model. Useful for servers with character selection systems.
Config.ForceDefaultPed = {
    Enabled = false,
    Ped = 'a_m_y_hipster_02',
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable/disable this feature
Pedstring'a_m_y_hipster_02'Ped model name to spawn players as

Cache Settings

Controls how long Discord data is cached to reduce API calls.
Config.Cache = {
    RolesTTL = 300,
    GuildTTL = 600,
    MemberTTL = 60,
    UserTTL = 300,
    MaxMembers = 500
}
OptionTypeDefaultDescription
RolesTTLnumber300Seconds to cache role data
GuildTTLnumber600Seconds to cache guild data
MemberTTLnumber60Seconds to cache member data
UserTTLnumber300Seconds to cache user data
MaxMembersnumber500Maximum members to keep in cache

Rate Limiting

Prevents hitting Discord API rate limits.
Config.RateLimit = {
    Enabled = true,
    MaxRequestsPerSecond = 40,
    MaxQueueSize = 100,
    RetryOnLimit = true,
    MaxRetries = 3,
    RetryDelay = 1000
}
OptionTypeDefaultDescription
EnabledbooleantrueEnable rate limiting
MaxRequestsPerSecondnumber40Maximum API requests per second
MaxQueueSizenumber100Maximum queued requests
RetryOnLimitbooleantrueRetry requests that hit rate limits
MaxRetriesnumber3Maximum retry attempts
RetryDelaynumber1000Delay between retries (ms)

Startup Options

Controls what happens when the resource starts.
Config.Startup = {
    FetchGuildInfo = true,
    FetchRoles = true,
    InitDelay = 2000,
    ValidateToken = true
}
OptionTypeDefaultDescription
FetchGuildInfobooleantrueFetch guild info on startup
FetchRolesbooleantrueFetch and cache roles on startup
InitDelaynumber2000Delay before initialization (ms)
ValidateTokenbooleantrueValidate bot token on startup

Permissions

Assigns FiveM ACE permissions based on Discord roles. Permissions are synced during player connection, ensuring compatibility with vMenu and other ACE-based resources.
Config.Permissions = {
    Enabled = true,
    RefreshOnFetch = true,
    LogAssignments = false,
}

-- Role mappings (in config.lua)
Roles = {
    ['DISCORD_ROLE_ID'] = 'groupname',
    ['DISCORD_ROLE_ID'] = { 'group1', 'group2' },
}
OptionTypeDefaultDescription
EnabledbooleantrueEnable permission system
RefreshOnFetchbooleantrueRefresh permissions when member data is fetched
LogAssignmentsbooleanfalseLog permission assignments to console

Role Mappings

The Roles table maps Discord Role IDs to FiveM ACE groups. Define this at the bottom of your config.lua:
Roles = {
    -- Single group
    ['1234567890123456789'] = 'member',
    
    -- Multiple groups
    ['9876543210987654321'] = { 'staff', 'moderator' },
    
    -- Admin with multiple groups
    ['1111111111111111111'] = { 'admin', 'staff', 'moderator' },
}
Getting Role IDs: Enable Discord Developer Mode → Right-click role → Copy Role ID

Setting Up ACE Groups

In your lonexperms.cfg or server.cfg, define what permissions each group has:
# Group definitions
add_ace group.member default allow
add_ace group.staff vMenu.NoClip allow
add_ace group.admin vMenu.Everything allow

# Group inheritance
add_principal group.staff group.member
add_principal group.admin group.staff

How It Works

  1. Player connects to server
  2. LonexDiscordAPI fetches their Discord roles during connection
  3. Matching roles are converted to ACE groups using the Roles table
  4. Groups are assigned using identifier.discord:ID format
  5. Player loads in with all permissions ready (vMenu, etc.)

Webhooks

Send messages to Discord channels via webhooks.
Config.Webhooks = {
    Enabled = true,
    RateLimit = 1000,
    MaxQueueSize = 50,
    DefaultColor = 5793266,
    IncludeTimestamp = true,
    Urls = {
        ['logs'] = 'https://discord.com/api/webhooks/...',
        ['admin'] = 'https://discord.com/api/webhooks/...',
    },
    Templates = { ... },
}
OptionTypeDefaultDescription
EnabledbooleantrueEnable webhook system
RateLimitnumber1000Minimum ms between webhook messages
MaxQueueSizenumber50Maximum queued webhook messages
DefaultColornumber5793266Default embed color (decimal)
IncludeTimestampbooleantrueInclude timestamp in embeds

Adding Webhook URLs

Urls = {
    ['logs'] = 'https://discord.com/api/webhooks/xxx/xxx',
    ['admin'] = 'https://discord.com/api/webhooks/xxx/xxx',
},

Templates

Pre-defined embed templates with placeholder support:
Templates = {
    ['player_join'] = {
        title = '👋 Player Connected',
        description = '**{player}** has joined the server',
        color = 5763719,
        fields = {
            { name = 'Discord', value = '{discord}', inline = true },
        },
    },
},
Use {placeholder} syntax for dynamic values.

Weapon Permissions

Restrict weapons based on Discord roles.
Config.WeaponPermissions = {
    Enabled = false,
    CheckInterval = 1000,
    RemoveWeapon = true,
    NotifyPlayer = true,
    NotifyMessage = 'You do not have permission to use this weapon.',
    Roles = { ... },
    RestrictedWeapons = { ... },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable weapon restrictions
CheckIntervalnumber1000How often to check (ms)
RemoveWeaponbooleantrueRemove unauthorized weapons
NotifyPlayerbooleantrueShow notification when weapon removed
NotifyMessagestring'...'Notification message

Configuring Weapon Roles

Roles = {
    ['POLICE_ROLE_ID'] = { 'WEAPON_PISTOL', 'WEAPON_STUNGUN', 'WEAPON_NIGHTSTICK' },
    ['ADMIN_ROLE_ID'] = {},  -- Empty = no restrictions
},

Restricted Weapons List

RestrictedWeapons = {
    'WEAPON_STUNGUN', 'WEAPON_NIGHTSTICK', 'WEAPON_FLASHLIGHT',
    'WEAPON_COMBATPISTOL', 'WEAPON_PUMPSHOTGUN',
},

Vehicle Permissions

Restrict vehicles based on Discord roles.
Config.VehiclePermissions = {
    Enabled = false,
    CheckInterval = 1000,
    EjectPlayer = true,
    DeleteVehicle = false,
    NotifyPlayer = true,
    NotifyMessage = 'You do not have permission to use this vehicle.',
    EjectDelay = 0,
    Roles = { ... },
    RestrictedVehicles = { ... },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable vehicle restrictions
CheckIntervalnumber1000How often to check (ms)
EjectPlayerbooleantrueEject player from unauthorized vehicle
DeleteVehiclebooleanfalseDelete vehicle after ejecting player
NotifyPlayerbooleantrueShow notification when ejected
EjectDelaynumber0Delay before ejecting (ms)

Configuring Vehicle Roles

Roles = {
    ['POLICE_ROLE_ID'] = { 'police', 'police2', 'police3', 'policeb' },
    ['EMS_ROLE_ID'] = { 'ambulance', 'firetruk' },
    ['ADMIN_ROLE_ID'] = {},  -- Empty = no restrictions
},

Restricted Vehicles List

RestrictedVehicles = {
    'police', 'police2', 'police3', 'sheriff',
    'ambulance', 'firetruk',
    'rhino', 'insurgent',
},

Ped Permissions

Restrict ped models (uniforms) based on Discord roles.
Config.PedPermissions = {
    Enabled = false,
    CheckInterval = 1000,
    ResetPed = true,
    NotifyPlayer = true,
    NotifyMessage = 'You do not have permission to use this ped model.',
    DefaultPed = 'a_m_y_hipster_02',
    Roles = { ... },
    RestrictedPeds = { ... },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable ped restrictions
CheckIntervalnumber1000How often to check (ms)
ResetPedbooleantrueReset player to default ped if unauthorized
NotifyPlayerbooleantrueShow notification when reset
DefaultPedstring'a_m_y_hipster_02'Ped to reset unauthorized players to

Configuring Ped Roles

Roles = {
    ['POLICE_ROLE_ID'] = { 's_m_y_cop_01', 's_f_y_cop_01', 's_m_y_sheriff_01' },
    ['EMS_ROLE_ID'] = { 's_m_m_paramedic_01', 's_m_y_fireman_01' },
    ['ADMIN_ROLE_ID'] = {},  -- Empty = no restrictions
},

Restricted Peds List

RestrictedPeds = {
    's_m_y_cop_01', 's_f_y_cop_01',
    's_m_m_paramedic_01', 's_m_y_fireman_01',
    's_m_m_marine_01',
},
Full ped list

Tags (Head Tags, Chat Tags & Voice Tags)

Unified tag system with NUI menu for head tags, chat prefixes, and pma-voice integration.
Config.Tags = {
    Enabled = false,
    MenuCommand = 'tags',
    MenuPosition = 'left',
    
    HeadTags = {
        Enabled = true,
        MaxDistance = 20.0,
        HeightOffset = 1.0,
        Font = 4,
        Scale = 0.4,
    },
    
    ChatTags = {
        Enabled = true,
    },
    
    VoiceTags = {
        Enabled = true,
        ShowSelf = true,
    },
    
    DefaultShowOthers = true,
    DefaultShowOwn = true,
    
    DefaultTag = {
        text = 'Player',
        color = { r = 255, g = 255, b = 255 },
        chatColor = '^7',
    },
    
    Roles = {
        { roleId = 'ROLE_ID', text = 'VIP', color = { r = 0, g = 255, b = 0 }, chatColor = '^2' },
        { roleId = 'ROLE_ID', text = 'Admin', color = { r = 255, g = 165, b = 0 }, chatColor = '^8' },
    },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable tags system
MenuCommandstring'tags'Command to open the tag menu
MenuPositionstring'left'Menu position: 'left' or 'right'
DefaultShowOthersbooleantrueShow other players’ tags by default
DefaultShowOwnbooleantrueShow own tag by default

Head Tags Options

OptionTypeDefaultDescription
EnabledbooleantrueEnable head tags
MaxDistancenumber20.0Maximum distance to see tags
HeightOffsetnumber1.0Height above player’s head
Fontnumber4GTA font ID
Scalenumber0.4Text scale

Chat Tags Options

OptionTypeDefaultDescription
EnabledbooleantrueEnable chat role prefixes

Voice Tags Options (pma-voice)

OptionTypeDefaultDescription
EnabledbooleantrueEnable voice tags (requires pma-voice)
ShowSelfbooleantrueShow your own voice tag

Default Tag

Displayed for players without any configured Discord roles:
DefaultTag = {
    text = 'Player',
    color = { r = 255, g = 255, b = 255 },
    chatColor = '^7',
},

Configuring Tag Roles

Roles = {
    { roleId = '111111111111111111', text = 'VIP', color = { r = 0, g = 255, b = 0 }, chatColor = '^2' },
    { roleId = '222222222222222222', text = 'Moderator', color = { r = 0, g = 191, b = 255 }, chatColor = '^4' },
    { roleId = '333333333333333333', text = 'Admin', color = { r = 255, g = 165, b = 0 }, chatColor = '^8' },
    { roleId = '444444444444444444', text = 'Owner', color = { r = 255, g = 0, b = 0 }, chatColor = '^1' },
},
PropertyTypeDescription
roleIdstringDiscord Role ID
textstringTag text displayed
colortableRGB color { r = 0-255, g = 0-255, b = 0-255 }
chatColorstringChat color code (e.g., '^2' for green)

Chat Color Codes

CodeColorCodeColor
^0White^5Cyan
^1Red^6Pink
^2Green^7White
^3Yellow^8Orange
^4Blue^9Grey

Player Menu

Players can type /tags to open a NUI menu where they can:
  • Toggle visibility of other players’ tags
  • Toggle visibility of their own tag
  • Select which tag to display (from their available roles)

Emergency Calls (911/311 System)

Players can make emergency calls that are sent to Discord and displayed to on-duty responders.
Config.EmergencyCalls = {
    Enabled = false,
    Cooldown = 60,
    
    Duty = {
        Enabled = false,
        Command = 'duty',
        DefaultOnDuty = false,
        Messages = {
            OnDuty = '^2You are now ^3ON DUTY^2 and will receive emergency calls.',
            OffDuty = '^1You are now ^3OFF DUTY^1 and will not receive emergency calls.',
            MustBeOnDuty = '^1You must be on duty to respond to calls. Use /duty to go on duty.',
        },
    },
    
    Types = {
        ['911'] = {
            Enabled = true,
            Command = '911',
            Label = '911 Emergency',
            Color = 0xFF0000,
            ChannelId = '',
            ResponderRoles = {},
            Prefix = '^1[911]^0',
            Messages = {
                Sent = '^2Your 911 call has been sent to emergency services.',
                NoMessage = '^1Please provide details for your 911 call. Usage: /911 <message>',
                Cooldown = '^1Please wait before making another call.',
            },
        },
        ['311'] = {
            Enabled = false,
            Command = '311',
            Label = '311 Non-Emergency',
            Color = 0x00FF00,
            ChannelId = '',
            ResponderRoles = {},
            Prefix = '^2[311]^0',
            Messages = { ... },
        },
    },
    
    Response = {
        Command = 'resp',
        Messages = {
            InvalidCall = '^1Invalid call ID or call no longer exists.',
            Responding = '^2Waypoint set. Responding to call #%s.',
            NoPermission = '^1You do not have permission to respond to calls.',
        },
    },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable emergency calls system
Cooldownnumber60Seconds between calls (per player)

Duty System

OptionTypeDefaultDescription
EnabledbooleanfalseRequire duty status to receive calls
Commandstring'duty'Command to toggle duty status
DefaultOnDutybooleanfalseDefault duty status on join

Call Types Configuration

OptionTypeDescription
EnabledbooleanEnable/disable this call type
CommandstringCommand to make this type of call
LabelstringDisplay name for the call type
ColornumberDiscord embed color (hex)
ChannelIdstringDiscord channel ID for call logs
ResponderRolestableDiscord role IDs that can see/respond
PrefixstringChat prefix for in-game notifications

Response Command

Use /resp <call_id> to set a waypoint to the caller’s location.

Area of Play (AOP)

Set and display the current area of play for your server.
Config.AOP = {
    Enabled = false,
    Command = 'aop',
    Default = 'All of San Andreas',
    
    AllowedRoles = {
        -- 'ROLE_ID_1',
    },
    
    Messages = {
        Changed = '^2AOP has been changed to: ^3%s',
        NoPermission = '^1You do not have permission to change the AOP.',
        Usage = '^1Usage: /aop <zone name>',
    },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable AOP system
Commandstring'aop'Command to change AOP
Defaultstring'All of San Andreas'Default AOP on server start
AllowedRolestable{}Discord role IDs that can change (empty = all)

PeaceTime

Toggle PeaceTime mode with weapon restrictions and speed limits.
Config.PeaceTime = {
    Enabled = false,
    Commands = { 'peacetime', 'pt' },
    Default = false,
    
    AllowedRoles = {
        -- 'ROLE_ID_1',
    },
    
    Restrictions = {
        DisableWeapons = true,
        
        SpeedLimit = {
            Enabled = true,
            Limit = 65,
            Unit = 'mph',
            WarningInterval = 5,
        },
    },
    
    Messages = {
        Enabled = '^2PeaceTime is now ^3ENABLED^2. No criminal activity!',
        Disabled = '^1PeaceTime is now ^3DISABLED^1. Crime is allowed.',
        NoPermission = '^1You do not have permission to toggle PeaceTime.',
        WeaponBlocked = '~r~Weapons are disabled during PeaceTime!',
        SpeedWarning = '~y~Slow down! Speed limit during PeaceTime is %s %s',
    },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable PeaceTime system
Commandstable{...}Commands to toggle PeaceTime
DefaultbooleanfalseDefault state on server start
AllowedRolestable{}Discord role IDs that can toggle (empty = all)

Restrictions

OptionTypeDefaultDescription
DisableWeaponsbooleantruePrevent weapon use during PeaceTime
SpeedLimit.EnabledbooleantrueEnable speed limit warnings
SpeedLimit.Limitnumber65Speed limit value
SpeedLimit.Unitstring'mph'Speed unit: 'mph' or 'kmh'
SpeedLimit.WarningIntervalnumber5Seconds between warning notifications

Announcements

Send server-wide announcements displayed on all players’ screens.
Config.Announcements = {
    Enabled = false,
    Command = 'announce',
    
    AllowedRoles = {
        -- 'ROLE_ID_1',
    },
    
    Header = '~b~[~p~Server Announcement~b~]',
    Duration = 10,
    Position = 0.3,
    
    Messages = {
        NoPermission = '^1You do not have permission to make announcements.',
        Usage = '^1Usage: /announce <message>',
        Sent = '^2Announcement sent!',
    },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable announcements system
Commandstring'announce'Command to send announcements
AllowedRolestable{}Discord role IDs that can announce (empty = all)
Headerstring'~b~[~p~Server Announcement~b~]'Header text with GTA color codes
Durationnumber10Seconds to display announcement
Positionnumber0.3Y position (0 = top, 0.5 = center)

Postals

Navigate to postal codes using waypoints.
Config.Postals = {
    Enabled = false,
    Command = 'postal',
    
    Messages = {
        Set = '^2Waypoint set to postal ^3%s^2.',
        Cancelled = '^3Postal waypoint cancelled.',
        NotFound = '^1Postal code ^3%s^1 not found.',
        Usage = '^1Usage: /postal <code> or /postal to cancel waypoint',
    },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable postal system
Commandstring'postal'Command to set/cancel postal waypoint
Usage:
  • /postal 123 - Set waypoint to postal 123
  • /postal - Cancel current postal waypoint

Moderation Commands

Server moderation tools with Discord role-based access control.

Delete Vehicle

Config.DeleteVehicle = {
    Enabled = true,
    Command = 'dv',
    
    AllowedRoles = {
        -- 'ROLE_ID_1',
    },
    
    SearchRadius = 5.0,
    
    Messages = {
        Deleted = '^2Vehicle deleted.',
        NotFound = '^1No vehicle found nearby.',
        NoPermission = '^1You do not have permission to delete vehicles.',
    },
}
OptionTypeDefaultDescription
EnabledbooleantrueEnable delete vehicle command
Commandstring'dv'Command to delete vehicle
AllowedRolestable{}Discord role IDs that can use (empty = all)
SearchRadiusnumber5.0Radius to search for nearby vehicle (meters)
Usage: /dv - Deletes the vehicle you’re in, or the closest vehicle within range.

Delete All Vehicles

Config.DeleteAllVehicles = {
    Enabled = true,
    Command = 'dvall',
    
    AllowedRoles = {
        -- 'ROLE_ID_1',
    },
    
    Countdown = 20,
    OnlyUnoccupied = true,
    
    Messages = {
        Starting = '^3[SERVER] ^1All unoccupied vehicles will be deleted in %d seconds!',
        Countdown = '^3[SERVER] ^1Vehicles being deleted in %d seconds...',
        Deleted = '^3[SERVER] ^2%d unoccupied vehicles have been deleted.',
        NoPermission = '^1You do not have permission to delete all vehicles.',
        AlreadyRunning = '^1A vehicle deletion is already in progress.',
    },
}
OptionTypeDefaultDescription
EnabledbooleantrueEnable delete all vehicles command
Commandstring'dvall'Command to delete all vehicles
AllowedRolestable{}Discord role IDs that can use (empty = all)
Countdownnumber20Seconds before deletion (with warnings)
OnlyUnoccupiedbooleantrueOnly delete vehicles with no occupants
Usage: /dvall - Starts a 20-second countdown, then deletes all unoccupied vehicles.

Clear Chat

Config.ClearChat = {
    Enabled = true,
    Command = 'clearchat',
    
    AllowedRoles = {
        -- 'ROLE_ID_1',
    },
    
    ShowClearedBy = true,
    
    Messages = {
        Cleared = '^3[SERVER] ^2Chat has been cleared by ^3%s^2.',
        NoPermission = '^1You do not have permission to clear chat.',
    },
}
OptionTypeDefaultDescription
EnabledbooleantrueEnable clear chat command
Commandstring'clearchat'Command to clear chat
AllowedRolestable{}Discord role IDs that can use (empty = all)
ShowClearedBybooleantrueShow who cleared the chat
Usage: /clearchat - Clears the chat for all players.

Activity System

Comprehensive duty tracking system for emergency services with blips, loadouts, database logging, and HTTP API.
Config.ActivitySystem = {
    Enabled = false,
    
    Commands = {
        Duty = 'duty',
        BlipTag = 'bliptag',
        Units = 'units',
    },
    
    Database = {
        Enabled = false,
        TablePrefix = 'lonex_',
    },
    
    API = {
        Enabled = false,
        Endpoint = '/lonex/activity',
        AuthToken = '',
    },
    
    Blips = {
        Enabled = true,
        OnlyForOnDuty = true,
        Scale = 0.85,
        ShowName = true,
        ShowDepartment = true,
        ShowHeading = true,
        RefreshInterval = 2000,
    },
    
    ClearOnOffDuty = {
        Weapons = false,
        Armor = false,
    },
    
    AutoOffDutyOnDisconnect = true,
    
    DiscordLogs = {
        Enabled = false,
        DefaultChannelId = '',
    },
    
    Departments = { ... },
    Messages = { ... },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable the activity system
AutoOffDutyOnDisconnectbooleantrueAutomatically clock out when player disconnects

Commands

OptionTypeDefaultDescription
Dutystring'duty'Command to clock in/out
BlipTagstring'bliptag'Command to change displayed tag
Unitsstring'units'Command to list on-duty players

Database (Optional)

Requires oxmysql to be installed. Run activity_schema.sql to create tables.
OptionTypeDefaultDescription
EnabledbooleanfalseEnable database logging
TablePrefixstring'lonex_'Prefix for database tables
Tables created:
  • lonex_duty_sessions - Individual clock-in/out records
  • lonex_duty_totals - Aggregated totals per player per department

HTTP API (Optional)

REST API for external access (websites, Discord bots, dashboards).
OptionTypeDefaultDescription
EnabledbooleanfalseEnable HTTP API
Endpointstring'/lonex/activity'Base URL path
AuthTokenstring''Secret token for auth
Endpoints:
  • GET /lonex/activity/online - Current on-duty players with department counts
  • GET /lonex/activity/history?discord_id=XXX&days=7 - Player duty history
  • GET /lonex/activity/leaderboard?department=leo&days=30&limit=10 - Top players by hours
Include Authorization: your-token header for authentication.

Blips

OptionTypeDefaultDescription
EnabledbooleantrueEnable blips for on-duty players
OnlyForOnDutybooleantrueOnly show blips to other on-duty players
Scalenumber0.85Blip scale
ShowNamebooleantrueShow player name on blip
ShowDepartmentbooleantrueShow department tag on blip
ShowHeadingbooleantrueShow direction cone (which way they’re facing)
RefreshIntervalnumber2000How often to sync blip positions (ms)
Blip Features:
  • Different sprites for on-foot vs in-vehicle
  • Flashing red/blue when sirens are active
  • Direction indicator showing which way player is facing

Discord Logs

OptionTypeDefaultDescription
EnabledbooleanfalseEnable Discord logging
DefaultChannelIdstring''Default channel (if department has none)
Clock-in/out embeds are sent via the bot to configured Discord channels.

Departments

Configure each department with role access, blips, loadouts, and logging.
Departments = {
    ['leo'] = {
        Label = 'Law Enforcement',
        ShortLabel = 'LEO',
        AllowedRoles = {
            'POLICE_ROLE_ID',
        },
        BlipSpriteOnFoot = 1,
        BlipSpriteInVehicle = 56,
        BlipColor = 3,
        LogChannelId = '',
        
        Loadout = {
            Armor = 100,
            Weapons = {
                { weapon = 'WEAPON_COMBATPISTOL', ammo = 120, tint = 5, attachments = { 'COMPONENT_AT_PI_FLSH' } },
                { weapon = 'WEAPON_STUNGUN', ammo = 1 },
                { weapon = 'WEAPON_NIGHTSTICK', ammo = 1 },
                { weapon = 'WEAPON_CARBINERIFLE', ammo = 180, tint = 5, attachments = { 
                    'COMPONENT_AT_AR_FLSH',
                    'COMPONENT_AT_SCOPE_MEDIUM',
                    'COMPONENT_AT_AR_AFGRIP',
                }},
            },
        },
    },
    ['fire'] = {
        Label = 'Fire Department',
        ShortLabel = 'FIRE',
        AllowedRoles = {},
        BlipSpriteOnFoot = 1,
        BlipSpriteInVehicle = 56,
        BlipColor = 1,
        LogChannelId = '',
        Loadout = { Armor = 50, Weapons = {} },
    },
    ['ems'] = {
        Label = 'Emergency Medical Services',
        ShortLabel = 'EMS',
        AllowedRoles = {},
        BlipSpriteOnFoot = 1,
        BlipSpriteInVehicle = 56,
        BlipColor = 2,
        LogChannelId = '',
        Loadout = { Armor = 0, Weapons = {} },
    },
},
PropertyTypeDescription
LabelstringFull department name
ShortLabelstringShort name for blip tag
AllowedRolestableDiscord role IDs (empty = everyone)
BlipSpriteOnFootnumberBlip sprite when on foot
BlipSpriteInVehiclenumberBlip sprite when in vehicle
BlipColornumberBlip color ID
LogChannelIdstringDiscord channel for clock-in/out logs
LoadouttableWeapons/armor given on duty

Loadout Configuration

Loadout = {
    Armor = 100,
    Weapons = {
        { 
            weapon = 'WEAPON_COMBATPISTOL', 
            ammo = 120, 
            tint = 5,
            attachments = { 'COMPONENT_AT_PI_FLSH' }
        },
    },
},
Weapon Tints:
IDColor
0Normal
1Green
2Gold
3Pink
4Army
5LSPD
6Orange
7Platinum
Common Attachments:
ComponentDescription
COMPONENT_AT_PI_FLSHPistol Flashlight
COMPONENT_AT_PI_SUPPPistol Suppressor
COMPONENT_AT_AR_FLSHRifle Flashlight
COMPONENT_AT_AR_SUPPRifle Suppressor
COMPONENT_AT_AR_AFGRIPRifle Grip
COMPONENT_AT_SCOPE_SMALLSmall Scope
COMPONENT_AT_SCOPE_MEDIUMMedium Scope
COMPONENT_AT_SCOPE_LARGELarge Scope

Blip Sprites Reference

SpriteIcon
1Circle/Dot
56Car
60Police Car
61Ambulance
64Helicopter
226Motorcycle
436Fire Truck

Blip Colors Reference

IDColor
0White
1Red
2Green
3Blue
5Yellow
17Orange
19Purple

Activity System Exports

-- Check if player is on duty
local isOnDuty = exports.LonexDiscordAPI:IsOnDuty(source)

-- Get player's current department
local department = exports.LonexDiscordAPI:GetPlayerDepartment(source)

-- Get full duty info
local dutyInfo = exports.LonexDiscordAPI:GetDutyInfo(source)

-- Get all on-duty players
local players = exports.LonexDiscordAPI:GetOnDutyPlayers()

-- Get on-duty players by department
local leoPlayers = exports.LonexDiscordAPI:GetOnDutyByDepartment('leo')

-- Get department counts
local counts = exports.LonexDiscordAPI:GetDepartmentCounts()

-- Set duty status programmatically
exports.LonexDiscordAPI:SetDutyStatus(source, true, 'leo')

-- Get duty duration in seconds
local duration = exports.LonexDiscordAPI:GetDutyDuration(source)

-- Get departments player has access to
local available = exports.LonexDiscordAPI:GetPlayerDepartments(source)

Activity System Events

-- Fired when player clocks in
AddEventHandler('LonexDiscord:Activity:OnDuty', function(source, department)
    print(GetPlayerName(source) .. ' is now on duty as ' .. department)
end)

-- Fired when player clocks out
AddEventHandler('LonexDiscord:Activity:OffDuty', function(source, department, durationSeconds)
    print(GetPlayerName(source) .. ' was on duty for ' .. durationSeconds .. ' seconds')
end)

Command Usage

/duty [department] - Clock in/out of duty
  • If only one department available, auto-selects it
  • If multiple departments, shows list or specify department name
  • If already on duty, clocks out
/bliptag [id] - Change your displayed blip tag
  • For players with access to multiple departments
  • Shows list of available tags if no argument provided
/units - List all on-duty players
  • Shows players grouped by department
  • Displays player name, ID, and time on duty

Server HUD

Configurable on-screen HUD with compass, street, postal, AOP, and player info displays.
Config.ServerHUD = {
    Enabled = false,
    ToggleCommand = 'togglehud',
    
    Watermark = {
        Enabled = false,
        Text = 'My RP Server | discord.gg/myserver',
        x = 0.165,
        y = 0.825,
        scale = 0.4,
    },
    
    Displays = {
        ['Compass'] = {
            x = 0.165,
            y = 0.85,
            display = "~w~| ~g~{COMPASS} ~w~|",
            scale = 1.0,
            enabled = true,
        },
        ['Street'] = {
            x = 0.22,
            y = 0.855,
            display = "~g~{STREET}",
            scale = 0.45,
            enabled = true,
        },
        ['Zone'] = {
            x = 0.22,
            y = 0.875,
            display = "~w~{ZONE}",
            scale = 0.45,
            enabled = true,
        },
        ['Postal'] = {
            x = 0.165,
            y = 0.91,
            display = "~w~Nearest ~g~Postal: ~w~{POSTAL} (~g~{POSTAL_DIST}m~w~)",
            scale = 0.4,
            enabled = true,
        },
        ['AOP'] = {
            x = 0.165,
            y = 0.93,
            display = "~w~Current ~g~AOP: ~w~{AOP} ~y~| ~w~PeaceTime: {PEACETIME}",
            scale = 0.4,
            enabled = true,
        },
        ['PlayerInfo'] = {
            x = 0.165,
            y = 0.953,
            display = "~w~Tag: ~g~{TAG} ~y~| ~w~ID: ~g~{ID}",
            scale = 0.4,
            enabled = true,
        },
    },
}
OptionTypeDefaultDescription
EnabledbooleanfalseEnable Server HUD
ToggleCommandstring'togglehud'Command to toggle HUD on/off

Watermark Options

OptionTypeDefaultDescription
EnabledbooleanfalseShow/hide the watermark
Textstring'...'Server name, discord link, etc.
xnumber0.165X position (0.0 = left)
ynumber0.825Y position (0.0 = top)
scalenumber0.4Text scale

Display Options

OptionTypeDescription
xnumberX position (0.0 = left, 1.0 = right)
ynumberY position (0.0 = top, 1.0 = bottom)
displaystringText with placeholders and color codes
scalenumberText size
enabledbooleanShow/hide this display

Placeholders

PlaceholderDescription
{COMPASS}Direction (N, NE, E, SE, S, SW, W, NW)
{STREET}Current street name
{ZONE}Current zone/area name
{POSTAL}Nearest postal code
{POSTAL_DIST}Distance to nearest postal (meters)
{AOP}Current Area of Play
{PEACETIME}PeaceTime status (gON or rOFF)
{ID}Player’s server ID
{PLAYERS}Online player count
{TAG}Player’s current tag

GTA Color Codes

CodeColorCodeColor
~w~White~p~Purple
~r~Red~c~Grey
~g~Green~o~Orange
~b~Blue~y~Yellow

Console Commands

Server console commands for debugging and administration.
CommandDescription
lonex_rolesList all configured role mappings
lonex_syncallManually sync permissions for all players
lonex_debug_player <id>Full diagnostic for player permissions
lonex_debug_vehicles <id>Debug vehicle permissions for player
lonex_discord_perms <id>Show player’s current groups and permissions
lonex_discord_test <id>Test Discord API for a player
lonex_discord_testid <discord>Test Discord API with a Discord ID
lonex_discord_syncperms <id>Force resync permissions for a player
lonex_discord_testwebhook <name>Send a test message to a webhook
lonex_updateCheck for updates

Badger_Discord_API Bridge

Drop-in compatibility layer for scripts using the Badger_Discord_API export functions. Located in extras/Badger_Discord_API/, this bridge allows existing scripts to work without modification.

Installation

  1. Copy extras/Badger_Discord_API to your resources folder
  2. Add to your server.cfg after LonexDiscordAPI:
    ensure LonexDiscordAPI
    ensure Badger_Discord_API
    

Supported Functions

All standard Badger_Discord_API exports are supported:
  • GetDiscordId(player)
  • GetDiscordName(player)
  • GetGuildIcon()
  • GetGuildName()
  • CheckEqual(player, role)
  • CheckGreater(player, role, includeEqual)
  • CheckLess(player, role, includeEqual)
  • GetRoles(player)
  • GetRoleName(roleId)
  • IsPlayerInServer(player)

Quick Reference

Getting Discord IDs

  1. Open Discord Settings → Advanced → Enable Developer Mode
  2. Server ID: Right-click server icon → Copy Server ID
  3. Role ID: Server Settings → Roles → Right-click role → Copy Role ID
  4. User ID: Right-click user → Copy User ID

Admin Bypass

For any permission system (weapons, vehicles, peds), use an empty table to grant full access:
['ADMIN_ROLE_ID'] = {},  -- No restrictions

Testing Configuration

  1. Set Config.Debug = true for verbose logging
  2. Set Config.LogLevel = 'debug' for detailed output
  3. Check server console for errors on startup
  4. Use lonex_debug_player <id> to diagnose permission issues