Resource General Thread for OM Code

Approved by The Immortal
Some of the OP stolen from Slayer95

Gen 6 Thread


Hi, there!
This thread intends to collect the code required to play the approved Other Metas, including Pet Mods.

How to contribute?

You may provide a Github Gist, Pastebin, or link to a similar site, containing either the code itself required to implement the OM or the diffs involved in its implementation (so a link to a dedicated commit or pull request would be cool).
This is the way to go for Pet Mods code, as well as for OMs that dynamically change (e.g. Theorymon, OM Mashup, Pokémon Throwback, etc.) Pet Mods must only show their current version. Past versions of periodical OMs can be published though.

For small, simple (code-wise) OMs, you may just post it fully, using the format showcased below.

If you wanna request, simply post it.

Gen 6 OMs

Code:
   {
     name: "Tier Shift",
     desc: [
       "Pokémon below OU/BL get all their stats boosted. UU/BL2 get +5, RU/BL3 get +10, NU/BL4 get +15, and PU or lower get +20.",
       "&bullet; <a href=\"https://www.smogon.com/forums/threads/3554765/\">Tier Shift</a>",
     ],

     mod: 'tiershift',
     ruleset: ['OU'],
     banlist: ['Damp Rock'],
   },
Code:
'use strict';

const BOOST_TABLE = {
   'UU': 5,
   'BL2': 5,
   'RU': 10,
   'BL3': 10,
   'NU': 15,
   'BL4': 15,
   'PU': 20,
   'NFE': 20,
   'LC Uber': 20,
   'LC': 20,
};

exports.BattleScripts = {
   pokemon: {
     formeChange: function (template, dontRecalculateStats) {
       template = this.battle.getTemplate(template);

       if (!template.abilities) return false;
       this.template = template;

       this.types = template.types;
       this.addedType = '';
       this.knownType = true;

       if (!dontRecalculateStats) {
         let tier = template.tier;
         if (this.set.item) {
           let item = this.battle.getItem(this.set.item);
           if (item.megaEvolves === template.species) tier = this.battle.getTemplate(item.megaStone).tier;
         }
         if (tier.charAt(0) === '(') tier = tier.slice(1, -1);
         let boost = (tier in BOOST_TABLE) ? BOOST_TABLE[tier] : 0;
         /*if (this.set.ability in {'Drizzle': 1, 'Drought': 1}) {
           boost = 0;
         }*/

         let baseStats = {};
         for (let statName in this.template.baseStats) {
           baseStats[statName] = this.battle.clampIntRange(this.template.baseStats[statName] + boost, 1, 255);
         }
         let stats = this.battle.spreadModify(baseStats, this.set);
         if (this.maxhp > 1 && stats.hp >= this.maxhp) {
           this.hp = this.maxhp = stats.hp;
         }

         for (let statName in this.stats) {
           this.stats[statName] = stats[statName];
           this.baseStats[statName] = stats[statName];
         }
         this.speed = this.stats.spe;
       }
       return true;
     },
   },
};
Code:
   {
     name: "2v2 Doubles",
     desc: [
       "Double battle where you bring four Pok&eacute;mon to Team Preview and choose only two.",
       "&bullet; <a href=\"https://www.smogon.com/forums/threads/3547040/\">2v2 Doubles</a>",
     ],

     gameType: 'doubles',

     teamLength: {
       validate: [2, 4],
       battle: 2,
     },
     ruleset: ['Doubles OU'],
     banlist: ['Kangaskhanite', 'Perish Song'],
   },
Code:
   {
     name: "Meta Man",
     desc: [
       "When a Pokemon faints, the opposing Pokemon replaces its current ability with the fainted Pokemon's and gains its last-used move in a new slot (for up to 9 total moves). These changes last the entire match. If a Pokemon faints before using a move during the match, no move is gained by the opponent.",
       "&bullet; <a href=\"http://www.smogon.com/forums/threads/meta-man.3565966/\">Meta Man</a>",
     ],
     mod: "metaman",
     ruleset: ['OU'],
     onFaint: function(pokemon)
     {
       this.add("-message",pokemon.side.foe.pokemon[0].name+" received "+pokemon.name+"'s "+this.data.Abilities[pokemon.ability].name+"!");
       pokemon.side.foe.pokemon[0].setAbility(pokemon.ability);
       pokemon.side.foe.pokemon[0].baseAbility = pokemon.ability;
       let lastMove = pokemon.lastM;
       let has
       if(pokemon.side.foe.pokemon[0].moveset.length<=9 && lastMove && !pokemon.side.foe.pokemon[0].hasMove(lastMove.id))
       {
         pokemon.side.foe.pokemon[0].moveset.push(lastMove);
         pokemon.side.foe.pokemon[0].baseMoveset.push(lastMove);
         this.add("-message",pokemon.side.foe.pokemon[0].name+" received "+pokemon.name+"'s "+pokemon.lastM.move+"!");
       }
     },
   },
Code:
'use strict';
exports.BattleScripts = {
     pokemon:{
         moveUsed(move) {
             this.lastMove = this.battle.getMove(move).id;
             for(let i=0;i<this.moveset.length;i++)
             {
               if(move.id == this.moveset[i].id)
               {
                 this.lastM = this.moveset[i];
                 this.lastM.disabled = false;
                 this.lastM.pp = this.lastM.maxpp;
                 break;
               }
             }
             this.moveThisTurn = this.lastMove;
         }
     }
};
Code:
   {
     name: "Hidden Type",
     desc: [
       "Pok&eacute;mon have an added type determined by their IVs. Same as the Hidden Power type.",
       "&bullet; <a href=\"https://www.smogon.com/forums/threads/3516349/\">Hidden Type</a>",
     ],


     mod: 'hiddentype',
     ruleset: ['OU'],
   },
Code:
'use strict';

