mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-09-13 03:35:42 -05:00
Super Staff Bros 4 (#7793)
Collaborative Project lead by @xInstruct with many contributors. See the Special Thanks section of https://www.smogon.com/articles/super-staff-bros-4
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
config/formats.ts @TheImmortal
|
||||
data/mods/*/random-teams.ts @TheImmortal
|
||||
data/mods/ssb/ @HoeenCoder
|
||||
data/mods/ssb/ @HoeenCoder @xInstruct
|
||||
data/random-teams.ts @TheImmortal
|
||||
data/text/ @Marty-D
|
||||
databases/ @monsanto
|
||||
|
||||
2
build
2
build
@@ -96,7 +96,7 @@ sucrase('./lib', './.lib-dist');
|
||||
|
||||
if (sucrase('./server', './.server-dist')) {
|
||||
replace('.server-dist', [
|
||||
{regex: /(require\(.*?)(lib|sim)/g, replace: `$1.$2-dist`},
|
||||
{regex: /(require\(.*?)(data|lib|sim)/g, replace: `$1.$2-dist`},
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1355,6 +1355,44 @@ export const Formats: FormatList = [
|
||||
team: 'random',
|
||||
ruleset: ['Obtainable', 'Same Type Clause', 'HP Percentage Mod', 'Cancel Mod', 'Sleep Clause Mod'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 8] Super Staff Bros 4",
|
||||
desc: "The fourth iteration of Super Staff Bros is here! Battle with a random team of pokemon created by the sim staff.",
|
||||
threads: [
|
||||
`• <a href="https://www.smogon.com/articles/super-staff-bros-4">Introduction & Roster</a>`,
|
||||
],
|
||||
|
||||
mod: 'ssb',
|
||||
team: 'randomStaffBros',
|
||||
ruleset: ['Dynamax Clause', 'HP Percentage Mod', 'Cancel Mod', 'Sleep Clause Mod'],
|
||||
onBegin() { // TODO look into making an event to put this right after turn|1
|
||||
// https://discordapp.com/channels/630837856075513856/630845310033330206/716126469528485909
|
||||
// Requires client change
|
||||
this.add(`raw|<div class='broadcast-green'><b>Wondering what all these custom moves, abilities, and items do?<br />Check out the <a href="https://www.smogon.com/articles/super-staff-bros-4" target="_blank">Super Staff Bros 4 Guide</a> or use /ssb to find out!</b></div>`);
|
||||
|
||||
this.add('message', [
|
||||
'THE BATTLE FOR SURVIVAL BEGINS!', 'WHO WILL SURVIVE?', 'GET READY TO KEEP UP!', 'GET READY!', 'DARE TO BELIEVE YOU CAN SURVIVE!', 'THERE CAN BE ONLY ONE WINNER!', 'GET READY FOR THE FIGHT OF YOUR LIFE!', 'WHO WILL PREVAIL?', 'ONLY ONE TEAM WILL BE LEFT STANDING!', 'BATTLE WITHOUT LIMITS!',
|
||||
][this.random(10)]);
|
||||
this.add('message', 'FIGHT!');
|
||||
},
|
||||
onSwitchInPriority: 100,
|
||||
onSwitchIn(pokemon) {
|
||||
let name: string = this.toID(pokemon.illusion ? pokemon.illusion.name : pokemon.name);
|
||||
if (this.dex.getSpecies(name).exists || this.dex.getMove(name).exists || this.dex.getAbility(name).exists) {
|
||||
// Certain pokemon have volatiles named after their id
|
||||
// To prevent overwriting those, and to prevent accidentaly leaking
|
||||
// that a pokemon is on a team through the onStart even triggering
|
||||
// at the start of a match, users with pokemon names will need their
|
||||
// statuses to end in "user".
|
||||
name = name + 'user';
|
||||
}
|
||||
// Add the mon's status effect to it as a volatile.
|
||||
const status = this.dex.getEffect(name);
|
||||
if (status?.exists) {
|
||||
pokemon.addVolatile(name, pokemon);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "[Gen 8] Challenge Cup 1v1",
|
||||
|
||||
@@ -1463,40 +1501,6 @@ export const Formats: FormatList = [
|
||||
searchShow: false,
|
||||
ruleset: ['HP Percentage Mod', 'Cancel Mod'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 7] Super Staff Bros Brawl",
|
||||
desc: "Super Staff Bros returns for another round! Battle with a random team of pokemon created by the sim staff.",
|
||||
threads: [
|
||||
`• <a href="https://www.smogon.com/articles/super-staff-bros-brawl">Introduction & Roster</a>`,
|
||||
],
|
||||
|
||||
mod: 'ssb',
|
||||
team: 'randomStaffBros',
|
||||
ruleset: ['HP Percentage Mod', 'Cancel Mod', 'Sleep Clause Mod'],
|
||||
onBegin() {
|
||||
this.add('raw|SUPER STAFF BROS <b>BRAWL</b>!!');
|
||||
this.add('message', 'GET READY FOR THE NEXT BATTLE!');
|
||||
if (this.teamGenerator.allXfix) this.add(`c|~HoeenHero|Oops I dropped my bag of xfix sets sorry!`);
|
||||
this.add(`raw|<div class='broadcast-green'><b>Wondering what all these custom moves, abilities, and items do?<br />Check out the <a href="https://www.smogon.com/articles/super-staff-bros-brawl" target="_blank">Super Staff Bros Brawl Guide</a> and find out!</b></div>`);
|
||||
},
|
||||
onSwitchInPriority: 100,
|
||||
onSwitchIn(pokemon) {
|
||||
let name: string = this.toID(pokemon.illusion ? pokemon.illusion.name : pokemon.name);
|
||||
if (this.dex.getSpecies(name).exists || name === 'rage') {
|
||||
// Certain pokemon have volatiles named after their id
|
||||
// To prevent overwriting those, and to prevent accidentaly leaking
|
||||
// that a pokemon is on a team through the onStart even triggering
|
||||
// at the start of a match, users with pokemon names will need their
|
||||
// statuses to end in "user".
|
||||
name = name + 'user';
|
||||
}
|
||||
// Add the mon's status effect to it as a volatile.
|
||||
const status = this.dex.getEffect(name);
|
||||
if (status?.exists) {
|
||||
pokemon.addVolatile(name, pokemon);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "[Gen 7 Let's Go] Random Battle",
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ export const Aliases: {[alias: string]: string} = {
|
||||
monorandom: "[Gen 8] Monotype Random Battle",
|
||||
bf: "[Gen 7] Battle Factory",
|
||||
bssf: "[Gen 7] BSS Factory",
|
||||
ssb: "[Gen 7] Super Staff Bros Brawl",
|
||||
ssb: "[Gen 8] Super Staff Bros 4",
|
||||
ssb4: "[Gen 8] Super Staff Bros 4",
|
||||
lgrandom: "[Gen 7] Let's Go Random Battle",
|
||||
gen6bf: "[Gen 6] Battle Factory",
|
||||
gen7mono: "[Gen 7] Monotype",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,147 +1,69 @@
|
||||
export const Items: {[k: string]: ModdedItemData} = {
|
||||
// Aeonic
|
||||
noseiumz: {
|
||||
name: "Noseium Z",
|
||||
// Alpha
|
||||
caioniumz: {
|
||||
name: "Caionium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Shitpost",
|
||||
zMoveFrom: "Fissure",
|
||||
itemUser: ["Nosepass"],
|
||||
gen: 7,
|
||||
desc: "If held by a Nosepass with Fissure, it can use Shitpost.",
|
||||
zMove: "Blistering Ice Age",
|
||||
zMoveFrom: "Blizzard",
|
||||
itemUser: ["Aurorus"],
|
||||
gen: 8,
|
||||
desc: "If held by an Aurorus with Blizzard, it can use Blistering Ice Age.",
|
||||
},
|
||||
// E4 Flint
|
||||
magmarizer: {
|
||||
inherit: true,
|
||||
megaStone: "Steelix-Mega",
|
||||
megaEvolves: "Steelix",
|
||||
onTakeItem(item, source) {
|
||||
if (item.megaEvolves === source.baseSpecies.baseSpecies) return false;
|
||||
return true;
|
||||
|
||||
// A Quag To The Past
|
||||
quagniumz: {
|
||||
name: "Quagnium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Bounty Place",
|
||||
zMoveFrom: "Scorching Sands",
|
||||
itemUser: ["Quagsire"],
|
||||
gen: 8,
|
||||
desc: "If held by a Quagsire with Scorching Sands, it can use Bounty Place.",
|
||||
},
|
||||
|
||||
// Kalalokki
|
||||
kalalokkiumz: {
|
||||
name: "Kalalokkium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Gaelstrom",
|
||||
zMoveFrom: "Blackbird",
|
||||
itemUser: ["Wingull"],
|
||||
gen: 8,
|
||||
desc: "If held by a Wingull with Blackbird, it can use Gaelstrom.",
|
||||
},
|
||||
|
||||
// Robb576
|
||||
modium6z: {
|
||||
name: "Modium-6 Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Integer Overflow",
|
||||
zMoveFrom: "Photon Geyser",
|
||||
itemUser: ["Necrozma-Ultra"],
|
||||
gen: 8,
|
||||
desc: "If held by a Robb576 with Photon Geyser, it can use Integer Overflow.",
|
||||
},
|
||||
|
||||
// xJoelituh
|
||||
rarebone: {
|
||||
onModifyAtkPriority: 2,
|
||||
onModifyAtk() {
|
||||
return this.chainModify(1.5);
|
||||
},
|
||||
fling: undefined, // Cannot be flung now since its a mega stone
|
||||
desc: "If held by a Steelix, this item allows it to Mega Evolve in battle.",
|
||||
},
|
||||
// FOMG
|
||||
astleyiumz: {
|
||||
name: "Astleyium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Rickrollout",
|
||||
zMoveFrom: "Rock Slide",
|
||||
itemUser: ["Golem"],
|
||||
gen: 7,
|
||||
desc: "If held by a Golem with Rock Slide, it can use Rickrollout.",
|
||||
},
|
||||
// inactive
|
||||
dusknoiriumz: {
|
||||
name: "Dusknoirium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Petrifying Gaze",
|
||||
zMoveFrom: "Mean Look",
|
||||
itemUser: ["Dusknoir"],
|
||||
gen: 7,
|
||||
desc: "If held by a Dusknoir with Mean Look, it can use Petrifying Gaze.",
|
||||
},
|
||||
// Kris
|
||||
thunderstone: {
|
||||
inherit: true,
|
||||
// @ts-ignore
|
||||
megaStone: ["Rotom-Wash", "Rotom-Mow", "Rotom-Heat", "Rotom-Frost", "Rotom-Fan"],
|
||||
megaEvolves: "Rotom",
|
||||
onTakeItem(item, source) {
|
||||
if (item.megaEvolves === source.baseSpecies.baseSpecies) return false;
|
||||
return true;
|
||||
onModifyDefPriority: 2,
|
||||
onModifyDef() {
|
||||
return this.chainModify(1.5);
|
||||
},
|
||||
fling: undefined, // Cannot be flung now since its a mega stone
|
||||
desc: "If held by a Rotom, this item allows it to Mega Evolve in battle.",
|
||||
shortDesc: "If held by a Rotom, this item allows it to Mega Evolve in battle.",
|
||||
},
|
||||
// MajorBowman
|
||||
victiniumz: {
|
||||
name: "Victinium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Blaze of Glory",
|
||||
zMoveFrom: "V-create",
|
||||
itemUser: ["Victini"],
|
||||
gen: 7,
|
||||
desc: "If held by a Victini with V-create, it can use Blaze of Glory.",
|
||||
},
|
||||
// Pohjis
|
||||
marowakiumz: {
|
||||
name: "Marowakium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Great Eqake",
|
||||
zMoveFrom: "Earthquake",
|
||||
itemUser: ["Marowak"],
|
||||
gen: 7,
|
||||
desc: "If held by a Marowak with Earthquake, it can use Great Eqake.",
|
||||
},
|
||||
// SamJo
|
||||
thicciniumz: {
|
||||
name: "Thiccinium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Extra T h i c c",
|
||||
zMoveFrom: "Thicc",
|
||||
itemUser: ["Mamoswine"],
|
||||
gen: 7,
|
||||
desc: "If held by a Mamoswine with Thicc, it can use Extra T h i c c.",
|
||||
},
|
||||
// Schiavetto
|
||||
mariahcariumz: {
|
||||
name: "Mariahcarium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Plurshift",
|
||||
zMoveFrom: "Poison Jab",
|
||||
itemUser: ["Scolipede"],
|
||||
gen: 7,
|
||||
desc: "If held by a Scolipede with Poison Jab, it can use Plurshift.",
|
||||
},
|
||||
// Snaquaza
|
||||
fakeclaimiumz: {
|
||||
name: "Fakeclaimium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Fake Claim",
|
||||
// @ts-ignore hack for Snaquaza's Z move.
|
||||
zMoveFrom: ["Brave Bird", "Superpower", "Sucker Punch", "Flamethrower", "Ice Beam", "Thunderbolt"],
|
||||
itemUser: ["Honchkrow"],
|
||||
gen: 7,
|
||||
desc: "If held by a Honchkrow, it can use Fake Claim.",
|
||||
},
|
||||
// The Immortal
|
||||
buzzniumz: {
|
||||
name: "Buzznium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Ultra Succ",
|
||||
zMoveFrom: "Drain Punch",
|
||||
itemUser: ["Buzzwole"],
|
||||
gen: 7,
|
||||
desc: "If held by a Buzzwole with Drain Punch, it can use Ultra Succ.",
|
||||
},
|
||||
// Teclis
|
||||
darkrainiumz: {
|
||||
name: "Darkrainium Z",
|
||||
isNonstandard: "Custom",
|
||||
onTakeItem: false,
|
||||
zMove: "Absolute Configuration",
|
||||
zMoveFrom: "Dark Void",
|
||||
itemUser: ["Darkrai"],
|
||||
gen: 7,
|
||||
desc: "If held by a Darkrai with Dark Void, it can use Absolute Configuration.",
|
||||
},
|
||||
// XpRienzo
|
||||
charcoal: {
|
||||
inherit: true,
|
||||
zMove: "Bleh Flame",
|
||||
zMoveFrom: "Blue Flare",
|
||||
itemUser: ["Reshiram"],
|
||||
desc: "Fire-type attacks have 1.2x power. Reshiram with Blue Flare can use Bleh Flame.",
|
||||
onModifySpDPriority: 2,
|
||||
onModifySpD() {
|
||||
return this.chainModify(1.5);
|
||||
},
|
||||
gen: 4,
|
||||
name: "Rare Bone",
|
||||
desc: "1.5x to Attack, Defense, and Special Defense.",
|
||||
shortDesc: "1.5x to Attack, Defense, and Special Defense.",
|
||||
},
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,186 +6,254 @@ export const Pokedex: {[k: string]: ModdedSpeciesData} = {
|
||||
baseStats: {hp: 100, atk: 100, def: 100, spa: 100, spd: 100, spe: 100}, // the base stats for the pokemon
|
||||
},
|
||||
*/
|
||||
// ACakeWearingAHat
|
||||
dunsparce: {
|
||||
// Abdelrahman
|
||||
cameruptmega: {
|
||||
inherit: true,
|
||||
types: ['Normal', 'Ghost'],
|
||||
abilities: {0: "Water Absorb"},
|
||||
},
|
||||
// Akiamara
|
||||
croagunk: {
|
||||
// Aelita
|
||||
zygardecomplete: {
|
||||
inherit: true,
|
||||
baseStats: {hp: 83, atk: 106, def: 65, spa: 86, spd: 65, spe: 85},
|
||||
abilities: {0: "Scyphozoa"},
|
||||
},
|
||||
// Arrested
|
||||
blastoisemega: {
|
||||
// aegii
|
||||
aegislash: {
|
||||
inherit: true,
|
||||
abilities: {0: "Shell Shocker"},
|
||||
abilities: {0: "Set the Stage"},
|
||||
},
|
||||
// Birdy
|
||||
oricorio: {
|
||||
aegislashblade: {
|
||||
inherit: true,
|
||||
abilities: {0: "Arabesque"},
|
||||
abilities: {0: "Set the Stage"},
|
||||
},
|
||||
oricoriopau: {
|
||||
// Aeonic
|
||||
nosepass: {
|
||||
inherit: true,
|
||||
abilities: {0: "Arabesque"},
|
||||
baseStats: {hp: 70, atk: 85, def: 135, spa: 45, spd: 90, spe: 70},
|
||||
},
|
||||
oricoriopompom: {
|
||||
// Aethernum
|
||||
lotad: {
|
||||
inherit: true,
|
||||
abilities: {0: "Arabesque"},
|
||||
baseStats: {hp: 40, atk: 70, def: 70, spa: 80, spd: 90, spe: 70},
|
||||
},
|
||||
oricoriosensu: {
|
||||
// Annika
|
||||
mewtwomegay: {
|
||||
inherit: true,
|
||||
abilities: {0: "Arabesque"},
|
||||
abilities: {0: "Overprotective"},
|
||||
},
|
||||
// E4 Flint
|
||||
steelixmega: {
|
||||
// A Quag To The Past
|
||||
quagsire: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Stark Mountain'},
|
||||
types: ['Steel', 'Ground', 'Fire'],
|
||||
baseStats: {hp: 95, atk: 65, def: 85, spa: 65, spd: 85, spe: 35},
|
||||
},
|
||||
// Eien
|
||||
mew: {
|
||||
// Billo
|
||||
cosmog: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Psychic Surge'},
|
||||
baseStats: {hp: 86, atk: 58, def: 62, spa: 87, spd: 62, spe: 74},
|
||||
},
|
||||
// dogknees
|
||||
furret: {
|
||||
inherit: true,
|
||||
types: ["Normal", "Ghost"],
|
||||
},
|
||||
// Elgino
|
||||
mimikyubusted: {
|
||||
celebi: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Gib love pls'},
|
||||
types: ["Grass", "Fairy"],
|
||||
},
|
||||
// eternally
|
||||
ducklett: {
|
||||
// EpicNikolai
|
||||
garchompmega: {
|
||||
inherit: true,
|
||||
// Doubled def, spa, spd and spe
|
||||
baseStats: {hp: 62, atk: 44, def: 100, spa: 88, spd: 100, spe: 110},
|
||||
abilities: {0: "Dragon Heart"},
|
||||
types: ["Dragon", "Fire"],
|
||||
},
|
||||
// fart
|
||||
kartana: {
|
||||
// Felucia
|
||||
uxie: {
|
||||
inherit: true,
|
||||
types: ['Fairy', 'Steel'],
|
||||
types: ["Psychic", "Normal"],
|
||||
},
|
||||
// frostyicelad
|
||||
laprasgmax: {
|
||||
inherit: true,
|
||||
heightm: 2.5,
|
||||
weightkg: 220,
|
||||
},
|
||||
// GMars
|
||||
minior: {
|
||||
inherit: true,
|
||||
abilities: {0: 'mysteryshell'},
|
||||
abilities: {0: "Capsule Armor"},
|
||||
},
|
||||
miniorviolet: {
|
||||
inherit: true,
|
||||
abilities: {0: "Capsule Armor"},
|
||||
},
|
||||
miniorindigo: {
|
||||
inherit: true,
|
||||
abilities: {0: "Capsule Armor"},
|
||||
},
|
||||
miniorblue: {
|
||||
inherit: true,
|
||||
abilities: {0: "Capsule Armor"},
|
||||
},
|
||||
miniorgreen: {
|
||||
inherit: true,
|
||||
abilities: {0: "Capsule Armor"},
|
||||
},
|
||||
minioryellow: {
|
||||
inherit: true,
|
||||
abilities: {0: "Capsule Armor"},
|
||||
},
|
||||
miniororange: {
|
||||
inherit: true,
|
||||
abilities: {0: "Capsule Armor"},
|
||||
},
|
||||
miniormeteor: {
|
||||
inherit: true,
|
||||
abilities: {0: 'mysteryshell'},
|
||||
abilities: {0: "Capsule Armor"},
|
||||
},
|
||||
// grimAuxiliatrix
|
||||
aggronmega: {
|
||||
// Hydro
|
||||
pichu: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Intimidate'},
|
||||
types: ["Electric", "Water"],
|
||||
baseStats: {hp: 70, atk: 80, def: 55, spa: 75, spd: 75, spe: 100},
|
||||
},
|
||||
// guishark
|
||||
sharpedomega: {
|
||||
// Inactive
|
||||
gyaradosmega: {
|
||||
inherit: true,
|
||||
abilities: {0: 'gz guishark'},
|
||||
abilities: {0: "Dragon's Fury"},
|
||||
},
|
||||
// Jho
|
||||
toxtricity: {
|
||||
inherit: true,
|
||||
abilities: {0: "Punk Rock"},
|
||||
},
|
||||
toxtricitylowkey: {
|
||||
inherit: true,
|
||||
abilities: {0: "Venomize"},
|
||||
},
|
||||
// Kaiju Bunny
|
||||
gliscor: {
|
||||
lopunnymega: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Poison Heal'}, // Ability change is permanent
|
||||
abilities: {0: "Second Wind"},
|
||||
types: ["Normal", "Fairy"],
|
||||
},
|
||||
// Kris
|
||||
rotomfan: {
|
||||
unown: {
|
||||
inherit: true,
|
||||
abilities: {0: "Adaptability"},
|
||||
baseStats: {hp: 50, atk: 65, def: 127, spa: 145, spd: 127, spe: 106},
|
||||
baseStats: {hp: 100, atk: 100, def: 100, spa: 100, spd: 100, spe: 100},
|
||||
// For reverting back to an Unown forme
|
||||
abilities: {0: "Protean"},
|
||||
},
|
||||
rotomfrost: {
|
||||
// Lamp
|
||||
lampent: {
|
||||
inherit: true,
|
||||
abilities: {0: "Adaptability"},
|
||||
baseStats: {hp: 50, atk: 65, def: 127, spa: 145, spd: 127, spe: 106},
|
||||
baseStats: {hp: 60, atk: 80, def: 100, spa: 135, spd: 100, spe: 95},
|
||||
},
|
||||
rotomheat: {
|
||||
// Meicoo
|
||||
venusaurmega: {
|
||||
inherit: true,
|
||||
abilities: {0: "Adaptability"},
|
||||
baseStats: {hp: 50, atk: 65, def: 127, spa: 145, spd: 127, spe: 106},
|
||||
abilities: {0: "Unaware"},
|
||||
},
|
||||
rotommow: {
|
||||
// nui
|
||||
jigglypuff: {
|
||||
inherit: true,
|
||||
abilities: {0: "Adaptability"},
|
||||
baseStats: {hp: 50, atk: 65, def: 127, spa: 145, spd: 127, spe: 106},
|
||||
},
|
||||
rotomwash: {
|
||||
inherit: true,
|
||||
abilities: {0: "Adaptability"},
|
||||
baseStats: {hp: 50, atk: 65, def: 127, spa: 145, spd: 127, spe: 106},
|
||||
},
|
||||
// Level 51
|
||||
porygon2: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Stamina'},
|
||||
},
|
||||
// MacChaeger
|
||||
mantyke: {
|
||||
inherit: true,
|
||||
baseStats: {hp: 90, atk: 40, def: 100, spa: 120, spd: 240, spe: 100},
|
||||
},
|
||||
// martha
|
||||
dianciemega: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Pixilate'},
|
||||
},
|
||||
// Morfent
|
||||
banettemega: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Comatose'},
|
||||
},
|
||||
// OM
|
||||
flareon: {
|
||||
inherit: true,
|
||||
types: ['Fire', 'Fairy'],
|
||||
baseStats: {hp: 115, atk: 128, def: 62, spa: 128, spd: 78, spe: 62},
|
||||
},
|
||||
// Overneat
|
||||
absolmega: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Filter'},
|
||||
types: ['Dark', 'Fairy'],
|
||||
abilities: {0: "Fluffy"},
|
||||
types: ["Dark", "Fairy"],
|
||||
},
|
||||
// Pirate Princess
|
||||
gulpin: {
|
||||
// PartMan
|
||||
chandelure: {
|
||||
inherit: true,
|
||||
baseStats: {hp: 70, atk: 43, def: 53, spa: 86, spd: 53, spe: 40},
|
||||
},
|
||||
// pre
|
||||
deoxys: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Optimize'},
|
||||
},
|
||||
deoxysattack: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Optimize'},
|
||||
},
|
||||
deoxysdefense: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Optimize'},
|
||||
},
|
||||
deoxysspeed: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Optimize'},
|
||||
abilities: {0: "Hecatomb"},
|
||||
},
|
||||
// Psynergy
|
||||
blazikenmega: {
|
||||
rayquaza: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Wrath'},
|
||||
abilities: {0: "Supernova"},
|
||||
},
|
||||
rayquazamega: {
|
||||
inherit: true,
|
||||
abilities: {0: "Supernova"},
|
||||
requiredMove: "Clear Breath",
|
||||
},
|
||||
// Robb576
|
||||
necrozmadawnwings: {
|
||||
inherit: true,
|
||||
abilities: {0: "The Numbers Game"},
|
||||
},
|
||||
necrozmaduskmane: {
|
||||
inherit: true,
|
||||
abilities: {0: "The Numbers Game"},
|
||||
},
|
||||
necrozmaultra: {
|
||||
inherit: true,
|
||||
abilities: {0: "The Numbers Game"},
|
||||
},
|
||||
// Strucni
|
||||
aggronmega: {
|
||||
inherit: true,
|
||||
abilities: {0: "Overasked Clause"},
|
||||
},
|
||||
// Finland
|
||||
alcremie: {
|
||||
inherit: true,
|
||||
abilities: {0: "Winding Song"},
|
||||
},
|
||||
// vivalospride's interaction with Coconut's move
|
||||
darumaka: {
|
||||
inherit: true,
|
||||
evos: ["Darmanitan", "Darmanitan-Zen"],
|
||||
},
|
||||
darmanitanzen: {
|
||||
inherit: true,
|
||||
prevo: "Darumaka",
|
||||
},
|
||||
// yuki
|
||||
pikachucosplay: {
|
||||
inherit: true,
|
||||
baseStats: {hp: 60, atk: 85, def: 50, spa: 95, spd: 85, spe: 110},
|
||||
abilities: {0: "Combat Training"},
|
||||
},
|
||||
pikachuphd: {
|
||||
inherit: true,
|
||||
baseStats: {hp: 60, atk: 85, def: 50, spa: 95, spd: 85, spe: 110},
|
||||
abilities: {0: "Triage"},
|
||||
},
|
||||
// Rach
|
||||
pikachulibre: {
|
||||
inherit: true,
|
||||
types: ['Electric', 'Fighting'],
|
||||
baseStats: {hp: 60, atk: 85, def: 50, spa: 95, spd: 85, spe: 110},
|
||||
abilities: {0: "White Smoke"},
|
||||
},
|
||||
// Sunny
|
||||
sceptilemega: {
|
||||
pikachupopstar: {
|
||||
inherit: true,
|
||||
abilities: {0: 'Contrary'},
|
||||
baseStats: {hp: 60, atk: 85, def: 50, spa: 95, spd: 85, spe: 110},
|
||||
abilities: {0: "Dancer"},
|
||||
},
|
||||
pikachurockstar: {
|
||||
inherit: true,
|
||||
baseStats: {hp: 60, atk: 85, def: 50, spa: 95, spd: 85, spe: 110},
|
||||
abilities: {0: "Punk Rock"},
|
||||
},
|
||||
pikachubelle: {
|
||||
inherit: true,
|
||||
baseStats: {hp: 60, atk: 85, def: 50, spa: 95, spd: 85, spe: 110},
|
||||
abilities: {0: "Tangled Feet"},
|
||||
},
|
||||
// Zalm
|
||||
weedle: {
|
||||
inherit: true,
|
||||
baseStats: {hp: 85, atk: 100, def: 90, spa: 20, spd: 90, spe: 90},
|
||||
baseStats: {hp: 100, atk: 35, def: 100, spa: 90, spd: 90, spe: 100},
|
||||
},
|
||||
// Zarel
|
||||
meloetta: {
|
||||
inherit: true,
|
||||
abilities: {0: "Dancer"},
|
||||
},
|
||||
meloettapirouette: {
|
||||
inherit: true,
|
||||
abilities: {0: "Serene Grace"},
|
||||
},
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,17 @@
|
||||
*/
|
||||
|
||||
import {FS} from "../../lib/fs";
|
||||
import {SSBSet, ssbSets} from "../../data/mods/ssb/random-teams";
|
||||
import {Utils} from "../../lib/utils";
|
||||
|
||||
const GEN_NAMES: {[k: string]: string} = {
|
||||
gen1: '[Gen 1]', gen2: '[Gen 2]', gen3: '[Gen 3]', gen4: '[Gen 4]', gen5: '[Gen 5]', gen6: '[Gen 6]', gen7: '[Gen 7]',
|
||||
};
|
||||
|
||||
const STAT_NAMES: {[k: string]: string} = {
|
||||
hp: "HP", atk: "Atk", def: "Def", spa: "SpA", spd: "SpD", spe: "Spe",
|
||||
};
|
||||
|
||||
const TIERS: {[k: string]: string} = {
|
||||
uber: "Uber", ubers: "Uber",
|
||||
ou: "OU", uu: "UU", ru: "RU", nu: "NU", pu: "PU",
|
||||
@@ -95,9 +101,6 @@ function battleFactorySets(species: string | Species, tier: string | null, gen =
|
||||
);
|
||||
if (!Object.keys(statsFile).length) return null;
|
||||
let buf = ``;
|
||||
const statNames: {[k: string]: string} = {
|
||||
hp: "HP", atk: "Atk", def: "Def", spa: "SpA", spd: "SpD", spe: "Spe",
|
||||
};
|
||||
if (!isBSS) {
|
||||
if (!tier) return {e: `Please provide a valid tier.`};
|
||||
if (!(toID(tier) in TIERS)) return {e: `That tier isn't supported.`};
|
||||
@@ -123,7 +126,7 @@ function battleFactorySets(species: string | Species, tier: string | null, gen =
|
||||
let ev: string;
|
||||
for (ev in set.evs) {
|
||||
if (set.evs[ev] === 0) continue;
|
||||
evs.push(`${set.evs[ev]} ${statNames[ev]}`);
|
||||
evs.push(`${set.evs[ev]} ${STAT_NAMES[ev]}`);
|
||||
}
|
||||
buf += `${evs.join(" / ")}</li>`;
|
||||
}
|
||||
@@ -134,7 +137,7 @@ function battleFactorySets(species: string | Species, tier: string | null, gen =
|
||||
let iv: string;
|
||||
for (iv in set.ivs) {
|
||||
if (set.ivs[iv] === 31) continue;
|
||||
ivs.push(`${set.ivs[iv]} ${statNames[iv]}`);
|
||||
ivs.push(`${set.ivs[iv]} ${STAT_NAMES[iv]}`);
|
||||
}
|
||||
buf += `${ivs.join(" / ")}</li>`;
|
||||
}
|
||||
@@ -163,7 +166,7 @@ function battleFactorySets(species: string | Species, tier: string | null, gen =
|
||||
let ev: string;
|
||||
for (ev in set.evs) {
|
||||
if (set.evs[ev] === 0) continue;
|
||||
evs.push(`${set.evs[ev]} ${statNames[ev]}`);
|
||||
evs.push(`${set.evs[ev]} ${STAT_NAMES[ev]}`);
|
||||
}
|
||||
buf += `${evs.join(" / ")}</li>`;
|
||||
}
|
||||
@@ -174,7 +177,7 @@ function battleFactorySets(species: string | Species, tier: string | null, gen =
|
||||
let iv: string;
|
||||
for (iv in set.ivs) {
|
||||
if (set.ivs[iv] === 31) continue;
|
||||
ivs.push(`${set.ivs[iv]} ${statNames[iv]}`);
|
||||
ivs.push(`${set.ivs[iv]} ${STAT_NAMES[iv]}`);
|
||||
}
|
||||
buf += `${ivs.join(" / ")}</li>`;
|
||||
}
|
||||
@@ -204,9 +207,6 @@ function CAP1v1Sets(species: string | Species) {
|
||||
return {e: `${species.name} doesn't have any sets in [Gen 8] CAP 1v1.`};
|
||||
}
|
||||
let buf = `<span style="color:#999999;">Sets for ${species.name} in [Gen 8] CAP 1v1:</span><br />`;
|
||||
const statNames: {[k: string]: string} = {
|
||||
hp: "HP", atk: "Atk", def: "Def", spa: "SpA", spd: "SpD", spe: "Spe",
|
||||
};
|
||||
for (const [i, set] of statsFile[species.name].entries()) {
|
||||
buf += `<details><summary>Set ${i + 1}</summary>`;
|
||||
buf += `<ul style="list-style-type:none;">`;
|
||||
@@ -221,7 +221,7 @@ function CAP1v1Sets(species: string | Species) {
|
||||
let ev: string;
|
||||
for (ev in set.evs) {
|
||||
if (set.evs[ev] === 0) continue;
|
||||
evs.push(`${set.evs[ev]} ${statNames[ev]}`);
|
||||
evs.push(`${set.evs[ev]} ${STAT_NAMES[ev]}`);
|
||||
}
|
||||
buf += `${evs.join(" / ")}</li>`;
|
||||
}
|
||||
@@ -232,7 +232,7 @@ function CAP1v1Sets(species: string | Species) {
|
||||
let iv: string;
|
||||
for (iv in set.ivs) {
|
||||
if (set.ivs[iv] === 31) continue;
|
||||
ivs.push(`${set.ivs[iv]} ${statNames[iv]}`);
|
||||
ivs.push(`${set.ivs[iv]} ${STAT_NAMES[iv]}`);
|
||||
}
|
||||
buf += `${ivs.join(" / ")}</li>`;
|
||||
}
|
||||
@@ -244,6 +244,375 @@ function CAP1v1Sets(species: string | Species) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
function generateSSBSet(set: SSBSet, dex: ModdedDex, baseDex: ModdedDex) {
|
||||
if (set.skip) {
|
||||
const baseSet = toID(Object.values(ssbSets[set.skip]).join());
|
||||
const skipSet = toID(Object.values(set).join()).slice(0, -toID(set.skip).length);
|
||||
if (baseSet === skipSet) return ``;
|
||||
}
|
||||
let buf = ``;
|
||||
buf += `<details><summary>Set</summary>`;
|
||||
buf += `<ul style="list-style-type:none;"><li>${set.species}${set.gender !== '' ? ` (${set.gender})` : ``} @ ${Array.isArray(set.item) ? set.item.map(x => dex.getItem(x).name).join(' / ') : dex.getItem(set.item).name}</li>`;
|
||||
buf += `<li>Ability: ${Array.isArray(set.ability) ? set.ability.map(x => dex.getAbility(x).name).join(' / ') : dex.getAbility(set.ability).name}</li>`;
|
||||
if (set.shiny) buf += `<li>Shiny: ${typeof set.shiny === 'number' ? `Sometimes` : `Yes`}</li>`;
|
||||
if (set.evs) {
|
||||
const evs: string[] = [];
|
||||
let ev: StatName;
|
||||
for (ev in set.evs) {
|
||||
if (set.evs[ev] === 0) continue;
|
||||
evs.push(`${set.evs[ev]} ${STAT_NAMES[ev]}`);
|
||||
}
|
||||
buf += `<li>EVs: ${evs.join(" / ")}</li>`;
|
||||
}
|
||||
if (set.nature) {
|
||||
buf += `<li>${Array.isArray(set.nature) ? set.nature.join(" / ") : formatNature(set.nature)} Nature</li>`;
|
||||
}
|
||||
if (set.ivs) {
|
||||
const ivs: string[] = [];
|
||||
let iv: StatName;
|
||||
for (iv in set.ivs) {
|
||||
if (set.ivs[iv] === 31) continue;
|
||||
ivs.push(`${set.ivs[iv]} ${STAT_NAMES[iv]}`);
|
||||
}
|
||||
buf += `<li>IVs: ${ivs.join(" / ")}</li>`;
|
||||
}
|
||||
for (const moveid of set.moves) {
|
||||
buf += `<li>- ${Array.isArray(moveid) ? moveid.map(x => dex.getMove(x).name).join(" / ") : dex.getMove(moveid).name}</li>`;
|
||||
}
|
||||
const italicize = !baseDex.getMove(set.signatureMove).exists;
|
||||
buf += `<li>- ${italicize ? `<i>` : ``}${dex.getMove(set.signatureMove).name}${italicize ? `</i>` : ``}</li>`;
|
||||
buf += `</ul>`;
|
||||
buf += `</details>`;
|
||||
return buf;
|
||||
}
|
||||
|
||||
function generateSSBMoveInfo(sigMove: Move, dex: ModdedDex) {
|
||||
let buf = ``;
|
||||
if (sigMove.shortDesc || sigMove.desc) {
|
||||
buf += `<hr />`;
|
||||
buf += Chat.getDataMoveHTML(sigMove);
|
||||
const details: {[k: string]: string} = {
|
||||
Priority: String(sigMove.priority),
|
||||
Gen: String(sigMove.gen) || 'CAP',
|
||||
};
|
||||
|
||||
if (sigMove.isNonstandard === "Past" && dex.gen >= 8) details["✗ Past Gens Only"] = "";
|
||||
if (sigMove.secondary || sigMove.secondaries) details["✓ Secondary effect"] = "";
|
||||
if (sigMove.flags['contact']) details["✓ Contact"] = "";
|
||||
if (sigMove.flags['sound']) details["✓ Sound"] = "";
|
||||
if (sigMove.flags['bullet']) details["✓ Bullet"] = "";
|
||||
if (sigMove.flags['pulse']) details["✓ Pulse"] = "";
|
||||
if (!sigMove.flags['protect'] && !/(ally|self)/i.test(sigMove.target)) details["✓ Bypasses Protect"] = "";
|
||||
if (sigMove.flags['authentic']) details["✓ Bypasses Substitutes"] = "";
|
||||
if (sigMove.flags['defrost']) details["✓ Thaws user"] = "";
|
||||
if (sigMove.flags['bite']) details["✓ Bite"] = "";
|
||||
if (sigMove.flags['punch']) details["✓ Punch"] = "";
|
||||
if (sigMove.flags['powder']) details["✓ Powder"] = "";
|
||||
if (sigMove.flags['reflectable']) details["✓ Bounceable"] = "";
|
||||
if (sigMove.flags['charge']) details["✓ Two-turn move"] = "";
|
||||
if (sigMove.flags['recharge']) details["✓ Has recharge turn"] = "";
|
||||
if (sigMove.flags['gravity']) details["✗ Suppressed by Gravity"] = "";
|
||||
if (sigMove.flags['dance']) details["✓ Dance move"] = "";
|
||||
|
||||
if (sigMove.zMove?.basePower) {
|
||||
details["Z-Power"] = String(sigMove.zMove.basePower);
|
||||
} else if (sigMove.zMove?.effect) {
|
||||
const zEffects: {[k: string]: string} = {
|
||||
clearnegativeboost: "Restores negative stat stages to 0",
|
||||
crit2: "Crit ratio +2",
|
||||
heal: "Restores HP 100%",
|
||||
curse: "Restores HP 100% if user is Ghost type, otherwise Attack +1",
|
||||
redirect: "Redirects opposing attacks to user",
|
||||
healreplacement: "Restores replacement's HP 100%",
|
||||
};
|
||||
details["Z-Effect"] = zEffects[sigMove.zMove.effect];
|
||||
} else if (sigMove.zMove?.boost) {
|
||||
details["Z-Effect"] = "";
|
||||
const boost = sigMove.zMove.boost;
|
||||
const stats: {[k in BoostName]: string} = {
|
||||
atk: 'Attack', def: 'Defense', spa: 'Sp. Atk', spd: 'Sp. Def', spe: 'Speed', accuracy: 'Accuracy', evasion: 'Evasiveness',
|
||||
};
|
||||
let h: BoostName;
|
||||
for (h in boost) {
|
||||
details["Z-Effect"] += ` ${stats[h]} +${boost[h]}`;
|
||||
}
|
||||
} else if (sigMove.isZ && typeof sigMove.isZ === 'string') {
|
||||
details["✓ Z-Move"] = "";
|
||||
const zCrystal = dex.getItem(sigMove.isZ);
|
||||
details["Z-Crystal"] = zCrystal.name;
|
||||
if (zCrystal.itemUser) {
|
||||
details["User"] = zCrystal.itemUser.join(", ");
|
||||
details["Required Move"] = dex.getItem(sigMove.isZ).zMoveFrom!;
|
||||
}
|
||||
} else {
|
||||
details["Z-Effect"] = "None";
|
||||
}
|
||||
|
||||
const targetTypes: {[k: string]: string} = {
|
||||
normal: "One Adjacent Pok\u00e9mon",
|
||||
self: "User",
|
||||
adjacentAlly: "One Ally",
|
||||
adjacentAllyOrSelf: "User or Ally",
|
||||
adjacentFoe: "One Adjacent Opposing Pok\u00e9mon",
|
||||
allAdjacentFoes: "All Adjacent Opponents",
|
||||
foeSide: "Opposing Side",
|
||||
allySide: "User's Side",
|
||||
allyTeam: "User's Side",
|
||||
allAdjacent: "All Adjacent Pok\u00e9mon",
|
||||
any: "Any Pok\u00e9mon",
|
||||
all: "All Pok\u00e9mon",
|
||||
scripted: "Chosen Automatically",
|
||||
randomNormal: "Random Adjacent Opposing Pok\u00e9mon",
|
||||
allies: "User and Allies",
|
||||
};
|
||||
details["Target"] = targetTypes[sigMove.target] || "Unknown";
|
||||
if (sigMove.isNonstandard === 'Unobtainable') {
|
||||
details[`Unobtainable in Gen ${dex.gen}`] = "";
|
||||
}
|
||||
buf += `<font size="1">${Object.keys(details).map(detail => {
|
||||
if (details[detail] === '') return detail;
|
||||
return `<font color="#686868">${detail}:</font> ${details[detail]}`;
|
||||
}).join(" |  ")}</font>`;
|
||||
if (sigMove.desc && sigMove.desc !== sigMove.shortDesc) {
|
||||
buf += `<details><summary><strong>In-Depth Description</strong></summary>${sigMove.desc}</details>`;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
function generateSSBItemInfo(set: SSBSet, dex: ModdedDex, baseDex: ModdedDex) {
|
||||
let buf = ``;
|
||||
if (!Array.isArray(set.item)) {
|
||||
const baseItem = baseDex.getItem(set.item);
|
||||
const sigItem = dex.getItem(set.item);
|
||||
if (!baseItem.exists || (baseItem.desc || baseItem.shortDesc) !== (sigItem.desc || sigItem.shortDesc)) {
|
||||
buf += `<hr />`;
|
||||
buf += Chat.getDataItemHTML(sigItem);
|
||||
const details: {[k: string]: string} = {
|
||||
Gen: String(sigItem.gen),
|
||||
};
|
||||
|
||||
if (dex.gen >= 4) {
|
||||
if (sigItem.fling) {
|
||||
details["Fling Base Power"] = String(sigItem.fling.basePower);
|
||||
if (sigItem.fling.status) details["Fling Effect"] = sigItem.fling.status;
|
||||
if (sigItem.fling.volatileStatus) details["Fling Effect"] = sigItem.fling.volatileStatus;
|
||||
if (sigItem.isBerry) details["Fling Effect"] = "Activates the Berry's effect on the target.";
|
||||
if (sigItem.id === 'whiteherb') details["Fling Effect"] = "Restores the target's negative stat stages to 0.";
|
||||
if (sigItem.id === 'mentalherb') {
|
||||
const flingEffect = "Removes the effects of Attract, Disable, Encore, Heal Block, Taunt, and Torment from the target.";
|
||||
details["Fling Effect"] = flingEffect;
|
||||
}
|
||||
} else {
|
||||
details["Fling"] = "This item cannot be used with Fling.";
|
||||
}
|
||||
}
|
||||
if (sigItem.naturalGift && dex.gen >= 3) {
|
||||
details["Natural Gift Type"] = sigItem.naturalGift.type;
|
||||
details["Natural Gift Base Power"] = String(sigItem.naturalGift.basePower);
|
||||
}
|
||||
if (sigItem.isNonstandard && sigItem.isNonstandard !== "Custom") {
|
||||
details[`Unobtainable in Gen ${dex.gen}`] = "";
|
||||
}
|
||||
buf += `<font size="1">${Object.keys(details).map(detail => {
|
||||
if (details[detail] === '') return detail;
|
||||
return `<font color="#686868">${detail}:</font> ${details[detail]}`;
|
||||
}).join(" |  ")}</font>`;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
function generateSSBAbilityInfo(set: SSBSet, dex: ModdedDex, baseDex: ModdedDex) {
|
||||
let buf = ``;
|
||||
if (!Array.isArray(set.ability) && !baseDex.getAbility(set.ability).exists) {
|
||||
const sigAbil = Dex.deepClone(dex.getAbility(set.ability));
|
||||
if (!sigAbil.desc && !sigAbil.shortDesc) {
|
||||
sigAbil.desc = `This ability doesn't have a description. Try contacting the SSB dev team.`;
|
||||
}
|
||||
buf += `<hr />`;
|
||||
buf += Chat.getDataAbilityHTML(sigAbil);
|
||||
const details: {[k: string]: string} = {
|
||||
Gen: String(sigAbil.gen) || 'CAP',
|
||||
};
|
||||
buf += `<font size="1">${Object.keys(details).map(detail => {
|
||||
if (details[detail] === '') return detail;
|
||||
return `<font color="#686868">${detail}:</font> ${details[detail]}`;
|
||||
}).join(" |  ")}</font>`;
|
||||
if (sigAbil.desc && sigAbil.shortDesc && sigAbil.desc !== sigAbil.shortDesc) {
|
||||
buf += `<details><summary><strong>In-Depth Description</strong></summary>${sigAbil.desc}</details>`;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
function generateSSBPokemonInfo(species: string, dex: ModdedDex, baseDex: ModdedDex) {
|
||||
let buf = ``;
|
||||
const origSpecies = baseDex.getSpecies(species);
|
||||
const newSpecies = dex.getSpecies(species);
|
||||
if (
|
||||
newSpecies.types.join('/') !== origSpecies.types.join('/') ||
|
||||
Object.values(newSpecies.abilities).join('/') !== Object.values(origSpecies.abilities).join('/') ||
|
||||
Object.values(newSpecies.baseStats).join('/') !== Object.values(origSpecies.baseStats).join('/')
|
||||
) {
|
||||
buf += `<hr />`;
|
||||
buf += Chat.getDataPokemonHTML(newSpecies, dex.gen, 'SSB');
|
||||
let weighthit = 20;
|
||||
if (newSpecies.weighthg >= 2000) {
|
||||
weighthit = 120;
|
||||
} else if (newSpecies.weighthg >= 1000) {
|
||||
weighthit = 100;
|
||||
} else if (newSpecies.weighthg >= 500) {
|
||||
weighthit = 80;
|
||||
} else if (newSpecies.weighthg >= 250) {
|
||||
weighthit = 60;
|
||||
} else if (newSpecies.weighthg >= 100) {
|
||||
weighthit = 40;
|
||||
}
|
||||
const details: {[k: string]: string} = {
|
||||
"Dex#": String(newSpecies.num),
|
||||
Gen: String(newSpecies.gen) || 'CAP',
|
||||
Height: `${newSpecies.heightm} m`,
|
||||
};
|
||||
details["Weight"] = `${newSpecies.weighthg / 10} kg <em>(${weighthit} BP)</em>`;
|
||||
if (newSpecies.color && dex.gen >= 5) details["Dex Colour"] = newSpecies.color;
|
||||
if (newSpecies.eggGroups && dex.gen >= 2) details["Egg Group(s)"] = newSpecies.eggGroups.join(", ");
|
||||
const evos: string[] = [];
|
||||
for (const evoName of newSpecies.evos) {
|
||||
const evo = dex.getSpecies(evoName);
|
||||
if (evo.gen <= dex.gen) {
|
||||
const condition = evo.evoCondition ? ` ${evo.evoCondition}` : ``;
|
||||
switch (evo.evoType) {
|
||||
case 'levelExtra':
|
||||
evos.push(`${evo.name} (level-up${condition})`);
|
||||
break;
|
||||
case 'levelFriendship':
|
||||
evos.push(`${evo.name} (level-up with high Friendship${condition})`);
|
||||
break;
|
||||
case 'levelHold':
|
||||
evos.push(`${evo.name} (level-up holding ${evo.evoItem}${condition})`);
|
||||
break;
|
||||
case 'useItem':
|
||||
evos.push(`${evo.name} (${evo.evoItem})`);
|
||||
break;
|
||||
case 'levelMove':
|
||||
evos.push(`${evo.name} (level-up with ${evo.evoMove}${condition})`);
|
||||
break;
|
||||
case 'other':
|
||||
evos.push(`${evo.name} (${evo.evoCondition})`);
|
||||
break;
|
||||
case 'trade':
|
||||
evos.push(`${evo.name} (trade${evo.evoItem ? ` holding ${evo.evoItem}` : condition})`);
|
||||
break;
|
||||
default:
|
||||
evos.push(`${evo.name} (${evo.evoLevel}${condition})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!evos.length) {
|
||||
details[`<font color="#686868">Does Not Evolve</font>`] = "";
|
||||
} else {
|
||||
details["Evolution"] = evos.join(", ");
|
||||
}
|
||||
buf += `<font size="1">${Object.keys(details).map(detail => {
|
||||
if (details[detail] === '') return detail;
|
||||
return `<font color="#686868">${detail}:</font> ${details[detail]}`;
|
||||
}).join(" |  ")}</font>`;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
function generateSSBInnateInfo(name: string, dex: ModdedDex, baseDex: ModdedDex) {
|
||||
let buf = ``;
|
||||
// Special casing for users whose usernames are already existing, i.e. Perish Song
|
||||
let effect = dex.getEffect(name + 'user');
|
||||
let longDesc = ``;
|
||||
const baseAbility = Dex.deepClone(baseDex.getAbility('noability'));
|
||||
// @ts-ignore hack to record the name of the innate abilities without using name
|
||||
if (effect.exists && effect.innateName && (effect.desc || effect.shortDesc)) {
|
||||
// @ts-ignore hack
|
||||
baseAbility.name = effect.innateName;
|
||||
if (effect.desc) baseAbility.desc = effect.desc;
|
||||
if (effect.shortDesc) baseAbility.shortDesc = effect.shortDesc;
|
||||
buf += `<hr />Innate Ability:<br />${Chat.getDataAbilityHTML(baseAbility)}`;
|
||||
if (effect.desc && effect.shortDesc && effect.desc !== effect.shortDesc) {
|
||||
longDesc = effect.desc;
|
||||
}
|
||||
} else {
|
||||
effect = dex.getEffect(name);
|
||||
// @ts-ignore hack
|
||||
if (effect.exists && effect.innateName && (effect.desc || effect.shortDesc)) {
|
||||
// @ts-ignore hack
|
||||
baseAbility.name = effect.innateName;
|
||||
if (effect.desc) baseAbility.desc = effect.desc;
|
||||
if (effect.shortDesc) baseAbility.shortDesc = effect.shortDesc;
|
||||
buf += `<hr />Innate Ability:<br />${Chat.getDataAbilityHTML(baseAbility)}`;
|
||||
if (effect.desc && effect.shortDesc && effect.desc !== effect.shortDesc) {
|
||||
longDesc = effect.desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buf) {
|
||||
const details: {[k: string]: string} = {Gen: '8'};
|
||||
buf += `<font size="1">${Object.keys(details).map(detail => {
|
||||
if (details[detail] === '') return detail;
|
||||
return `<font color="#686868">${detail}:</font> ${details[detail]}`;
|
||||
}).join(" |  ")}</font>`;
|
||||
}
|
||||
if (longDesc) {
|
||||
buf += `<details><summary><strong>In-Depth Description</strong></summary>${longDesc}</details>`;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
function SSBSets(target: string) {
|
||||
const baseDex = Dex;
|
||||
const dex = Dex.forFormat('gen8superstaffbros4');
|
||||
if (!Object.keys(ssbSets).map(toID).includes(toID(target))) {
|
||||
return {e: `Error: ${target.trim()} doesn't have a [Gen 8] Super Staff Bros 4 set.`};
|
||||
}
|
||||
let displayName = '';
|
||||
const names = [];
|
||||
for (const member in ssbSets) {
|
||||
if (toID(member).startsWith(toID(target))) names.push(member);
|
||||
if (toID(member) === toID(target)) displayName = member;
|
||||
}
|
||||
let buf = '';
|
||||
for (const name of names) {
|
||||
if (buf) buf += `<hr>`;
|
||||
const set = ssbSets[name];
|
||||
const mutatedSpecies = dex.getSpecies(set.species);
|
||||
if (!set.skip) {
|
||||
buf += Utils.html`<h1><psicon pokemon="${mutatedSpecies.id}">${displayName === 'yuki' ? name : displayName}</h1>`;
|
||||
} else {
|
||||
buf += `<details><summary><psicon pokemon="${set.species}"><strong>${name.split('-').slice(1).join('-') + ' forme'}</strong></summary>`;
|
||||
}
|
||||
buf += generateSSBSet(set, dex, baseDex);
|
||||
const item = dex.getItem(set.item as string);
|
||||
if (!set.skip || set.signatureMove !== ssbSets[set.skip].signatureMove) {
|
||||
const sigMove = baseDex.getMove(set.signatureMove).exists && !Array.isArray(set.item) &&
|
||||
typeof item.zMove === 'string' ?
|
||||
dex.getMove(item.zMove) : dex.getMove(set.signatureMove);
|
||||
buf += generateSSBMoveInfo(sigMove, dex);
|
||||
if (sigMove.id === 'blackbird') buf += generateSSBMoveInfo(dex.getMove('gaelstrom'), dex);
|
||||
}
|
||||
buf += generateSSBItemInfo(set, dex, baseDex);
|
||||
buf += generateSSBAbilityInfo(set, dex, baseDex);
|
||||
buf += generateSSBInnateInfo(name, dex, baseDex);
|
||||
buf += generateSSBPokemonInfo(set.species, dex, baseDex);
|
||||
if (!Array.isArray(set.item) && item.megaStone) {
|
||||
buf += generateSSBPokemonInfo(item.megaStone, dex, baseDex);
|
||||
// Psynergy, Struchni, and Raj.shoot have itemless Mega Evolutions
|
||||
} else if (['Aggron', 'Rayquaza'].includes(set.species)) {
|
||||
buf += generateSSBPokemonInfo(`${set.species}-Mega`, dex, baseDex);
|
||||
} else if (set.species === 'Charizard') {
|
||||
buf += generateSSBPokemonInfo('Charizard-Mega-X', dex, baseDex);
|
||||
}
|
||||
if (set.skip) buf += `</details>`;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
export const commands: ChatCommands = {
|
||||
randbats: 'randombattles',
|
||||
randombattles(target, room, user) {
|
||||
@@ -428,4 +797,17 @@ export const commands: ChatCommands = {
|
||||
cap1v1help: [
|
||||
`/cap1v1 [pokemon] - Displays a Pok\u00e9mon's CAP 1v1 sets.`,
|
||||
],
|
||||
|
||||
ssb(target, room, user) {
|
||||
if (!this.runBroadcast()) return;
|
||||
if (!target) return this.parse(`/help ssb`);
|
||||
const set = SSBSets(target);
|
||||
if (typeof set !== 'string') {
|
||||
throw new Chat.ErrorMessage(set.e);
|
||||
}
|
||||
return this.sendReplyBox(set);
|
||||
},
|
||||
ssbhelp: [
|
||||
`/ssb [staff member] - Displays a staff member's Super Staff Bros. Brawl set and custom features.`,
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1533,7 +1533,7 @@ export class Battle {
|
||||
this.makeRequest('move');
|
||||
}
|
||||
|
||||
private maybeTriggerEndlessBattleClause(
|
||||
maybeTriggerEndlessBattleClause(
|
||||
trappedBySide: boolean[], stalenessBySide: ('internal' | 'external' | undefined)[]
|
||||
) {
|
||||
if (this.turn <= 100 || !this.ruleTable.has('endlessbattleclause')) return;
|
||||
|
||||
@@ -240,7 +240,7 @@ export interface MoveData extends EffectData, MoveEventMethods, HitEffect {
|
||||
baseMove?: string;
|
||||
}
|
||||
|
||||
export type ModdedMoveData = MoveData | Partial<Omit<MoveData, 'name'>> & {inherit: true};
|
||||
export type ModdedMoveData = MoveData | Partial<Omit<MoveData, 'name'>> & {inherit: true, gen?: number};
|
||||
|
||||
export interface Move extends Readonly<BasicEffect & MoveData> {
|
||||
readonly effectType: 'Move';
|
||||
|
||||
@@ -372,6 +372,7 @@ interface ModdedBattleScriptsData extends Partial<BattleScriptsData> {
|
||||
this: Battle, baseDamage: number, pokemon: Pokemon, target: Pokemon, move: ActiveMove, suppressMessages?: boolean
|
||||
) => void;
|
||||
natureModify?: (this: Battle, stats: StatsTable, set: PokemonSet) => StatsTable;
|
||||
nextTurn?: (this: Battle) => void;
|
||||
runMove?: (
|
||||
this: Battle, moveOrMoveName: Move | string, pokemon: Pokemon, targetLoc: number, sourceEffect?: Effect | null,
|
||||
zMove?: string, externalMove?: boolean, maxMove?: string, originalTarget?: Pokemon
|
||||
|
||||
Reference in New Issue
Block a user