diff --git a/public/images/events/spr25event-de.png b/public/images/events/spr25event-de.png new file mode 100644 index 00000000000..1ccd9557460 Binary files /dev/null and b/public/images/events/spr25event-de.png differ diff --git a/public/images/events/spr25event-en.png b/public/images/events/spr25event-en.png new file mode 100644 index 00000000000..0e73f9247e3 Binary files /dev/null and b/public/images/events/spr25event-en.png differ diff --git a/public/images/events/spr25event-es-ES.png b/public/images/events/spr25event-es-ES.png new file mode 100644 index 00000000000..137f1c6e743 Binary files /dev/null and b/public/images/events/spr25event-es-ES.png differ diff --git a/public/images/events/spr25event-es-MX.png b/public/images/events/spr25event-es-MX.png new file mode 100644 index 00000000000..137f1c6e743 Binary files /dev/null and b/public/images/events/spr25event-es-MX.png differ diff --git a/public/images/events/spr25event-fr.png b/public/images/events/spr25event-fr.png new file mode 100644 index 00000000000..e7089eee4a1 Binary files /dev/null and b/public/images/events/spr25event-fr.png differ diff --git a/public/images/events/spr25event-it.png b/public/images/events/spr25event-it.png new file mode 100644 index 00000000000..2664b4367cc Binary files /dev/null and b/public/images/events/spr25event-it.png differ diff --git a/public/images/events/spr25event-ja.png b/public/images/events/spr25event-ja.png new file mode 100644 index 00000000000..90b02af8050 Binary files /dev/null and b/public/images/events/spr25event-ja.png differ diff --git a/public/images/events/spr25event-ko.png b/public/images/events/spr25event-ko.png new file mode 100644 index 00000000000..a8fe279617a Binary files /dev/null and b/public/images/events/spr25event-ko.png differ diff --git a/public/images/events/spr25event-pt-BR.png b/public/images/events/spr25event-pt-BR.png new file mode 100644 index 00000000000..ae195fecc97 Binary files /dev/null and b/public/images/events/spr25event-pt-BR.png differ diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 37ed8ce342c..29542b54f6d 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -6145,7 +6145,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { const faintedPokemon = globalScene.getEnemyParty().filter((p) => p.isFainted() && !p.isBoss()); const pokemon = faintedPokemon[user.randSeedInt(faintedPokemon.length)]; const slotIndex = globalScene.getEnemyParty().findIndex((p) => pokemon.id === p.id); - pokemon.resetStatus(); + pokemon.resetStatus(true, false, false, true); pokemon.heal(Math.min(toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); globalScene.queueMessage(i18next.t("moveTriggers:revivalBlessing", { pokemonName: getPokemonNameWithAffix(pokemon) }), 0, true); const allyPokemon = user.getAlly(); diff --git a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts index bfba553af5d..bab0c44db7d 100644 --- a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts @@ -106,7 +106,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui * If an event with more than 1 valid event encounter species is active, you have 20% chance to get one of those * If the rolled species has no HA, and there are valid event encounters, you will get one of those * If the rolled species has no HA and there are no valid event encounters, you will get Shiny Magikarp - * Mons rolled from the event encounter pool get 2 extra shiny rolls + * Mons rolled from the event encounter pool get 3 extra shiny rolls */ if ( r === 0 || @@ -120,12 +120,13 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui (validEventEncounters.length > 0 && (r <= EVENT_THRESHOLD || (isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE))) ) { - // If you roll 20%, give event encounter with 2 extra shiny rolls and its HA, if it has one + // If you roll 20%, give event encounter with 3 extra shiny rolls and its HA, if it has one const enc = randSeedItem(validEventEncounters); species = getPokemonSpecies(enc.species); pokemon = new PlayerPokemon(species, 5, species.abilityHidden === Abilities.NONE ? undefined : 2, enc.formIndex); pokemon.trySetShinySeed(); pokemon.trySetShinySeed(); + pokemon.trySetShinySeed(); } else { pokemon = new PlayerPokemon(species, 5, 2, species.formIndex); } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 48c2d93692c..0c412e73b52 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5608,13 +5608,44 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param revive Whether revive should be cured; defaults to true. * @param confusion Whether resetStatus should include confusion or not; defaults to false. * @param reloadAssets Whether to reload the assets or not; defaults to false. + * @param asPhase Whether to reset the status in a phase or immediately */ - resetStatus(revive = true, confusion = false, reloadAssets = false): void { + resetStatus(revive = true, confusion = false, reloadAssets = false, asPhase = true): void { const lastStatus = this.status?.effect; if (!revive && lastStatus === StatusEffect.FAINT) { return; } - globalScene.unshiftPhase(new ResetStatusPhase(this, confusion, reloadAssets)); + + if (asPhase) { + globalScene.unshiftPhase(new ResetStatusPhase(this, confusion, reloadAssets)); + } else { + this.clearStatus(confusion, reloadAssets); + } + } + + /** + * Performs the action of clearing a Pokemon's status + * + * This is a helper to {@linkcode resetStatus}, which should be called directly instead of this method + */ + public clearStatus(confusion: boolean, reloadAssets: boolean) { + const lastStatus = this.status?.effect; + this.status = null; + if (lastStatus === StatusEffect.SLEEP) { + this.setFrameRate(10); + if (this.getTag(BattlerTagType.NIGHTMARE)) { + this.lapseTag(BattlerTagType.NIGHTMARE); + } + } + if (confusion) { + if (this.getTag(BattlerTagType.CONFUSED)) { + this.lapseTag(BattlerTagType.CONFUSED); + } + } + if (reloadAssets) { + this.loadAssets(false).then(() => this.playAnim()); + } + this.updateInfo(true); } /** diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 7dfbcf6ca0b..549ce462c11 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1953,7 +1953,7 @@ export class PokemonInstantReviveModifier extends PokemonHeldItemModifier { ); // Remove the Pokemon's FAINT status - pokemon.resetStatus(true, false, true); + pokemon.resetStatus(true, false, true, false); // Reapply Commander on the Pokemon's side of the field, if applicable const field = pokemon.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField(); @@ -2161,7 +2161,7 @@ export class PokemonHpRestoreModifier extends ConsumablePokemonModifier { restorePoints = Math.floor(restorePoints * multiplier); } if (this.fainted || this.healStatus) { - pokemon.resetStatus(true, true); + pokemon.resetStatus(true, true, false, false); } pokemon.hp = Math.min( pokemon.hp + @@ -2181,7 +2181,7 @@ export class PokemonStatusHealModifier extends ConsumablePokemonModifier { * @returns always `true` */ override apply(playerPokemon: PlayerPokemon): boolean { - playerPokemon.resetStatus(true, true); + playerPokemon.resetStatus(true, true, false, false); return true; } } diff --git a/src/phases/party-heal-phase.ts b/src/phases/party-heal-phase.ts index a208ccfff92..4a9f8a0c888 100644 --- a/src/phases/party-heal-phase.ts +++ b/src/phases/party-heal-phase.ts @@ -21,7 +21,7 @@ export class PartyHealPhase extends BattlePhase { globalScene.ui.fadeOut(1000).then(() => { for (const pokemon of globalScene.getPlayerParty()) { pokemon.hp = pokemon.getMaxHp(); - pokemon.resetStatus(); + pokemon.resetStatus(true, false, false, true); for (const move of pokemon.moveset) { move.ppUsed = 0; } diff --git a/src/phases/reset-status-phase.ts b/src/phases/reset-status-phase.ts index 0ba3559d9b7..19bfc3027e2 100644 --- a/src/phases/reset-status-phase.ts +++ b/src/phases/reset-status-phase.ts @@ -1,7 +1,5 @@ import type Pokemon from "#app/field/pokemon"; import { BattlePhase } from "#app/phases/battle-phase"; -import { BattlerTagType } from "#enums/battler-tag-type"; -import { StatusEffect } from "#enums/status-effect"; /** * Phase which handles resetting a Pokemon's status to none @@ -22,23 +20,7 @@ export class ResetStatusPhase extends BattlePhase { } public override start() { - const lastStatus = this.pokemon.status?.effect; - this.pokemon.status = null; - if (lastStatus === StatusEffect.SLEEP) { - this.pokemon.setFrameRate(10); - if (this.pokemon.getTag(BattlerTagType.NIGHTMARE)) { - this.pokemon.lapseTag(BattlerTagType.NIGHTMARE); - } - } - if (this.affectConfusion) { - if (this.pokemon.getTag(BattlerTagType.CONFUSED)) { - this.pokemon.lapseTag(BattlerTagType.CONFUSED); - } - } - if (this.reloadAssets) { - this.pokemon.loadAssets(false).then(() => this.pokemon.playAnim()); - } - this.pokemon.updateInfo(true); + this.pokemon.clearStatus(this.affectConfusion, this.reloadAssets); this.end(); } } diff --git a/src/phases/revival-blessing-phase.ts b/src/phases/revival-blessing-phase.ts index 2de1c616f69..598d9109abc 100644 --- a/src/phases/revival-blessing-phase.ts +++ b/src/phases/revival-blessing-phase.ts @@ -32,7 +32,7 @@ export class RevivalBlessingPhase extends BattlePhase { } pokemon.resetTurnData(); - pokemon.resetStatus(); + pokemon.resetStatus(true, false, false, false); pokemon.heal(Math.min(toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); globalScene.queueMessage( i18next.t("moveTriggers:revivalBlessing", { diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 8f5a9c75428..3f5e0393ff7 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -310,6 +310,48 @@ const timedEvents: TimedEvent[] = [ }, ], }, + { + name: "Shining Spring", + eventType: EventType.SHINY, + startDate: new Date(Date.UTC(2025, 4, 2)), + endDate: new Date(Date.UTC(2025, 4, 12)), + bannerKey: "spr25event", + scale: 0.21, + availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-MX", "pt-BR", "zh-CN"], + shinyMultiplier: 2, + upgradeUnlockedVouchers: true, + eventEncounters: [ + { species: Species.HOPPIP }, + { species: Species.CELEBI }, + { species: Species.VOLBEAT }, + { species: Species.ILLUMISE }, + { species: Species.SPOINK }, + { species: Species.LILEEP }, + { species: Species.SHINX }, + { species: Species.PACHIRISU }, + { species: Species.CHERUBI }, + { species: Species.MUNCHLAX }, + { species: Species.TEPIG }, + { species: Species.PANSAGE }, + { species: Species.PANSEAR }, + { species: Species.PANPOUR }, + { species: Species.DARUMAKA }, + { species: Species.ARCHEN }, + { species: Species.DEERLING, formIndex: 0 }, // Spring Deerling + { species: Species.CLAUNCHER }, + { species: Species.WISHIWASHI }, + { species: Species.MUDBRAY }, + { species: Species.DRAMPA }, + { species: Species.JANGMO_O }, + { species: Species.APPLIN }, + ], + classicWaveRewards: [ + { wave: 8, type: "SHINY_CHARM" }, + { wave: 8, type: "ABILITY_CHARM" }, + { wave: 8, type: "CATCHING_CHARM" }, + { wave: 25, type: "SHINY_CHARM" }, + ], + } ]; export class TimedEventManager {