exports.BattleScripts = {
   pokemon: {
     formeChange: function (template, dontRecalculateStats) {
       template = this.battle.getTemplate(template);
       if (!template.abilities) return false;

       this.template = template;
       this.types = template.types;
       this.addedType = this.baseHpType;
       this.knownType = true;

       if (!dontRecalculateStats) {
         let stats = this.battle.spreadModify(this.template.baseStats, this.set);
         for (let statName in this.stats) {
           this.stats[statName] = stats[statName];
           this.baseStats[statName] = stats[statName];
         }
         this.speed = this.stats.spe;
       }
       return true;
     },
     transformInto: function (pokemon, user, effect) {
       let template = pokemon.template;
       if (pokemon.fainted || pokemon.illusion || pokemon.volatiles['substitute']) return false;
       if (!template.abilities || (pokemon && pokemon.transformed) || (user && user.transformed)) return false;
       if (!this.formeChange(template, true)) return false;

       this.transformed = true;
       this.types = pokemon.types;
       if (pokemon.addedType !== pokemon.hpType) {
         this.addedType = pokemon.addedType;
       } else if (this.types.indexOf(this.hpType) < 0) {
         this.addedType = this.hpType;
       } else {
         this.addedType = '';
       }
       for (let statName in this.stats) {
         this.stats[statName] = pokemon.stats[statName];
       }
       this.moveset = [];
       this.moves = [];
       this.set.ivs = this.set.ivs;
       this.hpType = this.hpType;
       this.hpPower = this.hpPower;
       for (let i = 0; i < pokemon.moveset.length; i++) {
         let moveData = pokemon.moveset[i];
         let moveName = moveData.move;
         if (moveData.id === 'hiddenpower') {
           moveName = 'Hidden Power ' + this.hpType;
         }
         this.moveset.push({
           move: moveName,
           id: moveData.id,
           pp: moveData.maxpp === 1 ? 1 : 5,
           maxpp: moveData.maxpp === 1 ? 1 : 5,
           target: moveData.target,
           disabled: false,
           used: false,
           virtual: true,
         });
         this.moves.push(toId(moveName));
       }
       for (let j in pokemon.boosts) {
         this.boosts[j] = pokemon.boosts[j];
       }
       if (effect) {
         this.battle.add('-transform', this, pokemon, '[from] ' + effect.fullname);
       } else {
         this.battle.add('-transform', this, pokemon);
       }
       this.setAbility(pokemon.ability, this, {id: 'transform'});
       return true;
     },
   },
};
Code:
'use strict';

exports.BattleMovedex = {
   reflecttype: {
     inherit: true,
     onHit: function (target, source) {
       if (source.template && (source.template.num === 493 || source.template.num === 773)) return false;
       this.add('-start', source, 'typechange', '[from] move: Reflect Type', '[of] ' + target);

       source.types = target.types;
       if (target.addedType !== target.hpType) {
         source.addedType = target.addedType;
       } else if (source.types.indexOf(source.hpType) < 0) {
         source.addedType = source.hpType;
       } else {
         source.addedType = '';
       }
       source.knownType = target.side === source.side && target.knownType;
     },
   },
};
Code:
{
     name: "Follow The Leader",
     desc: ["&bullet; <a href=\"https://www.smogon.com/forums/threads/3565685/\">Follow The Leader</a>"],

     ruleset: ['Pokemon', 'Standard', 'Team Preview', 'Swagger Clause', 'Baton Pass Clause'],
     banlist: ['Regigigas', 'Shedinja', 'Slaking', 'Smeargle', 'Gengarite', 'Kangaskhanite', 'Lucarionite', 'Mawilite', 'Salamencite', 'Soul Dew',
       'Arena Trap', 'Gale Wings', 'Huge Power', 'Imposter', 'Pure Power', 'Shadow Tag', 'Chatter',
     ],
     validateSet: function (set, teamHas) {
       let species = toId(set.species);
       let template = this.tools.getTemplate(species);
       if (!template.exists || template.isNonstandard) return ["" + set.species + " is not a real Pok\u00E9mon."];
       if (template.battleOnly) template = this.tools.getTemplate(template.baseSpecies);
       if (this.tools.getBanlistTable(this.format)[template.id] || template.tier in {'Uber': 1, 'Unreleased': 1} && template.species !== 'Aegislash') {
         return ["" + template.species + " is banned by Follow The Leader."];
       }

       if (!teamHas.donorTemplate) teamHas.donorTemplate = template;
       let name = set.name;
       if (name === set.species) delete set.name;
       set.species = teamHas.donorTemplate.species;
       let problems = this.validateSet(set, teamHas, teamHas.donorTemplate);

       set.species = template.species;
       set.name = (name === set.species ? "" : name);

       return problems;
     },
   },
Code:
{
   name: "Gifts of the Gods",
   desc: [
     "Each Pok&eacute;mon receives one base stat, depending on its position, from the Uber.",
     "&bullet; <a href=\"https://www.smogon.com/forums/threads/3579610/\">Gifts of the Gods</a>",
   ],
   column: 3,

   ruleset: ['Ubers', 'Baton Pass Clause'],
   banlist: ['Uber > 1', 'AG ++ Uber', 'Blissey', 'Chansey', 'Eviolite', 'Mawilite', 'Medichamite', 'Sablenite', 'Soul Dew', 'Huge Power', 'Pure Power', 'Shadow Tag'],
   onBegin: function() {
     let stats = ['hp', 'atk', 'def', 'spa', 'spd', 'spe'];
     for (let j = 0; j < this.sides.length; j++) {
       // onBegin happens before Mega Rayquaza clause
       let uber = this.sides[j].pokemon.find(pokemon => ['AG', 'Uber'].includes(this.getTemplate(pokemon.canMegaEvo || pokemon.baseTemplate).tier)) || this.sides[j].pokemon[0];
       for (let i = 0, len = this.sides[j].pokemon.length; i < len; i++) {
         let pokemon = this.sides[j].pokemon[i];
         ["baseTemplate", "canMegaEvo"].forEach(key => {
           if (pokemon[key]) {
             let template = Object.assign({}, this.getTemplate(pokemon[key]));
             template.baseStats = Object.assign({}, template.baseStats);
             template.baseStats[stats[i]] = uber.baseTemplate.baseStats[stats[i]];
             pokemon[key] = template;
           }
         });
         pokemon.formeChange(pokemon.baseTemplate);
         if (i === 0 && !pokemon.template.maxHP) {
           pokemon.hp = pokemon.maxhp = Math.floor(Math.floor(2 * pokemon.template.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100) * pokemon.level / 100 + 10);
         }
       }
     }
   },
},
Code:
{
   name: "Haxmons",

   ruleset: ['OU'],
   banlist: ["King's Rock", 'Razor Fang', 'Stench'],
   onModifyMovePriority: -100,
   onModifyMove: function(move) {
     if (move.accuracy !== true && move.accuracy < 100) move.accuracy = 0;
     move.willCrit = true;
     if (move.secondaries) {
       for (var i = 0; i < move.secondaries.length; i++) {
         move.secondaries[i].chance = 100;
       }
     }
   }
},
Code:
{
   name: "Metagamiate",
   desc: ["&bullet; <a href=\"https://www.smogon.com/forums/threads/3502303/\">Metagamiate</a>"],

   ruleset: ['OU'],
   banlist: ['Dragonite', 'Kyurem-Black'],
   onModifyMovePriority: -1,
   onModifyMove: function(move, pokemon) {
     if (move.type === 'Normal' && move.id !== 'hiddenpower' && !pokemon.hasAbility(['aerilate', 'pixilate', 'refrigerate'])) {
       let types = pokemon.getTypes();
       let type = types.length < 2 || !pokemon.set.shiny ? types[0] : types[1];
       move.type = type;
       move.isMetagamiate = true;
     }
   },
   onBasePowerPriority: 8,
   onBasePower: function(basePower, attacker, defender, move) {
     if (!move.isMetagamiate) return;
     return this.chainModify([0x14CD, 0x1000]);
   },
},
Code:
  {
     name: "Nature Swap",
     desc: ["&bullet; <a href=\"https://www.smogon.com/forums/threads/3577739/\">Nature Swap</a>"],

     ruleset: ['OU'],
     banlist: ['Chansey', 'Cloyster'],
     onBegin: function () {
       let allPokemon = this.p1.pokemon.concat(this.p2.pokemon);
       for (let i = 0, len = allPokemon.length; i < len; i++) {
         let pokemon = allPokemon[i];
         let nature = pokemon.battle.getNature(pokemon.set.nature);
         if (nature.plus !== nature.minus) {
           ["baseTemplate", "canMegaEvo"].forEach(key => {
             if (pokemon[key]) {
               let template = Object.assign({}, this.getTemplate(pokemon[key]));
               template.baseStats = Object.assign({}, template.baseStats);
               let plus = template.baseStats[nature.plus];
               let minus = template.baseStats[nature.minus];
               template.baseStats[nature.plus] = minus;
               template.baseStats[nature.minus] = plus;
               pokemon[key] = template;
             }
           });
           pokemon.formeChange(pokemon.baseTemplate);
         }
       }
     },
   },
