mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-14 13:55:20 +01:00
[Docs] Update battler-tags.ts module doc comment for clarity (#6658)
--------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
This commit is contained in:
parent
fef48ac2e8
commit
3cfbb695e9
@ -1,39 +1,51 @@
|
||||
/**
|
||||
* BattlerTags are used to represent semi-persistent effects that can be attached to a Pokemon.
|
||||
* Note that before serialization, a new tag object is created, and then `loadTag` is called on the
|
||||
* tag with the object that was serialized.
|
||||
* `BattlerTag`s are used to represent semi-persistent effects attached to individual Pokemon.
|
||||
*
|
||||
* This means it is straightforward to avoid serializing fields.
|
||||
* Fields that are not set in the constructor and not set in `loadTag` will thus not be serialized.
|
||||
* During serialization, a new blank tag object is created, before its `loadTag` is called
|
||||
* with the object that was serialized. \
|
||||
* This makes it fairly straightforward to avoid serializing fields — anything not set in the class constructor
|
||||
* or the tag's `loadTag` method will not be serialized.
|
||||
*
|
||||
* Any battler tag that can persist across sessions must extend SerializableBattlerTag in its class definition signature.
|
||||
* Only tags that persist across waves (meaning their effect can last >1 turn) should be considered
|
||||
* serializable.
|
||||
* Any battler tag that can persist across waves (meaning it lasts longer than 1 turn)
|
||||
* **must extend `SerializableBattlerTag`** in its class definition signature.
|
||||
*
|
||||
* Serializable battler tags have strict requirements for their fields.
|
||||
* Properties that are not necessary to reconstruct the tag must not be serialized. This can be avoided
|
||||
* by using a private property. If access to the property is needed outside of the class, then
|
||||
* a getter (and potentially, a setter) should be used instead.
|
||||
* `SerializableBattlerTag`s have strict requirements for their fields:
|
||||
* - Properties that are not necessary to reconstruct the tag **must not be serialized**
|
||||
* This can be accomplished by using {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_elements | private elements}
|
||||
* and/or {@link https://www.typescriptlang.org/docs/handbook/2/classes.html#getters--setters | `getters`}. \
|
||||
* Note that `getter`s do not need to be tied to a class field, for example:
|
||||
* ```ts
|
||||
* class Example {
|
||||
* public get thing(): number {
|
||||
* return 5;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If a property that is intended to be private must be serialized, then it should instead
|
||||
* be declared as a public readonly propety. Then, in the `loadTag` method (or any method inside the class that needs to adjust the property)
|
||||
* use `(this as Mutable<this>).propertyName = value;`
|
||||
* These rules ensure that Typescript is aware of the shape of the serialized version of the class.
|
||||
* - If a property that is intended to be "private" should be serialized, it **must**
|
||||
* be declared as `public readonly` instead.
|
||||
* Then, in the `loadTag` method (or any internal method that needs to adjust the property),
|
||||
* use a cast to `Mutable<this>` (such as `(this as Mutable<this>).propertyName = value`). \
|
||||
* This ensures that Typescript is aware of the shape of the serialized version of the class.
|
||||
*
|
||||
* If any new serializable fields *are* added, then the class *must* override the
|
||||
* `loadTag` method to set the new fields. Its signature *must* match the example below:
|
||||
* ```
|
||||
* class ExampleTag extends SerializableBattlerTag {
|
||||
* // Example, if we add 2 new fields that should be serialized:
|
||||
* public a: string;
|
||||
* public b: number;
|
||||
* // Then we must also define a loadTag method with one of the following signatures
|
||||
* public override loadTag(source: BaseBattlerTag & Pick<ExampleTag, "tagType" | "a" | "b"): void;
|
||||
* public override loadTag<const T extends this>(source: BaseBattlerTag & Pick<T, "tagType" | "a" | "b">): void;
|
||||
* }
|
||||
* ```
|
||||
* Notes
|
||||
* - If the class has any subclasses, then the second form of `loadTag` *must* be used.
|
||||
* - If any new serializable fields _are_ added, then the class **must** override the
|
||||
* `loadTag` method to set the new fields. \
|
||||
* Its signature must match the example below:
|
||||
* ```ts
|
||||
* class ExampleTag extends SerializableBattlerTag {
|
||||
* // Example, if we add 2 new fields that should be serialized:
|
||||
* public a: string;
|
||||
* public b: number;
|
||||
* // Then we must also define a loadTag method with one of the following signatures:
|
||||
* // This signature should be used if the class has no subclasses:
|
||||
* public override loadTag(source: BaseBattlerTag & Pick<ExampleTag, "tagType" | "a" | "b"): void;
|
||||
* // This signature should be used if the class has any subclasses:
|
||||
* public override loadTag<const T extends this>(source: BaseBattlerTag & Pick<T, "tagType" | "a" | "b">): void {
|
||||
* this.a = source.a;
|
||||
* this.b = source.b;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @module
|
||||
*/
|
||||
|
||||
@ -92,13 +104,14 @@ import { coerceArray } from "#utils/array";
|
||||
import { BooleanHolder, getFrameMs, NumberHolder, toDmgValue } from "#utils/common";
|
||||
import { toCamelCase } from "#utils/strings";
|
||||
|
||||
/** Interface containing the serializable fields of BattlerTag */
|
||||
/** Interface containing the serializable fields of `BattlerTag` */
|
||||
interface BaseBattlerTag {
|
||||
/** The tag's remaining duration */
|
||||
/** The tag's remaining duration. */
|
||||
// TODO: Add support for omitting `turnCount`
|
||||
turnCount: number;
|
||||
/** The {@linkcode MoveId} that created this tag, or `undefined` if not set by a move */
|
||||
/** The {@linkcode MoveId} that created this tag, or `undefined` if not set by a move. */
|
||||
sourceMove?: MoveId;
|
||||
/** The {@linkcode Pokemon.id | PID} of the Pokemon that added this tag, or `undefined` if not set by a pokemon */
|
||||
/** The {@linkcode Pokemon.id | PID} of the Pokemon that added this tag, or `undefined` if not set by a Pokemon. */
|
||||
sourceId?: number;
|
||||
}
|
||||
|
||||
@ -144,6 +157,7 @@ export class BattlerTag implements BaseBattlerTag {
|
||||
this.#lapseTypes = coerceArray(lapseType);
|
||||
this.turnCount = turnCount;
|
||||
// We intentionally don't want to set source move to `MoveId.NONE` here, so a raw boolean comparison is OK.
|
||||
// TODO: Rework tags passing `MoveId.NONE` to instead pass `undefined` for consistency
|
||||
if (sourceMove) {
|
||||
this.sourceMove = sourceMove;
|
||||
}
|
||||
@ -195,7 +209,7 @@ export class BattlerTag implements BaseBattlerTag {
|
||||
/**
|
||||
* Load the data for a given {@linkcode BattlerTag} or JSON representation thereof.
|
||||
* Should be inherited from by any battler tag with custom attributes.
|
||||
* @param source - An object containing the fields needed to reconstruct this tag.
|
||||
* @param source - An object containing the fields needed to reconstruct this tag
|
||||
*/
|
||||
public loadTag<const T extends this>(source: BaseBattlerTag & Pick<T, "tagType">): void {
|
||||
this.turnCount = source.turnCount;
|
||||
@ -205,7 +219,7 @@ export class BattlerTag implements BaseBattlerTag {
|
||||
|
||||
/**
|
||||
* Helper function that retrieves the source Pokemon object
|
||||
* @returns The source {@linkcode Pokemon}, or `null` if none is found
|
||||
* @returns The source {@linkcode Pokemon}, or `undefined` if none is found
|
||||
*/
|
||||
public getSourcePokemon(): Pokemon | undefined {
|
||||
return globalScene.getPokemonById(this.sourceId);
|
||||
@ -213,7 +227,12 @@ export class BattlerTag implements BaseBattlerTag {
|
||||
}
|
||||
|
||||
export class SerializableBattlerTag extends BattlerTag {
|
||||
/** Nonexistent, dummy field to allow typescript to distinguish this class from `BattlerTag` */
|
||||
/**
|
||||
* Nonexistent, dummy field to allow typescript to distinguish this class from `BattlerTag`.
|
||||
*
|
||||
* @remarks
|
||||
* Does not exist at runtime, so must not be used!
|
||||
*/
|
||||
private declare __SerializableBattlerTag: never;
|
||||
}
|
||||
|
||||
@ -223,7 +242,7 @@ export class SerializableBattlerTag extends BattlerTag {
|
||||
*
|
||||
* @remarks
|
||||
* Used to ensure type safety when serializing battler tags,
|
||||
* allowing typescript to properly infer the type of the tag.
|
||||
* allowing Typescript to properly infer the type of the tag.
|
||||
* @see BattlerTagTypeMap
|
||||
*/
|
||||
interface GenericSerializableBattlerTag<T extends BattlerTagType> extends SerializableBattlerTag {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user