Removed unnecessary null checks for turnData and co.

I explicitly made them initialized by default for this very reason
This commit is contained in:
Bertie690 2025-04-29 14:06:12 -04:00
parent f82d3529ad
commit c34fd10ccb
12 changed files with 63 additions and 96 deletions

@ -1 +1 @@
Subproject commit 18c1963ef309612a5a7fef76f9879709a7202189
Subproject commit e98f0eb9c2022bc78b53f0444424c636498e725a

View File

@ -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

View File

@ -768,15 +768,16 @@ class SpikesTag extends ArenaTrapTag {
}
override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
if (pokemon.isGrounded()) {
if (!pokemon.isGrounded()) {
return false;
}
const cancelled = new BooleanHolder(false);
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
if (simulated) {
if (simulated || cancelled.value) {
return !cancelled.value;
}
if (!cancelled.value) {
const damageHpRatio = 1 / (10 - 2 * this.layers);
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
@ -786,17 +787,11 @@ class SpikesTag extends ArenaTrapTag {
}),
);
pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT });
if (pokemon.turnData) {
pokemon.turnData.damageTaken += damage;
}
return true;
}
}
return false;
}
}
/**
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Spikes_(move) Toxic Spikes}.
* Applies up to 2 layers of Toxic Spikes, poisoning or badly poisoning any Pokémon who is
@ -962,17 +957,19 @@ 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", {
@ -980,15 +977,10 @@ class StealthRockTag extends ArenaTrapTag {
}),
);
pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT });
if (pokemon.turnData) {
pokemon.turnData.damageTaken += damage;
}
return true;
}
return false;
}
getMatchupScoreMultiplier(pokemon: Pokemon): number {
const damageHpRatio = this.getDamageHpRatio(pokemon);
return Phaser.Math.Linear(super.getMatchupScoreMultiplier(pokemon), 1, 1 - Math.pow(damageHpRatio, damageHpRatio));

View File

@ -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;
}

View File

@ -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) {

View File

@ -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

View File

@ -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;
}
}

View File

@ -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,11 +4973,7 @@ 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
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[] = [];

View File

@ -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(),

View File

@ -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()) {

View File

@ -277,9 +277,6 @@ export class MoveEffectPhase extends PokemonPhase {
super.end();
return;
}
if (isNullOrUndefined(user.turnData)) {
user.resetTurnData();
}
}
/**

View File

@ -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;
}