mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-18 05:19:29 +02:00
Merge b70bc05ae7
into f83ab00ce4
This commit is contained in:
commit
dbf6f1f35d
@ -975,7 +975,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
this.updateModifiers(true);
|
this.updateModifiers(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
addPokemonIcon(pokemon: Pokemon, x: number, y: number, originX: number = 0.5, originY: number = 0.5, ignoreOverride: boolean = false): Phaser.GameObjects.Container {
|
addPokemonIcon(pokemon: Pokemon, x: number, y: number, originX: number = 0.5, originY: number = 0.5, ignoreOverride: boolean = false, tint?: boolean): Phaser.GameObjects.Container {
|
||||||
const container = this.add.container(x, y);
|
const container = this.add.container(x, y);
|
||||||
container.setName(`${pokemon.name}-icon`);
|
container.setName(`${pokemon.name}-icon`);
|
||||||
|
|
||||||
@ -992,6 +992,11 @@ export default class BattleScene extends SceneBase {
|
|||||||
pokemon.shiny = temp;
|
pokemon.shiny = temp;
|
||||||
}
|
}
|
||||||
icon.setOrigin(0.5, 0);
|
icon.setOrigin(0.5, 0);
|
||||||
|
if (tint) {
|
||||||
|
icon.setTint(0x838383);
|
||||||
|
} else {
|
||||||
|
icon.clearTint();
|
||||||
|
}
|
||||||
|
|
||||||
container.add(icon);
|
container.add(icon);
|
||||||
|
|
||||||
|
@ -7886,6 +7886,61 @@ export class ExposedMoveAttr extends AddBattlerTagAttr {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Nullifies a Pokemon's held item until the battle ends.
|
||||||
|
* Simulates the item being removed, but it just neutralizes it until the next battle
|
||||||
|
* Used by: {@linkcode Moves.CORROSIVE_GAS | Corrosive Gas}
|
||||||
|
*
|
||||||
|
* @extends MoveEffectAttr
|
||||||
|
* @see {@linkcode apply}
|
||||||
|
*/
|
||||||
|
export class NullifyHeldItemAttr extends MoveEffectAttr {
|
||||||
|
public turnCount: integer;
|
||||||
|
constructor(turnCount: integer) {
|
||||||
|
super(false, { trigger: MoveEffectTrigger.HIT });
|
||||||
|
this.turnCount = turnCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param user {@linkcode Pokemon} that used the move
|
||||||
|
* @param target Target {@linkcode Pokemon} that the moves applies to
|
||||||
|
* @param move {@linkcode Move} that is used
|
||||||
|
* @param args N/A
|
||||||
|
* @returns {boolean} True if an item was nullified
|
||||||
|
*/
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
if (move.hitsSubstitute(user, target)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const cancelled = new Utils.BooleanHolder(false);
|
||||||
|
applyAbAttrs(BlockItemTheftAbAttr, target, cancelled); // Check for abilities that block item theft
|
||||||
|
if (cancelled.value === true) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const heldItems = this.getTargetHeldItems(target).filter(i => i.isTransferable && !i.isNullified);
|
||||||
|
|
||||||
|
if (heldItems.length) {
|
||||||
|
const nullifiedItem = heldItems[user.randSeedInt(heldItems.length)];
|
||||||
|
|
||||||
|
nullifiedItem.nullify(this.turnCount);
|
||||||
|
target.scene.updateModifiers(target.isPlayer());
|
||||||
|
|
||||||
|
user.scene.queueMessage(i18next.t("moveTriggers:corrosiveGasItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: nullifiedItem.type.name }));
|
||||||
|
|
||||||
|
}
|
||||||
|
if (move.id === Moves.CORROSIVE_GAS) {
|
||||||
|
applyPostItemLostAbAttrs(PostItemLostAbAttr, target, false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
||||||
|
return target.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||||
|
&& m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const unknownTypeCondition: MoveConditionFunc = (user, target, move) => !user.getTypes().includes(Type.UNKNOWN);
|
const unknownTypeCondition: MoveConditionFunc = (user, target, move) => !user.getTypes().includes(Type.UNKNOWN);
|
||||||
@ -10425,7 +10480,7 @@ export function initMoves() {
|
|||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new StatusMove(Moves.CORROSIVE_GAS, Type.POISON, 100, 40, -1, 0, 8)
|
new StatusMove(Moves.CORROSIVE_GAS, Type.POISON, 100, 40, -1, 0, 8)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS)
|
.target(MoveTarget.ALL_NEAR_OTHERS)
|
||||||
.unimplemented(),
|
.attr(NullifyHeldItemAttr, 1),
|
||||||
new StatusMove(Moves.COACHING, Type.FIGHTING, -1, 10, -1, 0, 8)
|
new StatusMove(Moves.COACHING, Type.FIGHTING, -1, 10, -1, 0, 8)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF ], 1)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF ], 1)
|
||||||
.target(MoveTarget.NEAR_ALLY)
|
.target(MoveTarget.NEAR_ALLY)
|
||||||
|
@ -646,23 +646,39 @@ export class TerastallizeAccessModifier extends PersistentModifier {
|
|||||||
export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
||||||
public pokemonId: number;
|
public pokemonId: number;
|
||||||
public isTransferable: boolean = true;
|
public isTransferable: boolean = true;
|
||||||
|
public isNullified: boolean = false;
|
||||||
|
/** The maximum amount of battles the modifier will exist for */
|
||||||
|
private maxBattles: number | undefined;
|
||||||
|
/** The current amount of battles the modifier will exist for */
|
||||||
|
private battleCount: number | undefined;
|
||||||
|
|
||||||
constructor(type: ModifierType, pokemonId: number, stackCount?: number) {
|
constructor(type: ModifierType, pokemonId: number, stackCount?: number, maxBattles?: number, battleCount?: number) {
|
||||||
super(type, stackCount);
|
super(type, stackCount);
|
||||||
|
|
||||||
this.pokemonId = pokemonId;
|
this.pokemonId = pokemonId;
|
||||||
|
this.maxBattles = maxBattles;
|
||||||
|
this.battleCount = battleCount ?? this.maxBattles;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract matchType(_modifier: Modifier): boolean;
|
abstract matchType(_modifier: Modifier): boolean;
|
||||||
|
|
||||||
match(modifier: Modifier) {
|
match(modifier: Modifier) {
|
||||||
return this.matchType(modifier) && (modifier as PokemonHeldItemModifier).pokemonId === this.pokemonId;
|
return this.matchType(modifier) && (modifier as PokemonHeldItemModifier).pokemonId === this.pokemonId && !this.isNullified;
|
||||||
}
|
}
|
||||||
|
|
||||||
getArgs(): any[] {
|
getArgs(): any[] {
|
||||||
return [ this.pokemonId ];
|
return [ this.pokemonId ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nullify(count: number) {
|
||||||
|
this.setNewBattleCount(count);
|
||||||
|
this.isNullified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeNullification() {
|
||||||
|
this.isNullified = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the {@linkcode PokemonHeldItemModifier} to the given {@linkcode Pokemon}.
|
* Applies the {@linkcode PokemonHeldItemModifier} to the given {@linkcode Pokemon}.
|
||||||
* @param pokemon The {@linkcode Pokemon} that holds the held item
|
* @param pokemon The {@linkcode Pokemon} that holds the held item
|
||||||
@ -677,7 +693,7 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
|||||||
* @returns if {@linkcode PokemonHeldItemModifier} should be applied
|
* @returns if {@linkcode PokemonHeldItemModifier} should be applied
|
||||||
*/
|
*/
|
||||||
override shouldApply(pokemon?: Pokemon, ..._args: unknown[]): boolean {
|
override shouldApply(pokemon?: Pokemon, ..._args: unknown[]): boolean {
|
||||||
return !!pokemon && (this.pokemonId === -1 || pokemon.id === this.pokemonId);
|
return !this.isNullified && !!pokemon && (this.pokemonId === -1 || pokemon.id === this.pokemonId);
|
||||||
}
|
}
|
||||||
|
|
||||||
isIconVisible(scene: BattleScene): boolean {
|
isIconVisible(scene: BattleScene): boolean {
|
||||||
@ -690,7 +706,7 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
|||||||
if (!forSummary) {
|
if (!forSummary) {
|
||||||
const pokemon = this.getPokemon(scene);
|
const pokemon = this.getPokemon(scene);
|
||||||
if (pokemon) {
|
if (pokemon) {
|
||||||
const pokemonIcon = scene.addPokemonIcon(pokemon, -2, 10, 0, 0.5);
|
const pokemonIcon = scene.addPokemonIcon(pokemon, -2, 10, 0, 0.5, false, this.isNullified);
|
||||||
container.add(pokemonIcon);
|
container.add(pokemonIcon);
|
||||||
container.setName(pokemon.id.toString());
|
container.setName(pokemon.id.toString());
|
||||||
}
|
}
|
||||||
@ -699,6 +715,11 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
|||||||
item.setScale(0.5);
|
item.setScale(0.5);
|
||||||
item.setOrigin(0, 0.5);
|
item.setOrigin(0, 0.5);
|
||||||
item.setTexture("items", this.type.iconImage);
|
item.setTexture("items", this.type.iconImage);
|
||||||
|
if (this.isNullified) {
|
||||||
|
item.setTint(0x838383);
|
||||||
|
} else {
|
||||||
|
item.clearTint();
|
||||||
|
}
|
||||||
container.add(item);
|
container.add(item);
|
||||||
|
|
||||||
const stackText = this.getIconStackText(scene);
|
const stackText = this.getIconStackText(scene);
|
||||||
@ -714,6 +735,28 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
|||||||
container.setScale(0.5);
|
container.setScale(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.battleCount && this.maxBattles && this.getPokemon(scene)?.isPlayer()) {
|
||||||
|
let hue;
|
||||||
|
if (this.isNullified) {
|
||||||
|
hue = 0;
|
||||||
|
} else {
|
||||||
|
hue = Math.floor(120 * (this.battleCount / this.maxBattles) + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates the color hex code with a constant saturation and lightness but varying hue
|
||||||
|
const typeHex = hslToHex(hue, 0.5, 0.9);
|
||||||
|
const strokeHex = hslToHex(hue, 0.7, 0.3);
|
||||||
|
|
||||||
|
const battleCountText = addTextObject(scene, 27, 0, this.battleCount.toString(), TextStyle.PARTY, {
|
||||||
|
fontSize: "66px",
|
||||||
|
color: typeHex,
|
||||||
|
});
|
||||||
|
battleCountText.setShadow(0, 0);
|
||||||
|
battleCountText.setStroke(strokeHex, 16);
|
||||||
|
battleCountText.setOrigin(1, 0);
|
||||||
|
container.add(battleCountText);
|
||||||
|
}
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,6 +780,57 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract getMaxHeldItemCount(pokemon?: Pokemon): number;
|
abstract getMaxHeldItemCount(pokemon?: Pokemon): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lapses the {@linkcode battleCount} by 1.
|
||||||
|
* @param _args passed arguments (not in use here)
|
||||||
|
* @returns `true` if the {@linkcode battleCount} is greater than 0
|
||||||
|
*/
|
||||||
|
public lapse(..._args: unknown[]): void {
|
||||||
|
if (this.battleCount) {
|
||||||
|
this.battleCount--;
|
||||||
|
if (this.battleCount === 0 && this.isNullified) {
|
||||||
|
this.removeNullification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getIconStackText(_scene: BattleScene, _virtual?: boolean): Phaser.GameObjects.BitmapText | null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBattleCount(): number {
|
||||||
|
if (this.battleCount) {
|
||||||
|
return this.battleCount;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetBattleCount(): void {
|
||||||
|
this.battleCount = this.maxBattles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates an existing modifier with a new `maxBattles` and `battleCount`.
|
||||||
|
*/
|
||||||
|
setNewBattleCount(count: number): void {
|
||||||
|
this.maxBattles = count;
|
||||||
|
this.battleCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMaxBattles(): number {
|
||||||
|
if (this.maxBattles) {
|
||||||
|
return this.maxBattles;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getBattleCountArgs(): any[] {
|
||||||
|
return [ this.maxBattles, this.battleCount ];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class LapsingPokemonHeldItemModifier extends PokemonHeldItemModifier {
|
export abstract class LapsingPokemonHeldItemModifier extends PokemonHeldItemModifier {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/ability";
|
import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/ability";
|
||||||
import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier";
|
import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
import { GameOverPhase } from "./game-over-phase";
|
import { GameOverPhase } from "./game-over-phase";
|
||||||
|
|
||||||
@ -52,16 +52,18 @@ export class BattleEndPhase extends BattlePhase {
|
|||||||
|
|
||||||
this.scene.clearEnemyHeldItemModifiers();
|
this.scene.clearEnemyHeldItemModifiers();
|
||||||
|
|
||||||
const lapsingModifiers = this.scene.findModifiers(m => m instanceof LapsingPersistentModifier || m instanceof LapsingPokemonHeldItemModifier) as (LapsingPersistentModifier | LapsingPokemonHeldItemModifier)[];
|
const lapsingModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.isNullified || m instanceof LapsingPersistentModifier || m instanceof LapsingPokemonHeldItemModifier) as (PokemonHeldItemModifier | LapsingPersistentModifier | LapsingPokemonHeldItemModifier)[];
|
||||||
for (const m of lapsingModifiers) {
|
for (const m of lapsingModifiers) {
|
||||||
const args: any[] = [];
|
const args: any[] = [];
|
||||||
if (m instanceof LapsingPokemonHeldItemModifier) {
|
if (m instanceof LapsingPokemonHeldItemModifier) {
|
||||||
args.push(this.scene.getPokemonById(m.pokemonId));
|
args.push(this.scene.getPokemonById(m.pokemonId));
|
||||||
}
|
}
|
||||||
if (!m.lapse(...args)) {
|
if (!m.lapse(...args)) {
|
||||||
|
if (!(m instanceof PokemonHeldItemModifier)) {
|
||||||
this.scene.removeModifier(m);
|
this.scene.removeModifier(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.scene.updateModifiers().then(() => this.end());
|
this.scene.updateModifiers().then(() => this.end());
|
||||||
}
|
}
|
||||||
|
292
src/test/moves/corrosive_gas.test.ts
Normal file
292
src/test/moves/corrosive_gas.test.ts
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
import { Abilities } from "#app/enums/abilities";
|
||||||
|
import { BerryType } from "#app/enums/berry-type";
|
||||||
|
import { WeatherType } from "#app/enums/weather-type";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import GameManager from "#test/utils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("Moves - Corrosive Gas", () => {
|
||||||
|
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
|
||||||
|
.moveset([ Moves.SPLASH, Moves.CORROSIVE_GAS ])
|
||||||
|
.battleType("double")
|
||||||
|
.enemySpecies(Species.MAGIKARP)
|
||||||
|
.enemyMoveset(Moves.SPLASH);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Corrosive Gas should nullify enemy and ally items", async () => {
|
||||||
|
game.override
|
||||||
|
.enemyHeldItems([
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
])
|
||||||
|
.startingHeldItems(
|
||||||
|
[
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
await game.classicMode.startBattle([ Species.STAKATAKA, Species.SALAZZLE ]);
|
||||||
|
const playerPokemon = game.scene.getPlayerField()!;
|
||||||
|
const enemyPokemon = game.scene.getEnemyField()!;
|
||||||
|
|
||||||
|
const staka = playerPokemon[0];
|
||||||
|
const karp1 = enemyPokemon[0];
|
||||||
|
const karp2 = enemyPokemon[1];
|
||||||
|
|
||||||
|
staka.hp *= 0.5;
|
||||||
|
karp1.hp *= 0.5;
|
||||||
|
karp2.hp *= 0.5;
|
||||||
|
|
||||||
|
const stakaHeldItems = staka.getHeldItems();
|
||||||
|
const magikarpItems1 = karp1.getHeldItems();
|
||||||
|
const magikarpItems2 = karp2.getHeldItems();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.CORROSIVE_GAS);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
expect(stakaHeldItems[0].isNullified).toEqual(true);
|
||||||
|
expect(magikarpItems1[0].isNullified).toEqual(true);
|
||||||
|
expect(magikarpItems2[0].isNullified).toEqual(true);
|
||||||
|
|
||||||
|
expect(staka.getHpRatio()).toBeCloseTo(0.5);
|
||||||
|
expect(karp1.getHpRatio()).toBeCloseTo(0.5);
|
||||||
|
expect(karp2.getHpRatio()).toBeCloseTo(0.5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Items should not be nullified the following battle", async () => {
|
||||||
|
game.override
|
||||||
|
.enemyHeldItems([
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
])
|
||||||
|
.startingHeldItems(
|
||||||
|
[
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
await game.classicMode.startBattle([ Species.STAKATAKA, Species.SALAZZLE ]);
|
||||||
|
const playerPokemon = game.scene.getPlayerField()!;
|
||||||
|
const staka = playerPokemon[0];
|
||||||
|
staka.hp *= 0.5;
|
||||||
|
const stakaHeldItems = staka.getHeldItems();
|
||||||
|
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.CORROSIVE_GAS);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
expect(stakaHeldItems[0].isNullified).toEqual(true);
|
||||||
|
expect(staka.getHpRatio()).toBeCloseTo(0.5);
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.doKillOpponents();
|
||||||
|
game.doSelectModifier();
|
||||||
|
await game.phaseInterceptor.to("TurnInitPhase");
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
|
||||||
|
expect(stakaHeldItems[0].isNullified).toEqual(false);
|
||||||
|
expect(staka.getHpRatio()).toBeGreaterThan(0.5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Corrosive Gas should not remove untransferrable items", async () => {
|
||||||
|
game.override
|
||||||
|
.enemyMoveset(Moves.CORROSIVE_GAS)
|
||||||
|
.startingHeldItems(
|
||||||
|
[
|
||||||
|
{ name: "MYSTERY_ENCOUNTER_MACHO_BRACE", count: 1 }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
await game.classicMode.startBattle([ Species.GIRATINA, Species.AGGRON ]);
|
||||||
|
const playerPokemon = game.scene.getPlayerField()!;
|
||||||
|
const giratina = playerPokemon[0];
|
||||||
|
const giratinaHeldItems = giratina.getHeldItems();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
|
||||||
|
expect(giratinaHeldItems[0].isNullified).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Corrosive Gas should not nullify items from sticky hold users", async () => {
|
||||||
|
game.override
|
||||||
|
.enemyAbility(Abilities.STICKY_HOLD)
|
||||||
|
.enemyHeldItems([
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
])
|
||||||
|
.startingHeldItems(
|
||||||
|
[
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
await game.classicMode.startBattle([ Species.STAKATAKA, Species.SALAZZLE ]);
|
||||||
|
const playerPokemon = game.scene.getPlayerField()!;
|
||||||
|
const enemyPokemon = game.scene.getEnemyField()!;
|
||||||
|
|
||||||
|
const staka = playerPokemon[0];
|
||||||
|
const karp1 = enemyPokemon[0];
|
||||||
|
const karp2 = enemyPokemon[1];
|
||||||
|
|
||||||
|
staka.hp *= 0.5;
|
||||||
|
karp1.hp *= 0.5;
|
||||||
|
karp2.hp *= 0.5;
|
||||||
|
|
||||||
|
const stakaHeldItems = staka.getHeldItems();
|
||||||
|
const magikarpItems1 = karp1.getHeldItems();
|
||||||
|
const magikarpItems2 = karp2.getHeldItems();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.CORROSIVE_GAS);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
expect(stakaHeldItems[0].isNullified).toEqual(true);
|
||||||
|
expect(magikarpItems1[0].isNullified).toEqual(false);
|
||||||
|
expect(magikarpItems2[0].isNullified).toEqual(false);
|
||||||
|
|
||||||
|
expect(staka.getHpRatio()).toBeCloseTo(0.5);
|
||||||
|
expect(karp1.getHpRatio()).toBeGreaterThan(0.5);
|
||||||
|
expect(karp2.getHpRatio()).toBeGreaterThan(0.5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Corrosive Gas should not nullify items if it hits a substitute", async () => {
|
||||||
|
game.override
|
||||||
|
.moveset([ Moves.SPLASH, Moves.CORROSIVE_GAS, Moves.SUBSTITUTE ])
|
||||||
|
.enemyHeldItems([
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
])
|
||||||
|
.startingHeldItems(
|
||||||
|
[
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
await game.classicMode.startBattle([ Species.STAKATAKA, Species.SALAZZLE ]);
|
||||||
|
const playerPokemon = game.scene.getPlayerField()!;
|
||||||
|
const staka = playerPokemon[0];
|
||||||
|
staka.hp *= 0.5;
|
||||||
|
|
||||||
|
const stakaHeldItems = staka.getHeldItems();
|
||||||
|
|
||||||
|
game.move.select(Moves.SUBSTITUTE);
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.CORROSIVE_GAS);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
expect(stakaHeldItems[0].isNullified).toEqual(false);
|
||||||
|
|
||||||
|
expect(staka.getHpRatio()).toBeGreaterThan(0.25);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Items nullified cannot be reobtained with Harvest", async () => {
|
||||||
|
game.override
|
||||||
|
.weather(WeatherType.SUNNY)
|
||||||
|
.ability(Abilities.HARVEST)
|
||||||
|
.enemyAbility(Abilities.HARVEST)
|
||||||
|
.enemyHeldItems([
|
||||||
|
{ name: "BERRY", type: BerryType.SITRUS, count: 1 },
|
||||||
|
])
|
||||||
|
.startingHeldItems(
|
||||||
|
[
|
||||||
|
{ name: "BERRY", type: BerryType.SITRUS, count: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
await game.classicMode.startBattle([ Species.STAKATAKA, Species.SALAZZLE ]);
|
||||||
|
const playerPokemon = game.scene.getPlayerField()!;
|
||||||
|
const enemyPokemon = game.scene.getEnemyField()!;
|
||||||
|
|
||||||
|
const staka = playerPokemon[0];
|
||||||
|
const karp1 = enemyPokemon[0];
|
||||||
|
const karp2 = enemyPokemon[1];
|
||||||
|
|
||||||
|
staka.hp *= 0.1;
|
||||||
|
karp1.hp *= 0.1;
|
||||||
|
karp2.hp *= 0.1;
|
||||||
|
|
||||||
|
const stakaHeldItems = staka.getHeldItems();
|
||||||
|
const magikarpItems1 = karp1.getHeldItems();
|
||||||
|
const magikarpItems2 = karp2.getHeldItems();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.CORROSIVE_GAS);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
|
||||||
|
expect(stakaHeldItems[0].isNullified).toEqual(true);
|
||||||
|
expect(magikarpItems1[0].isNullified).toEqual(true);
|
||||||
|
expect(magikarpItems2[0].isNullified).toEqual(true);
|
||||||
|
|
||||||
|
expect(staka.getHpRatio()).toBeCloseTo(0.1);
|
||||||
|
expect(karp1.getHpRatio()).toBeCloseTo(0.1);
|
||||||
|
expect(karp2.getHpRatio()).toBeCloseTo(0.1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Items stay nullified on switch out", async () => {
|
||||||
|
game.override
|
||||||
|
.enemyHeldItems([
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
])
|
||||||
|
.startingHeldItems(
|
||||||
|
[
|
||||||
|
{ name: "LEFTOVERS", count: 1 }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
await game.classicMode.startBattle([ Species.STAKATAKA, Species.SALAZZLE, Species.SALANDIT ]);
|
||||||
|
const playerPokemon = game.scene.getPlayerField()!;
|
||||||
|
|
||||||
|
const staka = playerPokemon[0];
|
||||||
|
|
||||||
|
staka.hp *= 0.5;
|
||||||
|
|
||||||
|
const stakaHeldItems = staka.getHeldItems();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
game.move.select(Moves.CORROSIVE_GAS);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
game.doSwitchPokemon(2);
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
game.doSwitchPokemon(2);
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
expect(stakaHeldItems[0].isNullified).toEqual(true);
|
||||||
|
expect(staka.getHpRatio()).toBeCloseTo(0.5);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user