update tests, bug fix MEs, and sprite assets

This commit is contained in:
ImperialSympathizer 2024-09-12 20:05:22 -04:00
parent 03ae134174
commit 3531086a67
23 changed files with 170 additions and 86 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1021 B

View File

@ -1,11 +1,11 @@
{ {
"textures": [ "textures": [
{ {
"image": "girawitch.png", "image": "global_trade_system.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": { "size": {
"w": 46, "w": 77,
"h": 76 "h": 78
}, },
"scale": 1, "scale": 1,
"frames": [ "frames": [
@ -14,20 +14,20 @@
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"sourceSize": { "sourceSize": {
"w": 46, "w": 77,
"h": 76 "h": 78
}, },
"spriteSourceSize": { "spriteSourceSize": {
"x": 0, "x": 0,
"y": 0, "y": 0,
"w": 46, "w": 77,
"h": 76 "h": 78
}, },
"frame": { "frame": {
"x": 0, "x": 0,
"y": 0, "y": 0,
"w": 46, "w": 77,
"h": 76 "h": 78
} }
} }
] ]
@ -36,6 +36,6 @@
"meta": { "meta": {
"app": "https://www.codeandweb.com/texturepacker", "app": "https://www.codeandweb.com/texturepacker",
"version": "3.0", "version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:e68bbc186f511d505c53b2beec3c3741:7108795fc29d953a1d3729ad93d70936:1661aeeeb2f0e4561c644aff254770b3$" "smartupdate": "$TexturePacker:SmartUpdate:8a51d7a17b3d8c32f0e5e4a0f15daeb4:6eba29c5345847f735d8b69a05fc49d1:98ad8b8b8d8c4865d7d23ec97b516594$"
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 707 B

View File

@ -1,33 +1,33 @@
{ {
"textures": [ "textures": [
{ {
"image": "gts_placeholder.png", "image": "warehouse_crate.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": { "size": {
"w": 47, "w": 71,
"h": 79 "h": 52
}, },
"scale": 1, "scale": 1,
"frames": [ "frames": [
{ {
"filename": "0000.png", "filename": "0001.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
"w": 80, "w": 80,
"h": 80 "h": 56
}, },
"spriteSourceSize": { "spriteSourceSize": {
"x": 17, "x": 5,
"y": 1, "y": 4,
"w": 47, "w": 71,
"h": 79 "h": 52
}, },
"frame": { "frame": {
"x": 0, "x": 0,
"y": 0, "y": 0,
"w": 47, "w": 71,
"h": 79 "h": 52
} }
} }
] ]
@ -36,6 +36,6 @@
"meta": { "meta": {
"app": "https://www.codeandweb.com/texturepacker", "app": "https://www.codeandweb.com/texturepacker",
"version": "3.0", "version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:4e95cf5cd2b0329629c40dfe871e5ae0:cf1cd6aef867fcde2439177ebb561178:39ec800be807afcf5dd13b9cc59fc386$" "smartupdate": "$TexturePacker:SmartUpdate:c8df5f0b35fb9c2a69b0e4aaa9fa9f91:f1d4643c26f2aed86ad77d354e669aaf:0c073e3c2048ea0779db9429e5e1d8bc$"
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "weird_dream_woman.png",
"format": "RGBA8888",
"size": {
"w": 78,
"h": 87
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 80,
"h": 87
},
"spriteSourceSize": {
"x": 1,
"y": 0,
"w": 78,
"h": 87
},
"frame": {
"x": 0,
"y": 0,
"w": 78,
"h": 87
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:d3cce87ee0e3a880d840bffe9373d5d4:7c776d33b75abad1fe36b14a5e5734af:56468b7a2883e66dadcd2af13ebd8010$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1170,8 +1170,7 @@ export default class BattleScene extends SceneBase {
// Check for mystery encounter // Check for mystery encounter
// Can only occur in place of a standard (non-boss) wild battle, waves 10-180 // Can only occur in place of a standard (non-boss) wild battle, waves 10-180
const highestMysteryEncounterWave = this.gameMode.maxMysteryEncounterWave; const [lowestMysteryEncounterWave, highestMysteryEncounterWave] = this.gameMode.getMysteryEncounterLegalWaves();
const lowestMysteryEncounterWave = this.gameMode.minMysteryEncounterWave;
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(newWaveIndex) && newWaveIndex < highestMysteryEncounterWave && newWaveIndex > lowestMysteryEncounterWave) { if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(newWaveIndex) && newWaveIndex < highestMysteryEncounterWave && newWaveIndex > lowestMysteryEncounterWave) {
const roll = Utils.randSeedInt(MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT); const roll = Utils.randSeedInt(MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT);
@ -2923,6 +2922,7 @@ export default class BattleScene extends SceneBase {
} }
} }
console.log("shiftPhase from initFinalBossPhaseTwo");
this.shiftPhase(); this.shiftPhase();
}); });
return; return;
@ -3104,6 +3104,10 @@ export default class BattleScene extends SceneBase {
if (encounterCandidate.encounterTier !== tier) { // Encounter is in tier if (encounterCandidate.encounterTier !== tier) { // Encounter is in tier
return false; return false;
} }
const disabledModes = encounterCandidate.disabledGameModes;
if (disabledModes && disabledModes.length > 0 && disabledModes.includes(this.gameMode.modeId)) { // Encounter is enabled for game mode
return false;
}
if (!encounterCandidate.meetsRequirements!(this)) { // Meets encounter requirements if (!encounterCandidate.meetsRequirements!(this)) { // Meets encounter requirements
return false; return false;
} }

View File

@ -266,7 +266,7 @@ async function tryGiveBerry(scene: BattleScene, prioritizedPokemon?: PlayerPokem
if (!heldBerriesOfType || heldBerriesOfType.getStackCount() < heldBerriesOfType.getMaxStackCount(scene)) { if (!heldBerriesOfType || heldBerriesOfType.getStackCount() < heldBerriesOfType.getMaxStackCount(scene)) {
await applyModifierTypeToPlayerPokemon(scene, pokemon, berry); await applyModifierTypeToPlayerPokemon(scene, pokemon, berry);
break; return;
} }
} }
} }

View File

@ -424,7 +424,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
scene.updateModifiers(true, true); scene.updateModifiers(true, true);
const bugNet = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!; const bugNet = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!;
bugNet.type.tier = ModifierTier.MASTER; bugNet.type.tier = ModifierTier.ROGUE;
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [bugNet], guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED], fillRemaining: false }); setEncounterRewards(scene, { guaranteedModifierTypeOptions: [bugNet], guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED], fillRemaining: false });
leaveEncounterWithoutBattle(scene, true); leaveEncounterWithoutBattle(scene, true);

