mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-08 08:29:37 +02:00
Applied review suggestions and added a _wee_ bit more docs
This commit is contained in:
parent
5d89e703f7
commit
fb19b2eea7
@ -3173,7 +3173,7 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr {
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: [overridden: BooleanHolder, useMode: MoveUseMode]): boolean {
|
||||
const useMode = args[1];
|
||||
if (useMode === MoveUseMode.TRANSPARENT) {
|
||||
if (useMode === MoveUseMode.DELAYED_ATTACK) {
|
||||
// don't trigger if already queueing an indirect attack
|
||||
return false;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { DelayedAttackTag, type PositionalTag, WishTag } from "#data/positional-tags/positional-tag";
|
||||
import { PositionalTagType } from "#enums/positional-tag-type";
|
||||
import type { EnumValues } from "#types/enum-types";
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
import type { Constructor } from "#utils/common";
|
||||
|
||||
/**
|
||||
* Add a new {@linkcode PositionalTag} to the arena.
|
||||
* Load the attributes of a {@linkcode PositionalTag}.
|
||||
* @param tagType - The {@linkcode PositionalTagType} to create
|
||||
* @param args - The arguments needed to instantize the given tag
|
||||
* @returns The newly created tag.
|
||||
@ -16,7 +16,7 @@ export function loadPositionalTag<T extends PositionalTagType>({
|
||||
...args
|
||||
}: serializedPosTagMap[T]): posTagInstanceMap[T];
|
||||
/**
|
||||
* Add a new {@linkcode PositionalTag} to the arena.
|
||||
* Load the attributes of a {@linkcode PositionalTag}.
|
||||
* @param tag - The {@linkcode SerializedPositionalTag} to instantiate
|
||||
* @returns The newly created tag.
|
||||
* @remarks
|
||||
@ -67,4 +67,4 @@ export type serializedPosTagMap = {
|
||||
};
|
||||
|
||||
/** Union type containing all serialized {@linkcode PositionalTag}s. */
|
||||
export type SerializedPositionalTag = EnumValues<serializedPosTagMap>;
|
||||
export type SerializedPositionalTag = ObjectValues<serializedPosTagMap>;
|
||||
|
@ -7,7 +7,8 @@ import type { PositionalTagType } from "#enums/positional-tag-type";
|
||||
export class PositionalTagManager {
|
||||
/**
|
||||
* Array containing all pending unactivated {@linkcode PositionalTag}s,
|
||||
* sorted by order of creation (oldest first). */
|
||||
* sorted by order of creation (oldest first).
|
||||
*/
|
||||
public tags: PositionalTag[] = [];
|
||||
|
||||
/**
|
||||
@ -30,12 +31,12 @@ export class PositionalTagManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement turn counts of and activate all pending {@linkcode PositionalTag}s on field.
|
||||
* Decrement turn counts of and trigger all pending {@linkcode PositionalTag}s on field.
|
||||
* @remarks
|
||||
* If multiple tags trigger simultaneously, they will activate **in order of initial creation**, regardless of speed order.
|
||||
* If multiple tags trigger simultaneously, they will activate in order of **initial creation**, regardless of current speed order.
|
||||
* (Source: [Smogon](<https://www.smogon.com/forums/threads/sword-shield-battle-mechanics-research.3655528/page-64#post-9244179>))
|
||||
*/
|
||||
public triggerAllTags(): void {
|
||||
public activateAllTags(): void {
|
||||
const leftoverTags: PositionalTag[] = [];
|
||||
for (const tag of this.tags) {
|
||||
// Check for silent removal, immediately removing invalid tags.
|
||||
@ -45,7 +46,7 @@ export class PositionalTagManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!tag.shouldDisappear()) {
|
||||
if (tag.shouldTrigger()) {
|
||||
tag.trigger();
|
||||
}
|
||||
}
|
||||
|
@ -14,19 +14,21 @@ import i18next from "i18next";
|
||||
/**
|
||||
* Baseline arguments used to construct all {@linkcode PositionalTag}s,
|
||||
* the contents of which are serialized and used to construct new tags. \
|
||||
* Does not contain the `tagType` parameter (which is used to select the proper class constructor to use).
|
||||
* Does not contain the `tagType` parameter (which is used to select the proper class constructor during tag loading).
|
||||
* @privateRemarks
|
||||
* All {@linkcode PositionalTag}s are intended to implement a sub-interface of this containing their respective parameters,
|
||||
* and should refrain from adding extra serializable fields not contained in said interface.
|
||||
* This ensures that all tags truly "become" their respective interfaces when converted to and from JSON.
|
||||
*/
|
||||
export interface PositionalTagBaseArgs {
|
||||
/**
|
||||
* The number of turns remaining until activation. \
|
||||
* Decremented by 1 at the end of each turn until reaching 0, at which point it will {@linkcode trigger} and be removed.
|
||||
* @remarks
|
||||
* If this is set to any number `<0` manually (such as through the effects of {@linkcode PositionalTag.shouldDisappear | shouldDisappear}),
|
||||
* this tag will be silently removed at the end of the next turn _without activating any effects_.
|
||||
* The number of turns remaining until this tag's activation. \
|
||||
* Decremented by 1 at the end of each turn until reaching 0, at which point it will
|
||||
* {@linkcode PositionalTag.trigger | trigger} the tag's effects and be removed.
|
||||
*/
|
||||
turnCount: number;
|
||||
/**
|
||||
* The {@linkcode BattlerIndex} of the Pokemon targeted by the effect.
|
||||
* The {@linkcode BattlerIndex} targeted by this effect.
|
||||
*/
|
||||
targetIndex: BattlerIndex;
|
||||
}
|
||||
@ -37,8 +39,10 @@ export interface PositionalTagBaseArgs {
|
||||
* Multiple tags of the same kind can stack with one another, provided they are affecting different targets.
|
||||
*/
|
||||
export abstract class PositionalTag implements PositionalTagBaseArgs {
|
||||
/** This tag's {@linkcode PositionalTagType | type} */
|
||||
public abstract readonly tagType: PositionalTagType;
|
||||
// These arguments have to be public to implement the interface, but are functionally private.
|
||||
// Left undocumented to inherit doc comments from the interface
|
||||
public turnCount: number;
|
||||
public targetIndex: BattlerIndex;
|
||||
|
||||
@ -51,16 +55,22 @@ export abstract class PositionalTag implements PositionalTagBaseArgs {
|
||||
public abstract trigger(): void;
|
||||
|
||||
/**
|
||||
* Check whether this tag should be removed without calling {@linkcode trigger} and triggering effects.
|
||||
* @returns Whether this tag should disappear without triggering.
|
||||
* Check whether this tag should be allowed to {@linkcode trigger} and activate its effects
|
||||
* upon its duration elapsing.
|
||||
* @returns Whether this tag should be allowed to trigger prior to being removed.
|
||||
*/
|
||||
abstract shouldDisappear(): boolean;
|
||||
public abstract shouldTrigger(): boolean;
|
||||
|
||||
/**
|
||||
* Get the {@linkcode Pokemon} currently targeted by this tag.
|
||||
* @returns The {@linkcode Pokemon} located in this tag's target position, or `undefined` if none exist in it.
|
||||
*/
|
||||
protected getTarget(): Pokemon | undefined {
|
||||
return globalScene.getField()[this.targetIndex];
|
||||
}
|
||||
}
|
||||
|
||||
/** Interface containing additional properties used to construct a {@linkcode DelayedAttackTag}. */
|
||||
interface DelayedAttackArgs extends PositionalTagBaseArgs {
|
||||
/**
|
||||
* The {@linkcode Pokemon.id | PID} of the {@linkcode Pokemon} having created this effect.
|
||||
@ -87,7 +97,8 @@ export class DelayedAttackTag extends PositionalTag implements DelayedAttackArgs
|
||||
}
|
||||
|
||||
override trigger(): void {
|
||||
// Bangs are justified as the `shouldDisappear` method will queue the tag for removal if the source or target leave the field
|
||||
// Bangs are justified as the `shouldTrigger` method will queue the tag for removal
|
||||
// if the source or target no longer exist
|
||||
const source = globalScene.getPokemonById(this.sourceId)!;
|
||||
const target = this.getTarget()!;
|
||||
|
||||
@ -104,19 +115,21 @@ export class DelayedAttackTag extends PositionalTag implements DelayedAttackArgs
|
||||
this.sourceId, // TODO: Find an alternate method of passing the source pokemon without a source ID
|
||||
[this.targetIndex],
|
||||
allMoves[this.sourceMove],
|
||||
MoveUseMode.TRANSPARENT,
|
||||
MoveUseMode.DELAYED_ATTACK,
|
||||
);
|
||||
}
|
||||
|
||||
override shouldDisappear(): boolean {
|
||||
override shouldTrigger(): boolean {
|
||||
const source = globalScene.getPokemonById(this.sourceId);
|
||||
const target = this.getTarget();
|
||||
// Silently disappear if either source or target are missing or happen to be the same pokemon
|
||||
// (i.e. targeting oneself)
|
||||
return !source || !target || source === target || target.isFainted();
|
||||
// We also need to check for fainted targets as they don't technically leave the field until _after_ the turn ends
|
||||
return !!source && !!target && source !== target && !target.isFainted();
|
||||
}
|
||||
}
|
||||
|
||||
/** Interface containing arguments used to construct a {@linkcode WishTag}. */
|
||||
interface WishArgs extends PositionalTagBaseArgs {
|
||||
/** The amount of {@linkcode Stat.HP | HP} to heal; set to 50% of the user's max HP during move usage. */
|
||||
healHp: number;
|
||||
@ -150,7 +163,7 @@ export class WishTag extends PositionalTag implements WishArgs {
|
||||
globalScene.phaseManager.unshiftNew("PokemonHealPhase", this.targetIndex, this.healHp, null, true, false);
|
||||
}
|
||||
|
||||
public shouldDisappear(): boolean {
|
||||
public shouldTrigger(): boolean {
|
||||
// Disappear if no target or target is fainted.
|
||||
// The source need not exist at the time of activation (since all we need is a simple message)
|
||||
// TODO: Verify whether Wish shows a message if the Pokemon it would affect is KO'd on the turn of activation
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { PostDancingMoveAbAttr } from "#abilities/ability";
|
||||
import type { DelayedAttackAttr } from "#app/@types/move-types";
|
||||
import type { BattlerTagLapseType } from "#enums/battler-tag-lapse-type";
|
||||
import type { EnumValues } from "#types/enum-types";
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
/**
|
||||
* Enum representing all the possible means through which a given move can be executed.
|
||||
@ -68,11 +68,13 @@ export const MoveUseMode = {
|
||||
*
|
||||
* In addition to inheriting the cancellation ignores and copy prevention from {@linkcode MoveUseMode.REFLECTED},
|
||||
* transparent moves are ignored by **all forms of move usage checks** due to **not pushing to move history**.
|
||||
* @todo Consider other means of implementing FS/DD than this - we currently only use it
|
||||
* to prevent pushing to move history and avoid re-delaying the attack portion
|
||||
*/
|
||||
TRANSPARENT: 6
|
||||
DELAYED_ATTACK: 6
|
||||
} as const;
|
||||
|
||||
export type MoveUseMode = EnumValues<typeof MoveUseMode>;
|
||||
export type MoveUseMode = ObjectValues<typeof MoveUseMode>;
|
||||
|
||||
// # HELPER FUNCTIONS
|
||||
// Please update the markdown tables if any new `MoveUseMode`s get added.
|
||||
@ -84,13 +86,14 @@ export type MoveUseMode = EnumValues<typeof MoveUseMode>;
|
||||
* @remarks
|
||||
* This function is equivalent to the following truth table:
|
||||
*
|
||||
* | Use Type | Returns |
|
||||
* |------------------------------------|---------|
|
||||
* | {@linkcode MoveUseMode.NORMAL} | `false` |
|
||||
* | {@linkcode MoveUseMode.IGNORE_PP} | `false` |
|
||||
* | {@linkcode MoveUseMode.INDIRECT} | `true` |
|
||||
* | {@linkcode MoveUseMode.FOLLOW_UP} | `true` |
|
||||
* | {@linkcode MoveUseMode.REFLECTED} | `true` |
|
||||
* | Use Type | Returns |
|
||||
* |----------------------------------------|---------|
|
||||
* | {@linkcode MoveUseMode.NORMAL} | `false` |
|
||||
* | {@linkcode MoveUseMode.IGNORE_PP} | `false` |
|
||||
* | {@linkcode MoveUseMode.INDIRECT} | `true` |
|
||||
* | {@linkcode MoveUseMode.FOLLOW_UP} | `true` |
|
||||
* | {@linkcode MoveUseMode.REFLECTED} | `true` |
|
||||
* | {@linkcode MoveUseMode.DELAYED_ATTACK} | `true` |
|
||||
*/
|
||||
export function isVirtual(useMode: MoveUseMode): boolean {
|
||||
return useMode >= MoveUseMode.INDIRECT
|
||||
@ -104,13 +107,14 @@ export function isVirtual(useMode: MoveUseMode): boolean {
|
||||
* @remarks
|
||||
* This function is equivalent to the following truth table:
|
||||
*
|
||||
* | Use Type | Returns |
|
||||
* |------------------------------------|---------|
|
||||
* | {@linkcode MoveUseMode.NORMAL} | `false` |
|
||||
* | {@linkcode MoveUseMode.IGNORE_PP} | `false` |
|
||||
* | {@linkcode MoveUseMode.INDIRECT} | `false` |
|
||||
* | {@linkcode MoveUseMode.FOLLOW_UP} | `true` |
|
||||
* | {@linkcode MoveUseMode.REFLECTED} | `true` |
|
||||
* | Use Type | Returns |
|
||||
* |----------------------------------------|---------|
|
||||
* | {@linkcode MoveUseMode.NORMAL} | `false` |
|
||||
* | {@linkcode MoveUseMode.IGNORE_PP} | `false` |
|
||||
* | {@linkcode MoveUseMode.INDIRECT} | `false` |
|
||||
* | {@linkcode MoveUseMode.FOLLOW_UP} | `true` |
|
||||
* | {@linkcode MoveUseMode.REFLECTED} | `true` |
|
||||
* | {@linkcode MoveUseMode.DELAYED_ATTACK} | `true` |
|
||||
*/
|
||||
export function isIgnoreStatus(useMode: MoveUseMode): boolean {
|
||||
return useMode >= MoveUseMode.FOLLOW_UP;
|
||||
@ -124,13 +128,14 @@ export function isIgnoreStatus(useMode: MoveUseMode): boolean {
|
||||
* @remarks
|
||||
* This function is equivalent to the following truth table:
|
||||
*
|
||||
* | Use Type | Returns |
|
||||
* |------------------------------------|---------|
|
||||
* | {@linkcode MoveUseMode.NORMAL} | `false` |
|
||||
* | {@linkcode MoveUseMode.IGNORE_PP} | `true` |
|
||||
* | {@linkcode MoveUseMode.INDIRECT} | `true` |
|
||||
* | {@linkcode MoveUseMode.FOLLOW_UP} | `true` |
|
||||
* | {@linkcode MoveUseMode.REFLECTED} | `true` |
|
||||
* | Use Type | Returns |
|
||||
* |----------------------------------------|---------|
|
||||
* | {@linkcode MoveUseMode.NORMAL} | `false` |
|
||||
* | {@linkcode MoveUseMode.IGNORE_PP} | `true` |
|
||||
* | {@linkcode MoveUseMode.INDIRECT} | `true` |
|
||||
* | {@linkcode MoveUseMode.FOLLOW_UP} | `true` |
|
||||
* | {@linkcode MoveUseMode.REFLECTED} | `true` |
|
||||
* | {@linkcode MoveUseMode.DELAYED_ATTACK} | `true` |
|
||||
*/
|
||||
export function isIgnorePP(useMode: MoveUseMode): boolean {
|
||||
return useMode >= MoveUseMode.IGNORE_PP;
|
||||
@ -145,14 +150,15 @@ export function isIgnorePP(useMode: MoveUseMode): boolean {
|
||||
* @remarks
|
||||
* This function is equivalent to the following truth table:
|
||||
*
|
||||
* | Use Type | Returns |
|
||||
* |------------------------------------|---------|
|
||||
* | {@linkcode MoveUseMode.NORMAL} | `false` |
|
||||
* | {@linkcode MoveUseMode.IGNORE_PP} | `false` |
|
||||
* | {@linkcode MoveUseMode.INDIRECT} | `false` |
|
||||
* | {@linkcode MoveUseMode.FOLLOW_UP} | `false` |
|
||||
* | {@linkcode MoveUseMode.REFLECTED} | `true` |
|
||||
* | Use Type | Returns |
|
||||
* |----------------------------------------|---------|
|
||||
* | {@linkcode MoveUseMode.NORMAL} | `false` |
|
||||
* | {@linkcode MoveUseMode.IGNORE_PP} | `false` |
|
||||
* | {@linkcode MoveUseMode.INDIRECT} | `false` |
|
||||
* | {@linkcode MoveUseMode.FOLLOW_UP} | `false` |
|
||||
* | {@linkcode MoveUseMode.REFLECTED} | `true` |
|
||||
* | {@linkcode MoveUseMode.DELAYED_ATTACK} | `false` |
|
||||
*/
|
||||
export function isReflected(useMode: MoveUseMode): boolean {
|
||||
return useMode === MoveUseMode.REFLECTED;
|
||||
}
|
||||
}
|
@ -52,7 +52,7 @@ export class Arena {
|
||||
public bgm: string;
|
||||
public ignoreAbilities: boolean;
|
||||
public ignoringEffectSource: BattlerIndex | null;
|
||||
public playerTerasUsed = 0;
|
||||
public playerTerasUsed: number;
|
||||
/**
|
||||
* Saves the number of times a party pokemon faints during a arena encounter.
|
||||
* {@linkcode globalScene.currentBattle.enemyFaints} is the corresponding faint counter for the enemy (this resets every wave).
|
||||
@ -71,6 +71,7 @@ export class Arena {
|
||||
this.bgm = bgm;
|
||||
this.trainerPool = biomeTrainerPools[biome];
|
||||
this.updatePoolsForTimeOfDay();
|
||||
this.playerTerasUsed = 0;
|
||||
this.playerFaints = playerFaints;
|
||||
}
|
||||
|
||||
|
@ -331,7 +331,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
*/
|
||||
private postAnimCallback(user: Pokemon, targets: Pokemon[]) {
|
||||
// Add to the move history entry
|
||||
if (this.firstHit && this.useMode !== MoveUseMode.TRANSPARENT) {
|
||||
if (this.firstHit && this.useMode !== MoveUseMode.DELAYED_ATTACK) {
|
||||
user.pushMoveHistory(this.moveHistoryEntry);
|
||||
applyAbAttrs("ExecutedMoveAbAttr", { pokemon: user });
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export class PositionalTagPhase extends Phase {
|
||||
public readonly phaseName = "PositionalTagPhase";
|
||||
|
||||
public override start(): void {
|
||||
globalScene.arena.positionalTagManager.triggerAllTags();
|
||||
globalScene.arena.positionalTagManager.activateAllTags();
|
||||
super.end();
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user