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 require
s 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
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 apackage.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
.