diff --git a/src/battle-scene.ts b/src/battle-scene.ts index b802466ee19..7a2e964e9e4 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -303,7 +303,7 @@ export default class BattleScene extends SceneBase { /** Session save data that pertains to Mystery Encounters */ public mysteryEncounterSaveData: MysteryEncounterSaveData = new MysteryEncounterSaveData(); /** 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 */ private biomeWaveText: Phaser.GameObjects.Text; private moneyText: Phaser.GameObjects.Text; diff --git a/src/battle.ts b/src/battle.ts index 245705f4801..4ec0bfedd9e 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -90,9 +90,9 @@ export default class Battle { public playerFaintsHistory: FaintLogEntry[] = []; public enemyFaintsHistory: FaintLogEntry[] = []; - public mysteryEncounterType?: MysteryEncounterType; + public mysteryEncounterType?: MysteryEncounterType | undefined; /** If the current battle is a Mystery Encounter, this will always be defined */ - public mysteryEncounter?: MysteryEncounter; + public mysteryEncounter?: MysteryEncounter | undefined; private rngCounter = 0; diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 120d1d413c4..b5a9bf09b98 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -1763,14 +1763,11 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr { } export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { - private weatherType: WeatherType; - protected condition?: PokemonDefendCondition; - - constructor(weatherType: WeatherType, condition?: PokemonDefendCondition) { + constructor( + private weatherType: WeatherType, + protected condition?: PokemonDefendCondition, + ) { super(); - - this.weatherType = weatherType; - this.condition = condition; } override canApplyPostDefend( @@ -2758,13 +2755,10 @@ export class GorillaTacticsAbAttr extends ExecutedMoveAbAttr { } export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { - private stealCondition: PokemonAttackCondition | null; private stolenItem?: PokemonHeldItemModifier; - constructor(stealCondition?: PokemonAttackCondition) { + constructor(private stealCondition?: PokemonAttackCondition) { super(); - - this.stealCondition = stealCondition ?? null; } override canApplyPostAttack( @@ -2791,7 +2785,6 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { } } } - this.stolenItem = undefined; return false; } @@ -2817,7 +2810,6 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { }), ); } - this.stolenItem = undefined; } getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] { @@ -2945,13 +2937,10 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { } export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { - private condition?: PokemonDefendCondition; private stolenItem?: PokemonHeldItemModifier; - constructor(condition?: PokemonDefendCondition) { + constructor(private condition?: PokemonDefendCondition) { super(); - - this.condition = condition; } override canApplyPostDefend( @@ -2997,7 +2986,6 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { }), ); } - this.stolenItem = undefined; } getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] { @@ -3375,18 +3363,16 @@ export class PostSummonRemoveArenaTagAbAttr extends PostSummonAbAttr { * Generic class to add an arena tag upon switching in */ export class PostSummonAddArenaTagAbAttr extends PostSummonAbAttr { - private readonly tagType: ArenaTagType; - private readonly turnCount: number; - private readonly side?: ArenaTagSide; - private readonly quiet?: boolean; 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); - this.tagType = tagType; - this.turnCount = turnCount; - this.side = side; - this.quiet = quiet; } public override applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): void { @@ -4340,7 +4326,7 @@ export class ReflectStatStageChangeAbAttr extends PreStatStageChangeAbAttr { */ export class ProtectStatAbAttr extends PreStatStageChangeAbAttr { /** {@linkcode BattleStat} to protect or `undefined` if **all** {@linkcode BattleStat} are protected */ - private protectedStat?: BattleStat; + private protectedStat: BattleStat | undefined = undefined; constructor(protectedStat?: BattleStat) { super(); @@ -6446,7 +6432,6 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr { }), ); } - this.randItem = undefined; } } @@ -7003,7 +6988,6 @@ export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageC export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { private multiplier: number; private tagType: BattlerTagType; - private recoilDamageFunc?: (pokemon: Pokemon) => number; private triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string; constructor( @@ -7011,13 +6995,12 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { multiplier: number, tagType: BattlerTagType, triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string, - recoilDamageFunc?: (pokemon: Pokemon) => number, + private recoilDamageFunc?: (pokemon: Pokemon) => number, ) { super(condition, multiplier); this.multiplier = multiplier; this.tagType = tagType; - this.recoilDamageFunc = recoilDamageFunc; this.triggerMessageFunc = triggerMessageFunc; } diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 8405fd1dd4d..062f9b1f14a 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -45,7 +45,6 @@ export class BattlerTag { public lapseTypes: BattlerTagLapseType[]; public turnCount: number; public sourceMove: MoveId; - public sourceId?: number; public isBatonPassable: boolean; constructor( @@ -53,14 +52,13 @@ export class BattlerTag { lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: number, sourceMove?: MoveId, - sourceId?: number, + public sourceId?: number, isBatonPassable = false, ) { this.tagType = tagType; this.lapseTypes = coerceArray(lapseType); this.turnCount = turnCount; this.sourceMove = sourceMove!; // TODO: is this bang correct? - this.sourceId = sourceId; this.isBatonPassable = isBatonPassable; } diff --git a/src/data/egg.ts b/src/data/egg.ts index a6e2e04a5fe..cbe5be3bef8 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -101,7 +101,7 @@ export class Egg { private _overrideHiddenAbility: boolean; - private _eggDescriptor?: string; + private _eggDescriptor: string | undefined; //// // #endregion diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index f94c59bb463..df170a670df 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -632,7 +632,7 @@ export default abstract class Move implements Localizable { doesFlagEffectApply({ flag, user, target, isFollowUp = false }: { flag: MoveFlags; user: Pokemon; - target?: Pokemon; + target?: Pokemon | undefined; isFollowUp?: 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 @@ -1223,15 +1223,14 @@ interface MoveEffectAttrOptions { * @see {@linkcode apply} */ export class MoveEffectAttr extends MoveAttr { - /** - * A container for this attribute's optional parameters - * @see {@linkcode MoveEffectAttrOptions} for supported params. - */ - protected options?: MoveEffectAttrOptions; - - constructor(selfTarget?: boolean, options?: MoveEffectAttrOptions) { + constructor( + selfTarget?: boolean, + /** + * A container for this attribute's optional parameters + * @see {@linkcode MoveEffectAttrOptions} for supported params. + */ + protected options?: MoveEffectAttrOptions) { super(selfTarget); - this.options = options; } /** @@ -1434,7 +1433,7 @@ export class PreMoveMessageAttr extends MoveAttr { * @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 conditionFunc: MoveConditionFunc; @@ -1442,10 +1441,10 @@ export class PreUseInterruptAttr extends MoveAttr { * 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. */ - 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(); this.message = message; - this.conditionFunc = conditionFunc ?? (() => true); + this.conditionFunc = conditionFunc; } /** @@ -2191,15 +2190,16 @@ export class SandHealAttr extends WeatherHealAttr { * @extends HealAttr * @see {@linkcode apply} */ +// TODO: Convert other healing attributes (WeatherHealAttr, etc) to base off of this class export class BoostHealAttr extends HealAttr { /** Healing received when {@linkcode condition} is false */ private normalHealRatio: number; /** Healing received when {@linkcode condition} is true */ private boostedHealRatio: number; /** 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); this.normalHealRatio = normalHealRatio; this.boostedHealRatio = boostedHealRatio; @@ -2213,8 +2213,8 @@ export class BoostHealAttr extends HealAttr { * @param args N/A * @returns true if the move was successful */ - 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; + override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const healRatio = this.condition(user, target, move) ? this.boostedHealRatio : this.normalHealRatio; this.addHealPhase(target, healRatio); return true; } @@ -2500,7 +2500,7 @@ export class WaterShurikenMultiHitTypeAttr extends ChangeMultiHitTypeAttr { export class StatusEffectAttr extends MoveEffectAttr { public effect: StatusEffect; - public turnsRemaining?: number; + public turnsRemaining?: number | undefined; public overrideStatus: boolean = false; constructor(effect: StatusEffect, selfTarget?: boolean, turnsRemaining?: number, overrideStatus: boolean = false) { @@ -3224,19 +3224,18 @@ interface StatStageChangeAttrOptions extends MoveEffectAttrOptions { * @see {@linkcode apply} */ export class StatStageChangeAttr extends MoveEffectAttr { - public stats: BattleStat[]; - public stages: number; - /** - * Container for optional parameters to this attribute. - * @see {@linkcode StatStageChangeAttrOptions} for available optional params - */ - protected override options?: StatStageChangeAttrOptions; - - constructor(stats: BattleStat[], stages: number, selfTarget?: boolean, options?: StatStageChangeAttrOptions) { + constructor( + public stats: BattleStat[], + public stages: number, + selfTarget?: boolean, + /** + * Container for optional parameters to this attribute. + * @see {@linkcode StatStageChangeAttrOptions} for available optional params + */ + protected override options?: StatStageChangeAttrOptions) { super(selfTarget, options); this.stats = stats; this.stages = stages; - this.options = options; } /** @@ -3468,16 +3467,16 @@ export class SecretPowerAttr extends MoveEffectAttr { export class PostVictoryStatStageChangeAttr extends MoveAttr { private stats: BattleStat[]; private stages: number; - private condition?: MoveConditionFunc; 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(); this.stats = stats; this.stages = stages; this.condition = condition; this.showMessage = showMessage; } + applyPostVictory(user: Pokemon, target: Pokemon, move: Move): void { if (this.condition && !this.condition(user, target, move)) { return; @@ -10501,7 +10500,7 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.SPD ], -1, true) .punchingMove(), 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() .reflectable(), new AttackMove(MoveId.HIGH_HORSEPOWER, PokemonType.GROUND, MoveCategory.PHYSICAL, 95, 95, 10, -1, 0, 7), diff --git a/src/data/moves/pokemon-move.ts b/src/data/moves/pokemon-move.ts index daad199fbbd..01ef944c55c 100644 --- a/src/data/moves/pokemon-move.ts +++ b/src/data/moves/pokemon-move.ts @@ -18,21 +18,19 @@ import type Move from "./move"; * @see {@linkcode getName} - returns name of {@linkcode Move}. **/ export class PokemonMove { - public moveId: MoveId; - public ppUsed: number; - public ppUp: number; - - /** - * 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`. - */ - public maxPpOverride?: number; - - constructor(moveId: MoveId, ppUsed = 0, ppUp = 0, maxPpOverride?: number) { + constructor( + public moveId: MoveId, + 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). + * This also nullifies all effects of `ppUp`. + */ + public maxPpOverride = 0, + ) { this.moveId = moveId; this.ppUsed = ppUsed; this.ppUp = ppUp; - this.maxPpOverride = maxPpOverride; } /** diff --git a/src/data/mystery-encounters/mystery-encounter-option.ts b/src/data/mystery-encounters/mystery-encounter-option.ts index 53b53392bb8..80399e39687 100644 --- a/src/data/mystery-encounters/mystery-encounter-option.ts +++ b/src/data/mystery-encounters/mystery-encounter-option.ts @@ -45,7 +45,7 @@ export default class MysteryEncounterOption implements IMysteryEncounterOption { requirements: EncounterSceneRequirement[]; primaryPokemonRequirements: EncounterPokemonRequirement[]; secondaryPokemonRequirements: EncounterPokemonRequirement[]; - primaryPokemon?: PlayerPokemon; + primaryPokemon?: PlayerPokemon | undefined; secondaryPokemon?: PlayerPokemon[]; excludePrimaryFromSecondaryRequirements: boolean; diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index fa97a7f4d40..3f9ee5cc0ee 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -53,9 +53,9 @@ export interface IMysteryEncounter { options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]]; spriteConfigs: MysteryEncounterSpriteConfig[]; encounterTier: MysteryEncounterTier; - encounterAnimations?: EncounterAnim[]; - disallowedGameModes?: GameModes[]; - disallowedChallenges?: Challenges[]; + encounterAnimations?: EncounterAnim[] | undefined; + disallowedGameModes?: GameModes[] | undefined; + disallowedChallenges?: Challenges[] | undefined; hideBattleIntroMessage: boolean; autoHideIntroVisuals: boolean; enterIntroVisualsFromRight: boolean; @@ -68,11 +68,11 @@ export interface IMysteryEncounter { skipToFightInput: boolean; preventGameStatsUpdates: boolean; - onInit?: () => boolean; - onVisualsStart?: () => boolean; - doEncounterExp?: () => boolean; - doEncounterRewards?: () => boolean; - doContinueEncounter?: () => Promise; + onInit?: (() => boolean) | undefined; + onVisualsStart?: (() => boolean) | undefined; + doEncounterExp?: (() => boolean) | undefined; + doEncounterRewards?: (() => boolean) | undefined; + doContinueEncounter?: (() => Promise) | undefined; requirements: EncounterSceneRequirement[]; primaryPokemonRequirements: EncounterPokemonRequirement[]; @@ -105,15 +105,15 @@ export default class MysteryEncounter implements IMysteryEncounter { * Custom battle animations that are configured for encounter effects and visuals * 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 */ - disallowedGameModes?: GameModes[]; + disallowedGameModes?: GameModes[] | undefined; /** * 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 * Default true @@ -172,24 +172,24 @@ export default class MysteryEncounter implements IMysteryEncounter { // #region Event callback functions /** 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 */ - onVisualsStart?: () => boolean; + onVisualsStart?: (() => boolean) | undefined; /** Event triggered prior to {@linkcode CommandPhase}, during {@linkcode TurnInitPhase} */ - onTurnStart?: () => boolean; + onTurnStart?: (() => boolean) | undefined; /** Event prior to any rewards logic in {@linkcode MysteryEncounterRewardsPhase} */ - onRewards?: () => Promise; + onRewards?: (() => Promise) | undefined; /** 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 */ - doEncounterRewards?: () => boolean; + doEncounterRewards?: (() => boolean) | undefined; /** Will execute callback during VictoryPhase of a continuousEncounter */ - doContinueEncounter?: () => Promise; + doContinueEncounter?: (() => Promise) | undefined; /** * 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. */ - onGameOver?: () => boolean; + onGameOver?: (() => boolean) | undefined; /** * Requirements @@ -204,8 +204,8 @@ export default class MysteryEncounter implements IMysteryEncounter { */ secondaryPokemonRequirements: EncounterPokemonRequirement[]; excludePrimaryFromSupportRequirements: boolean; - primaryPokemon?: PlayerPokemon; - secondaryPokemon?: PlayerPokemon[]; + primaryPokemon?: PlayerPokemon | undefined; + secondaryPokemon?: PlayerPokemon[] | undefined; // #region Post-construct / Auto-populated params localizationKey: string; @@ -224,7 +224,7 @@ export default class MysteryEncounter implements IMysteryEncounter { * Otherwise, will be undefined * You probably shouldn't do anything directly with this unless you have a very specific need */ - introVisuals?: MysteryEncounterIntroVisuals; + introVisuals?: MysteryEncounterIntroVisuals | undefined; // #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 */ - selectedOption?: MysteryEncounterOption; + selectedOption?: MysteryEncounterOption | undefined; /** * Array containing data pertaining to free moves used at the start of a battle mystery envounter. */ diff --git a/src/data/status-effect.ts b/src/data/status-effect.ts index a90304c9f7d..f3bc6a3eb84 100644 --- a/src/data/status-effect.ts +++ b/src/data/status-effect.ts @@ -7,9 +7,9 @@ export class Status { public effect: StatusEffect; /** Toxic damage is `1/16 max HP * toxicTurnCount` */ 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.toxicTurnCount = toxicTurnCount; this.sleepTurnsRemaining = sleepTurnsRemaining; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index e9cc4f70d70..8eb530aa47c 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -263,14 +263,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { public isTerastallized: boolean; public stellarTypesBoosted: PokemonType[]; - public fusionSpecies: PokemonSpecies | null; + public fusionSpecies?: PokemonSpecies | undefined = undefined; public fusionFormIndex: number; public fusionAbilityIndex: number; public fusionShiny: boolean; public fusionVariant: Variant; public fusionGender: Gender; public fusionLuck: number; - public fusionCustomPokemonData: CustomPokemonData | null; + public fusionCustomPokemonData?: CustomPokemonData | undefined = undefined; public fusionTeraType: PokemonType; public customPokemonData: CustomPokemonData = new CustomPokemonData(); @@ -372,7 +372,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ? dataSource.fusionSpecies : dataSource.fusionSpecies ? getPokemonSpecies(dataSource.fusionSpecies) - : null; + : undefined; this.fusionFormIndex = dataSource.fusionFormIndex; this.fusionAbilityIndex = dataSource.fusionAbilityIndex; this.fusionShiny = dataSource.fusionShiny; @@ -642,7 +642,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { gender: pokemon.gender, pokeball: pokemon.pokeball, fusionFormIndex: pokemon.fusionFormIndex, - fusionSpecies: pokemon.fusionSpecies || undefined, + fusionSpecies: pokemon.fusionSpecies, fusionGender: pokemon.fusionGender, }; @@ -2923,14 +2923,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } public clearFusionSpecies(): void { - this.fusionSpecies = null; this.fusionFormIndex = 0; this.fusionAbilityIndex = 0; this.fusionShiny = false; this.fusionVariant = 0; this.fusionGender = 0; this.fusionLuck = 0; - this.fusionCustomPokemonData = null; + this.fusionCustomPokemonData = this.fusionSpecies = undefined; this.generateName(); this.calculateStats(); @@ -4749,7 +4748,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { globalScene.phaseManager.unshiftNew( "ObtainStatusEffectPhase", this.getBattlerIndex(), - effect, + effect ?? StatusEffect.NONE, // This is addressed in a separate PR; please don't sue turnsRemaining, sourceText, sourcePokemon, @@ -6734,7 +6733,7 @@ interface IllusionData { /** The pokeball of the illusion */ pokeball: PokeballType; /** The fusion species of the illusion if it's a fusion */ - fusionSpecies?: PokemonSpecies; + fusionSpecies?: PokemonSpecies | undefined; /** The fusionFormIndex of the illusion */ fusionFormIndex?: number; /** The fusionGender of the illusion if it's a fusion */ @@ -6743,6 +6742,7 @@ interface IllusionData { level?: number; } +// TODO: Remove `turn` and make `result` mandatory export interface TurnMove { move: MoveId; targets: BattlerIndex[]; diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index a04a5e2be47..b5d0e597cf4 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -2499,7 +2499,7 @@ export interface CustomModifierSettings { guaranteedModifierTypeFuncs?: ModifierTypeFunc[]; fillRemaining?: boolean; /** Set to negative value to disable rerolls completely in shop */ - rerollMultiplier?: number; + rerollMultiplier?: number | undefined; allowLuckUpgrades?: boolean; } diff --git a/src/phases/common-anim-phase.ts b/src/phases/common-anim-phase.ts index abfe8ed99f0..1d2b83f5fef 100644 --- a/src/phases/common-anim-phase.ts +++ b/src/phases/common-anim-phase.ts @@ -9,19 +9,17 @@ export class CommonAnimPhase extends PokemonPhase { // we need to allow phaseName to be a union of the two public readonly phaseName: "CommonAnimPhase" | "PokemonHealPhase" | "WeatherEffectPhase" = "CommonAnimPhase"; private anim: CommonAnim | null; - private targetIndex?: BattlerIndex; private playOnEmptyField: boolean; constructor( battlerIndex?: BattlerIndex, - targetIndex?: BattlerIndex, + private targetIndex?: BattlerIndex, anim: CommonAnim | null = null, playOnEmptyField = false, ) { super(battlerIndex); this.anim = anim; - this.targetIndex = targetIndex; this.playOnEmptyField = playOnEmptyField; } diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index 675a198d096..e79aef97cdf 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -33,16 +33,17 @@ export class FaintPhase extends PokemonPhase { */ private preventInstantRevive: boolean; - /** - * The source Pokemon that dealt fatal damage - */ - private source?: Pokemon; - - constructor(battlerIndex: BattlerIndex, preventInstantRevive = false, source?: Pokemon) { + constructor( + battlerIndex: BattlerIndex, + preventInstantRevive = false, + /** + * The source Pokemon that dealt fatal damage + */ + private source?: Pokemon, + ) { super(battlerIndex); this.preventInstantRevive = preventInstantRevive; - this.source = source; } start() { diff --git a/src/phases/message-phase.ts b/src/phases/message-phase.ts index 61f9b74a037..c5c2f7ca521 100644 --- a/src/phases/message-phase.ts +++ b/src/phases/message-phase.ts @@ -4,17 +4,17 @@ import { Phase } from "#app/phase"; export class MessagePhase extends Phase { public readonly phaseName = "MessagePhase"; private text: string; - private callbackDelay?: number | null; - private prompt?: boolean | null; - private promptDelay?: number | null; - private speaker?: string; + private callbackDelay: number | null = null; + private prompt: boolean | null; + private promptDelay: number | null; + private speaker = ""; constructor( text: string, - callbackDelay?: number | null, - prompt?: boolean | null, - promptDelay?: number | null, - speaker?: string, + callbackDelay: number | null = null, + prompt: boolean | null = null, + promptDelay: number | null = null, + speaker = "", ) { super(); diff --git a/src/phases/mystery-encounter-phases.ts b/src/phases/mystery-encounter-phases.ts index 9aae796211f..af59c74b00d 100644 --- a/src/phases/mystery-encounter-phases.ts +++ b/src/phases/mystery-encounter-phases.ts @@ -30,15 +30,13 @@ import { isNullOrUndefined, randSeedItem } from "#app/utils/common"; export class MysteryEncounterPhase extends Phase { public readonly phaseName = "MysteryEncounterPhase"; 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 * @param optionSelectSettings allows overriding the typical options of an encounter with new ones */ - constructor(optionSelectSettings?: OptionSelectSettings) { + constructor(public optionSelectSettings?: OptionSelectSettings) { super(); - this.optionSelectSettings = optionSelectSettings; } /** @@ -574,7 +572,7 @@ export class MysteryEncounterRewardsPhase extends Phase { export class PostMysteryEncounterPhase extends Phase { public readonly phaseName = "PostMysteryEncounterPhase"; private readonly FIRST_DIALOGUE_PROMPT_DELAY = 750; - onPostOptionSelect?: OptionPhaseCallback; + onPostOptionSelect?: OptionPhaseCallback | undefined; constructor() { super(); diff --git a/src/phases/obtain-status-effect-phase.ts b/src/phases/obtain-status-effect-phase.ts index dc26d070029..8926a77a4e7 100644 --- a/src/phases/obtain-status-effect-phase.ts +++ b/src/phases/obtain-status-effect-phase.ts @@ -13,24 +13,15 @@ import { isNullOrUndefined } from "#app/utils/common"; export class ObtainStatusEffectPhase extends PokemonPhase { public readonly phaseName = "ObtainStatusEffectPhase"; - private statusEffect?: StatusEffect; - private turnsRemaining?: number; - private sourceText?: string | null; - private sourcePokemon?: Pokemon | null; constructor( battlerIndex: BattlerIndex, - statusEffect?: StatusEffect, - turnsRemaining?: number, - sourceText?: string | null, - sourcePokemon?: Pokemon | null, + private statusEffect: StatusEffect, + private turnsRemaining = 0, + private sourceText: string | null = null, + private sourcePokemon: Pokemon | null = null, ) { super(battlerIndex); - - this.statusEffect = statusEffect; - this.turnsRemaining = turnsRemaining; - this.sourceText = sourceText; - this.sourcePokemon = sourcePokemon; } start() { diff --git a/src/phases/party-exp-phase.ts b/src/phases/party-exp-phase.ts index 30fc97d9105..b9d75e3e42a 100644 --- a/src/phases/party-exp-phase.ts +++ b/src/phases/party-exp-phase.ts @@ -7,16 +7,13 @@ import { Phase } from "#app/phase"; */ export class PartyExpPhase extends Phase { public readonly phaseName = "PartyExpPhase"; - expValue: number; - useWaveIndexMultiplier?: boolean; - pokemonParticipantIds?: Set; - constructor(expValue: number, useWaveIndexMultiplier?: boolean, pokemonParticipantIds?: Set) { + constructor( + public expValue: number, + public useWaveIndexMultiplier?: boolean, + public pokemonParticipantIds?: Set, + ) { super(); - - this.expValue = expValue; - this.useWaveIndexMultiplier = useWaveIndexMultiplier; - this.pokemonParticipantIds = pokemonParticipantIds; } /** diff --git a/src/phases/post-game-over-phase.ts b/src/phases/post-game-over-phase.ts index 8e19dcd5498..2fd47760a5b 100644 --- a/src/phases/post-game-over-phase.ts +++ b/src/phases/post-game-over-phase.ts @@ -4,12 +4,9 @@ import type { EndCardPhase } from "./end-card-phase"; export class PostGameOverPhase extends Phase { public readonly phaseName = "PostGameOverPhase"; - private endCardPhase?: EndCardPhase; - constructor(endCardPhase?: EndCardPhase) { + constructor(private endCardPhase?: EndCardPhase) { super(); - - this.endCardPhase = endCardPhase; } start() { diff --git a/src/phases/reload-session-phase.ts b/src/phases/reload-session-phase.ts index ac9337753c4..0ed92b4049e 100644 --- a/src/phases/reload-session-phase.ts +++ b/src/phases/reload-session-phase.ts @@ -5,12 +5,9 @@ import { fixedInt } from "#app/utils/common"; export class ReloadSessionPhase extends Phase { public readonly phaseName = "ReloadSessionPhase"; - private systemDataStr?: string; - constructor(systemDataStr?: string) { + constructor(private systemDataStr?: string) { super(); - - this.systemDataStr = systemDataStr; } start(): void { diff --git a/src/phases/select-modifier-phase.ts b/src/phases/select-modifier-phase.ts index 53e1f5bc282..fc4d18c8d6d 100644 --- a/src/phases/select-modifier-phase.ts +++ b/src/phases/select-modifier-phase.ts @@ -35,25 +35,15 @@ export type ModifierSelectCallback = (rowCursor: number, cursor: number) => bool export class SelectModifierPhase extends BattlePhase { public readonly phaseName = "SelectModifierPhase"; - private rerollCount: number; - private modifierTiers?: ModifierTier[]; - private customModifierSettings?: CustomModifierSettings; - private isCopy: boolean; - private typeOptions: ModifierTypeOption[]; constructor( - rerollCount = 0, - modifierTiers?: ModifierTier[], - customModifierSettings?: CustomModifierSettings, - isCopy = false, + private rerollCount = 0, + private modifierTiers?: ModifierTier[], + private customModifierSettings?: CustomModifierSettings, + private isCopy = false, ) { super(); - - this.rerollCount = rerollCount; - this.modifierTiers = modifierTiers; - this.customModifierSettings = customModifierSettings; - this.isCopy = isCopy; } start() { diff --git a/src/plugins/api/api-base.ts b/src/plugins/api/api-base.ts index f55ffe2d3fd..3dcb9f6282f 100644 --- a/src/plugins/api/api-base.ts +++ b/src/plugins/api/api-base.ts @@ -32,8 +32,8 @@ export abstract class ApiBase { * @param bodyData The body-data to send. * @param dataType The data-type of the {@linkcode bodyData}. */ - protected async doPost(path: string, bodyData?: D, dataType: DataType = "json") { - let body: string | undefined = undefined; + protected async doPost(path: string, bodyData?: D, dataType: DataType = "json") { + let body: string | null = null; const headers: HeadersInit = {}; if (bodyData) { diff --git a/src/plugins/api/pokerogue-admin-api.ts b/src/plugins/api/pokerogue-admin-api.ts index 5923f286430..cc24c1c1e97 100644 --- a/src/plugins/api/pokerogue-admin-api.ts +++ b/src/plugins/api/pokerogue-admin-api.ts @@ -112,7 +112,9 @@ export class PokerogueAdminApi extends ApiBase { * @param params The {@linkcode SearchAccountRequest} to send * @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 { const urlSearchParams = this.toUrlSearchParams(params); const response = await this.doGet(`/admin/account/adminSearch?${urlSearchParams}`); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index e933c5704f9..ec61831553f 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -164,15 +164,15 @@ export interface StarterMoveData { } export interface StarterAttributes { - nature?: number; - ability?: number; - variant?: number; - form?: number; - female?: boolean; - shiny?: boolean; - favorite?: boolean; - nickname?: string; - tera?: PokemonType; + nature?: number | undefined; + ability?: number | undefined; + variant?: number | undefined; + form?: number | undefined; + female?: boolean | undefined; + shiny?: boolean | undefined; + favorite?: boolean | undefined; + nickname?: string | undefined; + tera?: PokemonType | undefined; } export interface DexAttrProps { diff --git a/src/system/version_migration/versions/v1_10_0.ts b/src/system/version_migration/versions/v1_10_0.ts index 4d1dedf701e..43e0fe83876 100644 --- a/src/system/version_migration/versions/v1_10_0.ts +++ b/src/system/version_migration/versions/v1_10_0.ts @@ -25,6 +25,7 @@ interface OldTurnMove { const fixMoveHistory: SessionSaveMigrator = { version: "1.10.0", migrate: (data: SessionSaveData): void => { + // @ts-expect-error - optional property jank const mapTurnMove = (tm: OldTurnMove): TurnMove => ({ move: tm.move, targets: tm.targets, diff --git a/src/ui/battle-info/enemy-battle-info.ts b/src/ui/battle-info/enemy-battle-info.ts index 7c16f01ac38..98dab4cfe70 100644 --- a/src/ui/battle-info/enemy-battle-info.ts +++ b/src/ui/battle-info/enemy-battle-info.ts @@ -21,7 +21,7 @@ export class EnemyBattleInfo extends BattleInfo { protected effectivenessContainer: Phaser.GameObjects.Container; protected effectivenessWindow: Phaser.GameObjects.NineSlice; protected effectivenessText: Phaser.GameObjects.Text; - protected currentEffectiveness?: string; + protected currentEffectiveness?: string | undefined; // #endregion override get statOrder(): Stat[] { diff --git a/src/ui/dropdown.ts b/src/ui/dropdown.ts index 2cbd1f0dfa9..8192dc5d63e 100644 --- a/src/ui/dropdown.ts +++ b/src/ui/dropdown.ts @@ -36,15 +36,11 @@ export enum SortCriteria { } export class DropDownLabel { - public state: DropDownState; - public text: string; - public sprite?: Phaser.GameObjects.Sprite; - - constructor(label: string, sprite?: Phaser.GameObjects.Sprite, state: DropDownState = DropDownState.OFF) { - this.text = label || ""; - this.sprite = sprite; - this.state = state; - } + constructor( + public text: string, + public sprite?: Phaser.GameObjects.Sprite, + public state: DropDownState = DropDownState.OFF, + ) {} } export class DropDownOption extends Phaser.GameObjects.Container { diff --git a/src/ui/form-modal-ui-handler.ts b/src/ui/form-modal-ui-handler.ts index 8c30b4e0bc4..56267549724 100644 --- a/src/ui/form-modal-ui-handler.ts +++ b/src/ui/form-modal-ui-handler.ts @@ -95,7 +95,7 @@ export abstract class FormModalUiHandler extends ModalUiHandler { const inputBg = addWindow(0, 0, 80, 16, false, false, 0, 0, WindowVariant.XTHIN); const isPassword = config?.isPassword; - const isReadOnly = config?.isReadOnly; + const isReadOnly = config?.isReadOnly ?? false; const input = addTextInputObject(4, -2, 440, 116, TextStyle.TOOLTIP_CONTENT, { type: isPassword ? "password" : "text", maxLength: isPassword ? 64 : 20, diff --git a/src/ui/mystery-encounter-ui-handler.ts b/src/ui/mystery-encounter-ui-handler.ts index 83ce88714f5..addfc84425d 100644 --- a/src/ui/mystery-encounter-ui-handler.ts +++ b/src/ui/mystery-encounter-ui-handler.ts @@ -18,7 +18,7 @@ import { globalScene } from "#app/global-scene"; export default class MysteryEncounterUiHandler extends UiHandler { private cursorContainer: Phaser.GameObjects.Container; - private cursorObj?: Phaser.GameObjects.Image; + private cursorObj?: Phaser.GameObjects.Image | undefined; private optionsContainer: Phaser.GameObjects.Container; // Length = max number of allowable options (4) @@ -26,18 +26,18 @@ export default class MysteryEncounterUiHandler extends UiHandler { private tooltipWindow: Phaser.GameObjects.NineSlice; private tooltipContainer: Phaser.GameObjects.Container; - private tooltipScrollTween?: Phaser.Tweens.Tween; + private tooltipScrollTween?: Phaser.Tweens.Tween | undefined; private descriptionWindow: Phaser.GameObjects.NineSlice; private descriptionContainer: Phaser.GameObjects.Container; - private descriptionScrollTween?: Phaser.Tweens.Tween; + private descriptionScrollTween?: Phaser.Tweens.Tween | undefined; private rarityBall: Phaser.GameObjects.Sprite; private dexProgressWindow: Phaser.GameObjects.NineSlice; private dexProgressContainer: Phaser.GameObjects.Container; private showDexProgress = false; - private overrideSettings?: OptionSelectSettings; + private overrideSettings?: OptionSelectSettings | undefined; private encounterOptions: MysteryEncounterOption[] = []; private optionsMeetsReqs: boolean[]; diff --git a/src/ui/pokedex-page-ui-handler.ts b/src/ui/pokedex-page-ui-handler.ts index 32a88ab36b2..3cd4b9d44e4 100644 --- a/src/ui/pokedex-page-ui-handler.ts +++ b/src/ui/pokedex-page-ui-handler.ts @@ -134,10 +134,10 @@ const valueReductionMax = 2; const speciesContainerX = 109; interface SpeciesDetails { - shiny?: boolean; - formIndex?: number; - female?: boolean; - variant?: number; + shiny?: boolean | undefined; + formIndex?: number | undefined; + female?: boolean | undefined; + variant?: number | undefined; } enum MenuOptions { diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 20f613fb694..5e1294d3a62 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -89,8 +89,8 @@ export interface Starter { nature: Nature; moveset?: StarterMoveset; pokerus: boolean; - nickname?: string; - teraType?: PokemonType; + nickname?: string | undefined; + teraType?: PokemonType | undefined; } interface LanguageSetting { diff --git a/test/testUtils/mocks/mockClock.ts b/test/testUtils/mocks/mockClock.ts index 67f399ae41d..beea62daeba 100644 --- a/test/testUtils/mocks/mockClock.ts +++ b/test/testUtils/mocks/mockClock.ts @@ -17,6 +17,7 @@ export class MockClock extends Clock { addEvent(config: Phaser.Time.TimerEvent | Phaser.Types.Time.TimerEventConfig): Phaser.Time.TimerEvent { 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); } } diff --git a/test/testUtils/phaseInterceptor.ts b/test/testUtils/phaseInterceptor.ts index 9d046fc85ba..e271782abf7 100644 --- a/test/testUtils/phaseInterceptor.ts +++ b/test/testUtils/phaseInterceptor.ts @@ -69,7 +69,7 @@ export interface PromptHandler { phaseTarget?: string; mode?: UiMode; callback?: () => void; - expireFn?: () => void; + expireFn?: (() => void) | undefined; awaitingActionInput?: boolean; } diff --git a/tsconfig.json b/tsconfig.json index 6af3e9ce650..4e2bdfe2bc9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ "strictNullChecks": true, "sourceMap": false, "strict": false, // TODO: Enable this eventually + "exactOptionalPropertyTypes": true, "rootDir": ".", "baseUrl": "./src", "paths": {