Code:
{ //code credits: ScarfWynaut
   name: "The All-Stars Metagame",
   section: "New Other Metagames",
   ruleset: ['OU'],
   desc: ["&bullet; <a href=\"http://www.smogon.com/forums/threads/the-all-stars-metagame-v2-enter-the-pu-a-pokemon-from-each-tier.3510864//\">The All-Stars Metagame</a>"],
   banlist: [],

   onValidateTeam: function(team) {
     let ouMons = 0,
       uuMons = 0,
       ruMons = 0,
       nuMons = 0,
       puMons = 0,
       problems = [],
       check = true,
       template;
     for (let i = 0; i < team.length; i++) {
       let item = this.getItem(team[i].item);
       if (item.megaStone) template = this.getTemplate(team[i].item.megaStone);
       else template = this.getTemplate(team[i].species);
       let ability = this.getAbility(template.ability);
       let tier = template.tier;
       for (var j in team[i].moves) {
         var move = this.getMove(team[i].moves[j]);
         if (move.id == "chatter") tier = "NU";
       }
       //Bans Drought + Drizzle users to OU
       if (ability.id == "drizzle" || ability.id == "drought") tier = "OU";
       //Bans Chatter to NU
       if (tier == "OU" || tier == "BL") ouMons++;
       if (tier == "UU" || tier == "BL2") uuMons++;
       if (tier == "RU" || tier == "BL3") ruMons++;
       if (tier == "NU" || tier == "BL4") nuMons++;
       if (tier == "PU") puMons++;
     }
     while (check) {
       if (1 < ouMons) problems.push("You are able to only bring a maximum of 1 OU / BL Pokemon.");
       if (2 < uuMons) problems.push("You are able to only bring a maximum of 2 UU / BL2 Pokemon.");
       if (1 < ruMons) problems.push("You are able to only bring a maximum of 1 RU / BL3 Pokemon.");
       if (1 < nuMons) problems.push("You are able to only bring a maximum of 1 NU / BL4 Pokemon.");
       if (1 < puMons) problems.push("You are able to only bring a maximum of 1 PU Pokemon.");
       else check = false;
     }
     return problems;
   },
},
Code:
{
     name: "Trademarked",
     desc: ["&bullet; <a href=\"http://www.smogon.com/forums/threads/trademarked.3572949/\">Trademarked</a>"],

     mod: 'trademarked',
     ruleset: ['OU','trademarkclause'],
     banlist: ['Slaking','Regigigas'],
     validateSet: function (set, teamHas) {
       if (!this.validateSet(set, teamHas).length) return [];
       let ability = this.tools.getAbility(set.ability);
       let template = this.tools.getTemplate(set.species);
       if (!set.moves.includes(ability.id) && !set.moves.includes(ability.name) && !this.checkLearnset(ability.id, template, {set: set})) {
         template = Object.assign({}, template);
         template.abilities = {0: ability.name};
       }
       return this.validateSet(set, teamHas, template);
     },
   },
Code:
'use strict';

exports.BattleScripts = {
   init: function() {
     Object.values(this.data.Movedex).forEach(move => {
       let bannedMoves = {'Detect':1, 'Mat Block':1, 'Protect':1, 'Roar':1, 'Skill Swap':1, 'Whirlwind':1, 'Assist':1, 'Mean Look':1, 'Block':1};
       if (move.category === 'Status' && !bannedMoves[move.name]) {
         this.data.Abilities[move.id] = {
           desc: move.desc,
           shortDesc: move.shortDesc,
           id: move.id,
           name: move.name,
           onStart: function (pokemon) {
             this.add('-activate', pokemon, 'ability: ' + move.name);
             if(move.id=='partingshot' || move.id=='batonpass')
             {
               if(this[pokemon.side.id].lastPshot==this.turn && (this.lastMove=="partingshot" || this.lastMove=="batonpass"))
                 this.add('-message',"But it failed!");
               else
               {
                 this.useMove(move.id, pokemon);
                 this[pokemon.side.id].lastPshot=this.turn;
               }
             }
             else
             {
               this.useMove(move.id, pokemon);
             }
           },
         };
       }
     });
   },
}
Code:
'use strict';

exports.BattleMovedex = {
   "copycat": {
     num: 383,
     accuracy: true,
     basePower: 0,
     category: "Status",
     desc: "The user uses the last move used by any Pokemon, including itself. Fails if no move has been used, or if the last move used was Assist, Belch, Bestow, Chatter, Circle Throw, Copycat, Counter, Covet, Destiny Bond, Detect, Dragon Tail, Endure, Feint, Focus Punch, Follow Me, Helping Hand, Hold Hands, King's Shield, Mat Block, Me First, Metronome, Mimic, Mirror Coat, Mirror Move, Nature Power, Protect, Rage Powder, Roar, Sketch, Sleep Talk, Snatch, Spiky Shield, Struggle, Switcheroo, Thief, Transform, Trick, or Whirlwind.",
     shortDesc: "Uses the last move used in the battle.",
     id: "copycat",
     name: "Copycat",
     pp: 20,
     priority: 0,
     flags: {},
     onHit: function(pokemon) {
       let noCopycat = {
         assist: 1,
         bestow: 1,
         chatter: 1,
         circlethrow: 1,
         copycat: 1,
         counter: 1,
         covet: 1,
         destinybond: 1,
         detect: 1,
         dragontail: 1,
         endure: 1,
         feint: 1,
         focuspunch: 1,
         followme: 1,
         helpinghand: 1,
         mefirst: 1,
         metronome: 1,
         mimic: 1,
         mirrorcoat: 1,
         mirrormove: 1,
         naturepower: 1,
         protect: 1,
         ragepowder: 1,
         roar: 1,
         sketch: 1,
         sleeptalk: 1,
         snatch: 1,
         struggle: 1,
         switcheroo: 1,
         thief: 1,
         transform: 1,
         trick: 1,
         whirlwind: 1
       };
       if (pokemon.ability == "copycat") {
         noCopycat.batonpass = 1;
         noCopycat.partingshot = 1;
         noCopycat.fakeout = 1;
       }
       if (!this.lastMove || noCopycat[this.lastMove]) {
         return false;
       }
       this.useMove(this.lastMove, pokemon);
     },
     secondary: false,
     target: "self",
     type: "Normal",
     contestType: "Cute",
   },
};


Gen 7 OMs

Code:
{
   name: "Gods and Followers",
   desc: [
     "The Pok&eacute;mon in the first slot is the God; the Followers must share a type with the God. If the God Pok&eacute;mon faints, the Followers are inflicted with Curse.",
     "&bullet; <a href=\"https://www.smogon.com/forums/threads/3545230/\">Gods and Followers</a>",
   ],

   mod: 'godsandfollowers',
   ruleset: ['Pokemon', 'Sleep Clause Mod', 'Species Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Team Preview', 'Swagger Clause', 'Baton Pass Clause', 'Followers Clause', 'Cancel Mod'],
   banlist: ['Illegal']
},
Code:
exports.BattleFormats = {
   followersclause: {
     effectType: 'Rule',
     onValidateTeam: function(team) {
       var problems = [];
       var god = team[0];
       var godName = god.name || god.species;
       var godTemplate = this.getTemplate(god.species);
       var godFormes = godTemplate.otherFormes || [];
       // Look for item changing a forme, if one exists (for example mega
       // stones or Red Orb).
       for (var i = 0; i < godFormes.length; i++) {
         var forme = this.getTemplate(godFormes[i]);
         if (forme.requiredItem === god.item) {
           godTemplate = forme;
           break;
         }
       }

       for (var i = 1; i < team.length; i++) {
         var pokemon = team[i];
         var name = pokemon.name || pokemon.species;
         var template = this.getTemplate(pokemon.species);
         if (template.types.intersect(godTemplate.types).isEmpty()) {
           problems.push("Your " + name + " must share a type with " + godName + ".");
         }
         if (template.tier === 'Uber' || template.isUnreleased) {
           problems.push("You cannot use " + name + " as non-god.");
         }
         var bannedItems = {
           'Soul Dew': true,
           'Gengarite': true,
           'Kangaskhanite': true,
           'Lucarionite': true,
           'Mawilite': true,
           'Salamencite': true
         }
         if (bannedItems[pokemon.item]) {
           problems.push(name + "'s item " + pokemon.item + " is banned for non-gods.");
         }
       }
       // Item check
       for (var i = 0; i < team.length; i++) {
         var pokemon = team[i];
         var name = pokemon.name || pokemon.species;
         var item = this.getItem(pokemon.item);
         if (item.isUnreleased) {
           problems.push(name + "'s item " + set.item + " is unreleased.");
         }
       }
       return problems;
     },
     onStart: function() {
       // Set up god, because the Pokemon positions during battle switch around.
       for (var i = 0; i < this.sides.length; i++) {
         this.sides[i].god = this.sides[i].pokemon[0];
       }
     },
     onFaint: function(pokemon) {
       if (pokemon.side.god === pokemon) {
         this.add('-message', pokemon.name + " has fallen! " +
           pokemon.side.name + "'s team has been Cursed!");
       }
     },
     onSwitchIn: function(pokemon) {
       if (pokemon.side.god.hp === 0) {
         // What a horrible night to have a Curse.
         pokemon.addVolatile('curse', pokemon);
       }
     }
   }
};
Code by urkerab
Code:
{
   name: "[Gen 7] Pokébilities",
   desc: [
     "Pok&eacute;mon have all their natural abilities at the same time.",
     "&bullet; <a href=\"https://www.smogon.com/forums/threads/3588652/\">Pokébilities</a>",
   ],

   mod: 'pokebilities',
   ruleset: ["[Gen 7] Pokebank OU"],
   onBegin: function() {
     let banlistTable = this.getBanlistTable(this.getFormat('gen7ou'));
     let allPokemon = this.p1.pokemon.concat(this.p2.pokemon);
     for (let i = 0, len = allPokemon.length; i < len; i++) {
       let pokemon = allPokemon[i];
       if (pokemon.ability === 'battlebond') {
         pokemon.innates = [];
         continue;
       }
       pokemon.innates = Object.keys(pokemon.template.abilities).filter(key => key !== 'S' && (key !== 'H' || !pokemon.template.unreleasedHidden)).map(key => toId(pokemon.template.abilities[key])).filter(ability => ability !== pokemon.ability && !banlistTable[ability]);
     }
   },
   onSwitchInPriority: 1,
   onSwitchIn: function(pokemon) {
     pokemon.innates.forEach(innate => pokemon.addVolatile("other" + innate, pokemon));
   },
   onAfterMega: function(pokemon) {
     pokemon.innates.forEach(innate => pokemon.removeVolatile("other" + innate, pokemon));
     pokemon.innates = [];
   },
},
Code:
'use strict';

exports.BattleScripts = {
   init: function() {
     Object.values(this.data.Abilities).forEach(ability => {
       if (ability.id === 'trace') return;
       let id = 'other' + ability.id;
       this.data.Statuses[id] = Object.assign({}, ability);
       this.data.Statuses[id].id = id;
       this.data.Statuses[id].noCopy = true;
       this.data.Statuses[id].effectType = "Ability";
       this.data.Statuses[id].fullname = 'ability: ' + ability.name;
     });
   },
   pokemon: {
     hasAbility: function(ability) {
       if (this.ignoringAbility()) return false;
       if (Array.isArray(ability)) return ability.some(ability => this.hasAbility(ability));
       ability = toId(ability);
       return this.ability === ability || !!this.volatiles[ability];
     },
   },
};
Code:
'use strict';

exports.BattleStatuses = {
   othertrace: {
     desc: "On switch-in, this Pokemon copies a random adjacent opposing Pokemon's Ability. If there is no Ability that can be copied at that time, this Ability will activate as soon as an Ability can be copied. Abilities that cannot be copied are Flower Gift, Forecast, Illusion, Imposter, Multitype, Stance Change, Trace, and Zen Mode.",
     shortDesc: "On switch-in, or when it can, this Pokemon copies a random adjacent foe's Ability.",
     onUpdate: function (pokemon) {
       let possibleInnates = [];
       let possibleTargets = [];
       for (let i = 0; i < pokemon.side.foe.active.length; i++) {
         let target = pokemon.side.foe.active[i];
         if (target && !target.fainted) {
           possibleInnates = possibleInnates.concat(target.innates);
           possibleTargets = possibleTargets.concat(target.innates.map(innate => target));
         }
       }
       while (possibleInnates.length) {
         let rand = 0;
         if (possibleInnates.length > 1) rand = this.random(possibleInnates.length);
         let innate = possibleInnates[rand];
         let bannedAbilities = {comatose:1, flowergift:1, forecast:1, illusion:1, imposter:1, multitype:1, schooling:1, stancechange:1, trace:1, zenmode:1};
         if (bannedAbilities[innate]) {
           possibleInnates.splice(rand, 1);
           possibleTargets.splice(rand, 1);
           continue;
         }
         this.add('-ability', pokemon, innate, '[from] ability: Trace', '[of] ' + possibleTargets[rand]);
         pokemon.removeVolatile("othertrace", pokemon);
         pokemon.addVolatile("other" + innate, pokemon);
         return;
       }
     },
     id: "othertrace",
     name: "Trace",
     rating: 3,
     num: 36,
     noCopy: true,
     effectType: "Ability",
     fullName: "ability: Trace",
   },
};