View File

@ -29,6 +29,7 @@ import { Moves } from "#enums/moves";
import { EncounterAnim, EncounterBattleAnim } from "#app/data/battle-anims"; import { EncounterAnim, EncounterBattleAnim } from "#app/data/battle-anims";
import { MoveCategory } from "#app/data/move"; import { MoveCategory } from "#app/data/move";
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
import { GameModes } from "#app/game-mode";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */
const namespace = "mysteryEncounter:clowningAround"; const namespace = "mysteryEncounter:clowningAround";
@ -59,6 +60,7 @@ const RANDOM_ABILITY_POOL = [
export const ClowningAroundEncounter: MysteryEncounter = export const ClowningAroundEncounter: MysteryEncounter =
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.CLOWNING_AROUND) MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.CLOWNING_AROUND)
.withEncounterTier(MysteryEncounterTier.ULTRA) .withEncounterTier(MysteryEncounterTier.ULTRA)
.withDisabledGameModes(GameModes.CHALLENGE)
.withSceneWaveRangeRequirement(80, 180) .withSceneWaveRangeRequirement(80, 180)
.withAnimations(EncounterAnim.SMOKESCREEN) .withAnimations(EncounterAnim.SMOKESCREEN)
.withAutoHideIntroVisuals(false) .withAutoHideIntroVisuals(false)

View File

@ -19,7 +19,7 @@ import PokemonData from "#app/system/pokemon-data";
import i18next from "i18next"; import i18next from "i18next";
import { Gender, getGenderSymbol } from "#app/data/gender"; import { Gender, getGenderSymbol } from "#app/data/gender";
import { getNatureName } from "#app/data/nature"; import { getNatureName } from "#app/data/nature";
import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball"; import { getPokeballAtlasKey, getPokeballTintColor, PokeballType } from "#app/data/pokeball";
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { trainerNamePools } from "#app/data/trainer-names"; import { trainerNamePools } from "#app/data/trainer-names";
@ -74,10 +74,13 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
.withAutoHideIntroVisuals(false) .withAutoHideIntroVisuals(false)
.withIntroSpriteConfigs([ .withIntroSpriteConfigs([
{ {
spriteKey: "gts_placeholder", spriteKey: "global_trade_system",
fileRoot: "mystery-encounters", fileRoot: "mystery-encounters",
hasShadow: false, hasShadow: true,
disableAnimation: true disableAnimation: true,
x: 3,
y: 5,
yShadow: 1
} }
]) ])
.withIntroDialogue([ .withIntroDialogue([
@ -92,11 +95,14 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
const encounter = scene.currentBattle.mysteryEncounter!; const encounter = scene.currentBattle.mysteryEncounter!;
// Load bgm // Load bgm
let bgmKey: string;
if (scene.musicPreference === 0) { if (scene.musicPreference === 0) {
scene.loadBgm("mystery_encounter_gen_5_gts", "mystery_encounter_gen_5_gts.mp3"); bgmKey = "mystery_encounter_gen_5_gts";
scene.loadBgm(bgmKey, `${bgmKey}.mp3`);
} else { } else {
// Mixed option // Mixed option
scene.loadBgm("mystery_encounter_gen_6_gts", "mystery_encounter_gen_6_gts.mp3"); bgmKey = "mystery_encounter_gen_6_gts";
scene.loadBgm(bgmKey, `${bgmKey}.mp3`);
} }
// Load possible trade options // Load possible trade options
@ -104,7 +110,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
// None of the trade options can be the same species // None of the trade options can be the same species
const tradeOptionsMap: Map<number, EnemyPokemon[]> = getPokemonTradeOptions(scene); const tradeOptionsMap: Map<number, EnemyPokemon[]> = getPokemonTradeOptions(scene);
encounter.misc = { encounter.misc = {
tradeOptionsMap tradeOptionsMap,
bgmKey
}; };
return true; return true;
@ -113,11 +120,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
// Change the bgm // Change the bgm
scene.fadeOutBgm(1500, false); scene.fadeOutBgm(1500, false);
scene.time.delayedCall(1500, () => { scene.time.delayedCall(1500, () => {
if (scene.musicPreference === 0) { scene.playBgm(scene.currentBattle.mysteryEncounter!.misc.bgmKey);
scene.playBgm("mystery_encounter_gen_5_gts");
} else {
scene.playBgm("mystery_encounter_gen_6_gts");
}
}); });
return true; return true;
@ -147,17 +150,15 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
// Pokemon trade selected // Pokemon trade selected
encounter.setDialogueToken("tradedPokemon", pokemon.getNameToRender()); encounter.setDialogueToken("tradedPokemon", pokemon.getNameToRender());
encounter.setDialogueToken("received", tradePokemon.getNameToRender()); encounter.setDialogueToken("received", tradePokemon.getNameToRender());
encounter.misc = { encounter.misc.tradedPokemon = pokemon;
tradedPokemon: pokemon, encounter.misc.receivedPokemon = tradePokemon;
receivedPokemon: tradePokemon,
};
return true; return true;
}, },
onHover: () => { onHover: () => {
const formName = tradePokemon.species.forms?.[pokemon.formIndex]?.formName; const formName = tradePokemon.species.forms?.[pokemon.formIndex]?.formName;
const line1 = i18next.t("pokemonInfoContainer:ability") + " " + tradePokemon.getAbility().name + (tradePokemon.getGender() !== Gender.GENDERLESS ? " | " + i18next.t("pokemonInfoContainer:gender") + " " + getGenderSymbol(tradePokemon.getGender()) : ""); const line1 = i18next.t("pokemonInfoContainer:ability") + " " + tradePokemon.getAbility().name + (tradePokemon.getGender() !== Gender.GENDERLESS ? " | " + i18next.t("pokemonInfoContainer:gender") + " " + getGenderSymbol(tradePokemon.getGender()) : "");
const line2 = i18next.t("pokemonInfoContainer:nature") + " " + getNatureName(tradePokemon.getNature()) + (formName ? " | " + i18next.t("pokemonInfoContainer:form") + " " + formName : ""); const line2 = i18next.t("pokemonInfoContainer:nature") + " " + getNatureName(tradePokemon.getNature()) + (formName ? " | " + i18next.t("pokemonInfoContainer:form") + " " + formName : "");
showEncounterText(scene, `${line1}\n${line2}`, 0); showEncounterText(scene, `${line1}\n${line2}`, 0, 0, false);
}, },
}; };
return option; return option;
@ -181,7 +182,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
// Set data properly, then generate the new Pokemon's assets // Set data properly, then generate the new Pokemon's assets
receivedPokemonData.passive = tradedPokemon.passive; receivedPokemonData.passive = tradedPokemon.passive;
receivedPokemonData.pokeball = randSeedInt(5); // Pokeball to Ultra ball, randomly
receivedPokemonData.pokeball = randInt(4) as PokeballType;
const dataSource = new PokemonData(receivedPokemonData); const dataSource = new PokemonData(receivedPokemonData);
const newPlayerPokemon = scene.addPlayerPokemon(receivedPokemonData.species, receivedPokemonData.level, dataSource.abilityIndex, dataSource.formIndex, dataSource.gender, dataSource.shiny, dataSource.variant, dataSource.ivs, dataSource.nature, dataSource); const newPlayerPokemon = scene.addPlayerPokemon(receivedPokemonData.species, receivedPokemonData.level, dataSource.abilityIndex, dataSource.formIndex, dataSource.gender, dataSource.shiny, dataSource.variant, dataSource.ivs, dataSource.nature, dataSource);
scene.getParty().push(newPlayerPokemon); scene.getParty().push(newPlayerPokemon);
@ -196,7 +198,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
await showTradeBackground(scene); await showTradeBackground(scene);
await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon); await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon);
await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000); await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000);
scene.playBgm("mystery_encounter_gts"); scene.playBgm(encounter.misc.bgmKey);
await hideTradeBackground(scene); await hideTradeBackground(scene);
tradedPokemon.destroy(); tradedPokemon.destroy();
@ -241,10 +243,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
encounter.setDialogueToken("tradedPokemon", pokemon.getNameToRender()); encounter.setDialogueToken("tradedPokemon", pokemon.getNameToRender());
encounter.setDialogueToken("received", tradePokemon.getNameToRender()); encounter.setDialogueToken("received", tradePokemon.getNameToRender());
encounter.misc = { encounter.misc.tradedPokemon = pokemon;
tradedPokemon: pokemon, encounter.misc.receivedPokemon = tradePokemon;
receivedPokemon: tradePokemon,
};
}; };
return selectPokemonForOption(scene, onPokemonSelected); return selectPokemonForOption(scene, onPokemonSelected);
@ -264,7 +264,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
// Set data properly, then generate the new Pokemon's assets // Set data properly, then generate the new Pokemon's assets
receivedPokemonData.passive = tradedPokemon.passive; receivedPokemonData.passive = tradedPokemon.passive;
receivedPokemonData.pokeball = randSeedInt(5); receivedPokemonData.pokeball = randInt(4) as PokeballType;
const dataSource = new PokemonData(receivedPokemonData); const dataSource = new PokemonData(receivedPokemonData);
const newPlayerPokemon = scene.addPlayerPokemon(receivedPokemonData.species, receivedPokemonData.level, dataSource.abilityIndex, dataSource.formIndex, dataSource.gender, dataSource.shiny, dataSource.variant, dataSource.ivs, dataSource.nature, dataSource); const newPlayerPokemon = scene.addPlayerPokemon(receivedPokemonData.species, receivedPokemonData.level, dataSource.abilityIndex, dataSource.formIndex, dataSource.gender, dataSource.shiny, dataSource.variant, dataSource.ivs, dataSource.nature, dataSource);
scene.getParty().push(newPlayerPokemon); scene.getParty().push(newPlayerPokemon);
@ -279,7 +279,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
await showTradeBackground(scene); await showTradeBackground(scene);
await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon); await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon);
await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000); await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000);
scene.playBgm("mystery_encounter_gts"); scene.playBgm(scene.currentBattle.mysteryEncounter!.misc.bgmKey);
await hideTradeBackground(scene); await hideTradeBackground(scene);
tradedPokemon.destroy(); tradedPokemon.destroy();
@ -309,9 +309,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
handler: () => { handler: () => {
// Pokemon and item selected // Pokemon and item selected
encounter.setDialogueToken("chosenItem", modifier.type.name); encounter.setDialogueToken("chosenItem", modifier.type.name);
encounter.misc = { encounter.misc.chosenModifier = modifier;
chosenModifier: modifier,
};
return true; return true;
}, },
}; };

