balance adjustments to certain ME battles

This commit is contained in:
ImperialSympathizer 2024-09-23 19:23:46 -04:00
parent cf80abe33f
commit 05b9e74729
9 changed files with 109 additions and 25 deletions

View File

@ -1201,7 +1201,7 @@ export default class BattleScene extends SceneBase {
// Check for mystery encounter
// Can only occur in place of a standard (non-boss) wild battle, waves 10-180
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex, mysteryEncounterType)) {
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex, mysteryEncounterType) || newBattleType === BattleType.MYSTERY_ENCOUNTER || !isNullOrUndefined(mysteryEncounterType)) {
newBattleType = BattleType.MYSTERY_ENCOUNTER;
// Reset base spawn weight
this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;

View File

@ -202,10 +202,15 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
const modifierType = generateModifierType(scene, modifierTypes.BERRY, [berryMod.berryType]) as PokemonHeldItemModifierType;
bossModifierConfigs.push({ modifier: modifierType });
}
scene.removeModifier(berryMod);
});
// Do NOT remove the real berries yet or else it will be persisted in the session data
// SpDef buff below wave 50, +1 to all stats otherwise
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
[Stat.SPDEF] :
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
// Calculate boss mon
const config: EnemyPartyConfig = {
levelAdditiveModifier: 1,
@ -214,12 +219,12 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
species: getPokemonSpecies(Species.GREEDENT),
isBoss: true,
bossSegments: 3,
moveSet: [Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.SLACK_OFF],
moveSet: [Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH],
modifierConfigs: bossModifierConfigs,
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.boss_enraged`);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD], 1));
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
}
}
],
@ -230,6 +235,18 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
return true;
})
.withOnVisualsStart((scene: BattleScene) => {
// Remove the berries from the party
// Session has been safely saved at this point, so data won't be lost
const berryItems = scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[];
berryItems.forEach(berryMod => {
scene.removeModifier(berryMod);
});
scene.updateModifiers(true);
return true;
})
.withOption(
MysteryEncounterOptionBuilder
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)

View File

@ -190,11 +190,16 @@ export const BerriesAboundEncounter: MysteryEncounter =
}
};
// Defense/Spd buffs below wave 50, +1 to all stats otherwise
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
[Stat.DEF, Stat.SPDEF, Stat.SPD] :
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
const config = scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
queueEncounterMessage(pokemon.scene, `${namespace}.option.2.boss_enraged`);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD], 1));
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
};
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards);
await showEncounterText(scene, `${namespace}.option.2.selected_bad`);

View File

@ -172,7 +172,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
// Defense/Spd buffs below wave 50, Atk/Def/Spd buffs otherwise
// Defense/Spd buffs below wave 50, +1 to all stats otherwise
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
[Stat.DEF, Stat.SPDEF, Stat.SPD] :
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];

View File

@ -72,6 +72,11 @@ export const UncommonBreedEncounter: MysteryEncounter =
encounter.misc.pokemon = pokemon;
// Defense/Spd buffs below wave 50, +1 to all stats otherwise
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
[Stat.DEF, Stat.SPDEF, Stat.SPD] :
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
const config: EnemyPartyConfig = {
pokemonConfigs: [{
level: level,
@ -81,7 +86,7 @@ export const UncommonBreedEncounter: MysteryEncounter =
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.stat_boost`);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD], 1));
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
}
}],
};

View File

@ -25,5 +25,5 @@
"selected": "You toss the {{chosenItem}} to the {{delibirdName}}s,\nwho chatter amongst themselves excitedly.$They turn back to you and happily give you a present!"
}
},
"outro": "The {{delibirdName}} pack happily waddles off into the distance.$What a curious little exchange!"
"outro": "The {{delibirdName}} flock happily waddles off into the distance.$What a curious little exchange!"
}

View File

@ -17,6 +17,7 @@ import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encount
import * as EncounterDialogueUtils from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { CommandPhase } from "#app/phases/command-phase";
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
import { Abilities } from "#enums/abilities";
const namespace = "mysteryEncounter:berriesAbound";
const defaultParty = [Species.PYUKUMUKU, Species.MAGIKARP, Species.PIKACHU];
@ -35,13 +36,15 @@ describe("Berries Abound - Mystery Encounter", () => {
beforeEach(async () => {
game = new GameManager(phaserGame);
scene = game.scene;
game.override.mysteryEncounterChance(100);
game.override.mysteryEncounterTier(MysteryEncounterTier.COMMON);
game.override.startingWave(defaultWave);
game.override.startingBiome(defaultBiome);
game.override.disableTrainerWaves();
game.override.startingModifier([]);
game.override.startingHeldItems([]);
game.override.mysteryEncounterChance(100)
.mysteryEncounterTier(MysteryEncounterTier.COMMON)
.startingWave(defaultWave)
.startingBiome(defaultBiome)
.disableTrainerWaves()
.startingModifier([])
.startingHeldItems([])
.enemyAbility(Abilities.BALL_FETCH)
.enemyPassiveAbility(Abilities.BALL_FETCH);
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
new Map<Biome, MysteryEncounterType[]>([
@ -168,7 +171,30 @@ describe("Berries Abound - Mystery Encounter", () => {
});
});
it("should start battle if fastest pokemon is slower than boss", async () => {
it("should start battle if fastest pokemon is slower than boss below wave 50", async () => {
game.override.startingWave(41);
const encounterTextSpy = vi.spyOn(EncounterDialogueUtils, "showEncounterText");
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);
const config = game.scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId;
// Setting enemy's level arbitrarily high to outspeed
config.pokemonConfigs![0].dataSource!.level = 1000;
await runMysteryEncounterToEnd(game, 2, undefined, true);
const enemyField = scene.getEnemyField();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyField.length).toBe(1);
expect(enemyField[0].species.speciesId).toBe(speciesToSpawn);
// Should be enraged
expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 1, 0, 0]);
expect(encounterTextSpy).toHaveBeenCalledWith(expect.any(BattleScene), `${namespace}.option.2.selected_bad`);
});
it("should start battle if fastest pokemon is slower than boss above wave 50", async () => {
game.override.startingWave(57);
const encounterTextSpy = vi.spyOn(EncounterDialogueUtils, "showEncounterText");
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);

View File

@ -42,6 +42,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => {
.startingWave(defaultWave)
.startingBiome(defaultBiome)
.disableTrainerWaves()
.enemyAbility(Abilities.BALL_FETCH)
.enemyPassiveAbility(Abilities.BALL_FETCH);
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
@ -257,8 +258,8 @@ describe("Teleporting Hijinks - Mystery Encounter", () => {
it("should start a battle against an extra enraged boss above wave 50", { retry: 5 }, async () => {
game.override.startingWave(56);
await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [Species.PIKACHU]);
await runMysteryEncounterToEnd(game, 2, undefined, true);
const enemyField = scene.getEnemyField();
expect(enemyField[0].summonData.statStages).toEqual([1, 1, 1, 1, 1, 0, 0]);
expect(enemyField[0].isBoss()).toBe(true);

View File

@ -24,6 +24,7 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
import { Stat } from "#enums/stat";
import { BerryModifier } from "#app/modifier/modifier";
import { modifierTypes } from "#app/modifier/modifier-type";
import { Abilities } from "#enums/abilities";
const namespace = "mysteryEncounter:uncommonBreed";
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
@ -42,11 +43,13 @@ describe("Uncommon Breed - Mystery Encounter", () => {
beforeEach(async () => {
game = new GameManager(phaserGame);
scene = game.scene;
game.override.mysteryEncounterChance(100);
game.override.mysteryEncounterTier(MysteryEncounterTier.COMMON);
game.override.startingWave(defaultWave);
game.override.startingBiome(defaultBiome);
game.override.disableTrainerWaves();
game.override.mysteryEncounterChance(100)
.mysteryEncounterTier(MysteryEncounterTier.COMMON)
.startingWave(defaultWave)
.startingBiome(defaultBiome)
.disableTrainerWaves()
.enemyAbility(Abilities.BALL_FETCH)
.enemyPassiveAbility(Abilities.BALL_FETCH);
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
new Map<Biome, MysteryEncounterType[]>([
@ -107,7 +110,34 @@ describe("Uncommon Breed - Mystery Encounter", () => {
});
});
it.skip("should start a fight against the boss", async () => {
it.skip("should start a fight against the boss below wave 50", async () => {
const phaseSpy = vi.spyOn(scene, "pushPhase");
const unshiftPhaseSpy = vi.spyOn(scene, "unshiftPhase");
await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty);
const config = game.scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId;
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyField = scene.getEnemyField();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyField.length).toBe(1);
expect(enemyField[0].species.speciesId).toBe(speciesToSpawn);
const statStagePhases = unshiftPhaseSpy.mock.calls.filter(p => p[0] instanceof StatStageChangePhase)[0][0] as any;
expect(statStagePhases.stats).toEqual([Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]);
// Should have used its egg move pre-battle
const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]);
expect(movePhases.length).toBe(1);
const eggMoves: Moves[] = speciesEggMoves[getPokemonSpecies(speciesToSpawn).getRootSpeciesId()];
const usedMove = (movePhases[0] as MovePhase).move.moveId;
expect(eggMoves.includes(usedMove)).toBe(true);
});
it.skip("should start a fight against the boss above wave 50", async () => {
game.override.startingWave(57);
const phaseSpy = vi.spyOn(scene, "pushPhase");
const unshiftPhaseSpy = vi.spyOn(scene, "unshiftPhase");
await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty);