Skip to content

Instantly share code, notes, and snippets.

@Xyphis12
Last active January 28, 2024 07:47
Show Gist options
  • Save Xyphis12/8789538 to your computer and use it in GitHub Desktop.
Save Xyphis12/8789538 to your computer and use it in GitHub Desktop.
General documentation for modifying Pokemon Showdown

Pokemon Showdown Source Documentation

Due to the amount of interest in adding pokemon to the source, I have decided to create a little bit of documentation to help explain modify the source to add and modify formats and Pokemon.

Table of Contents

Adding and Modifying Formats in Pokemon Showdown

The various formats in Pokemon Showdown are defined in config/formats.js, but the rules and bannings that the formats follow are defined in data/rulesets.js

config/formats.js

This defines each format displayed in the list, which section to catagorize it in and the various rules and banings for the format

// CAP Little Cup format definition in formats.js
{
	name: "CAP LC", // This shows up on the list of formats
	section: "Other Metagames", // This is what catagory it is listed under
	// This is a list of each ruleset that the format follows. Rulesets are defined in data/rulesets.js
	ruleset: ['CAP Pokemon', 'Standard', 'Team Preview', 'Little Cup'], 
	// This is a combonation of banned groups, single pokemon and single items
	banlist: ['Uber', 'Soul Dew', 'Gengarite', 'Kangaskhanite', 'Sonicboom', 'Dragon Rage', 'Scyther', 'Sneasel', 'Yanma', 'Tangela'] 
},

data/rulesets.js

Rulesets.js is a complicated but aptly named file that handles the rules for each format. Most rules are broken up between the actual rules (general stipulations on which pokemon can enter, if Team Preview is used and the various clauses) and ban lists

// Rules for CAP  
cappokemon: {
	effectType: 'Rule', // For this, it's usually a Rule or Banlist
	validateSet: function(set, format) {
		return this.getEffect('Pokemon').validateSet.call(this, set, format, true);
	}
},
// Standard Banlist
standard: {
	effectType: 'Banlist',
	ruleset: ['Sleep Clause Mod', 'Species Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod'],
	banlist: ['Unreleased', 'Illegal']
},
// Little Cup rules
littlecup: {
	effectType: 'Rule',
	validateSet: function(set) {
		var template = this.getTemplate(set.species || set.name);
		if (template.prevo) {
			return [set.species+" isn't the first in its evolution family."];
		}
		if (!template.nfe) {
			return [set.species+" doesn't have an evolution family."];
		}
	}
},

Adding and Modifying Pokemon in Pokemon Showdown's Server

Expanded and flattened data structures are seen the same way by the node.js, but flattened structures tend to be more difficult for people to read and expanded structures use more resources to host

Structures will be modified and created while expanded (also easier to see typos) but implemented after they have been flattened

My other version of this, when I was just making myself some notes can be found here: http://pastebin.com/dj1FrW7f

Pokedex.js

pokedex.js is where each pokemon is defined, and contains general information about each pokemon

Pokedex.js (flattened)

syclar:{num:-101,species:"Syclar",types:["Ice","Bug"],genderRatio:{M:0.5,F:0.5},baseStats:{hp:40,atk:76,def:45,spa:74,spd:39,spe:91},abilities:{0:"Compound Eyes",1:"Snow Cloak"},heightm:0.2,weightkg:4.0,color:"",evos:["syclant"],eggGroups:["Bug"]}

Pokedex.js (expanded)

syclar:{
		num:-101, // Pokedex Number
		species:"Syclar", // Friendly Species name (can use caps and space)
		types:["Ice","Bug"], // List of types (["type"] for mono or ["typea","typeb"] for dual types)
		genderRatio:{M:0.5,F:0.5}, // Genderless pokemon and pokemon with only 1 gender are done using gender:"N", gender:"M"/"F"
		baseStats:{hp:40,atk:76,def:45,spa:74,spd:39,spe:91},
		abilities:{0:"Compound Eyes",1:"Snow Cloak"}, // {index:"string"}
		heightm:0.2,
		weightkg:4.0,
		color:"", // if this has no color, make it a empty string
		evos:["syclant"], // don't bother defining this if it does not evolve
		eggGroups:["Bug"] // another list ["group"] or ["groupa","groupb"]
},

