Working on Gloomhaven Enhanced

Gloomhaven Enhanced (GHE) is split into different mods that support each other. There’s a base mod called "Enginehaven" that contains the basic engine of the mod. So all the scripts for the scenario engine, the round tracking, campaign manager, etc. It doesn’t contain any actual content, like scenarios, classes or items. Those are added from other mods, so-called content boxes.

Each actual game (Gloomhaven, Frosthaven, Crimson Scales, etc.) is a separate mod that contains such a content box. The box then contains the actual game components for that specific game. Loading the content box into Enginehaven analyzes and unpacks its content into the places where the engine needs them, so the game can be used.

The current state of each mod is stored in a directory inside the mods directory of the repository. A mod in TTS is a JSON file that contains the data of each object in the game, which includes it scripts and content for things like bags and decks. The repository doesn’t store the complete JSON file though. Instead, the JSON file is split into a directory structure, where each object in the mod has its own files that only contains the data for this specific object. This makes it easier to track and update individual objects. It also makes sure that saved data is smaller than it would be in a complete save file.

In the complete save file each object would contain its complete script. Since many objects use the require() syntax to load a specific script, which in turn typically also requires other scripts, TTS needs, a complete, bundled version of the script where each require is replaced with the actual script content. This would lead to lots of redundant scripts. Instead, for each object only the top-level script is saved.

The complete save file that can then be used in TTS can be recreated from this file structure, using a specific tool. To get this tool working, some setup needs to be done first.

Setup

  • Having git installed and a clone of the enhanced repository is already assumed.

  • Install node.js. This is a tool that can execute JavaScript code on your machine without a browser. The tools mentioned above a written in JavaScript (or TypeScript to be more precise) and need node.js to run.

  • Install pnpm. This is a package manager for node.js tools that manages dependencies the tools require.

  • Run pnpm install from the root directory of the mod. This will download all dependencies that the tools need in order to run

Building the mods

In order to build the working mods from the files in the repository,

Repository structure

imports

This directory contains all the scripts and XML files that are used in the various mods.

mods

This directory contains the different mods that we release. Each mod directory contains the extracted mod content inside a content directory. It also contains a package.json, where the scripts are defined that can be run to extract/embed/build and release that mod. Finally, there’s a .ttsrc file. This is a config file that defines the workshop item ids that are used for this mod. It’s used to upload the mod to the Steam workshop via a script.

tools

Contains various tools used. For now this should contain the kpsteam tool to easily upload files to the Steam workshop.

Basic workflow

Whenever there are physical changes on the mod (e.g. adding new object, moving or deleting existing ones, etc.) the mod has to be extracted. This will read the mod’s save file and put its data into this repository by splitting it into multiple files.

When the scripts are changed, a previously extracted save file can be embedded again. This will stitch the split files back together and update the script with the ones currently in the imports directory for all objects, even the ones in containers.

If a mod is ready for release (either the main version, a beta version, or simply the current development version), it can be build and uploaded to the Steam workshop, all without starting TTS itself (Steam with the correct account needs to run, though).

The following sections describe the different commands in more detail. The commands are typically run from the mod’s directory. However, they can also be run from the root directory. Check the package.json file in the root directory for possible aliases, e.g. embed:ghe will embed the GHE mod.

Extracting a mod

Run the command pnpm extract from the mod directory. This will find the save file for this mod on your local TTS save file directory and extract its content. The name of the save file that is looked for is defined inside the .ttsrc file of this mod.

Embedding a mod

Run the command pnpm embed from the mod directory. This will embed a previously extracted save file again and update its scripts with the current versions from imports. It will write the embedded save file to your TTS save file directory if there’s already as save file with the targeted name. If not, it will write the save file to the root directory of the mod. The name of the save file that is looked for is defined inside the .ttsrc file of this mod.

The embedded save file will also be written to dist/Save.json. The command also creates a releasable file inside the dist directory of the mod called Save.bson.

Releasing a mod

To automatically upload the build save file, run the command pnpm release [environment]. Environment defines the target workshop item (e.g. dev, beta or prod). If the parameter is omitted, dev will be the default. Which environments are available and wich workshop id is associated with it, can be found in the .ttsrc file within the mod directory.

Adding new mods

To add a new mod that can be extracted, embedded and releases, add a new directory inside the mods directory. The name should be all lowercase and spaces should be replaced with hyphens. Copy fhe package.json, .ttsrc and .gitignore files from another mod into the new directory.

Inside the package.json, change the name attribute to reflect the name of the mod directory (prefixed with mod, e.g. mod-ghe). You can also update the description field, though it’s currently not used.

Inside the .ttsrc file, change the ids for the different workshop mod versions. You can add as many as you want and delete existing ones. but at least prod and dev should exist, where prod is the main mod and dev is the current development build. A beta version would also be useful for the open beta version of this mod.

To make the command executable from the root directory, also modify the package.json in the root directory. Copy the lines of existing aliases. Replace the part after the colon with the new alias and the part after the -F with the name of the mod that was set as the name inside its package.json.