From c34fd10ccba2965e9c9376318e16c9109df01a35 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Tue, 29 Apr 2025 14:06:12 -0400 Subject: [PATCH] Removed unnecessary null checks for turnData and co. I explicitly made them initialized by default for this very reason --- public/locales | 2 +- src/data/abilities/ability.ts | 10 ++- src/data/arena-tag.ts | 72 +++++++++---------- src/data/moves/move.ts | 11 ++- .../encounters/clowning-around-encounter.ts | 3 - .../encounters/weird-dream-encounter.ts | 4 -- .../utils/encounter-pokemon-utils.ts | 3 - src/field/pokemon.ts | 29 ++++---- src/modifier/modifier.ts | 10 +-- src/phases/faint-phase.ts | 4 +- src/phases/move-effect-phase.ts | 3 - src/phases/stat-stage-change-phase.ts | 8 --- 12 files changed, 63 insertions(+), 96 deletions(-) diff --git a/public/locales b/public/locales index 18c1963ef30..e98f0eb9c20 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 18c1963ef309612a5a7fef76f9879709a7202189 +Subproject commit e98f0eb9c2022bc78b53f0444424c636498e725a diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 65ace1cb48c..1924ab21907 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -3631,14 +3631,10 @@ export class SuppressWeatherEffectAbAttr extends PreWeatherEffectAbAttr { * Condition function to applied to abilities related to Sheer Force. * Checks if last move used against target was affected by a Sheer Force user and: * Disables: Color Change, Pickpocket, Berserk, Anger Shell - * @returns {AbAttrCondition} If false disables the ability which the condition is applied to. + * @returns An {@linkcode AbAttrCondition} to disable the ability under the proper conditions. */ function getSheerForceHitDisableAbCondition(): AbAttrCondition { return (pokemon: Pokemon) => { - if (!pokemon.turnData) { - return true; - } - const lastReceivedAttack = pokemon.turnData.attacksReceived[0]; if (!lastReceivedAttack) { return true; @@ -3649,7 +3645,7 @@ function getSheerForceHitDisableAbCondition(): AbAttrCondition { return true; } - /**if the last move chance is greater than or equal to cero, and the last attacker's ability is sheer force*/ + /** `true` if the last move's chance is above 0 and the last attacker's ability is sheer force */ const SheerForceAffected = allMoves[lastReceivedAttack.move].chance >= 0 && lastAttacker.hasAbility(Abilities.SHEER_FORCE); return !SheerForceAffected; @@ -5695,6 +5691,7 @@ export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr { this.hpRatio = hpRatio; } + // TODO: Refactor to use more early returns public override canApplyPostDamage( pokemon: Pokemon, damage: number, @@ -5722,6 +5719,7 @@ export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr { if (fordbiddenDefendingMoves.includes(enemyLastMoveUsed.move) || enemyLastMoveUsed.move === Moves.SKY_DROP && enemyLastMoveUsed.result === MoveResult.OTHER) { return false; // Will not activate if the Pokémon's HP falls below half by a move affected by Sheer Force. + // TODO: Make this use the sheer force disable condition } else if (allMoves[enemyLastMoveUsed.move].chance >= 0 && source.hasAbility(Abilities.SHEER_FORCE)) { return false; // Activate only after the last hit of multistrike moves diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index ff9e4068292..19c94a8a045 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -768,32 +768,27 @@ class SpikesTag extends ArenaTrapTag { } override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { - if (pokemon.isGrounded()) { - const cancelled = new BooleanHolder(false); - applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); - - if (simulated) { - return !cancelled.value; - } - - if (!cancelled.value) { - const damageHpRatio = 1 / (10 - 2 * this.layers); - const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); - - globalScene.queueMessage( - i18next.t("arenaTag:spikesActivateTrap", { - pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - }), - ); - pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT }); - if (pokemon.turnData) { - pokemon.turnData.damageTaken += damage; - } - return true; - } + if (!pokemon.isGrounded()) { + return false; } - return false; + const cancelled = new BooleanHolder(false); + applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); + if (simulated || cancelled.value) { + return !cancelled.value; + } + + const damageHpRatio = 1 / (10 - 2 * this.layers); + const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); + + globalScene.queueMessage( + i18next.t("arenaTag:spikesActivateTrap", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + }), + ); + pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT }); + pokemon.turnData.damageTaken += damage; + return true; } } @@ -962,31 +957,28 @@ class StealthRockTag extends ArenaTrapTag { override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { const cancelled = new BooleanHolder(false); applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); - if (cancelled.value) { return false; } const damageHpRatio = this.getDamageHpRatio(pokemon); + if (!damageHpRatio) { + return false; + } - if (damageHpRatio) { - if (simulated) { - return true; - } - const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); - globalScene.queueMessage( - i18next.t("arenaTag:stealthRockActivateTrap", { - pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - }), - ); - pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT }); - if (pokemon.turnData) { - pokemon.turnData.damageTaken += damage; - } + if (simulated) { return true; } - return false; + const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); + globalScene.queueMessage( + i18next.t("arenaTag:stealthRockActivateTrap", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + }), + ); + pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT }); + pokemon.turnData.damageTaken += damage; + return true; } getMatchupScoreMultiplier(pokemon: Pokemon): number { diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index c791c363e3b..c11b0188991 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -4388,10 +4388,10 @@ export class LastMoveDoublePowerAttr extends VariablePowerAttr { const userAlly = user.getAlly(); const enemyAlly = enemy?.getAlly(); - if (!isNullOrUndefined(userAlly) && userAlly.turnData.acted) { + if (userAlly?.turnData.acted) { pokemonActed.push(userAlly); } - if (!isNullOrUndefined(enemyAlly) && enemyAlly.turnData.acted) { + if (enemyAlly?.turnData.acted) { pokemonActed.push(enemyAlly); } } @@ -4459,13 +4459,10 @@ export class CombinedPledgeStabBoostAttr extends MoveAttr { * @extends VariablePowerAttr */ export class RoundPowerAttr extends VariablePowerAttr { - override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + override apply(user: Pokemon, target: Pokemon, move: Move, args: [NumberHolder]): boolean { const power = args[0]; - if (!(power instanceof NumberHolder)) { - return false; - } - if (user.turnData?.joinedRound) { + if (user.turnData.joinedRound) { power.value *= 2; return true; } diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index 24c076f750e..ce5eb2cfdd1 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -397,9 +397,6 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder newTypes.push(secondType); // Apply the type changes (to both base and fusion, if pokemon is fused) - if (!pokemon.customPokemonData) { - pokemon.customPokemonData = new CustomPokemonData(); - } pokemon.customPokemonData.types = newTypes; if (pokemon.isFusion()) { if (!pokemon.fusionCustomPokemonData) { diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index cd9ffefb516..cceda25fcb4 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -23,7 +23,6 @@ import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species"; import type { PokemonHeldItemModifier } from "#app/modifier/modifier"; import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier } from "#app/modifier/modifier"; import { achvs } from "#app/system/achv"; -import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type"; @@ -601,9 +600,6 @@ async function postProcessTransformedPokemon( newType = randSeedInt(18) as PokemonType; } newTypes.push(newType); - if (!newPokemon.customPokemonData) { - newPokemon.customPokemonData = new CustomPokemonData(); - } newPokemon.customPokemonData.types = newTypes; // Enable passive if previous had it diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index ed94a46ac18..a6a87b4ab9a 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -1031,9 +1031,6 @@ export function applyAbilityOverrideToPokemon(pokemon: Pokemon, ability: Abiliti } pokemon.fusionCustomPokemonData.ability = ability; } else { - if (!pokemon.customPokemonData) { - pokemon.customPokemonData = new CustomPokemonData(); - } pokemon.customPokemonData.ability = ability; } } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 6bfaf58846c..65481c8a9f5 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1412,9 +1412,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * Retrieves the entire set of stats of the {@linkcode Pokemon}. - * @param bypassSummonData prefer actual stats (`true` by default) or in-battle overriden stats (`false`) - * @returns the numeric values of the {@linkcode Pokemon}'s stats + * Retrieves the entire set of stats of this {@linkcode Pokemon}. + * @param bypassSummonData - whether to use actual stats or in-battle overriden stats from Transform; default `true` + * @returns the numeric values of this {@linkcode Pokemon}'s stats */ getStats(bypassSummonData = true): number[] { if (!bypassSummonData && this.summonData.stats) { @@ -4973,13 +4973,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } transferTagsBySourceId(sourceId: number, newSourceId: number): void { - if (!this.summonData) { - return; - } - const tags = this.summonData.tags; - tags - .filter(t => t.sourceId === sourceId) - .forEach(t => (t.sourceId = newSourceId)); + this.summonData.tags + .filter(t => t.sourceId === sourceId) + .forEach(t => (t.sourceId = newSourceId)); } /** @@ -5664,6 +5660,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } this.summonData = new PokemonSummonData(); this.setSwitchOutStatus(false); + // TODO: Why do we remove leech seed on resetting summon data? That should be a BattlerTag thing... if (this.getTag(BattlerTagType.SEEDED)) { this.lapseTag(BattlerTagType.SEEDED); } @@ -7749,15 +7746,16 @@ export class PokemonSummonData { public moveQueue: TurnMove[] = []; public tags: BattlerTag[] = []; public abilitySuppressed = false; + + // Overrides for transform public speciesForm: PokemonSpeciesForm | null = null; public fusionSpeciesForm: PokemonSpeciesForm | null = null; - public ability: Abilities = Abilities.NONE; - public passiveAbility: Abilities = Abilities.NONE; - public gender: Gender; - public fusionGender: Gender; + public ability: Abilities | undefined; + public passiveAbility: Abilities | undefined; + public gender: Gender | undefined; + public fusionGender: Gender | undefined; public stats: number[] = [0, 0, 0, 0, 0, 0]; public moveset: PokemonMove[] | null; - public illusionBroken: boolean = false; // If not initialized this value will not be populated from save data. public types: PokemonType[] = []; @@ -7765,6 +7763,7 @@ export class PokemonSummonData { /** Data pertaining to this pokemon's illusion. */ public illusion: IllusionData | null = null; + public illusionBroken: boolean = false; /** Array containing all berries eaten in the last turn; used by {@linkcode Abilities.CUD_CHEW} */ public berriesEatenLast: BerryType[] = []; diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index b2609d12dd7..514e03a8aa8 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1649,13 +1649,14 @@ export class FlinchChanceModifier extends PokemonHeldItemModifier { } /** - * Applies {@linkcode FlinchChanceModifier} - * @param pokemon the {@linkcode Pokemon} that holds the item - * @param flinched {@linkcode BooleanHolder} that is `true` if the pokemon flinched - * @returns `true` if {@linkcode FlinchChanceModifier} has been applied + * Applies {@linkcode FlinchChanceModifier} to randomly flinch targets hit. + * @param pokemon - The {@linkcode Pokemon} that holds the item + * @param flinched - A {@linkcode BooleanHolder} holding whether the pokemon has flinched + * @returns `true` if {@linkcode FlinchChanceModifier} was applied successfully */ override apply(pokemon: Pokemon, flinched: BooleanHolder): boolean { // The check for pokemon.summonData is to ensure that a crash doesn't occur when a Pokemon with King's Rock procs a flinch + // TODO: Since summonData is always defined now, we can probably remove this if (pokemon.summonData && !flinched.value && pokemon.randSeedInt(100) < this.getStackCount() * this.chance) { flinched.value = true; return true; @@ -1782,6 +1783,7 @@ export class HitHealModifier extends PokemonHeldItemModifier { */ override apply(pokemon: Pokemon): boolean { if (pokemon.turnData.totalDamageDealt && !pokemon.isFullHp()) { + // TODO: this shouldn't be undefined AFAIK globalScene.unshiftPhase( new PokemonHealPhase( pokemon.getBattlerIndex(), diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index 4c99a609b11..1aa24d59fa0 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -118,7 +118,7 @@ export class FaintPhase extends PokemonPhase { pokemon.resetTera(); - if (pokemon.turnData?.attacksReceived?.length) { + if (pokemon.turnData.attacksReceived?.length) { const lastAttack = pokemon.turnData.attacksReceived[0]; applyPostFaintAbAttrs( PostFaintAbAttr, @@ -136,7 +136,7 @@ export class FaintPhase extends PokemonPhase { for (const p of alivePlayField) { applyPostKnockOutAbAttrs(PostKnockOutAbAttr, p, pokemon); } - if (pokemon.turnData?.attacksReceived?.length) { + if (pokemon.turnData.attacksReceived?.length) { const defeatSource = this.source; if (defeatSource?.isOnField()) { diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 4b4e62db71b..64cae923f07 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -277,9 +277,6 @@ export class MoveEffectPhase extends PokemonPhase { super.end(); return; } - if (isNullOrUndefined(user.turnData)) { - user.resetTurnData(); - } } /** diff --git a/src/phases/stat-stage-change-phase.ts b/src/phases/stat-stage-change-phase.ts index 9d64a81bbb4..6731e45025c 100644 --- a/src/phases/stat-stage-change-phase.ts +++ b/src/phases/stat-stage-change-phase.ts @@ -217,16 +217,8 @@ export class StatStageChangePhase extends PokemonPhase { for (const s of filteredStats) { if (stages.value > 0 && pokemon.getStatStage(s) < 6) { - if (!pokemon.turnData) { - // Temporary fix for missing turn data struct on turn 1 - pokemon.resetTurnData(); - } pokemon.turnData.statStagesIncreased = true; } else if (stages.value < 0 && pokemon.getStatStage(s) > -6) { - if (!pokemon.turnData) { - // Temporary fix for missing turn data struct on turn 1 - pokemon.resetTurnData(); - } pokemon.turnData.statStagesDecreased = true; }