Also, useful references:

Credits: AWailOfATail, Joim, Kris, Pikachuun, Scarfnaut, Slayer95, Snaquaza, The Immortal, urkerab, XpRienzo, me, and anyone whos name i forgot
 
Last edited:

dhelmise

everything is embarrassing
is a Site Content Manageris a Battle Simulator Administratoris a Top Social Media Contributoris a Community Leaderis a Programmeris a Community Contributoris a Top Contributoris a Top Smogon Media Contributoris a Top Dedicated Tournament Hostis a Smogon Discord Contributor Alumnus
Social Media Head
can you please make the code readable (as in proper spacing and everything), it's really aggravating to have to deal with this in its current state.

e: also, i've coded a handful of metas, so i should be credited.
 
Last edited:
can you please make the code readable (as in proper spacing and everything), it's really aggravating to have to deal with this in its current state.

e: also, i've coded a handful of metas, so i should be credited.
Right, I'll get working on it in a while
 
I'm just wondering what the best way of organising OM code is; I was thinking there could be a GitHub organisation with one repo per OM, and then each repo would have formats.js (and scripts.js and other files as necessary) so that on a side server you could just clone the OM(s) you wanted. Better still if it was possible to include OMs from formats.js perhaps along these lines:
Code:
	{
		include: './formats/inverse',
	},
	{
		include: './mods/mixandmega',
	},
 
I'm just wondering what the best way of organising OM code is; I was thinking there could be a GitHub organisation with one repo per OM, and then each repo would have formats.js (and scripts.js and other files as necessary) so that on a side server you could just clone the OM(s) you wanted. Better still if it was possible to include OMs from formats.js perhaps along these lines:
Code:
 {
include: './formats/inverse',
},
{
include: './mods/mixandmega',
},
Or, there could be one repo with folders for all OMs...
 
Now that GitHub PR #3228 has merged, many OMs that used to be mods don't have to be any more. Examples:
Code:
		onModifyTemplate: function (template, target, source, effect) {
			if (source) return;

			if (Object.values(template.baseStats).reduce((x, y) => x + y) > 350) return;

			template = Object.assign({}, template);
			template.baseStats = Object.assign({}, template.baseStats);
			for (let statName in template.baseStats) {
				template.baseStats[statName] *= 2;
			}
			return template;
		},
Code:
		onModifyTemplate: function (template, target, source, effect) {
			if (source) return;

			template = Object.assign({}, template);
			template.baseStats = {hp: 100, atk: 100, def: 100, spa: 100, spd: 100, spe: 100};
			return template;
		},
Code:
		onModifyTemplate: function (template, target, source, effect) {
			if (source) return;
			if (target.set.ability in {'Drizzle': 1, 'Drought': 1, 'Shadow Tag': 1}) return;

			let boosts = {
				'UU': 10,
				'BL2': 10,
				'RU': 20,
				'BL3': 20,
				'NU': 30,
				'BL4': 30,
				'PU': 40,
				'NFE': 40,
				'LC Uber': 40,
				'LC': 40,
			};
			let tier = template.tier;
			if (target.set.item) {
				let item = this.getItem(target.set.item);
				if (item.megaEvolves === template.species) tier = this.getTemplate(item.megaStone).tier;
			}
			if (tier[0] === '(') tier = tier.slice(1, -1);
			if (!(tier in boosts)) return;

			let boost = target.set.moves.includes('chatter') ? 30 : boosts[tier];
			template = Object.assign({}, template);
			template.baseStats = Object.assign({}, template.baseStats);
			for (let statName in template.baseStats) {
				template.baseStats[statName] += boost;
			}
			return template;
		},
Code:
		onModifyTemplate: function (template, target, source, effect) {
			if (source) return;

			if (this.baseAbility !== 'galewings') return;

			template = Object.assign({}, template);
			template.abilities = {0: 'Gale Wings'};
			return template;
		},
Code:
		onModifyTemplate: function (template, target, source, effect) {
			if (source) return;
			if (target.set.ability in {'Drizzle': 1, 'Drought': 1, 'Shadow Tag': 1}) return;

			let boosts = {
				'UU': 5,
				'BL2': 5,
				'RU': 10,
				'BL3': 10,
				'NU': 15,
				'BL4': 15,
				'PU': 20,
				'NFE': 20,
				'LC Uber': 20,
				'LC': 20,
			};
			let tier = template.tier;
			if (target.set.item) {
				let item = this.getItem(target.set.item);
				if (item.megaEvolves === template.species) tier = this.getTemplate(item.megaStone).tier;
			}
			if (tier[0] === '(') tier = tier.slice(1, -1);
			if (!(tier in boosts)) return;

			let boost = target.set.moves.includes('chatter') ? 15 : boosts[tier];
			template = Object.assign({}, template);
			template.baseStats = Object.assign({}, template.baseStats);
			for (let statName in template.baseStats) {
				template.baseStats[statName] += boost;
			}
			return template;
		},
It might also be possible to simplify the coding for Atk-Def Equality, Camomons, Cross Evolution, Gifts of the Gods, Gods Among Us, Nature Swap, Palette Pals, Therianmons and Type Control although I haven't tried that yet.
 

Rumplestiltskin

I will rain lels all over you and you will drown in them
Can someone code Status Hazard? Would be really interesting to see this OM in action.

I made a piratepad for its potential coding since I was told it's annoying/meticulous to code, feel free to PM me for the link.
 
Last edited:
I won't bore you with the usual config/formats.js boilerplate, it's nothing special. (ROM actually has a different version of getZMoveCopy and canZMove because I was fiddling around with the Z- prefix code, but this should work, as ROM's getZMoveCopy only had one extra line which I've deleted and canZMove is almost an exact copy of scripts.js anyway.)
Code:
'use strict';

exports.BattleScripts = {    
	getZMove: function (move, pokemon, skipChecks) {
		let item = pokemon.getItem();
		if (!skipChecks) {
			if (!item.zMove) return;
			if (item.zMoveUser && !item.zMoveUser.includes(pokemon.template.species)) return;
			let moveData = pokemon.getMoveData(move);
			if (!moveData || !moveData.pp) return; // Draining the PP of the base move prevents the corresponding Z-move from being used.
		}

		if (move.category === 'Status') return move.name;
		if (item.zMoveFrom) return move.name === item.zMoveFrom && item.zMove;
		return move.zMovePower && this.zMoveTable[item.zMoveType];
	},
	getZMoveCopy: function (move, pokemon) {
		move = this.getMove(move);
		if (move.category === 'Status') {
			let zMove = this.getMoveCopy(move);
			zMove.isZ = true;
			return zMove;
		}
		let item = pokemon.getItem();
		if (item.zMoveFrom) return this.getMoveCopy(item.zMove);
		let zMove = this.getMoveCopy(this.zMoveTable[item.zMoveType]);
		zMove.basePower = move.zMovePower;
		zMove.category = move.category;
		return zMove;
	},
	canZMove: function (pokemon) {
		let item = pokemon.getItem();
		if (!item.zMove) return;
		if (item.zMoveUser && !item.zMoveUser.includes(pokemon.template.species)) return;
		let atLeastOne = false;
		let zMoves = [];
		for (let i = 0; i < pokemon.moves.length; i++) {
			if (pokemon.moveset[i].pp <= 0) {
				zMoves.push(null);
				continue;
			}
			let move = this.getMove(pokemon.moves[i]);
			let zMoveName = this.getZMove(move, pokemon, true) || '';
			if (zMoveName) {
				let zMove = this.getMove(zMoveName);
				if (!zMove.isZ && zMove.category === 'Status') zMoveName = "Z-" + zMoveName;
				zMoves.push({move: zMoveName, target: zMove.target});
			} else {
				zMoves.push(null);
			}
			if (zMoveName) atLeastOne = true;
		}
		if (atLeastOne) return zMoves;
	},
}
 
Sadly with the Gen 7 mechanics changes, Nature Swap is back to being a mod again:
Code:
'use strict';

exports.BattleScripts = {
	natureModify: function (stats, nature) {
		nature = this.getNature(nature);
		if (nature.plus) {
			let stat = stats[nature.minus];
			stats[nature.minus] = stats[nature.plus];
			stats[nature.plus] = Math.floor(stat * 1.1);
		}
		return stats;
	},
};
 
Partners in Crime (updated for recentish TypeScript changes):
Code:
	{
		name: "[Gen 7] Partners in Crime",
		desc: [
			"&bullet; <a href=\"http://www.smogon.com/forums/threads/3618488/\">Partners in Crime</a>",
		],

		mod: 'pic',
		gameType: 'doubles',
		ruleset: ['[Gen 7] Doubles OU'],
		banlist: ['Kangaskhanite', 'Mawilite', 'Medichamite', /* mega bans by ability when? */'Huge Power', 'Imposter', 'Parental Bond', 'Pure Power', 'Wonder Guard', 'Mimic', 'Sketch', 'Transform'],
		onDisableMovePriority: -1,
		onDisableMove: function (pokemon) {
			let ally = pokemon.side.active.find(ally => ally && ally !== pokemon && !ally.fainted);
			if (!ally) ally = {baseMoveset: []};
			pokemon.moveset = pokemon.baseMoveset.concat(ally.baseMoveset);
		},
		onResidual: function () {
			this.eachEvent('ResetMoveset');
		},
		onResetMoveset: function (pokemon) {
			pokemon.moveset = pokemon.baseMoveset;
		},
		onSwitchInPriority: 2,
		onSwitchIn: function (pokemon) {
			if (this.p1.active.every(ally => ally && !ally.fainted)) {
				let p1a = this.p1.active[0], p1b = this.p1.active[1];
				if (p1a.ability !== p1b.ability) {
					let p1a_innate = 'ability' + p1b.ability;
					p1a.volatiles[p1a_innate] = {id: p1a_innate, target: p1a};
					let p1b_innate = 'ability' + p1a.ability;
					p1b.volatiles[p1b_innate] = {id: p1b_innate, target: p1b};
				}
			}
			if (this.p2.active.every(ally => ally && !ally.fainted)) {
				let p2a = this.p2.active[0], p2b = this.p2.active[1];
				if (p2a.ability !== p2b.ability) {
					let p2a_innate = 'ability' + p2b.ability;
					p2a.volatiles[p2a_innate] = {id: p2a_innate, target: p2a};
					let p2b_innate = 'ability' + p2a.ability;
					p2b.volatiles[p2b_innate] = {id: p2b_innate, target: p2b};
				}
			}
			let ally = pokemon.side.active.find(ally => ally && ally !== pokemon && !ally.fainted);
			if (ally && ally.ability !== pokemon.ability) {
				if (!pokemon.innate) {
					pokemon.innate = 'ability' + ally.ability;
					delete pokemon.volatiles[pokemon.innate];
					pokemon.addVolatile(pokemon.innate);
				}
				if (!ally.innate) {
					ally.innate = 'ability' + pokemon.ability;
					delete ally.volatiles[ally.innate];
					ally.addVolatile(ally.innate);
				}
			}
		},
		onSwitchOut: function (pokemon) {
			if (pokemon.innate) {
				pokemon.removeVolatile(pokemon.innate);
				delete pokemon.innate;
			}
			let ally = pokemon.side.active.find(ally => ally && ally !== pokemon && !ally.fainted);
			if (ally && ally.innate) {
				ally.removeVolatile(ally.innate);
				delete ally.innate;
			}
		},
		onFaint: function (pokemon) {
			if (pokemon.innate) {
				pokemon.removeVolatile(pokemon.innate);
				delete pokemon.innate;
			}
			let ally = pokemon.side.active.find(ally => ally && ally !== pokemon && !ally.fainted);
			if (ally && ally.innate) {
				ally.removeVolatile(ally.innate);
				delete ally.innate;
			}
		},
	},
Code:
'use strict';

exports.BattleScripts = {
	getEffect: function(name) {
		if (name && typeof name !== 'string') {
			return name;
		}
		let id = toId(name);
		if (id.startsWith('ability')) return Object.assign(Object.create(this.getAbility(id.slice(7))), {id});
		return Object.getPrototypeOf(this).getEffect.call(this, name);
	},
	pokemon: {
		setAbility: function (ability, source, effect, noForce) {
			if (!this.hp) return false;
			ability = this.battle.getAbility(ability);
			let oldAbility = this.ability;
			if (noForce && oldAbility === ability.id) {
				return false;
			}
			if (!effect || effect.id !== 'transform') {
				if (['illusion', 'multitype', 'stancechange'].includes(ability.id)) return false;
				if (['multitype', 'stancechange'].includes(oldAbility)) return false;
			}
			this.battle.singleEvent('End', this.battle.getAbility(oldAbility), this.abilityData, this, source, effect);
			let ally = this.side.active.find(ally => ally && ally !== this && !ally.fainted);
			if (ally && ally.innate) {
				ally.removeVolatile(ally.innate);
				delete ally.innate;
			}
			this.ability = ability.id;
			this.abilityData = {id: ability.id, target: this};
			if (ability.id) {
				this.battle.singleEvent('Start', ability, this.abilityData, this, source, effect);
				if (ally && ally.ability !== this.ability) {
					ally.innate = 'ability' + ability.id;
					ally.addVolatile(ally.innate);
				}
			}
			this.abilityOrder = this.battle.abilityOrder++;
			return oldAbility;
		},
		hasAbility: function (ability) {
			if (!this.ignoringAbility()) {
				if (Array.isArray(ability) ? ability.map(toId).includes(this.ability) : toId(ability) === this.ability) {
					return true;
				}
			}
			let ally = this.side.active.find(ally => ally && ally !== this && !ally.fainted);
			if (!ally || ally.ignoringAbility()) return false;
			if (Array.isArray(ability)) return ability.map(toId).includes(ally.ability);
			return toId(ability) === ally.ability;
		},
	},
}
 
