Push progress so I can sync to beta

This commit is contained in:
RedstonewolfX 2024-09-18 14:25:22 -04:00
parent 029dfa4b3b
commit 21315a3664
11 changed files with 131 additions and 32 deletions

View File

@ -1674,6 +1674,11 @@ export default class BattleScene extends SceneBase {
this.scoreText.setVisible(this.gameMode.isDaily);
}
/**
* Displays the current luck value.
* @param duration The time for this label to fade in, if it is not already visible.
* @param isDaily If true, hides the label. (This is done because Luck does not apply in Daily Mode anymore)
*/
updateAndShowText(duration: number, isDaily?: boolean): void {
const labels = [ this.luckLabelText, this.luckText ];
labels.forEach(t => t.setAlpha(0));
@ -1685,6 +1690,10 @@ export default class BattleScene extends SceneBase {
this.luckText.setTint(0xffef5c, 0x47ff69, 0x6b6bff, 0xff6969);
}
this.luckLabelText.setX((this.game.canvas.width / 6) - 2 - (this.luckText.displayWidth + 2));
if (isDaily) {
// Hide luck label
labels.forEach(t => t.setVisible(false));
}
this.tweens.add({
targets: labels,
duration: duration,

View File

@ -1700,7 +1700,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.AMULET_COIN, skipInLastClassicWaveOrDefault(3)),
new WeightedModifierType(modifierTypes.EVIOLITE, (party: Pokemon[]) => {
const { gameMode, gameData } = party[0].scene;
if (party[0].scene.gameMode.isDaily || gameMode.isDaily || (!gameMode.isFreshStartChallenge() && gameData.isUnlocked(Unlockables.EVIOLITE))) {
if (gameMode.isDaily || (!gameMode.isFreshStartChallenge() && gameData.isUnlocked(Unlockables.EVIOLITE))) {
return party.some(p => ((p.getSpeciesForm(true).speciesId in pokemonEvolutions) || (p.isFusion() && (p.getFusionSpeciesForm(true).speciesId in pokemonEvolutions))) && !p.getHeldItems().some(i => i instanceof Modifiers.EvolutionStatBoosterModifier)) ? 10 : 0;
}
return 0;
@ -2418,11 +2418,16 @@ export class ModifierTypeOption {
}
}
/**
* Calculates the team's luck value.
* @param party The player's party.
* @returns A value between 0 and 14, or 0 if the player is in Daily Run mode.
*/
export function getPartyLuckValue(party: Pokemon[]): integer {
if (party[0].scene.gameMode.isDaily) {
return 0;
}
const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() : 0)
const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? (p.scene.gameMode.isDaily ? 0 : p.getLuck()) : 0)
.reduce((total: integer, value: integer) => total += value, 0), 0, 14);
return luck || 0;
}

View File

@ -72,9 +72,9 @@ class DefaultOverrides {
},
};
/** Forces an item to be UNLOCKED */
readonly UNLOCK_OVERRIDE: Unlockables[] = [];
readonly ITEM_UNLOCK_OVERRIDE: Unlockables[] = [];
/** Set to `true` to show all tutorials */
readonly BYPASS_TUTORIAL_SKIP: boolean = false;
readonly BYPASS_TUTORIAL_SKIP_OVERRIDE: boolean = false;
// ----------------
// PLAYER OVERRIDES

View File

