From a67da46ea217afafd0bd6d7e55aa634bcbf48b90 Mon Sep 17 00:00:00 2001 From: Moka Date: Thu, 7 Nov 2024 23:31:06 +0100 Subject: [PATCH] [ME] Shiny lock MEs with custom or special sprites --- src/battle-scene.ts | 4 ++-- .../encounters/absolute-avarice-encounter.ts | 3 ++- .../encounters/dancing-lessons-encounter.ts | 2 +- .../encounters/fun-and-games-encounter.ts | 4 ++-- .../encounters/trash-to-treasure-encounter.ts | 3 ++- .../mystery-encounters/utils/encounter-phase-utils.ts | 4 ++-- src/data/trainer-config.ts | 4 ++-- src/field/pokemon.ts | 10 ++++++---- src/system/pokemon-data.ts | 2 +- 9 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index d1d520f5f9d..1ef732a5c34 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -890,7 +890,7 @@ export default class BattleScene extends SceneBase { return pokemon; } - addEnemyPokemon(species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean = false, dataSource?: PokemonData, postProcess?: (enemyPokemon: EnemyPokemon) => void): EnemyPokemon { + addEnemyPokemon(species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean = false, shinyLock: boolean = false, dataSource?: PokemonData, postProcess?: (enemyPokemon: EnemyPokemon) => void): EnemyPokemon { if (Overrides.OPP_LEVEL_OVERRIDE > 0) { level = Overrides.OPP_LEVEL_OVERRIDE; } @@ -900,7 +900,7 @@ export default class BattleScene extends SceneBase { boss = this.getEncounterBossSegments(this.currentBattle.waveIndex, level, species) > 1; } - const pokemon = new EnemyPokemon(this, species, level, trainerSlot, boss, dataSource); + const pokemon = new EnemyPokemon(this, species, level, trainerSlot, boss, shinyLock, dataSource); if (Overrides.OPP_FUSION_OVERRIDE) { pokemon.generateFusionSpecies(); } diff --git a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts index fa8e1aed1c7..3dbd842a1c6 100644 --- a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts +++ b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts @@ -216,6 +216,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = species: getPokemonSpecies(Species.GREEDENT), isBoss: true, bossSegments: 3, + shiny: false, moveSet: [ Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH ], modifierConfigs: bossModifierConfigs, tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], @@ -355,7 +356,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = // Let it have the food // Greedent joins the team, level equal to 2 below highest party member const level = getHighestLevelPlayerPokemon(scene, false, true).level - 2; - const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false); + const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false, true); greedent.moveset = [ new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF) ]; greedent.passive = true; diff --git a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts index bae5a8790e9..f0dcc238eb0 100644 --- a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts +++ b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts @@ -136,7 +136,7 @@ export const DancingLessonsEncounter: MysteryEncounter = } const oricorioData = new PokemonData(enemyPokemon); - const oricorio = scene.addEnemyPokemon(species, level, TrainerSlot.NONE, false, oricorioData); + const oricorio = scene.addEnemyPokemon(species, level, TrainerSlot.NONE, false, false, oricorioData); // Adds a real Pokemon sprite to the field (required for the animation) scene.getEnemyParty().forEach(enemyPokemon => { diff --git a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts index 7bf48aa5926..882104becbd 100644 --- a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts +++ b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts @@ -194,10 +194,10 @@ async function summonPlayerPokemon(scene: BattleScene) { playerAnimationPromise = summonPlayerPokemonAnimation(scene, playerPokemon); }); - // Also loads Wobbuffet data + // Also loads Wobbuffet data (cannot be shiny) const enemySpecies = getPokemonSpecies(Species.WOBBUFFET); scene.currentBattle.enemyParty = []; - const wobbuffet = scene.addEnemyPokemon(enemySpecies, encounter.misc.playerPokemon.level, TrainerSlot.NONE, false); + const wobbuffet = scene.addEnemyPokemon(enemySpecies, encounter.misc.playerPokemon.level, TrainerSlot.NONE, false, true); wobbuffet.ivs = [ 0, 0, 0, 0, 0, 0 ]; wobbuffet.setNature(Nature.MILD); wobbuffet.setAlpha(0); diff --git a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts index fba3a6ca95e..7573a088c78 100644 --- a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts +++ b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts @@ -61,11 +61,12 @@ export const TrashToTreasureEncounter: MysteryEncounter = .withOnInit((scene: BattleScene) => { const encounter = scene.currentBattle.mysteryEncounter!; - // Calculate boss mon + // Calculate boss mon (shiny locked) const bossSpecies = getPokemonSpecies(Species.GARBODOR); const pokemonConfig: EnemyPokemonConfig = { species: bossSpecies, isBoss: true, + shiny: false, formIndex: 1, // Gmax bossSegmentModifier: 1, // +1 Segment from normal moveSet: [ Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH ] diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index 429b6bfa292..186b2eb9477 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -183,7 +183,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig: dataSource = config.dataSource; enemySpecies = config.species; isBoss = config.isBoss; - battle.enemyParty[e] = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.TRAINER, isBoss, dataSource); + battle.enemyParty[e] = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.TRAINER, isBoss, false, dataSource); } else { battle.enemyParty[e] = battle.trainer.genPartyMember(e); } @@ -201,7 +201,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig: enemySpecies = scene.randomSpecies(battle.waveIndex, level, true); } - battle.enemyParty[e] = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, isBoss, dataSource); + battle.enemyParty[e] = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, isBoss, false, dataSource); } } diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 18bcec1f928..9bf0a92f5dc 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -1173,7 +1173,7 @@ export function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: Tr if (!ignoreEvolution) { species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex); } - return scene.addEnemyPokemon(getPokemonSpecies(species), level, trainerSlot, undefined, undefined, postProcess); + return scene.addEnemyPokemon(getPokemonSpecies(species), level, trainerSlot, undefined, false, undefined, postProcess); }; } @@ -1181,7 +1181,7 @@ function getSpeciesFilterRandomPartyMemberFunc(speciesFilter: PokemonSpeciesFilt const originalSpeciesFilter = speciesFilter; speciesFilter = (species: PokemonSpecies) => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden() && originalSpeciesFilter(species); return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => { - const ret = scene.addEnemyPokemon(getPokemonSpecies(scene.randomSpecies(scene.currentBattle.waveIndex, level, false, speciesFilter).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex)), level, trainerSlot, undefined, undefined, postProcess); + const ret = scene.addEnemyPokemon(getPokemonSpecies(scene.randomSpecies(scene.currentBattle.waveIndex, level, false, speciesFilter).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex)), level, trainerSlot, undefined, false, undefined, postProcess); return ret; }; } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index dcd75f34fc5..f3e8ae35671 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1954,6 +1954,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { /** * Function that tries to set a Pokemon shiny based on seed. * For manual use only, usually to roll a Pokemon's shiny chance a second time. + * If it rolls shiny, also sets a random variant and give the Pokemon the associated luck. * * The base shiny odds are {@linkcode BASE_SHINY_CHANCE} / `65536` * @param thresholdOverride number that is divided by `2^16` (`65536`) to get the shiny chance, overrides {@linkcode shinyThreshold} if set (bypassing shiny rate modifiers such as Shiny Charm) @@ -4564,12 +4565,13 @@ export class EnemyPokemon extends Pokemon { public aiType: AiType; public bossSegments: integer; public bossSegmentIndex: integer; - /** To indicate of the instance was populated with a dataSource -> e.g. loaded & populated from session data */ + /** To indicate if the instance was populated with a dataSource -> e.g. loaded & populated from session data */ public readonly isPopulatedFromDataSource: boolean; - constructor(scene: BattleScene, species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean, dataSource?: PokemonData) { - super(scene, 236, 84, species, level, dataSource?.abilityIndex, dataSource?.formIndex, - dataSource?.gender, dataSource ? dataSource.shiny : false, dataSource ? dataSource.variant : undefined, undefined, dataSource ? dataSource.nature : undefined, dataSource); + constructor(scene: BattleScene, species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean, shinyLock: boolean = false, dataSource?: PokemonData) { + super(scene, 236, 84, species, level, dataSource?.abilityIndex, dataSource?.formIndex, dataSource?.gender, + shinyLock ? false : (dataSource ? dataSource.shiny : false), shinyLock ? undefined : (dataSource ? dataSource.variant : undefined), + undefined, dataSource ? dataSource.nature : undefined, dataSource); this.trainerSlot = trainerSlot; this.isPopulatedFromDataSource = !!dataSource; // if a dataSource is provided, then it was populated from dataSource diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 485c1d90c1d..2d5c41eb4aa 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -171,7 +171,7 @@ export default class PokemonData { playerPokemon.nickname = this.nickname; } }) - : scene.addEnemyPokemon(species, this.level, battleType === BattleType.TRAINER ? !double || !(partyMemberIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER : TrainerSlot.NONE, this.boss, this); + : scene.addEnemyPokemon(species, this.level, battleType === BattleType.TRAINER ? !double || !(partyMemberIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER : TrainerSlot.NONE, this.boss, false, this); if (this.summonData) { ret.primeSummonData(this.summonData); }