View File

@ -25,19 +25,19 @@ export const PartTimerEncounter: MysteryEncounter =
.withEncounterTier(MysteryEncounterTier.COMMON) .withEncounterTier(MysteryEncounterTier.COMMON)
.withSceneWaveRangeRequirement(10, 180) .withSceneWaveRangeRequirement(10, 180)
.withIntroSpriteConfigs([ .withIntroSpriteConfigs([
{
spriteKey: "warehouse_crate",
fileRoot: "mystery-encounters",
hasShadow: false,
y: 6,
x: 15
},
{ {
spriteKey: "worker_f", spriteKey: "worker_f",
fileRoot: "trainer", fileRoot: "trainer",
hasShadow: true, hasShadow: true,
x: -20 x: -18,
}, y: 4
{
spriteKey: "training_gear",
fileRoot: "mystery-encounters",
hasShadow: true,
y: 6,
x: 20,
yShadow: -2
} }
]) ])
.withAutoHideIntroVisuals(false) .withAutoHideIntroVisuals(false)

View File

@ -1,4 +1,4 @@
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, generateModifierType, generateModifierTypeOption, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-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";
@ -21,6 +21,7 @@ import { PartyHealPhase } from "#app/phases/party-heal-phase";
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase"; import { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
import { ReturnPhase } from "#app/phases/return-phase"; import { ReturnPhase } from "#app/phases/return-phase";
import i18next from "i18next"; import i18next from "i18next";
import { ModifierTier } from "#app/modifier/modifier-tier";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */
const namespace = "mysteryEncounter:theWinstrateChallenge"; const namespace = "mysteryEncounter:theWinstrateChallenge";
@ -149,9 +150,12 @@ async function spawnNextTrainerOrEndEncounter(scene: BattleScene) {
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name })); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name }));
await showEncounterDialogue(scene, `${namespace}.victory_2`, `${namespace}.speaker`); await showEncounterDialogue(scene, `${namespace}.victory_2`, `${namespace}.speaker`);
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE], fillRemaining: false }); scene.ui.clearText(); // Clears "Winstrate" title from screen as rewards get animated in
const machoBrace = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE)!;
machoBrace.type.tier = ModifierTier.MASTER;
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [machoBrace], fillRemaining: false });
encounter.doContinueEncounter = undefined; encounter.doContinueEncounter = undefined;
leaveEncounterWithoutBattle(scene, false, MysteryEncounterMode.TRAINER_BATTLE); leaveEncounterWithoutBattle(scene, false, MysteryEncounterMode.NO_BATTLE);
} else { } else {
await initBattleWithEnemyConfig(scene, nextConfig); await initBattleWithEnemyConfig(scene, nextConfig);
} }

