ME data schema updates

This commit is contained in:
ImperialSympathizer 2024-09-07 20:56:47 -04:00
parent 70a703f152
commit 0db39f9a1d
20 changed files with 204 additions and 167 deletions

View File

@ -30,7 +30,7 @@
- [ ] The PR is self-contained and cannot be split into smaller PRs? - [ ] The PR is self-contained and cannot be split into smaller PRs?
- [ ] Have I provided a clear explanation of the changes? - [ ] Have I provided a clear explanation of the changes?
- [ ] Have I considered writing automated tests for the issue? - [ ] Have I considered writing automated tests for the issue?
- [ ] If I have text, did I add make it translatable and added a key in the English language? - [ ] If I have text, did I make it translatable and add a key in the English locale file(s)?
- [ ] Have I tested the changes (manually)? - [ ] Have I tested the changes (manually)?
- [ ] Are all unit tests still passing? (`npm run test`) - [ ] Are all unit tests still passing? (`npm run test`)
- [ ] Are the changes visual? - [ ] Are the changes visual?

View File

@ -4,7 +4,7 @@ import Pokemon, { PlayerPokemon, EnemyPokemon } from "./field/pokemon";
import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies } from "./data/pokemon-species"; import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies } from "./data/pokemon-species";
import { Constructor, isNullOrUndefined } from "#app/utils"; import { Constructor, isNullOrUndefined } from "#app/utils";
import * as Utils from "./utils"; import * as Utils from "./utils";
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, TurnHeldItemTransferModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems } from "./modifier/modifier"; import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, TurnHeldItemTransferModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems, PokemonIncrementingStatModifier, ExpShareModifier, ExpBalanceModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "./modifier/modifier";
import { PokeballType } from "./data/pokeball"; import { PokeballType } from "./data/pokeball";
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "./data/battle-anims"; import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "./data/battle-anims";
import { Phase } from "./phase"; import { Phase } from "./phase";
@ -96,10 +96,13 @@ import { TurnInitPhase } from "./phases/turn-init-phase";
import { ShopCursorTarget } from "./enums/shop-cursor-target"; import { ShopCursorTarget } from "./enums/shop-cursor-target";
import MysteryEncounter from "./data/mystery-encounters/mystery-encounter"; import MysteryEncounter from "./data/mystery-encounters/mystery-encounter";
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters"; import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters";
import { MysteryEncounterData } from "#app/data/mystery-encounters/mystery-encounter-data"; import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import HeldModifierConfig from "#app/interfaces/held-modifier-config"; import HeldModifierConfig from "#app/interfaces/held-modifier-config";
import { ExpPhase } from "#app/phases/exp-phase";
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
@ -253,7 +256,7 @@ export default class BattleScene extends SceneBase {
public money: integer; public money: integer;
public pokemonInfoContainer: PokemonInfoContainer; public pokemonInfoContainer: PokemonInfoContainer;
private party: PlayerPokemon[]; private party: PlayerPokemon[];
public mysteryEncounterData: MysteryEncounterData = new MysteryEncounterData(null); public mysteryEncounterSaveData: MysteryEncounterSaveData = new MysteryEncounterSaveData(null);
public lastMysteryEncounter?: MysteryEncounter; public lastMysteryEncounter?: MysteryEncounter;
/** Combined Biome and Wave count text */ /** Combined Biome and Wave count text */
private biomeWaveText: Phaser.GameObjects.Text; private biomeWaveText: Phaser.GameObjects.Text;
@ -1168,8 +1171,8 @@ export default class BattleScene extends SceneBase {
const roll = Utils.randSeedInt(256); const roll = Utils.randSeedInt(256);
// Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor // Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor
const sessionEncounterRate = this.mysteryEncounterData.encounterSpawnChance; const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
const encounteredEvents = this.mysteryEncounterData.encounteredEvents; const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents;
// If total number of encounters is lower than expected for the run, slightly favor a new encounter spawn (reverse as well) // If total number of encounters is lower than expected for the run, slightly favor a new encounter spawn (reverse as well)
// Reduces occurrence of runs with total encounters significantly different from AVERAGE_ENCOUNTERS_PER_RUN_TARGET // Reduces occurrence of runs with total encounters significantly different from AVERAGE_ENCOUNTERS_PER_RUN_TARGET
@ -1185,9 +1188,9 @@ export default class BattleScene extends SceneBase {
if (canSpawn && roll < successRate) { if (canSpawn && roll < successRate) {
newBattleType = BattleType.MYSTERY_ENCOUNTER; newBattleType = BattleType.MYSTERY_ENCOUNTER;
// Reset base spawn weight // Reset base spawn weight
this.mysteryEncounterData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT; this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
} else { } else {
this.mysteryEncounterData.encounterSpawnChance = sessionEncounterRate + WEIGHT_INCREMENT_ON_SPAWN_MISS; this.mysteryEncounterSaveData.encounterSpawnChance = sessionEncounterRate + WEIGHT_INCREMENT_ON_SPAWN_MISS;
} }
} }
} }
@ -2917,6 +2920,96 @@ export default class BattleScene extends SceneBase {
this.shiftPhase(); this.shiftPhase();
} }
applyPartyExp(expValue: number): void {
const participantIds = this.currentBattle.playerParticipantIds;
const party = this.getParty();
const expShareModifier = this.findModifier(m => m instanceof ExpShareModifier) as ExpShareModifier;
const expBalanceModifier = this.findModifier(m => m instanceof ExpBalanceModifier) as ExpBalanceModifier;
const multipleParticipantExpBonusModifier = this.findModifier(m => m instanceof MultipleParticipantExpBonusModifier) as MultipleParticipantExpBonusModifier;
const nonFaintedPartyMembers = party.filter(p => p.hp);
const expPartyMembers = nonFaintedPartyMembers.filter(p => p.level < this.getMaxExpLevel());
const partyMemberExp: number[] = [];
if (participantIds.size) {
if (this.currentBattle.battleType === BattleType.TRAINER || this.currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
expValue = Math.floor(expValue * 1.5);
} else if (this.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER && this.currentBattle.mysteryEncounter) {
expValue = Math.floor(expValue * this.currentBattle.mysteryEncounter.expMultiplier);
}
for (const partyMember of nonFaintedPartyMembers) {
const pId = partyMember.id;
const participated = participantIds.has(pId);
if (participated) {
partyMember.addFriendship(2);
const machoBraceModifier = partyMember.getHeldItems().find(m => m instanceof PokemonIncrementingStatModifier);
if (machoBraceModifier && machoBraceModifier.stackCount < machoBraceModifier.getMaxStackCount(this)) {
machoBraceModifier.stackCount++;
this.updateModifiers(true, true);
partyMember.updateInfo();
}
}
if (!expPartyMembers.includes(partyMember)) {
continue;
}
if (!participated && !expShareModifier) {
partyMemberExp.push(0);
continue;
}
let expMultiplier = 0;
if (participated) {
expMultiplier += (1 / participantIds.size);
if (participantIds.size > 1 && multipleParticipantExpBonusModifier) {
expMultiplier += multipleParticipantExpBonusModifier.getStackCount() * 0.2;
}
} else if (expShareModifier) {
expMultiplier += (expShareModifier.getStackCount() * 0.2) / participantIds.size;
}
if (partyMember.pokerus) {
expMultiplier *= 1.5;
}
if (Overrides.XP_MULTIPLIER_OVERRIDE !== null) {
expMultiplier = Overrides.XP_MULTIPLIER_OVERRIDE;
}
const pokemonExp = new Utils.NumberHolder(expValue * expMultiplier);
this.applyModifiers(PokemonExpBoosterModifier, true, partyMember, pokemonExp);
partyMemberExp.push(Math.floor(pokemonExp.value));
}
if (expBalanceModifier) {
let totalLevel = 0;
let totalExp = 0;
expPartyMembers.forEach((expPartyMember, epm) => {
totalExp += partyMemberExp[epm];
totalLevel += expPartyMember.level;
});
const medianLevel = Math.floor(totalLevel / expPartyMembers.length);
const recipientExpPartyMemberIndexes: number[] = [];
expPartyMembers.forEach((expPartyMember, epm) => {
if (expPartyMember.level <= medianLevel) {
recipientExpPartyMemberIndexes.push(epm);
}
});
const splitExp = Math.floor(totalExp / recipientExpPartyMemberIndexes.length);
expPartyMembers.forEach((_partyMember, pm) => {
partyMemberExp[pm] = Phaser.Math.Linear(partyMemberExp[pm], recipientExpPartyMemberIndexes.indexOf(pm) > -1 ? splitExp : 0, 0.2 * expBalanceModifier.getStackCount());
});
}
for (let pm = 0; pm < expPartyMembers.length; pm++) {
const exp = partyMemberExp[pm];
if (exp) {
const partyMemberIndex = party.indexOf(expPartyMembers[pm]);
this.unshiftPhase(expPartyMembers[pm].isOnField() ? new ExpPhase(this, partyMemberIndex, exp) : new ShowPartyExpBarPhase(this, partyMemberIndex, exp));
}
}
}
}
/** /**
* Loads or generates a mystery encounter * Loads or generates a mystery encounter
* @param override - used to load session encounter when restarting game, etc. * @param override - used to load session encounter when restarting game, etc.
@ -2932,13 +3025,13 @@ export default class BattleScene extends SceneBase {
} }
// Check for queued encounters first // Check for queued encounters first
if (!encounter && this.mysteryEncounterData?.nextEncounterQueue && this.mysteryEncounterData.nextEncounterQueue.length > 0) { if (!encounter && this.mysteryEncounterSaveData?.queuedEncounters && this.mysteryEncounterSaveData.queuedEncounters.length > 0) {
let i = 0; let i = 0;
while (i < this.mysteryEncounterData.nextEncounterQueue.length && !!encounter) { while (i < this.mysteryEncounterSaveData.queuedEncounters.length && !!encounter) {
const candidate = this.mysteryEncounterData.nextEncounterQueue[i]; const candidate = this.mysteryEncounterSaveData.queuedEncounters[i];
const forcedChance = candidate[1]; const forcedChance = candidate.spawnPercent;
if (Utils.randSeedInt(100) < forcedChance) { if (Utils.randSeedInt(100) < forcedChance) {
encounter = allMysteryEncounters[candidate[0]]; encounter = allMysteryEncounters[candidate.type];
} }
i++; i++;
@ -2955,7 +3048,7 @@ export default class BattleScene extends SceneBase {
const tierWeights = [MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE]; const tierWeights = [MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE];
// Adjust tier weights by previously encountered events to lower odds of only Common/Great in run // Adjust tier weights by previously encountered events to lower odds of only Common/Great in run
this.mysteryEncounterData.encounteredEvents.forEach(seenEncounterData => { this.mysteryEncounterSaveData.encounteredEvents.forEach(seenEncounterData => {
if (seenEncounterData.tier === MysteryEncounterTier.COMMON) { if (seenEncounterData.tier === MysteryEncounterTier.COMMON) {
tierWeights[0] = tierWeights[0] - 6; tierWeights[0] = tierWeights[0] - 6;
} else if (seenEncounterData.tier === MysteryEncounterTier.GREAT) { } else if (seenEncounterData.tier === MysteryEncounterTier.GREAT) {
@ -2976,7 +3069,7 @@ export default class BattleScene extends SceneBase {
let availableEncounters: MysteryEncounter[] = []; let availableEncounters: MysteryEncounter[] = [];
// New encounter should never be the same as the most recent encounter // New encounter should never be the same as the most recent encounter
const previousEncounter = this.mysteryEncounterData.encounteredEvents.length > 0 ? this.mysteryEncounterData.encounteredEvents[this.mysteryEncounterData.encounteredEvents.length - 1].type : null; const previousEncounter = this.mysteryEncounterSaveData.encounteredEvents.length > 0 ? this.mysteryEncounterSaveData.encounteredEvents[this.mysteryEncounterSaveData.encounteredEvents.length - 1].type : null;
const biomeMysteryEncounters = mysteryEncountersByBiome.get(this.arena.biomeType) ?? []; const biomeMysteryEncounters = mysteryEncountersByBiome.get(this.arena.biomeType) ?? [];
// If no valid encounters exist at tier, checks next tier down, continuing until there are some encounters available // If no valid encounters exist at tier, checks next tier down, continuing until there are some encounters available
while (availableEncounters.length === 0 && tier !== null) { while (availableEncounters.length === 0 && tier !== null) {
@ -2995,9 +3088,9 @@ export default class BattleScene extends SceneBase {
if (previousEncounter !== null && encounterType === previousEncounter) { // Previous encounter was not this one if (previousEncounter !== null && encounterType === previousEncounter) { // Previous encounter was not this one
return false; return false;
} }
if (this.mysteryEncounterData.encounteredEvents.length > 0 && // Encounter has not exceeded max allowed encounters if (this.mysteryEncounterSaveData.encounteredEvents.length > 0 && // Encounter has not exceeded max allowed encounters
(encounterCandidate.maxAllowedEncounters && encounterCandidate.maxAllowedEncounters > 0) (encounterCandidate.maxAllowedEncounters && encounterCandidate.maxAllowedEncounters > 0)
&& this.mysteryEncounterData.encounteredEvents.filter(e => e.type === encounterType).length >= encounterCandidate.maxAllowedEncounters) { && this.mysteryEncounterSaveData.encounteredEvents.filter(e => e.type === encounterType).length >= encounterCandidate.maxAllowedEncounters) {
return false; return false;
} }
return true; return true;

View File

@ -129,7 +129,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
}, },
{ // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter { // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
species: getPokemonSpecies(Species.BLACEPHALON), species: getPokemonSpecies(Species.BLACEPHALON),
mysteryEncounterData: new MysteryEncounterPokemonData(undefined, ability, undefined, [randSeedInt(18), randSeedInt(18)]), mysteryEncounterPokemonData: new MysteryEncounterPokemonData(undefined, ability, undefined, [randSeedInt(18), randSeedInt(18)]),
isBoss: true, isBoss: true,
moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN] moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN]
}, },
@ -344,10 +344,10 @@ export const ClowningAroundEncounter: MysteryEncounter =
} }
} }
newTypes.push(secondType); newTypes.push(secondType);
if (!pokemon.mysteryEncounterData) { if (!pokemon.mysteryEncounterPokemonData) {
pokemon.mysteryEncounterData = new MysteryEncounterPokemonData(undefined, undefined, undefined, newTypes); pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(undefined, undefined, undefined, newTypes);
} else { } else {
pokemon.mysteryEncounterData.types = newTypes; pokemon.mysteryEncounterPokemonData.types = newTypes;
} }
} }
}) })
@ -410,10 +410,10 @@ function displayYesNoOptions(scene: BattleScene, resolve) {
function onYesAbilitySwap(scene: BattleScene, resolve) { function onYesAbilitySwap(scene: BattleScene, resolve) {
const onPokemonSelected = (pokemon: PlayerPokemon) => { const onPokemonSelected = (pokemon: PlayerPokemon) => {
// Do ability swap // Do ability swap
if (!pokemon.mysteryEncounterData) { if (!pokemon.mysteryEncounterPokemonData) {
pokemon.mysteryEncounterData = new MysteryEncounterPokemonData(undefined, Abilities.AERILATE); pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(undefined, Abilities.AERILATE);
} }
pokemon.mysteryEncounterData.ability = scene.currentBattle.mysteryEncounter!.misc.ability; pokemon.mysteryEncounterPokemonData.ability = scene.currentBattle.mysteryEncounter!.misc.ability;
scene.currentBattle.mysteryEncounter!.setDialogueToken("chosenPokemon", pokemon.getNameToRender()); scene.currentBattle.mysteryEncounter!.setDialogueToken("chosenPokemon", pokemon.getNameToRender());
scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true)); scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true));
}; };

View File

@ -76,7 +76,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
species: getPokemonSpecies(Species.SHUCKLE), species: getPokemonSpecies(Species.SHUCKLE),
isBoss: true, isBoss: true,
bossSegments: 5, bossSegments: 5,
mysteryEncounterData: new MysteryEncounterPokemonData(1.25), mysteryEncounterPokemonData: new MysteryEncounterPokemonData(1.25),
nature: Nature.BOLD, nature: Nature.BOLD,
moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER], moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER],
modifierConfigs: [ modifierConfigs: [

View File

@ -369,10 +369,10 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
newType = randSeedInt(18) as Type; newType = randSeedInt(18) as Type;
} }
newTypes.push(newType); newTypes.push(newType);
if (!newPokemon.mysteryEncounterData) { if (!newPokemon.mysteryEncounterPokemonData) {
newPokemon.mysteryEncounterData = new MysteryEncounterPokemonData(undefined, undefined, undefined, newTypes); newPokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(undefined, undefined, undefined, newTypes);
} else { } else {
newPokemon.mysteryEncounterData.types = newTypes; newPokemon.mysteryEncounterPokemonData.types = newTypes;
} }
for (const item of transformation.heldItems) { for (const item of transformation.heldItems) {

View File

@ -123,11 +123,11 @@ export class PreviousEncounterRequirement extends EncounterSceneRequirement {
} }
meetsRequirement(scene: BattleScene): boolean { meetsRequirement(scene: BattleScene): boolean {
return scene.mysteryEncounterData.encounteredEvents.some(e => e.type === this.previousEncounterRequirement); return scene.mysteryEncounterSaveData.encounteredEvents.some(e => e.type === this.previousEncounterRequirement);
} }
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
return ["previousEncounter", scene.mysteryEncounterData.encounteredEvents.find(e => e.type === this.previousEncounterRequirement)?.[0].toString() ?? ""]; return ["previousEncounter", scene.mysteryEncounterSaveData.encounteredEvents.find(e => e.type === this.previousEncounterRequirement)?.[0].toString() ?? ""];
} }
} }

View File

@ -7,20 +7,27 @@ export class SeenEncounterData {
type: MysteryEncounterType; type: MysteryEncounterType;
tier: MysteryEncounterTier; tier: MysteryEncounterTier;
waveIndex: number; waveIndex: number;
selectedOption: number;
constructor(type: MysteryEncounterType, tier: MysteryEncounterTier, waveIndex: number) { constructor(type: MysteryEncounterType, tier: MysteryEncounterTier, waveIndex: number, selectedOption?: number) {
this.type = type; this.type = type;
this.tier = tier; this.tier = tier;
this.waveIndex = waveIndex; this.waveIndex = waveIndex;
this.selectedOption = selectedOption ?? -1;
} }
} }
export class MysteryEncounterData { export interface QueuedEncounter {
type: MysteryEncounterType;
spawnPercent: number; // Out of 100
}
export class MysteryEncounterSaveData {
encounteredEvents: SeenEncounterData[] = []; encounteredEvents: SeenEncounterData[] = [];
encounterSpawnChance: number = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT; encounterSpawnChance: number = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
nextEncounterQueue: [MysteryEncounterType, integer][] = []; queuedEncounters: QueuedEncounter[] = [];
constructor(data: MysteryEncounterData | null) { constructor(data: MysteryEncounterSaveData | null) {
if (!isNullOrUndefined(data)) { if (!isNullOrUndefined(data)) {
Object.assign(this, data); Object.assign(this, data);
} }

View File

@ -72,7 +72,7 @@ export interface EnemyPokemonConfig {
isBoss: boolean; isBoss: boolean;
bossSegments?: number; bossSegments?: number;
bossSegmentModifier?: number; // Additive to the determined segment number bossSegmentModifier?: number; // Additive to the determined segment number
mysteryEncounterData?: MysteryEncounterPokemonData; mysteryEncounterPokemonData?: MysteryEncounterPokemonData;
formIndex?: number; formIndex?: number;
abilityIndex?: number; abilityIndex?: number;
level?: number; level?: number;
@ -229,8 +229,8 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
} }
// Set custom mystery encounter data fields (such as sprite scale, custom abilities, types, etc.) // Set custom mystery encounter data fields (such as sprite scale, custom abilities, types, etc.)
if (!isNullOrUndefined(config.mysteryEncounterData)) { if (!isNullOrUndefined(config.mysteryEncounterPokemonData)) {
enemyPokemon.mysteryEncounterData = config.mysteryEncounterData!; enemyPokemon.mysteryEncounterPokemonData = config.mysteryEncounterPokemonData!;
} }
// Set Boss // Set Boss

View File

@ -112,7 +112,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
public battleData: PokemonBattleData; public battleData: PokemonBattleData;
public battleSummonData: PokemonBattleSummonData; public battleSummonData: PokemonBattleSummonData;
public turnData: PokemonTurnData; public turnData: PokemonTurnData;
public mysteryEncounterData: MysteryEncounterPokemonData; public mysteryEncounterPokemonData: MysteryEncounterPokemonData;
/** Used by Mystery Encounters to execute pokemon-specific logic (such as stat boosts) at start of battle */ /** Used by Mystery Encounters to execute pokemon-specific logic (such as stat boosts) at start of battle */
public mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void; public mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void;
@ -201,7 +201,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.fusionGender = dataSource.fusionGender; this.fusionGender = dataSource.fusionGender;
this.fusionLuck = dataSource.fusionLuck; this.fusionLuck = dataSource.fusionLuck;
this.usedTMs = dataSource.usedTMs ?? []; this.usedTMs = dataSource.usedTMs ?? [];
this.mysteryEncounterData = dataSource.mysteryEncounterData ?? new MysteryEncounterPokemonData(); this.mysteryEncounterPokemonData = dataSource.mysteryEncounterPokemonData ?? new MysteryEncounterPokemonData();
} else { } else {
this.id = Utils.randSeedInt(4294967296); this.id = Utils.randSeedInt(4294967296);
this.ivs = ivs || Utils.getIvsFromId(this.id); this.ivs = ivs || Utils.getIvsFromId(this.id);
@ -249,7 +249,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
this.luck = (this.shiny ? this.variant + 1 : 0) + (this.fusionShiny ? this.fusionVariant + 1 : 0); this.luck = (this.shiny ? this.variant + 1 : 0) + (this.fusionShiny ? this.fusionVariant + 1 : 0);
this.fusionLuck = this.luck; this.fusionLuck = this.luck;
this.mysteryEncounterData = new MysteryEncounterPokemonData(); this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
} }
this.generateName(); this.generateName();
@ -577,8 +577,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const formKey = this.getFormKey(); const formKey = this.getFormKey();
if (formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1 || formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1) { if (formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1 || formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1) {
return 1.5; return 1.5;
} else if (!isNullOrUndefined(this.mysteryEncounterData.spriteScale) && this.mysteryEncounterData.spriteScale !== 0) { } else if (!isNullOrUndefined(this.mysteryEncounterPokemonData.spriteScale) && this.mysteryEncounterPokemonData.spriteScale !== 0) {
return this.mysteryEncounterData.spriteScale!; return this.mysteryEncounterPokemonData.spriteScale!;
} }
return 1; return 1;
} }
@ -1082,9 +1082,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
if (!types.length || !includeTeraType) { if (!types.length || !includeTeraType) {
if (this.mysteryEncounterData.types && this.mysteryEncounterData.types.length > 0) { if (this.mysteryEncounterPokemonData.types && this.mysteryEncounterPokemonData.types.length > 0) {
// "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters // "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters
this.mysteryEncounterData.types.forEach(t => types.push(t)); this.mysteryEncounterPokemonData.types.forEach(t => types.push(t));
} else if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) { } else if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) {
this.summonData.types.forEach(t => types.push(t)); this.summonData.types.forEach(t => types.push(t));
} else { } else {
@ -1146,8 +1146,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (Overrides.OPP_ABILITY_OVERRIDE && !this.isPlayer()) { if (Overrides.OPP_ABILITY_OVERRIDE && !this.isPlayer()) {
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE]; return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
} }
if (this.mysteryEncounterData?.ability) { if (this.mysteryEncounterPokemonData?.ability) {
return allAbilities[this.mysteryEncounterData.ability]; return allAbilities[this.mysteryEncounterPokemonData.ability];
} }
if (this.isFusion()) { if (this.isFusion()) {
return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)]; return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)];
@ -1173,8 +1173,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) { if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) {
return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE]; return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE];
} }
if (this.mysteryEncounterData?.passive) { if (this.mysteryEncounterPokemonData?.passive) {
return allAbilities[this.mysteryEncounterData.passive]; return allAbilities[this.mysteryEncounterPokemonData.passive];
} }
let starterSpeciesId = this.species.speciesId; let starterSpeciesId = this.species.speciesId;

View File

@ -8,7 +8,7 @@
"label": "Battle the Pokémon", "label": "Battle the Pokémon",
"tooltip": "(-) Tricky Battle\n(+) Strong Catchable Foe", "tooltip": "(-) Tricky Battle\n(+) Strong Catchable Foe",
"selected": "You approach the\n{{enemyPokemon}} without fear.", "selected": "You approach the\n{{enemyPokemon}} without fear.",
"stat_boost": "The {{enemyPokemon}} heightened abilities boost its stats!" "stat_boost": "The {{enemyPokemon}}'s heightened abilities boost its stats!"
}, },
"2": { "2": {
"label": "Give It Food", "label": "Give It Food",

View File

@ -239,7 +239,7 @@ export class GameOverPhase extends BattlePhase {
timestamp: new Date().getTime(), timestamp: new Date().getTime(),
challenges: this.scene.gameMode.challenges.map(c => new ChallengeData(c)), challenges: this.scene.gameMode.challenges.map(c => new ChallengeData(c)),
mysteryEncounter: this.scene.currentBattle.mysteryEncounter, mysteryEncounter: this.scene.currentBattle.mysteryEncounter,
mysteryEncounterData: this.scene.mysteryEncounterData mysteryEncounterSaveData: this.scene.mysteryEncounterSaveData
} as SessionSaveData; } as SessionSaveData;
} }
} }

