diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 90f53d6a95e..6d56d84d035 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -37,6 +37,7 @@ import { PokemonHpRestoreModifier, PokemonIncrementingStatModifier, RememberMoveModifier, + ShinyRateBoosterModifier, } from "./modifier/modifier"; import { PokeballType } from "#enums/pokeball"; import { @@ -184,6 +185,7 @@ import { HideAbilityPhase } from "#app/phases/hide-ability-phase"; import { expSpriteKeys } from "./sprites/sprite-keys"; import { hasExpSprite } from "./sprites/sprite-utils"; import { timedEventManager } from "./global-event-manager"; +import { BASE_SHINY_CHANCE } from "./data/balance/rates"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -1295,6 +1297,17 @@ export default class BattleScene extends SceneBase { } } + /** + * Applies Shiny Charms and other modifiers to check the general shiny rate + * @returns The chance out of 65536 to get a shiny + */ + getModifiedShinyThreshold(): number { + const threshold = new NumberHolder(BASE_SHINY_CHANCE); + this.applyModifiers(ShinyRateBoosterModifier, true, threshold); + threshold.value *= timedEventManager.getShinyMultiplier(); + return threshold.value; + } + getDoubleBattleChance(newWaveIndex: number, playerField: PlayerPokemon[]) { const doubleChance = new NumberHolder(newWaveIndex % 10 === 0 ? 32 : 8); this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); 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 31a6df7046f..7f016ef132a 100644 --- a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts @@ -39,8 +39,8 @@ const MAX_POKEMON_PRICE_MULTIPLIER = 4; /** Odds of shiny magikarp will be 1/value */ const SHINY_MAGIKARP_WEIGHT = 100; -/** Odds of event sale will be 1/value */ -const EVENT_THRESHOLD = 20; +/** Odds of event sale will be value/100 */ +const EVENT_THRESHOLD = 50; /** * Pokemon Salesman encounter. @@ -122,10 +122,11 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui ) { // If you roll 20%, give event encounter with 2 extra shiny rolls and its HA, if it has one const enc = randSeedItem(validEventEncounters); + const thresh = globalScene.getModifiedShinyThreshold(); species = getPokemonSpecies(enc.species); pokemon = new PlayerPokemon(species, 5, species.abilityHidden === Abilities.NONE ? undefined : 2, enc.formIndex); - pokemon.trySetShinySeed(); - pokemon.trySetShinySeed(); + pokemon.trySetShinySeed(thresh); // Apply event shiny boost even though it's a PlayerPokemon + pokemon.trySetShinySeed(thresh); } else { pokemon = new PlayerPokemon(species, 5, 2, species.formIndex); } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 22ede4260c3..6a030ae8e76 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3165,7 +3165,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { /** * Function that tries to set a Pokemon shiny based on seed. * For manual use only, usually to roll a Pokemon's shiny chance a second time. - * If it rolls shiny, also sets a random variant and give the Pokemon the associated luck. + * If it rolls shiny, or if it's already shiny, also sets a random variant and give the Pokemon the associated luck. * * The base shiny odds are {@linkcode BASE_SHINY_CHANCE} / `65536` * @param thresholdOverride number that is divided by `2^16` (`65536`) to get the shiny chance, overrides {@linkcode shinyThreshold} if set (bypassing shiny rate modifiers such as Shiny Charm) @@ -3195,7 +3195,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { shinyThreshold.value = thresholdOverride; } - this.shiny = randSeedInt(65536) < shinyThreshold.value; + this.shiny = this.shiny || randSeedInt(65536) < shinyThreshold.value; // If it's already shiny, don't un-shiny it if (this.shiny) { this.variant = this.generateShinyVariant(); diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 84d70930fe6..7bbd157948b 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -310,47 +310,6 @@ const timedEvents: TimedEvent[] = [ }, ], }, - { - name: "Spring 2025", - eventType: EventType.SHINY, - startDate: new Date(Date.UTC(2025, 2, 30)), - endDate: new Date(Date.UTC(2025, 4, 30)), - bannerKey: "spr25", - scale: 0.21, - availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-MX", "pt-BR", "zh-CN"], - shinyMultiplier: 3, - upgradeUnlockedVouchers: true, - classicWaveRewards: [ - { wave: 8, type: "SHINY_CHARM" }, - { wave: 8, type: "ABILITY_CHARM" }, - { wave: 8, type: "CATCHING_CHARM" }, - { wave: 25, type: "SHINY_CHARM" }, - ], - eventEncounters: [ - { species: Species.NIDORAN_F }, - { species: Species.NIDORAN_M }, - { species: Species.EXEGGCUTE }, - { species: Species.HOPPIP }, - { species: Species.PINECO }, - { species: Species.TOGEPI }, - { species: Species.TORCHIC }, - { species: Species.NOSEPASS }, - { species: Species.SPOINK }, - { species: Species.STARLY }, - { 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.SEWADDLE }, - { species: Species.ARCHEN }, - { species: Species.JANGMO_O }, - { species: Species.APPLIN }, - ], - }, ]; export class TimedEventManager {