From 662da02042046ff71006e62717618fb078e0fc29 Mon Sep 17 00:00:00 2001 From: Dread134 Date: Sat, 11 May 2024 16:33:28 -0400 Subject: [PATCH 01/11] Finish Sweet Veil and Pastel Veil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented the ally check for Sweet Veil and Pastel Veil On status check the Pokémon checks if it's ally has an ability to prevent the status --- src/data/ability.ts | 52 ++++++++++++++++++++++++++++++++++++++++++-- src/field/pokemon.ts | 6 +++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 8a244b85b..2bff81304 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1675,6 +1675,29 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } } +export class AllyStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { + private immuneEffects: StatusEffect[]; + + constructor(...immuneEffects: StatusEffect[]) { + super(); + + this.immuneEffects = immuneEffects; + } + + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { + cancelled.value = true; + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); + } +} + export class PreApplyBattlerTagAbAttr extends AbAttr { applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; @@ -1704,6 +1727,29 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { } } +export class AllyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { + private immuneTagType: BattlerTagType; + + constructor(immuneTagType: BattlerTagType) { + super(); + + this.immuneTagType = immuneTagType; + } + + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (tag.tagType === this.immuneTagType) { + cancelled.value = true; + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); + } +} + export class BlockCritAbAttr extends AbAttr { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.BooleanHolder).value = true; @@ -3255,9 +3301,10 @@ export function initAbilities() { .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ICE, 1.2), new Ability(Abilities.SWEET_VEIL, 6) .attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) + .attr(AllyStatusEffectImmunityAbAttr, StatusEffect.SLEEP) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) - .ignorable() - .partial(), + .attr(AllyBattlerTagImmunityAbAttr, BattlerTagType.DROWSY) + .ignorable(), new Ability(Abilities.STANCE_CHANGE, 6) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) @@ -3524,6 +3571,7 @@ export function initAbilities() { .partial(), new Ability(Abilities.PASTEL_VEIL, 8) .attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) + .attr(AllyStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) .ignorable(), new Ability(Abilities.HUNGER_SWITCH, 8) .attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 0 : 1) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index e11a05032..aea8e081e 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, AllyStatusEffectImmunityAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -2021,7 +2021,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const cancelled = new Utils.BooleanHolder(false); applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet); - + if (!cancelled.value) + applyPreSetStatusAbAttrs(AllyStatusEffectImmunityAbAttr, this.getAlly(), effect, cancelled, quiet); + if (cancelled.value) return false; From 049c7e691c04d61a0280d610921df0584ae3d391 Mon Sep 17 00:00:00 2001 From: Dread134 Date: Sat, 11 May 2024 17:54:45 -0400 Subject: [PATCH 02/11] Partially Implemented Flower Veil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Blocks status conditions on self and allies that are grass type - Blocks stat lowering by other Pokémon on self and allies that are grass type --- src/data/ability.ts | 80 +++++++++++++++++++++++++++++++++++++++++-- src/data/arena-tag.ts | 6 +++- src/field/pokemon.ts | 4 ++- src/phases.ts | 4 ++- 4 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 8a244b85b..38e2d2da4 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1646,6 +1646,29 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { } } +export class AllyProtectStatAbAttr extends PreStatChangeAbAttr { + private protectedStat: BattleStat; + + constructor(protectedStat?: BattleStat) { + super(); + + this.protectedStat = protectedStat; + } + + applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (this.protectedStat === undefined || stat === this.protectedStat) { + cancelled.value = true; + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents lowering its ${this.protectedStat !== undefined ? getBattleStatName(this.protectedStat) : 'stats'}!`); + } +} + export class PreSetStatusAbAttr extends AbAttr { applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; @@ -1675,6 +1698,29 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } } +export class AllyStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { + private immuneEffects: StatusEffect[]; + + constructor(...immuneEffects: StatusEffect[]) { + super(); + + this.immuneEffects = immuneEffects; + } + + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { + cancelled.value = true; + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); + } +} + export class PreApplyBattlerTagAbAttr extends AbAttr { applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; @@ -1704,6 +1750,29 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { } } +export class AllyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { + private immuneTagType: BattlerTagType; + + constructor(immuneTagType: BattlerTagType) { + super(); + + this.immuneTagType = immuneTagType; + } + + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (tag.tagType === this.immuneTagType) { + cancelled.value = true; + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); + } +} + export class BlockCritAbAttr extends AbAttr { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.BooleanHolder).value = true; @@ -3232,9 +3301,16 @@ export function initAbilities() { new Ability(Abilities.AROMA_VEIL, 6) .ignorable() .unimplemented(), - new Ability(Abilities.FLOWER_VEIL, 6) + new Ability(Abilities.FLOWER_VEIL, 6) // TODO: Check against Spectral Thief once implemented, check against Toxic orb and flame orb once implemented. + // Also needs to not prevent the user from using Rest. + .conditionalAttr(p => (p.isOfType(Type.GRASS)), ProtectStatAbAttr) + .conditionalAttr(p => (p.isOfType(Type.GRASS)), AllyProtectStatAbAttr) + .conditionalAttr(p => (p.isOfType(Type.GRASS)), StatusEffectImmunityAbAttr) + .conditionalAttr(p => (p.isOfType(Type.GRASS)), AllyStatusEffectImmunityAbAttr) + .conditionalAttr(p => (p.isOfType(Type.GRASS)), BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) + .conditionalAttr(p => (p.isOfType(Type.GRASS)), AllyBattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .ignorable() - .unimplemented(), + .partial(), new Ability(Abilities.CHEEK_POUCH, 6) .unimplemented(), new Ability(Abilities.PROTEAN, 6) diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 8942cfe4b..42ae8215c 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -9,7 +9,7 @@ import { StatusEffect } from "./status-effect"; import { BattlerIndex } from "../battle"; import { Moves } from "./enums/moves"; import { ArenaTagType } from "./enums/arena-tag-type"; -import { BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability"; +import { AllyProtectStatAbAttr, BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability"; import { BattleStat } from "./battle-stat"; export enum ArenaTagSide { @@ -436,6 +436,10 @@ class StickyWebTag extends ArenaTrapTag { if (pokemon.isGrounded()) { const cancelled = new Utils.BooleanHolder(false); applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); + if (!cancelled.value) { + applyAbAttrs(AllyProtectStatAbAttr, pokemon.getAlly(), cancelled); + } + if (!cancelled.value) { pokemon.scene.queueMessage(`The opposing ${pokemon.name} was caught in a sticky web!`); const statLevels = new Utils.NumberHolder(-1); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index e11a05032..602354f75 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, AllyStatusEffectImmunityAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -2021,6 +2021,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const cancelled = new Utils.BooleanHolder(false); applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet); + if (!cancelled.value) + applyPreSetStatusAbAttrs(AllyStatusEffectImmunityAbAttr, this.getAlly(), effect, cancelled, quiet); if (cancelled.value) return false; diff --git a/src/phases.ts b/src/phases.ts index d8ce55e95..e34670e7b 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, AllyProtectStatAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -2740,6 +2740,8 @@ export class StatChangePhase extends PokemonPhase { if (!cancelled.value && !this.selfTarget && this.levels < 0) applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon(), stat, cancelled); + if (!cancelled.value && !this.selfTarget) + applyPreStatChangeAbAttrs(AllyProtectStatAbAttr, this.getPokemon().getAlly(), stat, cancelled); return !cancelled.value; }); From f930f733b2cca303bdf5a24dcac667db2510608b Mon Sep 17 00:00:00 2001 From: Dread134 Date: Sun, 12 May 2024 13:52:24 -0400 Subject: [PATCH 03/11] Shorten Code Reused classes to be able to check if an ability should be covering their allies too. Same checks as the parent class but a simple solution to implement ally checks too. --- src/data/ability.ts | 69 ++------------------------------------------- 1 file changed, 3 insertions(+), 66 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 38e2d2da4..5fad3e4ba 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1646,28 +1646,7 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { } } -export class AllyProtectStatAbAttr extends PreStatChangeAbAttr { - private protectedStat: BattleStat; - - constructor(protectedStat?: BattleStat) { - super(); - - this.protectedStat = protectedStat; - } - - applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.protectedStat === undefined || stat === this.protectedStat) { - cancelled.value = true; - return true; - } - - return false; - } - - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents lowering its ${this.protectedStat !== undefined ? getBattleStatName(this.protectedStat) : 'stats'}!`); - } -} +export class AllyProtectStatAbAttr extends ProtectStatAbAttr { } export class PreSetStatusAbAttr extends AbAttr { applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { @@ -1698,28 +1677,7 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } } -export class AllyStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { - private immuneEffects: StatusEffect[]; - - constructor(...immuneEffects: StatusEffect[]) { - super(); - - this.immuneEffects = immuneEffects; - } - - applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { - cancelled.value = true; - return true; - } - - return false; - } - - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); - } -} +export class AllyStatusEffectImmunityAbAttr extends StatusEffectImmunityAbAttr { } export class PreApplyBattlerTagAbAttr extends AbAttr { applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { @@ -1750,28 +1708,7 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { } } -export class AllyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { - private immuneTagType: BattlerTagType; - - constructor(immuneTagType: BattlerTagType) { - super(); - - this.immuneTagType = immuneTagType; - } - - applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (tag.tagType === this.immuneTagType) { - cancelled.value = true; - return true; - } - - return false; - } - - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); - } -} +export class AllyBattlerTagImmunityAbAttr extends BattlerTagImmunityAbAttr { } export class BlockCritAbAttr extends AbAttr { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { From 5f0942b7a5292f3dbb0fe949786a1629ecb8593d Mon Sep 17 00:00:00 2001 From: Dread134 Date: Sun, 12 May 2024 14:02:15 -0400 Subject: [PATCH 04/11] Added TSDoc Documentation Added documentation to the 3 new Ally classes to cover allies with the ability. --- src/data/ability.ts | 12 ++++++++++++ src/data/arena-tag.ts | 3 +-- src/field/pokemon.ts | 2 +- src/phases.ts | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 5fad3e4ba..2af4effef 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1646,6 +1646,10 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { } } +/** + * Extends from {@link ProtectStatAbAttr} to allow abilities to mark that they can protect allies from stat changes. + * Requires the Affected Pokemon to then check if ally has any ability with this attribute and apply the effect. + */ export class AllyProtectStatAbAttr extends ProtectStatAbAttr { } export class PreSetStatusAbAttr extends AbAttr { @@ -1677,6 +1681,10 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } } +/** + * Extends from {@link StatusEffectImmunityAbAttr} to allow abilities to mark that they can protect allies from status effects. + * Requires the Affected Pokemon to then check if ally has any ability with this attribute and apply the effect. + */ export class AllyStatusEffectImmunityAbAttr extends StatusEffectImmunityAbAttr { } export class PreApplyBattlerTagAbAttr extends AbAttr { @@ -1708,6 +1716,10 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { } } +/** + * Extends from {@link BattlerTagImmunityAbAttr} to allow abilities to mark that they can protect allies from battler tags. + * Requires the Affected Pokemon to then check if ally has any ability with this attribute and apply the effect. + */ export class AllyBattlerTagImmunityAbAttr extends BattlerTagImmunityAbAttr { } export class BlockCritAbAttr extends AbAttr { diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 42ae8215c..929da1c4e 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -436,9 +436,8 @@ class StickyWebTag extends ArenaTrapTag { if (pokemon.isGrounded()) { const cancelled = new Utils.BooleanHolder(false); applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); - if (!cancelled.value) { + if (!cancelled.value) // If Pokemon fails to protect themselves, check if ally has an ability to protect them applyAbAttrs(AllyProtectStatAbAttr, pokemon.getAlly(), cancelled); - } if (!cancelled.value) { pokemon.scene.queueMessage(`The opposing ${pokemon.name} was caught in a sticky web!`); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 602354f75..cf181580a 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2021,7 +2021,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const cancelled = new Utils.BooleanHolder(false); applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet); - if (!cancelled.value) + if (!cancelled.value) // If Pokemon fails to protect themselves, check if ally has an ability to protect them applyPreSetStatusAbAttrs(AllyStatusEffectImmunityAbAttr, this.getAlly(), effect, cancelled, quiet); if (cancelled.value) diff --git a/src/phases.ts b/src/phases.ts index e34670e7b..b0f79af45 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2740,7 +2740,7 @@ export class StatChangePhase extends PokemonPhase { if (!cancelled.value && !this.selfTarget && this.levels < 0) applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon(), stat, cancelled); - if (!cancelled.value && !this.selfTarget) + if (!cancelled.value && !this.selfTarget) // If Pokemon fails to protect themselves, check if ally has an ability to protect them applyPreStatChangeAbAttrs(AllyProtectStatAbAttr, this.getPokemon().getAlly(), stat, cancelled); return !cancelled.value; From bd44d1ab4c6e6055799a0a484427ba87a0a4851a Mon Sep 17 00:00:00 2001 From: Dread134 Date: Mon, 13 May 2024 10:08:19 -0400 Subject: [PATCH 05/11] Shortened Code Shortened code to better match Flower Veil implementation --- src/data/ability.ts | 46 ++------------------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 2bff81304..6e9b13512 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1675,28 +1675,7 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } } -export class AllyStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { - private immuneEffects: StatusEffect[]; - - constructor(...immuneEffects: StatusEffect[]) { - super(); - - this.immuneEffects = immuneEffects; - } - - applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { - cancelled.value = true; - return true; - } - - return false; - } - - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); - } -} +export class AllyStatusEffectImmunityAbAttr extends StatusEffectImmunityAbAttr { } export class PreApplyBattlerTagAbAttr extends AbAttr { applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { @@ -1727,28 +1706,7 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { } } -export class AllyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { - private immuneTagType: BattlerTagType; - - constructor(immuneTagType: BattlerTagType) { - super(); - - this.immuneTagType = immuneTagType; - } - - applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (tag.tagType === this.immuneTagType) { - cancelled.value = true; - return true; - } - - return false; - } - - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); - } -} +export class AllyBattlerTagImmunityAbAttr extends BattlerTagImmunityAbAttr { } export class BlockCritAbAttr extends AbAttr { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { From cc3df214f3509b2e6eb7a33b5586fca2437215b4 Mon Sep 17 00:00:00 2001 From: Dread134 Date: Mon, 13 May 2024 12:11:48 -0400 Subject: [PATCH 06/11] Fixed BattlerTagImmunity Added Ally check for Battler Tag immunity. --- src/field/pokemon.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index aea8e081e..c76e610bb 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, AllyStatusEffectImmunityAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, AllyStatusEffectImmunityAbAttr, AllyBattlerTagImmunityAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -1682,6 +1682,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const cancelled = new Utils.BooleanHolder(false); applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this, newTag, cancelled); + if (!cancelled.value) // If the tag was not cancelled, check if Ally has an ability that provides immunity to allies + applyPreApplyBattlerTagAbAttrs(AllyBattlerTagImmunityAbAttr, this.getAlly(), newTag, cancelled); if (!cancelled.value && newTag.canAdd(this)) { this.summonData.tags.push(newTag); From da622e8fa1d2c5d134196a55f7a6c1f63fac0c57 Mon Sep 17 00:00:00 2001 From: Dread134 Date: Mon, 13 May 2024 12:13:21 -0400 Subject: [PATCH 07/11] Fixed BattlerTagImmunity Added Ally check for Battler Tag immunity. --- src/field/pokemon.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 4612d0d71..11543cf23 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, AllyStatusEffectImmunityAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, AllyStatusEffectImmunityAbAttr, AllyBattlerTagImmunityAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -1723,6 +1723,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const cancelled = new Utils.BooleanHolder(false); applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this, newTag, cancelled); + if (!cancelled.value) // If the tag was not cancelled, check if Ally has an ability that provides immunity to allies + applyPreApplyBattlerTagAbAttrs(AllyBattlerTagImmunityAbAttr, this.getAlly(), newTag, cancelled); if (!cancelled.value && newTag.canAdd(this)) { this.summonData.tags.push(newTag); From e4ac88ede9604c4acff231f12ce2c15b56503771 Mon Sep 17 00:00:00 2001 From: Dread134 Date: Tue, 14 May 2024 15:02:37 -0400 Subject: [PATCH 08/11] Update ability.ts Set code back to full copy of normal immunity classes. Extending from the normal classes caused ability triggers to happen twice due to how the system is setup. --- src/data/ability.ts | 78 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index bb1cc50b6..8952e8c14 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1731,10 +1731,30 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { } /** - * Extends from {@link ProtectStatAbAttr} to allow abilities to mark that they can protect allies from stat changes. - * Requires the Affected Pokemon to then check if ally has any ability with this attribute and apply the effect. + * Attrbiute class to allow abilities to mark that they can protect allies from stat reductions. */ -export class AllyProtectStatAbAttr extends ProtectStatAbAttr { } +export class AllyProtectStatAbAttr extends PreStatChangeAbAttr { + private protectedStat: BattleStat; + + constructor(protectedStat?: BattleStat) { + super(); + + this.protectedStat = protectedStat; + } + + applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (this.protectedStat === undefined || stat === this.protectedStat) { + cancelled.value = true; + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents lowering its ${this.protectedStat !== undefined ? getBattleStatName(this.protectedStat) : 'stats'}!`); + } +} export class PreSetStatusAbAttr extends AbAttr { applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { @@ -1766,10 +1786,30 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } /** - * Extends from {@link StatusEffectImmunityAbAttr} to allow abilities to mark that they can protect allies from status effects. - * Requires the Affected Pokemon to then check if ally has any ability with this attribute and apply the effect. + * Attrbiute class to allow abilities to mark that they can protect allies from status effects. */ -export class AllyStatusEffectImmunityAbAttr extends StatusEffectImmunityAbAttr { } +export class AllyStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { + private immuneEffects: StatusEffect[]; + + constructor(...immuneEffects: StatusEffect[]) { + super(); + + this.immuneEffects = immuneEffects; + } + + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { + cancelled.value = true; + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); + } +} export class PreApplyBattlerTagAbAttr extends AbAttr { applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { @@ -1801,10 +1841,30 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { } /** - * Extends from {@link BattlerTagImmunityAbAttr} to allow abilities to mark that they can protect allies from battler tags. - * Requires the Affected Pokemon to then check if ally has any ability with this attribute and apply the effect. + * Attrbiute class to allow abilities to mark that they can protect allies from battler tags */ -export class AllyBattlerTagImmunityAbAttr extends BattlerTagImmunityAbAttr { } +export class AllyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { + private immuneTagType: BattlerTagType; + + constructor(immuneTagType: BattlerTagType) { + super(); + + this.immuneTagType = immuneTagType; + } + + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (tag.tagType === this.immuneTagType) { + cancelled.value = true; + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); + } +} export class BlockCritAbAttr extends AbAttr { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { From 86111a1019658470647bf4ba3b7bdf3136b08e64 Mon Sep 17 00:00:00 2001 From: Dread134 Date: Tue, 14 May 2024 17:55:34 -0400 Subject: [PATCH 09/11] Shortened Code Removed duplicate and renamed classes and added attributes to set them to apply to their allies to. Updated arena-tag, pokemon, and phases to pass if they are checking ally for an ability to block affected pokemon --- src/data/ability.ts | 136 ++++++++++++------------------------------ src/data/arena-tag.ts | 7 ++- src/field/pokemon.ts | 15 +++-- src/phases.ts | 7 ++- 4 files changed, 54 insertions(+), 111 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 8952e8c14..3420f6576 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1709,41 +1709,22 @@ export class PreStatChangeAbAttr extends AbAttr { export class ProtectStatAbAttr extends PreStatChangeAbAttr { private protectedStat: BattleStat; + private applyToAlly: boolean; - constructor(protectedStat?: BattleStat) { + constructor(protectedStat?: BattleStat, applyToAlly: boolean = false) { super(); this.protectedStat = protectedStat; + this.applyToAlly = applyToAlly; } applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.protectedStat === undefined || stat === this.protectedStat) { + const allyCheck = args[0]; + if ((this.protectedStat === undefined || stat === this.protectedStat) && !allyCheck) { cancelled.value = true; return true; - } - - return false; - } - - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents lowering its ${this.protectedStat !== undefined ? getBattleStatName(this.protectedStat) : 'stats'}!`); - } -} - -/** - * Attrbiute class to allow abilities to mark that they can protect allies from stat reductions. - */ -export class AllyProtectStatAbAttr extends PreStatChangeAbAttr { - private protectedStat: BattleStat; - - constructor(protectedStat?: BattleStat) { - super(); - - this.protectedStat = protectedStat; - } - - applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.protectedStat === undefined || stat === this.protectedStat) { + } else if ((this.protectedStat === undefined || stat === this.protectedStat) + && allyCheck && this.applyToAlly) { cancelled.value = true; return true; } @@ -1763,42 +1744,24 @@ export class PreSetStatusAbAttr extends AbAttr { } export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { + private applyToAlly: boolean; private immuneEffects: StatusEffect[]; - constructor(...immuneEffects: StatusEffect[]) { + constructor(immuneEffects: StatusEffect[] = [], applyToAlly: boolean = false) { super(); this.immuneEffects = immuneEffects; + this.applyToAlly = applyToAlly; } applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { + const allyCheck = args[2]; + if ((!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) && !allyCheck) { cancelled.value = true; return true; } - - return false; - } - - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); - } -} - -/** - * Attrbiute class to allow abilities to mark that they can protect allies from status effects. - */ -export class AllyStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { - private immuneEffects: StatusEffect[]; - - constructor(...immuneEffects: StatusEffect[]) { - super(); - - this.immuneEffects = immuneEffects; - } - - applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { + else if((!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) + && allyCheck && this.applyToAlly) { cancelled.value = true; return true; } @@ -1819,41 +1782,22 @@ export class PreApplyBattlerTagAbAttr extends AbAttr { export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { private immuneTagType: BattlerTagType; + private applyToAlly: boolean; - constructor(immuneTagType: BattlerTagType) { + constructor(immuneTagType: BattlerTagType, applyToAlly: boolean = false) { super(); this.immuneTagType = immuneTagType; + this.applyToAlly = applyToAlly; } applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (tag.tagType === this.immuneTagType) { + const allyCheck = args[0]; + if ((tag.tagType === this.immuneTagType) && !allyCheck) { cancelled.value = true; return true; - } - - return false; - } - - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); - } -} - -/** - * Attrbiute class to allow abilities to mark that they can protect allies from battler tags - */ -export class AllyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { - private immuneTagType: BattlerTagType; - - constructor(immuneTagType: BattlerTagType) { - super(); - - this.immuneTagType = immuneTagType; - } - - applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (tag.tagType === this.immuneTagType) { + } else if ((tag.tagType === this.immuneTagType) + && allyCheck && this.applyToAlly) { cancelled.value = true; return true; } @@ -2878,8 +2822,8 @@ export function applyPostStatChangeAbAttrs(attrType: { new(...args: any[]): Post export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSetStatusAbAttr }, pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - const simulated = args.length > 1 && args[1]; - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, false, !simulated); + const simulated = args.length > 2 && args[2]; + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, false, simulated); } export function applyPreApplyBattlerTagAbAttrs(attrType: { new(...args: any[]): PreApplyBattlerTagAbAttr }, @@ -2959,7 +2903,7 @@ export function initAbilities() { .attr(FieldPreventExplosiveMovesAbAttr) .ignorable(), new Ability(Abilities.LIMBER, 3) - .attr(StatusEffectImmunityAbAttr, StatusEffect.PARALYSIS) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.PARALYSIS]) .ignorable(), new Ability(Abilities.SAND_VEIL, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2) @@ -2984,13 +2928,13 @@ export function initAbilities() { new Ability(Abilities.COMPOUND_EYES, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.3), new Ability(Abilities.INSOMNIA, 3) - .attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.SLEEP]) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .ignorable(), new Ability(Abilities.COLOR_CHANGE, 3) .attr(PostDefendTypeChangeAbAttr), new Ability(Abilities.IMMUNITY, 3) - .attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.POISON, StatusEffect.TOXIC]) .ignorable(), new Ability(Abilities.FLASH_FIRE, 3) .attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1, (pokemon: Pokemon) => !pokemon.status || pokemon.status.effect !== StatusEffect.FREEZE) @@ -3059,10 +3003,10 @@ export function initAbilities() { .attr(IntimidateImmunityAbAttr) .ignorable(), new Ability(Abilities.MAGMA_ARMOR, 3) - .attr(StatusEffectImmunityAbAttr, StatusEffect.FREEZE) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.FREEZE]) .ignorable(), new Ability(Abilities.WATER_VEIL, 3) - .attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.BURN]) .ignorable(), new Ability(Abilities.MAGNET_PULL, 3) /*.attr(ArenaTrapAbAttr) @@ -3144,7 +3088,7 @@ export function initAbilities() { .attr(ArenaTrapAbAttr) .attr(DoubleBattleChanceAbAttr), new Ability(Abilities.VITAL_SPIRIT, 3) - .attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.SLEEP]) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .ignorable(), new Ability(Abilities.WHITE_SMOKE, 3) @@ -3421,12 +3365,9 @@ export function initAbilities() { .unimplemented(), new Ability(Abilities.FLOWER_VEIL, 6) // TODO: Check against Spectral Thief once implemented, check against Toxic orb and flame orb once implemented. // Also needs to not prevent the user from using Rest. - .conditionalAttr(p => (p.isOfType(Type.GRASS)), ProtectStatAbAttr) - .conditionalAttr(p => (p.isOfType(Type.GRASS)), AllyProtectStatAbAttr) - .conditionalAttr(p => (p.isOfType(Type.GRASS)), StatusEffectImmunityAbAttr) - .conditionalAttr(p => (p.isOfType(Type.GRASS)), AllyStatusEffectImmunityAbAttr) - .conditionalAttr(p => (p.isOfType(Type.GRASS)), BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) - .conditionalAttr(p => (p.isOfType(Type.GRASS)), AllyBattlerTagImmunityAbAttr, BattlerTagType.DROWSY) + .conditionalAttr(p => (p.isOfType(Type.GRASS)), ProtectStatAbAttr, undefined, true) + .conditionalAttr(p => (p.isOfType(Type.GRASS)), StatusEffectImmunityAbAttr, [], true) + .conditionalAttr(p => (p.isOfType(Type.GRASS)), BattlerTagImmunityAbAttr, BattlerTagType.DROWSY, true) .ignorable() .partial(), new Ability(Abilities.CHEEK_POUCH, 6) @@ -3448,10 +3389,8 @@ export function initAbilities() { new Ability(Abilities.REFRIGERATE, 6) .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ICE, 1.2), new Ability(Abilities.SWEET_VEIL, 6) - .attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) - .attr(AllyStatusEffectImmunityAbAttr, StatusEffect.SLEEP) - .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) - .attr(AllyBattlerTagImmunityAbAttr, BattlerTagType.DROWSY) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.SLEEP], true) + .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY, true) .ignorable(), new Ability(Abilities.STANCE_CHANGE, 6) .attr(UncopiableAbilityAbAttr) @@ -3519,7 +3458,7 @@ export function initAbilities() { new Ability(Abilities.WATER_BUBBLE, 7) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5) .attr(MoveTypePowerBoostAbAttr, Type.WATER, 1) - .attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.BURN]) .ignorable(), new Ability(Abilities.STEELWORKER, 7) .attr(MoveTypePowerBoostAbAttr, Type.STEEL), @@ -3719,8 +3658,7 @@ export function initAbilities() { .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, '\'s Neutralizing Gas filled the area!')) .partial(), new Ability(Abilities.PASTEL_VEIL, 8) - .attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) - .attr(AllyStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.POISON, StatusEffect.TOXIC], true) .ignorable(), new Ability(Abilities.HUNGER_SWITCH, 8) .attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 0 : 1) @@ -3763,7 +3701,7 @@ export function initAbilities() { .attr(PostDefendTerrainChangeAbAttr, TerrainType.GRASSY), new Ability(Abilities.THERMAL_EXCHANGE, 9) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.FIRE && move.category !== MoveCategory.STATUS, BattleStat.ATK, 1) - .attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) + .attr(StatusEffectImmunityAbAttr, [StatusEffect.BURN]) .ignorable(), new Ability(Abilities.ANGER_SHELL, 9) .attr(PostDefendHpGatedStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ BattleStat.ATK, BattleStat.SPATK, BattleStat.SPD ], 1) diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 929da1c4e..50734949f 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -9,7 +9,7 @@ import { StatusEffect } from "./status-effect"; import { BattlerIndex } from "../battle"; import { Moves } from "./enums/moves"; import { ArenaTagType } from "./enums/arena-tag-type"; -import { AllyProtectStatAbAttr, BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability"; +import { BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability"; import { BattleStat } from "./battle-stat"; export enum ArenaTagSide { @@ -435,9 +435,10 @@ class StickyWebTag extends ArenaTrapTag { activateTrap(pokemon: Pokemon): boolean { if (pokemon.isGrounded()) { const cancelled = new Utils.BooleanHolder(false); - applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); + const allyCheck = true; + applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled, !allyCheck); if (!cancelled.value) // If Pokemon fails to protect themselves, check if ally has an ability to protect them - applyAbAttrs(AllyProtectStatAbAttr, pokemon.getAlly(), cancelled); + applyAbAttrs(ProtectStatAbAttr, pokemon.getAlly(), cancelled, allyCheck); if (!cancelled.value) { pokemon.scene.queueMessage(`The opposing ${pokemon.name} was caught in a sticky web!`); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 36517fb87..982882cd4 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, AllyStatusEffectImmunityAbAttr, AllyBattlerTagImmunityAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -1718,9 +1718,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const newTag = getBattlerTag(tagType, turnCount, sourceMove, sourceId); const cancelled = new Utils.BooleanHolder(false); - applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this, newTag, cancelled); + const allyCheck = true; + applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this, newTag, cancelled, !allyCheck); if (!cancelled.value) // If the tag was not cancelled, check if Ally has an ability that provides immunity to allies - applyPreApplyBattlerTagAbAttrs(AllyBattlerTagImmunityAbAttr, this.getAlly(), newTag, cancelled); + applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this.getAlly(), newTag, cancelled, allyCheck); if (!cancelled.value && newTag.canAdd(this)) { this.summonData.tags.push(newTag); @@ -2059,9 +2060,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } const cancelled = new Utils.BooleanHolder(false); - applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet); - if (!cancelled.value) // If Pokemon fails to protect themselves, check if ally has an ability to protect them - applyPreSetStatusAbAttrs(AllyStatusEffectImmunityAbAttr, this.getAlly(), effect, cancelled, quiet); + const allyCheck = true; + applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet, !allyCheck); + if (!cancelled.value) {// If Pokemon fails to protect themselves, check if ally has an ability to protect them + applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this.getAlly(), effect, cancelled, quiet, allyCheck); + } if (cancelled.value) return false; diff --git a/src/phases.ts b/src/phases.ts index 569543479..c1a57cbe5 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, AllyProtectStatAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -2738,10 +2738,11 @@ export class StatChangePhase extends PokemonPhase { if (!this.selfTarget && this.levels < 0) this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled); + const allyCheck = true; if (!cancelled.value && !this.selfTarget && this.levels < 0) - applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon(), stat, cancelled); + applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon(), stat, cancelled, !allyCheck); if (!cancelled.value && !this.selfTarget) // If Pokemon fails to protect themselves, check if ally has an ability to protect them - applyPreStatChangeAbAttrs(AllyProtectStatAbAttr, this.getPokemon().getAlly(), stat, cancelled); + applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon().getAlly(), stat, cancelled, allyCheck); return !cancelled.value; }); From e580526a7315335d647780def72a8a9b408d32b2 Mon Sep 17 00:00:00 2001 From: Dread134 Date: Tue, 14 May 2024 19:12:26 -0400 Subject: [PATCH 10/11] Update ability.ts Corrected Arg index for Status immunity check for ally or not --- src/data/ability.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 637edf0ee..179d95045 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1755,7 +1755,7 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const allyCheck = args[2]; + const allyCheck = args[1]; if ((!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) && !allyCheck) { cancelled.value = true; return true; From a09d2639df29e62a0986168e4f034eda5fedd17c Mon Sep 17 00:00:00 2001 From: Brandon Rodgers Date: Tue, 14 May 2024 19:17:48 -0400 Subject: [PATCH 11/11] Update pokemon.ts Removed extra comma --- src/field/pokemon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index bd8891f74..fdee4ce0f 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle';