mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-21 09:02:47 +02:00
Compare commits
13 Commits
5e1ba36fdd
...
b8d8e46ea5
Author | SHA1 | Date | |
---|---|---|---|
|
b8d8e46ea5 | ||
|
1ff2701964 | ||
|
1e306e25b5 | ||
|
43aa772603 | ||
|
3f1772ceb9 | ||
|
e9d3f147ef | ||
|
958fd64d90 | ||
|
b5f40a3e0b | ||
|
3f2cdb0933 | ||
|
51c956860e | ||
|
caf3cc940f | ||
|
c7b7579f60 | ||
|
be7ba4f5dd |
@ -303,7 +303,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
/** Session save data that pertains to Mystery Encounters */
|
/** Session save data that pertains to Mystery Encounters */
|
||||||
public mysteryEncounterSaveData: MysteryEncounterSaveData = new MysteryEncounterSaveData();
|
public mysteryEncounterSaveData: MysteryEncounterSaveData = new MysteryEncounterSaveData();
|
||||||
/** If the previous wave was a MysteryEncounter, tracks the object with this variable. Mostly used for visual object cleanup */
|
/** If the previous wave was a MysteryEncounter, tracks the object with this variable. Mostly used for visual object cleanup */
|
||||||
public lastMysteryEncounter?: MysteryEncounter;
|
public lastMysteryEncounter: MysteryEncounter | undefined = undefined;
|
||||||
/** Combined Biome and Wave count text */
|
/** Combined Biome and Wave count text */
|
||||||
private biomeWaveText: Phaser.GameObjects.Text;
|
private biomeWaveText: Phaser.GameObjects.Text;
|
||||||
private moneyText: Phaser.GameObjects.Text;
|
private moneyText: Phaser.GameObjects.Text;
|
||||||
|
@ -90,9 +90,9 @@ export default class Battle {
|
|||||||
public playerFaintsHistory: FaintLogEntry[] = [];
|
public playerFaintsHistory: FaintLogEntry[] = [];
|
||||||
public enemyFaintsHistory: FaintLogEntry[] = [];
|
public enemyFaintsHistory: FaintLogEntry[] = [];
|
||||||
|
|
||||||
public mysteryEncounterType?: MysteryEncounterType;
|
public mysteryEncounterType?: MysteryEncounterType | undefined;
|
||||||
/** If the current battle is a Mystery Encounter, this will always be defined */
|
/** If the current battle is a Mystery Encounter, this will always be defined */
|
||||||
public mysteryEncounter?: MysteryEncounter;
|
public mysteryEncounter?: MysteryEncounter | undefined;
|
||||||
|
|
||||||
private rngCounter = 0;
|
private rngCounter = 0;
|
||||||
|
|
||||||
|
@ -1770,14 +1770,11 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr {
|
export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr {
|
||||||
private weatherType: WeatherType;
|
constructor(
|
||||||
protected condition?: PokemonDefendCondition;
|
private weatherType: WeatherType,
|
||||||
|
protected condition?: PokemonDefendCondition,
|
||||||
constructor(weatherType: WeatherType, condition?: PokemonDefendCondition) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.weatherType = weatherType;
|
|
||||||
this.condition = condition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override canApplyPostDefend(
|
override canApplyPostDefend(
|
||||||
@ -2765,13 +2762,10 @@ export class GorillaTacticsAbAttr extends ExecutedMoveAbAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
||||||
private stealCondition: PokemonAttackCondition | null;
|
|
||||||
private stolenItem?: PokemonHeldItemModifier;
|
private stolenItem?: PokemonHeldItemModifier;
|
||||||
|
|
||||||
constructor(stealCondition?: PokemonAttackCondition) {
|
constructor(private stealCondition?: PokemonAttackCondition) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.stealCondition = stealCondition ?? null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override canApplyPostAttack(
|
override canApplyPostAttack(
|
||||||
@ -2798,7 +2792,6 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.stolenItem = undefined;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2824,7 +2817,6 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.stolenItem = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
||||||
@ -2952,13 +2944,10 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
||||||
private condition?: PokemonDefendCondition;
|
|
||||||
private stolenItem?: PokemonHeldItemModifier;
|
private stolenItem?: PokemonHeldItemModifier;
|
||||||
|
|
||||||
constructor(condition?: PokemonDefendCondition) {
|
constructor(private condition?: PokemonDefendCondition) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.condition = condition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override canApplyPostDefend(
|
override canApplyPostDefend(
|
||||||
@ -3004,7 +2993,6 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.stolenItem = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
||||||
@ -3382,18 +3370,16 @@ export class PostSummonRemoveArenaTagAbAttr extends PostSummonAbAttr {
|
|||||||
* Generic class to add an arena tag upon switching in
|
* Generic class to add an arena tag upon switching in
|
||||||
*/
|
*/
|
||||||
export class PostSummonAddArenaTagAbAttr extends PostSummonAbAttr {
|
export class PostSummonAddArenaTagAbAttr extends PostSummonAbAttr {
|
||||||
private readonly tagType: ArenaTagType;
|
|
||||||
private readonly turnCount: number;
|
|
||||||
private readonly side?: ArenaTagSide;
|
|
||||||
private readonly quiet?: boolean;
|
|
||||||
private sourceId: number;
|
private sourceId: number;
|
||||||
|
|
||||||
constructor(showAbility: boolean, tagType: ArenaTagType, turnCount: number, side?: ArenaTagSide, quiet?: boolean) {
|
constructor(
|
||||||
|
showAbility: boolean,
|
||||||
|
private readonly tagType: ArenaTagType,
|
||||||
|
private readonly turnCount: number,
|
||||||
|
private readonly side?: ArenaTagSide,
|
||||||
|
private readonly quiet?: boolean,
|
||||||
|
) {
|
||||||
super(showAbility);
|
super(showAbility);
|
||||||
this.tagType = tagType;
|
|
||||||
this.turnCount = turnCount;
|
|
||||||
this.side = side;
|
|
||||||
this.quiet = quiet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): void {
|
public override applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): void {
|
||||||
@ -4347,7 +4333,7 @@ export class ReflectStatStageChangeAbAttr extends PreStatStageChangeAbAttr {
|
|||||||
*/
|
*/
|
||||||
export class ProtectStatAbAttr extends PreStatStageChangeAbAttr {
|
export class ProtectStatAbAttr extends PreStatStageChangeAbAttr {
|
||||||
/** {@linkcode BattleStat} to protect or `undefined` if **all** {@linkcode BattleStat} are protected */
|
/** {@linkcode BattleStat} to protect or `undefined` if **all** {@linkcode BattleStat} are protected */
|
||||||
private protectedStat?: BattleStat;
|
private protectedStat: BattleStat | undefined = undefined;
|
||||||
|
|
||||||
constructor(protectedStat?: BattleStat) {
|
constructor(protectedStat?: BattleStat) {
|
||||||
super();
|
super();
|
||||||
@ -6453,7 +6439,6 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.randItem = undefined;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7010,7 +6995,6 @@ export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageC
|
|||||||
export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
||||||
private multiplier: number;
|
private multiplier: number;
|
||||||
private tagType: BattlerTagType;
|
private tagType: BattlerTagType;
|
||||||
private recoilDamageFunc?: (pokemon: Pokemon) => number;
|
|
||||||
private triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string;
|
private triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -7018,13 +7002,12 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
|
|||||||
multiplier: number,
|
multiplier: number,
|
||||||
tagType: BattlerTagType,
|
tagType: BattlerTagType,
|
||||||
triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string,
|
triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string,
|
||||||
recoilDamageFunc?: (pokemon: Pokemon) => number,
|
private recoilDamageFunc?: (pokemon: Pokemon) => number,
|
||||||
) {
|
) {
|
||||||
super(condition, multiplier);
|
super(condition, multiplier);
|
||||||
|
|
||||||
this.multiplier = multiplier;
|
this.multiplier = multiplier;
|
||||||
this.tagType = tagType;
|
this.tagType = tagType;
|
||||||
this.recoilDamageFunc = recoilDamageFunc;
|
|
||||||
this.triggerMessageFunc = triggerMessageFunc;
|
this.triggerMessageFunc = triggerMessageFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ export class BattlerTag {
|
|||||||
public lapseTypes: BattlerTagLapseType[];
|
public lapseTypes: BattlerTagLapseType[];
|
||||||
public turnCount: number;
|
public turnCount: number;
|
||||||
public sourceMove: MoveId;
|
public sourceMove: MoveId;
|
||||||
public sourceId?: number;
|
|
||||||
public isBatonPassable: boolean;
|
public isBatonPassable: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -53,14 +52,13 @@ export class BattlerTag {
|
|||||||
lapseType: BattlerTagLapseType | BattlerTagLapseType[],
|
lapseType: BattlerTagLapseType | BattlerTagLapseType[],
|
||||||
turnCount: number,
|
turnCount: number,
|
||||||
sourceMove?: MoveId,
|
sourceMove?: MoveId,
|
||||||
sourceId?: number,
|
public sourceId?: number,
|
||||||
isBatonPassable = false,
|
isBatonPassable = false,
|
||||||
) {
|
) {
|
||||||
this.tagType = tagType;
|
this.tagType = tagType;
|
||||||
this.lapseTypes = coerceArray(lapseType);
|
this.lapseTypes = coerceArray(lapseType);
|
||||||
this.turnCount = turnCount;
|
this.turnCount = turnCount;
|
||||||
this.sourceMove = sourceMove!; // TODO: is this bang correct?
|
this.sourceMove = sourceMove!; // TODO: is this bang correct?
|
||||||
this.sourceId = sourceId;
|
|
||||||
this.isBatonPassable = isBatonPassable;
|
this.isBatonPassable = isBatonPassable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ export class Egg {
|
|||||||
|
|
||||||
private _overrideHiddenAbility: boolean;
|
private _overrideHiddenAbility: boolean;
|
||||||
|
|
||||||
private _eggDescriptor?: string;
|
private _eggDescriptor: string | undefined;
|
||||||
|
|
||||||
////
|
////
|
||||||
// #endregion
|
// #endregion
|
||||||
|
@ -93,6 +93,10 @@ import { ChargingMove, MoveAttrMap, MoveAttrString, MoveKindString, MoveClassMap
|
|||||||
import { applyMoveAttrs } from "./apply-attrs";
|
import { applyMoveAttrs } from "./apply-attrs";
|
||||||
import { frenzyMissFunc, getMoveTargets } from "./move-utils";
|
import { frenzyMissFunc, getMoveTargets } from "./move-utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function used to conditionally determine execution of a given {@linkcode MoveAttr}.
|
||||||
|
* Conventionally returns `true` for success and `false` for failure.
|
||||||
|
*/
|
||||||
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
|
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
|
||||||
export type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean;
|
export type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean;
|
||||||
|
|
||||||
@ -628,7 +632,7 @@ export default abstract class Move implements Localizable {
|
|||||||
doesFlagEffectApply({ flag, user, target, isFollowUp = false }: {
|
doesFlagEffectApply({ flag, user, target, isFollowUp = false }: {
|
||||||
flag: MoveFlags;
|
flag: MoveFlags;
|
||||||
user: Pokemon;
|
user: Pokemon;
|
||||||
target?: Pokemon;
|
target?: Pokemon | undefined;
|
||||||
isFollowUp?: boolean;
|
isFollowUp?: boolean;
|
||||||
}): boolean {
|
}): boolean {
|
||||||
// special cases below, eg: if the move flag is MAKES_CONTACT, and the user pokemon has an ability that ignores contact (like "Long Reach"), then overrides and move does not make contact
|
// special cases below, eg: if the move flag is MAKES_CONTACT, and the user pokemon has an ability that ignores contact (like "Long Reach"), then overrides and move does not make contact
|
||||||
@ -1219,15 +1223,14 @@ interface MoveEffectAttrOptions {
|
|||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
*/
|
*/
|
||||||
export class MoveEffectAttr extends MoveAttr {
|
export class MoveEffectAttr extends MoveAttr {
|
||||||
/**
|
constructor(
|
||||||
* A container for this attribute's optional parameters
|
selfTarget?: boolean,
|
||||||
* @see {@linkcode MoveEffectAttrOptions} for supported params.
|
/**
|
||||||
*/
|
* A container for this attribute's optional parameters
|
||||||
protected options?: MoveEffectAttrOptions;
|
* @see {@linkcode MoveEffectAttrOptions} for supported params.
|
||||||
|
*/
|
||||||
constructor(selfTarget?: boolean, options?: MoveEffectAttrOptions) {
|
protected options?: MoveEffectAttrOptions) {
|
||||||
super(selfTarget);
|
super(selfTarget);
|
||||||
this.options = options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1390,18 +1393,31 @@ export class BeakBlastHeaderAttr extends AddBattlerTagHeaderAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute to display a message before a move is executed.
|
||||||
|
*/
|
||||||
export class PreMoveMessageAttr extends MoveAttr {
|
export class PreMoveMessageAttr extends MoveAttr {
|
||||||
private message: string | ((user: Pokemon, target: Pokemon, move: Move) => string);
|
/** The message to display or a function returning one */
|
||||||
|
private message: string | ((user: Pokemon, target: Pokemon, move: Move) => string | undefined);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@linkcode PreMoveMessageAttr} to display a message before move execution.
|
||||||
|
* @param message - The message to display before move use, either as a string or a function producing one.
|
||||||
|
* @remarks
|
||||||
|
* If {@linkcode message} evaluates to an empty string (`''`), no message will be displayed
|
||||||
|
* (though the move will still succeed).
|
||||||
|
*/
|
||||||
constructor(message: string | ((user: Pokemon, target: Pokemon, move: Move) => string)) {
|
constructor(message: string | ((user: Pokemon, target: Pokemon, move: Move) => string)) {
|
||||||
super();
|
super();
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, _args: any[]): boolean {
|
||||||
const message = typeof this.message === "string"
|
const message = typeof this.message === "function"
|
||||||
? this.message as string
|
? this.message(user, target, move)
|
||||||
: this.message(user, target, move);
|
: this.message;
|
||||||
|
|
||||||
|
// TODO: Consider changing if/when MoveAttr `apply` return values become significant
|
||||||
if (message) {
|
if (message) {
|
||||||
globalScene.phaseManager.queueMessage(message, 500);
|
globalScene.phaseManager.queueMessage(message, 500);
|
||||||
return true;
|
return true;
|
||||||
@ -1417,7 +1433,7 @@ export class PreMoveMessageAttr extends MoveAttr {
|
|||||||
* @extends MoveAttr
|
* @extends MoveAttr
|
||||||
*/
|
*/
|
||||||
export class PreUseInterruptAttr extends MoveAttr {
|
export class PreUseInterruptAttr extends MoveAttr {
|
||||||
protected message?: string | ((user: Pokemon, target: Pokemon, move: Move) => string);
|
protected message: string | ((user: Pokemon, target: Pokemon, move: Move) => string);
|
||||||
protected overridesFailedMessage: boolean;
|
protected overridesFailedMessage: boolean;
|
||||||
protected conditionFunc: MoveConditionFunc;
|
protected conditionFunc: MoveConditionFunc;
|
||||||
|
|
||||||
@ -1425,10 +1441,10 @@ export class PreUseInterruptAttr extends MoveAttr {
|
|||||||
* Create a new MoveInterruptedMessageAttr.
|
* Create a new MoveInterruptedMessageAttr.
|
||||||
* @param message The message to display when the move is interrupted, or a function that formats the message based on the user, target, and move.
|
* @param message The message to display when the move is interrupted, or a function that formats the message based on the user, target, and move.
|
||||||
*/
|
*/
|
||||||
constructor(message?: string | ((user: Pokemon, target: Pokemon, move: Move) => string), conditionFunc?: MoveConditionFunc) {
|
constructor(message: string | ((user: Pokemon, target: Pokemon, move: Move) => string), conditionFunc: MoveConditionFunc) {
|
||||||
super();
|
super();
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.conditionFunc = conditionFunc ?? (() => true);
|
this.conditionFunc = conditionFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2174,15 +2190,16 @@ export class SandHealAttr extends WeatherHealAttr {
|
|||||||
* @extends HealAttr
|
* @extends HealAttr
|
||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
*/
|
*/
|
||||||
|
// TODO: Convert other healing attributes (WeatherHealAttr, etc) to base off of this class
|
||||||
export class BoostHealAttr extends HealAttr {
|
export class BoostHealAttr extends HealAttr {
|
||||||
/** Healing received when {@linkcode condition} is false */
|
/** Healing received when {@linkcode condition} is false */
|
||||||
private normalHealRatio: number;
|
private normalHealRatio: number;
|
||||||
/** Healing received when {@linkcode condition} is true */
|
/** Healing received when {@linkcode condition} is true */
|
||||||
private boostedHealRatio: number;
|
private boostedHealRatio: number;
|
||||||
/** The lambda expression to check against when boosting the healing value */
|
/** The lambda expression to check against when boosting the healing value */
|
||||||
private condition?: MoveConditionFunc;
|
private condition: MoveConditionFunc;
|
||||||
|
|
||||||
constructor(normalHealRatio: number = 0.5, boostedHealRatio: number = 2 / 3, showAnim?: boolean, selfTarget?: boolean, condition?: MoveConditionFunc) {
|
constructor(normalHealRatio: number, boostedHealRatio: number, condition: MoveConditionFunc, showAnim?: boolean, selfTarget?: boolean, ) {
|
||||||
super(normalHealRatio, showAnim, selfTarget);
|
super(normalHealRatio, showAnim, selfTarget);
|
||||||
this.normalHealRatio = normalHealRatio;
|
this.normalHealRatio = normalHealRatio;
|
||||||
this.boostedHealRatio = boostedHealRatio;
|
this.boostedHealRatio = boostedHealRatio;
|
||||||
@ -2196,8 +2213,8 @@ export class BoostHealAttr extends HealAttr {
|
|||||||
* @param args N/A
|
* @param args N/A
|
||||||
* @returns true if the move was successful
|
* @returns true if the move was successful
|
||||||
*/
|
*/
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
const healRatio: number = (this.condition ? this.condition(user, target, move) : false) ? this.boostedHealRatio : this.normalHealRatio;
|
const healRatio = this.condition(user, target, move) ? this.boostedHealRatio : this.normalHealRatio;
|
||||||
this.addHealPhase(target, healRatio);
|
this.addHealPhase(target, healRatio);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2483,7 +2500,7 @@ export class WaterShurikenMultiHitTypeAttr extends ChangeMultiHitTypeAttr {
|
|||||||
|
|
||||||
export class StatusEffectAttr extends MoveEffectAttr {
|
export class StatusEffectAttr extends MoveEffectAttr {
|
||||||
public effect: StatusEffect;
|
public effect: StatusEffect;
|
||||||
public turnsRemaining?: number;
|
public turnsRemaining?: number | undefined;
|
||||||
public overrideStatus: boolean = false;
|
public overrideStatus: boolean = false;
|
||||||
|
|
||||||
constructor(effect: StatusEffect, selfTarget?: boolean, turnsRemaining?: number, overrideStatus: boolean = false) {
|
constructor(effect: StatusEffect, selfTarget?: boolean, turnsRemaining?: number, overrideStatus: boolean = false) {
|
||||||
@ -3207,19 +3224,18 @@ interface StatStageChangeAttrOptions extends MoveEffectAttrOptions {
|
|||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
*/
|
*/
|
||||||
export class StatStageChangeAttr extends MoveEffectAttr {
|
export class StatStageChangeAttr extends MoveEffectAttr {
|
||||||
public stats: BattleStat[];
|
constructor(
|
||||||
public stages: number;
|
public stats: BattleStat[],
|
||||||
/**
|
public stages: number,
|
||||||
* Container for optional parameters to this attribute.
|
selfTarget?: boolean,
|
||||||
* @see {@linkcode StatStageChangeAttrOptions} for available optional params
|
/**
|
||||||
*/
|
* Container for optional parameters to this attribute.
|
||||||
protected override options?: StatStageChangeAttrOptions;
|
* @see {@linkcode StatStageChangeAttrOptions} for available optional params
|
||||||
|
*/
|
||||||
constructor(stats: BattleStat[], stages: number, selfTarget?: boolean, options?: StatStageChangeAttrOptions) {
|
protected override options?: StatStageChangeAttrOptions) {
|
||||||
super(selfTarget, options);
|
super(selfTarget, options);
|
||||||
this.stats = stats;
|
this.stats = stats;
|
||||||
this.stages = stages;
|
this.stages = stages;
|
||||||
this.options = options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3451,16 +3467,16 @@ export class SecretPowerAttr extends MoveEffectAttr {
|
|||||||
export class PostVictoryStatStageChangeAttr extends MoveAttr {
|
export class PostVictoryStatStageChangeAttr extends MoveAttr {
|
||||||
private stats: BattleStat[];
|
private stats: BattleStat[];
|
||||||
private stages: number;
|
private stages: number;
|
||||||
private condition?: MoveConditionFunc;
|
|
||||||
private showMessage: boolean;
|
private showMessage: boolean;
|
||||||
|
|
||||||
constructor(stats: BattleStat[], stages: number, selfTarget?: boolean, condition?: MoveConditionFunc, showMessage: boolean = true, firstHitOnly: boolean = false) {
|
constructor(stats: BattleStat[], stages: number, selfTarget?: boolean, private condition?: MoveConditionFunc, showMessage: boolean = true, firstHitOnly: boolean = false) {
|
||||||
super();
|
super();
|
||||||
this.stats = stats;
|
this.stats = stats;
|
||||||
this.stages = stages;
|
this.stages = stages;
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
this.showMessage = showMessage;
|
this.showMessage = showMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyPostVictory(user: Pokemon, target: Pokemon, move: Move): void {
|
applyPostVictory(user: Pokemon, target: Pokemon, move: Move): void {
|
||||||
if (this.condition && !this.condition(user, target, move)) {
|
if (this.condition && !this.condition(user, target, move)) {
|
||||||
return;
|
return;
|
||||||
@ -10484,7 +10500,7 @@ export function initMoves() {
|
|||||||
.attr(StatStageChangeAttr, [ Stat.SPD ], -1, true)
|
.attr(StatStageChangeAttr, [ Stat.SPD ], -1, true)
|
||||||
.punchingMove(),
|
.punchingMove(),
|
||||||
new StatusMove(MoveId.FLORAL_HEALING, PokemonType.FAIRY, -1, 10, -1, 0, 7)
|
new StatusMove(MoveId.FLORAL_HEALING, PokemonType.FAIRY, -1, 10, -1, 0, 7)
|
||||||
.attr(BoostHealAttr, 0.5, 2 / 3, true, false, (user, target, move) => globalScene.arena.terrain?.terrainType === TerrainType.GRASSY)
|
.attr(BoostHealAttr, 0.5, 2 / 3, (user, target, move) => globalScene.arena.terrain?.terrainType === TerrainType.GRASSY, true, false)
|
||||||
.triageMove()
|
.triageMove()
|
||||||
.reflectable(),
|
.reflectable(),
|
||||||
new AttackMove(MoveId.HIGH_HORSEPOWER, PokemonType.GROUND, MoveCategory.PHYSICAL, 95, 95, 10, -1, 0, 7),
|
new AttackMove(MoveId.HIGH_HORSEPOWER, PokemonType.GROUND, MoveCategory.PHYSICAL, 95, 95, 10, -1, 0, 7),
|
||||||
@ -11299,7 +11315,11 @@ export function initMoves() {
|
|||||||
.attr(ForceSwitchOutAttr, true, SwitchType.SHED_TAIL)
|
.attr(ForceSwitchOutAttr, true, SwitchType.SHED_TAIL)
|
||||||
.condition(failIfLastInPartyCondition),
|
.condition(failIfLastInPartyCondition),
|
||||||
new SelfStatusMove(MoveId.CHILLY_RECEPTION, PokemonType.ICE, -1, 10, -1, 0, 9)
|
new SelfStatusMove(MoveId.CHILLY_RECEPTION, PokemonType.ICE, -1, 10, -1, 0, 9)
|
||||||
.attr(PreMoveMessageAttr, (user, move) => i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(user) }))
|
.attr(PreMoveMessageAttr, (user, _target, _move) =>
|
||||||
|
// Don't display text if current move phase is follow up (ie move called indirectly)
|
||||||
|
isVirtual((globalScene.phaseManager.getCurrentPhase() as MovePhase).useMode)
|
||||||
|
? ""
|
||||||
|
: i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(user) }))
|
||||||
.attr(ChillyReceptionAttr, true),
|
.attr(ChillyReceptionAttr, true),
|
||||||
new SelfStatusMove(MoveId.TIDY_UP, PokemonType.NORMAL, -1, 10, -1, 0, 9)
|
new SelfStatusMove(MoveId.TIDY_UP, PokemonType.NORMAL, -1, 10, -1, 0, 9)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPD ], 1, true)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPD ], 1, true)
|
||||||
|
@ -18,21 +18,19 @@ import type Move from "./move";
|
|||||||
* @see {@linkcode getName} - returns name of {@linkcode Move}.
|
* @see {@linkcode getName} - returns name of {@linkcode Move}.
|
||||||
**/
|
**/
|
||||||
export class PokemonMove {
|
export class PokemonMove {
|
||||||
public moveId: MoveId;
|
constructor(
|
||||||
public ppUsed: number;
|
public moveId: MoveId,
|
||||||
public ppUp: number;
|
public ppUsed = 0,
|
||||||
|
public ppUp = 0,
|
||||||
/**
|
/**
|
||||||
* If defined and nonzero, overrides the maximum PP of the move (e.g., due to move being copied by Transform).
|
* If defined and nonzero, overrides the maximum PP of the move (e.g., due to move being copied by Transform).
|
||||||
* This also nullifies all effects of `ppUp`.
|
* This also nullifies all effects of `ppUp`.
|
||||||
*/
|
*/
|
||||||
public maxPpOverride?: number;
|
public maxPpOverride = 0,
|
||||||
|
) {
|
||||||
constructor(moveId: MoveId, ppUsed = 0, ppUp = 0, maxPpOverride?: number) {
|
|
||||||
this.moveId = moveId;
|
this.moveId = moveId;
|
||||||
this.ppUsed = ppUsed;
|
this.ppUsed = ppUsed;
|
||||||
this.ppUp = ppUp;
|
this.ppUp = ppUp;
|
||||||
this.maxPpOverride = maxPpOverride;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +45,7 @@ export default class MysteryEncounterOption implements IMysteryEncounterOption {
|
|||||||
requirements: EncounterSceneRequirement[];
|
requirements: EncounterSceneRequirement[];
|
||||||
primaryPokemonRequirements: EncounterPokemonRequirement[];
|
primaryPokemonRequirements: EncounterPokemonRequirement[];
|
||||||
secondaryPokemonRequirements: EncounterPokemonRequirement[];
|
secondaryPokemonRequirements: EncounterPokemonRequirement[];
|
||||||
primaryPokemon?: PlayerPokemon;
|
primaryPokemon?: PlayerPokemon | undefined;
|
||||||
secondaryPokemon?: PlayerPokemon[];
|
secondaryPokemon?: PlayerPokemon[];
|
||||||
excludePrimaryFromSecondaryRequirements: boolean;
|
excludePrimaryFromSecondaryRequirements: boolean;
|
||||||
|
|
||||||
|
@ -53,9 +53,9 @@ export interface IMysteryEncounter {
|
|||||||
options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]];
|
options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]];
|
||||||
spriteConfigs: MysteryEncounterSpriteConfig[];
|
spriteConfigs: MysteryEncounterSpriteConfig[];
|
||||||
encounterTier: MysteryEncounterTier;
|
encounterTier: MysteryEncounterTier;
|
||||||
encounterAnimations?: EncounterAnim[];
|
encounterAnimations?: EncounterAnim[] | undefined;
|
||||||
disallowedGameModes?: GameModes[];
|
disallowedGameModes?: GameModes[] | undefined;
|
||||||
disallowedChallenges?: Challenges[];
|
disallowedChallenges?: Challenges[] | undefined;
|
||||||
hideBattleIntroMessage: boolean;
|
hideBattleIntroMessage: boolean;
|
||||||
autoHideIntroVisuals: boolean;
|
autoHideIntroVisuals: boolean;
|
||||||
enterIntroVisualsFromRight: boolean;
|
enterIntroVisualsFromRight: boolean;
|
||||||
@ -68,11 +68,11 @@ export interface IMysteryEncounter {
|
|||||||
skipToFightInput: boolean;
|
skipToFightInput: boolean;
|
||||||
preventGameStatsUpdates: boolean;
|
preventGameStatsUpdates: boolean;
|
||||||
|
|
||||||
onInit?: () => boolean;
|
onInit?: (() => boolean) | undefined;
|
||||||
onVisualsStart?: () => boolean;
|
onVisualsStart?: (() => boolean) | undefined;
|
||||||
doEncounterExp?: () => boolean;
|
doEncounterExp?: (() => boolean) | undefined;
|
||||||
doEncounterRewards?: () => boolean;
|
doEncounterRewards?: (() => boolean) | undefined;
|
||||||
doContinueEncounter?: () => Promise<void>;
|
doContinueEncounter?: (() => Promise<void>) | undefined;
|
||||||
|
|
||||||
requirements: EncounterSceneRequirement[];
|
requirements: EncounterSceneRequirement[];
|
||||||
primaryPokemonRequirements: EncounterPokemonRequirement[];
|
primaryPokemonRequirements: EncounterPokemonRequirement[];
|
||||||
@ -105,15 +105,15 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||||||
* Custom battle animations that are configured for encounter effects and visuals
|
* Custom battle animations that are configured for encounter effects and visuals
|
||||||
* Specify here so that assets are loaded on initialization of encounter
|
* Specify here so that assets are loaded on initialization of encounter
|
||||||
*/
|
*/
|
||||||
encounterAnimations?: EncounterAnim[];
|
encounterAnimations?: EncounterAnim[] | undefined;
|
||||||
/**
|
/**
|
||||||
* If specified, defines any game modes where the {@linkcode MysteryEncounter} should *NOT* spawn
|
* If specified, defines any game modes where the {@linkcode MysteryEncounter} should *NOT* spawn
|
||||||
*/
|
*/
|
||||||
disallowedGameModes?: GameModes[];
|
disallowedGameModes?: GameModes[] | undefined;
|
||||||
/**
|
/**
|
||||||
* If specified, defines any challenges (from Challenge game mode) where the {@linkcode MysteryEncounter} should *NOT* spawn
|
* If specified, defines any challenges (from Challenge game mode) where the {@linkcode MysteryEncounter} should *NOT* spawn
|
||||||
*/
|
*/
|
||||||
disallowedChallenges?: Challenges[];
|
disallowedChallenges?: Challenges[] | undefined;
|
||||||
/**
|
/**
|
||||||
* If true, hides "A Wild X Appeared" etc. messages
|
* If true, hides "A Wild X Appeared" etc. messages
|
||||||
* Default true
|
* Default true
|
||||||
@ -172,24 +172,24 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||||||
// #region Event callback functions
|
// #region Event callback functions
|
||||||
|
|
||||||
/** Event when Encounter is first loaded, use it for data conditioning */
|
/** Event when Encounter is first loaded, use it for data conditioning */
|
||||||
onInit?: () => boolean;
|
onInit?: (() => boolean) | undefined;
|
||||||
/** Event when battlefield visuals have finished sliding in and the encounter dialogue begins */
|
/** Event when battlefield visuals have finished sliding in and the encounter dialogue begins */
|
||||||
onVisualsStart?: () => boolean;
|
onVisualsStart?: (() => boolean) | undefined;
|
||||||
/** Event triggered prior to {@linkcode CommandPhase}, during {@linkcode TurnInitPhase} */
|
/** Event triggered prior to {@linkcode CommandPhase}, during {@linkcode TurnInitPhase} */
|
||||||
onTurnStart?: () => boolean;
|
onTurnStart?: (() => boolean) | undefined;
|
||||||
/** Event prior to any rewards logic in {@linkcode MysteryEncounterRewardsPhase} */
|
/** Event prior to any rewards logic in {@linkcode MysteryEncounterRewardsPhase} */
|
||||||
onRewards?: () => Promise<void>;
|
onRewards?: (() => Promise<void>) | undefined;
|
||||||
/** Will provide the player party EXP before rewards are displayed for that wave */
|
/** Will provide the player party EXP before rewards are displayed for that wave */
|
||||||
doEncounterExp?: () => boolean;
|
doEncounterExp?: (() => boolean) | undefined;
|
||||||
/** Will provide the player a rewards shop for that wave */
|
/** Will provide the player a rewards shop for that wave */
|
||||||
doEncounterRewards?: () => boolean;
|
doEncounterRewards?: (() => boolean) | undefined;
|
||||||
/** Will execute callback during VictoryPhase of a continuousEncounter */
|
/** Will execute callback during VictoryPhase of a continuousEncounter */
|
||||||
doContinueEncounter?: () => Promise<void>;
|
doContinueEncounter?: (() => Promise<void>) | undefined;
|
||||||
/**
|
/**
|
||||||
* Can perform special logic when a ME battle is lost, before GameOver/battle retry prompt.
|
* Can perform special logic when a ME battle is lost, before GameOver/battle retry prompt.
|
||||||
* Should return `true` if it is treated as "real" Game Over, `false` if not.
|
* Should return `true` if it is treated as "real" Game Over, `false` if not.
|
||||||
*/
|
*/
|
||||||
onGameOver?: () => boolean;
|
onGameOver?: (() => boolean) | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requirements
|
* Requirements
|
||||||
@ -204,8 +204,8 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||||||
*/
|
*/
|
||||||
secondaryPokemonRequirements: EncounterPokemonRequirement[];
|
secondaryPokemonRequirements: EncounterPokemonRequirement[];
|
||||||
excludePrimaryFromSupportRequirements: boolean;
|
excludePrimaryFromSupportRequirements: boolean;
|
||||||
primaryPokemon?: PlayerPokemon;
|
primaryPokemon?: PlayerPokemon | undefined;
|
||||||
secondaryPokemon?: PlayerPokemon[];
|
secondaryPokemon?: PlayerPokemon[] | undefined;
|
||||||
|
|
||||||
// #region Post-construct / Auto-populated params
|
// #region Post-construct / Auto-populated params
|
||||||
localizationKey: string;
|
localizationKey: string;
|
||||||
@ -224,7 +224,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||||||
* Otherwise, will be undefined
|
* Otherwise, will be undefined
|
||||||
* You probably shouldn't do anything directly with this unless you have a very specific need
|
* You probably shouldn't do anything directly with this unless you have a very specific need
|
||||||
*/
|
*/
|
||||||
introVisuals?: MysteryEncounterIntroVisuals;
|
introVisuals?: MysteryEncounterIntroVisuals | undefined;
|
||||||
|
|
||||||
// #region Flags
|
// #region Flags
|
||||||
|
|
||||||
@ -252,7 +252,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||||||
/**
|
/**
|
||||||
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
|
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
|
||||||
*/
|
*/
|
||||||
selectedOption?: MysteryEncounterOption;
|
selectedOption?: MysteryEncounterOption | undefined;
|
||||||
/**
|
/**
|
||||||
* Array containing data pertaining to free moves used at the start of a battle mystery envounter.
|
* Array containing data pertaining to free moves used at the start of a battle mystery envounter.
|
||||||
*/
|
*/
|
||||||
|
@ -751,7 +751,7 @@ export async function catchPokemon(
|
|||||||
UiMode.POKEDEX_PAGE,
|
UiMode.POKEDEX_PAGE,
|
||||||
pokemon.species,
|
pokemon.species,
|
||||||
pokemon.formIndex,
|
pokemon.formIndex,
|
||||||
attributes,
|
[attributes],
|
||||||
null,
|
null,
|
||||||
() => {
|
() => {
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
|
globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
|
||||||
|
@ -764,7 +764,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
readonly subLegendary: boolean;
|
readonly subLegendary: boolean;
|
||||||
readonly legendary: boolean;
|
readonly legendary: boolean;
|
||||||
readonly mythical: boolean;
|
readonly mythical: boolean;
|
||||||
readonly species: string;
|
public category: string;
|
||||||
readonly growthRate: GrowthRate;
|
readonly growthRate: GrowthRate;
|
||||||
/** The chance (as a decimal) for this Species to be male, or `null` for genderless species */
|
/** The chance (as a decimal) for this Species to be male, or `null` for genderless species */
|
||||||
readonly malePercent: number | null;
|
readonly malePercent: number | null;
|
||||||
@ -778,7 +778,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
subLegendary: boolean,
|
subLegendary: boolean,
|
||||||
legendary: boolean,
|
legendary: boolean,
|
||||||
mythical: boolean,
|
mythical: boolean,
|
||||||
species: string,
|
category: string,
|
||||||
type1: PokemonType,
|
type1: PokemonType,
|
||||||
type2: PokemonType | null,
|
type2: PokemonType | null,
|
||||||
height: number,
|
height: number,
|
||||||
@ -829,7 +829,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
this.subLegendary = subLegendary;
|
this.subLegendary = subLegendary;
|
||||||
this.legendary = legendary;
|
this.legendary = legendary;
|
||||||
this.mythical = mythical;
|
this.mythical = mythical;
|
||||||
this.species = species;
|
this.category = category;
|
||||||
this.growthRate = growthRate;
|
this.growthRate = growthRate;
|
||||||
this.malePercent = malePercent;
|
this.malePercent = malePercent;
|
||||||
this.genderDiffs = genderDiffs;
|
this.genderDiffs = genderDiffs;
|
||||||
@ -968,6 +968,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
|
|
||||||
localize(): void {
|
localize(): void {
|
||||||
this.name = i18next.t(`pokemon:${SpeciesId[this.speciesId].toLowerCase()}`);
|
this.name = i18next.t(`pokemon:${SpeciesId[this.speciesId].toLowerCase()}`);
|
||||||
|
this.category = i18next.t(`pokemonCategory:${SpeciesId[this.speciesId].toLowerCase()}_category`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getWildSpeciesForLevel(level: number, allowEvolving: boolean, isBoss: boolean, gameMode: GameMode): SpeciesId {
|
getWildSpeciesForLevel(level: number, allowEvolving: boolean, isBoss: boolean, gameMode: GameMode): SpeciesId {
|
||||||
|
@ -7,9 +7,9 @@ export class Status {
|
|||||||
public effect: StatusEffect;
|
public effect: StatusEffect;
|
||||||
/** Toxic damage is `1/16 max HP * toxicTurnCount` */
|
/** Toxic damage is `1/16 max HP * toxicTurnCount` */
|
||||||
public toxicTurnCount = 0;
|
public toxicTurnCount = 0;
|
||||||
public sleepTurnsRemaining?: number;
|
public sleepTurnsRemaining = 0;
|
||||||
|
|
||||||
constructor(effect: StatusEffect, toxicTurnCount = 0, sleepTurnsRemaining?: number) {
|
constructor(effect: StatusEffect, toxicTurnCount = 0, sleepTurnsRemaining = 0) {
|
||||||
this.effect = effect;
|
this.effect = effect;
|
||||||
this.toxicTurnCount = toxicTurnCount;
|
this.toxicTurnCount = toxicTurnCount;
|
||||||
this.sleepTurnsRemaining = sleepTurnsRemaining;
|
this.sleepTurnsRemaining = sleepTurnsRemaining;
|
||||||
|
@ -263,14 +263,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
public isTerastallized: boolean;
|
public isTerastallized: boolean;
|
||||||
public stellarTypesBoosted: PokemonType[];
|
public stellarTypesBoosted: PokemonType[];
|
||||||
|
|
||||||
public fusionSpecies: PokemonSpecies | null;
|
public fusionSpecies?: PokemonSpecies | undefined = undefined;
|
||||||
public fusionFormIndex: number;
|
public fusionFormIndex: number;
|
||||||
public fusionAbilityIndex: number;
|
public fusionAbilityIndex: number;
|
||||||
public fusionShiny: boolean;
|
public fusionShiny: boolean;
|
||||||
public fusionVariant: Variant;
|
public fusionVariant: Variant;
|
||||||
public fusionGender: Gender;
|
public fusionGender: Gender;
|
||||||
public fusionLuck: number;
|
public fusionLuck: number;
|
||||||
public fusionCustomPokemonData: CustomPokemonData | null;
|
public fusionCustomPokemonData?: CustomPokemonData | undefined = undefined;
|
||||||
public fusionTeraType: PokemonType;
|
public fusionTeraType: PokemonType;
|
||||||
|
|
||||||
public customPokemonData: CustomPokemonData = new CustomPokemonData();
|
public customPokemonData: CustomPokemonData = new CustomPokemonData();
|
||||||
@ -372,7 +372,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
? dataSource.fusionSpecies
|
? dataSource.fusionSpecies
|
||||||
: dataSource.fusionSpecies
|
: dataSource.fusionSpecies
|
||||||
? getPokemonSpecies(dataSource.fusionSpecies)
|
? getPokemonSpecies(dataSource.fusionSpecies)
|
||||||
: null;
|
: undefined;
|
||||||
this.fusionFormIndex = dataSource.fusionFormIndex;
|
this.fusionFormIndex = dataSource.fusionFormIndex;
|
||||||
this.fusionAbilityIndex = dataSource.fusionAbilityIndex;
|
this.fusionAbilityIndex = dataSource.fusionAbilityIndex;
|
||||||
this.fusionShiny = dataSource.fusionShiny;
|
this.fusionShiny = dataSource.fusionShiny;
|
||||||
@ -642,7 +642,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
gender: pokemon.gender,
|
gender: pokemon.gender,
|
||||||
pokeball: pokemon.pokeball,
|
pokeball: pokemon.pokeball,
|
||||||
fusionFormIndex: pokemon.fusionFormIndex,
|
fusionFormIndex: pokemon.fusionFormIndex,
|
||||||
fusionSpecies: pokemon.fusionSpecies || undefined,
|
fusionSpecies: pokemon.fusionSpecies,
|
||||||
fusionGender: pokemon.fusionGender,
|
fusionGender: pokemon.fusionGender,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2923,14 +2923,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public clearFusionSpecies(): void {
|
public clearFusionSpecies(): void {
|
||||||
this.fusionSpecies = null;
|
|
||||||
this.fusionFormIndex = 0;
|
this.fusionFormIndex = 0;
|
||||||
this.fusionAbilityIndex = 0;
|
this.fusionAbilityIndex = 0;
|
||||||
this.fusionShiny = false;
|
this.fusionShiny = false;
|
||||||
this.fusionVariant = 0;
|
this.fusionVariant = 0;
|
||||||
this.fusionGender = 0;
|
this.fusionGender = 0;
|
||||||
this.fusionLuck = 0;
|
this.fusionLuck = 0;
|
||||||
this.fusionCustomPokemonData = null;
|
this.fusionCustomPokemonData = this.fusionSpecies = undefined;
|
||||||
|
|
||||||
this.generateName();
|
this.generateName();
|
||||||
this.calculateStats();
|
this.calculateStats();
|
||||||
@ -4749,7 +4748,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
globalScene.phaseManager.unshiftNew(
|
globalScene.phaseManager.unshiftNew(
|
||||||
"ObtainStatusEffectPhase",
|
"ObtainStatusEffectPhase",
|
||||||
this.getBattlerIndex(),
|
this.getBattlerIndex(),
|
||||||
effect,
|
effect ?? StatusEffect.NONE, // This is addressed in a separate PR; please don't sue
|
||||||
turnsRemaining,
|
turnsRemaining,
|
||||||
sourceText,
|
sourceText,
|
||||||
sourcePokemon,
|
sourcePokemon,
|
||||||
@ -6734,7 +6733,7 @@ interface IllusionData {
|
|||||||
/** The pokeball of the illusion */
|
/** The pokeball of the illusion */
|
||||||
pokeball: PokeballType;
|
pokeball: PokeballType;
|
||||||
/** The fusion species of the illusion if it's a fusion */
|
/** The fusion species of the illusion if it's a fusion */
|
||||||
fusionSpecies?: PokemonSpecies;
|
fusionSpecies?: PokemonSpecies | undefined;
|
||||||
/** The fusionFormIndex of the illusion */
|
/** The fusionFormIndex of the illusion */
|
||||||
fusionFormIndex?: number;
|
fusionFormIndex?: number;
|
||||||
/** The fusionGender of the illusion if it's a fusion */
|
/** The fusionGender of the illusion if it's a fusion */
|
||||||
@ -6743,6 +6742,7 @@ interface IllusionData {
|
|||||||
level?: number;
|
level?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove `turn` and make `result` mandatory
|
||||||
export interface TurnMove {
|
export interface TurnMove {
|
||||||
move: MoveId;
|
move: MoveId;
|
||||||
targets: BattlerIndex[];
|
targets: BattlerIndex[];
|
||||||
|
@ -2499,7 +2499,7 @@ export interface CustomModifierSettings {
|
|||||||
guaranteedModifierTypeFuncs?: ModifierTypeFunc[];
|
guaranteedModifierTypeFuncs?: ModifierTypeFunc[];
|
||||||
fillRemaining?: boolean;
|
fillRemaining?: boolean;
|
||||||
/** Set to negative value to disable rerolls completely in shop */
|
/** Set to negative value to disable rerolls completely in shop */
|
||||||
rerollMultiplier?: number;
|
rerollMultiplier?: number | undefined;
|
||||||
allowLuckUpgrades?: boolean;
|
allowLuckUpgrades?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,19 +9,17 @@ export class CommonAnimPhase extends PokemonPhase {
|
|||||||
// we need to allow phaseName to be a union of the two
|
// we need to allow phaseName to be a union of the two
|
||||||
public readonly phaseName: "CommonAnimPhase" | "PokemonHealPhase" | "WeatherEffectPhase" = "CommonAnimPhase";
|
public readonly phaseName: "CommonAnimPhase" | "PokemonHealPhase" | "WeatherEffectPhase" = "CommonAnimPhase";
|
||||||
private anim: CommonAnim | null;
|
private anim: CommonAnim | null;
|
||||||
private targetIndex?: BattlerIndex;
|
|
||||||
private playOnEmptyField: boolean;
|
private playOnEmptyField: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
battlerIndex?: BattlerIndex,
|
battlerIndex?: BattlerIndex,
|
||||||
targetIndex?: BattlerIndex,
|
private targetIndex?: BattlerIndex,
|
||||||
anim: CommonAnim | null = null,
|
anim: CommonAnim | null = null,
|
||||||
playOnEmptyField = false,
|
playOnEmptyField = false,
|
||||||
) {
|
) {
|
||||||
super(battlerIndex);
|
super(battlerIndex);
|
||||||
|
|
||||||
this.anim = anim;
|
this.anim = anim;
|
||||||
this.targetIndex = targetIndex;
|
|
||||||
this.playOnEmptyField = playOnEmptyField;
|
this.playOnEmptyField = playOnEmptyField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,16 +33,17 @@ export class FaintPhase extends PokemonPhase {
|
|||||||
*/
|
*/
|
||||||
private preventInstantRevive: boolean;
|
private preventInstantRevive: boolean;
|
||||||
|
|
||||||
/**
|
constructor(
|
||||||
* The source Pokemon that dealt fatal damage
|
battlerIndex: BattlerIndex,
|
||||||
*/
|
preventInstantRevive = false,
|
||||||
private source?: Pokemon;
|
/**
|
||||||
|
* The source Pokemon that dealt fatal damage
|
||||||
constructor(battlerIndex: BattlerIndex, preventInstantRevive = false, source?: Pokemon) {
|
*/
|
||||||
|
private source?: Pokemon,
|
||||||
|
) {
|
||||||
super(battlerIndex);
|
super(battlerIndex);
|
||||||
|
|
||||||
this.preventInstantRevive = preventInstantRevive;
|
this.preventInstantRevive = preventInstantRevive;
|
||||||
this.source = source;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
@ -4,17 +4,17 @@ import { Phase } from "#app/phase";
|
|||||||
export class MessagePhase extends Phase {
|
export class MessagePhase extends Phase {
|
||||||
public readonly phaseName = "MessagePhase";
|
public readonly phaseName = "MessagePhase";
|
||||||
private text: string;
|
private text: string;
|
||||||
private callbackDelay?: number | null;
|
private callbackDelay: number | null = null;
|
||||||
private prompt?: boolean | null;
|
private prompt: boolean | null;
|
||||||
private promptDelay?: number | null;
|
private promptDelay: number | null;
|
||||||
private speaker?: string;
|
private speaker = "";
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
text: string,
|
text: string,
|
||||||
callbackDelay?: number | null,
|
callbackDelay: number | null = null,
|
||||||
prompt?: boolean | null,
|
prompt: boolean | null = null,
|
||||||
promptDelay?: number | null,
|
promptDelay: number | null = null,
|
||||||
speaker?: string,
|
speaker = "",
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -668,6 +668,9 @@ export class MovePhase extends BattlePhase {
|
|||||||
}),
|
}),
|
||||||
500,
|
500,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Moves with pre-use messages (Magnitude, Chilly Reception, Fickle Beam, etc.) always display their messages even on failure
|
||||||
|
// TODO: This assumes single target for message funcs - is this sustainable?
|
||||||
applyMoveAttrs("PreMoveMessageAttr", this.pokemon, this.pokemon.getOpponents(false)[0], this.move.getMove());
|
applyMoveAttrs("PreMoveMessageAttr", this.pokemon, this.pokemon.getOpponents(false)[0], this.move.getMove());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,15 +30,13 @@ import { isNullOrUndefined, randSeedItem } from "#app/utils/common";
|
|||||||
export class MysteryEncounterPhase extends Phase {
|
export class MysteryEncounterPhase extends Phase {
|
||||||
public readonly phaseName = "MysteryEncounterPhase";
|
public readonly phaseName = "MysteryEncounterPhase";
|
||||||
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 300;
|
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 300;
|
||||||
optionSelectSettings?: OptionSelectSettings;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mostly useful for having repeated queries during a single encounter, where the queries and options may differ each time
|
* Mostly useful for having repeated queries during a single encounter, where the queries and options may differ each time
|
||||||
* @param optionSelectSettings allows overriding the typical options of an encounter with new ones
|
* @param optionSelectSettings allows overriding the typical options of an encounter with new ones
|
||||||
*/
|
*/
|
||||||
constructor(optionSelectSettings?: OptionSelectSettings) {
|
constructor(public optionSelectSettings?: OptionSelectSettings) {
|
||||||
super();
|
super();
|
||||||
this.optionSelectSettings = optionSelectSettings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -574,7 +572,7 @@ export class MysteryEncounterRewardsPhase extends Phase {
|
|||||||
export class PostMysteryEncounterPhase extends Phase {
|
export class PostMysteryEncounterPhase extends Phase {
|
||||||
public readonly phaseName = "PostMysteryEncounterPhase";
|
public readonly phaseName = "PostMysteryEncounterPhase";
|
||||||
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 750;
|
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 750;
|
||||||
onPostOptionSelect?: OptionPhaseCallback;
|
onPostOptionSelect?: OptionPhaseCallback | undefined;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -13,24 +13,15 @@ import { isNullOrUndefined } from "#app/utils/common";
|
|||||||
|
|
||||||
export class ObtainStatusEffectPhase extends PokemonPhase {
|
export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||||
public readonly phaseName = "ObtainStatusEffectPhase";
|
public readonly phaseName = "ObtainStatusEffectPhase";
|
||||||
private statusEffect?: StatusEffect;
|
|
||||||
private turnsRemaining?: number;
|
|
||||||
private sourceText?: string | null;
|
|
||||||
private sourcePokemon?: Pokemon | null;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
battlerIndex: BattlerIndex,
|
battlerIndex: BattlerIndex,
|
||||||
statusEffect?: StatusEffect,
|
private statusEffect: StatusEffect,
|
||||||
turnsRemaining?: number,
|
private turnsRemaining = 0,
|
||||||
sourceText?: string | null,
|
private sourceText: string | null = null,
|
||||||
sourcePokemon?: Pokemon | null,
|
private sourcePokemon: Pokemon | null = null,
|
||||||
) {
|
) {
|
||||||
super(battlerIndex);
|
super(battlerIndex);
|
||||||
|
|
||||||
this.statusEffect = statusEffect;
|
|
||||||
this.turnsRemaining = turnsRemaining;
|
|
||||||
this.sourceText = sourceText;
|
|
||||||
this.sourcePokemon = sourcePokemon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
@ -7,16 +7,13 @@ import { Phase } from "#app/phase";
|
|||||||
*/
|
*/
|
||||||
export class PartyExpPhase extends Phase {
|
export class PartyExpPhase extends Phase {
|
||||||
public readonly phaseName = "PartyExpPhase";
|
public readonly phaseName = "PartyExpPhase";
|
||||||
expValue: number;
|
|
||||||
useWaveIndexMultiplier?: boolean;
|
|
||||||
pokemonParticipantIds?: Set<number>;
|
|
||||||
|
|
||||||
constructor(expValue: number, useWaveIndexMultiplier?: boolean, pokemonParticipantIds?: Set<number>) {
|
constructor(
|
||||||
|
public expValue: number,
|
||||||
|
public useWaveIndexMultiplier?: boolean,
|
||||||
|
public pokemonParticipantIds?: Set<number>,
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.expValue = expValue;
|
|
||||||
this.useWaveIndexMultiplier = useWaveIndexMultiplier;
|
|
||||||
this.pokemonParticipantIds = pokemonParticipantIds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,12 +4,9 @@ import type { EndCardPhase } from "./end-card-phase";
|
|||||||
|
|
||||||
export class PostGameOverPhase extends Phase {
|
export class PostGameOverPhase extends Phase {
|
||||||
public readonly phaseName = "PostGameOverPhase";
|
public readonly phaseName = "PostGameOverPhase";
|
||||||
private endCardPhase?: EndCardPhase;
|
|
||||||
|
|
||||||
constructor(endCardPhase?: EndCardPhase) {
|
constructor(private endCardPhase?: EndCardPhase) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.endCardPhase = endCardPhase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
@ -5,12 +5,9 @@ import { fixedInt } from "#app/utils/common";
|
|||||||
|
|
||||||
export class ReloadSessionPhase extends Phase {
|
export class ReloadSessionPhase extends Phase {
|
||||||
public readonly phaseName = "ReloadSessionPhase";
|
public readonly phaseName = "ReloadSessionPhase";
|
||||||
private systemDataStr?: string;
|
|
||||||
|
|
||||||
constructor(systemDataStr?: string) {
|
constructor(private systemDataStr?: string) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.systemDataStr = systemDataStr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start(): void {
|
start(): void {
|
||||||
|
@ -35,25 +35,15 @@ export type ModifierSelectCallback = (rowCursor: number, cursor: number) => bool
|
|||||||
|
|
||||||
export class SelectModifierPhase extends BattlePhase {
|
export class SelectModifierPhase extends BattlePhase {
|
||||||
public readonly phaseName = "SelectModifierPhase";
|
public readonly phaseName = "SelectModifierPhase";
|
||||||
private rerollCount: number;
|
|
||||||
private modifierTiers?: ModifierTier[];
|
|
||||||
private customModifierSettings?: CustomModifierSettings;
|
|
||||||
private isCopy: boolean;
|
|
||||||
|
|
||||||
private typeOptions: ModifierTypeOption[];
|
private typeOptions: ModifierTypeOption[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
rerollCount = 0,
|
private rerollCount = 0,
|
||||||
modifierTiers?: ModifierTier[],
|
private modifierTiers?: ModifierTier[],
|
||||||
customModifierSettings?: CustomModifierSettings,
|
private customModifierSettings?: CustomModifierSettings,
|
||||||
isCopy = false,
|
private isCopy = false,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.rerollCount = rerollCount;
|
|
||||||
this.modifierTiers = modifierTiers;
|
|
||||||
this.customModifierSettings = customModifierSettings;
|
|
||||||
this.isCopy = isCopy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
@ -32,8 +32,8 @@ export abstract class ApiBase {
|
|||||||
* @param bodyData The body-data to send.
|
* @param bodyData The body-data to send.
|
||||||
* @param dataType The data-type of the {@linkcode bodyData}.
|
* @param dataType The data-type of the {@linkcode bodyData}.
|
||||||
*/
|
*/
|
||||||
protected async doPost<D = undefined>(path: string, bodyData?: D, dataType: DataType = "json") {
|
protected async doPost<D = null>(path: string, bodyData?: D, dataType: DataType = "json") {
|
||||||
let body: string | undefined = undefined;
|
let body: string | null = null;
|
||||||
const headers: HeadersInit = {};
|
const headers: HeadersInit = {};
|
||||||
|
|
||||||
if (bodyData) {
|
if (bodyData) {
|
||||||
|
@ -112,7 +112,9 @@ export class PokerogueAdminApi extends ApiBase {
|
|||||||
* @param params The {@linkcode SearchAccountRequest} to send
|
* @param params The {@linkcode SearchAccountRequest} to send
|
||||||
* @returns an array of {@linkcode SearchAccountResponse} and error. Both can be `undefined`
|
* @returns an array of {@linkcode SearchAccountResponse} and error. Both can be `undefined`
|
||||||
*/
|
*/
|
||||||
public async searchAccount(params: SearchAccountRequest): Promise<[data?: SearchAccountResponse, error?: string]> {
|
public async searchAccount(
|
||||||
|
params: SearchAccountRequest,
|
||||||
|
): Promise<[data?: SearchAccountResponse | undefined, error?: string | undefined]> {
|
||||||
try {
|
try {
|
||||||
const urlSearchParams = this.toUrlSearchParams(params);
|
const urlSearchParams = this.toUrlSearchParams(params);
|
||||||
const response = await this.doGet(`/admin/account/adminSearch?${urlSearchParams}`);
|
const response = await this.doGet(`/admin/account/adminSearch?${urlSearchParams}`);
|
||||||
|
@ -245,6 +245,7 @@ export async function initI18n(): Promise<void> {
|
|||||||
"pokeball",
|
"pokeball",
|
||||||
"pokedexUiHandler",
|
"pokedexUiHandler",
|
||||||
"pokemon",
|
"pokemon",
|
||||||
|
"pokemonCategory",
|
||||||
"pokemonEvolutions",
|
"pokemonEvolutions",
|
||||||
"pokemonForm",
|
"pokemonForm",
|
||||||
"pokemonInfo",
|
"pokemonInfo",
|
||||||
|
@ -164,15 +164,15 @@ export interface StarterMoveData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface StarterAttributes {
|
export interface StarterAttributes {
|
||||||
nature?: number;
|
nature?: number | undefined;
|
||||||
ability?: number;
|
ability?: number | undefined;
|
||||||
variant?: number;
|
variant?: number | undefined;
|
||||||
form?: number;
|
form?: number | undefined;
|
||||||
female?: boolean;
|
female?: boolean | undefined;
|
||||||
shiny?: boolean;
|
shiny?: boolean | undefined;
|
||||||
favorite?: boolean;
|
favorite?: boolean | undefined;
|
||||||
nickname?: string;
|
nickname?: string | undefined;
|
||||||
tera?: PokemonType;
|
tera?: PokemonType | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DexAttrProps {
|
export interface DexAttrProps {
|
||||||
|
@ -25,6 +25,7 @@ interface OldTurnMove {
|
|||||||
const fixMoveHistory: SessionSaveMigrator = {
|
const fixMoveHistory: SessionSaveMigrator = {
|
||||||
version: "1.10.0",
|
version: "1.10.0",
|
||||||
migrate: (data: SessionSaveData): void => {
|
migrate: (data: SessionSaveData): void => {
|
||||||
|
// @ts-expect-error - optional property jank
|
||||||
const mapTurnMove = (tm: OldTurnMove): TurnMove => ({
|
const mapTurnMove = (tm: OldTurnMove): TurnMove => ({
|
||||||
move: tm.move,
|
move: tm.move,
|
||||||
targets: tm.targets,
|
targets: tm.targets,
|
||||||
|
@ -21,7 +21,7 @@ export class EnemyBattleInfo extends BattleInfo {
|
|||||||
protected effectivenessContainer: Phaser.GameObjects.Container;
|
protected effectivenessContainer: Phaser.GameObjects.Container;
|
||||||
protected effectivenessWindow: Phaser.GameObjects.NineSlice;
|
protected effectivenessWindow: Phaser.GameObjects.NineSlice;
|
||||||
protected effectivenessText: Phaser.GameObjects.Text;
|
protected effectivenessText: Phaser.GameObjects.Text;
|
||||||
protected currentEffectiveness?: string;
|
protected currentEffectiveness?: string | undefined;
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
override get statOrder(): Stat[] {
|
override get statOrder(): Stat[] {
|
||||||
|
@ -36,15 +36,11 @@ export enum SortCriteria {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class DropDownLabel {
|
export class DropDownLabel {
|
||||||
public state: DropDownState;
|
constructor(
|
||||||
public text: string;
|
public text: string,
|
||||||
public sprite?: Phaser.GameObjects.Sprite;
|
public sprite?: Phaser.GameObjects.Sprite,
|
||||||
|
public state: DropDownState = DropDownState.OFF,
|
||||||
constructor(label: string, sprite?: Phaser.GameObjects.Sprite, state: DropDownState = DropDownState.OFF) {
|
) {}
|
||||||
this.text = label || "";
|
|
||||||
this.sprite = sprite;
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DropDownOption extends Phaser.GameObjects.Container {
|
export class DropDownOption extends Phaser.GameObjects.Container {
|
||||||
|
@ -95,7 +95,7 @@ export abstract class FormModalUiHandler extends ModalUiHandler {
|
|||||||
const inputBg = addWindow(0, 0, 80, 16, false, false, 0, 0, WindowVariant.XTHIN);
|
const inputBg = addWindow(0, 0, 80, 16, false, false, 0, 0, WindowVariant.XTHIN);
|
||||||
|
|
||||||
const isPassword = config?.isPassword;
|
const isPassword = config?.isPassword;
|
||||||
const isReadOnly = config?.isReadOnly;
|
const isReadOnly = config?.isReadOnly ?? false;
|
||||||
const input = addTextInputObject(4, -2, 440, 116, TextStyle.TOOLTIP_CONTENT, {
|
const input = addTextInputObject(4, -2, 440, 116, TextStyle.TOOLTIP_CONTENT, {
|
||||||
type: isPassword ? "password" : "text",
|
type: isPassword ? "password" : "text",
|
||||||
maxLength: isPassword ? 64 : 20,
|
maxLength: isPassword ? 64 : 20,
|
||||||
|
@ -18,7 +18,7 @@ import { globalScene } from "#app/global-scene";
|
|||||||
|
|
||||||
export default class MysteryEncounterUiHandler extends UiHandler {
|
export default class MysteryEncounterUiHandler extends UiHandler {
|
||||||
private cursorContainer: Phaser.GameObjects.Container;
|
private cursorContainer: Phaser.GameObjects.Container;
|
||||||
private cursorObj?: Phaser.GameObjects.Image;
|
private cursorObj?: Phaser.GameObjects.Image | undefined;
|
||||||
|
|
||||||
private optionsContainer: Phaser.GameObjects.Container;
|
private optionsContainer: Phaser.GameObjects.Container;
|
||||||
// Length = max number of allowable options (4)
|
// Length = max number of allowable options (4)
|
||||||
@ -26,18 +26,18 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
|
|
||||||
private tooltipWindow: Phaser.GameObjects.NineSlice;
|
private tooltipWindow: Phaser.GameObjects.NineSlice;
|
||||||
private tooltipContainer: Phaser.GameObjects.Container;
|
private tooltipContainer: Phaser.GameObjects.Container;
|
||||||
private tooltipScrollTween?: Phaser.Tweens.Tween;
|
private tooltipScrollTween?: Phaser.Tweens.Tween | undefined;
|
||||||
|
|
||||||
private descriptionWindow: Phaser.GameObjects.NineSlice;
|
private descriptionWindow: Phaser.GameObjects.NineSlice;
|
||||||
private descriptionContainer: Phaser.GameObjects.Container;
|
private descriptionContainer: Phaser.GameObjects.Container;
|
||||||
private descriptionScrollTween?: Phaser.Tweens.Tween;
|
private descriptionScrollTween?: Phaser.Tweens.Tween | undefined;
|
||||||
private rarityBall: Phaser.GameObjects.Sprite;
|
private rarityBall: Phaser.GameObjects.Sprite;
|
||||||
|
|
||||||
private dexProgressWindow: Phaser.GameObjects.NineSlice;
|
private dexProgressWindow: Phaser.GameObjects.NineSlice;
|
||||||
private dexProgressContainer: Phaser.GameObjects.Container;
|
private dexProgressContainer: Phaser.GameObjects.Container;
|
||||||
private showDexProgress = false;
|
private showDexProgress = false;
|
||||||
|
|
||||||
private overrideSettings?: OptionSelectSettings;
|
private overrideSettings?: OptionSelectSettings | undefined;
|
||||||
private encounterOptions: MysteryEncounterOption[] = [];
|
private encounterOptions: MysteryEncounterOption[] = [];
|
||||||
private optionsMeetsReqs: boolean[];
|
private optionsMeetsReqs: boolean[];
|
||||||
|
|
||||||
|
@ -134,10 +134,10 @@ const valueReductionMax = 2;
|
|||||||
const speciesContainerX = 109;
|
const speciesContainerX = 109;
|
||||||
|
|
||||||
interface SpeciesDetails {
|
interface SpeciesDetails {
|
||||||
shiny?: boolean;
|
shiny?: boolean | undefined;
|
||||||
formIndex?: number;
|
formIndex?: number | undefined;
|
||||||
female?: boolean;
|
female?: boolean | undefined;
|
||||||
variant?: number;
|
variant?: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MenuOptions {
|
enum MenuOptions {
|
||||||
@ -174,6 +174,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||||||
private pokemonCaughtHatchedContainer: Phaser.GameObjects.Container;
|
private pokemonCaughtHatchedContainer: Phaser.GameObjects.Container;
|
||||||
private pokemonCaughtCountText: Phaser.GameObjects.Text;
|
private pokemonCaughtCountText: Phaser.GameObjects.Text;
|
||||||
private pokemonFormText: Phaser.GameObjects.Text;
|
private pokemonFormText: Phaser.GameObjects.Text;
|
||||||
|
private pokemonCategoryText: Phaser.GameObjects.Text;
|
||||||
private pokemonHatchedIcon: Phaser.GameObjects.Sprite;
|
private pokemonHatchedIcon: Phaser.GameObjects.Sprite;
|
||||||
private pokemonHatchedCountText: Phaser.GameObjects.Text;
|
private pokemonHatchedCountText: Phaser.GameObjects.Text;
|
||||||
private pokemonShinyIcons: Phaser.GameObjects.Sprite[];
|
private pokemonShinyIcons: Phaser.GameObjects.Sprite[];
|
||||||
@ -409,6 +410,12 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonFormText.setOrigin(0, 0);
|
this.pokemonFormText.setOrigin(0, 0);
|
||||||
this.starterSelectContainer.add(this.pokemonFormText);
|
this.starterSelectContainer.add(this.pokemonFormText);
|
||||||
|
|
||||||
|
this.pokemonCategoryText = addTextObject(100, 18, "Category", TextStyle.WINDOW_ALT, {
|
||||||
|
fontSize: "42px",
|
||||||
|
});
|
||||||
|
this.pokemonCategoryText.setOrigin(1, 0);
|
||||||
|
this.starterSelectContainer.add(this.pokemonCategoryText);
|
||||||
|
|
||||||
this.pokemonCaughtHatchedContainer = globalScene.add.container(2, 25);
|
this.pokemonCaughtHatchedContainer = globalScene.add.container(2, 25);
|
||||||
this.pokemonCaughtHatchedContainer.setScale(0.5);
|
this.pokemonCaughtHatchedContainer.setScale(0.5);
|
||||||
this.starterSelectContainer.add(this.pokemonCaughtHatchedContainer);
|
this.starterSelectContainer.add(this.pokemonCaughtHatchedContainer);
|
||||||
@ -2354,6 +2361,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonCaughtHatchedContainer.setVisible(true);
|
this.pokemonCaughtHatchedContainer.setVisible(true);
|
||||||
this.pokemonCandyContainer.setVisible(false);
|
this.pokemonCandyContainer.setVisible(false);
|
||||||
this.pokemonFormText.setVisible(false);
|
this.pokemonFormText.setVisible(false);
|
||||||
|
this.pokemonCategoryText.setVisible(false);
|
||||||
|
|
||||||
const defaultDexAttr = globalScene.gameData.getSpeciesDefaultDexAttr(species, true, true);
|
const defaultDexAttr = globalScene.gameData.getSpeciesDefaultDexAttr(species, true, true);
|
||||||
const props = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
const props = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
@ -2382,6 +2390,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonCaughtHatchedContainer.setVisible(false);
|
this.pokemonCaughtHatchedContainer.setVisible(false);
|
||||||
this.pokemonCandyContainer.setVisible(false);
|
this.pokemonCandyContainer.setVisible(false);
|
||||||
this.pokemonFormText.setVisible(false);
|
this.pokemonFormText.setVisible(false);
|
||||||
|
this.pokemonCategoryText.setVisible(false);
|
||||||
|
|
||||||
this.setSpeciesDetails(species!, {
|
this.setSpeciesDetails(species!, {
|
||||||
// TODO: is this bang correct?
|
// TODO: is this bang correct?
|
||||||
@ -2534,6 +2543,13 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonNameText.setText(species ? "???" : "");
|
this.pokemonNameText.setText(species ? "???" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setting the category
|
||||||
|
if (isFormCaught) {
|
||||||
|
this.pokemonCategoryText.setText(species.category);
|
||||||
|
} else {
|
||||||
|
this.pokemonCategoryText.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
// Setting tint of the sprite
|
// Setting tint of the sprite
|
||||||
if (isFormCaught) {
|
if (isFormCaught) {
|
||||||
this.species.loadAssets(female!, formIndex, shiny, variant as Variant, true).then(() => {
|
this.species.loadAssets(female!, formIndex, shiny, variant as Variant, true).then(() => {
|
||||||
|
@ -89,8 +89,8 @@ export interface Starter {
|
|||||||
nature: Nature;
|
nature: Nature;
|
||||||
moveset?: StarterMoveset;
|
moveset?: StarterMoveset;
|
||||||
pokerus: boolean;
|
pokerus: boolean;
|
||||||
nickname?: string;
|
nickname?: string | undefined;
|
||||||
teraType?: PokemonType;
|
teraType?: PokemonType | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LanguageSetting {
|
interface LanguageSetting {
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import { AbilityId } from "#enums/ability-id";
|
import { RandomMoveAttr } from "#app/data/moves/move";
|
||||||
|
import { MoveResult } from "#enums/move-result";
|
||||||
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import { AbilityId } from "#app/enums/ability-id";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
|
import i18next from "i18next";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
//import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|
||||||
|
|
||||||
describe("Moves - Chilly Reception", () => {
|
describe("Moves - Chilly Reception", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
@ -25,95 +28,121 @@ describe("Moves - Chilly Reception", () => {
|
|||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override
|
game.override
|
||||||
.battleStyle("single")
|
.battleStyle("single")
|
||||||
.moveset([MoveId.CHILLY_RECEPTION, MoveId.SNOWSCAPE])
|
.moveset([MoveId.CHILLY_RECEPTION, MoveId.SNOWSCAPE, MoveId.SPLASH, MoveId.METRONOME])
|
||||||
.enemyMoveset(MoveId.SPLASH)
|
.enemyMoveset(MoveId.SPLASH)
|
||||||
.enemyAbility(AbilityId.BALL_FETCH)
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
.ability(AbilityId.BALL_FETCH);
|
.ability(AbilityId.BALL_FETCH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should still change the weather if user can't switch out", async () => {
|
it("should display message before use, switch the user out and change the weather to snow", async () => {
|
||||||
|
await game.classicMode.startBattle([SpeciesId.SLOWKING, SpeciesId.MEOWTH]);
|
||||||
|
|
||||||
|
const [slowking, meowth] = game.scene.getPlayerParty();
|
||||||
|
|
||||||
|
game.move.select(MoveId.CHILLY_RECEPTION);
|
||||||
|
game.doSelectPartyPokemon(1);
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
|
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
||||||
|
expect(game.scene.getPlayerPokemon()).toBe(meowth);
|
||||||
|
expect(slowking.isOnField()).toBe(false);
|
||||||
|
expect(game.phaseInterceptor.log).toContain("SwitchSummonPhase");
|
||||||
|
expect(game.textInterceptor.logs).toContain(
|
||||||
|
i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(slowking) }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should still change weather if user can't switch out", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.SLOWKING]);
|
await game.classicMode.startBattle([SpeciesId.SLOWKING]);
|
||||||
|
|
||||||
game.move.select(MoveId.CHILLY_RECEPTION);
|
game.move.select(MoveId.CHILLY_RECEPTION);
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
||||||
|
expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase");
|
||||||
|
expect(game.scene.getPlayerPokemon()?.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should switch out even if it's snowing", async () => {
|
it("should still switch out even if weather cannot be changed", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.SLOWKING, SpeciesId.MEOWTH]);
|
await game.classicMode.startBattle([SpeciesId.SLOWKING, SpeciesId.MEOWTH]);
|
||||||
// first turn set up snow with snowscape, try chilly reception on second turn
|
|
||||||
|
expect(game.scene.arena.weather?.weatherType).not.toBe(WeatherType.SNOW);
|
||||||
|
|
||||||
|
const [slowking, meowth] = game.scene.getPlayerParty();
|
||||||
|
|
||||||
game.move.select(MoveId.SNOWSCAPE);
|
game.move.select(MoveId.SNOWSCAPE);
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
await game.toNextTurn();
|
||||||
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
||||||
|
|
||||||
await game.phaseInterceptor.to("TurnInitPhase", false);
|
|
||||||
game.move.select(MoveId.CHILLY_RECEPTION);
|
game.move.select(MoveId.CHILLY_RECEPTION);
|
||||||
game.doSelectPartyPokemon(1);
|
game.doSelectPartyPokemon(1);
|
||||||
|
// TODO: Uncomment lines once wimp out PR fixes force switches to not reset summon data immediately
|
||||||
|
// await game.phaseInterceptor.to("SwitchSummonPhase", false);
|
||||||
|
// expect(slowking.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS);
|
||||||
|
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
||||||
expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MEOWTH);
|
expect(game.phaseInterceptor.log).toContain("SwitchSummonPhase");
|
||||||
|
expect(game.scene.getPlayerPokemon()).toBe(meowth);
|
||||||
|
expect(slowking.isOnField()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("happy case - switch out and weather changes", async () => {
|
// Source: https://replay.pokemonshowdown.com/gen9ou-2367532550
|
||||||
|
it("should fail (while still displaying message) if neither weather change nor switch out succeeds", async () => {
|
||||||
|
await game.classicMode.startBattle([SpeciesId.SLOWKING]);
|
||||||
|
|
||||||
|
expect(game.scene.arena.weather?.weatherType).not.toBe(WeatherType.SNOW);
|
||||||
|
|
||||||
|
const slowking = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(MoveId.SNOWSCAPE);
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
||||||
|
|
||||||
|
game.move.select(MoveId.CHILLY_RECEPTION);
|
||||||
|
game.doSelectPartyPokemon(1);
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
|
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
||||||
|
expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase");
|
||||||
|
expect(game.scene.getPlayerPokemon()).toBe(slowking);
|
||||||
|
expect(slowking.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
expect(game.textInterceptor.logs).toContain(
|
||||||
|
i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(slowking) }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should succeed without message if called indirectly", async () => {
|
||||||
|
vi.spyOn(RandomMoveAttr.prototype, "getMoveOverride").mockReturnValue(MoveId.CHILLY_RECEPTION);
|
||||||
await game.classicMode.startBattle([SpeciesId.SLOWKING, SpeciesId.MEOWTH]);
|
await game.classicMode.startBattle([SpeciesId.SLOWKING, SpeciesId.MEOWTH]);
|
||||||
|
|
||||||
game.move.select(MoveId.CHILLY_RECEPTION);
|
const [slowking, meowth] = game.scene.getPlayerParty();
|
||||||
game.doSelectPartyPokemon(1);
|
|
||||||
|
game.move.select(MoveId.METRONOME);
|
||||||
|
game.doSelectPartyPokemon(1);
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
||||||
expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MEOWTH);
|
expect(game.scene.getPlayerPokemon()).toBe(meowth);
|
||||||
|
expect(slowking.isOnField()).toBe(false);
|
||||||
|
expect(game.phaseInterceptor.log).toContain("SwitchSummonPhase");
|
||||||
|
expect(game.textInterceptor.logs).not.toContain(
|
||||||
|
i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(slowking) }),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// enemy uses another move and weather doesn't change
|
// Bugcheck test for enemy AI bug
|
||||||
it("check case - enemy not selecting chilly reception doesn't change weather ", async () => {
|
it("check case - enemy not selecting chilly reception doesn't change weather", async () => {
|
||||||
game.override.battleStyle("single").enemyMoveset([MoveId.CHILLY_RECEPTION, MoveId.TACKLE]).moveset(MoveId.SPLASH);
|
game.override.enemyMoveset([MoveId.CHILLY_RECEPTION, MoveId.TACKLE]);
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.SLOWKING, SpeciesId.MEOWTH]);
|
await game.classicMode.startBattle([SpeciesId.SLOWKING, SpeciesId.MEOWTH]);
|
||||||
|
|
||||||
game.move.select(MoveId.SPLASH);
|
game.move.select(MoveId.SPLASH);
|
||||||
await game.move.selectEnemyMove(MoveId.TACKLE);
|
await game.move.selectEnemyMove(MoveId.TACKLE);
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
expect(game.scene.arena.weather?.weatherType).toBeUndefined();
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("enemy trainer - expected behavior ", async () => {
|
|
||||||
game.override
|
|
||||||
.battleStyle("single")
|
|
||||||
.startingWave(8)
|
|
||||||
.enemyMoveset(MoveId.CHILLY_RECEPTION)
|
|
||||||
.enemySpecies(SpeciesId.MAGIKARP)
|
|
||||||
.moveset([MoveId.SPLASH, MoveId.THUNDERBOLT]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.JOLTEON]);
|
|
||||||
const RIVAL_MAGIKARP1 = game.scene.getEnemyPokemon()?.id;
|
|
||||||
|
|
||||||
game.move.select(MoveId.SPLASH);
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
|
||||||
expect(game.scene.getEnemyPokemon()?.id !== RIVAL_MAGIKARP1);
|
|
||||||
|
|
||||||
await game.phaseInterceptor.to("TurnInitPhase", false);
|
|
||||||
game.move.select(MoveId.SPLASH);
|
|
||||||
|
|
||||||
// second chilly reception should still switch out
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
|
||||||
await game.phaseInterceptor.to("TurnInitPhase", false);
|
|
||||||
expect(game.scene.getEnemyPokemon()?.id === RIVAL_MAGIKARP1);
|
|
||||||
game.move.select(MoveId.THUNDERBOLT);
|
|
||||||
|
|
||||||
// enemy chilly recep move should fail: it's snowing and no option to switch out
|
|
||||||
// no crashing
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
|
||||||
await game.phaseInterceptor.to("TurnInitPhase", false);
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
|
||||||
game.move.select(MoveId.SPLASH);
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SNOW);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -17,6 +17,7 @@ export class MockClock extends Clock {
|
|||||||
|
|
||||||
addEvent(config: Phaser.Time.TimerEvent | Phaser.Types.Time.TimerEventConfig): Phaser.Time.TimerEvent {
|
addEvent(config: Phaser.Time.TimerEvent | Phaser.Types.Time.TimerEventConfig): Phaser.Time.TimerEvent {
|
||||||
const cfg = { ...config, delay: this.overrideDelay ?? config.delay };
|
const cfg = { ...config, delay: this.overrideDelay ?? config.delay };
|
||||||
return super.addEvent(cfg);
|
// Type assertion needed to get around optional property shit
|
||||||
|
return super.addEvent(cfg as Phaser.Time.TimerEvent | Phaser.Types.Time.TimerEventConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ export interface PromptHandler {
|
|||||||
phaseTarget?: string;
|
phaseTarget?: string;
|
||||||
mode?: UiMode;
|
mode?: UiMode;
|
||||||
callback?: () => void;
|
callback?: () => void;
|
||||||
expireFn?: () => void;
|
expireFn?: (() => void) | undefined;
|
||||||
awaitingActionInput?: boolean;
|
awaitingActionInput?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
"strict": false, // TODO: Enable this eventually
|
"strict": false, // TODO: Enable this eventually
|
||||||
|
"exactOptionalPropertyTypes": true,
|
||||||
"rootDir": ".",
|
"rootDir": ".",
|
||||||
"baseUrl": "./src",
|
"baseUrl": "./src",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
Loading…
Reference in New Issue
Block a user