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
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
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']
},
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."];
}
}
},
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 is where each pokemon is defined, and contains general information about each pokemon
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"]}
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 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)
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"]}},
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 has information for each pokemon, more specific to Pokemon Showdown.
- Moves in this file are delimited and do not contain spaces or capital letters
syclar: {
viableMoves: {"furyattack":1,"leer":1,"leechlife":1,"iceshard":1,"focusenergy":1,"icywind":1,"xscissor":1,"hail":1},
isNonstandard: true,
tier: "CAP"
}
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"
},
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)
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.
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
})(),
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
To add new sprites for a pokemon, there needs to be 4 unique images:
- The normal front sprite
- the back sprite
- the shiny front sprite
- 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:
- sprites/bw
- sprites/bw-back
- sprites/bw-shiny
- 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.
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 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},
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
@Xyphis12 I know I'm very late but could you please update the guide I am struggling with this.