diff --git a/public/images/events/winter_holidays2024-event-de.png b/public/images/events/winter_holidays2024-event-de.png index 1a340958912..1c2e10086f2 100644 Binary files a/public/images/events/winter_holidays2024-event-de.png and b/public/images/events/winter_holidays2024-event-de.png differ diff --git a/public/locales b/public/locales index 6592ec05fce..3a141b9faed 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 6592ec05fce7035ee93aad253279e97ab6cdc1ab +Subproject commit 3a141b9faed725d2f160c38e441cad1d38d9d5bd diff --git a/src/constants.ts b/src/constants.ts index 927575c0a28..63f00b9f33f 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,7 +2,7 @@ export const PLAYER_PARTY_MAX_SIZE: number = 6; /** Whether to use seasonal splash messages in general */ -export const USE_SEASONAL_SPLASH_MESSAGES: boolean = true; +export const USE_SEASONAL_SPLASH_MESSAGES: boolean = false; /** Name of the session ID cookie */ export const SESSION_ID_COOKIE_NAME: string = "pokerogue_sessionId"; diff --git a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts index 786ca3e8fc0..090653e7ca9 100644 --- a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts +++ b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts @@ -13,7 +13,7 @@ import { ModifierTypeOption, modifierTypes, regenerateModifierPoolThresholds, } from "#app/modifier/modifier-type"; -import { randSeedInt } from "#app/utils"; +import { randSeedInt, randSeedItem } from "#app/utils"; import { BattlerTagType } from "#enums/battler-tag-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "#app/battle-scene"; @@ -31,6 +31,7 @@ import { BerryType } from "#enums/berry-type"; import { PERMANENT_STATS, Stat } from "#enums/stat"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import PokemonSpecies, { allSpecies } from "#app/data/pokemon-species"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/berriesAbound"; @@ -58,7 +59,14 @@ export const BerriesAboundEncounter: MysteryEncounter = // Calculate boss mon const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER); - const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getPlayerParty()), true); + let bossSpecies: PokemonSpecies; + if (scene.eventManager.isEventActive() && scene.eventManager.activeEvent()?.uncommonBreedEncounters && randSeedInt(2) === 1) { + const eventEncounter = randSeedItem(scene.eventManager.activeEvent()!.uncommonBreedEncounters!); + bossSpecies = allSpecies[eventEncounter.species]; + bossSpecies.speciesId = bossSpecies.getSpeciesForLevel(level, eventEncounter.allowEvolution); + } else { + bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getPlayerParty()), true); + } const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true); encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon)); const config: EnemyPartyConfig = { diff --git a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts index a3a97a01238..1df87a3d17f 100644 --- a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts +++ b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts @@ -13,6 +13,7 @@ import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifi import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase"; import i18next from "#app/plugins/i18n"; import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; +import { randSeedItem } from "#app/utils"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; @@ -33,7 +34,24 @@ const OPTION_3_DISALLOWED_MODIFIERS = [ "PokemonBaseStatTotalModifier" ]; -const DELIBIRDY_MONEY_PRICE_MULTIPLIER = 2; +const DELIBIRDY_MONEY_PRICE_MULTIPLIER = 1.5; + +const doEventReward = (scene: BattleScene) => { + const event_buff = scene.eventManager.activeEvent()?.delibirdyBuff ?? []; + if (event_buff.length > 0) { + const candidates = event_buff.filter((c => { + const mtype = generateModifierType(scene, modifierTypes[c]); + const existingCharm = scene.findModifier(m => m.type.id === mtype?.id); + return !(existingCharm && existingCharm.getStackCount() >= existingCharm.getMaxStackCount(scene)); + })); + if (candidates.length > 0) { + scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes[randSeedItem(candidates)])); + } else { + // At max stacks, give a Voucher instead + scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.VOUCHER)); + } + } +}; /** * Delibird-y encounter. @@ -42,7 +60,8 @@ const DELIBIRDY_MONEY_PRICE_MULTIPLIER = 2; */ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DELIBIRDY) - .withEncounterTier(MysteryEncounterTier.GREAT) + .withMaxAllowedEncounters(4) + .withEncounterTier(MysteryEncounterTier.COMMON) //Change back after event! .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) .withSceneRequirement(new MoneyRequirement(0, DELIBIRDY_MONEY_PRICE_MULTIPLIER)) // Must have enough money for it to spawn at the very least .withPrimaryPokemonRequirement( @@ -136,8 +155,10 @@ export const DelibirdyEncounter: MysteryEncounter = await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerPokemon()!, shellBell); scene.playSound("item_fanfare"); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true); + doEventReward(scene); } else { scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.AMULET_COIN)); + doEventReward(scene); } leaveEncounterWithoutBattle(scene, true); @@ -211,8 +232,10 @@ export const DelibirdyEncounter: MysteryEncounter = await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerPokemon()!, shellBell); scene.playSound("item_fanfare"); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true); + doEventReward(scene); } else { scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.CANDY_JAR)); + doEventReward(scene); } } else { // Check if the player has max stacks of that Berry Pouch already @@ -224,8 +247,10 @@ export const DelibirdyEncounter: MysteryEncounter = await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerPokemon()!, shellBell); scene.playSound("item_fanfare"); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true); + doEventReward(scene); } else { scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.BERRY_POUCH)); + doEventReward(scene); } } @@ -300,8 +325,10 @@ export const DelibirdyEncounter: MysteryEncounter = await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerParty()[0], shellBell); scene.playSound("item_fanfare"); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true); + doEventReward(scene); } else { scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.HEALING_CHARM)); + doEventReward(scene); } chosenPokemon.loseHeldItem(modifier, false); diff --git a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts index 3533e10df29..07e7a15c65c 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts @@ -26,9 +26,10 @@ import { getEncounterPokemonLevelForWave, getSpriteKeysFromPokemon, STANDARD_ENC import PokemonData from "#app/system/pokemon-data"; import { BattlerTagType } from "#enums/battler-tag-type"; import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; -import { randSeedInt } from "#app/utils"; +import { randSeedInt, randSeedItem } from "#app/utils"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import PokemonSpecies, { allSpecies } from "#app/data/pokemon-species"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/fightOrFlight"; @@ -56,7 +57,14 @@ export const FightOrFlightEncounter: MysteryEncounter = // Calculate boss mon const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER); - const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getPlayerParty()), true); + let bossSpecies: PokemonSpecies; + if (scene.eventManager.isEventActive() && scene.eventManager.activeEvent()?.uncommonBreedEncounters && randSeedInt(2) === 1) { + const eventEncounter = randSeedItem(scene.eventManager.activeEvent()!.uncommonBreedEncounters!); + bossSpecies = allSpecies[eventEncounter.species]; + bossSpecies.speciesId = bossSpecies.getSpeciesForLevel(level, eventEncounter.allowEvolution); + } else { + bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getPlayerParty()), true); + } const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true); encounter.setDialogueToken("enemyPokemon", bossPokemon.getNameToRender()); const config: EnemyPartyConfig = { diff --git a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts index d3679825ac8..15f7bce8945 100644 --- a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts +++ b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts @@ -12,7 +12,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode import { TrainerSlot } from "#app/data/trainer-config"; import { catchPokemon, getHighestLevelPlayerPokemon, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import PokemonData from "#app/system/pokemon-data"; -import { isNullOrUndefined, randSeedInt } from "#app/utils"; +import { isNullOrUndefined, randSeedInt, randSeedItem } from "#app/utils"; import { Moves } from "#enums/moves"; import { BattlerIndex } from "#app/battle"; import { SelfStatusMove } from "#app/data/move"; @@ -23,6 +23,7 @@ import { BerryModifier } from "#app/modifier/modifier"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { Stat } from "#enums/stat"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import PokemonSpecies, { allSpecies } from "#app/data/pokemon-species"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/uncommonBreed"; @@ -51,7 +52,14 @@ export const UncommonBreedEncounter: MysteryEncounter = // Calculate boss mon // Level equal to 2 below highest party member const level = getHighestLevelPlayerPokemon(scene, false, true).level - 2; - const species = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getPlayerParty()), true); + let species: PokemonSpecies; + if (scene.eventManager.isEventActive() && scene.eventManager.activeEvent()?.uncommonBreedEncounters && randSeedInt(2) === 1) { + const eventEncounter = randSeedItem(scene.eventManager.activeEvent()!.uncommonBreedEncounters!); + species = allSpecies[eventEncounter.species]; + species.speciesId = species.getSpeciesForLevel(level, eventEncounter.allowEvolution); + } else { + species = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getPlayerParty()), true); + } const pokemon = new EnemyPokemon(scene, species, level, TrainerSlot.NONE, true); // Pokemon will always have one of its egg moves in its moveset diff --git a/src/data/mystery-encounters/mystery-encounters.ts b/src/data/mystery-encounters/mystery-encounters.ts index 8c1c3bf6de4..8a747cd4cd4 100644 --- a/src/data/mystery-encounters/mystery-encounters.ts +++ b/src/data/mystery-encounters/mystery-encounters.ts @@ -177,7 +177,7 @@ export const allMysteryEncounters: { [encounterType: number]: MysteryEncounter } const extremeBiomeEncounters: MysteryEncounterType[] = []; const nonExtremeBiomeEncounters: MysteryEncounterType[] = [ - MysteryEncounterType.FIELD_TRIP, + // MysteryEncounterType.FIELD_TRIP, Disabled for holiday event MysteryEncounterType.DANCING_LESSONS, // Is also in BADLANDS, DESERT, VOLCANO, WASTELAND, ABYSS ]; @@ -185,14 +185,14 @@ const humanTransitableBiomeEncounters: MysteryEncounterType[] = [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS, MysteryEncounterType.SHADY_VITAMIN_DEALER, MysteryEncounterType.THE_POKEMON_SALESMAN, - MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, + // MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, Disabled for holiday event MysteryEncounterType.THE_WINSTRATE_CHALLENGE, MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER ]; const civilizationBiomeEncounters: MysteryEncounterType[] = [ - MysteryEncounterType.DEPARTMENT_STORE_SALE, - MysteryEncounterType.PART_TIMER, + // MysteryEncounterType.DEPARTMENT_STORE_SALE, Disabled for holiday event + // MysteryEncounterType.PART_TIMER, Disabled for holiday event MysteryEncounterType.FUN_AND_GAMES, MysteryEncounterType.GLOBAL_TRADE_SYSTEM ]; diff --git a/src/data/splash-messages.ts b/src/data/splash-messages.ts index 086a55189d0..1f00ce0d555 100644 --- a/src/data/splash-messages.ts +++ b/src/data/splash-messages.ts @@ -1,5 +1,4 @@ import { USE_SEASONAL_SPLASH_MESSAGES } from "#app/constants"; -import i18next from "i18next"; //#region Interfaces/Types @@ -38,6 +37,8 @@ interface Season { start: `${Month}-${Day}`; /** The end day and month of the season. Format `MM-DD` */ end: `${Month}-${Day}`; + /** Collection of the messages to display (without the `i18next.t()` call!) */ + messages: string[]; } //#region Constants @@ -45,57 +46,176 @@ interface Season { /** The weight multiplier for the battles-won splash message */ const BATTLES_WON_WEIGHT_MULTIPLIER = 10; /** The weight multiplier for the seasonal splash messages */ -const SEASONAL_WEIGHT_MULTIPLIER = 20; +const SEASONAL_WEIGHT_MULTIPLIER = 10; + +//#region Common Messages + +const commonSplashMessages = [ + ...Array(BATTLES_WON_WEIGHT_MULTIPLIER).fill("battlesWon"), + "joinTheDiscord", + "infiniteLevels", + "everythingIsStackable", + "optionalSaveScumming", + "biomes", + "openSource", + "playWithSpeed", + "liveBugTesting", + "heavyInfluence", + "pokemonRiskAndPokemonRain", + "nowWithMoreSalt", + "infiniteFusionAtHome", + "brokenEggMoves", + "magnificent", + "doPeopleReadThis", + "thatsCrazy", + "gottaCatchEmAll", + "questionableBalancing", + "coolShaders", + "aiFree", + "suddenDifficultySpikes", + "basedOnAnUnfinishedFlashGame", + "moreAddictiveThanIntended", + "mostlyConsistentSeeds", + "achievementPointsDontDoAnything", + "nothingBeatsAJellyFilledDonut", + "dontTalkAboutTheTinkatonIncident", + "alsoTryPokengine", + "alsoTryEmeraldRogue", + "alsoTryRadicalRed", + "eeveeExpo", + "checkOutYnoproject", + "breedersInSpace", + "alsoTryPokemonUnbound", + "tryTheJohtoDragonChallenge", + "basicReadingAbilityRecommended", + "shoutoutsToTheArtists", + "gamblingNotEncouraged", + "dontForgetToTakeABreak", + "wEvent", + "ifItsNotAccurateItsAccurate", + "everyLossIsProgressMade", + "liveWoChienReaction", + "itsAFeatureNotABug", + "theEggsAreNotForEating", + "7.8outOf10TooManyWaterBiomes", + "butNothingHappened", + "thePowerOfScienceIsAmazing", + "freeToPlay", + "theresATimeAndPlaceForEverything", + "nowWithShinierShinies", + "smilesGoForMiles", + "certainlyNotDragonFree", + "haveANiceDay", + "redacted", + "hi", + "transRights", + "shinyOddsHigherThanYouThink", + "noFalseTrades", + "notForProfit", + "timeForYourDailyRun", + "moreEggsThanADaycare", + "disclaimerHarshSunDoesNotGiveVitaminD", + "whoNeedsAMap", + "luxrayIsNotADarkType", + "selfDestructiveEncounters", + "mostOptionsAreViable", + "pokerogueMorse", + "smiley", + "beAwareOfPassives", + "asSeenOnTheWorldWideWeb", + "vaultinVeluzas", + "tooManyStarters", + "checkTheWiki", + "winWithYourFavorites", + "alsoTryPokerogueWait", + "theWayISeeItKyogreIsSurrounded", + "tryOutHoneyGather", + "notForTheFaintOfHeart", + "p", + "flipYourDeviceToEvolveInkay", + "inArceusWeTrust", + "whyDidTheTorchicCrossTheRoad", + "goodLuck", + "fuseWisely", + "compensation", + "prepareForTroubleAndMakeItDouble", + "anEggForYourTroubles", + "regirock", + "hereForAGoodTime", + "getGoodOrDont", + "checkTheSubreddit", + "betterNerfGreninja", + "inCaseOfUpdateClearYourCache", + "insertTextHere", + "endingEndlessNotFound", + "iLikeMyEggsVouchered", + "YOU", + "noAddedSugar", + "notSponsored", + "notRated", + "justOneMoreWaveMom", + "saltCured", + "onlyOnPokerogueNet", + "pixelPerfection", + "openSource", + "probablyGood", + "itsAMonsterHouse", + "dontForgetYourPassword", + "tripleTripleTripleAxel", + "questionExclamation", + "clownEncounters", + "fullOfBerries", + "limitsAreMeantToBeBrokenSometimes", + "keepItCasual", + "serversProbablyWorking", + "mew", + "makeItRainAndYourProblemsGoAway", + "customMusicTracks", + "youAreValid", + "number591IsLookingOff", + "timeForYourDeliDelivery", + "goodFirstImpression", + "iPreferRarerCandies", +]; //#region Seasonal Messages const seasonalSplashMessages: Season[] = [ { - name: "halloween", - start: "10-15", - end: "10-31" + name: "Halloween", + start: "09-15", + end: "10-31", + messages: [ "halloween.pumpkabooAbout", "halloween.mayContainSpiders", "halloween.spookyScarySkeledirge", "halloween.gourgeistUsedTrickOrTreat", "halloween.letsSnuggleForever" ], }, { - name: "xmas", - start: "12-16", - end: "12-31" + name: "XMAS", + start: "12-01", + end: "12-26", + messages: [ "xmas.happyHolidays", "xmas.unaffilicatedWithDelibirdServices", "xmas.delibirdSeason", "xmas.diamondsFromTheSky", "xmas.holidayStylePikachuNotIncluded" ], }, { - name: "newYears", - start: "12-31", - end: "01-14" + name: "New Year's", + start: "01-01", + end: "01-31", + messages: [ "newYears.happyNewYear" ], }, ]; //#endregion export function getSplashMessages(): string[] { - const existingKeys = i18next.getResourceBundle(i18next.language, "splashMessages"); - const splashMessages: string[] = [ ...Object.keys(existingKeys["common"]) ].map((message) => `common.${message}`); - if (splashMessages.includes("common.battlesWon")) { - splashMessages.push(...Array(Math.max(BATTLES_WON_WEIGHT_MULTIPLIER - 1, 1)).fill("common.battlesWon")); - } - + const splashMessages: string[] = [ ...commonSplashMessages ]; console.log("use seasonal splash messages", USE_SEASONAL_SPLASH_MESSAGES); if (USE_SEASONAL_SPLASH_MESSAGES) { // add seasonal splash messages if the season is active - for (const { name, start, end } of seasonalSplashMessages) { + for (const { name, start, end, messages } of seasonalSplashMessages) { const now = new Date(); const startDate = new Date(`${start}-${now.getFullYear()}`); const endDate = new Date(`${end}-${now.getFullYear()}`); - if (endDate < startDate) { // If the end date is earlier in the year, that means it's next year - if (now >= startDate) { - endDate.setFullYear(endDate.getFullYear() + 1); //Ends next year - } else if (now <= endDate) { - startDate.setFullYear(startDate.getFullYear() - 1); //Started last year - } - } - console.log(`${name} event starts ${startDate} and ends ${endDate}`); - if (existingKeys.hasOwnProperty(name) && now >= startDate && now <= endDate) { - const existingMessages: string[] = [ ...Object.keys(existingKeys[name]) ].map(m=>`${name}.${m}`); - console.log(`Adding ${existingMessages.length} ${name} splash messages from ${i18next.language} (weight: x${SEASONAL_WEIGHT_MULTIPLIER})`); - existingMessages.forEach((message) => { + if (now >= startDate && now <= endDate) { + console.log(`Adding ${messages.length} ${name} splash messages (weight: x${SEASONAL_WEIGHT_MULTIPLIER})`); + messages.forEach((message) => { const weightedMessage = Array(SEASONAL_WEIGHT_MULTIPLIER).fill(message); splashMessages.push(...weightedMessage); }); diff --git a/src/data/weather.ts b/src/data/weather.ts index 0a76a015402..19092716353 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -242,7 +242,7 @@ export function getTerrainBlockMessage(pokemon: Pokemon, terrainType: TerrainTyp return i18next.t("terrain:defaultBlockMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), terrainName: getTerrainName(terrainType) }); } -interface WeatherPoolEntry { +export interface WeatherPoolEntry { weatherType: WeatherType; weight: integer; } @@ -373,6 +373,10 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a break; } + if (arena.scene.eventManager.isEventActive() && arena.scene.eventManager.activeEvent()?.weather?.length > 0) { + arena.scene.eventManager.activeEvent().weather.map(w => weatherPool.push(w)); + } + if (weatherPool.length > 1) { let totalWeight = 0; weatherPool.forEach(w => totalWeight += w.weight); diff --git a/src/loading-scene.ts b/src/loading-scene.ts index c49b8d5aaa9..2e9484a847d 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -246,9 +246,9 @@ export class LoadingScene extends SceneBase { } const availableLangs = [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ]; if (lang && availableLangs.includes(lang)) { - this.loadImage("halloween2024-event-" + lang, "events"); + this.loadImage("winter_holidays2024-event-" + lang, "events"); } else { - this.loadImage("halloween2024-event-en", "events"); + this.loadImage("winter_holidays2024-event-en", "events"); } this.loadAtlas("statuses", ""); diff --git a/src/test/data/splash_messages.test.ts b/src/test/data/splash_messages.test.ts index e4ad547b704..b9ed5b9d365 100644 --- a/src/test/data/splash_messages.test.ts +++ b/src/test/data/splash_messages.test.ts @@ -9,7 +9,7 @@ describe("Data - Splash Messages", () => { // make sure to adjust this test if the weight it changed! it("should add contain 10 `battlesWon` splash messages", () => { - const battlesWonMessages = getSplashMessages().filter((message) => message === "splashMessages:common.battlesWon"); + const battlesWonMessages = getSplashMessages().filter((message) => message === "splashMessages:battlesWon"); expect(battlesWonMessages).toHaveLength(10); }); @@ -22,16 +22,16 @@ describe("Data - Splash Messages", () => { vi.useRealTimers(); // reset system time }); - it("should contain halloween messages from Oct 15 to Oct 31", () => { - testSeason(new Date("2024-10-15"), new Date("2024-10-31"), "halloween"); + it("should contain halloween messages from Sep 15 to Oct 31", () => { + testSeason(new Date("2024-09-15"), new Date("2024-10-31"), "halloween"); }); - it("should contain xmas messages from Dec 16 to Dec 31", () => { - testSeason(new Date("2024-12-16"), new Date("2024-12-31"), "xmas"); + it("should contain xmas messages from Dec 1 to Dec 26", () => { + testSeason(new Date("2024-12-01"), new Date("2024-12-26"), "xmas"); }); - it("should contain new years messages from Dec 31 '24 to Jan 14 '25", () => { - testSeason(new Date("2024-12-31"), new Date("2025-01-14"), "newYears"); + it("should contain new years messages frm Jan 1 to Jan 31", () => { + testSeason(new Date("2024-01-01"), new Date("2024-01-31"), "newYears"); }); }); }); @@ -60,7 +60,7 @@ function testSeason(startDate: Date, endDate: Date, prefix: string) { }); expect(before).toBe(0); - expect(start).toBeGreaterThanOrEqual(20); // make sure to adjust if weight is changed! - expect(end).toBeGreaterThanOrEqual(20); // make sure to adjust if weight is changed! + expect(start).toBeGreaterThanOrEqual(10); // make sure to adjust if weight is changed! + expect(end).toBeGreaterThanOrEqual(10); // make sure to adjust if weight is changed! expect(after).toBe(0); } diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 34756fe7d82..e4a376ac366 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -2,6 +2,9 @@ import BattleScene from "#app/battle-scene"; import { TextStyle, addTextObject } from "#app/ui/text"; import { nil } from "#app/utils"; import i18next from "i18next"; +import { Species } from "#enums/species"; +import { WeatherPoolEntry } from "#app/data/weather"; +import { WeatherType } from "#enums/weather-type"; export enum EventType { SHINY, @@ -16,6 +19,11 @@ interface EventBanner { availableLangs?: string[]; } +interface EventEncounter { + species: Species; + allowEvolution?: boolean; +} + interface TimedEvent extends EventBanner { name: string; eventType: EventType; @@ -23,6 +31,9 @@ interface TimedEvent extends EventBanner { friendshipMultiplier?: number; startDate: Date; endDate: Date; + uncommonBreedEncounters?: EventEncounter[]; + delibirdyBuff?: string[]; + weather?: WeatherPoolEntry[]; } const timedEvents: TimedEvent[] = [ @@ -35,7 +46,31 @@ const timedEvents: TimedEvent[] = [ endDate: new Date(Date.UTC(2025, 0, 4, 0)), bannerKey: "winter_holidays2024-event-", scale: 0.21, - availableLangs: [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ] + availableLangs: [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ], + uncommonBreedEncounters: [ + { species: Species.GIMMIGHOUL }, + { species: Species.DELIBIRD }, + { species: Species.STANTLER }, + { species: Species.CYNDAQUIL, allowEvolution: true }, + { species: Species.PIPLUP, allowEvolution: true }, + { species: Species.CHESPIN, allowEvolution: true }, + { species: Species.BALTOY, allowEvolution: true }, + { species: Species.SNOVER, allowEvolution: true }, + { species: Species.CHINGLING, allowEvolution: true }, + { species: Species.LITWICK, allowEvolution: true }, + { species: Species.CUBCHOO, allowEvolution: true }, + { species: Species.SWIRLIX, allowEvolution: true }, + { species: Species.AMAURA, allowEvolution: true }, + { species: Species.MUDBRAY, allowEvolution: true }, + { species: Species.ROLYCOLY, allowEvolution: true }, + { species: Species.MILCERY, allowEvolution: true }, + { species: Species.SMOLIV, allowEvolution: true }, + { species: Species.ALOLA_VULPIX, allowEvolution: true }, + { species: Species.GALAR_DARUMAKA, allowEvolution: true }, + { species: Species.IRON_BUNDLE } + ], + delibirdyBuff: [ "CATCHING_CHARM", "SHINY_CHARM", "ABILITY_CHARM", "EXP_CHARM", "SUPER_EXP_CHARM", "HEALING_CHARM" ], + weather: [{ weatherType: WeatherType.SNOW, weight: 1 }] } ]; diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index f1b0a673ea0..aec80f049c9 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -83,7 +83,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler { .then(stats => { if (stats) { this.playerCountLabel.setText(`${stats.playerCount} ${i18next.t("menu:playersOnline")}`); - if (this.splashMessage === "splashMessages:common.battlesWon") { + if (this.splashMessage === "splashMessages:battlesWon") { this.splashMessageText.setText(i18next.t(this.splashMessage, { count: stats.battleCount })); } } @@ -98,7 +98,6 @@ export default class TitleUiHandler extends OptionSelectUiHandler { if (ret) { this.splashMessage = Utils.randItem(getSplashMessages()); - console.log(this.splashMessage); this.splashMessageText.setText(i18next.t(this.splashMessage, { count: TitleUiHandler.BATTLES_WON_FALLBACK })); this.appVersionText.setText("v" + version);