[Bug] Fix exp gains speed not applying properly (#4243)
* update battle-info.ts * add: ExpGainsSpeed enum * address PR comments * add test coverage (exp gains speed) --------- Co-authored-by: Mr.WaterT <water.t.works@gmail.com> Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
This commit is contained in:
parent
bdc7c95c1c
commit
763c1922fb
|
@ -105,6 +105,7 @@ import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||||
import { ExpPhase } from "#app/phases/exp-phase";
|
import { ExpPhase } from "#app/phases/exp-phase";
|
||||||
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
|
import { ExpGainsSpeed } from "./enums/exp-gains-speed";
|
||||||
|
|
||||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||||
|
|
||||||
|
@ -180,7 +181,7 @@ export default class BattleScene extends SceneBase {
|
||||||
public experimentalSprites: boolean = false;
|
public experimentalSprites: boolean = false;
|
||||||
public musicPreference: integer = 0;
|
public musicPreference: integer = 0;
|
||||||
public moveAnimations: boolean = true;
|
public moveAnimations: boolean = true;
|
||||||
public expGainsSpeed: integer = 0;
|
public expGainsSpeed: ExpGainsSpeed = ExpGainsSpeed.DEFAULT;
|
||||||
public skipSeenDialogues: boolean = false;
|
public skipSeenDialogues: boolean = false;
|
||||||
/**
|
/**
|
||||||
* Determines if the egg hatching animation should be skipped
|
* Determines if the egg hatching animation should be skipped
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* Defines the speed of gaining experience.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* The `expGainSpeed` can have several modes:
|
||||||
|
* - `0` - Default: The normal speed.
|
||||||
|
* - `1` - Fast: Fast speed.
|
||||||
|
* - `2` - Faster: Faster speed.
|
||||||
|
* - `3` - Skip: Skip gaining exp animation.
|
||||||
|
*
|
||||||
|
* @default 0 - Uses the default normal speed.
|
||||||
|
*/
|
||||||
|
export enum ExpGainsSpeed {
|
||||||
|
/** The normal speed. */
|
||||||
|
DEFAULT,
|
||||||
|
/** Fast speed. */
|
||||||
|
FAST,
|
||||||
|
/** Faster speed. */
|
||||||
|
FASTER,
|
||||||
|
/** Skip gaining exp animation. */
|
||||||
|
SKIP
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
|
import { ExpGainsSpeed } from "#app/enums/exp-gains-speed";
|
||||||
import { ExpNotification } from "#app/enums/exp-notification";
|
import { ExpNotification } from "#app/enums/exp-notification";
|
||||||
import { ExpBoosterModifier } from "#app/modifier/modifier";
|
import { ExpBoosterModifier } from "#app/modifier/modifier";
|
||||||
import * as Utils from "#app/utils";
|
import * as Utils from "#app/utils";
|
||||||
|
@ -44,7 +45,7 @@ export class ShowPartyExpBarPhase extends PlayerPartyMemberPokemonPhase {
|
||||||
} else {
|
} else {
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
} else if (this.scene.expGainsSpeed < 3) {
|
} else if (this.scene.expGainsSpeed < ExpGainsSpeed.SKIP) {
|
||||||
this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, false, newLevel).then(() => {
|
this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, false, newLevel).then(() => {
|
||||||
setTimeout(() => this.end(), 500 / Math.pow(2, this.scene.expGainsSpeed));
|
setTimeout(() => this.end(), 500 / Math.pow(2, this.scene.expGainsSpeed));
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { ExpGainsSpeed } from "#app/enums/exp-gains-speed";
|
||||||
|
import { Species } from "#app/enums/species";
|
||||||
|
import { ExpPhase } from "#app/phases/exp-phase";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import GameManager from "#test/utils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
vi.mock("../data/exp", ({}) => {
|
||||||
|
return {
|
||||||
|
getLevelRelExp: vi.fn(() => 1), //consistent levelRelExp
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("UI - Battle Info", () => {
|
||||||
|
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.GUILLOTINE, Moves.SPLASH])
|
||||||
|
.battleType("single")
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
|
.enemyMoveset(Moves.SPLASH)
|
||||||
|
.enemySpecies(Species.CATERPIE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([ExpGainsSpeed.FAST, ExpGainsSpeed.FASTER, ExpGainsSpeed.SKIP])(
|
||||||
|
"should increase exp gains animation by 2^%i",
|
||||||
|
async (expGainsSpeed) => {
|
||||||
|
game.settings.expGainsSpeed(expGainsSpeed);
|
||||||
|
vi.spyOn(Math, "pow");
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.doKillOpponents();
|
||||||
|
await game.phaseInterceptor.to(ExpPhase, true);
|
||||||
|
|
||||||
|
expect(Math.pow).not.toHaveBeenCalledWith(2, expGainsSpeed);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
|
@ -54,6 +54,7 @@ import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
||||||
import { expect } from "vitest";
|
import { expect } from "vitest";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { isNullOrUndefined } from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
|
import { ExpGainsSpeed } from "#app/enums/exp-gains-speed";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage the game state and transitions between phases.
|
* Class to manage the game state and transitions between phases.
|
||||||
|
@ -148,7 +149,7 @@ export default class GameManager {
|
||||||
this.scene.gameSpeed = 5;
|
this.scene.gameSpeed = 5;
|
||||||
this.scene.moveAnimations = false;
|
this.scene.moveAnimations = false;
|
||||||
this.scene.showLevelUpStats = false;
|
this.scene.showLevelUpStats = false;
|
||||||
this.scene.expGainsSpeed = 3;
|
this.scene.expGainsSpeed = ExpGainsSpeed.SKIP;
|
||||||
this.scene.expParty = ExpNotification.SKIP;
|
this.scene.expParty = ExpNotification.SKIP;
|
||||||
this.scene.hpBarSpeed = 3;
|
this.scene.hpBarSpeed = 3;
|
||||||
this.scene.enableTutorials = false;
|
this.scene.enableTutorials = false;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { PlayerGender } from "#app/enums/player-gender";
|
import { PlayerGender } from "#app/enums/player-gender";
|
||||||
import { BattleStyle } from "#app/enums/battle-style";
|
import { BattleStyle } from "#app/enums/battle-style";
|
||||||
import { GameManagerHelper } from "./gameManagerHelper";
|
import { GameManagerHelper } from "./gameManagerHelper";
|
||||||
|
import { ExpGainsSpeed } from "#app/enums/exp-gains-speed";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to handle settings for tests
|
* Helper to handle settings for tests
|
||||||
|
@ -38,6 +39,15 @@ export class SettingsHelper extends GameManagerHelper {
|
||||||
this.log(`Gender set to: ${PlayerGender[gender]} (=${gender})` );
|
this.log(`Gender set to: ${PlayerGender[gender]} (=${gender})` );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the exp gains speed
|
||||||
|
* @param speed the {@linkcode ExpGainsSpeed} to set
|
||||||
|
*/
|
||||||
|
expGainsSpeed(speed: ExpGainsSpeed) {
|
||||||
|
this.game.scene.expGainsSpeed = speed;
|
||||||
|
this.log(`Exp Gains Speed set to: ${ExpGainsSpeed[speed]} (=${speed})` );
|
||||||
|
}
|
||||||
|
|
||||||
private log(...params: any[]) {
|
private log(...params: any[]) {
|
||||||
console.log("Settings:", ...params);
|
console.log("Settings:", ...params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ export interface PromptHandler {
|
||||||
expireFn?: () => void;
|
expireFn?: () => void;
|
||||||
awaitingActionInput?: boolean;
|
awaitingActionInput?: boolean;
|
||||||
}
|
}
|
||||||
|
import { ExpPhase } from "#app/phases/exp-phase";
|
||||||
|
|
||||||
export default class PhaseInterceptor {
|
export default class PhaseInterceptor {
|
||||||
public scene;
|
public scene;
|
||||||
|
@ -127,7 +128,8 @@ export default class PhaseInterceptor {
|
||||||
[MysteryEncounterRewardsPhase, this.startPhase],
|
[MysteryEncounterRewardsPhase, this.startPhase],
|
||||||
[PostMysteryEncounterPhase, this.startPhase],
|
[PostMysteryEncounterPhase, this.startPhase],
|
||||||
[ModifierRewardPhase, this.startPhase],
|
[ModifierRewardPhase, this.startPhase],
|
||||||
[PartyExpPhase, this.startPhase]
|
[PartyExpPhase, this.startPhase],
|
||||||
|
[ExpPhase, this.startPhase],
|
||||||
];
|
];
|
||||||
|
|
||||||
private endBySetMode = [
|
private endBySetMode = [
|
||||||
|
|
|
@ -11,8 +11,11 @@ import { Stat } from "#enums/stat";
|
||||||
import BattleFlyout from "./battle-flyout";
|
import BattleFlyout from "./battle-flyout";
|
||||||
import { WindowVariant, addWindow } from "./ui-theme";
|
import { WindowVariant, addWindow } from "./ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import { ExpGainsSpeed } from "#app/enums/exp-gains-speed";
|
||||||
|
|
||||||
export default class BattleInfo extends Phaser.GameObjects.Container {
|
export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||||
|
public static readonly EXP_GAINS_DURATION_BASE = 1650;
|
||||||
|
|
||||||
private baseY: number;
|
private baseY: number;
|
||||||
|
|
||||||
private player: boolean;
|
private player: boolean;
|
||||||
|
@ -702,7 +705,11 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||||
instant = true;
|
instant = true;
|
||||||
}
|
}
|
||||||
const durationMultiplier = Phaser.Tweens.Builders.GetEaseFunction("Sine.easeIn")(1 - (Math.max(this.lastLevel - 100, 0) / 150));
|
const durationMultiplier = Phaser.Tweens.Builders.GetEaseFunction("Sine.easeIn")(1 - (Math.max(this.lastLevel - 100, 0) / 150));
|
||||||
const duration = this.visible && !instant ? (((levelExp - this.lastLevelExp) / relLevelExp) * 1650) * durationMultiplier * levelDurationMultiplier : 0;
|
let duration = this.visible && !instant ? (((levelExp - this.lastLevelExp) / relLevelExp) * BattleInfo.EXP_GAINS_DURATION_BASE) * durationMultiplier * levelDurationMultiplier : 0;
|
||||||
|
const speed = (this.scene as BattleScene).expGainsSpeed;
|
||||||
|
if (speed && speed >= ExpGainsSpeed.DEFAULT) {
|
||||||
|
duration = speed >= ExpGainsSpeed.SKIP ? ExpGainsSpeed.DEFAULT : duration / Math.pow(2, speed);
|
||||||
|
}
|
||||||
if (ratio === 1) {
|
if (ratio === 1) {
|
||||||
this.lastLevelExp = 0;
|
this.lastLevelExp = 0;
|
||||||
this.lastLevel++;
|
this.lastLevel++;
|
||||||
|
|
Loading…
Reference in New Issue