View File

@ -305,7 +305,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
return true; return true;
}, },
onHover: () => { onHover: () => {
showEncounterText(scene, ability.description, 0); showEncounterText(scene, ability.description, 0, 0, false);
}, },
}; };
optionSelectItems.push(option); optionSelectItems.push(option);

View File

@ -53,16 +53,15 @@ export const UncommonBreedEncounter: MysteryEncounter =
const species = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true); const species = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
const pokemon = new EnemyPokemon(scene, species, level, TrainerSlot.NONE, true); const pokemon = new EnemyPokemon(scene, species, level, TrainerSlot.NONE, true);
const speciesRootForm = pokemon.species.getRootSpeciesId(); const speciesRootForm = pokemon.species.getRootSpeciesId();
encounter.misc = {
pokemon
};
// Pokemon will always have one of its egg moves in its moveset // Pokemon will always have one of its egg moves in its moveset
if (speciesEggMoves.hasOwnProperty(speciesRootForm)) { if (speciesEggMoves.hasOwnProperty(speciesRootForm)) {
const eggMoves: Moves[] = speciesEggMoves[speciesRootForm]; const eggMoves: Moves[] = speciesEggMoves[speciesRootForm];
const eggMoveIndex = randSeedInt(4); const eggMoveIndex = randSeedInt(4);
const randomEggMove: Moves = eggMoves[eggMoveIndex]; const randomEggMove: Moves = eggMoves[eggMoveIndex];
encounter.misc.eggMove = randomEggMove; encounter.misc = {
eggMove: randomEggMove
};
if (pokemon.moveset.length < 4) { if (pokemon.moveset.length < 4) {
pokemon.moveset.push(new PokemonMove(randomEggMove)); pokemon.moveset.push(new PokemonMove(randomEggMove));
} else { } else {
@ -70,6 +69,8 @@ export const UncommonBreedEncounter: MysteryEncounter =
} }
} }
encounter.misc.pokemon = pokemon;
const config: EnemyPartyConfig = { const config: EnemyPartyConfig = {
pokemonConfigs: [{ pokemonConfigs: [{
level: level, level: level,
@ -184,7 +185,7 @@ export const UncommonBreedEncounter: MysteryEncounter =
berryItems.splice(index, 1); berryItems.splice(index, 1);
} }
} }
scene.updateModifiers(true, true); await scene.updateModifiers(true, true);
// Pokemon joins the team, with 2 egg moves // Pokemon joins the team, with 2 egg moves
const encounter = scene.currentBattle.mysteryEncounter!; const encounter = scene.currentBattle.mysteryEncounter!;

View File

@ -20,6 +20,7 @@ import i18next from "#app/plugins/i18n";
import { doPokemonTransformationSequence, TransformationScreenPosition } from "#app/data/mystery-encounters/utils/encounter-transformation-sequence"; import { doPokemonTransformationSequence, TransformationScreenPosition } from "#app/data/mystery-encounters/utils/encounter-transformation-sequence";
import { getLevelTotalExp } from "#app/data/exp"; import { getLevelTotalExp } from "#app/data/exp";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { GameModes } from "#app/game-mode";
/** i18n namespace for encounter */ /** i18n namespace for encounter */
const namespace = "mysteryEncounter:weirdDream"; const namespace = "mysteryEncounter:weirdDream";
@ -94,13 +95,16 @@ const STANDARD_BST_TRANSFORM_BASE_VALUES = [40, 50];
export const WeirdDreamEncounter: MysteryEncounter = export const WeirdDreamEncounter: MysteryEncounter =
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.WEIRD_DREAM) MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.WEIRD_DREAM)
.withEncounterTier(MysteryEncounterTier.ROGUE) .withEncounterTier(MysteryEncounterTier.ROGUE)
.withDisabledGameModes(GameModes.CHALLENGE)
.withSceneWaveRangeRequirement(10, 180) .withSceneWaveRangeRequirement(10, 180)
.withIntroSpriteConfigs([ .withIntroSpriteConfigs([
{ {
spriteKey: "girawitch", spriteKey: "weird_dream_woman",
fileRoot: "mystery-encounters", fileRoot: "mystery-encounters",
hasShadow: false, hasShadow: true,
y: 4 y: 11,
yShadow: 6,
x: 4
}, },
]) ])
.withIntroDialogue([ .withIntroDialogue([

View File

@ -14,6 +14,7 @@ import { EncounterAnim } from "#app/data/battle-anims";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { GameModes } from "#app/game-mode";
export interface EncounterStartOfBattleEffect { export interface EncounterStartOfBattleEffect {
sourcePokemon?: Pokemon; sourcePokemon?: Pokemon;
@ -36,6 +37,7 @@ export interface IMysteryEncounter {
spriteConfigs: MysteryEncounterSpriteConfig[]; spriteConfigs: MysteryEncounterSpriteConfig[];
encounterTier: MysteryEncounterTier; encounterTier: MysteryEncounterTier;
encounterAnimations?: EncounterAnim[]; encounterAnimations?: EncounterAnim[];
disabledGameModes?: GameModes[];
hideBattleIntroMessage: boolean; hideBattleIntroMessage: boolean;
autoHideIntroVisuals: boolean; autoHideIntroVisuals: boolean;
enterIntroVisualsFromRight: boolean; enterIntroVisualsFromRight: boolean;
@ -85,6 +87,10 @@ export default class MysteryEncounter implements IMysteryEncounter {
* Specify here so that assets are loaded on initialization of encounter * Specify here so that assets are loaded on initialization of encounter
*/ */
encounterAnimations?: EncounterAnim[]; encounterAnimations?: EncounterAnim[];
/**
* If specified, defines any game modes where the MysteryEncounter should *NOT* spawn
*/
disabledGameModes?: GameModes[];
/** /**
* If true, hides "A Wild X Appeared" etc. messages * If true, hides "A Wild X Appeared" etc. messages
* Default true * Default true
@ -630,6 +636,16 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
return Object.assign(this, { encounterAnimations: animations }); return Object.assign(this, { encounterAnimations: animations });
} }
/**
* Defines any game modes where the Mystery Encounter should *NOT* spawn
* @returns
* @param disabledGameModes
*/
withDisabledGameModes(...disabledGameModes: GameModes[]): this & Required<Pick<IMysteryEncounter, "disabledGameModes">> {
const gameModes = Array.isArray(disabledGameModes) ? disabledGameModes : [disabledGameModes];
return Object.assign(this, { disabledGameModes: gameModes });
}
/** /**
* If true, encounter will continuously run through multiple battles/puzzles/etc. instead of going to next wave * If true, encounter will continuously run through multiple battles/puzzles/etc. instead of going to next wave
* MUST EVENTUALLY BE DISABLED TO CONTINUE TO NEXT WAVE * MUST EVENTUALLY BE DISABLED TO CONTINUE TO NEXT WAVE

View File

@ -456,7 +456,7 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
return true; return true;
}, },
onHover: () => { onHover: () => {
showEncounterText(scene, i18next.t("mysteryEncounterMessages:cancel_option"), 0); showEncounterText(scene, i18next.t("mysteryEncounterMessages:cancel_option"), 0, 0, false);
} }
}); });
@ -570,7 +570,7 @@ export function selectOptionThenPokemon(scene: BattleScene, options: OptionSelec
if (onHoverOverCancelOption) { if (onHoverOverCancelOption) {
onHoverOverCancelOption(); onHoverOverCancelOption();
} }
scene.ui.showText(i18next.t("mysteryEncounterMessages:cancel_option")); showEncounterText(scene, i18next.t("mysteryEncounterMessages:cancel_option"), 0, 0, false);
} }
}); });

View File

@ -30,10 +30,12 @@ interface GameModeConfig {
isSplicedOnly?: boolean; isSplicedOnly?: boolean;
isChallenge?: boolean; isChallenge?: boolean;
hasMysteryEncounters?: boolean; hasMysteryEncounters?: boolean;
minMysteryEncounterWave?: number;
maxMysteryEncounterWave?: number;
} }
// Describes min and max waves for MEs in specific game modes
const CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [10, 180];
const CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [10, 180];
export class GameMode implements GameModeConfig { export class GameMode implements GameModeConfig {
public modeId: GameModes; public modeId: GameModes;
public isClassic: boolean; public isClassic: boolean;
@ -60,8 +62,6 @@ export class GameMode implements GameModeConfig {
this.challenges = allChallenges.map(c => copyChallenge(c)); this.challenges = allChallenges.map(c => copyChallenge(c));
} }
this.battleConfig = battleConfig || {}; this.battleConfig = battleConfig || {};
this.minMysteryEncounterWave = this.minMysteryEncounterWave ?? 0;
this.maxMysteryEncounterWave = this.maxMysteryEncounterWave ?? 100000;
} }
/** /**
@ -325,6 +325,17 @@ export class GameMode implements GameModeConfig {
} }
} }
getMysteryEncounterLegalWaves(): [number, number] {
switch (this.modeId) {
default:
return [0, 0];
case GameModes.CLASSIC:
return CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES;
case GameModes.CHALLENGE:
return CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES;
}
}
static getModeName(modeId: GameModes): string { static getModeName(modeId: GameModes): string {
switch (modeId) { switch (modeId) {
case GameModes.CLASSIC: case GameModes.CLASSIC:
@ -344,7 +355,7 @@ export class GameMode implements GameModeConfig {
export function getGameMode(gameMode: GameModes): GameMode { export function getGameMode(gameMode: GameModes): GameMode {
switch (gameMode) { switch (gameMode) {
case GameModes.CLASSIC: case GameModes.CLASSIC:
return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true, maxMysteryEncounterWave: 180, minMysteryEncounterWave: 10 }, classicFixedBattles); return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true }, classicFixedBattles);
case GameModes.ENDLESS: case GameModes.ENDLESS:
return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true }); return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true });
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
@ -352,6 +363,6 @@ export function getGameMode(gameMode: GameModes): GameMode {
case GameModes.DAILY: case GameModes.DAILY:
return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true }); return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true });
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true }, classicFixedBattles); return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true, hasMysteryEncounters: true }, classicFixedBattles);
} }
} }

View File

@ -36,6 +36,7 @@ describe("Berries Abound - Mystery Encounter", () => {
game = new GameManager(phaserGame); game = new GameManager(phaserGame);
scene = game.scene; scene = game.scene;
game.override.mysteryEncounterChance(100); game.override.mysteryEncounterChance(100);
game.override.mysteryEncounterTier(MysteryEncounterTier.COMMON);
game.override.startingWave(defaultWave); game.override.startingWave(defaultWave);
game.override.startingBiome(defaultBiome); game.override.startingBiome(defaultBiome);
game.override.disableTrainerWaves(); game.override.disableTrainerWaves();
@ -132,7 +133,7 @@ describe("Berries Abound - Mystery Encounter", () => {
expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); expect(enemyField[0].species.speciesId).toBe(speciesToSpawn);
}); });
it("should reward the player with X berries based on wave", async () => { it("should reward the player with X berries based on wave", { retry: 5 }, async () => {
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);
const numBerries = game.scene.currentBattle.mysteryEncounter!.misc.numBerries; const numBerries = game.scene.currentBattle.mysteryEncounter!.misc.numBerries;

View File

@ -12,6 +12,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
import { CommandPhase } from "#app/phases/command-phase"; import { CommandPhase } from "#app/phases/command-phase";
import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter"; import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter";
@ -22,7 +23,6 @@ import { BerryType } from "#enums/berry-type";
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 { BerryModifier } from "#app/modifier/modifier"; import { BerryModifier } from "#app/modifier/modifier";
import { generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
const namespace = "mysteryEncounter:uncommonBreed"; const namespace = "mysteryEncounter:uncommonBreed";
@ -43,6 +43,7 @@ describe("Uncommon Breed - Mystery Encounter", () => {
game = new GameManager(phaserGame); game = new GameManager(phaserGame);
scene = game.scene; scene = game.scene;
game.override.mysteryEncounterChance(100); game.override.mysteryEncounterChance(100);
game.override.mysteryEncounterTier(MysteryEncounterTier.COMMON);
game.override.startingWave(defaultWave); game.override.startingWave(defaultWave);
game.override.startingBiome(defaultBiome); game.override.startingBiome(defaultBiome);
game.override.disableTrainerWaves(); game.override.disableTrainerWaves();
@ -166,12 +167,13 @@ describe("Uncommon Breed - Mystery Encounter", () => {
}); });
}); });
it("should NOT be selectable if the player doesn't have enough berries", async () => { it("should NOT be selectable if the player doesn't have enough berries", { retry: 5 }, async () => {
await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty);
// Clear out any pesky mods that slipped through test spin-up // Clear out any pesky mods that slipped through test spin-up
scene.modifiers.forEach(mod => { scene.modifiers.forEach(mod => {
scene.removeModifier(mod); scene.removeModifier(mod);
}); });
await scene.updateModifiers(true);
await game.phaseInterceptor.to(MysteryEncounterPhase, false); await game.phaseInterceptor.to(MysteryEncounterPhase, false);
const encounterPhase = scene.getCurrentPhase(); const encounterPhase = scene.getCurrentPhase();