mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-14 22:05:34 +01:00
[Ability] Poison Puppeteer now applies for abilities (#6836)
* [Ability] Poison Puppeteer now applies for abilities When a target is poisoned due to an ability of a Pokemon that also has Poison Puppeteer, Poison Puppeteer will now apply its effect * Add tests for Poison Puppeteer * Remove parameter properties from `ObtainStatusEffectPhase`
This commit is contained in:
parent
15f668e1b5
commit
46df6adab3
@ -3627,8 +3627,6 @@ export class ProtectStatAbAttr extends PreStatStageChangeAbAttr {
|
||||
export interface ConfusionOnStatusEffectAbAttrParams extends AbAttrBaseParams {
|
||||
/** The status effect that was applied */
|
||||
effect: StatusEffect;
|
||||
/** The move that applied the status effect */
|
||||
move: Move;
|
||||
/** The opponent that was inflicted with the status effect */
|
||||
opponent: Pokemon;
|
||||
}
|
||||
@ -3657,9 +3655,9 @@ export class ConfusionOnStatusEffectAbAttr extends AbAttr {
|
||||
/**
|
||||
* Applies confusion to the target pokemon.
|
||||
*/
|
||||
override apply({ opponent, simulated, pokemon, move }: ConfusionOnStatusEffectAbAttrParams): void {
|
||||
override apply({ opponent, simulated, pokemon }: ConfusionOnStatusEffectAbAttrParams): void {
|
||||
if (!simulated) {
|
||||
opponent.addTag(BattlerTagType.CONFUSED, pokemon.randBattleSeedIntRange(2, 5), move.id, opponent.id);
|
||||
opponent.addTag(BattlerTagType.CONFUSED, pokemon.randBattleSeedIntRange(2, 5), undefined, opponent.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -992,7 +992,7 @@ class ToxicSpikesTag extends EntryHazardTag {
|
||||
|
||||
// Attempt to poison the target, suppressing any status effect messages
|
||||
const effect = this.layers === 1 ? StatusEffect.POISON : StatusEffect.TOXIC;
|
||||
return pokemon.trySetStatus(effect, null, 0, this.getMoveName(), false, true);
|
||||
return pokemon.trySetStatus(effect, undefined, 0, this.getMoveName(), false, true);
|
||||
}
|
||||
|
||||
getMatchupScoreMultiplier(pokemon: Pokemon): number {
|
||||
|
||||
@ -2955,14 +2955,9 @@ export class StatusEffectAttr extends MoveEffectAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
// non-status moves don't play sound effects for failures
|
||||
const quiet = move.category !== MoveCategory.STATUS;
|
||||
|
||||
if (target.trySetStatus(this.effect, user, undefined, null, false, quiet)) {
|
||||
applyAbAttrs("ConfusionOnStatusEffectAbAttr", { pokemon: user, opponent: target, move, effect: this.effect });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return target.trySetStatus(this.effect, user, undefined, null, false, quiet);
|
||||
}
|
||||
|
||||
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number {
|
||||
|
||||
@ -4863,7 +4863,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
*/
|
||||
public trySetStatus(
|
||||
effect: StatusEffect,
|
||||
sourcePokemon: Pokemon | null = null,
|
||||
sourcePokemon?: Pokemon,
|
||||
sleepTurnsRemaining?: number,
|
||||
sourceText: string | null = null,
|
||||
overrideStatus?: boolean,
|
||||
|
||||
@ -13,6 +13,11 @@ import { PokemonPhase } from "#phases/pokemon-phase";
|
||||
export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||
public readonly phaseName = "ObtainStatusEffectPhase";
|
||||
|
||||
private readonly statusEffect: StatusEffect;
|
||||
private readonly sourcePokemon?: Pokemon;
|
||||
private readonly sleepTurnsRemaining?: number;
|
||||
private readonly statusMessage: string;
|
||||
|
||||
/**
|
||||
* @param battlerIndex - The {@linkcode BattlerIndex} of the Pokemon obtaining the status effect.
|
||||
* @param statusEffect - The {@linkcode StatusEffect} being applied.
|
||||
@ -27,19 +32,20 @@ export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||
*/
|
||||
constructor(
|
||||
battlerIndex: BattlerIndex,
|
||||
private statusEffect: StatusEffect,
|
||||
private sourcePokemon: Pokemon | null = null,
|
||||
private sleepTurnsRemaining?: number,
|
||||
sourceText: string | null = null, // TODO: This should take `undefined` instead of `null`
|
||||
private statusMessage = "",
|
||||
statusEffect: StatusEffect,
|
||||
sourcePokemon?: Pokemon,
|
||||
sleepTurnsRemaining?: number,
|
||||
sourceText: string | null = null, // TODO: this should be `sourceText?: string`, and then remove `?? undefined` below
|
||||
statusMessage?: string,
|
||||
) {
|
||||
super(battlerIndex);
|
||||
|
||||
this.statusMessage ||= getStatusEffectObtainText(
|
||||
statusEffect,
|
||||
getPokemonNameWithAffix(this.getPokemon()),
|
||||
sourceText ?? undefined,
|
||||
);
|
||||
this.statusEffect = statusEffect;
|
||||
this.sourcePokemon = sourcePokemon;
|
||||
this.sleepTurnsRemaining = sleepTurnsRemaining;
|
||||
this.statusMessage =
|
||||
statusMessage
|
||||
|| getStatusEffectObtainText(statusEffect, getPokemonNameWithAffix(this.getPokemon()), sourceText ?? undefined);
|
||||
}
|
||||
|
||||
start() {
|
||||
@ -58,8 +64,15 @@ export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||
applyAbAttrs("PostSetStatusAbAttr", {
|
||||
pokemon,
|
||||
effect: this.statusEffect,
|
||||
sourcePokemon: this.sourcePokemon ?? undefined,
|
||||
sourcePokemon: this.sourcePokemon,
|
||||
});
|
||||
if (this.sourcePokemon) {
|
||||
applyAbAttrs("ConfusionOnStatusEffectAbAttr", {
|
||||
pokemon: this.sourcePokemon,
|
||||
opponent: pokemon,
|
||||
effect: this.statusEffect,
|
||||
});
|
||||
}
|
||||
}
|
||||
this.end();
|
||||
});
|
||||
|
||||
112
test/abilities/poison-puppeteer.test.ts
Normal file
112
test/abilities/poison-puppeteer.test.ts
Normal file
@ -0,0 +1,112 @@
|
||||
import { allAbilities } from "#data/data-lists";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
describe("Abilities - Poison Puppeteer", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.ability(AbilityId.POISON_PUPPETEER)
|
||||
.battleStyle("single")
|
||||
.criticalHits(false)
|
||||
.enemySpecies(SpeciesId.MAGIKARP)
|
||||
.enemyAbility(AbilityId.BALL_FETCH)
|
||||
.enemyLevel(100)
|
||||
.enemyMoveset(MoveId.SPLASH);
|
||||
});
|
||||
|
||||
it("should confuse the target if the user poisons the target directly", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAREANIE]);
|
||||
|
||||
game.move.use(MoveId.MORTAL_SPIN);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon).toHaveStatusEffect(StatusEffect.POISON);
|
||||
expect(enemyPokemon).toHaveBattlerTag(BattlerTagType.CONFUSED);
|
||||
});
|
||||
|
||||
it("should confuse the target if the user badly poisons the target directly", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAREANIE]);
|
||||
|
||||
game.move.use(MoveId.TOXIC);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon).toHaveStatusEffect(StatusEffect.TOXIC);
|
||||
expect(enemyPokemon).toHaveBattlerTag(BattlerTagType.CONFUSED);
|
||||
});
|
||||
|
||||
it("should not confuse the target if the user poisons the target via Toxic Spikes", async () => {
|
||||
game.override.startingWave(5);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
game.move.use(MoveId.TOXIC_SPIKES);
|
||||
await game.toNextTurn();
|
||||
|
||||
game.move.use(MoveId.SPLASH);
|
||||
game.forceEnemyToSwitch();
|
||||
await game.toEndOfTurn();
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon).toHaveStatusEffect(StatusEffect.POISON);
|
||||
expect(enemyPokemon).not.toHaveBattlerTag(BattlerTagType.CONFUSED);
|
||||
});
|
||||
|
||||
it("should not confuse the target if the user paralyzes the target", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
game.move.use(MoveId.NUZZLE);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon).toHaveStatusEffect(StatusEffect.PARALYSIS);
|
||||
expect(enemyPokemon).not.toHaveBattlerTag(BattlerTagType.CONFUSED);
|
||||
});
|
||||
|
||||
it("should confuse the target if the target was poisoned due to Synchronize", async () => {
|
||||
game.override.passiveAbility(AbilityId.SYNCHRONIZE).enemyAbility(AbilityId.NO_GUARD);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
game.move.use(MoveId.SPLASH);
|
||||
await game.move.forceEnemyMove(MoveId.POISON_POWDER);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
expect(game.field.getEnemyPokemon()).toHaveStatusEffect(StatusEffect.POISON);
|
||||
expect(game.field.getEnemyPokemon()).toHaveBattlerTag(BattlerTagType.CONFUSED);
|
||||
});
|
||||
|
||||
it("should confuse the target if the target was poisoned due to Toxic Chain", async () => {
|
||||
game.override.passiveAbility(AbilityId.TOXIC_CHAIN);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const toxicChainAttr = allAbilities[AbilityId.TOXIC_CHAIN].getAttrs("PostAttackApplyStatusEffectAbAttr")[0];
|
||||
// @ts-expect-error: `chance` is private
|
||||
vi.spyOn(toxicChainAttr, "chance", "get").mockReturnValue(100);
|
||||
|
||||
game.move.use(MoveId.TACKLE);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
expect(game.field.getEnemyPokemon()).toHaveStatusEffect(StatusEffect.TOXIC);
|
||||
expect(game.field.getEnemyPokemon()).toHaveBattlerTag(BattlerTagType.CONFUSED);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user