Last edited:
Code:
		if (id.startsWith('ability')) return Object.assign({}, this.getAbility(id.slice(7)), {id});
Bah, this still isn't faking out the server properly for some reason... EDIT: Fixed:
Code:
		if (id.startsWith('ability')) return Object.assign(Object.create(this.getAbility(id.slice(7))), {id});
 
Last edited:

Ivy

resident enigma
is a Forum Moderatoris a Community Contributoris a Smogon Discord Contributor
Is Slayer95 still around? They did the original Linked coding and I'm hoping they'd be around to bring it forward to gen 7, but anyone else could step up to the plate. The original source code was extremely long and robust and it may not need to be as such, plus there are quite a few rule/mechanic differences between then and now. The actual OM thread for gen 7 Linked will be up on Saturday.
 
  • Like
Reactions: nv

charizard8888

Catch The Wave
is a Forum Moderator Alumnus
Some queries here

G-Luke's Ideal World
The mod includes some Pokemon getting intrinsic levitation so here's the code
typechart.js
JavaScript:
"Lev": {
        damageTaken: {
            "Bug": 0,
            "Dark": 0,
            "Dragon": 0,
            "Electric": 0,
            "Fairy": 0,
            "Fighting": 0,
            "Fire": 0,
            "Flying": 0,
            "Ghost": 0,
            "Grass": 0,
            "Ground": 3,
            "Ice": 0,
            "Normal": 0,
            "Poison": 0,
            "Psychic": 0,
            "Rock": 0,
            "Steel": 0,
            "Water": 0,
            "Lev": 0,
        },
    },
pokedex.js
JavaScript:
gastly: {
    inherit: true,
    types: ["Ghost", "Poison", "Lev"],
    abilities: {
        0: "Cursed Body"
    },
},
I ran it but it didn't work
Replay
Wanted to ask what's wrong with the code? Does the new typing need to be defined? If yes then how?
There's another way of intrinsic levitation as in GEN NEXT but this one looks easy and faster so wanted to work with this.

Eternal Pokemon
Shipwrecked Gale: Steals the opponent's stat changes before attacking, and then switches out, passing on the stolen stat changes on to the switch-in.
The move does work but doesn't show the boosted stats below the HP bar.
Replay
It's the same as Spectral Thief.
JavaScript:
"shipwreckedgale": {
    accuracy: 100,
    basePower: 70,
    category: "Physical",
    desc: "Steals the opponent's stat changes before attacking, and then switches out, passing on the stolen stat changes on to the switch-in.",
    shortDesc: "Steals the opponent's stat changes before attacking, and then switches out, passing on the stolen stat changes on to the switch-in.",
    id: "shipwreckedgale",
    isViable: true,
    name: "Shipwrecked Gale",
    pp: 20,
    priority: 0,
    flags: {contact: 1, protect: 1, mirror: 1, authentic: 1},
    stealsBoosts: true,
    selfSwitch: 'copyvolatile',
    secondary: false,
    target: "normal",
    type: "Ghost",
    zMovePower: 140,
},
Fusion Evolution
In this mod I'd need help with making the learnset of the fusion.
The fusion (For example Darkchomp) learns all the moves these two fused Pokemon and their prevos learn (In this case all the moves of Darkrai and Garchomp)
Currently it's going by copy-pasting the individual learnsets.
Is there any other way to do that from any other file like the scripts.js?

Thanks in advance! :]
 
The fusion (For example Darkchomp) learns all the moves these two fused Pokemon and their prevos learn (In this case all the moves of Darkrai and Garchomp)
Currently it's going by copy-pasting the individual learnsets.
Is there any other way to do that from any other file like the scripts.js?
If you added the two fused Pokémon as extra dex entries then you could use the new checkLearnset function in formats.js to check against each fused learnset separately. Example (untested):
JavaScript:
        checkLearnset: function (move, template, lsetData, set) {
            if (!template.fusion) return this.checkLearnset(move, template, lsetData, set);
            return this.checkLearnset(move, this.getTemplate(template.fusion[0])) || this.checkLearnset(move, this.getTemplate(template.fusion[1]));
        },
 

charizard8888

Catch The Wave
is a Forum Moderator Alumnus
If you added the two fused Pokémon as extra dex entries then you could use the new checkLearnset function in formats.js to check against each fused learnset separately. Example (untested):
JavaScript:
        checkLearnset: function (move, template, lsetData, set) {
            if (!template.fusion) return this.checkLearnset(move, template, lsetData, set);
            return this.checkLearnset(move, this.getTemplate(template.fusion[0])) || this.checkLearnset(move, this.getTemplate(template.fusion[1]));
        },
Ay thanks!
Just a quick question on that
By adding dex entries separately does that mean adding the fused Pokemon in the pokedex.js file?

Taking DarkChomp's example
Code:
darkchomp: {
        num: 7500114,
        species: "Darkchomp",
        types: ["Dark", "Dragon"],
        genderRatio: {
            M: 0.0,
            F: 0.0
        },
        baseStats: {
            hp: 109,
            atk: 130,
            def: 92,
            spa: 107,
            spd: 87,
            spe: 113
        },
        abilities: {
            0: "Sand Dreams"
        },
        heightm: 1.705,
        weightkg: 72.75,
    },
    garchomp: {
        num: 445,
        species: "Garchomp",
        types: ["Dragon", "Ground"],
        baseStats: {hp: 108, atk: 130, def: 95, spa: 80, spd: 85, spe: 102},
        abilities: {0: "Sand Veil", H: "Rough Skin"},
        heightm: 1.9,
        weightkg: 95,
        color: "Blue",
        prevo: "gabite",
        evoLevel: 48,
        eggGroups: ["Monster", "Dragon"],
        otherFormes: ["garchompmega"],
    },
    darkrai: {
        num: 491,
        species: "Darkrai",
        types: ["Dark"],
        gender: "N",
        baseStats: {hp: 70, atk: 90, def: 90, spa: 135, spd: 90, spe: 125},
        abilities: {0: "Bad Dreams"},
        heightm: 1.5,
        weightkg: 50.5,
        color: "Black",
        eggGroups: ["Undiscovered"],
    },
