The bridge tool port_er_map copies the Asset parts of an Elden Ring map into loaded Nightreign maps in one go. It
imports every model it needs into the project, then places the parts where they stood in Elden Ring, moved by an
offset you give.
There is no button for this in the editor. It only exists as a bridge tool, so you run it through the MCP server (see mcp-bridge.md). To place single Elden Ring assets by hand, use the Object Palette: place-er-asset.md.
What was checked for this page: every parameter and default was read from the code. Nothing was run. The in-game notes at the end come from the team's notes on the sewers work, not from the code.
What it copies, and what it does not
Copied:
Assetparts of the Elden Ring map, andDummyAssetparts if you ask for them.- For each part: its model, position, rotation and scale.
- Each distinct model, once, into the project: the same importer the Object Palette uses (model, collision, missing textures and materials). If Nightreign already uses that id for a different model, the import gets a free id of the same family, and the parts use that id. If Nightreign has its own copy of the same model, that copy is reused.
Not copied:
- Map pieces, collision parts, enemies, regions, events, lights, navmesh, or anything else in the map.
- Entity ids and entity groups. They are cleared by default (
clear_ids).
How a part is made: it is a clone of a template Asset part of the target map, so its draw groups and flags are
valid there. Then ModelName, Position, Rotation and Scale are set from the Elden Ring part. It is named
<model>_<free number> (four digits) with a matching InstanceID.
Before you start
- A Nightreign project with an Elden Ring install set up for it. Without one the tool answers "Porting ER maps needs a Nightreign project and an Elden Ring install." See project-setup.md.
- The target Nightreign maps must be loaded, and each needs at least one
Assetpart to use as a template (and oneDummyAssetpart if you port that class). - If the target should be a new map, make it first with
create_map_copy(below) and load it. - Check
smithbox_statusfirst. Do not run this in a Smithbox someone is editing without asking.
Steps
-
Make the target map if it does not exist:
create_map_copy(source="m60_44_36_00", new_id="m60_44_36_60")It writes
map/mapstudio/<new_id>.msb.dcxinto the project folder as a copy of the source's MSB, and lists the map in the Map Editor. Only the MSB is copied: no collision, navmesh, lights and so on. Map piece models resolve under the new id, so they may not draw. (with_navigation=Truealso copies the.nvaand the navmesh binder; see generate-navmesh.md.) -
load_mapevery target map. -
Do a dry run. It places nothing:
port_er_map(er_map="m35_00_00_00", target="m60_44_36_60", offset=[22, 90, 207], dry_run=True)It reports
er_parts_read,matching_filters,outside_targets,to_place,per_target_map,distinct_models, the bounds and centroid of the matching parts in Elden Ring coordinates, and for the models:models_already_imported,models_same_as_game,models_need_import,models_missing_in_erand the first 40 ofmodels_to_import. -
Run it with
dry_run=False. The job runs inside Smithbox, a slice per frame, so the editor keeps drawing. By default the tool waits and pollsport_statusevery 2 seconds until the state isdoneorerror. -
Look at the result (
screenshot,list_objects), thensave_mapeach target map. The tool never saves.
port_er_map parameters
| Parameter | Default | Meaning |
|---|---|---|
target |
none | One map id. Offset positions go straight into that map as its local positions. |
tiles |
none | A list of {"map_id": ..., "center": [x, z]} or [x, y, z]. See below. Give target or tiles, not both. |
er_map |
"m35_00_00_00" |
The Elden Ring map to read. |
offset |
[0, 0, 0] |
Added to each Elden Ring part position. |
box |
none | {"min": [x, y, z], "max": [x, y, z]} in Elden Ring coordinates, before the offset. |
y_min, y_max |
none | Height limits in Elden Ring coordinates, before the offset. |
classes |
["Asset"] |
"Asset" and/or "DummyAsset". Anything else is refused. |
models |
none | Only these Elden Ring model ids. |
limit |
0 (no limit) |
At most this many parts, first in MSB order. |
dry_run |
False |
Report counts only. |
name_models |
False |
Also give each imported model its Elden Ring community name. |
clear_ids |
True |
Clear EntityID and EntityGroupIDs on the new parts. |
wait |
True |
Poll until the job ends. False returns at once. |
wait_timeout |
3600 |
Seconds to wait before returning "still running". |
Tiles. With tiles, each entry gives an m60 tile and its centre in the offset world. A part goes to the tile
whose 256 m square [centre - 128, centre + 128) holds it, and its position is made tile-local by subtracting the
centre. A [x, y, z] centre also subtracts y. Parts outside every tile are counted in outside_targets and not
placed.
Positions are the part positions stored in the Elden Ring MSB plus offset.
port_status
No parameters. Returns the running or last job:
state:importing,placing,done,errorornonemodels_total,models_processed,models_imported_ok,models_failed,failed_models(with reasons),remapped_models(Elden Ring id to the id it got in the project)parts_total,parts_placed,parts_skipped_no_model, andmapswithplanned,placed,skipped,doneper target map- timings,
errorwhen it failed, andundo_stepswhen done
How to tell it worked
port_statussaysdone,parts_placedequalsparts_totalminus the skipped ones, andfailed_modelsis empty.- The parts show in the viewport with textures.
- Each target map is one undo step. One
undoper map takes the port out again. The imported model files stay in the project folder.
What goes wrong
| Message | Cause |
|---|---|
| "Give a target map id, or tiles [{map_id, center}]." | Neither target nor tiles was given. |
| "Give either target or tiles, not both." | Both were given. |
| "No parts match (see the dry_run counts)." | The filters or the tile squares leave nothing. Check offset. |
| "Map ... is not loaded. Call load_map first." | A target map is not loaded. This is checked before anything is copied. |
| "... has no Asset part to use as a template." | The target map has no part of that class. Leave one in. |
| "A port is still running (see port_status)." | Wait for the running job. |
| "Elden Ring has no /map/mapstudio/....msb.dcx." | Wrong er_map id. |
| Parts are skipped | Their model failed to import. failed_models in port_status says why. |
Limits
- Assets only. A ported area has no floor collision of its own beyond what the assets carry, no navmesh and no lights.
- The Elden Ring MSB is read once and kept in memory for the next call with the same
er_map. - A bulk port can import hundreds of models. Imports are copied into the project folder at once, before any save.
In game
Not proven as a whole. From the team's notes on the sewers work (local tests, 2026-11-11), not re-checked here:
- Ported Elden Ring assets on their own ids did draw in game.
- Static assets' collision ignored the MSB scale, so pieces placed at a scale other than 1 had collision of the wrong size until their collision files were rebuilt at that scale.
- Collision inside the ported rooms and textures were still unverified.
Treat anything else as untested until someone writes the result here.