F.A.Q

5 min readUpdated 2 weeks ago

Setup

The image file referenced in Config.Maps[mapId].image does not exist in the maps/ folder. Filenames are case-sensitive on Linux servers. Check that the path matches exactly.

Yes. Set Config.ItemMode = 'multi' and add one entry per map to Config.Items:

lua
1Config.Items = {
2    ['tourist_map']  = 'tourist',
3    ['treasure_map'] = 'treasure',
4    ['city_map']     = 'city',
5}

Each item opens its own map with its own saved markers.

Set Config.ItemMode = 'none'. The keybind and commands always work, no inventory check. Map and compass are always available.

Check Config.HideDefaultMinimap = true, Config.NativeMap.allowEveryone = false, and that the staff toggle (/nativemap) hasn't been enabled for the current session.

Yes. With Config.NativeMap.allowStaff = true, anyone with staffPermission can run /nativemap to toggle the GTA native map ON/OFF for themselves only. Other players are unaffected.

Default keybind is P: rebindable via GTA's keybind settings (Settings → Key Bindings → FiveM). Change the default key in Config.Keybind.key. The item-use path also opens the map when the player uses a map item from their inventory.

Set Config.Debug = true. This enables three extra commands:

  • /map [mapId] opens any map without an item
  • /compass toggles the compass HUD
  • /mapclose closes the map immediately

Debug mode also bypasses fog of war when Config.FogOfWar.bypassDebug = true (the default).

Calibration

  1. Drop the image into maps/
  2. Add a Config.Maps entry with the correct imageWidth / imageHeight
  3. Run /mapcalibrate <mapId> in-game (admin permission required)
  4. Walk to a known world location, click the matching spot on the overlay
  5. Repeat for at least 4 points spread across the map: more points = better accuracy
  6. Run /mapcalibrate done: the calibration block is printed to the F8 console and copied to clipboard
  7. Paste the block into Config.Maps[mapId].calibration and restart the resource

If points are clustered in a small area, the regression will be unstable. Spread them across the map.

Yes, if the images share the same dimensions and projection (e.g. satellite / road / atlas of the same area). Calibrate one, paste the same calibration block into every map entry.

Change subDone and subReset in Config.CalibrationCommand:

lua
1Config.CalibrationCommand = {
2    command  = 'mapcalibrate',
3    subDone  = 'salva',
4    subReset = 'annulla',
5}

Now you'll use /mapcalibrate salva and /mapcalibrate annulla.

Fog of War

The reveal radius is Config.FogOfWar.revealRadius meters, multiplied by the map's scaleX to get pixels. On small stylized maps (e.g. an 814×1222 tourist map), the default 100m gives a 9px reveal: tiny.

Add a per-map override inside the map entry:

lua
1Config.Maps['tourist'] = {
2    -- ...
3    fogRevealRadius = 800,
4}

Changing this value after players have explored invalidates their saved bitmask. Wipe it first:

sql
1UPDATE ml_custommap_data SET discovered = NULL WHERE map_id = 'tourist';

Yes. On player load (or resource restart while in-game), the client asks the server to bootstrap a fog session if the player holds a map item. Tracking runs in the background: the bitmask updates as the player walks, delta-synced to the server every 30 seconds.

sql
1UPDATE ml_custommap_data SET discovered = NULL;

Restart the resource. Every player rediscovers the map from scratch.

Set Config.FogOfWar.enabled = false. No tracking, no reveal, full map visible.

Markers, Radii, Labels

That was a bug in early versions caused by a save-on-close race condition. The current version saves synchronously before the close request is sent to Lua. Update to the latest release.

Right-click a marker and choose Copy. A short code is placed in your clipboard. The other player opens their map, right-clicks anywhere, chooses Import, and pastes the code. The same marker appears on their map.

Use /addblip <mapId> in-game (admin permission required). The map opens in admin mode. Place markers visually: each placement prints the config block to the console and copies it to clipboard. Paste the blocks into Config.DefaultMarkers and restart.

Or, if you know the world coordinates, write directly:

lua
1Config.DefaultMarkers = {
2    { mapId = 'tourist', worldX = 200.0, worldY = -800.0, preset = 'camp', label = 'Base Camp' },
3}

For security. The script rejects data:, file:, and javascript: URIs to prevent players from loading arbitrary payloads into the map interface. Host your images on any public web server or image CDN.

Storage

Use 'metadata' when you want markers to live with the item: if the item is consumed, traded, or dropped, the map goes with it. Use 'database' when you want markers to belong to the player's account regardless of which item they're holding.

In practice, 'metadata' is more RP-friendly (a paper map is a paper map), 'database' is more convenient.

Same ml_custommap_data table, discovered column. Base64-encoded bitmask with one bit per grid cell. Grid size is derived from the map's scaleX and Config.FogOfWar.revealRadius.

Compass

Check Config.Compass.enabled = true. If ItemMode = 'multi', the item name must match Config.Compass.item. If ItemMode = 'single', the compass is bound to Config.SingleItem.

Only Config.DefaultMarkers entries appear on the compass. Player-placed markers are map-only by design: otherwise the horizon would get crowded.

Paper Map In Hand

Bind the item with a table value instead of a string in Config.Items. A string opens the map fullscreen; a table opens it on a paper prop held in first person, with the live map drawn on the page.

shared/config.lua
1Config.Items = {
2    ['tourist_map'] = 'tourist',
3    ['dui_map']     = { map = 'mappa', mode = 'dui' },
4}

The prop, camera, and light are configured under Config.DuiMaps. See the Configuration page.

Set Config.Debug = true and run /duistudio <mapId>. Press Tab to switch between editing the camera and the prop, line them up in the 3D preview, then press Enter to copy both blocks to the clipboard and paste them into Config.DuiMaps.

Updates

  1. Download latest from CFX Portal
  2. Backup shared/config.lua
  3. Replace all files except shared/config.lua and anything in locales/
  4. Restart the resource

No manual migration needed. The table is created on first start and player data carries across updates.