mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-21 23:09:27 +02:00
Mystery Encounter bugfixes
This commit is contained in:
parent
a259ccfc34
commit
7489bfda17
@ -3416,12 +3416,12 @@
|
|||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": true,
|
"trimmed": true,
|
||||||
"sourceSize": {
|
"sourceSize": {
|
||||||
"w": 24,
|
"w": 32,
|
||||||
"h": 24
|
"h": 32
|
||||||
},
|
},
|
||||||
"spriteSourceSize": {
|
"spriteSourceSize": {
|
||||||
"x": 1,
|
"x": 5,
|
||||||
"y": 2,
|
"y": 7,
|
||||||
"w": 22,
|
"w": 22,
|
||||||
"h": 19
|
"h": 19
|
||||||
},
|
},
|
||||||
@ -8415,6 +8415,6 @@
|
|||||||
"meta": {
|
"meta": {
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
"version": "3.0",
|
"version": "3.0",
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:934ea4080bad980d4fea720cc771f133:ed564bc47b79b15a763de57045178e88:110e074689c9edd2c54833ce2e4d9270$"
|
"smartupdate": "$TexturePacker:SmartUpdate:9ef21166268f7487fc9ff8d0f9b996e4:82658ac7bdd4c2b417e1f59168179262:110e074689c9edd2c54833ce2e4d9270$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 285 B |
@ -86,7 +86,7 @@ import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-ph
|
|||||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||||
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
||||||
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome } from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-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";
|
||||||
@ -1206,12 +1206,10 @@ 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
|
||||||
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex, mysteryEncounterType) || newBattleType === BattleType.MYSTERY_ENCOUNTER) {
|
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex) || newBattleType === BattleType.MYSTERY_ENCOUNTER) {
|
||||||
newBattleType = BattleType.MYSTERY_ENCOUNTER;
|
newBattleType = BattleType.MYSTERY_ENCOUNTER;
|
||||||
// Reset base spawn weight
|
// Reset to base spawn weight
|
||||||
this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
|
this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
|
||||||
} else if (newBattleType === BattleType.WILD) {
|
|
||||||
this.mysteryEncounterSaveData.encounterSpawnChance += WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3117,18 +3115,26 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if a wave COULD spawn a {@linkcode MysteryEncounter}.
|
||||||
|
* Even if returns `true`, does not guarantee that a wave will actually be a ME.
|
||||||
|
* That check is made in {@linkcode BattleScene.isWaveMysteryEncounter} instead.
|
||||||
|
*/
|
||||||
|
isMysteryEncounterValidForWave(battleType: BattleType, waveIndex: number): boolean {
|
||||||
|
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||||
|
return this.gameMode.hasMysteryEncounters && battleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether a wave should randomly generate a {@linkcode MysteryEncounter}.
|
* Determines whether a wave should randomly generate a {@linkcode MysteryEncounter}.
|
||||||
* Currently, the only modes that MEs are allowed in are Classic and Challenge.
|
* Currently, the only modes that MEs are allowed in are Classic and Challenge.
|
||||||
* Additionally, MEs cannot spawn outside of waves 10-180 in those modes
|
* Additionally, MEs cannot spawn outside of waves 10-180 in those modes
|
||||||
*
|
|
||||||
* @param newBattleType
|
* @param newBattleType
|
||||||
* @param waveIndex
|
* @param waveIndex
|
||||||
* @param sessionDataEncounterType
|
|
||||||
*/
|
*/
|
||||||
private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number, sessionDataEncounterType?: MysteryEncounterType): boolean {
|
private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number): boolean {
|
||||||
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||||
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave) {
|
if (this.isMysteryEncounterValidForWave(newBattleType, waveIndex)) {
|
||||||
// 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.mysteryEncounterSaveData.encounterSpawnChance;
|
const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
|
||||||
const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents;
|
const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents;
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { Type } from "#app/data/type";
|
import { Type } from "#app/data/type";
|
||||||
import { isNullOrUndefined } from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
|
import { Nature } from "#enums/nature";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data that can customize a Pokemon in non-standard ways from its Species
|
* Data that can customize a Pokemon in non-standard ways from its Species
|
||||||
* Currently only used by Mystery Encounters, may need to be renamed if it becomes more widely used
|
* Currently only used by Mystery Encounters and Mints.
|
||||||
*/
|
*/
|
||||||
export class MysteryEncounterPokemonData {
|
export class CustomPokemonData {
|
||||||
public spriteScale: number;
|
public spriteScale: number;
|
||||||
public ability: Abilities | -1;
|
public ability: Abilities | -1;
|
||||||
public passive: Abilities | -1;
|
public passive: Abilities | -1;
|
||||||
|
public nature: Nature | -1;
|
||||||
public types: Type[];
|
public types: Type[];
|
||||||
|
|
||||||
constructor(data?: MysteryEncounterPokemonData | Partial<MysteryEncounterPokemonData>) {
|
constructor(data?: CustomPokemonData | Partial<CustomPokemonData>) {
|
||||||
if (!isNullOrUndefined(data)) {
|
if (!isNullOrUndefined(data)) {
|
||||||
Object.assign(this, data);
|
Object.assign(this, data);
|
||||||
}
|
}
|
||||||
@ -20,6 +22,7 @@ export class MysteryEncounterPokemonData {
|
|||||||
this.spriteScale = this.spriteScale ?? -1;
|
this.spriteScale = this.spriteScale ?? -1;
|
||||||
this.ability = this.ability ?? -1;
|
this.ability = this.ability ?? -1;
|
||||||
this.passive = this.passive ?? -1;
|
this.passive = this.passive ?? -1;
|
||||||
|
this.nature = this.nature ?? -1;
|
||||||
this.types = this.types ?? [];
|
this.types = this.types ?? [];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -41,7 +41,7 @@ import { AttackTypeBoosterModifierType, ModifierTypeOption, modifierTypes } from
|
|||||||
import {
|
import {
|
||||||
AttackTypeBoosterModifier,
|
AttackTypeBoosterModifier,
|
||||||
BypassSpeedChanceModifier,
|
BypassSpeedChanceModifier,
|
||||||
ContactHeldItemTransferChanceModifier,
|
ContactHeldItemTransferChanceModifier, GigantamaxAccessModifier, MegaEvolutionAccessModifier,
|
||||||
PokemonHeldItemModifier
|
PokemonHeldItemModifier
|
||||||
} from "#app/modifier/modifier";
|
} from "#app/modifier/modifier";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
@ -355,10 +355,16 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
// If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to a Master Ball
|
// If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to Dynamax Band, Mega Band, and Master Ball
|
||||||
const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)! ];
|
const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)! ];
|
||||||
const specialOptions: ModifierTypeOption[] = [];
|
const specialOptions: ModifierTypeOption[] = [];
|
||||||
|
|
||||||
|
if (!scene.findModifier(m => m instanceof MegaEvolutionAccessModifier)) {
|
||||||
|
specialOptions.push(generateModifierTypeOption(scene, modifierTypes.MEGA_BRACELET)!);
|
||||||
|
}
|
||||||
|
if (!scene.findModifier(m => m instanceof GigantamaxAccessModifier)) {
|
||||||
|
specialOptions.push(generateModifierTypeOption(scene, modifierTypes.DYNAMAX_BAND)!);
|
||||||
|
}
|
||||||
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
|
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
|
||||||
if (nonRareEvolutionModifier) {
|
if (nonRareEvolutionModifier) {
|
||||||
specialOptions.push(nonRareEvolutionModifier);
|
specialOptions.push(nonRareEvolutionModifier);
|
||||||
|
@ -28,7 +28,7 @@ import { BattlerIndex } from "#app/battle";
|
|||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
import { 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 { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
import { EncounterAnim } from "#enums/encounter-anims";
|
import { EncounterAnim } from "#enums/encounter-anims";
|
||||||
import { Challenges } from "#enums/challenges";
|
import { Challenges } from "#enums/challenges";
|
||||||
@ -133,7 +133,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),
|
||||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ]}),
|
customPokemonData: new CustomPokemonData({ ability: ability, types: [ 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 ]
|
||||||
},
|
},
|
||||||
@ -352,15 +352,15 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||||||
newTypes.push(secondType);
|
newTypes.push(secondType);
|
||||||
|
|
||||||
// Apply the type changes (to both base and fusion, if pokemon is fused)
|
// Apply the type changes (to both base and fusion, if pokemon is fused)
|
||||||
if (!pokemon.mysteryEncounterPokemonData) {
|
if (!pokemon.customPokemonData) {
|
||||||
pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
pokemon.customPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
pokemon.mysteryEncounterPokemonData.types = newTypes;
|
pokemon.customPokemonData.types = newTypes;
|
||||||
if (pokemon.isFusion()) {
|
if (pokemon.isFusion()) {
|
||||||
if (!pokemon.fusionMysteryEncounterPokemonData) {
|
if (!pokemon.fusionCustomPokemonData) {
|
||||||
pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
pokemon.fusionCustomPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
pokemon.fusionMysteryEncounterPokemonData.types = newTypes;
|
pokemon.fusionCustomPokemonData.types = newTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -425,15 +425,15 @@ function onYesAbilitySwap(scene: BattleScene, resolve) {
|
|||||||
// Do ability swap
|
// Do ability swap
|
||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
if (pokemon.isFusion()) {
|
if (pokemon.isFusion()) {
|
||||||
if (!pokemon.fusionMysteryEncounterPokemonData) {
|
if (!pokemon.fusionCustomPokemonData) {
|
||||||
pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
pokemon.fusionCustomPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
pokemon.fusionMysteryEncounterPokemonData.ability = encounter.misc.ability;
|
pokemon.fusionCustomPokemonData.ability = encounter.misc.ability;
|
||||||
} else {
|
} else {
|
||||||
if (!pokemon.mysteryEncounterPokemonData) {
|
if (!pokemon.customPokemonData) {
|
||||||
pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
pokemon.customPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
pokemon.mysteryEncounterPokemonData.ability = encounter.misc.ability;
|
pokemon.customPokemonData.ability = encounter.misc.ability;
|
||||||
}
|
}
|
||||||
encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender());
|
encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender());
|
||||||
scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true));
|
scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true));
|
||||||
|
@ -137,7 +137,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||||||
newNature = randSeedInt(25) as Nature;
|
newNature = randSeedInt(25) as Nature;
|
||||||
}
|
}
|
||||||
|
|
||||||
chosenPokemon.nature = newNature;
|
chosenPokemon.customPokemonData.nature = newNature;
|
||||||
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
||||||
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
||||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||||
|
@ -18,7 +18,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode
|
|||||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
|
|
||||||
/** i18n namespace for the encounter */
|
/** i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounters/slumberingSnorlax";
|
const namespace = "mysteryEncounters/slumberingSnorlax";
|
||||||
@ -72,7 +72,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
|||||||
stackCount: 2
|
stackCount: 2
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
||||||
aiType: AiType.SMART // Required to ensure Snorlax uses Sleep Talk while it is asleep
|
aiType: AiType.SMART // Required to ensure Snorlax uses Sleep Talk while it is asleep
|
||||||
};
|
};
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
|
@ -163,7 +163,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||||||
if (pokemon2CommonEggs > 0) {
|
if (pokemon2CommonEggs > 0) {
|
||||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||||
pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||||
encounter.setDialogueToken("pokemon1CommonEggs", eggsText);
|
encounter.setDialogueToken("pokemon2CommonEggs", eggsText);
|
||||||
}
|
}
|
||||||
encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip;
|
encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import { BattlerIndex } from "#app/battle";
|
|||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
@ -79,7 +79,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||||||
species: getPokemonSpecies(Species.SHUCKLE),
|
species: getPokemonSpecies(Species.SHUCKLE),
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
bossSegments: 5,
|
bossSegments: 5,
|
||||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
customPokemonData: new CustomPokemonData({ spriteScale: 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: [
|
||||||
|
@ -12,7 +12,7 @@ import { IntegerHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "
|
|||||||
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { achvs } from "#app/system/achv";
|
import { achvs } from "#app/system/achv";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
@ -378,10 +378,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.mysteryEncounterPokemonData) {
|
if (!newPokemon.customPokemonData) {
|
||||||
newPokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
newPokemon.customPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
newPokemon.mysteryEncounterPokemonData.types = newTypes;
|
newPokemon.customPokemonData.types = newTypes;
|
||||||
|
|
||||||
for (const item of transformation.heldItems) {
|
for (const item of transformation.heldItems) {
|
||||||
item.pokemonId = newPokemon.id;
|
item.pokemonId = newPokemon.id;
|
||||||
|
@ -577,10 +577,10 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
|
|||||||
|
|
||||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
if (!this.invertQuery) {
|
if (!this.invertQuery) {
|
||||||
return partyPokemon.filter((pokemon) => this.requiredAbilities.some((ability) => pokemon.getAbility().id === ability));
|
return partyPokemon.filter((pokemon) => this.requiredAbilities.some((ability) => pokemon.getAbility().id === ability || pokemon.getPassiveAbility().id === ability));
|
||||||
} else {
|
} else {
|
||||||
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilitiess
|
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilities
|
||||||
return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((ability) => pokemon.getAbility().id === ability).length === 0);
|
return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((ability) => pokemon.getAbility().id === ability || pokemon.getPassiveAbility().id === ability).length === 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import { Status, StatusEffect } from "#app/data/status-effect";
|
|||||||
import { TrainerConfig, trainerConfigs, TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerConfig, trainerConfigs, TrainerSlot } from "#app/data/trainer-config";
|
||||||
import PokemonSpecies from "#app/data/pokemon-species";
|
import PokemonSpecies from "#app/data/pokemon-species";
|
||||||
import { Egg, IEggOptions } from "#app/data/egg";
|
import { Egg, IEggOptions } from "#app/data/egg";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
import { MovePhase } from "#app/phases/move-phase";
|
||||||
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
||||||
@ -71,7 +71,7 @@ export interface EnemyPokemonConfig {
|
|||||||
nickname?: string;
|
nickname?: string;
|
||||||
bossSegments?: number;
|
bossSegments?: number;
|
||||||
bossSegmentModifier?: number; // Additive to the determined segment number
|
bossSegmentModifier?: number; // Additive to the determined segment number
|
||||||
mysteryEncounterPokemonData?: MysteryEncounterPokemonData;
|
customPokemonData?: CustomPokemonData;
|
||||||
formIndex?: number;
|
formIndex?: number;
|
||||||
abilityIndex?: number;
|
abilityIndex?: number;
|
||||||
level?: number;
|
level?: number;
|
||||||
@ -145,7 +145,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
newTrainer.setVisible(false);
|
newTrainer.setVisible(false);
|
||||||
scene.field.add(newTrainer);
|
scene.field.add(newTrainer);
|
||||||
scene.currentBattle.trainer = newTrainer;
|
scene.currentBattle.trainer = newTrainer;
|
||||||
loadEnemyAssets.push(newTrainer.loadAssets());
|
loadEnemyAssets.push(newTrainer.loadAssets().then(() => newTrainer.initSprite()));
|
||||||
|
|
||||||
battle.enemyLevels = scene.currentBattle.trainer.getPartyLevels(scene.currentBattle.waveIndex);
|
battle.enemyLevels = scene.currentBattle.trainer.getPartyLevels(scene.currentBattle.waveIndex);
|
||||||
} else {
|
} else {
|
||||||
@ -250,8 +250,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.mysteryEncounterPokemonData)) {
|
if (!isNullOrUndefined(config.customPokemonData)) {
|
||||||
enemyPokemon.mysteryEncounterPokemonData = config.mysteryEncounterPokemonData;
|
enemyPokemon.customPokemonData = config.customPokemonData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Boss
|
// Set Boss
|
||||||
|
@ -62,7 +62,7 @@ import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-ph
|
|||||||
import { Challenges } from "#enums/challenges";
|
import { Challenges } from "#enums/challenges";
|
||||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||||
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { SwitchType } from "#enums/switch-type";
|
import { SwitchType } from "#enums/switch-type";
|
||||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
|
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
|
||||||
@ -114,7 +114,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
public fusionVariant: Variant;
|
public fusionVariant: Variant;
|
||||||
public fusionGender: Gender;
|
public fusionGender: Gender;
|
||||||
public fusionLuck: integer;
|
public fusionLuck: integer;
|
||||||
public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData | null;
|
public fusionCustomPokemonData: CustomPokemonData | null;
|
||||||
|
|
||||||
private summonDataPrimer: PokemonSummonData | null;
|
private summonDataPrimer: PokemonSummonData | null;
|
||||||
|
|
||||||
@ -122,7 +122,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 mysteryEncounterPokemonData: MysteryEncounterPokemonData;
|
public customPokemonData: CustomPokemonData;
|
||||||
|
|
||||||
/** 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;
|
||||||
@ -193,7 +193,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
this.nature = dataSource.nature || 0 as Nature;
|
this.nature = dataSource.nature || 0 as Nature;
|
||||||
this.nickname = dataSource.nickname;
|
this.nickname = dataSource.nickname;
|
||||||
this.natureOverride = dataSource.natureOverride !== undefined ? dataSource.natureOverride : -1;
|
|
||||||
this.moveset = dataSource.moveset;
|
this.moveset = dataSource.moveset;
|
||||||
this.status = dataSource.status!; // TODO: is this bang correct?
|
this.status = dataSource.status!; // TODO: is this bang correct?
|
||||||
this.friendship = dataSource.friendship !== undefined ? dataSource.friendship : this.species.baseFriendship;
|
this.friendship = dataSource.friendship !== undefined ? dataSource.friendship : this.species.baseFriendship;
|
||||||
@ -212,9 +211,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.fusionVariant = dataSource.fusionVariant || 0;
|
this.fusionVariant = dataSource.fusionVariant || 0;
|
||||||
this.fusionGender = dataSource.fusionGender;
|
this.fusionGender = dataSource.fusionGender;
|
||||||
this.fusionLuck = dataSource.fusionLuck;
|
this.fusionLuck = dataSource.fusionLuck;
|
||||||
this.fusionMysteryEncounterPokemonData = dataSource.fusionMysteryEncounterPokemonData;
|
this.fusionCustomPokemonData = dataSource.fusionCustomPokemonData;
|
||||||
this.usedTMs = dataSource.usedTMs ?? [];
|
this.usedTMs = dataSource.usedTMs ?? [];
|
||||||
this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(dataSource.mysteryEncounterPokemonData);
|
this.customPokemonData = new CustomPokemonData(dataSource.customPokemonData);
|
||||||
} 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);
|
||||||
@ -235,7 +234,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.variant = this.shiny ? this.generateVariant() : 0;
|
this.variant = this.shiny ? this.generateVariant() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
this.customPokemonData = new CustomPokemonData();
|
||||||
|
|
||||||
if (nature !== undefined) {
|
if (nature !== undefined) {
|
||||||
this.setNature(nature);
|
this.setNature(nature);
|
||||||
@ -243,8 +242,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.generateNature();
|
this.generateNature();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.natureOverride = -1;
|
|
||||||
|
|
||||||
this.friendship = species.baseFriendship;
|
this.friendship = species.baseFriendship;
|
||||||
this.metLevel = level;
|
this.metLevel = level;
|
||||||
this.metBiome = scene.currentBattle ? scene.arena.biomeType : -1;
|
this.metBiome = scene.currentBattle ? scene.arena.biomeType : -1;
|
||||||
@ -593,8 +590,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
const formKey = this.getFormKey();
|
const formKey = this.getFormKey();
|
||||||
if (this.isMax() === true || formKey === "segin-starmobile" || formKey === "schedar-starmobile" || formKey === "navi-starmobile" || formKey === "ruchbah-starmobile" || formKey === "caph-starmobile") {
|
if (this.isMax() === true || formKey === "segin-starmobile" || formKey === "schedar-starmobile" || formKey === "navi-starmobile" || formKey === "ruchbah-starmobile" || formKey === "caph-starmobile") {
|
||||||
return 1.5;
|
return 1.5;
|
||||||
} else if (this.mysteryEncounterPokemonData.spriteScale > 0) {
|
} else if (this.customPokemonData.spriteScale > 0) {
|
||||||
return this.mysteryEncounterPokemonData.spriteScale;
|
return this.customPokemonData.spriteScale;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1012,7 +1009,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getNature(): Nature {
|
getNature(): Nature {
|
||||||
return this.natureOverride !== -1 ? this.natureOverride : this.nature;
|
return this.customPokemonData.nature !== -1 ? this.customPokemonData.nature : this.nature;
|
||||||
}
|
}
|
||||||
|
|
||||||
setNature(nature: Nature): void {
|
setNature(nature: Nature): void {
|
||||||
@ -1187,15 +1184,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if (!types.length || !includeTeraType) {
|
if (!types.length || !includeTeraType) {
|
||||||
if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) {
|
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 if (this.mysteryEncounterPokemonData.types && this.mysteryEncounterPokemonData.types.length > 0) {
|
} else if (this.customPokemonData.types && this.customPokemonData.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
|
||||||
types.push(this.mysteryEncounterPokemonData.types[0]);
|
types.push(this.customPokemonData.types[0]);
|
||||||
|
|
||||||
// Fusing a Pokemon onto something with "permanently changed" types will still apply the fusion's types as normal
|
// Fusing a Pokemon onto something with "permanently changed" types will still apply the fusion's types as normal
|
||||||
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride);
|
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride);
|
||||||
if (fusionSpeciesForm) {
|
if (fusionSpeciesForm) {
|
||||||
// Check if the fusion Pokemon also had "permanently changed" types
|
// Check if the fusion Pokemon also had "permanently changed" types
|
||||||
const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types;
|
const fusionMETypes = this.fusionCustomPokemonData?.types;
|
||||||
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
||||||
types.push(fusionMETypes[1]);
|
types.push(fusionMETypes[1]);
|
||||||
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
||||||
@ -1207,8 +1204,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (types.length === 1 && this.mysteryEncounterPokemonData.types.length >= 2) {
|
if (types.length === 1 && this.customPokemonData.types.length >= 2) {
|
||||||
types.push(this.mysteryEncounterPokemonData.types[1]);
|
types.push(this.customPokemonData.types[1]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const speciesForm = this.getSpeciesForm(ignoreOverride);
|
const speciesForm = this.getSpeciesForm(ignoreOverride);
|
||||||
@ -1219,7 +1216,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if (fusionSpeciesForm) {
|
if (fusionSpeciesForm) {
|
||||||
// Check if the fusion Pokemon also had "permanently changed" types
|
// Check if the fusion Pokemon also had "permanently changed" types
|
||||||
// Otherwise, use standard fusion type logic
|
// Otherwise, use standard fusion type logic
|
||||||
const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types;
|
const fusionMETypes = this.fusionCustomPokemonData?.types;
|
||||||
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
||||||
types.push(fusionMETypes[1]);
|
types.push(fusionMETypes[1]);
|
||||||
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
||||||
@ -1251,6 +1248,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If both types are the same (can happen in weird custom typing scenarios), reduce to single type
|
||||||
|
if (types.length > 1 && types[0] === types[1]) {
|
||||||
|
types.splice(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1277,14 +1279,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
|
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
|
||||||
}
|
}
|
||||||
if (this.isFusion()) {
|
if (this.isFusion()) {
|
||||||
if (!isNullOrUndefined(this.fusionMysteryEncounterPokemonData?.ability) && this.fusionMysteryEncounterPokemonData.ability !== -1) {
|
if (!isNullOrUndefined(this.fusionCustomPokemonData?.ability) && this.fusionCustomPokemonData.ability !== -1) {
|
||||||
return allAbilities[this.fusionMysteryEncounterPokemonData.ability];
|
return allAbilities[this.fusionCustomPokemonData.ability];
|
||||||
} else {
|
} else {
|
||||||
return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)];
|
return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isNullOrUndefined(this.mysteryEncounterPokemonData.ability) && this.mysteryEncounterPokemonData.ability !== -1) {
|
if (!isNullOrUndefined(this.customPokemonData.ability) && this.customPokemonData.ability !== -1) {
|
||||||
return allAbilities[this.mysteryEncounterPokemonData.ability];
|
return allAbilities[this.customPokemonData.ability];
|
||||||
}
|
}
|
||||||
let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex);
|
let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex);
|
||||||
if (abilityId === Abilities.NONE) {
|
if (abilityId === Abilities.NONE) {
|
||||||
@ -1307,8 +1309,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 (!isNullOrUndefined(this.mysteryEncounterPokemonData.passive) && this.mysteryEncounterPokemonData.passive !== -1) {
|
if (!isNullOrUndefined(this.customPokemonData.passive) && this.customPokemonData.passive !== -1) {
|
||||||
return allAbilities[this.mysteryEncounterPokemonData.passive];
|
return allAbilities[this.customPokemonData.passive];
|
||||||
}
|
}
|
||||||
|
|
||||||
let starterSpeciesId = this.species.speciesId;
|
let starterSpeciesId = this.species.speciesId;
|
||||||
@ -2007,7 +2009,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.fusionVariant = 0;
|
this.fusionVariant = 0;
|
||||||
this.fusionGender = 0;
|
this.fusionGender = 0;
|
||||||
this.fusionLuck = 0;
|
this.fusionLuck = 0;
|
||||||
this.fusionMysteryEncounterPokemonData = null;
|
this.fusionCustomPokemonData = null;
|
||||||
|
|
||||||
this.generateName();
|
this.generateName();
|
||||||
this.calculateStats();
|
this.calculateStats();
|
||||||
@ -4274,12 +4276,33 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
|
|
||||||
changeForm(formChange: SpeciesFormChange): Promise<void> {
|
changeForm(formChange: SpeciesFormChange): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
const previousFormIndex = this.formIndex;
|
||||||
this.formIndex = Math.max(this.species.forms.findIndex(f => f.formKey === formChange.formKey), 0);
|
this.formIndex = Math.max(this.species.forms.findIndex(f => f.formKey === formChange.formKey), 0);
|
||||||
this.generateName();
|
this.generateName();
|
||||||
const abilityCount = this.getSpeciesForm().getAbilityCount();
|
const abilityCount = this.getSpeciesForm().getAbilityCount();
|
||||||
if (this.abilityIndex >= abilityCount) { // Shouldn't happen
|
if (this.abilityIndex >= abilityCount) { // Shouldn't happen
|
||||||
this.abilityIndex = abilityCount - 1;
|
this.abilityIndex = abilityCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In cases where a form change updates the type of a Pokemon from its previous form (Arceus, Silvally, Castform, etc.),
|
||||||
|
// persist that type change in customPokemonData if necessary
|
||||||
|
const baseForm = this.species.forms[previousFormIndex];
|
||||||
|
const baseFormTypes = [ baseForm.type1, baseForm.type2 ];
|
||||||
|
if (this.customPokemonData.types.length > 0) {
|
||||||
|
if (this.getSpeciesForm().type1 !== baseFormTypes[0]) {
|
||||||
|
this.customPokemonData.types[0] = this.getSpeciesForm().type1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const type2 = this.getSpeciesForm().type2;
|
||||||
|
if (!isNullOrUndefined(type2) && type2 !== baseFormTypes[1]) {
|
||||||
|
if (this.customPokemonData.types.length > 1) {
|
||||||
|
this.customPokemonData.types[1] = type2;
|
||||||
|
} else {
|
||||||
|
this.customPokemonData.types.push(type2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.compatibleTms.splice(0, this.compatibleTms.length);
|
this.compatibleTms.splice(0, this.compatibleTms.length);
|
||||||
this.generateCompatibleTms();
|
this.generateCompatibleTms();
|
||||||
const updateAndResolve = () => {
|
const updateAndResolve = () => {
|
||||||
@ -4316,7 +4339,7 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
this.fusionVariant = pokemon.variant;
|
this.fusionVariant = pokemon.variant;
|
||||||
this.fusionGender = pokemon.gender;
|
this.fusionGender = pokemon.gender;
|
||||||
this.fusionLuck = pokemon.luck;
|
this.fusionLuck = pokemon.luck;
|
||||||
this.fusionMysteryEncounterPokemonData = pokemon.mysteryEncounterPokemonData;
|
this.fusionCustomPokemonData = pokemon.customPokemonData;
|
||||||
if ((pokemon.pauseEvolutions) || (this.pauseEvolutions)) {
|
if ((pokemon.pauseEvolutions) || (this.pauseEvolutions)) {
|
||||||
this.pauseEvolutions = true;
|
this.pauseEvolutions = true;
|
||||||
}
|
}
|
||||||
|
@ -1126,7 +1126,7 @@ class EvolutionItemModifierTypeGenerator extends ModifierTypeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||||
constructor(rare: boolean) {
|
constructor(isRareFormChangeItem: boolean) {
|
||||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
super((party: Pokemon[], pregenArgs?: any[]) => {
|
||||||
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in FormChangeItem)) {
|
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in FormChangeItem)) {
|
||||||
return new FormChangeItemModifierType(pregenArgs[0] as FormChangeItem);
|
return new FormChangeItemModifierType(pregenArgs[0] as FormChangeItem);
|
||||||
@ -1167,7 +1167,7 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
|||||||
}
|
}
|
||||||
return formChangeItemTriggers;
|
return formChangeItemTriggers;
|
||||||
}).flat())
|
}).flat())
|
||||||
].flat().flatMap(fc => fc.item).filter(i => (i && i < 100) === rare);
|
].flat().flatMap(fc => fc.item).filter(i => (i && i < 100) === isRareFormChangeItem);
|
||||||
// convert it into a set to remove duplicate values, which can appear when the same species with a potential form change is in the party.
|
// convert it into a set to remove duplicate values, which can appear when the same species with a potential form change is in the party.
|
||||||
|
|
||||||
if (!formChangeItemPool.length) {
|
if (!formChangeItemPool.length) {
|
||||||
|
@ -2180,7 +2180,7 @@ export class PokemonNatureChangeModifier extends ConsumablePokemonModifier {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
override apply(playerPokemon: PlayerPokemon): boolean {
|
override apply(playerPokemon: PlayerPokemon): boolean {
|
||||||
playerPokemon.natureOverride = this.nature;
|
playerPokemon.customPokemonData.nature = this.nature;
|
||||||
let speciesId = playerPokemon.species.speciesId;
|
let speciesId = playerPokemon.species.speciesId;
|
||||||
playerPokemon.scene.gameData.dexData[speciesId].natureAttr |= 1 << (this.nature + 1);
|
playerPokemon.scene.gameData.dexData[speciesId].natureAttr |= 1 << (this.nature + 1);
|
||||||
|
|
||||||
|
@ -31,7 +31,10 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
const overrides = {} satisfies Partial<InstanceType<typeof DefaultOverrides>>;
|
const overrides = {
|
||||||
|
MYSTERY_ENCOUNTER_RATE_OVERRIDE: 256,
|
||||||
|
MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType.WEIRD_DREAM
|
||||||
|
} satisfies Partial<InstanceType<typeof DefaultOverrides>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If you need to add Overrides values for local testing do that inside {@linkcode overrides}
|
* If you need to add Overrides values for local testing do that inside {@linkcode overrides}
|
||||||
|
@ -35,6 +35,7 @@ import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-d
|
|||||||
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
||||||
import { getGoldenBugNetSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { getGoldenBugNetSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { Biome } from "#enums/biome";
|
import { Biome } from "#enums/biome";
|
||||||
|
import { WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
|
|
||||||
export class EncounterPhase extends BattlePhase {
|
export class EncounterPhase extends BattlePhase {
|
||||||
private loaded: boolean;
|
private loaded: boolean;
|
||||||
@ -68,7 +69,7 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
this.scene.executeWithSeedOffset(() => {
|
this.scene.executeWithSeedOffset(() => {
|
||||||
const currentSessionEncounterType = battle.mysteryEncounterType;
|
const currentSessionEncounterType = battle.mysteryEncounterType;
|
||||||
battle.mysteryEncounter = this.scene.getMysteryEncounter(currentSessionEncounterType);
|
battle.mysteryEncounter = this.scene.getMysteryEncounter(currentSessionEncounterType);
|
||||||
}, battle.waveIndex << 4);
|
}, battle.waveIndex * 16);
|
||||||
}
|
}
|
||||||
const mysteryEncounter = battle.mysteryEncounter;
|
const mysteryEncounter = battle.mysteryEncounter;
|
||||||
if (mysteryEncounter) {
|
if (mysteryEncounter) {
|
||||||
@ -251,6 +252,13 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
this.scene.updateModifiers(true);
|
this.scene.updateModifiers(true);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
const { battleType, waveIndex, isBattleMysteryEncounter } = this.scene.currentBattle;
|
||||||
|
if (this.scene.isMysteryEncounterValidForWave(battleType, waveIndex) && !isBattleMysteryEncounter()) {
|
||||||
|
// Increment ME spawn chance if an ME could have spawned but did not
|
||||||
|
// Only do this AFTER session has been saved to avoid duplicating increments
|
||||||
|
this.scene.mysteryEncounterSaveData.encounterSpawnChance += WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
||||||
|
}
|
||||||
|
|
||||||
for (const pokemon of this.scene.getParty()) {
|
for (const pokemon of this.scene.getParty()) {
|
||||||
if (pokemon) {
|
if (pokemon) {
|
||||||
pokemon.resetBattleData();
|
pokemon.resetBattleData();
|
||||||
|
@ -12,7 +12,7 @@ import { loadBattlerTag } from "../data/battler-tags";
|
|||||||
import { Biome } from "#enums/biome";
|
import { Biome } from "#enums/biome";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
|
|
||||||
export default class PokemonData {
|
export default class PokemonData {
|
||||||
public id: integer;
|
public id: integer;
|
||||||
@ -54,14 +54,14 @@ export default class PokemonData {
|
|||||||
public fusionVariant: Variant;
|
public fusionVariant: Variant;
|
||||||
public fusionGender: Gender;
|
public fusionGender: Gender;
|
||||||
public fusionLuck: integer;
|
public fusionLuck: integer;
|
||||||
public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData;
|
public fusionCustomPokemonData: CustomPokemonData;
|
||||||
|
|
||||||
public boss: boolean;
|
public boss: boolean;
|
||||||
public bossSegments?: integer;
|
public bossSegments?: integer;
|
||||||
|
|
||||||
public summonData: PokemonSummonData;
|
public summonData: PokemonSummonData;
|
||||||
/** Data that can customize a Pokemon in non-standard ways from its Species */
|
/** Data that can customize a Pokemon in non-standard ways from its Species */
|
||||||
public mysteryEncounterPokemonData: MysteryEncounterPokemonData;
|
public customPokemonData: CustomPokemonData;
|
||||||
|
|
||||||
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;
|
||||||
@ -107,9 +107,10 @@ export default class PokemonData {
|
|||||||
this.fusionVariant = source.fusionVariant;
|
this.fusionVariant = source.fusionVariant;
|
||||||
this.fusionGender = source.fusionGender;
|
this.fusionGender = source.fusionGender;
|
||||||
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.fusionCustomPokemonData = new CustomPokemonData(source.fusionCustomPokemonData);
|
||||||
this.usedTMs = source.usedTMs ?? [];
|
this.usedTMs = source.usedTMs ?? [];
|
||||||
|
|
||||||
this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(source.mysteryEncounterPokemonData);
|
this.customPokemonData = new CustomPokemonData(source.customPokemonData);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { allSpecies } from "#app/data/pokemon-species";
|
import { allSpecies } from "#app/data/pokemon-species";
|
||||||
import { AbilityAttr, defaultStarterSpecies, DexAttr, SessionSaveData, SystemSaveData } from "./game-data";
|
import { AbilityAttr, defaultStarterSpecies, DexAttr, SessionSaveData, SystemSaveData } from "./game-data";
|
||||||
import { SettingKeys } from "./settings/settings";
|
import { SettingKeys } from "./settings/settings";
|
||||||
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
|
|
||||||
const LATEST_VERSION = "1.0.5";
|
const LATEST_VERSION = "1.0.5";
|
||||||
|
|
||||||
@ -75,6 +76,20 @@ export function applySessionDataPatches(data: SessionSaveData) {
|
|||||||
|
|
||||||
data.gameVersion = LATEST_VERSION;
|
data.gameVersion = LATEST_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix Pokemon nature overrides and custom data migration
|
||||||
|
data.party.forEach(pokemon => {
|
||||||
|
if (pokemon["mysteryEncounterData"]) {
|
||||||
|
pokemon.customPokemonData = new CustomPokemonData(pokemon["mysteryEncounterData"]);
|
||||||
|
}
|
||||||
|
if (pokemon["fusionMysteryEncounterData"]) {
|
||||||
|
pokemon.fusionCustomPokemonData = new CustomPokemonData(pokemon["fusionMysteryEncounterData"]);
|
||||||
|
}
|
||||||
|
pokemon.customPokemonData = pokemon.customPokemonData ?? new CustomPokemonData();
|
||||||
|
if (pokemon["natureOverride"]) {
|
||||||
|
pokemon.customPokemonData.nature = pokemon["natureOverride"];
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function applySystemDataPatches(data: SystemSaveData) {
|
export function applySystemDataPatches(data: SystemSaveData) {
|
||||||
|
@ -118,11 +118,11 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||||||
});
|
});
|
||||||
expect(config.pokemonConfigs?.[1]).toEqual({
|
expect(config.pokemonConfigs?.[1]).toEqual({
|
||||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
species: getPokemonSpecies(Species.BLACEPHALON),
|
||||||
mysteryEncounterPokemonData: expect.anything(),
|
customPokemonData: 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].mysteryEncounterPokemonData?.types.length).toBe(2);
|
expect(config.pokemonConfigs?.[1].customPokemonData?.types.length).toBe(2);
|
||||||
expect([
|
expect([
|
||||||
Abilities.STURDY,
|
Abilities.STURDY,
|
||||||
Abilities.PICKUP,
|
Abilities.PICKUP,
|
||||||
@ -139,8 +139,8 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||||||
Abilities.MAGICIAN,
|
Abilities.MAGICIAN,
|
||||||
Abilities.SHEER_FORCE,
|
Abilities.SHEER_FORCE,
|
||||||
Abilities.PRANKSTER
|
Abilities.PRANKSTER
|
||||||
]).toContain(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.ability);
|
]).toContain(config.pokemonConfigs?.[1].customPokemonData?.ability);
|
||||||
expect(ClowningAroundEncounter.misc.ability).toBe(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.ability);
|
expect(ClowningAroundEncounter.misc.ability).toBe(config.pokemonConfigs?.[1].customPokemonData?.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);
|
||||||
@ -219,7 +219,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.mysteryEncounterPokemonData?.ability).toBe(abilityToTrain);
|
expect(leadPokemon.customPokemonData?.ability).toBe(abilityToTrain);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -340,9 +340,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].mysteryEncounterPokemonData?.types;
|
const leadTypesAfter = scene.getParty()[0].customPokemonData?.types;
|
||||||
const secondaryTypesAfter = scene.getParty()[1].mysteryEncounterPokemonData?.types;
|
const secondaryTypesAfter = scene.getParty()[1].customPokemonData?.types;
|
||||||
const thirdTypesAfter = scene.getParty()[2].mysteryEncounterPokemonData?.types;
|
const thirdTypesAfter = scene.getParty()[2].customPokemonData?.types;
|
||||||
|
|
||||||
expect(leadTypesAfter.length).toBe(2);
|
expect(leadTypesAfter.length).toBe(2);
|
||||||
expect(leadTypesAfter[0]).toBe(Type.WATER);
|
expect(leadTypesAfter[0]).toBe(Type.WATER);
|
||||||
|
@ -21,7 +21,7 @@ import { BerryModifier, PokemonBaseStatTotalModifier } from "#app/modifier/modif
|
|||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
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 { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { CommandPhase } from "#app/phases/command-phase";
|
import { CommandPhase } from "#app/phases/command-phase";
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
import { MovePhase } from "#app/phases/move-phase";
|
||||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||||
@ -109,7 +109,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
species: getPokemonSpecies(Species.SHUCKLE),
|
species: getPokemonSpecies(Species.SHUCKLE),
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
bossSegments: 5,
|
bossSegments: 5,
|
||||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
customPokemonData: new CustomPokemonData({ spriteScale: 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),
|
||||||
|
@ -122,7 +122,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.mysteryEncounterPokemonData?.types.length).toBe(2);
|
expect(newPokemon.customPokemonData?.types.length).toBe(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const plus90To110 = bstDiff.filter(bst => bst > 80);
|
const plus90To110 = bstDiff.filter(bst => bst > 80);
|
||||||
|
Loading…
Reference in New Issue
Block a user