Learnset.js

learnset.js list each move for each pokemon, and how the move is learned

  • This DOES NOT need to be in alphabetical order.

  • The move Return needs to be delimited for every Pokemon, so it looks like "return". (otherwise javascript will interpret it wrong)

  • Moves in this file do not contain spaces or capital letters.

  • L is moves learned when leveling up (xLy where x is the generation and y is the * level it learns it).

  • T is Moves learned from the Tutor (xT, where x is the generation).

  • M is Learned from a Technical or Hidden Machine (TM/HM) (xM where x is the generation).

  • E is for Egg Moves (xE where x is the generation).

  • xV format - x is the generation, V denotes that the move is learned by a Relearner or Transfer from another game

  • xSy format - x is the generation, S denotes that it's a move that appears in one of the eventData movesets, and y denotes the position of the eventData array that the move appears in. (Thanks @rbely)

Learnset.js (flattened)

syclar:{learnset:{furyattack:["6L1"],leer:["6L1"],leachlife:["6L5"],iceshard:["6L8"],focusenergy:["6L13"],icywind:["6L18"],xscissor:["6L23"],hail:["6L28"],bugbuzz:["6L42"],sheercold:["6L49"],bugbite:["6T"],counter:["6T"],earthpower:["6T"],furycutter:["6T"],icywind:["6T"],mimic:["6T"],snore:["6T"],stringshot:["6T"],superpower:["6T"],waterpulse:["6M"],toxic:["6M"],hail:["6M"],hiddenpower:["6M"],taunt:["6M"],icebeam:["6M"],blizzard:["6M"],protect:["6M"],frustration:["6M"],"return":["6M"],doubleteam:["6M"],facade:["6M"],secretpower:["6M"],rest:["6M"],attract:["6M"],falseswipe:["6M"],fling:["6M"],endure:["6M"],silver Wind:["6M"],avalanche:["6M"],swordsdance:["6M"],captivate:["6M"],xscissor:["6M"],sleeptalk:["6M"],naturalgift:["6M"],swagger:["6M"],uturn:["6M"],substitute:["6M"],cut:["6M"],earthpower:["6E"],pinmissile:["6E"],spikes:["6E"],superpower:["6E"],tailglow:["6E"]}},

Learnset.js (expanded)

syclar:{
		learnset:{
				furyattack:["6L1"],
				leer:["6L1"],
				leachlife:["6L5"],
				focusenergy:["6L13"],
				...
				frustration:["6M"],
				// Return needs to be in quotes otherwise JS thinks it's the function return
				"return":["6M"],
				doubleteam:["6M"],
				...
				pinmissile:["6E"],
				tailglow:["6E"]
		}
},

formats-data.js

formats-data.js has information for each pokemon, more specific to Pokemon Showdown.

  • Moves in this file are delimited and do not contain spaces or capital letters

formats-data.js (flattened)

syclar: {
		viableMoves: {"furyattack":1,"leer":1,"leechlife":1,"iceshard":1,"focusenergy":1,"icywind":1,"xscissor":1,"hail":1},
		isNonstandard: true,
		tier: "CAP"
}

formats-data.js (expanded)

syclar: {
		viableMoves:{ // I don't know what the 1 is for, but every move for every pokemon is like this
				"furyattack":1,
				"leer":1,
				"leechlife":1,
				"iceshard":1,
				"focusenergy":1,
				"icywind":1,
				"xscissor":1,
				"hail":1
		},
		isNonstandard: true,
		tier: "CAP"
},

Adding and Modifying Pokemon in Pokemon Showdown's client

Aside from the server side edits, the pokemon showdown client needs to be modified to display and fully support new and modified pokemon (though the server changes are good enough for testing)

Sprites

