Scripting Capabilities

Porymap is extensible via scripting capabilities. This allows the user to write custom JavaScript (technically, ECMAScript) files to support enhanced workflows, without having to fork Porymap itself. While the possibilities are endless, some useful examples of scripting might be:

  • Toggle Day/Night Palettes

  • Custom Map Painting Brushes

  • Detect Tile Errors

  • Show Diagonistic Information

  • Procedurally Generated Maps

  • Randomize Grass Patterns

Writing a Custom Script

Let’s write a custom script that will randomize grass patterns when the user is editing the map. This is useful, since it’s cumbersome to manually add randomness to grass patches. With the custom script, it will happen automatically. Whenever the user paints a grass tile onto the map, the script will overwrite the tile with a random grass tile instead.

First, create a new script file called my_script.js–place it in the project directory (e.g. pokefirered/).

Next, open the Porymap project config file, porymap.project.cfg, in the project directory. Add the script file to the custom_scripts configuration value. Multiple script files can be loaded by separating the filepaths with a comma.

custom_scripts=my_script.js

Now that Porymap is configured to load the script file, let’s write the actual code that will power the grass-randomizer. Scripts have access to several “callbacks” for events that occur while Porymap is running. This means our script can define functions for each of these callbacks. We’re interested in the onBlockChanged() callback, since we want our script to take action whenever a user paints a block on the map.

// Porymap callback when a block is painted.
export function onBlockChanged(x, y, prevBlock, newBlock) {
    // Grass-randomizing logic goes here.
}

It’s very important to remember to export the callback functions in the script. Otherwise, Porymap will not be able to execute them.

In addition to the callbacks, Porymap also supports a scripting API so that the script can interact with Porymap in interesting ways. For example, a script can change a block or add overlay text on the map. Since we want to paint random grass tiles, we’ll be using the map.setMetatileId() function. Let’s fill in the rest of the grass-randomizing code.

function randInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min)) + min;
}

// These are the grass metatiles in pokefirered.
const grassTiles = [0x8, 0x9, 0x10, 0x11];

// Porymap callback when a block is painted.
export function onBlockChanged(x, y, prevBlock, newBlock) {
    // Check if the user is painting a grass tile.
    if (grassTiles.indexOf(newBlock.metatileId) != -1) {
        // Choose a random grass tile and paint it on the map.
        const i = randInt(0, grassTiles.length);
        map.setMetatileId(x, y, grassTiles[i]);
    }
}

Let’s test the script out by re-launching Porymap. If we try to paint grass on the map, we should see our script inserting a nice randomized grass pattern.

Grass-Randomizing Script

Grass-Randomizing Script

Registering Script Actions

The grass-randomizer script above happens implicitly when the user paints on the map. However, other times we probably want to call the custom script on demand. One of the API functions Porymap provides is the ability to trigger scripting functions from the Tools menu, or a keyboard shortcut. To do this, we will usually want to register the action when the project loads. Here is an example script where some custom actions are registered.

function applyNightTint() {
    // Apply night palette tinting...
}

// Porymap callback when project is opened.
export function onProjectOpened(projectPath) {
map.registerAction("applyNightTint", "View Night Tint", "T")
}

Then, to trigger the applyNightTint() function, we could either click Tools -> View Night Tint or use the T keyboard shortcut.

Now that we have an overview of how to utilize Porymap’s scripting capabilities, the entire scripting API is documented below.

Scripting API

Callbacks

onProjectOpened(projectPath)

Called when Porymap successfully opens a project.

Arguments
  • projectPath (string) – the directory path of the opened project

onProjectClosed(projectPath)

Called when Porymap closes a project. For example, this is called when opening a different project.

Arguments
  • projectPath (string) – the directory path of the closed project

onMapOpened(mapName)

Called when a map is opened.

Arguments
  • mapName (string) – the name of the opened map

onBlockChanged(x, y, prevBlock, newBlock)

Called when a block is changed on the map. For example, this is called when a user paints a new tile or changes the collision property of a block.

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

  • prevBlock (object) – the block’s state before it was modified. The object’s shape is {metatileId, collision, elevation, rawValue}

  • newBlock (object) – the block’s new state after it was modified. The object’s shape is {metatileId, collision, elevation, rawValue}

Functions

All scripting functions are callable via the global map object.

Map Editing Functions

The following functions are related to editing the map’s blocks or retrieving information about them.

