commit changes

This commit is contained in:
ImperialSympathizer 2024-07-15 21:45:33 -04:00
parent a40f27ff8f
commit e10a9caddc
13 changed files with 380 additions and 105 deletions

View File

@ -4,51 +4,72 @@
"image": "mud.png",
"format": "RGBA8888",
"size": {
"w": 18,
"h": 55
"w": 14,
"h": 68
},
"scale": 1,
"frames": [
{
"filename": "0002.png",
"filename": "0001.png",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 16,
"h": 16
"w": 12,
"h": 20
},
"spriteSourceSize": {
"x": 0,
"y": 3,
"w": 16,
"y": 0,
"w": 12,
"h": 13
},
"frame": {
"x": 1,
"y": 1,
"w": 16,
"w": 12,
"h": 13
}
},
{
"filename": "0002.png",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 12,
"h": 20
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 12,
"h": 14
},
"frame": {
"x": 1,
"y": 16,
"w": 12,
"h": 14
}
},
{
"filename": "0003.png",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 16,
"h": 16
"w": 12,
"h": 20
},
"spriteSourceSize": {
"x": 0,
"y": 4,
"w": 16,
"h": 12
"y": 1,
"w": 12,
"h": 16
},
"frame": {
"x": 1,
"y": 16,
"w": 16,
"h": 12
"y": 32,
"w": 12,
"h": 16
}
},
{
@ -56,41 +77,20 @@
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 16,
"h": 16
"w": 12,
"h": 20
},
"spriteSourceSize": {
"x": 0,
"y": 7,
"w": 16,
"h": 9
},
"frame": {
"x": 1,
"y": 30,
"w": 16,
"h": 9
}
},
{
"filename": "0001.png",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 16,
"h": 16
},
"spriteSourceSize": {
"x": 1,
"y": 3,
"w": 14,
"h": 13
"w": 12,
"h": 17
},
"frame": {
"x": 1,
"y": 41,
"w": 14,
"h": 13
"y": 50,
"w": 12,
"h": 17
}
}
]
@ -99,6 +99,6 @@
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:a9f7ae83758a2dffaacdaba2ee9dc2e2:0ebff9db47ce74a0ec049f5d74d589fa:c64f6b8befc3d5e9f836246d2b9536be$"
"smartupdate": "$TexturePacker:SmartUpdate:4f18a8effb8f01eb70f9f25b8294c1bf:ad663a73c51f780bbf45d00a52519553:c64f6b8befc3d5e9f836246d2b9536be$"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 B

After

Width:  |  Height:  |  Size: 375 B

View File

