Merge remote-tracking branch 'upstream/beta' into biome

This commit is contained in:
Bertie690 2025-04-29 13:11:05 -04:00
commit d12e8124b7
13 changed files with 813 additions and 475 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "pokemon-rogue-battle", "name": "pokemon-rogue-battle",
"private": true, "private": true,
"version": "1.8.4", "version": "1.8.5",
"type": "module", "type": "module",
"scripts": { "scripts": {
"start": "vite", "start": "vite",
@ -9,7 +9,7 @@
"build": "vite build", "build": "vite build",
"build:beta": "vite build --mode beta", "build:beta": "vite build --mode beta",
"preview": "vite preview", "preview": "vite preview",
"test": "vitest run", "test": "vitest run --no-isolate",
"test:cov": "vitest run --coverage --no-isolate", "test:cov": "vitest run --coverage --no-isolate",
"test:watch": "vitest watch --coverage --no-isolate", "test:watch": "vitest watch --coverage --no-isolate",
"test:silent": "vitest run --silent --no-isolate", "test:silent": "vitest run --silent --no-isolate",

View File

@ -3172,6 +3172,7 @@ export class PreSetStatusAbAttr extends AbAttr {
*/ */
export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
protected immuneEffects: StatusEffect[]; protected immuneEffects: StatusEffect[];
private lastEffect: StatusEffect;
/** /**
* @param immuneEffects - The status effects to which the Pokémon is immune. * @param immuneEffects - The status effects to which the Pokémon is immune.
@ -3197,6 +3198,7 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
*/ */
override applyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect, cancelled: BooleanHolder, args: any[]): void { override applyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect, cancelled: BooleanHolder, args: any[]): void {
cancelled.value = true; cancelled.value = true;
this.lastEffect = effect;
} }
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
@ -3204,7 +3206,7 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
i18next.t("abilityTriggers:statusEffectImmunityWithName", { i18next.t("abilityTriggers:statusEffectImmunityWithName", {
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
abilityName, abilityName,
statusEffectName: getStatusEffectDescriptor(args[0] as StatusEffect) statusEffectName: getStatusEffectDescriptor(this.lastEffect)
}) : }) :
i18next.t("abilityTriggers:statusEffectImmunity", { i18next.t("abilityTriggers:statusEffectImmunity", {
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),

View File

@ -4,12 +4,19 @@ export type SignatureSpecies = {
[key in string]: (Species | Species[])[]; [key in string]: (Species | Species[])[];
}; };
/* /**
* The signature species for each Gym Leader, Elite Four member, and Champion. * The signature species for each Gym Leader, Elite Four member, and Champion.
* The key is the trainer type, and the value is an array of Species or Species arrays. * The key is the trainer type, and the value is an array of Species or Species arrays.
* This is in a separate const so it can be accessed from other places and not just the trainerConfigs * This is in a separate const so it can be accessed from other places and not just the trainerConfigs
*
* @remarks
* The `Proxy` object allows us to define a handler that will intercept
* the property access and return an empty array if the property does not exist in the object.
*
* This means that accessing `signatureSpecies` will not throw an error if the property does not exist,
* but instead default to an empty array.
*/ */
export const signatureSpecies: SignatureSpecies = { export const signatureSpecies: SignatureSpecies = new Proxy({
// Gym Leaders- Kanto // Gym Leaders- Kanto
BROCK: [Species.ONIX, Species.GEODUDE, [Species.OMANYTE, Species.KABUTO], Species.AERODACTYL], BROCK: [Species.ONIX, Species.GEODUDE, [Species.OMANYTE, Species.KABUTO], Species.AERODACTYL],
MISTY: [Species.STARYU, Species.PSYDUCK, Species.WOOPER, Species.LAPRAS], MISTY: [Species.STARYU, Species.PSYDUCK, Species.WOOPER, Species.LAPRAS],
@ -92,71 +99,8 @@ export const signatureSpecies: SignatureSpecies = {
RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel
TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe
GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.SNOM, Species.CUBCHOO], // Tera Ice Swablu GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.SNOM, Species.CUBCHOO], // Tera Ice Swablu
}, {
// Elite Four- Kanto get(target, prop: string) {
LORELEI: [ return target[prop as keyof SignatureSpecies] ?? [];
Species.JYNX, }
[Species.SLOWBRO, Species.GALAR_SLOWBRO], });
Species.LAPRAS,
[Species.CLOYSTER, Species.ALOLA_SANDSLASH],
],
BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.GOLEM, Species.ALOLA_GOLEM]],
AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK],
LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR],
// Elite Four- Johto (Bruno included)
WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR],
KOGA: [[Species.MUK, Species.WEEZING], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL],
KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE],
// Elite Four- Hoenn
SIDNEY: [
[Species.SHIFTRY, Species.CACTURNE],
[Species.SHARPEDO, Species.CRAWDAUNT],
Species.ABSOL,
Species.MIGHTYENA,
],
PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.DRIFBLIM, Species.MISMAGIUS]],
GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW],
DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA],
// Elite Four- Sinnoh
AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION],
BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR],
FLINT: [
[Species.RAPIDASH, Species.FLAREON],
Species.MAGMORTAR,
[Species.STEELIX, Species.LOPUNNY],
Species.INFERNAPE,
], // Tera Fire Steelix or Lopunny
LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]],
// Elite Four- Unova
SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT],
MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK],
GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE],
CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS],
// Elite Four- Kalos
MALVA: [Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME],
SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE],
WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH],
DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN],
// Elite Four- Alola
HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]],
MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO],
OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC],
ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND],
KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON],
// Elite Four- Galar
MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL],
NESSA_ELITE: [Species.GOLISOPOD, [Species.QUAGSIRE, Species.PELIPPER], Species.TOXAPEX, Species.DREDNAW],
BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP],
ALLISTER_ELITE: [Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR],
RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON],
// Elite Four- Paldea
RIKA: [Species.CLODSIRE, [Species.DUGTRIO, Species.DONPHAN], Species.CAMERUPT, Species.WHISCASH], // Tera Ground Clodsire
POPPY: [Species.TINKATON, Species.BRONZONG, Species.CORVIKNIGHT, Species.COPPERAJAH], // Tera Steel Tinkaton
LARRY_ELITE: [Species.FLAMIGO, Species.STARAPTOR, [Species.ALTARIA, Species.TROPIUS], Species.ORICORIO], // Tera Flying Flamigo; random Oricorio
HASSEL: [Species.BAXCALIBUR, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.NOIVERN], // Tera Dragon Baxcalibur
// Elite Four- BBL
CRISPIN: [Species.BLAZIKEN, Species.MAGMORTAR, [Species.CAMERUPT, Species.TALONFLAME], Species.ROTOM], // Tera Fire Blaziken; Heat Rotom
AMARYS: [Species.METAGROSS, Species.SCIZOR, Species.EMPOLEON, Species.SKARMORY], // Tera Steel Metagross
LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.WHIMSICOTT, Species.ALCREMIE], Species.GRANBULL], // Tera Fairy Excadrill
DRAYTON: [Species.ARCHALUDON, Species.DRAGONITE, Species.HAXORUS, Species.SCEPTILE], // Tera Dragon Archaludon
};

View File

@ -2463,7 +2463,7 @@ export class StatusEffectAttr extends MoveEffectAttr {
return false; return false;
} }
if (((!pokemon.status || this.overrideStatus) || (pokemon.status.effect === this.effect && moveChance < 0)) if (((!pokemon.status || this.overrideStatus) || (pokemon.status.effect === this.effect && moveChance < 0))
&& pokemon.trySetStatus(this.effect, true, user, this.turnsRemaining, null, this.overrideStatus)) { && pokemon.trySetStatus(this.effect, true, user, this.turnsRemaining, null, this.overrideStatus, false)) {
applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, false, this.effect); applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, false, this.effect);
return true; return true;
} }

View File

@ -424,6 +424,7 @@ export async function initBattleWithEnemyConfig(partyConfig: EnemyPartyConfig):
console.log( console.log(
`Pokemon: ${getPokemonNameWithAffix(enemyPokemon)}`, `Pokemon: ${getPokemonNameWithAffix(enemyPokemon)}`,
`| Species ID: ${enemyPokemon.species.speciesId}`, `| Species ID: ${enemyPokemon.species.speciesId}`,
`| Level: ${enemyPokemon.level}`,
`| Nature: ${getNatureName(enemyPokemon.nature, true, true, true)}`, `| Nature: ${getNatureName(enemyPokemon.nature, true, true, true)}`,
); );
console.log(`Stats (IVs): ${stats}`); console.log(`Stats (IVs): ${stats}`);

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,6 @@ import BattleInfo, {
import type Move from "#app/data/moves/move"; import type Move from "#app/data/moves/move";
import { import {
HighCritAttr, HighCritAttr,
StatChangeBeforeDmgCalcAttr,
HitsTagAttr, HitsTagAttr,
applyMoveAttrs, applyMoveAttrs,
FixedDamageAttr, FixedDamageAttr,
@ -70,10 +69,8 @@ import {
EFFECTIVE_STATS, EFFECTIVE_STATS,
} from "#enums/stat"; } from "#enums/stat";
import { import {
DamageMoneyRewardModifier,
EnemyDamageBoosterModifier, EnemyDamageBoosterModifier,
EnemyDamageReducerModifier, EnemyDamageReducerModifier,
EnemyEndureChanceModifier,
EnemyFusionChanceModifier, EnemyFusionChanceModifier,
HiddenAbilityRateBoosterModifier, HiddenAbilityRateBoosterModifier,
BaseStatModifier, BaseStatModifier,
@ -119,7 +116,6 @@ import {
TypeImmuneTag, TypeImmuneTag,
getBattlerTag, getBattlerTag,
SemiInvulnerableTag, SemiInvulnerableTag,
TypeBoostTag,
MoveRestrictionBattlerTag, MoveRestrictionBattlerTag,
ExposedTag, ExposedTag,
DragonCheerTag, DragonCheerTag,
@ -188,7 +184,7 @@ import {
PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr, PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr,
applyAllyStatMultiplierAbAttrs, applyAllyStatMultiplierAbAttrs,
AllyStatMultiplierAbAttr, AllyStatMultiplierAbAttr,
MoveAbilityBypassAbAttr MoveAbilityBypassAbAttr,
} from "#app/data/abilities/ability"; } from "#app/data/abilities/ability";
import { allAbilities } from "#app/data/data-lists"; import { allAbilities } from "#app/data/data-lists";
import type PokemonData from "#app/system/pokemon-data"; import type PokemonData from "#app/system/pokemon-data";
@ -202,7 +198,7 @@ import {
EVOLVE_MOVE, EVOLVE_MOVE,
RELEARN_MOVE, RELEARN_MOVE,
} from "#app/data/balance/pokemon-level-moves"; } from "#app/data/balance/pokemon-level-moves";
import { DamageAchv, achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import type { StarterDataEntry, StarterMoveset } from "#app/system/game-data"; import type { StarterDataEntry, StarterMoveset } from "#app/system/game-data";
import { DexAttr } from "#app/system/game-data"; import { DexAttr } from "#app/system/game-data";
import { import {
@ -5533,9 +5529,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
sourcePokemon: Pokemon | null = null, sourcePokemon: Pokemon | null = null,
turnsRemaining = 0, turnsRemaining = 0,
sourceText: string | null = null, sourceText: string | null = null,
overrideStatus?: boolean overrideStatus?: boolean,
quiet = true,
): boolean { ): boolean {
if (!this.canSetStatus(effect, false, overrideStatus, sourcePokemon)) { if (!this.canSetStatus(effect, quiet, overrideStatus, sourcePokemon)) {
return false; return false;
} }
if (this.isFainted() && effect !== StatusEffect.FAINT) { if (this.isFainted() && effect !== StatusEffect.FAINT) {
@ -7030,6 +7027,15 @@ export class EnemyPokemon extends Pokemon {
} }
speciesId = prevolution; speciesId = prevolution;
} }
if (this.hasTrainer() && globalScene.currentBattle) {
const { waveIndex } = globalScene.currentBattle;
const ivs: number[] = [];
while (ivs.length < 6) {
ivs.push(this.randSeedIntRange(Math.floor(waveIndex / 10), 31));
}
this.ivs = ivs;
}
} }
this.aiType = this.aiType =

View File

@ -2,7 +2,12 @@ import { BattlerIndex } from "#app/battle";
import { BattleType } from "#enums/battle-type"; import { BattleType } from "#enums/battle-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
import { applyAbAttrs, SyncEncounterNatureAbAttr, applyPreSummonAbAttrs, PreSummonAbAttr } from "#app/data/abilities/ability"; import {
applyAbAttrs,
SyncEncounterNatureAbAttr,
applyPreSummonAbAttrs,
PreSummonAbAttr,
} from "#app/data/abilities/ability";
import { initEncounterAnims, loadEncounterAnimAssets } from "#app/data/battle-anims"; import { initEncounterAnims, loadEncounterAnimAssets } from "#app/data/battle-anims";
import { getCharVariantFromDialogue } from "#app/data/dialogue"; import { getCharVariantFromDialogue } from "#app/data/dialogue";
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
@ -196,6 +201,7 @@ export class EncounterPhase extends BattlePhase {
console.log( console.log(
`Pokemon: ${getPokemonNameWithAffix(enemyPokemon)}`, `Pokemon: ${getPokemonNameWithAffix(enemyPokemon)}`,
`| Species ID: ${enemyPokemon.species.speciesId}`, `| Species ID: ${enemyPokemon.species.speciesId}`,
`| Level: ${enemyPokemon.level}`,
`| Nature: ${getNatureName(enemyPokemon.nature, true, true, true)}`, `| Nature: ${getNatureName(enemyPokemon.nature, true, true, true)}`,
); );
console.log(`Stats (IVs): ${stats}`); console.log(`Stats (IVs): ${stats}`);

View File

@ -15,14 +15,17 @@ export class PokerogueSystemSavedataApi extends ApiBase {
/** /**
* Get a system savedata. * Get a system savedata.
* @param params The {@linkcode GetSystemSavedataRequest} to send * @param params The {@linkcode GetSystemSavedataRequest} to send
* @returns The system savedata as `string` or `null` on error * @returns The system savedata as `string` or either the status code or `null` on error
*/ */
public async get(params: GetSystemSavedataRequest) { public async get(params: GetSystemSavedataRequest): Promise<string | number | null> {
try { try {
const urlSearchParams = this.toUrlSearchParams(params); const urlSearchParams = this.toUrlSearchParams(params);
const response = await this.doGet(`/savedata/system/get?${urlSearchParams}`); const response = await this.doGet(`/savedata/system/get?${urlSearchParams}`);
const rawSavedata = await response.text(); const rawSavedata = await response.text();
if (!response.ok) {
console.warn("Could not get system savedata!", response.status, rawSavedata);
return response.status;
}
return rawSavedata; return rawSavedata;
} catch (err) { } catch (err) {
console.warn("Could not get system savedata!", err); console.warn("Could not get system savedata!", err);

View File

@ -462,8 +462,13 @@ export class GameData {
if (!bypassLogin) { if (!bypassLogin) {
pokerogueApi.savedata.system.get({ clientSessionId }).then(saveDataOrErr => { pokerogueApi.savedata.system.get({ clientSessionId }).then(saveDataOrErr => {
if (!saveDataOrErr || saveDataOrErr.length === 0 || saveDataOrErr[0] !== "{") { if (
if (saveDataOrErr?.startsWith("sql: no rows in result set")) { typeof saveDataOrErr === "number" ||
!saveDataOrErr ||
saveDataOrErr.length === 0 ||
saveDataOrErr[0] !== "{"
) {
if (saveDataOrErr === 404) {
globalScene.queueMessage( globalScene.queueMessage(
"Save data could not be found. If this is a new account, you can safely ignore this message.", "Save data could not be found. If this is a new account, you can safely ignore this message.",
null, null,
@ -471,7 +476,7 @@ export class GameData {
); );
return resolve(true); return resolve(true);
} }
if (saveDataOrErr?.includes("Too many connections")) { if (typeof saveDataOrErr === "string" && saveDataOrErr?.includes("Too many connections")) {
globalScene.queueMessage( globalScene.queueMessage(
"Too many people are trying to connect and the server is overloaded. Please try again later.", "Too many people are trying to connect and the server is overloaded. Please try again later.",
null, null,
@ -479,7 +484,6 @@ export class GameData {
); );
return resolve(false); return resolve(false);
} }
console.error(saveDataOrErr);
return resolve(false); return resolve(false);
} }
@ -1500,7 +1504,7 @@ export class GameData {
link.remove(); link.remove();
}; };
if (!bypassLogin && dataType < GameDataType.SETTINGS) { if (!bypassLogin && dataType < GameDataType.SETTINGS) {
let promise: Promise<string | null> = Promise.resolve(null); let promise: Promise<string | null | number> = Promise.resolve(null);
if (dataType === GameDataType.SYSTEM) { if (dataType === GameDataType.SYSTEM) {
promise = pokerogueApi.savedata.system.get({ clientSessionId }); promise = pokerogueApi.savedata.system.get({ clientSessionId });
@ -1512,7 +1516,7 @@ export class GameData {
} }
promise.then(response => { promise.then(response => {
if (!response?.length || response[0] !== "{") { if (typeof response === "number" || !response?.length || response[0] !== "{") {
console.error(response); console.error(response);
resolve(false); resolve(false);
return; return;

View File

@ -596,6 +596,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHandler();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub");
this.pokemonSprite.setPipeline(globalScene.spritePipeline, {
tone: [0.0, 0.0, 0.0, 0.0],
ignoreTimeTint: true,
});
this.starterSelectContainer.add(this.pokemonSprite);
this.pokemonNumberText = addTextObject(17, 1, "0000", TextStyle.SUMMARY); this.pokemonNumberText = addTextObject(17, 1, "0000", TextStyle.SUMMARY);
this.pokemonNumberText.setOrigin(0, 0); this.pokemonNumberText.setOrigin(0, 0);
this.starterSelectContainer.add(this.pokemonNumberText); this.starterSelectContainer.add(this.pokemonNumberText);
@ -825,13 +832,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
return icon; return icon;
}); });
this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub");
this.pokemonSprite.setPipeline(globalScene.spritePipeline, {
tone: [0.0, 0.0, 0.0, 0.0],
ignoreTimeTint: true,
});
this.starterSelectContainer.add(this.pokemonSprite);
this.type1Icon = globalScene.add.sprite(8, 98, getLocalizedSpriteKey("types")); this.type1Icon = globalScene.add.sprite(8, 98, getLocalizedSpriteKey("types"));
this.type1Icon.setScale(0.5); this.type1Icon.setScale(0.5);
this.type1Icon.setOrigin(0, 0); this.type1Icon.setOrigin(0, 0);

View File

@ -23,18 +23,18 @@ describe("Abilities - Illusion", () => {
beforeEach(() => { beforeEach(() => {
game = new GameManager(phaserGame); game = new GameManager(phaserGame);
game.override.battleStyle("single"); game.override
game.override.enemySpecies(Species.ZORUA); .battleStyle("single")
game.override.enemyAbility(Abilities.ILLUSION); .enemySpecies(Species.ZORUA)
game.override.enemyMoveset(Moves.TACKLE); .enemyAbility(Abilities.ILLUSION)
game.override.enemyHeldItems([{ name: "WIDE_LENS", count: 3 }]); .enemyMoveset(Moves.TACKLE)
.enemyHeldItems([{ name: "WIDE_LENS", count: 3 }])
game.override.moveset([Moves.WORRY_SEED, Moves.SOAK, Moves.TACKLE]); .moveset([Moves.WORRY_SEED, Moves.SOAK, Moves.TACKLE])
game.override.startingHeldItems([{ name: "WIDE_LENS", count: 3 }]); .startingHeldItems([{ name: "WIDE_LENS", count: 3 }]);
}); });
it("creates illusion at the start", async () => { it("creates illusion at the start", async () => {
await game.classicMode.startBattle([Species.ZOROARK, Species.AXEW]); await game.classicMode.startBattle([Species.ZOROARK, Species.FEEBAS]);
const zoroark = game.scene.getPlayerPokemon()!; const zoroark = game.scene.getPlayerPokemon()!;
const zorua = game.scene.getEnemyPokemon()!; const zorua = game.scene.getEnemyPokemon()!;
@ -43,7 +43,7 @@ describe("Abilities - Illusion", () => {
}); });
it("break after receiving damaging move", async () => { it("break after receiving damaging move", async () => {
await game.classicMode.startBattle([Species.AXEW]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -55,7 +55,7 @@ describe("Abilities - Illusion", () => {
}); });
it("break after getting ability changed", async () => { it("break after getting ability changed", async () => {
await game.classicMode.startBattle([Species.AXEW]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.WORRY_SEED); game.move.select(Moves.WORRY_SEED);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -76,7 +76,7 @@ describe("Abilities - Illusion", () => {
it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => { it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => {
game.override.enemyMoveset([Moves.FLAMETHROWER, Moves.PSYCHIC, Moves.TACKLE]); game.override.enemyMoveset([Moves.FLAMETHROWER, Moves.PSYCHIC, Moves.TACKLE]);
await game.classicMode.startBattle([Species.ZOROARK, Species.AXEW]); await game.classicMode.startBattle([Species.ZOROARK, Species.FEEBAS]);
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;
const zoroark = game.scene.getPlayerPokemon()!; const zoroark = game.scene.getPlayerPokemon()!;

View File

@ -209,4 +209,19 @@ describe("Spec - Pokemon", () => {
expect(types[1]).toBe(PokemonType.DARK); expect(types[1]).toBe(PokemonType.DARK);
}); });
}); });
it.each([5, 25, 55, 95, 145, 195])(
"should set minimum IVs for enemy trainer pokemon based on wave (%i)",
async wave => {
game.override.startingWave(wave);
await game.classicMode.startBattle([Species.FEEBAS]);
const { waveIndex } = game.scene.currentBattle;
for (const pokemon of game.scene.getEnemyParty()) {
for (const index in pokemon.ivs) {
expect(pokemon.ivs[index]).toBeGreaterThanOrEqual(Math.floor(waveIndex / 10));
}
}
},
);
}); });