Corrects mirror move implementation, rewrite unit test to adjust

This commit is contained in:
Christopher Schmidt 2024-10-26 20:34:10 -04:00
parent 365e77d328
commit 468275ba23
4 changed files with 32 additions and 45 deletions

View File

@ -88,8 +88,6 @@ export default class Battle {
public enemyFaints: number = 0;
public playerFaintsHistory: FaintLogEntry[] = [];
public enemyFaintsHistory: FaintLogEntry[] = [];
/** The list of moves used since the beginning of the battle */
public moveHistory: TurnMove[] = [];
public mysteryEncounterType?: MysteryEncounterType;

View File

@ -5973,6 +5973,7 @@ export class FirstMoveTypeAttr extends MoveEffectAttr {
export class CallMoveAttr extends OverrideMoveEffectAttr {
protected invalidMoves: Moves[];
protected hasTarget: boolean;
async apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
const replaceMoveTarget = move.moveTarget === MoveTarget.NEAR_OTHER ? MoveTarget.NEAR_ENEMY : undefined;
const moveTargets = getMoveTargets(user, move.id, replaceMoveTarget);
@ -5981,7 +5982,7 @@ export class CallMoveAttr extends OverrideMoveEffectAttr {
}
const targets = moveTargets.multiple || moveTargets.targets.length === 1
? moveTargets.targets
: [ moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ];
: [ this.hasTarget ? target.getBattlerIndex() : moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ]; // account for Mirror Move having a target already
user.getMoveQueue().push({ move: move.id, targets: targets, virtual: true, ignorePP: true });
user.scene.unshiftPhase(new MovePhase(user.scene, user, targets, new PokemonMove(move.id, 0, 0, true), true, true));
@ -6502,25 +6503,19 @@ export class CopyMoveAttr extends CallMoveAttr {
}
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
if (this.mirrorMove) {
const lastMove = user.scene.currentBattle.moveHistory.filter(m => m.targets.includes(user.getBattlerIndex()))[0].move;
return super.apply(user, target, allMoves[lastMove], args);
} else {
return super.apply(user, target, allMoves[user.scene.currentBattle.lastMove], args);
}
this.hasTarget = this.mirrorMove;
const lastMove = this.mirrorMove ? target.getLastXMoves()[0].move : user.scene.currentBattle.lastMove;
return super.apply(user, target, allMoves[lastMove], args);
}
getCondition(): MoveConditionFunc {
return (user, target, move) => {
if (this.mirrorMove) {
if (user.scene.currentBattle.moveHistory.filter(m => m.targets.includes(user.getBattlerIndex())).length === 0) {
return false;
}
} else if (user.scene.currentBattle.lastMove === undefined) {
return false;
return target.getMoveHistory().length !== 0;
} else {
const lastMove = user.scene.currentBattle.lastMove;
return lastMove !== undefined && !this.invalidMoves.includes(lastMove);
}
const lastMove = this.mirrorMove ? user.turnData.attacksReceived[0]?.move : user.scene.currentBattle.lastMove;
return !this.invalidMoves.includes(lastMove);
};
}
}
@ -7906,7 +7901,7 @@ export function initMoves() {
.unimplemented(),
new SelfStatusMove(Moves.METRONOME, Type.NORMAL, -1, 10, -1, 0, 1)
.attr(RandomMoveAttr, invalidMetronomeMoves),
new SelfStatusMove(Moves.MIRROR_MOVE, Type.FLYING, -1, 20, -1, 0, 1)
new StatusMove(Moves.MIRROR_MOVE, Type.FLYING, -1, 20, -1, 0, 1)
.attr(CopyMoveAttr, true),
new AttackMove(Moves.SELF_DESTRUCT, Type.NORMAL, MoveCategory.PHYSICAL, 200, 100, 5, -1, 0, 1)
.attr(SacrificialAttr)

View File

@ -274,10 +274,6 @@ export class MovePhase extends BattlePhase {
// The last move used is unaffected by moves that fail
if (success) {
this.scene.currentBattle.lastMove = this.move.moveId;
this.scene.currentBattle.moveHistory.unshift({
move: this.move.moveId,
targets: this.targets
});
}
}

View File

@ -34,15 +34,20 @@ describe("Moves - Mirror Move", () => {
.enemyMoveset(Moves.SPLASH);
});
it("should use the last move targeted at the user", async () => {
game.override.enemyMoveset(Moves.TACKLE);
await game.classicMode.startBattle([ Species.FEEBAS ]);
it("should use the last move that the target", async () => {
game.override
.battleType("double")
.enemyMoveset([ Moves.TACKLE, Moves.GROWL ]);
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
game.move.select(Moves.MIRROR_MOVE);
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]);
game.move.select(Moves.MIRROR_MOVE, 0, BattlerIndex.ENEMY); // target's last move is Tackle, enemy should receive damage from Mirror Move copying Tackle
game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.GROWL, BattlerIndex.PLAYER_2);
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER ]);
await game.toNextTurn();
expect(game.scene.getEnemyPokemon()!.isFullHp()).toBeFalsy();
expect(game.scene.getEnemyField()[0].isFullHp()).toBeFalsy();
});
it("should apply secondary effects of a move", async () => {
@ -56,24 +61,7 @@ describe("Moves - Mirror Move", () => {
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.SPDEF)).toBe(-2);
});
it("should fail if the user has never been targeted", { repeats: 10 }, async () => {
game.override
.battleType("double")
.startingLevel(100)
.enemyMoveset([ Moves.TACKLE, Moves.SPLASH ]);
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
game.move.select(Moves.MIRROR_MOVE);
game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.SPLASH);
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER ]);
await game.toNextTurn();
expect(game.scene.getPlayerField()![0].getLastXMoves()[0].result).toBe(MoveResult.FAIL);
});
it("should copy status moves that target the user", async () => {
it("should be able to copy status moves", async () => {
game.override.enemyMoveset(Moves.GROWL);
await game.classicMode.startBattle([ Species.FEEBAS ]);
@ -83,4 +71,14 @@ describe("Moves - Mirror Move", () => {
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
});
it("should fail if the target has not used any moves", async () => {
await game.classicMode.startBattle([ Species.FEEBAS ]);
game.move.select(Moves.MIRROR_MOVE);
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
await game.toNextTurn();
expect(game.scene.getPlayerPokemon()!.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
});
});