[Bug] Fix for Expert Breeder's Pokemon being invisible and IV scanner in safari zone (#4661)
* [Bug] Potential fix for Expert Breeder's Pokemon being invisible * PR Feedback * Consistency with await
This commit is contained in:
parent
50ff6e703a
commit
c6ec01958c
|
@ -789,7 +789,7 @@ export default class BattleScene extends SceneBase {
|
|||
}
|
||||
|
||||
getEnemyParty(): EnemyPokemon[] {
|
||||
return this.currentBattle?.enemyParty || [];
|
||||
return this.currentBattle?.enemyParty ?? [];
|
||||
}
|
||||
|
||||
getEnemyPokemon(): EnemyPokemon | undefined {
|
||||
|
|
|
@ -154,7 +154,7 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.epic`));
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SACRED_ASH ], guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ULTRA ], fillRemaining: true }, [ eggOptions ]);
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
|
|
|
@ -286,7 +286,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||
ignorePp: true
|
||||
});
|
||||
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||
})
|
||||
.build()
|
||||
|
@ -328,7 +328,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||
});
|
||||
await scene.updateModifiers(true);
|
||||
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
|
@ -359,7 +359,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||
greedent.moveset = [ new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF) ];
|
||||
greedent.passive = true;
|
||||
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await catchPokemon(scene, greedent, null, PokeballType.POKEBALL, false);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
|
|
|
@ -228,7 +228,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Learn its Dance
|
||||
hideOricorioPokemon(scene);
|
||||
await hideOricorioPokemon(scene);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
|
@ -303,7 +303,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
}
|
||||
}
|
||||
|
||||
hideOricorioPokemon(scene);
|
||||
await hideOricorioPokemon(scene);
|
||||
await catchPokemon(scene, oricorio, null, PokeballType.POKEBALL, false);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
|
|
|
@ -182,7 +182,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
|||
const config: EnemyPartyConfig = {
|
||||
pokemonConfigs: [ pokemonConfig ],
|
||||
};
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
|
|
|
@ -222,12 +222,13 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
|||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Do NOT await this, to prevent player from repeatedly pressing options
|
||||
transitionMysteryEncounterIntroVisuals(scene, false, false, 2000);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Fire types help calm the Volcarona
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
transitionMysteryEncounterIntroVisuals(scene);
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
setEncounterRewards(scene,
|
||||
{ fillRemaining: true },
|
||||
undefined,
|
||||
|
|
|
@ -152,7 +152,7 @@ export const FunAndGamesEncounter: MysteryEncounter =
|
|||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Leave encounter with no rewards or exp
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -399,7 +399,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
|||
if (modifier.stackCount === 0) {
|
||||
scene.removeModifier(modifier);
|
||||
}
|
||||
scene.updateModifiers(true, true);
|
||||
await scene.updateModifiers(true, true);
|
||||
|
||||
// Generate a trainer name
|
||||
const traderName = generateRandomTraderName();
|
||||
|
|
|
@ -129,7 +129,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||
*
|
||||
* @param scene Battle scene
|
||||
*/
|
||||
async function handlePokemonGuidingYouPhase(scene: BattleScene) {
|
||||
function handlePokemonGuidingYouPhase(scene: BattleScene) {
|
||||
const laprasSpecies = getPokemonSpecies(Species.LAPRAS);
|
||||
const { mysteryEncounter } = scene.currentBattle;
|
||||
|
||||
|
|
|
@ -147,11 +147,11 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
|||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
let initBattlePromise: Promise<void>;
|
||||
scene.executeWithSeedOffset(() => {
|
||||
ret = initBattleWithEnemyConfig(scene, config);
|
||||
initBattlePromise = initBattleWithEnemyConfig(scene, config);
|
||||
}, scene.currentBattle.waveIndex * 10);
|
||||
return ret;
|
||||
await initBattlePromise!;
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
|
@ -172,11 +172,11 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
|||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
let initBattlePromise: Promise<void>;
|
||||
scene.executeWithSeedOffset(() => {
|
||||
ret = initBattleWithEnemyConfig(scene, config);
|
||||
initBattlePromise = initBattleWithEnemyConfig(scene, config);
|
||||
}, scene.currentBattle.waveIndex * 100);
|
||||
return ret;
|
||||
await initBattlePromise!;
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
|
@ -200,11 +200,11 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
|||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
let initBattlePromise: Promise<void>;
|
||||
scene.executeWithSeedOffset(() => {
|
||||
ret = initBattleWithEnemyConfig(scene, config);
|
||||
initBattlePromise = initBattleWithEnemyConfig(scene, config);
|
||||
}, scene.currentBattle.waveIndex * 1000);
|
||||
return ret;
|
||||
await initBattlePromise!;
|
||||
}
|
||||
)
|
||||
.withOutroDialogue([
|
||||
|
|
|
@ -184,7 +184,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
|||
scene.unshiftPhase(new GameOverPhase(scene));
|
||||
} else {
|
||||
// Show which Pokemon was KOed, then start battle against Gimmighoul
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||
}
|
||||
|
|
|
@ -303,13 +303,22 @@ async function summonSafariPokemon(scene: BattleScene) {
|
|||
scene.unshiftPhase(new SummonPhase(scene, 0, false));
|
||||
|
||||
encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon));
|
||||
showEncounterText(scene, getEncounterText(scene, "battle:singleWildAppeared") ?? "", null, 1500, false)
|
||||
.then(() => {
|
||||
// TODO: If we await this showEncounterText, then the text will display without
|
||||
// the wild Pokemon on screen, but if we don't await it, then the text never
|
||||
// shows up and the IV scanner breaks. For now, we place the IV scanner code
|
||||
// separately so that at least the IV scanner works.
|
||||
//
|
||||
// showEncounterText(scene, getEncounterText(scene, "battle:singleWildAppeared") ?? "", null, 0, false)
|
||||
// .then(() => {
|
||||
// const ivScannerModifier = scene.findModifier(m => m instanceof IvScannerModifier);
|
||||
// if (ivScannerModifier) {
|
||||
// scene.pushPhase(new ScanIvsPhase(scene, pokemon.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6)));
|
||||
// }
|
||||
// });
|
||||
const ivScannerModifier = scene.findModifier(m => m instanceof IvScannerModifier);
|
||||
if (ivScannerModifier) {
|
||||
scene.pushPhase(new ScanIvsPhase(scene, pokemon.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function throwPokeball(scene: BattleScene, pokemon: EnemyPokemon): Promise<boolean> {
|
||||
|
|
|
@ -142,7 +142,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
||||
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||
chosenPokemon.updateInfo();
|
||||
await chosenPokemon.updateInfo();
|
||||
})
|
||||
.build()
|
||||
)
|
||||
|
@ -204,7 +204,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||
queueEncounterMessage(scene, `${namespace}:no_bad_effects`);
|
||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||
|
||||
chosenPokemon.updateInfo();
|
||||
await chosenPokemon.updateInfo();
|
||||
})
|
||||
.build()
|
||||
)
|
||||
|
|
|
@ -149,7 +149,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
|||
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.STEEL ])!;
|
||||
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.ELECTRIC ])!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ magnet, metalCoat ], fillRemaining: true });
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
)
|
||||
|
|
|
@ -245,7 +245,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
}
|
||||
|
||||
encounter.onGameOver = onGameOver;
|
||||
initBattleWithEnemyConfig(scene, config);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
await doPostEncounterCleanup(scene);
|
||||
|
@ -297,7 +297,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
}
|
||||
|
||||
encounter.onGameOver = onGameOver;
|
||||
initBattleWithEnemyConfig(scene, config);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
await doPostEncounterCleanup(scene);
|
||||
|
@ -349,7 +349,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
}
|
||||
|
||||
encounter.onGameOver = onGameOver;
|
||||
initBattleWithEnemyConfig(scene, config);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
await doPostEncounterCleanup(scene);
|
||||
|
|
|
@ -201,7 +201,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||
});
|
||||
|
||||
encounter.dialogue.outro = [];
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||
}
|
||||
)
|
||||
|
|
|
@ -111,8 +111,8 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter =
|
|||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Spawn 5 trainer battles back to back with Macho Brace in rewards
|
||||
scene.currentBattle.mysteryEncounter!.doContinueEncounter = (scene: BattleScene) => {
|
||||
return endTrainerBattleAndShowDialogue(scene);
|
||||
scene.currentBattle.mysteryEncounter!.doContinueEncounter = async (scene: BattleScene) => {
|
||||
await endTrainerBattleAndShowDialogue(scene);
|
||||
};
|
||||
await transitionMysteryEncounterIntroVisuals(scene, true, false);
|
||||
await spawnNextTrainerOrEndEncounter(scene);
|
||||
|
|
|
@ -162,7 +162,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
|
@ -238,7 +238,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
|
@ -351,7 +351,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
|
|
|
@ -105,7 +105,7 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
|||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Gain 2 Leftovers and 2 Shell Bell
|
||||
transitionMysteryEncounterIntroVisuals(scene);
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
await tryApplyDigRewardItems(scene);
|
||||
|
||||
const blackSludge = generateModifierType(scene, modifierTypes.MYSTERY_ENCOUNTER_BLACK_SLUDGE, [ SHOP_ITEM_COST_MULTIPLIER ]);
|
||||
|
@ -136,7 +136,7 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
|||
// Investigate garbage, battle Gmax Garbodor
|
||||
scene.setFieldScale(0.75);
|
||||
await showEncounterText(scene, `${namespace}:option.2.selected_2`);
|
||||
transitionMysteryEncounterIntroVisuals(scene);
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
|
@ -222,7 +222,7 @@ async function tryApplyDigRewardItems(scene: BattleScene) {
|
|||
await showEncounterText(scene, i18next.t("battle:rewardGainCount", { modifierName: shellBell.name, count: 2 }), null, undefined, true);
|
||||
}
|
||||
|
||||
async function doGarbageDig(scene: BattleScene) {
|
||||
function doGarbageDig(scene: BattleScene) {
|
||||
scene.playSound("battle_anims/PRSFX- Dig2");
|
||||
scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME, () => {
|
||||
scene.playSound("battle_anims/PRSFX- Dig2");
|
||||
|
|
|
@ -124,10 +124,31 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should start battle against the trainer", async () => {
|
||||
it("should start battle against the trainer with correctly loaded assets", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER, defaultParty);
|
||||
|
||||
let successfullyLoaded = false;
|
||||
vi.spyOn(scene, "getEnemyParty").mockImplementation(() => {
|
||||
const ace = scene.currentBattle?.enemyParty[0];
|
||||
if (ace) {
|
||||
// Pretend that loading assets takes an extra 500ms
|
||||
vi.spyOn(ace, "loadAssets").mockImplementation(() => new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
successfullyLoaded = true;
|
||||
resolve();
|
||||
}, 500);
|
||||
}));
|
||||
}
|
||||
|
||||
return scene.currentBattle?.enemyParty ?? [];
|
||||
});
|
||||
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
// Check that assets are successfully loaded
|
||||
expect(successfullyLoaded).toBe(true);
|
||||
|
||||
// Check usual battle stuff
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
|
@ -182,10 +203,31 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should start battle against the trainer", async () => {
|
||||
it("should start battle against the trainer with correctly loaded assets", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER, defaultParty);
|
||||
|
||||
let successfullyLoaded = false;
|
||||
vi.spyOn(scene, "getEnemyParty").mockImplementation(() => {
|
||||
const ace = scene.currentBattle?.enemyParty[0];
|
||||
if (ace) {
|
||||
// Pretend that loading assets takes an extra 500ms
|
||||
vi.spyOn(ace, "loadAssets").mockImplementation(() => new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
successfullyLoaded = true;
|
||||
resolve();
|
||||
}, 500);
|
||||
}));
|
||||
}
|
||||
|
||||
return scene.currentBattle?.enemyParty ?? [];
|
||||
});
|
||||
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
|
||||
// Check that assets are successfully loaded
|
||||
expect(successfullyLoaded).toBe(true);
|
||||
|
||||
// Check usual battle stuff
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
|
@ -240,10 +282,31 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should start battle against the trainer", async () => {
|
||||
it("should start battle against the trainer with correctly loaded assets", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER, defaultParty);
|
||||
|
||||
let successfullyLoaded = false;
|
||||
vi.spyOn(scene, "getEnemyParty").mockImplementation(() => {
|
||||
const ace = scene.currentBattle?.enemyParty[0];
|
||||
if (ace) {
|
||||
// Pretend that loading assets takes an extra 500ms
|
||||
vi.spyOn(ace, "loadAssets").mockImplementation(() => new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
successfullyLoaded = true;
|
||||
resolve();
|
||||
}, 500);
|
||||
}));
|
||||
}
|
||||
|
||||
return scene.currentBattle?.enemyParty ?? [];
|
||||
});
|
||||
|
||||
await runMysteryEncounterToEnd(game, 3, undefined, true);
|
||||
|
||||
// Check that assets are successfully loaded
|
||||
expect(successfullyLoaded).toBe(true);
|
||||
|
||||
// Check usual battle stuff
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
|
|
Loading…
Reference in New Issue