@@ -396,7 +396,23 @@ export abstract class AbAttr {
396396 }
397397}
398398
399- export class BlockRecoilDamageAttr extends AbAttr {
399+ /**
400+ * Abstract class for ability attributes that simply cancel an interaction
401+ *
402+ * @remarks
403+ * Abilities that have simple cancel interactions (e.g. {@linkcode BlockRecoilDamageAttr}) can extend this class to reuse the `canApply` and `apply` logic
404+ */
405+ abstract class CancelInteractionAbAttr extends AbAttr {
406+ override canApply ( { cancelled } : AbAttrParamsWithCancel ) : boolean {
407+ return ! cancelled . value ;
408+ }
409+
410+ override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
411+ cancelled . value = true ;
412+ }
413+ }
414+
415+ export class BlockRecoilDamageAttr extends CancelInteractionAbAttr {
400416 private declare readonly _ : never ;
401417 constructor ( ) {
402418 super ( false ) ;
@@ -592,11 +608,7 @@ export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr {
592608 }
593609}
594610
595- export class BlockItemTheftAbAttr extends AbAttr {
596- override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
597- cancelled . value = true ;
598- }
599-
611+ export class BlockItemTheftAbAttr extends CancelInteractionAbAttr {
600612 getTriggerMessage ( { pokemon } : AbAttrBaseParams , abilityName : string ) {
601613 return i18next . t ( "abilityTriggers:blockItemTheft" , {
602614 pokemonNameWithAffix : getPokemonNameWithAffix ( pokemon ) ,
@@ -869,8 +881,9 @@ export interface FieldPriorityMoveImmunityAbAttrParams extends AugmentMoveIntera
869881}
870882
871883export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
872- override canApply ( { move, opponent : attacker } : FieldPriorityMoveImmunityAbAttrParams ) : boolean {
884+ override canApply ( { move, opponent : attacker , cancelled } : FieldPriorityMoveImmunityAbAttrParams ) : boolean {
873885 return (
886+ ! cancelled . value &&
874887 ! ( move . moveTarget === MoveTarget . USER || move . moveTarget === MoveTarget . NEAR_ALLY ) &&
875888 move . getPriority ( attacker ) > 0 &&
876889 ! move . isMultiTarget ( )
@@ -897,10 +910,8 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr {
897910 this . immuneCondition = immuneCondition ;
898911 }
899912
900- override canApply ( { pokemon, opponent : attacker , move } : MoveImmunityAbAttrParams ) : boolean {
901- // TODO: Investigate whether this method should be checking against `cancelled`, specifically
902- // if not checking this results in multiple flyouts showing when multiple abilities block the move.
903- return this . immuneCondition ( pokemon , attacker , move ) ;
913+ override canApply ( { pokemon, opponent : attacker , move, cancelled } : MoveImmunityAbAttrParams ) : boolean {
914+ return ! cancelled . value && this . immuneCondition ( pokemon , attacker , move ) ;
904915 }
905916
906917 override apply ( { cancelled } : MoveImmunityAbAttrParams ) : void {
@@ -1591,12 +1602,7 @@ export interface FieldPreventExplosiveMovesAbAttrParams extends AbAttrBaseParams
15911602 cancelled : BooleanHolder ;
15921603}
15931604
1594- export class FieldPreventExplosiveMovesAbAttr extends AbAttr {
1595- // TODO: investigate whether we need to check against `cancelled` in a `canApply` method
1596- override apply ( { cancelled } : FieldPreventExplosiveMovesAbAttrParams ) : void {
1597- cancelled . value = true ;
1598- }
1599- }
1605+ export class FieldPreventExplosiveMovesAbAttr extends CancelInteractionAbAttr { }
16001606
16011607export interface FieldMultiplyStatAbAttrParams extends AbAttrBaseParams {
16021608 /** The kind of stat that is being checked for modification */
@@ -2535,15 +2541,11 @@ export class IgnoreOpponentStatStagesAbAttr extends AbAttr {
25352541 * Abilities with this attribute prevent the user from being affected by Intimidate.
25362542 * @sealed
25372543 */
2538- export class IntimidateImmunityAbAttr extends AbAttr {
2544+ export class IntimidateImmunityAbAttr extends CancelInteractionAbAttr {
25392545 constructor ( ) {
25402546 super ( false ) ;
25412547 }
25422548
2543- override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
2544- cancelled . value = true ;
2545- }
2546-
25472549 getTriggerMessage ( { pokemon } : AbAttrParamsWithCancel , abilityName : string , ..._args : any [ ] ) : string {
25482550 return i18next . t ( "abilityTriggers:intimidateImmunity" , {
25492551 pokemonNameWithAffix : getPokemonNameWithAffix ( pokemon ) ,
@@ -3577,8 +3579,8 @@ export class ProtectStatAbAttr extends PreStatStageChangeAbAttr {
35773579 this . protectedStat = protectedStat ;
35783580 }
35793581
3580- override canApply ( { stat } : PreStatStageChangeAbAttrParams ) : boolean {
3581- return isNullOrUndefined ( this . protectedStat ) || stat === this . protectedStat ;
3582+ override canApply ( { stat, cancelled } : PreStatStageChangeAbAttrParams ) : boolean {
3583+ return ! cancelled . value && ( isNullOrUndefined ( this . protectedStat ) || stat === this . protectedStat ) ;
35823584 }
35833585
35843586 /**
@@ -3669,8 +3671,11 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
36693671 this . immuneEffects = immuneEffects ;
36703672 }
36713673
3672- override canApply ( { effect } : PreSetStatusAbAttrParams ) : boolean {
3673- return ( this . immuneEffects . length === 0 && effect !== StatusEffect . FAINT ) || this . immuneEffects . includes ( effect ) ;
3674+ override canApply ( { effect, cancelled } : PreSetStatusAbAttrParams ) : boolean {
3675+ return (
3676+ ! cancelled . value &&
3677+ ( ( this . immuneEffects . length === 0 && effect !== StatusEffect . FAINT ) || this . immuneEffects . includes ( effect ) )
3678+ ) ;
36743679 }
36753680
36763681 /**
@@ -3720,7 +3725,8 @@ export interface UserFieldStatusEffectImmunityAbAttrParams extends AbAttrBasePar
37203725/**
37213726 * Provides immunity to status effects to the user's field.
37223727 */
3723- export class UserFieldStatusEffectImmunityAbAttr extends AbAttr {
3728+ export class UserFieldStatusEffectImmunityAbAttr extends CancelInteractionAbAttr {
3729+ private declare readonly _ : never ;
37243730 protected immuneEffects : StatusEffect [ ] ;
37253731
37263732 /**
@@ -3740,12 +3746,8 @@ export class UserFieldStatusEffectImmunityAbAttr extends AbAttr {
37403746 ) ;
37413747 }
37423748
3743- /**
3744- * Set the `cancelled` value to true, indicating that the status effect is prevented.
3745- */
3746- override apply ( { cancelled } : UserFieldStatusEffectImmunityAbAttrParams ) : void {
3747- cancelled . value = true ;
3748- }
3749+ // declare here to allow typescript to allow us to override `canApply` method without adjusting params
3750+ declare apply : ( params : UserFieldStatusEffectImmunityAbAttrParams ) => void ;
37493751}
37503752
37513753/**
@@ -3776,14 +3778,7 @@ export class ConditionalUserFieldStatusEffectImmunityAbAttr extends UserFieldSta
37763778 * @returns Whether the ability can be applied to cancel the status effect.
37773779 */
37783780 override canApply ( params : UserFieldStatusEffectImmunityAbAttrParams ) : boolean {
3779- return this . condition ( params . target , params . source ) && super . canApply ( params ) ;
3780- }
3781-
3782- /**
3783- * Set the `cancelled` value to true, indicating that the status effect is prevented.
3784- */
3785- override apply ( { cancelled } : UserFieldStatusEffectImmunityAbAttrParams ) : void {
3786- cancelled . value = true ;
3781+ return ! params . cancelled . value && this . condition ( params . target , params . source ) && super . canApply ( params ) ;
37873782 }
37883783}
37893784
@@ -4019,20 +4014,16 @@ export class ConditionalCritAbAttr extends AbAttr {
40194014 }
40204015}
40214016
4022- export class BlockNonDirectDamageAbAttr extends AbAttr {
4017+ export class BlockNonDirectDamageAbAttr extends CancelInteractionAbAttr {
40234018 constructor ( ) {
40244019 super ( false ) ;
40254020 }
4026-
4027- override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
4028- cancelled . value = true ;
4029- }
40304021}
40314022
40324023/**
40334024 * This attribute will block any status damage that you put in the parameter.
40344025 */
4035- export class BlockStatusDamageAbAttr extends AbAttr {
4026+ export class BlockStatusDamageAbAttr extends CancelInteractionAbAttr {
40364027 private effects : StatusEffect [ ] ;
40374028
40384029 /**
@@ -4044,20 +4035,12 @@ export class BlockStatusDamageAbAttr extends AbAttr {
40444035 this . effects = effects ;
40454036 }
40464037
4047- override canApply ( { pokemon } : AbAttrParamsWithCancel ) : boolean {
4048- return ! ! pokemon . status ?. effect && this . effects . includes ( pokemon . status . effect ) ;
4049- }
4050-
4051- override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
4052- cancelled . value = true ;
4038+ override canApply ( { pokemon, cancelled } : AbAttrParamsWithCancel ) : boolean {
4039+ return ! cancelled . value && ! ! pokemon . status ?. effect && this . effects . includes ( pokemon . status . effect ) ;
40534040 }
40544041}
40554042
4056- export class BlockOneHitKOAbAttr extends AbAttr {
4057- override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
4058- cancelled . value = true ;
4059- }
4060- }
4043+ export class BlockOneHitKOAbAttr extends CancelInteractionAbAttr { }
40614044
40624045export interface ChangeMovePriorityAbAttrParams extends AbAttrBaseParams {
40634046 /** The move being used */
@@ -4131,8 +4114,8 @@ export class BlockWeatherDamageAttr extends PreWeatherDamageAbAttr {
41314114 this . weatherTypes = weatherTypes ;
41324115 }
41334116
4134- override canApply ( { weather } : PreWeatherEffectAbAttrParams ) : boolean {
4135- if ( ! weather ) {
4117+ override canApply ( { weather, cancelled } : PreWeatherEffectAbAttrParams ) : boolean {
4118+ if ( ! weather || cancelled . value ) {
41364119 return false ;
41374120 }
41384121 const weatherType = weather . weatherType ;
@@ -4153,8 +4136,8 @@ export class SuppressWeatherEffectAbAttr extends PreWeatherEffectAbAttr {
41534136 this . affectsImmutable = affectsImmutable ;
41544137 }
41554138
4156- override canApply ( { weather } : PreWeatherEffectAbAttrParams ) : boolean {
4157- if ( ! weather ) {
4139+ override canApply ( { weather, cancelled } : PreWeatherEffectAbAttrParams ) : boolean {
4140+ if ( ! weather || cancelled . value ) {
41584141 return false ;
41594142 }
41604143 return this . affectsImmutable || weather . isImmutable ( ) ;
@@ -5151,15 +5134,11 @@ export class StatStageChangeCopyAbAttr extends AbAttr {
51515134 }
51525135}
51535136
5154- export class BypassBurnDamageReductionAbAttr extends AbAttr {
5137+ export class BypassBurnDamageReductionAbAttr extends CancelInteractionAbAttr {
51555138 private declare readonly _ : never ;
51565139 constructor ( ) {
51575140 super ( false ) ;
51585141 }
5159-
5160- override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
5161- cancelled . value = true ;
5162- }
51635142}
51645143
51655144export interface ReduceBurnDamageAbAttrParams extends AbAttrBaseParams {
@@ -5199,14 +5178,7 @@ export class DoubleBerryEffectAbAttr extends AbAttr {
51995178 * Attribute to prevent opposing berry use while on the field.
52005179 * Used by {@linkcode AbilityId.UNNERVE}, {@linkcode AbilityId.AS_ONE_GLASTRIER} and {@linkcode AbilityId.AS_ONE_SPECTRIER}
52015180 */
5202- export class PreventBerryUseAbAttr extends AbAttr {
5203- /**
5204- * Prevent use of opposing berries.
5205- */
5206- override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
5207- cancelled . value = true ;
5208- }
5209- }
5181+ export class PreventBerryUseAbAttr extends CancelInteractionAbAttr { }
52105182
52115183/**
52125184 * A Pokemon with this ability heals by a percentage of their maximum hp after eating a berry
@@ -5664,11 +5636,7 @@ export class IncreasePpAbAttr extends AbAttr {
56645636}
56655637
56665638/** @sealed */
5667- export class ForceSwitchOutImmunityAbAttr extends AbAttr {
5668- override apply ( { cancelled } : AbAttrParamsWithCancel ) : void {
5669- cancelled . value = true ;
5670- }
5671- }
5639+ export class ForceSwitchOutImmunityAbAttr extends CancelInteractionAbAttr { }
56725640
56735641export interface ReduceBerryUseThresholdAbAttrParams extends AbAttrBaseParams {
56745642 /** Holds the hp ratio for the berry to proc, which may be modified by ability application */
@@ -5747,8 +5715,8 @@ export class MoveAbilityBypassAbAttr extends AbAttr {
57475715 this . moveIgnoreFunc = moveIgnoreFunc || ( ( _pokemon , _move ) => true ) ;
57485716 }
57495717
5750- override canApply ( { pokemon, move } : MoveAbilityBypassAbAttrParams ) : boolean {
5751- return this . moveIgnoreFunc ( pokemon , move ) ;
5718+ override canApply ( { pokemon, move, cancelled } : MoveAbilityBypassAbAttrParams ) : boolean {
5719+ return ! cancelled . value && this . moveIgnoreFunc ( pokemon , move ) ;
57525720 }
57535721
57545722 override apply ( { cancelled } : MoveAbilityBypassAbAttrParams ) : void {
@@ -5842,8 +5810,8 @@ export class IgnoreTypeImmunityAbAttr extends AbAttr {
58425810 this . allowedMoveTypes = allowedMoveTypes ;
58435811 }
58445812
5845- override canApply ( { moveType, defenderType } : IgnoreTypeImmunityAbAttrParams ) : boolean {
5846- return this . defenderType === defenderType && this . allowedMoveTypes . includes ( moveType ) ;
5813+ override canApply ( { moveType, defenderType, cancelled } : IgnoreTypeImmunityAbAttrParams ) : boolean {
5814+ return ! cancelled . value && this . defenderType === defenderType && this . allowedMoveTypes . includes ( moveType ) ;
58475815 }
58485816
58495817 override apply ( { cancelled } : IgnoreTypeImmunityAbAttrParams ) : void {
0 commit comments