mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-07 00:42:16 +02:00
Implement Safeguard for non-volatile statuses
This commit is contained in:
parent
38303e6eb1
commit
b5f948ffec
@ -845,7 +845,7 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr {
|
||||
private chance: integer;
|
||||
public chance: integer;
|
||||
private effects: StatusEffect[];
|
||||
|
||||
constructor(chance: integer, ...effects: StatusEffect[]) {
|
||||
|
@ -1929,7 +1929,7 @@ export class StatusEffectAttr extends MoveEffectAttr {
|
||||
}
|
||||
}
|
||||
|
||||
if (user.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, targetSide)) {
|
||||
if (user !== target && user.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, targetSide)) {
|
||||
if (move.category === MoveCategory.STATUS) {
|
||||
user.scene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target)}));
|
||||
}
|
||||
@ -6748,7 +6748,8 @@ export function initMoves() {
|
||||
.attr(FriendshipPowerAttr, true),
|
||||
new StatusMove(Moves.SAFEGUARD, Type.NORMAL, -1, 25, -1, 0, 2)
|
||||
.target(MoveTarget.USER_SIDE)
|
||||
.attr(AddArenaTagAttr, ArenaTagType.SAFEGUARD, 5, true, true),
|
||||
.attr(AddArenaTagAttr, ArenaTagType.SAFEGUARD, 5, true, true)
|
||||
.partial(),
|
||||
new StatusMove(Moves.PAIN_SPLIT, Type.NORMAL, -1, 20, -1, 0, 2)
|
||||
.attr(HpSplitAttr)
|
||||
.condition(failOnBossCondition),
|
||||
|
@ -2686,6 +2686,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
const types = this.getTypes(true, true);
|
||||
|
||||
const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
||||
if (sourcePokemon && sourcePokemon !== this && this.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, defendingSide)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (effect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import Phaser from "phaser";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { CommandPhase, SelectTargetPhase, TurnEndPhase } from "#app/phases";
|
||||
@ -8,6 +8,8 @@ import { Species } from "#enums/species";
|
||||
import { BattlerIndex } from "#app/battle.js";
|
||||
import { Abilities } from "#app/enums/abilities.js";
|
||||
import { mockTurnOrder } from "../utils/testUtils";
|
||||
import { StatusEffect } from "#app/enums/status-effect.js";
|
||||
import { allAbilities, PostDefendContactApplyStatusEffectAbAttr } from "#app/data/ability.js";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
@ -34,10 +36,10 @@ describe("Moves - Safeguard", () => {
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyLevel(5)
|
||||
.starterSpecies(Species.DRATINI)
|
||||
.moveset([Moves.NUZZLE, Moves.SPORE])
|
||||
.moveset([Moves.NUZZLE, Moves.SPORE, Moves.YAWN, Moves.SPLASH])
|
||||
.ability(Abilities.BALL_FETCH);
|
||||
});
|
||||
it("protects from nuzzle status",
|
||||
it("protects from damaging moves with additional effects",
|
||||
async () => {
|
||||
await game.startBattle();
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
@ -49,9 +51,8 @@ describe("Moves - Safeguard", () => {
|
||||
expect(enemy.status).toBeUndefined();
|
||||
}, TIMEOUT
|
||||
);
|
||||
it("protects from spore",
|
||||
it("protects from status moves",
|
||||
async () => {
|
||||
|
||||
await game.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
@ -88,4 +89,71 @@ describe("Moves - Safeguard", () => {
|
||||
expect(enemyPokemon[1].status).toBeUndefined();
|
||||
}, TIMEOUT
|
||||
);
|
||||
|
||||
it.skip("protects from new volatile status", // not yet
|
||||
async () => {
|
||||
await game.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.YAWN));
|
||||
await mockTurnOrder(game, [BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(enemyPokemon.summonData.tags).toEqual([]);
|
||||
}, TIMEOUT
|
||||
);
|
||||
|
||||
it.skip("doesn't protect from already existing volatile status", // not yet
|
||||
async () => {
|
||||
await game.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.YAWN));
|
||||
await mockTurnOrder(game, [BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.toNextTurn();
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(enemyPokemon.status?.effect).toEqual(StatusEffect.SLEEP);
|
||||
}, TIMEOUT
|
||||
);
|
||||
|
||||
it("doesn't protect from self-inflicted via Rest or Flame Orb",
|
||||
async () => {
|
||||
game.override.enemyHeldItems([{name: "FLAME_ORB"}]);
|
||||
await game.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await mockTurnOrder(game, [BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(enemyPokemon.status?.effect).toEqual(StatusEffect.BURN);
|
||||
|
||||
game.override.enemyMoveset(Array(4).fill(Moves.REST));
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(enemyPokemon.status?.effect).toEqual(StatusEffect.SLEEP);
|
||||
}, TIMEOUT
|
||||
);
|
||||
|
||||
it("protects from ability-inflicted status",
|
||||
async () => {
|
||||
game.override.ability(Abilities.STATIC);
|
||||
vi.spyOn(allAbilities[Abilities.STATIC].getAttrs(PostDefendContactApplyStatusEffectAbAttr)[0], "chance", "get").mockReturnValue(100);
|
||||
await game.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await mockTurnOrder(game, [BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.toNextTurn();
|
||||
game.override.enemyMoveset(Array(4).fill(Moves.TACKLE));
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(enemyPokemon.status).toBeUndefined();
|
||||
}, TIMEOUT
|
||||
);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user