mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-25 16:59:27 +02:00
Implement Plasma Fists
This commit is contained in:
parent
70c6edfaed
commit
4d756e8fa4
@ -511,6 +511,39 @@ class WaterSportTag extends WeakenMoveTypeTag {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Arena Tag class for the secondary effect of {@link https://bulbapedia.bulbagarden.net/wiki/Plasma_Fists_(move) | Plasma Fists}.
|
||||
* Converts Normal-type moves to Electric type for the rest of the turn.
|
||||
*/
|
||||
export class PlasmaFistsTag extends ArenaTag {
|
||||
constructor() {
|
||||
super(ArenaTagType.PLASMA_FISTS, 1, Moves.PLASMA_FISTS);
|
||||
}
|
||||
|
||||
/** Queues Plasma Fists' on-add message */
|
||||
onAdd(arena: Arena): void {
|
||||
arena.scene.queueMessage(i18next.t("arenaTag:plasmaFistsOnAdd"));
|
||||
}
|
||||
|
||||
onRemove(arena: Arena): void { } // Removes default on-remove message
|
||||
|
||||
/**
|
||||
* Converts Normal-type moves to Electric type
|
||||
* @param arena n/a
|
||||
* @param args
|
||||
* - `[0]` {@linkcode Utils.NumberHolder} A container with a move's {@linkcode Type}
|
||||
* @returns `true` if the given move type changed; `false` otherwise.
|
||||
*/
|
||||
apply(arena: Arena, args: any[]): boolean {
|
||||
const moveType = args[0];
|
||||
if (moveType instanceof Utils.NumberHolder && moveType.value === Type.NORMAL) {
|
||||
moveType.value = Type.ELECTRIC;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class to implement arena traps.
|
||||
*/
|
||||
@ -1010,6 +1043,8 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
|
||||
return new MudSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.WATER_SPORT:
|
||||
return new WaterSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.PLASMA_FISTS:
|
||||
return new PlasmaFistsTag();
|
||||
case ArenaTagType.SPIKES:
|
||||
return new SpikesTag(sourceId, side);
|
||||
case ArenaTagType.TOXIC_SPIKES:
|
||||
|
@ -8869,8 +8869,8 @@ export function initMoves() {
|
||||
.attr(HalfSacrificialAttr)
|
||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||
new AttackMove(Moves.PLASMA_FISTS, Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 100, 15, -1, 0, 7)
|
||||
.punchingMove()
|
||||
.partial(),
|
||||
.attr(AddArenaTagAttr, ArenaTagType.PLASMA_FISTS, 1)
|
||||
.punchingMove(),
|
||||
new AttackMove(Moves.PHOTON_GEYSER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
||||
.attr(PhotonGeyserCategoryAttr)
|
||||
.ignoresAbilities()
|
||||
|
@ -25,4 +25,5 @@ export enum ArenaTagType {
|
||||
SAFEGUARD = "SAFEGUARD",
|
||||
NO_CRIT = "NO_CRIT",
|
||||
IMPRISON = "IMPRISON",
|
||||
PLASMA_FISTS = "PLASMA_FISTS",
|
||||
}
|
||||
|
@ -1508,6 +1508,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder);
|
||||
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder);
|
||||
|
||||
this.scene.arena.applyTags(ArenaTagType.PLASMA_FISTS, moveTypeHolder);
|
||||
|
||||
return moveTypeHolder.value as Type;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
"mudSportOnRemove": "The effects of Mud Sport\nhave faded.",
|
||||
"waterSportOnAdd": "Fire's power was weakened!",
|
||||
"waterSportOnRemove": "The effects of Water Sport\nhave faded.",
|
||||
"plasmaFistsOnAdd": "A deluge of ions showers the battlefield!",
|
||||
"spikesOnAdd": "{{moveName}} were scattered\nall around {{opponentDesc}}'s feet!",
|
||||
"spikesActivateTrap": "{{pokemonNameWithAffix}} is hurt\nby the spikes!",
|
||||
"toxicSpikesOnAdd": "{{moveName}} were scattered\nall around {{opponentDesc}}'s feet!",
|
||||
|
98
src/test/moves/plasma_fists.test.ts
Normal file
98
src/test/moves/plasma_fists.test.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { Type } from "#app/data/type";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
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, it, expect, vi } from "vitest";
|
||||
|
||||
describe("Moves - Plasma Fists", () => {
|
||||
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.PLASMA_FISTS, Moves.TACKLE])
|
||||
.battleType("double")
|
||||
.startingLevel(100)
|
||||
.enemySpecies(Species.DUSCLOPS)
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.TACKLE)
|
||||
.enemyLevel(100);
|
||||
});
|
||||
|
||||
it("should convert all subsequent Normal-type attacks to Electric-type", async () => {
|
||||
await game.classicMode.startBattle([Species.DUSCLOPS, Species.BLASTOISE]);
|
||||
|
||||
const field = game.scene.getField(true);
|
||||
field.forEach(p => vi.spyOn(p, "getMoveType"));
|
||||
|
||||
game.move.select(Moves.PLASMA_FISTS, 0, BattlerIndex.ENEMY);
|
||||
game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY_2);
|
||||
|
||||
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER);
|
||||
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2);
|
||||
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
field.forEach(p => {
|
||||
expect(p.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC);
|
||||
expect(p.hp).toBeLessThan(p.getMaxHp());
|
||||
});
|
||||
});
|
||||
|
||||
it("should not affect Normal-type attacks boosted by Pixilate", async () => {
|
||||
game.override
|
||||
.battleType("single")
|
||||
.enemyAbility(Abilities.PIXILATE);
|
||||
|
||||
await game.classicMode.startBattle([Species.ONIX]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemyPokemon, "getMoveType");
|
||||
|
||||
game.move.select(Moves.PLASMA_FISTS);
|
||||
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(enemyPokemon.getMoveType).toHaveLastReturnedWith(Type.FAIRY);
|
||||
expect(playerPokemon.hp).toBeLessThan(playerPokemon.getMaxHp());
|
||||
});
|
||||
|
||||
it("should affect moves that become Normal type due to Normalize", async () => {
|
||||
game.override
|
||||
.battleType("single")
|
||||
.enemyAbility(Abilities.NORMALIZE)
|
||||
.enemyMoveset(Moves.WATER_GUN);
|
||||
|
||||
await game.classicMode.startBattle([Species.DUSCLOPS]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemyPokemon, "getMoveType");
|
||||
|
||||
game.move.select(Moves.PLASMA_FISTS);
|
||||
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(enemyPokemon.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC);
|
||||
expect(playerPokemon.hp).toBeLessThan(playerPokemon.getMaxHp());
|
||||
});
|
||||
});
|
@ -300,7 +300,7 @@ export default class GameManager {
|
||||
|
||||
vi.spyOn(enemy, "getNextMove").mockReturnValueOnce({
|
||||
move: moveId,
|
||||
targets: (target && !legalTargets.multiple && legalTargets.targets.includes(target))
|
||||
targets: (target !== undefined && !legalTargets.multiple && legalTargets.targets.includes(target))
|
||||
? [target]
|
||||
: enemy.getNextTargets(moveId)
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user