diff --git a/src/data/ability.ts b/src/data/ability.ts index 0ad69407e2c..ea5c5cea4fd 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -20,8 +20,9 @@ import { SpeciesFormChangeManualTrigger } from "./pokemon-forms"; import { Abilities } from "./enums/abilities"; import i18next, { Localizable } from "#app/plugins/i18n.js"; import { Command } from "../ui/command-ui-handler"; -import { getPokeballName } from "./pokeball"; import { BerryModifierType } from "#app/modifier/modifier-type"; +import { getPokeballName } from "./pokeball"; +import { Species } from "./enums/species"; import {BattlerIndex} from "#app/battle"; export class Ability implements Localizable { @@ -1778,6 +1779,39 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { } } +/** + * This attribute applies confusion to the target whenever the user + * directly poisons them with a move, e.g. Poison Puppeteer. + * Called in {@linkcode StatusEffectAttr}. + * @extends PostAttackAbAttr + * @see {@linkcode applyPostAttack} + */ +export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { + /** List of effects to apply confusion after */ + private effects: StatusEffect[]; + + constructor(...effects: StatusEffect[]) { + super(); + this.effects = effects; + } + /** + * Applies confusion to the target pokemon. + * @param pokemon {@link Pokemon} attacking + * @param passive N/A + * @param defender {@link Pokemon} defending + * @param move {@link Move} used to apply status effect and confusion + * @param hitResult N/A + * @param args [0] {@linkcode StatusEffect} applied by move + * @returns true if defender is confused + */ + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + if (this.effects.indexOf(args[0]) > -1 && !defender.isFainted()) { + return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedInt(3,2), move.moveId, defender.id); + } + return false; + } +} + export class PreSetStatusAbAttr extends AbAttr { applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; @@ -4155,6 +4189,6 @@ export function initAbilities() { new Ability(Abilities.POISON_PUPPETEER, 9) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) - .unimplemented(), + .conditionalAttr(pokemon => pokemon.species.speciesId===Species.PECHARUNT,ConfusionOnStatusEffectAbAttr,StatusEffect.POISON,StatusEffect.TOXIC) ); } diff --git a/src/data/move.ts b/src/data/move.ts index ffd66a05d20..0020dd88a62 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -12,7 +12,7 @@ import * as Utils from "../utils"; import { WeatherType } from "./weather"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; import { ArenaTagType } from "./enums/arena-tag-type"; -import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr } from "./ability"; +import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr } from "./ability"; import { Abilities } from "./enums/abilities"; import { allAbilities } from "./ability"; import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier } from "../modifier/modifier"; @@ -1362,8 +1362,10 @@ export class StatusEffectAttr extends MoveEffectAttr { return false; } } - if (!pokemon.status || (pokemon.status.effect === this.effect && move.chance < 0)) { - return pokemon.trySetStatus(this.effect, true, user, this.cureTurn); + if ((!pokemon.status || (pokemon.status.effect === this.effect && move.chance < 0)) + && pokemon.trySetStatus(this.effect, true, user, this.cureTurn)) { + applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, new PokemonMove(move.id), null,this.effect); + return true; } } return false;