@ -76,7 +76,8 @@ export class TitlePhase extends Phase {
this.scene.ui.clearText();
this.end();
};
if (this.scene.gameData.isUnlocked(Unlockables.ENDLESS_MODE)) {
const { gameData } = this.scene;
if (gameData.isUnlocked(Unlockables.ENDLESS_MODE)) {
const options: OptionSelectItem[] = [
{
label: GameMode.getModeName(GameModes.CLASSIC),
@ -100,7 +101,7 @@ export class TitlePhase extends Phase {
}
}
];
if (this.scene.gameData.isUnlocked(Unlockables.SPLICED_ENDLESS_MODE)) {
if (gameData.isUnlocked(Unlockables.SPLICED_ENDLESS_MODE)) {
options.push({
label: GameMode.getModeName(GameModes.SPLICED_ENDLESS),
handler: () => {

View File

@ -371,8 +371,14 @@ export class GameData {
unlockPity: this.unlockPity.slice(0)
};
}
/**
* Checks if an `Unlockable` has been unlocked.
* @param unlockable The Unlockable to check
* @returns `true` if the player has unlocked this `Unlockable` or an override has enabled it
*/
public isUnlocked(unlockable: Unlockables): boolean {
if (Overrides.UNLOCK_OVERRIDE.includes(unlockable)) {
if (Overrides.ITEM_UNLOCK_OVERRIDE.includes(unlockable)) {
return true;
}
return this.unlocks[unlockable];

View File

@ -1,9 +1,12 @@
import { MapModifier } from "#app/modifier/modifier";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
import GameManager from "./utils/gameManager";
//import { Abilities } from "#app/enums/abilities";
//import { Moves } from "#app/enums/moves";
//import { itemPoolChecks } from "#app/modifier/modifier-type";
import { Moves } from "#app/enums/moves";
import { getPartyLuckValue, itemPoolChecks } from "#app/modifier/modifier-type";
import { Biome } from "#app/enums/biome";
import { BattleEndPhase } from "#app/phases/battle-end-phase";
import { Mode } from "#app/ui/ui";
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
//const TIMEOUT = 20 * 1000;
@ -38,7 +41,7 @@ describe("Daily Mode", () => {
});
});
/*
//*
// Need to figure out how to properly start a battle
// Need to fix eviolite - test keeps insisting it is not in loot table, even though Mini Black Hole (which is using the exact same condition) is
describe("Shop modifications", async () => {
@ -54,10 +57,14 @@ describe("Shop modifications", async () => {
game = new GameManager(phaserGame);
game.override
.startingWave(9)
.startingBiome(Biome.ICE_CAVE) // Will lead to Snowy Forest with randomly generated weather
.battleType("single")
.startingLevel(200)
.moveset([Moves.SURF])
.enemyAbility(Abilities.BALL_FETCH);
.startingLevel(100) // Avoid levelling up
.enemyLevel(1000) // Avoid opponent dying before game.doKillOpponents()
.disableTrainerWaves()
.moveset([Moves.KOWTOW_CLEAVE])
.enemyMoveset(Moves.SPLASH);
itemPoolChecks.set("EVIOLITE", false);
itemPoolChecks.set("MINI_BLACK_HOLE", false);
});
@ -66,5 +73,24 @@ describe("Shop modifications", async () => {
game.phaseInterceptor.restoreOg();
itemPoolChecks.clear();
});
it("should do literally anything please god im begging you", async () => {
await game.dailyMode.runToSummon();
const party = game.scene.getParty();
expect(party[0]).toBeDefined();
party[0].shiny = true;
expect(getPartyLuckValue(party)).toBe(0);
expect(itemPoolChecks.get("EVIOLITE")).toBeDefined();
expect(itemPoolChecks.get("EVIOLITE")).toBeFalsy();
expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeDefined();
expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeFalsy();
game.move.select(Moves.KOWTOW_CLEAVE);
await game.phaseInterceptor.to("DamagePhase");
await game.doKillOpponents();
await game.phaseInterceptor.to(BattleEndPhase);
game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => {
expect(game.scene.ui.getHandler()).toBeInstanceOf(ModifierSelectUiHandler);
});
});
});
//*/

View File

@ -2,8 +2,10 @@ import { GameMode, GameModes, getGameMode } from "#app/game-mode";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as Utils from "../utils";
import GameManager from "./utils/gameManager";
//import { getPartyLuckValue } from "#app/modifier/modifier-type";
//import { Species } from "#app/enums/species";
import { getPartyLuckValue } from "#app/modifier/modifier-type";
import { Species } from "#app/enums/species";
import { getPokemonSpecies } from "#app/data/pokemon-species";
describe("game-mode", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
@ -14,6 +16,7 @@ describe("game-mode", () => {
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
vi.clearAllMocks();
vi.resetAllMocks();
});
beforeEach(() => {
@ -43,12 +46,7 @@ describe("game-mode", () => {
expect(classicGameMode.isWaveTrainer(19, arena)).toBeFalsy();
});
});
/*
// Need to figure out how to properly start a battle
describe("Luck Check", async () => {
let classicGameMode: GameMode;
let dailyGameMode: GameMode;
describe.skip("Luck Check", async () => {
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
@ -61,24 +59,29 @@ describe("game-mode", () => {
beforeEach(() => {
game = new GameManager(phaserGame);
classicGameMode = getGameMode(GameModes.CLASSIC);
dailyGameMode = getGameMode(GameModes.DAILY);
});
it("applies luck in Classic", () => {
game.override
.shinyLevel(true, 2);
game.classicMode.startBattle([Species.PICHU]);
game.scene.addPlayerPokemon(getPokemonSpecies(Species.PICHU), 5, undefined, undefined, undefined, true, 2);
const party = game.scene.getParty();
expect(getPartyLuckValue(party)).toBe(3);
const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() : 0)
.reduce((total: integer, value: integer) => total += value, 0), 0, 14);
expect(luck).toBeGreaterThan(0);
expect(getPartyLuckValue(party)).toBeGreaterThan(0);
});
it("does not apply luck in Daily Runs", () => {
game.override
.shinyLevel(true, 2);
game.dailyMode.startBattle();
game.scene.addPlayerPokemon(getPokemonSpecies(Species.PICHU), 5, undefined, undefined, undefined, true, 2);
const party = game.scene.getParty();
const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() : 0)
.reduce((total: integer, value: integer) => total += value, 0), 0, 14);
expect(luck).toBeGreaterThan(0);
expect(getPartyLuckValue(party)).toBe(0);
});
});
//*/
});

View File

@ -2,6 +2,7 @@ import { BerryType } from "#app/enums/berry-type";
import { Button } from "#app/enums/buttons";
import { Moves } from "#app/enums/moves";
import { Species } from "#app/enums/species";
import { itemPoolChecks } from "#app/modifier/modifier-type";
import { BattleEndPhase } from "#app/phases/battle-end-phase";
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
@ -94,3 +95,47 @@ describe("UI - Transfer Items", () => {
await game.phaseInterceptor.to(SelectModifierPhase);
}, 20000);
});
describe("Test", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(async () => {
game = new GameManager(phaserGame);
game.override
.battleType("single")
.startingLevel(100)
.startingWave(1)
.startingHeldItems([
{ name: "BERRY", count: 1, type: BerryType.SITRUS },
{ name: "BERRY", count: 2, type: BerryType.APICOT },
{ name: "BERRY", count: 2, type: BerryType.LUM },
])
.moveset([Moves.DRAGON_CLAW])
.enemySpecies(Species.MAGIKARP)
.enemyMoveset([Moves.SPLASH]);
itemPoolChecks.set("EVIOLITE", false);
itemPoolChecks.set("MINI_BLACK_HOLE", false);
});
it("should run", async () => {
await game.classicMode.startBattle([Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA]);
game.move.select(Moves.DRAGON_CLAW);
game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => {
expect(game.scene.ui.getHandler()).toBeInstanceOf(ModifierSelectUiHandler);
});
await game.phaseInterceptor.to(BattleEndPhase);
});
});

View File

@ -302,8 +302,13 @@ export class OverridesHelper extends GameManagerHelper {
return this;
}
unlockUnlockable(unlockable: Unlockables[]) {
vi.spyOn(Overrides, "UNLOCK_OVERRIDE", "get").mockReturnValue(unlockable);
/**
* Gives the player access to an Unlockable.
* @param unlockable The Unlockable to enable.
* @returns this
*/
enableUnlockable(unlockable: Unlockables[]) {
vi.spyOn(Overrides, "ITEM_UNLOCK_OVERRIDE", "get").mockReturnValue(unlockable);
this.log("Temporarily unlocked the following content: ", unlockable);
return this;
}

View File

@ -74,11 +74,11 @@ const tutorialHandlers = {
* @returns a promise with result `true` if the tutorial was run and finished, `false` otherwise
*/
export async function handleTutorial(scene: BattleScene, tutorial: Tutorial): Promise<boolean> {
if (!scene.enableTutorials && !Overrides.BYPASS_TUTORIAL_SKIP) {
if (!scene.enableTutorials && !Overrides.BYPASS_TUTORIAL_SKIP_OVERRIDE) {
return false;
}
if (scene.gameData.getTutorialFlags()[tutorial] && !Overrides.BYPASS_TUTORIAL_SKIP) {
if (scene.gameData.getTutorialFlags()[tutorial] && !Overrides.BYPASS_TUTORIAL_SKIP_OVERRIDE) {
return false;
}

View File

@ -13,7 +13,6 @@ import * as Utils from "./../utils";
import Overrides from "#app/overrides";
import i18next from "i18next";
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
import { GameModes } from "#app/game-mode";
import { IntegerHolder } from "./../utils";
import Phaser from "phaser";
@ -231,7 +230,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
/* Multiplies the appearance duration by the speed parameter so that it is always constant, and avoids "flashbangs" at game speed x5 */
this.scene.showShopOverlay(750 * this.scene.gameSpeed);
this.scene.updateAndShowText(750, this.scene.gameMode.modeId === GameModes.DAILY);
this.scene.updateAndShowText(750, this.scene.gameMode.isDaily);
this.scene.updateBiomeWaveText();
this.scene.updateMoneyText();