Datapackable Move Effects: Difference between revisions

(Created page with "{{FutureContent}} {{TOC|right}} == Preface == As of version 1.7, Cobblemon now supports adding/replacing ability and move effects within the battle engine via datapacks. While it’s not required, it’s recommended to have a basic level of understanding in TypeScript or JavaScript before attempting to add/replace effects. == Understanding the data == In order to grasp what needs to be added to your datapack, you’ll likely need to reference Cobblemon’s fork of th...")
 
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{FutureContent}}
{{TOC|right}}
{{TOC|right}}
== Preface ==
== Preface ==
As of version 1.7, Cobblemon now supports adding/replacing ability and move effects within the battle engine via datapacks. While it’s not required, it’s recommended to have a basic level of understanding in TypeScript or JavaScript before attempting to add/replace effects.  
As of version 1.7, Cobblemon now supports adding/replacing ability and move effects within the battle engine via datapacks. While it’s not required, it’s recommended to have a basic level of understanding in TypeScript or JavaScript before attempting to add/replace effects.  
Line 58: Line 56:
Here’s an example of a custom move, with most of its effects based on <code>freezedry</code>:
Here’s an example of a custom move, with most of its effects based on <code>freezedry</code>:


  {
  ({
     accuracy: 100,
     accuracy: 100,
     basePower: 70,
     basePower: 70,
Line 77: Line 75:
     type: "Water",
     type: "Water",
     contestType: "Beautiful"
     contestType: "Beautiful"
   },
   })


This move changes only a few things from the code we copied from the <code>freezedry</code> block:
This move changes only a few things from the code we copied from the <code>freezedry</code> block:
Line 117: Line 115:


<blockquote>'''NOTE: As with many other addon entries, the inclusion of `assets` will mean your addon needs to be loaded as a resource pack. It’s usually easiest to have users load the same zip as both a datapack and a resource pack, but you’re welcome to separate them into individual packs if you wish.'''</blockquote>
<blockquote>'''NOTE: As with many other addon entries, the inclusion of `assets` will mean your addon needs to be loaded as a resource pack. It’s usually easiest to have users load the same zip as both a datapack and a resource pack, but you’re welcome to separate them into individual packs if you wish.'''</blockquote>
{{Addon Creation}}

Latest revision as of 21:49, 24 November 2025

Preface

As of version 1.7, Cobblemon now supports adding/replacing ability and move effects within the battle engine via datapacks. While it’s not required, it’s recommended to have a basic level of understanding in TypeScript or JavaScript before attempting to add/replace effects.

Understanding the data

In order to grasp what needs to be added to your datapack, you’ll likely need to reference Cobblemon’s fork of the Pokemon Showdown engine. Cobblemon utilizes a transpiled (into JavaScript) version of the TypeScript on this repository to run its battle engine. For this reason, all the files (aside from those containing UI data, such as move/ability names and localization) that we’ll be adding to the datapack will be in the .js format and use JavaScript.

The easiest way to learn what the files need to contain is to reference existing abilities/moves, which can be found in data/abilities.ts and data/moves.ts respectively.

JavaScript Approach

Instead of working directly within the Showdown repo’s files, you can instead look at the files Cobblemon generates within your own Minecraft instance, inside the showdown folder. From there, you can read the existing generated JavaScript and write your own .js files using the base Showdown effects as a reference.

This is effective when working with very simple changes (e.g. a base power change on an existing move), but if your changes require complex custom logic or you simply want your editor to give you better linting/type checking, the TypeScript approach below is likely more effective.

TypeScript Approach

