mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-15 06:15:20 +01:00
Hotfix 1.11.3 to Beta
Hotfix 1.11.3 to beta
This commit is contained in:
commit
e438536dc3
2
assets
2
assets
@ -1 +1 @@
|
||||
Subproject commit d2d9309cd1acfcebeefbf4c1c63e1104a1294ed8
|
||||
Subproject commit 9d391bd666f339c31db3d48a9907139950c14d1e
|
||||
2
locales
2
locales
@ -1 +1 @@
|
||||
Subproject commit ddf9509e1c6abe8fc93b455d79bfaa0202e05ede
|
||||
Subproject commit b5b0d94eee7cbcf0e055f8074ca1ebedb920e59e
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "pokemon-rogue-battle",
|
||||
"private": true,
|
||||
"version": "1.11.2",
|
||||
"version": "1.11.3",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start:prod": "vite --mode production",
|
||||
|
||||
@ -1833,13 +1833,13 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for abilities that modify the hit count and damage of a move
|
||||
* Parameters for abilities that modify the hit count of a move.
|
||||
*/
|
||||
export interface AddSecondStrikeAbAttrParams extends Omit<AugmentMoveInteractionAbAttrParams, "opponent"> {
|
||||
/** Holder for the number of hits. May be modified by ability application */
|
||||
hitCount?: NumberHolder;
|
||||
/** Holder for the damage multiplier _of the current hit_ */
|
||||
multiplier?: NumberHolder;
|
||||
/** Holder for the number of hits. Modified by ability application */
|
||||
hitCount: NumberHolder;
|
||||
/** The Pokemon on the other side of this interaction */
|
||||
opponent: Pokemon | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1847,35 +1847,12 @@ export interface AddSecondStrikeAbAttrParams extends Omit<AugmentMoveInteraction
|
||||
* Used by {@linkcode MoveId.PARENTAL_BOND | Parental Bond}.
|
||||
*/
|
||||
export class AddSecondStrikeAbAttr extends PreAttackAbAttr {
|
||||
/** The damage multiplier for the second strike, relative to the first */
|
||||
private readonly damageMultiplier: number;
|
||||
/**
|
||||
* @param damageMultiplier - The damage multiplier for the second strike, relative to the first
|
||||
*/
|
||||
constructor(damageMultiplier: number) {
|
||||
super(false);
|
||||
this.damageMultiplier = damageMultiplier;
|
||||
override canApply({ pokemon, opponent, move }: AddSecondStrikeAbAttrParams): boolean {
|
||||
return move.canBeMultiStrikeEnhanced(pokemon, true, opponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the move can be multi-strike enhanced.
|
||||
*/
|
||||
override canApply({ pokemon, move }: AddSecondStrikeAbAttrParams): boolean {
|
||||
return move.canBeMultiStrikeEnhanced(pokemon, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one to the move's hit count, and, if the pokemon has only one hit left, sets the damage multiplier
|
||||
* to the damage multiplier of this ability.
|
||||
*/
|
||||
override apply({ hitCount, multiplier, pokemon }: AddSecondStrikeAbAttrParams): void {
|
||||
if (hitCount?.value) {
|
||||
hitCount.value += 1;
|
||||
}
|
||||
|
||||
if (multiplier?.value && pokemon.turnData.hitsLeft === 1) {
|
||||
multiplier.value = this.damageMultiplier;
|
||||
}
|
||||
override apply({ hitCount }: AddSecondStrikeAbAttrParams): void {
|
||||
hitCount.value += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1895,10 +1872,12 @@ export interface PreAttackModifyDamageAbAttrParams extends AugmentMoveInteractio
|
||||
* @param damageMultiplier the amount to multiply the damage by
|
||||
* @param condition the condition for this ability to be applied
|
||||
*/
|
||||
export class DamageBoostAbAttr extends PreAttackAbAttr {
|
||||
export class MoveDamageBoostAbAttr extends PreAttackAbAttr {
|
||||
private readonly damageMultiplier: number;
|
||||
private readonly condition: PokemonAttackCondition;
|
||||
|
||||
// TODO: This should not take a `PokemonAttackCondition` (with nullish parameters)
|
||||
// as it's effectively offloading nullishness checks to its child attributes
|
||||
constructor(damageMultiplier: number, condition: PokemonAttackCondition) {
|
||||
super(false);
|
||||
this.damageMultiplier = damageMultiplier;
|
||||
@ -6657,7 +6636,7 @@ const AbilityAttrs = Object.freeze({
|
||||
MoveTypeChangeAbAttr,
|
||||
PokemonTypeChangeAbAttr,
|
||||
AddSecondStrikeAbAttr,
|
||||
DamageBoostAbAttr,
|
||||
MoveDamageBoostAbAttr,
|
||||
MovePowerBoostAbAttr,
|
||||
MoveTypePowerBoostAbAttr,
|
||||
LowHpMoveTypePowerBoostAbAttr,
|
||||
@ -7298,7 +7277,7 @@ export function initAbilities() {
|
||||
.ignorable()
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.TINTED_LENS, 4)
|
||||
.attr(DamageBoostAbAttr, 2, (user, target, move) => (target?.getMoveEffectiveness(user!, move) ?? 1) <= 0.5)
|
||||
.attr(MoveDamageBoostAbAttr, 2, (user, target, move) => (target?.getMoveEffectiveness(user!, move) ?? 1) <= 0.5)
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.FILTER, 4)
|
||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getMoveEffectiveness(user, move) >= 2, 0.75)
|
||||
@ -7636,7 +7615,15 @@ export function initAbilities() {
|
||||
.attr(MoveTypeChangeAbAttr, PokemonType.FLYING, 1.2, (_user, _target, move) => move.type === PokemonType.NORMAL)
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.PARENTAL_BOND, 6)
|
||||
.attr(AddSecondStrikeAbAttr, 0.25)
|
||||
.attr(AddSecondStrikeAbAttr)
|
||||
// Only multiply damage on the last strike of multi-strike moves
|
||||
.attr(MoveDamageBoostAbAttr, 0.25, (user, target, move) => (
|
||||
!!user
|
||||
&& user.turnData.hitCount > 1 // move was originally multi hit
|
||||
&& user.turnData.hitsLeft === 1 // move is on its final strike
|
||||
&& move.canBeMultiStrikeEnhanced(user, true, target)
|
||||
)
|
||||
)
|
||||
.build(),
|
||||
new AbBuilder(AbilityId.DARK_AURA, 6)
|
||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonDarkAura", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||
|
||||
@ -319,7 +319,11 @@ export class MistTag extends SerializableArenaTag {
|
||||
cancelled.value = true;
|
||||
|
||||
if (!simulated) {
|
||||
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:mistApply"));
|
||||
globalScene.phaseManager.queueMessage(
|
||||
i18next.t("arenaTag:mistApply", {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(this.getSourcePokemon()),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1532,6 +1536,11 @@ export class SuppressAbilitiesTag extends SerializableArenaTag {
|
||||
const setter = globalScene
|
||||
.getField(true)
|
||||
.filter(p => p.hasAbilityWithAttr("PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr", false))[0];
|
||||
// Setter may not exist if both NG Pokemon faint simultaneously
|
||||
if (setter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyOnGainAbAttrs({
|
||||
pokemon: setter,
|
||||
passive: setter.getAbility().hasAttr("PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr"),
|
||||
|
||||
@ -100,7 +100,6 @@ import i18next from "i18next";
|
||||
import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier";
|
||||
import { inSpeedOrder } from "#utils/speed-order-generator";
|
||||
import { canSpeciesTera, willTerastallize } from "#utils/pokemon-utils";
|
||||
import type { ReadonlyGenericUint8Array } from "#types/typed-arrays";
|
||||
import { MovePriorityInBracket } from "#enums/move-priority-in-bracket";
|
||||
|
||||
/**
|
||||
@ -1117,20 +1116,34 @@ export abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if this move can be given additional strikes
|
||||
* by enhancing effects.
|
||||
* Check whether this Move can be given additional strikes from enhancing effects.
|
||||
* Currently used for {@link https://bulbapedia.bulbagarden.net/wiki/Parental_Bond_(Ability) | Parental Bond}
|
||||
* and {@linkcode PokemonMultiHitModifier | Multi-Lens}.
|
||||
* @param user The {@linkcode Pokemon} using the move
|
||||
* @param restrictSpread `true` if the enhancing effect
|
||||
* should not affect multi-target moves (default `false`)
|
||||
* and {@linkcode PokemonMultiHitModifier | Multi Lens}.
|
||||
* @param user - The {@linkcode Pokemon} using the move
|
||||
* @param restrictSpread - Whether the enhancing effect should ignore multi-target moves; default `false`
|
||||
* @returns Whether this Move can be given additional strikes.
|
||||
*/
|
||||
canBeMultiStrikeEnhanced(user: Pokemon, restrictSpread: boolean = false): boolean {
|
||||
// TODO: Remove target parameter used solely to circumvent Pollen Puff shenanigans - the entire move needs to be fixed anyhow
|
||||
public canBeMultiStrikeEnhanced(user: Pokemon, restrictSpread: boolean = false, target?: Pokemon | null): boolean {
|
||||
// Multi-strike enhancers...
|
||||
|
||||
// ...cannot enhance moves that hit multiple targets
|
||||
// ...cannot enhance charging or 2-turn moves
|
||||
if (this.isChargingMove()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ...cannot enhance moves hitting multiple targets unless specified
|
||||
const { targets, multiple } = getMoveTargets(user, this.id);
|
||||
const isMultiTarget = multiple && targets.length > 1;
|
||||
if (restrictSpread && multiple && targets.length > 1) {
|
||||
return false;
|
||||
};
|
||||
|
||||
// ...cannot enhance status moves, including ally-targeting Pollen Puff
|
||||
if (
|
||||
this.category === MoveCategory.STATUS
|
||||
|| (target != null && user.getMoveCategory(target, this) === MoveCategory.STATUS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ...cannot enhance multi-hit or sacrificial moves
|
||||
const exceptAttrs: MoveAttrString[] = [
|
||||
@ -1138,6 +1151,9 @@ export abstract class Move implements Localizable {
|
||||
"SacrificialAttr",
|
||||
"SacrificialAttrOnHit"
|
||||
];
|
||||
if (exceptAttrs.some(attr => this.hasAttr(attr))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ...and cannot enhance these specific moves
|
||||
const exceptMoves: MoveId[] = [
|
||||
@ -1147,17 +1163,11 @@ export abstract class Move implements Localizable {
|
||||
MoveId.ICE_BALL,
|
||||
MoveId.ENDEAVOR
|
||||
];
|
||||
if (exceptMoves.includes(this.id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ...and cannot enhance Pollen Puff when targeting an ally.
|
||||
const ally = user.getAlly();
|
||||
const exceptPollenPuffAlly: boolean = this.id === MoveId.POLLEN_PUFF && ally != null && targets.includes(ally.getBattlerIndex())
|
||||
|
||||
return (!restrictSpread || !isMultiTarget)
|
||||
&& !this.isChargingMove()
|
||||
&& !exceptAttrs.some(attr => this.hasAttr(attr))
|
||||
&& !exceptMoves.some(id => this.id === id)
|
||||
&& !exceptPollenPuffAlly
|
||||
&& this.category !== MoveCategory.STATUS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9033,7 +9043,7 @@ export function initMoves() {
|
||||
new AttackMove(MoveId.STRUGGLE, PokemonType.NORMAL, MoveCategory.PHYSICAL, 50, -1, 1, -1, 0, 1)
|
||||
.attr(RecoilAttr, true, 0.25, true)
|
||||
.attr(TypelessAttr)
|
||||
.attr(PreMoveMessageAttr, (user: Pokemon) => i18next.t("moveTriggers:struggleMessage", { pokemonName: getPokemonNameWithAffix(user) }))
|
||||
.attr(PreMoveMessageAttr, (user: Pokemon) => i18next.t("moveTriggers:struggle", { pokemonName: getPokemonNameWithAffix(user) }))
|
||||
.target(MoveTarget.RANDOM_NEAR_ENEMY),
|
||||
new StatusMove(MoveId.SKETCH, PokemonType.NORMAL, -1, 1, -1, 0, 2)
|
||||
.ignoresSubstitute()
|
||||
@ -10700,7 +10710,7 @@ export function initMoves() {
|
||||
.attr(HealOnAllyAttr, 0.5, true, false)
|
||||
.ballBombMove()
|
||||
// Fail if used against an ally that is affected by heal block, during the second failure check
|
||||
.condition((user, target) => target.isOpponent(user) || !!target.getTag(BattlerTagType.HEAL_BLOCK), 2),
|
||||
.condition((user, target) => target == null || target.isOpponent(user) || !target.getTag(BattlerTagType.HEAL_BLOCK), 2),
|
||||
new AttackMove(MoveId.ANCHOR_SHOT, PokemonType.STEEL, MoveCategory.PHYSICAL, 80, 100, 20, 100, 0, 7)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1, 1, true),
|
||||
new StatusMove(MoveId.PSYCHIC_TERRAIN, PokemonType.PSYCHIC, -1, 10, -1, 0, 7)
|
||||
|
||||
@ -223,57 +223,47 @@ const PLASMA_COLRESS: TrainerTierPools = {
|
||||
|
||||
const FLARE: TrainerTierPools = {
|
||||
[TrainerPoolTier.COMMON]: [
|
||||
SpeciesId.FOONGUS,
|
||||
SpeciesId.SCRAGGY,
|
||||
SpeciesId.DRUDDIGON,
|
||||
SpeciesId.FOONGUS,
|
||||
SpeciesId.BUNNELBY,
|
||||
SpeciesId.FLETCHLING,
|
||||
SpeciesId.PANCHAM,
|
||||
SpeciesId.ESPURR,
|
||||
SpeciesId.PUMPKABOO,
|
||||
SpeciesId.PHANTUMP,
|
||||
SpeciesId.SKRELP,
|
||||
SpeciesId.CLAUNCHER,
|
||||
SpeciesId.HELIOPTILE,
|
||||
SpeciesId.KLEFKI,
|
||||
SpeciesId.PHANTUMP,
|
||||
SpeciesId.PUMPKABOO,
|
||||
],
|
||||
[TrainerPoolTier.UNCOMMON]: [
|
||||
SpeciesId.LITWICK,
|
||||
SpeciesId.HEATMOR,
|
||||
SpeciesId.BINACLE,
|
||||
SpeciesId.SKRELP,
|
||||
SpeciesId.BERGMITE,
|
||||
SpeciesId.HELIOPTILE,
|
||||
SpeciesId.AVALUGG,
|
||||
SpeciesId.CAPSAKID,
|
||||
],
|
||||
[TrainerPoolTier.RARE]: [SpeciesId.GOODRA, SpeciesId.HONEDGE],
|
||||
[TrainerPoolTier.RARE]: [SpeciesId.AERODACTYL, SpeciesId.HONEDGE, SpeciesId.GOOMY],
|
||||
};
|
||||
|
||||
const FLARE_XEROSIC: TrainerTierPools = {
|
||||
[TrainerPoolTier.COMMON]: [
|
||||
SpeciesId.EKANS,
|
||||
SpeciesId.LITWICK,
|
||||
SpeciesId.PANCHAM,
|
||||
SpeciesId.BINACLE,
|
||||
[SpeciesId.SKRELP, SpeciesId.CLAUNCHER],
|
||||
SpeciesId.HELIOPTILE,
|
||||
SpeciesId.CLAUNCHER,
|
||||
SpeciesId.BUNNELBY,
|
||||
SpeciesId.FLETCHLING,
|
||||
SpeciesId.LITLEO,
|
||||
SpeciesId.PANGORO,
|
||||
SpeciesId.ESPURR,
|
||||
SpeciesId.INKAY,
|
||||
SpeciesId.CLAUNCHER,
|
||||
SpeciesId.HELIOPTILE,
|
||||
SpeciesId.KLEFKI,
|
||||
],
|
||||
[TrainerPoolTier.UNCOMMON]: [
|
||||
[SpeciesId.AMAURA, SpeciesId.TYRUNT],
|
||||
SpeciesId.SNEASEL,
|
||||
SpeciesId.LITWICK,
|
||||
SpeciesId.LITLEO,
|
||||
SpeciesId.BINACLE,
|
||||
SpeciesId.SKRELP,
|
||||
SpeciesId.ROTOM, // Always Rotom-Heat, Xerosic has their specialty type set to fire
|
||||
[SpeciesId.TYRUNT, SpeciesId.AMAURA],
|
||||
SpeciesId.NOIBAT,
|
||||
SpeciesId.PHANTUMP,
|
||||
SpeciesId.PUMPKABOO,
|
||||
SpeciesId.SIZZLIPEDE,
|
||||
SpeciesId.CAPSAKID,
|
||||
],
|
||||
[TrainerPoolTier.RARE]: [SpeciesId.HISUI_GOODRA, SpeciesId.HONEDGE],
|
||||
[TrainerPoolTier.RARE]: [SpeciesId.BELDUM, SpeciesId.HISUI_SLIGGOO, SpeciesId.HISUI_AVALUGG],
|
||||
};
|
||||
|
||||
const AETHER: TrainerTierPools = {
|
||||
|
||||
@ -420,7 +420,7 @@ const SLOT_4_FIGHT_3 = [
|
||||
SpeciesId.GOLISOPOD,
|
||||
SpeciesId.MIMIKYU,
|
||||
SpeciesId.DHELMISE,
|
||||
SpeciesId.POLTEAGEIST,
|
||||
[SpeciesId.POLTEAGEIST, SpeciesId.SINISTCHA],
|
||||
SpeciesId.COPPERAJAH,
|
||||
SpeciesId.KLEAVOR,
|
||||
SpeciesId.BASCULIN,
|
||||
@ -431,7 +431,6 @@ const SLOT_4_FIGHT_3 = [
|
||||
SpeciesId.DONDOZO,
|
||||
SpeciesId.DUDUNSPARCE,
|
||||
SpeciesId.GHOLDENGO,
|
||||
SpeciesId.POLTCHAGEIST,
|
||||
[SpeciesId.GALAR_SLOWBRO, SpeciesId.GALAR_SLOWKING],
|
||||
SpeciesId.HISUI_ARCANINE,
|
||||
SpeciesId.PALDEA_TAUROS,
|
||||
@ -485,7 +484,7 @@ const SLOT_4_FINAL = [
|
||||
SpeciesId.GOLISOPOD,
|
||||
SpeciesId.MIMIKYU,
|
||||
SpeciesId.DHELMISE,
|
||||
SpeciesId.POLTEAGEIST,
|
||||
[SpeciesId.POLTEAGEIST, SpeciesId.SINISTCHA],
|
||||
SpeciesId.COPPERAJAH,
|
||||
SpeciesId.KLEAVOR,
|
||||
SpeciesId.BASCULEGION, // Ensure gender does not change
|
||||
@ -496,7 +495,6 @@ const SLOT_4_FINAL = [
|
||||
SpeciesId.DONDOZO,
|
||||
SpeciesId.DUDUNSPARCE,
|
||||
SpeciesId.GHOLDENGO,
|
||||
SpeciesId.POLTCHAGEIST,
|
||||
[SpeciesId.GALAR_SLOWBRO, SpeciesId.GALAR_SLOWKING],
|
||||
SpeciesId.HISUI_ARCANINE,
|
||||
SpeciesId.PALDEA_TAUROS,
|
||||
|
||||
@ -592,15 +592,9 @@ export class TrainerConfig {
|
||||
* @param poolName - The evil team the admin belongs to.
|
||||
* @param signatureSpecies - The signature species for the evil team leader.
|
||||
* @param specialtyType - The specialty Type of the admin, if they have one
|
||||
* @param starAdminInstantTeraSlot - (default `4`); If the admin is a Star Admin, the slot that should instantly Tera in {@linkcode ClassicFixedBossWaves.EVIL_ADMIN_3}
|
||||
* @returns The updated TrainerConfig instance.
|
||||
*/
|
||||
initForEvilTeamAdmin(
|
||||
title: string,
|
||||
poolName: EvilTeam,
|
||||
specialtyType?: PokemonType,
|
||||
starAdminInstantTeraSlot = 4,
|
||||
): TrainerConfig {
|
||||
initForEvilTeamAdmin(title: string, poolName: EvilTeam, specialtyType?: PokemonType): TrainerConfig {
|
||||
if (!getIsInitialized()) {
|
||||
initI18n();
|
||||
}
|
||||
@ -609,13 +603,6 @@ export class TrainerConfig {
|
||||
this.setSpecialtyType(specialtyType);
|
||||
}
|
||||
|
||||
if (title === "star_admin") {
|
||||
this.setInstantTera(
|
||||
starAdminInstantTeraSlot,
|
||||
() => globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3,
|
||||
);
|
||||
}
|
||||
|
||||
this.setPartyTemplates(trainerPartyTemplates.RIVAL_5);
|
||||
|
||||
// Set the species pools for the evil team admin.
|
||||
@ -2070,7 +2057,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.DRATINI, SpeciesId.LARVITAR],
|
||||
}),
|
||||
[TrainerType.ARCHER]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("rocket_admin", "rocket_archer")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2091,7 +2077,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
}),
|
||||
),
|
||||
[TrainerType.ARIANA]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("rocket_admin_female", "rocket_ariana")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2103,16 +2088,12 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.ARBOK], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 0; // Intimidate
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
),
|
||||
[TrainerType.PROTON]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("rocket_admin", "rocket_proton")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2124,15 +2105,11 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.CROBAT], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
),
|
||||
[TrainerType.PETREL]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("rocket_admin", "rocket_petrel")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2188,7 +2165,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.RHYHORN, SpeciesId.ARON],
|
||||
}),
|
||||
[TrainerType.TABITHA]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("magma_admin", "magma")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2200,16 +2176,12 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.CAMERUPT], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 1; // Solid Rock
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
),
|
||||
[TrainerType.COURTNEY]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("magma_admin_female", "magma")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2221,9 +2193,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.CAMERUPT], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 1; // Solid Rock
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
@ -2273,7 +2242,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.FEEBAS, SpeciesId.DONDOZO],
|
||||
}),
|
||||
[TrainerType.MATT]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("aqua_admin", "aqua")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2285,15 +2253,11 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.SHARPEDO], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
),
|
||||
[TrainerType.SHELLY]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("aqua_admin_female", "aqua")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2305,9 +2269,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.SHARPEDO], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
@ -2354,7 +2315,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.SPIRITOMB, SpeciesId.ROTOM],
|
||||
}),
|
||||
[TrainerType.JUPITER]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("galactic_commander_female", "galactic_jupiter")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2366,15 +2326,11 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.SKUNTANK], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
),
|
||||
[TrainerType.MARS]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("galactic_commander_female", "galactic_mars")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2386,16 +2342,12 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.PURUGLY], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 0; // Thick Fat
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
),
|
||||
[TrainerType.SATURN]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("galactic_commander", "galactic_saturn")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2407,9 +2359,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.TOXICROAK], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 1; // Dry Skin
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
@ -2460,7 +2409,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.AXEW, SpeciesId.DRUDDIGON, SpeciesId.DEINO, SpeciesId.HISUI_ZORUA],
|
||||
}),
|
||||
[TrainerType.ZINZOLIN]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("plasma_sage", "plasma_zinzolin")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2477,7 +2425,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
}),
|
||||
),
|
||||
[TrainerType.COLRESS]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("plasma_boss", "plasma_colress")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_colress")
|
||||
@ -2489,9 +2436,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.KLINKLANG], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 2; // Clear Body
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
@ -2537,7 +2481,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.GOOMY, SpeciesId.HONEDGE],
|
||||
}),
|
||||
[TrainerType.BRYONY]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("flare_admin_female", "flare")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2553,7 +2496,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
}),
|
||||
),
|
||||
[TrainerType.XEROSIC]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("flare_admin", "flare_xerosic", PokemonType.FIRE)
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2564,9 +2506,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.MALAMAR], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 0; // Contrary
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
@ -2624,7 +2563,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.PORYGON, SpeciesId.JANGMO_O],
|
||||
}),
|
||||
[TrainerType.FABA]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("aether_admin", "aether")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2636,9 +2574,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.HYPNO], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 1; // FOREWARN
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
@ -2691,7 +2626,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.PAWNIARD, SpeciesId.GRUBBIN],
|
||||
}),
|
||||
[TrainerType.PLUMERIA]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("skull_admin", "skull")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2703,9 +2637,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.SALAZZLE], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
@ -2756,7 +2687,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.DURALUDON, SpeciesId.DREEPY],
|
||||
}),
|
||||
[TrainerType.OLEANA]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("macro_admin", "macro_cosmos")
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2768,9 +2698,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.GARBODOR], TrainerSlot.TRAINER, true, p => {
|
||||
if (globalScene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_ADMIN_3) {
|
||||
p.setBoss(true, 2);
|
||||
}
|
||||
p.abilityIndex = 1; // Weak Armor
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
@ -2836,7 +2763,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerPoolTier.SUPER_RARE]: [SpeciesId.DONDOZO, SpeciesId.GIMMIGHOUL],
|
||||
}),
|
||||
[TrainerType.GIACOMO]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("star_admin", "star_dark", PokemonType.DARK)
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2853,6 +2779,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
} else {
|
||||
p.formIndex = 1; // Segin Starmobile
|
||||
p.gender = Gender.GENDERLESS;
|
||||
p.moveset = [
|
||||
new PokemonMove(MoveId.WICKED_TORQUE),
|
||||
new PokemonMove(MoveId.SPIN_OUT),
|
||||
@ -2863,7 +2790,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
}),
|
||||
),
|
||||
[TrainerType.MELA]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("star_admin", "star_fire", PokemonType.FIRE)
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2880,6 +2806,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
} else {
|
||||
p.formIndex = 2; // Schedar Starmobile
|
||||
p.gender = Gender.GENDERLESS;
|
||||
p.moveset = [
|
||||
new PokemonMove(MoveId.BLAZING_TORQUE),
|
||||
new PokemonMove(MoveId.SPIN_OUT),
|
||||
@ -2890,7 +2817,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
}),
|
||||
),
|
||||
[TrainerType.ATTICUS]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("star_admin", "star_poison", PokemonType.POISON)
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2907,6 +2833,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
} else {
|
||||
p.formIndex = 3; // Navi Starmobile
|
||||
p.gender = Gender.GENDERLESS;
|
||||
p.moveset = [
|
||||
new PokemonMove(MoveId.NOXIOUS_TORQUE),
|
||||
new PokemonMove(MoveId.SPIN_OUT),
|
||||
@ -2917,7 +2844,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
}),
|
||||
),
|
||||
[TrainerType.ORTEGA]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("star_admin", "star_fairy", PokemonType.FAIRY)
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2934,6 +2860,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
} else {
|
||||
p.formIndex = 4; // Ruchbah Starmobile
|
||||
p.gender = Gender.GENDERLESS;
|
||||
p.moveset = [
|
||||
new PokemonMove(MoveId.MAGICAL_TORQUE),
|
||||
new PokemonMove(MoveId.SPIN_OUT),
|
||||
@ -2944,7 +2871,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
}),
|
||||
),
|
||||
[TrainerType.ERI]: new TrainerConfig(++t)
|
||||
.setMoneyMultiplier(1.5)
|
||||
.initForEvilTeamAdmin("star_admin", "star_fighting", PokemonType.FIGHTING)
|
||||
.setEncounterBgm(TrainerType.PLASMA_GRUNT)
|
||||
.setBattleBgm("battle_plasma_grunt")
|
||||
@ -2961,6 +2887,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
} else {
|
||||
p.formIndex = 5; // Caph Starmobile
|
||||
p.gender = Gender.GENDERLESS;
|
||||
p.moveset = [
|
||||
new PokemonMove(MoveId.COMBAT_TORQUE),
|
||||
new PokemonMove(MoveId.SPIN_OUT),
|
||||
@ -4385,6 +4312,8 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
getRandomPartyMemberFunc([SpeciesId.TOGEKISS], TrainerSlot.TRAINER, true, p => {
|
||||
p.abilityIndex = 1; // Serene Grace
|
||||
p.generateAndPopulateMoveset();
|
||||
p.moveset[0] = new PokemonMove(MoveId.DAZZLING_GLEAM);
|
||||
p.moveset[1] = new PokemonMove(MoveId.AIR_SLASH);
|
||||
p.teraType = p.species.type1;
|
||||
}),
|
||||
)
|
||||
@ -4401,9 +4330,13 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
getRandomPartyMemberFunc([SpeciesId.GARCHOMP], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.formIndex = 1; // Mega Garchomp
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
p.gender = Gender.FEMALE;
|
||||
p.generateAndPopulateMoveset();
|
||||
if (!p.moveset.some(move => move != null && move.moveId === MoveId.SANDSTORM)) {
|
||||
// Check if Sandstorm is in the moveset, if not, replace the fourth move with Sandstorm.
|
||||
p.moveset[3] = new PokemonMove(MoveId.SANDSTORM);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.setInstantTera(2), // Tera Fairy Togekiss
|
||||
@ -4559,16 +4492,10 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
2,
|
||||
getRandomPartyMemberFunc(
|
||||
[SpeciesId.TORNADUS, SpeciesId.THUNDURUS, SpeciesId.LANDORUS],
|
||||
TrainerSlot.TRAINER,
|
||||
true,
|
||||
p => {
|
||||
p.formIndex = 1; // Therian Formes
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ROGUE_BALL;
|
||||
},
|
||||
),
|
||||
getRandomPartyMemberFunc([SpeciesId.SNORLAX], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1; // G-Max
|
||||
p.generateAndPopulateMoveset();
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
3,
|
||||
@ -4580,9 +4507,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
4,
|
||||
getRandomPartyMemberFunc([SpeciesId.SNORLAX], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1; // G-Max Snorlax
|
||||
getRandomPartyMemberFunc([SpeciesId.LUNALA], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
@ -5522,9 +5449,12 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.NECROZMA], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.formIndex = 2; // Dawn Wings
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
p.generateAndPopulateMoveset();
|
||||
if (!p.moveset.some(move => move != null && move.moveId === MoveId.PHOTON_GEYSER)) {
|
||||
// Check if Photon Geyser is in the moveset, if not, replace the first move with Photon Geyser.
|
||||
p.moveset[0] = new PokemonMove(MoveId.PHOTON_GEYSER);
|
||||
}
|
||||
}),
|
||||
),
|
||||
[TrainerType.GUZMA]: new TrainerConfig(++t)
|
||||
@ -5543,18 +5473,15 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.HERACROSS]))
|
||||
.setPartyMemberFunc(
|
||||
2,
|
||||
getRandomPartyMemberFunc([SpeciesId.SCIZOR, SpeciesId.KLEAVOR], TrainerSlot.TRAINER, true, p => {
|
||||
if (p.species.speciesId === SpeciesId.SCIZOR) {
|
||||
p.abilityIndex = 1; // Technician
|
||||
} else if (p.species.speciesId === SpeciesId.KLEAVOR) {
|
||||
p.abilityIndex = 2; // Sharpness
|
||||
}
|
||||
1,
|
||||
getRandomPartyMemberFunc([SpeciesId.SCIZOR], TrainerSlot.TRAINER, true, p => {
|
||||
p.abilityIndex = 1; // Technician
|
||||
p.generateAndPopulateMoveset();
|
||||
p.gender = Gender.MALE;
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.HERACROSS]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.GALVANTULA, SpeciesId.VIKAVOLT]))
|
||||
.setPartyMemberFunc(
|
||||
4,
|
||||
@ -5562,6 +5489,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1; // Mega Pinsir
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.gender = Gender.MALE;
|
||||
p.generateName();
|
||||
}),
|
||||
)
|
||||
@ -5569,11 +5497,11 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.GOLISOPOD], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.gender = Gender.MALE;
|
||||
p.generateAndPopulateMoveset();
|
||||
if (!p.moveset.some(move => move != null && move.moveId === MoveId.FIRST_IMPRESSION)) {
|
||||
// Check if First Impression is in the moveset, if not, replace the third move with First Impression.
|
||||
p.moveset[2] = new PokemonMove(MoveId.FIRST_IMPRESSION);
|
||||
p.gender = Gender.MALE;
|
||||
}
|
||||
}),
|
||||
),
|
||||
@ -5586,27 +5514,36 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
0,
|
||||
getRandomPartyMemberFunc([SpeciesId.GOLISOPOD], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.abilityIndex = 2; // Anticipation
|
||||
p.gender = Gender.MALE;
|
||||
p.generateAndPopulateMoveset();
|
||||
if (!p.moveset.some(move => move != null && move.moveId === MoveId.FIRST_IMPRESSION)) {
|
||||
// Check if First Impression is in the moveset, if not, replace the third move with First Impression.
|
||||
p.moveset[2] = new PokemonMove(MoveId.FIRST_IMPRESSION);
|
||||
p.abilityIndex = 2; // Anticipation
|
||||
p.gender = Gender.MALE;
|
||||
}
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
1,
|
||||
getRandomPartyMemberFunc([SpeciesId.BUZZWOLE], TrainerSlot.TRAINER, true, p => {
|
||||
getRandomPartyMemberFunc([SpeciesId.SCIZOR], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ROGUE_BALL;
|
||||
p.abilityIndex = 1; // Technician
|
||||
p.moveset[0] = new PokemonMove(MoveId.BUG_BITE);
|
||||
p.moveset[1] = new PokemonMove(MoveId.BULLET_PUNCH);
|
||||
p.gender = Gender.MALE;
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
2,
|
||||
getRandomPartyMemberFunc([SpeciesId.CRAWDAUNT, SpeciesId.HISUI_SAMUROTT], TrainerSlot.TRAINER, true, p => {
|
||||
p.abilityIndex = 2; // Sharpness Hisuian Samurott, Adaptability Crawdaunt
|
||||
p.abilityIndex = 2; // Adaptability Crawdaunt, Sharpness Samurott
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.generateAndPopulateMoveset();
|
||||
if (!p.moveset.some(move => move != null && move.moveId === MoveId.AQUA_JET)) {
|
||||
// Check if Aqua Jet is in the moveset, if not, replace the third move with Aqua Jet.
|
||||
p.moveset[2] = new PokemonMove(MoveId.AQUA_JET);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
@ -5618,26 +5555,22 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
4,
|
||||
getRandomPartyMemberFunc([SpeciesId.GENESECT], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ROGUE_BALL;
|
||||
p.formIndex = randSeedInt(4, 1); // Shock, Burn, Chill, or Douse Drive
|
||||
if (!p.moveset.some(move => move != null && move.moveId === MoveId.TECHNO_BLAST)) {
|
||||
// Check if Techno Blast is in the moveset, if not, replace the third move with Techno Blast.
|
||||
p.moveset[2] = new PokemonMove(MoveId.TECHNO_BLAST);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.PINSIR], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.formIndex = 1; // Mega Pinsir
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
p.gender = Gender.MALE;
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}),
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
5,
|
||||
getRandomPartyMemberFunc([SpeciesId.BUZZWOLE], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ROGUE_BALL;
|
||||
}),
|
||||
),
|
||||
[TrainerType.ROSE]: new TrainerConfig(++t)
|
||||
.setName("Rose")
|
||||
@ -5825,6 +5758,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
getRandomPartyMemberFunc([SpeciesId.REVAVROOM], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.formIndex = randSeedInt(5, 1); // Random Starmobile form
|
||||
p.gender = Gender.GENDERLESS;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ROGUE_BALL;
|
||||
}),
|
||||
|
||||
@ -3675,15 +3675,6 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
multiStrikeEnhancementMultiplier,
|
||||
);
|
||||
|
||||
if (!ignoreSourceAbility) {
|
||||
applyAbAttrs("AddSecondStrikeAbAttr", {
|
||||
pokemon: source,
|
||||
move,
|
||||
simulated,
|
||||
multiplier: multiStrikeEnhancementMultiplier,
|
||||
});
|
||||
}
|
||||
|
||||
/** Doubles damage if this Pokemon's last move was Glaive Rush */
|
||||
const glaiveRushMultiplier = new NumberHolder(1);
|
||||
if (this.getTag(BattlerTagType.RECEIVE_DOUBLE_DAMAGE)) {
|
||||
@ -3772,9 +3763,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* mistyTerrainMultiplier,
|
||||
);
|
||||
|
||||
/** Doubles damage if the attacker has Tinted Lens and is using a resisted move */
|
||||
if (!ignoreSourceAbility) {
|
||||
applyAbAttrs("DamageBoostAbAttr", {
|
||||
applyAbAttrs("MoveDamageBoostAbAttr", {
|
||||
pokemon: source,
|
||||
opponent: this,
|
||||
move,
|
||||
|
||||
@ -276,7 +276,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
// Assume single target for multi hit
|
||||
applyMoveAttrs("MultiHitAttr", user, this.getFirstTarget() ?? null, move, hitCount);
|
||||
// If Parental Bond is applicable, add another hit
|
||||
applyAbAttrs("AddSecondStrikeAbAttr", { pokemon: user, move, hitCount });
|
||||
applyAbAttrs("AddSecondStrikeAbAttr", { pokemon: user, move, hitCount, opponent: this.getFirstTarget() });
|
||||
// If Multi-Lens is applicable, add hits equal to the number of held Multi-Lenses
|
||||
globalScene.applyModifiers(PokemonMultiHitModifier, user.isPlayer(), user, move.id, hitCount);
|
||||
// Set the user's relevant turnData fields to reflect the final hit count
|
||||
|
||||
@ -205,7 +205,7 @@ export class MovePhase extends PokemonPhase {
|
||||
user.cureStatus(
|
||||
StatusEffect.FREEZE,
|
||||
i18next.t("statusEffect:freeze.healByMove", {
|
||||
pokemonName: getPokemonNameWithAffix(user),
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(user),
|
||||
moveName: this.move.getMove().name,
|
||||
}),
|
||||
);
|
||||
@ -509,6 +509,9 @@ export class MovePhase extends PokemonPhase {
|
||||
) {
|
||||
this.showFailedText();
|
||||
this.fail();
|
||||
// clear out 2 turn moves
|
||||
// TODO: Make a helper for this atp
|
||||
this.pokemon.getMoveQueue().shift();
|
||||
this.pokemon.pushMoveHistory(this.moveHistoryEntry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -268,7 +268,13 @@ export class TitlePhase extends Phase {
|
||||
globalScene.addModifier(m, true, false, false, true);
|
||||
}
|
||||
for (const m of timedEventManager.getEventDailyStartingItems()) {
|
||||
globalScene.addModifier(modifierTypes[m]().newModifier(), true, false, false, true);
|
||||
globalScene.addModifier(
|
||||
modifierTypes[m]().withIdFromFunc(modifierTypes[m]).newModifier(),
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
}
|
||||
globalScene.updateModifiers(true, true);
|
||||
|
||||
|
||||
@ -396,7 +396,7 @@ const timedEvents: readonly TimedEvent[] = [
|
||||
name: "Halloween 25",
|
||||
eventType: EventType.SHINY,
|
||||
startDate: new Date(Date.UTC(2025, 9, 30)),
|
||||
endDate: new Date(Date.UTC(2025, 10, 10)),
|
||||
endDate: new Date(Date.UTC(2025, 10, 12)),
|
||||
bannerKey: "halloween2025",
|
||||
scale: 0.19,
|
||||
availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-419", "pt-BR", "zh-Hans", "zh-Hant", "da", "ru"],
|
||||
|
||||
@ -384,4 +384,24 @@ describe("Abilities - Parental Bond", () => {
|
||||
// TODO: Update hit count to 1 once Future Sight is fixed to not activate abilities if user is off the field
|
||||
expect(enemyPokemon.damageAndUpdate).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("should not reduce damage against the remaining target if the first one faints", async () => {
|
||||
game.override.battleStyle("double").enemySpecies(SpeciesId.MAGIKARP);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const feebas = game.field.getPlayerPokemon();
|
||||
const [karp1, karp2] = game.scene.getEnemyField();
|
||||
|
||||
// Mock base damage for both mons for consistent results
|
||||
vi.spyOn(karp1, "getBaseDamage").mockReturnValue(100);
|
||||
vi.spyOn(karp2, "getBaseDamage").mockReturnValue(100);
|
||||
karp1.hp = 1;
|
||||
|
||||
game.move.use(MoveId.HYPER_VOICE);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
expect(karp1).toHaveFainted();
|
||||
expect(feebas).not.toHaveAbilityApplied(AbilityId.PARENTAL_BOND);
|
||||
expect(karp2).toHaveTakenDamage(100);
|
||||
});
|
||||
});
|
||||
|
||||
@ -26,6 +26,7 @@ describe("Items - Multi Lens", () => {
|
||||
game.override
|
||||
.moveset([MoveId.TACKLE, MoveId.TRAILBLAZE, MoveId.TACHYON_CUTTER, MoveId.FUTURE_SIGHT])
|
||||
.ability(AbilityId.BALL_FETCH)
|
||||
.passiveAbility(AbilityId.NO_GUARD)
|
||||
.startingHeldItems([{ name: "MULTI_LENS" }])
|
||||
.battleStyle("single")
|
||||
.criticalHits(false)
|
||||
@ -135,61 +136,36 @@ describe("Items - Multi Lens", () => {
|
||||
expect(damageResults[1]).toBe(Math.floor(playerPokemon.level * 0.25));
|
||||
});
|
||||
|
||||
it("should result in correct damage for hp% attacks with 1 lens", async () => {
|
||||
it.each([1, 2])("should result in original damage for HP-cutting attacks with %d lenses", async lensCount => {
|
||||
game.override
|
||||
.startingHeldItems([{ name: "MULTI_LENS", count: 1 }])
|
||||
.moveset(MoveId.SUPER_FANG)
|
||||
.ability(AbilityId.COMPOUND_EYES)
|
||||
.startingHeldItems([{ name: "MULTI_LENS", count: lensCount }])
|
||||
.enemyLevel(1000)
|
||||
.enemySpecies(SpeciesId.BLISSEY); // allows for unrealistically high levels of accuracy
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const blissey = game.field.getEnemyPokemon();
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
game.move.use(MoveId.SUPER_FANG);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
game.move.select(MoveId.SUPER_FANG);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
expect(enemyPokemon.getHpRatio()).toBeCloseTo(0.5, 5);
|
||||
expect(blissey.getHpRatio()).toBeCloseTo(0.5, 5);
|
||||
});
|
||||
|
||||
it("should result in correct damage for hp% attacks with 2 lenses", async () => {
|
||||
it("should result in original damage for HP-cutting attacks with 2 lenses + Parental Bond", async () => {
|
||||
game.override
|
||||
.startingHeldItems([{ name: "MULTI_LENS", count: 2 }])
|
||||
.moveset(MoveId.SUPER_FANG)
|
||||
.ability(AbilityId.COMPOUND_EYES)
|
||||
.enemyMoveset(MoveId.SPLASH)
|
||||
.enemyLevel(1000)
|
||||
.enemySpecies(SpeciesId.BLISSEY); // allows for unrealistically high levels of accuracy
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.SUPER_FANG);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
expect(enemyPokemon.getHpRatio()).toBeCloseTo(0.5, 5);
|
||||
});
|
||||
|
||||
it("should result in correct damage for hp% attacks with 2 lenses + Parental Bond", async () => {
|
||||
game.override
|
||||
.startingHeldItems([{ name: "MULTI_LENS", count: 2 }])
|
||||
.moveset(MoveId.SUPER_FANG)
|
||||
.ability(AbilityId.PARENTAL_BOND)
|
||||
.passiveAbility(AbilityId.COMPOUND_EYES)
|
||||
.enemyMoveset(MoveId.SPLASH)
|
||||
.enemyLevel(1000)
|
||||
.enemySpecies(SpeciesId.BLISSEY); // allows for unrealistically high levels of accuracy
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const blissey = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.SUPER_FANG);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
expect(enemyPokemon.getHpRatio()).toBeCloseTo(0.25, 5);
|
||||
game.move.use(MoveId.SUPER_FANG);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
expect(blissey.getHpRatio()).toBeCloseTo(0.25, 5);
|
||||
});
|
||||
|
||||
it("should not allow Future Sight to hit infinitely many times if the user switches out", async () => {
|
||||
|
||||
@ -131,4 +131,26 @@ describe("Moves - Dig", () => {
|
||||
expect(postDigEarthquakeDmg).toBeGreaterThanOrEqual(2 * preDigEarthquakeDmg);
|
||||
expect(postDigEarthquakeDmg).toBeLessThan(2 * (preDigEarthquakeDmg + 1));
|
||||
});
|
||||
|
||||
it("should not softlock when used against a dying enemy 2 in Doubles", async () => {
|
||||
game.override.battleStyle("double");
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const feebas = game.field.getPlayerPokemon();
|
||||
const enemy2 = game.scene.getEnemyField()[1];
|
||||
|
||||
// use dig and make the targeted enemy faint post charge
|
||||
game.move.use(MoveId.DIG, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2);
|
||||
await game.toEndOfTurn();
|
||||
await game.killPokemon(enemy2);
|
||||
await game.phaseInterceptor.to("CommandPhase");
|
||||
|
||||
expect(feebas.getMoveQueue()[0]?.targets).toEqual([BattlerIndex.ENEMY_2]);
|
||||
expect(enemy2).toHaveFainted();
|
||||
|
||||
await game.toEndOfTurn();
|
||||
|
||||
// TODO: Does this redirect to the other enemy?
|
||||
expect(feebas.getMoveQueue()).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user