@ -0,0 +1,173 @@
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { modifierTypes, } from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "../../../battle-scene";
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
import { TypeRequirement } from "../mystery-encounter-requirements";
import { Species } from "#enums/species";
import { getPokemonSpecies } from "#app/data/pokemon-species";
import { Gender } from "#app/data/gender";
import { Type } from "#app/data/type";
import { BattlerIndex } from "#app/battle";
import { PokemonMove } from "#app/field/pokemon";
import { Moves } from "#enums/moves";
import { initMoveAnim } from "#app/data/battle-anims";
import { WeatherType } from "#app/data/weather";
/** the i18n namespace for the encounter */
const namespace = "mysteryEncounter:fiery_fallout";
export const FieryFalloutEncounter: IMysteryEncounter =
MysteryEncounterBuilder.withEncounterType(
MysteryEncounterType.FIERY_FALLOUT
)
.withEncounterTier(MysteryEncounterTier.COMMON)
.withSceneWaveRangeRequirement(40, 180) // waves 10 to 180
.withCatchAllowed(true)
.withIntroSpriteConfigs([]) // Set in onInit()
.withIntroDialogue([
{
text: `${namespace}_intro_message`,
},
])
.withOnInit((scene: BattleScene) => {
const encounter = scene.currentBattle.mysteryEncounter;
// Calculate boss mon
const volcaronaSpecies = getPokemonSpecies(Species.VOLCARONA);
const config: EnemyPartyConfig = {
levelAdditiveMultiplier: 0.25,
pokemonConfigs: [
{
species: volcaronaSpecies,
isBoss: false,
gender: Gender.MALE
},
{
species: volcaronaSpecies,
isBoss: false,
gender: Gender.FEMALE
}
],
doubleBattle: true,
disableSwitch: true
};
encounter.enemyPartyConfigs = [config];
const spriteKey = volcaronaSpecies.getSpriteId(false, null, false, null);
encounter.spriteConfigs = [
{
spriteKey: spriteKey,
fileRoot: "pokemon",
tint: 0.9,
repeat: true
}
];
// Sets weather for 5 turns
scene.arena.trySetWeather(WeatherType.SUNNY, true);
return true;
})
.withTitle(`${namespace}_title`)
.withDescription(`${namespace}_description`)
.withQuery(`${namespace}_query`)
.withSimpleOption(
{
buttonLabel: `${namespace}_option_1_label`,
buttonTooltip: `${namespace}_option_1_tooltip`,
selected: [
{
text: `${namespace}_option_1_selected`,
},
],
},
async (scene: BattleScene) => {
// Pick battle
const encounter = scene.currentBattle.mysteryEncounter;
// TODO: play heat wave animation for weather effect
// await initMoveAnim(scene, Moves.HEAT_WAVE);
// await loadMoveAnimAssets(scene, [ Moves.HEAT_WAVE ], true);
// const heatWave = new MoveAnim(Moves.HEAT_WAVE, scene.getPlayerPokemon(), 0);
// heatWave.play(scene);
await initMoveAnim(scene, Moves.QUIVER_DANCE);
await initMoveAnim(scene, Moves.FIRE_SPIN);
await initMoveAnim(scene, Moves.HEAT_WAVE);
const charcoal = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]);
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [charcoal], fillRemaining: true });
encounter.startOfBattleEffects.push(
{
sourceBattlerIndex: BattlerIndex.ENEMY,
targets: [BattlerIndex.PLAYER, BattlerIndex.PLAYER_2],
move: new PokemonMove(Moves.HEAT_WAVE),
ignorePp: true
},
{
sourceBattlerIndex: BattlerIndex.ENEMY,
targets: [BattlerIndex.ENEMY],
move: new PokemonMove(Moves.QUIVER_DANCE),
ignorePp: true
},
{
sourceBattlerIndex: BattlerIndex.ENEMY_2,
targets: [BattlerIndex.ENEMY_2],
move: new PokemonMove(Moves.QUIVER_DANCE),
ignorePp: true
},
{
sourceBattlerIndex: BattlerIndex.ENEMY,
targets: [BattlerIndex.PLAYER],
move: new PokemonMove(Moves.FIRE_SPIN),
ignorePp: true
},
{
sourceBattlerIndex: BattlerIndex.ENEMY_2,
targets: [BattlerIndex.PLAYER_2],
move: new PokemonMove(Moves.FIRE_SPIN),
ignorePp: true
});
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0]);
}
)
.withSimpleOption(
{
buttonLabel: `${namespace}_option_2_label`,
buttonTooltip: `${namespace}_option_2_tooltip`,
selected: [
{
text: `${namespace}_option_2_selected`,
},
],
},
async (scene: BattleScene) => {
// Damage party and burn 1 random member
// No rewards
leaveEncounterWithoutBattle(scene);
}
)
.withOption(
new MysteryEncounterOptionBuilder()
.withOptionMode(EncounterOptionMode.DISABLED_OR_SPECIAL)
.withPrimaryPokemonRequirement(new TypeRequirement(Type.FIRE, 2)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
.withDialogue({
buttonLabel: `${namespace}_option_3_label`,
buttonTooltip: `${namespace}_option_3_tooltip`,
selected: [
{
text: `${namespace}_option_3_selected`,
},
],
})
.withOptionPhase(async (scene: BattleScene) => {
// Fire types help calm the Volcarona
// const encounter = scene.currentBattle.mysteryEncounter;
const charcoal = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]);
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [charcoal], fillRemaining: true });
setEncounterExp(scene, scene.getParty().map(p => p.id), 500);
leaveEncounterWithoutBattle(scene);
})
.build()
)
.build();

