From b183f26330831ca4668a7024eb631da6be7d5307 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Fri, 9 May 2025 00:16:06 -0700 Subject: [PATCH 01/26] Update version to 1.9.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index da89f87b0bd..02a5d375588 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pokemon-rogue-battle", - "version": "1.9.2", + "version": "1.9.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pokemon-rogue-battle", - "version": "1.9.2", + "version": "1.9.3", "hasInstallScript": true, "dependencies": { "@material/material-color-utilities": "^0.2.7", diff --git a/package.json b/package.json index d5eb1138776..715deefbe32 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.9.2", + "version": "1.9.3", "type": "module", "scripts": { "start": "vite", From 0712f86462fde33333f84024988fd11521724046 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 9 May 2025 01:34:28 -0700 Subject: [PATCH 02/26] [Bug][Hotfix] Fix crashes when loading save with a transformed pokemon (#5806) * Fix speciesForm being saved incorrectly * Fix transformed icon * Fix moveset loading errors --- src/battle-scene.ts | 8 ++++---- src/field/pokemon.ts | 2 +- src/system/pokemon-data.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 39bd1dd64cf..9f70b33b296 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1045,7 +1045,7 @@ export default class BattleScene extends SceneBase { y: number, originX = 0.5, originY = 0.5, - ignoreOverride = false, + ignoreOverride = true, useIllusion = false, ): Phaser.GameObjects.Container { const container = this.add.container(x, y); @@ -1053,9 +1053,9 @@ export default class BattleScene extends SceneBase { const icon = this.add.sprite(0, 0, pokemon.getIconAtlasKey(ignoreOverride, useIllusion)); icon.setName(`sprite-${pokemon.name}-icon`); - icon.setFrame(pokemon.getIconId(true, useIllusion)); + icon.setFrame(pokemon.getIconId(ignoreOverride, useIllusion)); // Temporary fix to show pokemon's default icon if variant icon doesn't exist - if (icon.frame.name !== pokemon.getIconId(true, useIllusion)) { + if (icon.frame.name !== pokemon.getIconId(ignoreOverride, useIllusion)) { console.log(`${pokemon.name}'s variant icon does not exist. Replacing with default.`); const temp = pokemon.shiny; pokemon.shiny = false; @@ -1071,7 +1071,7 @@ export default class BattleScene extends SceneBase { const fusionIcon = this.add.sprite(0, 0, pokemon.getFusionIconAtlasKey(ignoreOverride, useIllusion)); fusionIcon.setName("sprite-fusion-icon"); fusionIcon.setOrigin(0.5, 0); - fusionIcon.setFrame(pokemon.getFusionIconId(true, useIllusion)); + fusionIcon.setFrame(pokemon.getFusionIconId(ignoreOverride, useIllusion)); const originalWidth = icon.width; const originalHeight = icon.height; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 6a05bea4c6d..43669c874a9 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -7862,7 +7862,7 @@ export class PokemonSummonData { } if (key === "moveset") { - this.moveset = value.map((m: any) => PokemonMove.loadMove(m)); + this.moveset = value?.map((m: any) => PokemonMove.loadMove(m)); continue; } diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 8d4fd7c05df..00169678ed0 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -188,7 +188,7 @@ export default class PokemonData { // when loading from saved session, recover summonData.speciesFrom and form index species object // used to stay transformed on reload session if (this.summonData.speciesForm) { - this.summonData.speciesForm = getPokemonSpeciesForm( + ret.summonData.speciesForm = getPokemonSpeciesForm( this.summonData.speciesForm.speciesId, this.summonDataSpeciesFormIndex, ); From 09e38bad39d33f21eeec6f95c944a4c31dc7a13f Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Sat, 10 May 2025 19:05:18 -0500 Subject: [PATCH 03/26] Set lastHit to true when target faints during multi-hit move --- src/phases/move-effect-phase.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index c65e8e15271..462e4ba47b8 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -905,6 +905,14 @@ export class MoveEffectPhase extends PokemonPhase { target.destroySubstitute(); target.lapseTag(BattlerTagType.COMMANDED); + + // Force `lastHit` to be true if this is a multi hit move with hits left + // `hitsLeft` must be left as-is in order for the message displaying the number of hits + // to display the proper number. + // Note: When Dragon Darts' smart targeting is implemented, this logic may need to be adjusted. + if (!this.lastHit && user.turnData.hitsLeft > 1) { + this.lastHit = true; + } } /** From 6c6821b47d96df23a6b71f508e1a810a70d4b1ec Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Sun, 11 May 2025 20:10:19 -0500 Subject: [PATCH 04/26] [Bug] [Move] Fix KO causing effects to occur twice (#5811) * Fix firstTarget calculation when a target was fainted * Update type annotation in applyMoveEffects Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- src/phases/move-effect-phase.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 462e4ba47b8..d067807486d 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -206,11 +206,13 @@ export class MoveEffectPhase extends PokemonPhase { * @throws Error if there was an unexpected hit check result */ private applyToTargets(user: Pokemon, targets: Pokemon[]): void { + let firstHit = true; for (const [i, target] of targets.entries()) { const [hitCheckResult, effectiveness] = this.hitChecks[i]; switch (hitCheckResult) { case HitCheckResult.HIT: - this.applyMoveEffects(target, effectiveness); + this.applyMoveEffects(target, effectiveness, firstHit); + firstHit = false; if (isFieldTargeted(this.move)) { // Stop processing other targets if the move is a field move return; @@ -763,15 +765,12 @@ export class MoveEffectPhase extends PokemonPhase { * - Invoking {@linkcode applyOnTargetEffects} if the move does not hit a substitute * - Triggering form changes and emergency exit / wimp out if this is the last hit * - * @param target the {@linkcode Pokemon} hit by this phase's move. - * @param effectiveness the effectiveness of the move (as previously evaluated in {@linkcode hitCheck}) + * @param target - the {@linkcode Pokemon} hit by this phase's move. + * @param effectiveness - The effectiveness of the move (as previously evaluated in {@linkcode hitCheck}) + * @param firstTarget - Whether this is the first target successfully struck by the move */ - protected applyMoveEffects(target: Pokemon, effectiveness: TypeDamageMultiplier): void { + protected applyMoveEffects(target: Pokemon, effectiveness: TypeDamageMultiplier, firstTarget: boolean): void { const user = this.getUserPokemon(); - - /** The first target hit by the move */ - const firstTarget = target === this.getTargets().find((_, i) => this.hitChecks[i][1] > 0); - if (isNullOrUndefined(user)) { return; } From d790b30a30f26fd9a31af96b4b84c83d7b61151a Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Sun, 11 May 2025 18:23:37 -0700 Subject: [PATCH 05/26] [Bug][Hotfix] Fix Transformed Sprites not loading properly (#5808) * Fix ditto sprite not loading properly * Remove review comment --- src/field/pokemon.ts | 17 ++++++++++------- src/system/game-data.ts | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 43669c874a9..eec20beb01c 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -909,19 +909,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const originalWarn = console.warn; // Ignore warnings for missing frames, because there will be a lot console.warn = () => {}; - const battleFrameNames = globalScene.anims.generateFrameNames(this.getBattleSpriteKey(), { + const battleSpriteKey = this.getBattleSpriteKey(this.isPlayer(), ignoreOverride); + const battleFrameNames = globalScene.anims.generateFrameNames(battleSpriteKey, { zeroPad: 4, suffix: ".png", start: 1, end: 400, }); console.warn = originalWarn; - globalScene.anims.create({ - key: this.getBattleSpriteKey(), - frames: battleFrameNames, - frameRate: 10, - repeat: -1, - }); + if (!globalScene.anims.exists(battleSpriteKey)) { + globalScene.anims.create({ + key: battleSpriteKey, + frames: battleFrameNames, + frameRate: 10, + repeat: -1, + }); + } } // With everything loaded, now begin playing the animation. this.playAnim(); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 51e488210be..0c5e0b349ed 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -1110,7 +1110,7 @@ export class GameData { for (const p of sessionData.party) { const pokemon = p.toPokemon() as PlayerPokemon; pokemon.setVisible(false); - loadPokemonAssets.push(pokemon.loadAssets()); + loadPokemonAssets.push(pokemon.loadAssets(false)); party.push(pokemon); } From 9b1a222935a032a65432103c8875c46439b6a3e9 Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Mon, 12 May 2025 15:33:52 -0500 Subject: [PATCH 06/26] [Bug] Fix old session load modifier crash (#5814) Fix inability to load saves due to modifier type being nulled --- src/battle-scene.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 9f70b33b296..5835ee08af5 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -2921,7 +2921,10 @@ export default class BattleScene extends SceneBase { instant?: boolean, cost?: number, ): boolean { - if (!modifier) { + // We check against modifier.type to stop a bug related to loading in a pokemon that has a form change item, which prior to some patch + // that changed form change modifiers worked, had previously set the `type` field to null. + // TODO: This is not the right place to check for this; it should ideally go in a session migrator. + if (!modifier || !modifier.type) { return false; } let success = false; From 30ba53894ec6de86e7373803852ed26047db052a Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Mon, 12 May 2025 17:58:28 -0700 Subject: [PATCH 07/26] [i18n] Update locales --- public/locales | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales b/public/locales index f4b8b7b737e..ee6bb371afe 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit f4b8b7b737e47eaf7e7231855d0b59f8c7c7c0f8 +Subproject commit ee6bb371afefe4c6d872cc7765f0e0d26e630d4e From 84192cd3230be998c1e4a1b2620993545144dcc9 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 15 May 2025 14:51:16 -0700 Subject: [PATCH 08/26] Update version to 1.9.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 02a5d375588..66400b14459 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pokemon-rogue-battle", - "version": "1.9.3", + "version": "1.9.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pokemon-rogue-battle", - "version": "1.9.3", + "version": "1.9.4", "hasInstallScript": true, "dependencies": { "@material/material-color-utilities": "^0.2.7", diff --git a/package.json b/package.json index 715deefbe32..7d1ba35154a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.9.3", + "version": "1.9.4", "type": "module", "scripts": { "start": "vite", From 0c48fff14bbca1628134934b1e1b9c4e078d0997 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Sat, 17 May 2025 08:35:38 -0700 Subject: [PATCH 09/26] [Bug] Fix Substitute sprite crash & revived Pokemon softlock (#5829) Break `resetSummonData` into two methods Co-authored-by: damocleas Co-authored-by: Bertie690 <136088738+Bertie690@users.noreply.github.com> Co-authored-by: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Co-authored-by: lxy-lxy-lxy <55084073+lxy-lxy-lxy@users.noreply.github.com> Co-authored-by: Xavion3 Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Co-authored-by: Lylian BALL <131535108+PyGaVS@users.noreply.github.com> --- src/field/pokemon.ts | 32 ++++++++++++++++++++----------- src/phases/encounter-phase.ts | 2 +- src/phases/summon-phase.ts | 2 ++ src/phases/switch-summon-phase.ts | 2 +- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index eec20beb01c..983494b36c8 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5721,17 +5721,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * Reset this Pokemon's {@linkcode PokemonSummonData | SummonData} and {@linkcode PokemonTempSummonData | TempSummonData} - * in preparation for switching pokemon, as well as removing any relevant on-switch tags. + * Performs miscellaneous setup for when the Pokemon is summoned, like generating the substitute sprite + * @param resetSummonData - Whether to additionally reset the Pokemon's summon data (default: `false`) */ - resetSummonData(): void { - const illusion: IllusionData | null = this.summonData.illusion; - if (this.summonData.speciesForm) { - this.summonData.speciesForm = null; - this.updateFusionPalette(); - } - this.summonData = new PokemonSummonData(); - this.tempSummonData = new PokemonTempSummonData(); + public fieldSetup(resetSummonData?: boolean): void { this.setSwitchOutStatus(false); if (globalScene) { globalScene.triggerPokemonFormChange( @@ -5740,7 +5733,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { true, ); } - // If this Pokemon has a Substitute when loading in, play an animation to add its sprite if (this.getTag(SubstituteTag)) { globalScene.triggerPokemonBattleAnim( @@ -5758,6 +5750,24 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ) { this.setVisible(false); } + + if (resetSummonData) { + this.resetSummonData(); + } + } + + /** + * Reset this Pokemon's {@linkcode PokemonSummonData | SummonData} and {@linkcode PokemonTempSummonData | TempSummonData} + * in preparation for switching pokemon, as well as removing any relevant on-switch tags. + */ + resetSummonData(): void { + const illusion: IllusionData | null = this.summonData.illusion; + if (this.summonData.speciesForm) { + this.summonData.speciesForm = null; + this.updateFusionPalette(); + } + this.summonData = new PokemonSummonData(); + this.tempSummonData = new PokemonTempSummonData(); this.summonData.illusion = illusion this.updateInfo(); } diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index 5b799bd9316..3cfd2b9a901 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -146,7 +146,7 @@ export class EncounterPhase extends BattlePhase { const enemyPokemon = globalScene.getEnemyParty()[e]; if (e < (battle.double ? 2 : 1)) { enemyPokemon.setX(-66 + enemyPokemon.getFieldPositionOffset()[0]); - enemyPokemon.resetSummonData(); + enemyPokemon.fieldSetup(true); } if (!this.loaded) { diff --git a/src/phases/summon-phase.ts b/src/phases/summon-phase.ts index fef9b356348..c217583f163 100644 --- a/src/phases/summon-phase.ts +++ b/src/phases/summon-phase.ts @@ -196,6 +196,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { onComplete: () => { pokemon.cry(pokemon.getHpRatio() > 0.25 ? undefined : { rate: 0.85 }); pokemon.getSprite().clearTint(); + pokemon.fieldSetup(); // necessary to stay transformed during wild waves if (pokemon.summonData.speciesForm) { pokemon.loadAssets(false); @@ -261,6 +262,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { onComplete: () => { pokemon.cry(pokemon.getHpRatio() > 0.25 ? undefined : { rate: 0.85 }); pokemon.getSprite().clearTint(); + pokemon.fieldSetup(); globalScene.updateFieldScale(); globalScene.time.delayedCall(1000, () => this.end()); }, diff --git a/src/phases/switch-summon-phase.ts b/src/phases/switch-summon-phase.ts index bb31f87cc3d..a063b6e6863 100644 --- a/src/phases/switch-summon-phase.ts +++ b/src/phases/switch-summon-phase.ts @@ -193,7 +193,7 @@ export class SwitchSummonPhase extends SummonPhase { switchedInPokemon.setAlpha(0.5); } } else { - switchedInPokemon.resetSummonData(); + switchedInPokemon.fieldSetup(true); } this.summon(); }; From 998619e7e565ff06c1624f6b4d22ab444554a037 Mon Sep 17 00:00:00 2001 From: Jimmybald1 <122436263+Jimmybald1@users.noreply.github.com> Date: Sat, 17 May 2025 17:36:16 +0200 Subject: [PATCH 10/26] [Bug] IVs of trainers were incorrectly using the battle seed (#5822) * Fixed IVs of trainers using the Battle Seed. * Renamed the randSeedInt functions that use the Battle Seed to randBattleSeedInt functions * Incorrectly used this in common * Fixed tests that were still calling the old function name --------- Co-authored-by: damocleas Co-authored-by: Bertie690 <136088738+Bertie690@users.noreply.github.com> Co-authored-by: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Co-authored-by: Dean <69436131+emdeann@users.noreply.github.com> Co-authored-by: lxy-lxy-lxy <55084073+lxy-lxy-lxy@users.noreply.github.com> Co-authored-by: Xavion3 Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Co-authored-by: Lylian BALL <131535108+PyGaVS@users.noreply.github.com> Co-authored-by: Jimmybald1 <147992650+IBBCalc@users.noreply.github.com> --- src/data/abilities/ability.ts | 36 +- src/data/battler-tags.ts | 8 +- src/data/moves/move.ts | 52 +- src/data/trainers/trainer-config.ts | 693 ++++++++++++++++++------ src/field/pokemon.ts | 16 +- src/modifier/modifier.ts | 14 +- src/phases/attempt-capture-phase.ts | 6 +- src/phases/attempt-run-phase.ts | 2 +- src/phases/move-effect-phase.ts | 2 +- src/phases/move-phase.ts | 4 +- src/utils/common.ts | 10 + test/abilities/cud_chew.test.ts | 2 +- test/abilities/desolate-land.test.ts | 2 +- test/abilities/neutralizing_gas.test.ts | 2 +- test/items/reviver_seed.test.ts | 2 +- test/moves/u_turn.test.ts | 2 +- 16 files changed, 608 insertions(+), 245 deletions(-) diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 4609ff6ec1a..ff86937622b 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -850,14 +850,14 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && !attacker.status - && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) + && (this.chance === -1 || pokemon.randBattleSeedInt(100) < this.chance) && attacker.canSetStatus(effect, true, false, pokemon); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; attacker.trySetStatus(effect, true, pokemon); } } @@ -891,7 +891,7 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && pokemon.randSeedInt(100) < this.chance + return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && pokemon.randBattleSeedInt(100) < this.chance && attacker.canAddTag(this.tagType); } @@ -1068,7 +1068,7 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { return attacker.getTag(BattlerTagType.DISABLED) === null - && move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance); + && move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && (this.chance === -1 || pokemon.randBattleSeedInt(100) < this.chance); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { @@ -1741,7 +1741,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { const heldItems = this.getTargetHeldItems(defender).filter((i) => i.isTransferable); if (heldItems.length) { // Ensure that the stolen item in testing is the same as when the effect is applied - this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)]; if (globalScene.canTransferHeldItemModifier(this.stolenItem, pokemon)) { return true; } @@ -1762,7 +1762,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { ): void { const heldItems = this.getTargetHeldItems(defender).filter((i) => i.isTransferable); if (!this.stolenItem) { - this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)]; } if (globalScene.tryTransferHeldItemModifier(this.stolenItem, pokemon, false)) { globalScene.queueMessage( @@ -1799,9 +1799,9 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { if ( super.canApplyPostAttack(pokemon, passive, simulated, attacker, move, hitResult, args) && (simulated || !attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker - && (!this.contactRequired || move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon})) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) + && (!this.contactRequired || move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon})) && pokemon.randBattleSeedInt(100) < this.chance && !pokemon.status) ) { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; return simulated || attacker.canSetStatus(effect, true, false, pokemon); } @@ -1809,7 +1809,7 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { } applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; attacker.trySetStatus(effect, true, pokemon); } } @@ -1839,12 +1839,12 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { return super.canApplyPostAttack(pokemon, passive, simulated, attacker, move, hitResult, args) && !attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && (!this.contactRequired || move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon})) && - pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status; + pokemon.randBattleSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status; } override applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { if (!simulated) { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; attacker.addTag(effect); } } @@ -1868,7 +1868,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { ) { const heldItems = this.getTargetHeldItems(attacker).filter((i) => i.isTransferable); if (heldItems.length) { - this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)]; if (globalScene.canTransferHeldItemModifier(this.stolenItem, pokemon)) { return true; } @@ -1889,7 +1889,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { const heldItems = this.getTargetHeldItems(attacker).filter((i) => i.isTransferable); if (!this.stolenItem) { - this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)]; } if (globalScene.tryTransferHeldItemModifier(this.stolenItem, pokemon, false)) { globalScene.queueMessage( @@ -3171,7 +3171,7 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { */ override applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { if (!simulated) { - defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 5), move.id, defender.id); + defender.addTag(BattlerTagType.CONFUSED, pokemon.randBattleSeedIntRange(2, 5), move.id, defender.id); } } } @@ -4235,12 +4235,12 @@ export class MoodyAbAttr extends PostTurnAbAttr { if (!simulated) { if (canRaise.length > 0) { - const raisedStat = canRaise[pokemon.randSeedInt(canRaise.length)]; + const raisedStat = canRaise[pokemon.randBattleSeedInt(canRaise.length)]; canLower = canRaise.filter(s => s !== raisedStat); globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ raisedStat ], 2)); } if (canLower.length > 0) { - const loweredStat = canLower[pokemon.randSeedInt(canLower.length)]; + const loweredStat = canLower[pokemon.randBattleSeedInt(canLower.length)]; globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ loweredStat ], -1)); } } @@ -5349,7 +5349,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr { const isCommandFight = turnCommand?.command === Command.FIGHT; const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null; const isDamageMove = move?.category === MoveCategory.PHYSICAL || move?.category === MoveCategory.SPECIAL; - return !simulated && !bypassSpeed.value && pokemon.randSeedInt(100) < this.chance && isCommandFight && isDamageMove; + return !simulated && !bypassSpeed.value && pokemon.randBattleSeedInt(100) < this.chance && isCommandFight && isDamageMove; } /** diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 8a512f3c16c..34fdd5409c8 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -766,11 +766,11 @@ export class ConfusedTag extends BattlerTag { globalScene.unshiftPhase(new CommonAnimPhase(pokemon.getBattlerIndex(), undefined, CommonAnim.CONFUSION)); // 1/3 chance of hitting self with a 40 base power move - if (pokemon.randSeedInt(3) === 0 || Overrides.CONFUSION_ACTIVATION_OVERRIDE === true) { + if (pokemon.randBattleSeedInt(3) === 0 || Overrides.CONFUSION_ACTIVATION_OVERRIDE === true) { const atk = pokemon.getEffectiveStat(Stat.ATK); const def = pokemon.getEffectiveStat(Stat.DEF); const damage = toDmgValue( - ((((2 * pokemon.level) / 5 + 2) * 40 * atk) / def / 50 + 2) * (pokemon.randSeedIntRange(85, 100) / 100), + ((((2 * pokemon.level) / 5 + 2) * 40 * atk) / def / 50 + 2) * (pokemon.randBattleSeedIntRange(85, 100) / 100), ); // Intentionally don't increment rage fist's hitCount globalScene.queueMessage(i18next.t("battlerTags:confusedLapseHurtItself")); @@ -890,7 +890,7 @@ export class InfatuatedTag extends BattlerTag { ); globalScene.unshiftPhase(new CommonAnimPhase(pokemon.getBattlerIndex(), undefined, CommonAnim.ATTRACT)); - if (pokemon.randSeedInt(2)) { + if (pokemon.randBattleSeedInt(2)) { globalScene.queueMessage( i18next.t("battlerTags:infatuatedLapseImmobilize", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), @@ -1119,7 +1119,7 @@ export class FrenzyTag extends BattlerTag { if (this.turnCount < 2) { // Only add CONFUSED tag if a disruption occurs on the final confusion-inducing turn of FRENZY - pokemon.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 4)); + pokemon.addTag(BattlerTagType.CONFUSED, pokemon.randBattleSeedIntRange(2, 4)); } } } diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 3ef70fd75be..235cb954ea5 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -1591,7 +1591,7 @@ export class RandomLevelDamageAttr extends FixedDamageAttr { } getDamage(user: Pokemon, target: Pokemon, move: Move): number { - return toDmgValue(user.level * (user.randSeedIntRange(50, 150) * 0.01)); + return toDmgValue(user.level * (user.randBattleSeedIntRange(50, 150) * 0.01)); } } @@ -2352,7 +2352,7 @@ export class MultiHitAttr extends MoveAttr { switch (this.multiHitType) { case MultiHitType._2_TO_5: { - const rand = user.randSeedInt(20); + const rand = user.randBattleSeedInt(20); const hitValue = new NumberHolder(rand); applyAbAttrs(MaxMultiHitAbAttr, user, null, false, hitValue); if (hitValue.value >= 13) { @@ -2453,7 +2453,7 @@ export class StatusEffectAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); - const statusCheck = moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance; + const statusCheck = moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance; const quiet = move.category !== MoveCategory.STATUS; if (statusCheck) { const pokemon = this.selfTarget ? user : target; @@ -2560,7 +2560,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr { const poolType = target.isPlayer() ? ModifierPoolType.PLAYER : target.hasTrainer() ? ModifierPoolType.TRAINER : ModifierPoolType.WILD; const highestItemTier = heldItems.map((m) => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier!, highestTier), 0); // TODO: is the bang after tier correct? const tierHeldItems = heldItems.filter((m) => m.type.getOrInferTier(poolType) === highestItemTier); - const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)]; + const stolenItem = tierHeldItems[user.randBattleSeedInt(tierHeldItems.length)]; if (!globalScene.tryTransferHeldItemModifier(stolenItem, user, false)) { return false; } @@ -2636,7 +2636,7 @@ export class RemoveHeldItemAttr extends MoveEffectAttr { return false; } - const removedItem = heldItems[user.randSeedInt(heldItems.length)]; + const removedItem = heldItems[user.randBattleSeedInt(heldItems.length)]; // Decrease item amount and update icon target.loseHeldItem(removedItem); @@ -2697,7 +2697,7 @@ export class EatBerryAttr extends MoveEffectAttr { } // pick a random berry to gobble and check if we preserve it - this.chosenBerry = heldBerries[user.randSeedInt(heldBerries.length)]; + this.chosenBerry = heldBerries[user.randBattleSeedInt(heldBerries.length)]; const preserve = new BooleanHolder(false); // check for berry pouch preservation globalScene.applyModifiers(PreserveBerryModifier, pokemon.isPlayer(), pokemon, preserve); @@ -2774,7 +2774,7 @@ export class StealEatBerryAttr extends EatBerryAttr { } // pick a random berry and eat it - this.chosenBerry = heldBerries[user.randSeedInt(heldBerries.length)]; + this.chosenBerry = heldBerries[user.randBattleSeedInt(heldBerries.length)]; applyPostItemLostAbAttrs(PostItemLostAbAttr, target, false); const message = i18next.t("battle:stealEatBerry", { pokemonName: user.name, targetName: target.name, berryName: this.chosenBerry.type.name }); globalScene.queueMessage(message); @@ -3205,7 +3205,7 @@ export class StatStageChangeAttr extends MoveEffectAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { + if (moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) { const stages = this.getLevels(user); globalScene.unshiftPhase(new StatStageChangePhase((this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, stages, this.showMessage)); return true; @@ -3431,7 +3431,7 @@ export class AcupressureStatStageChangeAttr extends MoveEffectAttr { override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const randStats = BATTLE_STATS.filter((s) => target.getStatStage(s) < 6); if (randStats.length > 0) { - const boostStat = [ randStats[user.randSeedInt(randStats.length)] ]; + const boostStat = [ randStats[user.randBattleSeedInt(randStats.length)] ]; globalScene.unshiftPhase(new StatStageChangePhase(target.getBattlerIndex(), this.selfTarget, boostStat, 2)); return true; } @@ -4823,7 +4823,7 @@ export class ShellSideArmCategoryAttr extends VariableMoveCategoryAttr { if (predictedPhysDmg > predictedSpecDmg) { category.value = MoveCategory.PHYSICAL; return true; - } else if (predictedPhysDmg === predictedSpecDmg && user.randSeedInt(2) === 0) { + } else if (predictedPhysDmg === predictedSpecDmg && user.randBattleSeedInt(2) === 0) { category.value = MoveCategory.PHYSICAL; return true; } @@ -5404,7 +5404,7 @@ export class FrenzyAttr extends MoveEffectAttr { } if (!user.getTag(BattlerTagType.FRENZY) && !user.getMoveQueue().length) { - const turnCount = user.randSeedIntRange(1, 2); + const turnCount = user.randBattleSeedIntRange(1, 2); new Array(turnCount).fill(null).map(() => user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true })); user.addTag(BattlerTagType.FRENZY, turnCount, move.id, user.id); } else { @@ -5485,8 +5485,8 @@ export class AddBattlerTagAttr extends MoveEffectAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { - return (this.selfTarget ? user : target).addTag(this.tagType, user.randSeedIntRange(this.turnCountMin, this.turnCountMax), move.id, user.id); + if (moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) { + return (this.selfTarget ? user : target).addTag(this.tagType, user.randBattleSeedIntRange(this.turnCountMin, this.turnCountMax), move.id, user.id); } return false; @@ -5654,7 +5654,7 @@ export class JawLockAttr extends AddBattlerTagAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { + if (moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) { /** * Add the tag to both the user and the target. * The target's tag source is considered to be the user and vice versa @@ -5792,7 +5792,7 @@ export class ProtectAttr extends AddBattlerTagAttr { timesUsed++; } if (timesUsed) { - return !user.randSeedInt(Math.pow(3, timesUsed)); + return !user.randBattleSeedInt(Math.pow(3, timesUsed)); } return true; }); @@ -5916,7 +5916,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { return false; } - if ((move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { + if ((move.chance < 0 || move.chance === 100 || user.randBattleSeedInt(100) < move.chance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { const side = ((this.selfSideTarget ? user : target).isPlayer() !== (move.hasAttr(AddArenaTrapTagAttr) && target === user)) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; globalScene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, side); return true; @@ -5992,7 +5992,7 @@ export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const tag = globalScene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; - if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { + if ((moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { globalScene.arena.addTag(this.tagType, 0, move.id, user.id, side); if (!tag) { return true; @@ -6167,7 +6167,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { // If used by an enemy trainer with at least one fainted non-boss Pokemon, this // revives one of said Pokemon selected at random. const faintedPokemon = globalScene.getEnemyParty().filter((p) => p.isFainted() && !p.isBoss()); - const pokemon = faintedPokemon[user.randSeedInt(faintedPokemon.length)]; + const pokemon = faintedPokemon[user.randBattleSeedInt(faintedPokemon.length)]; const slotIndex = globalScene.getEnemyParty().findIndex((p) => pokemon.id === p.id); pokemon.resetStatus(true, false, false, true); pokemon.heal(Math.min(toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); @@ -6263,7 +6263,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { if (switchOutTarget.hp > 0) { if (this.switchType === SwitchType.FORCE_SWITCH) { switchOutTarget.leaveField(true); - const slotIndex = eligibleNewIndices[user.randSeedInt(eligibleNewIndices.length)]; + const slotIndex = eligibleNewIndices[user.randBattleSeedInt(eligibleNewIndices.length)]; globalScene.prependToPhase( new SwitchSummonPhase( this.switchType, @@ -6306,7 +6306,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { if (switchOutTarget.hp > 0) { if (this.switchType === SwitchType.FORCE_SWITCH) { switchOutTarget.leaveField(true); - const slotIndex = eligibleNewIndices[user.randSeedInt(eligibleNewIndices.length)]; + const slotIndex = eligibleNewIndices[user.randBattleSeedInt(eligibleNewIndices.length)]; globalScene.prependToPhase( new SwitchSummonPhase( this.switchType, @@ -6725,7 +6725,7 @@ class CallMoveAttr extends OverrideMoveEffectAttr { } const targets = moveTargets.multiple || moveTargets.targets.length === 1 ? moveTargets.targets - : [ this.hasTarget ? target.getBattlerIndex() : moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ]; // account for Mirror Move having a target already + : [ this.hasTarget ? target.getBattlerIndex() : moveTargets.targets[user.randBattleSeedInt(moveTargets.targets.length)] ]; // account for Mirror Move having a target already user.getMoveQueue().push({ move: move.id, targets: targets, virtual: true, ignorePP: true }); globalScene.unshiftPhase(new LoadMoveAnimPhase(move.id)); globalScene.unshiftPhase(new MovePhase(user, targets, new PokemonMove(move.id, 0, 0, true), true, true)); @@ -6765,7 +6765,7 @@ export class RandomMoveAttr extends CallMoveAttr { const moveIds = getEnumValues(Moves).map(m => !this.invalidMoves.has(m) && !allMoves[m].name.endsWith(" (N)") ? m : Moves.NONE); let moveId: Moves = Moves.NONE; do { - moveId = this.getMoveOverride() ?? moveIds[user.randSeedInt(moveIds.length)]; + moveId = this.getMoveOverride() ?? moveIds[user.randBattleSeedInt(moveIds.length)]; } while (moveId === Moves.NONE); return super.apply(user, target, allMoves[moveId], args); @@ -6817,7 +6817,7 @@ export class RandomMovesetMoveAttr extends CallMoveAttr { return false; } - this.moveId = moves[user.randSeedInt(moves.length)]!.moveId; + this.moveId = moves[user.randBattleSeedInt(moves.length)]!.moveId; return true; }; } @@ -7900,7 +7900,7 @@ const phaseForcedSlower = (phase: MovePhase, target: Pokemon, trickRoom: boolean let slower: boolean; // quashed pokemon still have speed ties if (phase.pokemon.getEffectiveStat(Stat.SPD) === target.getEffectiveStat(Stat.SPD)) { - slower = !!target.randSeedInt(2); + slower = !!target.randBattleSeedInt(2); } else { slower = !trickRoom ? phase.pokemon.getEffectiveStat(Stat.SPD) < target.getEffectiveStat(Stat.SPD) : phase.pokemon.getEffectiveStat(Stat.SPD) > target.getEffectiveStat(Stat.SPD); } @@ -8103,7 +8103,7 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr { if (!validTypes.length) { return false; } - const type = validTypes[user.randSeedInt(validTypes.length)]; + const type = validTypes[user.randBattleSeedInt(validTypes.length)]; user.summonData.types = [ type ]; globalScene.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: toReadableString(PokemonType[type]) })); user.updateInfo(); @@ -8218,7 +8218,7 @@ export function getMoveTargets(user: Pokemon, move: Moves, replaceTarget?: MoveT multiple = moveTarget !== MoveTarget.NEAR_ENEMY; break; case MoveTarget.RANDOM_NEAR_ENEMY: - set = [ opponents[user.randSeedInt(opponents.length)] ]; + set = [ opponents[user.randBattleSeedInt(opponents.length)] ]; break; case MoveTarget.ATTACKER: return { targets: [ -1 as BattlerIndex ], multiple: false }; diff --git a/src/data/trainers/trainer-config.ts b/src/data/trainers/trainer-config.ts index 50acf84efa6..839a1cdc0cc 100644 --- a/src/data/trainers/trainer-config.ts +++ b/src/data/trainers/trainer-config.ts @@ -1,7 +1,7 @@ import { globalScene } from "#app/global-scene"; import { modifierTypes } from "#app/modifier/modifier-type"; import { PokemonMove } from "#app/field/pokemon"; -import { toReadableString, isNullOrUndefined, randSeedItem, randSeedInt } from "#app/utils/common"; +import { toReadableString, isNullOrUndefined, randSeedItem, randSeedInt, randSeedIntRange } from "#app/utils/common"; import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { tmSpecies } from "#app/data/balance/tms"; @@ -2856,21 +2856,29 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["LORELEI"], false, PokemonType.ICE, 2) .setBattleBgm("battle_kanto_gym") .setMixedBattleBgm("battle_kanto_gym") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DEWGONG], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.DEWGONG], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 0; // Thick Fat p.generateAndPopulateMoveset(); }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SLOWBRO, Species.GALAR_SLOWBRO], TrainerSlot.TRAINER, true, p => { // Tera Ice Slowbro/G-Slowbro + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.SLOWBRO, Species.GALAR_SLOWBRO], TrainerSlot.TRAINER, true, p => { + // Tera Ice Slowbro/G-Slowbro p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.ICE_BEAM)) { // Check if Ice Beam is in the moveset, if not, replace the third move with Ice Beam. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.ICE_BEAM)) { + // Check if Ice Beam is in the moveset, if not, replace the third move with Ice Beam. p.moveset[2] = new PokemonMove(Moves.ICE_BEAM); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.JYNX])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CLOYSTER, Species.ALOLA_SANDSLASH])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2880,9 +2888,13 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_kanto_gym") .setMixedBattleBgm("battle_kanto_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.HITMONLEE, Species.HITMONCHAN, Species.HITMONTOP])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.STEELIX], TrainerSlot.TRAINER, true, p => { // Tera Fighting Steelix + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.STEELIX], TrainerSlot.TRAINER, true, p => { + // Tera Fighting Steelix p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.BODY_PRESS)) { // Check if Body Press is in the moveset, if not, replace the third move with Body Press. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.BODY_PRESS)) { + // Check if Body Press is in the moveset, if not, replace the third move with Body Press. p.moveset[2] = new PokemonMove(Moves.BODY_PRESS); } }), @@ -2901,16 +2913,22 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_kanto_gym") .setMixedBattleBgm("battle_kanto_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.MISMAGIUS])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.ARBOK, Species.WEEZING], TrainerSlot.TRAINER, true, p => { // Tera Ghost Arbok/Weezing + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.ARBOK, Species.WEEZING], TrainerSlot.TRAINER, true, p => { + // Tera Ghost Arbok/Weezing p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.ALOLA_MAROWAK])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CURSOLA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2921,16 +2939,22 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_kanto_gym") .setMixedBattleBgm("battle_kanto_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.KINGDRA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GYARADOS, Species.AERODACTYL], TrainerSlot.TRAINER, true, p => { // Tera Dragon Gyarados/Aerodactyl + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.GYARADOS, Species.AERODACTYL], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Gyarados/Aerodactyl p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.ALOLA_EXEGGUTOR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SALAMENCE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DRAGONITE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DRAGONITE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2943,7 +2967,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SLOWKING, Species.GALAR_SLOWKING])) // Tera Psychic Slowking/G-Slowking .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.EXEGGUTOR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.WYRDEER, Species.FARIGIRAF])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.XATU], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.XATU], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2952,7 +2978,9 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["KOGA"], true, PokemonType.POISON, 2) .setBattleBgm("battle_johto_gym") .setMixedBattleBgm("battle_johto_gym") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENOMOTH], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.VENOMOTH], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Tinted Lens p.generateAndPopulateMoveset(); }), @@ -2960,7 +2988,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MUK, Species.WEEZING])) // Tera Poison Muk/Weezing .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TENTACRUEL])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SNEASLER, Species.OVERQWIL])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CROBAT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CROBAT], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2970,16 +3000,22 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_johto_gym") .setMixedBattleBgm("battle_johto_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.UMBREON])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { // Tera Dark Gengar + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { + // Tera Dark Gengar p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.DARK_PULSE)) { // Check if Dark Pulse is in the moveset, if not, replace the third move with Dark Pulse. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.DARK_PULSE)) { + // Check if Dark Pulse is in the moveset, if not, replace the third move with Dark Pulse. p.moveset[2] = new PokemonMove(Moves.DARK_PULSE); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.HONCHKROW])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.WEAVILE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.HOUNDOOM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.HOUNDOOM], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2987,7 +3023,9 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.SIDNEY]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["SIDNEY"], true, PokemonType.DARK, 2) .setMixedBattleBgm("battle_hoenn_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.MIGHTYENA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.MIGHTYENA], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 0; // Intimidate p.generateAndPopulateMoveset(); }), @@ -3008,12 +3046,16 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SABLEYE])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.BANETTE])) // Tera Ghost Banette .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.DRIFBLIM, Species.MISMAGIUS])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ORICORIO, Species.ALOLA_MAROWAK], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.ORICORIO, Species.ALOLA_MAROWAK], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.formIndex = p.species.speciesId === Species.ORICORIO ? 3 : 0; // Oricorio-Sensu }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DUSKNOIR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DUSKNOIR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3021,7 +3063,9 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.GLACIA]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["GLACIA"], false, PokemonType.ICE, 2) .setMixedBattleBgm("battle_hoenn_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ABOMASNOW], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.ABOMASNOW], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 0; // Snow Warning p.generateAndPopulateMoveset(); }), @@ -3029,7 +3073,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GLALIE])) // Tera Ice Glalie .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.FROSLASS])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ALOLA_NINETALES])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.WALREIN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.WALREIN], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3038,16 +3084,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["DRAKE"], true, PokemonType.DRAGON, 2) .setMixedBattleBgm("battle_hoenn_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALTARIA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.DHELMISE], TrainerSlot.TRAINER, true, p => { // Tera Dragon Dhelmise + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.DHELMISE], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Dhelmise p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.FLYGON])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.KINGDRA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.SALAMENCE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.SALAMENCE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3060,11 +3112,15 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HERACROSS])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.VESPIQUEN])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SCIZOR, Species.KLEAVOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DRAPION], TrainerSlot.TRAINER, true, p => { // Tera Bug Drapion + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DRAPION], TrainerSlot.TRAINER, true, p => { + // Tera Bug Drapion p.setBoss(true, 2); p.abilityIndex = 1; // Sniper p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.X_SCISSOR)) { // Check if X-Scissor is in the moveset, if not, replace the third move with X-Scissor. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.X_SCISSOR)) { + // Check if X-Scissor is in the moveset, if not, replace the third move with X-Scissor. p.moveset[2] = new PokemonMove(Moves.X_SCISSOR); } }), @@ -3074,14 +3130,19 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_sinnoh_gym") .setMixedBattleBgm("battle_sinnoh_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.WHISCASH])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HIPPOWDON], TrainerSlot.TRAINER, true, p => { // Tera Ground Hippowdon + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.HIPPOWDON], TrainerSlot.TRAINER, true, p => { + // Tera Ground Hippowdon p.abilityIndex = 0; // Sand Stream p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GLISCOR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MAMOSWINE, Species.URSALUNA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.RHYPERIOR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.RHYPERIOR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.abilityIndex = 1; // Solid Rock p.generateAndPopulateMoveset(); @@ -3092,16 +3153,22 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_sinnoh_gym") .setMixedBattleBgm("battle_sinnoh_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.RAPIDASH])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.STEELIX, Species.LOPUNNY], TrainerSlot.TRAINER, true, p => { // Tera Fire Steelix/Lopunny + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.STEELIX, Species.LOPUNNY], TrainerSlot.TRAINER, true, p => { + // Tera Fire Steelix/Lopunny p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.INFERNAPE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ARCANINE, Species.HISUI_ARCANINE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MAGMORTAR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.MAGMORTAR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3114,7 +3181,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.FARIGIRAF])) // Tera Psychic Farigiraf .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BRONZONG])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MR_RIME, Species.HISUI_BRAVIARY])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GALLADE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GALLADE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.abilityIndex = 1; // Sharpness p.generateAndPopulateMoveset(); @@ -3126,8 +3195,10 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.COFAGRIGUS])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GOLURK])) // Tera Ghost Golurk .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.JELLICENT])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MISMAGIUS, Species.FROSLASS ])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CHANDELURE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MISMAGIUS, Species.FROSLASS])) + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CHANDELURE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3139,7 +3210,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MIENSHAO])) // Tera Fighting Mienshao .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.EMBOAR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.BRELOOM, Species.TOXICROAK])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CONKELDURR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CONKELDURR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3151,7 +3224,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.KROOKODILE])) // Tera Dark Krookodile .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SCRAFTY])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ZOROARK, Species.HISUI_SAMUROTT])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.KINGAMBIT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.KINGAMBIT], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3161,7 +3236,9 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_unova_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.MUSHARNA])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.REUNICLUS])) // Tera Psychic Reuniclus - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GALLADE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.GALLADE], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Sharpness p.generateAndPopulateMoveset(); }), @@ -3177,19 +3254,25 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.MALVA]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["MALVA"], false, PokemonType.FIRE, 2) .setMixedBattleBgm("battle_kalos_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PYROAR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.PYROAR], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.FEMALE; }), ) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HOUNDOOM])) // Tera Fire Houndoom - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TORKOAL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TORKOAL], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drought p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CHANDELURE, Species.DELPHOX])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.TALONFLAME], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.TALONFLAME], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3201,7 +3284,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GYARADOS])) // Tera Water Gyarados .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.STARMIE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.BLASTOISE, Species.DONDOZO])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.BARBARACLE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.BARBARACLE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.abilityIndex = 1; // Tough Claws p.generateAndPopulateMoveset(); @@ -3211,16 +3296,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["WIKSTROM"], true, PokemonType.STEEL, 2) .setMixedBattleBgm("battle_kalos_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.KLEFKI])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.CERULEDGE], TrainerSlot.TRAINER, true, p => { // Tera Steel Ceruledge + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.CERULEDGE], TrainerSlot.TRAINER, true, p => { + // Tera Steel Ceruledge p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.IRON_HEAD)) { // Check if Iron Head is in the moveset, if not, replace the third move with Iron Head. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.IRON_HEAD)) { + // Check if Iron Head is in the moveset, if not, replace the third move with Iron Head. p.moveset[2] = new PokemonMove(Moves.IRON_HEAD); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SCIZOR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CORVIKNIGHT])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.AEGISLASH], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.AEGISLASH], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3232,7 +3323,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GARCHOMP])) // Tera Dragon Garchomp .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.ALTARIA])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.DRUDDIGON])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.NOIVERN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.NOIVERN], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3241,16 +3334,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["HALA"], true, PokemonType.FIGHTING, 2) .setMixedBattleBgm("battle_alola_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.HARIYAMA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.INCINEROAR], TrainerSlot.TRAINER, true, p => { // Tera Fighting Incineroar + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.INCINEROAR], TrainerSlot.TRAINER, true, p => { + // Tera Fighting Incineroar p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.CROSS_CHOP)) { // Check if Cross Chop is in the moveset, if not, replace the third move with Cross Chop. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.CROSS_CHOP)) { + // Check if Cross Chop is in the moveset, if not, replace the third move with Cross Chop. p.moveset[2] = new PokemonMove(Moves.CROSS_CHOP); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BEWEAR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.POLIWRATH, Species.ANNIHILAPE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CRABOMINABLE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CRABOMINABLE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3262,7 +3361,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.ALOLA_SANDSLASH])) // Tera Steel A-Sandslash .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.MAGNEZONE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.METAGROSS, Species.KINGAMBIT])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.ALOLA_DUGTRIO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.ALOLA_DUGTRIO], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3270,7 +3371,9 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.OLIVIA]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["OLIVIA"], false, PokemonType.ROCK, 2) .setMixedBattleBgm("battle_alola_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GIGALITH], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.GIGALITH], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Sand Stream p.generateAndPopulateMoveset(); }), @@ -3278,7 +3381,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.PROBOPASS])) // Tera Rock Probopass .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.ALOLA_GOLEM])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.RELICANTH, Species.CARBINK])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.formIndex = 1; p.generateAndPopulateMoveset(); @@ -3291,7 +3396,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MIMIKYU])) // Tera Ghost Mimikyu .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.DHELMISE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.FROSLASS])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.PALOSSAND], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.PALOSSAND], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3300,16 +3407,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["KAHILI"], false, PokemonType.FLYING, 2) .setMixedBattleBgm("battle_alola_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.HAWLUCHA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.DECIDUEYE], TrainerSlot.TRAINER, true, p => { // Tera Flying Decidueye + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.DECIDUEYE], TrainerSlot.TRAINER, true, p => { + // Tera Flying Decidueye p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.BRAVE_BIRD)) { // Check if Brave Bird is in the moveset, if not, replace the third move with Brave Bird. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.BRAVE_BIRD)) { + // Check if Brave Bird is in the moveset, if not, replace the third move with Brave Bird. p.moveset[2] = new PokemonMove(Moves.BRAVE_BIRD); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BRAVIARY, Species.MANDIBUZZ])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ORICORIO])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.TOUCANNON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.TOUCANNON], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3319,7 +3432,10 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["MARNIE_ELITE"], false, PokemonType.DARK, 2) .setMixedBattleBgm("battle_galar_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LIEPARD])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.TOXICROAK], TrainerSlot.TRAINER, true, p => { // Tera Dark Toxicroak + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.TOXICROAK], TrainerSlot.TRAINER, true, p => { + // Tera Dark Toxicroak p.generateAndPopulateMoveset(); if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.SUCKER_PUNCH)) { // Check if Sucker Punch is in the moveset, if not, replace the third move with Sucker Punch. @@ -3329,7 +3445,9 @@ export const trainerConfigs: TrainerConfigs = { ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SCRAFTY, Species.PANGORO])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MORPEKO])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GRIMMSNARL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GRIMMSNARL], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3339,20 +3457,28 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["NESSA_ELITE"], false, PokemonType.WATER, 2) .setMixedBattleBgm("battle_galar_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GOLISOPOD])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.EISCUE], TrainerSlot.TRAINER, true, p => { // Tera Water Eiscue + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.EISCUE], TrainerSlot.TRAINER, true, p => { + // Tera Water Eiscue p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.LIQUIDATION)) { // Check if Liquidation is in the moveset, if not, replace the third move with Liquidation. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.LIQUIDATION)) { + // Check if Liquidation is in the moveset, if not, replace the third move with Liquidation. p.moveset[2] = new PokemonMove(Moves.LIQUIDATION); } }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drizzle p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.TOXAPEX])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DREDNAW], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DREDNAW], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3365,7 +3491,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SIRFETCHD])) // Tera Fighting Sirfetch'd .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GRAPPLOCT, Species.FALINKS])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.HITMONTOP])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MACHAMP], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.MACHAMP], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3378,7 +3506,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.RUNERIGUS])) // Tera Ghost Runerigus .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.POLTEAGEIST, Species.SINISTCHA])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CURSOLA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3388,17 +3518,23 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["RAIHAN_ELITE"], true, PokemonType.DRAGON, 2) .setMixedBattleBgm("battle_galar_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.FLYGON])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.TORKOAL], TrainerSlot.TRAINER, true, p => { // Tera Dragon Torkoal + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.TORKOAL], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Torkoal p.abilityIndex = 1; // Drought p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GOODRA])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.TURTONATOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3410,7 +3546,10 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.DONPHAN])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SWAMPERT, Species.TORTERRA])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CAMERUPT])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CLODSIRE], TrainerSlot.TRAINER, true, p => { // Tera Ground Clodsire + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CLODSIRE], TrainerSlot.TRAINER, true, p => { + // Tera Ground Clodsire p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3420,13 +3559,18 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_paldea_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.COPPERAJAH])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MAGNEZONE])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BRONZONG, Species.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.BRONZONG, Species.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { p.abilityIndex = p.species.speciesId === Species.BRONZONG ? 0 : 1; // Levitate Bronzong, Unnerve Corviknight p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.STEELIX])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.TINKATON], TrainerSlot.TRAINER, true, p => { // Tera Steel Tinkaton + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.TINKATON], TrainerSlot.TRAINER, true, p => { + // Tera Steel Tinkaton p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3439,7 +3583,10 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.BOMBIRDIER])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TROPIUS])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.STARAPTOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.FLAMIGO], TrainerSlot.TRAINER, true, p => { // Tera Flying Flamigo + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.FLAMIGO], TrainerSlot.TRAINER, true, p => { + // Tera Flying Flamigo p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3451,7 +3598,10 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.DRAGALGE])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.FLAPPLE, Species.APPLETUN, Species.HYDRAPPLE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.HAXORUS])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.BAXCALIBUR], TrainerSlot.TRAINER, true, p => { // Tera Dragon Baxcalibur + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.BAXCALIBUR], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Baxcalibur p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3459,27 +3609,38 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.CRISPIN]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["CRISPIN"], true, PokemonType.FIRE, 2) .setMixedBattleBgm("battle_bb_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ROTOM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.ROTOM], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Heat Rotom p.generateAndPopulateMoveset(); }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.EXEGGUTOR], TrainerSlot.TRAINER, true, p => { // Tera Fire Exeggutor + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.EXEGGUTOR], TrainerSlot.TRAINER, true, p => { + // Tera Fire Exeggutor p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TALONFLAME], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TALONFLAME], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.SUNNY_DAY)) { // Check if Sunny Day is in the moveset, if not, replace the third move with Sunny Day. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.SUNNY_DAY)) { + // Check if Sunny Day is in the moveset, if not, replace the third move with Sunny Day. p.moveset[2] = new PokemonMove(Moves.SUNNY_DAY); } }), ) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MAGMORTAR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.BLAZIKEN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.BLAZIKEN], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3488,16 +3649,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["AMARYS"], false, PokemonType.STEEL, 2) .setMixedBattleBgm("battle_bb_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SKARMORY])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.REUNICLUS], TrainerSlot.TRAINER, true, p => { // Tera Steel Reuniclus + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.REUNICLUS], TrainerSlot.TRAINER, true, p => { + // Tera Steel Reuniclus p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.FLASH_CANNON)) { // Check if Flash Cannon is in the moveset, if not, replace the third move with Flash Cannon. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.FLASH_CANNON)) { + // Check if Flash Cannon is in the moveset, if not, replace the third move with Flash Cannon. p.moveset[2] = new PokemonMove(Moves.FLASH_CANNON); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.EMPOLEON])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SCIZOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3509,10 +3676,14 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.PRIMARINA])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GRANBULL])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ALCREMIE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.EXCADRILL], TrainerSlot.TRAINER, true, p => { // Tera Fairy Excadrill + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.EXCADRILL], TrainerSlot.TRAINER, true, p => { + // Tera Fairy Excadrill p.setBoss(true, 2); p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), @@ -3521,16 +3692,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["DRAYTON"], true, PokemonType.DRAGON, 2) .setMixedBattleBgm("battle_bb_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DRAGONITE])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SCEPTILE], TrainerSlot.TRAINER, true, p => { // Tera Dragon Sceptile + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.SCEPTILE], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Sceptile p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.DUAL_CHOP)) { // Check if Dual Chop is in the moveset, if not, replace the third move with Dual Chop. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.DUAL_CHOP)) { + // Check if Dual Chop is in the moveset, if not, replace the third move with Dual Chop. p.moveset[2] = new PokemonMove(Moves.DUAL_CHOP); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.HAXORUS])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.KINGDRA, Species.DRACOVISH])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3545,18 +3722,29 @@ export const trainerConfigs: TrainerConfigs = { .setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALAKAZAM])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.MACHAMP])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HO_OH], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.HO_OH], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.RHYPERIOR, Species.ELECTIVIRE])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ARCANINE, Species.EXEGGUTOR, Species.GYARADOS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc( + [Species.ARCANINE, Species.EXEGGUTOR, Species.GYARADOS], + TrainerSlot.TRAINER, + true, + p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); - }), + }, + ), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.PIDGEOT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.PIDGEOT], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Pidgeot p.generateAndPopulateMoveset(); p.generateName(); @@ -3571,7 +3759,9 @@ export const trainerConfigs: TrainerConfigs = { .setHasDouble("red_blue_double") .setDoubleTrainerType(TrainerType.BLUE) .setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PIKACHU], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.PIKACHU], TrainerSlot.TRAINER, true, p => { p.formIndex = 8; // G-Max Pikachu p.generateAndPopulateMoveset(); p.generateName(); @@ -3579,24 +3769,34 @@ export const trainerConfigs: TrainerConfigs = { }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.ESPEON, Species.UMBREON, Species.SYLVEON])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.LUGIA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.LUGIA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SNORLAX], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.SNORLAX], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc( - [Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc( + [Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE], + TrainerSlot.TRAINER, + true, + p => { p.formIndex = 1; // Mega Venusaur, Mega Charizard X, or Mega Blastoise p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.MALE; - }), + }, + ), ) .setInstantTera(3), // Tera Grass Meganium / Fire Typhlosion / Water Feraligatr [TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t) @@ -3606,20 +3806,26 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_johto_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GYARADOS, Species.KINGDRA])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.AERODACTYL])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SALAMENCE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.SALAMENCE], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Salamence p.generateAndPopulateMoveset(); p.generateName(); }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.CHARIZARD])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.TYRANITAR, Species.GARCHOMP, Species.KOMMO_O], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.TYRANITAR, Species.GARCHOMP, Species.KOMMO_O], TrainerSlot.TRAINER, true, p => { p.teraType = PokemonType.DRAGON; p.generateAndPopulateMoveset(); p.abilityIndex = p.species.speciesId === Species.KOMMO_O ? 1 : 2; // Soundproof Kommo-o, Unnerve Tyranitar, Rough Skin Garchomp }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DRAGONITE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DRAGONITE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); @@ -3635,18 +3841,24 @@ export const trainerConfigs: TrainerConfigs = { .setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SKARMORY])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.CRADILY, Species.ARMALDO])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.AGGRON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.AGGRON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GOLURK, Species.RUNERIGUS])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.REGIROCK, Species.REGICE, Species.REGISTEEL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.REGIROCK, Species.REGICE, Species.REGISTEEL], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Metagross p.generateAndPopulateMoveset(); p.generateName(); @@ -3660,13 +3872,17 @@ export const trainerConfigs: TrainerConfigs = { .setHasDouble("wallace_steven_double") .setDoubleTrainerType(TrainerType.STEVEN) .setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drizzle p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.LUDICOLO])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.LATIAS, Species.LATIOS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.LATIAS, Species.LATIOS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Latios or Mega Latias p.generateAndPopulateMoveset(); p.generateName(); @@ -3674,12 +3890,16 @@ export const trainerConfigs: TrainerConfigs = { }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SWAMPERT, Species.GASTRODON, Species.SEISMITOAD])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.REGIELEKI, Species.REGIDRAGO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.REGIELEKI, Species.REGIDRAGO], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MILOTIC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.MILOTIC], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.FEMALE; p.setBoss(true, 2); @@ -3692,22 +3912,35 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_sinnoh_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SPIRITOMB])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.LUCARIO])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GIRATINA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.GIRATINA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.MILOTIC, Species.ROSERADE, Species.HISUI_ARCANINE], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.teraType = p.species.type1; - }), + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc( + [Species.MILOTIC, Species.ROSERADE, Species.HISUI_ARCANINE], + TrainerSlot.TRAINER, + true, + p => { + p.generateAndPopulateMoveset(); + p.teraType = p.species.type1; + }, + ), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.TOGEKISS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.TOGEKISS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GARCHOMP], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GARCHOMP], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Garchomp p.generateAndPopulateMoveset(); p.generateName(); @@ -3723,28 +3956,47 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_champion_alder") .setMixedBattleBgm("battle_champion_alder") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BOUFFALANT, Species.BRAVIARY])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.HISUI_LILLIGANT, Species.HISUI_ZOROARK, Species.BASCULEGION], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 1, + getRandomPartyMemberFunc( + [Species.HISUI_LILLIGANT, Species.HISUI_ZOROARK, Species.BASCULEGION], + TrainerSlot.TRAINER, + true, + p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; - }), + }, + ), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.ZEKROM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.ZEKROM], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.KELDEO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.KELDEO], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc( - [Species.CHANDELURE, Species.KROOKODILE, Species.REUNICLUS, Species.CONKELDURR], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.teraType = p.species.speciesId === Species.KROOKODILE ? PokemonType.DARK : p.species.type1; - }), + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc( + [Species.CHANDELURE, Species.KROOKODILE, Species.REUNICLUS, Species.CONKELDURR], + TrainerSlot.TRAINER, + true, + p => { + p.generateAndPopulateMoveset(); + p.teraType = p.species.speciesId === Species.KROOKODILE ? PokemonType.DARK : p.species.type1; + }, + ), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.VOLCARONA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.VOLCARONA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); @@ -3760,23 +4012,36 @@ export const trainerConfigs: TrainerConfigs = { .setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DRUDDIGON])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.ARCHEOPS])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.RESHIRAM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.RESHIRAM], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SALAMENCE, Species.HYDREIGON, Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.teraType = PokemonType.DRAGON; - }), + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc( + [Species.SALAMENCE, Species.HYDREIGON, Species.ARCHALUDON], + TrainerSlot.TRAINER, + true, + p => { + p.generateAndPopulateMoveset(); + p.teraType = PokemonType.DRAGON; + }, + ), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // G-Max Lapras p.generateAndPopulateMoveset(); p.generateName(); }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.HAXORUS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.HAXORUS], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Mold Breaker p.generateAndPopulateMoveset(); p.gender = Gender.FEMALE; @@ -3787,28 +4052,38 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.DIANTHA]: new TrainerConfig(++t) .initForChampion(false) .setMixedBattleBgm("battle_kalos_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.HAWLUCHA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.HAWLUCHA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.TREVENANT, Species.GOURGEIST])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.XERNEAS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.XERNEAS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TYRANTRUM, Species.AURORUS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TYRANTRUM, Species.AURORUS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 2; // Rock Head Tyrantrum, Snow Warning Aurorus p.teraType = p.species.type2!; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.GOODRA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.GOODRA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GARDEVOIR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GARDEVOIR], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Gardevoir p.generateAndPopulateMoveset(); p.generateName(); @@ -3819,29 +4094,45 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.KUKUI]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_champion_kukui") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.formIndex = 2; // Dusk Lycanroc }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.MAGNEZONE, Species.ALOLA_NINETALES])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.TORNADUS, Species.THUNDURUS, Species.LANDORUS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Therian Formes + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc( + [Species.TORNADUS, Species.THUNDURUS, Species.LANDORUS], + TrainerSlot.TRAINER, + true, + p => { + p.formIndex = 1; // Therian Formes p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; - }), + }, + ), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TAPU_KOKO, Species.TAPU_FINI], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TAPU_KOKO, Species.TAPU_FINI], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SNORLAX], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.SNORLAX], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.formIndex = 1; // G-Max Snorlax }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.INCINEROAR, Species.HISUI_DECIDUEYE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.INCINEROAR, Species.HISUI_DECIDUEYE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.teraType = p.species.type2!; @@ -3853,24 +4144,32 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_alola_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALOLA_RAICHU])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.NOIVERN])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SOLGALEO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.SOLGALEO], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TAPU_LELE, Species.TAPU_BULU], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TAPU_LELE, Species.TAPU_BULU], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.teraType = p.species.type1; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ZYGARDE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.ZYGARDE], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Zygarde 10% forme, Aura Break p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DECIDUEYE, Species.PRIMARINA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DECIDUEYE, Species.PRIMARINA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); p.gender = p.species.speciesId === Species.PRIMARINA ? Gender.FEMALE : Gender.MALE; @@ -3882,18 +4181,29 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_galar_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.AEGISLASH])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.RHYPERIOR, Species.SEISMITOAD, Species.MR_RIME])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.ZACIAN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.ZACIAN], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.DRAGAPULT])) - .setPartyMemberFunc(4,getRandomPartyMemberFunc([Species.RILLABOOM, Species.CINDERACE, Species.INTELEON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc( + [Species.RILLABOOM, Species.CINDERACE, Species.INTELEON], + TrainerSlot.TRAINER, + true, + p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); - }), + }, + ), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CHARIZARD], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CHARIZARD], TrainerSlot.TRAINER, true, p => { p.formIndex = 3; // G-Max Charizard p.generateAndPopulateMoveset(); p.generateName(); @@ -3904,35 +4214,47 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.MUSTARD]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_mustard") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.KOMMO_O], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 1, + getRandomPartyMemberFunc([Species.KOMMO_O], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.teraType = p.species.type1; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GALAR_DARMANITAN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.GALAR_DARMANITAN], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.BLASTOISE, Species.VENUSAUR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.BLASTOISE, Species.VENUSAUR], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.URSHIFU], TrainerSlot.TRAINER, true, p => { - p.formIndex = randSeedInt(2, 2); // Random G-Max Urshifu + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.URSHIFU], TrainerSlot.TRAINER, true, p => { + p.formIndex = randSeedIntRange(2, 3); // Random G-Max Urshifu p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.MALE; @@ -3943,21 +4265,27 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.GEETA]: new TrainerConfig(++t) .initForChampion(false) .setMixedBattleBgm("battle_champion_geeta") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GLIMMORA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.GLIMMORA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.ESPATHRA, Species.VELUZA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MIRAIDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.MIRAIDON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BAXCALIBUR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.KINGAMBIT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.KINGAMBIT], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. @@ -3971,50 +4299,71 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.NEMONA]: new TrainerConfig(++t) .initForChampion(false) .setMixedBattleBgm("battle_champion_nemona") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { p.formIndex = 0; // Midday form p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PAWMOT])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.KORAIDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.KORAIDON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GHOLDENGO])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ARMAROUGE, Species.CERULEDGE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.ARMAROUGE, Species.CERULEDGE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.teraType = p.species.type2!; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc( + [Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], + TrainerSlot.TRAINER, + true, + p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); - }), + }, + ), ) .setInstantTera(4), // Tera Psychic Armarouge / Ghost Ceruledge [TrainerType.KIERAN]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_champion_kieran") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.POLIWRATH, Species.POLITOED])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.INCINEROAR, Species.GRIMMSNARL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 1, + getRandomPartyMemberFunc([Species.INCINEROAR, Species.GRIMMSNARL], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = p.species.speciesId === Species.INCINEROAR ? 2 : 0; // Intimidate Incineroar, Prankster Grimmsnarl }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.TERAPAGOS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.TERAPAGOS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.URSALUNA, Species.BLOODMOON_URSALUNA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.URSALUNA, Species.BLOODMOON_URSALUNA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.OGERPON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.OGERPON], TrainerSlot.TRAINER, true, p => { p.formIndex = randSeedInt(4); // Random Ogerpon Tera Mask p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; @@ -4024,7 +4373,9 @@ export const trainerConfigs: TrainerConfigs = { } }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.HYDRAPPLE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.HYDRAPPLE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 983494b36c8..8abe3a303ca 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -54,7 +54,7 @@ import { getStarterValueFriendshipCap, speciesStarterCosts, } from "#app/data/balance/starters"; -import { NumberHolder, randSeedInt, getIvsFromId, BooleanHolder, randSeedItem, isNullOrUndefined, getEnumValues, toDmgValue, fixedInt, rgbaToInt, rgbHexToRgba, rgbToHsv, deltaRgb, isBetween, type nil, type Constructor } from "#app/utils/common"; +import { NumberHolder, randSeedInt, getIvsFromId, BooleanHolder, randSeedItem, isNullOrUndefined, getEnumValues, toDmgValue, fixedInt, rgbaToInt, rgbHexToRgba, rgbToHsv, deltaRgb, isBetween, type nil, type Constructor, randSeedIntRange } from "#app/utils/common"; import type { TypeDamageMultiplier } from "#app/data/type"; import { getTypeDamageMultiplier, getTypeRgb } from "#app/data/type"; import { PokemonType } from "#enums/pokemon-type"; @@ -4485,7 +4485,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ const randomMultiplier = simulated ? 1 - : this.randSeedIntRange(85, 100) / 100; + : this.randBattleSeedIntRange(85, 100) / 100; /** A damage multiplier for when the attack is of the attacker's type and/or Tera type. */ @@ -5629,7 +5629,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { let sleepTurnsRemaining: NumberHolder; if (effect === StatusEffect.SLEEP) { - sleepTurnsRemaining = new NumberHolder(this.randSeedIntRange(2, 4)); + sleepTurnsRemaining = new NumberHolder(this.randBattleSeedIntRange(2, 4)); this.setFrameRate(4); @@ -6292,7 +6292,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param min The minimum integer to pick, default `0` * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) */ - randSeedInt(range: number, min = 0): number { + randBattleSeedInt(range: number, min = 0): number { return globalScene.currentBattle ? globalScene.randBattleSeedInt(range, min) : randSeedInt(range, min); @@ -6304,8 +6304,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param max The maximum integer to generate * @returns a random integer between {@linkcode min} and {@linkcode max} inclusive */ - randSeedIntRange(min: number, max: number): number { - return this.randSeedInt(max - min + 1, min); + randBattleSeedIntRange(min: number, max: number): number { + return globalScene.currentBattle + ? globalScene.randBattleSeedInt(max - min + 1, min) + : randSeedIntRange(min, max); } /** @@ -7143,7 +7145,7 @@ export class EnemyPokemon extends Pokemon { const { waveIndex } = globalScene.currentBattle; const ivs: number[] = []; while (ivs.length < 6) { - ivs.push(this.randSeedIntRange(Math.floor(waveIndex / 10), 31)); + ivs.push(randSeedIntRange(Math.floor(waveIndex / 10), 31)); } this.ivs = ivs; } diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 763b40c8555..94bb0e3419a 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1548,7 +1548,7 @@ export class SurviveDamageModifier extends PokemonHeldItemModifier { * @returns `true` if the survive damage has been applied */ override apply(pokemon: Pokemon, surviveDamage: BooleanHolder): boolean { - if (!surviveDamage.value && pokemon.randSeedInt(10) < this.getStackCount()) { + if (!surviveDamage.value && pokemon.randBattleSeedInt(10) < this.getStackCount()) { surviveDamage.value = true; globalScene.queueMessage( @@ -1594,7 +1594,7 @@ export class BypassSpeedChanceModifier extends PokemonHeldItemModifier { * @returns `true` if {@linkcode BypassSpeedChanceModifier} has been applied */ override apply(pokemon: Pokemon, doBypassSpeed: BooleanHolder): boolean { - if (!doBypassSpeed.value && pokemon.randSeedInt(10) < this.getStackCount()) { + if (!doBypassSpeed.value && pokemon.randBattleSeedInt(10) < this.getStackCount()) { doBypassSpeed.value = true; const isCommandFight = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]?.command === Command.FIGHT; @@ -1658,7 +1658,7 @@ export class FlinchChanceModifier extends PokemonHeldItemModifier { override apply(pokemon: Pokemon, flinched: BooleanHolder): boolean { // The check for pokemon.summonData is to ensure that a crash doesn't occur when a Pokemon with King's Rock procs a flinch // TODO: Since summonData is always defined now, we can probably remove this - if (pokemon.summonData && !flinched.value && pokemon.randSeedInt(100) < this.getStackCount() * this.chance) { + if (pokemon.summonData && !flinched.value && pokemon.randBattleSeedInt(100) < this.getStackCount() * this.chance) { flinched.value = true; return true; } @@ -1927,7 +1927,7 @@ export class PreserveBerryModifier extends PersistentModifier { * @returns always `true` */ override apply(pokemon: Pokemon, doPreserve: BooleanHolder): boolean { - doPreserve.value ||= pokemon.randSeedInt(10) < this.getStackCount() * 3; + doPreserve.value ||= pokemon.randBattleSeedInt(10) < this.getStackCount() * 3; return true; } @@ -3240,7 +3240,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier { return false; } - const targetPokemon = opponents[pokemon.randSeedInt(opponents.length)]; + const targetPokemon = opponents[pokemon.randBattleSeedInt(opponents.length)]; const transferredItemCount = this.getTransferredItemCount(); if (!transferredItemCount) { @@ -3272,7 +3272,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier { break; } } - const randItemIndex = pokemon.randSeedInt(itemModifiers.length); + const randItemIndex = pokemon.randBattleSeedInt(itemModifiers.length); const randItem = itemModifiers[randItemIndex]; if (globalScene.tryTransferHeldItemModifier(randItem, pokemon, false)) { transferredModifierTypes.push(randItem.type); @@ -3731,7 +3731,7 @@ export class EnemyEndureChanceModifier extends EnemyPersistentModifier { * @returns `true` if {@linkcode Pokemon} endured */ override apply(target: Pokemon): boolean { - if (target.waveData.endured || target.randSeedInt(100) >= this.chance * this.getStackCount()) { + if (target.waveData.endured || target.randBattleSeedInt(100) >= this.chance * this.getStackCount()) { return false; } diff --git a/src/phases/attempt-capture-phase.ts b/src/phases/attempt-capture-phase.ts index 795aa7010e1..8592cd98508 100644 --- a/src/phases/attempt-capture-phase.ts +++ b/src/phases/attempt-capture-phase.ts @@ -63,7 +63,7 @@ export class AttemptCapturePhase extends PokemonPhase { const modifiedCatchRate = Math.round((((_3m - _2h) * catchRate * pokeballMultiplier) / _3m) * statusMultiplier); const shakeProbability = Math.round(65536 / Math.pow(255 / modifiedCatchRate, 0.1875)); // Formula taken from gen 6 const criticalCaptureChance = getCriticalCaptureChance(modifiedCatchRate); - const isCritical = pokemon.randSeedInt(256) < criticalCaptureChance; + const isCritical = pokemon.randBattleSeedInt(256) < criticalCaptureChance; const fpOffset = pokemon.getFieldPositionOffset(); const pokeballAtlasKey = getPokeballAtlasKey(this.pokeballType); @@ -135,14 +135,14 @@ export class AttemptCapturePhase extends PokemonPhase { pokeballMultiplier === -1 || isCritical || modifiedCatchRate >= 255 || - pokemon.randSeedInt(65536) < shakeProbability + pokemon.randBattleSeedInt(65536) < shakeProbability ) { globalScene.playSound("se/pb_move"); } else { shakeCounter.stop(); this.failCatch(shakeCount); } - } else if (isCritical && pokemon.randSeedInt(65536) >= shakeProbability) { + } else if (isCritical && pokemon.randBattleSeedInt(65536) >= shakeProbability) { // Above, perform the one shake check for critical captures after the ball shakes once shakeCounter.stop(); this.failCatch(shakeCount); diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index 274d3c40576..15c521c01fc 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -34,7 +34,7 @@ export class AttemptRunPhase extends PokemonPhase { applyAbAttrs(RunSuccessAbAttr, playerPokemon, null, false, escapeChance); - if (playerPokemon.randSeedInt(100) < escapeChance.value && !this.forceFailEscape) { + if (playerPokemon.randBattleSeedInt(100) < escapeChance.value && !this.forceFailEscape) { enemyField.forEach(enemyPokemon => applyPreLeaveFieldAbAttrs(PreLeaveFieldAbAttr, enemyPokemon)); globalScene.playSound("se/flee"); diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index d067807486d..59f5ac69fd8 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -594,7 +594,7 @@ export class MoveEffectPhase extends PokemonPhase { } const accuracyMultiplier = user.getAccuracyMultiplier(target, this.move); - const rand = user.randSeedInt(100); + const rand = user.randBattleSeedInt(100); if (rand < moveAccuracy * accuracyMultiplier) { return [HitCheckResult.HIT, effectiveness]; diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index e704b040d20..5d63fe6efea 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -232,7 +232,7 @@ export class MovePhase extends BattlePhase { switch (this.pokemon.status.effect) { case StatusEffect.PARALYSIS: activated = - (!this.pokemon.randSeedInt(4) || Overrides.STATUS_ACTIVATION_OVERRIDE === true) && + (!this.pokemon.randBattleSeedInt(4) || Overrides.STATUS_ACTIVATION_OVERRIDE === true) && Overrides.STATUS_ACTIVATION_OVERRIDE !== false; break; case StatusEffect.SLEEP: { @@ -258,7 +258,7 @@ export class MovePhase extends BattlePhase { .findAttr( attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE), ) || - (!this.pokemon.randSeedInt(5) && Overrides.STATUS_ACTIVATION_OVERRIDE !== true) || + (!this.pokemon.randBattleSeedInt(5) && Overrides.STATUS_ACTIVATION_OVERRIDE !== true) || Overrides.STATUS_ACTIVATION_OVERRIDE === false; activated = !healed; diff --git a/src/utils/common.ts b/src/utils/common.ts index 4cf7ceccff2..b9111578e2f 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -99,6 +99,16 @@ export function randSeedInt(range: number, min = 0): number { return Phaser.Math.RND.integerInRange(min, range - 1 + min); } +/** + * Generates a random number using the global seed + * @param min The minimum integer to generate + * @param max The maximum integer to generate + * @returns a random integer between {@linkcode min} and {@linkcode max} inclusive + */ +export function randSeedIntRange(min: number, max: number): number { + return randSeedInt(max - min + 1, min); +} + /** * Returns a random integer between min and max (non-inclusive) * @param min The lowest number diff --git a/test/abilities/cud_chew.test.ts b/test/abilities/cud_chew.test.ts index f99060cb744..2f65ac5fd97 100644 --- a/test/abilities/cud_chew.test.ts +++ b/test/abilities/cud_chew.test.ts @@ -111,7 +111,7 @@ describe("Abilities - Cud Chew", () => { it("can store multiple berries across 2 turns with teatime", async () => { // always eat first berry for stuff cheeks & company - vi.spyOn(Pokemon.prototype, "randSeedInt").mockReturnValue(0); + vi.spyOn(Pokemon.prototype, "randBattleSeedInt").mockReturnValue(0); game.override .startingHeldItems([ { name: "BERRY", type: BerryType.PETAYA, count: 3 }, diff --git a/test/abilities/desolate-land.test.ts b/test/abilities/desolate-land.test.ts index d6f01f7aa5e..697bd0a4c48 100644 --- a/test/abilities/desolate-land.test.ts +++ b/test/abilities/desolate-land.test.ts @@ -139,7 +139,7 @@ describe("Abilities - Desolate Land", () => { await game.classicMode.startBattle([Species.MAGIKARP]); expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.HARSH_SUN); - vi.spyOn(game.scene.getPlayerPokemon()!, "randSeedInt").mockReturnValue(0); + vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0); const commandPhase = game.scene.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); diff --git a/test/abilities/neutralizing_gas.test.ts b/test/abilities/neutralizing_gas.test.ts index 32c61b72e4d..979583b7d97 100644 --- a/test/abilities/neutralizing_gas.test.ts +++ b/test/abilities/neutralizing_gas.test.ts @@ -164,7 +164,7 @@ describe("Abilities - Neutralizing Gas", () => { await game.classicMode.startBattle([Species.MAGIKARP]); expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined(); - vi.spyOn(game.scene.getPlayerPokemon()!, "randSeedInt").mockReturnValue(0); + vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0); const commandPhase = game.scene.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); diff --git a/test/items/reviver_seed.test.ts b/test/items/reviver_seed.test.ts index c109794d3d2..3c67481a904 100644 --- a/test/items/reviver_seed.test.ts +++ b/test/items/reviver_seed.test.ts @@ -73,7 +73,7 @@ describe("Items - Reviver Seed", () => { const reviverSeed = player.getHeldItems()[0] as PokemonInstantReviveModifier; vi.spyOn(reviverSeed, "apply"); - vi.spyOn(player, "randSeedInt").mockReturnValue(0); // Force confusion self-hit + vi.spyOn(player, "randBattleSeedInt").mockReturnValue(0); // Force confusion self-hit game.move.select(Moves.TACKLE); await game.phaseInterceptor.to("BerryPhase"); diff --git a/test/moves/u_turn.test.ts b/test/moves/u_turn.test.ts index 4ceb6865be0..9dca29414a1 100644 --- a/test/moves/u_turn.test.ts +++ b/test/moves/u_turn.test.ts @@ -74,7 +74,7 @@ describe("Moves - U-turn", () => { // arrange game.override.enemyAbility(Abilities.POISON_POINT); await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]); - vi.spyOn(game.scene.getEnemyPokemon()!, "randSeedInt").mockReturnValue(0); + vi.spyOn(game.scene.getEnemyPokemon()!, "randBattleSeedInt").mockReturnValue(0); // act game.move.select(Moves.U_TURN); From 4376a22a7c665e9070afbd60d9e994ea807727b8 Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Sat, 17 May 2025 16:04:16 -0500 Subject: [PATCH 11/26] [Bug] Fix field moves always playing their animations (#5830) --- src/phases/move-effect-phase.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 59f5ac69fd8..e3773952214 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -354,8 +354,8 @@ export class MoveEffectPhase extends PokemonPhase { move.id as Moves, user, firstTarget?.getBattlerIndex() ?? BattlerIndex.ATTACKER, - // Field moves and some moves used in mystery encounters should be played even on an empty field - fieldMove || (globalScene.currentBattle?.mysteryEncounter?.hasBattleAnimationsWithoutTargets ?? false), + // Some moves used in mystery encounters should be played even on an empty field + globalScene.currentBattle?.mysteryEncounter?.hasBattleAnimationsWithoutTargets ?? false, ).play(move.hitsSubstitute(user, firstTarget), () => this.postAnimCallback(user, targets)); return; From 22f5ed1232ec4b02811593ccd406da9873d4fbb6 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Sat, 17 May 2025 20:34:06 -0700 Subject: [PATCH 12/26] [i18n] Update locales --- public/locales | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales b/public/locales index ee6bb371afe..a074ddb28c3 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit ee6bb371afefe4c6d872cc7765f0e0d26e630d4e +Subproject commit a074ddb28c3f0c7e9bbd0560efa33e3ce5f71bcd From 9ae969117b0dd1d4bc39be3dd6d2624bd585dbaa Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Sun, 18 May 2025 00:22:09 -0500 Subject: [PATCH 13/26] [Bug][UI/UX] Fix fiery fallout message bug (#5834) * Fix fiery fallout message bug * Ensure pokemon names are replaced when there is no separator --- src/phases/message-phase.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/phases/message-phase.ts b/src/phases/message-phase.ts index f6777579857..b277d67de82 100644 --- a/src/phases/message-phase.ts +++ b/src/phases/message-phase.ts @@ -35,20 +35,22 @@ export class MessagePhase extends Phase { this.text = this.text.split(pokename[p]).join(repname[p]); } const pageIndex = this.text.indexOf("$"); - for (let p = 0; p < globalScene.getPlayerField().length; p++) { - this.text = this.text.split(repname[p]).join(pokename[p]); - } if (pageIndex !== -1) { + let page0 = this.text.slice(0, pageIndex); + let page1 = this.text.slice(pageIndex + 1); + // Pokemon names must be re-inserted _after_ the split, otherwise the index will be wrong + for (let p = 0; p < globalScene.getPlayerField().length; p++) { + page0 = page0.split(repname[p]).join(pokename[p]); + page1 = page1.split(repname[p]).join(pokename[p]); + } globalScene.unshiftPhase( - new MessagePhase( - this.text.slice(pageIndex + 1), - this.callbackDelay, - this.prompt, - this.promptDelay, - this.speaker, - ), + new MessagePhase(page1, this.callbackDelay, this.prompt, this.promptDelay, this.speaker), ); - this.text = this.text.slice(0, pageIndex).trim(); + this.text = page0.trim(); + } else { + for (let p = 0; p < globalScene.getPlayerField().length; p++) { + this.text = this.text.split(repname[p]).join(pokename[p]); + } } } From bd14ed640c8c11da897128ca621e5951b7cd0113 Mon Sep 17 00:00:00 2001 From: Lugiad <2070109+Adri1@users.noreply.github.com> Date: Tue, 20 May 2025 00:00:51 +0200 Subject: [PATCH 14/26] [Localization] Localizable "Cancel" text in Ball selection menu (#5836) "Cancel" text localizable --- src/ui/ball-ui-handler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index abb106a6553..eb7c208662a 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -7,6 +7,7 @@ import { addWindow } from "./ui-theme"; import { Button } from "#enums/buttons"; import type { CommandPhase } from "#app/phases/command-phase"; import { globalScene } from "#app/global-scene"; +import i18next from "i18next"; export default class BallUiHandler extends UiHandler { private pokeballSelectContainer: Phaser.GameObjects.Container; @@ -31,7 +32,7 @@ export default class BallUiHandler extends UiHandler { for (let pb = 0; pb < Object.keys(globalScene.pokeballCounts).length; pb++) { optionsTextContent += `${getPokeballName(pb)}\n`; } - optionsTextContent += "Cancel"; + optionsTextContent += i18next.t("pokeball:cancel"); const optionsText = addTextObject(0, 0, optionsTextContent, TextStyle.WINDOW, { align: "right", maxLines: 6 }); const optionsTextWidth = optionsText.displayWidth; this.pokeballSelectContainer = globalScene.add.container( From a9ec3b324c8deb88de9cc7b986fc92814922dd5a Mon Sep 17 00:00:00 2001 From: Lugiad <2070109+Adri1@users.noreply.github.com> Date: Tue, 20 May 2025 00:03:42 +0200 Subject: [PATCH 15/26] [UI/UX] [i18n] Text ratio adjustment for es-MX Egg Gatcha (#5839) --- src/ui/egg-gacha-ui-handler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index 5377cf3d283..1bb7124d935 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -108,7 +108,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { let pokemonIconX = -20; let pokemonIconY = 6; - if (["de", "es-ES", "fr", "ko", "pt-BR"].includes(currentLanguage)) { + if (["de", "es-ES", "es-MX", "fr", "ko", "pt-BR"].includes(currentLanguage)) { gachaTextStyle = TextStyle.SMALLER_WINDOW_ALT; gachaX = 2; gachaY = 2; @@ -116,7 +116,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { let legendaryLabelX = gachaX; let legendaryLabelY = gachaY; - if (["de", "es-ES"].includes(currentLanguage)) { + if (["de", "es-ES", "es-MX"].includes(currentLanguage)) { pokemonIconX = -25; pokemonIconY = 10; legendaryLabelX = -6; From dda94c7b22411af71f7f1e52725f8587af89ad55 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Mon, 19 May 2025 17:18:26 -0700 Subject: [PATCH 16/26] [i18n] Update locales --- public/locales | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales b/public/locales index a074ddb28c3..42cd5cf577f 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit a074ddb28c3f0c7e9bbd0560efa33e3ce5f71bcd +Subproject commit 42cd5cf577f475c22bc82d55e7ca358eb4f3184f From 9746f1a2a6aa61d03137674dad92ef2c72225469 Mon Sep 17 00:00:00 2001 From: Lugiad <2070109+Adri1@users.noreply.github.com> Date: Tue, 20 May 2025 02:39:17 +0200 Subject: [PATCH 17/26] [UI/UX] [Localization] Update Korean starterInfoText --- src/ui/starter-select-ui-handler.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 09d7322cb75..ac781a71da0 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -145,8 +145,10 @@ const languageSettings: { [key: string]: LanguageSetting } = { starterInfoXPos: 33, }, ko: { - starterInfoTextSize: "52px", + starterInfoTextSize: "60px", instructionTextSize: "38px", + starterInfoYOffset: -0.5, + starterInfoXPos: 30, }, ja: { starterInfoTextSize: "51px", From 23e1d88c3ad45914602d815fc10ef8b14d1c2c92 Mon Sep 17 00:00:00 2001 From: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Tue, 20 May 2025 15:40:05 -0400 Subject: [PATCH 18/26] [Balance] Update TM compatibility for Curse (#5791) * Update Curse TM compat with former egg moves/level ups * Pumpkaboo is not Phantump --- src/data/balance/tms.ts | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/data/balance/tms.ts b/src/data/balance/tms.ts index 69aef9b135d..b7480e9131d 100644 --- a/src/data/balance/tms.ts +++ b/src/data/balance/tms.ts @@ -19057,8 +19057,15 @@ export const tmSpecies: TmSpecies = { Species.SLAKING, Species.HARIYAMA, Species.NOSEPASS, + Species.ARON, + Species.LAIRON, + Species.AGGRON, + Species.ELECTRIKE, + Species.MANECTRIC, Species.GULPIN, Species.SWALOT, + Species.WAILMER, + Species.WAILORD, Species.NUMEL, Species.CAMERUPT, Species.TORKOAL, @@ -19067,18 +19074,28 @@ export const tmSpecies: TmSpecies = { Species.ZANGOOSE, Species.SEVIPER, Species.WHISCASH, + Species.LILEEP, + Species.CRADILY, + Species.ANORITH, + Species.ARMALDO, Species.SHUPPET, Species.BANETTE, Species.DUSKULL, Species.DUSCLOPS, Species.TROPIUS, Species.CHIMECHO, + Species.ABSOL, + Species.SPHEAL, + Species.SEALEO, + Species.WALREIN, Species.REGIROCK, Species.REGICE, Species.REGISTEEL, Species.TURTWIG, Species.GROTLE, Species.TORTERRA, + Species.BIDOOF, + Species.BIBAREL, Species.CRANIDOS, Species.RAMPARDOS, Species.SHIELDON, @@ -19120,6 +19137,11 @@ export const tmSpecies: TmSpecies = { Species.TEPIG, Species.PIGNITE, Species.EMBOAR, + Species.MUNNA, + Species.MUSHARNA, + Species.ROGGENROLA, + Species.BOLDORE, + Species.GIGALITH, Species.DRILBUR, Species.EXCADRILL, Species.TIMBURR, @@ -19128,28 +19150,44 @@ export const tmSpecies: TmSpecies = { Species.SANDILE, Species.KROKOROK, Species.KROOKODILE, + Species.DWEBBLE, + Species.CRUSTLE, Species.SCRAGGY, Species.SCRAFTY, Species.YAMASK, - Species.COFAGRIGUS, + Species.COFAGRIGUS, + Species.TRUBBISH, + Species.GARBODOR, Species.SAWSBUCK, + Species.FERROSEED, + Species.FERROTHORN, Species.LITWICK, Species.LAMPENT, Species.CHANDELURE, Species.BEARTIC, + Species.SHELMET, + Species.ACCELGOR, + Species.STUNFISK, Species.GOLETT, Species.GOLURK, + Species.HEATMOR, Species.CHESPIN, Species.QUILLADIN, Species.CHESNAUGHT, + Species.TYRUNT, + Species.TYRANTRUM, Species.SYLVEON, Species.GOOMY, Species.SLIGGOO, Species.GOODRA, Species.PHANTUMP, Species.TREVENANT, + Species.PUMPKABOO, + Species.GOURGEIST, Species.BERGMITE, Species.AVALUGG, + Species.ROWLET, + Species.DARTRIX, Species.DECIDUEYE, Species.GUMSHOOS, Species.MUDBRAY, @@ -19157,7 +19195,9 @@ export const tmSpecies: TmSpecies = { Species.PASSIMIAN, Species.SANDYGAST, Species.PALOSSAND, + Species.PYUKUMUKU, Species.KOMALA, + Species.TURTONATOR, Species.MIMIKYU, Species.SKWOVET, Species.GREEDENT, @@ -19169,6 +19209,7 @@ export const tmSpecies: TmSpecies = { Species.SINISTEA, Species.POLTEAGEIST, Species.PERRSERKER, + Species.CURSOLA, Species.RUNERIGUS, Species.PINCURCHIN, Species.STONJOURNER, @@ -19236,6 +19277,7 @@ export const tmSpecies: TmSpecies = { Species.GALAR_WEEZING, Species.GALAR_SLOWKING, Species.GALAR_YAMASK, + Species.GALAR_STUNFISK, Species.HISUI_ELECTRODE, Species.HISUI_TYPHLOSION, Species.HISUI_QWILFISH, From 663c64fdb41c51a4104ba270639f93c862698296 Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Tue, 20 May 2025 16:46:23 -0500 Subject: [PATCH 19/26] [Misc] Fix trailing whitespace (#5856) Remove trailing whitespace --- src/data/balance/signature-species.ts | 6 +++--- src/data/balance/tms.ts | 4 ++-- src/field/pokemon.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/data/balance/signature-species.ts b/src/data/balance/signature-species.ts index fb8f33d4435..04749a67521 100644 --- a/src/data/balance/signature-species.ts +++ b/src/data/balance/signature-species.ts @@ -8,11 +8,11 @@ export type SignatureSpecies = { * The signature species for each Gym Leader, Elite Four member, and Champion. * The key is the trainer type, and the value is an array of Species or Species arrays. * This is in a separate const so it can be accessed from other places and not just the trainerConfigs - * + * * @remarks - * The `Proxy` object allows us to define a handler that will intercept + * The `Proxy` object allows us to define a handler that will intercept * the property access and return an empty array if the property does not exist in the object. - * + * * This means that accessing `signatureSpecies` will not throw an error if the property does not exist, * but instead default to an empty array. */ diff --git a/src/data/balance/tms.ts b/src/data/balance/tms.ts index b7480e9131d..06d191c3b2a 100644 --- a/src/data/balance/tms.ts +++ b/src/data/balance/tms.ts @@ -67104,7 +67104,7 @@ export const tmSpecies: TmSpecies = { Species.CHEWTLE, Species.DREDNAW, Species.YAMPER, - Species.BOLTUND, + Species.BOLTUND, Species.ROLYCOLY, Species.CARKOL, Species.COALOSSAL, @@ -67121,7 +67121,7 @@ export const tmSpecies: TmSpecies = { Species.SIZZLIPEDE, Species.CENTISKORCH, Species.CLOBBOPUS, - Species.GRAPPLOCT, + Species.GRAPPLOCT, Species.SINISTEA, Species.POLTEAGEIST, Species.HATENNA, diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 8abe3a303ca..fcca0c5614a 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5678,7 +5678,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { /** * Performs the action of clearing a Pokemon's status - * + * * This is a helper to {@linkcode resetStatus}, which should be called directly instead of this method */ public clearStatus(confusion: boolean, reloadAssets: boolean) { From 288e4e7e7eb9e6a9d450369a9c11cb0945845fcd Mon Sep 17 00:00:00 2001 From: itgalex24 <123003541+itgalex24@users.noreply.github.com> Date: Tue, 20 May 2025 19:12:54 -0400 Subject: [PATCH 20/26] [Bug] [Move] Synchronoise hitting Tera Type fix (#5779) * synchronoize fix * Add regression test for synchronoise --------- Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> --- src/data/moves/move.ts | 6 ++--- test/moves/synchronoise.test.ts | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 test/moves/synchronoise.test.ts diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 235cb954ea5..b190729621c 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -8052,10 +8052,10 @@ export class UpperHandCondition extends MoveCondition { } } -export class hitsSameTypeAttr extends VariableMoveTypeMultiplierAttr { +export class HitsSameTypeAttr extends VariableMoveTypeMultiplierAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const multiplier = args[0] as NumberHolder; - if (!user.getTypes().some(type => target.getTypes().includes(type))) { + if (!user.getTypes(true).some(type => target.getTypes(true).includes(type))) { multiplier.value = 0; return true; } @@ -9756,7 +9756,7 @@ export function initMoves() { new AttackMove(Moves.SYNCHRONOISE, PokemonType.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 5) .target(MoveTarget.ALL_NEAR_OTHERS) .condition(unknownTypeCondition) - .attr(hitsSameTypeAttr), + .attr(HitsSameTypeAttr), new AttackMove(Moves.ELECTRO_BALL, PokemonType.ELECTRIC, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 5) .attr(ElectroBallPowerAttr) .ballBombMove(), diff --git a/test/moves/synchronoise.test.ts b/test/moves/synchronoise.test.ts new file mode 100644 index 00000000000..0f59bce26b4 --- /dev/null +++ b/test/moves/synchronoise.test.ts @@ -0,0 +1,47 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { PokemonType } from "#enums/pokemon-type"; +import { Species } from "#enums/species"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Synchronoise", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([Moves.SYNCHRONOISE]) + .ability(Abilities.BALL_FETCH) + .battleStyle("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should consider the user's tera type if it is terastallized", async () => { + await game.classicMode.startBattle([Species.BIDOOF]); + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + + // force the player to be terastallized + playerPokemon.teraType = PokemonType.WATER; + playerPokemon.isTerastallized = true; + game.move.select(Moves.SYNCHRONOISE); + await game.phaseInterceptor.to("BerryPhase"); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + }); +}); From b72389295e69625406393f4b4087be3191ec8382 Mon Sep 17 00:00:00 2001 From: Madmadness65 <59298170+Madmadness65@users.noreply.github.com> Date: Tue, 20 May 2025 21:07:37 -0500 Subject: [PATCH 21/26] [Animation] [P3 Bug] Fix Sandstorm weather animation not playing properly (#5853) Fix Sandstorm weather animation not playing properly The sandstorm background image is now properly used within the weather animation's JSON. --- public/battle-anims/common-sandstorm.json | 73 +++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/public/battle-anims/common-sandstorm.json b/public/battle-anims/common-sandstorm.json index b5b2d29f54c..fba90a08645 100644 --- a/public/battle-anims/common-sandstorm.json +++ b/public/battle-anims/common-sandstorm.json @@ -542,6 +542,79 @@ "volume": 100, "pitch": 55, "eventType": "AnimTimedSoundEvent" + }, + { + "frameIndex": 0, + "resourceName": "PRAS- Sandstorm", + "bgX": -50, + "bgY": 0, + "opacity": 0, + "duration": 5, + "eventType": "AnimTimedAddBgEvent" + }, + { + "frameIndex": 0, + "resourceName": "", + "bgX": -50, + "bgY": 0, + "opacity": 96, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "3": [ + { + "frameIndex": 3, + "resourceName": "", + "bgX": -25, + "bgY": 0, + "opacity": 128, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "6": [ + { + "frameIndex": 6, + "resourceName": "", + "bgX": 0, + "bgY": 0, + "opacity": 192, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "9": [ + { + "frameIndex": 9, + "resourceName": "", + "bgX": 25, + "bgY": 0, + "opacity": 128, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "12": [ + { + "frameIndex": 12, + "resourceName": "", + "bgX": 50, + "bgY": 0, + "opacity": 96, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "15": [ + { + "frameIndex": 15, + "resourceName": "", + "bgX": 50, + "bgY": 0, + "opacity": 0, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" } ] }, From f01e7599ac8ea7a1c8fc14f556f0c5ae090c4ea1 Mon Sep 17 00:00:00 2001 From: Lugiad <2070109+Adri1@users.noreply.github.com> Date: Wed, 21 May 2025 04:21:35 +0200 Subject: [PATCH 22/26] [UI/UX] [Localization] Update Japanese starterInfoText (#5852) Update Japanese starterInfoText --- src/ui/starter-select-ui-handler.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index ac781a71da0..a35f426e8bd 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -151,8 +151,10 @@ const languageSettings: { [key: string]: LanguageSetting } = { starterInfoXPos: 30, }, ja: { - starterInfoTextSize: "51px", + starterInfoTextSize: "62px", instructionTextSize: "38px", + starterInfoYOffset: 0.5, + starterInfoXPos: 33, }, "ca-ES": { starterInfoTextSize: "52px", From 1cf19b49f26d0b82c102d304d7585fe5bacea785 Mon Sep 17 00:00:00 2001 From: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Tue, 20 May 2025 22:59:39 -0400 Subject: [PATCH 23/26] [Balance] Moveset generation adjustments (#5801) * Moveset generation adjustments * Remove shiny explosion check, prevent 2 self-KO moves --- src/field/pokemon.ts | 74 +++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index fcca0c5614a..74ccb0c7f49 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3500,11 +3500,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } let weight = levelMove[0]; // Evolution Moves - if (weight === 0) { + if (weight === EVOLVE_MOVE) { weight = 50; } - // Assume level 1 moves with 80+ BP are "move reminder" moves and bump their weight - if (weight === 1 && allMoves[levelMove[1]].power >= 80) { + // Assume level 1 moves with 80+ BP are "move reminder" moves and bump their weight. Trainers use actual relearn moves. + if (weight === 1 && allMoves[levelMove[1]].power >= 80 || weight === RELEARN_MOVE && this.hasTrainer()) { weight = 40; } if ( @@ -3609,9 +3609,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Bosses never get self ko moves or Pain Split if (this.isBoss()) { - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr)); - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(HpSplitAttr)); + movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr) && !allMoves[m[0]].hasAttr(HpSplitAttr)); } + // No one gets Memento or Final Gambit movePool = movePool.filter( m => !allMoves[m[0]].hasAttr(SacrificialAttrOnHit), ); @@ -3623,10 +3623,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { m[0], m[1] * (allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1), ]); - movePool = movePool.map(m => [ - m[0], - m[1] * (allMoves[m[0]].hasAttr(SacrificialAttrOnHit) ? 0.5 : 1), - ]); // Trainers get a weight bump to stat buffing moves movePool = movePool.map(m => [ m[0], @@ -3687,10 +3683,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ]); /** The higher this is the more the game weights towards higher level moves. At `0` all moves are equal weight. */ - let weightMultiplier = 0.9; - if (this.hasTrainer()) { - weightMultiplier += 0.7; - } + let weightMultiplier = 1.6; if (this.isBoss()) { weightMultiplier += 0.4; } @@ -3699,37 +3692,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { Math.ceil(Math.pow(m[1], weightMultiplier) * 100), ]); - // Trainers and bosses always force a stab move - if (this.hasTrainer() || this.isBoss()) { - const stabMovePool = baseWeights.filter( - m => - allMoves[m[0]].category !== MoveCategory.STATUS && - this.isOfType(allMoves[m[0]].type), - ); + // All Pokemon force a STAB move first + const stabMovePool = baseWeights.filter( + m => + allMoves[m[0]].category !== MoveCategory.STATUS && + this.isOfType(allMoves[m[0]].type), + ); - if (stabMovePool.length) { - const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0); - let rand = randSeedInt(totalWeight); - let index = 0; - while (rand > stabMovePool[index][1]) { - rand -= stabMovePool[index++][1]; - } - this.moveset.push(new PokemonMove(stabMovePool[index][0], 0, 0)); - } - } else { - // Normal wild pokemon just force a random damaging move - const attackMovePool = baseWeights.filter( - m => allMoves[m[0]].category !== MoveCategory.STATUS, - ); - if (attackMovePool.length) { - const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0); - let rand = randSeedInt(totalWeight); - let index = 0; - while (rand > attackMovePool[index][1]) { - rand -= attackMovePool[index++][1]; - } - this.moveset.push(new PokemonMove(attackMovePool[index][0], 0, 0)); + if (stabMovePool.length) { + const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0); + let rand = randSeedInt(totalWeight); + let index = 0; + while (rand > stabMovePool[index][1]) { + rand -= stabMovePool[index++][1]; } + this.moveset.push(new PokemonMove(stabMovePool[index][0], 0, 0)); } while ( @@ -3741,7 +3718,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Other damaging moves 2x weight if 0-1 damaging moves, 0.5x if 2, 0.125x if 3. These weights get 20x if STAB. // Status moves remain unchanged on weight, this encourages 1-2 movePool = baseWeights - .filter(m => !this.moveset.some(mo => m[0] === mo.moveId)) + .filter(m => !this.moveset.some( + mo => + m[0] === mo.moveId || + (allMoves[m[0]].hasAttr(SacrificialAttr) && mo.getMove().hasAttr(SacrificialAttr)) // Only one self-KO move allowed + )) .map(m => { let ret: number; if ( @@ -3772,7 +3753,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }); } else { // Non-trainer pokemon just use normal weights - movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo.moveId)); + movePool = baseWeights.filter(m => !this.moveset.some( + mo => + m[0] === mo.moveId || + (allMoves[m[0]].hasAttr(SacrificialAttr) && mo.getMove().hasAttr(SacrificialAttr)) // Only one self-KO move allowed + )); } const totalWeight = movePool.reduce((v, m) => v + m[1], 0); let rand = randSeedInt(totalWeight); @@ -7104,7 +7089,6 @@ export class EnemyPokemon extends Pokemon { if (!dataSource) { this.generateAndPopulateMoveset(); - if (shinyLock || Overrides.OPP_SHINY_OVERRIDE === false) { this.shiny = false; } else { From 4a39adacf88fa9b13a98def0d6dbf10329daba38 Mon Sep 17 00:00:00 2001 From: damocleas Date: Tue, 20 May 2025 23:05:39 -0400 Subject: [PATCH 24/26] [UI/UX] Remove Redundant Unlock Passive text (#5845) * Update starter-select-ui-handler.ts * Update pokedex-page-ui-handler.ts --- src/ui/pokedex-page-ui-handler.ts | 2 +- src/ui/starter-select-ui-handler.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/pokedex-page-ui-handler.ts b/src/ui/pokedex-page-ui-handler.ts index ddc16ab5a88..051d267259f 100644 --- a/src/ui/pokedex-page-ui-handler.ts +++ b/src/ui/pokedex-page-ui-handler.ts @@ -1888,7 +1888,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler { if (!(passiveAttr & PassiveAttr.UNLOCKED)) { const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.starterId]); options.push({ - label: `x${passiveCost} ${i18next.t("pokedexUiHandler:unlockPassive")} (${allAbilities[this.passive].name})`, + label: `x${passiveCost} ${i18next.t("pokedexUiHandler:unlockPassive")}`, handler: () => { if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) { starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED; diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index a35f426e8bd..f24a3ff9265 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -2184,7 +2184,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (!(passiveAttr & PassiveAttr.UNLOCKED)) { const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.lastSpecies.speciesId]); options.push({ - label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")} (${allAbilities[this.lastSpecies.getPassiveAbility()].name})`, + label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")}`, handler: () => { if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) { starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED; From 3c934808c004f4e90ef77c30308197eb9ef33e90 Mon Sep 17 00:00:00 2001 From: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Tue, 20 May 2025 23:42:17 -0400 Subject: [PATCH 25/26] [Sprite] Fix T1 shiny Eternatus not animating in consistent, remove unused exp for Giratina Origin (#5802) Remove Origin Giratina exp, fix consistent shiny Etern Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> --- public/exp-sprites.json | 8 - public/images/pokemon/exp/487-origin.json | 566 ------ public/images/pokemon/exp/487-origin.png | Bin 9290 -> 0 bytes .../images/pokemon/exp/back/487-origin.json | 566 ------ public/images/pokemon/exp/back/487-origin.png | Bin 11381 -> 0 bytes .../pokemon/exp/back/shiny/487-origin.json | 293 --- .../pokemon/exp/back/shiny/487-origin.png | Bin 11381 -> 0 bytes .../images/pokemon/exp/shiny/487-origin.json | 293 --- .../images/pokemon/exp/shiny/487-origin.png | Bin 9290 -> 0 bytes public/images/pokemon/shiny/890.json | 1807 ++++++++++++++++- public/images/pokemon/shiny/890.png | Bin 1666 -> 33055 bytes 11 files changed, 1796 insertions(+), 1737 deletions(-) delete mode 100644 public/images/pokemon/exp/487-origin.json delete mode 100644 public/images/pokemon/exp/487-origin.png delete mode 100644 public/images/pokemon/exp/back/487-origin.json delete mode 100644 public/images/pokemon/exp/back/487-origin.png delete mode 100644 public/images/pokemon/exp/back/shiny/487-origin.json delete mode 100644 public/images/pokemon/exp/back/shiny/487-origin.png delete mode 100644 public/images/pokemon/exp/shiny/487-origin.json delete mode 100644 public/images/pokemon/exp/shiny/487-origin.png diff --git a/public/exp-sprites.json b/public/exp-sprites.json index 2595b5a7983..5580bb5cb7d 100644 --- a/public/exp-sprites.json +++ b/public/exp-sprites.json @@ -179,8 +179,6 @@ "483-origin", "484-origin", "484-origin", - "487-origin", - "487-origin", "531-mega", "531-mega", "569-gigantamax", @@ -1293,8 +1291,6 @@ "483b-origin", "484b-origin", "484b-origin", - "487b-origin", - "487b-origin", "531b-mega", "531b-mega", "569b-gigantamax", @@ -2407,8 +2403,6 @@ "483sb-origin", "484sb-origin", "484sb-origin", - "487sb-origin", - "487sb-origin", "531sb-mega", "531sb-mega", "569sb-gigantamax", @@ -3526,8 +3520,6 @@ "483s-origin", "484s-origin", "484s-origin", - "487s-origin", - "487s-origin", "531s-mega", "531s-mega", "569s-gigantamax", diff --git a/public/images/pokemon/exp/487-origin.json b/public/images/pokemon/exp/487-origin.json deleted file mode 100644 index a146f68d70d..00000000000 --- a/public/images/pokemon/exp/487-origin.json +++ /dev/null @@ -1,566 +0,0 @@ -{ - "textures": [ - { - "image": "487-origin.png", - "format": "RGBA8888", - "size": { - "w": 318, - "h": 318 - }, - "scale": 1, - "frames": [ - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 8, - "w": 91, - "h": 77 - }, - "frame": { - "x": 0, - "y": 0, - "w": 91, - "h": 77 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 8, - "w": 91, - "h": 77 - }, - "frame": { - "x": 0, - "y": 0, - "w": 91, - "h": 77 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 9, - "w": 91, - "h": 74 - }, - "frame": { - "x": 91, - "y": 0, - "w": 91, - "h": 74 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 10, - "w": 91, - "h": 74 - }, - "frame": { - "x": 91, - "y": 0, - "w": 91, - "h": 74 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 10, - "w": 91, - "h": 74 - }, - "frame": { - "x": 91, - "y": 0, - "w": 91, - "h": 74 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 7, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 7, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 7, - "w": 86, - "h": 79 - }, - "frame": { - "x": 91, - "y": 74, - "w": 86, - "h": 79 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 86, - "h": 79 - }, - "frame": { - "x": 91, - "y": 74, - "w": 86, - "h": 79 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 85, - "h": 83 - }, - "frame": { - "x": 0, - "y": 77, - "w": 85, - "h": 83 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 85, - "h": 83 - }, - "frame": { - "x": 0, - "y": 77, - "w": 85, - "h": 83 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 85, - "h": 82 - }, - "frame": { - "x": 177, - "y": 75, - "w": 85, - "h": 82 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 83, - "h": 83 - }, - "frame": { - "x": 85, - "y": 153, - "w": 83, - "h": 83 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 4, - "y": 1, - "w": 83, - "h": 83 - }, - "frame": { - "x": 85, - "y": 153, - "w": 83, - "h": 83 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 80, - "h": 82 - }, - "frame": { - "x": 0, - "y": 236, - "w": 80, - "h": 82 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 80, - "h": 82 - }, - "frame": { - "x": 0, - "y": 236, - "w": 80, - "h": 82 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 6, - "y": 3, - "w": 80, - "h": 82 - }, - "frame": { - "x": 0, - "y": 236, - "w": 80, - "h": 82 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 83, - "h": 76 - }, - "frame": { - "x": 0, - "y": 160, - "w": 83, - "h": 76 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 83, - "h": 76 - }, - "frame": { - "x": 0, - "y": 160, - "w": 83, - "h": 76 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 81, - "h": 81 - }, - "frame": { - "x": 80, - "y": 236, - "w": 81, - "h": 81 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 81, - "h": 80 - }, - "frame": { - "x": 161, - "y": 236, - "w": 81, - "h": 80 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 81, - "h": 80 - }, - "frame": { - "x": 161, - "y": 236, - "w": 81, - "h": 80 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 3, - "w": 81, - "h": 79 - }, - "frame": { - "x": 168, - "y": 157, - "w": 81, - "h": 79 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 81, - "h": 79 - }, - "frame": { - "x": 168, - "y": 157, - "w": 81, - "h": 79 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 81, - "h": 79 - }, - "frame": { - "x": 168, - "y": 157, - "w": 81, - "h": 79 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:f669baef18fc6ae83124ad81c9b726f9:b705ee5bfe7dc7d92c348ffa4a4d6ce2:5d19509f6557fe13b0b6311434ba7e2d$" - } -} diff --git a/public/images/pokemon/exp/487-origin.png b/public/images/pokemon/exp/487-origin.png deleted file mode 100644 index 370ddf89173dc731773c3d0904099d582a00e295..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9290 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 sR?Pp9(#aC%{ diff --git a/public/images/pokemon/exp/back/487-origin.json b/public/images/pokemon/exp/back/487-origin.json deleted file mode 100644 index 72f5e4d4dc4..00000000000 --- a/public/images/pokemon/exp/back/487-origin.json +++ /dev/null @@ -1,566 +0,0 @@ -{ - "textures": [ - { - "image": "487-origin.png", - "format": "RGBA8888", - "size": { - "w": 326, - "h": 326 - }, - "scale": 1, - "frames": [ - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 95, - "h": 84 - }, - "frame": { - "x": 0, - "y": 0, - "w": 95, - "h": 84 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 95, - "h": 84 - }, - "frame": { - "x": 0, - "y": 0, - "w": 95, - "h": 84 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 97, - "h": 79 - }, - "frame": { - "x": 0, - "y": 84, - "w": 97, - "h": 79 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 97, - "h": 79 - }, - "frame": { - "x": 0, - "y": 84, - "w": 97, - "h": 79 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 97, - "h": 78 - }, - "frame": { - "x": 95, - "y": 0, - "w": 97, - "h": 78 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 97, - "h": 78 - }, - "frame": { - "x": 95, - "y": 0, - "w": 97, - "h": 78 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 97, - "h": 78 - }, - "frame": { - "x": 95, - "y": 0, - "w": 97, - "h": 78 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 4, - "w": 94, - "h": 84 - }, - "frame": { - "x": 97, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 94, - "h": 84 - }, - "frame": { - "x": 97, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 94, - "h": 84 - }, - "frame": { - "x": 97, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 95, - "h": 81 - }, - "frame": { - "x": 97, - "y": 162, - "w": 95, - "h": 81 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 7, - "w": 95, - "h": 81 - }, - "frame": { - "x": 97, - "y": 162, - "w": 95, - "h": 81 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 1, - "w": 94, - "h": 84 - }, - "frame": { - "x": 191, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 94, - "h": 84 - }, - "frame": { - "x": 191, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 94, - "h": 77 - }, - "frame": { - "x": 192, - "y": 0, - "w": 94, - "h": 77 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 94, - "h": 77 - }, - "frame": { - "x": 192, - "y": 0, - "w": 94, - "h": 77 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 94, - "h": 77 - }, - "frame": { - "x": 192, - "y": 0, - "w": 94, - "h": 77 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 94, - "h": 83 - }, - "frame": { - "x": 0, - "y": 163, - "w": 94, - "h": 83 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 92, - "h": 83 - }, - "frame": { - "x": 192, - "y": 162, - "w": 92, - "h": 83 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 92, - "h": 82 - }, - "frame": { - "x": 94, - "y": 243, - "w": 92, - "h": 82 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 92, - "h": 82 - }, - "frame": { - "x": 94, - "y": 243, - "w": 92, - "h": 82 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 90, - "h": 78 - }, - "frame": { - "x": 0, - "y": 246, - "w": 90, - "h": 78 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 90, - "h": 78 - }, - "frame": { - "x": 0, - "y": 246, - "w": 90, - "h": 78 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 91, - "h": 81 - }, - "frame": { - "x": 186, - "y": 245, - "w": 91, - "h": 81 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 91, - "h": 81 - }, - "frame": { - "x": 186, - "y": 245, - "w": 91, - "h": 81 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 91, - "h": 81 - }, - "frame": { - "x": 186, - "y": 245, - "w": 91, - "h": 81 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:d1a63c2aac4c99e778e6efb9fa120e53:11f49886c328fc8474daefc2533a7f5d:5d19509f6557fe13b0b6311434ba7e2d$" - } -} diff --git a/public/images/pokemon/exp/back/487-origin.png b/public/images/pokemon/exp/back/487-origin.png deleted file mode 100644 index ec3dfd6c8f80a4965e4bfbc29aa3f66ca7884c35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11381 zcmW++1yCGK6FuAs&K-KVySpFm?rwqLE(spwa7b{w!#xS^5S-v{!975L015W<{adv) zRj=N3?`+S`o9>-BEe%B+OfpOW0Dz;cB(DPiAVB`R(UD#e8jPX-*M>t&O;6#qeZ5#% zSVTotR8&k%c<@|Yg1vPB85yOeG@`Y^fWgVd$vnV|tj^0Kz!{NC6o{IUENU~(%m;bWeZ7P|LM?`$n4j{(N=c+ zVQIvZdqMQijED0)9Y)>^kCE_8!@Ex!9U`8SmM#_t-GyRQ@IH=lloGVZzt zywN!9vHV&B?f5$Xe)D~3=?DFosB2)P`QV>kN;#xSlsHhAFaMCjQG3$+k-#?^qT3&! zqekQ9XU(Db$Lo0me>=yok%n1^P&>m{;@iF^UG}l@BmP2bjpsPevR_a1;ayzE(jHcQ zPJ>NkL%YL)PYSLloOF2@IZ0j=?qjVl7VlozS`+a7s7{pZ%%K@kPugXk}PE^8#P!`KjZ3sZ*sP9EZtC^zFG#Q_00AqwIq%*UcH!9pOL_4LP@0QU6n@(+S7!m+6J5?@m8E z>MtxpL-9eDACl~lNo=8cb9ThNOU=2?H^etSo6b1B)3Nzv=x9bm6{0zcyk#u8G2SLh zf~f820ic#HLrV>1KyM>-{K^FSmom`|$`Y}A&f#D_w_RP#_t$kZ6;+8!T7eWNHasGZ z<~bF*+&R7PrG)laY?^LbKw?=Ay9NVw@3A6lryC_N z?2txy9VkPQDxJAMB=5G1ueP3HQDPErd}2^b#DhgbJK}Q%9H<$Kbn9?tB{>lyhwLmdDGemWzKeBjT$WM03C}$%}?Mc=*POEvJ(24bFGs zbs=eA@kBM8@{2*8s?k;kP-H4OfRr{LI^I{c-?<fL5r zfCiZdP3+jwtAXCKT~XDI(2GS$*!eh+7RCHni{c3U{fHiRDi0jw5~}?i+4Mo6BYV=f z@0#8p?d7nhPf512a0Ty0;|zdz0{dDTggE4 zUl4!&jubT3x(*_x;*8^1obLQ@@dO|#RmppUL-W=TZoLt8iC@W2e$*CvLqVev!fG@+ z>~HL#fz-yw_ijEK=T45RSPka-zwiW2opr$WA9;J55wcPeZ@%`Q9+jKilkRsW+;NeC znV7%Mx%B6R@Z?#gv~CA|Alfo@Xfjesq}|0n<5{Idu)=A~p{6UUD=|d|`^X2#@76TB z_znFyMZZY;+0U@H*ExQtiDTq-w^ILGLs2!x*&P4~duIv&sJ1@ALKN9cBz5 zi7Z0pgMYa?4!V{^golva4wK0}Aur`%I$iCFj;!JtRHGYpbN`kJ#g2}bhXSN=ww6nI zNZTy&+6JD*EwF3+Xi&KgaZT^HRbS#w@bSB^`*_AS3?W0UlSAW2i+|W*h5na^^<}PB z)J)R_9g}O{jG|Gm7AYsz3M)rG>9qA_g#@hFertLb$^TMHE6NJ#-fhIPqM=d}7E6zp z%v@b-nZ+$bB{sY|F4jVudR7D)U{DN*DL_R zzz8enV-%g;--*hGt0xUK0yD@3_u@J0Y6IkBh7XqGTskMrl6>r;1NEx%OS-4`fSote z@28vwB%}69C4=^xl<3^k19Lqd&WMNl!Z&OB>ca+O>LYHIzAZ`CLQq{y3!PzZEhCbk zvfbvey}#gGC2fT$BDs7y2|c)~^9<>Q<%6py?*UHr%MYe=Ysa0W(o9HO{hFs~OMKa& z3nTQd)(1+O9H zBO{aSH{Eu<4Y8ZR2{XB@kvqeVZmzgWroZ8=5<4i|D>#B0@I3c)zJg)JO&b=RK~f`>4I+@ud2LgbP)S7UlBd7YL5agFhh+uDnic8!d?I1t4)#H9sZ!*Z zbbDQPFPRQHP0=>C*VI7^rSpaB2fs0S z|1GTivzvifW(*G#Zse)3aeU8%P3}-`3}u!UC}M!jvFcYGNtu1HCEFf~dZfA-`mLXl zueWBx+cU~Yr@aeK=IYG7dW^9`!>_s#meUQb8CFc9NC#uT1~{5&cTRW^b*|IEfAZXu z)aX;s+@E_BBP`#$I$wDoIe6%O(n*7dBXfV|?&W~I=Me}IP^0lF$(`#TOIG+{e7o#q zc+B}8RCNNJoC-l|#Hf}yxe8w*NNBzsSv^3iI}V51u&9$Y?6$XlWfGCYowb(QdSh^W z@a>1n1v|MxLcjT!%(s{ET%}gyI2r1_Xcqqdjz!~SPYB9RRyHw~Q@(pT?bAnTOjLM# zUXBHVnw=6#rY=wI-Q+5`_zjaWCLpTS<@m2Pr5(!{emN(7)vkS~%mw~2y;v?=i(FVW zSngK+Uv(kP8SNeV24eRd&}&HZ;;*h|KTO33yM*LSQ)dpz!v3*QuF1tZrE}SdiSo1@ zp}IBQP6`d~&nOO=y9gDF!v{QEE?6zrL)GOdzGh>_xeDi> zJQ_!_*eSh9y9tBy?(TJd!V`GpvPkF8)ei6;{t21JRx@ww)=YY&4U4`mY5`yCAZMMg zh!W`>V!x6a;iq7SlVVlDqITFuXEpotUkxL6p~~HKu7q!;HxIKy;w+BK8(x_SVZ24r znQt}MCg$Y~S0ZxW_dI46q_6BDUp8IEwWsfjE)KN{Sh&2-;IBpbWV23 z#mAm7UJ-PR-kj0B^w(;w;t>1R$>N*QiqkIu0Qo$ueI%xR>!Iy|C9WrZK*cp z)?-jZZ#?mkn!S}g9-H(W6!?Okob83=@b~)UVP)tq?Q{;`H&YC^eI&jnlEuL1YcH<6 zGk3!?^_t4?!H14)O9?6zi&0>XcZ{IBUQLJ5uu*A%!@UL zctcZzgQSbh^oAje}Vi zl4sWTu~4tl(=S;nj>-m%{%QuB{CwDbDnE^~=A^qqku44a^9QOwN@B%}%t-s+_}v<- zVNtpmYzpeS^i9wloa6R{2&LdES=RfSx8Q^|E#ju6)*xDQn2WKO%^JTosEf|dDmXeK z%i5K&>>l?H5xPm&us)ktoOp{kE_d^5P>(Foia}`Z-|61%gQk;cjKxq&cNB=og4yh6 zAskNnH5Yn88~*ESR+Z?9L6yVeJ0H#PTaNcL(!wxD^V<*Uh|3=>kE(2!2IqeOU1nVE z2Pdl1eg`DCa9{YZOjXy2O(!IeJYpFHp6@%lHV>Z%E!&W7(p8!`FIw%Z3e4rdrwCRJ zS&K-{sMpwiZd{semqPr@VeKEybN{FM!|a?l&tP2UqT6DA8Q09j<>!g9U(=@R-Sf{e zogcO*pNsc~3xz+rQ@n4hUb2z!;Q1r^SmvO@Rx37mGuaZHP%7FCjDPpFXO}6+CFt`3 zW$xui<|3SbE0Vt5R2*fFxXzk2(DYl%&V5_hz%oP=f%|21pf4|2k#e=oTf-}&73poF zq_G-#2DU+6|JWT$6NQO%T;kUmHLLdUqK^Ycf@y!1liE&hEW3 zAwddg>x7QJ{Ho^}{QS-fP>`0QOzuS>f2gZlZ}2ix8xrmS)*R>zuKnZR{;1~lBatnY zQdcY|a9?0A-w>Yw`)>Y}RI_U}ajE9)9V1|G?c+!4>n+wTS|;lR7E}3=zF13@dX6$C z13y7N)ZKgJVZ}q<)f};oL_nN+$sVTxOUSw#7xyqbP-Zbw~8+zT_V0!PHW{ju7 z{^)-G9XCBPNMu-*X<7e`TD3p#qUK-*wEqfy#w^<5MS(l_Ph4vR;`iRVfp9IO9AQsq2^ z?%zPP^9iK;g$jjgeOoLCC^IfT*3T)Na~2CRt2<4lX<~r&-Cck1U;ok3Ba!UpMD@HGkiX2Gjo=bEpvcTgno^x5D;}Oja zRelYxQIEuO`RyJK9ySTu2%U(EuIjT6`3ZEW*05cUxo2|`iC+EP5s}Yry1La;Tkp0b z8sb%gtRNx4W}WoZc^&))zatPLTM^kkhA4Ya)v7adNJiF{PPV?YB)z0<(ZFHO3)js+ zhn}c%MA%OX1{4>0Wu!jX9$?Xg9Of?*lS1{~3WKSmH`;(8|LcZ-k8RMH(JX7dJczxC zhhF96q{c*RgrdT7 zgfFXlwJXVc-|6a22t<^BC#B_cNBTQ_|IS1duC!iK4=wK zr@+RO2pN6(d1AcP9u=M0yASQlz7nMGWGDAJ)>)ZXMQ!{l$Tv;fJ|=w69R#u0+Nn5@ zV^4}a@<3J^3qPDN^9U(swjDJyO0t_rpu?VvuuK2`O`KiI@xUa$hh@vP! zeK@k^i>q85e4fNuZf?L!%G!(w=+!ofho&Z2>!_b?B^Pkbo_2nU)Ifh$?5|kF3?x(( z`63^d!U6JB6stFe5KW-yLwbSp0J^9I{EeAJyoDJ>s3fn718@c(WUWyPppnteiHqMB(7mFcRMg>k|04xG zMHZ51?m1yLB9dt5OUwk_T#&Jp_=aRh^c2uVg8Bzjp#tgG7&;zNZC*|JNS0w706%j_ z)lb2;*6OEn-wCVTO}QWs;>q!h1YB;0(`fT`$rfCd%}pG}_PTcuGdQ2pzK4 zoEhX?LH-${h=euDNmQ)KQK=UUJ3$lJs{E{)9bYIQO@s0_f-=LOgG_qy!28CweRW{s zdCY@|fD?}MI&oo-I$T=Yhd*4hy3n$_njYSX>B|ayHiUIk5q$?KgDIa+*kn&O2W{X{Pj+ zG&cf*`RZPChSh~M<*?sBQIJR6N82Of&{H-hun{oMFe3m6`N39iu&Zl00bw{m!^5`q zxzK03{nXAk@aAKaFv7mv)BQ!CUe9^9-?bt<07_GCHGY8VEqR zjWsxipk z+-U*~(&{*#?S`#QWHTRV^WRST!86TQ|4ic<5aE+J zyVxnQI*rbTCIPV42Y7c@1h@S5WHCHkAbXZz{3}-rGX&C@rYhq7*2sq>E~lD?I58d& z*u*W}Nypo(HS--*%|@*x)~l1jlNVqbL7M#-{^WJKfU%(xueZk|Dw^=`Jn8nT(HRm} zvCi$Oq!XY*o(kP00~lN+J%@`KFK<})=96mS)*$yF3b;mF)&Kq+pP<)Agq~vZHz<*u z5d=>2i+~uAwl)0`fk4viLGINRcXBBCMDyH9I<=w6@%nOM>keVk{RgJT=DzfxjSvYrbV%~ztqS8CqSi9lljGgXRXLifO*tbasC+aRVI-fqIRxh(RDk zcqYQE&)r%;>I1KVQJ6YJcD(0;PC5q&{(zRI#;5c1lOV9t4Mubz%Z3P#M!32IkB+&q z-$7j!5SnSFO4hFJU5%btXo*I>bhp?FTqV`Qkv*B)0O1Bt$ZQznX|fn8iFLOP~+#6=4aE z@K&t{|Mxt#|L@%h`Gll^2d=k89$7`5Z$~^O`$*q0E@I4e1CIb?C*y-%$hA%pE$zT* zXPk$2UDJfb#M2S4KQ7)1Tr0%Tj-GpKtOl3B*wiQyB4Po~PQ{sAUWE$_ejA5*-^Pr- zc|-tye-WaQE>jIjC9kP_IA2co)_J!LMEGJM8)mkhU}o$4XS$K_5WXt=Y5)3Jj8>=RaEsI6+TgK9xfp0i~UlPt$TtH-${}tv+fVk zq$usbZMi6 ziEd2KJ4p~1LQEa>&|kAa?7GGqv1g+D`?Z?ILoAuyu9@A=Z2JL7EFH#Q_C7Xq>~9)D zLM`3UmICny#|#!TxLQ-SFgip(MK3Em4=$S^GUvrt%S&~FZh>+{YhR^5EW^!eBF#5n zWV0{NqO3rI?{=Fd>N~u;+WgQE_N)u)7^ukN>!!o!B$rcSRrs;Un5^th&JtUhmPBu? z)s<=jv(k%(#tbT|=wJkgP0%`D0=d_J=wJ^bP#$C2om4?Xt@UOwgi~TBIUzb2nQ?tC zJQRUYAiY`y55uui_cI=h?vMOioCs~}uY^$K*#>Z?GV92`iLx+D&RIr*p_YwyqTy-+4_i(^{kV-$6sdG*IDCgR zE8@(1iwA|AWoe*P4NX>&mjE&sT_HdL(YNt`%opykNf6I5O4eK?4Ar-1N5cqQL*Z5P z1Ta9$(6n8Ip(=>ZI?MKcqG_1RxGDLoi{hx{^D;RZ*0Xjuk>74oJlUZt0Ou=>2wG_h zWfUJej!{YCWCTpXw3DRlBxDrGHC}}P6@;Nt3Z#rq_~7)moB>Woggu2TT+`L^1Euyl{MxxaOamV@JFVLIJ63RmR%kq zRL`P3c#t+lakeWI@wTh*XADl-G!MS}t@YKL$& zuz4&R+aHDdC_o%)7z-{TV@>Q4rJ&lBF9i-vr%`Nhd!K(lZ6R<;(XOUD8}=m?lk$n1 zVMLFL$JWTbsiI+C7~k3^#WBrdE(#%lRZtcBMbt}eX0D8OI;FF^;~y-*GSfS zqA5eYz^@=8=74)>K5aRUt3E^vj45@9_A>M*y*3^gGj#fg=E7Vc_@A zJKL&>u5b~qdDjerAhf$=f7F4B28+IPJX-Y;Gvql1UTGZ;`8=GoQ_B$*7Z|^DY%129 zH$#0DI&sC^mwaKYNKpjNK4(em2~3Wp%SD)1jH5>3YTM_(C!K)A2DtEWw!g1gc}|1a z&Le|Za1h3@Kv6g2zOO|xSl2(^BE-)-fDqbnju?eMKh+U(rN3Cx2f8XF!LBuam?r6*}x~={diR zKRs6wG0y^KcK-(7S|4{6wDiCxc59c`Eo-~ zGTQn6x*K0u`$+3nZea_~yA4)W6S&G#GR zui{px(2KK7uGJn(FWZR@w_eH+*uEjUjR~LW+MwVo;|vOpjF&=&^@CDkB0cNE?#_A2JTQ8Eib)5o^*;9s8wT*d0qXVy zE&4nt1N8}khgbCEV_EIX3DgnV`n|%*m11%rUE728udyNW8-YP(QW-o8{*%677X2`O ziK^o__G%LO-bhw@C@E#6X;$zSsnbC)kQjpRj2iT?Ywjp@v6uP`(2NXw_hJ{!P4=bkGl z`FBxr^uay`X{3VBbE2L8MewX z!qsH!x9N}Dv9ZXp1`*1AniLZ1&X~d$$5k5G^2)IJlO?jf2a1Kcqd?`)H3S?%Ukbq| zo6Nkt7QkQXFsKy5pbUhK+UE4;hw36Gf)1*zNg z4%0eJT4NfUNd_1#=YhD+3my>~1$!#0Xppqm^*D01A4qPy29Znes$b^}(;K%uH3&?E z7KXwIKnBvsBPqU#MP|eI4Q?##)SsXCQp4cFZmhu1_GX%Bveu#qKm$-SP;sT9fqz%0 zq50TIrB0&j?$0ZAawD2!{VXqJq#q~}CPv%ZrVWygm{qpYas;JU!nqi@uwDD#=?%9- zZHt6siPPKaHEGR|-;C&qVq%~4zb|pDPr&a5W|GF(^oMp&5~Rs!QNTrILmta%&8D4- z0g<9(S%EyodfY9klWku8`SK?+T6uae7D%Wv5c7TwjQSCX)%2`7#LhyETVF$j_izlu zA6WTO#uE|CP#7Q6(`7Uh&`OTk@laYKmmLCf9?;t|>#2EFR_4ZMlkQSLOqECT zB6+vpjx;rDQJes>uK5YJcgAyo9KF4?l$Nz-BCyd(=`y~3md}S~RregzzVXn=Vqt<= z;)HDtakE~ssAS#c)qD7Nufb_omP!=~e6!^!5PEBae1eEf9Zt-SlF|~k1;4~cEJD~| zh%8B4M>BH_Su;ywYXkS;7Z3IUU7FBWd(4!*9?h{A4;kSy*weh_HVXk&JMPXE1B2W) zIK$EV9FPKX1ap7*4uBcg00+3of@Ft6+Y6qSdr%_@jF@J{rwpIjqtS{olJl?zcTeSo(qKyO(*13CNT6c7mS#3kxSV` z05ad?#gMpTBhV4?20C{6K%f#jV(Ob`n=dJgHrH8%iSxN-L->FyHX_AB#fPVs8vvp+ z6@wKXGa((iNN#zUjK-1Dr+;*<%(k?P_am+37z55c@88CN$|B1MLc6qA+4ivpir2`dzR z&jj7jp8*oc*kme4%fTH^^~V#%*lfVok=FhNH~510P_Y)pJ1PuWtbi%Q6L@aQ@9l)u z7y{9-Hl+e%C-}wo-)9svsMO_xc_aS*`3?#(jyw&@U4m<$sggO5?u zWq^FGYxX;Q9wvNJ*b*f*<{&eTHo!5ytq~VU8ZNUq9ze}4jKYZc%8#DLS29r^ zj1n1b&B}oy6$|J2@YT16bEb|_ZFNkFgU9Zr2hAQod$`P(_lC1=%Yg>-knIvpxCRyrN%qpatuk`Vg5>>;9`zC_WK$Zpp{ZKR6F(S8w4dB%ui!#D|TTHL#8kp4Ea*5{ag@cfI*{M22KN-O}7dzxaKd z?8Mp}LnwsdPw^1Nd#C%%r8dF1kX*$6kC4PiuKoy~fOm-M^eQ0x=>4Tg3`lyFHL~Nf zDYYQ(YFLvCJ+0n7#gG4^#eBzoCguQ9){rEJ|GXx}$J5x}I5A43YXd~zh9nvMAN0F( z<2zn0jbPv{g7qH;G<`Y*VhpBIP5U!S_zw3TqD$&*dw+{yh>`Ww%2o<>(0M~S^_QaU z@;Wu^b!c9UO{s1{U;HM0#CN^5SO;h{teA<=gp`GvT^8J31RB1hNGb~Zi;g+GhKXu| z{~3)dyM6^9eXbN;?ru^9=<{R`_obaUT~Rlmz{TIAR|BG-?X}wGtj91!;(ShoXudxwCv3uupQ#D5ZL?nYTsR-nC zn2#Z8_%6+?Ve{=SI84U%-;EeQZPR*#5x}!FR z-;2v~+(Vk5d_m2DX;czMY>w6asvd5P`6+Je8^&Q*wd%IK!yX(FQ@<(Ld0qn{-=3{M zt1kcTlEI$bJQkET)o6H)mWy!&6ey7ML_9ulV#Huidy0Fz_%S32jXDT7Y6twY1H1vx zp3m9y%iG+&r=TkqW<6#Me!i6}0!ntm?kSLpg&pC!FC>MwV4_1bWuYa*i|2*&kF-V4 xNbp>=^G*ET-)hwY|mOtxE6KtqFvCumAu60d!JM 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 DdfIMP diff --git a/public/images/pokemon/exp/shiny/487-origin.json b/public/images/pokemon/exp/shiny/487-origin.json deleted file mode 100644 index d770a34a1b8..00000000000 --- a/public/images/pokemon/exp/shiny/487-origin.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "textures": [ - { - "image": "487-origin.png", - "format": "RGBA8888", - "size": { - "w": 318, - "h": 318 - }, - "scale": 1, - "frames": [ - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 8, - "w": 91, - "h": 77 - }, - "frame": { - "x": 0, - "y": 0, - "w": 91, - "h": 77 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 10, - "w": 91, - "h": 74 - }, - "frame": { - "x": 91, - "y": 0, - "w": 91, - "h": 74 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 7, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 7, - "w": 86, - "h": 79 - }, - "frame": { - "x": 91, - "y": 74, - "w": 86, - "h": 79 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 85, - "h": 83 - }, - "frame": { - "x": 0, - "y": 77, - "w": 85, - "h": 83 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 85, - "h": 82 - }, - "frame": { - "x": 177, - "y": 75, - "w": 85, - "h": 82 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 83, - "h": 83 - }, - "frame": { - "x": 85, - "y": 153, - "w": 83, - "h": 83 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 80, - "h": 82 - }, - "frame": { - "x": 0, - "y": 236, - "w": 80, - "h": 82 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 83, - "h": 76 - }, - "frame": { - "x": 0, - "y": 160, - "w": 83, - "h": 76 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 81, - "h": 81 - }, - "frame": { - "x": 80, - "y": 236, - "w": 81, - "h": 81 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 81, - "h": 80 - }, - "frame": { - "x": 161, - "y": 236, - "w": 81, - "h": 80 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 81, - "h": 79 - }, - "frame": { - "x": 168, - "y": 157, - "w": 81, - "h": 79 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:00abebb007c47ada81d4e754581d7146:4691e19364eb9392dbee1ee37d737c8b:5d19509f6557fe13b0b6311434ba7e2d$" - } -} diff --git a/public/images/pokemon/exp/shiny/487-origin.png b/public/images/pokemon/exp/shiny/487-origin.png deleted file mode 100644 index d0f0fdb6b9b40f63b37a71c4d9197fbdd095c60d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9290 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

oS}2mx?{p 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 delta 1649 zcmV-%29Eikf&zjKGKo-5M-2)Z3IG5A4M|8uQUCw|TmS$7SOfzA004?mjeP(B05DKY zR7C&)00993GXN}+GADlzf~QRY0004WQchCl(Q?R&sKm! zDRoJ!Yg(X6qyQjw5R`-T_ulO8?cC&Y7a6-|%=^smecx~P&v<`tv<2+7G?3RR+*b}X zE})^|1)8`+az2L+zLj@D{`P|g@*)MC&w~!W4=&8X@@(Brw0|CEE(a7mQ0Hl7bJXCP zcY-q=8=W$RrcI`0Bk=Hhc>#ycb;=#3zt6+I;t97H`XGID$sUcTzEnlx~ zJ{${#E|L@vv)N z!0i{t{LS1d!{i1%;Vg^rq%YlCn|bqi*njxE`{EcmWxVEuS18n1}x% zHb3lUA|$pv$H7@!GUviMH|F6nCc)y{qF9m7Q#ya|V$mf(EDCJ>ae&@74ht40q~IV59!_~J2iG)m{P~SoPrS`24LUlee%u@B%t3$Fby9FX;Pa1KRQi6UQZic=xWw>t z&aJL;o-!#@=F*H#bin4Q^lhi1jtY(QU`|=b*Cn5CqLF2|iOGvq#CG$y@$DJWwp*y^V7i2unQaV%7X&%T} zb@u69$Usrr(yb1SWg{qo(S^tpd& zQd}@&iI=!66`pM0o0y5AgIH-bV*MMGQrTu9d3p4BJ2&IW_h0Kh4QeEZeIt}Ha!4?~ zKO!Ydkl#iA&G^?J_b|<}9Hq@z$o6Pt`7@VB_9fL^j@mo>$RkHCBA zV2Vjjy!hTE|Ngt9qx)LuOOnwHyZBZj52RdNX~0t@B__o35wQFi|5@KVj5>-@jS;AqL{gANO@U00v(2qZ-cmXHg{zRn$X9=S;?spF zfHh{^WB7RTk$!hWWTrJh@(GnMd@D^rIe2gwi#T~EP8N4fka8eq#oRo`O zi8+*4PlzopNs03XPK(ZC4h*#7*)dKRvR3Y?%QByb+E$r3u>(UI@~80%u@c*eADfJtz#^*E$26d00000NkvXXu0mjfz!NVj From d1b0bbb155087d174d053aeab4de643382878062 Mon Sep 17 00:00:00 2001 From: Sophia Date: Wed, 21 May 2025 08:14:16 +0100 Subject: [PATCH 26/26] [Bug]: Fix #5010: roar and whirlwind missing fail message when against a trainer (#5659) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [BUG] Fixes #5010 Roar and Whirlwind don´t display a fail message Roar and Whirlwind should now display a fail message when used against a trainer with only one pokémon left * Apply suggestions from code review made by SirzBenjie --- src/data/moves/move.ts | 15 +++++++++++++++ test/moves/whirlwind.test.ts | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index b190729621c..71807288abc 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -6390,8 +6390,23 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { return (user, target, move) => { const switchOutTarget = (this.selfSwitch ? user : target); const player = switchOutTarget instanceof PlayerPokemon; + const forceSwitchAttr = move.getAttrs(ForceSwitchOutAttr).find(attr => attr.switchType === SwitchType.FORCE_SWITCH); if (!this.selfSwitch) { + if (move.hitsSubstitute(user, target)) { + return false; + } + + // Check if the move is Roar or Whirlwind and if there is a trainer with only Pokémon left. + if (forceSwitchAttr && globalScene.currentBattle.trainer) { + const enemyParty = globalScene.getEnemyParty(); + // Filter out any Pokémon that are not allowed in battle (e.g. fainted ones) + const remainingPokemon = enemyParty.filter(p => p.hp > 0 && p.isAllowedInBattle()); + if (remainingPokemon.length <= 1) { + return false; + } + } + // Dondozo with an allied Tatsugiri in its mouth cannot be forced out const commandedTag = switchOutTarget.getTag(BattlerTagType.COMMANDED); if (commandedTag?.getSourcePokemon()?.isActive(true)) { diff --git a/test/moves/whirlwind.test.ts b/test/moves/whirlwind.test.ts index 6b5133ec7b1..67ffb77612c 100644 --- a/test/moves/whirlwind.test.ts +++ b/test/moves/whirlwind.test.ts @@ -10,6 +10,7 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { Status } from "#app/data/status-effect"; import { StatusEffect } from "#enums/status-effect"; +import { globalScene } from "#app/global-scene"; import { BattlerIndex } from "#app/battle"; import { BattleType } from "#enums/battle-type"; import { TrainerType } from "#enums/trainer-type"; @@ -161,6 +162,37 @@ describe("Moves - Whirlwind", () => { expect(eevee.isOnField()).toBe(false); }); + it("should fail when player uses Whirlwind against an opponent with only one available Pokémon", async () => { + // Set up the battle scenario with the player knowing Whirlwind + game.override.startingWave(5).enemySpecies(Species.PIDGEY).moveset([Moves.WHIRLWIND]); + await game.classicMode.startBattle(); + + const enemyParty = game.scene.getEnemyParty(); + + // Ensure the opponent has only one available Pokémon + if (enemyParty.length > 1) { + enemyParty.slice(1).forEach(p => { + p.hp = 0; + p.status = new Status(StatusEffect.FAINT); + }); + } + const eligibleEnemy = enemyParty.filter(p => p.hp > 0 && p.isAllowedInBattle()); + expect(eligibleEnemy.length).toBe(1); + + // Spy on the queueMessage function + const queueSpy = vi.spyOn(globalScene, "queueMessage"); + + // Player uses Whirlwind; opponent uses Splash + game.move.select(Moves.WHIRLWIND); + await game.forceEnemyMove(Moves.SPLASH); + await game.toNextTurn(); + + // Verify that the failure message is displayed for Whirlwind + expect(queueSpy).toHaveBeenCalledWith(expect.stringContaining("But it failed")); + // Verify the opponent's Splash message + expect(queueSpy).toHaveBeenCalledWith(expect.stringContaining("But nothing happened!")); + }); + it("should not pull in the other trainer's pokemon in a partner trainer battle", async () => { game.override .startingWave(2)