Winter Holiday Event (#5015)
* Update trainer-victory-phase.ts * Update starters.ts for event * Update timed-event-manager.ts * Event stuff * Cleaning up * Winter Holiday 2024 Banners * Update timed-event-manager.ts * Fix event banner * Update trainer-config.ts * FoF, BBound, weather changes * Fix German Banner * Add Iron Bundle to event encounters * Update delibirdy-encounter.test.ts * Update src/data/weather.ts Co-authored-by: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> --------- Co-authored-by: AJ Fontaine <fontbane@gmail.com> Co-authored-by: Lugiad <2070109+Adri1@users.noreply.github.com> Co-authored-by: AJ Fontaine <36677462+Fontbane@users.noreply.github.com>
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 38 KiB |
|
@ -4,7 +4,7 @@ export const POKERUS_STARTER_COUNT = 5;
|
||||||
|
|
||||||
// #region Friendship constants
|
// #region Friendship constants
|
||||||
export const CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER = 3;
|
export const CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER = 3;
|
||||||
export const FRIENDSHIP_GAIN_FROM_BATTLE = 3;
|
export const FRIENDSHIP_GAIN_FROM_BATTLE = 4;
|
||||||
export const FRIENDSHIP_GAIN_FROM_RARE_CANDY = 6;
|
export const FRIENDSHIP_GAIN_FROM_RARE_CANDY = 6;
|
||||||
export const FRIENDSHIP_LOSS_FROM_FAINT = 5;
|
export const FRIENDSHIP_LOSS_FROM_FAINT = 5;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
ModifierTypeOption, modifierTypes,
|
ModifierTypeOption, modifierTypes,
|
||||||
regenerateModifierPoolThresholds,
|
regenerateModifierPoolThresholds,
|
||||||
} from "#app/modifier/modifier-type";
|
} from "#app/modifier/modifier-type";
|
||||||
import { randSeedInt } from "#app/utils";
|
import { randSeedInt, randSeedItem } from "#app/utils";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
|
@ -31,6 +31,7 @@ import { BerryType } from "#enums/berry-type";
|
||||||
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
import PokemonSpecies, { allSpecies } from "#app/data/pokemon-species";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounters/berriesAbound";
|
const namespace = "mysteryEncounters/berriesAbound";
|
||||||
|
@ -58,7 +59,14 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||||
|
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
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);
|
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
||||||
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifi
|
||||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
|
import { randSeedItem } from "#app/utils";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
|
@ -33,7 +34,24 @@ const OPTION_3_DISALLOWED_MODIFIERS = [
|
||||||
"PokemonBaseStatTotalModifier"
|
"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.
|
* Delibird-y encounter.
|
||||||
|
@ -42,7 +60,8 @@ const DELIBIRDY_MONEY_PRICE_MULTIPLIER = 2;
|
||||||
*/
|
*/
|
||||||
export const DelibirdyEncounter: MysteryEncounter =
|
export const DelibirdyEncounter: MysteryEncounter =
|
||||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DELIBIRDY)
|
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DELIBIRDY)
|
||||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
.withMaxAllowedEncounters(4)
|
||||||
|
.withEncounterTier(MysteryEncounterTier.COMMON) //Change back after event!
|
||||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
.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
|
.withSceneRequirement(new MoneyRequirement(0, DELIBIRDY_MONEY_PRICE_MULTIPLIER)) // Must have enough money for it to spawn at the very least
|
||||||
.withPrimaryPokemonRequirement(
|
.withPrimaryPokemonRequirement(
|
||||||
|
@ -136,8 +155,10 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||||
await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerPokemon()!, shellBell);
|
await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerPokemon()!, shellBell);
|
||||||
scene.playSound("item_fanfare");
|
scene.playSound("item_fanfare");
|
||||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
||||||
|
doEventReward(scene);
|
||||||
} else {
|
} else {
|
||||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.AMULET_COIN));
|
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.AMULET_COIN));
|
||||||
|
doEventReward(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
|
@ -211,8 +232,10 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||||
await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerPokemon()!, shellBell);
|
await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerPokemon()!, shellBell);
|
||||||
scene.playSound("item_fanfare");
|
scene.playSound("item_fanfare");
|
||||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
||||||
|
doEventReward(scene);
|
||||||
} else {
|
} else {
|
||||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.CANDY_JAR));
|
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.CANDY_JAR));
|
||||||
|
doEventReward(scene);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Check if the player has max stacks of that Berry Pouch already
|
// 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);
|
await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerPokemon()!, shellBell);
|
||||||
scene.playSound("item_fanfare");
|
scene.playSound("item_fanfare");
|
||||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
||||||
|
doEventReward(scene);
|
||||||
} else {
|
} else {
|
||||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.BERRY_POUCH));
|
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);
|
await applyModifierTypeToPlayerPokemon(scene, scene.getPlayerParty()[0], shellBell);
|
||||||
scene.playSound("item_fanfare");
|
scene.playSound("item_fanfare");
|
||||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, undefined, true);
|
||||||
|
doEventReward(scene);
|
||||||
} else {
|
} else {
|
||||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.HEALING_CHARM));
|
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.HEALING_CHARM));
|
||||||
|
doEventReward(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
chosenPokemon.loseHeldItem(modifier, false);
|
chosenPokemon.loseHeldItem(modifier, false);
|
||||||
|
|
|
@ -26,9 +26,10 @@ import { getEncounterPokemonLevelForWave, getSpriteKeysFromPokemon, STANDARD_ENC
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
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 { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
import PokemonSpecies, { allSpecies } from "#app/data/pokemon-species";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounters/fightOrFlight";
|
const namespace = "mysteryEncounters/fightOrFlight";
|
||||||
|
@ -56,7 +57,14 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||||
|
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
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);
|
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
||||||
encounter.setDialogueToken("enemyPokemon", bossPokemon.getNameToRender());
|
encounter.setDialogueToken("enemyPokemon", bossPokemon.getNameToRender());
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode
|
||||||
import { TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerSlot } from "#app/data/trainer-config";
|
||||||
import { catchPokemon, getHighestLevelPlayerPokemon, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { catchPokemon, getHighestLevelPlayerPokemon, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
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 { Moves } from "#enums/moves";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#app/battle";
|
||||||
import { SelfStatusMove } from "#app/data/move";
|
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 { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
import PokemonSpecies, { allSpecies } from "#app/data/pokemon-species";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounters/uncommonBreed";
|
const namespace = "mysteryEncounters/uncommonBreed";
|
||||||
|
@ -51,7 +52,14 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
// Level equal to 2 below highest party member
|
// Level equal to 2 below highest party member
|
||||||
const level = getHighestLevelPlayerPokemon(scene, false, true).level - 2;
|
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);
|
const pokemon = new EnemyPokemon(scene, species, level, TrainerSlot.NONE, true);
|
||||||
|
|
||||||
// Pokemon will always have one of its egg moves in its moveset
|
// Pokemon will always have one of its egg moves in its moveset
|
||||||
|
|
|
@ -177,7 +177,7 @@ export const allMysteryEncounters: { [encounterType: number]: MysteryEncounter }
|
||||||
const extremeBiomeEncounters: MysteryEncounterType[] = [];
|
const extremeBiomeEncounters: MysteryEncounterType[] = [];
|
||||||
|
|
||||||
const nonExtremeBiomeEncounters: 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
|
MysteryEncounterType.DANCING_LESSONS, // Is also in BADLANDS, DESERT, VOLCANO, WASTELAND, ABYSS
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -185,14 +185,14 @@ const humanTransitableBiomeEncounters: MysteryEncounterType[] = [
|
||||||
MysteryEncounterType.MYSTERIOUS_CHALLENGERS,
|
MysteryEncounterType.MYSTERIOUS_CHALLENGERS,
|
||||||
MysteryEncounterType.SHADY_VITAMIN_DEALER,
|
MysteryEncounterType.SHADY_VITAMIN_DEALER,
|
||||||
MysteryEncounterType.THE_POKEMON_SALESMAN,
|
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_WINSTRATE_CHALLENGE,
|
||||||
MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER
|
MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER
|
||||||
];
|
];
|
||||||
|
|
||||||
const civilizationBiomeEncounters: MysteryEncounterType[] = [
|
const civilizationBiomeEncounters: MysteryEncounterType[] = [
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE,
|
// MysteryEncounterType.DEPARTMENT_STORE_SALE, Disabled for holiday event
|
||||||
MysteryEncounterType.PART_TIMER,
|
// MysteryEncounterType.PART_TIMER, Disabled for holiday event
|
||||||
MysteryEncounterType.FUN_AND_GAMES,
|
MysteryEncounterType.FUN_AND_GAMES,
|
||||||
MysteryEncounterType.GLOBAL_TRADE_SYSTEM
|
MysteryEncounterType.GLOBAL_TRADE_SYSTEM
|
||||||
];
|
];
|
||||||
|
|
|
@ -1855,7 +1855,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
|
|
||||||
[TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL)
|
[TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL)
|
||||||
.setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE)
|
.setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE)
|
||||||
.setEventModifierRewardFuncs(() => modifierTypes.SHINY_CHARM, () => modifierTypes.ABILITY_CHARM)
|
.setEventModifierRewardFuncs(() => modifierTypes.SHINY_CHARM, () => modifierTypes.ABILITY_CHARM, () => modifierTypes.CATCHING_CHARM)
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO, Species.GROOKEY, Species.SCORBUNNY, Species.SOBBLE, Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY ], TrainerSlot.TRAINER, true,
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO, Species.GROOKEY, Species.SCORBUNNY, Species.SOBBLE, Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY ], TrainerSlot.TRAINER, true,
|
||||||
(p => p.abilityIndex = 0)))
|
(p => p.abilityIndex = 0)))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEY, Species.HOOTHOOT, Species.TAILLOW, Species.STARLY, Species.PIDOVE, Species.FLETCHLING, Species.PIKIPEK, Species.ROOKIDEE, Species.WATTREL ], TrainerSlot.TRAINER, true)),
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEY, Species.HOOTHOOT, Species.TAILLOW, Species.STARLY, Species.PIDOVE, Species.FLETCHLING, Species.PIKIPEK, Species.ROOKIDEE, Species.WATTREL ], TrainerSlot.TRAINER, true)),
|
||||||
|
|
|
@ -242,7 +242,7 @@ export function getTerrainBlockMessage(pokemon: Pokemon, terrainType: TerrainTyp
|
||||||
return i18next.t("terrain:defaultBlockMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), terrainName: getTerrainName(terrainType) });
|
return i18next.t("terrain:defaultBlockMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), terrainName: getTerrainName(terrainType) });
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WeatherPoolEntry {
|
export interface WeatherPoolEntry {
|
||||||
weatherType: WeatherType;
|
weatherType: WeatherType;
|
||||||
weight: integer;
|
weight: integer;
|
||||||
}
|
}
|
||||||
|
@ -373,6 +373,10 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arena.biomeType === Biome.TOWN && 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) {
|
if (weatherPool.length > 1) {
|
||||||
let totalWeight = 0;
|
let totalWeight = 0;
|
||||||
weatherPool.forEach(w => totalWeight += w.weight);
|
weatherPool.forEach(w => totalWeight += w.weight);
|
||||||
|
|
|
@ -246,9 +246,9 @@ export class LoadingScene extends SceneBase {
|
||||||
}
|
}
|
||||||
const availableLangs = [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ];
|
const availableLangs = [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ];
|
||||||
if (lang && availableLangs.includes(lang)) {
|
if (lang && availableLangs.includes(lang)) {
|
||||||
this.loadImage("halloween2024-event-" + lang, "events");
|
this.loadImage("winter_holidays2024-event-" + lang, "events");
|
||||||
} else {
|
} else {
|
||||||
this.loadImage("halloween2024-event-en", "events");
|
this.loadImage("winter_holidays2024-event-en", "events");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadAtlas("statuses", "");
|
this.loadAtlas("statuses", "");
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class TrainerVictoryPhase extends BattlePhase {
|
||||||
// Validate Voucher for boss trainers
|
// Validate Voucher for boss trainers
|
||||||
if (vouchers.hasOwnProperty(TrainerType[trainerType])) {
|
if (vouchers.hasOwnProperty(TrainerType[trainerType])) {
|
||||||
if (!this.scene.validateVoucher(vouchers[TrainerType[trainerType]]) && this.scene.currentBattle.trainer?.config.isBoss) {
|
if (!this.scene.validateVoucher(vouchers[TrainerType[trainerType]]) && this.scene.currentBattle.trainer?.config.isBoss) {
|
||||||
this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType]));
|
this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Breeders in Space achievement
|
// Breeders in Space achievement
|
||||||
|
|
|
@ -56,7 +56,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty);
|
||||||
|
|
||||||
expect(DelibirdyEncounter.encounterType).toBe(MysteryEncounterType.DELIBIRDY);
|
expect(DelibirdyEncounter.encounterType).toBe(MysteryEncounterType.DELIBIRDY);
|
||||||
expect(DelibirdyEncounter.encounterTier).toBe(MysteryEncounterTier.GREAT);
|
expect(DelibirdyEncounter.encounterTier).toBe(MysteryEncounterTier.COMMON);
|
||||||
expect(DelibirdyEncounter.dialogue).toBeDefined();
|
expect(DelibirdyEncounter.dialogue).toBeDefined();
|
||||||
expect(DelibirdyEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}:intro` }]);
|
expect(DelibirdyEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}:intro` }]);
|
||||||
expect(DelibirdyEncounter.dialogue.outro).toStrictEqual([{ text: `${namespace}:outro` }]);
|
expect(DelibirdyEncounter.dialogue.outro).toStrictEqual([{ text: `${namespace}:outro` }]);
|
||||||
|
|
|
@ -2,6 +2,9 @@ import BattleScene from "#app/battle-scene";
|
||||||
import { TextStyle, addTextObject } from "#app/ui/text";
|
import { TextStyle, addTextObject } from "#app/ui/text";
|
||||||
import { nil } from "#app/utils";
|
import { nil } from "#app/utils";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { WeatherPoolEntry } from "#app/data/weather";
|
||||||
|
import { WeatherType } from "#enums/weather-type";
|
||||||
|
|
||||||
export enum EventType {
|
export enum EventType {
|
||||||
SHINY,
|
SHINY,
|
||||||
|
@ -16,6 +19,11 @@ interface EventBanner {
|
||||||
availableLangs?: string[];
|
availableLangs?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface EventEncounter {
|
||||||
|
species: Species;
|
||||||
|
allowEvolution?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface TimedEvent extends EventBanner {
|
interface TimedEvent extends EventBanner {
|
||||||
name: string;
|
name: string;
|
||||||
eventType: EventType;
|
eventType: EventType;
|
||||||
|
@ -23,19 +31,46 @@ interface TimedEvent extends EventBanner {
|
||||||
friendshipMultiplier?: number;
|
friendshipMultiplier?: number;
|
||||||
startDate: Date;
|
startDate: Date;
|
||||||
endDate: Date;
|
endDate: Date;
|
||||||
|
uncommonBreedEncounters?: EventEncounter[];
|
||||||
|
delibirdyBuff?: string[];
|
||||||
|
weather?: WeatherPoolEntry[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const timedEvents: TimedEvent[] = [
|
const timedEvents: TimedEvent[] = [
|
||||||
{
|
{
|
||||||
name: "Halloween Update",
|
name: "Winter Holiday Update",
|
||||||
eventType: EventType.SHINY,
|
eventType: EventType.SHINY,
|
||||||
shinyMultiplier: 2,
|
shinyMultiplier: 2,
|
||||||
friendshipMultiplier: 2,
|
friendshipMultiplier: 1,
|
||||||
startDate: new Date(Date.UTC(2024, 9, 27, 0)),
|
startDate: new Date(Date.UTC(2024, 11, 21, 0)),
|
||||||
endDate: new Date(Date.UTC(2024, 10, 4, 0)),
|
endDate: new Date(Date.UTC(2025, 0, 4, 0)),
|
||||||
bannerKey: "halloween2024-event-",
|
bannerKey: "winter_holidays2024-event-",
|
||||||
scale: 0.21,
|
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 }]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|