mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-15 12:52:20 +02:00
Merge 48b3730754
into 2bd07cb84e
This commit is contained in:
commit
33137d1c2e
@ -327,6 +327,49 @@ export class ShellTrapTag extends BattlerTag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BattlerTag implementing Rage
|
||||||
|
* Pokémon with this tag will recieve an attack boost when successfully damaged by an attacking move
|
||||||
|
* This tag will be lost if a target reaches the MOVE_EFFECT lapse condition with a move other than Rage
|
||||||
|
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Rage_(move) | Rage}
|
||||||
|
*/
|
||||||
|
export class RageTag extends BattlerTag {
|
||||||
|
constructor() {
|
||||||
|
super(BattlerTagType.RAGE, [BattlerTagLapseType.MOVE_EFFECT], 1, Moves.RAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a message to show that the user has started Raging.
|
||||||
|
* This is message isn't displayed on cartridge, and was included for clarity during gameplay and while testing.
|
||||||
|
* @param pokemon {@linkcode Pokemon} the Pokémon this tag is being added to.
|
||||||
|
*/
|
||||||
|
onAdd(pokemon: Pokemon) {
|
||||||
|
super.onAdd(pokemon);
|
||||||
|
/* This message might not exist on cartridge */
|
||||||
|
pokemon.scene.queueMessage(i18next.t("battlerTags:rageOnAdd", {
|
||||||
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon)}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to maintain a Pokémon should maintain their rage, and provides an attack boost when hit.
|
||||||
|
* @param pokemon {@linkcode Pokemon} The owner of this tag
|
||||||
|
* @param lapseType {@linkcode BattlerTagLapseType} the type of functionality invoked in battle
|
||||||
|
* @returns `true` if invoked with the MOVE_EFFECT lapse type and {@linkcode pokemon} most recently used Rage,
|
||||||
|
* or if invoked with the CUSTOM lapse type. false otherwise.
|
||||||
|
*/
|
||||||
|
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||||
|
if (lapseType === BattlerTagLapseType.MOVE_EFFECT) {
|
||||||
|
return (pokemon.scene.getCurrentPhase() as MovePhase).move.getMove().id === Moves.RAGE;
|
||||||
|
} else if (lapseType === BattlerTagLapseType.CUSTOM) {
|
||||||
|
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK], 1, false));
|
||||||
|
pokemon.scene.queueMessage(i18next.t("battlerTags:rageOnHit", {
|
||||||
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon)}));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class TrappedTag extends BattlerTag {
|
export class TrappedTag extends BattlerTag {
|
||||||
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: number, sourceMove: Moves, sourceId: number) {
|
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: number, sourceMove: Moves, sourceId: number) {
|
||||||
super(tagType, lapseType, turnCount, sourceMove, sourceId, true);
|
super(tagType, lapseType, turnCount, sourceMove, sourceId, true);
|
||||||
@ -2125,6 +2168,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
|||||||
case BattlerTagType.GULP_MISSILE_ARROKUDA:
|
case BattlerTagType.GULP_MISSILE_ARROKUDA:
|
||||||
case BattlerTagType.GULP_MISSILE_PIKACHU:
|
case BattlerTagType.GULP_MISSILE_PIKACHU:
|
||||||
return new GulpMissileTag(tagType, sourceMove);
|
return new GulpMissileTag(tagType, sourceMove);
|
||||||
|
case BattlerTagType.RAGE:
|
||||||
|
return new RageTag();
|
||||||
case BattlerTagType.NONE:
|
case BattlerTagType.NONE:
|
||||||
default:
|
default:
|
||||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||||
|
@ -6744,7 +6744,7 @@ export function initMoves() {
|
|||||||
.attr(StatStageChangeAttr, [ Stat.SPD ], 2, true),
|
.attr(StatStageChangeAttr, [ Stat.SPD ], 2, true),
|
||||||
new AttackMove(Moves.QUICK_ATTACK, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 30, -1, 1, 1),
|
new AttackMove(Moves.QUICK_ATTACK, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 30, -1, 1, 1),
|
||||||
new AttackMove(Moves.RAGE, Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 20, -1, 0, 1)
|
new AttackMove(Moves.RAGE, Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 20, -1, 0, 1)
|
||||||
.partial(),
|
.attr(AddBattlerTagAttr, BattlerTagType.RAGE, true, false, 0, 0, false, true),
|
||||||
new SelfStatusMove(Moves.TELEPORT, Type.PSYCHIC, -1, 20, -1, -6, 1)
|
new SelfStatusMove(Moves.TELEPORT, Type.PSYCHIC, -1, 20, -1, -6, 1)
|
||||||
.attr(ForceSwitchOutAttr, true)
|
.attr(ForceSwitchOutAttr, true)
|
||||||
.hidesUser(),
|
.hidesUser(),
|
||||||
|
@ -71,6 +71,7 @@ export enum BattlerTagType {
|
|||||||
GULP_MISSILE_PIKACHU = "GULP_MISSILE_PIKACHU",
|
GULP_MISSILE_PIKACHU = "GULP_MISSILE_PIKACHU",
|
||||||
BEAK_BLAST_CHARGING = "BEAK_BLAST_CHARGING",
|
BEAK_BLAST_CHARGING = "BEAK_BLAST_CHARGING",
|
||||||
SHELL_TRAP = "SHELL_TRAP",
|
SHELL_TRAP = "SHELL_TRAP",
|
||||||
|
RAGE = "RAGE",
|
||||||
DRAGON_CHEER = "DRAGON_CHEER",
|
DRAGON_CHEER = "DRAGON_CHEER",
|
||||||
NO_RETREAT = "NO_RETREAT",
|
NO_RETREAT = "NO_RETREAT"
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,8 @@
|
|||||||
"cursedOnAdd": "{{pokemonNameWithAffix}} cut its own HP and put a curse on the {{pokemonName}}!",
|
"cursedOnAdd": "{{pokemonNameWithAffix}} cut its own HP and put a curse on the {{pokemonName}}!",
|
||||||
"cursedLapse": "{{pokemonNameWithAffix}} is afflicted by the Curse!",
|
"cursedLapse": "{{pokemonNameWithAffix}} is afflicted by the Curse!",
|
||||||
"stockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!",
|
"stockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!",
|
||||||
|
"rageOnAdd": "{{pokemonNameWithAffix}}'s rage is starting to build.",
|
||||||
|
"rageOnHit": "{{pokemonNameWithAffix}}'s rage is building.",
|
||||||
"disabledOnAdd": "{{pokemonNameWithAffix}}'s {{moveName}}\nwas disabled!",
|
"disabledOnAdd": "{{pokemonNameWithAffix}}'s {{moveName}}\nwas disabled!",
|
||||||
"disabledLapse": "{{pokemonNameWithAffix}}'s {{moveName}}\nis no longer disabled."
|
"disabledLapse": "{{pokemonNameWithAffix}}'s {{moveName}}\nis no longer disabled."
|
||||||
}
|
}
|
||||||
|
@ -67,5 +67,8 @@
|
|||||||
"saltCuredLapse": "¡{{moveName}} ha herido a {{pokemonNameWithAffix}}!",
|
"saltCuredLapse": "¡{{moveName}} ha herido a {{pokemonNameWithAffix}}!",
|
||||||
"cursedOnAdd": "¡{{pokemonNameWithAffix}} sacrifica algunos PS y maldice a {{pokemonName}}!",
|
"cursedOnAdd": "¡{{pokemonNameWithAffix}} sacrifica algunos PS y maldice a {{pokemonName}}!",
|
||||||
"cursedLapse": "¡{{pokemonNameWithAffix}} es víctima de una maldición!",
|
"cursedLapse": "¡{{pokemonNameWithAffix}} es víctima de una maldición!",
|
||||||
"stockpilingOnAdd": "¡{{pokemonNameWithAffix}} ha reservado energía por {{stockpiledCount}}ª vez!"
|
"stockpilingOnAdd": "¡{{pokemonNameWithAffix}} ha reservado energía por {{stockpiledCount}}ª vez!",
|
||||||
|
"rageOnAdd": "¡La furia de {{pokemonNameWithAffix}} comienza a crecer!",
|
||||||
|
"rageOnHit": "¡La furia de {{pokemonNameWithAffix}} está aumentando!"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,5 +67,7 @@
|
|||||||
"saltCuredLapse": "{{pokemonNameWithAffix}} est blessé\npar la capacité {{moveName}} !",
|
"saltCuredLapse": "{{pokemonNameWithAffix}} est blessé\npar la capacité {{moveName}} !",
|
||||||
"cursedOnAdd": "{{pokemonNameWithAffix}} sacrifie des PV\net lance une malédiction sur {{pokemonName}} !",
|
"cursedOnAdd": "{{pokemonNameWithAffix}} sacrifie des PV\net lance une malédiction sur {{pokemonName}} !",
|
||||||
"cursedLapse": "{{pokemonNameWithAffix}} est touché par la malédiction !",
|
"cursedLapse": "{{pokemonNameWithAffix}} est touché par la malédiction !",
|
||||||
"stockpilingOnAdd": "{{pokemonNameWithAffix}} utilise\nla capacité Stockage {{stockpiledCount}} fois !"
|
"stockpilingOnAdd": "{{pokemonNameWithAffix}} utilise\nla capacité Stockage {{stockpiledCount}} fois !",
|
||||||
|
"rageOnAdd": "La Frénésie s’empare\nde {{pokemonNameWithAffix}} !",
|
||||||
|
"rageOnHit": "La Frénésie de {{pokemonNameWithAffix}}\naugmente !"
|
||||||
}
|
}
|
@ -67,5 +67,7 @@
|
|||||||
"saltCuredLapse": "{{pokemonNameWithAffix}} viene colpito da {{moveName}}!",
|
"saltCuredLapse": "{{pokemonNameWithAffix}} viene colpito da {{moveName}}!",
|
||||||
"cursedOnAdd": "{{pokemonNameWithAffix}} ha sacrificato metà dei suoi PS per\nlanciare una maledizione su {{pokemonName}}!",
|
"cursedOnAdd": "{{pokemonNameWithAffix}} ha sacrificato metà dei suoi PS per\nlanciare una maledizione su {{pokemonName}}!",
|
||||||
"cursedLapse": "{{pokemonNameWithAffix}} subisce la maledizione!",
|
"cursedLapse": "{{pokemonNameWithAffix}} subisce la maledizione!",
|
||||||
"stockpilingOnAdd": "{{pokemonNameWithAffix}} ha usato Accumulo per la\n{{stockpiledCount}}ª volta!"
|
"stockpilingOnAdd": "{{pokemonNameWithAffix}} ha usato Accumulo per la\n{{stockpiledCount}}ª volta!",
|
||||||
}
|
"rageOnAdd": "{{pokemonNameWithAffix}} comincia ad accumulare ira!",
|
||||||
|
"rageOnHit": "L’ira di {{pokemonNameWithAffix}} aumenta!"
|
||||||
|
}
|
||||||
|
@ -67,5 +67,7 @@
|
|||||||
"saltCuredLapse": "{{pokemonNameWithAffix}}[[는]] 소금절이의\n데미지를 입고 있다.",
|
"saltCuredLapse": "{{pokemonNameWithAffix}}[[는]] 소금절이의\n데미지를 입고 있다.",
|
||||||
"cursedOnAdd": "{{pokemonNameWithAffix}}[[는]] 자신의 체력을 깎아서\n{{pokemonName}}에게 저주를 걸었다!",
|
"cursedOnAdd": "{{pokemonNameWithAffix}}[[는]] 자신의 체력을 깎아서\n{{pokemonName}}에게 저주를 걸었다!",
|
||||||
"cursedLapse": "{{pokemonNameWithAffix}}[[는]]\n저주받고 있다!",
|
"cursedLapse": "{{pokemonNameWithAffix}}[[는]]\n저주받고 있다!",
|
||||||
"stockpilingOnAdd": "{{pokemonNameWithAffix}}[[는]]\n{{stockpiledCount}}개 비축했다!"
|
"stockpilingOnAdd": "{{pokemonNameWithAffix}}[[는]]\n{{stockpiledCount}}개 비축했다!",
|
||||||
}
|
"rageOnAdd": "{{pokemonNameWithAffix}}[[는]]\n분노 볼티지를 쌓기 시작했다.",
|
||||||
|
"rageOnHit": "{{pokemonNameWithAffix}}의\n분노 볼티지가 올라가고 있다!"
|
||||||
|
}
|
||||||
|
@ -67,5 +67,7 @@
|
|||||||
"saltCuredLapse": "{{pokemonNameWithAffix}} foi ferido pelo {{moveName}}!",
|
"saltCuredLapse": "{{pokemonNameWithAffix}} foi ferido pelo {{moveName}}!",
|
||||||
"cursedOnAdd": "{{pokemonNameWithAffix}} cortou seus PS pela metade e amaldiçoou {{pokemonName}}!",
|
"cursedOnAdd": "{{pokemonNameWithAffix}} cortou seus PS pela metade e amaldiçoou {{pokemonName}}!",
|
||||||
"cursedLapse": "{{pokemonNameWithAffix}} foi ferido pelo Curse!",
|
"cursedLapse": "{{pokemonNameWithAffix}} foi ferido pelo Curse!",
|
||||||
"stockpilingOnAdd": "{{pokemonNameWithAffix}} estocou {{stockpiledCount}}!"
|
"stockpilingOnAdd": "{{pokemonNameWithAffix}} estocou {{stockpiledCount}}!",
|
||||||
}
|
"rageOnAdd": "A raiva de {{pokemonNameWithAffix}} está começando a aumentar.",
|
||||||
|
"rageOnHit": "A raiva de {{pokemonNameWithAffix}} está aumentando."
|
||||||
|
}
|
||||||
|
@ -67,5 +67,7 @@
|
|||||||
"saltCuredLapse": "{{pokemonNameWithAffix}}\n受到了{{moveName}}的伤害!",
|
"saltCuredLapse": "{{pokemonNameWithAffix}}\n受到了{{moveName}}的伤害!",
|
||||||
"cursedOnAdd": "{{pokemonNameWithAffix}}削减了自己的体力,\n并诅咒了{{pokemonName}}!",
|
"cursedOnAdd": "{{pokemonNameWithAffix}}削减了自己的体力,\n并诅咒了{{pokemonName}}!",
|
||||||
"cursedLapse": "{{pokemonNameWithAffix}}\n正受到诅咒!",
|
"cursedLapse": "{{pokemonNameWithAffix}}\n正受到诅咒!",
|
||||||
"stockpilingOnAdd": "{{pokemonNameWithAffix}}蓄力了{{stockpiledCount}}次!"
|
"stockpilingOnAdd": "{{pokemonNameWithAffix}}蓄力了{{stockpiledCount}}次!",
|
||||||
}
|
"rageOnAdd": "{{pokemonNameWithAffix}}的\n怒气开始上升了。",
|
||||||
|
"rageOnHit": "{{pokemonNameWithAffix}}的\n怒气正在上升!."
|
||||||
|
}
|
||||||
|
@ -66,5 +66,7 @@
|
|||||||
"saltCuredOnAdd": "{{pokemonNameWithAffix}} 陷入了鹽腌狀態!",
|
"saltCuredOnAdd": "{{pokemonNameWithAffix}} 陷入了鹽腌狀態!",
|
||||||
"saltCuredLapse": "{{pokemonNameWithAffix}} 受到了{{moveName}}的傷害!",
|
"saltCuredLapse": "{{pokemonNameWithAffix}} 受到了{{moveName}}的傷害!",
|
||||||
"cursedOnAdd": "{{pokemonNameWithAffix}}削減了自己的體力,並詛咒了{{pokemonName}}!",
|
"cursedOnAdd": "{{pokemonNameWithAffix}}削減了自己的體力,並詛咒了{{pokemonName}}!",
|
||||||
"cursedLapse": "{{pokemonNameWithAffix}}正受到詛咒!"
|
"cursedLapse": "{{pokemonNameWithAffix}}正受到詛咒!",
|
||||||
}
|
"rageOnAdd": "{{pokemonNameWithAffix}}的\n怒氣開始上升了。",
|
||||||
|
"rageOnHit": "{{pokemonNameWithAffix}}的\n怒氣正在上升!"
|
||||||
|
}
|
||||||
|
@ -262,6 +262,9 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
if (move.category === MoveCategory.PHYSICAL && user.isPlayer() !== target.isPlayer()) {
|
if (move.category === MoveCategory.PHYSICAL && user.isPlayer() !== target.isPlayer()) {
|
||||||
target.lapseTag(BattlerTagType.SHELL_TRAP);
|
target.lapseTag(BattlerTagType.SHELL_TRAP);
|
||||||
}
|
}
|
||||||
|
if (hitResult < HitResult.NO_EFFECT && move.category !== MoveCategory.STATUS) {
|
||||||
|
target.lapseTag(BattlerTagType.RAGE);
|
||||||
|
}
|
||||||
if (!user.isPlayer() && this.move.getMove() instanceof AttackMove) {
|
if (!user.isPlayer() && this.move.getMove() instanceof AttackMove) {
|
||||||
user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target);
|
user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target);
|
||||||
}
|
}
|
||||||
|
259
src/test/moves/rage.test.ts
Normal file
259
src/test/moves/rage.test.ts
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
import GameManager from "#test/utils/gameManager";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import {StatusEffect} from "#enums/status-effect";
|
||||||
|
import {RageTag} from "#app/data/battler-tags";
|
||||||
|
import {PlayerPokemon} from "#app/field/pokemon";
|
||||||
|
import {Nature} from "#enums/nature";
|
||||||
|
import {CommandPhase} from "#app/phases/command-phase";
|
||||||
|
import {BattlerIndex} from "#app/battle";
|
||||||
|
import {TurnEndPhase} from "#app/phases/turn-end-phase";
|
||||||
|
import {Stat} from "#enums/stat";
|
||||||
|
|
||||||
|
|
||||||
|
const TIMEOUT = 20 * 1000;
|
||||||
|
|
||||||
|
function fullOf(move: Moves) : Moves[] {
|
||||||
|
return [move, move, move, move];
|
||||||
|
}
|
||||||
|
describe("Moves - Rage", () => {
|
||||||
|
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
|
||||||
|
.battleType("single")
|
||||||
|
.ability(Abilities.UNNERVE)
|
||||||
|
.starterSpecies(Species.BOLTUND)
|
||||||
|
.moveset([Moves.RAGE, Moves.SPLASH, Moves.SPORE, Moves.VITAL_THROW])
|
||||||
|
.startingLevel(100)
|
||||||
|
.enemyLevel(100)
|
||||||
|
.disableCrits();
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ally Attack-Boost Test.
|
||||||
|
*
|
||||||
|
* Checks that Rage provides an attack boost if the user it hit after use.
|
||||||
|
*
|
||||||
|
* Checks that Rage provides an attack boost if the user is hit before moving
|
||||||
|
* on the following turn, regardless of what move they selected.
|
||||||
|
*
|
||||||
|
* Checks that a pokemon stops raging if they use a different move.
|
||||||
|
*/
|
||||||
|
it(
|
||||||
|
"should raise attack if hit after use",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.SHUCKLE)
|
||||||
|
.enemyMoveset(fullOf(Moves.TACKLE));
|
||||||
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
// Player Boltund uses Rage. Opponent Shuckle uses Tackle.
|
||||||
|
// Boltund's attack is raised.
|
||||||
|
game.move.select(Moves.RAGE);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||||
|
|
||||||
|
// Opponent Shuckle uses Tackle. Player Boltund uses Vital Throw (Negative Priority).
|
||||||
|
// Boltund's attack is raised.
|
||||||
|
game.move.select(Moves.VITAL_THROW);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(2);
|
||||||
|
|
||||||
|
// Opponent Shuckle uses Tackle. Player Boltund uses Vital Throw (Negative Priority).
|
||||||
|
// Boltund's attack not raised.
|
||||||
|
game.move.select(Moves.VITAL_THROW);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(2);
|
||||||
|
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that Opponent Pokemon correctly receive the Attack boost from Rage
|
||||||
|
* Checks that using a Status Move on a Pokemon that used Rage does NOT provide an Attack Boost
|
||||||
|
* Checks that Pokemon do not lose the {@linkcode RageTag} BattlerTag when sleeping.
|
||||||
|
*/
|
||||||
|
it(
|
||||||
|
"should not raise ATK if hit by status move",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.SHUCKLE)
|
||||||
|
.enemyMoveset(fullOf(Moves.RAGE));
|
||||||
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const oppPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
// Opponent Shuckle uses Rage. Ally Boltund uses Vital Throw.
|
||||||
|
// Shuckle gets an Attack boost
|
||||||
|
game.move.select(Moves.VITAL_THROW);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
|
expect(oppPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||||
|
|
||||||
|
// Ally Boltund uses Spore. Shuckle is asleep.
|
||||||
|
// Shuckle does not get an attack boost. Shuckle still has the RageTag tag.
|
||||||
|
game.move.select(Moves.SPORE);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
|
expect(oppPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||||
|
expect(oppPokemon.getTag(RageTag)).toBeTruthy;
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the {@linkcode RageTag} tag is not given if the target is immune
|
||||||
|
*/
|
||||||
|
it(
|
||||||
|
"should not raise ATK if target is immune",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.GASTLY)
|
||||||
|
.enemyMoveset(fullOf(Moves.TACKLE)); // Has semi-invulnerable turn
|
||||||
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
// Boltund uses rage, but it has no effect, Gastly uses Tackle
|
||||||
|
// Boltund does not have RageTag or Attack boost.
|
||||||
|
game.move.select(Moves.RAGE);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
|
expect(leadPokemon.getTag(RageTag)).toBeNull;
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the {@linkcode RageTag} tag is not given if the target is semi-invulnerable
|
||||||
|
* Checks that Pokémon does not get Attack boost if it uses Rage after getting hit on a turn
|
||||||
|
*/
|
||||||
|
it(
|
||||||
|
"should not raise ATK if target is semi-invulnerable",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.REGIELEKI)
|
||||||
|
.enemyMoveset(fullOf(Moves.PHANTOM_FORCE)); // Has semi-invulnerable turn
|
||||||
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
// Regieliki uses Fly. Boltund uses Rage, but Regieleki is invulnerable
|
||||||
|
// Boltund does not gain RageTag or Attack boost
|
||||||
|
game.move.select(Moves.RAGE);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
|
expect(leadPokemon.getTag(RageTag)).toBeNull;
|
||||||
|
|
||||||
|
// Regieleki finishes Fly, Boltund uses Rage
|
||||||
|
// Boltund gains RageTag, but no boost
|
||||||
|
game.move.select(Moves.RAGE);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
|
expect(leadPokemon.getTag(RageTag)).toBeTruthy;
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should not stop raging if rage fails",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.SHUCKLE)
|
||||||
|
.enemyMoveset(fullOf(Moves.PHANTOM_FORCE)); // Has semi-invulnerable turn
|
||||||
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
// Boltund uses Rage, Shuckle uses Fly
|
||||||
|
// Boltund gains RageTag
|
||||||
|
game.move.select(Moves.RAGE);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
|
expect(leadPokemon.getTag(RageTag)).toBeTruthy;
|
||||||
|
|
||||||
|
// Boltund uses Rage, Shuckle is underwater, Shuckle finishes Dive
|
||||||
|
// Boltund gains gains boost, does not lose RageTag
|
||||||
|
game.move.select(Moves.RAGE);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||||
|
expect(leadPokemon.getTag(RageTag)).toBeTruthy;
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic doubles test
|
||||||
|
* Checks that if a raging Pokemon is hit multiple times in one turn, they get multiple boosts
|
||||||
|
* Should also cover multi-hit moves
|
||||||
|
*/
|
||||||
|
it(
|
||||||
|
"should provide boost per hit in doubles",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.moveset([Moves.RAGE, Moves.MEMENTO, Moves.SPORE, Moves.VITAL_THROW])
|
||||||
|
.battleType("double")
|
||||||
|
.enemySpecies(Species.SHUCKLE)
|
||||||
|
.enemyMoveset(fullOf(Moves.TACKLE));
|
||||||
|
await game.classicMode.startBattle([Species.BOLTUND, Species.BOLTUND]);
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getParty()[0];
|
||||||
|
|
||||||
|
game.move.select(Moves.RAGE, 1, BattlerIndex.ENEMY);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase);
|
||||||
|
|
||||||
|
game.move.select(Moves.MEMENTO, 1, BattlerIndex.ENEMY_2);
|
||||||
|
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase, false);
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(2);
|
||||||
|
expect(leadPokemon.getTag(RageTag)).toBeTruthy;
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that a pokemon does not lose the RageTag if it is unable to act
|
||||||
|
* regardless of what it was otherwise going to do
|
||||||
|
*/
|
||||||
|
it(
|
||||||
|
"should stay raging if unable to act",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.moveset([Moves.RAGE, Moves.SPLASH, Moves.SPORE, Moves.VITAL_THROW])
|
||||||
|
.battleType("double")
|
||||||
|
.enemySpecies(Species.SHUCKLE)
|
||||||
|
.enemyMoveset(fullOf(Moves.SPLASH)); // Has semi-invulnerable turn
|
||||||
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
const leadPokemon: PlayerPokemon = game.scene.getParty()[0];
|
||||||
|
// Ensure that second pokemon is faster.
|
||||||
|
leadPokemon.natureOverride = Nature.SASSY;
|
||||||
|
game.scene.getParty()[1].natureOverride = Nature.JOLLY;
|
||||||
|
|
||||||
|
game.move.select(Moves.RAGE, 1, BattlerIndex.ENEMY);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase);
|
||||||
|
|
||||||
|
game.move.select(Moves.SPORE, 1, BattlerIndex.PLAYER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase, false);
|
||||||
|
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
|
expect(leadPokemon.getTag(RageTag)).toBeTruthy;
|
||||||
|
expect(leadPokemon.status?.effect).toBe(StatusEffect.SLEEP);
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user