Slide 1
Slide 1
Welcome to the Map Editor!
You can now create your own mods for Northgard. When you create a new mod, it is saved in local by default and you will be the only one who can test it. To make your mod available for everyone, you will need to upload it to Steam Workshop.


Please ensure your mod is stored in the folder “mods”, located in the root folder of Northgard local files. To open Northgard local files, right click on Northgard in Steam > Properties > Local files > Browse local files.

Each folder in “Northgard/mods” corresponds to a local mod, with organized files as below:

  • map.dat: an edited map.

  • script.hx: a script, which must be associated to an edited map; a script cannot exist without.

  • cdb.diff: the file that modifies all allowed game data.

The folder name is used for your mod name as well.


To create a new map, click on « Create Map » located in this menu.

As you save your map, a folder containing all your mod local files will automatically be generated, as stated above.


Getting started

A script in Northgard is a text file written in Haxe which will be read and interpreted by the game during gameplay. To add a script to your map, simply create a new text file named “script.hx” in your mod folder.

Your script will be an empty file at this point. To obtain some visible some behaviour, you will need to add the following to your file :

function init() {
function regularUpdate(dt : Float) {

The init() function is called each time at the execution of your script. It can be the first time you start a game with your mod, or when you load an ongoing saved game.

If you need to execute a piece of code only at the start of a new game, you can test for state.time to check the passed time. A time of 0 is when the game starts for the first time.

function init() {
      if(state.time == 0){
            // This part will be executed on the first launch only.
      // This part is executed each time the script is loaded.
The regularUpdate(dt : Float) function will be called each 0.5 seconds. You can use it to regularly check conditions related to your own gameplay rules, such as checking if a player reached the conditions required to win a game.
function regularUpdate(dt : Float) {
      if(state.time >= 10){
            me().triggerVictory(VictoryKind.VFame);    // After 10 seconds, we instantly grant a victory by Fame to the main player. 

Variables and data persistency

Variables are values kept in memory for your script to use. You can define them simply inside or outside the functions. Variables defined inside a function are available only in the function, this is called a local variable, while a variable defined outside is available for the whole script, this is called a global variable.
var myInt = 10;        // global variable of type Int initialized at 10
var myFloat = 3.8;    // global variable of type float initialized at 3.8
var myZone;          // global variable of unknown type
function init() {     var myLocalInt = 20;    // local variable of type int initialized at 20     myFloat = 1.;    // We change the value of myFloat to 1;     myZone= getZone(43); // We use the variable of unknown type to save a zone } // Past this point, myLocalInt doesn’t exist anymore
Global variables exists only while the script is executed, during a game. Once the game is closed, all the stored values will be lost. In some cases, we want those variables to be saved with the current game, to get back to it later. This is where data persistency is used.
Each time the game saves the player’s progress, during a manual or an automatic save, the function saveState() is called in the script. This is where you can save some of your variables.
myFloat = 3.8;    // global variable I want to be persistent
var myZone;        // variable with a “var” prefix won’t be restored
function saveState() {     state.scriptProps = {         myFloat : myFloat    // Your variable to save. Ensure the name of the variable is repeated twice here } }

In saveState(), we assign a structure to state.scriptProps. This allows the game to include this structure and its content to the save data.

Be sure to repeat the variable name twice in the structure, else the data won’t be properly loaded in the variable when executing the script. Also, the variables you want to save shouldn’t be prefixed by a var. This is a technical specification for the game to properly locate your variable and restore its value.

Blocking functions and synchronization

Some functions, like ScriptApi’s wait() or moveCamera(), are blocking functions. Which means the rest of your script will stop until those functions have been completed.
function init() {
      var zone = getZone(182);        // get a zone where we added a warrior
      var warrior = pz.getUnit(Unit.Warrior);    // get the warrior
      moveCamera({x:560, y:612}, 0.8); // move the camera at a certain speed toward coordinates [560, 612]
      moveUnit(warrior, 10, 0, true);    // Move warrior by 10 units slowly walking
// Past this point, myLocalInt doesn’t exist anymore
In the above example, we try to move the camera along some warrior, for a small cinematic effect.
Since moveCamera() is blocking, the warrior will move only after the camera finished moving. The @async keyword exists for that. It will allow you to bypass the blocking aspect of the moveCamera() function and execute moveUnit() at the same time, instead of waiting for the camera movement to end.
    @async moveCamera({x:560, y:612}, 0.8); // dont wait for this function to end
    moveUnit(rig, 10, 0, true);
// Or
    @async {    // bypass all blocking functions in the block         moveCamera({x:560, y:612}, 0.8);         moveUnit(rig, 10, 0, true);        }
By default, the compiler first considers all functions as blocking. Because of this, when multiple loops are imbricated as in the example below, it may cause a horrible stack overflow error when executed. To avoid this issue, it is highly recommended you use @sync for your loops. Be careful though, all blocking functions in your @sync loop will be considered as non blocking.
function init(){
      var lookAtZone = getZone(80);
      @sync {
            for(zone in state.zones) {
                for(u in zone.units)
Lastly, you could ask multiple units to move at the same time toward a point, but wait for all of them to finish their move before proceeding. For this, you can use the @split keyword. @split will execute multiple blocks of code and wait for all of them to finish before continuing to execute the code.
function init(){
      var zone = getZone(152);
      var rig = zone.getUnit(Unit.Hero09);
      var brand = zone.getUnit(Unit.Hero07);
      var svarn = zone.getUnit(Unit.Hero08);
    @split[         moveUnit(rig, 10, 0, true), // rig move slowly walking         {             wait(1.);             moveUnit(svarn, 10, 0, false); // svarn is late and hurry to join his friends         },         {             wait(0.5);             moveUnit(brand, 10, 0, true); // brand walk after waiting a bit         } ]; moveCamera(554, 257, 0.08); // The camera will pan once svarn start moving }

Northgard Editor

To edit your scripts, you can use any text editor, but to benefit from features such as the syntaxic coloration and error check, you are provided with Northgard Editor, a subset of the tool used to develop Northgard. You can find it in your Northgard install folder.

To edit your script with Northgard Editor, start “Editor.exe” and drag and drop your script file in the editor window. It will check everything you are writing. If your code contains invalid syntax or unauthorized functions, the editor will highlight it in red and will display an error message.

Don’t forget to save your changes with the “Ctrl + S” shortcut key once done !

For more information

You can find a script file “script.hx” summarizing the above in the folder Northgard/NGEditor/res. You can simply past it in your mod folder and modify it with Northgard Editor to your suit needs.

You’ll find the complete online script documentation by clicking on “Documentation” in Northgard Editor or by clicking on this link.

If you’d rather go for our local version, open Northgard/NGEditor/documentation/index.html in your preferred browser.


You can find a detailed explanation on how to script for multiplayer Multiplayer Script by following this link.


Open Northgard Editor. To create a .diff file and modify your mod data, click on Database > Diff > Create. Save the file in your mod folder under the name “cdb.diff”. Once your file is created, click on Database > Diff > Load to edit it.

When a .diff file is loaded in Northgard Editor, any editable field you change will be added to the file. Be cautious, as an auto save system is triggered for each change you make. Press Ctrl + Z to cancel your last action.


Satisfied with your mod? You need to test it before releasing it on Steam Workshop. In the Single “New Game” menu, select your local mod and start a game. You can also come back to your game later by saving and loading it as you would normally.

Once you tested and verified your mod function properly, upload it on Steam Workshop using the “Upload Mod” menu.


To add a mod preview image in the Steam Workshop, add a file named « preview.jpg » in your local mod folder. This preview will sync next time you upload your mod on the worskhop


You will find the Northgard Editor here: Northgard/NGEditor/Editor.exe

Right now, the Northgard Editor tool is only available on PC.


Create your translation

You can now make your own translations of the game. For that, you’ll need to retrieve the english translation files at the following links :

(Right click and download)

Once you have downloaded the files, follow these steps to create your translation :

  • Create a “langs” folder into your Northgard game folder.

  • Create a folder into langs with the name you want to give your translation.

  • Save texts.xml and export.xml into your new translation folder.

  • Edit texts.xml and export.xml to replace the english sentences with the translation you want, then save them.

Now that your translation is ready, simply start Northgard and go to the ingame options. In the language selection box, you will see your folder name at the end of the list. Select it and ensure the texts are translated as you intended.

Plural and lang specifics

Some languages have entirely different words between singular and plural. For such, each item name in the export.xml can be associated with a specific name for plural, nominative, dative and such with <> markup.

Below, the english version.

    <desc>[Food] is necessary to feed your clan. Stock up on food before winter. Avoid starvation at all costs.</desc>
    <langs.plural>Food</langs.plural> // The plural name for Food. This will ommit the ‘s’ which is automatically added otherwise.

And the russian version.

    <desc>[Food] необходима, чтобы прокормить клан. Запасайте еду на зиму и избегайте голода любой ценой.</desc>

Install a translation

To install a translation, simply download the translation folder you wish to use and save it under northgard/langs/. If the translation works properly, you will see it at the end of the Language selection list. (See above.)


  • “Resources” tab only shows a “No longer exists” notification.

    • Click on Project > Open and select the NGEditor folder contained in your game local files.

  • I’m trying to open a .diff file but nothing happens.

    • Click on Database > View. It should be displayed now.

  • I’ve just updated a mod on the Steam Workshop, I’ve changed the Mod kind but I still see the “old version” in the upload menu.

    • In case you have subscribed to your own mod, a self-resolving conflict may occur between the Steam Workshop information and your outdated downloaded mod.

©Copyright 2016-2021 Shiro Unlimited and Shiro Games.

The Northgard name and logo are trademarks of Shiro Games and may be registered trademarks in certain countries. All rights reserved.


All our developers can be reached directly on our Discord or by email at