<!-- fivemad.com, Markdown source of https://fivemad.com/docs/tools/ymap-builder -->
> Source: https://fivemad.com/docs/tools/ymap-builder
> Section: Tools
> Tags: ymap, props, CodeWalker, map, CEntityDef, RequestIpl
> Tool: https://fivemad.com/tools/ymap-builder
> Last updated: 2026-09-24
> Site map for assistants: https://fivemad.com/llms.txt

# YMAP Builder

Place props by coordinates or in a 3D world, get CodeWalker ready .ymap XML with correct rotations and extents, and stream it from a FiveM resource.

The YMAP Builder turns a list of props and positions into a `.ymap` placement file without opening a map editor. You paste coordinates from the game (or place props in the 3D world), set heading or full rotation, and the tool writes CodeWalker XML with the quaternions, entity extents, streaming extents and map flags already calculated. It is for server owners and devs who want a few benches, barriers or decorations streamed with the map instead of spawned by a script.

## What it is for

A ymap is part of the map itself. The game streams it in when you get close and drops it when you leave, with no script at all. The catch is the file format: rotations are stored as an inverted quaternion, extents have to cover every entity plus its draw distance, and the map flags depend on the LOD levels you use. Get one of those wrong and props face the wrong way, pop out early or never load. This tool handles those parts so you only think about model, position and heading.