To get Pokemon Showdown's Client to have sprites for custom pokemon, battledata.js needs to be modified, and all other sprites need to be hosted.

Battledata.js Edits

in battledata.js the following function needs to be modifed

resourcePrefix: (function() {
	var prefix = '';
	if (document.location.protocol === 'file:') prefix = 'http:';
	return prefix + '//play.pokemonshowdown.com/'; // this is the prefix it uses to fetch resources, like sprites
})(),

Getting the Resources

using wget (or wget for windows), this script can download most of the files from the server, and removes the index.htmls

# Download all the sprites
wget --execute="robots = off" --mirror --convert-links --no-parent http://play.pokemonshowdown.com/sprites/
# Download all the audio
wget --execute="robots = off" --mirror --convert-links --no-parent http://play.pokemonshowdown.com/audio/
# Download other resources
wget --execute="robots = off" --mirror --convert-links --no-parent http://play.pokemonshowdown.com/fx/
# remove index.html files
rm $(find ./play.pokemonshowdown.com/ -name 'index.html*')

The previous scripts missed the trainer sprites, so here is a loop that goes through and downloads them:

# Download the range of trainer sprites from 1 to 294
for i in {1..294}
	do wget http://play.pokemonshowdown.com/sprites/trainers/$i.png
	done 

Adding New sprites

To add new sprites for a pokemon, there needs to be 4 unique images:

  1. The normal front sprite
  2. the back sprite
  3. the shiny front sprite
  4. the shiny back sprite

Each image needs to be on a 96x96 canvas, png file format and they need to have transparent backgrounds. The Server expects each image to be in it's corresponding folder. There are 4 folders:

  1. sprites/bw
  2. sprites/bw-back
  3. sprites/bw-shiny
  4. sprites/bw-back-shiny

The name of each image is expected to be the pokemon's name (all lowercase, no spaces) and the .png file extension.

Note that this is not for animations and mini-sprites. Animations have their own folders that they go in, and mini-sprites are part of a sprite sheet.

Recently, Pokemon Showdown added gif images that had animations from pokemon X/Y. I was worried this was going to cause a problem with your Black/White sprites, but thus far it has not. For future reference, X/Y anumations are in sprites/xyani, sprites/xyani-back etc.

Data Files

in /data there are a few files that have to be changed to accommodate for the new pokemon. Most of the changes are already done on the server side in the /data folder, and the files just need to be copied over to the client. One specific file still needs to be changed specifically for the client.

Pokedex-mini.js

pokedex-mini.js looks similar to pokedex.js, but has info regarding animated sprites for each pokemon. Not all pokemon need to have an animation, but they do need to have a entry in this file. If the pokemon doesn't have an animation, then just put it's pokedex number.

"binacle":{num:688, front:{ani:{w: 96, h: 96}},back:{ani:{w: 96, h: 96}}},
"barbaracle":{num:689},

learnsets-g6.js

This file is a data structure with gen6 specific movesets. Because we code our moves for gen 6, this needs to be updated with the same data that went in Learnset.js for teambuilder to work correctly

References

@bajunkins
Copy link

A more updated version of this would be awesome, lot of things have changed since this evidently

@Dedemetrionator
Copy link

Dedemetrionator commented Oct 23, 2020

why can't I find these files in the client master on my pc?

@nbely
Copy link

nbely commented Jun 6, 2022

@XBagon This is reaaaaaal late but I was looking for an answer to your question for my own reasons and figured out the following:

  • xV format - x is the generation, V denotes that the move is learned by a Relearner or Transfer from another game
  • xSy format - x is the generation, S denotes that it's a move that appears in one of the eventData movesets, and y denotes the position of the eventData array that the move appears in.

@Xyphis12
Copy link
Author

Xyphis12 commented Jun 7, 2022

Thank you @nbely! I probably should add that to the guide.

To everyone who is still trying to go through this guide, I’m very curious if this information is still accurate. It’s been more then 7 years since I last edited this, and I imagine Showdown has evolved (no pun intended) a bit since I last worked with the source.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment