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
Gen 7 OMs
Also, useful references:
Credits: AWailOfATail, Joim, Kris, Pikachuun, Scarfnaut, Slayer95, Snaquaza, The Immortal, urkerab, XpRienzo, me, and anyone whos name i forgot
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.",
"• <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émon to Team Preview and choose only two.",
"• <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.",
"• <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émon have an added type determined by their IVs. Same as the Hidden Power type.",
"• <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: ["• <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émon receives one base stat, depending on its position, from the Uber.",
"• <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: ["• <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: ["• <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: ["• <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: ["• <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émon in the first slot is the God; the Followers must share a type with the God. If the God Pokémon faints, the Followers are inflicted with Curse.",
"• <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émon have all their natural abilities at the same time.",
"• <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:
- Github repository for Dragon Heaven server.
- Old Seasonals orphan branch in main server's Github repository.
Credits: AWailOfATail, Joim, Kris, Pikachuun, Scarfnaut, Slayer95, Snaquaza, The Immortal, urkerab, XpRienzo, me, and anyone whos name i forgot
Last edited: