mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-09-09 17:55:37 -05:00
Allow Picked Team Size to be used without Team Preview (#11224)
* Add Pick Team rule * Make Team Preview and Pick Team mutually exclusive * Automatically apply rule if Picked Team Size exists without preview * Remove mutually exclusive part * Move teamsize to start action
This commit is contained in:
committed by
GitHub
parent
bc832df368
commit
d3d834c91a
@@ -4653,7 +4653,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
mod: 'gen4',
|
||||
gameType: 'doubles',
|
||||
searchShow: false,
|
||||
ruleset: ['Flat Rules', 'Min Team Size = 4', 'Max Team Size = 4', 'Limit Two Restricted'],
|
||||
ruleset: ['Flat Rules', 'Limit Two Restricted'],
|
||||
restricted: ['Restricted Legendary'],
|
||||
banlist: ['Soul Dew'],
|
||||
},
|
||||
@@ -4662,7 +4662,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
mod: 'gen4pt',
|
||||
gameType: 'doubles',
|
||||
searchShow: false,
|
||||
ruleset: ['Flat Rules', '! Adjust Level Down', 'Max Level = 50', 'Min Team Size = 4', 'Max Team Size = 4'],
|
||||
ruleset: ['Flat Rules', '! Adjust Level Down', 'Max Level = 50'],
|
||||
banlist: ['Tyranitar', 'Rotom', 'Judgment', 'Soul Dew'],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable
|
||||
},
|
||||
flatrules: {
|
||||
inherit: true,
|
||||
ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Item Clause = 1', 'Adjust Level Down = 50', 'Cancel Mod'],
|
||||
ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Item Clause = 1', 'Adjust Level Down = 50', 'Picked Team Size = Auto', 'Cancel Mod'],
|
||||
},
|
||||
teampreview: {
|
||||
inherit: true,
|
||||
|
||||
@@ -65,15 +65,52 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
case 'start': {
|
||||
for (const side of this.sides) {
|
||||
if (side.pokemonLeft) side.pokemonLeft = side.pokemon.length;
|
||||
this.add('teamsize', side.id, side.pokemon.length);
|
||||
}
|
||||
|
||||
this.add('start');
|
||||
|
||||
if (this.format.onBattleStart) this.format.onBattleStart.call(this);
|
||||
// Change Zacian/Zamazenta into their Crowned formes
|
||||
for (const pokemon of this.getAllPokemon()) {
|
||||
let rawSpecies: Species | null = null;
|
||||
if (pokemon.species.id === 'zacian' && pokemon.item === 'rustedsword') {
|
||||
rawSpecies = this.dex.species.get('Zacian-Crowned');
|
||||
} else if (pokemon.species.id === 'zamazenta' && pokemon.item === 'rustedshield') {
|
||||
rawSpecies = this.dex.species.get('Zamazenta-Crowned');
|
||||
}
|
||||
if (!rawSpecies) continue;
|
||||
const species = pokemon.setSpecies(rawSpecies);
|
||||
if (!species) continue;
|
||||
pokemon.baseSpecies = rawSpecies;
|
||||
pokemon.details = pokemon.getUpdatedDetails();
|
||||
// pokemon.setAbility(species.abilities['0'], null, true);
|
||||
// pokemon.baseAbility = pokemon.ability;
|
||||
|
||||
const behemothMove: { [k: string]: string } = {
|
||||
'Zacian-Crowned': 'behemothblade', 'Zamazenta-Crowned': 'behemothbash',
|
||||
};
|
||||
const ironHead = pokemon.baseMoves.indexOf('ironhead');
|
||||
if (ironHead >= 0) {
|
||||
const move = this.dex.moves.get(behemothMove[rawSpecies.name]);
|
||||
pokemon.baseMoveSlots[ironHead] = {
|
||||
move: move.name,
|
||||
id: move.id,
|
||||
pp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
|
||||
maxpp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
|
||||
target: move.target,
|
||||
disabled: false,
|
||||
disabledSource: '',
|
||||
used: false,
|
||||
};
|
||||
pokemon.moveSlots = pokemon.baseMoveSlots.slice();
|
||||
}
|
||||
}
|
||||
|
||||
this.format.onBattleStart?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onBattleStart) subFormat.onBattleStart.call(this);
|
||||
subFormat.onBattleStart?.call(this);
|
||||
}
|
||||
|
||||
for (const side of this.sides) {
|
||||
|
||||
@@ -369,6 +369,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
case 'start': {
|
||||
for (const side of this.sides) {
|
||||
if (side.pokemonLeft) side.pokemonLeft = side.pokemon.length;
|
||||
this.add('teamsize', side.id, side.pokemon.length);
|
||||
}
|
||||
|
||||
this.add('start');
|
||||
@@ -409,11 +410,11 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.format.onBattleStart) this.format.onBattleStart.call(this);
|
||||
this.format.onBattleStart?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onBattleStart) subFormat.onBattleStart.call(this);
|
||||
subFormat.onBattleStart?.call(this);
|
||||
}
|
||||
|
||||
for (const side of this.sides) {
|
||||
|
||||
@@ -42,10 +42,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
}
|
||||
}
|
||||
|
||||
for (const side of this.sides) {
|
||||
this.add('teamsize', side.id, side.pokemon.length);
|
||||
}
|
||||
|
||||
this.add('gen', this.gen);
|
||||
|
||||
this.add('tier', format.name);
|
||||
@@ -54,11 +50,11 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
this.add('rated', typeof this.rated === 'string' ? this.rated : '');
|
||||
}
|
||||
|
||||
if (format.onBegin) format.onBegin.call(this);
|
||||
format.onBegin?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onBegin) subFormat.onBegin.call(this);
|
||||
subFormat.onBegin?.call(this);
|
||||
}
|
||||
for (const pokemon of this.getAllPokemon()) {
|
||||
const item = pokemon.getItem();
|
||||
@@ -87,11 +83,25 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
this.add(`raw|<div class="infobox"><details class="readmore"${open}><summary><strong>${format.customRules.length} custom rule${plural}:</strong></summary> ${format.customRules.join(', ')}</details></div>`);
|
||||
}
|
||||
|
||||
if (format.onTeamPreview) format.onTeamPreview.call(this);
|
||||
format.onTeamPreview?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onTeamPreview) subFormat.onTeamPreview.call(this);
|
||||
subFormat.onTeamPreview?.call(this);
|
||||
}
|
||||
|
||||
if (this.requestState !== 'teampreview' && this.ruleTable.pickedTeamSize) {
|
||||
this.add('clearpoke');
|
||||
for (const side of this.sides) {
|
||||
for (const pokemon of side.pokemon) {
|
||||
// Still need to hide these formes since they change on battle start
|
||||
const details = pokemon.details.replace(', shiny', '')
|
||||
.replace(/(Zacian|Zamazenta)(?!-Crowned)/g, '$1-*')
|
||||
.replace(/(Xerneas)(-[a-zA-Z?-]+)?/g, '$1-*');
|
||||
this.addSplit(side.id, ['poke', pokemon.side.id, details, '']);
|
||||
}
|
||||
}
|
||||
this.makeRequest('teampreview');
|
||||
}
|
||||
|
||||
this.queue.addChoice({ choice: 'start' });
|
||||
@@ -106,6 +116,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
case 'start': {
|
||||
for (const side of this.sides) {
|
||||
if (side.pokemonLeft) side.pokemonLeft = side.pokemon.length;
|
||||
this.add('teamsize', side.id, side.pokemon.length);
|
||||
}
|
||||
|
||||
this.add('start');
|
||||
@@ -147,11 +158,11 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.format.onBattleStart) this.format.onBattleStart.call(this);
|
||||
this.format.onBattleStart?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onBattleStart) subFormat.onBattleStart.call(this);
|
||||
subFormat.onBattleStart?.call(this);
|
||||
}
|
||||
|
||||
for (const side of this.sides) {
|
||||
|
||||
@@ -188,6 +188,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
case 'start': {
|
||||
for (const side of this.sides) {
|
||||
if (side.pokemonLeft) side.pokemonLeft = side.pokemon.length;
|
||||
this.add('teamsize', side.id, side.pokemon.length);
|
||||
}
|
||||
|
||||
this.add('start');
|
||||
@@ -228,11 +229,11 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.format.onBattleStart) this.format.onBattleStart.call(this);
|
||||
this.format.onBattleStart?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onBattleStart) subFormat.onBattleStart.call(this);
|
||||
subFormat.onBattleStart?.call(this);
|
||||
}
|
||||
|
||||
for (const side of this.sides) {
|
||||
|
||||
@@ -80,10 +80,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
}
|
||||
}
|
||||
|
||||
for (const side of this.sides) {
|
||||
this.add('teamsize', side.id, side.pokemon.length);
|
||||
}
|
||||
|
||||
this.add('gen', this.gen);
|
||||
|
||||
this.add('tier', format.name);
|
||||
@@ -92,11 +88,11 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
this.add('rated', typeof this.rated === 'string' ? this.rated : '');
|
||||
}
|
||||
|
||||
if (format.onBegin) format.onBegin.call(this);
|
||||
format.onBegin?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onBegin) subFormat.onBegin.call(this);
|
||||
subFormat.onBegin?.call(this);
|
||||
}
|
||||
|
||||
if (this.sides.some(side => !side.pokemon[0])) {
|
||||
@@ -113,11 +109,25 @@ export const Scripts: ModdedBattleScriptsData = {
|
||||
this.add(`raw|<div class="infobox"><details class="readmore"${open}><summary><strong>${format.customRules.length} custom rule${plural}:</strong></summary> ${format.customRules.join(', ')}</details></div>`);
|
||||
}
|
||||
|
||||
if (format.onTeamPreview) format.onTeamPreview.call(this);
|
||||
format.onTeamPreview?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onTeamPreview) subFormat.onTeamPreview.call(this);
|
||||
subFormat.onTeamPreview?.call(this);
|
||||
}
|
||||
|
||||
if (this.requestState !== 'teampreview' && this.ruleTable.pickedTeamSize) {
|
||||
this.add('clearpoke');
|
||||
for (const side of this.sides) {
|
||||
for (const pokemon of side.pokemon) {
|
||||
// Still need to hide these formes since they change on battle start
|
||||
const details = pokemon.details.replace(', shiny', '')
|
||||
.replace(/(Zacian|Zamazenta)(?!-Crowned)/g, '$1-*')
|
||||
.replace(/(Xerneas)(-[a-zA-Z?-]+)?/g, '$1-*');
|
||||
this.addSplit(side.id, ['poke', pokemon.side.id, details, '']);
|
||||
}
|
||||
}
|
||||
this.makeRequest('teampreview');
|
||||
}
|
||||
|
||||
this.queue.addChoice({ choice: 'start' });
|
||||
|
||||
@@ -1976,12 +1976,7 @@ export const Rulesets: import('../sim/dex-formats').FormatDataTable = {
|
||||
name: 'Picked Team Size',
|
||||
desc: "Team size (number of pokemon) that can be brought out of Team Preview",
|
||||
hasValue: 'positive-integer',
|
||||
// hardcoded in sim/side
|
||||
onValidateRule() {
|
||||
if (!(this.ruleTable.has('teampreview') || this.ruleTable.has('teamtypepreview'))) {
|
||||
throw new Error(`The "Picked Team Size" rule${this.ruleTable.blame('pickedteamsize')} requires Team Preview.`);
|
||||
}
|
||||
},
|
||||
// hardcoded in sim/side and sim/battle
|
||||
},
|
||||
minteamsize: {
|
||||
effectType: 'ValidatorRule',
|
||||
|
||||
@@ -1868,10 +1868,6 @@ export class Battle {
|
||||
}
|
||||
}
|
||||
|
||||
for (const side of this.sides) {
|
||||
this.add('teamsize', side.id, side.pokemon.length);
|
||||
}
|
||||
|
||||
this.add('gen', this.gen);
|
||||
|
||||
this.add('tier', format.name);
|
||||
@@ -1908,6 +1904,20 @@ export class Battle {
|
||||
subFormat.onTeamPreview?.call(this);
|
||||
}
|
||||
|
||||
if (this.requestState !== 'teampreview' && this.ruleTable.pickedTeamSize) {
|
||||
this.add('clearpoke');
|
||||
for (const side of this.sides) {
|
||||
for (const pokemon of side.pokemon) {
|
||||
// Still need to hide these formes since they change on battle start
|
||||
const details = pokemon.details.replace(', shiny', '')
|
||||
.replace(/(Zacian|Zamazenta)(?!-Crowned)/g, '$1-*')
|
||||
.replace(/(Xerneas)(-[a-zA-Z?-]+)?/g, '$1-*');
|
||||
this.addSplit(side.id, ['poke', pokemon.side.id, details, '']);
|
||||
}
|
||||
}
|
||||
this.makeRequest('teampreview');
|
||||
}
|
||||
|
||||
this.queue.addChoice({ choice: 'start' });
|
||||
this.midTurn = true;
|
||||
if (!this.requestState) this.turnLoop();
|
||||
@@ -2601,6 +2611,7 @@ export class Battle {
|
||||
case 'start': {
|
||||
for (const side of this.sides) {
|
||||
if (side.pokemonLeft) side.pokemonLeft = side.pokemon.length;
|
||||
this.add('teamsize', side.id, side.pokemon.length);
|
||||
}
|
||||
|
||||
this.add('start');
|
||||
@@ -2641,11 +2652,11 @@ export class Battle {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.format.onBattleStart) this.format.onBattleStart.call(this);
|
||||
this.format.onBattleStart?.call(this);
|
||||
for (const rule of this.ruleTable.keys()) {
|
||||
if ('+*-!'.includes(rule.charAt(0))) continue;
|
||||
const subFormat = this.dex.formats.get(rule);
|
||||
if (subFormat.onBattleStart) subFormat.onBattleStart.call(this);
|
||||
subFormat.onBattleStart?.call(this);
|
||||
}
|
||||
|
||||
for (const side of this.sides) {
|
||||
|
||||
Reference in New Issue
Block a user