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] [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);