Write your custom logic into a cloned (i.e. downloaded) copy of the repo, utilizing TypeScript to make your changes/add your new effects inside the existing tables. You can then use the Node (https://nodejs.org/en) command node build which will transpile the tables into JavaScript, outputting them to the dist folder. You can then extract your changes from the compiled JavaScript table (within dist/data/abilites.js and so on) and place them into individual .js files in your datapack (see the individual sections below for exact paths and formatting).

If you have experience with TypeScript environments, there are many other ways to get your code from TypeScript to JavaScript. This is the simplest, as it ensures any linting and type checking is done within the context of the Showdown environment.

If you have a large number of changes, it may also benefit you to write a script to transpile and place your scripts inside their own files automatically. The existing `build` method can be found inside `tools/build-utils.js`.

Creating the data files

When added to a datapack, each effect needs to be an individual .js file within the data/cobblemon/abilities or data/cobblemon/moves folder. It should additionally have no comments within it (e.g. beginning with // or otherwise). The file name should be whatever you want the unique ID of the ability to be and can only contain the characters a-z | 0-9 | - | _ (e.g. my-ability.js).

It’s important to note that the script file must begin and end with a curly brace (e.g. { and } respectively). This means when copying existing effects, you should take care to not include the internal name of the effect. Cobblemon will instead fill in the unique ID of the move automatically based on the file name of the effect within your datapack.

Examples

Here’s a full example of a very simple ability modification, placed into the file intimidate.js, which changes Intimidate to lower Special Attack instead of Attack:

{
   onStart(pokemon) {
     let activated = false;
     for (const target of pokemon.adjacentFoes()) {
       if (!activated) {
         this.add("-ability", pokemon, "Intimidate", "boost");
         activated = true;
       }
       if (target.volatiles["substitute"]) {
         this.add("-immune", target);
       } else {
         this.boost({ spa: -1 }, target, pokemon, null, true);
       }
     }
   },
   flags: {},
   name: "Intimidate",
   rating: 3.5,
   num: 22
}

As you can see, it copies all the logic from the existing Intimidate effect, but we’ve changed atk: -1 to spa: -1.

Here’s an example of a custom move, with most of its effects based on freezedry:

({
   accuracy: 100,
   basePower: 70,
   category: "Special",
   name: "Bug Spray",
   pp: 20,
   priority: 0,
   flags: { protect: 1, mirror: 1, metronome: 1 },
   onEffectiveness(typeMod, target, type) {
     if (type === "Bug")
       return 1;
   },
   secondary: {
     chance: 10,
     status: "psn"
   },
   target: "normal",
   type: "Water",
   contestType: "Beautiful"
 })

This move changes only a few things from the code we copied from the freezedry block:

  • The name field is now our own move’s name
  • The type inside the onEffectiveness block is now "Bug" so it’s now super-effective against bug types
  • The secondary effect’s status type is now Poison (”frz” to "psn")
  • Our move’s type is now Water instead of Ice

Once the changes are made, we save it into a file named bugspray.js inside our datapack’s data/cobblemon/moves folder.

Fields

Important: the num field

The num field can be a bit confusing, since it’s a numerical ID that Showdown uses. For replacing effects (such as the Intimidate change above) it’s important to keep the same ID number. For brand new effects, you should remove the field entirely.

The name field

While most uses of the move/ability strings will be dependent on your datapack’s localization files (see below) it’s still important to give them Showdown-internal names. These should be proper names encapsulated within quotes, e.g. "Fire Blast" rather than "fireblast".

It’s rare that this should be an issue, but if Showdown needs to use the name it’s important to keep it consistent with what the player is seeing in Cobblemon’s menus.

Other fields/functions

For most other fields and functions within an effect, the name will either be self-explanatory or you’ll have to do some digging within Showdown’s code. An understanding of TS/JS is essential here, but you can likely get by if you know at least one programming language in general.

It may be that certain numerical values don’t behave exactly how you’d expect, so if something is behaving oddly, be sure to check similar effects in the Showdown code to see how the value is actually handled.

When in doubt, stick to deriving your custom effects from similar existing effects and you should run into less issues and confusion overall.

Localization

As with most other addon-modified components of Cobblemon, you’ll need to add proper language files to ensure your custom effects are displayed correctly. These are found in Cobblemon’s files within assets/cobblemon/lang and your addon should contain the same structure. You can check any of the JSON files within that directory for examples in addition to the localization keys for any names/descriptions that you need to replace.

If you fail to do so, your addon will still load but all effects without entries will display text in the Cobblemon menus as their tag, e.g. cobblemon.move.bugspray or cobblemon.ability.myability.desc.

If you are only replacing an existing effect and its description is still accurate, then you do not need to recreate/overwrite the existing localization data.

NOTE: As with many other addon entries, the inclusion of `assets` will mean your addon needs to be loaded as a resource pack. It’s usually easiest to have users load the same zip as both a datapack and a resource pack, but you’re welcome to separate them into individual packs if you wish.