Then I assume that I'll have to tell Showdown in some way that Darkchomp is a fusion of both of these.
So how would it be done? By adding Darkchomp as a common forme of both of the fused Pokemon or common evolution or add in a new parameter for "fusion" somehow and add in both of the fused Pokemon as an argument.
 

Pikachuun

the entire waruda machine
So how would it be done? By adding Darkchomp as a common forme of both of the fused Pokemon or common evolution or add in a new parameter for "fusion" somehow and add in both of the fused Pokemon as an argument.
From what I know about how the template structure works and going by urkerab's code, you simply would add fusion: ["darkrai", "garchomp"], into the Pokedex entry since the pokedex data gets passed through to it.
As a nitpick, try to keep your code consistent with the rest of the dex file. As in using gender: "N", instead of your genderRatio bit, making baseStats/abilities on one line including the color, egg group(s)... it won't make it any more/less functional but it's always good to do so for stylistic reasons (plus in the case of getting data through commands the last two may be important...).
 
Hello I really want to create a playable tier with all the luck factors removed. Every single luck factor just gone.

This is a pretty huge task and would require more changes to code than most OMs I think.
The easiest way I am thinking to do this would be to adjust the damage calculation to always be min, max or somewhere in between (just make it constant), remove critical hits and secondary effects, misses etc. and everything else that is a luck factor is either removed (full para, effect spore, etc) or made constant (1 or 2 turns of sleep, multi-hit moves hit a set number of times, etc.)

Anyways this could lead to a lot of discussion and explanation, which is not exactly what I want but I'm not opposed to it :)
I just want someone to tell me how I can accomplish this task myself. If someone would be willing to help me that would be nice :)

I'm just thinking that I play pokemon showdown so often and I feel like it is a bad habit. I want to turn my bad habit into something productive (at least in my eyes) by creating a luck free tier.
How can I code this so it can be implemented into a ps server?
 

Rumplestiltskin

I will rain lels all over you and you will drown in them
Hello I really want to create a playable tier with all the luck factors removed. Every single luck factor just gone.

This is a pretty huge task and would require more changes to code than most OMs I think.
The easiest way I am thinking to do this would be to adjust the damage calculation to always be min, max or somewhere in between (just make it constant), remove critical hits and secondary effects, misses etc. and everything else that is a luck factor is either removed (full para, effect spore, etc) or made constant (1 or 2 turns of sleep, multi-hit moves hit a set number of times, etc.)

Anyways this could lead to a lot of discussion and explanation, which is not exactly what I want but I'm not opposed to it :)
I just want someone to tell me how I can accomplish this task myself. If someone would be willing to help me that would be nice :)

I'm just thinking that I play pokemon showdown so often and I feel like it is a bad habit. I want to turn my bad habit into something productive (at least in my eyes) by creating a luck free tier.
How can I code this so it can be implemented into a ps server?
What you're talking about has been attempted already, it's called Skillmons, and the code is here. It was a pet mod though and Joim wanted to remake it so it could be classified as an OM.
 
What you're talking about has been attempted already, it's called Skillmons, and the code is here. It was a pet mod though and Joim wanted to remake it so it could be classified as an OM.
Thank you very much! It looks like that code was for gen 6, still amazing! If I wanted to have that code implemented into a server (with admins permission and all) how could it be done so it could be played?
 

charizard8888

Catch The Wave
is a Forum Moderator Alumnus
From what I know about how the template structure works and going by urkerab's code, you simply would add fusion: ["darkrai", "garchomp"], into the Pokedex entry since the pokedex data gets passed through to it.
As a nitpick, try to keep your code consistent with the rest of the dex file. As in using gender: "N", instead of your genderRatio bit, making baseStats/abilities on one line including the color, egg group(s)... it won't make it any more/less functional but it's always good to do so for stylistic reasons (plus in the case of getting data through commands the last two may be important...).
ground immunity checks isGrounded, which has flying type hardcoded in
Sorry for the late reply but thanks a lot!
I've added checkLearnset in the formats.js and the fusion parameter in pokedex.js (along with the dex entries of the fused Pokemon) but it isn't working which I think is most probably because Dragon Heaven hasn't been updated with main for a very long time, will return to it after the update.
JavaScript:
{
          name: "[Gen 7] Fusion Evolution",
          desc: ["&bullet; <a href=http://www.smogon.com/forums/threads/fusion-evolution-v2-submission-phase.3560216/>Fusion Evolution</a>",
                 "&bullet; <a href=http://www.smogon.com/forums/threads/fusion-moves-fusion-evolution-companion-project.3564805/>Fusion Moves</a>",
                ],
          ruleset: ['Pokemon', 'Sleep Clause Mod', 'Species Clause', 'Moody Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview', 'Swagger Clause', 'Baton Pass Clause'],
        //banlist: ['Unreleased', 'Illegal'],
          mod: 'fe',
          checkLearnset: function (move, template, lsetData, set) {
              if (!template.fusion) return this.checkLearnset(move, template, lsetData, set);
              return this.checkLearnset(move, this.getTemplate(template.fusion[0])) || this.checkLearnset(move, this.getTemplate(template.fusion[1]));
          },
      },
And now I know why the /felist command (A command which displays a clickable list of coded fusions) takes so much time. I just run the code into jsbeatuifiermost of the time. I'll try to find out better alignment and liner break settings for it or look for another beautifier.

For altering the Lev type, it worked when I edited the main sim/pokemon.js file of the server [https://replay.pokemonshowdown.com/dragonheaven-gen7glukesidealworld-50457] but not when I copied it into the mods folder so does that mean that pokemon.js can't be edited from mods? (Sorry I'm bad and don't know) It wouldn't cause any trouble if I do it from Pokemon.js as well since Lev typing doesn't exist outside of the mod but that would break the organisation.

Thank you very much! It looks like that code was for gen 6, still amazing! If I wanted to have that code implemented into a server (with admins permission and all) how could it be done so it could be played?
First you'll have to put this in formats.js of your server
Code:
{
        name: "Skillmons",
        desc: ["&bullet; <a href=https://www.smogon.com/forums/threads/.3524601/>Skillmons</a>",],
        mod: 'skillmons',
        ruleset: ['Pokemon', 'Team Preview', 'Sleep Clause Mod', 'Species Clause', 'Endless Battle Clause', 'Exact HP Mod', 'Baton Pass Clause'],
        banlist: ['Unreleased', 'Illegal'],
    },

Then go to the mods folder and make a new folder for the said Pet Mod, which would be skillmons

Then make a new file in the skillmons folder named scripts.js and add the scripts.js code in it
Followed by a new file named abilities.js and its code in it (Can be found in the link which Rumplestiltskin gave), and the same for items.js, moves.js, and statuses.js
After that /updateserver and /hotpatch formats (or restart the server) and it'll show up on the formats list. Feel free to ping me if it didn't work.
 

Users Who Are Viewing This Thread (Users: 1, Guests: 0)

Top