Merge branch 'main' into feature/local-server-mock
1
.env
@ -1,3 +1,4 @@
|
||||
VITE_BYPASS_LOGIN=0
|
||||
VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=http://localhost:8001
|
||||
VITE_MOCK_API=0
|
@ -1,3 +1,4 @@
|
||||
VITE_BYPASS_LOGIN=1
|
||||
VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=http://localhost:8001
|
||||
VITE_MOCK_API=1
|
@ -46,7 +46,14 @@ Check out [Github Issues](https://github.com/pagefaultgames/pokerogue/issues) to
|
||||
- Keisuke Ito
|
||||
- Arata Iiyoshi
|
||||
- Atsuhiro Ishizuna
|
||||
- Pokémon HeartGold/SoulSilver
|
||||
- Pokémon Black/White 2
|
||||
- Pokémon X/Y
|
||||
- Pokémon Omega Ruby/Alpha Sapphire
|
||||
- Pokémon Sun/Moon
|
||||
- Pokémon Ultra Sun/Ultra Moon
|
||||
- Pokémon Sword/Shield
|
||||
- Pokémon Scarlet/Violet
|
||||
- Firel (Custom Metropolis and Laboratory biome music)
|
||||
- Lmz (Custom Jungle biome music)
|
||||
|
||||
|
@ -146,13 +146,13 @@ body {
|
||||
margin-left: 10%;
|
||||
}
|
||||
|
||||
#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_DISPLAY']):not([data-ui-mode='SETTINGS_AUDIO']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadRectBtnContainer > .apadSqBtn,
|
||||
#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_DISPLAY']):not([data-ui-mode='SETTINGS_AUDIO']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadSqBtnContainer
|
||||
#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_DISPLAY']):not([data-ui-mode='SETTINGS_AUDIO']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadRectBtnContainer > .apadSqBtn:not(.apadBattle),
|
||||
#touchControls:not([data-ui-mode='STARTER_SELECT']):not([data-ui-mode='SETTINGS']):not([data-ui-mode='SETTINGS_DISPLAY']):not([data-ui-mode='SETTINGS_AUDIO']):not([data-ui-mode='SETTINGS_GAMEPAD']):not([data-ui-mode='SETTINGS_KEYBOARD']) #apad .apadSqBtnContainer > .apadSqBtn:not(.apadBattle)
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']) #apad .apadBattle {
|
||||
#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']):not([data-ui-mode='MODIFIER_SELECT']) #apad .apadBattle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
"test": "vitest run",
|
||||
"test:cov": "vitest run --coverage",
|
||||
"test:watch": "vitest watch --coverage",
|
||||
"test:silent": "vitest run --silent",
|
||||
"eslint": "eslint --fix .",
|
||||
"eslint-ci": "eslint .",
|
||||
"docs": "typedoc"
|
||||
|
BIN
public/audio/bgm/battle_alola_champion.mp3
Normal file
BIN
public/audio/bgm/battle_alola_elite.mp3
Normal file
BIN
public/audio/bgm/battle_bb_elite.mp3
Normal file
BIN
public/audio/bgm/battle_champion_geeta.mp3
Normal file
BIN
public/audio/bgm/battle_champion_kieran.mp3
Normal file
BIN
public/audio/bgm/battle_champion_nemona.mp3
Normal file
BIN
public/audio/bgm/battle_galar_champion.mp3
Normal file
BIN
public/audio/bgm/battle_galar_elite.mp3
Normal file
BIN
public/audio/bgm/battle_galar_gym.mp3
Normal file
BIN
public/audio/bgm/battle_hoenn_elite.mp3
Normal file
BIN
public/audio/bgm/battle_kalos_champion.mp3
Normal file
BIN
public/audio/bgm/battle_kalos_elite.mp3
Normal file
BIN
public/audio/bgm/battle_kalos_gym.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_arceus.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_birds_galar.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_calyrex.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_deoxys.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_dia_pal.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_dusk_dawn.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_entei.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_giratina.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_glas_spec.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_gro_kyo.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_ho_oh.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_kanto.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_lake_trio.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_loyal_three.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_lugia.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_ogerpon.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_pecharunt.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_raikou.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_rayquaza.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_regis_g6.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_ruinous.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_sinnoh.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_sol_lun.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_suicune.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_tapu.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_terapagos.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_ub.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_ultra_nec.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_xern_yvel.mp3
Normal file
BIN
public/audio/bgm/battle_legendary_zac_zam.mp3
Normal file
BIN
public/audio/bgm/battle_paldea_elite.mp3
Normal file
BIN
public/audio/bgm/battle_paldea_gym.mp3
Normal file
2834
public/images/pokemon/133-partner.json
Normal file
BIN
public/images/pokemon/133-partner.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
2456
public/images/pokemon/25-partner.json
Normal file
BIN
public/images/pokemon/25-partner.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
2834
public/images/pokemon/back/133-partner.json
Normal file
BIN
public/images/pokemon/back/133-partner.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
2456
public/images/pokemon/back/25-partner.json
Normal file
BIN
public/images/pokemon/back/25-partner.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
2456
public/images/pokemon/back/female/25-partner.json
Normal file
BIN
public/images/pokemon/back/female/25-partner.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
2834
public/images/pokemon/back/shiny/133-partner.json
Normal file
BIN
public/images/pokemon/back/shiny/133-partner.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
2456
public/images/pokemon/back/shiny/25-partner.json
Normal file
BIN
public/images/pokemon/back/shiny/25-partner.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
2456
public/images/pokemon/back/shiny/female/25-partner.json
Normal file
BIN
public/images/pokemon/back/shiny/female/25-partner.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
2456
public/images/pokemon/female/25-partner.json
Normal file
BIN
public/images/pokemon/female/25-partner.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
public/images/pokemon/icons/1/133-partner.png
Normal file
After Width: | Height: | Size: 394 B |
BIN
public/images/pokemon/icons/1/133s-partner.png
Normal file
After Width: | Height: | Size: 419 B |
BIN
public/images/pokemon/icons/1/25-partner.png
Normal file
After Width: | Height: | Size: 397 B |
BIN
public/images/pokemon/icons/1/25s-partner.png
Normal file
After Width: | Height: | Size: 397 B |
2834
public/images/pokemon/shiny/133-partner.json
Normal file
BIN
public/images/pokemon/shiny/133-partner.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
2456
public/images/pokemon/shiny/25-partner.json
Normal file
BIN
public/images/pokemon/shiny/25-partner.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
2456
public/images/pokemon/shiny/female/25-partner.json
Normal file
BIN
public/images/pokemon/shiny/female/25-partner.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
@ -1745,27 +1745,27 @@
|
||||
1
|
||||
],
|
||||
"641-incarnate": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"641-therian": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"642-incarnate": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"642-therian": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"645-incarnate": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
@ -4608,32 +4608,32 @@
|
||||
1
|
||||
],
|
||||
"641-incarnate": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"641-therian": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"642-incarnate": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"642-therian": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"645-incarnate": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"645-therian": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
41
public/images/trainer/sailor.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "sailor.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 72,
|
||||
"h": 72
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 72,
|
||||
"h": 72
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 73,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 39,
|
||||
"h": 72
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:f692676a166fc1915532cd94d5799af4:fb833f76fb6797474657726bb59a7eee:aeb55e30992938f494b6cd2420158dda$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/sailor.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
@ -13,15 +13,15 @@ import { Biome } from "./data/enums/biome";
|
||||
import { Arena, ArenaBase } from "./field/arena";
|
||||
import { GameData } from "./system/game-data";
|
||||
import { PlayerGender } from "./data/enums/player-gender";
|
||||
import { TextStyle, addTextObject } from "./ui/text";
|
||||
import { TextStyle, addTextObject, getTextColor } from "./ui/text";
|
||||
import { Moves } from "./data/enums/moves";
|
||||
import { allMoves } from "./data/move";
|
||||
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getPartyLuckValue } from "./modifier/modifier-type";
|
||||
import AbilityBar from "./ui/ability-bar";
|
||||
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
|
||||
import { allAbilities } from "./data/ability";
|
||||
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from "./battle";
|
||||
import { GameMode, GameModes, gameModes } from "./game-mode";
|
||||
import Battle, { BattleType, FixedBattleConfig } from "./battle";
|
||||
import { GameMode, GameModes, getGameMode } from "./game-mode";
|
||||
import FieldSpritePipeline from "./pipelines/field-sprite";
|
||||
import SpritePipeline from "./pipelines/sprite";
|
||||
import PartyExpBar from "./ui/party-exp-bar";
|
||||
@ -62,6 +62,7 @@ import { NewArenaEvent } from "./battle-scene-events";
|
||||
import { Abilities } from "./data/enums/abilities";
|
||||
import ArenaFlyout from "./ui/arena-flyout";
|
||||
import { EaseType } from "./ui/enums/ease-type";
|
||||
import { ExpNotification } from "./enums/exp-notification";
|
||||
|
||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||
|
||||
@ -125,6 +126,7 @@ export default class BattleScene extends SceneBase {
|
||||
public uiTheme: UiTheme = UiTheme.DEFAULT;
|
||||
public windowType: integer = 0;
|
||||
public experimentalSprites: boolean = false;
|
||||
public musicPreference: integer = 0;
|
||||
public moveAnimations: boolean = true;
|
||||
public expGainsSpeed: integer = 0;
|
||||
public skipSeenDialogues: boolean = false;
|
||||
@ -141,7 +143,7 @@ export default class BattleScene extends SceneBase {
|
||||
* Modes `1` and `2` are still compatible with stats display, level up, new move, etc.
|
||||
* @default 0 - Uses the default normal experience gain display.
|
||||
*/
|
||||
public expParty: integer = 0;
|
||||
public expParty: ExpNotification = 0;
|
||||
public hpBarSpeed: integer = 0;
|
||||
public fusionPaletteSwaps: boolean = true;
|
||||
public enableTouchControls: boolean = false;
|
||||
@ -153,12 +155,19 @@ export default class BattleScene extends SceneBase {
|
||||
*/
|
||||
public battleStyle: integer = 0;
|
||||
|
||||
/**
|
||||
* Defines whether or not to show type effectiveness hints
|
||||
* - true: No hints
|
||||
* - false: Show hints for moves
|
||||
*/
|
||||
public typeHints: boolean = false;
|
||||
|
||||
public disableMenu: boolean = false;
|
||||
|
||||
public gameData: GameData;
|
||||
public sessionSlotId: integer;
|
||||
|
||||
private phaseQueue: Phase[];
|
||||
public phaseQueue: Phase[];
|
||||
private phaseQueuePrepend: Phase[];
|
||||
private phaseQueuePrependSpliceIndex: integer;
|
||||
private nextCommandPhaseQueue: Phase[];
|
||||
@ -200,7 +209,7 @@ export default class BattleScene extends SceneBase {
|
||||
public arenaFlyout: ArenaFlyout;
|
||||
|
||||
private fieldOverlay: Phaser.GameObjects.Rectangle;
|
||||
private modifiers: PersistentModifier[];
|
||||
public modifiers: PersistentModifier[];
|
||||
private enemyModifiers: PersistentModifier[];
|
||||
public uiContainer: Phaser.GameObjects.Container;
|
||||
public ui: UI;
|
||||
@ -225,6 +234,7 @@ export default class BattleScene extends SceneBase {
|
||||
public rngSeedOverride: string = "";
|
||||
public rngOffset: integer = 0;
|
||||
|
||||
public inputMethod: string;
|
||||
private infoToggles: InfoToggle[] = [];
|
||||
|
||||
/**
|
||||
@ -299,7 +309,8 @@ export default class BattleScene extends SceneBase {
|
||||
this.fieldSpritePipeline = new FieldSpritePipeline(this.game);
|
||||
(this.renderer as Phaser.Renderer.WebGL.WebGLRenderer).pipelines.add("FieldSprite", this.fieldSpritePipeline);
|
||||
|
||||
this.time.delayedCall(20, () => this.launchBattle());
|
||||
|
||||
this.launchBattle();
|
||||
}
|
||||
|
||||
update() {
|
||||
@ -320,6 +331,7 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
const field = this.add.container(0, 0);
|
||||
field.setScale(6);
|
||||
field.setName("container-field");
|
||||
|
||||
this.field = field;
|
||||
|
||||
@ -409,28 +421,28 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
this.biomeWaveText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, startingWave.toString(), TextStyle.BATTLE_INFO);
|
||||
this.biomeWaveText.setName("text-biome-wave");
|
||||
this.biomeWaveText.setOrigin(1, 0);
|
||||
this.biomeWaveText.setOrigin(1, 0.5);
|
||||
this.fieldUI.add(this.biomeWaveText);
|
||||
|
||||
this.moneyText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, "", TextStyle.MONEY);
|
||||
this.moneyText.setName("text-money");
|
||||
this.moneyText.setOrigin(1, 0);
|
||||
this.moneyText.setOrigin(1, 0.5);
|
||||
this.fieldUI.add(this.moneyText);
|
||||
|
||||
this.scoreText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, "", TextStyle.PARTY, { fontSize: "54px" });
|
||||
this.scoreText.setName("text-score");
|
||||
this.scoreText.setOrigin(1, 0);
|
||||
this.scoreText.setOrigin(1, 0.5);
|
||||
this.fieldUI.add(this.scoreText);
|
||||
|
||||
this.luckText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, "", TextStyle.PARTY, { fontSize: "54px" });
|
||||
this.luckText.setName("text-luck");
|
||||
this.luckText.setOrigin(1, 0);
|
||||
this.luckText.setOrigin(1, 0.5);
|
||||
this.luckText.setVisible(false);
|
||||
this.fieldUI.add(this.luckText);
|
||||
|
||||
this.luckLabelText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, "Luck:", TextStyle.PARTY, { fontSize: "54px" });
|
||||
this.luckLabelText.setName("text-luck-label");
|
||||
this.luckLabelText.setOrigin(1, 0);
|
||||
this.luckLabelText.setOrigin(1, 0.5);
|
||||
this.luckLabelText.setVisible(false);
|
||||
this.fieldUI.add(this.luckLabelText);
|
||||
|
||||
@ -455,9 +467,13 @@ export default class BattleScene extends SceneBase {
|
||||
const loadPokemonAssets = [];
|
||||
|
||||
this.arenaPlayer = new ArenaBase(this, true);
|
||||
this.arenaPlayer.setName("container-arena-player");
|
||||
this.arenaPlayerTransition = new ArenaBase(this, true);
|
||||
this.arenaPlayerTransition.setName("container-arena-player-transition");
|
||||
this.arenaEnemy = new ArenaBase(this, false);
|
||||
this.arenaEnemy.setName("container-arena-enemy");
|
||||
this.arenaNextEnemy = new ArenaBase(this, false);
|
||||
this.arenaNextEnemy.setName("container-arena-next-enemy");
|
||||
|
||||
this.arenaBgTransition.setVisible(false);
|
||||
this.arenaPlayerTransition.setVisible(false);
|
||||
@ -472,6 +488,7 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
const trainer = this.addFieldSprite(0, 0, `trainer_${this.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`);
|
||||
trainer.setOrigin(0.5, 1);
|
||||
trainer.setName("sprite-trainer");
|
||||
|
||||
field.add(trainer);
|
||||
|
||||
@ -844,7 +861,7 @@ export default class BattleScene extends SceneBase {
|
||||
this.gameData = new GameData(this);
|
||||
}
|
||||
|
||||
this.gameMode = gameModes[GameModes.CLASSIC];
|
||||
this.gameMode = getGameMode(GameModes.CLASSIC);
|
||||
|
||||
this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24));
|
||||
console.log("Seed:", this.seed);
|
||||
@ -940,7 +957,8 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean): Battle {
|
||||
const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (startingWave - 1)) + 1);
|
||||
const _startingWave = Overrides.STARTING_WAVE_OVERRIDE || startingWave;
|
||||
const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (_startingWave - 1)) + 1);
|
||||
let newDouble: boolean;
|
||||
let newBattleType: BattleType;
|
||||
let newTrainer: Trainer;
|
||||
@ -951,8 +969,8 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
const playerField = this.getPlayerField();
|
||||
|
||||
if (this.gameMode.hasFixedBattles && fixedBattles.hasOwnProperty(newWaveIndex) && trainerData === undefined) {
|
||||
battleConfig = fixedBattles[newWaveIndex];
|
||||
if (this.gameMode.isFixedBattle(newWaveIndex) && trainerData === undefined) {
|
||||
battleConfig = this.gameMode.getFixedBattle(newWaveIndex);
|
||||
newDouble = battleConfig.double;
|
||||
newBattleType = battleConfig.battleType;
|
||||
this.executeWithSeedOffset(() => newTrainer = battleConfig.getTrainer(this), (battleConfig.seedOffsetWaveIndex || newWaveIndex) << 8);
|
||||
@ -1000,6 +1018,10 @@ export default class BattleScene extends SceneBase {
|
||||
if (Overrides.DOUBLE_BATTLE_OVERRIDE) {
|
||||
newDouble = true;
|
||||
}
|
||||
/* Override battles into single only if not fighting with trainers */
|
||||
if (newBattleType !== BattleType.TRAINER && Overrides.SINGLE_BATTLE_OVERRIDE) {
|
||||
newDouble = false;
|
||||
}
|
||||
|
||||
const lastBattle = this.currentBattle;
|
||||
|
||||
@ -1369,8 +1391,7 @@ export default class BattleScene extends SceneBase {
|
||||
if (this.money === undefined) {
|
||||
return;
|
||||
}
|
||||
const formattedMoney =
|
||||
this.moneyFormat === MoneyFormat.ABBREVIATED ? Utils.formatFancyLargeNumber(this.money, 3) : this.money.toLocaleString();
|
||||
const formattedMoney = Utils.formatMoney(this.moneyFormat, this.money);
|
||||
this.moneyText.setText(`₽${formattedMoney}`);
|
||||
this.fieldUI.moveAbove(this.moneyText, this.luckText);
|
||||
if (forceVisible) {
|
||||
@ -1378,6 +1399,22 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
}
|
||||
|
||||
animateMoneyChanged(positiveChange: boolean): void {
|
||||
if (this.tweens.getTweensOf(this.moneyText).length > 0) {
|
||||
return;
|
||||
}
|
||||
const deltaScale = this.moneyText.scale * 0.14 * (positiveChange ? 1 : -1);
|
||||
this.moneyText.setShadowColor(positiveChange ? "#008000" : "#FF0000");
|
||||
this.tweens.add({
|
||||
targets: this.moneyText,
|
||||
duration: 250,
|
||||
scale: this.moneyText.scale + deltaScale,
|
||||
loop: 0,
|
||||
yoyo: true,
|
||||
onComplete: (_) => this.moneyText.setShadowColor(getTextColor(TextStyle.MONEY, true)),
|
||||
});
|
||||
}
|
||||
|
||||
updateScoreText(): void {
|
||||
this.scoreText.setText(`Score: ${this.score.toString()}`);
|
||||
this.scoreText.setVisible(this.gameMode.isDaily);
|
||||
@ -1421,7 +1458,10 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
updateUIPositions(): void {
|
||||
const enemyModifierCount = this.enemyModifiers.filter(m => m.isIconVisible(this)).length;
|
||||
this.biomeWaveText.setY(-(this.game.canvas.height / 6) + (enemyModifierCount ? enemyModifierCount <= 12 ? 15 : 24 : 0));
|
||||
const biomeWaveTextHeight = this.biomeWaveText.getBottomLeft().y - this.biomeWaveText.getTopLeft().y;
|
||||
this.biomeWaveText.setY(
|
||||
-(this.game.canvas.height / 6) + (enemyModifierCount ? enemyModifierCount <= 12 ? 15 : 24 : 0) + (biomeWaveTextHeight / 2)
|
||||
);
|
||||
this.moneyText.setY(this.biomeWaveText.y + 10);
|
||||
this.scoreText.setY(this.moneyText.y + 10);
|
||||
[ this.luckLabelText, this.luckText ].map(l => l.setY((this.scoreText.visible ? this.scoreText : this.moneyText).y + 10));
|
||||
@ -1640,55 +1680,145 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
getBgmLoopPoint(bgmName: string): number {
|
||||
switch (bgmName) {
|
||||
case "battle_kanto_champion":
|
||||
case "battle_kanto_champion": //B2W2 Kanto Champion Battle
|
||||
return 13.950;
|
||||
case "battle_johto_champion":
|
||||
case "battle_johto_champion": //B2W2 Johto Champion Battle
|
||||
return 23.498;
|
||||
case "battle_hoenn_champion":
|
||||
case "battle_hoenn_champion": //B2W2 Hoenn Champion Battle
|
||||
return 11.328;
|
||||
case "battle_sinnoh_champion":
|
||||
case "battle_sinnoh_champion": //B2W2 Sinnoh Champion Battle
|
||||
return 12.235;
|
||||
case "battle_champion_alder":
|
||||
case "battle_champion_alder": //BW Unova Champion Battle
|
||||
return 27.653;
|
||||
case "battle_champion_iris":
|
||||
case "battle_champion_iris": //B2W2 Unova Champion Battle
|
||||
return 10.145;
|
||||
case "battle_elite":
|
||||
case "battle_kalos_champion": //XY Kalos Champion Battle
|
||||
return 10.380;
|
||||
case "battle_alola_champion": //USUM Alola Champion Battle
|
||||
return 13.025;
|
||||
case "battle_galar_champion": //SWSH Galar Champion Battle
|
||||
return 61.635;
|
||||
case "battle_champion_geeta": //SV Champion Geeta Battle
|
||||
return 37.447;
|
||||
case "battle_champion_nemona": //SV Champion Nemona Battle
|
||||
return 14.914;
|
||||
case "battle_champion_kieran": //SV Champion Kieran Battle
|
||||
return 7.206;
|
||||
case "battle_hoenn_elite": //ORAS Elite Four Battle
|
||||
return 11.350;
|
||||
case "battle_unova_elite": //BW Elite Four Battle
|
||||
return 17.730;
|
||||
case "battle_final_encounter":
|
||||
case "battle_kalos_elite": //XY Elite Four Battle
|
||||
return 12.340;
|
||||
case "battle_alola_elite": //SM Elite Four Battle
|
||||
return 19.212;
|
||||
case "battle_galar_elite": //SWSH League Tournament Battle
|
||||
return 164.069;
|
||||
case "battle_paldea_elite": //SV Elite Four Battle
|
||||
return 12.770;
|
||||
case "battle_bb_elite": //SV BB League Elite Four Battle
|
||||
return 19.434;
|
||||
case "battle_final_encounter": //PMD RTDX Rayquaza's Domain
|
||||
return 19.159;
|
||||
case "battle_final":
|
||||
case "battle_final": //BW Ghetsis Battle
|
||||
return 16.453;
|
||||
case "battle_kanto_gym":
|
||||
case "battle_kanto_gym": //B2W2 Kanto Gym Battle
|
||||
return 13.857;
|
||||
case "battle_johto_gym":
|
||||
case "battle_johto_gym": //B2W2 Johto Gym Battle
|
||||
return 12.911;
|
||||
case "battle_hoenn_gym":
|
||||
case "battle_hoenn_gym": //B2W2 Hoenn Gym Battle
|
||||
return 12.379;
|
||||
case "battle_sinnoh_gym":
|
||||
case "battle_sinnoh_gym": //B2W2 Sinnoh Gym Battle
|
||||
return 13.122;
|
||||
case "battle_unova_gym":
|
||||
case "battle_unova_gym": //BW Unova Gym Battle
|
||||
return 19.145;
|
||||
case "battle_legendary_regis": //B2W2 Legendary Titan Battle
|
||||
case "battle_kalos_gym": //XY Kalos Gym Battle
|
||||
return 44.810;
|
||||
case "battle_galar_gym": //SWSH Galar Gym Battle
|
||||
return 171.262;
|
||||
case "battle_paldea_gym": //SV Paldea Gym Battle
|
||||
return 127.489;
|
||||
case "battle_legendary_kanto": //XY Kanto Legendary Battle
|
||||
return 32.966;
|
||||
case "battle_legendary_raikou": //HGSS Raikou Battle
|
||||
return 12.632;
|
||||
case "battle_legendary_entei": //HGSS Entei Battle
|
||||
return 2.905;
|
||||
case "battle_legendary_suicune": //HGSS Suicune Battle
|
||||
return 12.636;
|
||||
case "battle_legendary_lugia": //HGSS Lugia Battle
|
||||
return 19.770;
|
||||
case "battle_legendary_ho_oh": //HGSS Ho-oh Battle
|
||||
return 17.668;
|
||||
case "battle_legendary_regis_g5": //B2W2 Legendary Titan Battle
|
||||
return 49.500;
|
||||
case "battle_legendary_regis_g6": //ORAS Legendary Titan Battle
|
||||
return 21.130;
|
||||
case "battle_legendary_gro_kyo": //ORAS Groudon & Kyogre Battle
|
||||
return 10.547;
|
||||
case "battle_legendary_rayquaza": //ORAS Rayquaza Battle
|
||||
return 10.495;
|
||||
case "battle_legendary_deoxys": //ORAS Deoxys Battle
|
||||
return 13.333;
|
||||
case "battle_legendary_lake_trio": //ORAS Lake Guardians Battle
|
||||
return 16.887;
|
||||
case "battle_legendary_sinnoh": //ORAS Sinnoh Legendary Battle
|
||||
return 22.770;
|
||||
case "battle_legendary_dia_pal": //ORAS Dialga & Palkia Battle
|
||||
return 16.009;
|
||||
case "battle_legendary_giratina": //ORAS Giratina Battle
|
||||
return 10.451;
|
||||
case "battle_legendary_arceus": //HGSS Arceus Battle
|
||||
return 9.595;
|
||||
case "battle_legendary_unova": //BW Unova Legendary Battle
|
||||
return 13.855;
|
||||
case "battle_legendary_kyurem": //BW Kyurem Battle
|
||||
return 18.314;
|
||||
case "battle_legendary_res_zek": //BW Reshiram & Zekrom Battle
|
||||
return 18.329;
|
||||
case "battle_rival":
|
||||
case "battle_legendary_xern_yvel": //XY Xerneas & Yveltal Battle
|
||||
return 26.468;
|
||||
case "battle_legendary_tapu": //SM Tapu Battle
|
||||
return 0.000;
|
||||
case "battle_legendary_sol_lun": //SM Solgaleo & Lunala Battle
|
||||
return 6.525;
|
||||
case "battle_legendary_ub": //SM Ultra Beast Battle
|
||||
return 9.818;
|
||||
case "battle_legendary_dusk_dawn": //USUM Dusk Mane & Dawn Wings Necrozma Battle
|
||||
return 5.211;
|
||||
case "battle_legendary_ultra_nec": //USUM Ultra Necrozma Battle
|
||||
return 10.344;
|
||||
case "battle_legendary_zac_zam": //SWSH Zacian & Zamazenta Battle
|
||||
return 11.424;
|
||||
case "battle_legendary_glas_spec": //SWSH Glastrier & Spectrier Battle
|
||||
return 12.503;
|
||||
case "battle_legendary_calyrex": //SWSH Calyrex Battle
|
||||
return 50.641;
|
||||
case "battle_legendary_birds_galar": //SWSH Galarian Legendary Birds Battle
|
||||
return 0.175;
|
||||
case "battle_legendary_ruinous": //SV Treasures of Ruin Battle
|
||||
return 6.333;
|
||||
case "battle_legendary_loyal_three": //SV Loyal Three Battle
|
||||
return 6.500;
|
||||
case "battle_legendary_ogerpon": //SV Ogerpon Battle
|
||||
return 14.335;
|
||||
case "battle_legendary_terapagos": //SV Terapagos Battle
|
||||
return 24.377;
|
||||
case "battle_legendary_pecharunt": //SV Pecharunt Battle
|
||||
return 6.508;
|
||||
case "battle_rival": //BW Rival Battle
|
||||
return 13.689;
|
||||
case "battle_rival_2":
|
||||
case "battle_rival_2": //BW N Battle
|
||||
return 17.714;
|
||||
case "battle_rival_3":
|
||||
case "battle_rival_3": //BW Final N Battle
|
||||
return 17.586;
|
||||
case "battle_trainer":
|
||||
case "battle_trainer": //BW Trainer Battle
|
||||
return 13.686;
|
||||
case "battle_wild":
|
||||
case "battle_wild": //BW Wild Battle
|
||||
return 12.703;
|
||||
case "battle_wild_strong":
|
||||
case "battle_wild_strong": //BW Strong Wild Battle
|
||||
return 13.940;
|
||||
case "end_summit":
|
||||
case "end_summit": //PMD RTDX Sky Tower Summit
|
||||
return 30.025;
|
||||
}
|
||||
|
||||
@ -1823,6 +1953,7 @@ export default class BattleScene extends SceneBase {
|
||||
addMoney(amount: integer): void {
|
||||
this.money = Math.min(this.money + amount, Number.MAX_SAFE_INTEGER);
|
||||
this.updateMoneyText();
|
||||
this.animateMoneyChanged(true);
|
||||
this.validateAchvs(MoneyAchv);
|
||||
}
|
||||
|
||||
|
110
src/battle.ts
@ -197,7 +197,11 @@ export default class Battle {
|
||||
if (!this.started && this.trainer.config.encounterBgm && this.trainer.getEncounterMessages()?.length) {
|
||||
return `encounter_${this.trainer.getEncounterBgm()}`;
|
||||
}
|
||||
if (scene.musicPreference === 0) {
|
||||
return this.trainer.getBattleBgm();
|
||||
} else {
|
||||
return this.trainer.getMixedBattleBgm();
|
||||
}
|
||||
} else if (this.gameMode.isClassic && this.waveIndex > 195 && this.battleSpec !== BattleSpec.FINAL_BOSS) {
|
||||
return "end_summit";
|
||||
}
|
||||
@ -209,15 +213,13 @@ export default class Battle {
|
||||
return "battle_final_encounter";
|
||||
}
|
||||
if (pokemon.species.legendary || pokemon.species.subLegendary || pokemon.species.mythical) {
|
||||
if (scene.musicPreference === 0) {
|
||||
if (pokemon.species.speciesId === Species.REGIROCK || pokemon.species.speciesId === Species.REGICE || pokemon.species.speciesId === Species.REGISTEEL || pokemon.species.speciesId === Species.REGIGIGAS || pokemon.species.speciesId === Species.REGIELEKI || pokemon.species.speciesId === Species.REGIDRAGO) {
|
||||
return "battle_legendary_regis";
|
||||
return "battle_legendary_regis_g5";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.COBALION || pokemon.species.speciesId === Species.TERRAKION || pokemon.species.speciesId === Species.VIRIZION || pokemon.species.speciesId === Species.TORNADUS || pokemon.species.speciesId === Species.THUNDURUS || pokemon.species.speciesId === Species.LANDORUS || pokemon.species.speciesId === Species.KELDEO || pokemon.species.speciesId === Species.MELOETTA || pokemon.species.speciesId === Species.GENESECT) {
|
||||
return "battle_legendary_unova";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.RESHIRAM || pokemon.species.speciesId === Species.ZEKROM) {
|
||||
return "battle_legendary_res_zek";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.KYUREM) {
|
||||
return "battle_legendary_kyurem";
|
||||
}
|
||||
@ -225,6 +227,102 @@ export default class Battle {
|
||||
return "battle_legendary_res_zek";
|
||||
}
|
||||
return "battle_legendary_unova";
|
||||
} else {
|
||||
if (pokemon.species.speciesId === Species.ARTICUNO || pokemon.species.speciesId === Species.ZAPDOS || pokemon.species.speciesId === Species.MOLTRES || pokemon.species.speciesId === Species.MEWTWO || pokemon.species.speciesId === Species.MEW) {
|
||||
return "battle_legendary_kanto";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.RAIKOU) {
|
||||
return "battle_legendary_raikou";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.ENTEI) {
|
||||
return "battle_legendary_entei";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.SUICUNE) {
|
||||
return "battle_legendary_suicune";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.LUGIA) {
|
||||
return "battle_legendary_lugia";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.HO_OH) {
|
||||
return "battle_legendary_ho_oh";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.REGIROCK || pokemon.species.speciesId === Species.REGICE || pokemon.species.speciesId === Species.REGISTEEL || pokemon.species.speciesId === Species.REGIGIGAS || pokemon.species.speciesId === Species.REGIELEKI || pokemon.species.speciesId === Species.REGIDRAGO) {
|
||||
return "battle_legendary_regis_g6";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.GROUDON || pokemon.species.speciesId === Species.KYOGRE) {
|
||||
return "battle_legendary_gro_kyo";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.RAYQUAZA) {
|
||||
return "battle_legendary_rayquaza";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.DEOXYS) {
|
||||
return "battle_legendary_deoxys";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.UXIE || pokemon.species.speciesId === Species.MESPRIT || pokemon.species.speciesId === Species.AZELF) {
|
||||
return "battle_legendary_lake_trio";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.HEATRAN || pokemon.species.speciesId === Species.CRESSELIA || pokemon.species.speciesId === Species.DARKRAI || pokemon.species.speciesId === Species.SHAYMIN) {
|
||||
return "battle_legendary_sinnoh";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.DIALGA || pokemon.species.speciesId === Species.PALKIA) {
|
||||
return "battle_legendary_dia_pal";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.GIRATINA) {
|
||||
return "battle_legendary_giratina";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.ARCEUS) {
|
||||
return "battle_legendary_arceus";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.COBALION || pokemon.species.speciesId === Species.TERRAKION || pokemon.species.speciesId === Species.VIRIZION || pokemon.species.speciesId === Species.TORNADUS || pokemon.species.speciesId === Species.THUNDURUS || pokemon.species.speciesId === Species.LANDORUS || pokemon.species.speciesId === Species.KELDEO || pokemon.species.speciesId === Species.MELOETTA || pokemon.species.speciesId === Species.GENESECT) {
|
||||
return "battle_legendary_unova";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.KYUREM) {
|
||||
return "battle_legendary_kyurem";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.XERNEAS || pokemon.species.speciesId === Species.YVELTAL || pokemon.species.speciesId === Species.ZYGARDE) {
|
||||
return "battle_legendary_xern_yvel";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.TAPU_KOKO || pokemon.species.speciesId === Species.TAPU_LELE || pokemon.species.speciesId === Species.TAPU_BULU || pokemon.species.speciesId === Species.TAPU_FINI) {
|
||||
return "battle_legendary_tapu";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.COSMOG || pokemon.species.speciesId === Species.COSMOEM || pokemon.species.speciesId === Species.SOLGALEO || pokemon.species.speciesId === Species.LUNALA || pokemon.species.speciesId === Species.NECROZMA) {
|
||||
return "battle_legendary_sol_lun";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.NIHILEGO || pokemon.species.speciesId === Species.BUZZWOLE || pokemon.species.speciesId === Species.PHEROMOSA || pokemon.species.speciesId === Species.XURKITREE || pokemon.species.speciesId === Species.CELESTEELA || pokemon.species.speciesId === Species.KARTANA || pokemon.species.speciesId === Species.GUZZLORD || pokemon.species.speciesId === Species.POIPOLE || pokemon.species.speciesId === Species.NAGANADEL || pokemon.species.speciesId === Species.STAKATAKA || pokemon.species.speciesId === Species.BLACEPHALON) {
|
||||
return "battle_legendary_ub";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.ZACIAN || pokemon.species.speciesId === Species.ZAMAZENTA) {
|
||||
return "battle_legendary_zac_zam";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.GLASTRIER || pokemon.species.speciesId === Species.SPECTRIER) {
|
||||
return "battle_legendary_glas_spec";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.CALYREX) {
|
||||
return "battle_legendary_calyrex";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.GALAR_ARTICUNO || pokemon.species.speciesId === Species.GALAR_ZAPDOS || pokemon.species.speciesId === Species.GALAR_MOLTRES) {
|
||||
return "battle_legendary_birds_galar";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.WO_CHIEN || pokemon.species.speciesId === Species.CHIEN_PAO || pokemon.species.speciesId === Species.TING_LU || pokemon.species.speciesId === Species.CHI_YU) {
|
||||
return "battle_legendary_ruinous";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.OKIDOGI || pokemon.species.speciesId === Species.MUNKIDORI || pokemon.species.speciesId === Species.FEZANDIPITI) {
|
||||
return "battle_legendary_loyal_three";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.OGERPON) {
|
||||
return "battle_legendary_ogerpon";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.TERAPAGOS) {
|
||||
return "battle_legendary_terapagos";
|
||||
}
|
||||
if (pokemon.species.speciesId === Species.PECHARUNT) {
|
||||
return "battle_legendary_pecharunt";
|
||||
}
|
||||
if (pokemon.species.legendary) {
|
||||
return "battle_legendary_res_zek";
|
||||
}
|
||||
return "battle_legendary_unova";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,11 +420,11 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[]): Get
|
||||
};
|
||||
}
|
||||
|
||||
interface FixedBattleConfigs {
|
||||
export interface FixedBattleConfigs {
|
||||
[key: integer]: FixedBattleConfig
|
||||
}
|
||||
|
||||
export const fixedBattles: FixedBattleConfigs = {
|
||||
export const classicFixedBattles: FixedBattleConfigs = {
|
||||
[5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
[8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
|
@ -235,10 +235,10 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: PokemonMove) => boolean;
|
||||
type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: Move) => boolean;
|
||||
|
||||
export class PreDefendAbAttr extends AbAttr {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -252,7 +252,7 @@ export class PreDefendFormChangeAbAttr extends PreDefendAbAttr {
|
||||
this.formFunc = formFunc;
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const formIndex = this.formFunc(pokemon);
|
||||
if (formIndex !== pokemon.formIndex) {
|
||||
pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
|
||||
@ -263,7 +263,7 @@ export class PreDefendFormChangeAbAttr extends PreDefendAbAttr {
|
||||
}
|
||||
}
|
||||
export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (pokemon.hp === pokemon.getMaxHp() &&
|
||||
pokemon.getMaxHp() > 1 && //Checks if pokemon has wonder_guard (which forces 1hp)
|
||||
(args[0] as Utils.NumberHolder).value >= pokemon.hp) { //Damage >= hp
|
||||
@ -308,8 +308,8 @@ export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr {
|
||||
this.powerMultiplier = powerMultiplier;
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move.getMove())) {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
(args[0] as Utils.NumberHolder).value *= this.powerMultiplier;
|
||||
return true;
|
||||
}
|
||||
@ -329,8 +329,8 @@ export class PreDefendMovePowerToOneAbAttr extends ReceivedMoveDamageMultiplierA
|
||||
super(condition, 1);
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move.getMove())) {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
(args[0] as Utils.NumberHolder).value = 1;
|
||||
return true;
|
||||
}
|
||||
@ -339,6 +339,12 @@ export class PreDefendMovePowerToOneAbAttr extends ReceivedMoveDamageMultiplierA
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a Pokemon is immune to a move because of an ability.
|
||||
* @extends PreDefendAbAttr
|
||||
* @see {@linkcode applyPreDefend}
|
||||
* @see {@linkcode getCondition}
|
||||
*/
|
||||
export class TypeImmunityAbAttr extends PreDefendAbAttr {
|
||||
private immuneType: Type;
|
||||
private condition: AbAttrCondition;
|
||||
@ -350,8 +356,17 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if ((move.getMove() instanceof AttackMove || move.getMove().getAttrs(StatusMoveTypeImmunityAttr).find(attr => attr.immuneType === this.immuneType)) && move.getMove().type === this.immuneType) {
|
||||
/**
|
||||
* @param pokemon {@linkcode Pokemon} the defending Pokemon
|
||||
* @param passive N/A
|
||||
* @param attacker {@linkcode Pokemon} the attacking Pokemon
|
||||
* @param move {@linkcode Move} the attacking move
|
||||
* @param cancelled N/A
|
||||
* @param args [0] {@linkcode Utils.NumberHolder} gets set to 0 if move is immuned by an ability.
|
||||
* @param args [1] {@linkcode Utils.NumberHolder} type of move being defended against in case it has changed from default type
|
||||
*/
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if ((move instanceof AttackMove || move.getAttrs(StatusMoveTypeImmunityAttr).find(attr => attr.immuneType === this.immuneType)) && move.type === this.immuneType) {
|
||||
(args[0] as Utils.NumberHolder).value = 0;
|
||||
return true;
|
||||
}
|
||||
@ -369,7 +384,7 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr {
|
||||
super(immuneType);
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args);
|
||||
|
||||
if (ret) {
|
||||
@ -399,7 +414,7 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr {
|
||||
this.levels = levels;
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args);
|
||||
|
||||
if (ret) {
|
||||
@ -425,7 +440,7 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr {
|
||||
this.turnCount = turnCount;
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args);
|
||||
|
||||
if (ret) {
|
||||
@ -445,8 +460,8 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr {
|
||||
super(null, condition);
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, attacker) < 2) {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (move instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.type, attacker) < 2) {
|
||||
cancelled.value = true;
|
||||
(args[0] as Utils.NumberHolder).value = 0;
|
||||
return true;
|
||||
@ -461,15 +476,15 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr {
|
||||
}
|
||||
|
||||
export class PostDefendAbAttr extends AbAttr {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class PostDefendDisguiseAbAttr extends PostDefendAbAttr {
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (pokemon.formIndex === 0 && pokemon.battleData.hitCount !== 0 && (move.getMove().category === MoveCategory.SPECIAL || move.getMove().category === MoveCategory.PHYSICAL)) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (pokemon.formIndex === 0 && pokemon.battleData.hitCount !== 0 && (move.category === MoveCategory.SPECIAL || move.category === MoveCategory.PHYSICAL)) {
|
||||
|
||||
const recoilDamage = Math.ceil((pokemon.getMaxHp() / 8) - attacker.turnData.damageDealt);
|
||||
if (!recoilDamage) {
|
||||
@ -494,7 +509,7 @@ export class PostDefendFormChangeAbAttr extends PostDefendAbAttr {
|
||||
this.formFunc = formFunc;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
const formIndex = this.formFunc(pokemon);
|
||||
if (formIndex !== pokemon.formIndex) {
|
||||
pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
|
||||
@ -506,16 +521,16 @@ export class PostDefendFormChangeAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const attackPriority = new Utils.IntegerHolder(move.getMove().priority);
|
||||
applyMoveAttrs(IncrementMovePriorityAttr,attacker,null,move.getMove(),attackPriority);
|
||||
applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move.getMove(), attackPriority);
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const attackPriority = new Utils.IntegerHolder(move.priority);
|
||||
applyMoveAttrs(IncrementMovePriorityAttr,attacker,null,move,attackPriority);
|
||||
applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move, attackPriority);
|
||||
|
||||
if (move.getMove().moveTarget===MoveTarget.USER || move.getMove().moveTarget===MoveTarget.NEAR_ALLY) {
|
||||
if (move.moveTarget===MoveTarget.USER || move.moveTarget===MoveTarget.NEAR_ALLY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (attackPriority.value > 0 && !move.getMove().isMultiTarget()) {
|
||||
if (attackPriority.value > 0 && !move.isMultiTarget()) {
|
||||
cancelled.value = true;
|
||||
return true;
|
||||
}
|
||||
@ -539,7 +554,7 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr {
|
||||
this.immuneCondition = immuneCondition;
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.immuneCondition(pokemon, attacker, move)) {
|
||||
cancelled.value = true;
|
||||
return true;
|
||||
@ -563,7 +578,7 @@ export class MoveImmunityStatChangeAbAttr extends MoveImmunityAbAttr {
|
||||
this.levels = levels;
|
||||
}
|
||||
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args);
|
||||
if (ret) {
|
||||
const simulated = args.length > 1 && args[1];
|
||||
@ -593,8 +608,8 @@ export class ReverseDrainAbAttr extends PostDefendAbAttr {
|
||||
* @args N/A
|
||||
* @returns true if healing should be reversed on a healing move, false otherwise.
|
||||
*/
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.getMove().hasAttr(HitHealAttr)) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.hasAttr(HitHealAttr)) {
|
||||
pokemon.scene.queueMessage(getPokemonMessage(attacker, " sucked up the liquid ooze!"));
|
||||
return true;
|
||||
}
|
||||
@ -619,8 +634,8 @@ export class PostDefendStatChangeAbAttr extends PostDefendAbAttr {
|
||||
this.allOthers = allOthers;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move.getMove())) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
if (this.allOthers) {
|
||||
const otherPokemon = pokemon.getAlly() ? pokemon.getOpponents().concat([ pokemon.getAlly() ]) : pokemon.getOpponents();
|
||||
for (const other of otherPokemon) {
|
||||
@ -653,10 +668,10 @@ export class PostDefendHpGatedStatChangeAbAttr extends PostDefendAbAttr {
|
||||
this.selfTarget = selfTarget;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
const hpGateFlat: integer = Math.ceil(pokemon.getMaxHp() * this.hpGate);
|
||||
const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1];
|
||||
if (this.condition(pokemon, attacker, move.getMove()) && (pokemon.hp <= hpGateFlat && (pokemon.hp + lastAttackReceived.damage) > hpGateFlat)) {
|
||||
if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + lastAttackReceived.damage) > hpGateFlat)) {
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.levels));
|
||||
return true;
|
||||
}
|
||||
@ -676,8 +691,8 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr {
|
||||
this.tagType = tagType;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move.getMove())) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
const tag = pokemon.scene.arena.getTag(this.tagType) as ArenaTrapTag;
|
||||
if (!pokemon.scene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers) {
|
||||
pokemon.scene.arena.addTag(this.tagType, 0, undefined, pokemon.id, pokemon.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER);
|
||||
@ -698,11 +713,11 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
|
||||
this.tagType = tagType;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move.getMove())) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move)) {
|
||||
if (!pokemon.getTag(this.tagType)) {
|
||||
pokemon.addTag(this.tagType, undefined, undefined, pokemon.id);
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.getName() }));
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.name }));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -711,9 +726,9 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (hitResult < HitResult.NO_EFFECT) {
|
||||
const type = move.getMove().type;
|
||||
const type = move.type;
|
||||
const pokemonTypes = pokemon.getTypes(true);
|
||||
if (pokemonTypes.length !== 1 || pokemonTypes[0] !== type) {
|
||||
pokemon.summonData.types = [ type ];
|
||||
@ -738,7 +753,7 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr {
|
||||
this.terrainType = terrainType;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (hitResult < HitResult.NO_EFFECT) {
|
||||
return pokemon.scene.arena.trySetTerrain(this.terrainType, true);
|
||||
}
|
||||
@ -758,8 +773,8 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr {
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) {
|
||||
const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)];
|
||||
return attacker.trySetStatus(effect, true, pokemon);
|
||||
}
|
||||
@ -773,7 +788,7 @@ export class EffectSporeAbAttr extends PostDefendContactApplyStatusEffectAbAttr
|
||||
super(10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP);
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (attacker.hasAbility(Abilities.OVERCOAT) || attacker.isOfType(Type.GRASS)) {
|
||||
return false;
|
||||
}
|
||||
@ -794,9 +809,9 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr {
|
||||
this.turnCount = turnCount;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) {
|
||||
return attacker.addTag(this.tagType, this.turnCount, move.moveId, attacker.id);
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) {
|
||||
return attacker.addTag(this.tagType, this.turnCount, move.id, attacker.id);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -814,7 +829,7 @@ export class PostDefendCritStatChangeAbAttr extends PostDefendAbAttr {
|
||||
this.levels = levels;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels));
|
||||
|
||||
return true;
|
||||
@ -834,8 +849,8 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr {
|
||||
this.damageRatio = damageRatio;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
||||
attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER);
|
||||
attacker.turnData.damageTaken += Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio));
|
||||
return true;
|
||||
@ -864,8 +879,8 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr {
|
||||
this.turns = turns;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
||||
if (pokemon.getTag(BattlerTagType.PERISH_SONG) || attacker.getTag(BattlerTagType.PERISH_SONG)) {
|
||||
return false;
|
||||
} else {
|
||||
@ -891,7 +906,7 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr {
|
||||
this.weatherType = weatherType;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (!pokemon.scene.arena.weather?.isImmutable()) {
|
||||
return pokemon.scene.arena.trySetWeather(this.weatherType, true);
|
||||
}
|
||||
@ -905,8 +920,8 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr {
|
||||
super();
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) {
|
||||
const tempAbilityId = attacker.getAbility().id;
|
||||
attacker.summonData.ability = pokemon.getAbility().id;
|
||||
pokemon.summonData.ability = tempAbilityId;
|
||||
@ -929,8 +944,8 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr {
|
||||
this.ability = ability;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) {
|
||||
attacker.summonData.ability = this.ability;
|
||||
|
||||
return true;
|
||||
@ -947,7 +962,7 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr {
|
||||
export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr {
|
||||
private chance: integer;
|
||||
private attacker: Pokemon;
|
||||
private move: PokemonMove;
|
||||
private move: Move;
|
||||
|
||||
constructor(chance: integer) {
|
||||
super();
|
||||
@ -955,13 +970,13 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr {
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (!attacker.summonData.disabledMove) {
|
||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !attacker.isMax()) {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !attacker.isMax()) {
|
||||
this.attacker = attacker;
|
||||
this.move = move;
|
||||
|
||||
attacker.summonData.disabledMove = move.moveId;
|
||||
attacker.summonData.disabledMove = move.id;
|
||||
attacker.summonData.disabledTurns = 4;
|
||||
return true;
|
||||
}
|
||||
@ -970,7 +985,7 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return getPokemonMessage(this.attacker, `'s ${this.move.getName()}\nwas disabled!`);
|
||||
return getPokemonMessage(this.attacker, `'s ${this.move.name}\nwas disabled!`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -998,49 +1013,18 @@ export class PostStatChangeStatChangeAbAttr extends PostStatChangeAbAttr {
|
||||
}
|
||||
|
||||
export class PreAttackAbAttr extends AbAttr {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise<boolean> {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean | Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class VariableMovePowerAbAttr extends PreAttackAbAttr {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
|
||||
//const power = args[0] as Utils.NumberHolder;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class VariableMoveTypeAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
//const power = args[0] as Utils.IntegerHolder;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveTypeChangePowerMultiplierAbAttr extends VariableMoveTypeAbAttr {
|
||||
private matchType: Type;
|
||||
private newType: Type;
|
||||
private powerMultiplier: number;
|
||||
|
||||
constructor(matchType: Type, newType: Type, powerMultiplier: number) {
|
||||
super(true);
|
||||
this.matchType = matchType;
|
||||
this.newType = newType;
|
||||
this.powerMultiplier = powerMultiplier;
|
||||
}
|
||||
|
||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
if (type.value === this.matchType) {
|
||||
type.value = this.newType;
|
||||
(args[1] as Utils.NumberHolder).value *= this.powerMultiplier;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class FieldPreventExplosiveMovesAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
|
||||
cancelled.value = true;
|
||||
@ -1060,11 +1044,10 @@ export class MoveTypeChangeAttr extends PreAttackAbAttr {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
|
||||
if (this.condition(pokemon, defender, move.getMove())) {
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
type.value = this.newType;
|
||||
(args[1] as Utils.NumberHolder).value *= this.powerMultiplier;
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (this.condition(pokemon, defender, move)) {
|
||||
move.type = this.newType;
|
||||
(args[0] as Utils.NumberHolder).value *= this.powerMultiplier;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1097,8 +1080,8 @@ export class DamageBoostAbAttr extends PreAttackAbAttr {
|
||||
* @param args Utils.NumberHolder as damage
|
||||
* @returns true if the function succeeds
|
||||
*/
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
|
||||
if (this.condition(pokemon, defender, move.getMove())) {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (this.condition(pokemon, defender, move)) {
|
||||
const power = args[0] as Utils.NumberHolder;
|
||||
power.value = Math.floor(power.value * this.damageMultiplier);
|
||||
return true;
|
||||
@ -1118,8 +1101,8 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr {
|
||||
this.powerMultiplier = powerMultiplier;
|
||||
}
|
||||
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
|
||||
if (this.condition(pokemon, defender, move.getMove())) {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (this.condition(pokemon, defender, move)) {
|
||||
(args[0] as Utils.NumberHolder).value *= this.powerMultiplier;
|
||||
|
||||
return true;
|
||||
@ -1165,8 +1148,8 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
|
||||
const multiplier = this.mult(pokemon, defender, move.getMove());
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move, args: any[]): boolean {
|
||||
const multiplier = this.mult(pokemon, defender, move);
|
||||
if (multiplier !== 1) {
|
||||
(args[0] as Utils.NumberHolder).value *= multiplier;
|
||||
return true;
|
||||
@ -1177,7 +1160,7 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr {
|
||||
}
|
||||
|
||||
export class FieldVariableMovePowerAbAttr extends AbAttr {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
|
||||
//const power = args[0] as Utils.NumberHolder;
|
||||
return false;
|
||||
}
|
||||
@ -1193,8 +1176,8 @@ export class FieldMovePowerBoostAbAttr extends FieldVariableMovePowerAbAttr {
|
||||
this.powerMultiplier = powerMultiplier;
|
||||
}
|
||||
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
|
||||
if (this.condition(pokemon, defender, move.getMove())) {
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (this.condition(pokemon, defender, move)) {
|
||||
(args[0] as Utils.NumberHolder).value *= this.powerMultiplier;
|
||||
|
||||
return true;
|
||||
@ -1235,7 +1218,7 @@ export class BattleStatMultiplierAbAttr extends AbAttr {
|
||||
}
|
||||
|
||||
export class PostAttackAbAttr extends AbAttr {
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1249,9 +1232,9 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, defender, move.getMove()))) {
|
||||
if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, defender, move))) {
|
||||
const heldItems = this.getTargetHeldItems(defender).filter(i => i.getTransferrable(false));
|
||||
if (heldItems.length) {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
@ -1287,8 +1270,8 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr {
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (pokemon !== attacker && (!this.contactRequired || move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) {
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) {
|
||||
const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)];
|
||||
return attacker.trySetStatus(effect, true, pokemon);
|
||||
}
|
||||
@ -1305,11 +1288,11 @@ export class PostAttackContactApplyStatusEffectAbAttr extends PostAttackApplySta
|
||||
|
||||
export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr {
|
||||
private contactRequired: boolean;
|
||||
private chance: (user: Pokemon, target: Pokemon, move: PokemonMove) => integer;
|
||||
private chance: (user: Pokemon, target: Pokemon, move: Move) => integer;
|
||||
private effects: BattlerTagType[];
|
||||
|
||||
|
||||
constructor(contactRequired: boolean, chance: (user: Pokemon, target: Pokemon, move: PokemonMove) => integer, ...effects: BattlerTagType[]) {
|
||||
constructor(contactRequired: boolean, chance: (user: Pokemon, target: Pokemon, move: Move) => integer, ...effects: BattlerTagType[]) {
|
||||
super();
|
||||
|
||||
this.contactRequired = contactRequired;
|
||||
@ -1317,8 +1300,8 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr {
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (pokemon !== attacker && (!this.contactRequired || move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status) {
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status) {
|
||||
const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)];
|
||||
|
||||
|
||||
@ -1338,9 +1321,9 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move.getMove()))) {
|
||||
if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) {
|
||||
const heldItems = this.getTargetHeldItems(attacker).filter(i => i.getTransferrable(false));
|
||||
if (heldItems.length) {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
@ -1693,7 +1676,6 @@ export class DownloadAbAttr extends PostSummonAbAttr {
|
||||
this.enemySpDef = 0;
|
||||
this.enemyCountTally = 0;
|
||||
|
||||
if (pokemon.getOpponents()[0].summonData !== undefined) {
|
||||
for (const opponent of pokemon.getOpponents()) {
|
||||
this.enemyCountTally++;
|
||||
this.enemyDef += opponent.getBattleStat(Stat.DEF);
|
||||
@ -1701,7 +1683,6 @@ export class DownloadAbAttr extends PostSummonAbAttr {
|
||||
}
|
||||
this.enemyDef = Math.round(this.enemyDef / this.enemyCountTally);
|
||||
this.enemySpDef = Math.round(this.enemySpDef / this.enemyCountTally);
|
||||
}
|
||||
|
||||
if (this.enemyDef < this.enemySpDef) {
|
||||
this.stats = [BattleStat.ATK];
|
||||
@ -1728,7 +1709,9 @@ export class PostSummonWeatherChangeAbAttr extends PostSummonAbAttr {
|
||||
}
|
||||
|
||||
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||
if (!pokemon.scene.arena.weather?.isImmutable()) {
|
||||
if ((this.weatherType === WeatherType.HEAVY_RAIN ||
|
||||
this.weatherType === WeatherType.HARSH_SUN ||
|
||||
this.weatherType === WeatherType.STRONG_WINDS) || !pokemon.scene.arena.weather?.isImmutable()) {
|
||||
return pokemon.scene.arena.trySetWeather(this.weatherType, true);
|
||||
}
|
||||
|
||||
@ -1856,6 +1839,52 @@ export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears Desolate Land/Primordial Sea/Delta Stream upon the Pokemon switching out.
|
||||
*/
|
||||
export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr {
|
||||
|
||||
/**
|
||||
* @param pokemon The {@linkcode Pokemon} with the ability
|
||||
* @param passive N/A
|
||||
* @param args N/A
|
||||
* @returns {boolean} Returns true if the weather clears, otherwise false.
|
||||
*/
|
||||
applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
|
||||
const weatherType = pokemon.scene.arena.weather.weatherType;
|
||||
let turnOffWeather = false;
|
||||
|
||||
// Clear weather only if user's ability matches the weather and no other pokemon has the ability.
|
||||
switch (weatherType) {
|
||||
case (WeatherType.HARSH_SUN):
|
||||
if (pokemon.hasAbility(Abilities.DESOLATE_LAND)
|
||||
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.HEAVY_RAIN):
|
||||
if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA)
|
||||
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.STRONG_WINDS):
|
||||
if (pokemon.hasAbility(Abilities.DELTA_STREAM)
|
||||
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (turnOffWeather) {
|
||||
pokemon.scene.arena.trySetWeather(WeatherType.NONE, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr {
|
||||
applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
|
||||
if (pokemon.getHpRatio() < 1 ) {
|
||||
@ -1956,9 +1985,9 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr {
|
||||
* @param args [0] {@linkcode StatusEffect} applied by move
|
||||
* @returns true if defender is confused
|
||||
*/
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.effects.indexOf(args[0]) > -1 && !defender.isFainted()) {
|
||||
return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedInt(3,2), move.moveId, defender.id);
|
||||
return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedInt(3,2), move.id, defender.id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -2216,7 +2245,7 @@ function getAnticipationCondition(): AbAttrCondition {
|
||||
for (const opponent of pokemon.getOpponents()) {
|
||||
for (const move of opponent.moveset) {
|
||||
// move is super effective
|
||||
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent) >= 2) {
|
||||
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent, true) >= 2) {
|
||||
return true;
|
||||
}
|
||||
// move is a OHKO
|
||||
@ -2561,7 +2590,7 @@ export class PostTurnLootAbAttr extends PostTurnAbAttr {
|
||||
|
||||
if (!berryModifier) {
|
||||
pokemon.scene.addModifier(new BerryModifier(chosenBerry, pokemon.id, chosenBerryType, 1));
|
||||
} else {
|
||||
} else if (berryModifier.stackCount < berryModifier.getMaxHeldItemCount(pokemon)) {
|
||||
berryModifier.stackCount++;
|
||||
}
|
||||
|
||||
@ -2920,6 +2949,7 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr {
|
||||
/**
|
||||
* Checks if enemy Pokemon is trapped by an Arena Trap-esque ability
|
||||
* If the enemy is a Ghost type, it is not trapped
|
||||
* If the enemy has the ability Run Away, it is not trapped.
|
||||
* If the user has Magnet Pull and the enemy is not a Steel type, it is not trapped.
|
||||
* If the user has Arena Trap and the enemy is not grounded, it is not trapped.
|
||||
* @param pokemon The {@link Pokemon} with this {@link AbAttr}
|
||||
@ -2934,6 +2964,9 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr {
|
||||
if (otherPokemon.getTypes(true).includes(Type.GHOST) || (otherPokemon.getTypes(true).includes(Type.STELLAR) && otherPokemon.getTypes().includes(Type.GHOST))) {
|
||||
trapped.value = false;
|
||||
return false;
|
||||
} else if (otherPokemon.hasAbility(Abilities.RUN_AWAY)) {
|
||||
trapped.value = false;
|
||||
return false;
|
||||
}
|
||||
trapped.value = true;
|
||||
return true;
|
||||
@ -2982,7 +3015,56 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr {
|
||||
}
|
||||
|
||||
export class PostFaintAbAttr extends AbAttr {
|
||||
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears Desolate Land/Primordial Sea/Delta Stream upon the Pokemon fainting
|
||||
*/
|
||||
export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr {
|
||||
|
||||
/**
|
||||
* @param pokemon The {@linkcode Pokemon} with the ability
|
||||
* @param passive N/A
|
||||
* @param attacker N/A
|
||||
* @param move N/A
|
||||
* @param hitResult N/A
|
||||
* @param args N/A
|
||||
* @returns {boolean} Returns true if the weather clears, otherwise false.
|
||||
*/
|
||||
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
const weatherType = pokemon.scene.arena.weather.weatherType;
|
||||
let turnOffWeather = false;
|
||||
|
||||
// Clear weather only if user's ability matches the weather and no other pokemon has the ability.
|
||||
switch (weatherType) {
|
||||
case (WeatherType.HARSH_SUN):
|
||||
if (pokemon.hasAbility(Abilities.DESOLATE_LAND)
|
||||
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.HEAVY_RAIN):
|
||||
if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA)
|
||||
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.STRONG_WINDS):
|
||||
if (pokemon.hasAbility(Abilities.DELTA_STREAM)
|
||||
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (turnOffWeather) {
|
||||
pokemon.scene.arena.trySetWeather(WeatherType.NONE, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -2996,8 +3078,8 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
|
||||
this.damageRatio = damageRatio;
|
||||
}
|
||||
|
||||
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
||||
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
pokemon.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled));
|
||||
if (cancelled.value) {
|
||||
@ -3024,7 +3106,7 @@ export class PostFaintHPDamageAbAttr extends PostFaintAbAttr {
|
||||
super ();
|
||||
}
|
||||
|
||||
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
const damage = pokemon.turnData.attacksReceived[0].damage;
|
||||
attacker.damageAndUpdate((damage), HitResult.OTHER);
|
||||
attacker.turnData.damageTaken += damage;
|
||||
@ -3361,7 +3443,7 @@ export class IceFaceMoveImmunityAbAttr extends MoveImmunityAbAttr {
|
||||
* @param {any[]} args - Additional arguments.
|
||||
* @returns {boolean} - Whether the immunity was applied.
|
||||
*/
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const isImmune = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args);
|
||||
|
||||
if (isImmune) {
|
||||
@ -3471,13 +3553,13 @@ export function applyPostBattleInitAbAttrs(attrType: { new(...args: any[]): Post
|
||||
}
|
||||
|
||||
export function applyPreDefendAbAttrs(attrType: { new(...args: any[]): PreDefendAbAttr },
|
||||
pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
|
||||
pokemon: Pokemon, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
|
||||
const simulated = args.length > 1 && args[1];
|
||||
return applyAbAttrsInternal<PreDefendAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreDefend(pokemon, passive, attacker, move, cancelled, args), args, false, false, simulated);
|
||||
}
|
||||
|
||||
export function applyPostDefendAbAttrs(attrType: { new(...args: any[]): PostDefendAbAttr },
|
||||
pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise<void> {
|
||||
pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise<void> {
|
||||
return applyAbAttrsInternal<PostDefendAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostDefend(pokemon, passive, attacker, move, hitResult, args), args);
|
||||
}
|
||||
|
||||
@ -3492,12 +3574,12 @@ export function applyBattleStatMultiplierAbAttrs(attrType: { new(...args: any[])
|
||||
}
|
||||
|
||||
export function applyPreAttackAbAttrs(attrType: { new(...args: any[]): PreAttackAbAttr },
|
||||
pokemon: Pokemon, defender: Pokemon, move: PokemonMove, ...args: any[]): Promise<void> {
|
||||
pokemon: Pokemon, defender: Pokemon, move: Move, ...args: any[]): Promise<void> {
|
||||
return applyAbAttrsInternal<PreAttackAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, defender, move, args), args);
|
||||
}
|
||||
|
||||
export function applyPostAttackAbAttrs(attrType: { new(...args: any[]): PostAttackAbAttr },
|
||||
pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise<void> {
|
||||
pokemon: Pokemon, defender: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise<void> {
|
||||
return applyAbAttrsInternal<PostAttackAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, defender, move, hitResult, args), args);
|
||||
}
|
||||
|
||||
@ -3578,7 +3660,7 @@ export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBatt
|
||||
}
|
||||
|
||||
export function applyPostFaintAbAttrs(attrType: { new(...args: any[]): PostFaintAbAttr },
|
||||
pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise<void> {
|
||||
pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise<void> {
|
||||
return applyAbAttrsInternal<PostFaintAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, attacker, move, hitResult, args), args);
|
||||
}
|
||||
|
||||
@ -3597,7 +3679,7 @@ export const allAbilities = [ new Ability(Abilities.NONE, 3) ];
|
||||
export function initAbilities() {
|
||||
allAbilities.push(
|
||||
new Ability(Abilities.STENCH, 3)
|
||||
.attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => (move.getMove().category !== MoveCategory.STATUS && !move.getMove().hasAttr(FlinchAttr)) ? 10 : 0, BattlerTagType.FLINCHED),
|
||||
.attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => (move.category !== MoveCategory.STATUS && !move.hasAttr(FlinchAttr)) ? 10 : 0, BattlerTagType.FLINCHED),
|
||||
new Ability(Abilities.DRIZZLE, 3)
|
||||
.attr(PostSummonWeatherChangeAbAttr, WeatherType.RAIN)
|
||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.RAIN),
|
||||
@ -3734,7 +3816,7 @@ export function initAbilities() {
|
||||
return false;
|
||||
}),
|
||||
new Ability(Abilities.SOUNDPROOF, 3)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.SOUND_BASED))
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.SOUND_BASED))
|
||||
.ignorable(),
|
||||
new Ability(Abilities.RAIN_DISH, 3)
|
||||
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.RAIN, WeatherType.HEAVY_RAIN)
|
||||
@ -4020,13 +4102,13 @@ export function initAbilities() {
|
||||
)
|
||||
.partial(),
|
||||
new Ability(Abilities.TELEPATHY, 5)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move.getMove() instanceof AttackMove)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move instanceof AttackMove)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.MOODY, 5)
|
||||
.attr(MoodyAbAttr),
|
||||
new Ability(Abilities.OVERCOAT, 5)
|
||||
.attr(BlockWeatherDamageAttr)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.POWDER_MOVE))
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.POWDER_MOVE))
|
||||
.ignorable(),
|
||||
new Ability(Abilities.POISON_TOUCH, 5)
|
||||
.attr(PostAttackContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON),
|
||||
@ -4115,14 +4197,14 @@ export function initAbilities() {
|
||||
new Ability(Abilities.MAGICIAN, 6)
|
||||
.attr(PostAttackStealHeldItemAbAttr),
|
||||
new Ability(Abilities.BULLETPROOF, 6)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.BALLBOMB_MOVE))
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.BALLBOMB_MOVE))
|
||||
.ignorable(),
|
||||
new Ability(Abilities.COMPETITIVE, 6)
|
||||
.attr(PostStatChangeStatChangeAbAttr, (target, statsChanged, levels) => levels < 0, [BattleStat.SPATK], 2),
|
||||
new Ability(Abilities.STRONG_JAW, 6)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.BITING_MOVE), 1.5),
|
||||
new Ability(Abilities.REFRIGERATE, 6)
|
||||
.attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ICE, 1.2),
|
||||
.attr(MoveTypeChangeAttr, Type.ICE, 1.2, (user, target, move) => move.type === Type.NORMAL),
|
||||
new Ability(Abilities.SWEET_VEIL, 6)
|
||||
.attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP)
|
||||
.attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY)
|
||||
@ -4145,11 +4227,11 @@ export function initAbilities() {
|
||||
new Ability(Abilities.TOUGH_CLAWS, 6)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 1.3),
|
||||
new Ability(Abilities.PIXILATE, 6)
|
||||
.attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.FAIRY, 1.2),
|
||||
.attr(MoveTypeChangeAttr, Type.FAIRY, 1.2, (user, target, move) => move.type === Type.NORMAL),
|
||||
new Ability(Abilities.GOOEY, 6)
|
||||
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), BattleStat.SPD, -1, false),
|
||||
new Ability(Abilities.AERILATE, 6)
|
||||
.attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.FLYING, 1.2),
|
||||
.attr(MoveTypeChangeAttr, Type.FLYING, 1.2, (user, target, move) => move.type === Type.NORMAL),
|
||||
new Ability(Abilities.PARENTAL_BOND, 6)
|
||||
.unimplemented(),
|
||||
new Ability(Abilities.DARK_AURA, 6)
|
||||
@ -4163,13 +4245,22 @@ export function initAbilities() {
|
||||
.unimplemented(),
|
||||
new Ability(Abilities.PRIMORDIAL_SEA, 6)
|
||||
.attr(PostSummonWeatherChangeAbAttr, WeatherType.HEAVY_RAIN)
|
||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HEAVY_RAIN),
|
||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HEAVY_RAIN)
|
||||
.attr(PreSwitchOutClearWeatherAbAttr)
|
||||
.attr(PostFaintClearWeatherAbAttr)
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.DESOLATE_LAND, 6)
|
||||
.attr(PostSummonWeatherChangeAbAttr, WeatherType.HARSH_SUN)
|
||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HARSH_SUN),
|
||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HARSH_SUN)
|
||||
.attr(PreSwitchOutClearWeatherAbAttr)
|
||||
.attr(PostFaintClearWeatherAbAttr)
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.DELTA_STREAM, 6)
|
||||
.attr(PostSummonWeatherChangeAbAttr, WeatherType.STRONG_WINDS)
|
||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.STRONG_WINDS),
|
||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.STRONG_WINDS)
|
||||
.attr(PreSwitchOutClearWeatherAbAttr)
|
||||
.attr(PostFaintClearWeatherAbAttr)
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.STAMINA, 7)
|
||||
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattleStat.DEF, 1),
|
||||
new Ability(Abilities.WIMP_OUT, 7)
|
||||
@ -4210,7 +4301,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.TRIAGE, 7)
|
||||
.attr(IncrementMovePriorityAbAttr, (pokemon, move) => move.hasFlag(MoveFlags.TRIAGE_MOVE), 3),
|
||||
new Ability(Abilities.GALVANIZE, 7)
|
||||
.attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ELECTRIC, 1.2),
|
||||
.attr(MoveTypeChangeAttr, Type.ELECTRIC, 1.2, (user, target, move) => move.type === Type.NORMAL),
|
||||
new Ability(Abilities.SURGE_SURFER, 7)
|
||||
.conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), BattleStatMultiplierAbAttr, BattleStat.SPD, 2),
|
||||
new Ability(Abilities.SCHOOLING, 7)
|
||||
@ -4378,7 +4469,7 @@ export function initAbilities() {
|
||||
.conditionalAttr(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW), PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0)
|
||||
// When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE
|
||||
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW)
|
||||
.attr(IceFaceMoveImmunityAbAttr, (target, user, move) => move.getMove().category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE))
|
||||
.attr(IceFaceMoveImmunityAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE))
|
||||
.ignorable(),
|
||||
new Ability(Abilities.POWER_SPOT, 8)
|
||||
.unimplemented(),
|
||||
@ -4463,7 +4554,7 @@ export function initAbilities() {
|
||||
.attr(TypeImmunityStatChangeAbAttr, Type.FIRE, BattleStat.DEF, 2)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.WIND_RIDER, 9)
|
||||
.attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE) && move.getMove().category !== MoveCategory.STATUS, BattleStat.ATK, 1)
|
||||
.attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.WIND_MOVE) && move.category !== MoveCategory.STATUS, BattleStat.ATK, 1)
|
||||
.attr(PostSummonStatChangeOnArenaAbAttr, ArenaTagType.TAILWIND)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.GUARD_DOG, 9)
|
||||
@ -4503,7 +4594,7 @@ export function initAbilities() {
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages
|
||||
new Ability(Abilities.GOOD_AS_GOLD, 9)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().category === MoveCategory.STATUS)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS)
|
||||
.ignorable()
|
||||
.partial(),
|
||||
new Ability(Abilities.VESSEL_OF_RUIN, 9)
|
||||
|
@ -29,6 +29,7 @@ export abstract class ArenaTag {
|
||||
public sourceId: integer;
|
||||
public side: ArenaTagSide;
|
||||
|
||||
|
||||
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId?: integer, side: ArenaTagSide = ArenaTagSide.BOTH) {
|
||||
this.tagType = tagType;
|
||||
this.turnCount = turnCount;
|
||||
@ -41,11 +42,13 @@ export abstract class ArenaTag {
|
||||
return true;
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void { }
|
||||
onAdd(arena: Arena, quiet: boolean = false): void { }
|
||||
|
||||
onRemove(arena: Arena): void {
|
||||
onRemove(arena: Arena, quiet: boolean = false): void {
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`${this.getMoveName()}\'s effect wore off${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`);
|
||||
}
|
||||
}
|
||||
|
||||
onOverlap(arena: Arena): void { }
|
||||
|
||||
@ -65,12 +68,14 @@ export class MistTag extends ArenaTag {
|
||||
super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
super.onAdd(arena);
|
||||
|
||||
const source = arena.scene.getPokemonById(this.sourceId);
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(getPokemonMessage(source, "'s team became\nshrouded in mist!"));
|
||||
}
|
||||
}
|
||||
|
||||
apply(arena: Arena, args: any[]): boolean {
|
||||
(args[0] as Utils.BooleanHolder).value = true;
|
||||
@ -113,10 +118,12 @@ class ReflectTag extends WeakenMoveScreenTag {
|
||||
return false;
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`Reflect reduced the damage of physical moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LightScreenTag extends WeakenMoveScreenTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
@ -135,20 +142,24 @@ class LightScreenTag extends WeakenMoveScreenTag {
|
||||
return false;
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`Light Screen reduced the damage of special moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AuroraVeilTag extends WeakenMoveScreenTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`Aurora Veil reduced the damage of moves${this.side === ArenaTagSide.PLAYER ? "\non your side" : this.side === ArenaTagSide.ENEMY ? "\non the foe's side" : ""}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ProtectConditionFunc = (...args: any[]) => boolean;
|
||||
|
||||
@ -386,12 +397,14 @@ class SpikesTag extends ArenaTrapTag {
|
||||
super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
super.onAdd(arena);
|
||||
|
||||
const source = arena.scene.getPokemonById(this.sourceId);
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${source.getOpponentDescriptor()}'s feet!`);
|
||||
}
|
||||
}
|
||||
|
||||
activateTrap(pokemon: Pokemon): boolean {
|
||||
if (pokemon.isGrounded()) {
|
||||
@ -423,12 +436,14 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
||||
this.neutralized = false;
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
super.onAdd(arena);
|
||||
|
||||
const source = arena.scene.getPokemonById(this.sourceId);
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${source.getOpponentDescriptor()}'s feet!`);
|
||||
}
|
||||
}
|
||||
|
||||
onRemove(arena: Arena): void {
|
||||
if (!this.neutralized) {
|
||||
@ -493,15 +508,17 @@ class StealthRockTag extends ArenaTrapTag {
|
||||
super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
super.onAdd(arena);
|
||||
|
||||
const source = arena.scene.getPokemonById(this.sourceId);
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`Pointed stones float in the air\naround ${source.getOpponentDescriptor()}!`);
|
||||
}
|
||||
}
|
||||
|
||||
getDamageHpRatio(pokemon: Pokemon): number {
|
||||
const effectiveness = pokemon.getAttackTypeEffectiveness(Type.ROCK);
|
||||
const effectiveness = pokemon.getAttackTypeEffectiveness(Type.ROCK, undefined, true);
|
||||
|
||||
let damageHpRatio: number;
|
||||
|
||||
@ -562,14 +579,16 @@ class StickyWebTag extends ArenaTrapTag {
|
||||
super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
super.onAdd(arena);
|
||||
|
||||
// does not seem to be used anywhere
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const source = arena.scene.getPokemonById(this.sourceId);
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`A ${this.getMoveName()} has been laid out on the ground around the opposing team!`);
|
||||
}
|
||||
}
|
||||
|
||||
activateTrap(pokemon: Pokemon): boolean {
|
||||
if (pokemon.isGrounded()) {
|
||||
@ -626,8 +645,10 @@ class TailwindTag extends ArenaTag {
|
||||
super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? "\nyour" : this.side === ArenaTagSide.ENEMY ? "\nthe opposing" : ""} team!`);
|
||||
}
|
||||
|
||||
const source = arena.scene.getPokemonById(this.sourceId);
|
||||
const party = source.isPlayer() ? source.scene.getPlayerField() : source.scene.getEnemyField();
|
||||
@ -646,10 +667,12 @@ class TailwindTag extends ArenaTag {
|
||||
}
|
||||
}
|
||||
|
||||
onRemove(arena: Arena): void {
|
||||
onRemove(arena: Arena, quiet: boolean = false): void {
|
||||
if (!quiet) {
|
||||
arena.scene.queueMessage(`${this.side === ArenaTagSide.PLAYER ? "Your" : this.side === ArenaTagSide.ENEMY ? "The opposing" : ""} team's Tailwind petered out!`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag {
|
||||
switch (tagType) {
|
||||
|
@ -1691,7 +1691,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||
},
|
||||
[Biome.SEA]: {
|
||||
[BiomePoolTier.COMMON]: [ TrainerType.SWIMMER ],
|
||||
[BiomePoolTier.COMMON]: [ TrainerType.SWIMMER, TrainerType.SAILOR ],
|
||||
[BiomePoolTier.UNCOMMON]: [],
|
||||
[BiomePoolTier.RARE]: [],
|
||||
[BiomePoolTier.SUPER_RARE]: [],
|
||||
@ -1713,7 +1713,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||
},
|
||||
[Biome.BEACH]: {
|
||||
[BiomePoolTier.COMMON]: [ TrainerType.FISHERMAN, TrainerType.PARASOL_LADY ],
|
||||
[BiomePoolTier.COMMON]: [ TrainerType.FISHERMAN, TrainerType.PARASOL_LADY, TrainerType.SAILOR ],
|
||||
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER, TrainerType.BREEDER ],
|
||||
[BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ],
|
||||
[BiomePoolTier.SUPER_RARE]: [],
|
||||
@ -7308,6 +7308,11 @@ export function initBiomes() {
|
||||
[ Biome.VOLCANO, BiomePoolTier.COMMON ]
|
||||
]
|
||||
],
|
||||
[ TrainerType.SAILOR, [
|
||||
[ Biome.SEA, BiomePoolTier.COMMON ],
|
||||
[ Biome.BEACH, BiomePoolTier.COMMON ]
|
||||
]
|
||||
],
|
||||
[ TrainerType.BROCK, [
|
||||
[ Biome.CAVE, BiomePoolTier.BOSS ]
|
||||
]
|
||||
|
577
src/data/challenge.ts
Normal file
@ -0,0 +1,577 @@
|
||||
import * as Utils from "../utils";
|
||||
import { Challenges } from "./enums/challenges";
|
||||
import i18next from "#app/plugins/i18n.js";
|
||||
import { GameData } from "#app/system/game-data.js";
|
||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species";
|
||||
import Pokemon from "#app/field/pokemon.js";
|
||||
import { BattleType, FixedBattleConfig } from "#app/battle.js";
|
||||
import { TrainerType } from "./enums/trainer-type";
|
||||
import Trainer, { TrainerVariant } from "#app/field/trainer.js";
|
||||
import { GameMode } from "#app/game-mode.js";
|
||||
import { Species } from "./enums/species";
|
||||
import { Type } from "./type";
|
||||
|
||||
/**
|
||||
* An enum for all the challenge types. The parameter entries on these describe the
|
||||
* parameters to use when calling the applyChallenges function.
|
||||
*/
|
||||
export enum ChallengeType {
|
||||
/**
|
||||
* Challenges which modify what starters you can choose
|
||||
* @param args [0] {@link PokemonSpecies} The species to check
|
||||
* [1] {@link Utils.BooleanHolder} Sets to false if illegal, pass in true.
|
||||
*/
|
||||
STARTER_CHOICE,
|
||||
/**
|
||||
* Challenges which modify how many starter points you have
|
||||
* @param args [0] {@link Utils.NumberHolder} The amount of starter points you have
|
||||
*/
|
||||
STARTER_POINTS,
|
||||
/**
|
||||
* Challenges which modify your starters in some way
|
||||
* Not Fully Implemented
|
||||
*/
|
||||
STARTER_MODIFY,
|
||||
/**
|
||||
* Challenges which limit which pokemon you can have in battle.
|
||||
* @param args [0] {@link Pokemon} The pokemon to check
|
||||
* [1] {@link Utils.BooleanHolder} Sets to false if illegal, pass in true.
|
||||
*/
|
||||
POKEMON_IN_BATTLE,
|
||||
/**
|
||||
* Adds or modifies the fixed battles in a run
|
||||
* @param args [0] integer The wave to get a battle for
|
||||
* [1] {@link FixedBattleConfig} A new fixed battle. It'll be modified if a battle exists.
|
||||
*/
|
||||
FIXED_BATTLES,
|
||||
}
|
||||
|
||||
/**
|
||||
* A challenge object. Exists only to serve as a base class.
|
||||
*/
|
||||
export abstract class Challenge {
|
||||
public id: Challenges; // The id of the challenge
|
||||
|
||||
public value: integer; // The "strength" of the challenge, all challenges have a numerical value.
|
||||
public maxValue: integer; // The maximum strength of the challenge.
|
||||
public severity: integer; // The current severity of the challenge. Some challenges have multiple severities in addition to strength.
|
||||
public maxSeverity: integer; // The maximum severity of the challenge.
|
||||
|
||||
public conditions: ChallengeCondition[];
|
||||
public challengeTypes: ChallengeType[];
|
||||
|
||||
/**
|
||||
* @param {Challenges} id The enum value for the challenge
|
||||
*/
|
||||
constructor(id: Challenges, maxValue: integer = Number.MAX_SAFE_INTEGER) {
|
||||
this.id = id;
|
||||
|
||||
this.value = 0;
|
||||
this.maxValue = maxValue;
|
||||
this.severity = 0;
|
||||
this.maxSeverity = 0;
|
||||
this.conditions = [];
|
||||
this.challengeTypes = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the challenge to a base state.
|
||||
*/
|
||||
reset(): void {
|
||||
this.value = 0;
|
||||
this.severity = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the localisation key for the challenge
|
||||
* @returns The i18n key for this challenge
|
||||
*/
|
||||
geti18nKey(): string {
|
||||
return Challenges[this.id].split("_").map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for unlockable challenges to check if they're unlocked.
|
||||
* @param {GameData} data The save data.
|
||||
* @returns {boolean} Whether this challenge is unlocked.
|
||||
*/
|
||||
isUnlocked(data: GameData): boolean {
|
||||
return this.conditions.every(f => f(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an unlock condition to this challenge.
|
||||
* @param {ChallengeCondition} condition The condition to add.
|
||||
* @returns {Challenge} This challenge
|
||||
*/
|
||||
condition(condition: ChallengeCondition): Challenge {
|
||||
this.conditions.push(condition);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this challenge is of a particular type
|
||||
* @param {ChallengeType} challengeType The challenge type to check.
|
||||
* @returns {Challenge} This challenge
|
||||
*/
|
||||
isOfType(challengeType: ChallengeType): boolean {
|
||||
return this.challengeTypes.some(c => c === challengeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a challenge type to this challenge.
|
||||
* @param {ChallengeType} challengeType The challenge type to add.
|
||||
* @returns {Challenge} This challenge
|
||||
*/
|
||||
addChallengeType(challengeType: ChallengeType): Challenge {
|
||||
this.challengeTypes.push(challengeType);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} The localised name of this challenge.
|
||||
*/
|
||||
getName(): string {
|
||||
return i18next.t(`challenges:${this.geti18nKey()}.name`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the textual representation of a challenge's current value.
|
||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
||||
* @returns {string} The localised name for the current value.
|
||||
*/
|
||||
getValue(overrideValue?: integer): string {
|
||||
if (overrideValue === undefined) {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
return i18next.t(`challenges:${this.geti18nKey()}.value.${this.value}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of a challenge's current value.
|
||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
||||
* @returns {string} The localised description for the current value.
|
||||
*/
|
||||
getDescription(overrideValue?: integer): string {
|
||||
if (overrideValue === undefined) {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
return i18next.t(`challenges:${this.geti18nKey()}.desc.${this.value}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the value of the challenge
|
||||
* @returns {boolean} Returns true if the value changed
|
||||
*/
|
||||
increaseValue(): boolean {
|
||||
if (this.value < this.maxValue) {
|
||||
this.value = Math.min(this.value + 1, this.maxValue);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the value of the challenge
|
||||
* @returns {boolean} Returns true if the value changed
|
||||
*/
|
||||
decreaseValue(): boolean {
|
||||
if (this.value > 0) {
|
||||
this.value = Math.max(this.value - 1, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to allow choosing this challenge's severity.
|
||||
*/
|
||||
hasSeverity(): boolean {
|
||||
return this.value !== 0 && this.maxSeverity > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the severity of the challenge
|
||||
* @returns {boolean} Returns true if the value changed
|
||||
*/
|
||||
decreaseSeverity(): boolean {
|
||||
if (this.severity > 0) {
|
||||
this.severity = Math.max(this.severity - 1, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the severity of the challenge
|
||||
* @returns {boolean} Returns true if the value changed
|
||||
*/
|
||||
increaseSeverity(): boolean {
|
||||
if (this.severity < this.maxSeverity) {
|
||||
this.severity = Math.min(this.severity + 1, this.maxSeverity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "difficulty" value of this challenge.
|
||||
* @returns {integer} The difficulty value.
|
||||
*/
|
||||
getDifficulty(): integer {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum difficulty added by this challenge.
|
||||
* @returns {integer} The difficulty value.
|
||||
*/
|
||||
getMinDifficulty(): integer {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the data or game state in some way to apply the challenge.
|
||||
* @param {ChallengeType} challengeType Which challenge type this is being applied for.
|
||||
* @param args Irrelevant. See the specific challenge's apply function for additional information.
|
||||
*/
|
||||
abstract apply(challengeType: ChallengeType, args: any[]): boolean;
|
||||
|
||||
/**
|
||||
* Clones a challenge, either from another challenge or json. Chainable.
|
||||
* @param {Challenge | any} source The source challenge of json.
|
||||
* @returns {Challenge} This challenge.
|
||||
*/
|
||||
static loadChallenge(source: Challenge | any): Challenge {
|
||||
throw new Error("Method not implemented! Use derived class");
|
||||
}
|
||||
}
|
||||
|
||||
type ChallengeCondition = (data: GameData) => boolean;
|
||||
|
||||
/**
|
||||
* Implements a mono generation challenge.
|
||||
*/
|
||||
export class SingleGenerationChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.SINGLE_GENERATION, 9);
|
||||
this.addChallengeType(ChallengeType.STARTER_CHOICE);
|
||||
this.addChallengeType(ChallengeType.POKEMON_IN_BATTLE);
|
||||
this.addChallengeType(ChallengeType.FIXED_BATTLES);
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* We have special code below for victini because it is classed as a generation 4 pokemon in the code
|
||||
* despite being a generation 5 pokemon. This is due to UI constraints, the starter select screen has
|
||||
* no more room for pokemon so victini is put in the gen 4 section instead. This code just overrides the
|
||||
* normal generation check to correctly treat victini as gen 5.
|
||||
*/
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
const species = args[0] as PokemonSpecies;
|
||||
const isValidStarter = args[1] as Utils.BooleanHolder;
|
||||
const starterGeneration = species.speciesId === Species.VICTINI ? 5 : species.generation;
|
||||
if (starterGeneration !== this.value) {
|
||||
isValidStarter.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ChallengeType.POKEMON_IN_BATTLE:
|
||||
const pokemon = args[0] as Pokemon;
|
||||
const isValidPokemon = args[1] as Utils.BooleanHolder;
|
||||
const baseGeneration = pokemon.species.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.species.speciesId).generation;
|
||||
const fusionGeneration = pokemon.isFusion() ? pokemon.fusionSpecies.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.fusionSpecies.speciesId).generation : 0;
|
||||
if (pokemon.isPlayer() && (baseGeneration !== this.value || (pokemon.isFusion() && fusionGeneration !== this.value))) {
|
||||
isValidPokemon.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ChallengeType.FIXED_BATTLES:
|
||||
const waveIndex = args[0] as integer;
|
||||
const battleConfig = args[1] as FixedBattleConfig;
|
||||
let trainerTypes: TrainerType[] = [];
|
||||
switch (waveIndex) {
|
||||
case 182:
|
||||
trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]),TrainerType.MARNIE_ELITE, TrainerType.RIKA ];
|
||||
break;
|
||||
case 184:
|
||||
trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ];
|
||||
break;
|
||||
case 186:
|
||||
trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([TrainerType.BEA_ELITE,TrainerType.ALLISTER_ELITE]), TrainerType.LARRY_ELITE ];
|
||||
break;
|
||||
case 188:
|
||||
trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ];
|
||||
break;
|
||||
case 190:
|
||||
trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ];
|
||||
break;
|
||||
}
|
||||
if (trainerTypes.length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
battleConfig.setBattleType(BattleType.TRAINER).setGetTrainerFunc(scene => new Trainer(scene, trainerTypes[this.value - 1], TrainerVariant.DEFAULT));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overrides
|
||||
*/
|
||||
getDifficulty(): number {
|
||||
return this.value > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static loadChallenge(source: SingleGenerationChallenge | any): SingleGenerationChallenge {
|
||||
const newChallenge = new SingleGenerationChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
interface monotypeOverride {
|
||||
/** The species to override */
|
||||
species: Species;
|
||||
/** The type to count as */
|
||||
type: Type;
|
||||
/** If part of a fusion, should we check the fused species instead of the base species? */
|
||||
fusion: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a mono type challenge.
|
||||
*/
|
||||
export class SingleTypeChallenge extends Challenge {
|
||||
private static TYPE_OVERRIDES: monotypeOverride[] = [
|
||||
{species: Species.MELOETTA, type: Type.PSYCHIC, fusion: true},
|
||||
{species: Species.CASTFORM, type: Type.NORMAL, fusion: false},
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super(Challenges.SINGLE_TYPE, 18);
|
||||
this.addChallengeType(ChallengeType.STARTER_CHOICE);
|
||||
this.addChallengeType(ChallengeType.POKEMON_IN_BATTLE);
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
const species = args[0] as PokemonSpecies;
|
||||
const isValidStarter = args[1] as Utils.BooleanHolder;
|
||||
if (!species.isOfType(this.value - 1)) {
|
||||
isValidStarter.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ChallengeType.POKEMON_IN_BATTLE:
|
||||
const pokemon = args[0] as Pokemon;
|
||||
const isValidPokemon = args[1] as Utils.BooleanHolder;
|
||||
if (pokemon.isPlayer() && !pokemon.isOfType(this.value - 1, false, false, true)
|
||||
&& !SingleTypeChallenge.TYPE_OVERRIDES.some(o => o.type === (this.value - 1) && (pokemon.isFusion() && o.fusion ? pokemon.fusionSpecies : pokemon.species).speciesId === o.species)) {
|
||||
isValidPokemon.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overrides
|
||||
*/
|
||||
getDifficulty(): number {
|
||||
return this.value > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static loadChallenge(source: SingleTypeChallenge | any): SingleTypeChallenge {
|
||||
const newChallenge = new SingleTypeChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a fresh start challenge.
|
||||
*/
|
||||
export class FreshStartChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.FRESH_START, 1);
|
||||
this.addChallengeType(ChallengeType.STARTER_CHOICE);
|
||||
this.addChallengeType(ChallengeType.STARTER_MODIFY);
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
const species = args[0] as PokemonSpecies;
|
||||
const isValidStarter = args[1] as Utils.BooleanHolder;
|
||||
if (species) {
|
||||
isValidStarter.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overrides
|
||||
*/
|
||||
getDifficulty(): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static loadChallenge(source: FreshStartChallenge | any): FreshStartChallenge {
|
||||
const newChallenge = new FreshStartChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lowers the amount of starter points available.
|
||||
*/
|
||||
export class LowerStarterMaxCostChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.LOWER_MAX_STARTER_COST, 9);
|
||||
this.addChallengeType(ChallengeType.STARTER_CHOICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getValue(overrideValue?: integer): string {
|
||||
if (overrideValue === undefined) {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
return (10 - overrideValue).toString();
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
const species = args[0] as PokemonSpecies;
|
||||
const isValid = args[1] as Utils.BooleanHolder;
|
||||
if (speciesStarters[species.speciesId] > 10 - this.value) {
|
||||
isValid.value = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static loadChallenge(source: LowerStarterMaxCostChallenge | any): LowerStarterMaxCostChallenge {
|
||||
const newChallenge = new LowerStarterMaxCostChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lowers the maximum cost of starters available.
|
||||
*/
|
||||
export class LowerStarterPointsChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.LOWER_STARTER_POINTS, 9);
|
||||
this.addChallengeType(ChallengeType.STARTER_POINTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getValue(overrideValue?: integer): string {
|
||||
if (overrideValue === undefined) {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
return (10 - overrideValue).toString();
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_POINTS:
|
||||
const points = args[0] as Utils.NumberHolder;
|
||||
points.value -= this.value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static loadChallenge(source: LowerStarterPointsChallenge | any): LowerStarterPointsChallenge {
|
||||
const newChallenge = new LowerStarterPointsChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all challenges of a given challenge type.
|
||||
* @param {BattleScene} scene The current scene
|
||||
* @param {ChallengeType} challengeType What challenge type to apply
|
||||
* @param {any[]} args Any args for that challenge type
|
||||
* @returns {boolean} True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean {
|
||||
let ret = false;
|
||||
gameMode.challenges.forEach(v => {
|
||||
if (v.isOfType(challengeType)) {
|
||||
ret ||= v.apply(challengeType, args);
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function copyChallenge(source: Challenge | any): Challenge {
|
||||
switch (source.id) {
|
||||
case Challenges.SINGLE_GENERATION:
|
||||
return SingleGenerationChallenge.loadChallenge(source);
|
||||
case Challenges.SINGLE_TYPE:
|
||||
return SingleTypeChallenge.loadChallenge(source);
|
||||
case Challenges.LOWER_MAX_STARTER_COST:
|
||||
return LowerStarterMaxCostChallenge.loadChallenge(source);
|
||||
case Challenges.LOWER_STARTER_POINTS:
|
||||
return LowerStarterPointsChallenge.loadChallenge(source);
|
||||
}
|
||||
throw new Error("Unknown challenge copied");
|
||||
}
|
||||
|
||||
export const allChallenges: Challenge[] = [];
|
||||
|
||||
export function initChallenges() {
|
||||
allChallenges.push(
|
||||
new SingleGenerationChallenge(),
|
||||
new SingleTypeChallenge(),
|
||||
// new LowerStarterMaxCostChallenge(),
|
||||
// new LowerStarterPointsChallenge(),
|
||||
// new FreshStartChallenge()
|
||||
);
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import { PlayerPokemon } from "../field/pokemon";
|
||||
import { GameModes, gameModes } from "../game-mode";
|
||||
import { Starter } from "../ui/starter-select-ui-handler";
|
||||
import * as Utils from "../utils";
|
||||
import { Species } from "./enums/species";
|
||||
@ -29,7 +28,7 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
|
||||
const starters: Starter[] = [];
|
||||
|
||||
scene.executeWithSeedOffset(() => {
|
||||
const startingLevel = gameModes[GameModes.DAILY].getStartingLevel();
|
||||
const startingLevel = scene.gameMode.getStartingLevel();
|
||||
|
||||
if (/\d{18}$/.test(seed)) {
|
||||
for (let s = 0; s < 3; s++) {
|
||||
|
@ -435,6 +435,20 @@ export const trainerTypeDialogue: TrainerTypeDialogue = {
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.SAILOR]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:sailor.encounter.1",
|
||||
"dialogue:sailor.encounter.2",
|
||||
"dialogue:sailor.encounter.3",
|
||||
],
|
||||
victory: [
|
||||
"dialogue:sailor.victory.1",
|
||||
"dialogue:sailor.victory.2",
|
||||
"dialogue:sailor.victory.3",
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.BROCK]: {
|
||||
encounter: [
|
||||
"dialogue:brock.encounter.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import { Species } from "./enums/species";
|
||||
import { getPokemonSpecies, speciesStarters } from "./pokemon-species";
|
||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species";
|
||||
import { EggTier } from "./enums/egg-type";
|
||||
import i18next from "../plugins/i18n";
|
||||
|
||||
@ -111,3 +111,20 @@ export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timesta
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a given species EggTier Value
|
||||
* @param species - Species for wich we will check the egg tier it belongs to
|
||||
* @returns The egg tier of a given pokemon species
|
||||
*/
|
||||
export function getEggTierForSpecies(pokemonSpecies :PokemonSpecies): EggTier {
|
||||
const speciesBaseValue = speciesStarters[pokemonSpecies.getRootSpeciesId()];
|
||||
if (speciesBaseValue <= 3) {
|
||||
return EggTier.COMMON;
|
||||
} else if (speciesBaseValue <= 5) {
|
||||
return EggTier.GREAT;
|
||||
} else if (speciesBaseValue <= 7) {
|
||||
return EggTier.ULTRA;
|
||||
}
|
||||
return EggTier.MASTER;
|
||||
}
|
||||
|
7
src/data/enums/challenges.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export enum Challenges {
|
||||
SINGLE_GENERATION,
|
||||
SINGLE_TYPE,
|
||||
LOWER_MAX_STARTER_COST,
|
||||
LOWER_STARTER_POINTS,
|
||||
FRESH_START
|
||||
}
|
@ -40,6 +40,7 @@ export enum TrainerType {
|
||||
RICH,
|
||||
RICH_KID,
|
||||
ROUGHNECK,
|
||||
SAILOR,
|
||||
SCIENTIST,
|
||||
SMASHER,
|
||||
SNOW_WORKER,
|
||||
|
361
src/data/move.ts
Executable file → Normal file
@ -42,7 +42,7 @@ export enum MoveTarget {
|
||||
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_Pok%C3%A9mon Moves that target all adjacent Pokemon} */
|
||||
ALL_NEAR_OTHERS,
|
||||
NEAR_ENEMY,
|
||||
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_foes Moves that taret all adjacent foes} */
|
||||
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_foes Moves that target all adjacent foes} */
|
||||
ALL_NEAR_ENEMIES,
|
||||
RANDOM_NEAR_ENEMY,
|
||||
ALL_ENEMIES,
|
||||
@ -99,6 +99,7 @@ export default class Move implements Localizable {
|
||||
public id: Moves;
|
||||
public name: string;
|
||||
public type: Type;
|
||||
public defaultType: Type;
|
||||
public category: MoveCategory;
|
||||
public moveTarget: MoveTarget;
|
||||
public power: integer;
|
||||
@ -118,6 +119,7 @@ export default class Move implements Localizable {
|
||||
|
||||
this.nameAppend = "";
|
||||
this.type = type;
|
||||
this.defaultType = type;
|
||||
this.category = category;
|
||||
this.moveTarget = defaultMoveTarget;
|
||||
this.power = power;
|
||||
@ -166,10 +168,22 @@ export default class Move implements Localizable {
|
||||
return this.attrs.some((attr) => attr instanceof attrType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes as input a boolean function and returns the first MoveAttr in attrs that matches true
|
||||
* @param attrPredicate
|
||||
* @returns the first {@linkcode MoveAttr} element in attrs that makes the input function return true
|
||||
*/
|
||||
findAttr(attrPredicate: (attr: MoveAttr) => boolean): MoveAttr {
|
||||
return this.attrs.find(attrPredicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new MoveAttr to the move (appends to the attr array)
|
||||
* if the MoveAttr also comes with a condition, also adds that to the conditions array: {@linkcode MoveCondition}
|
||||
* @param AttrType {@linkcode MoveAttr} the constructor of a MoveAttr class
|
||||
* @param args the args needed to instantiate a the given class
|
||||
* @returns the called object {@linkcode Move}
|
||||
*/
|
||||
attr<T extends new (...args: any[]) => MoveAttr>(AttrType: T, ...args: ConstructorParameters<T>): this {
|
||||
const attr = new AttrType(...args);
|
||||
this.attrs.push(attr);
|
||||
@ -184,9 +198,16 @@ export default class Move implements Localizable {
|
||||
return this;
|
||||
}
|
||||
|
||||
addAttr(attr: MoveAttr): this {
|
||||
this.attrs.push(attr);
|
||||
let attrCondition = attr.getCondition();
|
||||
/**
|
||||
* Adds a new MoveAttr to the move (appends to the attr array)
|
||||
* if the MoveAttr also comes with a condition, also adds that to the conditions array: {@linkcode MoveCondition}
|
||||
* Almost identical to {@link attr}, except you are passing in a MoveAttr object, instead of a constructor and it's arguments
|
||||
* @param attrAdd {@linkcode MoveAttr} the attribute to add
|
||||
* @returns the called object {@linkcode Move}
|
||||
*/
|
||||
addAttr(attrAdd: MoveAttr): this {
|
||||
this.attrs.push(attrAdd);
|
||||
let attrCondition = attrAdd.getCondition();
|
||||
if (attrCondition) {
|
||||
if (typeof attrCondition === "function") {
|
||||
attrCondition = new MoveCondition(attrCondition);
|
||||
@ -197,15 +218,30 @@ export default class Move implements Localizable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the move target of this move
|
||||
* @param moveTarget {@linkcode MoveTarget} the move target to set
|
||||
* @returns the called object {@linkcode Move}
|
||||
*/
|
||||
target(moveTarget: MoveTarget): this {
|
||||
this.moveTarget = moveTarget;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter function that returns if this Move has a MoveFlag
|
||||
* @param flag {@linkcode MoveFlags} to check
|
||||
* @returns boolean
|
||||
*/
|
||||
hasFlag(flag: MoveFlags): boolean {
|
||||
// internally it is taking the bitwise AND (MoveFlags are represented as bit-shifts) and returning False if result is 0 and true otherwise
|
||||
return !!(this.flags & flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter function that returns if the move hits multiple targets
|
||||
* @returns boolean
|
||||
*/
|
||||
isMultiTarget(): boolean {
|
||||
switch (this.moveTarget) {
|
||||
case MoveTarget.ALL_OTHERS:
|
||||
@ -222,6 +258,11 @@ export default class Move implements Localizable {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter function that returns if the move targets itself or an ally
|
||||
* @returns boolean
|
||||
*/
|
||||
|
||||
isAllyTarget(): boolean {
|
||||
switch (this.moveTarget) {
|
||||
case MoveTarget.USER:
|
||||
@ -235,6 +276,12 @@ export default class Move implements Localizable {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the move is immune to certain types
|
||||
* currently only look at case of Grass types and powder moves
|
||||
* @param type {@linkcode Type} enum
|
||||
* @returns boolean
|
||||
*/
|
||||
isTypeImmune(type: Type): boolean {
|
||||
switch (type) {
|
||||
case Type.GRASS:
|
||||
@ -246,6 +293,11 @@ export default class Move implements Localizable {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a move condition to the move
|
||||
* @param condition {@linkcode MoveCondition} or {@linkcode MoveConditionFunc}, appends to conditions array a new MoveCondition object
|
||||
* @returns the called object {@linkcode Move}
|
||||
*/
|
||||
condition(condition: MoveCondition | MoveConditionFunc): this {
|
||||
if (typeof condition === "function") {
|
||||
condition = new MoveCondition(condition as MoveConditionFunc);
|
||||
@ -255,17 +307,31 @@ export default class Move implements Localizable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the move as "partial": appends texts to the move name
|
||||
* @returns the called object {@linkcode Move}
|
||||
*/
|
||||
partial(): this {
|
||||
this.nameAppend += " (P)";
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the move as "unimplemented": appends texts to the move name
|
||||
* @returns the called object {@linkcode Move}
|
||||
*/
|
||||
unimplemented(): this {
|
||||
this.nameAppend += " (N)";
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flags of the move
|
||||
* @param flag {@linkcode MoveFlags}
|
||||
* @param on a boolean, if True, then "ORs" the flag onto existing ones, if False then "XORs" the flag onto existing ones
|
||||
*/
|
||||
private setFlag(flag: MoveFlags, on: boolean): void {
|
||||
// bitwise OR and bitwise XOR respectively
|
||||
if (on) {
|
||||
this.flags |= flag;
|
||||
} else {
|
||||
@ -273,51 +339,110 @@ export default class Move implements Localizable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.MAKES_CONTACT} flag for the calling Move
|
||||
* @param makesContact The value (boolean) to set the flag to
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
makesContact(makesContact?: boolean): this {
|
||||
this.setFlag(MoveFlags.MAKES_CONTACT, makesContact);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.IGNORE_PROTECT} flag for the calling Move
|
||||
* @param ignoresProtect The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.CURSE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ignoresProtect(ignoresProtect?: boolean): this {
|
||||
this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.IGNORE_VIRTUAL} flag for the calling Move
|
||||
* @param ignoresVirtual The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.NATURE_POWER}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ignoresVirtual(ignoresVirtual?: boolean): this {
|
||||
this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.SOUND_BASED} flag for the calling Move
|
||||
* @param soundBased The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.UPROAR}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
soundBased(soundBased?: boolean): this {
|
||||
this.setFlag(MoveFlags.SOUND_BASED, soundBased);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.HIDE_USER} flag for the calling Move
|
||||
* @param hidesUser The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.TELEPORT}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
hidesUser(hidesUser?: boolean): this {
|
||||
this.setFlag(MoveFlags.HIDE_USER, hidesUser);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.HIDE_TARGET} flag for the calling Move
|
||||
* @param hidesTarget The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.WHIRLWIND}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
hidesTarget(hidesTarget?: boolean): this {
|
||||
this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.BITING_MOVE} flag for the calling Move
|
||||
* @param bitingMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.BITE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
bitingMove(bitingMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.BITING_MOVE, bitingMove);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.PULSE_MOVE} flag for the calling Move
|
||||
* @param pulseMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.WATER_PULSE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
pulseMove(pulseMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.PULSE_MOVE, pulseMove);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.PUNCHING_MOVE} flag for the calling Move
|
||||
* @param punchingMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.DRAIN_PUNCH}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
punchingMove(punchingMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.PUNCHING_MOVE, punchingMove);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.SLICING_MOVE} flag for the calling Move
|
||||
* @param slicingMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.X_SCISSOR}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
slicingMove(slicingMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.SLICING_MOVE, slicingMove);
|
||||
return this;
|
||||
@ -334,42 +459,92 @@ export default class Move implements Localizable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.BALLBOMB_MOVE} flag for the calling Move
|
||||
* @param ballBombMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.ELECTRO_BALL}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ballBombMove(ballBombMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.BALLBOMB_MOVE, ballBombMove);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.POWDER_MOVE} flag for the calling Move
|
||||
* @param powderMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.STUN_SPORE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
powderMove(powderMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.POWDER_MOVE, powderMove);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.DANCE_MOVE} flag for the calling Move
|
||||
* @param danceMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.PETAL_DANCE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
danceMove(danceMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.DANCE_MOVE, danceMove);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.WIND_MOVE} flag for the calling Move
|
||||
* @param windMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.HURRICANE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
windMove(windMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.WIND_MOVE, windMove);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.TRIAGE_MOVE} flag for the calling Move
|
||||
* @param triageMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.ABSORB}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
triageMove(triageMove?: boolean): this {
|
||||
this.setFlag(MoveFlags.TRIAGE_MOVE, triageMove);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.IGNORE_ABILITIES} flag for the calling Move
|
||||
* @param ignoresAbilities sThe value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.SUNSTEEL_STRIKE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ignoresAbilities(ignoresAbilities?: boolean): this {
|
||||
this.setFlag(MoveFlags.IGNORE_ABILITIES, ignoresAbilities);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.CHECK_ALL_HITS} flag for the calling Move
|
||||
* @param checkAllHits The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.TRIPLE_AXEL}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
checkAllHits(checkAllHits?: boolean): this {
|
||||
this.setFlag(MoveFlags.CHECK_ALL_HITS, checkAllHits);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the move flag applies to the pokemon(s) using/receiving the move
|
||||
* @param flag {@linkcode MoveFlags} MoveFlag to check on user and/or target
|
||||
* @param user {@linkcode Pokemon} the Pokemon using the move
|
||||
* @param target {@linkcode Pokemon} the Pokemon receiving the move
|
||||
* @returns boolean
|
||||
*/
|
||||
checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean {
|
||||
// special cases below, eg: if the move flag is MAKES_CONTACT, and the user pokemon has an ability that ignores contact (like "Long Reach"), then overrides and move does not make contact
|
||||
switch (flag) {
|
||||
case MoveFlags.MAKES_CONTACT:
|
||||
if (user.hasAbilityWithAttr(IgnoreContactAbAttr)) {
|
||||
@ -389,6 +564,13 @@ export default class Move implements Localizable {
|
||||
return !!(this.flags & flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies each {@linkcode MoveCondition} of this move to the params
|
||||
* @param user {@linkcode Pokemon} to apply conditions to
|
||||
* @param target {@linkcode Pokemon} to apply conditions to
|
||||
* @param move {@linkcode Move} to apply conditions to
|
||||
* @returns boolean: false if any of the apply()'s return false, else true
|
||||
*/
|
||||
applyConditions(user: Pokemon, target: Pokemon, move: Move): boolean {
|
||||
for (const condition of this.conditions) {
|
||||
if (!condition.apply(user, target, move)) {
|
||||
@ -399,6 +581,14 @@ export default class Move implements Localizable {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sees if, given the target pokemon, a move fails on it (by looking at each {@linkcode MoveAttr} of this move
|
||||
* @param user {@linkcode Pokemon} using the move
|
||||
* @param target {@linkcode Pokemon} receiving the move
|
||||
* @param move {@linkcode Move} using the move
|
||||
* @param cancelled {@linkcode Utils.BooleanHolder} to hold boolean value
|
||||
* @returns string of the failed text, or null
|
||||
*/
|
||||
getFailedText(user: Pokemon, target: Pokemon, move: Move, cancelled: Utils.BooleanHolder): string | null {
|
||||
for (const attr of this.attrs) {
|
||||
const failedText = attr.getFailedText(user, target, move, cancelled);
|
||||
@ -409,6 +599,13 @@ export default class Move implements Localizable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the userBenefitScore across all the attributes and conditions
|
||||
* @param user {@linkcode Pokemon} using the move
|
||||
* @param target {@linkcode Pokemon} receiving the move
|
||||
* @param move {@linkcode Move} using the move
|
||||
* @returns integer representing the total benefitScore
|
||||
*/
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||
let score = 0;
|
||||
|
||||
@ -423,10 +620,18 @@ export default class Move implements Localizable {
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the targetBenefitScore across all the attributes
|
||||
* @param user {@linkcode Pokemon} using the move
|
||||
* @param target {@linkcode Pokemon} receiving the move
|
||||
* @param move {@linkcode Move} using the move
|
||||
* @returns integer representing the total benefitScore
|
||||
*/
|
||||
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||
let score = 0;
|
||||
|
||||
for (const attr of this.attrs) {
|
||||
// conditionals to check if the move is self targeting (if so then you are applying the move to yourself, not the target)
|
||||
score += attr.getTargetBenefitScore(user, !attr.selfTarget ? target : user, move) * (target !== user && attr.selfTarget ? -1 : 1);
|
||||
}
|
||||
|
||||
@ -1046,11 +1251,18 @@ export class PartyStatusCureAttr extends MoveEffectAttr {
|
||||
this.abilityCondition = abilityCondition;
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!super.apply(user, target, move, args)) {
|
||||
return false;
|
||||
//The same as MoveEffectAttr.canApply, except it doesn't check for the target's HP.
|
||||
canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]) {
|
||||
const isTargetValid =
|
||||
(this.selfTarget && user.hp && !user.getTag(BattlerTagType.FRENZY)) ||
|
||||
(!this.selfTarget && (!target.getTag(BattlerTagType.PROTECTED) || move.hasFlag(MoveFlags.IGNORE_PROTECT)));
|
||||
return !!isTargetValid;
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!this.canApply(user, target, move, args)) {
|
||||
return false;
|
||||
}
|
||||
this.addPartyCurePhase(user);
|
||||
}
|
||||
|
||||
@ -1262,7 +1474,7 @@ export class HitHealAttr extends MoveEffectAttr {
|
||||
message = i18next.t("battle:drainMessage", {pokemonName: target.name});
|
||||
} else {
|
||||
// Default healing formula used by draining moves like Absorb, Draining Kiss, Bitter Blade, etc.
|
||||
healAmount = Math.max(Math.floor(user.turnData.damageDealt * this.healRatio), 1);
|
||||
healAmount = Math.max(Math.floor(user.turnData.currDamageDealt * this.healRatio), 1);
|
||||
message = i18next.t("battle:regainHealth", {pokemonName: user.name});
|
||||
}
|
||||
if (reverseDrain) {
|
||||
@ -1426,7 +1638,7 @@ export class StatusEffectAttr extends MoveEffectAttr {
|
||||
}
|
||||
if ((!pokemon.status || (pokemon.status.effect === this.effect && move.chance < 0))
|
||||
&& pokemon.trySetStatus(this.effect, true, user, this.cureTurn)) {
|
||||
applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, new PokemonMove(move.id), null,this.effect);
|
||||
applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null,this.effect);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1992,7 +2204,7 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr {
|
||||
(args[0] as Utils.BooleanHolder).value = true;
|
||||
user.scene.queueMessage(getPokemonMessage(user, ` ${this.chargeText.replace("{TARGET}", target.name)}`));
|
||||
user.pushMoveHistory({ move: move.id, targets: [ target.getBattlerIndex() ], result: MoveResult.OTHER });
|
||||
user.scene.arena.addTag(this.tagType, 3, move.id, user.id, ArenaTagSide.BOTH, target.getBattlerIndex());
|
||||
user.scene.arena.addTag(this.tagType, 3, move.id, user.id, ArenaTagSide.BOTH, false, target.getBattlerIndex());
|
||||
|
||||
resolve(true);
|
||||
});
|
||||
@ -3120,23 +3332,22 @@ export class TechnoBlastTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.GENESECT)) {
|
||||
const form = user.species.speciesId === Species.GENESECT ? user.formIndex : user.fusionSpecies.formIndex;
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
|
||||
switch (form) {
|
||||
case 1: // Shock Drive
|
||||
type.value = Type.ELECTRIC;
|
||||
move.type = Type.ELECTRIC;
|
||||
break;
|
||||
case 2: // Burn Drive
|
||||
type.value = Type.FIRE;
|
||||
move.type = Type.FIRE;
|
||||
break;
|
||||
case 3: // Chill Drive
|
||||
type.value = Type.ICE;
|
||||
move.type = Type.ICE;
|
||||
break;
|
||||
case 4: // Douse Drive
|
||||
type.value = Type.WATER;
|
||||
move.type = Type.WATER;
|
||||
break;
|
||||
default:
|
||||
type.value = Type.NORMAL;
|
||||
move.type = Type.NORMAL;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@ -3150,14 +3361,13 @@ export class AuraWheelTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.MORPEKO)) {
|
||||
const form = user.species.speciesId === Species.MORPEKO ? user.formIndex : user.fusionSpecies.formIndex;
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
|
||||
switch (form) {
|
||||
case 1: // Hangry Mode
|
||||
type.value = Type.DARK;
|
||||
move.type = Type.DARK;
|
||||
break;
|
||||
default: // Full Belly Mode
|
||||
type.value = Type.ELECTRIC;
|
||||
move.type = Type.ELECTRIC;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@ -3171,17 +3381,16 @@ export class RagingBullTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.PALDEA_TAUROS)) {
|
||||
const form = user.species.speciesId === Species.PALDEA_TAUROS ? user.formIndex : user.fusionSpecies.formIndex;
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
|
||||
switch (form) {
|
||||
case 1: // Blaze breed
|
||||
type.value = Type.FIRE;
|
||||
move.type = Type.FIRE;
|
||||
break;
|
||||
case 2: // Aqua breed
|
||||
type.value = Type.WATER;
|
||||
move.type = Type.WATER;
|
||||
break;
|
||||
default:
|
||||
type.value = Type.FIGHTING;
|
||||
move.type = Type.FIGHTING;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@ -3195,32 +3404,31 @@ export class IvyCudgelTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.OGERPON)) {
|
||||
const form = user.species.speciesId === Species.OGERPON ? user.formIndex : user.fusionSpecies.formIndex;
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
|
||||
switch (form) {
|
||||
case 1: // Wellspring Mask
|
||||
type.value = Type.WATER;
|
||||
move.type = Type.WATER;
|
||||
break;
|
||||
case 2: // Hearthflame Mask
|
||||
type.value = Type.FIRE;
|
||||
move.type = Type.FIRE;
|
||||
break;
|
||||
case 3: // Cornerstone Mask
|
||||
type.value = Type.ROCK;
|
||||
move.type = Type.ROCK;
|
||||
break;
|
||||
case 4: // Teal Mask Tera
|
||||
type.value = Type.GRASS;
|
||||
move.type = Type.GRASS;
|
||||
break;
|
||||
case 5: // Wellspring Mask Tera
|
||||
type.value = Type.WATER;
|
||||
move.type = Type.WATER;
|
||||
break;
|
||||
case 6: // Hearthflame Mask Tera
|
||||
type.value = Type.FIRE;
|
||||
move.type = Type.FIRE;
|
||||
break;
|
||||
case 7: // Cornerstone Mask Tera
|
||||
type.value = Type.ROCK;
|
||||
move.type = Type.ROCK;
|
||||
break;
|
||||
default:
|
||||
type.value = Type.GRASS;
|
||||
move.type = Type.GRASS;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@ -3233,23 +3441,21 @@ export class IvyCudgelTypeAttr extends VariableMoveTypeAttr {
|
||||
export class WeatherBallTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!user.scene.arena.weather?.isEffectSuppressed(user.scene)) {
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
|
||||
switch (user.scene.arena.weather?.weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
case WeatherType.HARSH_SUN:
|
||||
type.value = Type.FIRE;
|
||||
move.type = Type.FIRE;
|
||||
break;
|
||||
case WeatherType.RAIN:
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
type.value = Type.WATER;
|
||||
move.type = Type.WATER;
|
||||
break;
|
||||
case WeatherType.SANDSTORM:
|
||||
type.value = Type.ROCK;
|
||||
move.type = Type.ROCK;
|
||||
break;
|
||||
case WeatherType.HAIL:
|
||||
case WeatherType.SNOW:
|
||||
type.value = Type.ICE;
|
||||
move.type = Type.ICE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
@ -3281,20 +3487,18 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
|
||||
}
|
||||
|
||||
const currentTerrain = user.scene.arena.getTerrainType();
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
|
||||
switch (currentTerrain) {
|
||||
case TerrainType.MISTY:
|
||||
type.value = Type.FAIRY;
|
||||
move.type = Type.FAIRY;
|
||||
break;
|
||||
case TerrainType.ELECTRIC:
|
||||
type.value = Type.ELECTRIC;
|
||||
move.type = Type.ELECTRIC;
|
||||
break;
|
||||
case TerrainType.GRASSY:
|
||||
type.value = Type.GRASS;
|
||||
move.type = Type.GRASS;
|
||||
break;
|
||||
case TerrainType.PSYCHIC:
|
||||
type.value = Type.PSYCHIC;
|
||||
move.type = Type.PSYCHIC;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
@ -3305,8 +3509,6 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
|
||||
|
||||
export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
|
||||
const iv_val = Math.floor(((user.ivs[Stat.HP] & 1)
|
||||
+(user.ivs[Stat.ATK] & 1) * 2
|
||||
+(user.ivs[Stat.DEF] & 1) * 4
|
||||
@ -3314,7 +3516,7 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
|
||||
+(user.ivs[Stat.SPATK] & 1) * 16
|
||||
+(user.ivs[Stat.SPDEF] & 1) * 32) * 15/63);
|
||||
|
||||
type.value = [
|
||||
move.type = [
|
||||
Type.FIGHTING, Type.FLYING, Type.POISON, Type.GROUND,
|
||||
Type.ROCK, Type.BUG, Type.GHOST, Type.STEEL,
|
||||
Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC,
|
||||
@ -3326,16 +3528,14 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
|
||||
|
||||
export class MatchUserTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const type = (args[0] as Utils.IntegerHolder);
|
||||
|
||||
const userTypes = user.getTypes(true);
|
||||
|
||||
if (userTypes.includes(Type.STELLAR)) { // will not change to stellar type
|
||||
const nonTeraTypes = user.getTypes();
|
||||
type.value = nonTeraTypes[0];
|
||||
move.type = nonTeraTypes[0];
|
||||
return true;
|
||||
} else if (userTypes.length > 0) {
|
||||
type.value = userTypes[0];
|
||||
move.type = userTypes[0];
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -4021,6 +4221,48 @@ export class RemoveScreensAttr extends MoveEffectAttr {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*Swaps arena effects between the player and enemy side
|
||||
* @extends MoveEffectAttr
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class SwapArenaTagsAttr extends MoveEffectAttr {
|
||||
public SwapTags: ArenaTagType[];
|
||||
|
||||
|
||||
constructor(SwapTags: ArenaTagType[]) {
|
||||
super(true, MoveEffectTrigger.POST_APPLY);
|
||||
this.SwapTags = SwapTags;
|
||||
}
|
||||
|
||||
apply(user:Pokemon, target:Pokemon, move:Move, args: any[]): boolean {
|
||||
if (!super.apply(user, target, move, args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const tagPlayerTemp = user.scene.arena.findTagsOnSide((t => this.SwapTags.includes(t.tagType)), ArenaTagSide.PLAYER);
|
||||
const tagEnemyTemp = user.scene.arena.findTagsOnSide((t => this.SwapTags.includes(t.tagType)), ArenaTagSide.ENEMY);
|
||||
|
||||
|
||||
if (tagPlayerTemp) {
|
||||
for (const swapTagsType of tagPlayerTemp) {
|
||||
user.scene.arena.removeTagOnSide(swapTagsType.tagType, ArenaTagSide.PLAYER, true);
|
||||
user.scene.arena.addTag(swapTagsType.tagType, swapTagsType.turnCount, swapTagsType.sourceMove, swapTagsType.sourceId, ArenaTagSide.ENEMY, true);
|
||||
}
|
||||
}
|
||||
if (tagEnemyTemp) {
|
||||
for (const swapTagsType of tagEnemyTemp) {
|
||||
user.scene.arena.removeTagOnSide(swapTagsType.tagType, ArenaTagSide.ENEMY, true);
|
||||
user.scene.arena.addTag(swapTagsType.tagType, swapTagsType.turnCount, swapTagsType.sourceMove, swapTagsType.sourceId, ArenaTagSide.PLAYER, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
user.scene.queueMessage( `${user.name} swapped the battle effects affecting each side of the field!`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for Revival Blessing.
|
||||
* @extends MoveEffectAttr
|
||||
@ -4100,7 +4342,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
||||
// Check if the move category is not STATUS or if the switch out condition is not met
|
||||
if (!this.getSwitchOutCondition()(user, target, move)) {
|
||||
//Apply effects before switch out i.e. poison point, flame body, etc
|
||||
applyPostDefendAbAttrs(PostDefendContactApplyStatusEffectAbAttr, target, user, new PokemonMove(move.id), null);
|
||||
applyPostDefendAbAttrs(PostDefendContactApplyStatusEffectAbAttr, target, user, move, null);
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
@ -4181,7 +4423,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
||||
}
|
||||
|
||||
const party = player ? user.scene.getParty() : user.scene.getEnemyParty();
|
||||
return (!player && !user.scene.currentBattle.battleType) || party.filter(p => !p.isFainted() && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > user.scene.currentBattle.getBattlerCount();
|
||||
return (!player && !user.scene.currentBattle.battleType) || party.filter(p => p.isAllowedInBattle() && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > user.scene.currentBattle.getBattlerCount();
|
||||
};
|
||||
}
|
||||
|
||||
@ -5710,6 +5952,7 @@ export function initMoves() {
|
||||
.attr(BypassSleepAttr)
|
||||
.attr(RandomMovesetMoveAttr)
|
||||
.condition(userSleptOrComatoseCondition)
|
||||
.target(MoveTarget.ALL_ENEMIES)
|
||||
.ignoresVirtual(),
|
||||
new StatusMove(Moves.HEAL_BELL, Type.NORMAL, -1, 5, -1, 0, 2)
|
||||
.attr(PartyStatusCureAttr, "A bell chimed!", Abilities.SOUNDPROOF)
|
||||
@ -5769,7 +6012,7 @@ export function initMoves() {
|
||||
], true)
|
||||
.attr(RemoveArenaTrapAttr),
|
||||
new StatusMove(Moves.SWEET_SCENT, Type.NORMAL, 100, 20, -1, 0, 2)
|
||||
.attr(StatChangeAttr, BattleStat.EVA, -1)
|
||||
.attr(StatChangeAttr, BattleStat.EVA, -2)
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||
new AttackMove(Moves.IRON_TAIL, Type.STEEL, MoveCategory.PHYSICAL, 100, 75, 15, 30, 0, 2)
|
||||
.attr(StatChangeAttr, BattleStat.DEF, -1),
|
||||
@ -6683,7 +6926,11 @@ export function initMoves() {
|
||||
.condition((user, target, move) => user.battleData.berriesEaten.length > 0),
|
||||
new StatusMove(Moves.ROTOTILLER, Type.GROUND, -1, 10, 100, 0, 6)
|
||||
.target(MoveTarget.ALL)
|
||||
.unimplemented(),
|
||||
.condition((user,target,move) => {
|
||||
// If any fielded pokémon is grass-type and grounded.
|
||||
return [...user.scene.getEnemyParty(),...user.scene.getParty()].some((poke) => poke.isOfType(Type.GRASS) && poke.isGrounded());
|
||||
})
|
||||
.attr(StatChangeAttr, [BattleStat.ATK, BattleStat.SPATK], 1, false, (user, target, move) => target.isOfType(Type.GRASS) && target.isGrounded()),
|
||||
new StatusMove(Moves.STICKY_WEB, Type.BUG, -1, 20, -1, 0, 6)
|
||||
.attr(AddArenaTrapTagAttr, ArenaTagType.STICKY_WEB)
|
||||
.target(MoveTarget.ENEMY_SIDE),
|
||||
@ -7253,9 +7500,7 @@ export function initMoves() {
|
||||
.attr(FirstAttackDoublePowerAttr)
|
||||
.bitingMove(),
|
||||
new StatusMove(Moves.COURT_CHANGE, Type.NORMAL, 100, 10, -1, 0, 8)
|
||||
.target(MoveTarget.BOTH_SIDES)
|
||||
.unimplemented(),
|
||||
/* Unused */
|
||||
.attr(SwapArenaTagsAttr, [ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.MIST, ArenaTagType.REFLECT, ArenaTagType.SPIKES, ArenaTagType.STEALTH_ROCK, ArenaTagType.STICKY_WEB, ArenaTagType.TAILWIND, ArenaTagType.TOXIC_SPIKES]),
|
||||
new AttackMove(Moves.MAX_FLARE, Type.FIRE, MoveCategory.PHYSICAL, 10, -1, 10, -1, 0, 8)
|
||||
.target(MoveTarget.NEAR_ENEMY)
|
||||
.unimplemented()
|
||||
|
@ -363,7 +363,8 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
||||
new SpeciesFormChange(Species.PIDGEOT, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.PIDGEOTITE))
|
||||
],
|
||||
[Species.PIKACHU]: [
|
||||
new SpeciesFormChange(Species.PIKACHU, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
|
||||
new SpeciesFormChange(Species.PIKACHU, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)),
|
||||
new SpeciesFormChange(Species.PIKACHU, "partner", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
|
||||
],
|
||||
[Species.MEOWTH]: [
|
||||
new SpeciesFormChange(Species.MEOWTH, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
|
||||
@ -397,7 +398,8 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
||||
new SpeciesFormChange(Species.LAPRAS, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
|
||||
],
|
||||
[Species.EEVEE]: [
|
||||
new SpeciesFormChange(Species.EEVEE, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
|
||||
new SpeciesFormChange(Species.EEVEE, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)),
|
||||
new SpeciesFormChange(Species.EEVEE, "partner", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
|
||||
],
|
||||
[Species.SNORLAX]: [
|
||||
new SpeciesFormChange(Species.SNORLAX, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
|
||||
|
@ -917,7 +917,7 @@ export function initSpecies() {
|
||||
new PokemonSpecies(Species.ARBOK, 1, false, false, false, "Cobra Pokémon", Type.POISON, null, 3.5, 65, Abilities.INTIMIDATE, Abilities.SHED_SKIN, Abilities.UNNERVE, 448, 60, 95, 69, 65, 79, 80, 90, 70, 157, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(Species.PIKACHU, 1, false, false, false, "Mouse Pokémon", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 320, 35, 55, 40, 50, 50, 90, 190, 50, 112, GrowthRate.MEDIUM_FAST, 50, true, true,
|
||||
new PokemonForm("Normal", "", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 320, 35, 55, 40, 50, 50, 90, 190, 50, 112, true, null, true),
|
||||
new PokemonForm("Partner", "partner", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, "", true),
|
||||
new PokemonForm("Partner", "partner", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true),
|
||||
new PokemonForm("Cosplay", "cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
||||
new PokemonForm("Cool Cosplay", "cool-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
||||
new PokemonForm("Beauty Cosplay", "beauty-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
||||
@ -1066,7 +1066,7 @@ export function initSpecies() {
|
||||
new PokemonSpecies(Species.DITTO, 1, false, false, false, "Transform Pokémon", Type.NORMAL, null, 0.3, 4, Abilities.LIMBER, Abilities.NONE, Abilities.IMPOSTER, 288, 48, 48, 48, 48, 48, 48, 35, 50, 101, GrowthRate.MEDIUM_FAST, null, false),
|
||||
new PokemonSpecies(Species.EEVEE, 1, false, false, false, "Evolution Pokémon", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 325, 55, 55, 50, 45, 65, 55, 45, 50, 65, GrowthRate.MEDIUM_FAST, 87.5, false, true,
|
||||
new PokemonForm("Normal", "", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 325, 55, 55, 50, 45, 65, 55, 45, 50, 65, false, null, true),
|
||||
new PokemonForm("Partner", "partner", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 435, 65, 75, 70, 65, 85, 75, 45, 50, 65, false, "", true),
|
||||
new PokemonForm("Partner", "partner", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 435, 65, 75, 70, 65, 85, 75, 45, 50, 65, false, null, true),
|
||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 18, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 425, 70, 75, 80, 60, 95, 45, 45, 50, 65),
|
||||
),
|
||||
new PokemonSpecies(Species.VAPOREON, 1, false, false, false, "Bubble Jet Pokémon", Type.WATER, null, 1, 29, Abilities.WATER_ABSORB, Abilities.NONE, Abilities.HYDRATION, 525, 130, 65, 60, 110, 95, 65, 45, 50, 184, GrowthRate.MEDIUM_FAST, 87.5, false),
|
||||
@ -1286,7 +1286,7 @@ export function initSpecies() {
|
||||
new PokemonSpecies(Species.PELIPPER, 3, false, false, false, "Water Bird Pokémon", Type.WATER, Type.FLYING, 1.2, 28, Abilities.KEEN_EYE, Abilities.DRIZZLE, Abilities.RAIN_DISH, 440, 60, 50, 100, 95, 70, 65, 45, 50, 154, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(Species.RALTS, 3, false, false, false, "Feeling Pokémon", Type.PSYCHIC, Type.FAIRY, 0.4, 6.6, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 198, 28, 25, 25, 45, 35, 40, 235, 35, 40, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(Species.KIRLIA, 3, false, false, false, "Emotion Pokémon", Type.PSYCHIC, Type.FAIRY, 0.8, 20.2, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 278, 38, 35, 35, 65, 55, 50, 120, 35, 97, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(Species.GARDEVOIR, 3, false, false, false, "Embrace Pokémon", Type.PSYCHIC, Type.FAIRY, 1.6, 48.4, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 518, 68, 65, 65, 125, 115, 80, 45, 35, 259, GrowthRate.SLOW, 0, false, true,
|
||||
new PokemonSpecies(Species.GARDEVOIR, 3, false, false, false, "Embrace Pokémon", Type.PSYCHIC, Type.FAIRY, 1.6, 48.4, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 518, 68, 65, 65, 125, 115, 80, 45, 35, 259, GrowthRate.SLOW, 50, false, true,
|
||||
new PokemonForm("Normal", "", Type.PSYCHIC, Type.FAIRY, 1.6, 48.4, Abilities.SYNCHRONIZE, Abilities.TRACE, Abilities.TELEPATHY, 518, 68, 65, 65, 125, 115, 80, 45, 35, 259, false, null, true),
|
||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.PSYCHIC, Type.FAIRY, 1.6, 48.4, Abilities.PIXILATE, Abilities.PIXILATE, Abilities.PIXILATE, 618, 68, 85, 65, 165, 135, 100, 45, 35, 259),
|
||||
),
|
||||
@ -1404,7 +1404,7 @@ export function initSpecies() {
|
||||
),
|
||||
new PokemonSpecies(Species.WYNAUT, 3, false, false, false, "Bright Pokémon", Type.PSYCHIC, null, 0.6, 14, Abilities.SHADOW_TAG, Abilities.NONE, Abilities.TELEPATHY, 260, 95, 23, 48, 23, 48, 23, 125, 50, 52, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(Species.SNORUNT, 3, false, false, false, "Snow Hat Pokémon", Type.ICE, null, 0.7, 16.8, Abilities.INNER_FOCUS, Abilities.ICE_BODY, Abilities.MOODY, 300, 50, 50, 50, 50, 50, 50, 190, 50, 60, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(Species.GLALIE, 3, false, false, false, "Face Pokémon", Type.ICE, null, 1.5, 256.5, Abilities.INNER_FOCUS, Abilities.ICE_BODY, Abilities.MOODY, 480, 80, 80, 80, 80, 80, 80, 75, 50, 168, GrowthRate.MEDIUM_FAST, 100, false, true,
|
||||
new PokemonSpecies(Species.GLALIE, 3, false, false, false, "Face Pokémon", Type.ICE, null, 1.5, 256.5, Abilities.INNER_FOCUS, Abilities.ICE_BODY, Abilities.MOODY, 480, 80, 80, 80, 80, 80, 80, 75, 50, 168, GrowthRate.MEDIUM_FAST, 50, false, true,
|
||||
new PokemonForm("Normal", "", Type.ICE, null, 1.5, 256.5, Abilities.INNER_FOCUS, Abilities.ICE_BODY, Abilities.MOODY, 480, 80, 80, 80, 80, 80, 80, 75, 50, 168, false, null, true),
|
||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.ICE, null, 2.1, 350.2, Abilities.REFRIGERATE, Abilities.REFRIGERATE, Abilities.REFRIGERATE, 580, 80, 120, 80, 120, 80, 100, 75, 50, 168),
|
||||
),
|
||||
@ -1829,7 +1829,7 @@ export function initSpecies() {
|
||||
new PokemonForm("Ordinary Form", "ordinary", Type.WATER, Type.FIGHTING, 1.4, 48.5, Abilities.JUSTIFIED, Abilities.NONE, Abilities.NONE, 580, 91, 72, 90, 129, 90, 108, 3, 35, 290, false, null, true),
|
||||
new PokemonForm("Resolute", "resolute", Type.WATER, Type.FIGHTING, 1.4, 48.5, Abilities.JUSTIFIED, Abilities.NONE, Abilities.NONE, 580, 91, 72, 90, 129, 90, 108, 3, 35, 290),
|
||||
),
|
||||
new PokemonSpecies(Species.MELOETTA, 5, false, false, true, "Melody Pokémon", Type.NORMAL, Type.PSYCHIC, 0.6, 6.5, Abilities.SERENE_GRACE, Abilities.NONE, Abilities.NONE, 600, 100, 77, 77, 128, 128, 90, 3, 100, 270, GrowthRate.SLOW, 0, false, true,
|
||||
new PokemonSpecies(Species.MELOETTA, 5, false, false, true, "Melody Pokémon", Type.NORMAL, Type.PSYCHIC, 0.6, 6.5, Abilities.SERENE_GRACE, Abilities.NONE, Abilities.NONE, 600, 100, 77, 77, 128, 128, 90, 3, 100, 270, GrowthRate.SLOW, null, false, true,
|
||||
new PokemonForm("Aria Forme", "aria", Type.NORMAL, Type.PSYCHIC, 0.6, 6.5, Abilities.SERENE_GRACE, Abilities.NONE, Abilities.NONE, 600, 100, 77, 77, 128, 128, 90, 3, 100, 270, false, null, true),
|
||||
new PokemonForm("Pirouette Forme", "pirouette", Type.NORMAL, Type.FIGHTING, 0.6, 6.5, Abilities.SERENE_GRACE, Abilities.NONE, Abilities.NONE, 600, 100, 128, 90, 77, 77, 128, 3, 100, 270),
|
||||
),
|
||||
|
@ -187,6 +187,7 @@ export class TrainerConfig {
|
||||
public isBoss: boolean = false;
|
||||
public hasStaticParty: boolean = false;
|
||||
public useSameSeedForAllMembers: boolean = false;
|
||||
public mixedBattleBgm: string;
|
||||
public battleBgm: string;
|
||||
public encounterBgm: string;
|
||||
public femaleEncounterBgm: string;
|
||||
@ -217,6 +218,7 @@ export class TrainerConfig {
|
||||
this.trainerType = trainerType;
|
||||
this.name = Utils.toReadableString(TrainerType[this.getDerivedType()]);
|
||||
this.battleBgm = "battle_trainer";
|
||||
this.mixedBattleBgm = "battle_trainer";
|
||||
this.victoryBgm = "victory_trainer";
|
||||
this.partyTemplates = [trainerPartyTemplates.TWO_AVG];
|
||||
this.speciesFilter = species => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden();
|
||||
@ -440,6 +442,11 @@ export class TrainerConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
setMixedBattleBgm(mixedBattleBgm: string): TrainerConfig {
|
||||
this.mixedBattleBgm = mixedBattleBgm;
|
||||
return this;
|
||||
}
|
||||
|
||||
setBattleBgm(battleBgm: string): TrainerConfig {
|
||||
this.battleBgm = battleBgm;
|
||||
return this;
|
||||
@ -605,7 +612,7 @@ export class TrainerConfig {
|
||||
this.setMoneyMultiplier(3.25);
|
||||
this.setBoss();
|
||||
this.setStaticParty();
|
||||
this.setBattleBgm("battle_elite");
|
||||
this.setBattleBgm("battle_unova_elite");
|
||||
this.setVictoryBgm("victory_gym");
|
||||
this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 2, specialtyTypes.length ? specialtyTypes : null));
|
||||
|
||||
@ -876,22 +883,22 @@ export const signatureSpecies: SignatureSpecies = {
|
||||
RYME: [Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU],
|
||||
TULIP: [Species.GIRAFARIG, Species.FLITTLE, Species.RALTS],
|
||||
GRUSHA: [Species.CETODDLE, Species.ALOLA_VULPIX, Species.CUBCHOO],
|
||||
LORELEI: [Species.SLOWBRO, Species.LAPRAS, Species.DEWGONG, Species.ALOLA_SANDSLASH],
|
||||
BRUNO: [Species.ONIX, Species.HITMONCHAN, Species.HITMONLEE, Species.ALOLA_GOLEM],
|
||||
AGATHA: [Species.GENGAR, Species.ARBOK, Species.CROBAT, Species.ALOLA_MAROWAK],
|
||||
LORELEI: [Species.JYNX, [Species.SLOWBRO, Species.GALAR_SLOWBRO], Species.LAPRAS, [Species.ALOLA_SANDSLASH, Species.CLOYSTER]],
|
||||
BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.ALOLA_GOLEM, Species.GOLEM]],
|
||||
AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK],
|
||||
LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR],
|
||||
WILL: [Species.XATU, Species.JYNX, Species.SLOWBRO, Species.EXEGGUTOR],
|
||||
KOGA: [Species.WEEZING, Species.VENOMOTH, Species.CROBAT, Species.TENTACRUEL],
|
||||
WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR],
|
||||
KOGA: [[Species.WEEZING, Species.MUK], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL],
|
||||
KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE],
|
||||
SIDNEY: [Species.SHIFTRY, Species.SHARPEDO, Species.ABSOL, Species.ZOROARK],
|
||||
PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, Species.CHANDELURE],
|
||||
SIDNEY: [[Species.SHIFTRY, Species.CACTURNE], [Species.SHARPEDO, Species.CRAWDAUNT], Species.ABSOL, Species.MIGHTYENA],
|
||||
PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.MISMAGIUS, Species.DRIFBLIM]],
|
||||
GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW],
|
||||
DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA],
|
||||
AARON: [Species.SCIZOR, Species.HERACROSS, Species.VESPIQUEN, Species.DRAPION],
|
||||
AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION],
|
||||
BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR],
|
||||
FLINT: [Species.FLAREON, Species.HOUNDOOM, Species.RAPIDASH, Species.INFERNAPE],
|
||||
LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, Species.ALAKAZAM],
|
||||
SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.DRIFBLIM],
|
||||
FLINT: [[Species.FLAREON, Species.RAPIDASH], Species.MAGMORTAR, [Species.STEELIX, Species.LOPUNNY], Species.INFERNAPE],
|
||||
LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]],
|
||||
SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT],
|
||||
MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK],
|
||||
GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE],
|
||||
CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS],
|
||||
@ -899,35 +906,35 @@ export const signatureSpecies: SignatureSpecies = {
|
||||
SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE],
|
||||
WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH],
|
||||
DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN],
|
||||
HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, Species.POLIWRATH],
|
||||
HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]],
|
||||
MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO],
|
||||
OLIVIA: [Species.ARMALDO, Species.CRADILY, Species.ALOLA_GOLEM, Species.LYCANROC],
|
||||
ACEROLA: [Species.BANETTE, Species.DRIFBLIM, Species.DHELMISE, Species.PALOSSAND],
|
||||
KAHILI: [Species.BRAVIARY, Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON],
|
||||
MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, Species.TOXICROAK, Species.SCRAFTY, Species.GRIMMSNARL],
|
||||
NESSA_ELITE: [Species.GOLISOPOD, Species.PELIPPER, Species.QUAGSIRE, Species.TOXAPEX, Species.DREDNAW],
|
||||
BEA_ELITE: [Species.HAWLUCHA, Species.GRAPPLOCT, Species.SIRFETCHD, Species.FALINKS, Species.MACHAMP],
|
||||
ALLISTER_ELITE:[Species.DUSKNOIR, Species.CHANDELURE, Species.CURSOLA, Species.RUNERIGUS, Species.GENGAR],
|
||||
RAIHAN_ELITE: [Species.TORKOAL, Species.GOODRA, Species.TURTONATOR, Species.FLYGON, Species.DURALUDON],
|
||||
RIKA: [Species.WHISCASH, Species.DONPHAN, Species.CAMERUPT, Species.CLODSIRE],
|
||||
OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC],
|
||||
ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND],
|
||||
KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON],
|
||||
MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL],
|
||||
NESSA_ELITE: [Species.GOLISOPOD, [Species.PELIPPER, Species.QUAGSIRE], Species.TOXAPEX, Species.DREDNAW],
|
||||
BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP],
|
||||
ALLISTER_ELITE:[Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR],
|
||||
RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON],
|
||||
RIKA: [Species.WHISCASH, [Species.DONPHAN, Species.DUGTRIO], Species.CAMERUPT, Species.CLODSIRE],
|
||||
POPPY: [Species.COPPERAJAH, Species.BRONZONG, Species.CORVIKNIGHT, Species.TINKATON],
|
||||
LARRY_ELITE: [Species.STARAPTOR, Species.FLAMIGO, Species.ALTARIA, Species.TROPIUS],
|
||||
HASSEL: [Species.NOIVERN, Species.HAXORUS, Species.DRAGALGE, Species.BAXCALIBUR],
|
||||
HASSEL: [Species.NOIVERN, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.BAXCALIBUR],
|
||||
CRISPIN: [Species.TALONFLAME, Species.CAMERUPT, Species.MAGMORTAR, Species.BLAZIKEN],
|
||||
AMARYS: [Species.SKARMORY, Species.EMPOLEON, Species.SCIZOR, Species.METAGROSS],
|
||||
LACEY: [Species.EXCADRILL, Species.PRIMARINA, Species.ALCREMIE, Species.GALAR_SLOWBRO],
|
||||
DRAYTON: [Species.DRAGONITE, Species.ARCHALUDON, Species.FLYGON, Species.SCEPTILE],
|
||||
LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.ALCREMIE, Species.GRANBULL], Species.WHIMSICOTT],
|
||||
DRAYTON: [Species.DRAGONITE, Species.ARCHALUDON, Species.HAXORUS, Species.SCEPTILE],
|
||||
BLUE: [[Species.GYARADOS, Species.EXEGGUTOR, Species.ARCANINE], Species.HO_OH, [Species.RHYPERIOR, Species.MAGNEZONE]], // Alakazam lead, Mega Pidgeot
|
||||
RED: [Species.LUGIA, Species.SNORLAX, [Species.ESPEON, Species.UMBREON, Species.SYLVEON]], // GMax Pikachu lead, Mega gen 1 starter
|
||||
LANCE_CHAMPION: [Species.DRAGONITE, Species.KINGDRA, Species.ALOLA_EXEGGUTOR], // Aerodactyl lead, Mega Lati@s
|
||||
STEVEN: [Species.AGGRON, [Species.ARMALDO, Species.CRADILY], Species.DIALGA], // Skarmorly lead, Mega Metagross
|
||||
LANCE_CHAMPION: [Species.DRAGONITE, Species.KINGDRA, Species.ALOLA_EXEGGUTOR], // Aerodactyl lead, Mega Latias/Latios
|
||||
STEVEN: [Species.AGGRON, [Species.ARMALDO, Species.CRADILY], Species.DIALGA], // Skarmory lead, Mega Metagross
|
||||
WALLACE: [Species.MILOTIC, Species.PALKIA, Species.LUDICOLO], // Pelipper lead, Mega Swampert
|
||||
CYNTHIA: [Species.GIRATINA, Species.LUCARIO, Species.TOGEKISS], // Spiritomb lead, Mega Garchomp
|
||||
ALDER: [Species.VOLCARONA, Species.ZEKROM, [Species.ACCELGOR, Species.ESCAVALIER], Species.KELDEO], // Bouffalant/Braviary lead
|
||||
IRIS: [Species.HAXORUS, Species.RESHIRAM, Species.ARCHEOPS], // Druddigon lead, Gmax Lapras
|
||||
DIANTHA: [Species.HAWLUCHA, Species.XERNEAS, Species.GOODRA], // Gourgeist lead, Mega Gardevoir
|
||||
HAU: [[Species.SOLGALEO, Species.LUNALA], Species.NOIVERN, [Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA], [Species.TAPU_BULU, Species.TAPU_FINI, Species.TAPU_KOKO, Species.TAPU_LELE]], // Alola Raichu lead
|
||||
LEON: [Species.DRAGAPULT, [Species.ZACIAN, Species.ZAMAZENTA], Species.AEGISLASH], // Rillaboom/Cinderace/Inteleon lead
|
||||
LEON: [Species.DRAGAPULT, [Species.ZACIAN, Species.ZAMAZENTA], Species.AEGISLASH], // Rillaboom/Cinderace/Inteleon lead, GMax Charizard
|
||||
GEETA: [Species.MIRAIDON, [Species.ESPATHRA, Species.VELUZA], [Species.AVALUGG, Species.HISUI_AVALUGG], Species.KINGAMBIT], // Glimmora lead
|
||||
NEMONA: [Species.KORAIDON, Species.PAWMOT, [Species.DUDUNSPARCE, Species.ORTHWORM], [Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL]], // Lycanroc lead
|
||||
KIERAN: [[Species.GRIMMSNARL, Species.INCINEROAR, Species.PORYGON_Z], Species.OGERPON, Species.TERAPAGOS, Species.HYDRAPPLE], // Poliwrath/Politoed lead
|
||||
@ -1059,6 +1066,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerType.RICH]: new TrainerConfig(++t).setMoneyMultiplier(5).setName("Gentleman").setHasGenders("Madame").setHasDouble("Rich Couple"),
|
||||
[TrainerType.RICH_KID]: new TrainerConfig(++t).setMoneyMultiplier(3.75).setName("Rich Boy").setHasGenders("Lady").setHasDouble("Rich Kids").setEncounterBgm(TrainerType.RICH),
|
||||
[TrainerType.ROUGHNECK]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.DARK)),
|
||||
[TrainerType.SAILOR]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.BACKPACKER).setSpeciesFilter(s => s.isOfType(Type.WATER) || s.isOfType(Type.FIGHTING)),
|
||||
[TrainerType.SCIENTIST]: new TrainerConfig(++t).setHasGenders("Scientist Female").setHasDouble("Scientists").setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.SCIENTIST)
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [Species.MAGNEMITE, Species.GRIMER, Species.DROWZEE, Species.VOLTORB, Species.KOFFING],
|
||||
@ -1095,124 +1103,124 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setSpeciesPools(
|
||||
[Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP]
|
||||
),
|
||||
[TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(signatureSpecies["BROCK"],true, Type.ROCK).setBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MISTY"],false, Type.WATER).setBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.LT_SURGE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LT_SURGE"],true, Type.ELECTRIC).setBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.ERIKA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ERIKA"],false, Type.GRASS).setBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.JANINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JANINE"],false, Type.POISON).setBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.SABRINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["SABRINA"],false, Type.PSYCHIC).setBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.BLAINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BLAINE"],true, Type.FIRE).setBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.GIOVANNI]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GIOVANNI"],true, Type.DARK).setBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.FALKNER]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FALKNER"],true, Type.FLYING).setBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.BUGSY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BUGSY"],true, Type.BUG).setBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WHITNEY"],false, Type.NORMAL).setBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.MORTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MORTY"],true, Type.GHOST).setBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHUCK"],true, Type.FIGHTING).setBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.JASMINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JASMINE"],false, Type.STEEL).setBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.PRYCE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["PRYCE"],true, Type.ICE).setBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.CLAIR]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLAIR"],false, Type.DRAGON).setBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.ROXANNE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROXANNE"],false, Type.ROCK).setBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.BRAWLY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRAWLY"],true, Type.FIGHTING).setBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.WATTSON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WATTSON"],true, Type.ELECTRIC).setBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.FLANNERY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FLANNERY"],false, Type.FIRE).setBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.NORMAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["NORMAN"],true, Type.NORMAL).setBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.WINONA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WINONA"],false, Type.FLYING).setBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.TATE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["TATE"],true, Type.PSYCHIC).setBattleBgm("battle_hoenn_gym").setHasDouble("tate_liza_double").setDoubleTrainerType(TrainerType.LIZA).setDoubleTitle("gym_leader_double"),
|
||||
[TrainerType.LIZA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LIZA"],false, Type.PSYCHIC).setBattleBgm("battle_hoenn_gym").setHasDouble("liza_tate_double").setDoubleTrainerType(TrainerType.TATE).setDoubleTitle("gym_leader_double"),
|
||||
[TrainerType.JUAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JUAN"],true, Type.WATER).setBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.ROARK]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROARK"],true, Type.ROCK).setBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.GARDENIA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GARDENIA"],false, Type.GRASS).setBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.MAYLENE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MAYLENE"],false, Type.FIGHTING).setBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.CRASHER_WAKE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CRASHER_WAKE"],true, Type.WATER).setBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.FANTINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FANTINA"],false, Type.GHOST).setBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.BYRON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BYRON"],true, Type.STEEL).setBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.CANDICE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CANDICE"],false, Type.ICE).setBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.VOLKNER]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VOLKNER"],true, Type.ELECTRIC).setBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.CILAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CILAN"],true, Type.GRASS),
|
||||
[TrainerType.CHILI]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHILI"],true, Type.FIRE),
|
||||
[TrainerType.CRESS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CRESS"],true, Type.WATER),
|
||||
[TrainerType.CHEREN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHEREN"],true, Type.NORMAL),
|
||||
[TrainerType.LENORA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LENORA"],false, Type.NORMAL),
|
||||
[TrainerType.ROXIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROXIE"],false, Type.POISON),
|
||||
[TrainerType.BURGH]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BURGH"],true, Type.BUG),
|
||||
[TrainerType.ELESA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ELESA"],false, Type.ELECTRIC),
|
||||
[TrainerType.CLAY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLAY"],true, Type.GROUND),
|
||||
[TrainerType.SKYLA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["SKYLA"],false, Type.FLYING),
|
||||
[TrainerType.BRYCEN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRYCEN"],true, Type.ICE),
|
||||
[TrainerType.DRAYDEN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["DRAYDEN"],true, Type.DRAGON),
|
||||
[TrainerType.MARLON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MARLON"],true, Type.WATER),
|
||||
[TrainerType.VIOLA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VIOLA"],false, Type.BUG),
|
||||
[TrainerType.GRANT]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GRANT"],true, Type.ROCK),
|
||||
[TrainerType.KORRINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KORRINA"],false, Type.FIGHTING),
|
||||
[TrainerType.RAMOS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["RAMOS"],true, Type.GRASS),
|
||||
[TrainerType.CLEMONT]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLEMONT"],true, Type.ELECTRIC),
|
||||
[TrainerType.VALERIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VALERIE"],false, Type.FAIRY),
|
||||
[TrainerType.OLYMPIA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["OLYMPIA"],false, Type.PSYCHIC),
|
||||
[TrainerType.WULFRIC]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WULFRIC"],true, Type.ICE),
|
||||
[TrainerType.MILO]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MILO"],true, Type.GRASS),
|
||||
[TrainerType.NESSA]: new TrainerConfig(++t).setName("Nessa").initForGymLeader(signatureSpecies["NESSA"],false, Type.WATER),
|
||||
[TrainerType.KABU]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KABU"],true, Type.FIRE),
|
||||
[TrainerType.BEA]: new TrainerConfig(++t).setName("Bea").initForGymLeader(signatureSpecies["BEA"],false, Type.FIGHTING),
|
||||
[TrainerType.ALLISTER]: new TrainerConfig(++t).setName("Allister").initForGymLeader(signatureSpecies["ALLISTER"],true, Type.GHOST),
|
||||
[TrainerType.OPAL]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["OPAL"],false, Type.FAIRY),
|
||||
[TrainerType.BEDE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BEDE"],true, Type.FAIRY),
|
||||
[TrainerType.GORDIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GORDIE"],true, Type.ROCK),
|
||||
[TrainerType.MELONY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MELONY"],false, Type.ICE),
|
||||
[TrainerType.PIERS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["PIERS"],true, Type.DARK).setHasDouble("piers_marnie_double").setDoubleTrainerType(TrainerType.MARNIE).setDoubleTitle("gym_leader_double"),
|
||||
[TrainerType.MARNIE]: new TrainerConfig(++t).setName("Marnie").initForGymLeader(signatureSpecies["MARNIE"],false, Type.DARK).setHasDouble("marnie_piers_double").setDoubleTrainerType(TrainerType.PIERS).setDoubleTitle("gym_leader_double"),
|
||||
[TrainerType.RAIHAN]: new TrainerConfig(++t).setName("Raihan").initForGymLeader(signatureSpecies["RAIHAN"],true, Type.DRAGON),
|
||||
[TrainerType.KATY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KATY"],false, Type.BUG),
|
||||
[TrainerType.BRASSIUS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRASSIUS"],true, Type.GRASS),
|
||||
[TrainerType.IONO]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["IONO"],false, Type.ELECTRIC),
|
||||
[TrainerType.KOFU]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KOFU"],true, Type.WATER),
|
||||
[TrainerType.LARRY]: new TrainerConfig(++t).setName("Larry").initForGymLeader(signatureSpecies["LARRY"],true, Type.NORMAL),
|
||||
[TrainerType.RYME]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["RYME"],false, Type.GHOST),
|
||||
[TrainerType.TULIP]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["TULIP"],false, Type.PSYCHIC),
|
||||
[TrainerType.GRUSHA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GRUSHA"],true, Type.ICE),
|
||||
[TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(signatureSpecies["BROCK"],true, Type.ROCK).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MISTY"],false, Type.WATER).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.LT_SURGE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LT_SURGE"],true, Type.ELECTRIC).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.ERIKA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ERIKA"],false, Type.GRASS).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.JANINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JANINE"],false, Type.POISON).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.SABRINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["SABRINA"],false, Type.PSYCHIC).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.BLAINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BLAINE"],true, Type.FIRE).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.GIOVANNI]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GIOVANNI"],true, Type.DARK).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.FALKNER]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FALKNER"],true, Type.FLYING).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.BUGSY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BUGSY"],true, Type.BUG).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WHITNEY"],false, Type.NORMAL).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.MORTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MORTY"],true, Type.GHOST).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHUCK"],true, Type.FIGHTING).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.JASMINE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JASMINE"],false, Type.STEEL).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.PRYCE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["PRYCE"],true, Type.ICE).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.CLAIR]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLAIR"],false, Type.DRAGON).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.ROXANNE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROXANNE"],false, Type.ROCK).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.BRAWLY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRAWLY"],true, Type.FIGHTING).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.WATTSON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WATTSON"],true, Type.ELECTRIC).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.FLANNERY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FLANNERY"],false, Type.FIRE).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.NORMAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["NORMAN"],true, Type.NORMAL).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.WINONA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WINONA"],false, Type.FLYING).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.TATE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["TATE"],true, Type.PSYCHIC).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym").setHasDouble("tate_liza_double").setDoubleTrainerType(TrainerType.LIZA).setDoubleTitle("gym_leader_double"),
|
||||
[TrainerType.LIZA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LIZA"],false, Type.PSYCHIC).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym").setHasDouble("liza_tate_double").setDoubleTrainerType(TrainerType.TATE).setDoubleTitle("gym_leader_double"),
|
||||
[TrainerType.JUAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["JUAN"],true, Type.WATER).setBattleBgm("battle_hoenn_gym").setMixedBattleBgm("battle_hoenn_gym"),
|
||||
[TrainerType.ROARK]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROARK"],true, Type.ROCK).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.GARDENIA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GARDENIA"],false, Type.GRASS).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.MAYLENE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MAYLENE"],false, Type.FIGHTING).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.CRASHER_WAKE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CRASHER_WAKE"],true, Type.WATER).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.FANTINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["FANTINA"],false, Type.GHOST).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.BYRON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BYRON"],true, Type.STEEL).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.CANDICE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CANDICE"],false, Type.ICE).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.VOLKNER]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VOLKNER"],true, Type.ELECTRIC).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.CILAN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CILAN"],true, Type.GRASS).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.CHILI]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHILI"],true, Type.FIRE).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.CRESS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CRESS"],true, Type.WATER).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.CHEREN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CHEREN"],true, Type.NORMAL).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.LENORA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LENORA"],false, Type.NORMAL).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.ROXIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ROXIE"],false, Type.POISON).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.BURGH]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BURGH"],true, Type.BUG).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.ELESA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["ELESA"],false, Type.ELECTRIC).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.CLAY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLAY"],true, Type.GROUND).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.SKYLA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["SKYLA"],false, Type.FLYING).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.BRYCEN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRYCEN"],true, Type.ICE).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.DRAYDEN]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["DRAYDEN"],true, Type.DRAGON).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.MARLON]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MARLON"],true, Type.WATER).setMixedBattleBgm("battle_unova_gym"),
|
||||
[TrainerType.VIOLA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VIOLA"],false, Type.BUG).setMixedBattleBgm("battle_kalos_gym"),
|
||||
[TrainerType.GRANT]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GRANT"],true, Type.ROCK).setMixedBattleBgm("battle_kalos_gym"),
|
||||
[TrainerType.KORRINA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KORRINA"],false, Type.FIGHTING).setMixedBattleBgm("battle_kalos_gym"),
|
||||
[TrainerType.RAMOS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["RAMOS"],true, Type.GRASS).setMixedBattleBgm("battle_kalos_gym"),
|
||||
[TrainerType.CLEMONT]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["CLEMONT"],true, Type.ELECTRIC).setMixedBattleBgm("battle_kalos_gym"),
|
||||
[TrainerType.VALERIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["VALERIE"],false, Type.FAIRY).setMixedBattleBgm("battle_kalos_gym"),
|
||||
[TrainerType.OLYMPIA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["OLYMPIA"],false, Type.PSYCHIC).setMixedBattleBgm("battle_kalos_gym"),
|
||||
[TrainerType.WULFRIC]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["WULFRIC"],true, Type.ICE).setMixedBattleBgm("battle_kalos_gym"),
|
||||
[TrainerType.MILO]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MILO"],true, Type.GRASS).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.NESSA]: new TrainerConfig(++t).setName("Nessa").initForGymLeader(signatureSpecies["NESSA"],false, Type.WATER).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.KABU]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KABU"],true, Type.FIRE).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.BEA]: new TrainerConfig(++t).setName("Bea").initForGymLeader(signatureSpecies["BEA"],false, Type.FIGHTING).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.ALLISTER]: new TrainerConfig(++t).setName("Allister").initForGymLeader(signatureSpecies["ALLISTER"],true, Type.GHOST).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.OPAL]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["OPAL"],false, Type.FAIRY).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.BEDE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BEDE"],true, Type.FAIRY).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.GORDIE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GORDIE"],true, Type.ROCK).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.MELONY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MELONY"],false, Type.ICE).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.PIERS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["PIERS"],true, Type.DARK).setHasDouble("piers_marnie_double").setDoubleTrainerType(TrainerType.MARNIE).setDoubleTitle("gym_leader_double").setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.MARNIE]: new TrainerConfig(++t).setName("Marnie").initForGymLeader(signatureSpecies["MARNIE"],false, Type.DARK).setHasDouble("marnie_piers_double").setDoubleTrainerType(TrainerType.PIERS).setDoubleTitle("gym_leader_double").setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.RAIHAN]: new TrainerConfig(++t).setName("Raihan").initForGymLeader(signatureSpecies["RAIHAN"],true, Type.DRAGON).setMixedBattleBgm("battle_galar_gym"),
|
||||
[TrainerType.KATY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KATY"],false, Type.BUG).setMixedBattleBgm("battle_paldea_gym"),
|
||||
[TrainerType.BRASSIUS]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["BRASSIUS"],true, Type.GRASS).setMixedBattleBgm("battle_paldea_gym"),
|
||||
[TrainerType.IONO]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["IONO"],false, Type.ELECTRIC).setMixedBattleBgm("battle_paldea_gym"),
|
||||
[TrainerType.KOFU]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["KOFU"],true, Type.WATER).setMixedBattleBgm("battle_paldea_gym"),
|
||||
[TrainerType.LARRY]: new TrainerConfig(++t).setName("Larry").initForGymLeader(signatureSpecies["LARRY"],true, Type.NORMAL).setMixedBattleBgm("battle_paldea_gym"),
|
||||
[TrainerType.RYME]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["RYME"],false, Type.GHOST).setMixedBattleBgm("battle_paldea_gym"),
|
||||
[TrainerType.TULIP]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["TULIP"],false, Type.PSYCHIC).setMixedBattleBgm("battle_paldea_gym"),
|
||||
[TrainerType.GRUSHA]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["GRUSHA"],true, Type.ICE).setMixedBattleBgm("battle_paldea_gym"),
|
||||
|
||||
[TrainerType.LORELEI]: new TrainerConfig((t = TrainerType.LORELEI)).initForEliteFour(signatureSpecies["LORELEI"],false, Type.ICE),
|
||||
[TrainerType.BRUNO]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["BRUNO"], true, Type.FIGHTING),
|
||||
[TrainerType.AGATHA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AGATHA"], false,Type.GHOST),
|
||||
[TrainerType.LANCE]: new TrainerConfig(++t).setName("Lance").initForEliteFour(signatureSpecies["LANCE"],true, Type.DRAGON),
|
||||
[TrainerType.WILL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["WILL"],true, Type.PSYCHIC),
|
||||
[TrainerType.KOGA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KOGA"], true, Type.POISON),
|
||||
[TrainerType.KAREN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KAREN"],false, Type.DARK),
|
||||
[TrainerType.SIDNEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SIDNEY"],true, Type.DARK),
|
||||
[TrainerType.PHOEBE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["PHOEBE"],false, Type.GHOST),
|
||||
[TrainerType.GLACIA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["GLACIA"],false, Type.ICE),
|
||||
[TrainerType.DRAKE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAKE"],true, Type.DRAGON),
|
||||
[TrainerType.AARON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AARON"],true, Type.BUG),
|
||||
[TrainerType.BERTHA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["BERTHA"],false, Type.GROUND),
|
||||
[TrainerType.FLINT]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["FLINT"],true, Type.FIRE),
|
||||
[TrainerType.LUCIAN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LUCIAN"], true,Type.PSYCHIC),
|
||||
[TrainerType.SHAUNTAL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SHAUNTAL"],false, Type.GHOST),
|
||||
[TrainerType.MARSHAL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MARSHAL"],true, Type.FIGHTING),
|
||||
[TrainerType.GRIMSLEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["GRIMSLEY"],true, Type.DARK),
|
||||
[TrainerType.CAITLIN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["CAITLIN"],false, Type.PSYCHIC),
|
||||
[TrainerType.MALVA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MALVA"], false,Type.FIRE),
|
||||
[TrainerType.SIEBOLD]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SIEBOLD"], true,Type.WATER),
|
||||
[TrainerType.WIKSTROM]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["WIKSTROM"],true, Type.STEEL),
|
||||
[TrainerType.DRASNA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRASNA"],false, Type.DRAGON),
|
||||
[TrainerType.HALA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["HALA"],true, Type.FIGHTING),
|
||||
[TrainerType.MOLAYNE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MOLAYNE"],true, Type.STEEL),
|
||||
[TrainerType.OLIVIA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["OLIVIA"],false, Type.ROCK),
|
||||
[TrainerType.ACEROLA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["ACEROLA"],false, Type.GHOST),
|
||||
[TrainerType.KAHILI]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KAHILI"],false, Type.FLYING),
|
||||
[TrainerType.MARNIE_ELITE]: new TrainerConfig(++t).setName("Marnie").initForEliteFour(signatureSpecies["MARNIE_ELITE"],false, Type.DARK),
|
||||
[TrainerType.NESSA_ELITE]: new TrainerConfig(++t).setName("Nessa").initForEliteFour(signatureSpecies["NESSA_ELITE"],false, Type.WATER),
|
||||
[TrainerType.BEA_ELITE]: new TrainerConfig(++t).setName("Bea").initForEliteFour(signatureSpecies["BEA_ELITE"],false, Type.FIGHTING),
|
||||
[TrainerType.ALLISTER_ELITE]: new TrainerConfig(++t).setName("Allister").initForEliteFour(signatureSpecies["ALLISTER_ELITE"],true, Type.GHOST),
|
||||
[TrainerType.RAIHAN_ELITE]: new TrainerConfig(++t).setName("Raihan").initForEliteFour(signatureSpecies["RAIHAN_ELITE"],true, Type.DRAGON),
|
||||
[TrainerType.RIKA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["RIKA"],false, Type.GROUND),
|
||||
[TrainerType.POPPY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["POPPY"],false, Type.STEEL),
|
||||
[TrainerType.LARRY_ELITE]: new TrainerConfig(++t).setName("Larry").initForEliteFour(signatureSpecies["LARRY_ELITE"],true, Type.NORMAL, Type.FLYING),
|
||||
[TrainerType.HASSEL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["HASSEL"],true, Type.DRAGON),
|
||||
[TrainerType.CRISPIN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["CRISPIN"],true, Type.FIRE),
|
||||
[TrainerType.AMARYS]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AMARYS"],false, Type.STEEL),
|
||||
[TrainerType.LACEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LACEY"],false, Type.FAIRY),
|
||||
[TrainerType.DRAYTON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAYTON"],true, Type.DRAGON),
|
||||
[TrainerType.LORELEI]: new TrainerConfig((t = TrainerType.LORELEI)).initForEliteFour(signatureSpecies["LORELEI"],false, Type.ICE).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.BRUNO]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["BRUNO"], true, Type.FIGHTING).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.AGATHA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AGATHA"], false,Type.GHOST).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.LANCE]: new TrainerConfig(++t).setName("Lance").initForEliteFour(signatureSpecies["LANCE"],true, Type.DRAGON).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.WILL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["WILL"],true, Type.PSYCHIC).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.KOGA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KOGA"], true, Type.POISON).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.KAREN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KAREN"],false, Type.DARK).setBattleBgm("battle_johto_gym").setMixedBattleBgm("battle_johto_gym"),
|
||||
[TrainerType.SIDNEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SIDNEY"],true, Type.DARK).setMixedBattleBgm("battle_hoenn_elite"),
|
||||
[TrainerType.PHOEBE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["PHOEBE"],false, Type.GHOST).setMixedBattleBgm("battle_hoenn_elite"),
|
||||
[TrainerType.GLACIA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["GLACIA"],false, Type.ICE).setMixedBattleBgm("battle_hoenn_elite"),
|
||||
[TrainerType.DRAKE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAKE"],true, Type.DRAGON).setMixedBattleBgm("battle_hoenn_elite"),
|
||||
[TrainerType.AARON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AARON"],true, Type.BUG).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.BERTHA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["BERTHA"],false, Type.GROUND).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.FLINT]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["FLINT"],true, Type.FIRE).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.LUCIAN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LUCIAN"], true,Type.PSYCHIC).setBattleBgm("battle_sinnoh_gym").setMixedBattleBgm("battle_sinnoh_gym"),
|
||||
[TrainerType.SHAUNTAL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SHAUNTAL"],false, Type.GHOST).setMixedBattleBgm("battle_unova_elite"),
|
||||
[TrainerType.MARSHAL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MARSHAL"],true, Type.FIGHTING).setMixedBattleBgm("battle_unova_elite"),
|
||||
[TrainerType.GRIMSLEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["GRIMSLEY"],true, Type.DARK).setMixedBattleBgm("battle_unova_elite"),
|
||||
[TrainerType.CAITLIN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["CAITLIN"],false, Type.PSYCHIC).setMixedBattleBgm("battle_unova_elite"),
|
||||
[TrainerType.MALVA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MALVA"], false,Type.FIRE).setMixedBattleBgm("battle_kalos_elite"),
|
||||
[TrainerType.SIEBOLD]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["SIEBOLD"], true,Type.WATER).setMixedBattleBgm("battle_kalos_elite"),
|
||||
[TrainerType.WIKSTROM]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["WIKSTROM"],true, Type.STEEL).setMixedBattleBgm("battle_kalos_elite"),
|
||||
[TrainerType.DRASNA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRASNA"],false, Type.DRAGON).setMixedBattleBgm("battle_kalos_elite"),
|
||||
[TrainerType.HALA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["HALA"],true, Type.FIGHTING).setMixedBattleBgm("battle_alola_elite"),
|
||||
[TrainerType.MOLAYNE]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["MOLAYNE"],true, Type.STEEL).setMixedBattleBgm("battle_alola_elite"),
|
||||
[TrainerType.OLIVIA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["OLIVIA"],false, Type.ROCK).setMixedBattleBgm("battle_alola_elite"),
|
||||
[TrainerType.ACEROLA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["ACEROLA"],false, Type.GHOST).setMixedBattleBgm("battle_alola_elite"),
|
||||
[TrainerType.KAHILI]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["KAHILI"],false, Type.FLYING).setMixedBattleBgm("battle_alola_elite"),
|
||||
[TrainerType.MARNIE_ELITE]: new TrainerConfig(++t).setName("Marnie").initForEliteFour(signatureSpecies["MARNIE_ELITE"],false, Type.DARK).setMixedBattleBgm("battle_galar_elite"),
|
||||
[TrainerType.NESSA_ELITE]: new TrainerConfig(++t).setName("Nessa").initForEliteFour(signatureSpecies["NESSA_ELITE"],false, Type.WATER).setMixedBattleBgm("battle_galar_elite"),
|
||||
[TrainerType.BEA_ELITE]: new TrainerConfig(++t).setName("Bea").initForEliteFour(signatureSpecies["BEA_ELITE"],false, Type.FIGHTING).setMixedBattleBgm("battle_galar_elite"),
|
||||
[TrainerType.ALLISTER_ELITE]: new TrainerConfig(++t).setName("Allister").initForEliteFour(signatureSpecies["ALLISTER_ELITE"],true, Type.GHOST).setMixedBattleBgm("battle_galar_elite"),
|
||||
[TrainerType.RAIHAN_ELITE]: new TrainerConfig(++t).setName("Raihan").initForEliteFour(signatureSpecies["RAIHAN_ELITE"],true, Type.DRAGON).setMixedBattleBgm("battle_galar_elite"),
|
||||
[TrainerType.RIKA]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["RIKA"],false, Type.GROUND).setMixedBattleBgm("battle_paldea_elite"),
|
||||
[TrainerType.POPPY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["POPPY"],false, Type.STEEL).setMixedBattleBgm("battle_paldea_elite"),
|
||||
[TrainerType.LARRY_ELITE]: new TrainerConfig(++t).setName("Larry").initForEliteFour(signatureSpecies["LARRY_ELITE"],true, Type.NORMAL, Type.FLYING).setMixedBattleBgm("battle_paldea_elite"),
|
||||
[TrainerType.HASSEL]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["HASSEL"],true, Type.DRAGON).setMixedBattleBgm("battle_paldea_elite"),
|
||||
[TrainerType.CRISPIN]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["CRISPIN"],true, Type.FIRE).setMixedBattleBgm("battle_bb_elite"),
|
||||
[TrainerType.AMARYS]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["AMARYS"],false, Type.STEEL).setMixedBattleBgm("battle_bb_elite"),
|
||||
[TrainerType.LACEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LACEY"],false, Type.FAIRY).setMixedBattleBgm("battle_bb_elite"),
|
||||
[TrainerType.DRAYTON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAYTON"],true, Type.DRAGON).setMixedBattleBgm("battle_bb_elite"),
|
||||
|
||||
[TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(signatureSpecies["BLUE"],true).setBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double")
|
||||
[TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(signatureSpecies["BLUE"],true).setBattleBgm("battle_kanto_champion").setMixedBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALAKAZAM], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
@ -1220,7 +1228,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.RED]: new TrainerConfig(++t).initForChampion(signatureSpecies["RED"],true).setBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double")
|
||||
[TrainerType.RED]: new TrainerConfig(++t).initForChampion(signatureSpecies["RED"],true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PIKACHU], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 8;
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -1229,7 +1237,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(signatureSpecies["LANCE_CHAMPION"],true).setBattleBgm("battle_johto_champion")
|
||||
[TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(signatureSpecies["LANCE_CHAMPION"],true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.AERODACTYL], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
@ -1237,7 +1245,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(signatureSpecies["STEVEN"],true).setBattleBgm("battle_hoenn_champion").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double")
|
||||
[TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(signatureSpecies["STEVEN"],true).setBattleBgm("battle_hoenn_champion").setMixedBattleBgm("battle_hoenn_champion").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SKARMORY], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
@ -1245,7 +1253,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(signatureSpecies["WALLACE"],true).setBattleBgm("battle_hoenn_champion").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double")
|
||||
[TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(signatureSpecies["WALLACE"],true).setBattleBgm("battle_hoenn_champion").setMixedBattleBgm("battle_hoenn_champion").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => {
|
||||
p.abilityIndex = 1; // Drizzle
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -1254,7 +1262,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(signatureSpecies["CYNTHIA"],false).setBattleBgm("battle_sinnoh_champion")
|
||||
[TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(signatureSpecies["CYNTHIA"],false).setBattleBgm("battle_sinnoh_champion").setMixedBattleBgm("battle_sinnoh_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SPIRITOMB], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
@ -1262,11 +1270,11 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(signatureSpecies["ALDER"],true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder")
|
||||
[TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(signatureSpecies["ALDER"],true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder").setMixedBattleBgm("battle_champion_alder")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BOUFFALANT, Species.BRAVIARY], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(signatureSpecies["IRIS"],false).setBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double")
|
||||
[TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(signatureSpecies["IRIS"],false).setBattleBgm("battle_champion_iris").setMixedBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DRUDDIGON], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
@ -1274,7 +1282,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(signatureSpecies["DIANTHA"],false)
|
||||
[TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(signatureSpecies["DIANTHA"],false).setMixedBattleBgm("battle_kalos_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GOURGEIST], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
@ -1282,11 +1290,11 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.HAU]: new TrainerConfig(++t).initForChampion(signatureSpecies["HAU"],true)
|
||||
[TrainerType.HAU]: new TrainerConfig(++t).initForChampion(signatureSpecies["HAU"],true).setMixedBattleBgm("battle_alola_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALOLA_RAICHU], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.LEON]: new TrainerConfig(++t).initForChampion(signatureSpecies["LEON"],true)
|
||||
[TrainerType.LEON]: new TrainerConfig(++t).initForChampion(signatureSpecies["LEON"],true).setMixedBattleBgm("battle_galar_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.RILLABOOM, Species.CINDERACE, Species.INTELEON], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
@ -1294,15 +1302,16 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 3;
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(signatureSpecies["GEETA"],false)
|
||||
[TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(signatureSpecies["GEETA"],false).setMixedBattleBgm("battle_champion_geeta")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GLIMMORA], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(signatureSpecies["NEMONA"],false)
|
||||
[TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(signatureSpecies["NEMONA"],false).setMixedBattleBgm("battle_champion_nemona")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 0; // Midday form
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
[TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(signatureSpecies["KIERAN"],true)
|
||||
[TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(signatureSpecies["KIERAN"],true).setMixedBattleBgm("battle_champion_kieran")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.POLIWRATH, Species.POLITOED], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
|