The .dmod format (api 1)

A .dmod is a zip file. The Mod Studio makes it for you; this page is for making or changing mods outside the game, and for knowing exactly what is allowed. The site checks every upload against these rules and repacks it (every file stored, uncompressed, manifest.json first) — the game server reads it without unpacking.

Limits: 25 MB and 2000 files in all, scripts up to 512 KB each, JSON files up to 4 MB, pictures up to 4096 pixels a side (2048 in sprites/).

The files

Path What
manifest.json Required. The mod's card and its settings
server.lua The rules, run by the game server (Scripting)
client.lua The screen, run by each player's game
lua/<name>.lua Modules for require("<name>") (both scripts)
lobby.json The mod's lobby
sprites.json The mod's sprites (new ones, or replacing the game's)
characters/<name>.json Changes to a character
characters/<name>.lua Its own moves, in Lua (api 2)
objects/<name>.json An object: coins, traps, enemies... (api 2)
objects/<name>.lua Its events in Lua (api 2)
maps/<name>.json A map
maps/<name>.png Map pictures: tilesets, backgrounds, art, previews
sprites/<name>.png Sprite strips
sounds/<name>.ogg Sounds and music (Ogg Vorbis). sounds/snd_jump.ogg replaces the game's snd_jump
preview.png The picture on the site (else the first map's preview)
readme.txt Anything you want to say

File names inside the folders: lower case, digits, _ . -. Nothing else is allowed in the package.

manifest.json

{
  "id": "hot_potato",
  "name": "Hot Potato",
  "version": "1.0.0",
  "api": 1,
  "author": "you",
  "description": "Pass the potato before it blows up.",
  "maps": "add",
  "bots": false,
  "settings": [
    {"key": "fuse", "name": "Fuse (seconds)", "type": "int", "default": 20, "min": 5, "max": 120}
  ]
}
Field
id 3-32 characters, a-z 0-9 _ -, starting with a letter or digit. Unique on the site
name 1-40 characters
version major.minor.patch; every upload needs a higher one
api 1, or 2 when the mod has objects (the Mod Studio sets it)
author, description Up to 40 and 1000 characters
maps "add" (the mod's maps join the game's in the vote; the default) or "only"
bots false: the server's bots don't play (default true)
settings Up to 32 options the server host changes. The scripts read them as mod.config.<key>

A setting: key (lower case, unique), name (what the host sees), type and default:

type default also
int a whole number min, max
number a number min, max
bool true / false
text up to 200 characters
choice one of choices choices: a list of texts

Maps: maps/<name>.json

Coordinates are pixels, y going down. The map editor writes all of this; an editor object it adds is ignored by the game.

{
  "name": "Test Hill",
  "description": "Slopes, platforms and springs.",
  "width": 3200, "height": 1024,
  "time": 150,
  "music": "mus_hill", "chase_music": "mus_hill_chase",
  "background": {"image": "maps/sky.png", "color": "#203050", "parallax": 0.3},
  "art": [{"image": "maps/castle.png", "x": 900, "y": 300}],
  "tileset": "maps/tiles.png",
  "tiles": {"data": "2:5,196:0,4:5,196:0"},
  "solids": [[0, 800, 3200, 224]],
  "platforms": [[300, 680, 160]],
  "slopes": [[1072, 672, 128, 128, 1]],
  "objects": [
    {"type": "spawn", "x": 100, "y": 799},
    {"type": "exe_spawn", "x": 3000, "y": 799},
    {"type": "ring", "x": 600, "y": 760},
    {"type": "exit", "x": 1600, "y": 800},
    {"type": "spring_up", "x": 2000, "y": 800}
  ],
  "preview": "maps/preview.png"
}
Field
width, height 480-32768 by 270-8192
name 1-40 characters; description up to 300
time The round's length in seconds, 30-900 (default 180)
music, chase_music A game music (mus_hill, mus_...) or a sound of the mod (sounds/x.ogg)
background image (a picture of the mod or a sprite name), color (#rrggbb), parallax 0-1 (0 stays still, 1 moves with the map)
art Pictures drawn over the background and under the players
tileset, tiles.data 16x16 tiles: the tileset is a picture of tiles, numbered left to right, top to bottom from 0. data covers the map row by row in runs count:value, where value is the tile's number + 1 (0: empty)
solids [x, y, w, h] solid blocks
platforms [x, y, w] one-way platforms
slopes [x, y, w, h, dir]: dir 1 rises to the right, -1 to the left
objects spawn (survivors), exe_spawn, ring, exit (where the big ring can appear), spring_up, spring_left, spring_right; also solid and platform with w / h; and the mod's objects: {"type": "object", "object": "coin", "x": 300, "y": 760} (at most 256)
preview The map's card in the vote

A map needs a spawn, an exe_spawn and an exit; at most 255 rings. Tiles are only pictures: what players stand on is solids, platforms and slopes (the editor makes them from the tile flags when it saves). An exit's y is where the big ring stands (its bottom): on the ground, players run into it. The map's left and right edges are walls; falling off the bottom brings a player back to the nearest spawn, hurt.

sprites.json

{"sprites": {
  "spr_ring": {"image": "sprites/blue_ring.png", "frames": 4, "origin": [8, 8]},
  "potato":   {"image": "sprites/potato.png", "frames": 1, "origin": [16, 16], "speed": 0.2}
}}

A sprite named like one of the game's (spr_ring, spr_tails_idle...) is drawn instead of it and keeps the game's hit box. Other names are new sprites for client.lua (hud.sprite), for map backgrounds, or for characters. frames: a strip left to right (1-256). origin: the point placed on the position. speed: frames per game frame (default: the game sprite's, or 0.25).

characters/<name>.json

{
  "replaces": "tails",
  "name": "Speedy Tails",
  "stats": {"speed": 1.25, "acceleration": 1.2, "jump": 1, "gravity": 1, "damage_taken": 1, "hp": 120},
  "sprites": {"spr_tails_idle": "speedy_idle"}
}

replaces: tails, knuckles, eggman, amy, cream, sally, exe, chaos, exetior, exeller. The stats multiply the character's own (1 = unchanged): speed, acceleration, jump and gravity 0.3-3, damage taken 0-5; hp 10-127 is its starting HP. sprites swaps the character's game sprites for sprites of sprites.json.

objects/<name>.json (api 2)

{
  "sprite": "coin",
  "box": [-8, -8, 16, 16],
  "front": false,
  "vars": {"value": 5}
}

An object the mod's maps place and its scripts make (game.spawn). sprite: a sprite of the mod (sprites.json) or of the game (spr_ring); none: it is not drawn. box: where players touch it, [left, top, width, height] from its x, y. front: drawn in front of the players. solid: "solid" (players stand on it and bump into it) or "platform" (they stand on its top, and jump through it from below); a moving one carries who stands on it. vars: the fields each one starts with (numbers, texts, true / false), as self.<name>.

Its events are in objects/<name>.lua, each a function: create(self), step(self) (60 times a second), touch(self, player), leave(self, player) and destroy(self). They run on the server with the game rules' functions.

lobby.json

{
  "title": "`HOT POTATO",
  "text": "Touch another survivor to pass the potato.",
  "background": "maps/preview.png",
  "music": "mus_waiting"
}

Shown while players wait. title and text up to 300 characters; background a picture of the mod or a sprite; music a game music or a sound of the mod.

Colour codes

Texts (lobby, map names, game.say, hud.text...) take the game's colour codes: ` yellow, @ green, & purple, / blue, | grey, \ red, ~ back to the normal colour.

Checking a package

The Mod Studio's Check runs the same checks as the upload page: open your .dmod with Open a .dmod file and check it there.