Wiki

Modding

From 2D Tower Wiki
Revision as of 17:50, 6 October 2026 by Gary (talk | contribs) (Categorize for shared dynamic Main Page and navigation groups)
This page was last edited on 6 October 2026, at 17:50.

Modding in 2D Tower uses data-only content packs. Packs can add room variants based on built-in room behaviours, decorative rooms, wallpapers and custom maps. They cannot supply scripts or replace the game's runtime code.

Choose Using mods for installation and save troubleshooting, or Creating mods for the template-to-publishing walkthrough. This page keeps the complete pack format reference.

Create or install a pack

Open Mods → Create on the title screen. Enter a title and description, choose Store, Restaurant, Residential, Office, Decor, Wallpaper or Map, then select Create mod. The game creates a local pack and opens the Edit step. Use Open mods folder to reach its files. Keep the title-derived pack ID stable once saves depend on it; its displayed name can change independently.

For a local mod, place one pack folder inside the game's local mods directory:

user://mods/
└── my_record_store/
    ├── manifest.json
    ├── rooms/
    │   └── record_store.json
    ├── textures/
    │   └── records.png
    ├── i18n/
    │   ├── en_US.json
    │   └── de_DE.json
    └── icon.png

user:// is Godot's per-user data folder. From the title screen, use Mods → Create, then Open mods folder in the Edit step to open the correct location; on a standard Windows installation it is normally %APPDATA%\Godot\app_userdata\2D Tower\mods\. Development builds also discover packs in res://mods/. The game discovers only direct subfolders of these directories that contain manifest.json.

The supplied project examples are examples/mods/example_store, example_restaurant, example_residential, example_office, example_decor, example_wallpaper and example_map. Create copies the selected template into your local mods directory; project examples are not discovered automatically in release builds.

Manifest

manifest.json is at the root of the pack folder. Paths in the manifest are relative to that folder and may not escape it.

{
  "pack_id": "my_record_store",
  "version": "1.0.0",
  "enabled": true,
  "dependencies": ["base"],
  "rooms": ["rooms/record_store.json"],
  "translations": {
    "en_US": "i18n/en_US.json",
    "de_DE": "i18n/de_DE.json"
  }
}
  • pack_id is the pack's permanent identifier. It must start with a lowercase letter and otherwise use only lowercase letters, numbers, periods, underscores and hyphens. Keep it stable after publishing because saves refer to it.
  • version identifies the pack release.
  • save_compatibility_version is a positive integer, defaulting to 1. Save loading requires the recorded compatibility version to match, independently of the release version string. Keep it unchanged for compatible updates; change it when your content breaks the saved-content contract.
  • enabled is optional and sets the initial state for a local pack. The Mods window stores the player's final selection in user://mods.cfg.
  • dependencies lists required pack IDs. Most packs depend on base.
  • rooms, wallpapers and maps list their definition JSON files relative to the pack folder. A pack does not need all three kinds.
  • Optional name, description and author describe the pack in the Mods window. Workshop packs show the item owner as their author.
  • translations is optional. Each key is a locale and each value is a JSON translation file.

Pack folders are scanned in a stable order. Local packs need distinct IDs. Workshop items also use their Workshop item ID, allowing different creators to use the same author-supplied pack ID without colliding. Duplicate effective IDs are rejected; a user pack cannot replace a shipped pack.

Room definitions

Every room JSON file inherits a registered built-in room. The file name supplies the room's local ID unless it has an explicit id. For example, rooms/record_store.json in the my_record_store pack becomes my_record_store:room:record_store. Moving the file to another subfolder does not change that ID.

{
  "extends": "base:room:store",
  "occupancy_mode": "immediate",
  "overrides": {
    "display_name": "Record Store",
    "description": "A specialist shop selling vinyl records.",
    "width": 24,
    "height": 1,
    "entrance_offset": [6, 0],
    "construction_cost": 125000,
    "maintenance_cost": 100,
    "worker_count": 2
  },
  "icon": "icon.png",
  "visual": {
    "texture": "textures/records.png",
    "region": [0, 0, 16, 2],
    "horizontal_frames": 1,
    "vertical_frames": 2,
    "frames": [
      { "variant": 0, "mode": "open", "frame": 0 },
      { "variant": 0, "mode": "closed", "frame": 1 }
    ]
  }
}

extends must name an existing room. The loader makes an independent copy of that parent, so a mod never changes the original room. The supported general overrides are the display name and description, category and palette order, size and entrance, construction/demolition/maintenance costs, worker count, visit duration and custom-entrance setting. Values have to use the required data type; dimensions, coordinates and texture regions are integers.

Depending on the inherited runtime, a room may also use supported profiles such as commercial, residential, stock, garbage, demand and evaluation. Unsupported fields or profiles cause validation to fail rather than being silently ignored. Start with the template for the room type you want to inherit.

Artwork and translations

icon is a PNG path inside the pack. A custom visual uses a texture and region in the form [x, y, width, height], measured in 32 × 128 pixel tile cells, not pixels. The example above selects 512 × 256 pixels. horizontal_frames and vertical_frames split the region into frames; frames maps their indices to cosmetic variants and modes. The store example uses open/closed modes; residential and office artwork use different mappings. Start with the matching template rather than assuming every room uses two open/closed rows. Without a custom visual, the room keeps its parent's artwork, footprint and appearance definitions.

Optional appearances entries define stable cosmetic IDs and a variant matching the visual frame mappings. A custom texture clears inherited appearances unless the mod provides its own entries. Translation files supply localized text; a short appearance display_name_key is scoped automatically to that room's ID.

Wallpaper artwork

Use the Wallpaper template as a working starting point. Wallpaper textures contain a top row of luminance artwork and a bottom row of RGB recoloring masks. Each cell is 32 × 128 pixels, so the complete image is a multiple of 32 pixels wide and exactly 256 pixels high. Up to 64 cells across are supported.

The visual mode is auto_repeat or cap_repeat_cap. The latter needs at least three cells across for the left end, repeating middle and right end. The visual can specify one to three HTML colors, such as "#d99a63", for the recolorable channels. These dimensions and accepted modes are format requirements; construction cost, environment contribution and colors are editable content values.

List wallpaper JSON files under wallpapers in the manifest, for example "wallpapers": ["wallpapers/my_wallpaper.json"].

Custom maps

The Map template provides a playable harbor example. Map packs can define painted scenery, restricted construction cells, street entrances, sky colors, aerial artwork and a subway line. Their objectives and progression can also differ from the built-in maps. List map JSON files under maps in the manifest.

The visual Map Mod Kit is supplied in the project's source checkout at tools/map-mod-kit; this wiki currently provides no separate kit download. The game's Mods → Create → Map template is available for players with only the game. For the visual editor, copy tools/map-mod-kit into your own working folder and import its project.godot in Godot 4.7. Open map.tscn as a separate project. Use its Export Map Mod command to produce a data-only pack; the editor project itself is not the pack to install.

Choose stable lowercase pack and map IDs, edit the title and gameplay settings, paint the map and export. Use the kit's example as a guide to scenery and entrances. Validate the resulting pack in the game's Mods window before publishing it. Map settings and objective plans are customizable, so a modded map need not share the built-in star requirements.

Enable, publish and save

Open Mods on the title screen to enable or disable local packs. Restart the game after installing, removing, enabling, disabling or editing a pack because the content catalog is built at startup.

Steam Workshop packs use the same layout: manifest.json sits at the root of the uploaded folder. Workshop installations stay in Steam's managed directory, not in user://mods. New subscriptions start disabled; enable them in Mods and restart. Use Mods → Create for templates. In Mods → Publish, select a local pack and choose Validate; with Steam running, Upload to Steam Workshop uploads it. New items start private. View on Workshop opens the item page for review and visibility changes. Use a square preview around 512 × 512 pixels and under 1 MB for Workshop compatibility. Its Workshop sidecar file is stored beside the pack folder; keep it to update the same Workshop item later.

Saves record required pack identities, compatibility versions and Workshop IDs. To open a save, keep its required packs installed and enabled with matching save_compatibility_version values and all referenced content IDs available. The game reports missing or incompatible content instead of silently substituting it. A similarly named Workshop item is not a replacement for the original item.