View File

@ -304,14 +304,14 @@ async function throwBait(scene: BattleScene, pokemon: EnemyPokemon): Promise<boo
bait.setOrigin(0.5, 0.625);
scene.field.add(bait);
scene.playSound("pb_throw");
return new Promise(resolve => {
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
scene.time.delayedCall(512, () => {
scene.playSound("pb_throw");
// Trainer throw frames
scene.trainer.setFrame("2");
scene.time.delayedCall(256, () => {
scene.time.delayedCall(184, () => {
scene.trainer.setFrame("3");
scene.time.delayedCall(768, () => {
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`);
@ -366,18 +366,18 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise<bool
const originalY: number = pokemon.y;
const fpOffset = pokemon.getFieldPositionOffset();
const mud: Phaser.GameObjects.Sprite = scene.addFieldSprite(16 + 75, 80 + 25, "mud", "0001.png");
const mud: Phaser.GameObjects.Sprite = scene.addFieldSprite(16 + 75, 80 + 35, "mud", "0001.png");
mud.setOrigin(0.5, 0.625);
scene.field.add(mud);
scene.playSound("pb_throw");
return new Promise(resolve => {
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
scene.time.delayedCall(512, () => {
scene.playSound("pb_throw");
// Trainer throw frames
scene.trainer.setFrame("2");
scene.time.delayedCall(256, () => {
scene.time.delayedCall(184, () => {
scene.trainer.setFrame("3");
scene.time.delayedCall(768, () => {
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`);
@ -395,32 +395,39 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise<bool
scene.playSound("PRSFX- Sludge Bomb2");
mud.setFrame("0002.png");
// Mud splat
scene.time.delayedCall(512, () => {
scene.time.delayedCall(200, () => {
mud.setFrame("0003.png");
scene.time.delayedCall(512, () => {
scene.time.delayedCall(400, () => {
mud.setFrame("0004.png");
});
});
scene.time.delayedCall(1536, () => {
mud.destroy();
scene.tweens.add({
targets: pokemon,
duration: 300,
ease: "Cubic.easeOut",
yoyo: true,
y: originalY - 20,
loop: 1,
onStart: () => {
scene.playSound("PRSFX- Taunt2");
},
onLoop: () => {
scene.playSound("PRSFX- Taunt2");
},
onComplete: () => {
resolve(true);
}
});
// Fade mud then angry animation
scene.tweens.add({
targets: mud,
alpha: 0,
ease: "Cubic.easeIn",
duration: 1000,
onComplete: () => {
mud.destroy();
scene.tweens.add({
targets: pokemon,
duration: 300,
ease: "Cubic.easeOut",
yoyo: true,
y: originalY - 20,
loop: 1,
onStart: () => {
scene.playSound("PRSFX- Taunt2");
},
onLoop: () => {
scene.playSound("PRSFX- Taunt2");
},
onComplete: () => {
resolve(true);
}
});
}
});
}
});

View File

@ -1,5 +1,5 @@
import { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { isNullOrUndefined } from "#app/utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "../../battle-scene";
@ -18,6 +18,7 @@ import {
StatusEffectRequirement,
WaveRangeRequirement
} from "./mystery-encounter-requirements";
import { BattlerIndex } from "#app/battle";
export enum MysteryEncounterVariant {
DEFAULT,
@ -36,6 +37,15 @@ export enum MysteryEncounterTier {
MASTER // Not currently used
}
export class StartOfBattleEffect {
sourcePokemon?: Pokemon;
sourceBattlerIndex?: BattlerIndex;
targets: BattlerIndex[];
move: PokemonMove;
followUp?: boolean;
ignorePp?: boolean;
}
export default interface IMysteryEncounter {
/**
* Required params
@ -90,6 +100,15 @@ export default interface IMysteryEncounter {
* You probably shouldn't do anything with this unless you have a very specific need
*/
introVisuals?: MysteryEncounterIntroVisuals;
/**
* Used for keeping RNG consistent on session resets, but increments when cycling through multiple "Encounters" on the same wave
* You should never need to modify this
*/
seedOffset?: any;
/**
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
*/
startOfBattleEffectsComplete?: boolean;
/**
* Flags
@ -116,16 +135,15 @@ export default interface IMysteryEncounter {
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
*/
selectedOption?: MysteryEncounterOption;
/**
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
*/
startOfBattleEffects?: StartOfBattleEffect[];
/**
* Can be set higher or lower based on the type of battle or exp gained for an option/encounter
* Defaults to 1
*/
expMultiplier?: number;
/**
* Used for keeping RNG consistent on session resets, but increments when cycling through multiple "Encounters" on the same wave
* You should never need to modify this
*/
seedOffset?: any;
/**
* Generic property to set any custom data required for the encounter
* Extremely useful for carrying state/data between onPreOptionPhase/onOptionPhase/onPostOptionPhase
@ -151,8 +169,10 @@ export default class IMysteryEncounter implements IMysteryEncounter {
this.requirements = this.requirements ? this.requirements : [];
this.hideBattleIntroMessage = !isNullOrUndefined(this.hideBattleIntroMessage) ? this.hideBattleIntroMessage : false;
this.hideIntroVisuals = !isNullOrUndefined(this.hideIntroVisuals) ? this.hideIntroVisuals : true;
this.startOfBattleEffects = this.startOfBattleEffects ?? [];
// Reset any dirty flags or encounter data
this.startOfBattleEffectsComplete = false;
this.lockEncounterRewardTiers = true;
this.dialogueTokens = {};
this.enemyPartyConfigs = [];

View File

@ -11,6 +11,7 @@ import { DepartmentStoreSaleEncounter } from "./encounters/department-store-sale
import { ShadyVitaminDealerEncounter } from "./encounters/shady-vitamin-dealer-encounter";
import { FieldTripEncounter } from "./encounters/field-trip-encounter";
import { SafariZoneEncounter } from "#app/data/mystery-encounters/encounters/safari-zone-encounter";
import { FieryFalloutEncounter } from "#app/data/mystery-encounters/encounters/fiery-fallout-encounter";
// Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / 256
export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1;
@ -184,7 +185,9 @@ export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
[Biome.ICE_CAVE, []],
[Biome.MEADOW, []],
[Biome.POWER_PLANT, []],
[Biome.VOLCANO, []],
[Biome.VOLCANO, [
MysteryEncounterType.FIERY_FALLOUT
]],
[Biome.GRAVEYARD, []],
[Biome.DOJO, []],
[Biome.FACTORY, []],
@ -215,6 +218,7 @@ export function initMysteryEncounters() {
allMysteryEncounters[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerEncounter;
allMysteryEncounters[MysteryEncounterType.FIELD_TRIP] = FieldTripEncounter;
allMysteryEncounters[MysteryEncounterType.SAFARI_ZONE] = SafariZoneEncounter;
allMysteryEncounters[MysteryEncounterType.FIERY_FALLOUT] = FieryFalloutEncounter;
// Add extreme encounters to biome map
extremeBiomeEncounters.forEach(encounter => {

View File

@ -1,5 +1,5 @@
import i18next from "i18next";
import { BattleType } from "#app/battle";
import { BattlerIndex, BattleType } from "#app/battle";
import BattleScene from "../../../battle-scene";
import PokemonSpecies from "../../pokemon-species";
import { MysteryEncounterVariant } from "../mystery-encounter";
@ -9,7 +9,7 @@ import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon";
import Trainer, { TrainerVariant } from "../../../field/trainer";
import { ExpBalanceModifier, ExpShareModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "#app/modifier/modifier";
import { CustomModifierSettings, getModifierPoolForType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, PokemonHeldItemModifierType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
import { BattleEndPhase, EggLapsePhase, ExpPhase, ModifierRewardPhase, SelectModifierPhase, ShowPartyExpBarPhase, TrainerVictoryPhase } from "#app/phases";
import { BattleEndPhase, EggLapsePhase, ExpPhase, ModifierRewardPhase, MovePhase, SelectModifierPhase, ShowPartyExpBarPhase, TrainerVictoryPhase } from "#app/phases";
import { MysteryEncounterBattlePhase, MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phase";
import * as Utils from "../../../utils";
import { isNullOrUndefined } from "#app/utils";
@ -25,6 +25,7 @@ import { WIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/myst
import * as Overrides from "#app/overrides";
import MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { Gender } from "#app/data/gender";
export class EnemyPokemonConfig {
species: PokemonSpecies;
@ -33,6 +34,7 @@ export class EnemyPokemonConfig {
bossSegmentModifier?: number; // Additive to the determined segment number
formIndex?: number;
level?: number;
gender?: Gender;
modifierTypes?: PokemonHeldItemModifierType[];
dataSource?: PokemonData;
tags?: BattlerTagType[];
@ -48,6 +50,7 @@ export class EnemyPartyConfig {
trainerConfig?: TrainerConfig; // More customizable option for configuring trainer battle
pokemonConfigs?: EnemyPokemonConfig[];
female?: boolean; // True for female trainer, false for male
disableSwitch?: boolean; // True will prevent player from switching
}
/**
@ -161,6 +164,11 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
enemyPokemon.formIndex = config.formIndex;
}
// Set gender
if (!isNullOrUndefined(config.gender)) {
enemyPokemon.gender = config.gender;
}
// Set Boss
if (config.isBoss) {
let segments = !isNullOrUndefined(config.bossSegments) ? config.bossSegments : scene.getEncounterBossSegments(scene.currentBattle.waveIndex, level, enemySpecies, true);
@ -201,7 +209,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
console.log(enemyPokemon.name, enemyPokemon.species.speciesId, enemyPokemon.stats);
});
scene.pushPhase(new MysteryEncounterBattlePhase(scene));
scene.pushPhase(new MysteryEncounterBattlePhase(scene, partyConfig.disableSwitch));
await Promise.all(loadEnemyAssets);
battle.enemyParty.forEach((enemyPokemon_2, e_1) => {
@ -562,6 +570,36 @@ export function hideMysteryEncounterIntroVisuals(scene: BattleScene): Promise<bo
});
}
export function handleEncounterStartOfBattleEffects(scene: BattleScene) {
const encounter = scene.currentBattle?.mysteryEncounter;
if (scene.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER && encounter.encounterVariant !== MysteryEncounterVariant.NO_BATTLE && !encounter.startOfBattleEffectsComplete) {
const effects = encounter.startOfBattleEffects;
effects.forEach(effect => {
let source;
if (effect.sourcePokemon) {
source = effect.sourcePokemon;
} else if (!isNullOrUndefined(effect.sourceBattlerIndex)) {
if (effect.sourceBattlerIndex === BattlerIndex.ATTACKER) {
source = scene.getEnemyField()[0];
} else if (effect.sourceBattlerIndex === BattlerIndex.ENEMY) {
source = scene.getEnemyField()[0];
} else if (effect.sourceBattlerIndex === BattlerIndex.ENEMY_2) {
source = scene.getEnemyField()[1];
} else if (effect.sourceBattlerIndex === BattlerIndex.PLAYER) {
source = scene.getPlayerField()[0];
} else if (effect.sourceBattlerIndex === BattlerIndex.PLAYER_2) {
source = scene.getPlayerField()[1];
}
} else {
source = scene.getEnemyField()[0];
}
scene.pushPhase(new MovePhase(scene, source, effect.targets, effect.move, effect.followUp, effect.followUp));
});
encounter.startOfBattleEffectsComplete = true;
}
}
/**
* TODO: remove once encounter spawn rate is finalized
* Just a helper function to calculate aggregate stats for MEs in a Classic run

View File

@ -167,7 +167,6 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
pokeball.setOrigin(0.5, 0.625);
scene.field.add(pokeball);
scene.playSound("pb_throw");
scene.time.delayedCall(300, () => {
scene.field.moveBelow(pokeball as Phaser.GameObjects.GameObject, pokemon);
});
@ -175,6 +174,8 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
return new Promise(resolve => {
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
scene.time.delayedCall(512, () => {
scene.playSound("pb_throw");
// Trainer throw frames
scene.trainer.setFrame("2");
scene.time.delayedCall(256, () => {

View File

@ -8,5 +8,6 @@ export enum MysteryEncounterType {
DEPARTMENT_STORE_SALE,
SHADY_VITAMIN_DEALER,
FIELD_TRIP,
SAFARI_ZONE
SAFARI_ZONE,
FIERY_FALLOUT
}

View File

@ -172,6 +172,26 @@ export const mysteryEncounter: SimpleTranslationEntries = {
"safari_zone_pokemon_beside_itself_angry": "{{pokemonName}} is beside itself with anger!",
"safari_zone_remaining_count": "{{remainingCount}} Pokémon remaining!",
"fiery_fallout_intro_message": "You encounter a blistering storm of smoke and ash!",
"fiery_fallout_title": "Fiery Fallout",
"fiery_fallout_description": "The whirling storm of ash and embers has cut visibility to nearly zero. It seems like there might be some... source that is causing these conditions. But what could be behind a phenomenon of this magnitude?",
"fiery_fallout_query": "What will you do?",
"fiery_fallout_option_1_label": "Find the source",
"fiery_fallout_option_1_tooltip": "(?) Discover the source\n(-) Hard Battle",
"fiery_fallout_option_2_label": "Hunker down",
"fiery_fallout_option_2_tooltip": "(-) Suffer the effects of the weather",
"fiery_fallout_option_3_label": "Your Fire types help",
"fiery_fallout_option_3_tooltip": "(+) End the conditions\n(+) Gain a Charcoal",
"fiery_fallout_option_3_disabled_tooltip": "You need at least 2 Fire Type Pokémon to choose this",
"fiery_fallout_option_1_selected": `You push through the storm, and find two Volcarona in the middle of a mating dance!
$They don't take kindly to the interruption and attack!`,
"fiery_fallout_option_2_selected": `The weather effects cause significant harm as you struggle to find shelter!
$Your party takes 30% Max HP damage!
$Your {burnTarget} also becomes burned!`,
// "fiery_fallout_boss_enraged": "The opposing {{enemyPokemon}} has become enraged!",
"fiery_fallout_option_3_selected": `Your {{primaryPokemonName}} and {{secondaryPokemonName}} guide you to where two Volcarona are in the middle of a mating dance!
$Thankfully, your Pokémon are able to calm them, and they depart without issue.`,
// Mystery Encounters -- Ultra Tier
"training_session_intro_message": "You've come across some\ntraining tools and supplies.",

View File

@ -117,9 +117,9 @@ export const EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0;
*/
// 1 to 256, set to null to ignore
export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = null;
export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 256;
export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null;
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null;
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.FIERY_FALLOUT;
/**
* MODIFIER / ITEM OVERRIDES

View File

@ -1,15 +1,16 @@
import BattleScene, { bypassLogin } from "./battle-scene";
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon";
import { DamageResult, default as Pokemon, EnemyPokemon, FieldPosition, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "./field/pokemon";
import * as Utils from "./utils";
import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr, IncrementMovePriorityAttr } from "./data/move";
import { isNullOrUndefined } from "./utils";
import { allMoves, applyFilteredMoveAttrs, applyMoveAttrs, AttackMove, BypassRedirectAttr, BypassSleepAttr, ChargeAttr, CopyMoveAttr, FixedDamageAttr, ForceSwitchOutAttr, getMoveTargets, HealStatusEffectAttr, HitsTagAttr, IgnoreOpponentStatChangesAttr, IncrementMovePriorityAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveEffectTrigger, MoveFlags, MoveTarget, MoveTargetSet, MultiHitAttr, NoEffectAttr, OneHitKOAccuracyAttr, OverrideMoveEffectAttr, PostVictoryStatChangeAttr, PreMoveMessageAttr, SelfStatusMove, VariableAccuracyAttr, VariableTargetAttr } from "./data/move";
import { Mode } from "./ui/ui";
import { Command } from "./ui/command-ui-handler";
import { Stat } from "./data/pokemon-stat";
import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier, overrideModifiers, overrideHeldItems, BypassSpeedChanceModifier, TurnStatusEffectModifier } from "./modifier/modifier";
import { BerryModifier, BypassSpeedChanceModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, IvScannerModifier, LapsingPersistentModifier, LapsingPokemonHeldItemModifier, MapModifier, Modifier, MoneyInterestModifier, MoneyMultiplierModifier, MultipleParticipantExpBonusModifier, overrideHeldItems, overrideModifiers, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, TurnStatusEffectModifier } from "./modifier/modifier";
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims";
import { StatusEffect, getStatusEffectActivationText, getStatusEffectCatchRateMultiplier, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText } from "./data/status-effect";
import { CommonAnim, CommonBattleAnim, initMoveAnim, loadMoveAnimAssets, MoveAnim } from "./data/battle-anims";
import { getStatusEffectActivationText, getStatusEffectCatchRateMultiplier, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText, StatusEffect } from "./data/status-effect";
import { SummaryUiMode } from "./ui/summary-ui-handler";
import EvolutionSceneHandler from "./ui/evolution-scene-handler";
import { EvolutionPhase } from "./evolution-phase";
@ -17,21 +18,21 @@ import { Phase } from "./phase";
import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat";
import { biomeLinks, getBiomeName } from "./data/biomes";
import { ModifierTier } from "./modifier/modifier-tier";
import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds, CustomModifierSettings } from "./modifier/modifier-type";
import { CustomModifierSettings, FusePokemonModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, modifierTypes, PokemonModifierType, PokemonMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, regenerateModifierPoolThresholds, RememberMoveModifierType, TmModifierType } from "./modifier/modifier-type";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import { BattlerTagLapseType, CenterOfAttentionTag, EncoreTag, ProtectedTag, SemiInvulnerableTag, TrappedTag, MysteryEncounterPostSummonTag } from "./data/battler-tags";
import { BattlerTagLapseType, CenterOfAttentionTag, EncoreTag, MysteryEncounterPostSummonTag, ProtectedTag, SemiInvulnerableTag, TrappedTag } from "./data/battler-tags";
import { getPokemonMessage, getPokemonNameWithAffix } from "./messages";
import { Starter } from "./ui/starter-select-ui-handler";
import { Gender } from "./data/gender";
import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather";
import { getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage, Weather, WeatherType } from "./data/weather";
import { TempBattleStat } from "./data/temp-battle-stat";
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, WonderSkinAbAttr, applyPreDefendAbAttrs, IgnoreMoveEffectsAbAttr, BlockStatusDamageAbAttr, BypassSpeedChanceAbAttr, AddSecondStrikeAbAttr } from "./data/ability";
import { Unlockables, getUnlockableName } from "./system/unlockables";
import { getBiomeKey } from "./field/arena";
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
import { ChallengeAchv, HealAchv, LevelAchv, achvs } from "./system/achv";
import { TrainerSlot, trainerConfigs } from "./data/trainer-config";
import { BattlerIndex, BattleType, TurnCommand } from "./battle";
import { achvs, ChallengeAchv, HealAchv, LevelAchv } from "./system/achv";
import { trainerConfigs, TrainerSlot } from "./data/trainer-config";
import { EggHatchPhase } from "./egg-hatch-phase";
import { Egg } from "./data/egg";
import { vouchers } from "./system/voucher";
@ -41,7 +42,7 @@ import { addPokeballCaptureStars, addPokeballOpenParticles } from "./field/anims
import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger } from "./data/pokemon-forms";
import { battleSpecDialogue, getCharVariantFromDialogue, miscDialogue } from "./data/dialogue";
import { SettingKeys } from "./system/settings/settings";
import { Tutorial, handleTutorial } from "./tutorial";
import { handleTutorial, Tutorial } from "./tutorial";
import { TerrainType } from "./data/terrain";
import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select-ui-handler";
import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler";
@ -50,7 +51,7 @@ import { GameMode, GameModes, getGameMode } from "./game-mode";
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./data/pokemon-species";
import i18next from "./plugins/i18n";
import * as Overrides from "./overrides";
import { TextStyle, addTextObject } from "./ui/text";
import { addTextObject, TextStyle } from "./ui/text";
import { Type } from "./data/type";
import { BerryUsedEvent, EncounterPhaseEvent, MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./events/battle-scene";
import { Abilities } from "#enums/abilities";
@ -66,9 +67,8 @@ import { Species } from "#enums/species";
import { TrainerType } from "#enums/trainer-type";
import { MysteryEncounterVariant } from "#app/data/mystery-encounters/mystery-encounter";
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phase";
import { handleMysteryEncounterVictory } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { handleEncounterStartOfBattleEffects, handleMysteryEncounterVictory } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "#app/ui/modifier-select-ui-handler";
import { isNullOrUndefined } from "./utils";
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
const { t } = i18next;
@ -891,6 +891,11 @@ export class EncounterPhase extends BattlePhase {
if (battle.battleType === BattleType.TRAINER) {
loadEnemyAssets.push(battle.trainer.loadAssets().then(() => battle.trainer.initSprite()));
} else if (battle.battleType === BattleType.MYSTERY_ENCOUNTER) {
// this.scene.getEnemyParty().forEach(p => {
// this.scene.field.remove(p);
// p.destroy();
// });
// this.scene.currentBattle.enemyParty = [];
if (!battle.mysteryEncounter) {
const newEncounter = this.scene.getMysteryEncounter(mysteryEncounter);
battle.mysteryEncounter = newEncounter;
@ -2034,6 +2039,9 @@ export class TurnInitPhase extends FieldPhase {
//this.scene.pushPhase(new MoveAnimTestPhase(this.scene));
this.scene.eventTarget.dispatchEvent(new TurnInitEvent());
// Start of battle effects for Mystery Encounters
handleEncounterStartOfBattleEffects(this.scene);
this.scene.getField().forEach((pokemon, i) => {
if (pokemon?.isActive()) {
if (pokemon.isPlayer()) {

View File

@ -173,8 +173,11 @@ export class MysteryEncounterOptionSelectedPhase extends Phase {
* - Queue the SummonPhases, PostSummonPhases, etc., required to initialize the phase queue for a battle
*/
export class MysteryEncounterBattlePhase extends Phase {
constructor(scene: BattleScene) {
disableSwitch: boolean;
constructor(scene: BattleScene, disableSwitch = false) {
super(scene);
this.disableSwitch = disableSwitch;
}
start() {
@ -219,7 +222,7 @@ export class MysteryEncounterBattlePhase extends Phase {
}
if (!scene.currentBattle.mysteryEncounter.hideBattleIntroMessage) {
scene.ui.showText(this.getBattleMessage(scene), null, () => this.endBattleSetup(scene), 1500);
scene.ui.showText(this.getBattleMessage(scene), null, () => this.endBattleSetup(scene), 500);
} else {
this.endBattleSetup(scene);
}
@ -302,7 +305,7 @@ export class MysteryEncounterBattlePhase extends Phase {
scene.pushPhase(new ToggleDoublePositionPhase(scene, false));
}
if (encounterVariant !== MysteryEncounterVariant.TRAINER_BATTLE && (scene.currentBattle.waveIndex > 1 || !scene.gameMode.isDaily)) {
if (encounterVariant !== MysteryEncounterVariant.TRAINER_BATTLE && !this.disableSwitch) {
const minPartySize = scene.currentBattle.double ? 2 : 1;
if (availablePartyMembers.length > minPartySize) {
scene.pushPhase(new CheckSwitchPhase(scene, 0, scene.currentBattle.double));