mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-09 00:49:27 +02:00
[WIP]
This commit is contained in:
parent
2d3002ce2d
commit
c690b19d74
@ -1,8 +1,16 @@
|
||||
// biome-ignore-start lint/correctness/noUnusedImports: Used in a TSDoc comment
|
||||
import type { AbilityBattlerTag, BattlerTagTypeMap, SerializableBattlerTag, TypeBoostTag } from "#data/battler-tags";
|
||||
import type {
|
||||
AbilityBattlerTag,
|
||||
BattlerTag,
|
||||
BattlerTagTypeMap,
|
||||
SerializableBattlerTag,
|
||||
TypeBoostTag,
|
||||
} from "#data/battler-tags";
|
||||
import type { AbilityId } from "#enums/ability-id";
|
||||
// biome-ignore-end lint/correctness/noUnusedImports: end
|
||||
import type { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import type { MatchShape } from "#types/type-helpers";
|
||||
|
||||
/**
|
||||
* Subset of {@linkcode BattlerTagType}s that restrict the use of moves.
|
||||
@ -97,6 +105,17 @@ export type CritStageBoostTagType = BattlerTagType.CRIT_BOOST | BattlerTagType.D
|
||||
/** Subset of {@linkcode BattlerTagType}s that remove one of the users' types */
|
||||
export type RemovedTypeTagType = BattlerTagType.DOUBLE_SHOCKED | BattlerTagType.BURNED_UP;
|
||||
|
||||
/**
|
||||
* Subset of {@linkcode BattlerTagType}s that provide type boosts
|
||||
*/
|
||||
export type TypeBoostTagType = BattlerTagType.FIRE_BOOST | BattlerTagType.CHARGED;
|
||||
|
||||
/** Subset of {@linkcode BattlerTagType}s that boost the user's critical stage */
|
||||
export type CritStageBoostTagType = BattlerTagType.CRIT_BOOST | BattlerTagType.DRAGON_CHEER;
|
||||
|
||||
/** Subset of {@linkcode BattlerTagType}s that remove one of the users' types */
|
||||
export type RemovedTypeTagType = BattlerTagType.DOUBLE_SHOCKED | BattlerTagType.BURNED_UP;
|
||||
|
||||
/**
|
||||
* Subset of {@linkcode BattlerTagType}s related to abilities that boost the highest stat.
|
||||
*/
|
||||
@ -122,14 +141,38 @@ export type NonSerializableBattlerTagType = Exclude<BattlerTagType, Serializable
|
||||
*/
|
||||
export type BattlerTagTypeData = Parameters<
|
||||
BattlerTagTypeMap[keyof {
|
||||
[K in keyof BattlerTagTypeMap as K extends SerializableBattlerTagType ? K : never]: BattlerTagTypeMap[K];
|
||||
[K in SerializableBattlerTagType]: BattlerTagTypeMap[K];
|
||||
}]["loadTag"]
|
||||
>[0];
|
||||
|
||||
/**
|
||||
* Subset of {@linkcode BattlerTagType}s whose associated `BattlerTag` adds a serializable `moveId` field
|
||||
* Subset of {@linkcode BattlerTagType}s whose associated `BattlerTag`
|
||||
* adds no additional fields that are serialized.
|
||||
*/
|
||||
export type BattlerTagTypeWithMoveId = BattlerTagType.DISABLED | BattlerTagType.GORILLA_TACTICS | BattlerTagType.ENCORE;
|
||||
export type BasicBattlerTag = keyof {
|
||||
[K in SerializableBattlerTagType as MatchShape<
|
||||
Parameters<BattlerTagTypeMap[K]["loadTag"]>[0],
|
||||
Parameters<BattlerTag["loadTag"]>[0]
|
||||
> extends never
|
||||
? never
|
||||
: K]: any;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subset of {@linkcode BattlerTagType}s whose associated `BattlerTag` adds a serializable `moveId` field
|
||||
* (and no other serialized fields).
|
||||
*
|
||||
* @remarks
|
||||
* Intended to be used to simplify type safety in the zod schemas.
|
||||
*/
|
||||
export type BattlerTagTypeWithMoveId = keyof {
|
||||
[K in SerializableBattlerTagType as MatchShape<
|
||||
Parameters<BattlerTagTypeMap[K]["loadTag"]>[0],
|
||||
Parameters<BattlerTag["loadTag"]>[0] & { moveId: MoveId }
|
||||
> extends never
|
||||
? never
|
||||
: K]: any;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dummy, typescript-only declaration to ensure that
|
||||
|
@ -44,20 +44,12 @@ export type InferKeys<O extends object, V extends ObjectValues<O>> = {
|
||||
}[keyof O];
|
||||
|
||||
/**
|
||||
* Type helper to construct a union type of the type of each field in an object.
|
||||
*
|
||||
* @typeParam T - The type of the object to extract values from.
|
||||
*
|
||||
* Utility type to obtain the values of a given object. \
|
||||
* Functions similar to `keyof E`, except producing the values instead of the keys.
|
||||
* @remarks
|
||||
* Can be used to convert an `enum` interface produced by `typeof Enum` into the union type representing its members.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* type oneThruThree = ObjectValues<{ a: 1, b: 2, c: 3 }>
|
||||
* // ^? 1 | 2 | 3
|
||||
* ```
|
||||
* This can be used to convert an `enum` interface produced by `typeof Enum` into the union type representing its members.
|
||||
*/
|
||||
export type ObjectValues<T extends object> = T[keyof T];
|
||||
export type ObjectValues<E extends object> = E[keyof E];
|
||||
|
||||
/**
|
||||
* Type helper that matches any `Function` type.
|
||||
@ -72,7 +64,6 @@ export type AnyFn = (...args: any[]) => any;
|
||||
* Useful to produce a type that is roughly the same as the type of `{... obj}`, where `obj` is an instance of `T`.
|
||||
* A couple of differences:
|
||||
* - Private and protected properties are not included.
|
||||
* - Accessors with getters *are* included
|
||||
* - Nested properties are not recursively extracted. For this, use {@linkcode NonFunctionPropertiesRecursive}
|
||||
*/
|
||||
export type NonFunctionProperties<T> = {
|
||||
@ -103,3 +94,16 @@ export type AbstractConstructor<T> = abstract new (...args: any[]) => T;
|
||||
export type CoerceNullPropertiesToUndefined<T extends object> = {
|
||||
[K in keyof T]: null extends T[K] ? Exclude<T[K], null> | undefined : T[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* Type helper that takes two types and ensures that their shapes match *exactly*.
|
||||
* Resolves to T1 if T1 and T2 have the same shape, otherwise resolves to `never`.
|
||||
*
|
||||
* @remarks
|
||||
* Meant to be used in the `as` clause of a mapped type
|
||||
*/
|
||||
export type MatchShape<T1 extends object, T2 extends object> = T1 extends T2
|
||||
? Exclude<keyof T1, keyof T2> extends never
|
||||
? T1
|
||||
: never
|
||||
: never;
|
||||
|
@ -5,29 +5,16 @@ Schemas for commonly used primitive types, to avoid repeated instantiations.
|
||||
*/
|
||||
|
||||
/** Reusable schema for a positive integer, equivalent to `z.int().positive()`.*/
|
||||
export const Z$PositiveInt = /*@__PURE__*/ z
|
||||
.int()
|
||||
.positive();
|
||||
export const Z$PositiveInt = z.int().positive();
|
||||
|
||||
/** Reusable schema for a non-negative integer, equivalent to `z.int().nonnegative()`.*/
|
||||
export const Z$NonNegativeInt = /*@__PURE__*/ z
|
||||
.int()
|
||||
.nonnegative();
|
||||
export const Z$NonNegativeInt = z.int().nonnegative();
|
||||
|
||||
/** Reusable schema for a boolean that coerces non-boolean inputs to `false` */
|
||||
export const Z$BoolCatchToFalse = /*@__PURE__*/ z
|
||||
.boolean()
|
||||
.catch(false);
|
||||
export const Z$BoolCatchToFalse = 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);
|
||||
export const Z$PositiveNumber = 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()
|
||||
.nonnegative()
|
||||
.optional()
|
||||
.catch(undefined);
|
||||
export const Z$OptionalNonNegativeIntCatchToUndef = z.int().nonnegative().optional().catch(undefined);
|
||||
|
@ -1,12 +1,9 @@
|
||||
import { loadBattlerTag } from "#data/battler-tags";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { Z$NonNegativeInt, Z$PositiveInt } from "#system/schemas/common";
|
||||
import { Z$BattlerIndex } from "#system/schemas/pokemon/battler-index";
|
||||
import { Z$Stat } from "#system/schemas/pokemon/pokemon-stats";
|
||||
import type {
|
||||
BattlerTagTypeWithMoveId,
|
||||
HighestStatBoostTagType,
|
||||
SerializableBattlerTagType,
|
||||
} from "#types/battler-tags";
|
||||
import type { BasicBattlerTag, BattlerTagTypeWithMoveId, HighestStatBoostTagType } from "#types/battler-tags";
|
||||
import type { DiscriminatedUnionFake } from "#types/schema-helpers";
|
||||
import { z } from "zod";
|
||||
|
||||
@ -15,22 +12,17 @@ Schemas for battler tags are a bit more cumbersome,
|
||||
as we need to have schemas for each subclass that has a different shape.
|
||||
*/
|
||||
|
||||
type BasicBattlerTag = Exclude<SerializableBattlerTagType, BattlerTagTypeWithMoveId | HighestStatBoostTagType>;
|
||||
|
||||
/**
|
||||
* Zod enum of {@linkcode BattlerTagType}s whose associated `BattlerTag` adds no
|
||||
* additional fields that are serialized.
|
||||
*
|
||||
*/
|
||||
const Z$BaseBattlerTags = /** @__PURE__ */ z.literal([
|
||||
const BasicBattlerTag = z.literal([
|
||||
BattlerTagType.RECHARGING,
|
||||
BattlerTagType.CONFUSED,
|
||||
BattlerTagType.INFATUATED,
|
||||
BattlerTagType.SEEDED,
|
||||
BattlerTagType.NIGHTMARE,
|
||||
BattlerTagType.FRENZY,
|
||||
BattlerTagType.CHARGING,
|
||||
BattlerTagType.ENCORE,
|
||||
BattlerTagType.INGRAIN,
|
||||
BattlerTagType.OCTOLOCK,
|
||||
BattlerTagType.AQUA_RING,
|
||||
@ -46,12 +38,9 @@ const Z$BaseBattlerTags = /** @__PURE__ */ z.literal([
|
||||
BattlerTagType.SNAP_TRAP,
|
||||
BattlerTagType.THUNDER_CAGE,
|
||||
BattlerTagType.INFESTATION,
|
||||
BattlerTagType.STURDY,
|
||||
BattlerTagType.PERISH_SONG,
|
||||
BattlerTagType.TRUANT,
|
||||
BattlerTagType.SLOW_START,
|
||||
BattlerTagType.PROTOSYNTHESIS,
|
||||
BattlerTagType.QUARK_DRIVE,
|
||||
BattlerTagType.FLYING,
|
||||
BattlerTagType.UNDERGROUND,
|
||||
BattlerTagType.UNDERWATER,
|
||||
@ -60,7 +49,6 @@ const Z$BaseBattlerTags = /** @__PURE__ */ z.literal([
|
||||
BattlerTagType.CRIT_BOOST,
|
||||
BattlerTagType.ALWAYS_CRIT,
|
||||
BattlerTagType.IGNORE_ACCURACY,
|
||||
BattlerTagType.BYPASS_SLEEP,
|
||||
BattlerTagType.IGNORE_FLYING,
|
||||
BattlerTagType.SALT_CURED,
|
||||
BattlerTagType.CURSED,
|
||||
@ -70,24 +58,19 @@ const Z$BaseBattlerTags = /** @__PURE__ */ z.literal([
|
||||
BattlerTagType.DESTINY_BOND,
|
||||
BattlerTagType.ICE_FACE,
|
||||
BattlerTagType.DISGUISE,
|
||||
BattlerTagType.STOCKPILING,
|
||||
BattlerTagType.RECEIVE_DOUBLE_DAMAGE,
|
||||
BattlerTagType.ALWAYS_GET_HIT,
|
||||
BattlerTagType.DISABLED,
|
||||
BattlerTagType.SUBSTITUTE,
|
||||
BattlerTagType.IGNORE_GHOST,
|
||||
BattlerTagType.IGNORE_DARK,
|
||||
BattlerTagType.GULP_MISSILE_ARROKUDA,
|
||||
BattlerTagType.GULP_MISSILE_PIKACHU,
|
||||
BattlerTagType.DRAGON_CHEER,
|
||||
BattlerTagType.NO_RETREAT,
|
||||
BattlerTagType.GORILLA_TACTICS,
|
||||
BattlerTagType.UNBURDEN,
|
||||
BattlerTagType.THROAT_CHOPPED,
|
||||
BattlerTagType.TAR_SHOT,
|
||||
BattlerTagType.BURNED_UP,
|
||||
BattlerTagType.DOUBLE_SHOCKED,
|
||||
BattlerTagType.AUTOTOMIZED,
|
||||
BattlerTagType.POWER_TRICK,
|
||||
BattlerTagType.HEAL_BLOCK,
|
||||
BattlerTagType.TORMENT,
|
||||
@ -95,26 +78,10 @@ const Z$BaseBattlerTags = /** @__PURE__ */ z.literal([
|
||||
BattlerTagType.IMPRISON,
|
||||
BattlerTagType.SYRUP_BOMB,
|
||||
BattlerTagType.TELEKINESIS,
|
||||
BattlerTagType.COMMANDED,
|
||||
BattlerTagType.GRUDGE,
|
||||
] satisfies SerializableBattlerTagType[]);
|
||||
] satisfies BasicBattlerTag[]);
|
||||
|
||||
/**
|
||||
* Zod schema for {@linkcode BattlerTagLapseType} as of version 1.10
|
||||
* @remarks
|
||||
* - `0`: Faint
|
||||
* - `1`: Move
|
||||
* - `2`: Pre-Move
|
||||
* - `3`: After Move
|
||||
* - `4`: Move Effect
|
||||
* - `5`: Turn End
|
||||
* - `6`: Hit
|
||||
* - `7`: After Hit
|
||||
* - `8`: Custom
|
||||
*/
|
||||
const Z$BattlerTagLapseType = /** @__PURE__ */ z.literal([0, 1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
const Z$BaseBattlerTag = /** @__PURE__ */ z.object({
|
||||
const Z$BaseBattlerTag = z.object({
|
||||
turnCount: Z$PositiveInt,
|
||||
// Source move can be `none` for tags not applied by move, so allow `0` here.
|
||||
sourceMove: Z$NonNegativeInt.optional().catch(undefined),
|
||||
@ -126,41 +93,56 @@ const Z$BaseTagWithMoveId = z.object({
|
||||
moveId: Z$PositiveInt,
|
||||
});
|
||||
|
||||
/** Subset of battler tags that have a moveID field */
|
||||
const Z$TagWithMoveId = /** @__PURE__ */ z.object({
|
||||
...Z$BaseTagWithMoveId.shape,
|
||||
tagType: z.literal([BattlerTagType.DISABLED, BattlerTagType.GORILLA_TACTICS, BattlerTagType.ENCORE]),
|
||||
moveId: Z$PositiveInt,
|
||||
}) as DiscriminatedUnionFake<
|
||||
BattlerTagType.DISABLED | BattlerTagType.GORILLA_TACTICS | BattlerTagType.ENCORE,
|
||||
typeof Z$TagWithMoveId.shape,
|
||||
"tagType"
|
||||
>;
|
||||
/**
|
||||
* Zod schema for a basic {@linkcode BattlerTag} (i.e., one that does not have
|
||||
* additional fields beyond the base `BattlerTag`).
|
||||
*/
|
||||
const Z$PlainBattlerTag = z.object({
|
||||
...Z$BaseBattlerTag.shape,
|
||||
tagType: BasicBattlerTag,
|
||||
}) as DiscriminatedUnionFake<BasicBattlerTag, typeof Z$PlainBattlerTag.shape, "tagType">;
|
||||
|
||||
const Z$SeedTag = /** @__PURE__ */ z.object({
|
||||
/** Subset of battler tags that have a moveID field */
|
||||
const Z$TagWithMoveId = z.object({
|
||||
...Z$BaseTagWithMoveId.shape,
|
||||
tagType: z.literal([
|
||||
BattlerTagType.DISABLED,
|
||||
BattlerTagType.GORILLA_TACTICS,
|
||||
BattlerTagType.ENCORE,
|
||||
] satisfies BattlerTagTypeWithMoveId[]),
|
||||
moveId: Z$PositiveInt,
|
||||
}) as DiscriminatedUnionFake<BattlerTagTypeWithMoveId, typeof Z$TagWithMoveId.shape, "tagType">;
|
||||
|
||||
/**
|
||||
* Zod schema for {@linkcode SeedTag} as of version 1.10.
|
||||
*/
|
||||
const Z$SeedTag = z.object({
|
||||
...Z$BaseBattlerTag.shape,
|
||||
tagType: z.literal(BattlerTagType.SEEDED),
|
||||
sourceIndex: Z$BattlerIndex,
|
||||
});
|
||||
|
||||
const Z$BaseHighestStatBoostTag = /** @__PURE__ */ z.object({
|
||||
/**
|
||||
* Zod schema for {@linkcode HighestStatBoostTag} as of version 1.10.
|
||||
*/
|
||||
const Z$BaseHighestStatBoostTag = z.object({
|
||||
...Z$BaseBattlerTag.shape,
|
||||
stat: Z$Stat,
|
||||
multiplier: z.number(),
|
||||
});
|
||||
|
||||
const Z$HighestStatBoostTag = /** @__PURE__ */ z.object({
|
||||
const Z$HighestStatBoostTag = z.object({
|
||||
...Z$BaseHighestStatBoostTag.shape,
|
||||
tagType: z.literal([BattlerTagType.QUARK_DRIVE, BattlerTagType.PROTOSYNTHESIS] satisfies HighestStatBoostTagType[]),
|
||||
}) as DiscriminatedUnionFake<HighestStatBoostTagType, typeof Z$HighestStatBoostTag.shape, "tagType">;
|
||||
|
||||
const Z$CommandedTag = /** @__PURE__ */ z.object({
|
||||
const Z$CommandedTag = z.object({
|
||||
...Z$BaseBattlerTag.shape,
|
||||
tagType: z.literal(BattlerTagType.COMMANDED),
|
||||
tatsugiriFormKey: z.string().catch("curly"),
|
||||
});
|
||||
|
||||
const Z$StockpilingTag = /** @__PURE__ */ z.object({
|
||||
const Z$StockpilingTag = z.object({
|
||||
...Z$BaseBattlerTag.shape,
|
||||
tagType: z.literal(BattlerTagType.STOCKPILING),
|
||||
stockpiledCount: Z$PositiveInt.catch(1),
|
||||
@ -170,14 +152,22 @@ const Z$StockpilingTag = /** @__PURE__ */ z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
const Z$AutotomizedTag = /** @__PURE__ */ z.object({
|
||||
const Z$AutotomizedTag = z.object({
|
||||
...Z$BaseBattlerTag.shape,
|
||||
tagType: z.literal(BattlerTagType.AUTOTOMIZED),
|
||||
autotomizeCount: Z$PositiveInt.catch(1),
|
||||
});
|
||||
|
||||
const Z$SubstituteTag = /** @__PURE__ */ z.object({
|
||||
const Z$SubstituteTag = z.object({
|
||||
...Z$BaseBattlerTag.shape,
|
||||
tagType: z.literal(BattlerTagType.SUBSTITUTE),
|
||||
hp: Z$PositiveInt,
|
||||
// hp: Z$PositiveInt,
|
||||
});
|
||||
|
||||
export const Z$BattlerTag = z.discriminatedUnion("tagType", [Z$SubstituteTag]);
|
||||
|
||||
declare const t: any;
|
||||
|
||||
const o = Z$BattlerTag.parse(t);
|
||||
|
||||
const r = loadBattlerTag(Z$SubstituteTag.parse(t));
|
||||
|
Loading…
Reference in New Issue
Block a user