map.getBlock(x, y)

Gets a block in the currently-opened map.

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

Returns {metatileId, collision, elevation, rawValue}

the block object

map.setBlock(x, y, metatileId, collision, elevation, forceRedraw = true, commitChanges = true)

Sets a block in the currently-opened map.

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

  • metatileId (number) – the metatile id of the block

  • collision (number) – the collision of the block (0 = passable, 1 = impassable)

  • elevation (number) – the elevation of the block

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.getMetatileId(x, y)

Gets the metatile id of a block in the currently-opened map.

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

Returns number

the metatile id of the block

map.setMetatileId(x, y, metatileId, forceRedraw = true, commitChanges = true)

Sets the metatile id of a block in the currently-opened map.

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

  • metatileId (number) – the metatile id of the block

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.getCollision(x, y)

Gets the collision of a block in the currently-opened map. (0 = passable, 1 = impassable)

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

Returns number

the collision of the block

map.setCollision(x, y, collision, forceRedraw = true, commitChanges = true)

Sets the collision of a block in the currently-opened map. (0 = passable, 1 = impassable)

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

  • collision (number) – the collision of the block

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.getElevation(x, y)

Gets the elevation of a block in the currently-opened map.

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

Returns number

the elevation of the block

map.setElevation(x, y, elevation, forceRedraw = true, commitChanges = true)

Sets the elevation of a block in the currently-opened map.

Arguments
  • x (number) – x coordinate of the block

  • y (number) – y coordinate of the block

  • elevation (number) – the elevation of the block

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.setBlocksFromSelection(x, y, forceRedraw = true, commitChanges = true)

Sets blocks on the map using the user’s current metatile selection.

Arguments
  • x (number) – initial x coordinate

  • y (number) – initial y coordinate

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.bucketFill(x, y, metatileId, forceRedraw = true, commitChanges = true)

Performs a bucket fill of a metatile id, starting at the given coordinates.

Arguments
  • x (number) – initial x coordinate

  • y (number) – initial y coordinate

  • metatileId (number) – metatile id to fill

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.bucketFillFromSelection(x, y, forceRedraw = true, commitChanges = true)

Performs a bucket fill using the user’s current metatile selection, starting at the given coordinates.

Arguments
  • x (number) – initial x coordinate

  • y (number) – initial y coordinate

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.magicFill(x, y, metatileId, forceRedraw = true, commitChanges = true)

Performs a magic fill of a metatile id, starting at the given coordinates.

Arguments
  • x (number) – initial x coordinate

  • y (number) – initial y coordinate

  • metatileId (number) – metatile id to magic fill

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.magicFillFromSelection(x, y, forceRedraw = true, commitChanges = true)

Performs a magic fill using the user’s current metatile selection, starting at the given coordinates.

Arguments
  • x (number) – initial x coordinate

  • y (number) – initial y coordinate

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.shift(xDelta, yDelta, forceRedraw = true, commitChanges = true)

Performs a shift on the map’s blocks.

Arguments
  • xDelta (number) – number of blocks to shift horizontally

  • yDelta (number) – number of blocks to shift vertically

  • forceRedraw (boolean) – Force the map view to refresh. Defaults to true. Redrawing the map view is expensive, so set to false when making many consecutive map edits, and then redraw the map once using map.redraw().

  • commitChanges (boolean) – Commit the changes to the map’s edit/undo history. Defaults to true. When making many related map edits, it can be useful to set this to false, and then commit all of them together with map.commit().

map.getDimensions()

Gets the dimensions of the currently-opened map.

Returns {width, height}

the dimensions of the map

map.getWidth()

Gets the width of the currently-opened map.

Returns number

the width of the map

map.getHeight()

Gets the height of the currently-opened map.

Returns number

the height of the map

map.setDimensions(width, height)

Sets the dimensions of the currently-opened map.

Arguments
  • width (number) – width in blocks

  • height (number) – height in blocks

map.setWidth(width)

Sets the width of the currently-opened map.

Arguments
  • width (number) – width in blocks

map.setHeight()

Sets the height of the currently-opened map.

Arguments
  • height (number) – height in blocks

map.redraw()

Redraws the entire map area. Useful when delaying map redraws using forceRedraw = false in certain map editing functions.

map.commit()

Commits any uncommitted changes to the map’s edit/undo history. Useful when delaying commits using commitChanges = false in certain map editing functions.

