Mod manager for the game CrossCode!
Open the menu from the options menu and look for the Mods button.
Read the in-game manual in the help menu for usage instructions.
You can attach this image at the top of your mod's README.md:
Markdown code:
[](https://github.com/CCDirectLink/CCModManager)You can define custom options pages for your own mod.
See full example below.
{type: 'CHECKBOX',init: true,changeEvent(){/* optional */// code},name: 'My checkbox',description: 'My least favorite button.',}{type: 'BUTTON_GROUP',init: 0/* option1 */,enum: {option1: 0,option2: 1},buttonNames: ['Option 1','Option 2'],name: 'My buttons',description: 'My (not really) favorite button group.',}// Or with an enum variableconstmyenum={option1: 0,option2: 1,}/// ...{type: 'BUTTON_GROUP',init: myenum.option1/* option1 */,enum: myenum,buttonNames: ['Option 1','Option 2'],name: 'My buttons',description: 'My beloved button group.',}{// Creates a slider that displays values from 1 to 8type: 'OBJECT_SLIDER',init: 1,min: 0.8,max: 1.5,step: 0.1,fill: true,name: 'Slider',description: 'My somewhat favorite slider.',}{// Creates a slider that displays values from 0% to 100%type: 'OBJECT_SLIDER',init: 0.5,min: 0,max: 1,step: 0.1,fill: true,showPercentage: true,thumbWidth: 50,// Force the thumb width to 50pxname: 'Percentage slider',description: 'My (maybe) somewhat favorite slider.',}{// Creates a slider that displays values from 4 to 13 type: 'OBJECT_SLIDER',init: 7,min: 4,max: 13,step: 1,fill: true,// note: when using typescript, you need to specify// the return type of this function manuallycustomNumberDisplay(index){returnthis.min+index},name: 'Number slider',description: 'My (definitely) somewhat favorite slider.',}{type: 'BUTTON',name: 'Button',description: 'My favorite button.',onPress(button){// code// you can update the button text as you pleasebutton.setText("hi!!")},}{type: 'INFO',name: 'Hello to all!\n<-- New line.',description: '',}{type: 'CONTROLS',init: {key1: ig.KEY.I},// If false, the keybinding only works in-game// If true, the keybinding works everywhereglobal: false,/* optional, false by default */pressEvent(){/* optional */// keybinding pressed! I will trigger only once// code},holdEvent(){/* optional */// keybinding is pressed now! I will trigger every frame the key is pressed// code},name: 'My keybinding',description: 'Does something I guess.',}// Without name{type: 'INPUT_FIELD',name: '',description: 'boring text, carry on',init: 'initial text',changeEvent(){/* optional */// code}},// With name{type: 'INPUT_FIELD',name: 'favorite food',description: 'whats your favorite food??',init: 'bricks',changeEvent(){/* optional */// code}},// Without name{type: 'INPUT_FIELD',name: '',init: 'crossthecodes 123',description: 'how to cross the codes',changeEvent(){/* optional */// code},isValid(text){returntext.includes('crossthecodes')}}},// With name{type: 'INPUT_FIELD',name: 'favorite plushie',init: 'lea',changeEvent(){/* optional */// code},isValid(text){returntext=='lea'}}},{type: 'JSON_DATA',init: 123,changeEvent(){/* optional */// code}}Each visible option has the optional functions onInit and onDeinit.
For example:
{type: 'BUTTON',name: 'Button',description: 'My favorite button.',onPress(){console.log('Button presssed!')},onInit(gui){gui.button.setText("(evil) Button")},onDeinit(gui){console.log("the evil button will return someday!")}},On any option with a name visible, you can set the noNamePadding field to true to disable the padding.
For example:
{type: 'CHECKBOX',init: true,name: 'My checkbox',noNamePadding: true,description: "It's initialized as true by default.",}Here's the whole page with noNamePadding set to true:
// for typescript:// import type {} from 'ccmodmanager/types/plugin'constOpts=modmanager.registerAndGetModOptions({modId: 'my-mod',// the same as the `id` field in `ccmod.json`title: 'My mod',// the same as the `title` field in `ccmod.json`},{general: {settings: {title: 'General',// tab titletabIcon: 'general',// icon id},headers: {'My header title': {myCheckbox: {type: 'CHECKBOX',init: true,name: 'My checkbox',description: "It's initialized as true by default.",},myEnum: {type: 'BUTTON_GROUP',init: 0/* option1 */,enum: {option1: 0,option2: 1},buttonNames: ['Option 1','Option 2'],name: 'My buttons',description: 'Hello.',},mySlider: {// Creates a slider with the following text:// 1 2 3 4 5 6 7 8// that resolve to the following values:// 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5type: 'OBJECT_SLIDER',init: 1,min: 0.8,max: 1.5,step: 0.1,fill: true,showPercentage: false/* Show the values as % (example: 0.9 => 90%) */,name: 'Slider',description: 'My somewhat favorite slider.',},myButton: {type: 'BUTTON',name: 'Button',description: 'My favorite button.',onPress(){console.log('Button presssed!')},},myInfo: {type: 'INFO',name: 'Hello!',description: '',},myKeybinding: {type: 'CONTROLS',init: {key1: ig.KEY.I},// If false, the keybinding only works in-game// If true, the keybinding works everywhereglobal: false,pressEvent(){console.log('keybinding pressed!')},name: 'Keybinding',description: 'Does something I guess.',},// JSON_DATA is not visible in the menumyNumberStorage: {type: 'JSON_DATA',init: 123,},myJsonStorage: {type: 'JSON_DATA',init: {a: 1,b: 2,c: 3},},myInputField: {type: 'INPUT_FIELD',name: '',description: 'boring text, carry on',init: 'initial text',changeEvent(){/* optional */// code},},myValidatedInputField: {type: 'INPUT_FIELD',name: '',description: 'how to cross the codes',init: 'crossthecodes 123',changeEvent(){/* optional */// code},isValid(text){returntext.includes('crossthecodes')},},},},},})// UsageOpts.myCheckbox// booleanOpts.myEnum// 0 | 1Opts.mySlider// 0.8 | 0.9 | 1.0 | 1.1 | 1.2 | 1.3 | 1.4 | 1.5// Opts.myInfo is not accessible, since it does not store data// Opts.myKeybinding is not accessible, since it does not store dataOpts.myInputField// stringOpts.myValidatedInputField// stringOpts.myNumberStorage// numberOpts.myJsonStorage.a// numberOpts.myJsonStorage.b// numberOpts.myJsonStorage.c// number/* Invalid code: */// Opts.myJsonStorage.a = 2 // The stored data is read-only, you need to override the whole object/* This is how you do it: */Opts.myJsonStorage={ ...Opts.myJsonStorage,a: 2}- (javascript) cc-staircase-effect-fix as an example of
INFO,CHECKBOXandOBJECT_SLIDER - (typescript) cc-fancy-crash as an example of
BUTTON_GROUPandCHECKBOX - (typescript) cc-record as an example of
OBJECT_SLIDERandCONTROLS - (typescript) CCModManager as an example of
JSON_DATA,BUTTONandINPUT_FIELD - (typescript) CrossedEyes as an example of a big multi-tab menu with a custom language getter
git clone https://github.com/CCDirectLink/CCModManager
cd CCModManager
pnpm install
pnpm run start
# this should return no errors (hopefully)
npx tsc
















