├── images ├── nwjsRoot.png ├── leaRecolor.png ├── rootFolder.png ├── ccloaderRoot.png └── leaRecolored.png ├── example ├── assets │ ├── media │ │ └── entity │ │ │ └── player │ │ │ └── move.png │ └── data │ │ └── player │ │ └── lea.json.patch ├── plugin.js └── ccmod.json ├── readme.md ├── installingCCLoader.md ├── findingCrossCode.md ├── installingNWJS.md ├── publishMod.md ├── LICENSE ├── makingAMod.md ├── editingJSON.md └── javascriptMod.md /images/nwjsRoot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCDirectLink/CrossCode-Modding-Tutorial/HEAD/images/nwjsRoot.png -------------------------------------------------------------------------------- /images/leaRecolor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCDirectLink/CrossCode-Modding-Tutorial/HEAD/images/leaRecolor.png -------------------------------------------------------------------------------- /images/rootFolder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCDirectLink/CrossCode-Modding-Tutorial/HEAD/images/rootFolder.png -------------------------------------------------------------------------------- /images/ccloaderRoot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCDirectLink/CrossCode-Modding-Tutorial/HEAD/images/ccloaderRoot.png -------------------------------------------------------------------------------- /images/leaRecolored.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCDirectLink/CrossCode-Modding-Tutorial/HEAD/images/leaRecolored.png -------------------------------------------------------------------------------- /example/assets/media/entity/player/move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CCDirectLink/CrossCode-Modding-Tutorial/HEAD/example/assets/media/entity/player/move.png -------------------------------------------------------------------------------- /example/assets/data/player/lea.json.patch: -------------------------------------------------------------------------------- 1 | [{ 2 | "type": "ENTER", 3 | "index": ["stats", "attack"] 4 | }, { 5 | "type": "SET_KEY", 6 | "index": "base", 7 | "content": 200 8 | }, { 9 | "type": "EXIT", 10 | "count": 2 11 | }] -------------------------------------------------------------------------------- /example/plugin.js: -------------------------------------------------------------------------------- 1 | export default class MyMod { 2 | prestart() { 3 | sc.PlayerModel.inject({ 4 | addSkillPoints(points, element, all, extra) { 5 | this.parent(points*2, element, all, extra); 6 | } 7 | }); 8 | } 9 | } -------------------------------------------------------------------------------- /example/ccmod.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "my-mod", 3 | "version": "1.0.0", 4 | "title": "My Mod", 5 | "description": "Example mod", 6 | "repository": "https://github.com/CCDirectLink/CrossCode-Modding-Tutorial", 7 | "tags": ["fun"], 8 | "authors": ["my_nick"], 9 | "icons": { 10 | "24": "icon/icon.png" 11 | }, 12 | "dependencies": { 13 | "crosscode": ">=1.4.0" 14 | }, 15 | "plugin": "plugin.js" 16 | } 17 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [![Discord Server](https://img.shields.io/discord/382339402338402315.svg?label=Discord%20Server)](https://discord.gg/3Xw69VjXfW) 2 | # CrossCode Modding Tutorial 3 | 4 | * [Finding the CrossCode installation folder](./findingCrossCode.md) 5 | * [Installing CCLoader](./installingCCLoader.md) 6 | * [Installing NW.js](./installingNWJS.md) 7 | * [Making a mod](./makingAMod.md) 8 | * [Editing JSON](./editingJSON.md) 9 | * [Making a JavaScript mod](./javascriptMod.md) 10 | * [Share your mod](./publishMod.md) 11 | -------------------------------------------------------------------------------- /installingCCLoader.md: -------------------------------------------------------------------------------- 1 | # Installing the modloader (CCLoader) 2 | 3 | | :warning: Due to DRM it is not possible to mod XBox Game Pass or Microsoft Store versions of the game. | 4 | |---| 5 | 6 | ## Requirements 7 | 8 | * [Finding the CrossCode installation folder](./findingCrossCode.md) 9 | * [CCLoader](https://github.com/CCDirectLink/CCLoader/releases/latest) (Download `Source code (zip)`) 10 | 11 | ## Steps 12 | 13 | 1. Open the downloaded zip 14 | 2. Open the folder inside the zip so that you can see the `package.json` file: 15 | 16 | ![Example of package.json](./images/ccloaderRoot.png "Example of package.json") 17 | 18 | 3. Extract/drag all these files into the [CrossCode installation folder](./findingCrossCode.md) 19 | 4. Should you be asked to override files, choose `yes` -------------------------------------------------------------------------------- /findingCrossCode.md: -------------------------------------------------------------------------------- 1 | # Finding the CrossCode installation folder 2 | 3 | 4 | | :warning: Due to DRM it is not possible to mod XBox Game Pass or Microsoft Store versions of the game. | 5 | |---| 6 | 7 | The installation folder is contains these files: 8 | 9 | ![CrossCode root folder](./images/rootFolder.png "CrossCode root folder") 10 | 11 | ## Steam 12 | 13 | In order to open the installation folder through Steam you can follow these steps: 14 | 15 | 1. Go to the Steam library 16 | 2. On the left side, right click on CrossCode 17 | 3. Click on `Properties` 18 | 4. Choose the `Local Files` tab 19 | 5. Click `Browse Local Files...` and the folder should open 20 | 21 | ### Video 22 | 23 | [![How to Find Your Local Game Files on Steam the Easy Way](http://img.youtube.com/vi/L_OiijviEyM/0.jpg)](https://youtu.be/L_OiijviEyM) 24 | -------------------------------------------------------------------------------- /installingNWJS.md: -------------------------------------------------------------------------------- 1 | # Installing the Developer Tools (NW.js SDK) 2 | 3 | ## Requirements 4 | 5 | * [Finding the CrossCode installation folder](./findingCrossCode.md) 6 | * [NW.js SDK](https://nwjs.io/) (Download `SDK`) 7 | 8 | | :warning: The game uses an outdated version of NW.js so you might want to use the version [0.35.5](https://dl.nwjs.io/v0.35.5/nwjs-sdk-v0.35.5-win-x64.zip) to avoid accidentally using features not yet available in CrossCode.| 9 | |---| 10 | 11 | ## Steps 12 | 13 | 1. Open the nwjs-sdk zip 14 | 2. Open the folder so that you can see the `nw.exe` file: 15 | 16 | ![NW.js folder](./images/nwjsRoot.png "NW.js folder") 17 | 18 | 3. Extract/drag all files into [the CrossCode installation folder](./findingCrossCode.md) (replace existing files) 19 | 4. Delete `CrossCode.exe` 20 | 5. Rename `nw.exe` to `CrossCode.exe` 21 | 6. Open the game 22 | 7. Press F12 to open the DevTools 23 | 8. Choose the `Console` tab 24 | 9. In the top bar, click `top` 25 | 10. Choose the second entry of the dropdown list 26 | 11. You can now enter commands into the white area below 27 | -------------------------------------------------------------------------------- /publishMod.md: -------------------------------------------------------------------------------- 1 | # Share a mod 2 | 3 | ## Requirements 4 | 5 | * [Making a mod](./makingAMod.md) 6 | 7 | ## Steps 8 | 9 | 1. Open your mod folder that contains the `package.json` file 10 | 2. Select all files/folders needed for the mod 11 | 3. Create a zip archive from these files. On Windows you can do this using right click > send to > zip-archived folder 12 | 13 | You can already share this file 14 | 15 | 4. Rename the .zip file to .ccmod 16 | 17 | This allows other users to simply drag the file into the mods folder and not have to worry about extracting it 18 | 19 | ## Publish on the official list 20 | 21 | 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: 22 | * Publish your source code on [Github](https://github.com/) 23 | * Make sure you have a correct version number 24 | * Create a [Github Release](https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/managing-releases-in-a-repository) - you can upload your .ccmod file there 25 | * Message (an admin) on the [CrossCode Modding Discord](https://discord.gg/3Xw69VjXfW) to add your mod to the list 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /makingAMod.md: -------------------------------------------------------------------------------- 1 | # Making a mod 2 | 3 | ## Requirements 4 | 5 | * [Installing CCLoader](./installingCCLoader.md) 6 | * [Finding the CrossCode installation folder](./findingCrossCode.md) 7 | 8 | ## Steps 9 | 10 | 1. Open [the CrossCode installation folder](./findingCrossCode.md) 11 | 2. Open `assets` -> `mods` 12 | 3. Create a new folder for your mod. In this example we are going to use `myMod` 13 | 4. Create a new file called `package.json` 14 | 15 | This file is used to tell CCLoader how to load your mod. It contains the internal name (`name`) the displayed name (`ccmodHumanName`), versions (`version`) and dependencies (`ccmodDependencies`). Only `name` and `version` are required. 16 | 17 | ### Example `package.json` 18 | ```json 19 | { 20 | "name": "my-mod", 21 | "ccmodHumanName": "My Mod", 22 | "version": "1.0.0" 23 | } 24 | ``` 25 | 26 | 5. Find a file to modify 27 | 28 | In this example we will do a simple palette swap of Lea. You can find her sprites in `assets/media/entity/player/move.png`. 29 | 30 | 6. Copy the file to your mod 31 | 32 | 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`. 33 | 34 | | :warning: Do not publish original CrossCode files in your mod | 35 | |---| 36 | 37 | 7. Edit the file 38 | 39 | In this example I am using Paint.net to swap Lea's red clothes for green ones: 40 | 41 | ![Recolor example](./images/leaRecolor.png "Recolor example") 42 | 43 | 8. Restart the game and test your mod 44 | 45 | ![Recolor result](./images/leaRecolored.png "Recolor result") -------------------------------------------------------------------------------- /editingJSON.md: -------------------------------------------------------------------------------- 1 | # Editing JSON 2 | 3 | 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. 4 | 5 | ## Requirements 6 | 7 | * [Making a mod](./makingAMod.md) 8 | 9 | ## New JSON files 10 | 11 | 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. 12 | 13 | ## Existing JSON files 14 | 15 | 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. 16 | 17 | 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 [this wiki page](https://wiki.c2dl.info/Patching). 18 | 19 | In order to work with JSON files it is recommend to beautify them before using them. You can use [beautifier.io](https://beautifier.io/) to do that for you. 20 | 21 | 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. 22 | 23 | ```json 24 | { 25 | "character": "main.lea", 26 | "sheet": "player", 27 | "headIdx": 0, 28 | "class": "SPHEROMANCER", 29 | "stats": { 30 | "hp": { 31 | "base": 200, 32 | "increase": 2000, 33 | "variance": 0.1 34 | }, 35 | "attack": { 36 | "base": 20, 37 | "increase": 200, 38 | "variance": 0.9 39 | }, 40 | ... 41 | ``` 42 | 43 | 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` 44 | 45 | | :rocket: 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.| 46 | |---| 47 | 48 | First you can begin the file with `[]` to signal that this file is using the "Patch Step" format: 49 | ```json 50 | [ 51 | 52 | ] 53 | ``` 54 | 55 | Next we insert a step that navigates into the `attack` object: 56 | 57 | ```json 58 | { 59 | "type": "ENTER", 60 | "index": ["stats", "attack"] 61 | } 62 | ``` 63 | 64 | Now we can overwride a value: 65 | 66 | ```json 67 | { 68 | "type": "SET_KEY", 69 | "index": "base", 70 | "content": 200 71 | } 72 | ``` 73 | 74 | 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. 75 | 76 | ```json 77 | { 78 | "type": "EXIT", 79 | "count": 2 80 | } 81 | ``` 82 | 83 | At the end we end up with this `lea.json.patch` file: 84 | ```json 85 | [{ 86 | "type": "ENTER", 87 | "index": ["stats", "attack"] 88 | }, { 89 | "type": "SET_KEY", 90 | "index": "base", 91 | "content": 200 92 | }, { 93 | "type": "EXIT", 94 | "count": 2 95 | }] 96 | ``` -------------------------------------------------------------------------------- /javascriptMod.md: -------------------------------------------------------------------------------- 1 | # Making a JavaScript mod 2 | 3 | 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. 4 | 5 | ## Requirements 6 | 7 | * [Making a mod](./makingAMod.md) 8 | 9 | ## Entry points 10 | 11 | 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. 12 | 13 | For example, if we want to double all gained CP points we need to add a script: 14 | ```json 15 | { 16 | "name": "my-mod", 17 | "ccmodHumanName": "My Mod", 18 | "version": "1.0.0", 19 | "plugin": "plugin.js" 20 | } 21 | ``` 22 | | :warning: If you use entry points other than `plugin` you should always set `"module": true` as well. | 23 | |---| 24 | 25 | ## Mod loading stages 26 | 27 | ### Prestart 28 | 29 | 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. 30 | 31 | ### Preload 32 | 33 | 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. 34 | 35 | ### Postload 36 | 37 | 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. 38 | 39 | ### Main 40 | 41 | 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. 42 | 43 | 44 | ## Plugin 45 | 46 | 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. 47 | 48 | Since we defined the file as `plugin.js` above we create a new file `assets/mods/myMod/plugin.js`: 49 | ```js 50 | export default class MyMod { 51 | prestart() { 52 | //Prestart code will go in here. 53 | } 54 | } 55 | ``` 56 | 57 | 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. 58 | 59 | | :rocket: 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. | 60 | |---| 61 | 62 | 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 63 | ```ts 64 | public addSkillPoints(points: number, element: number, all: boolean, extra: boolean): void 65 | ``` 66 | 67 | 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. 68 | 69 | We can use this to make a mod that doubles all CP: 70 | ```js 71 | export default class MyMod { 72 | prestart() { 73 | sc.PlayerModel.inject({ 74 | addSkillPoints(points, element, all, extra) { 75 | this.parent(points*2, element, all, extra); 76 | } 77 | }); 78 | } 79 | } 80 | ``` --------------------------------------------------------------------------------