CrossCode Modding Tutorial: Difference between revisions
Ported 2767mr's tutorial. |
m fix the mentioned nw.js version |
||
Line 14: | Line 14: | ||
* [https://nwjs.io NW.js SDK zip] | * [https://nwjs.io NW.js SDK zip] | ||
⚠ '''The game uses an outdated version of NW.js, so you might want to use version <code>0. | ⚠ '''The game uses an outdated version of NW.js, so you might want to use version <code>0.35.5</code> to avoid accidentally using features not yet available in CrossCode.''' | ||
== Steps == | == Steps == |
Revision as of 19:40, 26 January 2021
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.
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
- Open the nwjs-sdk zip
- Open the folder so you can see the
nw.exe
file
- Extract/drag all files into the CC installation folder and replace existing files when prompted.
- Delete
CrossCode.exe
- Rename
nw.exe
toCrossCode.exe
- Open the game
- Press F12 to open the Chrome DevTools
- Click the
Console
tab - In the top bar, click
top
- Choose the second entry in the dropdown list
- You can now enter commands into the console
Making a mod
Requirements
Steps
- Open the CC installation folder
- Open
assets
->mods
- Create a new folder for your mod. In this example, we are going to use
myMod
- 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"
}
- 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
- 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.
- Edit the file
In this example I am using Paint.NET to swap Lea's red clothes for green ones:
- 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]
Requirements
Steps
- Open your mod folder that contains the
package.json
file - Select all files/folders needed for the mod
- 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
- 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:
- Publish your source code on GitHub
- Make sure you have a correct version number
- Create a Github Release - you can upload your .ccmod file there
- Message (an admin) on the CrossCode Modding Discord to add your mod to the list