This commit is contained in:
Slayer95 2026-06-02 12:31:45 -07:00 committed by GitHub
commit e1b8bec1d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 253 additions and 63 deletions

View File

@ -1669,7 +1669,6 @@ export const Formats: import('../sim/dex-formats').FormatList = [
'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palafin', 'Palkia', 'Palkia-Origin', 'Rayquaza', 'Regieleki', 'Reshiram', 'Shaymin-Sky',
'Solgaleo', 'Terapagos', 'Urshifu-Single-Strike', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Crowned', 'Zekrom',
],
// Implemented the mechanics as a Rule because I'm too lazy to make battles read base format for `onResidual` at the moment
},
{
name: "[Gen 9] Flipped",

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
terastalclause: {
effectType: 'Rule',
name: 'Terastal Clause',

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standardag: {
inherit: true,
ruleset: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standardag: {
inherit: true,
ruleset: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standard: {
effectType: 'ValidatorRule',
name: 'Standard',

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standardag: {
inherit: true,
ruleset: [

View File

@ -1,6 +1,6 @@
import type { Learnset } from "../../../sim/dex-species";
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
obtainablemoves: {
inherit: true,
banlist: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standardag: {
inherit: true,
ruleset: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standard: {
effectType: 'ValidatorRule',
name: 'Standard',

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standard: {
effectType: 'ValidatorRule',
name: 'Standard',

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standardag: {
inherit: true,
ruleset: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standard: {
inherit: true,
ruleset: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standard: {
inherit: true,
ruleset: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standard: {
inherit: true,
ruleset: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
standard: {
inherit: true,
ruleset: [

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
teampreview: {
inherit: true,
onBattleStart() {

View File

@ -1,4 +1,4 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
export const Rulesets: import('../../../sim/dex-formats').ModdedRulesetTable = {
sleepclausemod: {
inherit: true,
onSetStatus(status, target, source) {

View File

@ -3,7 +3,7 @@
import type { Learnset } from "../sim/dex-species";
// The list of formats is stored in config/formats.js
export const Rulesets: import('../sim/dex-formats').FormatDataTable = {
export const Rulesets: import('../sim/dex-formats').RulesetTable = {
// Rulesets
///////////////////////////////////////////////////////////////////
@ -564,7 +564,7 @@ export const Rulesets: import('../sim/dex-formats').FormatDataTable = {
},
},
forceselect: {
effectType: 'ValidatorRule',
effectType: 'Rule',
name: 'Force Select',
desc: `Forces a Pokemon to be on the team and selected at Team Preview. Usage: Force Select = [Pokemon], e.g. "Force Select = Magikarp"`,
hasValue: true,
@ -3253,8 +3253,11 @@ export const Rulesets: import('../sim/dex-formats').FormatDataTable = {
if (this.ruleTable.adjustLevel) {
throw new Error(`This format's rules force Pokemon to be level ${this.ruleTable.adjustLevel}, so they can't be rebalanced.`);
}
const speciesMods = [...this.ruleTable.keys()].map(r => this.dex.data.Rulesets[r]).filter(r => r?.onModifySpecies);
if (!speciesMods.length) throw new Error('This format has no rules that modify base stats.');
const anySpeciesMods = [...this.ruleTable.keys()].some(ruleName => {
const rule = this.dex.data.Rulesets[ruleName];
return rule && rule.effectType !== 'ValidatorRule' && rule.onModifySpecies;
});
if (!anySpeciesMods) throw new Error('This format has no rules that modify base stats.');
},
},
};

View File

@ -10,7 +10,7 @@
import * as ConfigLoader from '../config-loader';
import { ProcessManager, Utils } from '../../lib';
import type { FormatData } from '../../sim/dex-formats';
import type { RulesetData } from '../../sim/dex-formats';
import { TeamValidator } from '../../sim/team-validator';
import { Chat } from '../chat';
@ -635,8 +635,12 @@ function getRule(target: string) {
x => x.toLowerCase().replace(/[^a-z0-9=]+/g, '').split('rule=')[1]), count };
}
function prepareDexsearchValidator(usedMod: string | undefined, rules: FormatData[], nationalSearch: boolean | null) {
const format = Object.entries(Dex.data.Rulesets).find(([a, f]) => f.mod === usedMod)?.[1].name || 'gen9ou';
function prepareDexsearchValidator(
usedMod: string | undefined,
rules: RulesetData[],
nationalSearch: boolean | null
) {
const format = Dex.formats.find(f => f.mod === usedMod)?.name || 'gen9ou';
const ruleTable = Dex.formats.getRuleTable(Dex.formats.get(format));
const additionalRules = [];
for (const rule of rules) {
@ -661,7 +665,7 @@ function runDexsearch(target: string, cmd: string, message: string, isTest: bool
}
}
const mod = Dex.mod(usedMod || 'base');
const rules: FormatData[] = [];
const rules: RulesetData[] = [];
for (const rule of usedRules) {
if (!dexsearchHelpRules.includes(rule))
return { error: `${rule} is an unsupported rule, see /dexsearchhelp` };
@ -1316,7 +1320,8 @@ function runDexsearch(target: string, cmd: string, message: string, isTest: bool
) {
let newSpecies = species;
for (const rule of rules) {
newSpecies = rule?.onModifySpecies?.call({ dex: mod, clampIntRange: Utils.clampIntRange, toID } as Battle,
if (!rule || rule.effectType === 'ValidatorRule') continue;
newSpecies = rule.onModifySpecies?.call({ dex: mod, clampIntRange: Utils.clampIntRange, toID } as Battle,
newSpecies) || newSpecies;
}
dex[newSpecies.id] = newSpecies;

View File

@ -125,6 +125,9 @@ export interface EventMethods {
onWeatherModifyDamage?: CommonHandlers['ModifierSourceMove'];
onModifyDamagePhase1?: CommonHandlers['ModifierSourceMove'];
onModifyDamagePhase2?: CommonHandlers['ModifierSourceMove'];
onModifySpecies?: (
this: Battle, species: Species, target?: Pokemon, source?: Pokemon, effect?: Effect
) => Species | void;
onFoeDamagingHit?: (this: Battle, damage: number, target: Pokemon, source: Pokemon, move: ActiveMove) => void;
onFoeAfterEachBoost?: (this: Battle, boost: SparseBoostsTable, target: Pokemon, source: Pokemon) => void;
onFoeAfterHit?: MoveEventMethods['onAfterHit'];
@ -472,6 +475,7 @@ export interface EventMethods {
onModifySpAPriority?: number;
onModifySpDPriority?: number;
onModifySpePriority?: number;
onModifySpeciesPriority?: number;
onModifySTABPriority?: number;
onModifyTypePriority?: number;
onModifyWeightPriority?: number;
@ -616,6 +620,14 @@ export interface FieldEventMethods extends EventMethods {
onFieldResidualPriority?: number;
onFieldResidualSubOrder?: number;
}
export interface RuleEventMethods extends EventMethods {
onBegin?: (this: Battle) => void;
onBattleStart?: (this: Battle) => void;
onTeamPreview?: (this: Battle) => void;
onChooseTeam?: (
this: Battle, positions: number[], pokemon: Pokemon[], autoChoose?: boolean
) => number[] | string | void;
}
export interface PokemonConditionData extends Partial<Condition>, PokemonEventMethods {}
export interface SideConditionData extends
Partial<Omit<Condition, 'onStart' | 'onRestart' | 'onEnd'>>, SideEventMethods {}

View File

@ -1,21 +1,174 @@
import { Utils } from '../lib/utils';
import { assignMissingFields, toID, BasicEffect } from './dex-data';
import type { EventMethods } from './dex-conditions';
import type { RuleEventMethods } from './dex-conditions';
import type { SpeciesData } from './dex-species';
import { Tags } from '../data/tags';
const DEFAULT_MOD = 'gen9';
export interface FormatData extends Partial<Format>, EventMethods {
name: string;
export type RuleValueType = boolean | 'integer' | 'positive-integer';
/** Used for onValidateRule handlers */
export interface RuleTableBuildContext {
format: Format;
ruleTable: RuleTable;
dex: ModdedDex;
}
export type FormatList = (FormatData | { section: string, column?: number })[];
export type ModdedFormatData = FormatData | Omit<FormatData, 'name'> & { inherit: true };
export interface FormatDataTable { [id: IDEntry]: FormatData }
export interface ModdedFormatDataTable { [id: IDEntry]: ModdedFormatData }
type NamedBasicEffectFragment = Omit<WithRequired<Readonly<BasicEffect>, 'name'>, 'effectType'>;
type FormatEffectType = 'Format' | 'Ruleset' | 'Rule' | 'ValidatorRule';
interface ValidatorRuleFields {
/** List of rule names. */
ruleset?: string[];
/** List of banned effects. */
banlist?: string[];
/** List of effects that aren't completely banned. */
restricted?: string[];
/** List of inherited banned effects to override. */
unbanlist?: string[];
/** Needed in order to print clauses */
onBegin?: RuleEventMethods['onBegin'];
checkCanLearn?: (
this: TeamValidator, move: Move, species: Species, setSources: PokemonSources, set: PokemonSet
) => string | null;
onChangeSet?: (
this: TeamValidator, set: PokemonSet, format: Format, setHas?: AnyObject, teamHas?: AnyObject
) => string[] | void;
onValidateSet?: (
this: TeamValidator, set: PokemonSet, format: Format, setHas: AnyObject, teamHas: AnyObject
) => string[] | void;
onValidateTeam?: (
this: TeamValidator, team: PokemonSet[], format: Format, teamHas: AnyObject
) => string[] | void;
/** ID of rule that can't be combined with this rule */
mutuallyExclusiveWith?: string;
}
interface RuleFields extends ValidatorRuleFields, RuleEventMethods {}
interface FormatFields extends RuleFields {
mod?: string;
/**
* Name of the team generator algorithm, if this format uses
* random/fixed teams. null if players can bring teams.
*/
team?: string;
debug?: boolean;
noLog?: boolean;
/**
* Whether or not a format will update ladder points if searched
* for using the "Battle!" button.
* (Challenge and tournament games will never update ladder points.)
* (Defaults to `true`.)
*/
rated?: boolean | string;
/** Game type. */
gameType?: GameType;
threads?: string[];
/** Overrides for battle scripts */
battle?: ModdedBattleScriptsData;
pokemon?: ModdedBattlePokemon;
queue?: ModdedBattleQueue;
field?: ModdedField;
actions?: ModdedBattleActions;
side?: ModdedBattleSide;
/** Flags for the formats list */
challengeShow?: boolean;
searchShow?: boolean;
tournamentShow?: boolean;
bestOfDefault?: boolean;
teraPreviewDefault?: boolean;
itemClauseDefault?: boolean;
/** Validator overrides */
validateSet?: (this: TeamValidator, set: PokemonSet, teamHas: AnyObject) => string[] | null;
validateTeam?: (this: TeamValidator, team: PokemonSet[], options?: {
removeNicknames?: boolean,
skipSets?: { [name: string]: { [key: string]: boolean } },
}) => string[] | void;
// OMs
getEvoFamily?: (this: Format, speciesid: string) => ID;
getSharedPower?: (this: Format, pokemon: Pokemon) => Set<string>;
getSharedItems?: (this: Format, pokemon: Pokemon) => Set<string>;
}
interface TaggedValidatorRuleFields extends ValidatorRuleFields {
effectType: 'ValidatorRule';
/**
* Only applies to rules, not formats
*/
hasValue?: RuleValueType;
onValidateRule?: (this: RuleTableBuildContext, value: string) => string | void;
}
interface TaggedRuleFields extends RuleFields {
effectType: 'Rule';
/**
* Only applies to rules, not formats
*/
hasValue?: RuleValueType;
onValidateRule?: (this: RuleTableBuildContext, value: string) => string | void;
}
interface TaggedFormatFields extends FormatFields {
/**
* A format can be used as a rule, but without an associated value.
*/
onValidateRule?: (this: RuleTableBuildContext) => string | void;
}
export interface ValidatorRuleData extends NamedBasicEffectFragment, Readonly<TaggedValidatorRuleFields> {}
export interface RuleData extends NamedBasicEffectFragment, Readonly<TaggedRuleFields> {}
export interface FormatData extends NamedBasicEffectFragment, Readonly<TaggedFormatFields> {}
/** Distinguishes types for formats in `config/formats.ts` vs in `Dex.data.Rulesets` */
export interface LoadedFormatData extends FormatData {
effectType: 'Format';
section: string;
column: number;
ruleTable: RuleTable | null;
}
type FormatDataVariantMap = {
Format: FormatData,
Rule: RuleData,
ValidatorRule: ValidatorRuleData,
};
export type FormatEffectType = keyof FormatDataVariantMap;
export type RulesetEffectType = Exclude<FormatEffectType, 'Format'>;
type FormatDataVariant<K extends FormatEffectType> = FormatDataVariantMap[K];
export type GeneralizedFormatData = FormatDataVariant<FormatEffectType>;
type GeneralizedRuleData = FormatDataVariant<RulesetEffectType>;
export type ModdedRuleData = RuleData | (Omit<
Omit<RuleData, 'name'>,
'effectType'
> & { inherit: true });
export type ModdedValidatorRuleData = ValidatorRuleData | (Omit<
Omit<ValidatorRuleData, 'name'>,
'effectType'
> & { inherit: true });
export type ModdedGeneralizedRuleData = GeneralizedRuleData | (Omit<
Omit<GeneralizedRuleData, 'name'>,
'effectType'
> & { inherit: true });
export type FormatList = (FormatData | { section: string, column?: number })[];
export interface RulesetTable { [id: IDEntry]: GeneralizedRuleData }
export interface ModdedRulesetTable { [id: IDEntry]: ModdedGeneralizedRuleData }
/** Union type for formats OR rules in `Dex.data.Rulesets` */
export type RulesetData = (LoadedFormatData | GeneralizedRuleData);
/** rule, source, limit, bans */
export type ComplexBan = [string, string, number, string[]];
@ -46,7 +199,7 @@ export class RuleTable extends Map<string, string> {
complexBans: ComplexBan[];
complexTeamBans: ComplexTeamBan[];
checkCanLearn: [TeamValidator['checkCanLearn'], string] | null;
onChooseTeam: [NonNullable<Format['onChooseTeam']>, string] | null;
onChooseTeam: [NonNullable<RuleEventMethods['onChooseTeam']>, string] | null;
timer: [Partial<GameTimerSettings>, string] | null;
tagRules: string[];
valueRules: Map<string, string>;
@ -375,7 +528,7 @@ export class RuleTable extends Map<string, string> {
}
}
export class Format extends BasicEffect implements Readonly<BasicEffect> {
export class Format extends BasicEffect implements Readonly<BasicEffect>, RuleEventMethods {
readonly mod: string;
/**
* Name of the team generator algorithm, if this format uses
@ -384,6 +537,7 @@ export class Format extends BasicEffect implements Readonly<BasicEffect> {
declare readonly team?: string;
override readonly effectType: FormatEffectType;
readonly debug: boolean;
readonly noLog: boolean;
/**
* Whether or not a format will update ladder points if searched
* for using the "Battle!" button.
@ -412,16 +566,13 @@ export class Format extends BasicEffect implements Readonly<BasicEffect> {
readonly customRules: string[] | null;
/** Table of rule names and banned effects. */
ruleTable: RuleTable | null;
/** An optional function that runs at the start of a battle. */
readonly onBegin?: (this: Battle) => void;
readonly noLog: boolean;
/**
* Only applies to rules, not formats
*/
declare readonly hasValue?: boolean | 'integer' | 'positive-integer';
declare readonly hasValue?: RuleValueType;
declare readonly onValidateRule?: (
this: { format: Format, ruleTable: RuleTable, dex: ModdedDex }, value: string
this: RuleTableBuildContext, value: string
) => string | void;
/** ID of rule that can't be combined with this rule */
declare readonly mutuallyExclusiveWith?: string;
@ -432,49 +583,54 @@ export class Format extends BasicEffect implements Readonly<BasicEffect> {
declare readonly field?: ModdedField;
declare readonly actions?: ModdedBattleActions;
declare readonly side?: ModdedBattleSide;
declare readonly challengeShow?: boolean;
declare readonly searchShow?: boolean;
declare readonly tournamentShow?: boolean;
declare readonly bestOfDefault?: boolean;
declare readonly teraPreviewDefault?: boolean;
declare readonly itemClauseDefault?: boolean;
declare readonly threads?: string[];
declare readonly tournamentShow?: boolean;
declare readonly checkCanLearn?: (
this: TeamValidator, move: Move, species: Species, setSources: PokemonSources, set: PokemonSet
) => string | null;
declare readonly getEvoFamily?: (this: Format, speciesid: string) => ID;
declare readonly getSharedPower?: (this: Format, pokemon: Pokemon) => Set<string>;
declare readonly getSharedItems?: (this: Format, pokemon: Pokemon) => Set<string>;
declare readonly onChangeSet?: (
this: TeamValidator, set: PokemonSet, format: Format, setHas?: AnyObject, teamHas?: AnyObject
) => string[] | void;
declare readonly onModifySpeciesPriority?: number;
declare readonly onModifySpecies?: (
this: Battle, species: Species, target?: Pokemon, source?: Pokemon, effect?: Effect
) => Species | void;
declare readonly onBattleStart?: (this: Battle) => void;
declare readonly onTeamPreview?: (this: Battle) => void;
declare readonly onChooseTeam?: (
this: Battle, positions: number[], pokemon: Pokemon[], autoChoose?: boolean
) => number[] | string | void;
declare readonly onValidateSet?: (
this: TeamValidator, set: PokemonSet, format: Format, setHas: AnyObject, teamHas: AnyObject
) => string[] | void;
declare readonly onValidateTeam?: (
this: TeamValidator, team: PokemonSet[], format: Format, teamHas: AnyObject
) => string[] | void;
declare readonly validateSet?: (this: TeamValidator, set: PokemonSet, teamHas: AnyObject) => string[] | null;
declare readonly validateTeam?: (this: TeamValidator, team: PokemonSet[], options?: {
removeNicknames?: boolean,
skipSets?: { [name: string]: { [key: string]: boolean } },
}) => string[] | void;
declare readonly onBegin?: RuleEventMethods['onBegin'];
declare readonly onBattleStart?: RuleEventMethods['onBattleStart'];
declare readonly onTeamPreview?: RuleEventMethods['onTeamPreview'];
declare readonly onChooseTeam?: RuleEventMethods['onChooseTeam'];
declare readonly onModifySpeciesPriority?: RuleEventMethods['onModifySpeciesPriority'];
declare readonly onModifySpecies?: RuleEventMethods['onModifySpecies'];
declare readonly section?: string;
declare readonly column?: number;
// OMs
getEvoFamily?: (this: Format, speciesid: string) => ID;
getSharedPower?: (this: Format, pokemon: Pokemon) => Set<string>;
getSharedItems?: (this: Format, pokemon: Pokemon) => Set<string>;
constructor(data: AnyObject) {
super(data);
this.mod = Utils.getString(data.mod) || 'gen9';
this.mod = Utils.getString(data.mod) || DEFAULT_MOD;
this.effectType = Utils.getString(data.effectType) as FormatEffectType || 'Condition';
this.debug = !!data.debug;
this.rated = (typeof data.rated === 'string' ? data.rated : data.rated !== false);
@ -514,11 +670,11 @@ function mergeFormatLists(main: FormatList, custom: FormatList | undefined): For
// populates the original sections and formats easily
// there should be no repeat sections at this point.
for (const element of main) {
if (element.section) {
if ('section' in element) {
current = { section: element.section, column: element.column, formats: [] };
build.push(current);
} else if ((element as FormatData).name) {
current.formats.push((element as FormatData));
} else if (element.name) {
current.formats.push(element);
}
}
@ -526,7 +682,7 @@ function mergeFormatLists(main: FormatList, custom: FormatList | undefined): For
if (custom !== undefined) {
for (const element of custom) {
// finds the section and makes it if it doesn't exist.
if (element.section) {
if ('section' in element) {
current = build.find(e => e.section === element.section);
// if it's new it makes a new entry.
@ -534,8 +690,8 @@ function mergeFormatLists(main: FormatList, custom: FormatList | undefined): For
current = { section: element.section, column: element.column, formats: [] };
build.push(current);
}
} else if ((element as FormatData).name) { // otherwise, adds the element to its section.
current.formats.push(element as FormatData);
} else if (element.name) { // otherwise, adds the element to its section.
current.formats.push(element);
}
}
}
@ -605,7 +761,7 @@ export class DexFormats {
if (format.bestOfDefault === undefined) format.bestOfDefault = false;
if (format.teraPreviewDefault === undefined) format.teraPreviewDefault = false;
if (format.itemClauseDefault === undefined) format.itemClauseDefault = false;
if (format.mod === undefined) format.mod = 'gen9';
if (format.mod === undefined) format.mod = DEFAULT_MOD;
if (!this.dex.dexes[format.mod]) throw new Error(`Format "${format.name}" requires nonexistent mod: '${format.mod}'`);
this.checkDeprecated(format);
@ -729,6 +885,19 @@ export class DexFormats {
return this.formatsListCache!;
}
find(filterFn: (format: Format) => boolean): Format | null {
this.load();
for (const format of this.formatsListCache!) {
if (filterFn(format)) return format;
}
return null;
}
filter(filterFn: (format: Format) => boolean): Format[] {
this.load();
return this.formatsListCache!.filter(filterFn);
}
isPokemonRule(ruleSpec: string) {
return (
ruleSpec.slice(1).startsWith('pokemontag:') || ruleSpec.slice(1).startsWith('pokemon:') ||

View File

@ -73,7 +73,7 @@ export interface AliasesTable { [id: IDEntry]: string }
interface DexTableData {
Abilities: DexTable<import('./dex-abilities').AbilityData>;
Rulesets: DexTable<import('./dex-formats').FormatData>;
Rulesets: DexTable<import('./dex-formats').RulesetData>;
Items: DexTable<import('./dex-items').ItemData>;
Learnsets: DexTable<import('./dex-species').LearnsetData>;
Moves: DexTable<import('./dex-moves').MoveData>;

View File

@ -4,6 +4,8 @@ type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
type WithRequired<T, K extends keyof T> = Partial<T> & Required<Pick<T, K>>;
type Battle = import('./battle').Battle;
type BattleQueue = import('./battle-queue').BattleQueue;
type BattleActions = import('./battle-actions').BattleActions;