Wiki

Modding: Difference between revisions

From 2D Tower Wiki
This page was last edited on 5 October 2026, at 20:40.
Gary (talk | contribs)
Create modding guide
 
Gary (talk | contribs)
Update mod templates, tile-cell artwork, maps, wallpapers and save compatibility
Line 1: Line 1:
'''Modding''' in 2D Tower uses data-only content packs. A pack can add room variants by inheriting one of the game's built-in room behaviours and changing the supported data fields. Mods cannot include scripts, so they cannot replace game code or add a wholly new runtime behaviour.
'''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.


== Create or install a pack ==
== 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:
For a local mod, place one pack folder inside the game's local mods directory:


Line 18: Line 20:
</pre>
</pre>


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


The example pack at <code>examples/mods/records/</code> is a working reference. To use it locally, copy its whole folder to <code>user://mods/records/</code>; examples are not discovered automatically in release builds.
The supplied project examples are <code>examples/mods/example_store</code>, <code>example_restaurant</code>, <code>example_residential</code>, <code>example_office</code>, <code>example_decor</code>, <code>example_wallpaper</code> and <code>example_map</code>. Create copies the selected template into your local mods directory; project examples are not discovered automatically in release builds.


== Manifest ==
== Manifest ==
Line 40: Line 42:


* '''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.
* '''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 compatible pack revision saved with games. Use a new version when a change would make old saves incompatible.
* '''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 <code>user://mods.cfg</code>.
* '''enabled''' is optional and sets the initial state for a local pack. The '''Mods''' window stores the player's final selection in <code>user://mods.cfg</code>.
* '''dependencies''' lists required pack IDs. Most packs depend on <code>base</code>.
* '''dependencies''' lists required pack IDs. Most packs depend on <code>base</code>.
* '''rooms''' is an ordered list of room-definition JSON files.
* '''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.
* '''translations''' is optional. Each key is a locale and each value is a JSON translation file.


Pack folders are scanned in a stable order. Duplicate IDs are rejected; a user pack cannot replace a shipped pack.
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 ==
== Room definitions ==
Line 68: Line 72:
   "visual": {
   "visual": {
     "texture": "textures/records.png",
     "texture": "textures/records.png",
     "region": [0, 0, 768, 258]
     "region": [0, 0, 16, 2],
    "horizontal_frames": 1,
    "vertical_frames": 2,
    "frames": [
      { "variant": 0, "mode": "open", "frame": 0 },
      { "variant": 0, "mode": "closed", "frame": 1 }
    ]
   }
   }
}
}
Line 75: Line 85:
<code>extends</code> 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.
<code>extends</code> 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 <code>commercial</code>, <code>residential</code>, <code>stock</code>, <code>garbage</code>, <code>demand</code> and <code>evaluation</code>. Unsupported fields or profiles cause validation to fail rather than being silently ignored. The title-screen templates for Store, Restaurant, Residential and Office create valid starting packs for their respective parent rooms.
Depending on the inherited runtime, a room may also use supported profiles such as <code>commercial</code>, <code>residential</code>, <code>stock</code>, <code>garbage</code>, <code>demand</code> and <code>evaluation</code>. 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 ==
== Artwork and translations ==
<code>icon</code> is a PNG path inside the pack. A custom <code>visual</code> uses a texture and <code>region</code> in the form <code>[x, y, width, height]</code>. The selected region contains two equal-height rows: the open appearance first and the closed appearance second. Without a custom visual, the room keeps its parent's artwork, footprint and appearance definitions.
<code>icon</code> is a PNG path inside the pack. A custom <code>visual</code> uses a texture and <code>region</code> in the form <code>[x, y, width, height]</code>, measured in 32 × 128 pixel tile cells, not pixels. The example above selects 512 × 256 pixels. <code>horizontal_frames</code> and <code>vertical_frames</code> split the region into frames; <code>frames</code> 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 <code>appearances</code> entries define stable cosmetic IDs and a <code>variant</code> 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 <code>display_name_key</code> 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 <code>auto_repeat</code> or <code>cap_repeat_cap</code>. 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 <code>"#d99a63"</code>, 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 <code>wallpapers</code> in the manifest, for example <code>"wallpapers": ["wallpapers/my_wallpaper.json"]</code>.
 
== 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 <code>maps</code> in the manifest.
 
If you have the project's Map Mod Kit, copy <code>tools/map-mod-kit</code> into your own working folder and import its <code>project.godot</code> in Godot 4.7. Open <code>map.tscn</code> 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.


Optional <code>appearances</code> entries define stable cosmetic IDs and their zero-based open-row sprite frame. A custom texture clears inherited appearances unless the mod provides its own entries. Translation files supply localized text; a short appearance <code>display_name_key</code> is scoped automatically to that room's ID.
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 rating|star requirements]].


== Enable, publish and save ==
== 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.
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: <code>manifest.json</code> sits at the root of the uploaded folder. Workshop installations stay in Steam's managed directory, not in <code>user://mods</code>. New subscriptions start disabled; enable them in '''Mods''' and restart. The Publish tab can create a template, validate a selected pack folder and publish it privately. Its Workshop sidecar file is stored beside the pack folder; keep it to update the same Workshop item later.
Steam Workshop packs use the same layout: <code>manifest.json</code> sits at the root of the uploaded folder. Workshop installations stay in Steam's managed directory, not in <code>user://mods</code>. 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 the enabled pack IDs, versions and Workshop IDs. To open a save, its required packs must be installed, enabled and at matching versions. The game reports missing, disabled and version-mismatched packs instead of silently substituting different content.
Saves record required pack identities, compatibility versions and Workshop IDs. To open a save, keep its required packs installed and enabled with matching <code>save_compatibility_version</code> 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.


[[Category:Game mechanics]]
[[Category:Game mechanics]]
{{Navbox All}}
{{Navbox All}}

Revision as of 20:40, 5 October 2026

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.

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.

If you have the project's Map Mod Kit, 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.