The same props can also be spawned from Lua at runtime, and the tool exports that too: a ready resource with no `.ymap` in it and no CodeWalker step. See [Spawn it from Lua instead](#spawn-it-from-lua-instead) for what each one is good for.

Typical jobs:

- Decorating a spot (benches, bins, barriers, plants) around an MLO or a job location.
- Turning a list of `vector4` spawn points from your config into static props.
- Editing an existing ymap XML: fix a rotation, move a group of props, change `lodDist` on everything.

## Quick start

1. Add the helper from **Grab positions in game** (bottom of the page) to a client script on your dev server. Stand where a prop should go and run `/ymappos`, or look at an existing prop and run `/ymapprop`. Finish with `/ymapdump`.
2. In **Import**, keep the **Coordinates** tab, paste the lines, pick a **Default model** and press **Add**.
3. Fine tune rows in **Entities**, or select several and use the bulk edit bar. Open **3D world** (desktop) to move them with a gizmo inside the GTA V map.
4. Set **Name** in the **Ymap** panel. It becomes the file name.
5. Check the warnings under the preview, then press **Download** on the **XML** tab of **Export**. You get `<name>.ymap.xml`.
6. Convert it to a binary `.ymap` with CodeWalker (see the **Convert** tab), put it in `stream/` of a resource and `ensure` it.

The page starts with three sample props at Vespucci Beach so you can see the output before adding your own. Your work is saved in the browser (local storage) and comes back when you reopen the page.

## Panels

### Ymap

| Field | What it does | Default |
| --- | --- | --- |
| **Name** | Ymap name and file name (`stream/<name>.ymap`). Lowercase letters, digits, `_` and `-` only; anything else is replaced on export. Must be unique across all your resources. | `fivemad_props` |
| **Parent** | Parent ymap name, written to `<parent>`. Leave empty for standalone props. | empty |
| **Assumed entity radius (m)** | The tool does not know model sizes, so this radius (times the entity scale) stands in for each prop when the extents are filled in. Raise it for big props. | `10` |
| **lodDist when set to -1 (m)** | Entities with `lodDist -1` use the model's own draw distance. The extents still need a number, so this one is used. | `150` |
| **Scripted (flags 1)** | Sets map flag 1. The game then only loads the ymap after `RequestIpl('name')`. Leave it off for props that should always be there. | off |

**Undo** reverts the last structural change (add, delete, duplicate, reorder, import, bulk edit, 3D edits), up to 40 steps. Typing in a field is not recorded, to keep the history useful. **Clear** removes every entity, and Undo brings them back.

### Entities

Each row has a model field (with autocomplete from the vanilla objects list), `x`, `y`, `z` and `heading`. A model name that is not in the objects list is marked, and the row number turns amber when the row has a warning.

- **Add** appends a row 2 m east of the last one, with the same z and heading, using the model, flags and lodDist from the import defaults.
- Paste a whole `vector3(...)`, `vector4(...)` or a `/ymapprop` line into the **x** field and it fills x, y, z, heading (and pitch, roll and model when the line has them).
- The row buttons duplicate (the copy sits 1 m east) or delete that row. The chevron opens **More fields**.
- The checkbox bar on top selects rows. With a selection you get move up, move down, duplicate and delete for all of them, plus the bulk edit bar.
- Long lists show 60 rows at a time with a **Show more** button.

**More fields** per entity:

| Field | Written to | Notes |
| --- | --- | --- |
| **Rotation**: Heading only / Pitch / roll / yaw | `rotation` | Pitch/roll/yaw adds `pitch` and `roll` inputs and renames heading to `yaw`. The stored quaternion is shown next to it. |
| **lodDist** | `lodDist` | Draw distance in metres. `-1` uses the model's own value. Default `100`. |
| **childLodDist** | `childLodDist` | Only matters for LOD parents. Default `0`. |
| **priority** | `priorityLevel` | `REQUIRED`, `OPTIONAL_HIGH`, `OPTIONAL_MEDIUM`, `OPTIONAL_LOW`. |
| **lodLevel** | `lodLevel` | `ORPHANHD` for standalone props. HD, LOD and SLOD levels are for LOD chains. |
| **AO multiplier** | `ambientOcclusionMultiplier` | 0-255, default 255. |
| **artificial AO** | `artificialAmbientOcclusion` | 0-255, default 255. |
| **tint** | `tintValue` | Texture variation, same as `SetObjectTextureVariation`. |
| **scale xy / z** | `scaleXY`, `scaleZ` | Default 1. |
| **flags** | `flags` | Number field plus a preset menu and a **Flag bits** list with every known bit. |

Flag presets:

| Preset | Value | Use |
| --- | --- | --- |
| Static + shadows | `1572896` | Frozen prop that casts shadows. The default for new rows. |
| Static | `32` | Frozen prop, CodeWalker's default. |
| Dynamic + shadows | `1572864` | Physics on (if the model has physics), like most vanilla props. |
| Dynamic | `0` | Physics on, no extra bits. |

If an entity is tilted (pitch or roll not zero), flag `1` (allow full rotation) is added on export, and the flags editor says so. Without it the game ignores pitch and roll.

For entities loaded from an XML, `guid`, `parentIndex`, `numChildren` and any `extensions` block are kept and written back unchanged.

### Bulk edit

With rows selected, the bar under the toolbar edits all of them at once. Empty fields stay unchanged, offsets are added.

- **model**, **flags** (presets), **lodDist**, **priority**, **lodLevel**: replace the value.
- **offset x**, **offset y**, **offset z**: add to the position (move a whole group).
- **rotate heading by**: adds degrees to each heading. **set heading**: sets one heading for all (wins over rotate).
- **Apply to N** runs it, **Reset** empties the bar.

### Import: Coordinates

Paste one entity per line. It accepts `vector3`, `vector4`, `vec3`/`vec4`, `{x = , y = , z = , w = }`, JSON objects or arrays and plain numbers. A model name, `model=<hash>` or `rot=vector3(pitch, roll, yaw)` on the same line is picked up too. Model hashes are turned back into names when they are vanilla props, otherwise into `hash_XXXXXXXX`.

```lua
vector4(-1386.72, -1004.23, 3.86, 125.0)
{x = -1383.35, y = -1008.94, z = 3.86, w = 125.0}
prop_bin_07a vector3(-1385.1, -1006.62, 3.86)
model=prop_bench_01a pos=vector3(-1374.0, -1018.5, 3.86) rot=vector3(0.0, 0.0, 125.0)
```

| Option | What it does | Default |
| --- | --- | --- |
| **Default model** | Used for lines without a model. | `prop_bench_01a` |
| **Heading if missing** | Used for lines without a heading (vector3). | `0` |
| **Z offset (m)** | Added to every z. The **-1** link sets it for player coords. | `0` |
| **Flags for new rows** | Flag preset for the imported rows. | Static + shadows |
| **lodDist for new rows** | lodDist for the imported rows. | `100` |

**Add N** appends, **Replace all** replaces the list. Lines it cannot read are counted and the first five are listed.

### Import: Ymap XML

**Open .ymap.xml** or paste XML and press **Load pasted XML**. It replaces the current entities (Undo brings them back). Get the XML from CodeWalker: RPF Explorer, right click the ymap, Export XML. Rotations are read the way CodeWalker stores them and shown as in-game heading or pitch/roll/yaw. Sections the builder does not edit (car generators, occluders, LOD lights, time cycle modifiers and so on) are kept and written back as they were.

### Top-down preview

An SVG plan of every entity. The line on each dot shows its heading. Click a dot to jump to its row, <kbd>Shift</kbd> or <kbd>Ctrl</kbd> click to add it to the selection. The solid box is the entity extents; tick **Streaming extents** to also draw the dashed streaming box (the area in which the ymap is loaded).

### Warnings

The list under the preview checks your ymap as you edit. Click a warning to select the rows it is about.

- Missing or invalid name, empty model, invalid numbers.
- Models not in the vanilla objects list (fine for custom props, otherwise a typo).
- Two entities within 1 cm of each other, entities outside the playable map, entities at 0, 0.
- A ymap spanning a very large area, or more than 1000 entities (split it by area).
- `lodDist` under 20 m.
- HD levels without a LOD parent (use `ORPHANHD` for standalone props).
- Tilted entities that get flag 1 on export (info).

### 3D world

The **3D world** button in the preview panel (desktop only) opens the ymap inside the GTA V world at the top of the page, starting next to the active entity. Props that have a model in the Objects List show as the real mesh, others as a box of their real size (or a 1 m box). Everything you do there updates the entity list and the export right away, and Undo works for moves, rotations and placed props.

| Control | What it does |
| --- | --- |
| Click a prop | Select it (it becomes the active row). <kbd>Shift</kbd>, <kbd>Ctrl</kbd> or <kbd>Cmd</kbd> click adds it to the selection. |
| **Move** or <kbd>G</kbd> | Move gizmo (world axes). Drag an arrow or plane. |
| **Rotate** or <kbd>T</kbd> | Rotate gizmo (local axes). Heading-only entities only get the vertical ring; switch the row to Pitch / roll / yaw to tilt it. |
| **Place** | Pick a model, then click the ground to drop it. A ghost follows the mouse and the coordinates under it are shown. <kbd>R</kbd> turns it 15 degrees (<kbd>Shift</kbd> <kbd>R</kbd> the other way), <kbd>Esc</kbd> stops placing. |
| **Snap to ground** | Drops the selected entities (or the active one) so the model's lowest point rests on the ground or roof under it. Entities with no loaded ground under them are skipped and counted. |
| **Focus** | Moves the camera to the active entity. |
| Right mouse drag, <kbd>W</kbd> <kbd>A</kbd> <kbd>S</kbd> <kbd>D</kbd> | Look and move the freecam. Clicking does not capture the mouse here, so you can click props. |

The camera, quality setting and full screen work the same as in the [3D world](/docs/tools/world-3d) docs. **Close 3D** hides the panel again.

## Output

### Export tabs

- **XML**: a stats line (`entities`, map `flags`, `contentFlags`, entity extent size) and the full CMapData XML. **Download** saves it as `<name>.ymap.xml`.
- **Resource**: the folder layout, a ready `fxmanifest.lua`, and a `client.lua` with `RequestIpl` when **Scripted** is on.
- **Convert**: the CodeWalker steps below.

For the second output, a resource that spawns the same props from Lua with no ymap at all, see [Spawn it from Lua instead](#spawn-it-from-lua-instead).

Each entity is written like this (a `prop_bench_01a` at heading 125):

```xml title="fivemad_props.ymap.xml"
  <Item type="CEntityDef">
   <archetypeName>prop_bench_01a</archetypeName>
   <flags value="1572896" />
   <guid value="0" />
   <position x="-1386.72" y="-1004.23" z="3.86" />
   <rotation x="0" y="0" z="-0.8870108" w="0.4617486" />
   <scaleXY value="1" />
   <scaleZ value="1" />
   <parentIndex value="-1" />
   <lodDist value="100" />
   <childLodDist value="0" />
   <lodLevel>LODTYPES_DEPTH_ORPHANHD</lodLevel>
   <numChildren value="0" />
   <priorityLevel>PRI_REQUIRED</priorityLevel>
   <extensions />
   <ambientOcclusionMultiplier value="255" />
   <artificialAmbientOcclusion value="255" />
   <tintValue value="0" />
  </Item>
```

### Converting with CodeWalker

Browsers cannot write the binary ymap format, so CodeWalker does the last step:

1. Put `<name>.ymap.xml` in your resource's `stream` folder. Keep the double extension, CodeWalker uses it to know the file type.
2. Open CodeWalker's **RPF Explorer**, then **File, Open Folder** and pick that stream folder.
3. Turn on **Edit mode**, then **Edit, Import XML** (or drag the file into the window) and choose the XML.
4. CodeWalker writes `<name>.ymap` next to it. Delete the `.xml` from stream.
5. `ensure` the resource and reconnect.

To check it first, open CodeWalker's world view, use the Project window, **File, Open Files** to load the ymap and fly to it.

### The resource

```text
fivemad_props/
├── fxmanifest.lua
└── stream/
    └── fivemad_props.ymap        <- binary, converted with CodeWalker
```

```lua title="fxmanifest.lua"
fx_version 'cerulean'
game 'gta5'

name 'fivemad_props'
description 'Props streamed with fivemad_props.ymap'

-- A .ymap inside stream/ is picked up on its own, nothing else is required.
-- this_is_a_map 'yes' reloads the map store when the resource starts. Only add it
-- if you replace vanilla map files or ship map data files.
-- this_is_a_map 'yes'
```

```cfg title="server.cfg"
ensure fivemad_props
```

With **Scripted** on, the manifest adds `client_script 'client.lua'` and the tool gives you:

```lua title="client.lua"
-- The ymap has the "scripted" flag, so the game only loads it on request.
CreateThread(function()
    RequestIpl('fivemad_props')
end)

-- Later, to remove the props again:
-- RemoveIpl('fivemad_props')
```

## Spawn it from Lua instead

The panel at the bottom of the page builds a second resource that creates the same props from Lua at runtime. There is no `.ymap` in it, so there is no CodeWalker step and no reconnect: `restart` the resource and the props are there.

### What you get

```text
fivemad_props_lua/
├── fxmanifest.lua
├── config.lua        <- the props, one readable row each
├── client.lua        <- spawns and deletes them
└── README.md
```

**Download resource** saves it as a zip. Drop the folder in `resources`, add `ensure fivemad_props_lua` to your server.cfg and restart it.

A row in `config.lua` looks like this:

```lua title="config.lua"
Config.objects = {
    { model = 'prop_bench_01a', x = -1386.72, y = -1004.23, z = 3.86, pitch = 0.0, roll = 0.0, yaw = 125.0, lod = 100, freeze = true },
}
```

`x`, `y` and `z` are the entity origin, the same numbers the ymap stores. `pitch`, `roll` and `yaw` are the rotation in degrees the way `GetEntityRotation(entity, 2)` reads it back, so they are the values you would read off the prop in game. `lod` is `SetEntityLodDist` in metres, `-1` keeps the model's own distance. `freeze` is the ymap's flag 32. `collision = false` and `tint` are only written on the rows that need them.

### Settings

| Field | What it does | Default |
| --- | --- | --- |
| **Resource name** | Folder and resource name. Empty uses the ymap name plus `_lua`, so it cannot clash with the ymap resource. | `<name>_lua` |
| **spawn radius (m)** | A prop closer than this to the player exists. | `150` |
| **despawn margin (m)** | Extra distance before a prop is deleted again, so one sitting on the line cannot flicker. | `25` |
| **max at once** | Ceiling on how many props this resource holds. | `400` |
| **spawns per pass** | How many props one pass may create. Higher fills in faster after a teleport, at the cost of a heavier frame. | `5` |
| **pass every (ms)** | Time between two distance checks. | `500` |
| **Wait for an export (manual)** | Nothing spawns until `exports['<name>']:Load()` runs. The same idea as the ymap scripted flag with `RequestIpl`. | off |

Every one of these is a plain number in `config.lua`, so you can change your mind after the download.

Exports on the generated resource:

```lua
exports['fivemad_props_lua']:Load()     -- start spawning
exports['fivemad_props_lua']:Unload()   -- take them all away again
exports['fivemad_props_lua']:Count()    -- how many props it holds right now
```

### The short version

One prop, done the way the resource does it:

```lua
local model = `prop_bench_01a`
RequestModel(model)
while not HasModelLoaded(model) do Wait(0) end

-- CreateObjectNoOffset puts the entity origin on the coordinates, which is what
-- a ymap stores. CreateObject would lift it by the radius of the model.
-- isNetwork false: the prop is local to this client, the way map geometry is.
local prop = CreateObjectNoOffset(model, -1386.720, -1004.230, 3.860, false, false, false)

-- pitch, roll, yaw in degrees. Rotation order 2 is ROT_ZXY, the one
-- GetEntityRotation(entity, 2) reads back.
SetEntityRotation(prop, 0.00, 0.00, 125.00, 2, true)
FreezeEntityPosition(prop, true)
SetEntityLodDist(prop, 100)
SetModelAsNoLongerNeeded(model)
```

The block on the page shows the same thing in Lua, JavaScript, TypeScript or C#, using the model and rotation of the row you have selected.

### Which one belongs in your map

| | Ymap | Lua spawner |
| --- | --- | --- |
| What it is | Map data the engine streams | A resource that creates objects |
| Loading | By the streaming extents, no script | A loop measuring distance to the player |
| Appearing | Fades in on `lodDist`, LOD chains work | Pops in at your spawn radius |
| Cost | None while you are away from it | Every prop is a live object in the client's object pool |
| `scaleXY` / `scaleZ` | Works | No native for it, props spawn at normal size |
| Entity extensions (lights, particles) | Work | Not reproduced, only the prop is spawned |
| Changing it | CodeWalker, then reconnect | Edit `config.lua` and `restart` |
| Other players | Everyone streams the same map | Everyone runs the same script and builds their own copy |

For a map that ships with your server, use the ymap. Use the Lua spawner for testing without CodeWalker, for event props, and for anything that has to appear and disappear.

> [!NOTE]
> The spawned props are not networked entities. Every client creates its own copy of the scenery, which is how a streamed map behaves anyway, but the server has no handle on any of them and no other player can be given one.

### Limits worth knowing

Every spawned prop takes a slot in the client's `Object` pool. The `gameconfig.xml` FiveM ships gives that pool 3,300 entries, and the props the map itself streams are already in it, so the exported script spawns in batches and keeps a ceiling. `#GetGamePool('CObject')` prints how many objects exist right now. The pool can be raised from server.cfg by at most 2,000:

```cfg title="server.cfg"
increase_pool_size "Object" 2000
```

That is a startup only command and every client has to restart the game before joining, so tune the radius first.

The warnings under the settings list what your ymap carries that a spawner cannot: scaled entities, entities with extensions, and entities in a LOD chain.

## Grabbing positions in game

The **Grab positions in game** panel gives you `ymap_helper.lua`, a client script for your dev server:

| Command | Output |
| --- | --- |
| `/ymappos` | Your position snapped to the ground (`GetGroundZFor_3dCoord`) plus heading, as `vector4(...)`. |
| `/ymapprop` | Model hash, position and rotation (`GetEntityRotation(ent, 2)`) of the object in front of the camera, found with a shape test ray of 30 m. |
| `/ymapdump` | Prints every collected line so you can paste them all at once. |
| `/ymapclear` | Forgets the collected lines. |

Each line is printed to the F8 console and chat. Tick **Copy to clipboard (ox_lib)** to also copy it with `lib.setClipboard` (needs ox_lib). Every line it prints is a format the importer reads. Remove the helper before going live.

> [!NOTE]
> `/ymapprop` only finds props the game spawned as objects. Static map geometry is not an object and will not be hit by the ray.

## Rotation

Enter rotations the way you read them in game: heading from `GetEntityHeading`, or pitch, roll and yaw from `GetEntityRotation(entity, 2)`. Heading 0 faces north and 90 faces west. The tool writes the quaternion a ymap expects, so you never type one yourself. The expanded row shows the value that will be written, if you want to compare it with another file.

When you open the result in CodeWalker, its entity panel shows the stored rotation as is, so its Euler Z reads minus your in-game heading. That is normal, the prop still faces the heading you entered.

## Common mistakes

- **Props float 1 m in the air.** `GetEntityCoords(PlayerPedId())` is at the pelvis. Use `/ymappos` (ground snapped) or set **Z offset** to -1 when importing.
- **Props face the wrong way.** Someone wrote the heading straight into the quaternion without inverting it. Import the XML here and headings are read correctly.
- **Props vanish when you walk away.** lodDist too low, or the streaming extents were not recalculated after moving things. The builder recalculates them on every change.
- **Nothing shows up.** The file in `stream/` is still the `.xml`, the name clashes with another ymap, or **Scripted** is on and nothing calls `RequestIpl`.
- **Custom props are invisible.** The ymap only places them. Their `.ydr`, `.ytd` and `.ytyp` must be streamed too.
- **One huge ymap.** The whole file streams in as soon as you enter its extents. Keep one ymap per area.
- **Changes do not show.** Reconnect. Map files load when you join, a resource restart is not always enough.

> [!TIP]
> You do not need `this_is_a_map 'yes'` to add props. It only matters when you replace vanilla map files.

## Limitations

- The ymap output is CodeWalker XML. You still need CodeWalker to make the binary `.ymap`. The Lua spawner needs nothing.
- The tool does not know model sizes, so extents use the **Assumed entity radius**. Raise it for big props.
- No LOD chain authoring (parents, LOD models), occluders, car generators or MLO interiors. Those sections are only passed through from an imported XML.
- The 3D world needs a desktop browser with WebGL 2, and it does not include Cayo Perico or North Yankton.
- Everything runs in your browser and is saved locally. Nothing is uploaded.

## Related tools

- [Objects / Props List](/docs/tools/objects-list): find model names, sizes and 3D previews.
- [3D world](/docs/tools/world-3d): camera modes, keys and performance tips for the 3D view.
- [Interactive Map](/docs/tools/interactive-map): grab coordinates without starting the game.
- [YTYP Creator](/docs/tools/ytyp-creator): archetypes for custom props you place with a ymap.
- [fxmanifest Generator](/docs/tools/fxmanifest-generator)
