CrossCode Modding Tutorial

From CCDirectLink
Revision as of 19:40, 26 January 2021 by Dmitmel (talk | contribs) (fix the mentioned nw.js version)

This page contains the steps on how to create your very first CrossCode mod. (header WIP, ask 2767mr)

Installing CCLoader

Due to DRM it is not possible to mod Xbox Game Pass or Microsoft Store versions of the game.

See CCLoader#Installation

Installing NW.js

Requirements

The game uses an outdated version of NW.js, so you might want to use version 0.35.5 to avoid accidentally using features not yet available in CrossCode.

Steps

  1. Open the nwjs-sdk zip
  2. Open the folder so you can see the nw.exe file

  1. Extract/drag all files into the CC installation folder and replace existing files when prompted.
  2. Delete CrossCode.exe
  3. Rename nw.exe to CrossCode.exe
  4. Open the game
  5. Press F12 to open the Chrome DevTools
  6. Click the Console tab
  7. In the top bar, click top
  8. Choose the second entry in the dropdown list
  9. You can now enter commands into the console

Making a mod

Requirements

Steps

  1. Open the CC installation folder
  2. Open assets -> mods
  3. Create a new folder for your mod. In this example, we are going to use myMod
  4. Create a new file called package.json

This file is used to tell CCLoader how to load your mod. It contains the internal name (name), the in-game displayed name (ccmodHumanName), the version number (version) and dependencies (ccmodDependencies). Only name and version are required.

Example package.json

{
  "name": "my-mod",
  "ccmodHumanName": "My Mod",
  "version": "1.0.0"
}
  1. Find a file to modify

In this example we will do a simple palette swap of Lea. You can find her sprites in assets/media/entity/player/move.png

  1. Copy the file to your mod

In order for CCLoader to pick up the file from the mod it needs to be inside the mod folder with the same name as the original. This means that assets/media/entity/player/move.png turns into assets/mods/myMod/assets/media/entity/player/move.png.

Do not publish original CrossCode files in your mod.

  1. Edit the file

In this example I am using Paint.NET to swap Lea's red clothes for green ones:

  1. Restart the game and test your mod

Editing JSON

Often it is not enough to just edit png files to make mods. Changing sizes, making new entities or maps require one to edit or create new JSON files. This guide shows you how to work with JSON files in your mod.

Requirements

New JSON files

Adding new JSON files does not require any special attention. Simply put the file into the correct folder and CCLoader will pick it up automatically.

Existing JSON files

Editing existing JSON files is problematic in a few cases. Now only are these files pretty big but there are also a lot of instances where multiple mods want to modify the same file. In that case simply replacing the entire file doesn’t work.

Instead you can use a mechanism called patches. These are files that only record the changes made to the original file, allowing multiple mods to apply patches to the same file. They work similar to file replacements as they require you to use the same name as the original file. The difference is that they append a .patch to the filename and use special sytanx exmplained in more detail on Patching.

In order to work with JSON files it is recommend to beautify them before using them. You can use beautifier.io to do that for you.

In this example we will make a patch that will increase the damage Lea does. This information can be found in assets/data/players/lea.json. Once beautified one can easily see the value we want to modify.

{
    "character": "main.lea",
    "sheet": "player",
    "headIdx": 0,
    "class": "SPHEROMANCER",
    "stats": {
        "hp": {
            "base": 200,
            "increase": 2000,
            "variance": 0.1
        },
        "attack": {
            "base": 20,
            "increase": 200,
            "variance": 0.9
        },
        ...

Now we want to somehow change stats.attack.base to 200. For that we first create a patch file assets/mods/myMod/assets/data/players/lea.json.patch

🚀 Tip: Most editors will not recognize these files as JSON by default. Almost all popular editors include a feature to manually set which type of file you are currently editing.

First you can begin the file with [] to signal that this file is using the “Patch Step” format:

[

]

Next we insert a step that navigates into the attack object:

{
    "type": "ENTER",
    "index": ["stats", "attack"]
}

Now we can overwride a value:

{
    "type": "SET_KEY",
    "index": "base",
    "content": 200
}

At the end, we navigate back to the root of the document. In this case it is not required but will make future additions a lot easier.

{
    "type": "EXIT",
    "count": 2
}

At the end we end up with this lea.json.patch file:

[{
    "type": "ENTER",
    "index": ["stats", "attack"]
}, {
    "type": "SET_KEY",
    "index": "base",
    "content": 200
}, {
    "type": "EXIT",
    "count": 2
}]

Making a JavaScript mod

Although the game provides a very powerful JSON scripting system it is sometimes required to add new puzzle elements or edit internal workings of existing ones. For this one needs javascript mods.

Requirements

Entry points

In order to load a JavaScript file, there needs to be an entry in the package.json of the mod. There are multiple possible values here that reference different points in time at which a mod is loaded. Furthermore there is an entry called plugin which combines all these entry points.

For example, if we want to double all gained CP points we need to add a script:

{
    "name": "my-mod",
    "ccmodHumanName": "My Mod",
    "version": "1.0.0",
    "plugin": "plugin.js"
}
⚠ If you use entry points other than plugin you should always set "module": true as well.

Mod loading stages

Prestart

This is the entry point you usually want to use. At this point, most of the game code is loaded but almost none of it executed yet. This makes it the perfect chance to change how the internals work.

Preload

At this point none of the game has been loaded yet. This means that while nothing has loaded yet but one can use this to set up libraries or use some JavaScript black magic.

Postload

Here some of the game code has been loaded, however pretty much nothing has been executed yet. Specifically, none of the resources have been been loaded yet, making it possible to intercept and work with them.

Main

This stage, which has been called “main” for legacy reasons, executes code as soon as the title menu start playing. This allows mods to use code that may have not been executed yet in the prestart stage, though it should be avoided is easily possible.

Plugin

While using loading stages directly in the package.json directly executes the code in a script the plugin combines multiple stages at once. Every plugin defines an exported JavaScript class that is used to execute the code.

Since we defined the file as plugin.js above we create a new file assets/mods/myMod/plugin.js:

export default class MyMod {
    prestart() {
        //Prestart code will go in here.
    }
}

The advantage of using plugins over direct stages is that the constructor of the plugin receives an object as argument which can be used to find out which folder the current mod is stored in.

🚀 Tip: A plugin can also be used to write async code in a loading stage, blocking all other mods from loading until it has finished.

Now that we can execute code in the prestart stage, we need to find out how to double the CP points. If we look into the assets/js/game.compiled.js file we can find out that there is a class called sc.PlayerModel which contains a function

public addSkillPoints(points: number, element: number, all: boolean, extra: boolean): void

We now want to manipulate addSkillPoints so that points are doubled. For that we can use the inject function. This is a function that exists on all classes that allows you to add and overwrite existing functions. Furthermore, inside that function you can use this.parent(...) to call the original functon.

We can use this to make a mod that doubles all CP:

export default class MyMod {
    prestart() {
        sc.PlayerModel.inject({
            addSkillPoints(points, element, all, extra) {
                this.parent(points*2, element, all, extra);
            }
        });
    }
}

This example mod can be found on GitHub.[1]

Share your mod

Requirements

Steps

  1. Open your mod folder that contains the package.json file
  2. Select all files/folders needed for the mod
  3. Create a zip archive from these files. On Windows you can do this using right click > send to > zip-archived folder

You can already share this file

  1. Rename the .zip file to .ccmod

This allows other users to simply drag the file into the mods folder and not have to worry about extracting it

Publish on the official list

Since the process of approving a mod for the official list is a bit complicated (and is likely to change in the future) the best way is to:

References