mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-12-01 03:06:19 +00:00
[Move] Fully Implement Round (#4783)
This commit is contained in:
parent
3f97c9e39f
commit
c3d832aaca
@ -4161,6 +4161,60 @@ export class CombinedPledgeStabBoostAttr extends MoveAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variable Power attribute for {@link https://bulbapedia.bulbagarden.net/wiki/Round_(move) | Round}.
|
||||||
|
* Doubles power if another Pokemon has previously selected Round this turn.
|
||||||
|
* @extends VariablePowerAttr
|
||||||
|
*/
|
||||||
|
export class RoundPowerAttr extends VariablePowerAttr {
|
||||||
|
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
const power = args[0];
|
||||||
|
if (!(power instanceof Utils.NumberHolder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.turnData?.joinedRound) {
|
||||||
|
power.value *= 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for the "combo" effect of {@link https://bulbapedia.bulbagarden.net/wiki/Round_(move) | Round}.
|
||||||
|
* Preempts the next move in the turn order with the first instance of any Pokemon
|
||||||
|
* using Round. Also marks the Pokemon using the cued Round to double the move's power.
|
||||||
|
* @extends MoveEffectAttr
|
||||||
|
* @see {@linkcode RoundPowerAttr}
|
||||||
|
*/
|
||||||
|
export class CueNextRoundAttr extends MoveEffectAttr {
|
||||||
|
constructor() {
|
||||||
|
super(true, { lastHitOnly: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
override apply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean {
|
||||||
|
const nextRoundPhase = user.scene.findPhase<MovePhase>(phase =>
|
||||||
|
phase instanceof MovePhase && phase.move.moveId === Moves.ROUND
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!nextRoundPhase) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the phase queue so that the next Pokemon using Round moves next
|
||||||
|
const nextRoundIndex = user.scene.phaseQueue.indexOf(nextRoundPhase);
|
||||||
|
const nextMoveIndex = user.scene.phaseQueue.findIndex(phase => phase instanceof MovePhase);
|
||||||
|
if (nextRoundIndex !== nextMoveIndex) {
|
||||||
|
user.scene.prependToPhase(user.scene.phaseQueue.splice(nextRoundIndex, 1)[0], MovePhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the corresponding Pokemon as having "joined the Round" (for doubling power later)
|
||||||
|
nextRoundPhase.pokemon.turnData.joinedRound = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class VariableAtkAttr extends MoveAttr {
|
export class VariableAtkAttr extends MoveAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -8960,8 +9014,9 @@ export function initMoves() {
|
|||||||
.condition((user, target, move) => !target.turnData.acted)
|
.condition((user, target, move) => !target.turnData.acted)
|
||||||
.attr(AfterYouAttr),
|
.attr(AfterYouAttr),
|
||||||
new AttackMove(Moves.ROUND, Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5)
|
new AttackMove(Moves.ROUND, Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5)
|
||||||
.soundBased()
|
.attr(CueNextRoundAttr)
|
||||||
.partial(), // No effect implemented
|
.attr(RoundPowerAttr)
|
||||||
|
.soundBased(),
|
||||||
new AttackMove(Moves.ECHOED_VOICE, Type.NORMAL, MoveCategory.SPECIAL, 40, 100, 15, -1, 0, 5)
|
new AttackMove(Moves.ECHOED_VOICE, Type.NORMAL, MoveCategory.SPECIAL, 40, 100, 15, -1, 0, 5)
|
||||||
.attr(ConsecutiveUseMultiBasePowerAttr, 5, false)
|
.attr(ConsecutiveUseMultiBasePowerAttr, 5, false)
|
||||||
.soundBased(),
|
.soundBased(),
|
||||||
|
@ -5194,6 +5194,7 @@ export class PokemonTurnData {
|
|||||||
public combiningPledge?: Moves;
|
public combiningPledge?: Moves;
|
||||||
public switchedInThisTurn: boolean = false;
|
public switchedInThisTurn: boolean = false;
|
||||||
public failedRunAway: boolean = false;
|
public failedRunAway: boolean = false;
|
||||||
|
public joinedRound: boolean = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AiType {
|
export enum AiType {
|
||||||
|
65
src/test/moves/round.test.ts
Normal file
65
src/test/moves/round.test.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { BattlerIndex } from "#app/battle";
|
||||||
|
import { allMoves } from "#app/data/move";
|
||||||
|
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||||
|
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, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
describe("Moves - Round", () => {
|
||||||
|
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.SPLASH, Moves.ROUND ])
|
||||||
|
.ability(Abilities.BALL_FETCH)
|
||||||
|
.battleType("double")
|
||||||
|
.disableCrits()
|
||||||
|
.enemySpecies(Species.MAGIKARP)
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
|
.enemyMoveset([ Moves.SPLASH, Moves.ROUND ])
|
||||||
|
.startingLevel(100)
|
||||||
|
.enemyLevel(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should cue other instances of Round together in Speed order", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.MAGIKARP, Species.FEEBAS ]);
|
||||||
|
|
||||||
|
const round = allMoves[Moves.ROUND];
|
||||||
|
const spy = vi.spyOn(round, "calculateBattlePower");
|
||||||
|
|
||||||
|
game.move.select(Moves.ROUND, 0, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.ROUND, 1, BattlerIndex.ENEMY_2);
|
||||||
|
|
||||||
|
await game.forceEnemyMove(Moves.ROUND, BattlerIndex.PLAYER);
|
||||||
|
await game.forceEnemyMove(Moves.SPLASH);
|
||||||
|
|
||||||
|
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]);
|
||||||
|
|
||||||
|
const actualTurnOrder: BattlerIndex[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
await game.phaseInterceptor.to("MoveEffectPhase", false);
|
||||||
|
actualTurnOrder.push((game.scene.getCurrentPhase() as MoveEffectPhase).getUserPokemon()!.getBattlerIndex());
|
||||||
|
await game.phaseInterceptor.to("MoveEndPhase");
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(actualTurnOrder).toEqual([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]);
|
||||||
|
const powerResults = spy.mock.results.map(result => result.value);
|
||||||
|
expect(powerResults).toEqual( [ 60, 120, 120 ]);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user