diff --git a/src/system/schemas/common.ts b/src/system/schemas/common.ts index 19f95241d8b..230639ce874 100644 --- a/src/system/schemas/common.ts +++ b/src/system/schemas/common.ts @@ -19,6 +19,12 @@ export const Z$BoolCatchToFalse = /*@__PURE__*/ z .boolean() .catch(false); +/** Reusable schema for a positive number, equivalent to `z.number().positive()`. */ +export const Z$PositiveNumber = /*@__PURE__*/ z + .number() + .positive() + .catch(0); + /** Reusable schema for an optional non-negative integer that coerces invalid inputs to `undefined` */ export const Z$OptionalNonNegativeIntCatchToUndef = /*@__PURE__*/ z .int() diff --git a/src/system/schemas/v1.10/pokemon-data.ts b/src/system/schemas/v1.10/pokemon-data.ts index 9f4fa01b128..824a56b5614 100644 --- a/src/system/schemas/v1.10/pokemon-data.ts +++ b/src/system/schemas/v1.10/pokemon-data.ts @@ -4,7 +4,7 @@ import { Z$PokemonMove } from "#schemas/pokemon-move"; import { Z$Gender } from "#system/schemas/v1.10/pokemon-gender"; import z from "zod"; import { NatureSchema } from "./pokemon-nature"; -import { IVSetSchema, statSetSchema } from "./pokemon-stats"; +import { Z$IVSet, Z$StatSet } from "./pokemon-stats"; import { Z$PokemonType } from "./pokemon-type"; import { StatusSchema } from "./status-effect"; @@ -37,8 +37,8 @@ const Z$PokemonData = z.looseObject({ gender: Z$Gender.catch(-1), // hp can be 0 if fainted hp: Z$NonNegativeInt, - stats: statSetSchema, - ivs: IVSetSchema, + stats: Z$StatSet, + ivs: Z$IVSet, nature: NatureSchema, moveset: z.array(Z$PokemonMove).catch([]), status: z.union([z.null(), StatusSchema]).catch(null), @@ -88,8 +88,6 @@ export const Z$EnemyPokemonData = z.object({ bossSegments: z.int().nonnegative().default(0), }); - - // TODO: Replace output assertion type with the type of pokemon data that has CustomPokemonData. export function PreCustomPokemonDataMigrator( data: z.output, diff --git a/src/system/schemas/v1.10/pokemon-species-form.ts b/src/system/schemas/v1.10/pokemon-species-form.ts new file mode 100644 index 00000000000..aed8bbea42e --- /dev/null +++ b/src/system/schemas/v1.10/pokemon-species-form.ts @@ -0,0 +1,30 @@ +import { Z$NonNegativeInt, Z$PositiveInt, Z$PositiveNumber } from "#system/schemas/common"; +import { Z$PokemonType } from "#system/schemas/v1.10/pokemon-type"; +import { z } from "zod"; + +export const Z$PokemonSpeciesForm = z.object({ + speciesId: Z$PositiveInt, + _formIndex: Z$NonNegativeInt.catch(0), + _generation: Z$PositiveInt.catch(1), + type1: Z$PokemonType, + type2: Z$PokemonType.nullable().catch(null), + height: Z$PositiveNumber, + weight: Z$PositiveNumber, + ability: Z$NonNegativeInt, + ability2: Z$NonNegativeInt, + abilityHidden: Z$NonNegativeInt, + baseTotal: Z$PositiveInt, + baseStats: z.tuple([ + Z$PositiveInt, // hp + Z$PositiveInt, // atk + Z$PositiveInt, // def + Z$PositiveInt, // spa + Z$PositiveInt, // spd + Z$PositiveInt, // spe + ]), + catchRate: z.int().min(0).max(255), + baseFriendship: Z$NonNegativeInt, + baseExp: Z$PositiveInt, + genderDiffs: z.boolean(), + isStarterSelectable: z.boolean(), +}); diff --git a/src/system/schemas/v1.10/pokemon-stats.ts b/src/system/schemas/v1.10/pokemon-stats.ts index a52f5b9cb33..cb855525990 100644 --- a/src/system/schemas/v1.10/pokemon-stats.ts +++ b/src/system/schemas/v1.10/pokemon-stats.ts @@ -8,7 +8,7 @@ import { z } from "zod"; * - Each IV is an integer between 0 and 31, inclusive. * - Malformed values parse to 15 by default. */ -export const IVSchema = z.int().min(0).max(31).catch(15); +export const Z$IV = z.int().min(0).max(31).catch(15); /** * Schema for a set of 6 Pokémon IVs, as of version 1.10 @@ -16,9 +16,7 @@ export const IVSchema = z.int().min(0).max(31).catch(15); * @remarks * Malformed IV sets default to [15, 15, 15, 15, 15, 15]. */ -export const IVSetSchema = z - .tuple([IVSchema, IVSchema, IVSchema, IVSchema, IVSchema, IVSchema]) - .catch([15, 15, 15, 15, 15, 15]); +export const Z$IVSet = z.tuple([Z$IV, Z$IV, Z$IV, Z$IV, Z$IV, Z$IV]).catch([15, 15, 15, 15, 15, 15]); /** * Schema for a Pokémon's stats, as of version 1.10 @@ -29,7 +27,7 @@ export const IVSetSchema = z * - [4]: Special Defense, * - [5]: Speed */ -export const statSetSchema = z.tuple([ +export const Z$StatSet = z.tuple([ Z$PositiveInt, // HP Z$PositiveInt, // Attack Z$PositiveInt, // Defense diff --git a/src/system/schemas/v1.10/pokemon-summon-data.ts b/src/system/schemas/v1.10/pokemon-summon-data.ts index 15a5be30f4a..2cd078f3631 100644 --- a/src/system/schemas/v1.10/pokemon-summon-data.ts +++ b/src/system/schemas/v1.10/pokemon-summon-data.ts @@ -1,7 +1,11 @@ +import { Z$NonNegativeInt } from "#system/schemas/common"; +import { Z$Gender } from "#system/schemas/v1.10/pokemon-gender"; +import { Z$PokemonSpeciesForm } from "#system/schemas/v1.10/pokemon-species-form"; +import { Z$StatSet } from "#system/schemas/v1.10/pokemon-stats"; +import { Z$PokemonType } from "#system/schemas/v1.10/pokemon-type"; import { Z$TurnMove } from "#system/schemas/v1.10/turn-move"; import { z } from "zod"; - const Z$StatStage = z.int().min(-6).max(6).catch(0); const Z$StatStageSet = z.tuple([ @@ -11,17 +15,33 @@ const Z$StatStageSet = z.tuple([ Z$StatStage, Z$StatStage, Z$StatStage, - Z$StatStage]) + Z$StatStage, +]); + +// Pre version 1.10 pokemon summon data migration needs to rename +// input fields + /** * Zod schema for Pokémon summon data as of version 1.10. - * + * */ export const Z$PokemonSummonData = z.object({ - statStages: Z$StatStageSet.optional().catch(undefined), - moveQueue: z.array(Z$TurnMove).optional().catch(undefined), + statStages: Z$StatStageSet.optional().catch(undefined), + moveQueue: z.array(Z$TurnMove).optional().catch(undefined), + // todo: tags + abilitySuppressed: z.boolean().optional().catch(undefined), - //#region Overrides for transform + //#region Overrides for transform + speciesForm: Z$PokemonSpeciesForm.nullable().catch(null), + fusionSpeciesForm: Z$PokemonSpeciesForm.nullable().catch(null), + ability: Z$NonNegativeInt.optional().catch(undefined), + passiveAbility: Z$NonNegativeInt.optional().catch(undefined), + gender: Z$Gender.optional().catch(undefined), + fusionGender: Z$Gender.optional().catch(undefined), + stats: Z$StatSet.optional().catch(undefined), + moveset: z.array(Z$TurnMove).nullable().catch(null), + //#endregion Overrides for transform - //#endregion Overrides for transform - -}); \ No newline at end of file + types: z.array(Z$PokemonType).optional().catch(undefined), + addedType: Z$PokemonType.nullable().catch(null), +});