Map Overlay Functions

The following functions are related to an overlay that is drawn on top of the map area. Text, images, and shapes can be drawn using these functions.

map.clearOverlay()

Clears and erases all overlay items that were previously-added to the map.

map.addText(text, x, y, color = "#000000", size = 12)

Adds a text item to the overlay.

Arguments
  • text (string) – the text to display

  • x (number) – the x pixel coordinate of the text

  • y (number) – the y pixel coordinate of the text

  • color (string) – the color of the text. Can be specified as “#RRGGBB” or “#AARRGGBB”. Defaults to black.

  • size (number) – the font size of the text. Defaults to 12.

map.addRect(x, y, width, height, color = "#000000")

Adds a rectangle outline item to the overlay.

Arguments
  • x (number) – the x pixel coordinate of the rectangle’s top-left corner

  • y (number) – the y pixel coordinate of the rectangle’s top-left corner

  • width (number) – the pixel width of the rectangle

  • height (number) – the pixel height of the rectangle

  • color (string) – the color of the rectangle. Can be specified as “#RRGGBB” or “#AARRGGBB”. Defaults to black.

map.addFilledRect(x, y, width, height, color = "#000000")

Adds a filled rectangle item to the overlay.

Arguments
  • x (number) – the x pixel coordinate of the rectangle’s top-left corner

  • y (number) – the y pixel coordinate of the rectangle’s top-left corner

  • width (number) – the pixel width of the rectangle

  • height (number) – the pixel height of the rectangle

  • color (string) – the color of the rectangle. Can be specified as “#RRGGBB” or “#AARRGGBB”. Defaults to black.

map.addImage(x, y, filepath)

Adds an image item to the overlay.

Arguments
  • x (number) – the x pixel coordinate of the image’s top-left corner

  • y (number) – the y pixel coordinate of the image’s top-left corner

  • filepath (string) – the image’s filepath

Tileset Functions

The following functions are related to tilesets and their palettes. The functions with “preview” in their name operate on a “fake” version of the palette colors. This means that changing these “preview” colors won’t affect the actual tileset colors in the project. A good use of the “preview” palettes would be Day/Night tints, for example.

map.getPrimaryTilesetPalettePreview(paletteIndex)

Gets a palette from the primary tileset of the currently-opened map.

Arguments
  • paletteIndex (number) – the palette index

Returns array

array of colors. Each color is a 3-element RGB array

map.setPrimaryTilesetPalettePreview(paletteIndex, colors)

Sets a palette in the primary tileset of the currently-opened map. This will NOT affect the true underlying colors–it only displays these colors in the map-editing area of Porymap.

Arguments
  • paletteIndex (number) – the palette index

  • colors (array) – array of colors. Each color is a 3-element RGB array

map.getPrimaryTilesetPalettesPreview()

Gets all of the palettes from the primary tileset of the currently-opened map.

Returns array

array of arrays of colors. Each color is a 3-element RGB array

map.setPrimaryTilesetPalettesPreview(palettes)

Sets all of the palettes in the primary tileset of the currently-opened map. This will NOT affect the true underlying colors–it only displays these colors in the map-editing area of Porymap.

Arguments
  • palettes (array) – array of arrays of colors. Each color is a 3-element RGB array

map.getSecondaryTilesetPalettePreview(paletteIndex)

Gets a palette from the secondary tileset of the currently-opened map.

Arguments
  • paletteIndex (number) – the palette index

Returns array

array of colors. Each color is a 3-element RGB array

map.setSecondaryTilesetPalettePreview(paletteIndex, colors)

Sets a palette in the secondary tileset of the currently-opened map. This will NOT affect the true underlying colors–it only displays these colors in the map-editing area of Porymap.

Arguments
  • paletteIndex (number) – the palette index

  • colors (array) – array of colors. Each color is a 3-element RGB array

map.getSecondaryTilesetPalettesPreview()

Gets all of the palettes from the secondary tileset of the currently-opened map.

Returns array

array of arrays of colors. Each color is a 3-element RGB array

map.setSecondaryTilesetPalettesPreview(palettes)

Sets all of the palettes in the secondary tileset of the currently-opened map. This will NOT affect the true underlying colors–it only displays these colors in the map-editing area of Porymap.

Arguments
  • palettes (array) – array of arrays of colors. Each color is a 3-element RGB array

map.getPrimaryTilesetPalette(paletteIndex)

Gets a palette from the primary tileset of the currently-opened map.

Arguments
  • paletteIndex (number) – the palette index

Returns array

array of colors. Each color is a 3-element RGB array

map.setPrimaryTilesetPalette(paletteIndex, colors)

Sets a palette in the primary tileset of the currently-opened map. This will permanently affect the palette and save the palette to disk.

Arguments
  • paletteIndex (number) – the palette index

  • colors (array) – array of colors. Each color is a 3-element RGB array

map.getPrimaryTilesetPalettes()

Gets all of the palettes from the primary tileset of the currently-opened map.

Returns array

array of arrays of colors. Each color is a 3-element RGB array

map.setPrimaryTilesetPalettes(palettes)

Sets all of the palettes in the primary tileset of the currently-opened map. This will permanently affect the palettes and save the palettes to disk.

Arguments
  • palettes (array) – array of arrays of colors. Each color is a 3-element RGB array

map.getSecondaryTilesetPalette(paletteIndex)

Gets a palette from the secondary tileset of the currently-opened map.

Arguments
  • paletteIndex (number) – the palette index

Returns array

array of colors. Each color is a 3-element RGB array

map.setSecondaryTilesetPalette(paletteIndex, colors)

Sets a palette in the secondary tileset of the currently-opened map. This will permanently affect the palette and save the palette to disk.

Arguments
  • paletteIndex (number) – the palette index

  • colors (array) – array of colors. Each color is a 3-element RGB array

map.getSecondaryTilesetPalettes()

Gets all of the palettes from the secondary tileset of the currently-opened map.

Returns array

array of arrays of colors. Each color is a 3-element RGB array

map.setSecondaryTilesetPalettes(palettes)

Sets all of the palettes in the secondary tileset of the currently-opened map. This will permanently affect the palettes and save the palettes to disk.

Arguments
  • palettes (array) – array of arrays of colors. Each color is a 3-element RGB array

map.getPrimaryTileset()

Gets the name of the primary tileset for the currently-opened map.

Returns string

primary tileset name

map.setPrimaryTileset(tileset)

Sets the primary tileset for the currently-opened map.

Arguments
  • tileset (string) – the tileset name

map.getSecondaryTileset()

Gets the name of the secondary tileset for the currently-opened map.

Returns string

secondary tileset name

map.setSecondaryTileset(tileset)

Sets the secondary tileset for the currently-opened map.

Arguments
  • tileset (string) – the tileset name

Settings Functions

The following functions are related to settings.

map.getGridVisibility()

Gets the visibility of the map grid overlay.

Returns boolean

grid visibility

map.setGridVisibility(visible)

Sets the visibility of the map grid overlay.

Arguments
  • visible (boolean) – grid visibility

map.getBorderVisibility()

Gets the visibility of the map’s border.

Returns boolean

border visibility

map.setBorderVisibility(visible)

Sets the visibility of the map’s border.

Arguments
  • visible (boolean) – border visibility

map.getSmartPathsEnabled()

Gets the toggle state of smart paths.

Returns boolean

smart paths enabled

map.setSmartPathsEnabled(enabled)

Sets the toggle state of smart paths.

Arguments
  • enabled (boolean) – smart paths enabled

Utility Functions

These are some miscellaneous functions that can be very useful when building custom scripts.

map.registerAction(functionName, actionName, shortcut = "")

Registers a JavaScript function to an action that can be manually triggered in Porymap’s Tools menu. Optionally, a keyboard shortcut (e.g. "Ctrl+P") can also be specified, assuming it doesn’t collide with any existing shortcuts used by Porymap.

Arguments
  • functionName (string) – name of the JavaScript function

  • actionName (string) – name of the action that will be displayed in the Tools menu

  • shortcut (string) – optional keyboard shortcut

map.setTimeout(func, delayMs)

This behaves essentially the same as JavaScript’s setTimeout() that is used in web browsers or NodeJS. The func argument is a JavaScript function (NOT the name of a function) which will be executed after a delay. This is useful for creating animations or refreshing the overlay at constant intervals.

Arguments
  • func (function) – a JavaScript function that will be executed later

  • delayMs (number) – the number of milliseconds to wait before executing func

map.log(message)

Logs a message to the Porymap log file. This is useful for debugging custom scripts.

Arguments
  • message (string) – the message to log