[UI/UX] Pokedex updates batch (#5282)
* Introducing tray to display form icons in the pokedex; displaying correct information for uncaught and seen forms in pokedex page; dexForDevs now unlocks everything in the main page * Filtering correctly passive abilities and form abilities. Passive candy symbol is now colored * Pikachu does not break the dex due to having no passive * Fixed position of pokemonFormText * Added button instructions to show forms * Allowing candy upgrades for evolutions; too expensive options shown in shadow text * Apply suggestions from code review Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Fixed game crashing after save and quit * Updating import of BBCodeText * Restoring name on dex page * getStarterSpecies now looks at speciesStarterCosts to determine what is a starter instead of looking at game data (exception for Pikachu) * Selecting pokedex option in starter select menu does not play error sound * Mons having no TM moves don't freeze the game in the dex * Menu in pokedex page is not pushed to the left when localized options are long * Removed spurious globalScene.clearPhaseQueue() call * Showing error message when clicking tm option if no tm moves are available * Egg move icon and passive icon are darkened when filtering if the respective move or passive has not been unlocked * Hiding form button when switching to filters * Hiding "Show forms" button while forms are being shown --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
This commit is contained in:
parent
f5ef4a5da9
commit
60b27f4f62
|
@ -6,7 +6,7 @@ import { addWindow } from "./ui-theme";
|
|||
import * as Utils from "../utils";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import { Button } from "#enums/buttons";
|
||||
import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
||||
import BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
||||
|
||||
export interface OptionSelectConfig {
|
||||
xOffset?: number;
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
import type { Variant } from "#app/data/variant";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { isNullOrUndefined } from "#app/utils";
|
||||
import type PokemonSpecies from "../data/pokemon-species";
|
||||
import { addTextObject, TextStyle } from "./text";
|
||||
|
||||
|
||||
interface SpeciesDetails {
|
||||
shiny?: boolean,
|
||||
formIndex?: number
|
||||
female?: boolean,
|
||||
variant?: Variant
|
||||
}
|
||||
|
||||
export class PokedexMonContainer extends Phaser.GameObjects.Container {
|
||||
public species: PokemonSpecies;
|
||||
public icon: Phaser.GameObjects.Sprite;
|
||||
|
@ -19,16 +29,34 @@ export class PokedexMonContainer extends Phaser.GameObjects.Container {
|
|||
public tmMove2Icon: Phaser.GameObjects.Image;
|
||||
public passive1Icon: Phaser.GameObjects.Image;
|
||||
public passive2Icon: Phaser.GameObjects.Image;
|
||||
public passive1OverlayIcon: Phaser.GameObjects.Image;
|
||||
public passive2OverlayIcon: Phaser.GameObjects.Image;
|
||||
public cost: number = 0;
|
||||
|
||||
constructor(species: PokemonSpecies) {
|
||||
constructor(species: PokemonSpecies, options: SpeciesDetails = {}) {
|
||||
super(globalScene, 0, 0);
|
||||
|
||||
this.species = species;
|
||||
|
||||
const { shiny, formIndex, female, variant } = options;
|
||||
|
||||
const defaultDexAttr = globalScene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
||||
const defaultProps = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||
|
||||
if (!isNullOrUndefined(formIndex)) {
|
||||
defaultProps.formIndex = formIndex;
|
||||
}
|
||||
if (!isNullOrUndefined(shiny)) {
|
||||
defaultProps.shiny = shiny;
|
||||
}
|
||||
if (!isNullOrUndefined(variant)) {
|
||||
defaultProps.variant = variant;
|
||||
}
|
||||
if (!isNullOrUndefined(female)) {
|
||||
defaultProps.female = female;
|
||||
}
|
||||
|
||||
|
||||
// starter passive bg
|
||||
const starterPassiveBg = globalScene.add.image(2, 5, "passive_bg");
|
||||
starterPassiveBg.setOrigin(0, 0);
|
||||
|
@ -137,7 +165,7 @@ export class PokedexMonContainer extends Phaser.GameObjects.Container {
|
|||
this.tmMove2Icon = tmMove2Icon;
|
||||
|
||||
|
||||
// move icons
|
||||
// passive icons
|
||||
const passive1Icon = globalScene.add.image(3, 3, "candy");
|
||||
passive1Icon.setOrigin(0, 0);
|
||||
passive1Icon.setScale(0.25);
|
||||
|
@ -145,13 +173,27 @@ export class PokedexMonContainer extends Phaser.GameObjects.Container {
|
|||
this.add(passive1Icon);
|
||||
this.passive1Icon = passive1Icon;
|
||||
|
||||
// move icons
|
||||
const passive1OverlayIcon = globalScene.add.image(12, 12, "candy_overlay");
|
||||
passive1OverlayIcon.setOrigin(0, 0);
|
||||
passive1OverlayIcon.setScale(0.25);
|
||||
passive1OverlayIcon.setVisible(false);
|
||||
this.add(passive1OverlayIcon);
|
||||
this.passive1OverlayIcon = passive1OverlayIcon;
|
||||
|
||||
// passive icons
|
||||
const passive2Icon = globalScene.add.image(12, 3, "candy");
|
||||
passive2Icon.setOrigin(0, 0);
|
||||
passive2Icon.setScale(0.25);
|
||||
passive2Icon.setVisible(false);
|
||||
this.add(passive2Icon);
|
||||
this.passive2Icon = passive2Icon;
|
||||
|
||||
const passive2OverlayIcon = globalScene.add.image(12, 12, "candy_overlay");
|
||||
passive2OverlayIcon.setOrigin(0, 0);
|
||||
passive2OverlayIcon.setScale(0.25);
|
||||
passive2OverlayIcon.setVisible(false);
|
||||
this.add(passive2OverlayIcon);
|
||||
this.passive2OverlayIcon = passive2OverlayIcon;
|
||||
}
|
||||
|
||||
checkIconId(female, formIndex, shiny, variant) {
|
||||
|
|
|
@ -43,7 +43,6 @@ import type { Moves } from "#enums/moves";
|
|||
import { Species } from "#enums/species";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { StarterContainer } from "#app/ui/starter-container";
|
||||
import { getPassiveCandyCount, getValueReductionCandyCounts, getSameSpeciesEggCandyCounts } from "#app/data/balance/starters";
|
||||
import { BooleanHolder, capitalizeString, getLocalizedSpriteKey, isNullOrUndefined, NumberHolder, padInt, rgbHexToRgba, toReadableString } from "#app/utils";
|
||||
import type { Nature } from "#enums/nature";
|
||||
|
@ -128,7 +127,6 @@ interface SpeciesDetails {
|
|||
formIndex?: number
|
||||
female?: boolean,
|
||||
variant?: number,
|
||||
forSeen?: boolean, // default = false
|
||||
}
|
||||
|
||||
enum MenuOptions {
|
||||
|
@ -147,8 +145,6 @@ enum MenuOptions {
|
|||
export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
private starterSelectContainer: Phaser.GameObjects.Container;
|
||||
private shinyOverlay: Phaser.GameObjects.Image;
|
||||
private starterContainers: StarterContainer[] = [];
|
||||
private filteredStarterContainers: StarterContainer[] = [];
|
||||
private pokemonNumberText: Phaser.GameObjects.Text;
|
||||
private pokemonSprite: Phaser.GameObjects.Sprite;
|
||||
private pokemonNameText: Phaser.GameObjects.Text;
|
||||
|
@ -199,6 +195,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
private allSpecies: PokemonSpecies[] = [];
|
||||
private species: PokemonSpecies;
|
||||
private starterId: number;
|
||||
private formIndex: number;
|
||||
private speciesLoaded: Map<Species, boolean> = new Map<Species, boolean>();
|
||||
private levelMoves: LevelMoves;
|
||||
|
@ -312,10 +309,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
this.speciesLoaded.set(species.speciesId, false);
|
||||
this.allSpecies.push(species);
|
||||
|
||||
const starterContainer = new StarterContainer(species).setVisible(false);
|
||||
this.starterContainers.push(starterContainer);
|
||||
starterBoxContainer.add(starterContainer);
|
||||
}
|
||||
|
||||
this.starterSelectContainer.add(starterBoxContainer);
|
||||
|
@ -513,7 +506,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale;
|
||||
this.menuBg = addWindow(
|
||||
(globalScene.game.canvas.width / 6) - (this.optionSelectText.displayWidth + 25),
|
||||
(globalScene.game.canvas.width / 6 - 83),
|
||||
0,
|
||||
this.optionSelectText.displayWidth + 19 + 24 * this.scale,
|
||||
(globalScene.game.canvas.height / 6) - 2
|
||||
|
@ -555,8 +548,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
// Filter bar sits above everything, except the message box
|
||||
this.starterSelectContainer.bringToTop(this.starterSelectMessageBoxContainer);
|
||||
|
||||
this.updateInstructions();
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
|
@ -603,6 +594,8 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
const species = this.species;
|
||||
const formIndex = this.formIndex ?? 0;
|
||||
|
||||
this.starterId = this.getStarterSpeciesId(this.species.speciesId);
|
||||
|
||||
const allEvolutions = pokemonEvolutions.hasOwnProperty(species.speciesId) ? pokemonEvolutions[species.speciesId] : [];
|
||||
|
||||
if (species.forms.length > 0) {
|
||||
|
@ -629,17 +622,19 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
this.baseTotal = species.baseTotal;
|
||||
}
|
||||
|
||||
this.eggMoves = speciesEggMoves[this.getStarterSpeciesId(species.speciesId)] ?? [];
|
||||
this.hasEggMoves = Array.from({ length: 4 }, (_, em) => (globalScene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].eggMoves & (1 << em)) !== 0);
|
||||
this.eggMoves = speciesEggMoves[this.starterId] ?? [];
|
||||
this.hasEggMoves = Array.from({ length: 4 }, (_, em) => (globalScene.gameData.starterData[this.starterId].eggMoves & (1 << em)) !== 0);
|
||||
|
||||
const formKey = this.species?.forms.length > 0 ? this.species.forms[this.formIndex].formKey : "";
|
||||
this.tmMoves = speciesTmMoves[species.speciesId]?.filter(m => Array.isArray(m) ? (m[0] === formKey ? true : false ) : true)
|
||||
.map(m => Array.isArray(m) ? m[1] : m).sort((a, b) => allMoves[a].name > allMoves[b].name ? 1 : -1) ?? [];
|
||||
|
||||
const passives = starterPassiveAbilities[this.getStarterSpeciesId(species.speciesId)];
|
||||
const passiveId = starterPassiveAbilities.hasOwnProperty(species.speciesId) ? species.speciesId :
|
||||
starterPassiveAbilities.hasOwnProperty(this.starterId) ? this.starterId : pokemonPrevolutions[this.starterId];
|
||||
const passives = starterPassiveAbilities[passiveId];
|
||||
this.passive = (this.formIndex in passives) ? passives[formIndex] : passives[0];
|
||||
|
||||
const starterData = globalScene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)];
|
||||
const starterData = globalScene.gameData.starterData[this.starterId];
|
||||
const abilityAttr = starterData.abilityAttr;
|
||||
this.hasPassive = starterData.passiveAttr > 0;
|
||||
|
||||
|
@ -655,9 +650,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
const allBiomes = catchableSpecies[species.speciesId] ?? [];
|
||||
this.preBiomes = this.sanitizeBiomes(
|
||||
(catchableSpecies[this.getStarterSpeciesId(species.speciesId)] ?? [])
|
||||
(catchableSpecies[this.starterId] ?? [])
|
||||
.filter(b => !allBiomes.some(bm => (b.biome === bm.biome && b.tier === bm.tier)) && !(b.biome === Biome.TOWN)),
|
||||
this.getStarterSpeciesId(species.speciesId));
|
||||
this.starterId);
|
||||
this.biomes = this.sanitizeBiomes(allBiomes, species.speciesId);
|
||||
|
||||
const allFormChanges = pokemonFormChanges.hasOwnProperty(species.speciesId) ? pokemonFormChanges[species.speciesId] : [];
|
||||
|
@ -799,39 +794,43 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
const hasShiny = caughtAttr & DexAttr.SHINY;
|
||||
const hasNonShiny = caughtAttr & DexAttr.NON_SHINY;
|
||||
if (starterAttributes.shiny && !hasShiny) {
|
||||
if (!hasShiny || (starterAttributes.shiny === undefined && hasNonShiny)) {
|
||||
// shiny form wasn't unlocked, purging shiny and variant setting
|
||||
starterAttributes.shiny = false;
|
||||
starterAttributes.variant = 0;
|
||||
} else if (starterAttributes.shiny === false && !hasNonShiny) {
|
||||
// non shiny form wasn't unlocked, purging shiny setting
|
||||
starterAttributes.shiny = false;
|
||||
} else if (!hasNonShiny || (starterAttributes.shiny === undefined && hasShiny)) {
|
||||
starterAttributes.shiny = true;
|
||||
starterAttributes.variant = 0;
|
||||
}
|
||||
|
||||
if (starterAttributes.variant !== undefined) {
|
||||
const unlockedVariants = [
|
||||
hasShiny && caughtAttr & DexAttr.DEFAULT_VARIANT,
|
||||
hasShiny && caughtAttr & DexAttr.VARIANT_2,
|
||||
hasShiny && caughtAttr & DexAttr.VARIANT_3
|
||||
];
|
||||
if (isNaN(starterAttributes.variant) || starterAttributes.variant < 0) {
|
||||
starterAttributes.variant = 0;
|
||||
} else if (!unlockedVariants[starterAttributes.variant]) {
|
||||
let highestValidIndex = -1;
|
||||
for (let i = 0; i <= starterAttributes.variant && i < unlockedVariants.length; i++) {
|
||||
if (unlockedVariants[i] !== 0n) {
|
||||
highestValidIndex = i;
|
||||
}
|
||||
const unlockedVariants = [
|
||||
hasShiny && caughtAttr & DexAttr.DEFAULT_VARIANT,
|
||||
hasShiny && caughtAttr & DexAttr.VARIANT_2,
|
||||
hasShiny && caughtAttr & DexAttr.VARIANT_3
|
||||
];
|
||||
if (starterAttributes.variant === undefined || isNaN(starterAttributes.variant) || starterAttributes.variant < 0) {
|
||||
starterAttributes.variant = 0;
|
||||
} else if (!unlockedVariants[starterAttributes.variant]) {
|
||||
let highestValidIndex = -1;
|
||||
for (let i = 0; i <= starterAttributes.variant && i < unlockedVariants.length; i++) {
|
||||
if (unlockedVariants[i] !== 0n) {
|
||||
highestValidIndex = i;
|
||||
}
|
||||
// Set to the highest valid index found or default to 0
|
||||
starterAttributes.variant = highestValidIndex !== -1 ? highestValidIndex : 0;
|
||||
}
|
||||
// Set to the highest valid index found or default to 0
|
||||
starterAttributes.variant = highestValidIndex !== -1 ? highestValidIndex : 0;
|
||||
}
|
||||
|
||||
if (starterAttributes.female !== undefined) {
|
||||
if ((starterAttributes.female && !(caughtAttr & DexAttr.FEMALE)) || (!starterAttributes.female && !(caughtAttr & DexAttr.MALE))) {
|
||||
starterAttributes.female = !starterAttributes.female;
|
||||
}
|
||||
} else {
|
||||
if (caughtAttr & DexAttr.FEMALE) {
|
||||
starterAttributes.female = true;
|
||||
} else if (caughtAttr & DexAttr.MALE) {
|
||||
starterAttributes.female = false;
|
||||
}
|
||||
}
|
||||
|
||||
return starterAttributes;
|
||||
|
@ -878,7 +877,14 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
* @returns the id of the corresponding starter
|
||||
*/
|
||||
getStarterSpeciesId(speciesId): number {
|
||||
if (globalScene.gameData.starterData.hasOwnProperty(speciesId)) {
|
||||
if (speciesId === Species.PIKACHU) {
|
||||
if ([ 0, 1, 8 ].includes(this.formIndex)) {
|
||||
return Species.PICHU;
|
||||
} else {
|
||||
return Species.PIKACHU;
|
||||
}
|
||||
}
|
||||
if (speciesStarterCosts.hasOwnProperty(speciesId)) {
|
||||
return speciesId;
|
||||
} else {
|
||||
return pokemonStarters[speciesId];
|
||||
|
@ -886,7 +892,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
}
|
||||
|
||||
getStarterSpecies(species): PokemonSpecies {
|
||||
if (globalScene.gameData.starterData.hasOwnProperty(species.speciesId)) {
|
||||
if (speciesStarterCosts.hasOwnProperty(species.speciesId)) {
|
||||
return species;
|
||||
} else {
|
||||
return allSpecies.find(sp => sp.speciesId === pokemonStarters[species.speciesId]) ?? species;
|
||||
|
@ -970,7 +976,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
}
|
||||
} else {
|
||||
|
||||
const starterData = globalScene.gameData.starterData[this.getStarterSpeciesId(this.species.speciesId)];
|
||||
const starterData = globalScene.gameData.starterData[this.starterId];
|
||||
// prepare persistent starter data to store changes
|
||||
const starterAttributes = this.starterAttributes;
|
||||
|
||||
|
@ -1126,6 +1132,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
if (!isCaught || !isFormCaught) {
|
||||
error = true;
|
||||
} else if (this.tmMoves.length < 1) {
|
||||
ui.showText(i18next.t("pokedexUiHandler:noTmMoves"));
|
||||
error = true;
|
||||
} else {
|
||||
this.blockInput = true;
|
||||
|
||||
|
@ -1633,90 +1642,55 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
error = true;
|
||||
} else {
|
||||
const ui = this.getUi();
|
||||
ui.showText("");
|
||||
const options: any[] = []; // TODO: add proper type
|
||||
|
||||
const passiveAttr = starterData.passiveAttr;
|
||||
const candyCount = starterData.candyCount;
|
||||
|
||||
if (!pokemonPrevolutions.hasOwnProperty(this.species.speciesId)) {
|
||||
if (!(passiveAttr & PassiveAttr.UNLOCKED)) {
|
||||
const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.getStarterSpeciesId(this.species.speciesId)]);
|
||||
options.push({
|
||||
label: `x${passiveCost} ${i18next.t("pokedexUiHandler:unlockPassive")} (${allAbilities[this.passive].name})`,
|
||||
handler: () => {
|
||||
if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) {
|
||||
starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED;
|
||||
if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) {
|
||||
starterData.candyCount -= passiveCost;
|
||||
}
|
||||
this.pokemonCandyCountText.setText(`x${starterData.candyCount}`);
|
||||
globalScene.gameData.saveSystem().then(success => {
|
||||
if (!success) {
|
||||
return globalScene.reset(true);
|
||||
}
|
||||
});
|
||||
ui.setMode(Mode.POKEDEX_PAGE, "refresh");
|
||||
this.setSpeciesDetails(this.species);
|
||||
globalScene.playSound("se/buy");
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
item: "candy",
|
||||
itemArgs: starterColors[this.getStarterSpeciesId(this.species.speciesId)]
|
||||
});
|
||||
}
|
||||
|
||||
// Reduce cost option
|
||||
const valueReduction = starterData.valueReduction;
|
||||
if (valueReduction < valueReductionMax) {
|
||||
const reductionCost = getValueReductionCandyCounts(speciesStarterCosts[this.getStarterSpeciesId(this.species.speciesId)])[valueReduction];
|
||||
options.push({
|
||||
label: `x${reductionCost} ${i18next.t("pokedexUiHandler:reduceCost")}`,
|
||||
handler: () => {
|
||||
if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= reductionCost) {
|
||||
starterData.valueReduction++;
|
||||
if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) {
|
||||
starterData.candyCount -= reductionCost;
|
||||
}
|
||||
this.pokemonCandyCountText.setText(`x${starterData.candyCount}`);
|
||||
globalScene.gameData.saveSystem().then(success => {
|
||||
if (!success) {
|
||||
return globalScene.reset(true);
|
||||
}
|
||||
});
|
||||
ui.setMode(Mode.POKEDEX_PAGE, "refresh");
|
||||
globalScene.playSound("se/buy");
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
item: "candy",
|
||||
itemArgs: starterColors[this.getStarterSpeciesId(this.species.speciesId)]
|
||||
});
|
||||
}
|
||||
|
||||
// Same species egg menu option.
|
||||
const sameSpeciesEggCost = getSameSpeciesEggCandyCounts(speciesStarterCosts[this.getStarterSpeciesId(this.species.speciesId)]);
|
||||
if (!(passiveAttr & PassiveAttr.UNLOCKED)) {
|
||||
const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.starterId]);
|
||||
options.push({
|
||||
label: `x${sameSpeciesEggCost} ${i18next.t("pokedexUiHandler:sameSpeciesEgg")}`,
|
||||
label: `x${passiveCost} ${i18next.t("pokedexUiHandler:unlockPassive")} (${allAbilities[this.passive].name})`,
|
||||
handler: () => {
|
||||
if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= sameSpeciesEggCost) {
|
||||
if (globalScene.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 || candyCount >= passiveCost) {
|
||||
starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED;
|
||||
if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) {
|
||||
starterData.candyCount -= sameSpeciesEggCost;
|
||||
starterData.candyCount -= passiveCost;
|
||||
}
|
||||
this.pokemonCandyCountText.setText(`x${starterData.candyCount}`);
|
||||
globalScene.gameData.saveSystem().then(success => {
|
||||
if (!success) {
|
||||
return globalScene.reset(true);
|
||||
}
|
||||
});
|
||||
this.setSpeciesDetails(this.species);
|
||||
globalScene.playSound("se/buy");
|
||||
ui.setMode(Mode.POKEDEX_PAGE, "refresh");
|
||||
|
||||
const egg = new Egg({ scene: globalScene, species: this.species.speciesId, sourceType: EggSourceType.SAME_SPECIES_EGG });
|
||||
egg.addEggToGameData();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
style: this.isPassiveAvailable() ? TextStyle.WINDOW : TextStyle.SHADOW_TEXT,
|
||||
item: "candy",
|
||||
itemArgs: this.isPassiveAvailable() ? starterColors[this.starterId] : [ "808080", "808080" ]
|
||||
});
|
||||
}
|
||||
|
||||
// Reduce cost option
|
||||
const valueReduction = starterData.valueReduction;
|
||||
if (valueReduction < valueReductionMax) {
|
||||
const reductionCost = getValueReductionCandyCounts(speciesStarterCosts[this.starterId])[valueReduction];
|
||||
options.push({
|
||||
label: `x${reductionCost} ${i18next.t("pokedexUiHandler:reduceCost")}`,
|
||||
handler: () => {
|
||||
if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= reductionCost) {
|
||||
starterData.valueReduction++;
|
||||
if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) {
|
||||
starterData.candyCount -= reductionCost;
|
||||
}
|
||||
this.pokemonCandyCountText.setText(`x${starterData.candyCount}`);
|
||||
globalScene.gameData.saveSystem().then(success => {
|
||||
if (!success) {
|
||||
return globalScene.reset(true);
|
||||
|
@ -1729,24 +1703,59 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
}
|
||||
return false;
|
||||
},
|
||||
style: this.isValueReductionAvailable() ? TextStyle.WINDOW : TextStyle.SHADOW_TEXT,
|
||||
item: "candy",
|
||||
itemArgs: starterColors[this.getStarterSpeciesId(this.species.speciesId)]
|
||||
itemArgs: this.isValueReductionAvailable() ? starterColors[this.starterId] : [ "808080", "808080" ]
|
||||
});
|
||||
options.push({
|
||||
label: i18next.t("menu:cancel"),
|
||||
handler: () => {
|
||||
}
|
||||
|
||||
// Same species egg menu option.
|
||||
const sameSpeciesEggCost = getSameSpeciesEggCandyCounts(speciesStarterCosts[this.starterId]);
|
||||
options.push({
|
||||
label: `x${sameSpeciesEggCost} ${i18next.t("pokedexUiHandler:sameSpeciesEgg")}`,
|
||||
handler: () => {
|
||||
if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= sameSpeciesEggCost) {
|
||||
if (globalScene.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;
|
||||
}
|
||||
this.pokemonCandyCountText.setText(`x${starterData.candyCount}`);
|
||||
|
||||
const egg = new Egg({ scene: globalScene, species: this.species.speciesId, sourceType: EggSourceType.SAME_SPECIES_EGG });
|
||||
egg.addEggToGameData();
|
||||
|
||||
globalScene.gameData.saveSystem().then(success => {
|
||||
if (!success) {
|
||||
return globalScene.reset(true);
|
||||
}
|
||||
});
|
||||
ui.setMode(Mode.POKEDEX_PAGE, "refresh");
|
||||
globalScene.playSound("se/buy");
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||
options: options,
|
||||
yOffset: 47
|
||||
});
|
||||
success = true;
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
style: this.isSameSpeciesEggAvailable() ? TextStyle.WINDOW : TextStyle.SHADOW_TEXT,
|
||||
item: "candy",
|
||||
itemArgs: this.isSameSpeciesEggAvailable() ? starterColors[this.starterId] : [ "808080", "808080" ]
|
||||
});
|
||||
options.push({
|
||||
label: i18next.t("menu:cancel"),
|
||||
handler: () => {
|
||||
ui.setMode(Mode.POKEDEX_PAGE, "refresh");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||
options: options,
|
||||
yOffset: 47
|
||||
});
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
case Button.CYCLE_ABILITY:
|
||||
|
@ -1877,9 +1886,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
if (this.isCaught()) {
|
||||
if (isFormCaught) {
|
||||
if (!pokemonPrevolutions.hasOwnProperty(this.species.speciesId)) {
|
||||
this.updateButtonIcon(SettingKeyboard.Button_Stats, gamepadType, this.candyUpgradeIconElement, this.candyUpgradeLabel);
|
||||
}
|
||||
this.updateButtonIcon(SettingKeyboard.Button_Stats, gamepadType, this.candyUpgradeIconElement, this.candyUpgradeLabel);
|
||||
if (this.canCycleShiny) {
|
||||
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Shiny, gamepadType, this.shinyIconElement, this.shinyLabel);
|
||||
}
|
||||
|
@ -1936,16 +1943,51 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
}
|
||||
|
||||
getFriendship(speciesId: number) {
|
||||
let currentFriendship = globalScene.gameData.starterData[this.getStarterSpeciesId(speciesId)].friendship;
|
||||
let currentFriendship = globalScene.gameData.starterData[this.starterId].friendship;
|
||||
if (!currentFriendship || currentFriendship === undefined) {
|
||||
currentFriendship = 0;
|
||||
}
|
||||
|
||||
const friendshipCap = getStarterValueFriendshipCap(speciesStarterCosts[this.getStarterSpeciesId(speciesId)]);
|
||||
const friendshipCap = getStarterValueFriendshipCap(speciesStarterCosts[this.starterId]);
|
||||
|
||||
return { currentFriendship, friendshipCap };
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a passive upgrade is available for the current species
|
||||
* @returns true if the user has enough candies and a passive has not been unlocked already
|
||||
*/
|
||||
isPassiveAvailable(): boolean {
|
||||
// Get this species ID's starter data
|
||||
const starterData = globalScene.gameData.starterData[this.starterId];
|
||||
|
||||
return starterData.candyCount >= getPassiveCandyCount(speciesStarterCosts[this.starterId])
|
||||
&& !(starterData.passiveAttr & PassiveAttr.UNLOCKED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a value reduction upgrade is available for the current species
|
||||
* @returns true if the user has enough candies and all value reductions have not been unlocked already
|
||||
*/
|
||||
isValueReductionAvailable(): boolean {
|
||||
// Get this species ID's starter data
|
||||
const starterData = globalScene.gameData.starterData[this.starterId];
|
||||
|
||||
return starterData.candyCount >= getValueReductionCandyCounts(speciesStarterCosts[this.starterId])[starterData.valueReduction]
|
||||
&& starterData.valueReduction < valueReductionMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an same species egg can be bought for the current species
|
||||
* @returns true if the user has enough candies
|
||||
*/
|
||||
isSameSpeciesEggAvailable(): boolean {
|
||||
// Get this species ID's starter data
|
||||
const starterData = globalScene.gameData.starterData[this.starterId];
|
||||
|
||||
return starterData.candyCount >= getSameSpeciesEggCandyCounts(speciesStarterCosts[this.starterId]);
|
||||
}
|
||||
|
||||
setSpecies() {
|
||||
const species = this.species;
|
||||
const starterAttributes : StarterAttributes | null = species ? { ...this.starterAttributes } : null;
|
||||
|
@ -1967,88 +2009,10 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
if (species && (this.speciesStarterDexEntry?.seenAttr || this.isCaught())) {
|
||||
this.pokemonNumberText.setText(padInt(species.speciesId, 4));
|
||||
if (starterAttributes?.nickname) {
|
||||
const name = decodeURIComponent(escape(atob(starterAttributes.nickname)));
|
||||
this.pokemonNameText.setText(name);
|
||||
} else {
|
||||
this.pokemonNameText.setText(species.name);
|
||||
}
|
||||
|
||||
if (this.isCaught()) {
|
||||
const colorScheme = starterColors[species.speciesId];
|
||||
|
||||
const luck = globalScene.gameData.getDexAttrLuck(this.isCaught());
|
||||
this.pokemonLuckText.setVisible(!!luck);
|
||||
this.pokemonLuckText.setText(luck.toString());
|
||||
this.pokemonLuckText.setTint(getVariantTint(Math.min(luck - 1, 2) as Variant));
|
||||
this.pokemonLuckLabelText.setVisible(this.pokemonLuckText.visible);
|
||||
|
||||
//Growth translate
|
||||
let growthReadable = toReadableString(GrowthRate[species.growthRate]);
|
||||
const growthAux = growthReadable.replace(" ", "_");
|
||||
if (i18next.exists("growth:" + growthAux)) {
|
||||
growthReadable = i18next.t("growth:" + growthAux as any);
|
||||
}
|
||||
this.pokemonGrowthRateText.setText(growthReadable);
|
||||
|
||||
this.pokemonGrowthRateText.setColor(getGrowthRateColor(species.growthRate));
|
||||
this.pokemonGrowthRateText.setShadowColor(getGrowthRateColor(species.growthRate, true));
|
||||
this.pokemonGrowthRateLabelText.setVisible(true);
|
||||
this.pokemonUncaughtText.setVisible(false);
|
||||
this.pokemonCaughtCountText.setText(`${this.speciesStarterDexEntry?.caughtCount}`);
|
||||
if (species.speciesId === Species.MANAPHY || species.speciesId === Species.PHIONE) {
|
||||
this.pokemonHatchedIcon.setFrame("manaphy");
|
||||
} else {
|
||||
this.pokemonHatchedIcon.setFrame(getEggTierForSpecies(species));
|
||||
}
|
||||
this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry?.hatchedCount}`);
|
||||
|
||||
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||
const defaultProps = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||
const variant = defaultProps.variant;
|
||||
const tint = getVariantTint(variant);
|
||||
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
||||
this.pokemonShinyIcon.setTint(tint);
|
||||
this.pokemonShinyIcon.setVisible(defaultProps.shiny);
|
||||
this.pokemonCaughtHatchedContainer.setVisible(true);
|
||||
this.pokemonFormText.setVisible(true);
|
||||
|
||||
if (pokemonPrevolutions.hasOwnProperty(species.speciesId)) {
|
||||
this.pokemonCaughtHatchedContainer.setY(16);
|
||||
this.pokemonShinyIcon.setY(135);
|
||||
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
||||
[
|
||||
this.pokemonCandyContainer,
|
||||
this.pokemonHatchedIcon,
|
||||
this.pokemonHatchedCountText
|
||||
].map(c => c.setVisible(false));
|
||||
this.pokemonFormText.setY(25);
|
||||
} else {
|
||||
this.pokemonCaughtHatchedContainer.setY(25);
|
||||
this.pokemonShinyIcon.setY(117);
|
||||
this.pokemonCandyIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[0])));
|
||||
this.pokemonCandyOverlayIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[1])));
|
||||
this.pokemonCandyCountText.setText(`x${globalScene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].candyCount}`);
|
||||
this.pokemonCandyContainer.setVisible(true);
|
||||
this.pokemonFormText.setY(42);
|
||||
this.pokemonHatchedIcon.setVisible(true);
|
||||
this.pokemonHatchedCountText.setVisible(true);
|
||||
|
||||
const { currentFriendship, friendshipCap } = this.getFriendship(this.species.speciesId);
|
||||
const candyCropY = 16 - (16 * (currentFriendship / friendshipCap));
|
||||
this.pokemonCandyDarknessOverlay.setCrop(0, 0, 16, candyCropY);
|
||||
|
||||
this.pokemonCandyContainer.on("pointerover", () => {
|
||||
globalScene.ui.showTooltip("", `${currentFriendship}/${friendshipCap}`, true);
|
||||
this.activeTooltip = "CANDY";
|
||||
});
|
||||
this.pokemonCandyContainer.on("pointerout", () => {
|
||||
globalScene.ui.hideTooltip();
|
||||
this.activeTooltip = undefined;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Set default attributes if for some reason starterAttributes does not exist or attributes missing
|
||||
const props: StarterAttributes = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||
if (starterAttributes?.variant && !isNaN(starterAttributes.variant)) {
|
||||
|
@ -2065,12 +2029,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
female: props.female,
|
||||
variant: props.variant ?? 0,
|
||||
});
|
||||
|
||||
if (this.isFormCaught(this.species, props.form)) {
|
||||
const speciesForm = getPokemonSpeciesForm(species.speciesId, props.form ?? 0);
|
||||
this.setTypeIcons(speciesForm.type1, speciesForm.type2);
|
||||
this.pokemonSprite.clearTint();
|
||||
}
|
||||
} else {
|
||||
this.pokemonGrowthRateText.setText("");
|
||||
this.pokemonGrowthRateLabelText.setVisible(false);
|
||||
|
@ -2092,7 +2050,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
formIndex: props.formIndex,
|
||||
female: props.female,
|
||||
variant: props.variant,
|
||||
forSeen: true
|
||||
});
|
||||
this.pokemonSprite.setTint(0x808080);
|
||||
}
|
||||
|
@ -2123,7 +2080,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
|
||||
setSpeciesDetails(species: PokemonSpecies, options: SpeciesDetails = {}, forceUpdate?: boolean): void {
|
||||
let { shiny, formIndex, female, variant } = options;
|
||||
const forSeen: boolean = options.forSeen ?? false;
|
||||
const oldProps = species ? this.starterAttributes : null;
|
||||
|
||||
// We will only update the sprite if there is a change to form, shiny/variant
|
||||
|
@ -2194,12 +2150,12 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
}
|
||||
|
||||
const isFormCaught = this.isFormCaught();
|
||||
const isFormSeen = dexEntry ? (dexEntry.seenAttr & globalScene.gameData.getFormAttr(formIndex ?? 0)) > 0n : false;
|
||||
|
||||
this.shinyOverlay.setVisible(shiny ?? false); // TODO: is false the correct default?
|
||||
this.pokemonNumberText.setColor(this.getTextColor(shiny ? TextStyle.SUMMARY_GOLD : TextStyle.SUMMARY, false));
|
||||
this.pokemonNumberText.setShadowColor(this.getTextColor(shiny ? TextStyle.SUMMARY_GOLD : TextStyle.SUMMARY, true));
|
||||
|
||||
|
||||
const assetLoadCancelled = new BooleanHolder(false);
|
||||
this.assetLoadCancelled = assetLoadCancelled;
|
||||
|
||||
|
@ -2221,13 +2177,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
this.pokemonSprite.setVisible(!this.statsMode);
|
||||
}
|
||||
|
||||
const currentFilteredContainer = this.filteredStarterContainers.find(p => p.species.speciesId === species.speciesId);
|
||||
if (currentFilteredContainer) {
|
||||
const starterSprite = currentFilteredContainer.icon as Phaser.GameObjects.Sprite;
|
||||
starterSprite.setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female!, formIndex, shiny, variant));
|
||||
currentFilteredContainer.checkIconId(female, formIndex, shiny, variant);
|
||||
}
|
||||
|
||||
const isNonShinyCaught = !!(caughtAttr & DexAttr.NON_SHINY);
|
||||
const isShinyCaught = !!(caughtAttr & DexAttr.SHINY);
|
||||
|
||||
|
@ -2250,27 +2199,129 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
|||
this.pokemonGenderText.setText("");
|
||||
}
|
||||
|
||||
if (caughtAttr) {
|
||||
if (isFormCaught) {
|
||||
this.species.loadAssets(female!, formIndex, shiny, variant as Variant, true).then(() => {
|
||||
const crier = (this.species.forms && this.species.forms.length > 0) ? this.species.forms[formIndex ?? this.formIndex] : this.species;
|
||||
crier.cry();
|
||||
});
|
||||
|
||||
this.pokemonSprite.clearTint();
|
||||
} else {
|
||||
this.pokemonSprite.setTint(0x000000);
|
||||
}
|
||||
// Setting the name
|
||||
if (isFormCaught || isFormSeen) {
|
||||
this.pokemonNameText.setText(species.name);
|
||||
} else {
|
||||
this.pokemonNameText.setText(species ? "???" : "");
|
||||
}
|
||||
|
||||
if (caughtAttr || forSeen) {
|
||||
// Setting tint of the sprite
|
||||
if (isFormCaught) {
|
||||
this.species.loadAssets(female!, formIndex, shiny, variant as Variant, true).then(() => {
|
||||
const crier = (this.species.forms && this.species.forms.length > 0) ? this.species.forms[formIndex ?? this.formIndex] : this.species;
|
||||
crier.cry();
|
||||
});
|
||||
this.pokemonSprite.clearTint();
|
||||
} else if (isFormSeen) {
|
||||
this.pokemonSprite.setTint(0x808080);
|
||||
} else {
|
||||
this.pokemonSprite.setTint(0);
|
||||
}
|
||||
|
||||
// Setting luck text and sparks
|
||||
if (isFormCaught) {
|
||||
const luck = globalScene.gameData.getDexAttrLuck(this.isCaught());
|
||||
this.pokemonLuckText.setVisible(!!luck);
|
||||
this.pokemonLuckText.setText(luck.toString());
|
||||
this.pokemonLuckText.setTint(getVariantTint(Math.min(luck - 1, 2) as Variant));
|
||||
this.pokemonLuckLabelText.setVisible(this.pokemonLuckText.visible);
|
||||
} else {
|
||||
this.pokemonLuckText.setVisible(false);
|
||||
this.pokemonLuckLabelText.setVisible(false);
|
||||
}
|
||||
|
||||
// Setting growth rate text
|
||||
if (isFormCaught) {
|
||||
let growthReadable = toReadableString(GrowthRate[species.growthRate]);
|
||||
const growthAux = growthReadable.replace(" ", "_");
|
||||
if (i18next.exists("growth:" + growthAux)) {
|
||||
growthReadable = i18next.t("growth:" + growthAux as any);
|
||||
}
|
||||
this.pokemonGrowthRateText.setText(growthReadable);
|
||||
|
||||
this.pokemonGrowthRateText.setColor(getGrowthRateColor(species.growthRate));
|
||||
this.pokemonGrowthRateText.setShadowColor(getGrowthRateColor(species.growthRate, true));
|
||||
this.pokemonGrowthRateLabelText.setVisible(true);
|
||||
} else {
|
||||
this.pokemonGrowthRateText.setText("");
|
||||
this.pokemonGrowthRateLabelText.setVisible(false);
|
||||
}
|
||||
|
||||
// Caught and hatched
|
||||
if (isFormCaught) {
|
||||
const colorScheme = starterColors[this.starterId];
|
||||
|
||||
this.pokemonUncaughtText.setVisible(false);
|
||||
this.pokemonCaughtCountText.setText(`${this.speciesStarterDexEntry?.caughtCount}`);
|
||||
if (species.speciesId === Species.MANAPHY || species.speciesId === Species.PHIONE) {
|
||||
this.pokemonHatchedIcon.setFrame("manaphy");
|
||||
} else {
|
||||
this.pokemonHatchedIcon.setFrame(getEggTierForSpecies(species));
|
||||
}
|
||||
this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry?.hatchedCount}`);
|
||||
|
||||
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||
const defaultProps = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||
const variant = defaultProps.variant;
|
||||
const tint = getVariantTint(variant);
|
||||
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
||||
this.pokemonShinyIcon.setTint(tint);
|
||||
this.pokemonShinyIcon.setVisible(defaultProps.shiny);
|
||||
this.pokemonCaughtHatchedContainer.setVisible(true);
|
||||
|
||||
this.pokemonCaughtHatchedContainer.setY(25);
|
||||
this.pokemonCandyIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[0])));
|
||||
this.pokemonCandyOverlayIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[1])));
|
||||
this.pokemonCandyCountText.setText(`x${globalScene.gameData.starterData[this.starterId].candyCount}`);
|
||||
this.pokemonCandyContainer.setVisible(true);
|
||||
|
||||
if (pokemonPrevolutions.hasOwnProperty(species.speciesId)) {
|
||||
this.pokemonShinyIcon.setY(135);
|
||||
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
||||
this.pokemonHatchedIcon.setVisible(false);
|
||||
this.pokemonHatchedCountText.setVisible(false);
|
||||
this.pokemonFormText.setY(36);
|
||||
} else {
|
||||
this.pokemonShinyIcon.setY(117);
|
||||
this.pokemonHatchedIcon.setVisible(true);
|
||||
this.pokemonHatchedCountText.setVisible(true);
|
||||
this.pokemonFormText.setY(42);
|
||||
|
||||
const { currentFriendship, friendshipCap } = this.getFriendship(this.species.speciesId);
|
||||
const candyCropY = 16 - (16 * (currentFriendship / friendshipCap));
|
||||
this.pokemonCandyDarknessOverlay.setCrop(0, 0, 16, candyCropY);
|
||||
|
||||
this.pokemonCandyContainer.on("pointerover", () => {
|
||||
globalScene.ui.showTooltip("", `${currentFriendship}/${friendshipCap}`, true);
|
||||
this.activeTooltip = "CANDY";
|
||||
});
|
||||
this.pokemonCandyContainer.on("pointerout", () => {
|
||||
globalScene.ui.hideTooltip();
|
||||
this.activeTooltip = undefined;
|
||||
});
|
||||
|
||||
}
|
||||
} else {
|
||||
this.pokemonUncaughtText.setVisible(true);
|
||||
this.pokemonCaughtHatchedContainer.setVisible(false);
|
||||
this.pokemonCandyContainer.setVisible(false);
|
||||
this.pokemonShinyIcon.setVisible(false);
|
||||
}
|
||||
|
||||
// Setting type icons and form text
|
||||
if (isFormCaught || isFormSeen) {
|
||||
const speciesForm = getPokemonSpeciesForm(species.speciesId, formIndex!); // TODO: is the bang correct?
|
||||
this.setTypeIcons(speciesForm.type1, speciesForm.type2);
|
||||
this.pokemonFormText.setText(this.getFormString((speciesForm as PokemonForm).formKey, species));
|
||||
|
||||
this.pokemonFormText.setVisible(true);
|
||||
if (!isFormCaught) {
|
||||
this.pokemonFormText.setY(18);
|
||||
}
|
||||
} else {
|
||||
this.setTypeIcons(null, null);
|
||||
this.pokemonFormText.setText("");
|
||||
this.pokemonFormText.setVisible(false);
|
||||
}
|
||||
} else {
|
||||
this.shinyOverlay.setVisible(false);
|
||||
|
|
|
@ -11,7 +11,7 @@ import { allSpecies, getPokemonSpeciesForm, getPokerusStarters } from "#app/data
|
|||
import { getStarterValueFriendshipCap, speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters";
|
||||
import { catchableSpecies } from "#app/data/balance/biomes";
|
||||
import { Type } from "#enums/type";
|
||||
import type { DexAttrProps, DexEntry, StarterMoveset, StarterAttributes, StarterPreferences } from "#app/system/game-data";
|
||||
import type { DexAttrProps, DexEntry, StarterAttributes, StarterPreferences } from "#app/system/game-data";
|
||||
import { AbilityAttr, DexAttr, StarterPrefs } from "#app/system/game-data";
|
||||
import MessageUiHandler from "#app/ui/message-ui-handler";
|
||||
import PokemonIconAnimHandler, { PokemonIconAnimMode } from "#app/ui/pokemon-icon-anim-handler";
|
||||
|
@ -19,7 +19,6 @@ import { TextStyle, addTextObject } from "#app/ui/text";
|
|||
import { Mode } from "#app/ui/ui";
|
||||
import { SettingKeyboard } from "#app/system/settings/settings-keyboard";
|
||||
import { Passive as PassiveAttr } from "#enums/passive";
|
||||
import type { Moves } from "#enums/moves";
|
||||
import type { Species } from "#enums/species";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#app/ui/dropdown";
|
||||
|
@ -42,7 +41,6 @@ import { pokemonStarters } from "#app/data/balance/pokemon-evolutions";
|
|||
import { Biome } from "#enums/biome";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
|
||||
|
||||
interface LanguageSetting {
|
||||
starterInfoTextSize: string,
|
||||
instructionTextSize: string,
|
||||
|
@ -139,7 +137,6 @@ interface SpeciesDetails {
|
|||
variant?: Variant,
|
||||
abilityIndex?: number,
|
||||
natureIndex?: number,
|
||||
forSeen?: boolean, // default = false
|
||||
}
|
||||
|
||||
export default class PokedexUiHandler extends MessageUiHandler {
|
||||
|
@ -161,7 +158,6 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
|
||||
private filterMode: boolean;
|
||||
private filterBarCursor: number = 0;
|
||||
private starterMoveset: StarterMoveset | null;
|
||||
private scrollCursor: number;
|
||||
|
||||
private allSpecies: PokemonSpecies[] = [];
|
||||
|
@ -169,7 +165,6 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
private speciesLoaded: Map<Species, boolean> = new Map<Species, boolean>();
|
||||
private pokerusSpecies: PokemonSpecies[] = [];
|
||||
private speciesStarterDexEntry: DexEntry | null;
|
||||
private speciesStarterMoves: Moves[];
|
||||
|
||||
private assetLoadCancelled: BooleanHolder | null;
|
||||
public cursorObj: Phaser.GameObjects.Image;
|
||||
|
@ -206,6 +201,20 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
private toggleDecorationsIconElement: Phaser.GameObjects.Sprite;
|
||||
private toggleDecorationsLabel: Phaser.GameObjects.Text;
|
||||
|
||||
private formTrayContainer: Phaser.GameObjects.Container;
|
||||
private trayBg: Phaser.GameObjects.NineSlice;
|
||||
private trayForms: PokemonForm[];
|
||||
private trayContainers: PokedexMonContainer[] = [];
|
||||
private trayNumIcons: number;
|
||||
private trayRows: number;
|
||||
private trayColumns: number;
|
||||
private trayCursorObj: Phaser.GameObjects.Image;
|
||||
private trayCursor: number = 0;
|
||||
private showingTray: boolean = false;
|
||||
private showFormTrayIconElement: Phaser.GameObjects.Sprite;
|
||||
private showFormTrayLabel: Phaser.GameObjects.Text;
|
||||
private canShowFormTray: boolean;
|
||||
|
||||
constructor() {
|
||||
super(Mode.POKEDEX);
|
||||
}
|
||||
|
@ -425,7 +434,6 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
|
||||
this.cursorObj = globalScene.add.image(0, 0, "select_cursor");
|
||||
this.cursorObj.setOrigin(0, 0);
|
||||
|
||||
starterBoxContainer.add(this.cursorObj);
|
||||
|
||||
for (const species of allSpecies) {
|
||||
|
@ -438,6 +446,20 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
starterBoxContainer.add(pokemonContainer);
|
||||
}
|
||||
|
||||
// Tray to display forms
|
||||
this.formTrayContainer = globalScene.add.container(0, 0);
|
||||
|
||||
this.trayBg = addWindow(0, 0, 0, 0);
|
||||
this.trayBg.setOrigin(0, 0);
|
||||
this.formTrayContainer.add(this.trayBg);
|
||||
|
||||
this.trayCursorObj = globalScene.add.image(0, 0, "select_cursor");
|
||||
this.trayCursorObj.setOrigin(0, 0);
|
||||
this.formTrayContainer.add(this.trayCursorObj);
|
||||
starterBoxContainer.add(this.formTrayContainer);
|
||||
starterBoxContainer.bringToTop(this.formTrayContainer);
|
||||
this.formTrayContainer.setVisible(false);
|
||||
|
||||
this.starterSelectContainer.add(starterBoxContainer);
|
||||
|
||||
this.pokemonSprite = globalScene.add.sprite(96, 143, "pkmn__sub");
|
||||
|
@ -449,7 +471,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
this.type1Icon.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.type1Icon);
|
||||
|
||||
this.type2Icon = globalScene.add.sprite(10, 166, getLocalizedSpriteKey("types"));
|
||||
this.type2Icon = globalScene.add.sprite(28, 158, getLocalizedSpriteKey("types"));
|
||||
this.type2Icon.setScale(0.5);
|
||||
this.type2Icon.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.type2Icon);
|
||||
|
@ -488,6 +510,17 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
this.starterSelectContainer.add(this.toggleDecorationsIconElement);
|
||||
this.starterSelectContainer.add(this.toggleDecorationsLabel);
|
||||
|
||||
this.showFormTrayIconElement = new Phaser.GameObjects.Sprite(globalScene, 6, 168, "keyboard", "F.png");
|
||||
this.showFormTrayIconElement.setName("sprite-showFormTray-icon-element");
|
||||
this.showFormTrayIconElement.setScale(0.675);
|
||||
this.showFormTrayIconElement.setOrigin(0.0, 0.0);
|
||||
this.showFormTrayLabel = addTextObject(16, 168, i18next.t("pokedexUiHandler:showForms"), TextStyle.PARTY, { fontSize: instructionTextSize });
|
||||
this.showFormTrayLabel.setName("text-showFormTray-label");
|
||||
this.showFormTrayIconElement.setVisible(false);
|
||||
this.showFormTrayLabel.setVisible(false);
|
||||
this.starterSelectContainer.add(this.showFormTrayIconElement);
|
||||
this.starterSelectContainer.add(this.showFormTrayLabel);
|
||||
|
||||
this.message = addTextObject(8, 8, "", TextStyle.WINDOW, { maxLines: 2 });
|
||||
this.message.setOrigin(0, 0);
|
||||
this.starterSelectMessageBoxContainer.add(this.message);
|
||||
|
@ -527,7 +560,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
|
||||
this.starterPreferences[species.speciesId] = this.initStarterPrefs(species);
|
||||
|
||||
if (dexEntry.caughtAttr) {
|
||||
if (dexEntry.caughtAttr || globalScene.dexForDevs) {
|
||||
icon.clearTint();
|
||||
} else if (dexEntry.seenAttr) {
|
||||
icon.setTint(0x808080);
|
||||
|
@ -860,32 +893,42 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
} else if (this.filterTextMode && !(this.filterText.getValue(this.filterTextCursor) === this.filterText.defaultText)) {
|
||||
this.filterText.resetSelection(this.filterTextCursor);
|
||||
success = true;
|
||||
} else if (this.showingTray) {
|
||||
success = this.closeFormTray();
|
||||
} else {
|
||||
this.tryExit();
|
||||
success = true;
|
||||
}
|
||||
} else if (button === Button.STATS) {
|
||||
if (!this.filterMode) {
|
||||
if (!this.filterMode && !this.showingTray) {
|
||||
this.cursorObj.setVisible(false);
|
||||
this.setSpecies(null);
|
||||
this.filterText.cursorObj.setVisible(false);
|
||||
this.filterTextMode = false;
|
||||
this.filterBarCursor = 0;
|
||||
this.setFilterMode(true);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
} else if (button === Button.V) {
|
||||
if (!this.filterTextMode) {
|
||||
if (!this.filterTextMode && !this.showingTray) {
|
||||
this.cursorObj.setVisible(false);
|
||||
this.setSpecies(null);
|
||||
this.filterBar.cursorObj.setVisible(false);
|
||||
this.filterMode = false;
|
||||
this.filterTextCursor = 0;
|
||||
this.setFilterTextMode(true);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
} else if (button === Button.CYCLE_SHINY) {
|
||||
this.showDecorations = !this.showDecorations;
|
||||
this.updateScroll();
|
||||
success = true;
|
||||
if (!this.showingTray) {
|
||||
this.showDecorations = !this.showDecorations;
|
||||
this.updateScroll();
|
||||
success = true;
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
} else if (this.filterMode) {
|
||||
switch (button) {
|
||||
case Button.LEFT:
|
||||
|
@ -982,8 +1025,55 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
success = true;
|
||||
break;
|
||||
}
|
||||
} else if (this.showingTray) {
|
||||
if (button === Button.ACTION) {
|
||||
const formIndex = this.trayForms[this.trayCursor].formIndex;
|
||||
ui.setOverlayMode(Mode.POKEDEX_PAGE, this.lastSpecies, formIndex, { form: formIndex });
|
||||
success = true;
|
||||
} else {
|
||||
const numberOfForms = this.trayContainers.length;
|
||||
const numOfRows = Math.ceil(numberOfForms / maxColumns);
|
||||
const currentRow = Math.floor(this.trayCursor / maxColumns);
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (currentRow > 0) {
|
||||
success = this.setTrayCursor(this.trayCursor - 9);
|
||||
} else {
|
||||
const targetCol = this.trayCursor;
|
||||
if (numberOfForms % 9 > targetCol) {
|
||||
success = this.setTrayCursor(numberOfForms - (numberOfForms) % 9 + targetCol);
|
||||
} else {
|
||||
success = this.setTrayCursor(Math.max(numberOfForms - (numberOfForms) % 9 + targetCol - 9, 0));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (currentRow < numOfRows - 1) {
|
||||
success = this.setTrayCursor(this.trayCursor + 9);
|
||||
} else {
|
||||
success = this.setTrayCursor(this.trayCursor % 9);
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
if (this.trayCursor % 9 !== 0) {
|
||||
success = this.setTrayCursor(this.trayCursor - 1);
|
||||
} else {
|
||||
success = this.setTrayCursor(currentRow < numOfRows - 1 ? (currentRow + 1) * maxColumns - 1 : numberOfForms - 1);
|
||||
}
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
if (this.trayCursor % 9 < (currentRow < numOfRows - 1 ? 8 : (numberOfForms - 1) % 9)) {
|
||||
success = this.setTrayCursor(this.trayCursor + 1);
|
||||
} else {
|
||||
success = this.setTrayCursor(currentRow * 9);
|
||||
}
|
||||
break;
|
||||
case Button.CYCLE_FORM:
|
||||
success = this.closeFormTray();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (button === Button.ACTION) {
|
||||
ui.setOverlayMode(Mode.POKEDEX_PAGE, this.lastSpecies, 0);
|
||||
success = true;
|
||||
|
@ -1042,6 +1132,12 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
success = true;
|
||||
}
|
||||
break;
|
||||
case Button.CYCLE_FORM:
|
||||
const species = this.filteredPokemonContainers[this.cursor].species;
|
||||
if (this.canShowFormTray) {
|
||||
success = this.openFormTray(species);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1068,6 +1164,9 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
case SettingKeyboard.Button_Cycle_Variant:
|
||||
iconPath = "V.png";
|
||||
break;
|
||||
case SettingKeyboard.Button_Cycle_Form:
|
||||
iconPath = "F.png";
|
||||
break;
|
||||
case SettingKeyboard.Button_Stats:
|
||||
iconPath = "C.png";
|
||||
break;
|
||||
|
@ -1145,13 +1244,15 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
this.validPokemonContainers.forEach(container => {
|
||||
container.setVisible(false);
|
||||
|
||||
container.cost = globalScene.gameData.getSpeciesStarterValue(this.getStarterSpeciesId(container.species.speciesId));
|
||||
const starterId = this.getStarterSpeciesId(container.species.speciesId);
|
||||
|
||||
container.cost = globalScene.gameData.getSpeciesStarterValue(starterId);
|
||||
|
||||
// First, ensure you have the caught attributes for the species else default to bigint 0
|
||||
// TODO: This might be removed depending on how accessible we want the pokedex function to be
|
||||
const caughtAttr = globalScene.gameData.dexData[container.species.speciesId]?.caughtAttr || BigInt(0);
|
||||
const starterData = globalScene.gameData.starterData[this.getStarterSpeciesId(container.species.speciesId)];
|
||||
const isStarterProgressable = speciesEggMoves.hasOwnProperty(this.getStarterSpeciesId(container.species.speciesId));
|
||||
const starterData = globalScene.gameData.starterData[starterId];
|
||||
const isStarterProgressable = speciesEggMoves.hasOwnProperty(starterId);
|
||||
|
||||
// Name filter
|
||||
const selectedName = this.filterText.getValue(FilterTextRow.NAME);
|
||||
|
@ -1162,8 +1263,8 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
// On the other hand, in some cases it is possible to switch between different forms and combine (Deoxys)
|
||||
const levelMoves = pokemonSpeciesLevelMoves[container.species.speciesId].map(m => allMoves[m[1]].name);
|
||||
// This always gets egg moves from the starter
|
||||
const eggMoves = speciesEggMoves[this.getStarterSpeciesId(container.species.speciesId)]?.map(m => allMoves[m].name) ?? [];
|
||||
const tmMoves = speciesTmMoves[this.getStarterSpeciesId(container.species.speciesId)]?.map(m => allMoves[Array.isArray(m) ? m[1] : m].name) ?? [];
|
||||
const eggMoves = speciesEggMoves[starterId]?.map(m => allMoves[m].name) ?? [];
|
||||
const tmMoves = speciesTmMoves[starterId]?.map(m => allMoves[Array.isArray(m) ? m[1] : m].name) ?? [];
|
||||
const selectedMove1 = this.filterText.getValue(FilterTextRow.MOVE_1);
|
||||
const selectedMove2 = this.filterText.getValue(FilterTextRow.MOVE_2);
|
||||
|
||||
|
@ -1185,27 +1286,40 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
container.tmMove2Icon.setVisible(false);
|
||||
if (fitsEggMove1 && !fitsLevelMove1) {
|
||||
container.eggMove1Icon.setVisible(true);
|
||||
const em1 = eggMoves.findIndex(name => name === selectedMove1);
|
||||
if ((starterData[starterId].eggMoves & (1 << em1)) === 0) {
|
||||
container.eggMove1Icon.setTint(0x808080);
|
||||
} else {
|
||||
container.eggMove1Icon.clearTint();
|
||||
}
|
||||
} else if (fitsTmMove1 && !fitsLevelMove1) {
|
||||
container.tmMove1Icon.setVisible(true);
|
||||
}
|
||||
if (fitsEggMove2 && !fitsLevelMove2) {
|
||||
container.eggMove2Icon.setVisible(true);
|
||||
const em2 = eggMoves.findIndex(name => name === selectedMove2);
|
||||
if ((starterData[starterId].eggMoves & (1 << em2)) === 0) {
|
||||
container.eggMove2Icon.setTint(0x808080);
|
||||
} else {
|
||||
container.eggMove2Icon.clearTint();
|
||||
}
|
||||
} else if (fitsTmMove2 && !fitsLevelMove2) {
|
||||
container.tmMove2Icon.setVisible(true);
|
||||
}
|
||||
|
||||
// Ability filter
|
||||
const abilities = [ container.species.ability1, container.species.ability2, container.species.abilityHidden ].map(a => allAbilities[a].name);
|
||||
const passives = starterPassiveAbilities[this.getStarterSpeciesId(container.species.speciesId)] ?? {} as PassiveAbilities;
|
||||
const passives = starterPassiveAbilities[starterId] ?? {} as PassiveAbilities;
|
||||
|
||||
const selectedAbility1 = this.filterText.getValue(FilterTextRow.ABILITY_1);
|
||||
const fitsFormAbility = container.species.forms.some(form => allAbilities[form.ability1].name === selectedAbility1);
|
||||
const fitsAbility1 = abilities.includes(selectedAbility1) || fitsFormAbility || selectedAbility1 === this.filterText.defaultText;
|
||||
const fitsPassive1 = Object.values(passives).some(p => p.name === selectedAbility1);
|
||||
const fitsFormAbility1 = container.species.forms.some(form => [ form.ability1, form.ability2, form.abilityHidden ].map(a => allAbilities[a].name).includes(selectedAbility1));
|
||||
const fitsAbility1 = abilities.includes(selectedAbility1) || fitsFormAbility1 || selectedAbility1 === this.filterText.defaultText;
|
||||
const fitsPassive1 = Object.values(passives).some(p => allAbilities[p].name === selectedAbility1);
|
||||
|
||||
const selectedAbility2 = this.filterText.getValue(FilterTextRow.ABILITY_2);
|
||||
const fitsAbility2 = abilities.includes(selectedAbility2) || fitsFormAbility || selectedAbility2 === this.filterText.defaultText;
|
||||
const fitsPassive2 = Object.values(passives).some(p => p.name === selectedAbility2);
|
||||
const fitsFormAbility2 = container.species.forms.some(form => [ form.ability1, form.ability2, form.abilityHidden ].map(a => allAbilities[a].name).includes(selectedAbility2));
|
||||
const fitsAbility2 = abilities.includes(selectedAbility2) || fitsFormAbility2 || selectedAbility2 === this.filterText.defaultText;
|
||||
const fitsPassive2 = Object.values(passives).some(p => allAbilities[p].name === selectedAbility2);
|
||||
|
||||
// If both fields have been set to the same ability, show both ability and passive
|
||||
const fitsAbilities = (fitsAbility1 && (fitsPassive2 || selectedAbility2 === this.filterText.defaultText)) ||
|
||||
|
@ -1213,11 +1327,26 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
|
||||
container.passive1Icon.setVisible(false);
|
||||
container.passive2Icon.setVisible(false);
|
||||
if (fitsPassive1) {
|
||||
container.passive1Icon.setVisible(true);
|
||||
}
|
||||
if (fitsPassive2) {
|
||||
container.passive2Icon.setVisible(true);
|
||||
if (fitsPassive1 || fitsPassive2) {
|
||||
if (fitsPassive1) {
|
||||
if (starterData.passiveAttr > 0) {
|
||||
container.passive1Icon.clearTint();
|
||||
container.passive1OverlayIcon.clearTint();
|
||||
} else {
|
||||
container.passive1Icon.setTint(0x808080);
|
||||
container.passive1OverlayIcon.setTint(0x808080);
|
||||
}
|
||||
container.passive1Icon.setVisible(true);
|
||||
} else {
|
||||
if (starterData.passiveAttr > 0) {
|
||||
container.passive2Icon.clearTint();
|
||||
container.passive2OverlayIcon.clearTint();
|
||||
} else {
|
||||
container.passive2Icon.setTint(0x808080);
|
||||
container.passive2OverlayIcon.setTint(0x808080);
|
||||
}
|
||||
container.passive2Icon.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Gen filter
|
||||
|
@ -1236,7 +1365,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
|
||||
// We get biomes for both the mon and its starters to ensure that evolutions get the correct filters.
|
||||
// TODO: We might also need to do it the other way around.
|
||||
const biomes = catchableSpecies[container.species.speciesId].concat(catchableSpecies[this.getStarterSpeciesId(container.species.speciesId)]).map(b => Biome[b.biome]);
|
||||
const biomes = catchableSpecies[container.species.speciesId].concat(catchableSpecies[starterId]).map(b => Biome[b.biome]);
|
||||
if (biomes.length === 0) {
|
||||
biomes.push("Uncatchable");
|
||||
}
|
||||
|
@ -1530,6 +1659,8 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
this.cursorObj.setVisible(!filterMode);
|
||||
this.filterBar.cursorObj.setVisible(filterMode);
|
||||
this.pokemonSprite.setVisible(false);
|
||||
this.showFormTrayIconElement.setVisible(false);
|
||||
this.showFormTrayLabel.setVisible(false);
|
||||
|
||||
if (filterMode !== this.filterMode) {
|
||||
this.filterMode = filterMode;
|
||||
|
@ -1546,6 +1677,8 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
this.cursorObj.setVisible(!filterTextMode);
|
||||
this.filterText.cursorObj.setVisible(filterTextMode);
|
||||
this.pokemonSprite.setVisible(false);
|
||||
this.showFormTrayIconElement.setVisible(false);
|
||||
this.showFormTrayLabel.setVisible(false);
|
||||
|
||||
if (filterTextMode !== this.filterTextMode) {
|
||||
this.filterTextMode = filterTextMode;
|
||||
|
@ -1558,6 +1691,101 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
openFormTray(species: PokemonSpecies): boolean {
|
||||
|
||||
this.trayForms = species.forms;
|
||||
|
||||
this.trayNumIcons = this.trayForms.length;
|
||||
this.trayRows = Math.floor(this.trayNumIcons / 9) + (this.trayNumIcons % 9 === 0 ? 0 : 1);
|
||||
this.trayColumns = Math.min(this.trayNumIcons, 9);
|
||||
|
||||
const maxColumns = 9;
|
||||
const onScreenFirstIndex = this.scrollCursor * maxColumns;
|
||||
const boxCursor = this.cursor - onScreenFirstIndex;
|
||||
const boxCursorY = Math.floor(boxCursor / maxColumns);
|
||||
const boxCursorX = boxCursor - boxCursorY * 9;
|
||||
const spaceBelow = 9 - 1 - boxCursorY;
|
||||
const spaceRight = 9 - boxCursorX;
|
||||
const boxPos = calcStarterPosition(this.cursor, this.scrollCursor);
|
||||
const goUp = this.trayRows <= spaceBelow - 1 ? 0 : 1;
|
||||
const goLeft = this.trayColumns <= spaceRight ? 0 : 1;
|
||||
|
||||
this.trayBg.setSize(13 + this.trayColumns * 17, 8 + this.trayRows * 18);
|
||||
this.formTrayContainer.setX(
|
||||
(goLeft ? boxPos.x - 18 * (this.trayColumns - spaceRight) : boxPos.x) - 3
|
||||
);
|
||||
this.formTrayContainer.setY(
|
||||
goUp ? boxPos.y - this.trayBg.height : boxPos.y + 17
|
||||
);
|
||||
|
||||
const dexEntry = globalScene.gameData.dexData[species.speciesId];
|
||||
const dexAttr = this.getCurrentDexProps(species.speciesId);
|
||||
const props = this.getSanitizedProps(globalScene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr));
|
||||
|
||||
this.trayContainers = [];
|
||||
this.trayForms.map((f, index) => {
|
||||
const isFormCaught = dexEntry ? (dexEntry.caughtAttr & globalScene.gameData.getFormAttr(f.formIndex ?? 0)) > 0n : false;
|
||||
const isFormSeen = dexEntry ? (dexEntry.seenAttr & globalScene.gameData.getFormAttr(f.formIndex ?? 0)) > 0n : false;
|
||||
const formContainer = new PokedexMonContainer(species, { formIndex: f.formIndex, female: props.female, shiny: props.shiny, variant: props.variant });
|
||||
this.iconAnimHandler.addOrUpdate(formContainer.icon, PokemonIconAnimMode.NONE);
|
||||
// Setting tint, for all saves some caught forms may only show up as seen
|
||||
if (isFormCaught || globalScene.dexForDevs) {
|
||||
formContainer.icon.clearTint();
|
||||
} else if (isFormSeen) {
|
||||
formContainer.icon.setTint(0x808080);
|
||||
}
|
||||
formContainer.setPosition(5 + (index % 9) * 18, 4 + Math.floor(index / 9) * 17);
|
||||
this.formTrayContainer.add(formContainer);
|
||||
this.trayContainers.push(formContainer);
|
||||
});
|
||||
|
||||
this.showingTray = true;
|
||||
|
||||
this.setTrayCursor(0);
|
||||
|
||||
this.formTrayContainer.setVisible(true);
|
||||
|
||||
this.showFormTrayIconElement.setVisible(false);
|
||||
this.showFormTrayLabel.setVisible(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
closeFormTray(): boolean {
|
||||
|
||||
this.trayContainers.forEach(obj => {
|
||||
this.formTrayContainer.remove(obj, true); // Removes from container and destroys it
|
||||
});
|
||||
|
||||
this.trayContainers = [];
|
||||
this.formTrayContainer.setVisible(false);
|
||||
this.showingTray = false;
|
||||
|
||||
this.setSpeciesDetails(this.lastSpecies);
|
||||
return true;
|
||||
}
|
||||
|
||||
setTrayCursor(cursor: number): boolean {
|
||||
if (!this.showingTray) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cursor = Phaser.Math.Clamp(this.trayContainers.length - 1, cursor, 0);
|
||||
const changed = this.trayCursor !== cursor;
|
||||
if (changed) {
|
||||
this.trayCursor = cursor;
|
||||
}
|
||||
|
||||
this.trayCursorObj.setPosition(5 + (cursor % 9) * 18, 4 + Math.floor(cursor / 9) * 17);
|
||||
|
||||
const species = this.lastSpecies;
|
||||
const formIndex = this.trayForms[cursor].formIndex;
|
||||
|
||||
this.setSpeciesDetails(species, { formIndex: formIndex });
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
getFriendship(speciesId: number) {
|
||||
let currentFriendship = globalScene.gameData.starterData[this.getStarterSpeciesId(speciesId)].friendship;
|
||||
if (!currentFriendship || currentFriendship === undefined) {
|
||||
|
@ -1592,13 +1820,13 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
|
||||
this.lastSpecies = species!; // TODO: is this bang correct?
|
||||
|
||||
if (species && (this.speciesStarterDexEntry?.seenAttr || this.speciesStarterDexEntry?.caughtAttr)) {
|
||||
if (species && (this.speciesStarterDexEntry?.seenAttr || this.speciesStarterDexEntry?.caughtAttr || globalScene.dexForDevs)) {
|
||||
|
||||
this.pokemonNumberText.setText(i18next.t("pokedexUiHandler:pokemonNumber") + padInt(species.speciesId, 4));
|
||||
|
||||
this.pokemonNameText.setText(species.name);
|
||||
|
||||
if (this.speciesStarterDexEntry?.caughtAttr) {
|
||||
if (this.speciesStarterDexEntry?.caughtAttr || globalScene.dexForDevs) {
|
||||
|
||||
// Pause the animation when the species is selected
|
||||
const speciesIndex = this.allSpecies.indexOf(species);
|
||||
|
@ -1627,9 +1855,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
this.type1Icon.setVisible(true);
|
||||
this.type2Icon.setVisible(true);
|
||||
|
||||
this.setSpeciesDetails(species, {
|
||||
forSeen: true
|
||||
});
|
||||
this.setSpeciesDetails(species);
|
||||
this.pokemonSprite.setTint(0x808080);
|
||||
}
|
||||
} else {
|
||||
|
@ -1646,7 +1872,6 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
|
||||
setSpeciesDetails(species: PokemonSpecies, options: SpeciesDetails = {}): void {
|
||||
let { shiny, formIndex, female, variant } = options;
|
||||
const forSeen: boolean = options.forSeen ?? false;
|
||||
|
||||
// We will only update the sprite if there is a change to form, shiny/variant
|
||||
// or gender for species with gender sprite differences
|
||||
|
@ -1667,34 +1892,33 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
this.assetLoadCancelled = null;
|
||||
}
|
||||
|
||||
this.starterMoveset = null;
|
||||
this.speciesStarterMoves = [];
|
||||
|
||||
if (species) {
|
||||
const dexEntry = globalScene.gameData.dexData[species.speciesId];
|
||||
|
||||
if (!dexEntry.caughtAttr) {
|
||||
const props = this.getSanitizedProps(globalScene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)));
|
||||
|
||||
if (shiny === undefined || shiny !== props.shiny) {
|
||||
if (shiny === undefined) {
|
||||
shiny = props.shiny;
|
||||
}
|
||||
if (formIndex === undefined || formIndex !== props.formIndex) {
|
||||
if (formIndex === undefined) {
|
||||
formIndex = props.formIndex;
|
||||
}
|
||||
if (female === undefined || female !== props.female) {
|
||||
if (female === undefined) {
|
||||
female = props.female;
|
||||
}
|
||||
if (variant === undefined || variant !== props.variant) {
|
||||
if (variant === undefined) {
|
||||
variant = props.variant;
|
||||
}
|
||||
}
|
||||
|
||||
const isFormCaught = dexEntry ? (dexEntry.caughtAttr & globalScene.gameData.getFormAttr(formIndex ?? 0)) > 0n : false;
|
||||
const isFormSeen = dexEntry ? (dexEntry.seenAttr & globalScene.gameData.getFormAttr(formIndex ?? 0)) > 0n : false;
|
||||
|
||||
const assetLoadCancelled = new BooleanHolder(false);
|
||||
this.assetLoadCancelled = assetLoadCancelled;
|
||||
|
||||
if (shouldUpdateSprite) {
|
||||
|
||||
species.loadAssets(female!, formIndex, shiny, variant, true).then(() => { // TODO: is this bang correct?
|
||||
if (assetLoadCancelled.value) {
|
||||
return;
|
||||
|
@ -1711,21 +1935,37 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
this.pokemonSprite.setVisible(!(this.filterMode || this.filterTextMode));
|
||||
}
|
||||
|
||||
if (dexEntry.caughtAttr || forSeen) {
|
||||
if (isFormCaught || globalScene.dexForDevs) {
|
||||
this.pokemonSprite.clearTint();
|
||||
} else if (isFormSeen) {
|
||||
this.pokemonSprite.setTint(0x808080);
|
||||
} else {
|
||||
this.pokemonSprite.setTint(0);
|
||||
}
|
||||
|
||||
if (isFormCaught || isFormSeen || globalScene.dexForDevs) {
|
||||
const speciesForm = getPokemonSpeciesForm(species.speciesId, 0); // TODO: always selecting the first form
|
||||
|
||||
this.setTypeIcons(speciesForm.type1, speciesForm.type2);
|
||||
} else {
|
||||
this.setTypeIcons(null, null);
|
||||
}
|
||||
|
||||
if (species?.forms?.length > 1) {
|
||||
if (!this.showingTray) {
|
||||
this.showFormTrayIconElement.setVisible(true);
|
||||
this.showFormTrayLabel.setVisible(true);
|
||||
}
|
||||
this.canShowFormTray = true;
|
||||
} else {
|
||||
this.showFormTrayIconElement.setVisible(false);
|
||||
this.showFormTrayLabel.setVisible(false);
|
||||
this.canShowFormTray = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
this.setTypeIcons(null, null);
|
||||
}
|
||||
|
||||
if (!this.starterMoveset) {
|
||||
this.starterMoveset = this.speciesStarterMoves.slice(0, 4) as StarterMoveset;
|
||||
}
|
||||
}
|
||||
|
||||
setTypeIcons(type1: Type | null, type2: Type | null): void {
|
||||
|
@ -1784,7 +2024,6 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||
ui.showText(i18next.t("pokedexUiHandler:confirmExit"), null, () => {
|
||||
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
||||
ui.setMode(Mode.POKEDEX, "refresh");
|
||||
globalScene.clearPhaseQueue();
|
||||
this.clearText();
|
||||
this.clear();
|
||||
ui.revertMode();
|
||||
|
|
|
@ -1981,8 +1981,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
female: starterAttributes.female
|
||||
};
|
||||
ui.setOverlayMode(Mode.POKEDEX_PAGE, this.lastSpecies, starterAttributes.form, attributes);
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
options.push({
|
||||
|
|
Loading…
Reference in New Issue