From 648506e03695a8b99d1f10960fd47f9e12c6f7dd Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Fri, 15 Nov 2024 00:53:41 -0800 Subject: [PATCH] Clean up all the bangs caused by movesets allowing `null` --- src/battle-scene.ts | 1 + src/data/balance/pokemon-evolutions.ts | 44 +++---- src/data/battler-tags.ts | 10 +- src/data/berry.ts | 4 +- src/data/challenge.ts | 2 +- src/data/move.ts | 123 ++++++++++++------ .../global-trade-system-encounter.ts | 2 +- .../encounters/weird-dream-encounter.ts | 8 +- .../mystery-encounter-requirements.ts | 6 +- src/data/pokemon-forms.ts | 2 +- src/data/pokemon-species.ts | 20 --- src/field/pokemon.ts | 25 ++-- src/modifier/modifier-type.ts | 18 +-- src/phases/command-phase.ts | 22 ++-- src/phases/learn-move-phase.ts | 2 +- src/phases/party-heal-phase.ts | 2 +- src/phases/turn-start-phase.ts | 2 +- src/test/moves/grudge.test.ts | 6 +- .../absolute-avarice-encounter.test.ts | 4 +- .../dancing-lessons-encounter.test.ts | 4 +- src/test/utils/gameManager.ts | 2 +- src/test/utils/gameManagerUtils.ts | 2 +- src/ui/fight-ui-handler.ts | 2 +- src/ui/party-ui-handler.ts | 6 +- src/ui/summary-ui-handler.ts | 2 +- 25 files changed, 170 insertions(+), 151 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 2f062667808..ae6ceeb7c28 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1167,6 +1167,7 @@ export default class BattleScene extends SceneBase { return Math.max(doubleChance.value, 1); } + // TODO: ...this never returns `null`, right? newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean, mysteryEncounterType?: MysteryEncounterType): Battle | null { const _startingWave = Overrides.STARTING_WAVE_OVERRIDE || startingWave; const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (_startingWave - 1)) + 1); diff --git a/src/data/balance/pokemon-evolutions.ts b/src/data/balance/pokemon-evolutions.ts index 9e86ea7397b..dce056c1630 100644 --- a/src/data/balance/pokemon-evolutions.ts +++ b/src/data/balance/pokemon-evolutions.ts @@ -1300,17 +1300,17 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.EXEGGUTOR, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.TANGELA]: [ - new SpeciesEvolution(Species.TANGROWTH, 34, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.TANGROWTH, 34, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.LICKITUNG]: [ - new SpeciesEvolution(Species.LICKILICKY, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.ROLLOUT).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.LICKILICKY, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.ROLLOUT).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.STARYU]: [ new SpeciesEvolution(Species.STARMIE, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.EEVEE]: [ - new SpeciesFormEvolution(Species.SYLVEON, "", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => !!p.getMoveset().find(m => m?.getMove().type === Type.FAIRY)), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.SYLVEON, "partner", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => !!p.getMoveset().find(m => m?.getMove().type === Type.FAIRY)), SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.SYLVEON, "", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => !!p.getMoveset().find(m => m.getMove().type === Type.FAIRY)), SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.SYLVEON, "partner", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => !!p.getMoveset().find(m => m.getMove().type === Type.FAIRY)), SpeciesWildEvolutionDelay.LONG), new SpeciesFormEvolution(Species.ESPEON, "", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), SpeciesWildEvolutionDelay.LONG), new SpeciesFormEvolution(Species.ESPEON, "partner", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), SpeciesWildEvolutionDelay.LONG), new SpeciesFormEvolution(Species.UMBREON, "", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), SpeciesWildEvolutionDelay.LONG), @@ -1330,13 +1330,13 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.TOGEKISS, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.AIPOM]: [ - new SpeciesEvolution(Species.AMBIPOM, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.DOUBLE_HIT).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.AMBIPOM, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.DOUBLE_HIT).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.SUNKERN]: [ new SpeciesEvolution(Species.SUNFLORA, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.YANMA]: [ - new SpeciesEvolution(Species.YANMEGA, 33, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.YANMEGA, 33, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.MURKROW]: [ new SpeciesEvolution(Species.HONCHKROW, 1, EvolutionItem.DUSK_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG) @@ -1345,17 +1345,17 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.MISMAGIUS, 1, EvolutionItem.DUSK_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.GIRAFARIG]: [ - new SpeciesEvolution(Species.FARIGIRAF, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.TWIN_BEAM).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.FARIGIRAF, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.TWIN_BEAM).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.DUNSPARCE]: [ new SpeciesFormEvolution(Species.DUDUNSPARCE, "", "three-segment", 32, null, new SpeciesEvolutionCondition(p => { let ret = false; - if (p.moveset.filter(m => m?.moveId === Moves.HYPER_DRILL).length > 0) { + if (p.moveset.filter(m => m.moveId === Moves.HYPER_DRILL).length > 0) { p.scene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); } return ret; }), SpeciesWildEvolutionDelay.LONG), - new SpeciesEvolution(Species.DUDUNSPARCE, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.HYPER_DRILL).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.DUDUNSPARCE, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.HYPER_DRILL).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.GLIGAR]: [ new SpeciesEvolution(Species.GLISCOR, 1, EvolutionItem.RAZOR_FANG, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.DUSK || p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT /* Razor fang at night*/), SpeciesWildEvolutionDelay.VERY_LONG) @@ -1367,10 +1367,10 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.URSALUNA, 1, EvolutionItem.PEAT_BLOCK, null, SpeciesWildEvolutionDelay.VERY_LONG) //Ursaring does not evolve into Bloodmoon Ursaluna ], [Species.PILOSWINE]: [ - new SpeciesEvolution(Species.MAMOSWINE, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.MAMOSWINE, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.STANTLER]: [ - new SpeciesEvolution(Species.WYRDEER, 25, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.PSYSHIELD_BASH).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.WYRDEER, 25, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.PSYSHIELD_BASH).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.LOMBRE]: [ new SpeciesEvolution(Species.LUDICOLO, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG) @@ -1388,11 +1388,11 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.ROSERADE, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.BONSLY]: [ - new SpeciesEvolution(Species.SUDOWOODO, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.MIMIC).length > 0), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.SUDOWOODO, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.MIMIC).length > 0), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.MIME_JR]: [ - new SpeciesEvolution(Species.GALAR_MR_MIME, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.MIMIC).length > 0 && (p.scene.arena.getTimeOfDay() === TimeOfDay.DUSK || p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), SpeciesWildEvolutionDelay.MEDIUM), - new SpeciesEvolution(Species.MR_MIME, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.MIMIC).length > 0 && (p.scene.arena.getTimeOfDay() === TimeOfDay.DAWN || p.scene.arena.getTimeOfDay() === TimeOfDay.DAY)), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.GALAR_MR_MIME, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.MIMIC).length > 0 && (p.scene.arena.getTimeOfDay() === TimeOfDay.DUSK || p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), SpeciesWildEvolutionDelay.MEDIUM), + new SpeciesEvolution(Species.MR_MIME, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.MIMIC).length > 0 && (p.scene.arena.getTimeOfDay() === TimeOfDay.DAWN || p.scene.arena.getTimeOfDay() === TimeOfDay.DAY)), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.PANSAGE]: [ new SpeciesEvolution(Species.SIMISAGE, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG) @@ -1447,10 +1447,10 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesFormEvolution(Species.LYCANROC, "", "midnight", 25, null, new SpeciesEvolutionCondition(p => (p.scene.arena.getTimeOfDay() === TimeOfDay.DUSK || p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT) && (p.formIndex === 0))) ], [Species.STEENEE]: [ - new SpeciesEvolution(Species.TSAREENA, 28, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.STOMP).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.TSAREENA, 28, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.STOMP).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.POIPOLE]: [ - new SpeciesEvolution(Species.NAGANADEL, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.DRAGON_PULSE).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.NAGANADEL, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.DRAGON_PULSE).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.ALOLA_SANDSHREW]: [ new SpeciesEvolution(Species.ALOLA_SANDSLASH, 1, EvolutionItem.ICE_STONE, null, SpeciesWildEvolutionDelay.LONG) @@ -1464,7 +1464,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.APPLETUN, 1, EvolutionItem.SWEET_APPLE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.CLOBBOPUS]: [ - new SpeciesEvolution(Species.GRAPPLOCT, 35, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.TAUNT).length > 0)/*Once Taunt is implemented, change evo level to 1 and delay to LONG*/) + new SpeciesEvolution(Species.GRAPPLOCT, 35, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.TAUNT).length > 0)/*Once Taunt is implemented, change evo level to 1 and delay to LONG*/) ], [Species.SINISTEA]: [ new SpeciesFormEvolution(Species.POLTEAGEIST, "phony", "phony", 1, EvolutionItem.CRACKED_POT, null, SpeciesWildEvolutionDelay.LONG), @@ -1498,7 +1498,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.HISUI_ELECTRODE, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.HISUI_QWILFISH]: [ - new SpeciesEvolution(Species.OVERQWIL, 28, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.BARB_BARRAGE).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.OVERQWIL, 28, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.BARB_BARRAGE).length > 0), SpeciesWildEvolutionDelay.LONG) ], [Species.HISUI_SNEASEL]: [ new SpeciesEvolution(Species.SNEASLER, 1, EvolutionItem.RAZOR_CLAW, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.DAWN || p.scene.arena.getTimeOfDay() === TimeOfDay.DAY /* Razor claw at day*/), SpeciesWildEvolutionDelay.VERY_LONG) @@ -1521,7 +1521,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesFormEvolution(Species.SINISTCHA, "artisan", "masterpiece", 1, EvolutionItem.MASTERPIECE_TEACUP, null, SpeciesWildEvolutionDelay.LONG) ], [Species.DIPPLIN]: [ - new SpeciesEvolution(Species.HYDRAPPLE, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.DRAGON_CHEER).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.HYDRAPPLE, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.DRAGON_CHEER).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.KADABRA]: [ new SpeciesEvolution(Species.ALAKAZAM, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG) @@ -1537,7 +1537,7 @@ export const pokemonEvolutions: PokemonEvolutions = { ], [Species.ONIX]: [ new SpeciesEvolution(Species.STEELIX, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition( - p => p.moveset.filter(m => m?.getMove().type === Type.STEEL).length > 0), + p => p.moveset.filter(m => m.getMove().type === Type.STEEL).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.RHYDON]: [ @@ -1548,7 +1548,7 @@ export const pokemonEvolutions: PokemonEvolutions = { ], [Species.SCYTHER]: [ new SpeciesEvolution(Species.SCIZOR, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition( - p => p.moveset.filter(m => m?.getMove().type === Type.STEEL).length > 0), + p => p.moveset.filter(m => m.getMove().type === Type.STEEL).length > 0), SpeciesWildEvolutionDelay.VERY_LONG), new SpeciesEvolution(Species.KLEAVOR, 1, EvolutionItem.BLACK_AUGURITE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], @@ -1602,7 +1602,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.ALOLA_GOLEM, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.PRIMEAPE]: [ - new SpeciesEvolution(Species.ANNIHILAPE, 35, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.RAGE_FIST).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.ANNIHILAPE, 35, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.RAGE_FIST).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.GOLBAT]: [ new SpeciesEvolution(Species.CROBAT, 1, null, new SpeciesFriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.VERY_LONG) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index ce25b56157c..79785bc5efd 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -965,11 +965,11 @@ export class EncoreTag extends MoveRestrictionBattlerTag { const movePhase = pokemon.scene.findPhase(m => m instanceof MovePhase && m.pokemon === pokemon); if (movePhase) { - const movesetMove = pokemon.getMoveset().find(m => m!.moveId === this.moveId); // TODO: is this bang correct? + const movesetMove = pokemon.getMoveset().find(m => m.moveId === this.moveId); if (movesetMove) { const lastMove = pokemon.getLastXMoves(1)[0]; pokemon.scene.tryReplacePhase((m => m instanceof MovePhase && m.pokemon === pokemon), - new MovePhase(pokemon.scene, pokemon, lastMove.targets!, movesetMove)); // TODO: is this bang correct? + new MovePhase(pokemon.scene, pokemon, lastMove.targets ?? [], movesetMove)); } } } @@ -980,7 +980,7 @@ export class EncoreTag extends MoveRestrictionBattlerTag { */ override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { if (lapseType === BattlerTagLapseType.CUSTOM) { - const encoredMove = pokemon.getMoveset().find(m => m?.moveId === this.moveId); + const encoredMove = pokemon.getMoveset().find(m => m.moveId === this.moveId); if (encoredMove && encoredMove?.getPpRatio() > 0) { return true; } @@ -2767,7 +2767,7 @@ export class ImprisonTag extends MoveRestrictionBattlerTag { public override isMoveRestricted(move: Moves, user: Pokemon): boolean { const source = this.getSourcePokemon(user.scene); if (source) { - const sourceMoveset = source.getMoveset().map(m => m!.moveId); + const sourceMoveset = source.getMoveset().map(m => m.moveId); return sourceMoveset?.includes(move) && source.isActive(true); } return false; @@ -2901,7 +2901,7 @@ export class GrudgeTag extends BattlerTag { if (lapseType === BattlerTagLapseType.CUSTOM && sourcePokemon) { if (sourcePokemon.isActive() && pokemon.isOpponent(sourcePokemon)) { const lastMove = pokemon.turnData.attacksReceived[0]; - const lastMoveData = sourcePokemon.getMoveset().find(m => m?.moveId === lastMove.move); + const lastMoveData = sourcePokemon.getMoveset().find(m => m.moveId === lastMove.move); if (lastMoveData && lastMove.move !== Moves.STRUGGLE) { lastMoveData.ppUsed = lastMoveData.getMovePp(); pokemon.scene.queueMessage(i18next.t("battlerTags:grudgeLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: lastMoveData.getName() })); diff --git a/src/data/berry.ts b/src/data/berry.ts index dfd6a7ddcf0..a473f3c679a 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -56,7 +56,7 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate { return (pokemon: Pokemon) => { const threshold = new Utils.NumberHolder(0.25); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); - return !!pokemon.getMoveset().find(m => !m?.getPpRatio()); + return !!pokemon.getMoveset().find(m => !m.getPpRatio()); }; } } @@ -129,7 +129,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { if (pokemon.battleData) { pokemon.battleData.berriesEaten.push(berryType); } - const ppRestoreMove = pokemon.getMoveset().find(m => !m?.getPpRatio()) ? pokemon.getMoveset().find(m => !m?.getPpRatio()) : pokemon.getMoveset().find(m => m!.getPpRatio() < 1); // TODO: is this bang correct? + const ppRestoreMove = pokemon.getMoveset().find(m => !m.getPpRatio()) ? pokemon.getMoveset().find(m => !m.getPpRatio()) : pokemon.getMoveset().find(m => m.getPpRatio() < 1); if (ppRestoreMove !== undefined) { ppRestoreMove!.ppUsed = Math.max(ppRestoreMove!.ppUsed - 10, 0); pokemon.scene.queueMessage(i18next.t("battle:ppHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: ppRestoreMove!.getName(), berryName: getBerryName(berryType) })); diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 4301ea7b375..7a758824c3a 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -437,7 +437,7 @@ export class SingleGenerationChallenge extends Challenge { applyPokemonInBattle(pokemon: Pokemon, valid: Utils.BooleanHolder): boolean { const baseGeneration = pokemon.species.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.species.speciesId).generation; - const fusionGeneration = pokemon.isFusion() ? pokemon.fusionSpecies?.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.fusionSpecies!.speciesId).generation : 0; // TODO: is the bang on fusionSpecies correct? + const fusionGeneration = pokemon.isFusion() ? pokemon.fusionSpecies?.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.fusionSpecies?.speciesId).generation : 0; if (pokemon.isPlayer() && (baseGeneration !== this.value || (pokemon.isFusion() && fusionGeneration !== this.value))) { valid.value = false; return true; diff --git a/src/data/move.ts b/src/data/move.ts index 2ac4d74b712..1cce069ef5c 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1772,14 +1772,14 @@ export class HealAttr extends MoveEffectAttr { */ export class PartyStatusCureAttr extends MoveEffectAttr { /** Message to display after using move */ - private message: string; + private message: string | null; /** Skips mons with this ability, ie. Soundproof */ private abilityCondition: Abilities; constructor(message: string | null, abilityCondition: Abilities) { super(); - this.message = message!; // TODO: is this bang correct? + this.message = message; this.abilityCondition = abilityCondition; } @@ -1977,10 +1977,10 @@ export class BoostHealAttr extends HealAttr { /** The lambda expression to check against when boosting the healing value */ private condition?: MoveConditionFunc; - constructor(normalHealRatio?: number, boostedHealRatio?: number, showAnim?: boolean, selfTarget?: boolean, condition?: MoveConditionFunc) { + constructor(normalHealRatio: number = 0.5, boostedHealRatio: number = 2 / 3, showAnim?: boolean, selfTarget?: boolean, condition?: MoveConditionFunc) { super(normalHealRatio, showAnim, selfTarget); - this.normalHealRatio = normalHealRatio!; // TODO: is this bang correct? - this.boostedHealRatio = boostedHealRatio!; // TODO: is this bang correct? + this.normalHealRatio = normalHealRatio; + this.boostedHealRatio = boostedHealRatio; this.condition = condition; } @@ -3214,14 +3214,14 @@ export class SecretPowerAttr extends MoveEffectAttr { export class PostVictoryStatStageChangeAttr extends MoveAttr { private stats: BattleStat[]; private stages: number; - private condition: MoveConditionFunc | null; + private condition?: MoveConditionFunc; private showMessage: boolean; constructor(stats: BattleStat[], stages: number, selfTarget?: boolean, condition?: MoveConditionFunc, showMessage: boolean = true, firstHitOnly: boolean = false) { super(); this.stats = stats; this.stages = stages; - this.condition = condition!; // TODO: is this bang correct? + this.condition = condition; this.showMessage = showMessage; } applyPostVictory(user: Pokemon, target: Pokemon, move: Move): void { @@ -3513,7 +3513,7 @@ export class LessPPMorePowerAttr extends VariablePowerAttr { */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const ppMax = move.pp; - const ppUsed = user.moveset.find((m) => m?.moveId === move.id)?.ppUsed!; // TODO: is the bang correct? + const ppUsed = user.moveset.find((m) => m.moveId === move.id)?.ppUsed ?? 0; let ppRemains = ppMax - ppUsed; /** Reduce to 0 to avoid negative numbers if user has 1PP before attack and target has Ability.PRESSURE */ @@ -3639,7 +3639,13 @@ export abstract class ConsecutiveUsePowerMultiplierAttr extends MovePowerMultipl let count = 0; let turnMove: TurnMove | undefined; - while (((turnMove = moveHistory.shift())?.move === move.id || (comboMoves.length && comboMoves.includes(turnMove?.move!))) && (!resetOnFail || turnMove?.result === MoveResult.SUCCESS)) { // TODO: is this bang correct? + while ( + ( + (turnMove = moveHistory.shift())?.move === move.id + || (comboMoves.length && comboMoves.includes(turnMove?.move ?? Moves.NONE)) + ) + && (!resetOnFail || turnMove?.result === MoveResult.SUCCESS) + ) { if (count < (limit - 1)) { count++; } else if (resetOnLimit) { @@ -5237,7 +5243,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { : null; } - getTagTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer | void { + getTagTargetBenefitScore(): number { switch (this.tagType) { case BattlerTagType.RECHARGING: case BattlerTagType.PERISH_SONG: @@ -5281,6 +5287,9 @@ export class AddBattlerTagAttr extends MoveEffectAttr { case BattlerTagType.CRIT_BOOST: case BattlerTagType.ALWAYS_CRIT: return 5; + default: + console.warn(`BattlerTag ${BattlerTagType[this.tagType]} is missing a score!`); + return 0; } } @@ -5289,7 +5298,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { if (moveChance < 0) { moveChance = 100; } - return Math.floor(this.getTagTargetBenefitScore(user, target, move)! * (moveChance / 100)); // TODO: is the bang correct? + return Math.floor(this.getTagTargetBenefitScore() * (moveChance / 100)); } } @@ -5519,7 +5528,7 @@ export class ProtectAttr extends AddBattlerTagAttr { while (moveHistory.length) { turnMove = moveHistory.shift(); - if (!allMoves[turnMove?.move!].hasAttr(ProtectAttr) || turnMove?.result !== MoveResult.SUCCESS) { // TODO: is the bang correct? + if (!allMoves[turnMove?.move ?? Moves.NONE].hasAttr(ProtectAttr) || turnMove?.result !== MoveResult.SUCCESS) { break; } timesUsed++; @@ -6370,7 +6379,7 @@ export class FirstMoveTypeAttr extends MoveEffectAttr { return false; } - const firstMoveType = target.getMoveset()[0]?.getMove().type!; // TODO: is this bang correct? + const firstMoveType = target.getMoveset()[0].getMove().type; user.summonData.types = [ firstMoveType ]; user.scene.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: i18next.t(`pokemonInfo:Type.${Type[firstMoveType]}`) })); @@ -6389,11 +6398,11 @@ export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const moveset = (!this.enemyMoveset ? user : target).getMoveset(); - const moves = moveset.filter(m => !m?.getMove().hasFlag(MoveFlags.IGNORE_VIRTUAL)); + const moves = moveset.filter(m => !m.getMove().hasFlag(MoveFlags.IGNORE_VIRTUAL)); if (moves.length) { const move = moves[user.randSeedInt(moves.length)]; - const moveIndex = moveset.findIndex(m => m?.moveId === move?.moveId); - const moveTargets = getMoveTargets(user, move?.moveId!); // TODO: is this bang correct? + const moveIndex = moveset.findIndex(m => m.moveId === move?.moveId); + const moveTargets = getMoveTargets(user, move.moveId); if (!moveTargets.targets.length) { return false; } @@ -6414,8 +6423,8 @@ export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr { } } const targets = selectTargets; - user.getMoveQueue().push({ move: move?.moveId!, targets: targets, ignorePP: true }); // TODO: is this bang correct? - user.scene.unshiftPhase(new MovePhase(user.scene, user, targets, moveset[moveIndex]!, true)); // There's a PR to re-do the move(s) that use this Attr, gonna put `!` for now + user.getMoveQueue().push({ move: move.moveId, targets: targets, ignorePP: true }); + user.scene.unshiftPhase(new MovePhase(user.scene, user, targets, moveset[moveIndex], true)); return true; } @@ -6657,19 +6666,19 @@ export class ReducePpMoveAttr extends MoveEffectAttr { * * @param user {@linkcode Pokemon} that used the attack * @param target {@linkcode Pokemon} targeted by the attack - * @param move {@linkcode Move} being used + * @param move N/A * @param args N/A - * @returns {boolean} true + * @returns `true` */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { // Null checks can be skipped due to condition function - const lastMove = target.getLastXMoves().find(() => true); - const movesetMove = target.getMoveset().find(m => m?.moveId === lastMove?.move); - const lastPpUsed = movesetMove?.ppUsed!; // TODO: is the bang correct? - movesetMove!.ppUsed = Math.min((movesetMove?.ppUsed!) + this.reduction, movesetMove?.getMovePp()!); // TODO: is the bang correct? + const lastMove = target.getLastXMoves()[0]; + const movesetMove = target.getMoveset().find(m => m.moveId === lastMove.move)!; + const lastPpUsed = movesetMove.ppUsed; + movesetMove.ppUsed = Math.min((lastPpUsed) + this.reduction, movesetMove.getMovePp()); - const message = i18next.t("battle:ppReduced", { targetName: getPokemonNameWithAffix(target), moveName: movesetMove?.getName(), reduction: (movesetMove?.ppUsed!) - lastPpUsed }); // TODO: is the bang correct? - user.scene.eventTarget.dispatchEvent(new MoveUsedEvent(target?.id, movesetMove?.getMove()!, movesetMove?.ppUsed!)); // TODO: are these bangs correct? + const message = i18next.t("battle:ppReduced", { targetName: getPokemonNameWithAffix(target), moveName: movesetMove.getName(), reduction: (movesetMove.ppUsed) - lastPpUsed }); + user.scene.eventTarget.dispatchEvent(new MoveUsedEvent(target.id, movesetMove.getMove(), movesetMove.ppUsed)); user.scene.queueMessage(message); return true; @@ -6677,9 +6686,9 @@ export class ReducePpMoveAttr extends MoveEffectAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { - const lastMove = target.getLastXMoves().find(() => true); + const lastMove = target.getLastXMoves()[0]; if (lastMove) { - const movesetMove = target.getMoveset().find(m => m?.moveId === lastMove.move); + const movesetMove = target.getMoveset().find(m => m.moveId === lastMove.move); return !!movesetMove?.getPpRatio(); } return false; @@ -6687,9 +6696,9 @@ export class ReducePpMoveAttr extends MoveEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { - const lastMove = target.getLastXMoves().find(() => true); + const lastMove = target.getLastXMoves()[0]; if (lastMove) { - const movesetMove = target.getMoveset().find(m => m?.moveId === lastMove.move); + const movesetMove = target.getMoveset().find(m => m.moveId === lastMove.move); if (movesetMove) { const maxPp = movesetMove.getMovePp(); const ppLeft = maxPp - movesetMove.ppUsed; @@ -6726,7 +6735,7 @@ export class AttackReducePpMoveAttr extends ReducePpMoveAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const lastMove = target.getLastXMoves().find(() => true); if (lastMove) { - const movesetMove = target.getMoveset().find(m => m?.moveId === lastMove.move); + const movesetMove = target.getMoveset().find(m => m.moveId === lastMove.move); if (Boolean(movesetMove?.getPpRatio())) { super.apply(user, target, move, args); } @@ -6772,7 +6781,7 @@ export class MovesetCopyMoveAttr extends OverrideMoveEffectAttr { const copiedMove = allMoves[targetMoves[0].move]; - const thisMoveIndex = user.getMoveset().findIndex(m => m?.moveId === move.id); + const thisMoveIndex = user.getMoveset().findIndex(m => m.moveId === move.id); if (thisMoveIndex === -1) { return false; @@ -6824,7 +6833,7 @@ export class SketchAttr extends MoveEffectAttr { } const sketchedMove = allMoves[targetMove.move]; - const sketchIndex = user.getMoveset().findIndex(m => m?.moveId === move.id); + const sketchIndex = user.getMoveset().findIndex(m => m.moveId === move.id); if (sketchIndex === -1) { return false; } @@ -6863,7 +6872,7 @@ export class SketchAttr extends MoveEffectAttr { return false; } - if (user.getMoveset().find(m => m?.moveId === targetMove.move)) { + if (user.getMoveset().find(m => m.moveId === targetMove.move)) { return false; } @@ -7347,7 +7356,7 @@ export class LastResortAttr extends MoveAttr { getCondition(): MoveConditionFunc { return (user: Pokemon, target: Pokemon, move: Move) => { const uniqueUsedMoveIds = new Set(); - const movesetMoveIds = user.getMoveset().map(m => m?.moveId); + const movesetMoveIds = user.getMoveset().map(m => m.moveId); user.getMoveHistory().map(m => { if (m.move !== move.id && movesetMoveIds.find(mm => mm === m.move)) { uniqueUsedMoveIds.add(m.move); @@ -8649,7 +8658,17 @@ export function initMoves() { .attr(FlinchAttr), new AttackMove(Moves.WEATHER_BALL, Type.NORMAL, MoveCategory.SPECIAL, 50, 100, 10, -1, 0, 3) .attr(WeatherBallTypeAttr) - .attr(MovePowerMultiplierAttr, (user, target, move) => [ WeatherType.SUNNY, WeatherType.RAIN, WeatherType.SANDSTORM, WeatherType.HAIL, WeatherType.SNOW, WeatherType.FOG, WeatherType.HEAVY_RAIN, WeatherType.HARSH_SUN ].includes(user.scene.arena.weather?.weatherType!) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 2 : 1) // TODO: is this bang correct? + .attr(MovePowerMultiplierAttr, (user, target, move) => { + const weather = user.scene.arena.weather; + if (!weather) { + return 1; + } + const weatherTypes = [ WeatherType.SUNNY, WeatherType.RAIN, WeatherType.SANDSTORM, WeatherType.HAIL, WeatherType.SNOW, WeatherType.FOG, WeatherType.HEAVY_RAIN, WeatherType.HARSH_SUN ]; + if (weatherTypes.includes(weather.weatherType) && !weather.isEffectSuppressed(user.scene)) { + return 2; + } + return 1; + }) .ballBombMove(), new StatusMove(Moves.AROMATHERAPY, Type.GRASS, -1, 5, -1, 0, 3) .attr(PartyStatusCureAttr, i18next.t("moveTriggers:soothingAromaWaftedThroughArea"), Abilities.SAP_SIPPER) @@ -8879,7 +8898,13 @@ export function initMoves() { new StatusMove(Moves.WORRY_SEED, Type.GRASS, 100, 10, -1, 0, 4) .attr(AbilityChangeAttr, Abilities.INSOMNIA), new AttackMove(Moves.SUCKER_PUNCH, Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, 1, 4) - .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].category !== MoveCategory.STATUS), // TODO: is this bang correct? + .condition((user, target, move) => { + const turnCommand = user.scene.currentBattle.turnCommands[target.getBattlerIndex()]; + if (!turnCommand || !turnCommand.move) { + return false; + } + return (turnCommand.command === Command.FIGHT && !target.turnData.acted && allMoves[turnCommand.move.move].category !== MoveCategory.STATUS); + }), new StatusMove(Moves.TOXIC_SPIKES, Type.POISON, -1, 20, -1, 0, 4) .attr(AddArenaTrapTagAttr, ArenaTagType.TOXIC_SPIKES) .target(MoveTarget.ENEMY_SIDE), @@ -9788,8 +9813,12 @@ export function initMoves() { .ignoresSubstitute(), new AttackMove(Moves.SMART_STRIKE, Type.STEEL, MoveCategory.PHYSICAL, 70, -1, 10, -1, 0, 7), new StatusMove(Moves.PURIFY, Type.POISON, -1, 20, -1, 0, 7) - .condition( - (user: Pokemon, target: Pokemon, move: Move) => isNonVolatileStatusEffect(target.status?.effect!)) // TODO: is this bang correct? + .condition((user, target, move) => { + if (!target.status) { + return false; + } + return isNonVolatileStatusEffect(target.status.effect); + }) .attr(HealAttr, 0.5) .attr(HealStatusEffectAttr, false, getNonVolatileStatusEffects()) .triageMove(), @@ -10521,7 +10550,13 @@ export function initMoves() { .slicingMove(), new AttackMove(Moves.HYDRO_STEAM, Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 9) .attr(IgnoreWeatherTypeDebuffAttr, WeatherType.SUNNY) - .attr(MovePowerMultiplierAttr, (user, target, move) => [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(user.scene.arena.weather?.weatherType!) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 1.5 : 1), // TODO: is this bang correct? + .attr(MovePowerMultiplierAttr, (user, target, move) => { + const weather = user.scene.arena.weather; + if (!weather) { + return 1; + } + return [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(weather.weatherType) && !weather.isEffectSuppressed(user.scene) ? 1.5 : 1; + }), new AttackMove(Moves.RUINATION, Type.DARK, MoveCategory.SPECIAL, -1, 90, 10, -1, 0, 9) .attr(TargetHalfHpDamageAttr), new AttackMove(Moves.COLLISION_COURSE, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9) @@ -10636,7 +10671,13 @@ export function initMoves() { .attr(ProtectAttr, BattlerTagType.BURNING_BULWARK) .condition(failIfLastCondition), new AttackMove(Moves.THUNDERCLAP, Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 5, -1, 1, 9) - .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].category !== MoveCategory.STATUS), // TODO: is this bang correct? + .condition((user, target, move) => { + const turnCommand = user.scene.currentBattle.turnCommands[target.getBattlerIndex()]; + if (!turnCommand || !turnCommand.move) { + return false; + } + return (turnCommand.command === Command.FIGHT && !target.turnData.acted && allMoves[turnCommand.move.move].category !== MoveCategory.STATUS); + }), new AttackMove(Moves.MIGHTY_CLEAVE, Type.ROCK, MoveCategory.PHYSICAL, 95, 100, 5, -1, 0, 9) .slicingMove() .ignoresProtect(), diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index 2d569621449..7985c625fb5 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -264,7 +264,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = if (eggMoves) { // Cannot gen the rare egg move, only 1 of the first 3 common moves const eggMove = eggMoves[randSeedInt(3)]; - if (!tradePokemon.moveset.some(m => m?.moveId === eggMove)) { + if (!tradePokemon.moveset.some(m => m.moveId === eggMove)) { if (tradePokemon.moveset.length < 4) { tradePokemon.moveset.push(new PokemonMove(eggMove)); } else { diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index 3d2e8493d44..10e5ec6c32d 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -694,7 +694,7 @@ async function addEggMoveToNewPokemonMoveset(scene: BattleScene, newPokemon: Pla let randomEggMoveIndex = eggMoveIndices.pop(); let randomEggMove = !isNullOrUndefined(randomEggMoveIndex) ? eggMoves[randomEggMoveIndex] : null; let retries = 0; - while (retries < 3 && (!randomEggMove || newPokemon.moveset.some(m => m?.moveId === randomEggMove))) { + while (retries < 3 && (!randomEggMove || newPokemon.moveset.some(m => m.moveId === randomEggMove))) { // If Pokemon already knows this move, roll for another egg move randomEggMoveIndex = eggMoveIndices.pop(); randomEggMove = !isNullOrUndefined(randomEggMoveIndex) ? eggMoves[randomEggMoveIndex] : null; @@ -702,7 +702,7 @@ async function addEggMoveToNewPokemonMoveset(scene: BattleScene, newPokemon: Pla } if (randomEggMove) { - if (!newPokemon.moveset.some(m => m?.moveId === randomEggMove)) { + if (!newPokemon.moveset.some(m => m.moveId === randomEggMove)) { if (newPokemon.moveset.length < 4) { newPokemon.moveset.push(new PokemonMove(randomEggMove)); } else { @@ -731,7 +731,7 @@ function addFavoredMoveToNewPokemonMoveset(newPokemon: PlayerPokemon, newPokemon let favoredMove: PokemonMove | null = null; for (const move of newPokemonGeneratedMoveset) { // Needs to match first type, second type will be replaced - if (move?.getMove().type === newPokemon.getTypes()[0] && !newPokemon.moveset.some(m => m?.moveId === move?.moveId)) { + if (move?.getMove().type === newPokemon.getTypes()[0] && !newPokemon.moveset.some(m => m.moveId === move?.moveId)) { favoredMove = move; break; } @@ -741,7 +741,7 @@ function addFavoredMoveToNewPokemonMoveset(newPokemon: PlayerPokemon, newPokemon if (!favoredMove) { for (const move of newPokemonGeneratedMoveset) { // Needs to match first type, second type will be replaced - if (!newPokemon.moveset.some(m => m?.moveId === move?.moveId)) { + if (!newPokemon.moveset.some(m => m.moveId === move?.moveId)) { favoredMove = move; break; } diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index 811b622de76..1a872d2ad8c 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -603,15 +603,15 @@ export class CompatibleMoveRequirement extends EncounterPokemonRequirement { override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] { if (!this.invertQuery) { - return partyPokemon.filter((pokemon) => this.requiredMoves.filter((learnableMove) => pokemon.compatibleTms.filter(tm => !pokemon.moveset.find(m => m?.moveId === tm)).includes(learnableMove)).length > 0); + return partyPokemon.filter((pokemon) => this.requiredMoves.filter((learnableMove) => pokemon.compatibleTms.filter(tm => !pokemon.moveset.find(m => m.moveId === tm)).includes(learnableMove)).length > 0); } else { // for an inverted query, we only want to get the pokemon that don't have ANY of the listed learnableMoves - return partyPokemon.filter((pokemon) => this.requiredMoves.filter((learnableMove) => pokemon.compatibleTms.filter(tm => !pokemon.moveset.find(m => m?.moveId === tm)).includes(learnableMove)).length === 0); + return partyPokemon.filter((pokemon) => this.requiredMoves.filter((learnableMove) => pokemon.compatibleTms.filter(tm => !pokemon.moveset.find(m => m.moveId === tm)).includes(learnableMove)).length === 0); } } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - const includedCompatMoves = this.requiredMoves.filter((reqMove) => pokemon?.compatibleTms.filter((tm) => !pokemon.moveset.find(m => m?.moveId === tm)).includes(reqMove)); + const includedCompatMoves = this.requiredMoves.filter((reqMove) => pokemon?.compatibleTms.filter((tm) => !pokemon.moveset.find(m => m.moveId === tm)).includes(reqMove)); if (includedCompatMoves.length > 0) { return [ "compatibleMove", Moves[includedCompatMoves[0]] ]; } diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 2db0ed54294..29f088bb36b 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -318,7 +318,7 @@ export class SpeciesFormChangeMoveLearnedTrigger extends SpeciesFormChangeTrigge } canChange(pokemon: Pokemon): boolean { - return (!!pokemon.moveset.filter(m => m?.moveId === this.move).length) === this.known; + return (!!pokemon.moveset.filter(m => m.moveId === this.move).length) === this.known; } } diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index ec104d4d4aa..e76412f8395 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -2784,23 +2784,3 @@ export function initSpecies() { new PokemonSpecies(Species.BLOODMOON_URSALUNA, 9, true, false, false, "Peat Pokémon", Type.GROUND, Type.NORMAL, 2.7, 333, Abilities.MINDS_EYE, Abilities.NONE, Abilities.NONE, 555, 113, 70, 120, 135, 65, 52, 75, 50, 275, GrowthRate.MEDIUM_FAST, 50, false), //Marked as Sub-Legend, for casing purposes ); } - -// TODO: Remove -{ - //setTimeout(() => { - /*for (let tc of Object.keys(trainerConfigs)) { - console.log(TrainerType[tc], !trainerConfigs[tc].speciesFilter ? 'all' : [...new Set(allSpecies.filter(s => s.generation <= 9).filter(trainerConfigs[tc].speciesFilter).map(s => { - while (pokemonPrevolutions.hasOwnProperty(s.speciesId)) - s = getPokemonSpecies(pokemonPrevolutions[s.speciesId]); - return s; - }))].map(s => s.name)); - } - - const speciesFilter = (species: PokemonSpecies) => !species.legendary && !species.pseudoLegendary && !species.mythical && species.baseTotal >= 540; - console.log(!speciesFilter ? 'all' : [...new Set(allSpecies.filter(s => s.generation <= 9).filter(speciesFilter).map(s => { - while (pokemonPrevolutions.hasOwnProperty(s.speciesId)) - s = getPokemonSpecies(pokemonPrevolutions[s.speciesId]); - return s; - }))].map(s => s.name));*/ - //}, 1000); -} diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 8b13b462469..9d6df6835de 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -418,7 +418,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { loadAssets(ignoreOverride: boolean = true): Promise { return new Promise(resolve => { - const moveIds = this.getMoveset().map(m => m!.getMove().id); // TODO: is this bang correct? + const moveIds = this.getMoveset().map(m => m.getMove().id); Promise.allSettled(moveIds.map(m => initMoveAnim(this.scene, m))) .then(() => { loadMoveAnimAssets(this.scene, moveIds); @@ -1231,7 +1231,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (Array.isArray(this.usedTMs) && this.usedTMs.length > 0) { levelMoves = this.usedTMs.filter(m => !levelMoves.includes(m)).concat(levelMoves); } - levelMoves = levelMoves.filter(lm => !this.moveset.some(m => m?.moveId === lm)); + levelMoves = levelMoves.filter(lm => !this.moveset.some(m => m.moveId === lm)); return levelMoves; } @@ -4639,10 +4639,7 @@ export class PlayerPokemon extends Pokemon { copyMoveset(): PokemonMove[] { const newMoveset : PokemonMove[] = []; this.moveset.forEach((move) => { - // TODO: refactor `moveset` to not accept `null`s - if (move) { - newMoveset.push(new PokemonMove(move.moveId, 0, move.ppUp, move.virtual, move.maxPpOverride)); - } + newMoveset.push(new PokemonMove(move.moveId, 0, move.ppUp, move.virtual, move.maxPpOverride)); }); return newMoveset; @@ -4788,7 +4785,7 @@ export class EnemyPokemon extends Pokemon { getNextMove(): QueuedMove { // If this Pokemon has a move already queued, return it. const queuedMove = this.getMoveQueue().length - ? this.getMoveset().find(m => m?.moveId === this.getMoveQueue()[0].move) + ? this.getMoveset().find(m => m.moveId === this.getMoveQueue()[0].move) : null; if (queuedMove) { if (queuedMove.isUsable(this, this.getMoveQueue()[0].ignorePP)) { @@ -4800,24 +4797,24 @@ export class EnemyPokemon extends Pokemon { } // Filter out any moves this Pokemon cannot use - let movePool = this.getMoveset().filter(m => m?.isUsable(this)); + let movePool = this.getMoveset().filter(m => m.isUsable(this)); // If no moves are left, use Struggle. Otherwise, continue with move selection if (movePool.length) { // If there's only 1 move in the move pool, use it. if (movePool.length === 1) { - return { move: movePool[0]!.moveId, targets: this.getNextTargets(movePool[0]!.moveId) }; // TODO: are the bangs correct? + return { move: movePool[0].moveId, targets: this.getNextTargets(movePool[0].moveId) }; } // If a move is forced because of Encore, use it. const encoreTag = this.getTag(EncoreTag) as EncoreTag; if (encoreTag) { - const encoreMove = movePool.find(m => m?.moveId === encoreTag.moveId); + const encoreMove = movePool.find(m => m.moveId === encoreTag.moveId); if (encoreMove) { return { move: encoreMove.moveId, targets: this.getNextTargets(encoreMove.moveId) }; } } switch (this.aiType) { case AiType.RANDOM: // No enemy should spawn with this AI type in-game - const moveId = movePool[this.scene.randBattleSeedInt(movePool.length)]!.moveId; // TODO: is the bang correct? + const moveId = movePool[this.scene.randBattleSeedInt(movePool.length)].moveId; return { move: moveId, targets: this.getNextTargets(moveId) }; case AiType.SMART_RANDOM: case AiType.SMART: @@ -4860,9 +4857,9 @@ export class EnemyPokemon extends Pokemon { * For more information on how benefit scores are calculated, see `docs/enemy-ai.md`. */ const moveScores = movePool.map(() => 0); - const moveTargets = Object.fromEntries(movePool.map(m => [ m!.moveId, this.getNextTargets(m!.moveId) ])); // TODO: are those bangs correct? + const moveTargets = Object.fromEntries(movePool.map(m => [ m.moveId, this.getNextTargets(m.moveId) ])); for (const m in movePool) { - const pokemonMove = movePool[m]!; // TODO: is the bang correct? + const pokemonMove = movePool[m]; const move = pokemonMove.getMove(); let moveScore = moveScores[m]; @@ -4943,7 +4940,7 @@ export class EnemyPokemon extends Pokemon { r++; } } - console.log(movePool.map(m => m!.getName()), moveScores, r, sortedMovePool.map(m => m!.getName())); // TODO: are those bangs correct? + console.log(movePool.map(m => m.getName()), moveScores, r, sortedMovePool.map(m => m.getName())); return { move: sortedMovePool[r]!.moveId, targets: moveTargets[sortedMovePool[r]!.moveId] }; } } diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 4986c1feab1..740aa530a0f 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -383,7 +383,7 @@ export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType { constructor(localeKey: string, iconImage: string, restorePoints: integer) { super(localeKey, iconImage, (_type, args) => new PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints), (pokemon: PlayerPokemon) => { - if (!pokemon.getMoveset().filter(m => m?.ppUsed).length) { + if (!pokemon.getMoveset().filter(m => m.ppUsed).length) { return PartyUiHandler.NoEffectMessage; } return null; @@ -810,7 +810,7 @@ export class TmModifierType extends PokemonModifierType { constructor(moveId: Moves) { super("", `tm_${Type[allMoves[moveId].type].toLowerCase()}`, (_type, args) => new TmModifier(this, (args[0] as PlayerPokemon).id), (pokemon: PlayerPokemon) => { - if (pokemon.compatibleTms.indexOf(moveId) === -1 || pokemon.getMoveset().filter(m => m?.moveId === moveId).length) { + if (pokemon.compatibleTms.indexOf(moveId) === -1 || pokemon.getMoveset().filter(m => m.moveId === moveId).length) { return PartyUiHandler.NoEffectMessage; } return null; @@ -926,7 +926,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator { return new AttackTypeBoosterModifierType(pregenArgs[0] as Type, 20); } - const attackMoveTypes = party.map(p => p.getMoveset().map(m => m?.getMove()).filter(m => m instanceof AttackMove).map(m => m.type)).flat(); + const attackMoveTypes = party.map(p => p.getMoveset().map(m => m.getMove()).filter(m => m instanceof AttackMove).map(m => m.type)).flat(); if (!attackMoveTypes.length) { return null; } @@ -1040,7 +1040,7 @@ class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator { for (const p of party) { const speciesId = p.getSpeciesForm(true).speciesId; const fusionSpeciesId = p.isFusion() ? p.getFusionSpeciesForm(true).speciesId : null; - const hasFling = p.getMoveset(true).some(m => m?.moveId === Moves.FLING); + const hasFling = p.getMoveset(true).some(m => m.moveId === Moves.FLING); for (const i in values) { const checkedSpecies = values[i].species; @@ -1093,7 +1093,7 @@ class TmModifierTypeGenerator extends ModifierTypeGenerator { if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in Moves)) { return new TmModifierType(pregenArgs[0] as Moves); } - const partyMemberCompatibleTms = party.map(p => (p as PlayerPokemon).compatibleTms.filter(tm => !p.moveset.find(m => m?.moveId === tm))); + const partyMemberCompatibleTms = party.map(p => (p as PlayerPokemon).compatibleTms.filter(tm => !p.moveset.find(m => m.moveId === tm))); const tierUniqueCompatibleTms = partyMemberCompatibleTms.flat().filter(tm => tmPoolTiers[tm] === tier).filter(tm => !allMoves[tm].name.endsWith(" (N)")).filter((tm, i, array) => array.indexOf(tm) === i); if (!tierUniqueCompatibleTms.length) { return null; @@ -1630,12 +1630,12 @@ const modifierPool: ModifierPool = { }, 3), new WeightedModifierType(modifierTypes.ETHER, (party: Pokemon[]) => { const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && !p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) - && p.getMoveset().filter(m => m?.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2)).length).length, 3); + && p.getMoveset().filter(m => m.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2)).length).length, 3); return thresholdPartyMemberCount * 3; }, 9), new WeightedModifierType(modifierTypes.MAX_ETHER, (party: Pokemon[]) => { const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && !p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) - && p.getMoveset().filter(m => m?.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2)).length).length, 3); + && p.getMoveset().filter(m => m.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2)).length).length, 3); return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.LURE, lureWeightFunc(10, 2)), @@ -1688,12 +1688,12 @@ const modifierPool: ModifierPool = { }, 3), new WeightedModifierType(modifierTypes.ELIXIR, (party: Pokemon[]) => { const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && !p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) - && p.getMoveset().filter(m => m?.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2)).length).length, 3); + && p.getMoveset().filter(m => m.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2)).length).length, 3); return thresholdPartyMemberCount * 3; }, 9), new WeightedModifierType(modifierTypes.MAX_ELIXIR, (party: Pokemon[]) => { const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && !p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) - && p.getMoveset().filter(m => m?.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2)).length).length, 3); + && p.getMoveset().filter(m => m.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2)).length).length, 3); return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.DIRE_HIT, 4), diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index eab76282908..3d0240916fe 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -76,8 +76,8 @@ export class CommandPhase extends FieldPhase { const moveQueue = playerPokemon.getMoveQueue(); while (moveQueue.length && moveQueue[0] - && moveQueue[0].move && (!playerPokemon.getMoveset().find(m => m?.moveId === moveQueue[0].move) - || !playerPokemon.getMoveset()[playerPokemon.getMoveset().findIndex(m => m?.moveId === moveQueue[0].move)]!.isUsable(playerPokemon, moveQueue[0].ignorePP))) { // TODO: is the bang correct? + && moveQueue[0].move && (!playerPokemon.getMoveset().find(m => m.moveId === moveQueue[0].move) + || !playerPokemon.getMoveset()[playerPokemon.getMoveset().findIndex(m => m.moveId === moveQueue[0].move)].isUsable(playerPokemon, moveQueue[0].ignorePP))) { moveQueue.shift(); } @@ -86,8 +86,8 @@ export class CommandPhase extends FieldPhase { if (!queuedMove.move) { this.handleCommand(Command.FIGHT, -1, false); } else { - const moveIndex = playerPokemon.getMoveset().findIndex(m => m?.moveId === queuedMove.move); - if (moveIndex > -1 && playerPokemon.getMoveset()[moveIndex]!.isUsable(playerPokemon, queuedMove.ignorePP)) { // TODO: is the bang correct? + const moveIndex = playerPokemon.getMoveset().findIndex(m => m.moveId === queuedMove.move); + if (moveIndex > -1 && playerPokemon.getMoveset()[moveIndex].isUsable(playerPokemon, queuedMove.ignorePP)) { this.handleCommand(Command.FIGHT, moveIndex, queuedMove.ignorePP, { targets: queuedMove.targets, multiple: queuedMove.targets.length > 1 }); } else { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); @@ -112,8 +112,8 @@ export class CommandPhase extends FieldPhase { let useStruggle = false; if (cursor === -1 || playerPokemon.trySelectMove(cursor, args[0] as boolean) || - (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m?.isUsable(playerPokemon)).length)) { - const moveId = !useStruggle ? cursor > -1 ? playerPokemon.getMoveset()[cursor]!.moveId : Moves.NONE : Moves.STRUGGLE; // TODO: is the bang correct? + (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)) { + const moveId = !useStruggle ? cursor > -1 ? playerPokemon.getMoveset()[cursor].moveId : Moves.NONE : Moves.STRUGGLE; const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args }; const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, moveId) : args[2]; if (!moveId) { @@ -123,17 +123,17 @@ export class CommandPhase extends FieldPhase { if (moveTargets.targets.length > 1 && moveTargets.multiple) { this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); } - if (moveTargets.targets.length <= 1 || moveTargets.multiple) { - turnCommand.move!.targets = moveTargets.targets; //TODO: is the bang correct here? - } else if (playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1) { - turnCommand.move!.targets = playerPokemon.getMoveQueue()[0].targets; //TODO: is the bang correct here? + if (turnCommand.move && (moveTargets.targets.length <= 1 || moveTargets.multiple)) { + turnCommand.move.targets = moveTargets.targets; + } else if (turnCommand.move && playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1) { + turnCommand.move.targets = playerPokemon.getMoveQueue()[0].targets; } else { this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); } this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand; success = true; } else if (cursor < playerPokemon.getMoveset().length) { - const move = playerPokemon.getMoveset()[cursor]!; //TODO: is this bang correct? + const move = playerPokemon.getMoveset()[cursor]; this.scene.ui.setMode(Mode.MESSAGE); // Decides between a Disabled, Not Implemented, or No PP translation message diff --git a/src/phases/learn-move-phase.ts b/src/phases/learn-move-phase.ts index fefda384092..679c391f9b6 100644 --- a/src/phases/learn-move-phase.ts +++ b/src/phases/learn-move-phase.ts @@ -43,7 +43,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { const currentMoveset = pokemon.getMoveset(); // The game first checks if the Pokemon already has the move and ends the phase if it does. - const hasMoveAlready = currentMoveset.some(m => m?.moveId === move.id) && this.moveId !== Moves.SKETCH; + const hasMoveAlready = currentMoveset.some(m => m.moveId === move.id) && this.moveId !== Moves.SKETCH; if (hasMoveAlready) { return this.end(); } diff --git a/src/phases/party-heal-phase.ts b/src/phases/party-heal-phase.ts index 4841bf9a5b4..2478882847e 100644 --- a/src/phases/party-heal-phase.ts +++ b/src/phases/party-heal-phase.ts @@ -23,7 +23,7 @@ export class PartyHealPhase extends BattlePhase { pokemon.hp = pokemon.getMaxHp(); pokemon.resetStatus(); for (const move of pokemon.moveset) { - move!.ppUsed = 0; // TODO: is this bang correct? + move.ppUsed = 0; } pokemon.updateInfo(true); } diff --git a/src/phases/turn-start-phase.ts b/src/phases/turn-start-phase.ts index b48b018a046..f2a54edd14c 100644 --- a/src/phases/turn-start-phase.ts +++ b/src/phases/turn-start-phase.ts @@ -154,7 +154,7 @@ export class TurnStartPhase extends FieldPhase { if (!queuedMove) { continue; } - const move = pokemon.getMoveset().find(m => m?.moveId === queuedMove.move && m?.ppUsed < m?.getMovePp()) || new PokemonMove(queuedMove.move); + const move = pokemon.getMoveset().find(m => m.moveId === queuedMove.move && m.ppUsed < m.getMovePp()) || new PokemonMove(queuedMove.move); if (move.getMove().hasAttr(MoveHeaderAttr)) { this.scene.unshiftPhase(new MoveHeaderPhase(this.scene, pokemon, move)); } diff --git a/src/test/moves/grudge.test.ts b/src/test/moves/grudge.test.ts index 340808929ab..88c99d53e25 100644 --- a/src/test/moves/grudge.test.ts +++ b/src/test/moves/grudge.test.ts @@ -41,7 +41,7 @@ describe("Moves - Grudge", () => { await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase"); - const playerMove = playerPokemon?.getMoveset().find(m => m?.moveId === Moves.EMBER); + const playerMove = playerPokemon?.getMoveset().find(m => m.moveId === Moves.EMBER); expect(playerMove?.getPpRatio()).toBe(0); }); @@ -60,7 +60,7 @@ describe("Moves - Grudge", () => { await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("BerryPhase"); - const playerMove = playerPokemon?.getMoveset().find(m => m?.moveId === Moves.EMBER); + const playerMove = playerPokemon?.getMoveset().find(m => m.moveId === Moves.EMBER); expect(playerMove?.getPpRatio()).toBe(0); }); @@ -84,7 +84,7 @@ describe("Moves - Grudge", () => { expect(enemyPokemon?.isFainted()).toBe(true); - const playerMove = playerPokemon?.getMoveset().find(m => m?.moveId === Moves.FALSE_SWIPE); + const playerMove = playerPokemon?.getMoveset().find(m => m.moveId === Moves.FALSE_SWIPE); expect(playerMove?.getPpRatio()).toBeGreaterThan(0); }); }); diff --git a/src/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts b/src/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts index 61d8aaa9f5a..9b07c9ee653 100644 --- a/src/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts @@ -127,7 +127,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(Species.GREEDENT); - const moveset = enemyField[0].moveset.map(m => m?.moveId); + const moveset = enemyField[0].moveset.map(m => m.moveId); expect(moveset?.length).toBe(4); expect(moveset).toEqual([ Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH ]); @@ -238,7 +238,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { expect(partyCountBefore + 1).toBe(partyCountAfter); const greedent = scene.getPlayerParty()[scene.getPlayerParty().length - 1]; expect(greedent.species.speciesId).toBe(Species.GREEDENT); - const moveset = greedent.moveset.map(m => m?.moveId); + const moveset = greedent.moveset.map(m => m.moveId); expect(moveset?.length).toBe(4); expect(moveset).toEqual([ Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.SLACK_OFF ]); }); diff --git a/src/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts b/src/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts index 147930f05d1..1deb8a0682e 100644 --- a/src/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts @@ -108,7 +108,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(Species.ORICORIO); expect(enemyField[0].summonData.statStages).toEqual([ 1, 1, 1, 1, 0, 0, 0 ]); - const moveset = enemyField[0].moveset.map(m => m?.moveId); + const moveset = enemyField[0].moveset.map(m => m.moveId); expect(moveset.some(m => m === Moves.REVELATION_DANCE)).toBeTruthy(); const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); @@ -204,7 +204,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { expect(partyCountBefore + 1).toBe(partyCountAfter); const oricorio = scene.getPlayerParty()[scene.getPlayerParty().length - 1]; expect(oricorio.species.speciesId).toBe(Species.ORICORIO); - const moveset = oricorio.moveset.map(m => m?.moveId); + const moveset = oricorio.moveset.map(m => m.moveId); expect(moveset?.some(m => m === Moves.REVELATION_DANCE)).toBeTruthy(); expect(moveset?.some(m => m === Moves.DRAGON_DANCE)).toBeTruthy(); }); diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index fe8d06c2c3b..0ae19cf64bf 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -257,7 +257,7 @@ export default class GameManager { selectTarget(movePosition: integer, targetIndex?: BattlerIndex) { this.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { const handler = this.scene.ui.getHandler() as TargetSelectUiHandler; - const move = (this.scene.getCurrentPhase() as SelectTargetPhase).getPokemon().getMoveset()[movePosition]!.getMove(); // TODO: is the bang correct? + const move = (this.scene.getCurrentPhase() as SelectTargetPhase).getPokemon().getMoveset()[movePosition].getMove(); if (!move.isMultiTarget()) { handler.setCursor(targetIndex !== undefined ? targetIndex : BattlerIndex.ENEMY); } diff --git a/src/test/utils/gameManagerUtils.ts b/src/test/utils/gameManagerUtils.ts index 0c70bcf7f18..6188b35eaac 100644 --- a/src/test/utils/gameManagerUtils.ts +++ b/src/test/utils/gameManagerUtils.ts @@ -86,7 +86,7 @@ export function waitUntil(truth) { export function getMovePosition(scene: BattleScene, pokemonIndex: 0 | 1, move: Moves) { const playerPokemon = scene.getPlayerField()[pokemonIndex]; const moveSet = playerPokemon.getMoveset(); - const index = moveSet.findIndex((m) => m?.moveId === move && m?.ppUsed < m?.getMovePp()); + const index = moveSet.findIndex((m) => m.moveId === move && m.ppUsed < m.getMovePp()); console.log(`Move position for ${Moves[move]} (=${move}):`, index); return index; } diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index eaf504495d5..bd1b7ff9c9f 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -232,7 +232,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle { const hasMove = cursor < moveset.length; if (hasMove) { - const pokemonMove = moveset[cursor]!; // TODO: is the bang correct? + const pokemonMove = moveset[cursor]; const moveType = pokemon.getMoveType(pokemonMove.getMove()); const textureKey = Utils.getLocalizedSpriteKey("types"); this.typeIcon.setTexture(textureKey, Type[moveType].toLowerCase()).setScale(0.8); diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index bd3561dd0b4..fdc5943583a 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -406,7 +406,7 @@ export default class PartyUiHandler extends MessageUiHandler { filterResult = this.FilterChallengeLegal(pokemon); } if (filterResult === null && this.partyUiMode === PartyUiMode.MOVE_MODIFIER) { - filterResult = this.moveSelectFilter(pokemon.moveset[this.optionsCursor]!); // TODO: is this bang correct? + filterResult = this.moveSelectFilter(pokemon.moveset[this.optionsCursor]); } } else { filterResult = (this.selectFilter as PokemonModifierTransferSelectFilter)(pokemon, getTransferrableItemsFromPokemon(this.scene.getPlayerParty()[this.transferCursor])[this.transferOptionCursor]); @@ -966,7 +966,7 @@ export default class PartyUiHandler extends MessageUiHandler { case PartyOption.MOVE_2: case PartyOption.MOVE_3: case PartyOption.MOVE_4: - const move = pokemon.moveset[option - PartyOption.MOVE_1]!; // TODO: is the bang correct? + const move = pokemon.moveset[option - PartyOption.MOVE_1]; if (this.showMovePp) { const maxPP = move.getMovePp(); const currPP = maxPP - move.ppUsed; @@ -1339,7 +1339,7 @@ class PartySlot extends Phaser.GameObjects.Container { this.slotHpText.setVisible(false); let slotTmText: string; - if (this.pokemon.getMoveset().filter(m => m?.moveId === tmMoveId).length > 0) { + if (this.pokemon.getMoveset().filter(m => m.moveId === tmMoveId).length > 0) { slotTmText = i18next.t("partyUiHandler:learned"); } else if (this.pokemon.compatibleTms.indexOf(tmMoveId) === -1) { slotTmText = i18next.t("partyUiHandler:notAble"); diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 2e05f3de4c1..0bd178e1cb7 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -1069,7 +1069,7 @@ export default class SummaryUiHandler extends UiHandler { } if (this.moveCursor < 4 && this.pokemon && this.moveCursor < this.pokemon.moveset.length) { - return this.pokemon.moveset[this.moveCursor]!.getMove(); // TODO: is this bang correct? + return this.pokemon.moveset[this.moveCursor].getMove(); } else if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.moveCursor === 4) { return this.newMove; }