View File

@ -24,7 +24,7 @@ import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
import { NewBattlePhase } from "#app/phases/new-battle-phase"; import { NewBattlePhase } from "#app/phases/new-battle-phase";
import { GameOverPhase } from "#app/phases/game-over-phase"; import { GameOverPhase } from "#app/phases/game-over-phase";
import { SwitchPhase } from "#app/phases/switch-phase"; import { SwitchPhase } from "#app/phases/switch-phase";
import { SeenEncounterData } from "#app/data/mystery-encounters/mystery-encounter-data"; import { SeenEncounterData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
/** /**
* Will handle (in order): * Will handle (in order):
@ -63,7 +63,7 @@ export class MysteryEncounterPhase extends Phase {
if (!this.optionSelectSettings) { if (!this.optionSelectSettings) {
// Sets flag that ME was encountered, only if this is not a followup option select phase // Sets flag that ME was encountered, only if this is not a followup option select phase
// Can be used in later MEs to check for requirements to spawn, run history, etc. // Can be used in later MEs to check for requirements to spawn, run history, etc.
this.scene.mysteryEncounterData.encounteredEvents.push(new SeenEncounterData(encounter.encounterType, encounter.encounterTier, this.scene.currentBattle.waveIndex)); this.scene.mysteryEncounterSaveData.encounteredEvents.push(new SeenEncounterData(encounter.encounterType, encounter.encounterTier, this.scene.currentBattle.waveIndex));
} }
// Initiates encounter dialogue window and option select // Initiates encounter dialogue window and option select
@ -74,6 +74,15 @@ export class MysteryEncounterPhase extends Phase {
// Set option selected flag // Set option selected flag
this.scene.currentBattle.mysteryEncounter!.selectedOption = option; this.scene.currentBattle.mysteryEncounter!.selectedOption = option;
if (!this.optionSelectSettings) {
// Saves the selected option in the ME save data, only if this is not a followup option select phase
// Can be used for analytics purposes to track what options are popular on certain encounters
const encounterSaveData = this.scene.mysteryEncounterSaveData.encounteredEvents[this.scene.mysteryEncounterSaveData.encounteredEvents.length - 1];
if (encounterSaveData.type === this.scene.currentBattle.mysteryEncounter?.encounterType) {
encounterSaveData.selectedOption = index;
}
}
if (!option.onOptionPhase) { if (!option.onOptionPhase) {
return false; return false;
} }

View File

@ -0,0 +1,20 @@
import BattleScene from "#app/battle-scene.js";
import { Phase } from "#app/phase";
export class PartyExpPhase extends Phase {
expValue: number;
constructor(scene: BattleScene, expValue: number) {
super(scene);
this.expValue = expValue;
}
start() {
super.start();
this.scene.applyPartyExp(this.expValue);
this.end();
}
}

View File

@ -1,21 +1,15 @@
import BattleScene from "#app/battle-scene.js"; import BattleScene from "#app/battle-scene.js";
import { BattlerIndex, BattleType } from "#app/battle.js"; import { BattlerIndex, BattleType } from "#app/battle.js";
import { modifierTypes } from "#app/modifier/modifier-type.js"; import { modifierTypes } from "#app/modifier/modifier-type.js";
import { ExpShareModifier, ExpBalanceModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "#app/modifier/modifier.js";
import * as Utils from "#app/utils.js";
import Overrides from "#app/overrides";
import { BattleEndPhase } from "./battle-end-phase"; import { BattleEndPhase } from "./battle-end-phase";
import { NewBattlePhase } from "./new-battle-phase"; import { NewBattlePhase } from "./new-battle-phase";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "./pokemon-phase";
import { AddEnemyBuffModifierPhase } from "./add-enemy-buff-modifier-phase"; import { AddEnemyBuffModifierPhase } from "./add-enemy-buff-modifier-phase";
import { EggLapsePhase } from "./egg-lapse-phase"; import { EggLapsePhase } from "./egg-lapse-phase";
import { ExpPhase } from "./exp-phase";
import { GameOverPhase } from "./game-over-phase"; import { GameOverPhase } from "./game-over-phase";
import { ModifierRewardPhase } from "./modifier-reward-phase"; import { ModifierRewardPhase } from "./modifier-reward-phase";
import { SelectModifierPhase } from "./select-modifier-phase"; import { SelectModifierPhase } from "./select-modifier-phase";
import { ShowPartyExpBarPhase } from "./show-party-exp-bar-phase";
import { TrainerVictoryPhase } from "./trainer-victory-phase"; import { TrainerVictoryPhase } from "./trainer-victory-phase";
import { PokemonIncrementingStatModifier } from "#app/modifier/modifier";
import { handleMysteryEncounterVictory } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { handleMysteryEncounterVictory } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
export class VictoryPhase extends PokemonPhase { export class VictoryPhase extends PokemonPhase {
@ -33,94 +27,8 @@ export class VictoryPhase extends PokemonPhase {
this.scene.gameData.gameStats.pokemonDefeated++; this.scene.gameData.gameStats.pokemonDefeated++;
const participantIds = this.scene.currentBattle.playerParticipantIds; const expValue = this.getPokemon().getExpValue();
const party = this.scene.getParty(); this.scene.applyPartyExp(expValue);
const expShareModifier = this.scene.findModifier(m => m instanceof ExpShareModifier) as ExpShareModifier;
const expBalanceModifier = this.scene.findModifier(m => m instanceof ExpBalanceModifier) as ExpBalanceModifier;
const multipleParticipantExpBonusModifier = this.scene.findModifier(m => m instanceof MultipleParticipantExpBonusModifier) as MultipleParticipantExpBonusModifier;
const nonFaintedPartyMembers = party.filter(p => p.hp);
const expPartyMembers = nonFaintedPartyMembers.filter(p => p.level < this.scene.getMaxExpLevel());
const partyMemberExp: number[] = [];
if (participantIds.size) {
let expValue = this.getPokemon().getExpValue();
if (this.scene.currentBattle.battleType === BattleType.TRAINER) {
expValue = Math.floor(expValue * 1.5);
} else if (this.scene.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER && this.scene.currentBattle.mysteryEncounter) {
expValue = Math.floor(expValue * this.scene.currentBattle.mysteryEncounter.expMultiplier);
}
for (const partyMember of nonFaintedPartyMembers) {
const pId = partyMember.id;
const participated = participantIds.has(pId);
if (participated) {
partyMember.addFriendship(2);
const machoBraceModifier = partyMember.getHeldItems().find(m => m instanceof PokemonIncrementingStatModifier);
if (machoBraceModifier && machoBraceModifier.stackCount < machoBraceModifier.getMaxStackCount(this.scene)) {
machoBraceModifier.stackCount++;
this.scene.updateModifiers(true, true);
partyMember.updateInfo();
}
}
if (!expPartyMembers.includes(partyMember)) {
continue;
}
if (!participated && !expShareModifier) {
partyMemberExp.push(0);
continue;
}
let expMultiplier = 0;
if (participated) {
expMultiplier += (1 / participantIds.size);
if (participantIds.size > 1 && multipleParticipantExpBonusModifier) {
expMultiplier += multipleParticipantExpBonusModifier.getStackCount() * 0.2;
}
} else if (expShareModifier) {
expMultiplier += (expShareModifier.getStackCount() * 0.2) / participantIds.size;
}
if (partyMember.pokerus) {
expMultiplier *= 1.5;
}
if (Overrides.XP_MULTIPLIER_OVERRIDE !== null) {
expMultiplier = Overrides.XP_MULTIPLIER_OVERRIDE;
}
const pokemonExp = new Utils.NumberHolder(expValue * expMultiplier);
this.scene.applyModifiers(PokemonExpBoosterModifier, true, partyMember, pokemonExp);
partyMemberExp.push(Math.floor(pokemonExp.value));
}
if (expBalanceModifier) {
let totalLevel = 0;
let totalExp = 0;
expPartyMembers.forEach((expPartyMember, epm) => {
totalExp += partyMemberExp[epm];
totalLevel += expPartyMember.level;
});
const medianLevel = Math.floor(totalLevel / expPartyMembers.length);
const recipientExpPartyMemberIndexes: number[] = [];
expPartyMembers.forEach((expPartyMember, epm) => {
if (expPartyMember.level <= medianLevel) {
recipientExpPartyMemberIndexes.push(epm);
}
});
const splitExp = Math.floor(totalExp / recipientExpPartyMemberIndexes.length);
expPartyMembers.forEach((_partyMember, pm) => {
partyMemberExp[pm] = Phaser.Math.Linear(partyMemberExp[pm], recipientExpPartyMemberIndexes.indexOf(pm) > -1 ? splitExp : 0, 0.2 * expBalanceModifier.getStackCount());
});
}
for (let pm = 0; pm < expPartyMembers.length; pm++) {
const exp = partyMemberExp[pm];
if (exp) {
const partyMemberIndex = party.indexOf(expPartyMembers[pm]);
this.scene.unshiftPhase(expPartyMembers[pm].isOnField() ? new ExpPhase(this.scene, partyMemberIndex, exp) : new ShowPartyExpBarPhase(this.scene, partyMemberIndex, exp));
}
}
}
if (this.scene.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER) { if (this.scene.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER) {
handleMysteryEncounterVictory(this.scene, false, this.isExpOnly); handleMysteryEncounterVictory(this.scene, false, this.isExpOnly);

View File

@ -45,7 +45,7 @@ import { TerrainType } from "#app/data/terrain.js";
import { OutdatedPhase } from "#app/phases/outdated-phase.js"; import { OutdatedPhase } from "#app/phases/outdated-phase.js";
import { ReloadSessionPhase } from "#app/phases/reload-session-phase.js"; import { ReloadSessionPhase } from "#app/phases/reload-session-phase.js";
import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler"; import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler";
import { MysteryEncounterData } from "../data/mystery-encounters/mystery-encounter-data"; import { MysteryEncounterSaveData } from "../data/mystery-encounters/mystery-encounter-save-data";
import MysteryEncounter from "../data/mystery-encounters/mystery-encounter"; import MysteryEncounter from "../data/mystery-encounters/mystery-encounter";
export const defaultStarterSpecies: Species[] = [ export const defaultStarterSpecies: Species[] = [
@ -132,7 +132,7 @@ export interface SessionSaveData {
timestamp: integer; timestamp: integer;
challenges: ChallengeData[]; challenges: ChallengeData[];
mysteryEncounter: MysteryEncounter; mysteryEncounter: MysteryEncounter;
mysteryEncounterData: MysteryEncounterData; mysteryEncounterSaveData: MysteryEncounterSaveData;
} }
interface Unlocks { interface Unlocks {
@ -978,7 +978,7 @@ export class GameData {
timestamp: new Date().getTime(), timestamp: new Date().getTime(),
challenges: scene.gameMode.challenges.map(c => new ChallengeData(c)), challenges: scene.gameMode.challenges.map(c => new ChallengeData(c)),
mysteryEncounter: scene.currentBattle.mysteryEncounter, mysteryEncounter: scene.currentBattle.mysteryEncounter,
mysteryEncounterData: scene.mysteryEncounterData mysteryEncounterSaveData: scene.mysteryEncounterSaveData
} as SessionSaveData; } as SessionSaveData;
} }
@ -1069,7 +1069,7 @@ export class GameData {
scene.score = sessionData.score; scene.score = sessionData.score;
scene.updateScoreText(); scene.updateScoreText();
scene.mysteryEncounterData = sessionData?.mysteryEncounterData ? sessionData?.mysteryEncounterData : new MysteryEncounterData(null); scene.mysteryEncounterSaveData = sessionData?.mysteryEncounterSaveData ?? new MysteryEncounterSaveData(null);
scene.newArena(sessionData.arena.biome); scene.newArena(sessionData.arena.biome);
@ -1294,8 +1294,8 @@ export class GameData {
return new MysteryEncounter(v); return new MysteryEncounter(v);
} }
if (k === "mysteryEncounterData") { if (k === "mysteryEncounterSaveData") {
return new MysteryEncounterData(v); return new MysteryEncounterSaveData(v);
} }
return v; return v;

View File

@ -57,7 +57,7 @@ export default class PokemonData {
public bossSegments?: integer; public bossSegments?: integer;
public summonData: PokemonSummonData; public summonData: PokemonSummonData;
public mysteryEncounterData: MysteryEncounterPokemonData; public mysteryEncounterPokemonData: MysteryEncounterPokemonData;
constructor(source: Pokemon | any, forHistory: boolean = false) { constructor(source: Pokemon | any, forHistory: boolean = false) {
const sourcePokemon = source instanceof Pokemon ? source : null; const sourcePokemon = source instanceof Pokemon ? source : null;
@ -103,7 +103,7 @@ export default class PokemonData {
this.fusionLuck = source.fusionLuck !== undefined ? source.fusionLuck : (source.fusionShiny ? source.fusionVariant + 1 : 0); this.fusionLuck = source.fusionLuck !== undefined ? source.fusionLuck : (source.fusionShiny ? source.fusionVariant + 1 : 0);
this.usedTMs = source.usedTMs ?? []; this.usedTMs = source.usedTMs ?? [];
this.mysteryEncounterData = source.mysteryEncounterData ?? new MysteryEncounterPokemonData(); this.mysteryEncounterPokemonData = source.mysteryEncounterPokemonData ?? new MysteryEncounterPokemonData();
if (!forHistory) { if (!forHistory) {
this.boss = (source instanceof EnemyPokemon && !!source.bossSegments) || (!this.player && !!source.boss); this.boss = (source instanceof EnemyPokemon && !!source.bossSegments) || (!this.player && !!source.boss);

View File

@ -126,11 +126,11 @@ describe("Clowning Around - Mystery Encounter", () => {
}); });
expect(config.pokemonConfigs?.[1]).toEqual({ expect(config.pokemonConfigs?.[1]).toEqual({
species: getPokemonSpecies(Species.BLACEPHALON), species: getPokemonSpecies(Species.BLACEPHALON),
mysteryEncounterData: expect.anything(), mysteryEncounterPokemonData: expect.anything(),
isBoss: true, isBoss: true,
moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN] moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN]
}); });
expect(config.pokemonConfigs?.[1].mysteryEncounterData?.types.length).toBe(2); expect(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.types.length).toBe(2);
expect([ expect([
Abilities.STURDY, Abilities.STURDY,
Abilities.PICKUP, Abilities.PICKUP,
@ -147,8 +147,8 @@ describe("Clowning Around - Mystery Encounter", () => {
Abilities.MAGICIAN, Abilities.MAGICIAN,
Abilities.SHEER_FORCE, Abilities.SHEER_FORCE,
Abilities.PRANKSTER Abilities.PRANKSTER
]).toContain(config.pokemonConfigs?.[1].mysteryEncounterData?.ability); ]).toContain(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.ability);
expect(ClowningAroundEncounter.misc.ability).toBe(config.pokemonConfigs?.[1].mysteryEncounterData?.ability); expect(ClowningAroundEncounter.misc.ability).toBe(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.ability);
await vi.waitFor(() => expect(moveInitSpy).toHaveBeenCalled()); await vi.waitFor(() => expect(moveInitSpy).toHaveBeenCalled());
await vi.waitFor(() => expect(moveLoadSpy).toHaveBeenCalled()); await vi.waitFor(() => expect(moveLoadSpy).toHaveBeenCalled());
expect(onInitResult).toBe(true); expect(onInitResult).toBe(true);
@ -227,7 +227,7 @@ describe("Clowning Around - Mystery Encounter", () => {
await game.phaseInterceptor.to(NewBattlePhase, false); await game.phaseInterceptor.to(NewBattlePhase, false);
const leadPokemon = scene.getParty()[0]; const leadPokemon = scene.getParty()[0];
expect(leadPokemon.mysteryEncounterData?.ability).toBe(abilityToTrain); expect(leadPokemon.mysteryEncounterPokemonData?.ability).toBe(abilityToTrain);
}); });
}); });
@ -348,9 +348,9 @@ describe("Clowning Around - Mystery Encounter", () => {
scene.getParty()[2].moveset = []; scene.getParty()[2].moveset = [];
await runMysteryEncounterToEnd(game, 3); await runMysteryEncounterToEnd(game, 3);
const leadTypesAfter = scene.getParty()[0].mysteryEncounterData?.types; const leadTypesAfter = scene.getParty()[0].mysteryEncounterPokemonData?.types;
const secondaryTypesAfter = scene.getParty()[1].mysteryEncounterData?.types; const secondaryTypesAfter = scene.getParty()[1].mysteryEncounterPokemonData?.types;
const thirdTypesAfter = scene.getParty()[2].mysteryEncounterData?.types; const thirdTypesAfter = scene.getParty()[2].mysteryEncounterPokemonData?.types;
expect(leadTypesAfter.length).toBe(2); expect(leadTypesAfter.length).toBe(2);
expect(leadTypesAfter[0]).toBe(Type.WATER); expect(leadTypesAfter[0]).toBe(Type.WATER);

View File

@ -121,7 +121,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
species: getPokemonSpecies(Species.SHUCKLE), species: getPokemonSpecies(Species.SHUCKLE),
isBoss: true, isBoss: true,
bossSegments: 5, bossSegments: 5,
mysteryEncounterData: new MysteryEncounterPokemonData(1.25), mysteryEncounterPokemonData: new MysteryEncounterPokemonData(1.25),
nature: Nature.BOLD, nature: Nature.BOLD,
moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER], moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER],
modifierConfigs: expect.any(Array), modifierConfigs: expect.any(Array),

View File

@ -138,7 +138,7 @@ describe("Weird Dream - Mystery Encounter", () => {
for (let i = 0; i < pokemonAfter.length; i++) { for (let i = 0; i < pokemonAfter.length; i++) {
const newPokemon = pokemonAfter[i]; const newPokemon = pokemonAfter[i];
expect(newPokemon.getSpeciesForm().speciesId).not.toBe(pokemonPrior[i].getSpeciesForm().speciesId); expect(newPokemon.getSpeciesForm().speciesId).not.toBe(pokemonPrior[i].getSpeciesForm().speciesId);
expect(newPokemon.mysteryEncounterData?.types.length).toBe(2); expect(newPokemon.mysteryEncounterPokemonData?.types.length).toBe(2);
} }
const plus90To110 = bstDiff.filter(bst => bst > 80); const plus90To110 = bstDiff.filter(bst => bst > 80);

View File

@ -49,9 +49,9 @@ describe("Mystery Encounter Phases", () => {
}); });
await game.phaseInterceptor.run(MysteryEncounterPhase); await game.phaseInterceptor.run(MysteryEncounterPhase);
expect(game.scene.mysteryEncounterData.encounteredEvents.length).toBeGreaterThan(0); expect(game.scene.mysteryEncounterSaveData.encounteredEvents.length).toBeGreaterThan(0);
expect(game.scene.mysteryEncounterData.encounteredEvents[0].type).toEqual(MysteryEncounterType.MYSTERIOUS_CHALLENGERS); expect(game.scene.mysteryEncounterSaveData.encounteredEvents[0].type).toEqual(MysteryEncounterType.MYSTERIOUS_CHALLENGERS);
expect(game.scene.mysteryEncounterData.encounteredEvents[0].tier).toEqual(MysteryEncounterTier.GREAT); expect(game.scene.mysteryEncounterSaveData.encounteredEvents[0].tier).toEqual(MysteryEncounterTier.GREAT);
expect(game.scene.ui.getMode()).toBe(Mode.MYSTERY_ENCOUNTER); expect(game.scene.ui.getMode()).toBe(Mode.MYSTERY_ENCOUNTER);
}); });