Merge branch 'beta' into stuff-cheeks-implementation
This commit is contained in:
commit
810e143376
|
@ -16,9 +16,9 @@ interface PokemonSpeciesFormLevelMoves {
|
|||
}
|
||||
|
||||
/** Moves that can only be learned with a memory-mushroom */
|
||||
const RELEARN_MOVE = -1;
|
||||
export const RELEARN_MOVE = -1;
|
||||
/** Moves that can only be learned with an evolve */
|
||||
const EVOLVE_MOVE = 0;
|
||||
export const EVOLVE_MOVE = 0;
|
||||
|
||||
export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||
[Species.BULBASAUR]: [
|
||||
|
|
|
@ -582,7 +582,13 @@ function doPokemonTradeSequence(scene: BattleScene, tradedPokemon: PlayerPokemon
|
|||
receivedPokemonTintSprite.setTintFill(getPokeballTintColor(receivedPokemon.pokeball));
|
||||
|
||||
[ tradedPokemonSprite, tradedPokemonTintSprite ].map(sprite => {
|
||||
sprite.play(tradedPokemon.getSpriteKey(true));
|
||||
const spriteKey = tradedPokemon.getSpriteKey(true);
|
||||
try {
|
||||
sprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipeline(scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(tradedPokemon.getTeraType()) });
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", tradedPokemon.getSpriteKey());
|
||||
|
@ -597,7 +603,13 @@ function doPokemonTradeSequence(scene: BattleScene, tradedPokemon: PlayerPokemon
|
|||
});
|
||||
|
||||
[ receivedPokemonSprite, receivedPokemonTintSprite ].map(sprite => {
|
||||
sprite.play(receivedPokemon.getSpriteKey(true));
|
||||
const spriteKey = receivedPokemon.getSpriteKey(true);
|
||||
try {
|
||||
sprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipeline(scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(tradedPokemon.getTeraType()) });
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", receivedPokemon.getSpriteKey());
|
||||
|
|
|
@ -34,6 +34,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
|||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.MYSTERIOUS_CHEST)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withScenePartySizeRequirement(2, 6, true)
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withCatchAllowed(true)
|
||||
.withIntroSpriteConfigs([
|
||||
|
|
|
@ -290,7 +290,10 @@ export function applyDamageToPokemon(scene: BattleScene, pokemon: PlayerPokemon,
|
|||
if (damage <= 0) {
|
||||
console.warn("Healing pokemon with `applyDamageToPokemon` is not recommended! Please use `applyHealToPokemon` instead.");
|
||||
}
|
||||
|
||||
// If a Pokemon would faint from the damage applied, its HP is instead set to 1.
|
||||
if (pokemon.isAllowedInBattle() && pokemon.hp - damage <= 0) {
|
||||
damage = pokemon.hp - 1;
|
||||
}
|
||||
applyHpChangeToPokemon(scene, pokemon, -damage);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,13 @@ export function doPokemonTransformationSequence(scene: BattleScene, previousPoke
|
|||
pokemonEvoTintSprite.setTintFill(0xFFFFFF);
|
||||
|
||||
[ pokemonSprite, pokemonTintSprite, pokemonEvoSprite, pokemonEvoTintSprite ].map(sprite => {
|
||||
sprite.play(previousPokemon.getSpriteKey(true));
|
||||
const spriteKey = previousPokemon.getSpriteKey(true);
|
||||
try {
|
||||
sprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipeline(scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(previousPokemon.getTeraType()) });
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", previousPokemon.getSpriteKey());
|
||||
|
@ -69,7 +75,13 @@ export function doPokemonTransformationSequence(scene: BattleScene, previousPoke
|
|||
});
|
||||
|
||||
[ pokemonEvoSprite, pokemonEvoTintSprite ].map(sprite => {
|
||||
sprite.play(transformPokemon.getSpriteKey(true));
|
||||
const spriteKey = transformPokemon.getSpriteKey(true);
|
||||
try {
|
||||
sprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", transformPokemon.getSpriteKey());
|
||||
sprite.setPipelineData("shiny", transformPokemon.shiny);
|
||||
|
|
|
@ -29,7 +29,7 @@ import { BattlerIndex } from "#app/battle";
|
|||
import { Mode } from "#app/ui/ui";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { LevelMoves } from "#app/data/balance/pokemon-level-moves";
|
||||
import { EVOLVE_MOVE, LevelMoves, RELEARN_MOVE } from "#app/data/balance/pokemon-level-moves";
|
||||
import { DamageAchv, achvs } from "#app/system/achv";
|
||||
import { DexAttr, StarterDataEntry, StarterMoveset } from "#app/system/game-data";
|
||||
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
|
||||
|
@ -71,6 +71,15 @@ import { Nature } from "#enums/nature";
|
|||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { doShinySparkleAnim } from "#app/field/anims";
|
||||
|
||||
export enum LearnMoveSituation {
|
||||
MISC,
|
||||
LEVEL_UP,
|
||||
RELEARN,
|
||||
EVOLUTION,
|
||||
EVOLUTION_FUSED, // If fusionSpecies has Evolved
|
||||
EVOLUTION_FUSED_BASE // If fusion's base species has Evolved
|
||||
}
|
||||
|
||||
export enum FieldPosition {
|
||||
CENTER,
|
||||
LEFT,
|
||||
|
@ -1817,40 +1826,44 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
* @param {boolean} includeRelearnerMoves Whether to include moves that would require a relearner. Note the move relearner inherently allows evolution moves
|
||||
* @returns {LevelMoves} A list of moves and the levels they can be learned at
|
||||
*/
|
||||
getLevelMoves(startingLevel?: integer, includeEvolutionMoves: boolean = false, simulateEvolutionChain: boolean = false, includeRelearnerMoves: boolean = false): LevelMoves {
|
||||
getLevelMoves(startingLevel?: integer, includeEvolutionMoves: boolean = false, simulateEvolutionChain: boolean = false, includeRelearnerMoves: boolean = false, learnSituation: LearnMoveSituation = LearnMoveSituation.MISC): LevelMoves {
|
||||
const ret: LevelMoves = [];
|
||||
let levelMoves: LevelMoves = [];
|
||||
if (!startingLevel) {
|
||||
startingLevel = this.level;
|
||||
}
|
||||
if (simulateEvolutionChain) {
|
||||
const evolutionChain = this.species.getSimulatedEvolutionChain(this.level, this.hasTrainer(), this.isBoss(), this.isPlayer());
|
||||
for (let e = 0; e < evolutionChain.length; e++) {
|
||||
// TODO: Might need to pass specific form index in simulated evolution chain
|
||||
const speciesLevelMoves = getPokemonSpeciesForm(evolutionChain[e][0], this.formIndex).getLevelMoves();
|
||||
if (includeRelearnerMoves) {
|
||||
levelMoves.push(...speciesLevelMoves);
|
||||
} else {
|
||||
levelMoves.push(...speciesLevelMoves.filter(lm => (includeEvolutionMoves && lm[0] === 0) || ((!e || lm[0] > 1) && (e === evolutionChain.length - 1 || lm[0] <= evolutionChain[e + 1][1]))));
|
||||
}
|
||||
}
|
||||
if (learnSituation === LearnMoveSituation.EVOLUTION_FUSED && this.fusionSpecies) { // For fusion evolutions, get ONLY the moves of the component mon that evolved
|
||||
levelMoves = this.getFusionSpeciesForm(true).getLevelMoves().filter(lm => (includeEvolutionMoves && lm[0] === EVOLVE_MOVE) || (includeRelearnerMoves && lm[0] === RELEARN_MOVE) || lm[0] > 0);
|
||||
} else {
|
||||
levelMoves = this.getSpeciesForm(true).getLevelMoves().filter(lm => (includeEvolutionMoves && lm[0] === 0) || (includeRelearnerMoves && lm[0] === -1) || lm[0] > 0);
|
||||
}
|
||||
if (this.fusionSpecies) {
|
||||
if (simulateEvolutionChain) {
|
||||
const fusionEvolutionChain = this.fusionSpecies.getSimulatedEvolutionChain(this.level, this.hasTrainer(), this.isBoss(), this.isPlayer());
|
||||
for (let e = 0; e < fusionEvolutionChain.length; e++) {
|
||||
const evolutionChain = this.species.getSimulatedEvolutionChain(this.level, this.hasTrainer(), this.isBoss(), this.isPlayer());
|
||||
for (let e = 0; e < evolutionChain.length; e++) {
|
||||
// TODO: Might need to pass specific form index in simulated evolution chain
|
||||
const speciesLevelMoves = getPokemonSpeciesForm(fusionEvolutionChain[e][0], this.fusionFormIndex).getLevelMoves();
|
||||
const speciesLevelMoves = getPokemonSpeciesForm(evolutionChain[e][0], this.formIndex).getLevelMoves();
|
||||
if (includeRelearnerMoves) {
|
||||
levelMoves.push(...speciesLevelMoves.filter(lm => (includeEvolutionMoves && lm[0] === 0) || lm[0] !== 0));
|
||||
levelMoves.push(...speciesLevelMoves);
|
||||
} else {
|
||||
levelMoves.push(...speciesLevelMoves.filter(lm => (includeEvolutionMoves && lm[0] === 0) || ((!e || lm[0] > 1) && (e === fusionEvolutionChain.length - 1 || lm[0] <= fusionEvolutionChain[e + 1][1]))));
|
||||
levelMoves.push(...speciesLevelMoves.filter(lm => (includeEvolutionMoves && lm[0] === EVOLVE_MOVE) || ((!e || lm[0] > 1) && (e === evolutionChain.length - 1 || lm[0] <= evolutionChain[e + 1][1]))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
levelMoves.push(...this.getFusionSpeciesForm(true).getLevelMoves().filter(lm => (includeEvolutionMoves && lm[0] === 0) || (includeRelearnerMoves && lm[0] === -1) || lm[0] > 0));
|
||||
levelMoves = this.getSpeciesForm(true).getLevelMoves().filter(lm => (includeEvolutionMoves && lm[0] === EVOLVE_MOVE) || (includeRelearnerMoves && lm[0] === RELEARN_MOVE) || lm[0] > 0);
|
||||
}
|
||||
if (this.fusionSpecies && learnSituation !== LearnMoveSituation.EVOLUTION_FUSED_BASE) { // For fusion evolutions, get ONLY the moves of the component mon that evolved
|
||||
if (simulateEvolutionChain) {
|
||||
const fusionEvolutionChain = this.fusionSpecies.getSimulatedEvolutionChain(this.level, this.hasTrainer(), this.isBoss(), this.isPlayer());
|
||||
for (let e = 0; e < fusionEvolutionChain.length; e++) {
|
||||
// TODO: Might need to pass specific form index in simulated evolution chain
|
||||
const speciesLevelMoves = getPokemonSpeciesForm(fusionEvolutionChain[e][0], this.fusionFormIndex).getLevelMoves();
|
||||
if (includeRelearnerMoves) {
|
||||
levelMoves.push(...speciesLevelMoves.filter(lm => (includeEvolutionMoves && lm[0] === EVOLVE_MOVE) || lm[0] !== EVOLVE_MOVE));
|
||||
} else {
|
||||
levelMoves.push(...speciesLevelMoves.filter(lm => (includeEvolutionMoves && lm[0] === EVOLVE_MOVE) || ((!e || lm[0] > 1) && (e === fusionEvolutionChain.length - 1 || lm[0] <= fusionEvolutionChain[e + 1][1]))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
levelMoves.push(...this.getFusionSpeciesForm(true).getLevelMoves().filter(lm => (includeEvolutionMoves && lm[0] === EVOLVE_MOVE) || (includeRelearnerMoves && lm[0] === RELEARN_MOVE) || lm[0] > 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
levelMoves.sort((lma: [integer, integer], lmb: [integer, integer]) => lma[0] > lmb[0] ? 1 : lma[0] < lmb[0] ? -1 : 0);
|
||||
|
@ -3728,8 +3741,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
|
||||
setFrameRate(frameRate: integer) {
|
||||
this.scene.anims.get(this.getBattleSpriteKey()).frameRate = frameRate;
|
||||
this.getSprite().play(this.getBattleSpriteKey());
|
||||
this.getTintSprite()?.play(this.getBattleSpriteKey());
|
||||
try {
|
||||
this.getSprite().play(this.getBattleSpriteKey());
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${this.getBattleSpriteKey()}`, err);
|
||||
}
|
||||
try {
|
||||
this.getTintSprite()?.play(this.getBattleSpriteKey());
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${this.getBattleSpriteKey()}`, err);
|
||||
}
|
||||
}
|
||||
|
||||
tint(color: number, alpha?: number, duration?: integer, ease?: string) {
|
||||
|
@ -4271,28 +4292,29 @@ export class PlayerPokemon extends Pokemon {
|
|||
});
|
||||
}
|
||||
|
||||
addFriendship(friendship: integer): void {
|
||||
const starterSpeciesId = this.species.getRootSpeciesId();
|
||||
const fusionStarterSpeciesId = this.isFusion() && this.fusionSpecies ? this.fusionSpecies.getRootSpeciesId() : 0;
|
||||
const starterData = [
|
||||
this.scene.gameData.starterData[starterSpeciesId],
|
||||
fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null
|
||||
].filter(d => !!d);
|
||||
const amount = new Utils.IntegerHolder(friendship);
|
||||
let candyFriendshipMultiplier = CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER;
|
||||
if (this.scene.eventManager.isEventActive()) {
|
||||
candyFriendshipMultiplier *= this.scene.eventManager.getFriendshipMultiplier();
|
||||
}
|
||||
const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic && friendship > 0 ? candyFriendshipMultiplier : 1) / (fusionStarterSpeciesId ? 2 : 1)));
|
||||
if (amount.value > 0) {
|
||||
addFriendship(friendship: number): void {
|
||||
if (friendship > 0) {
|
||||
const starterSpeciesId = this.species.getRootSpeciesId();
|
||||
const fusionStarterSpeciesId = this.isFusion() && this.fusionSpecies ? this.fusionSpecies.getRootSpeciesId() : 0;
|
||||
const starterData = [
|
||||
this.scene.gameData.starterData[starterSpeciesId],
|
||||
fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null
|
||||
].filter(d => !!d);
|
||||
const amount = new Utils.NumberHolder(friendship);
|
||||
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount);
|
||||
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount);
|
||||
let candyFriendshipMultiplier = CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER;
|
||||
if (this.scene.eventManager.isEventActive()) {
|
||||
candyFriendshipMultiplier *= this.scene.eventManager.getFriendshipMultiplier();
|
||||
}
|
||||
const starterAmount = new Utils.NumberHolder(Math.floor(amount.value * (this.scene.gameMode.isClassic ? candyFriendshipMultiplier : 1) / (fusionStarterSpeciesId ? 2 : 1)));
|
||||
|
||||
// Add friendship to this PlayerPokemon
|
||||
this.friendship = Math.min(this.friendship + amount.value, 255);
|
||||
if (this.friendship === 255) {
|
||||
this.scene.validateAchv(achvs.MAX_FRIENDSHIP);
|
||||
}
|
||||
starterData.forEach((sd: StarterDataEntry, i: integer) => {
|
||||
// Add to candy progress for this mon's starter species and its fused species (if it has one)
|
||||
starterData.forEach((sd: StarterDataEntry, i: number) => {
|
||||
const speciesId = !i ? starterSpeciesId : fusionStarterSpeciesId as Species;
|
||||
sd.friendship = (sd.friendship || 0) + starterAmount.value;
|
||||
if (sd.friendship >= getStarterValueFriendshipCap(speciesStarterCosts[speciesId])) {
|
||||
|
@ -4301,10 +4323,8 @@ export class PlayerPokemon extends Pokemon {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
this.friendship = Math.max(this.friendship + amount.value, 0);
|
||||
for (const sd of starterData) {
|
||||
sd.friendship = Math.max((sd.friendship || 0) + starterAmount.value, 0);
|
||||
}
|
||||
// Lose friendship upon fainting
|
||||
this.friendship = Math.max(this.friendship + friendship, 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -177,7 +177,11 @@ class DefaultOverrides {
|
|||
// MYSTERY ENCOUNTER OVERRIDES
|
||||
// -------------------------
|
||||
|
||||
/** 1 to 256, set to null to ignore */
|
||||
/**
|
||||
* `1` (almost never) to `256` (always), set to `null` to disable the override
|
||||
*
|
||||
* Note: Make sure `STARTING_WAVE_OVERRIDE > 10`, otherwise MEs won't trigger
|
||||
*/
|
||||
readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number | null = null;
|
||||
readonly MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier | null = null;
|
||||
readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType | null = null;
|
||||
|
|
|
@ -330,7 +330,12 @@ export class EggHatchPhase extends Phase {
|
|||
this.scene.validateAchv(achvs.HATCH_SHINY);
|
||||
}
|
||||
this.eggContainer.setVisible(false);
|
||||
this.pokemonSprite.play(this.pokemon.getSpriteKey(true));
|
||||
const spriteKey = this.pokemon.getSpriteKey(true);
|
||||
try {
|
||||
this.pokemonSprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
this.pokemonSprite.setPipelineData("ignoreTimeTint", true);
|
||||
this.pokemonSprite.setPipelineData("spriteKey", this.pokemon.getSpriteKey());
|
||||
this.pokemonSprite.setPipelineData("shiny", this.pokemon.shiny);
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { Phase } from "#app/phase";
|
||||
import BattleScene, { AnySound } from "#app/battle-scene";
|
||||
import { SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
||||
import { FusionSpeciesFormEvolution, SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
||||
import EvolutionSceneHandler from "#app/ui/evolution-scene-handler";
|
||||
import * as Utils from "#app/utils";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import { cos, sin } from "#app/field/anims";
|
||||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||
import Pokemon, { LearnMoveSituation, PlayerPokemon } from "#app/field/pokemon";
|
||||
import { getTypeRgb } from "#app/data/type";
|
||||
import i18next from "i18next";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||
import { EndEvolutionPhase } from "#app/phases/end-evolution-phase";
|
||||
import { EVOLVE_MOVE } from "#app/data/balance/pokemon-level-moves";
|
||||
|
||||
export class EvolutionPhase extends Phase {
|
||||
protected pokemon: PlayerPokemon;
|
||||
|
@ -20,6 +21,7 @@ export class EvolutionPhase extends Phase {
|
|||
private preEvolvedPokemonName: string;
|
||||
|
||||
private evolution: SpeciesFormEvolution | null;
|
||||
private fusionSpeciesEvolved: boolean; // Whether the evolution is of the fused species
|
||||
private evolutionBgm: AnySound;
|
||||
private evolutionHandler: EvolutionSceneHandler;
|
||||
|
||||
|
@ -39,6 +41,7 @@ export class EvolutionPhase extends Phase {
|
|||
this.pokemon = pokemon;
|
||||
this.evolution = evolution;
|
||||
this.lastLevel = lastLevel;
|
||||
this.fusionSpeciesEvolved = evolution instanceof FusionSpeciesFormEvolution;
|
||||
}
|
||||
|
||||
validate(): boolean {
|
||||
|
@ -102,7 +105,13 @@ export class EvolutionPhase extends Phase {
|
|||
this.scene.ui.add(this.evolutionOverlay);
|
||||
|
||||
[ this.pokemonSprite, this.pokemonTintSprite, this.pokemonEvoSprite, this.pokemonEvoTintSprite ].map(sprite => {
|
||||
sprite.play(this.pokemon.getSpriteKey(true));
|
||||
const spriteKey = this.pokemon.getSpriteKey(true);
|
||||
try {
|
||||
sprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(this.pokemon.getTeraType()) });
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", this.pokemon.getSpriteKey());
|
||||
|
@ -127,7 +136,13 @@ export class EvolutionPhase extends Phase {
|
|||
this.pokemon.getPossibleEvolution(this.evolution).then(evolvedPokemon => {
|
||||
|
||||
[ this.pokemonEvoSprite, this.pokemonEvoTintSprite ].map(sprite => {
|
||||
sprite.play(evolvedPokemon.getSpriteKey(true));
|
||||
const spriteKey = evolvedPokemon.getSpriteKey(true);
|
||||
try {
|
||||
sprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", evolvedPokemon.getSpriteKey());
|
||||
sprite.setPipelineData("shiny", evolvedPokemon.shiny);
|
||||
|
@ -261,7 +276,8 @@ export class EvolutionPhase extends Phase {
|
|||
this.evolutionHandler.canCancel = false;
|
||||
|
||||
this.pokemon.evolve(this.evolution, this.pokemon.species).then(() => {
|
||||
const levelMoves = this.pokemon.getLevelMoves(this.lastLevel + 1, true);
|
||||
const learnSituation: LearnMoveSituation = this.fusionSpeciesEvolved ? LearnMoveSituation.EVOLUTION_FUSED : this.pokemon.fusionSpecies ? LearnMoveSituation.EVOLUTION_FUSED_BASE : LearnMoveSituation.EVOLUTION;
|
||||
const levelMoves = this.pokemon.getLevelMoves(this.lastLevel + 1, true, false, false, learnSituation).filter(lm => lm[0] === EVOLVE_MOVE);
|
||||
for (const lm of levelMoves) {
|
||||
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.scene.getPlayerParty().indexOf(this.pokemon), lm[1]));
|
||||
}
|
||||
|
|
|
@ -39,7 +39,13 @@ export class FormChangePhase extends EvolutionPhase {
|
|||
this.pokemon.getPossibleForm(this.formChange).then(transformedPokemon => {
|
||||
|
||||
[ this.pokemonEvoSprite, this.pokemonEvoTintSprite ].map(sprite => {
|
||||
sprite.play(transformedPokemon.getSpriteKey(true));
|
||||
const spriteKey = transformedPokemon.getSpriteKey(true);
|
||||
try {
|
||||
sprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", transformedPokemon.getSpriteKey());
|
||||
sprite.setPipelineData("shiny", transformedPokemon.shiny);
|
||||
|
|
|
@ -23,6 +23,12 @@ import * as Utils from "#app/utils";
|
|||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import i18next from "i18next";
|
||||
import { SessionSaveData } from "#app/system/game-data";
|
||||
import PersistentModifierData from "#app/system/modifier-data";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import ChallengeData from "#app/system/challenge-data";
|
||||
import TrainerData from "#app/system/trainer-data";
|
||||
import ArenaData from "#app/system/arena-data";
|
||||
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
|
||||
|
||||
export class GameOverPhase extends BattlePhase {
|
||||
|
@ -109,7 +115,7 @@ export class GameOverPhase extends BattlePhase {
|
|||
this.scene.gameData.gameStats.dailyRunSessionsWon++;
|
||||
}
|
||||
}
|
||||
this.scene.gameData.saveRunHistory(this.scene, this.scene.gameData.getSessionSaveData(this.scene), this.isVictory);
|
||||
|
||||
const fadeDuration = this.isVictory ? 10000 : 5000;
|
||||
this.scene.fadeOutBgm(fadeDuration, true);
|
||||
const activeBattlers = this.scene.getField().filter(p => p?.isActive(true));
|
||||
|
@ -135,8 +141,11 @@ export class GameOverPhase extends BattlePhase {
|
|||
this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM));
|
||||
}
|
||||
}
|
||||
this.scene.pushPhase(new PostGameOverPhase(this.scene, endCardPhase));
|
||||
this.end();
|
||||
this.getRunHistoryEntry().then(runHistoryEntry => {
|
||||
this.scene.gameData.saveRunHistory(this.scene, runHistoryEntry, this.isVictory);
|
||||
this.scene.pushPhase(new PostGameOverPhase(this.scene, endCardPhase));
|
||||
this.end();
|
||||
});
|
||||
};
|
||||
|
||||
if (this.isVictory && this.scene.gameMode.isClassic) {
|
||||
|
@ -212,5 +221,34 @@ export class GameOverPhase extends BattlePhase {
|
|||
this.firstRibbons.push(getPokemonSpecies(pokemon.species.getRootSpeciesId(forStarter)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Slightly modified version of {@linkcode GameData.getSessionSaveData}.
|
||||
* @returns A promise containing the {@linkcode SessionSaveData}
|
||||
*/
|
||||
private async getRunHistoryEntry(): Promise<SessionSaveData> {
|
||||
const preWaveSessionData = await this.scene.gameData.getSession(this.scene.sessionSlotId);
|
||||
return {
|
||||
seed: this.scene.seed,
|
||||
playTime: this.scene.sessionPlayTime,
|
||||
gameMode: this.scene.gameMode.modeId,
|
||||
party: this.scene.getPlayerParty().map(p => new PokemonData(p)),
|
||||
enemyParty: this.scene.getEnemyParty().map(p => new PokemonData(p)),
|
||||
modifiers: preWaveSessionData ? preWaveSessionData.modifiers : this.scene.findModifiers(() => true).map(m => new PersistentModifierData(m, true)),
|
||||
enemyModifiers: preWaveSessionData ? preWaveSessionData.enemyModifiers : this.scene.findModifiers(() => true, false).map(m => new PersistentModifierData(m, false)),
|
||||
arena: new ArenaData(this.scene.arena),
|
||||
pokeballCounts: this.scene.pokeballCounts,
|
||||
money: Math.floor(this.scene.money),
|
||||
score: this.scene.score,
|
||||
waveIndex: this.scene.currentBattle.waveIndex,
|
||||
battleType: this.scene.currentBattle.battleType,
|
||||
trainer: this.scene.currentBattle.trainer ? new TrainerData(this.scene.currentBattle.trainer) : null,
|
||||
gameVersion: this.scene.game.config.gameVersion,
|
||||
timestamp: new Date().getTime(),
|
||||
challenges: this.scene.gameMode.challenges.map(c => new ChallengeData(c)),
|
||||
mysteryEncounterType: this.scene.currentBattle.mysteryEncounter?.encounterType ?? -1,
|
||||
mysteryEncounterSaveData: this.scene.mysteryEncounterSaveData
|
||||
} as SessionSaveData;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,12 @@ export class QuietFormChangePhase extends BattlePhase {
|
|||
const getPokemonSprite = () => {
|
||||
const sprite = this.scene.addPokemonSprite(this.pokemon, this.pokemon.x + this.pokemon.getSprite().x, this.pokemon.y + this.pokemon.getSprite().y, "pkmn__sub");
|
||||
sprite.setOrigin(0.5, 1);
|
||||
sprite.play(this.pokemon.getBattleSpriteKey()).stop();
|
||||
const spriteKey = this.pokemon.getBattleSpriteKey();
|
||||
try {
|
||||
sprite.play(spriteKey).stop();
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
sprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(this.pokemon.getTeraType()) });
|
||||
[ "spriteColors", "fusionSpriteColors" ].map(k => {
|
||||
if (this.pokemon.summonData?.speciesForm) {
|
||||
|
@ -81,7 +86,12 @@ export class QuietFormChangePhase extends BattlePhase {
|
|||
this.pokemon.setVisible(false);
|
||||
this.pokemon.changeForm(this.formChange).then(() => {
|
||||
pokemonFormTintSprite.setScale(0.01);
|
||||
pokemonFormTintSprite.play(this.pokemon.getBattleSpriteKey()).stop();
|
||||
const spriteKey = this.pokemon.getBattleSpriteKey();
|
||||
try {
|
||||
pokemonFormTintSprite.play(spriteKey).stop();
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
pokemonFormTintSprite.setVisible(true);
|
||||
this.scene.tweens.add({
|
||||
targets: pokemonTintSprite,
|
||||
|
|
|
@ -118,6 +118,7 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||
this.runResultContainer = this.scene.add.container(0, 24);
|
||||
const runResultWindow = addWindow(this.scene, 0, 0, this.statsBgWidth - 11, 65);
|
||||
runResultWindow.setOrigin(0, 0);
|
||||
runResultWindow.setName("Run_Result_Window");
|
||||
this.runResultContainer.add(runResultWindow);
|
||||
if (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) {
|
||||
this.parseRunResult();
|
||||
|
@ -254,8 +255,6 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||
* Mystery Encounters contain sprites associated with MEs + the title of the specific ME.
|
||||
*/
|
||||
private parseRunStatus() {
|
||||
const runStatusText = addTextObject(this.scene, 6, 5, `${i18next.t("saveSlotSelectUiHandler:wave")} ${this.runInfo.waveIndex} - ${getBiomeName(this.runInfo.arena.biome)}`, TextStyle.WINDOW, { fontSize : "65px", lineSpacing: 0.1 });
|
||||
|
||||
const enemyContainer = this.scene.add.container(0, 0);
|
||||
this.runResultContainer.add(enemyContainer);
|
||||
if (this.runInfo.battleType === BattleType.WILD) {
|
||||
|
@ -271,7 +270,7 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||
const pokeball = this.scene.add.sprite(0, 0, "pb");
|
||||
pokeball.setFrame(getPokeballAtlasKey(p.pokeball));
|
||||
pokeball.setScale(0.5);
|
||||
pokeball.setPosition(52 + ((i % row_limit) * 8), (i <= 2) ? 18 : 25);
|
||||
pokeball.setPosition(58 + ((i % row_limit) * 8), (i <= 2) ? 18 : 25);
|
||||
enemyContainer.add(pokeball);
|
||||
});
|
||||
const trainerObj = this.runInfo.trainer.toTrainer(this.scene);
|
||||
|
@ -286,7 +285,7 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||
const descContainer = this.scene.add.container(0, 0);
|
||||
const textBox = addTextObject(this.scene, 0, 0, boxString, TextStyle.WINDOW, { fontSize : "35px", wordWrap: { width: 200 }});
|
||||
descContainer.add(textBox);
|
||||
descContainer.setPosition(52, 29);
|
||||
descContainer.setPosition(55, 32);
|
||||
this.runResultContainer.add(descContainer);
|
||||
} else if (this.runInfo.battleType === BattleType.MYSTERY_ENCOUNTER) {
|
||||
const encounterExclaim = this.scene.add.sprite(0, 0, "encounter_exclaim");
|
||||
|
@ -303,7 +302,17 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||
this.runResultContainer.add([ encounterExclaim, subSprite, descContainer ]);
|
||||
}
|
||||
|
||||
this.runResultContainer.add(runStatusText);
|
||||
const runResultWindow = this.runResultContainer.getByName("Run_Result_Window") as Phaser.GameObjects.Image;
|
||||
const windowCenterX = runResultWindow.getTopCenter().x;
|
||||
const windowBottomY = runResultWindow.getBottomCenter().y;
|
||||
|
||||
const runStatusText = addTextObject(this.scene, windowCenterX, 5, `${i18next.t("saveSlotSelectUiHandler:wave")} ${this.runInfo.waveIndex}`, TextStyle.WINDOW, { fontSize : "60px", lineSpacing: 0.1 });
|
||||
runStatusText.setOrigin(0.5, 0);
|
||||
|
||||
const currentBiomeText = addTextObject(this.scene, windowCenterX, windowBottomY - 5, `${getBiomeName(this.runInfo.arena.biome)}`, TextStyle.WINDOW, { fontSize: "60px" });
|
||||
currentBiomeText.setOrigin(0.5, 1);
|
||||
|
||||
this.runResultContainer.add([ runStatusText, currentBiomeText ]);
|
||||
this.runContainer.add(this.runResultContainer);
|
||||
}
|
||||
|
||||
|
@ -387,12 +396,12 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||
tObjSprite.setPosition(-9, -3);
|
||||
tObjPartnerSprite.setScale(0.55);
|
||||
doubleContainer.add([ tObjSprite, tObjPartnerSprite ]);
|
||||
doubleContainer.setPosition(28, 40);
|
||||
doubleContainer.setPosition(28, 34);
|
||||
}
|
||||
enemyContainer.add(doubleContainer);
|
||||
} else {
|
||||
const scale = (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) ? 0.35 : 0.65;
|
||||
const position = (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) ? [ 12, 28 ] : [ 32, 36 ];
|
||||
const scale = (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) ? 0.35 : 0.55;
|
||||
const position = (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) ? [ 12, 28 ] : [ 30, 32 ];
|
||||
tObjSprite.setScale(scale, scale);
|
||||
tObjSprite.setPosition(position[0], position[1]);
|
||||
enemyContainer.add(tObjSprite);
|
||||
|
|
|
@ -39,7 +39,6 @@ import { Moves } from "#enums/moves";
|
|||
import { Species } from "#enums/species";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import AwaitableUiHandler from "#app/ui/awaitable-ui-handler";
|
||||
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#app/ui/dropdown";
|
||||
import { StarterContainer } from "#app/ui/starter-container";
|
||||
import { DropDownColumn, FilterBar } from "#app/ui/filter-bar";
|
||||
|
@ -1062,15 +1061,21 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
}
|
||||
}
|
||||
|
||||
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) {
|
||||
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer, moveToTop?: boolean) {
|
||||
super.showText(text, delay, callback, callbackDelay, prompt, promptDelay);
|
||||
|
||||
if (text?.indexOf("\n") === -1) {
|
||||
this.starterSelectMessageBox.setSize(318, 28);
|
||||
this.message.setY(-22);
|
||||
const singleLine = text?.indexOf("\n") === -1;
|
||||
|
||||
this.starterSelectMessageBox.setSize(318, singleLine ? 28 : 42);
|
||||
|
||||
if (moveToTop) {
|
||||
this.starterSelectMessageBox.setOrigin(0, 0);
|
||||
this.starterSelectMessageBoxContainer.setY(0);
|
||||
this.message.setY(4);
|
||||
} else {
|
||||
this.starterSelectMessageBox.setSize(318, 42);
|
||||
this.message.setY(-37);
|
||||
this.starterSelectMessageBoxContainer.setY(this.scene.game.canvas.height / 6);
|
||||
this.starterSelectMessageBox.setOrigin(0, 1);
|
||||
this.message.setY(singleLine ? -22 : -37);
|
||||
}
|
||||
|
||||
this.starterSelectMessageBoxContainer.setVisible(!!text?.length);
|
||||
|
@ -1804,8 +1809,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
options.push({
|
||||
label: `x${sameSpeciesEggCost} ${i18next.t("starterSelectUiHandler:sameSpeciesEgg")}`,
|
||||
handler: () => {
|
||||
if ((this.scene.gameData.eggs.length < 99 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE)
|
||||
&& (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= sameSpeciesEggCost)) {
|
||||
if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= sameSpeciesEggCost) {
|
||||
if (this.scene.gameData.eggs.length >= 99 && !Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
|
||||
// Egg list full, show error message at the top of the screen and abort
|
||||
this.showText(i18next.t("egg:tooManyEggs"), undefined, () => this.showText("", 0, () => this.tutorialActive = false), 2000, false, undefined, true);
|
||||
return false;
|
||||
}
|
||||
if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) {
|
||||
starterData.candyCount -= sameSpeciesEggCost;
|
||||
}
|
||||
|
@ -3565,9 +3574,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
}, cancel, null, null, 19);
|
||||
});
|
||||
} else {
|
||||
const handler = this.scene.ui.getHandler() as AwaitableUiHandler;
|
||||
handler.tutorialActive = true;
|
||||
this.scene.ui.showText(i18next.t("starterSelectUiHandler:invalidParty"), null, () => this.scene.ui.showText("", 0, () => handler.tutorialActive = false), null, true);
|
||||
this.tutorialActive = true;
|
||||
this.showText(i18next.t("starterSelectUiHandler:invalidParty"), undefined, () => this.showText("", 0, () => this.tutorialActive = false), undefined, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -321,8 +321,12 @@ export default class SummaryUiHandler extends UiHandler {
|
|||
this.numberText.setText(Utils.padInt(this.pokemon.species.speciesId, 4));
|
||||
this.numberText.setColor(this.getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD));
|
||||
this.numberText.setShadowColor(this.getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD, true));
|
||||
|
||||
this.pokemonSprite.play(this.pokemon.getSpriteKey(true));
|
||||
const spriteKey = this.pokemon.getSpriteKey(true);
|
||||
try {
|
||||
this.pokemonSprite.play(spriteKey);
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
this.pokemonSprite.setPipelineData("teraColor", getTypeRgb(this.pokemon.getTeraType()));
|
||||
this.pokemonSprite.setPipelineData("ignoreTimeTint", true);
|
||||
this.pokemonSprite.setPipelineData("spriteKey", this.pokemon.getSpriteKey());
|
||||
|
|
Loading…
Reference in New Issue