mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-11 18:09:29 +02:00
Merge branch 'beta' into WorkingDiscardFunction
This commit is contained in:
commit
4478f41ff9
2
.github/workflows/deploy-beta.yml
vendored
2
.github/workflows/deploy-beta.yml
vendored
@ -11,7 +11,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
if: github.repository == 'pagefaultgames/pokerogue' && github.ref_name == ${{ vars.BETA_DEPLOY_BRANCH || 'beta' }}
|
if: github.repository == 'pagefaultgames/pokerogue' && github.ref_name == (vars.BETA_DEPLOY_BRANCH || 'beta')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
32
package.json
32
package.json
@ -29,34 +29,34 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.0.0",
|
"@biomejs/biome": "2.0.0",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/node": "^22.13.14",
|
"@types/node": "^22.16.3",
|
||||||
"@vitest/coverage-istanbul": "^3.0.9",
|
"@vitest/coverage-istanbul": "^3.2.4",
|
||||||
"chalk": "^5.4.1",
|
"chalk": "^5.4.1",
|
||||||
"dependency-cruiser": "^16.3.10",
|
"dependency-cruiser": "^16.10.4",
|
||||||
"inquirer": "^12.4.2",
|
"inquirer": "^12.7.0",
|
||||||
"jsdom": "^26.0.0",
|
"jsdom": "^26.1.0",
|
||||||
"lefthook": "^1.11.5",
|
"lefthook": "^1.12.2",
|
||||||
"msw": "^2.7.3",
|
"msw": "^2.10.4",
|
||||||
"phaser3spectorjs": "^0.0.8",
|
"phaser3spectorjs": "^0.0.8",
|
||||||
"typedoc": "^0.28.1",
|
"typedoc": "^0.28.7",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.3",
|
||||||
"vite": "^6.3.4",
|
"vite": "^6.3.5",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
"vitest": "^3.0.9",
|
"vitest": "^3.2.4",
|
||||||
"vitest-canvas-mock": "^0.3.3"
|
"vitest-canvas-mock": "^0.3.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material/material-color-utilities": "^0.2.7",
|
"@material/material-color-utilities": "^0.2.7",
|
||||||
"compare-versions": "^6.1.1",
|
"compare-versions": "^6.1.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"i18next": "^24.2.2",
|
"i18next": "^24.2.3",
|
||||||
"i18next-browser-languagedetector": "^8.0.4",
|
"i18next-browser-languagedetector": "^8.2.0",
|
||||||
"i18next-http-backend": "^3.0.2",
|
"i18next-http-backend": "^3.0.2",
|
||||||
"i18next-korean-postposition-processor": "^1.0.0",
|
"i18next-korean-postposition-processor": "^1.0.0",
|
||||||
"json-stable-stringify": "^1.2.0",
|
"json-stable-stringify": "^1.3.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"phaser": "^3.88.2",
|
"phaser": "^3.90.0",
|
||||||
"phaser3-rex-plugins": "^1.80.15"
|
"phaser3-rex-plugins": "^1.80.16"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.0.0"
|
"node": ">=22.0.0"
|
||||||
|
1987
pnpm-lock.yaml
1987
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,8 @@ import type { PartyMemberStrength } from "#enums/party-member-strength";
|
|||||||
import type { SpeciesId } from "#enums/species-id";
|
import type { SpeciesId } from "#enums/species-id";
|
||||||
import type { EnemyPokemon } from "#field/pokemon";
|
import type { EnemyPokemon } from "#field/pokemon";
|
||||||
import type { PersistentModifier } from "#modifiers/modifier";
|
import type { PersistentModifier } from "#modifiers/modifier";
|
||||||
import type { TrainerPartyTemplate } from "#trainers/TrainerPartyTemplate";
|
|
||||||
import type { TrainerConfig } from "#trainers/trainer-config";
|
import type { TrainerConfig } from "#trainers/trainer-config";
|
||||||
|
import type { TrainerPartyTemplate } from "#trainers/trainer-party-template";
|
||||||
|
|
||||||
export type PartyTemplateFunc = () => TrainerPartyTemplate;
|
export type PartyTemplateFunc = () => TrainerPartyTemplate;
|
||||||
export type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
export type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
||||||
|
369
src/battle.ts
369
src/battle.ts
@ -5,12 +5,9 @@ import { BattleSpec } from "#enums/battle-spec";
|
|||||||
import { BattleType } from "#enums/battle-type";
|
import { BattleType } from "#enums/battle-type";
|
||||||
import { BattlerIndex } from "#enums/battler-index";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import type { Command } from "#enums/command";
|
import type { Command } from "#enums/command";
|
||||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
|
||||||
import { ModifierTier } from "#enums/modifier-tier";
|
|
||||||
import type { MoveId } from "#enums/move-id";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { PlayerGender } from "#enums/player-gender";
|
|
||||||
import type { PokeballType } from "#enums/pokeball";
|
import type { PokeballType } from "#enums/pokeball";
|
||||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
@ -577,369 +574,3 @@ export function getRandomTrainerFunc(
|
|||||||
return new Trainer(trainerTypes[rand], trainerGender);
|
return new Trainer(trainerTypes[rand], trainerGender);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FixedBattleConfigs {
|
|
||||||
[key: number]: FixedBattleConfig;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Youngster/Lass on 5
|
|
||||||
* Rival on 8, 55, 95, 145, 195
|
|
||||||
* Evil team grunts on 35, 62, 64, and 112
|
|
||||||
* Evil team admin on 66 and 114
|
|
||||||
* Evil leader on 115, 165
|
|
||||||
* E4 on 182, 184, 186, 188
|
|
||||||
* Champion on 190
|
|
||||||
*/
|
|
||||||
export const classicFixedBattles: FixedBattleConfigs = {
|
|
||||||
[ClassicFixedBossWaves.TOWN_YOUNGSTER]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
() => new Trainer(TrainerType.YOUNGSTER, randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.RIVAL_1]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
() =>
|
|
||||||
new Trainer(
|
|
||||||
TrainerType.RIVAL,
|
|
||||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.RIVAL_2]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
() =>
|
|
||||||
new Trainer(
|
|
||||||
TrainerType.RIVAL_2,
|
|
||||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.setCustomModifierRewards({
|
|
||||||
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT],
|
|
||||||
allowLuckUpgrades: false,
|
|
||||||
}),
|
|
||||||
[ClassicFixedBossWaves.EVIL_GRUNT_1]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc(
|
|
||||||
[
|
|
||||||
TrainerType.ROCKET_GRUNT,
|
|
||||||
TrainerType.MAGMA_GRUNT,
|
|
||||||
TrainerType.AQUA_GRUNT,
|
|
||||||
TrainerType.GALACTIC_GRUNT,
|
|
||||||
TrainerType.PLASMA_GRUNT,
|
|
||||||
TrainerType.FLARE_GRUNT,
|
|
||||||
TrainerType.AETHER_GRUNT,
|
|
||||||
TrainerType.SKULL_GRUNT,
|
|
||||||
TrainerType.MACRO_GRUNT,
|
|
||||||
TrainerType.STAR_GRUNT,
|
|
||||||
],
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.RIVAL_3]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
() =>
|
|
||||||
new Trainer(
|
|
||||||
TrainerType.RIVAL_3,
|
|
||||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.setCustomModifierRewards({
|
|
||||||
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT],
|
|
||||||
allowLuckUpgrades: false,
|
|
||||||
}),
|
|
||||||
[ClassicFixedBossWaves.EVIL_GRUNT_2]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc(
|
|
||||||
[
|
|
||||||
TrainerType.ROCKET_GRUNT,
|
|
||||||
TrainerType.MAGMA_GRUNT,
|
|
||||||
TrainerType.AQUA_GRUNT,
|
|
||||||
TrainerType.GALACTIC_GRUNT,
|
|
||||||
TrainerType.PLASMA_GRUNT,
|
|
||||||
TrainerType.FLARE_GRUNT,
|
|
||||||
TrainerType.AETHER_GRUNT,
|
|
||||||
TrainerType.SKULL_GRUNT,
|
|
||||||
TrainerType.MACRO_GRUNT,
|
|
||||||
TrainerType.STAR_GRUNT,
|
|
||||||
],
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.EVIL_GRUNT_3]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc(
|
|
||||||
[
|
|
||||||
TrainerType.ROCKET_GRUNT,
|
|
||||||
TrainerType.MAGMA_GRUNT,
|
|
||||||
TrainerType.AQUA_GRUNT,
|
|
||||||
TrainerType.GALACTIC_GRUNT,
|
|
||||||
TrainerType.PLASMA_GRUNT,
|
|
||||||
TrainerType.FLARE_GRUNT,
|
|
||||||
TrainerType.AETHER_GRUNT,
|
|
||||||
TrainerType.SKULL_GRUNT,
|
|
||||||
TrainerType.MACRO_GRUNT,
|
|
||||||
TrainerType.STAR_GRUNT,
|
|
||||||
],
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.EVIL_ADMIN_1]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc(
|
|
||||||
[
|
|
||||||
[TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL],
|
|
||||||
[TrainerType.TABITHA, TrainerType.COURTNEY],
|
|
||||||
[TrainerType.MATT, TrainerType.SHELLY],
|
|
||||||
[TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN],
|
|
||||||
[TrainerType.ZINZOLIN, TrainerType.COLRESS],
|
|
||||||
[TrainerType.XEROSIC, TrainerType.BRYONY],
|
|
||||||
TrainerType.FABA,
|
|
||||||
TrainerType.PLUMERIA,
|
|
||||||
TrainerType.OLEANA,
|
|
||||||
[TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI],
|
|
||||||
],
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.RIVAL_4]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
() =>
|
|
||||||
new Trainer(
|
|
||||||
TrainerType.RIVAL_4,
|
|
||||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.setCustomModifierRewards({
|
|
||||||
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA],
|
|
||||||
allowLuckUpgrades: false,
|
|
||||||
}),
|
|
||||||
[ClassicFixedBossWaves.EVIL_GRUNT_4]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc(
|
|
||||||
[
|
|
||||||
TrainerType.ROCKET_GRUNT,
|
|
||||||
TrainerType.MAGMA_GRUNT,
|
|
||||||
TrainerType.AQUA_GRUNT,
|
|
||||||
TrainerType.GALACTIC_GRUNT,
|
|
||||||
TrainerType.PLASMA_GRUNT,
|
|
||||||
TrainerType.FLARE_GRUNT,
|
|
||||||
TrainerType.AETHER_GRUNT,
|
|
||||||
TrainerType.SKULL_GRUNT,
|
|
||||||
TrainerType.MACRO_GRUNT,
|
|
||||||
TrainerType.STAR_GRUNT,
|
|
||||||
],
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.EVIL_ADMIN_2]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc(
|
|
||||||
[
|
|
||||||
[TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL],
|
|
||||||
[TrainerType.TABITHA, TrainerType.COURTNEY],
|
|
||||||
[TrainerType.MATT, TrainerType.SHELLY],
|
|
||||||
[TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN],
|
|
||||||
[TrainerType.ZINZOLIN, TrainerType.COLRESS],
|
|
||||||
[TrainerType.XEROSIC, TrainerType.BRYONY],
|
|
||||||
TrainerType.FABA,
|
|
||||||
TrainerType.PLUMERIA,
|
|
||||||
TrainerType.OLEANA,
|
|
||||||
[TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI],
|
|
||||||
],
|
|
||||||
true,
|
|
||||||
1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc([
|
|
||||||
TrainerType.ROCKET_BOSS_GIOVANNI_1,
|
|
||||||
TrainerType.MAXIE,
|
|
||||||
TrainerType.ARCHIE,
|
|
||||||
TrainerType.CYRUS,
|
|
||||||
TrainerType.GHETSIS,
|
|
||||||
TrainerType.LYSANDRE,
|
|
||||||
TrainerType.LUSAMINE,
|
|
||||||
TrainerType.GUZMA,
|
|
||||||
TrainerType.ROSE,
|
|
||||||
TrainerType.PENNY,
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
.setCustomModifierRewards({
|
|
||||||
guaranteedModifierTiers: [
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
],
|
|
||||||
allowLuckUpgrades: false,
|
|
||||||
}),
|
|
||||||
[ClassicFixedBossWaves.RIVAL_5]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
() =>
|
|
||||||
new Trainer(
|
|
||||||
TrainerType.RIVAL_5,
|
|
||||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.setCustomModifierRewards({
|
|
||||||
guaranteedModifierTiers: [
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
],
|
|
||||||
allowLuckUpgrades: false,
|
|
||||||
}),
|
|
||||||
[ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc([
|
|
||||||
TrainerType.ROCKET_BOSS_GIOVANNI_2,
|
|
||||||
TrainerType.MAXIE_2,
|
|
||||||
TrainerType.ARCHIE_2,
|
|
||||||
TrainerType.CYRUS_2,
|
|
||||||
TrainerType.GHETSIS_2,
|
|
||||||
TrainerType.LYSANDRE_2,
|
|
||||||
TrainerType.LUSAMINE_2,
|
|
||||||
TrainerType.GUZMA_2,
|
|
||||||
TrainerType.ROSE_2,
|
|
||||||
TrainerType.PENNY_2,
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
.setCustomModifierRewards({
|
|
||||||
guaranteedModifierTiers: [
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
],
|
|
||||||
allowLuckUpgrades: false,
|
|
||||||
}),
|
|
||||||
[ClassicFixedBossWaves.ELITE_FOUR_1]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc([
|
|
||||||
TrainerType.LORELEI,
|
|
||||||
TrainerType.WILL,
|
|
||||||
TrainerType.SIDNEY,
|
|
||||||
TrainerType.AARON,
|
|
||||||
TrainerType.SHAUNTAL,
|
|
||||||
TrainerType.MALVA,
|
|
||||||
[TrainerType.HALA, TrainerType.MOLAYNE],
|
|
||||||
TrainerType.MARNIE_ELITE,
|
|
||||||
TrainerType.RIKA,
|
|
||||||
TrainerType.CRISPIN,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.ELITE_FOUR_2]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc([
|
|
||||||
TrainerType.BRUNO,
|
|
||||||
TrainerType.KOGA,
|
|
||||||
TrainerType.PHOEBE,
|
|
||||||
TrainerType.BERTHA,
|
|
||||||
TrainerType.MARSHAL,
|
|
||||||
TrainerType.SIEBOLD,
|
|
||||||
TrainerType.OLIVIA,
|
|
||||||
TrainerType.NESSA_ELITE,
|
|
||||||
TrainerType.POPPY,
|
|
||||||
TrainerType.AMARYS,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.ELITE_FOUR_3]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc([
|
|
||||||
TrainerType.AGATHA,
|
|
||||||
TrainerType.BRUNO,
|
|
||||||
TrainerType.GLACIA,
|
|
||||||
TrainerType.FLINT,
|
|
||||||
TrainerType.GRIMSLEY,
|
|
||||||
TrainerType.WIKSTROM,
|
|
||||||
TrainerType.ACEROLA,
|
|
||||||
[TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE],
|
|
||||||
TrainerType.LARRY_ELITE,
|
|
||||||
TrainerType.LACEY,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.ELITE_FOUR_4]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc([
|
|
||||||
TrainerType.LANCE,
|
|
||||||
TrainerType.KAREN,
|
|
||||||
TrainerType.DRAKE,
|
|
||||||
TrainerType.LUCIAN,
|
|
||||||
TrainerType.CAITLIN,
|
|
||||||
TrainerType.DRASNA,
|
|
||||||
TrainerType.KAHILI,
|
|
||||||
TrainerType.RAIHAN_ELITE,
|
|
||||||
TrainerType.HASSEL,
|
|
||||||
TrainerType.DRAYTON,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.CHAMPION]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
getRandomTrainerFunc([
|
|
||||||
TrainerType.BLUE,
|
|
||||||
[TrainerType.RED, TrainerType.LANCE_CHAMPION],
|
|
||||||
[TrainerType.STEVEN, TrainerType.WALLACE],
|
|
||||||
TrainerType.CYNTHIA,
|
|
||||||
[TrainerType.ALDER, TrainerType.IRIS],
|
|
||||||
TrainerType.DIANTHA,
|
|
||||||
[TrainerType.KUKUI, TrainerType.HAU],
|
|
||||||
[TrainerType.LEON, TrainerType.MUSTARD],
|
|
||||||
[TrainerType.GEETA, TrainerType.NEMONA],
|
|
||||||
TrainerType.KIERAN,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
[ClassicFixedBossWaves.RIVAL_6]: new FixedBattleConfig()
|
|
||||||
.setBattleType(BattleType.TRAINER)
|
|
||||||
.setGetTrainerFunc(
|
|
||||||
() =>
|
|
||||||
new Trainer(
|
|
||||||
TrainerType.RIVAL_6,
|
|
||||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.setCustomModifierRewards({
|
|
||||||
guaranteedModifierTiers: [
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ROGUE,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
ModifierTier.ULTRA,
|
|
||||||
ModifierTier.GREAT,
|
|
||||||
ModifierTier.GREAT,
|
|
||||||
],
|
|
||||||
allowLuckUpgrades: false,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
@ -490,7 +490,7 @@ export const biomePokemonPools: BiomePokemonPools = {
|
|||||||
[TimeOfDay.NIGHT]: [],
|
[TimeOfDay.NIGHT]: [],
|
||||||
[TimeOfDay.ALL]: [ SpeciesId.POLITOED, SpeciesId.GALAR_STUNFISK ]
|
[TimeOfDay.ALL]: [ SpeciesId.POLITOED, SpeciesId.GALAR_STUNFISK ]
|
||||||
},
|
},
|
||||||
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.AZELF, SpeciesId.POIPOLE ] },
|
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.AZELF, { 1: [ SpeciesId.POIPOLE ], 60: [ SpeciesId.NAGANADEL ] } ] },
|
||||||
[BiomePoolTier.BOSS]: {
|
[BiomePoolTier.BOSS]: {
|
||||||
[TimeOfDay.DAWN]: [ SpeciesId.QUAGSIRE, SpeciesId.LUDICOLO ],
|
[TimeOfDay.DAWN]: [ SpeciesId.QUAGSIRE, SpeciesId.LUDICOLO ],
|
||||||
[TimeOfDay.DAY]: [ SpeciesId.QUAGSIRE, SpeciesId.LUDICOLO ],
|
[TimeOfDay.DAY]: [ SpeciesId.QUAGSIRE, SpeciesId.LUDICOLO ],
|
||||||
@ -505,7 +505,7 @@ export const biomePokemonPools: BiomePokemonPools = {
|
|||||||
[TimeOfDay.NIGHT]: [],
|
[TimeOfDay.NIGHT]: [],
|
||||||
[TimeOfDay.ALL]: [ SpeciesId.FERALIGATR, SpeciesId.POLITOED, SpeciesId.SWAMPERT, SpeciesId.GALAR_STUNFISK ]
|
[TimeOfDay.ALL]: [ SpeciesId.FERALIGATR, SpeciesId.POLITOED, SpeciesId.SWAMPERT, SpeciesId.GALAR_STUNFISK ]
|
||||||
},
|
},
|
||||||
[BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.AZELF, SpeciesId.NAGANADEL ] },
|
[BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.AZELF, { 1: [ SpeciesId.POIPOLE ], 60: [ SpeciesId.NAGANADEL ] } ] },
|
||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }
|
[BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }
|
||||||
},
|
},
|
||||||
[BiomeId.BEACH]: {
|
[BiomeId.BEACH]: {
|
||||||
@ -1118,7 +1118,7 @@ export const biomePokemonPools: BiomePokemonPools = {
|
|||||||
},
|
},
|
||||||
[BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.HITMONLEE, SpeciesId.HITMONCHAN, SpeciesId.LUCARIO, SpeciesId.THROH, SpeciesId.SAWK, { 1: [ SpeciesId.PANCHAM ], 52: [ SpeciesId.PANGORO ] } ] },
|
[BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.HITMONLEE, SpeciesId.HITMONCHAN, SpeciesId.LUCARIO, SpeciesId.THROH, SpeciesId.SAWK, { 1: [ SpeciesId.PANCHAM ], 52: [ SpeciesId.PANGORO ] } ] },
|
||||||
[BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.HITMONTOP, SpeciesId.GALLADE, SpeciesId.GALAR_FARFETCHD ] },
|
[BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.HITMONTOP, SpeciesId.GALLADE, SpeciesId.GALAR_FARFETCHD ] },
|
||||||
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TERRAKION, SpeciesId.KUBFU, SpeciesId.GALAR_ZAPDOS ] },
|
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TERRAKION, { 1: [ SpeciesId.KUBFU ], 60: [ SpeciesId.URSHIFU] }, SpeciesId.GALAR_ZAPDOS ] },
|
||||||
[BiomePoolTier.BOSS]: {
|
[BiomePoolTier.BOSS]: {
|
||||||
[TimeOfDay.DAWN]: [],
|
[TimeOfDay.DAWN]: [],
|
||||||
[TimeOfDay.DAY]: [],
|
[TimeOfDay.DAY]: [],
|
||||||
@ -1127,7 +1127,7 @@ export const biomePokemonPools: BiomePokemonPools = {
|
|||||||
[TimeOfDay.ALL]: [ SpeciesId.HITMONLEE, SpeciesId.HITMONCHAN, SpeciesId.HARIYAMA, SpeciesId.MEDICHAM, SpeciesId.LUCARIO, SpeciesId.TOXICROAK, SpeciesId.THROH, SpeciesId.SAWK, SpeciesId.SCRAFTY, SpeciesId.MIENSHAO, SpeciesId.BEWEAR, SpeciesId.GRAPPLOCT, SpeciesId.ANNIHILAPE ]
|
[TimeOfDay.ALL]: [ SpeciesId.HITMONLEE, SpeciesId.HITMONCHAN, SpeciesId.HARIYAMA, SpeciesId.MEDICHAM, SpeciesId.LUCARIO, SpeciesId.TOXICROAK, SpeciesId.THROH, SpeciesId.SAWK, SpeciesId.SCRAFTY, SpeciesId.MIENSHAO, SpeciesId.BEWEAR, SpeciesId.GRAPPLOCT, SpeciesId.ANNIHILAPE ]
|
||||||
},
|
},
|
||||||
[BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.HITMONTOP, SpeciesId.GALLADE, SpeciesId.PANGORO, SpeciesId.SIRFETCHD, SpeciesId.HISUI_DECIDUEYE ] },
|
[BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.HITMONTOP, SpeciesId.GALLADE, SpeciesId.PANGORO, SpeciesId.SIRFETCHD, SpeciesId.HISUI_DECIDUEYE ] },
|
||||||
[BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TERRAKION, SpeciesId.URSHIFU ] },
|
[BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TERRAKION, { 1: [ SpeciesId.KUBFU ], 60: [ SpeciesId.URSHIFU] } ] },
|
||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ZAMAZENTA, SpeciesId.GALAR_ZAPDOS ] }
|
[BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ZAMAZENTA, SpeciesId.GALAR_ZAPDOS ] }
|
||||||
},
|
},
|
||||||
[BiomeId.FACTORY]: {
|
[BiomeId.FACTORY]: {
|
||||||
@ -1418,8 +1418,8 @@ export const biomePokemonPools: BiomePokemonPools = {
|
|||||||
{ 1: [ SpeciesId.HATENNA ], 32: [ SpeciesId.HATTREM ], 42: [ SpeciesId.HATTERENE ] }
|
{ 1: [ SpeciesId.HATENNA ], 32: [ SpeciesId.HATTREM ], 42: [ SpeciesId.HATTERENE ] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
[BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.AUDINO, SpeciesId.ETERNAL_FLOETTE ] },
|
[BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.AUDINO ] },
|
||||||
[BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] },
|
[BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ETERNAL_FLOETTE ] },
|
||||||
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DIANCIE, SpeciesId.ENAMORUS ] },
|
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DIANCIE, SpeciesId.ENAMORUS ] },
|
||||||
[BiomePoolTier.BOSS]: {
|
[BiomePoolTier.BOSS]: {
|
||||||
[TimeOfDay.DAWN]: [],
|
[TimeOfDay.DAWN]: [],
|
||||||
@ -1596,10 +1596,10 @@ export const biomePokemonPools: BiomePokemonPools = {
|
|||||||
[BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ SpeciesId.SOLOSIS ], 32: [ SpeciesId.DUOSION ], 41: [ SpeciesId.REUNICLUS ] } ] },
|
[BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ SpeciesId.SOLOSIS ], 32: [ SpeciesId.DUOSION ], 41: [ SpeciesId.REUNICLUS ] } ] },
|
||||||
[BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, { 1: [ SpeciesId.PORYGON ], 30: [ SpeciesId.PORYGON2 ] } ] },
|
[BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, { 1: [ SpeciesId.PORYGON ], 30: [ SpeciesId.PORYGON2 ] } ] },
|
||||||
[BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM ] },
|
[BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM ] },
|
||||||
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TYPE_NULL ] },
|
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [SpeciesId.TYPE_NULL], 60: [ SpeciesId.SILVALLY ] } ] },
|
||||||
[BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MUK, SpeciesId.ELECTRODE, SpeciesId.BRONZONG, SpeciesId.MAGNEZONE, SpeciesId.PORYGON_Z, SpeciesId.REUNICLUS, SpeciesId.KLINKLANG ] },
|
[BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MUK, SpeciesId.ELECTRODE, SpeciesId.BRONZONG, SpeciesId.MAGNEZONE, SpeciesId.PORYGON_Z, SpeciesId.REUNICLUS, SpeciesId.KLINKLANG ] },
|
||||||
[BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] },
|
[BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] },
|
||||||
[BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM, SpeciesId.ZYGARDE, SpeciesId.SILVALLY ] },
|
[BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM, SpeciesId.ZYGARDE, { 1: [SpeciesId.TYPE_NULL], 60: [ SpeciesId.SILVALLY ] } ] },
|
||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MEWTWO, SpeciesId.MIRAIDON ] }
|
[BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MEWTWO, SpeciesId.MIRAIDON ] }
|
||||||
},
|
},
|
||||||
[BiomeId.END]: {
|
[BiomeId.END]: {
|
||||||
@ -6969,7 +6969,7 @@ export function initBiomes() {
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
[ SpeciesId.ETERNAL_FLOETTE, PokemonType.FAIRY, -1, [
|
[ SpeciesId.ETERNAL_FLOETTE, PokemonType.FAIRY, -1, [
|
||||||
[ BiomeId.FAIRY_CAVE, BiomePoolTier.RARE ],
|
[ BiomeId.FAIRY_CAVE, BiomePoolTier.SUPER_RARE ],
|
||||||
[ BiomeId.FAIRY_CAVE, BiomePoolTier.BOSS_RARE ]
|
[ BiomeId.FAIRY_CAVE, BiomePoolTier.BOSS_RARE ]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
@ -1630,7 +1630,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
|
|||||||
new SpeciesEvolution(SpeciesId.TSAREENA, 28, null, {key: EvoCondKey.MOVE, move: MoveId.STOMP}, SpeciesWildEvolutionDelay.LONG)
|
new SpeciesEvolution(SpeciesId.TSAREENA, 28, null, {key: EvoCondKey.MOVE, move: MoveId.STOMP}, SpeciesWildEvolutionDelay.LONG)
|
||||||
],
|
],
|
||||||
[SpeciesId.POIPOLE]: [
|
[SpeciesId.POIPOLE]: [
|
||||||
new SpeciesEvolution(SpeciesId.NAGANADEL, 1, null, {key: EvoCondKey.MOVE, move: MoveId.DRAGON_PULSE}, SpeciesWildEvolutionDelay.LONG)
|
new SpeciesEvolution(SpeciesId.NAGANADEL, 1, null, {key: EvoCondKey.MOVE, move: MoveId.DRAGON_PULSE}, SpeciesWildEvolutionDelay.VERY_LONG)
|
||||||
],
|
],
|
||||||
[SpeciesId.ALOLA_SANDSHREW]: [
|
[SpeciesId.ALOLA_SANDSHREW]: [
|
||||||
new SpeciesEvolution(SpeciesId.ALOLA_SANDSLASH, 1, EvolutionItem.ICE_STONE, null, SpeciesWildEvolutionDelay.LONG)
|
new SpeciesEvolution(SpeciesId.ALOLA_SANDSLASH, 1, EvolutionItem.ICE_STONE, null, SpeciesWildEvolutionDelay.LONG)
|
||||||
@ -1845,7 +1845,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
|
|||||||
new SpeciesEvolution(SpeciesId.LEAVANNY, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 120}, SpeciesWildEvolutionDelay.LONG)
|
new SpeciesEvolution(SpeciesId.LEAVANNY, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 120}, SpeciesWildEvolutionDelay.LONG)
|
||||||
],
|
],
|
||||||
[SpeciesId.TYPE_NULL]: [
|
[SpeciesId.TYPE_NULL]: [
|
||||||
new SpeciesEvolution(SpeciesId.SILVALLY, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 100}, SpeciesWildEvolutionDelay.LONG)
|
new SpeciesEvolution(SpeciesId.SILVALLY, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 100}, SpeciesWildEvolutionDelay.VERY_LONG)
|
||||||
],
|
],
|
||||||
[SpeciesId.ALOLA_MEOWTH]: [
|
[SpeciesId.ALOLA_MEOWTH]: [
|
||||||
new SpeciesEvolution(SpeciesId.ALOLA_PERSIAN, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 120}, SpeciesWildEvolutionDelay.LONG)
|
new SpeciesEvolution(SpeciesId.ALOLA_PERSIAN, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 120}, SpeciesWildEvolutionDelay.LONG)
|
||||||
|
@ -44,8 +44,8 @@ import {
|
|||||||
HeldItemRequirement,
|
HeldItemRequirement,
|
||||||
TypeRequirement,
|
TypeRequirement,
|
||||||
} from "#mystery-encounters/mystery-encounter-requirements";
|
} from "#mystery-encounters/mystery-encounter-requirements";
|
||||||
import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/TrainerPartyTemplate";
|
|
||||||
import { getRandomPartyMemberFunc, trainerConfigs } from "#trainers/trainer-config";
|
import { getRandomPartyMemberFunc, trainerConfigs } from "#trainers/trainer-config";
|
||||||
|
import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/trainer-party-template";
|
||||||
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler";
|
||||||
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
||||||
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#utils/common";
|
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#utils/common";
|
||||||
|
@ -43,8 +43,8 @@ import {
|
|||||||
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
|
||||||
import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/TrainerPartyTemplate";
|
|
||||||
import { trainerConfigs } from "#trainers/trainer-config";
|
import { trainerConfigs } from "#trainers/trainer-config";
|
||||||
|
import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/trainer-party-template";
|
||||||
import type { OptionSelectConfig } from "#ui/abstact-option-select-ui-handler";
|
import type { OptionSelectConfig } from "#ui/abstact-option-select-ui-handler";
|
||||||
import { randSeedInt, randSeedShuffle } from "#utils/common";
|
import { randSeedInt, randSeedShuffle } from "#utils/common";
|
||||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||||
|
@ -9,12 +9,12 @@ import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils
|
|||||||
import { initBattleWithEnemyConfig, setEncounterRewards } from "#mystery-encounters/encounter-phase-utils";
|
import { initBattleWithEnemyConfig, setEncounterRewards } from "#mystery-encounters/encounter-phase-utils";
|
||||||
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
|
||||||
|
import { trainerConfigs } from "#trainers/trainer-config";
|
||||||
import {
|
import {
|
||||||
TrainerPartyCompoundTemplate,
|
TrainerPartyCompoundTemplate,
|
||||||
TrainerPartyTemplate,
|
TrainerPartyTemplate,
|
||||||
trainerPartyTemplates,
|
trainerPartyTemplates,
|
||||||
} from "#trainers/TrainerPartyTemplate";
|
} from "#trainers/trainer-party-template";
|
||||||
import { trainerConfigs } from "#trainers/trainer-config";
|
|
||||||
import { randSeedInt } from "#utils/common";
|
import { randSeedInt } from "#utils/common";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
|
@ -36,8 +36,8 @@ import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encou
|
|||||||
import i18next from "#plugins/i18n";
|
import i18next from "#plugins/i18n";
|
||||||
import { achvs } from "#system/achv";
|
import { achvs } from "#system/achv";
|
||||||
import { PokemonData } from "#system/pokemon-data";
|
import { PokemonData } from "#system/pokemon-data";
|
||||||
import { TrainerPartyTemplate } from "#trainers/TrainerPartyTemplate";
|
|
||||||
import { trainerConfigs } from "#trainers/trainer-config";
|
import { trainerConfigs } from "#trainers/trainer-config";
|
||||||
|
import { TrainerPartyTemplate } from "#trainers/trainer-party-template";
|
||||||
import type { HeldModifierConfig } from "#types/held-modifier-config";
|
import type { HeldModifierConfig } from "#types/held-modifier-config";
|
||||||
import { isNullOrUndefined, NumberHolder, randSeedInt, randSeedShuffle } from "#utils/common";
|
import { isNullOrUndefined, NumberHolder, randSeedInt, randSeedShuffle } from "#utils/common";
|
||||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||||
|
@ -521,7 +521,7 @@ export function trainerThrowPokeball(
|
|||||||
repeatDelay: 500,
|
repeatDelay: 500,
|
||||||
onUpdate: t => {
|
onUpdate: t => {
|
||||||
if (shakeCount && shakeCount < 4) {
|
if (shakeCount && shakeCount < 4) {
|
||||||
const value = t.getValue();
|
const value = t.getValue() ?? 0;
|
||||||
const directionMultiplier = shakeCount % 2 === 1 ? 1 : -1;
|
const directionMultiplier = shakeCount % 2 === 1 ? 1 : -1;
|
||||||
pokeball.setX(pbX + value * 4 * directionMultiplier);
|
pokeball.setX(pbX + value * 4 * directionMultiplier);
|
||||||
pokeball.setAngle(value * 27.5 * directionMultiplier);
|
pokeball.setAngle(value * 27.5 * directionMultiplier);
|
||||||
|
@ -127,7 +127,7 @@ export function doPokemonTransformationSequence(
|
|||||||
to: 1,
|
to: 1,
|
||||||
duration: 1000,
|
duration: 1000,
|
||||||
onUpdate: t => {
|
onUpdate: t => {
|
||||||
pokemonTintSprite.setAlpha(t.getValue());
|
pokemonTintSprite.setAlpha(t.getValue() ?? 1);
|
||||||
},
|
},
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
pokemonSprite.setVisible(false);
|
pokemonSprite.setVisible(false);
|
||||||
|
376
src/data/trainers/fixed-battle-configs.ts
Normal file
376
src/data/trainers/fixed-battle-configs.ts
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
import { FixedBattleConfig, getRandomTrainerFunc } from "#app/battle";
|
||||||
|
import { Trainer } from "#app/field/trainer";
|
||||||
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { randSeedInt } from "#app/utils/common";
|
||||||
|
import { BattleType } from "#enums/battle-type";
|
||||||
|
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||||
|
import { ModifierTier } from "#enums/modifier-tier";
|
||||||
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
|
|
||||||
|
export interface FixedBattleConfigs {
|
||||||
|
[key: number]: FixedBattleConfig;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Youngster/Lass on 5
|
||||||
|
* Rival on 8, 55, 95, 145, 195
|
||||||
|
* Evil team grunts on 35, 62, 64, and 112
|
||||||
|
* Evil team admin on 66 and 114
|
||||||
|
* Evil leader on 115, 165
|
||||||
|
* E4 on 182, 184, 186, 188
|
||||||
|
* Champion on 190
|
||||||
|
*/
|
||||||
|
export const classicFixedBattles: FixedBattleConfigs = {
|
||||||
|
[ClassicFixedBossWaves.TOWN_YOUNGSTER]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
() => new Trainer(TrainerType.YOUNGSTER, randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.RIVAL_1]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
() =>
|
||||||
|
new Trainer(
|
||||||
|
TrainerType.RIVAL,
|
||||||
|
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.RIVAL_2]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
() =>
|
||||||
|
new Trainer(
|
||||||
|
TrainerType.RIVAL_2,
|
||||||
|
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.setCustomModifierRewards({
|
||||||
|
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT],
|
||||||
|
allowLuckUpgrades: false,
|
||||||
|
}),
|
||||||
|
[ClassicFixedBossWaves.EVIL_GRUNT_1]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc(
|
||||||
|
[
|
||||||
|
TrainerType.ROCKET_GRUNT,
|
||||||
|
TrainerType.MAGMA_GRUNT,
|
||||||
|
TrainerType.AQUA_GRUNT,
|
||||||
|
TrainerType.GALACTIC_GRUNT,
|
||||||
|
TrainerType.PLASMA_GRUNT,
|
||||||
|
TrainerType.FLARE_GRUNT,
|
||||||
|
TrainerType.AETHER_GRUNT,
|
||||||
|
TrainerType.SKULL_GRUNT,
|
||||||
|
TrainerType.MACRO_GRUNT,
|
||||||
|
TrainerType.STAR_GRUNT,
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.RIVAL_3]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
() =>
|
||||||
|
new Trainer(
|
||||||
|
TrainerType.RIVAL_3,
|
||||||
|
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.setCustomModifierRewards({
|
||||||
|
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT],
|
||||||
|
allowLuckUpgrades: false,
|
||||||
|
}),
|
||||||
|
[ClassicFixedBossWaves.EVIL_GRUNT_2]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc(
|
||||||
|
[
|
||||||
|
TrainerType.ROCKET_GRUNT,
|
||||||
|
TrainerType.MAGMA_GRUNT,
|
||||||
|
TrainerType.AQUA_GRUNT,
|
||||||
|
TrainerType.GALACTIC_GRUNT,
|
||||||
|
TrainerType.PLASMA_GRUNT,
|
||||||
|
TrainerType.FLARE_GRUNT,
|
||||||
|
TrainerType.AETHER_GRUNT,
|
||||||
|
TrainerType.SKULL_GRUNT,
|
||||||
|
TrainerType.MACRO_GRUNT,
|
||||||
|
TrainerType.STAR_GRUNT,
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.EVIL_GRUNT_3]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc(
|
||||||
|
[
|
||||||
|
TrainerType.ROCKET_GRUNT,
|
||||||
|
TrainerType.MAGMA_GRUNT,
|
||||||
|
TrainerType.AQUA_GRUNT,
|
||||||
|
TrainerType.GALACTIC_GRUNT,
|
||||||
|
TrainerType.PLASMA_GRUNT,
|
||||||
|
TrainerType.FLARE_GRUNT,
|
||||||
|
TrainerType.AETHER_GRUNT,
|
||||||
|
TrainerType.SKULL_GRUNT,
|
||||||
|
TrainerType.MACRO_GRUNT,
|
||||||
|
TrainerType.STAR_GRUNT,
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.EVIL_ADMIN_1]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc(
|
||||||
|
[
|
||||||
|
[TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL],
|
||||||
|
[TrainerType.TABITHA, TrainerType.COURTNEY],
|
||||||
|
[TrainerType.MATT, TrainerType.SHELLY],
|
||||||
|
[TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN],
|
||||||
|
[TrainerType.ZINZOLIN, TrainerType.COLRESS],
|
||||||
|
[TrainerType.XEROSIC, TrainerType.BRYONY],
|
||||||
|
TrainerType.FABA,
|
||||||
|
TrainerType.PLUMERIA,
|
||||||
|
TrainerType.OLEANA,
|
||||||
|
[TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI],
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.RIVAL_4]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
() =>
|
||||||
|
new Trainer(
|
||||||
|
TrainerType.RIVAL_4,
|
||||||
|
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.setCustomModifierRewards({
|
||||||
|
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA],
|
||||||
|
allowLuckUpgrades: false,
|
||||||
|
}),
|
||||||
|
[ClassicFixedBossWaves.EVIL_GRUNT_4]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc(
|
||||||
|
[
|
||||||
|
TrainerType.ROCKET_GRUNT,
|
||||||
|
TrainerType.MAGMA_GRUNT,
|
||||||
|
TrainerType.AQUA_GRUNT,
|
||||||
|
TrainerType.GALACTIC_GRUNT,
|
||||||
|
TrainerType.PLASMA_GRUNT,
|
||||||
|
TrainerType.FLARE_GRUNT,
|
||||||
|
TrainerType.AETHER_GRUNT,
|
||||||
|
TrainerType.SKULL_GRUNT,
|
||||||
|
TrainerType.MACRO_GRUNT,
|
||||||
|
TrainerType.STAR_GRUNT,
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.EVIL_ADMIN_2]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc(
|
||||||
|
[
|
||||||
|
[TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL],
|
||||||
|
[TrainerType.TABITHA, TrainerType.COURTNEY],
|
||||||
|
[TrainerType.MATT, TrainerType.SHELLY],
|
||||||
|
[TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN],
|
||||||
|
[TrainerType.ZINZOLIN, TrainerType.COLRESS],
|
||||||
|
[TrainerType.XEROSIC, TrainerType.BRYONY],
|
||||||
|
TrainerType.FABA,
|
||||||
|
TrainerType.PLUMERIA,
|
||||||
|
TrainerType.OLEANA,
|
||||||
|
[TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI],
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc([
|
||||||
|
TrainerType.ROCKET_BOSS_GIOVANNI_1,
|
||||||
|
TrainerType.MAXIE,
|
||||||
|
TrainerType.ARCHIE,
|
||||||
|
TrainerType.CYRUS,
|
||||||
|
TrainerType.GHETSIS,
|
||||||
|
TrainerType.LYSANDRE,
|
||||||
|
TrainerType.LUSAMINE,
|
||||||
|
TrainerType.GUZMA,
|
||||||
|
TrainerType.ROSE,
|
||||||
|
TrainerType.PENNY,
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
.setCustomModifierRewards({
|
||||||
|
guaranteedModifierTiers: [
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
],
|
||||||
|
allowLuckUpgrades: false,
|
||||||
|
}),
|
||||||
|
[ClassicFixedBossWaves.RIVAL_5]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
() =>
|
||||||
|
new Trainer(
|
||||||
|
TrainerType.RIVAL_5,
|
||||||
|
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.setCustomModifierRewards({
|
||||||
|
guaranteedModifierTiers: [
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
],
|
||||||
|
allowLuckUpgrades: false,
|
||||||
|
}),
|
||||||
|
[ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc([
|
||||||
|
TrainerType.ROCKET_BOSS_GIOVANNI_2,
|
||||||
|
TrainerType.MAXIE_2,
|
||||||
|
TrainerType.ARCHIE_2,
|
||||||
|
TrainerType.CYRUS_2,
|
||||||
|
TrainerType.GHETSIS_2,
|
||||||
|
TrainerType.LYSANDRE_2,
|
||||||
|
TrainerType.LUSAMINE_2,
|
||||||
|
TrainerType.GUZMA_2,
|
||||||
|
TrainerType.ROSE_2,
|
||||||
|
TrainerType.PENNY_2,
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
.setCustomModifierRewards({
|
||||||
|
guaranteedModifierTiers: [
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
],
|
||||||
|
allowLuckUpgrades: false,
|
||||||
|
}),
|
||||||
|
[ClassicFixedBossWaves.ELITE_FOUR_1]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc([
|
||||||
|
TrainerType.LORELEI,
|
||||||
|
TrainerType.WILL,
|
||||||
|
TrainerType.SIDNEY,
|
||||||
|
TrainerType.AARON,
|
||||||
|
TrainerType.SHAUNTAL,
|
||||||
|
TrainerType.MALVA,
|
||||||
|
[TrainerType.HALA, TrainerType.MOLAYNE],
|
||||||
|
TrainerType.MARNIE_ELITE,
|
||||||
|
TrainerType.RIKA,
|
||||||
|
TrainerType.CRISPIN,
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.ELITE_FOUR_2]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc([
|
||||||
|
TrainerType.BRUNO,
|
||||||
|
TrainerType.KOGA,
|
||||||
|
TrainerType.PHOEBE,
|
||||||
|
TrainerType.BERTHA,
|
||||||
|
TrainerType.MARSHAL,
|
||||||
|
TrainerType.SIEBOLD,
|
||||||
|
TrainerType.OLIVIA,
|
||||||
|
TrainerType.NESSA_ELITE,
|
||||||
|
TrainerType.POPPY,
|
||||||
|
TrainerType.AMARYS,
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.ELITE_FOUR_3]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc([
|
||||||
|
TrainerType.AGATHA,
|
||||||
|
TrainerType.BRUNO,
|
||||||
|
TrainerType.GLACIA,
|
||||||
|
TrainerType.FLINT,
|
||||||
|
TrainerType.GRIMSLEY,
|
||||||
|
TrainerType.WIKSTROM,
|
||||||
|
TrainerType.ACEROLA,
|
||||||
|
[TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE],
|
||||||
|
TrainerType.LARRY_ELITE,
|
||||||
|
TrainerType.LACEY,
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.ELITE_FOUR_4]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc([
|
||||||
|
TrainerType.LANCE,
|
||||||
|
TrainerType.KAREN,
|
||||||
|
TrainerType.DRAKE,
|
||||||
|
TrainerType.LUCIAN,
|
||||||
|
TrainerType.CAITLIN,
|
||||||
|
TrainerType.DRASNA,
|
||||||
|
TrainerType.KAHILI,
|
||||||
|
TrainerType.RAIHAN_ELITE,
|
||||||
|
TrainerType.HASSEL,
|
||||||
|
TrainerType.DRAYTON,
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.CHAMPION]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
getRandomTrainerFunc([
|
||||||
|
TrainerType.BLUE,
|
||||||
|
[TrainerType.RED, TrainerType.LANCE_CHAMPION],
|
||||||
|
[TrainerType.STEVEN, TrainerType.WALLACE],
|
||||||
|
TrainerType.CYNTHIA,
|
||||||
|
[TrainerType.ALDER, TrainerType.IRIS],
|
||||||
|
TrainerType.DIANTHA,
|
||||||
|
[TrainerType.KUKUI, TrainerType.HAU],
|
||||||
|
[TrainerType.LEON, TrainerType.MUSTARD],
|
||||||
|
[TrainerType.GEETA, TrainerType.NEMONA],
|
||||||
|
TrainerType.KIERAN,
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
[ClassicFixedBossWaves.RIVAL_6]: new FixedBattleConfig()
|
||||||
|
.setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(
|
||||||
|
() =>
|
||||||
|
new Trainer(
|
||||||
|
TrainerType.RIVAL_6,
|
||||||
|
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.setCustomModifierRewards({
|
||||||
|
guaranteedModifierTiers: [
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ROGUE,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
ModifierTier.ULTRA,
|
||||||
|
ModifierTier.GREAT,
|
||||||
|
ModifierTier.GREAT,
|
||||||
|
],
|
||||||
|
allowLuckUpgrades: false,
|
||||||
|
}),
|
||||||
|
};
|
@ -30,7 +30,7 @@ import {
|
|||||||
TrainerPartyCompoundTemplate,
|
TrainerPartyCompoundTemplate,
|
||||||
TrainerPartyTemplate,
|
TrainerPartyTemplate,
|
||||||
trainerPartyTemplates,
|
trainerPartyTemplates,
|
||||||
} from "#trainers/TrainerPartyTemplate";
|
} from "#trainers/trainer-party-template";
|
||||||
import type { ModifierTypeFunc } from "#types/modifier-types";
|
import type { ModifierTypeFunc } from "#types/modifier-types";
|
||||||
import type {
|
import type {
|
||||||
GenAIFunc,
|
GenAIFunc,
|
||||||
|
@ -168,19 +168,11 @@ export class Arena {
|
|||||||
ret = getPokemonSpecies(species!);
|
ret = getPokemonSpecies(species!);
|
||||||
|
|
||||||
if (ret.subLegendary || ret.legendary || ret.mythical) {
|
if (ret.subLegendary || ret.legendary || ret.mythical) {
|
||||||
switch (true) {
|
const waveDifficulty = globalScene.gameMode.getWaveForDifficulty(waveIndex);
|
||||||
case ret.baseTotal >= 720:
|
if (ret.baseTotal >= 660) {
|
||||||
regen = level < 90;
|
regen = waveDifficulty < 80; // Wave 50+ in daily (however, max Daily wave is 50 currently so not possible)
|
||||||
break;
|
} else {
|
||||||
case ret.baseTotal >= 670:
|
regen = waveDifficulty < 55; // Wave 25+ in daily
|
||||||
regen = level < 70;
|
|
||||||
break;
|
|
||||||
case ret.baseTotal >= 580:
|
|
||||||
regen = level < 50;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
regen = level < 30;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,38 +490,37 @@ export class Arena {
|
|||||||
getTrainerChance(): number {
|
getTrainerChance(): number {
|
||||||
switch (this.biomeType) {
|
switch (this.biomeType) {
|
||||||
case BiomeId.METROPOLIS:
|
case BiomeId.METROPOLIS:
|
||||||
return 2;
|
|
||||||
case BiomeId.SLUM:
|
|
||||||
case BiomeId.BEACH:
|
|
||||||
case BiomeId.DOJO:
|
case BiomeId.DOJO:
|
||||||
case BiomeId.CONSTRUCTION_SITE:
|
|
||||||
return 4;
|
return 4;
|
||||||
case BiomeId.PLAINS:
|
case BiomeId.PLAINS:
|
||||||
case BiomeId.GRASS:
|
case BiomeId.GRASS:
|
||||||
|
case BiomeId.BEACH:
|
||||||
case BiomeId.LAKE:
|
case BiomeId.LAKE:
|
||||||
case BiomeId.CAVE:
|
case BiomeId.CAVE:
|
||||||
|
case BiomeId.DESERT:
|
||||||
|
case BiomeId.CONSTRUCTION_SITE:
|
||||||
|
case BiomeId.SLUM:
|
||||||
return 6;
|
return 6;
|
||||||
case BiomeId.TALL_GRASS:
|
case BiomeId.TALL_GRASS:
|
||||||
case BiomeId.FOREST:
|
case BiomeId.FOREST:
|
||||||
case BiomeId.SEA:
|
|
||||||
case BiomeId.SWAMP:
|
case BiomeId.SWAMP:
|
||||||
case BiomeId.MOUNTAIN:
|
case BiomeId.MOUNTAIN:
|
||||||
case BiomeId.BADLANDS:
|
case BiomeId.BADLANDS:
|
||||||
case BiomeId.DESERT:
|
|
||||||
case BiomeId.MEADOW:
|
case BiomeId.MEADOW:
|
||||||
case BiomeId.POWER_PLANT:
|
case BiomeId.POWER_PLANT:
|
||||||
case BiomeId.GRAVEYARD:
|
|
||||||
case BiomeId.FACTORY:
|
case BiomeId.FACTORY:
|
||||||
case BiomeId.SNOWY_FOREST:
|
case BiomeId.SNOWY_FOREST:
|
||||||
return 8;
|
return 8;
|
||||||
|
case BiomeId.SEA:
|
||||||
case BiomeId.ICE_CAVE:
|
case BiomeId.ICE_CAVE:
|
||||||
case BiomeId.VOLCANO:
|
case BiomeId.VOLCANO:
|
||||||
|
case BiomeId.GRAVEYARD:
|
||||||
case BiomeId.RUINS:
|
case BiomeId.RUINS:
|
||||||
case BiomeId.WASTELAND:
|
case BiomeId.WASTELAND:
|
||||||
case BiomeId.JUNGLE:
|
case BiomeId.JUNGLE:
|
||||||
case BiomeId.FAIRY_CAVE:
|
case BiomeId.FAIRY_CAVE:
|
||||||
|
case BiomeId.ISLAND:
|
||||||
return 12;
|
return 12;
|
||||||
case BiomeId.SEABED:
|
|
||||||
case BiomeId.ABYSS:
|
case BiomeId.ABYSS:
|
||||||
case BiomeId.SPACE:
|
case BiomeId.SPACE:
|
||||||
case BiomeId.TEMPLE:
|
case BiomeId.TEMPLE:
|
||||||
|
@ -2520,41 +2520,50 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @returns A score value based on how favorable this Pokemon is when fighting the given Pokemon
|
* @returns A score value based on how favorable this Pokemon is when fighting the given Pokemon
|
||||||
*/
|
*/
|
||||||
getMatchupScore(opponent: Pokemon): number {
|
getMatchupScore(opponent: Pokemon): number {
|
||||||
const types = this.getTypes(true);
|
const enemyTypes = opponent.getTypes(true, false, false, true);
|
||||||
|
|
||||||
const enemyTypes = opponent.getTypes(true, true, false, true);
|
|
||||||
/** Is this Pokemon faster than the opponent? */
|
/** Is this Pokemon faster than the opponent? */
|
||||||
const outspeed =
|
const outspeed =
|
||||||
(this.isActive(true) ? this.getEffectiveStat(Stat.SPD, opponent) : this.getStat(Stat.SPD, false)) >=
|
(this.isActive(true) ? this.getEffectiveStat(Stat.SPD, opponent) : this.getStat(Stat.SPD, false)) >=
|
||||||
opponent.getEffectiveStat(Stat.SPD, this);
|
opponent.getEffectiveStat(Stat.SPD, this);
|
||||||
/**
|
|
||||||
* Based on how effective this Pokemon's types are offensively against the opponent's types.
|
|
||||||
* This score is increased by 25 percent if this Pokemon is faster than the opponent.
|
|
||||||
*/
|
|
||||||
let atkScore =
|
|
||||||
opponent.getAttackTypeEffectiveness(types[0], this, false, true, undefined, true) * (outspeed ? 1.25 : 1);
|
|
||||||
/**
|
/**
|
||||||
* Based on how effectively this Pokemon defends against the opponent's types.
|
* Based on how effectively this Pokemon defends against the opponent's types.
|
||||||
* This score cannot be higher than 4.
|
* This score cannot be higher than 4.
|
||||||
*/
|
*/
|
||||||
let defScore = 1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[0], opponent), 0.25);
|
let defScore = 1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[0], opponent), 0.25);
|
||||||
if (types.length > 1) {
|
|
||||||
atkScore *= opponent.getAttackTypeEffectiveness(types[1], this);
|
|
||||||
}
|
|
||||||
if (enemyTypes.length > 1) {
|
if (enemyTypes.length > 1) {
|
||||||
defScore *=
|
defScore *=
|
||||||
1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[1], opponent, false, false, undefined, true), 0.25);
|
1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[1], opponent, false, false, undefined, true), 0.25);
|
||||||
}
|
}
|
||||||
atkScore *= 1.25; //give more value for the pokemon's typing
|
|
||||||
const moveset = this.moveset;
|
const moveset = this.moveset;
|
||||||
let moveAtkScoreLength = 0;
|
let moveAtkScoreLength = 0;
|
||||||
|
let atkScore = 0;
|
||||||
|
// TODO: this calculation needs to consider more factors; it's currently very simplistic
|
||||||
for (const move of moveset) {
|
for (const move of moveset) {
|
||||||
if (move.getMove().category === MoveCategory.SPECIAL || move.getMove().category === MoveCategory.PHYSICAL) {
|
const resolvedMove = move.getMove();
|
||||||
atkScore += opponent.getAttackTypeEffectiveness(move.getMove().type, this, false, true, undefined, true);
|
// NOTE: Counter and Mirror Coat are considered as attack moves here
|
||||||
moveAtkScoreLength++;
|
if (resolvedMove.category === MoveCategory.STATUS || move.getPpRatio() <= 0) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
const moveType = resolvedMove.type;
|
||||||
|
let thisScore = opponent.getAttackTypeEffectiveness(moveType, this, false, true, undefined, true);
|
||||||
|
|
||||||
|
// Add STAB multiplier for attack type effectiveness.
|
||||||
|
// For now, simply don't apply STAB to moves that may change type
|
||||||
|
if (this.getTypes(true).includes(moveType) && !move.getMove().hasAttr("VariableMoveTypeAttr")) {
|
||||||
|
thisScore *= 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
atkScore += thisScore;
|
||||||
|
moveAtkScoreLength++;
|
||||||
}
|
}
|
||||||
atkScore = atkScore / (moveAtkScoreLength + 1); //calculate the median for the attack score
|
// Get average attack score of all damaging moves (|| 1 prevents division by zero))
|
||||||
|
// TODO: Averaging the attack score is excessively simplistic, and doesn't reflect the AI's move selection logic
|
||||||
|
// e.g. if the mon has one 4x effective move and three 0.5x effective moves, this score would be ~1.375
|
||||||
|
// which does not seem fair, given that if the AI were to switch, in all likelihood it would use the 4x move.
|
||||||
|
// We could consider a weighted average...
|
||||||
|
atkScore /= moveAtkScoreLength || 1;
|
||||||
/**
|
/**
|
||||||
* Based on this Pokemon's HP ratio compared to that of the opponent.
|
* Based on this Pokemon's HP ratio compared to that of the opponent.
|
||||||
* This ratio is multiplied by 1.5 if this Pokemon outspeeds the opponent;
|
* This ratio is multiplied by 1.5 if this Pokemon outspeeds the opponent;
|
||||||
@ -2562,6 +2571,9 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
*/
|
*/
|
||||||
const hpRatio = this.getHpRatio();
|
const hpRatio = this.getHpRatio();
|
||||||
const oppHpRatio = opponent.getHpRatio();
|
const oppHpRatio = opponent.getHpRatio();
|
||||||
|
// TODO: use better logic for predicting whether the pokemon "is dying"
|
||||||
|
// E.g., perhaps check if it would faint if the opponent were to use the same move it just used
|
||||||
|
// (twice if the user is slower)
|
||||||
const isDying = hpRatio <= 0.2;
|
const isDying = hpRatio <= 0.2;
|
||||||
let hpDiffRatio = hpRatio + (1 - oppHpRatio);
|
let hpDiffRatio = hpRatio + (1 - oppHpRatio);
|
||||||
if (isDying && this.isActive(true)) {
|
if (isDying && this.isActive(true)) {
|
||||||
@ -2571,15 +2583,15 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
//It might not be a worthy sacrifice if it doesn't outspeed or doesn't do enough damage
|
//It might not be a worthy sacrifice if it doesn't outspeed or doesn't do enough damage
|
||||||
hpDiffRatio *= 0.85;
|
hpDiffRatio *= 0.85;
|
||||||
} else {
|
} else {
|
||||||
hpDiffRatio = Math.min(1 - hpRatio + (outspeed ? 0.2 : 0.1), 1);
|
hpDiffRatio = 1 - hpRatio + (outspeed ? 0.2 : 0.1);
|
||||||
}
|
}
|
||||||
} else if (outspeed) {
|
} else if (outspeed) {
|
||||||
hpDiffRatio = Math.min(hpDiffRatio * 1.25, 1);
|
hpDiffRatio = hpDiffRatio * 1.25;
|
||||||
} else if (hpRatio > 0.2 && hpRatio <= 0.4) {
|
} else if (hpRatio > 0.2 && hpRatio <= 0.4) {
|
||||||
//Might be considered to be switched because it's not in low enough health
|
// Might be considered to be switched because it's not in low enough health
|
||||||
hpDiffRatio = Math.min(hpDiffRatio * 0.5, 1);
|
hpDiffRatio = hpDiffRatio * 0.5;
|
||||||
}
|
}
|
||||||
return (atkScore + defScore) * hpDiffRatio;
|
return (atkScore + defScore) * Math.min(hpDiffRatio, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEvolution(): SpeciesFormEvolution | null {
|
getEvolution(): SpeciesFormEvolution | null {
|
||||||
|
@ -14,10 +14,13 @@ import { TrainerVariant } from "#enums/trainer-variant";
|
|||||||
import type { EnemyPokemon } from "#field/pokemon";
|
import type { EnemyPokemon } from "#field/pokemon";
|
||||||
import type { PersistentModifier } from "#modifiers/modifier";
|
import type { PersistentModifier } from "#modifiers/modifier";
|
||||||
import { getIsInitialized, initI18n } from "#plugins/i18n";
|
import { getIsInitialized, initI18n } from "#plugins/i18n";
|
||||||
import type { TrainerPartyTemplate } from "#trainers/TrainerPartyTemplate";
|
|
||||||
import { TrainerPartyCompoundTemplate, trainerPartyTemplates } from "#trainers/TrainerPartyTemplate";
|
|
||||||
import type { TrainerConfig } from "#trainers/trainer-config";
|
import type { TrainerConfig } from "#trainers/trainer-config";
|
||||||
import { trainerConfigs } from "#trainers/trainer-config";
|
import { trainerConfigs } from "#trainers/trainer-config";
|
||||||
|
import {
|
||||||
|
TrainerPartyCompoundTemplate,
|
||||||
|
type TrainerPartyTemplate,
|
||||||
|
trainerPartyTemplates,
|
||||||
|
} from "#trainers/trainer-party-template";
|
||||||
import { randSeedInt, randSeedItem, randSeedWeightedItem } from "#utils/common";
|
import { randSeedInt, randSeedItem, randSeedWeightedItem } from "#utils/common";
|
||||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { FixedBattleConfigs } from "#app/battle";
|
import { FixedBattleConfig } from "#app/battle";
|
||||||
import { classicFixedBattles, FixedBattleConfig } from "#app/battle";
|
|
||||||
import { CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
@ -14,6 +13,7 @@ import { Challenges } from "#enums/challenges";
|
|||||||
import { GameModes } from "#enums/game-modes";
|
import { GameModes } from "#enums/game-modes";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import type { Arena } from "#field/arena";
|
import type { Arena } from "#field/arena";
|
||||||
|
import { classicFixedBattles, type FixedBattleConfigs } from "#trainers/fixed-battle-configs";
|
||||||
import { isNullOrUndefined, randSeedInt, randSeedItem } from "#utils/common";
|
import { isNullOrUndefined, randSeedInt, randSeedItem } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -164,14 +164,14 @@ export class GameMode implements GameModeConfig {
|
|||||||
if (waveIndex % 10 !== 1 && waveIndex % 10) {
|
if (waveIndex % 10 !== 1 && waveIndex % 10) {
|
||||||
/**
|
/**
|
||||||
* Do not check X1 floors since there's a bug that stops trainer sprites from appearing
|
* Do not check X1 floors since there's a bug that stops trainer sprites from appearing
|
||||||
* after a X0 full party heal
|
* after a X0 full party heal, this also allows for a smoother biome transition for general gameplay feel
|
||||||
*/
|
*/
|
||||||
const trainerChance = arena.getTrainerChance();
|
const trainerChance = arena.getTrainerChance();
|
||||||
let allowTrainerBattle = true;
|
let allowTrainerBattle = true;
|
||||||
if (trainerChance) {
|
if (trainerChance) {
|
||||||
const waveBase = Math.floor(waveIndex / 10) * 10;
|
const waveBase = Math.floor(waveIndex / 10) * 10;
|
||||||
// Stop generic trainers from spawning in within 3 waves of a trainer battle
|
// Stop generic trainers from spawning in within 2 waves of a fixed trainer battle
|
||||||
for (let w = Math.max(waveIndex - 3, waveBase + 2); w <= Math.min(waveIndex + 3, waveBase + 9); w++) {
|
for (let w = Math.max(waveIndex - 2, waveBase + 2); w <= Math.min(waveIndex + 2, waveBase + 9); w++) {
|
||||||
if (w === waveIndex) {
|
if (w === waveIndex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ export class AttemptCapturePhase extends PokemonPhase {
|
|||||||
repeatDelay: 500,
|
repeatDelay: 500,
|
||||||
onUpdate: t => {
|
onUpdate: t => {
|
||||||
if (shakeCount && shakeCount < (isCritical ? 2 : 4)) {
|
if (shakeCount && shakeCount < (isCritical ? 2 : 4)) {
|
||||||
const value = t.getValue();
|
const value = t.getValue() ?? 0;
|
||||||
const directionMultiplier = shakeCount % 2 === 1 ? 1 : -1;
|
const directionMultiplier = shakeCount % 2 === 1 ? 1 : -1;
|
||||||
this.pokeball.setX(pbX + value * 4 * directionMultiplier);
|
this.pokeball.setX(pbX + value * 4 * directionMultiplier);
|
||||||
this.pokeball.setAngle(value * 27.5 * directionMultiplier);
|
this.pokeball.setAngle(value * 27.5 * directionMultiplier);
|
||||||
|
@ -239,7 +239,7 @@ export class EvolutionPhase extends Phase {
|
|||||||
to: 1,
|
to: 1,
|
||||||
duration: 2000,
|
duration: 2000,
|
||||||
onUpdate: t => {
|
onUpdate: t => {
|
||||||
this.pokemonTintSprite.setAlpha(t.getValue());
|
this.pokemonTintSprite.setAlpha(t.getValue() ?? 1);
|
||||||
},
|
},
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
this.pokemonSprite.setVisible(false);
|
this.pokemonSprite.setVisible(false);
|
||||||
|
@ -179,7 +179,7 @@ export class SelectModifierPhase extends BattlePhase {
|
|||||||
} else {
|
} else {
|
||||||
this.applyModifier(modifierType.newModifier()!);
|
this.applyModifier(modifierType.newModifier()!);
|
||||||
}
|
}
|
||||||
return !cost;
|
return cost === -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reroll rewards
|
// Reroll rewards
|
||||||
|
@ -269,13 +269,22 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||||||
globalScene.updateBiomeWaveText();
|
globalScene.updateBiomeWaveText();
|
||||||
globalScene.updateMoneyText();
|
globalScene.updateMoneyText();
|
||||||
|
|
||||||
|
// DO NOT REMOVE: Fixes bug which allows action input to be processed before the UI is shown,
|
||||||
|
// causing errors if reroll is selected
|
||||||
|
this.awaitingActionInput = false;
|
||||||
|
|
||||||
|
// TODO: Replace with `Promise.withResolvers` when possible.
|
||||||
|
let tweenResolve: () => void;
|
||||||
|
const tweenPromise = new Promise<void>(resolve => (tweenResolve = resolve));
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
|
// TODO: Rework this bespoke logic for animating the modifier options.
|
||||||
globalScene.tweens.addCounter({
|
globalScene.tweens.addCounter({
|
||||||
ease: "Sine.easeIn",
|
ease: "Sine.easeIn",
|
||||||
duration: 1250,
|
duration: 1250,
|
||||||
onUpdate: t => {
|
onUpdate: t => {
|
||||||
const value = t.getValue();
|
// The bang here is safe, as `getValue()` only returns null if the tween has been destroyed (which obviously isn't the case inside onUpdate)
|
||||||
|
const value = t.getValue()!;
|
||||||
const index = Math.floor(value * typeOptions.length);
|
const index = Math.floor(value * typeOptions.length);
|
||||||
if (index > i && index <= typeOptions.length) {
|
if (index > i && index <= typeOptions.length) {
|
||||||
const option = this.options[i];
|
const option = this.options[i];
|
||||||
@ -286,67 +295,77 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onComplete: () => {
|
||||||
|
tweenResolve();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
globalScene.time.delayedCall(1000 + maxUpgradeCount * 2000, () => {
|
let shopResolve: () => void;
|
||||||
for (const shopOption of this.shopOptionsRows.flat()) {
|
const shopPromise = new Promise<void>(resolve => (shopResolve = resolve));
|
||||||
shopOption.show(0, 0);
|
tweenPromise.then(() => {
|
||||||
}
|
globalScene.time.delayedCall(1000, () => {
|
||||||
|
for (const shopOption of this.shopOptionsRows.flat()) {
|
||||||
|
shopOption.show(0, 0);
|
||||||
|
}
|
||||||
|
shopResolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
globalScene.time.delayedCall(4000 + maxUpgradeCount * 2000, () => {
|
shopPromise.then(() => {
|
||||||
if (partyHasHeldItem) {
|
globalScene.time.delayedCall(500, () => {
|
||||||
this.transferButtonContainer.setAlpha(0);
|
if (partyHasHeldItem) {
|
||||||
this.transferButtonContainer.setVisible(true);
|
this.transferButtonContainer.setAlpha(0);
|
||||||
|
this.transferButtonContainer.setVisible(true);
|
||||||
|
globalScene.tweens.add({
|
||||||
|
targets: this.transferButtonContainer,
|
||||||
|
alpha: 1,
|
||||||
|
duration: 250,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rerollButtonContainer.setAlpha(0);
|
||||||
|
this.checkButtonContainer.setAlpha(0);
|
||||||
|
this.lockRarityButtonContainer.setAlpha(0);
|
||||||
|
this.continueButtonContainer.setAlpha(0);
|
||||||
|
this.rerollButtonContainer.setVisible(true);
|
||||||
|
this.checkButtonContainer.setVisible(true);
|
||||||
|
this.continueButtonContainer.setVisible(this.rerollCost < 0);
|
||||||
|
this.lockRarityButtonContainer.setVisible(canLockRarities);
|
||||||
|
|
||||||
globalScene.tweens.add({
|
globalScene.tweens.add({
|
||||||
targets: this.transferButtonContainer,
|
targets: [this.checkButtonContainer, this.continueButtonContainer],
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
duration: 250,
|
duration: 250,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
this.rerollButtonContainer.setAlpha(0);
|
globalScene.tweens.add({
|
||||||
this.checkButtonContainer.setAlpha(0);
|
targets: [this.rerollButtonContainer, this.lockRarityButtonContainer],
|
||||||
this.lockRarityButtonContainer.setAlpha(0);
|
alpha: this.rerollCost < 0 ? 0.5 : 1,
|
||||||
this.continueButtonContainer.setAlpha(0);
|
duration: 250,
|
||||||
this.rerollButtonContainer.setVisible(true);
|
});
|
||||||
this.checkButtonContainer.setVisible(true);
|
|
||||||
this.continueButtonContainer.setVisible(this.rerollCost < 0);
|
|
||||||
this.lockRarityButtonContainer.setVisible(canLockRarities);
|
|
||||||
|
|
||||||
globalScene.tweens.add({
|
const updateCursorTarget = () => {
|
||||||
targets: [this.checkButtonContainer, this.continueButtonContainer],
|
if (globalScene.shopCursorTarget === ShopCursorTarget.CHECK_TEAM) {
|
||||||
alpha: 1,
|
this.setRowCursor(0);
|
||||||
duration: 250,
|
this.setCursor(2);
|
||||||
});
|
} else if (globalScene.shopCursorTarget === ShopCursorTarget.SHOP && globalScene.gameMode.hasNoShop) {
|
||||||
|
this.setRowCursor(ShopCursorTarget.REWARDS);
|
||||||
|
this.setCursor(0);
|
||||||
|
} else {
|
||||||
|
this.setRowCursor(globalScene.shopCursorTarget);
|
||||||
|
this.setCursor(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
globalScene.tweens.add({
|
updateCursorTarget();
|
||||||
targets: [this.rerollButtonContainer, this.lockRarityButtonContainer],
|
|
||||||
alpha: this.rerollCost < 0 ? 0.5 : 1,
|
|
||||||
duration: 250,
|
|
||||||
});
|
|
||||||
|
|
||||||
const updateCursorTarget = () => {
|
handleTutorial(Tutorial.Select_Item).then(res => {
|
||||||
if (globalScene.shopCursorTarget === ShopCursorTarget.CHECK_TEAM) {
|
if (res) {
|
||||||
this.setRowCursor(0);
|
updateCursorTarget();
|
||||||
this.setCursor(2);
|
}
|
||||||
} else if (globalScene.shopCursorTarget === ShopCursorTarget.SHOP && globalScene.gameMode.hasNoShop) {
|
this.awaitingActionInput = true;
|
||||||
this.setRowCursor(ShopCursorTarget.REWARDS);
|
this.onActionInput = args[2];
|
||||||
this.setCursor(0);
|
});
|
||||||
} else {
|
|
||||||
this.setRowCursor(globalScene.shopCursorTarget);
|
|
||||||
this.setCursor(0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
updateCursorTarget();
|
|
||||||
|
|
||||||
handleTutorial(Tutorial.Select_Item).then(res => {
|
|
||||||
if (res) {
|
|
||||||
updateCursorTarget();
|
|
||||||
}
|
|
||||||
this.awaitingActionInput = true;
|
|
||||||
this.onActionInput = args[2];
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -687,7 +706,11 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||||||
scale: 0.01,
|
scale: 0.01,
|
||||||
duration: 250,
|
duration: 250,
|
||||||
ease: "Cubic.easeIn",
|
ease: "Cubic.easeIn",
|
||||||
onComplete: () => options.forEach(o => o.destroy()),
|
onComplete: () => {
|
||||||
|
options.forEach(o => {
|
||||||
|
o.destroy();
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
[
|
[
|
||||||
@ -819,7 +842,7 @@ class ModifierOption extends Phaser.GameObjects.Container {
|
|||||||
if (!globalScene) {
|
if (!globalScene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const value = t.getValue();
|
const value = t.getValue()!;
|
||||||
if (!bounce && value > lastValue) {
|
if (!bounce && value > lastValue) {
|
||||||
globalScene.playSound("se/pb_bounce_1", {
|
globalScene.playSound("se/pb_bounce_1", {
|
||||||
volume: 1 / ++bounceCount,
|
volume: 1 / ++bounceCount,
|
||||||
@ -832,41 +855,38 @@ class ModifierOption extends Phaser.GameObjects.Container {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Figure out proper delay between chains and then convert this into a single tween chain
|
||||||
|
// rather than starting multiple tween chains.
|
||||||
for (let u = 0; u < this.modifierTypeOption.upgradeCount; u++) {
|
for (let u = 0; u < this.modifierTypeOption.upgradeCount; u++) {
|
||||||
const upgradeIndex = u;
|
globalScene.tweens.chain({
|
||||||
globalScene.time.delayedCall(
|
tweens: [
|
||||||
remainingDuration - 2000 * (this.modifierTypeOption.upgradeCount - (upgradeIndex + 1 + upgradeCountOffset)),
|
{
|
||||||
() => {
|
delay: remainingDuration - 2000 * (this.modifierTypeOption.upgradeCount - (u + 1 + upgradeCountOffset)),
|
||||||
globalScene.playSound("se/upgrade", {
|
onStart: () => {
|
||||||
rate: 1 + 0.25 * upgradeIndex,
|
globalScene.playSound("se/upgrade", {
|
||||||
});
|
rate: 1 + 0.25 * u,
|
||||||
this.pbTint.setPosition(this.pb.x, this.pb.y);
|
});
|
||||||
this.pbTint.setTintFill(0xffffff);
|
this.pbTint.setPosition(this.pb.x, this.pb.y).setTintFill(0xffffff).setVisible(true).setAlpha(0);
|
||||||
this.pbTint.setAlpha(0);
|
},
|
||||||
this.pbTint.setVisible(true);
|
|
||||||
globalScene.tweens.add({
|
|
||||||
targets: this.pbTint,
|
targets: this.pbTint,
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
duration: 1000,
|
duration: 1000,
|
||||||
ease: "Sine.easeIn",
|
ease: "Sine.easeIn",
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
this.pb.setTexture(
|
this.pb.setTexture("pb", this.getPbAtlasKey(-this.modifierTypeOption.upgradeCount + (u + 1)));
|
||||||
"pb",
|
|
||||||
this.getPbAtlasKey(-this.modifierTypeOption.upgradeCount + (upgradeIndex + 1)),
|
|
||||||
);
|
|
||||||
globalScene.tweens.add({
|
|
||||||
targets: this.pbTint,
|
|
||||||
alpha: 0,
|
|
||||||
duration: 750,
|
|
||||||
ease: "Sine.easeOut",
|
|
||||||
onComplete: () => {
|
|
||||||
this.pbTint.setVisible(false);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
},
|
{
|
||||||
);
|
targets: this.pbTint,
|
||||||
|
alpha: 0,
|
||||||
|
duration: 750,
|
||||||
|
ease: "Sine.easeOut",
|
||||||
|
onComplete: () => {
|
||||||
|
this.pbTint.setVisible(false);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ export class StatsContainer extends Phaser.GameObjects.Container {
|
|||||||
duration: 1000,
|
duration: 1000,
|
||||||
ease: "Cubic.easeOut",
|
ease: "Cubic.easeOut",
|
||||||
onUpdate: (tween: Phaser.Tweens.Tween) => {
|
onUpdate: (tween: Phaser.Tweens.Tween) => {
|
||||||
const progress = tween.getValue();
|
const progress = tween.getValue() ?? 1;
|
||||||
const interpolatedData = ivChartData.map(
|
const interpolatedData = ivChartData.map(
|
||||||
(v: number, i: number) => v * progress + lastIvChartData[i] * (1 - progress),
|
(v: number, i: number) => v * progress + lastIvChartData[i] * (1 - progress),
|
||||||
);
|
);
|
||||||
|
@ -157,8 +157,8 @@ export class TargetSelectUiHandler extends UiHandler {
|
|||||||
yoyo: true,
|
yoyo: true,
|
||||||
onUpdate: t => {
|
onUpdate: t => {
|
||||||
for (const target of this.targetsHighlighted) {
|
for (const target of this.targetsHighlighted) {
|
||||||
target.setAlpha(t.getValue());
|
target.setAlpha(t.getValue() ?? 1);
|
||||||
this.highlightItems(target.id, t.getValue());
|
this.highlightItems(target.id, t.getValue() ?? 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@ import { UiTheme } from "#enums/ui-theme";
|
|||||||
import i18next from "#plugins/i18n";
|
import i18next from "#plugins/i18n";
|
||||||
import type Phaser from "phaser";
|
import type Phaser from "phaser";
|
||||||
import BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
import BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
||||||
import InputText from "phaser3-rex-plugins/plugins/inputtext";
|
import type InputText from "phaser3-rex-plugins/plugins/inputtext";
|
||||||
|
|
||||||
export enum TextStyle {
|
export enum TextStyle {
|
||||||
MESSAGE,
|
MESSAGE,
|
||||||
@ -152,8 +152,7 @@ export function addTextInputObject(
|
|||||||
): InputText {
|
): InputText {
|
||||||
const { scale, styleOptions } = getTextStyleOptions(style, globalScene.uiTheme, extraStyleOptions);
|
const { scale, styleOptions } = getTextStyleOptions(style, globalScene.uiTheme, extraStyleOptions);
|
||||||
|
|
||||||
const ret = new InputText(globalScene, x, y, width, height, styleOptions as InputText.IConfig);
|
const ret = globalScene.add.rexInputText(x, y, width, height, styleOptions as InputText.IConfig);
|
||||||
globalScene.add.existing(ret);
|
|
||||||
ret.setScale(scale);
|
ret.setScale(scale);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -159,7 +159,8 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
expect(game.scene.getEnemyPokemon()!.getTag(BattlerTagType.CURSED)).toBeDefined();
|
expect(game.scene.getEnemyPokemon()!.getTag(BattlerTagType.CURSED)).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not cause encore to be interrupted after bouncing", async () => {
|
// TODO: enable when Magic Bounce is fixed to properly reset the hit count
|
||||||
|
it.todo("should not cause encore to be interrupted after bouncing", async () => {
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.GROWL, MoveId.ENCORE]).enemyMoveset([MoveId.TACKLE, MoveId.GROWL]);
|
game.override.moveset([MoveId.SPLASH, MoveId.GROWL, MoveId.ENCORE]).enemyMoveset([MoveId.TACKLE, MoveId.GROWL]);
|
||||||
// game.override.ability(AbilityId.MOLD_BREAKER);
|
// game.override.ability(AbilityId.MOLD_BREAKER);
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
@ -167,7 +168,7 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
// Give the player MOLD_BREAKER for this turn to bypass Magic Bounce.
|
// Give the player MOLD_BREAKER for this turn to bypass Magic Bounce.
|
||||||
vi.spyOn(playerPokemon, "getAbility").mockReturnValue(allAbilities[AbilityId.MOLD_BREAKER]);
|
const playerAbilitySpy = game.field.mockAbility(playerPokemon, AbilityId.MOLD_BREAKER);
|
||||||
|
|
||||||
// turn 1
|
// turn 1
|
||||||
game.move.select(MoveId.ENCORE);
|
game.move.select(MoveId.ENCORE);
|
||||||
@ -177,7 +178,7 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
expect(enemyPokemon.getTag(BattlerTagType.ENCORE)!["moveId"]).toBe(MoveId.TACKLE);
|
expect(enemyPokemon.getTag(BattlerTagType.ENCORE)!["moveId"]).toBe(MoveId.TACKLE);
|
||||||
|
|
||||||
// turn 2
|
// turn 2
|
||||||
vi.spyOn(playerPokemon, "getAbility").mockRestore();
|
playerAbilitySpy.mockRestore();
|
||||||
game.move.select(MoveId.GROWL);
|
game.move.select(MoveId.GROWL);
|
||||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
@ -101,7 +101,8 @@ describe("BattlerTag - StockpilingTag", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("stack limit, stat tracking, and removal", () => {
|
describe("stack limit, stat tracking, and removal", () => {
|
||||||
it("can be added up to three times, even when one stat does not change", async () => {
|
// TODO: do we even want this file at all? regardless, this test is broken and is also likely unimportant
|
||||||
|
it.todo("can be added up to three times, even when one stat does not change", async () => {
|
||||||
const mockPokemon = {
|
const mockPokemon = {
|
||||||
summonData: new PokemonSummonData(),
|
summonData: new PokemonSummonData(),
|
||||||
getBattlerIndex: () => 0,
|
getBattlerIndex: () => 0,
|
||||||
@ -150,7 +151,7 @@ describe("BattlerTag - StockpilingTag", () => {
|
|||||||
expect(subject.stockpiledCount).toBe(3);
|
expect(subject.stockpiledCount).toBe(3);
|
||||||
|
|
||||||
vi.spyOn(game.scene.phaseManager, "unshiftPhase").mockImplementationOnce(_phase => {
|
vi.spyOn(game.scene.phaseManager, "unshiftPhase").mockImplementationOnce(_phase => {
|
||||||
throw new Error("Should not be called a fourth time");
|
expect.fail("Should not be called a fourth time");
|
||||||
});
|
});
|
||||||
|
|
||||||
// fourth stack should not be applied
|
// fourth stack should not be applied
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import { allMoves } from "#data/data-lists";
|
import { allMoves } from "#data/data-lists";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { BattleType } from "#enums/battle-type";
|
|
||||||
import { BattlerIndex } from "#enums/battler-index";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { MoveUseMode } from "#enums/move-use-mode";
|
import { MoveUseMode } from "#enums/move-use-mode";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
|
||||||
import { GameManager } from "#test/testUtils/gameManager";
|
import { GameManager } from "#test/testUtils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
@ -29,8 +27,7 @@ describe("Moves - Fishious Rend & Bolt Beak", () => {
|
|||||||
game.override
|
game.override
|
||||||
.ability(AbilityId.STURDY)
|
.ability(AbilityId.STURDY)
|
||||||
.battleStyle("single")
|
.battleStyle("single")
|
||||||
.battleType(BattleType.TRAINER)
|
.startingWave(5)
|
||||||
.randomTrainer({ trainerType: TrainerType.YOUNGSTER })
|
|
||||||
.criticalHits(false)
|
.criticalHits(false)
|
||||||
.enemyLevel(100)
|
.enemyLevel(100)
|
||||||
.enemySpecies(SpeciesId.DRACOVISH)
|
.enemySpecies(SpeciesId.DRACOVISH)
|
||||||
|
@ -20,8 +20,8 @@ import {
|
|||||||
} from "#test/mystery-encounter/encounter-test-utils";
|
} from "#test/mystery-encounter/encounter-test-utils";
|
||||||
import { GameManager } from "#test/testUtils/gameManager";
|
import { GameManager } from "#test/testUtils/gameManager";
|
||||||
import { initSceneWithoutEncounterPhase } from "#test/testUtils/gameManagerUtils";
|
import { initSceneWithoutEncounterPhase } from "#test/testUtils/gameManagerUtils";
|
||||||
import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/TrainerPartyTemplate";
|
|
||||||
import { TrainerConfig } from "#trainers/trainer-config";
|
import { TrainerConfig } from "#trainers/trainer-config";
|
||||||
|
import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/trainer-party-template";
|
||||||
import { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler";
|
import { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import type { MockGameObject } from "#test/testUtils/mocks/mockGameObject";
|
import type { MockGameObject } from "#test/testUtils/mocks/mockGameObject";
|
||||||
|
import { MockBBCodeText } from "#test/testUtils/mocks/mocksContainer/mock-bbcode-text";
|
||||||
|
import { MockInputText } from "#test/testUtils/mocks/mocksContainer/mock-input-text";
|
||||||
import { MockContainer } from "#test/testUtils/mocks/mocksContainer/mockContainer";
|
import { MockContainer } from "#test/testUtils/mocks/mocksContainer/mockContainer";
|
||||||
import { MockImage } from "#test/testUtils/mocks/mocksContainer/mockImage";
|
import { MockImage } from "#test/testUtils/mocks/mocksContainer/mockImage";
|
||||||
import { MockNineslice } from "#test/testUtils/mocks/mocksContainer/mockNineslice";
|
import { MockNineslice } from "#test/testUtils/mocks/mocksContainer/mockNineslice";
|
||||||
@ -33,6 +35,8 @@ export class MockTextureManager {
|
|||||||
image: this.image.bind(this),
|
image: this.image.bind(this),
|
||||||
polygon: this.polygon.bind(this),
|
polygon: this.polygon.bind(this),
|
||||||
text: this.text.bind(this),
|
text: this.text.bind(this),
|
||||||
|
rexBBCodeText: this.rexBBCodeText.bind(this),
|
||||||
|
rexInputText: this.rexInputText.bind(this),
|
||||||
bitmapText: this.text.bind(this),
|
bitmapText: this.text.bind(this),
|
||||||
displayList: this.displayList,
|
displayList: this.displayList,
|
||||||
video: () => new MockVideoGameObject(),
|
video: () => new MockVideoGameObject(),
|
||||||
@ -103,9 +107,25 @@ export class MockTextureManager {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rexBBCodeText(x, y, content, styleOptions) {
|
||||||
|
const text = new MockBBCodeText(this, x, y, content, styleOptions);
|
||||||
|
this.list.push(text);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
rexInputText(x, y, w, h, content, styleOptions) {
|
||||||
|
const text = new MockInputText(this, x, y, w, h, content, styleOptions);
|
||||||
|
this.list.push(text);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
polygon(x, y, content, fillColor, fillAlpha) {
|
polygon(x, y, content, fillColor, fillAlpha) {
|
||||||
const polygon = new MockPolygon(this, x, y, content, fillColor, fillAlpha);
|
const polygon = new MockPolygon(this, x, y, content, fillColor, fillAlpha);
|
||||||
this.list.push(polygon);
|
this.list.push(polygon);
|
||||||
return polygon;
|
return polygon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exists(key: string): boolean {
|
||||||
|
return this.textures.has(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
6
test/testUtils/mocks/mocksContainer/mock-bbcode-text.ts
Normal file
6
test/testUtils/mocks/mocksContainer/mock-bbcode-text.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { MockText } from "#test/testUtils/mocks/mocksContainer/mockText";
|
||||||
|
|
||||||
|
export class MockBBCodeText extends MockText {
|
||||||
|
setMaxLines(_lines: number) {}
|
||||||
|
setWrapMode(_mode: 0 | 1 | 2 | 3 | "none" | "word" | "char" | "character" | "mix") {}
|
||||||
|
}
|
24
test/testUtils/mocks/mocksContainer/mock-input-text.ts
Normal file
24
test/testUtils/mocks/mocksContainer/mock-input-text.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { MockText } from "#test/testUtils/mocks/mocksContainer/mockText";
|
||||||
|
|
||||||
|
export class MockInputText extends MockText {
|
||||||
|
public inputType: string;
|
||||||
|
public selectionStart: number;
|
||||||
|
public selectionEnd: number;
|
||||||
|
public selectedText: string;
|
||||||
|
|
||||||
|
constructor(textureManager, x, y, _w, _h, content, styleOptions) {
|
||||||
|
super(textureManager, x, y, content, styleOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectText(_selectionStart?: number, _selectionEnd?: number) {}
|
||||||
|
|
||||||
|
selectAll() {}
|
||||||
|
|
||||||
|
setCursorPosition(_value: number) {}
|
||||||
|
|
||||||
|
scrollToBottom() {}
|
||||||
|
|
||||||
|
resize(_width: number, _height: number) {}
|
||||||
|
|
||||||
|
setElement(_element, _style, _innerText) {}
|
||||||
|
}
|
@ -47,11 +47,5 @@
|
|||||||
"outDir": "./build",
|
"outDir": "./build",
|
||||||
"noEmit": true
|
"noEmit": true
|
||||||
},
|
},
|
||||||
"typedocOptions": {
|
|
||||||
"entryPoints": ["./src"],
|
|
||||||
"entryPointStrategy": "expand",
|
|
||||||
"exclude": "**/*+.test.ts",
|
|
||||||
"out": "typedoc"
|
|
||||||
},
|
|
||||||
"exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"]
|
"exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"]
|
||||||
}
|
}
|
||||||
|
14
tsdoc.json
Normal file
14
tsdoc.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json",
|
||||||
|
"noStandardTags": false,
|
||||||
|
"tagDefinitions": [
|
||||||
|
{
|
||||||
|
"tagName": "@todo",
|
||||||
|
"syntaxKind": "block"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tagName": "@linkcode",
|
||||||
|
"syntaxKind": "inline"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
7
typedoc.json
Normal file
7
typedoc.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"entryPoints": ["./src"],
|
||||||
|
"entryPointStrategy": "expand",
|
||||||
|
"exclude": ["**/*+.test.ts"],
|
||||||
|
"out": "typedoc",
|
||||||
|
"highlightLanguages": ["javascript", "json", "jsonc", "json5", "tsx", "typescript", "markdown"]
|
||||||
|
}
|
@ -2,31 +2,13 @@ import { defineProject } from "vitest/config";
|
|||||||
import { BaseSequencer, type TestSpecification } from "vitest/node";
|
import { BaseSequencer, type TestSpecification } from "vitest/node";
|
||||||
import { defaultConfig } from "./vite.config";
|
import { defaultConfig } from "./vite.config";
|
||||||
|
|
||||||
function getTestOrder(testName: string): number {
|
|
||||||
if (testName.includes("battle-scene.test.ts")) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (testName.includes("inputs.test.ts")) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default defineProject(({ mode }) => ({
|
export default defineProject(({ mode }) => ({
|
||||||
...defaultConfig,
|
...defaultConfig,
|
||||||
test: {
|
test: {
|
||||||
testTimeout: 20000,
|
testTimeout: 20000,
|
||||||
setupFiles: ["./test/fontFace.setup.ts", "./test/vitest.setup.ts"],
|
setupFiles: ["./test/fontFace.setup.ts", "./test/vitest.setup.ts"],
|
||||||
sequence: {
|
sequence: {
|
||||||
sequencer: class CustomSequencer extends BaseSequencer {
|
sequencer: MySequencer,
|
||||||
async sort(files: TestSpecification[]) {
|
|
||||||
// use default sorting at first.
|
|
||||||
files = await super.sort(files);
|
|
||||||
// Except, forcibly reorder
|
|
||||||
|
|
||||||
return files.sort((a, b) => getTestOrder(a.moduleId) - getTestOrder(b.moduleId));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
environment: "jsdom" as const,
|
environment: "jsdom" as const,
|
||||||
environmentOptions: {
|
environmentOptions: {
|
||||||
@ -55,3 +37,38 @@ export default defineProject(({ mode }) => ({
|
|||||||
keepNames: true,
|
keepNames: true,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
//#region Helpers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for sorting test files in the desired order.
|
||||||
|
*/
|
||||||
|
class MySequencer extends BaseSequencer {
|
||||||
|
async sort(files: TestSpecification[]) {
|
||||||
|
files = await super.sort(files);
|
||||||
|
|
||||||
|
return files.sort((a, b) => {
|
||||||
|
const aTestOrder = getTestOrder(a.moduleId);
|
||||||
|
const bTestOrder = getTestOrder(b.moduleId);
|
||||||
|
return aTestOrder - bTestOrder;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper function for sorting test files in a desired order.
|
||||||
|
*
|
||||||
|
* A lower number means that a test file must be run earlier,
|
||||||
|
* or else it breaks due to running tests with `--no-isolate.`
|
||||||
|
*/
|
||||||
|
function getTestOrder(testName: string): number {
|
||||||
|
if (testName.includes("battle-scene.test.ts")) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (testName.includes("inputs.test.ts")) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { defineWorkspace } from "vitest/config";
|
|
||||||
import { defaultConfig } from "./vite.config";
|
|
||||||
|
|
||||||
export default defineWorkspace([
|
|
||||||
{
|
|
||||||
...defaultConfig,
|
|
||||||
test: {
|
|
||||||
name: "pre",
|
|
||||||
include: ["./test/pre.test.ts"],
|
|
||||||
environment: "jsdom",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"./vitest.config.ts",
|
|
||||||
]);
|
|
Loading…
Reference in New Issue
Block a user