diff --git a/public/locales b/public/locales index e98f0eb9c20..18c1963ef30 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit e98f0eb9c2022bc78b53f0444424c636498e725a +Subproject commit 18c1963ef309612a5a7fef76f9879709a7202189 diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 2ff5d718ede..8fe6c85263d 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1394,9 +1394,9 @@ export default class BattleScene extends SceneBase { if (double === undefined && newWaveIndex > 1) { if (newBattleType === BattleType.WILD && !this.gameMode.isWaveFinal(newWaveIndex)) { newDouble = !randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField)); + } else if (newBattleType === BattleType.TRAINER) { + newDouble = newTrainer?.variant === TrainerVariant.DOUBLE; } - } else if (double === undefined && newBattleType === BattleType.TRAINER) { - newDouble = newTrainer?.variant === TrainerVariant.DOUBLE; } else if (!battleConfig) { newDouble = !!double; } diff --git a/src/battle.ts b/src/battle.ts index 6630d53bd67..07e520d6bc0 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -31,29 +31,7 @@ import type { CustomModifierSettings } from "#app/modifier/modifier-type"; import { ModifierTier } from "#app/modifier/modifier-tier"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { BattleType } from "#enums/battle-type"; - -export enum ClassicFixedBossWaves { - TOWN_YOUNGSTER = 5, - RIVAL_1 = 8, - RIVAL_2 = 25, - EVIL_GRUNT_1 = 35, - RIVAL_3 = 55, - EVIL_GRUNT_2 = 62, - EVIL_GRUNT_3 = 64, - EVIL_ADMIN_1 = 66, - RIVAL_4 = 95, - EVIL_GRUNT_4 = 112, - EVIL_ADMIN_2 = 114, - EVIL_BOSS_1 = 115, - RIVAL_5 = 145, - EVIL_BOSS_2 = 165, - ELITE_FOUR_1 = 182, - ELITE_FOUR_2 = 184, - ELITE_FOUR_3 = 186, - ELITE_FOUR_4 = 188, - CHAMPION = 190, - RIVAL_6 = 195, -} +import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; export enum BattlerIndex { ATTACKER = -1, diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index d8b648ebe82..b018a87a08d 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -7227,7 +7227,7 @@ export function initAbilities() { new Ability(Abilities.CURIOUS_MEDICINE, 8) .attr(PostSummonClearAllyStatStagesAbAttr), new Ability(Abilities.TRANSISTOR, 8) - .attr(MoveTypePowerBoostAbAttr, PokemonType.ELECTRIC), + .attr(MoveTypePowerBoostAbAttr, PokemonType.ELECTRIC, 1.3), new Ability(Abilities.DRAGONS_MAW, 8) .attr(MoveTypePowerBoostAbAttr, PokemonType.DRAGON), new Ability(Abilities.CHILLING_NEIGH, 8) @@ -7412,4 +7412,4 @@ export function initAbilities() { .unreplaceable() // TODO is this true? .attr(ConfusionOnStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) ); -} \ No newline at end of file +} diff --git a/src/data/challenge.ts b/src/data/challenge.ts index f786152ca3d..7388f397c7e 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -8,7 +8,8 @@ import { speciesStarterCosts } from "#app/data/balance/starters"; import type Pokemon from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon"; import type { FixedBattleConfig } from "#app/battle"; -import { ClassicFixedBossWaves, getRandomTrainerFunc } from "#app/battle"; +import { getRandomTrainerFunc } from "#app/battle"; +import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; import { BattleType } from "#enums/battle-type"; import Trainer, { TrainerVariant } from "#app/field/trainer"; import { PokemonType } from "#enums/pokemon-type"; diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 5d57bb6dc49..903b2726676 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -2459,14 +2459,7 @@ export class StatusEffectAttr extends MoveEffectAttr { const statusCheck = moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance; if (statusCheck) { const pokemon = this.selfTarget ? user : target; - if (pokemon.status && !this.overrideStatus) { - return false; - } - - if (user !== target && target.isSafeguarded(user)) { - if (move.category === MoveCategory.STATUS) { - globalScene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target) })); - } + if (user !== target && move.category === MoveCategory.STATUS && !target.canSetStatus(this.effect, false, false, user, true)) { return false; } if (((!pokemon.status || this.overrideStatus) || (pokemon.status.effect === this.effect && moveChance < 0)) diff --git a/src/data/trainers/TrainerPartyTemplate.ts b/src/data/trainers/TrainerPartyTemplate.ts index 5d02ffdc6af..1952bcc179e 100644 --- a/src/data/trainers/TrainerPartyTemplate.ts +++ b/src/data/trainers/TrainerPartyTemplate.ts @@ -1,6 +1,8 @@ import { startingWave } from "#app/starting-wave"; import { globalScene } from "#app/global-scene"; import { PartyMemberStrength } from "#enums/party-member-strength"; +import { GameModes } from "#app/game-mode"; +import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; export class TrainerPartyTemplate { public size: number; @@ -222,19 +224,18 @@ export const trainerPartyTemplates = { */ export function getEvilGruntPartyTemplate(): TrainerPartyTemplate { const waveIndex = globalScene.currentBattle?.waveIndex; - if (waveIndex < 40) { - return trainerPartyTemplates.TWO_AVG; + switch (waveIndex) { + case ClassicFixedBossWaves.EVIL_GRUNT_1: + return trainerPartyTemplates.TWO_AVG; + case ClassicFixedBossWaves.EVIL_GRUNT_2: + return trainerPartyTemplates.THREE_AVG; + case ClassicFixedBossWaves.EVIL_GRUNT_3: + return trainerPartyTemplates.TWO_AVG_ONE_STRONG; + case ClassicFixedBossWaves.EVIL_ADMIN_1: + return trainerPartyTemplates.GYM_LEADER_4; // 3avg 1 strong 1 stronger + default: + return trainerPartyTemplates.GYM_LEADER_5; // 3 avg 2 strong 1 stronger } - if (waveIndex < 63) { - return trainerPartyTemplates.THREE_AVG; - } - if (waveIndex < 65) { - return trainerPartyTemplates.TWO_AVG_ONE_STRONG; - } - if (waveIndex < 112) { - return trainerPartyTemplates.GYM_LEADER_4; // 3avg 1 strong 1 stronger - } - return trainerPartyTemplates.GYM_LEADER_5; // 3 avg 2 strong 1 stronger } export function getWavePartyTemplate(...templates: TrainerPartyTemplate[]) { @@ -245,11 +246,36 @@ export function getWavePartyTemplate(...templates: TrainerPartyTemplate[]) { } export function getGymLeaderPartyTemplate() { - return getWavePartyTemplate( - trainerPartyTemplates.GYM_LEADER_1, - trainerPartyTemplates.GYM_LEADER_2, - trainerPartyTemplates.GYM_LEADER_3, - trainerPartyTemplates.GYM_LEADER_4, - trainerPartyTemplates.GYM_LEADER_5, - ); + const { currentBattle, gameMode } = globalScene; + switch (gameMode.modeId) { + case GameModes.DAILY: + if (currentBattle?.waveIndex <= 20) { + return trainerPartyTemplates.GYM_LEADER_2 + } + return trainerPartyTemplates.GYM_LEADER_3; + case GameModes.CHALLENGE: // In the future, there may be a ChallengeType to call here. For now, use classic's. + case GameModes.CLASSIC: + if (currentBattle?.waveIndex <= 20) { + return trainerPartyTemplates.GYM_LEADER_1; // 1 avg 1 strong + } + else if (currentBattle?.waveIndex <= 30) { + return trainerPartyTemplates.GYM_LEADER_2; // 1 avg 1 strong 1 stronger + } + else if (currentBattle?.waveIndex <= 60) { // 50 and 60 + return trainerPartyTemplates.GYM_LEADER_3; // 2 avg 1 strong 1 stronger + } + else if (currentBattle?.waveIndex <= 90) { // 80 and 90 + return trainerPartyTemplates.GYM_LEADER_4; // 3 avg 1 strong 1 stronger + } + // 110+ + return trainerPartyTemplates.GYM_LEADER_5; // 3 avg 2 strong 1 stronger + default: + return getWavePartyTemplate( + trainerPartyTemplates.GYM_LEADER_1, + trainerPartyTemplates.GYM_LEADER_2, + trainerPartyTemplates.GYM_LEADER_3, + trainerPartyTemplates.GYM_LEADER_4, + trainerPartyTemplates.GYM_LEADER_5, + ); + } } diff --git a/src/enums/fixed-boss-waves.ts b/src/enums/fixed-boss-waves.ts new file mode 100644 index 00000000000..623d9035472 --- /dev/null +++ b/src/enums/fixed-boss-waves.ts @@ -0,0 +1,22 @@ +export enum ClassicFixedBossWaves { + TOWN_YOUNGSTER = 5, + RIVAL_1 = 8, + RIVAL_2 = 25, + EVIL_GRUNT_1 = 35, + RIVAL_3 = 55, + EVIL_GRUNT_2 = 62, + EVIL_GRUNT_3 = 64, + EVIL_ADMIN_1 = 66, + RIVAL_4 = 95, + EVIL_GRUNT_4 = 112, + EVIL_ADMIN_2 = 114, + EVIL_BOSS_1 = 115, + RIVAL_5 = 145, + EVIL_BOSS_2 = 165, + ELITE_FOUR_1 = 182, + ELITE_FOUR_2 = 184, + ELITE_FOUR_3 = 186, + ELITE_FOUR_4 = 188, + CHAMPION = 190, + RIVAL_6 = 195 +} diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index d565a590792..2de8cc150c9 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -248,6 +248,7 @@ import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { SwitchType } from "#enums/switch-type"; import { SpeciesFormKey } from "#enums/species-form-key"; +import {getStatusEffectOverlapText } from "#app/data/status-effect"; import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, @@ -5364,6 +5365,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ); } + queueImmuneMessage(quiet: boolean, effect?: StatusEffect): void { + if (!effect || quiet) { + return; + } + const message = effect && this.status?.effect === effect + ? getStatusEffectOverlapText(effect ?? StatusEffect.NONE, getPokemonNameWithAffix(this)) + : i18next.t("abilityTriggers:moveImmunity", { + pokemonNameWithAffix: getPokemonNameWithAffix(this), + }); + globalScene.queueMessage(message); + } + /** * Checks if a status effect can be applied to the Pokemon. * @@ -5382,6 +5395,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ): boolean { if (effect !== StatusEffect.FAINT) { if (overrideStatus ? this.status?.effect === effect : this.status) { + this.queueImmuneMessage(quiet, effect); return false; } if ( @@ -5389,18 +5403,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { !ignoreField && globalScene.arena.terrain?.terrainType === TerrainType.MISTY ) { + this.queueImmuneMessage(quiet, effect); return false; } } - if ( - sourcePokemon && - sourcePokemon !== this && - this.isSafeguarded(sourcePokemon) - ) { - return false; - } - const types = this.getTypes(true, true); switch (effect) { @@ -5429,17 +5436,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - return true; + return true; }); if (this.isOfType(PokemonType.POISON) || this.isOfType(PokemonType.STEEL)) { if (poisonImmunity.includes(true)) { + this.queueImmuneMessage(quiet, effect); return false; } } break; case StatusEffect.PARALYSIS: if (this.isOfType(PokemonType.ELECTRIC)) { + this.queueImmuneMessage(quiet, effect); return false; } break; @@ -5448,6 +5457,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.isGrounded() && globalScene.arena.terrain?.terrainType === TerrainType.ELECTRIC ) { + this.queueImmuneMessage(quiet, effect); return false; } break; @@ -5460,11 +5470,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { globalScene.arena.weather.weatherType, )) ) { + this.queueImmuneMessage(quiet, effect); return false; } break; case StatusEffect.BURN: if (this.isOfType(PokemonType.FIRE)) { + this.queueImmuneMessage(quiet, effect); return false; } break; @@ -5499,6 +5511,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return false; } + if ( + sourcePokemon && + sourcePokemon !== this && + this.isSafeguarded(sourcePokemon) + ) { + if(!quiet){ + globalScene.queueMessage( + i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(this) + })); + } + return false; + } + return true; } @@ -5510,7 +5535,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { sourceText: string | null = null, overrideStatus?: boolean ): boolean { - if (!this.canSetStatus(effect, asPhase, overrideStatus, sourcePokemon)) { + if (!this.canSetStatus(effect, false, overrideStatus, sourcePokemon)) { return false; } if (this.isFainted() && effect !== StatusEffect.FAINT) { diff --git a/src/phases/victory-phase.ts b/src/phases/victory-phase.ts index 6e1837a4749..1204877fec2 100644 --- a/src/phases/victory-phase.ts +++ b/src/phases/victory-phase.ts @@ -1,5 +1,5 @@ import type { BattlerIndex } from "#app/battle"; -import { ClassicFixedBossWaves } from "#app/battle"; +import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; import { BattleType } from "#enums/battle-type"; import type { CustomModifierSettings } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type"; diff --git a/test/moves/whirlwind.test.ts b/test/moves/whirlwind.test.ts index b0ca1783f2f..6b5133ec7b1 100644 --- a/test/moves/whirlwind.test.ts +++ b/test/moves/whirlwind.test.ts @@ -163,6 +163,7 @@ describe("Moves - Whirlwind", () => { it("should not pull in the other trainer's pokemon in a partner trainer battle", async () => { game.override + .startingWave(2) .battleType(BattleType.TRAINER) .randomTrainer({ trainerType: TrainerType.BREEDER,