mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-15 06:15:20 +01:00
Merge pull request #6736 from pagefaultgames/hotfix-1.11.2
Hotfix 1.11.2 to beta
This commit is contained in:
commit
7b3e00a55b
2
locales
2
locales
@ -1 +1 @@
|
||||
Subproject commit 67a0c02606848cc6ca3f8998a7cbacb0d7dd5a9e
|
||||
Subproject commit ddf9509e1c6abe8fc93b455d79bfaa0202e05ede
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "pokemon-rogue-battle",
|
||||
"private": true,
|
||||
"version": "1.11.1",
|
||||
"version": "1.11.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start:prod": "vite --mode production",
|
||||
|
||||
@ -34,6 +34,7 @@ import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveFlags } from "#enums/move-flags";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
|
||||
import { MovePriorityInBracket } from "#enums/move-priority-in-bracket";
|
||||
import { MoveResult } from "#enums/move-result";
|
||||
import { MoveTarget } from "#enums/move-target";
|
||||
import { MoveUseMode } from "#enums/move-use-mode";
|
||||
@ -4142,6 +4143,25 @@ export class ChangeMovePriorityAbAttr extends AbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
export class ChangeMovePriorityInBracketAbAttr extends AbAttr {
|
||||
private readonly newModifier: MovePriorityInBracket;
|
||||
private readonly moveFunc: (pokemon: Pokemon, move: Move) => boolean;
|
||||
|
||||
constructor(moveFunc: (pokemon: Pokemon, move: Move) => boolean, newModifier: MovePriorityInBracket) {
|
||||
super(false);
|
||||
this.newModifier = newModifier;
|
||||
this.moveFunc = moveFunc;
|
||||
}
|
||||
|
||||
override canApply({ pokemon, move }: ChangeMovePriorityAbAttrParams): boolean {
|
||||
return this.moveFunc(pokemon, move);
|
||||
}
|
||||
|
||||
override apply({ priority }: ChangeMovePriorityAbAttrParams): void {
|
||||
priority.value = this.newModifier;
|
||||
}
|
||||
}
|
||||
|
||||
export class IgnoreContactAbAttr extends AbAttr {
|
||||
private declare readonly _: never;
|
||||
}
|
||||
@ -6721,6 +6741,7 @@ const AbilityAttrs = Object.freeze({
|
||||
BlockStatusDamageAbAttr,
|
||||
BlockOneHitKOAbAttr,
|
||||
ChangeMovePriorityAbAttr,
|
||||
ChangeMovePriorityInBracketAbAttr,
|
||||
IgnoreContactAbAttr,
|
||||
PreWeatherEffectAbAttr,
|
||||
PreWeatherDamageAbAttr,
|
||||
@ -7238,7 +7259,7 @@ export function initAbilities() {
|
||||
.attr(DoubleBattleChanceAbAttr)
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.STALL, 4)
|
||||
.attr(ChangeMovePriorityAbAttr, (_pokemon, _move: Move) => true, -0.2)
|
||||
.attr(ChangeMovePriorityInBracketAbAttr, (_pokemon, _move: Move) => true, MovePriorityInBracket.LAST)
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.TECHNICIAN, 4)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => {
|
||||
@ -7440,17 +7461,18 @@ export function initAbilities() {
|
||||
1.3)
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.ILLUSION, 5)
|
||||
// The Pokemon generate an illusion if it's available
|
||||
.attr(IllusionPreSummonAbAttr, false)
|
||||
.attr(IllusionBreakAbAttr)
|
||||
// The Pokemon loses its illusion when damaged by a move
|
||||
.attr(PostDefendIllusionBreakAbAttr, true)
|
||||
// Disable Illusion in fusions
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
// Illusion is available again after a battle
|
||||
.conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionPostBattleAbAttr, false)
|
||||
// // The Pokemon generate an illusion if it's available
|
||||
// .attr(IllusionPreSummonAbAttr, false)
|
||||
// .attr(IllusionBreakAbAttr)
|
||||
// // The Pokemon loses its illusion when damaged by a move
|
||||
// .attr(PostDefendIllusionBreakAbAttr, true)
|
||||
// // Disable Illusion in fusions
|
||||
// .attr(NoFusionAbilityAbAttr)
|
||||
// // Illusion is available again after a battle
|
||||
// .conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionPostBattleAbAttr, false)
|
||||
.uncopiable()
|
||||
.bypassFaint()
|
||||
// .bypassFaint()
|
||||
.unimplemented() // TODO reimplement Illusion properly
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.IMPOSTER, 5)
|
||||
.attr(PostSummonTransformAbAttr)
|
||||
@ -8185,7 +8207,7 @@ export function initAbilities() {
|
||||
.ignorable()
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.MYCELIUM_MIGHT, 9)
|
||||
.attr(ChangeMovePriorityAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, -0.2)
|
||||
.attr(ChangeMovePriorityInBracketAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, MovePriorityInBracket.LAST)
|
||||
.attr(PreventBypassSpeedChanceAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS)
|
||||
.attr(MoveAbilityBypassAbAttr, (_pokemon, move: Move) => move.category === MoveCategory.STATUS)
|
||||
.build(),
|
||||
|
||||
@ -506,7 +506,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = {
|
||||
[SpeciesId.SNOVER]: { 0: AbilityId.SLUSH_RUSH },
|
||||
[SpeciesId.ABOMASNOW]: { 0: AbilityId.SLUSH_RUSH, 1: AbilityId.SEED_SOWER },
|
||||
[SpeciesId.ROTOM]: { 0: AbilityId.HADRON_ENGINE, 1: AbilityId.HADRON_ENGINE, 2: AbilityId.HADRON_ENGINE, 3: AbilityId.HADRON_ENGINE, 4: AbilityId.HADRON_ENGINE, 5: AbilityId.HADRON_ENGINE },
|
||||
[SpeciesId.UXIE]: { 0: AbilityId.ILLUSION },
|
||||
[SpeciesId.UXIE]: { 0: AbilityId.MAGIC_BOUNCE },
|
||||
[SpeciesId.MESPRIT]: { 0: AbilityId.MOODY },
|
||||
[SpeciesId.AZELF]: { 0: AbilityId.NEUROFORCE },
|
||||
[SpeciesId.DIALGA]: { 0: AbilityId.BERSERK, 1: AbilityId.BERSERK },
|
||||
|
||||
@ -58,11 +58,19 @@ export function getDailyRunStarters(seed: string): StarterTuple {
|
||||
}
|
||||
|
||||
// TODO: Refactor this unmaintainable mess
|
||||
function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLevel: number): Starter {
|
||||
function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLevel: number, variant?: Variant): Starter {
|
||||
const starterSpecies =
|
||||
starterSpeciesForm instanceof PokemonSpecies ? starterSpeciesForm : getPokemonSpecies(starterSpeciesForm.speciesId);
|
||||
const formIndex = starterSpeciesForm instanceof PokemonSpecies ? undefined : starterSpeciesForm.formIndex;
|
||||
const pokemon = globalScene.addPlayerPokemon(starterSpecies, startingLevel, undefined, formIndex);
|
||||
const pokemon = globalScene.addPlayerPokemon(
|
||||
starterSpecies,
|
||||
startingLevel,
|
||||
undefined,
|
||||
formIndex,
|
||||
undefined,
|
||||
variant != null,
|
||||
variant,
|
||||
);
|
||||
const starter: Starter = {
|
||||
speciesId: starterSpecies.speciesId,
|
||||
shiny: pokemon.shiny,
|
||||
@ -172,7 +180,11 @@ export function isDailyEventSeed(seed: string): boolean {
|
||||
* Must be updated whenever the `MoveId` enum gets a new digit!
|
||||
*/
|
||||
const MOVE_ID_STRING_LENGTH = 4;
|
||||
|
||||
/**
|
||||
* The regex literal used to parse daily run custom movesets.
|
||||
* @privateRemarks
|
||||
* Intentionally does not use the `g` flag to avoid altering `lastIndex` after each match.
|
||||
*/
|
||||
const MOVE_ID_SEED_REGEX = /(?<=\/moves)((?:\d{4}){0,4})(?:,((?:\d{4}){0,4}))?(?:,((?:\d{4}){0,4}))?/;
|
||||
|
||||
/**
|
||||
@ -215,14 +227,106 @@ function setDailyRunEventStarterMovesets(seed: string, starters: StarterTuple):
|
||||
}
|
||||
}
|
||||
|
||||
/** The regex literal string used to extract the content of the "starters" block of Daily Run custom seeds. */
|
||||
const STARTER_SEED_PREFIX_REGEX = /\/starters(.*?)(?:\/|$)/;
|
||||
/**
|
||||
* The regex literal used to parse daily run custom starter information for a single starter. \
|
||||
* Contains a 4-digit species ID, as well as an optional 2-digit form index and 1-digit variant.
|
||||
*
|
||||
* If either of form index or variant are omitted, the starter will default to its species' base form/
|
||||
* not be shiny, respectively.
|
||||
*/
|
||||
const STARTER_SEED_MATCH_REGEX = /(?:s(?<species>\d{4}))(?:f(?<form>\d{2}))?(?:v(?<variant>\d))?/g;
|
||||
|
||||
/**
|
||||
* Parse a custom daily run seed into a set of pre-defined starters.
|
||||
* @see {@linkcode STARTER_SEED_MATCH_REGEX}
|
||||
* @param seed - The daily run seed
|
||||
* @returns An array of {@linkcode Starter}s, or `null` if it did not match.
|
||||
*/
|
||||
// TODO: Rework this setup into JSON or similar - this is quite hard to maintain
|
||||
function getDailyEventSeedStarters(seed: string): StarterTuple | null {
|
||||
if (!isDailyEventSeed(seed)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const seedAfterPrefix = seed.split(STARTER_SEED_PREFIX_REGEX)[1] as string | undefined;
|
||||
if (!seedAfterPrefix) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const speciesConfigurations = [...seedAfterPrefix.matchAll(STARTER_SEED_MATCH_REGEX)];
|
||||
|
||||
if (speciesConfigurations.length !== 3) {
|
||||
// TODO: Remove legacy fallback code after next hotfix version - this is needed for Oct 31's daily to function
|
||||
const legacyStarters = getDailyEventSeedStartersLegacy(seed);
|
||||
if (legacyStarters == null) {
|
||||
return legacyStarters;
|
||||
}
|
||||
console.error("Invalid starters used for custom daily run seed!", seed);
|
||||
return null;
|
||||
}
|
||||
|
||||
const speciesIds = getEnumValues(SpeciesId);
|
||||
const starters: Starter[] = [];
|
||||
|
||||
for (const match of speciesConfigurations) {
|
||||
const { groups } = match;
|
||||
if (!groups) {
|
||||
console.error("Invalid seed used for custom daily run starter:", match);
|
||||
return null;
|
||||
}
|
||||
|
||||
const { species: speciesStr, form: formStr, variant: variantStr } = groups;
|
||||
|
||||
const speciesId = Number.parseInt(speciesStr) as SpeciesId;
|
||||
|
||||
// NB: We check the parsed integer here to exclude SpeciesID.NONE as well as invalid values;
|
||||
// other fields only check the string to permit 0 as valid inputs
|
||||
if (!speciesId || !speciesIds.includes(speciesId)) {
|
||||
console.error("Invalid species ID used for custom daily run starter:", speciesStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
const starterSpecies = getPokemonSpecies(speciesId);
|
||||
// Omitted form index = use base form
|
||||
const starterForm = formStr ? starterSpecies.forms[Number.parseInt(formStr)] : starterSpecies;
|
||||
|
||||
if (!starterForm) {
|
||||
console.log(starterSpecies.name);
|
||||
console.error("Invalid form index used for custom daily run starter:", formStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get and validate variant
|
||||
let variant = (variantStr ? Number.parseInt(variantStr) : undefined) as Variant | undefined;
|
||||
if (!isBetween(variant ?? 0, 0, 2)) {
|
||||
console.error("Variant used for custom daily run seed starter out of bounds:", variantStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fall back to default variant if none exists
|
||||
if (!starterSpecies.hasVariants() && !!variant) {
|
||||
console.warn("Variant for custom daily run seed starter does not exist, using base variant...", variant);
|
||||
variant = undefined;
|
||||
}
|
||||
|
||||
const startingLevel = globalScene.gameMode.getStartingLevel();
|
||||
const starter = getDailyRunStarter(starterForm, startingLevel, variant);
|
||||
starters.push(starter);
|
||||
}
|
||||
|
||||
return starters as StarterTuple;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the seed to contain `/starters\d{18}/`
|
||||
* where the digits alternate between 4 digits for the species ID and 2 digits for the form index
|
||||
* (left padded with `0`s as necessary).
|
||||
* @returns An array of {@linkcode Starter}s, or `null` if no valid match.
|
||||
*/
|
||||
// TODO: Rework this setup into JSON or similar - this is quite hard to maintain
|
||||
export function getDailyEventSeedStarters(seed: string): StarterTuple | null {
|
||||
// TODO: Can be removed after october 31st 2025
|
||||
function getDailyEventSeedStartersLegacy(seed: string): StarterTuple | null {
|
||||
if (!isDailyEventSeed(seed)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -101,6 +101,7 @@ import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
|
||||
import { inSpeedOrder } from "#utils/speed-order-generator";
|
||||
import { canSpeciesTera, willTerastallize } from "#utils/pokemon-utils";
|
||||
import type { ReadonlyGenericUint8Array } from "#types/typed-arrays";
|
||||
import { MovePriorityInBracket } from "#enums/move-priority-in-bracket";
|
||||
|
||||
/**
|
||||
* A function used to conditionally determine execution of a given {@linkcode MoveAttr}.
|
||||
@ -1060,17 +1061,21 @@ export abstract class Move implements Localizable {
|
||||
|
||||
getPriority(user: Pokemon, simulated: boolean = true) {
|
||||
const priority = new NumberHolder(this.priority);
|
||||
|
||||
applyMoveAttrs("IncrementMovePriorityAttr", user, null, this, priority);
|
||||
applyAbAttrs("ChangeMovePriorityAbAttr", {pokemon: user, simulated, move: this, priority});
|
||||
|
||||
if (user.getTag(BattlerTagType.BYPASS_SPEED)) {
|
||||
priority.value += 0.2;
|
||||
}
|
||||
|
||||
return priority.value;
|
||||
}
|
||||
|
||||
public getPriorityModifier(user: Pokemon, simulated = true) {
|
||||
if (user.getTag(BattlerTagType.BYPASS_SPEED)) {
|
||||
return MovePriorityInBracket.FIRST;
|
||||
}
|
||||
const modifierHolder = new NumberHolder(MovePriorityInBracket.NORMAL);
|
||||
applyAbAttrs("ChangeMovePriorityInBracketAbAttr", { pokemon: user, simulated, move: this, priority: modifierHolder });
|
||||
return modifierHolder.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the [Expected Power](https://en.wikipedia.org/wiki/Expected_value) per turn
|
||||
* of this move, taking into account multi hit moves, accuracy, and the number of turns it
|
||||
|
||||
@ -67,7 +67,7 @@ export class Terrain {
|
||||
return (
|
||||
!isFieldTargeted(move)
|
||||
&& !isSpreadMove(move)
|
||||
&& move.getPriority(user) > 0.2 // fractional priority is used by quick claw etc and is not blocked by terrain
|
||||
&& move.getPriority(user) > 0
|
||||
&& user.getOpponents(true).some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded())
|
||||
);
|
||||
}
|
||||
|
||||
13
src/enums/move-priority-in-bracket.ts
Normal file
13
src/enums/move-priority-in-bracket.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
/**
|
||||
* Enum representing modifiers for Move priorities.
|
||||
*/
|
||||
export const MovePriorityInBracket = Object.freeze({
|
||||
/** Used when moves go last in their priority bracket, but before moves of lower priority. */
|
||||
LAST: 0,
|
||||
NORMAL: 1,
|
||||
/** Used when moves go first in their priority bracket, but before moves of lower priority. */
|
||||
FIRST: 2,
|
||||
});
|
||||
export type MovePriorityInBracket = ObjectValues<typeof MovePriorityInBracket>;
|
||||
@ -143,7 +143,6 @@ import type { AbAttrMap, AbAttrString, TypeMultiplierAbAttrParams } from "#types
|
||||
import type { Constructor } from "#types/common";
|
||||
import type { getAttackDamageParams, getBaseDamageParams } from "#types/damage-params";
|
||||
import type { DamageCalculationResult, DamageResult } from "#types/damage-result";
|
||||
import type { IllusionData } from "#types/illusion-data";
|
||||
import type { LevelMoves } from "#types/pokemon-level-moves";
|
||||
import type { StarterDataEntry, StarterMoveset } from "#types/save-data";
|
||||
import type { TurnMove } from "#types/turn-move";
|
||||
@ -5119,14 +5118,12 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* in preparation for switching pokemon, as well as removing any relevant on-switch tags.
|
||||
*/
|
||||
public resetSummonData(): void {
|
||||
const illusion: IllusionData | null = this.summonData.illusion;
|
||||
if (this.summonData.speciesForm) {
|
||||
this.summonData.speciesForm = null;
|
||||
this.updateFusionPalette();
|
||||
}
|
||||
this.summonData = new PokemonSummonData();
|
||||
this.tempSummonData = new PokemonTempSummonData();
|
||||
this.summonData.illusion = illusion;
|
||||
this.updateInfo();
|
||||
}
|
||||
|
||||
|
||||
@ -69,6 +69,10 @@ export class TurnStartPhase extends FieldPhase {
|
||||
|
||||
const phaseManager = globalScene.phaseManager;
|
||||
for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) {
|
||||
if (globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]?.command !== Command.FIGHT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
applyAbAttrs("BypassSpeedChanceAbAttr", { pokemon });
|
||||
globalScene.applyModifiers(BypassSpeedChanceModifier, pokemon.isPlayer(), pokemon);
|
||||
}
|
||||
|
||||
@ -92,11 +92,18 @@ export class MovePhasePriorityQueue extends PokemonPhasePriorityQueue<MovePhase>
|
||||
});
|
||||
|
||||
const timingModifiers = [a, b].map(movePhase => movePhase.timingModifier);
|
||||
const priorityModifiers = [a, b].map(movePhase =>
|
||||
movePhase.move.getMove().getPriorityModifier(movePhase.pokemon),
|
||||
);
|
||||
|
||||
if (timingModifiers[0] !== timingModifiers[1]) {
|
||||
return timingModifiers[1] - timingModifiers[0];
|
||||
}
|
||||
|
||||
if (priority[0] === priority[1] && priorityModifiers[0] !== priorityModifiers[1]) {
|
||||
return priorityModifiers[1] - priorityModifiers[0];
|
||||
}
|
||||
|
||||
return priority[1] - priority[0];
|
||||
});
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
|
||||
let pokemonIconX = -20;
|
||||
let pokemonIconY = 6;
|
||||
|
||||
if (["de", "es-ES", "es-419", "fr", "ko", "pt-BR", "ja", "ru"].includes(currentLanguage)) {
|
||||
if (["de", "es-ES", "es-419", "fr", "ko", "pt-BR", "ja", "ru", "tr"].includes(currentLanguage)) {
|
||||
gachaTextStyle = TextStyle.SMALLER_WINDOW_ALT;
|
||||
gachaX = 2;
|
||||
gachaY = 2;
|
||||
@ -89,7 +89,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
|
||||
|
||||
let legendaryLabelX = gachaX;
|
||||
let legendaryLabelY = gachaY;
|
||||
if (["de", "es-ES", "es-419"].includes(currentLanguage)) {
|
||||
if (["de", "es-ES", "es-419", "tr"].includes(currentLanguage)) {
|
||||
pokemonIconX = -25;
|
||||
pokemonIconY = 10;
|
||||
legendaryLabelX = -6;
|
||||
@ -108,8 +108,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
|
||||
let xOffset = 0;
|
||||
const pokemonIcon = globalScene.add.sprite(pokemonIconX, pokemonIconY, "pokemon_icons_0");
|
||||
|
||||
// Intentionally left as "array includes" instead of an equality check to allow for future languages to reuse
|
||||
if (["pt-BR"].includes(currentLanguage)) {
|
||||
if (["pt-BR", "tr"].includes(currentLanguage)) {
|
||||
xOffset = 2;
|
||||
pokemonIcon.setX(pokemonIconX - 2);
|
||||
}
|
||||
@ -120,14 +119,14 @@ export class EggGachaUiHandler extends MessageUiHandler {
|
||||
}
|
||||
break;
|
||||
case GachaType.MOVE:
|
||||
if (["de", "es-ES", "fr", "pt-BR", "ru"].includes(currentLanguage)) {
|
||||
if (["de", "es-ES", "fr", "pt-BR", "ru", "tr"].includes(currentLanguage)) {
|
||||
gachaUpLabel.setAlign("center").setY(0);
|
||||
}
|
||||
|
||||
gachaUpLabel.setText(i18next.t("egg:moveUpGacha")).setX(0).setOrigin(0.5, 0);
|
||||
break;
|
||||
case GachaType.SHINY:
|
||||
if (["de", "fr", "ko", "ru"].includes(currentLanguage)) {
|
||||
if (["de", "fr", "ko", "ru", "tr"].includes(currentLanguage)) {
|
||||
gachaUpLabel.setAlign("center").setY(0);
|
||||
}
|
||||
|
||||
|
||||
@ -251,7 +251,7 @@ export class GameStatsUiHandler extends UiHandler {
|
||||
const resolvedLang = i18next.resolvedLanguage ?? "en";
|
||||
// NOTE TO TRANSLATION TEAM: Add more languages that want to display
|
||||
// in a single-column inside of the `[]` (e.g. `["ru", "fr"]`)
|
||||
return ["fr", "es-ES", "es-419", "it", "ja", "pt-BR", "ru"].includes(resolvedLang);
|
||||
return ["fr", "es-ES", "es-419", "it", "ja", "pt-BR", "ru", "tr"].includes(resolvedLang);
|
||||
}
|
||||
/** The number of columns used by this menu in the resolved language */
|
||||
private get columnCount(): 1 | 2 {
|
||||
|
||||
@ -155,6 +155,7 @@ const languageSettings: { [key: string]: LanguageSetting } = {
|
||||
tr: {
|
||||
starterInfoTextSize: "56px",
|
||||
instructionTextSize: "38px",
|
||||
starterInfoXPos: 34,
|
||||
},
|
||||
ro: {
|
||||
starterInfoTextSize: "56px",
|
||||
|
||||
@ -118,11 +118,9 @@ export function getFusedSpeciesName(speciesAName: string, speciesBName: string):
|
||||
}
|
||||
|
||||
export function getPokemonSpeciesForm(species: SpeciesId, formIndex: number): PokemonSpeciesForm {
|
||||
const retSpecies: PokemonSpecies =
|
||||
species >= 2000
|
||||
? allSpecies.find(s => s.speciesId === species)! // TODO: is the bang correct?
|
||||
: allSpecies[species - 1];
|
||||
if (formIndex < retSpecies.forms?.length) {
|
||||
const retSpecies: PokemonSpecies = getPokemonSpecies(species);
|
||||
|
||||
if (formIndex < retSpecies.forms.length) {
|
||||
return retSpecies.forms[formIndex];
|
||||
}
|
||||
return retSpecies;
|
||||
|
||||
@ -7,7 +7,7 @@ import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
describe("Abilities - Illusion", () => {
|
||||
describe.todo("Abilities - Illusion", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ describe("Arena - Psychic Terrain", () => {
|
||||
await game.phaseInterceptor.to("MovePhase", false);
|
||||
|
||||
const feebas = game.field.getPlayerPokemon();
|
||||
expect(allMoves[MoveId.POUND].getPriority(feebas)).toBe(0.2);
|
||||
expect(allMoves[MoveId.POUND].getPriority(feebas)).toBe(0);
|
||||
|
||||
await game.toEndOfTurn();
|
||||
|
||||
@ -93,7 +93,7 @@ describe("Arena - Psychic Terrain", () => {
|
||||
await game.phaseInterceptor.to("MovePhase", false);
|
||||
|
||||
const feebas = game.field.getPlayerPokemon();
|
||||
expect(allMoves[MoveId.QUICK_ATTACK].getPriority(feebas)).toBe(1.2);
|
||||
expect(allMoves[MoveId.QUICK_ATTACK].getPriority(feebas)).toBe(1);
|
||||
|
||||
await game.toEndOfTurn();
|
||||
|
||||
|
||||
@ -21,6 +21,8 @@ describe("Daily Mode", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
|
||||
game.override.disableShinies = false;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -41,52 +43,85 @@ describe("Daily Mode", () => {
|
||||
});
|
||||
|
||||
describe("Custom Seeds", () => {
|
||||
it("should support custom moves", async () => {
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004,03320006,01300919");
|
||||
await game.dailyMode.startBattle();
|
||||
describe("Moves", () => {
|
||||
it("should support custom moves", async () => {
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004,03320006,01300919");
|
||||
await game.dailyMode.startBattle();
|
||||
|
||||
const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId));
|
||||
expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([
|
||||
MoveId.POUND,
|
||||
MoveId.KARATE_CHOP,
|
||||
MoveId.DOUBLE_SLAP,
|
||||
MoveId.COMET_PUNCH,
|
||||
]);
|
||||
expect(moves2, stringifyEnumArray(MoveId, moves2)).toEqual([
|
||||
MoveId.AERIAL_ACE,
|
||||
MoveId.PAY_DAY,
|
||||
expect.anything(), // make sure it doesn't replace normal moveset gen
|
||||
expect.anything(),
|
||||
]);
|
||||
expect(moves3, stringifyEnumArray(MoveId, moves3)).toEqual([
|
||||
MoveId.SKULL_BASH,
|
||||
MoveId.MALIGNANT_CHAIN,
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
]);
|
||||
const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId));
|
||||
expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([
|
||||
MoveId.POUND,
|
||||
MoveId.KARATE_CHOP,
|
||||
MoveId.DOUBLE_SLAP,
|
||||
MoveId.COMET_PUNCH,
|
||||
]);
|
||||
expect(moves2, stringifyEnumArray(MoveId, moves2)).toEqual([
|
||||
MoveId.AERIAL_ACE,
|
||||
MoveId.PAY_DAY,
|
||||
expect.anything(), // make sure it doesn't replace normal moveset gen
|
||||
expect.anything(),
|
||||
]);
|
||||
expect(moves3, stringifyEnumArray(MoveId, moves3)).toEqual([
|
||||
MoveId.SKULL_BASH,
|
||||
MoveId.MALIGNANT_CHAIN,
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
]);
|
||||
});
|
||||
|
||||
it("should allow omitting movesets for some starters", async () => {
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004");
|
||||
await game.dailyMode.startBattle();
|
||||
|
||||
const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId));
|
||||
expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([
|
||||
MoveId.POUND,
|
||||
MoveId.KARATE_CHOP,
|
||||
MoveId.DOUBLE_SLAP,
|
||||
MoveId.COMET_PUNCH,
|
||||
]);
|
||||
expect(moves2, "was not a random moveset").toHaveLength(4);
|
||||
expect(moves3, "was not a random moveset").toHaveLength(4);
|
||||
});
|
||||
|
||||
it("should skip invalid move IDs", async () => {
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves9999,,0919");
|
||||
await game.dailyMode.startBattle();
|
||||
|
||||
const moves = game.field.getPlayerPokemon().moveset.map(pm => pm.moveId);
|
||||
expect(moves, "invalid move was in moveset").not.toContain(MoveId[9999]);
|
||||
});
|
||||
});
|
||||
|
||||
it("should allow omitting movesets for some starters", async () => {
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004");
|
||||
await game.dailyMode.startBattle();
|
||||
describe("Starters", () => {
|
||||
it("should support custom species IDs", async () => {
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("foo/starterss0001s0113s1024");
|
||||
await game.dailyMode.startBattle();
|
||||
|
||||
const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId));
|
||||
expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([
|
||||
MoveId.POUND,
|
||||
MoveId.KARATE_CHOP,
|
||||
MoveId.DOUBLE_SLAP,
|
||||
MoveId.COMET_PUNCH,
|
||||
]);
|
||||
expect(moves2, "was not a random moveset").toHaveLength(4);
|
||||
expect(moves3, "was not a random moveset").toHaveLength(4);
|
||||
});
|
||||
const party = game.scene.getPlayerParty().map(p => p.species.speciesId);
|
||||
expect(party, stringifyEnumArray(SpeciesId, party)).toEqual([
|
||||
SpeciesId.BULBASAUR,
|
||||
SpeciesId.CHANSEY,
|
||||
SpeciesId.TERAPAGOS,
|
||||
]);
|
||||
});
|
||||
|
||||
it("should skip invalid move IDs", async () => {
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves9999,,0919");
|
||||
await game.dailyMode.startBattle();
|
||||
it("should support custom forms and variants", async () => {
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/starterss0006f01v2s0113v0s1024f02");
|
||||
await game.dailyMode.startBattle();
|
||||
|
||||
const moves = game.field.getPlayerPokemon().moveset.map(pm => pm.moveId);
|
||||
expect(moves, "invalid move was in moveset").not.toContain(MoveId[9999]);
|
||||
const party = game.scene.getPlayerParty().map(p => ({
|
||||
speciesId: p.species.speciesId,
|
||||
variant: p.getVariant(),
|
||||
form: p.formIndex,
|
||||
shiny: p.isShiny(),
|
||||
}));
|
||||
expect(party).toEqual<typeof party>([
|
||||
{ speciesId: SpeciesId.CHARIZARD, variant: 2, form: 1, shiny: true },
|
||||
{ speciesId: SpeciesId.CHANSEY, variant: 0, form: 0, shiny: true },
|
||||
{ speciesId: SpeciesId.TERAPAGOS, variant: expect.anything(), form: 2, shiny: false },
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user