Fixed Flame Burst/substitute interaction
This commit is contained in:
parent
cae4342d98
commit
698aa62fdd
|
@ -1837,6 +1837,15 @@ export class PartyStatusCureAttr extends MoveEffectAttr {
|
|||
* @extends MoveEffectAttr
|
||||
*/
|
||||
export class FlameBurstAttr extends MoveEffectAttr {
|
||||
constructor() {
|
||||
/**
|
||||
* This is self-targeted to bypass immunity to target-facing secondary
|
||||
* effects when the target has an active Substitute doll.
|
||||
* TODO: Find a more intuitive way to implement Substitute bypassing.
|
||||
*/
|
||||
super(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param user - n/a
|
||||
* @param target - The target Pokémon.
|
||||
|
@ -5176,21 +5185,19 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
|||
public tagType: BattlerTagType;
|
||||
public turnCountMin: integer;
|
||||
public turnCountMax: integer;
|
||||
protected cancelOnFail: boolean;
|
||||
private failOnOverlap: boolean;
|
||||
|
||||
constructor(tagType: BattlerTagType, selfTarget: boolean = false, failOnOverlap: boolean = false, turnCountMin: integer = 0, turnCountMax?: integer, lastHitOnly: boolean = false, cancelOnFail: boolean = false) {
|
||||
constructor(tagType: BattlerTagType, selfTarget: boolean = false, failOnOverlap: boolean = false, turnCountMin: integer = 0, turnCountMax?: integer, lastHitOnly: boolean = false) {
|
||||
super(selfTarget, { lastHitOnly: lastHitOnly });
|
||||
|
||||
this.tagType = tagType;
|
||||
this.turnCountMin = turnCountMin;
|
||||
this.turnCountMax = turnCountMax !== undefined ? turnCountMax : turnCountMin;
|
||||
this.failOnOverlap = !!failOnOverlap;
|
||||
this.cancelOnFail = cancelOnFail;
|
||||
}
|
||||
|
||||
canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!super.canApply(user, target, move, args) || (this.cancelOnFail === true && user.getLastXMoves(1)[0]?.result === MoveResult.FAIL)) {
|
||||
if (!super.canApply(user, target, move, args)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
|
@ -5452,7 +5459,7 @@ export class ConfuseAttr extends AddBattlerTagAttr {
|
|||
|
||||
export class RechargeAttr extends AddBattlerTagAttr {
|
||||
constructor() {
|
||||
super(BattlerTagType.RECHARGING, true, false, 1, 1, true, true);
|
||||
super(BattlerTagType.RECHARGING, true, false, 1, 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { BattlerIndex } from "#app/battle";
|
||||
import { allAbilities } from "#app/data/ability";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import { TurnEndPhase } from "#app/phases/turn-end-phase";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
|
@ -46,12 +46,12 @@ describe("Moves - Flame Burst", () => {
|
|||
});
|
||||
|
||||
it("inflicts damage to the target's ally equal to 1/16 of its max HP", async () => {
|
||||
await game.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
await game.classicMode.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField();
|
||||
|
||||
game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex());
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(leftEnemy.hp).toBeLessThan(leftEnemy.getMaxHp());
|
||||
expect(rightEnemy.hp).toBe(rightEnemy.getMaxHp() - getEffectDamage(rightEnemy));
|
||||
|
@ -60,46 +60,65 @@ describe("Moves - Flame Burst", () => {
|
|||
it("does not inflict damage to the target's ally if the target was not affected by Flame Burst", async () => {
|
||||
game.override.enemyAbility(Abilities.FLASH_FIRE);
|
||||
|
||||
await game.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
await game.classicMode.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField();
|
||||
|
||||
game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex());
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(leftEnemy.hp).toBe(leftEnemy.getMaxHp());
|
||||
expect(rightEnemy.hp).toBe(rightEnemy.getMaxHp());
|
||||
});
|
||||
|
||||
it("does not interact with the target ally's abilities", async () => {
|
||||
await game.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
await game.classicMode.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField();
|
||||
|
||||
vi.spyOn(rightEnemy, "getAbility").mockReturnValue(allAbilities[Abilities.FLASH_FIRE]);
|
||||
|
||||
game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex());
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(leftEnemy.hp).toBeLessThan(leftEnemy.getMaxHp());
|
||||
expect(rightEnemy.hp).toBe(rightEnemy.getMaxHp() - getEffectDamage(rightEnemy));
|
||||
});
|
||||
|
||||
it("effect damage is prevented by Magic Guard", async () => {
|
||||
await game.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
await game.classicMode.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField();
|
||||
|
||||
vi.spyOn(rightEnemy, "getAbility").mockReturnValue(allAbilities[Abilities.MAGIC_GUARD]);
|
||||
|
||||
game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex());
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(leftEnemy.hp).toBeLessThan(leftEnemy.getMaxHp());
|
||||
expect(rightEnemy.hp).toBe(rightEnemy.getMaxHp());
|
||||
});
|
||||
|
||||
it("is not affected by protection moves and Endure", async () => {
|
||||
it("effect damage should apply even when targeting a Substitute", async () => {
|
||||
game.override.enemyMoveset([ Moves.SUBSTITUTE, Moves.SPLASH ]);
|
||||
|
||||
await game.classicMode.startBattle([ Species.PIKACHU, Species.PIKACHU ]);
|
||||
const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField();
|
||||
|
||||
game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex());
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
|
||||
await game.forceEnemyMove(Moves.SUBSTITUTE);
|
||||
await game.forceEnemyMove(Moves.SPLASH);
|
||||
|
||||
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2 ]);
|
||||
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(rightEnemy.hp).toBe(rightEnemy.getMaxHp() - getEffectDamage(rightEnemy));
|
||||
});
|
||||
|
||||
it.skip("is not affected by protection moves and Endure", async () => {
|
||||
// TODO: update this test when it's possible to select move for each enemy
|
||||
}, { skip: true });
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue