Can access evolution page

This commit is contained in:
Wlowscha 2025-01-02 01:53:29 +01:00
parent e8d15a4d80
commit 3d0b4480e4
No known key found for this signature in database
GPG Key ID: 3C8F1AD330565D04
3 changed files with 112 additions and 98 deletions

View File

@ -1,11 +1,12 @@
import BattleScene from "../battle-scene"; import BattleScene from "../battle-scene";
import { TextStyle, addTextObject, getTextStyleOptions } from "./text"; import { TextStyle, addBBCodeTextObject, getTextStyleOptions } from "./text";
import { Mode } from "./ui"; import { Mode } from "./ui";
import UiHandler from "./ui-handler"; import UiHandler from "./ui-handler";
import { addWindow } from "./ui-theme"; import { addWindow } from "./ui-theme";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { argbFromRgba } from "@material/material-color-utilities"; import { argbFromRgba } from "@material/material-color-utilities";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
export interface OptionSelectConfig { export interface OptionSelectConfig {
xOffset?: number; xOffset?: number;
@ -21,8 +22,10 @@ export interface OptionSelectItem {
label: string; label: string;
handler: () => boolean; handler: () => boolean;
onHover?: () => void; onHover?: () => void;
skip?: boolean;
keepOpen?: boolean; keepOpen?: boolean;
overrideSound?: boolean; overrideSound?: boolean;
color?: string;
item?: string; item?: string;
itemArgs?: any[]; itemArgs?: any[];
} }
@ -33,7 +36,7 @@ const scrollDownLabel = "↓";
export default abstract class AbstractOptionSelectUiHandler extends UiHandler { export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
protected optionSelectContainer: Phaser.GameObjects.Container; protected optionSelectContainer: Phaser.GameObjects.Container;
protected optionSelectBg: Phaser.GameObjects.NineSlice; protected optionSelectBg: Phaser.GameObjects.NineSlice;
protected optionSelectText: Phaser.GameObjects.Text; protected optionSelectText: BBCodeText;
protected optionSelectIcons: Phaser.GameObjects.Sprite[]; protected optionSelectIcons: Phaser.GameObjects.Sprite[];
protected config: OptionSelectConfig | null; protected config: OptionSelectConfig | null;
@ -46,6 +49,9 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
private cursorObj: Phaser.GameObjects.Image | null; private cursorObj: Phaser.GameObjects.Image | null;
protected unskippedIndices: number[];
constructor(scene: BattleScene, mode: Mode | null) { constructor(scene: BattleScene, mode: Mode | null) {
super(scene, mode); super(scene, mode);
} }
@ -93,6 +99,8 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
options = configOptions; options = configOptions;
} }
this.unskippedIndices = this.getUnskippedIndices(options);
if (this.optionSelectText) { if (this.optionSelectText) {
this.optionSelectText.destroy(); this.optionSelectText.destroy();
} }
@ -101,10 +109,15 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
this.optionSelectIcons.splice(0, this.optionSelectIcons.length); this.optionSelectIcons.splice(0, this.optionSelectIcons.length);
} }
this.optionSelectText = addTextObject(this.scene, 0, 0, options.map(o => o.item ? ` ${o.label}` : o.label).join("\n"), TextStyle.WINDOW, { maxLines: options.length }); this.optionSelectText = addBBCodeTextObject(
this.optionSelectText.setLineSpacing(this.scale * 72); this.scene, 0, 0, options.map(o => o.item
? `[color=${o.color || "white"}] ${o.label}[/color]`
: `[color=${o.color || "white"}]${o.label}[/color]`
).join("\n"),
TextStyle.WINDOW, { maxLines: options.length, lineSpacing: 12 }
);
this.optionSelectText.setOrigin(0, 0);
this.optionSelectText.setName("text-option-select"); this.optionSelectText.setName("text-option-select");
this.optionSelectText.setLineSpacing(12);
this.optionSelectContainer.add(this.optionSelectText); this.optionSelectContainer.add(this.optionSelectText);
this.optionSelectContainer.setPosition((this.scene.game.canvas.width / 6) - 1 - (this.config?.xOffset || 0), -48 + (this.config?.yOffset || 0)); this.optionSelectContainer.setPosition((this.scene.game.canvas.width / 6) - 1 - (this.config?.xOffset || 0), -48 + (this.config?.yOffset || 0));
@ -116,7 +129,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
this.optionSelectBg.height = this.getWindowHeight(); this.optionSelectBg.height = this.getWindowHeight();
this.optionSelectText.setPositionRelative(this.optionSelectBg, 12 + 24 * this.scale, 2 + 42 * this.scale); this.optionSelectText.setPosition(this.optionSelectBg.x - this.optionSelectBg.width + 12 + 24 * this.scale, this.optionSelectBg.y - this.optionSelectBg.height + 2 + 42 * this.scale);
options.forEach((option: OptionSelectItem, i: integer) => { options.forEach((option: OptionSelectItem, i: integer) => {
if (option.item) { if (option.item) {
@ -178,6 +191,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
let success = false; let success = false;
const options = this.getOptionsWithScroll(); const options = this.getOptionsWithScroll();
const unskippedIndices = this.getUnskippedIndices(options);
let playSound = true; let playSound = true;
@ -226,11 +240,11 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
if (this.cursor) { if (this.cursor) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} else if (this.cursor === 0) { } else if (this.cursor === 0) {
success = this.setCursor(options.length - 1); success = this.setCursor(unskippedIndices.length - 1);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (this.cursor < options.length - 1) { if (this.cursor < unskippedIndices.length - 1) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} else { } else {
success = this.setCursor(0); success = this.setCursor(0);
@ -295,11 +309,19 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
return options; return options;
} }
getUnskippedIndices(options: OptionSelectItem[]) {
const unskippedIndices = options
.map((option, index) => (option.skip ? null : index)) // Map to index or null if skipped
.filter(index => index !== null) as number[];
return unskippedIndices;
}
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {
const changed = this.cursor !== cursor; const changed = this.cursor !== cursor;
let isScroll = false; let isScroll = false;
const options = this.getOptionsWithScroll(); const options = this.getOptionsWithScroll();
const unskippedIndices = this.getUnskippedIndices(options);
if (changed && this.config?.maxOptions && this.config.options.length > this.config.maxOptions) { if (changed && this.config?.maxOptions && this.config.options.length > this.config.maxOptions) {
if (Math.abs(cursor - this.cursor) === options.length - 1) { if (Math.abs(cursor - this.cursor) === options.length - 1) {
// Wrap around the list // Wrap around the list
@ -337,7 +359,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
} }
this.cursorObj.setScale(this.scale * 6); this.cursorObj.setScale(this.scale * 6);
this.cursorObj.setPositionRelative(this.optionSelectBg, 12, 102 * this.scale + this.cursor * (114 * this.scale - 3)); this.cursorObj.setPositionRelative(this.optionSelectBg, 12, 102 * this.scale + unskippedIndices[this.cursor] * (114 * this.scale - 3));
return changed; return changed;
} }

View File

@ -1,4 +1,4 @@
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonPrevolutions, pokemonStarters } from "#app/data/balance/pokemon-evolutions";
import { Variant, getVariantTint, getVariantIcon } from "#app/data/variant"; import { Variant, getVariantTint, getVariantIcon } from "#app/data/variant";
import { argbFromRgba } from "@material/material-color-utilities"; import { argbFromRgba } from "@material/material-color-utilities";
import i18next from "i18next"; import i18next from "i18next";
@ -755,9 +755,11 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
starterSetup(species): void { starterSetup(species): void {
// TODO: Make sure this takes into account all of pokemonFormLevelMoves properly! Should change when toggling forms. // TODO: Make sure this takes into account all of pokemonFormLevelMoves properly! Should change when toggling forms.
this.levelMoves = pokemonSpeciesLevelMoves[species.speciesId]; this.levelMoves = pokemonSpeciesLevelMoves[species.speciesId];
this.eggMoves = speciesEggMoves[species.speciesId] ?? []; this.eggMoves = speciesEggMoves[this.getStarterSpeciesId(species.speciesId)] ?? [];
this.hasEggMoves = Array.from({ length: 4 }, (_, em) => (this.scene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) !== 0); this.hasEggMoves = Array.from({ length: 4 }, (_, em) => (this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].eggMoves & (1 << em)) !== 0);
this.tmMoves = speciesTmMoves[species.speciesId].sort() ?? []; console.log(speciesTmMoves[species.speciesId ?? []]);
this.tmMoves = (speciesTmMoves[species.speciesId] ?? []).sort((a, b) => allMoves[a].name > allMoves[b].name ? 1 : -1);
console.log(this.tmMoves);
} }
/** /**
@ -771,7 +773,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
initStarterPrefs(species: PokemonSpecies): StarterAttributes { initStarterPrefs(species: PokemonSpecies): StarterAttributes {
const starterAttributes = this.starterPreferences[species.speciesId]; const starterAttributes = this.starterPreferences[species.speciesId];
const dexEntry = this.scene.gameData.dexData[species.speciesId]; const dexEntry = this.scene.gameData.dexData[species.speciesId];
const starterData = this.scene.gameData.starterData[species.speciesId]; const starterData = this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)];
// no preferences or Pokemon wasn't caught, return empty attribute // no preferences or Pokemon wasn't caught, return empty attribute
if (!starterAttributes || !dexEntry.caughtAttr) { if (!starterAttributes || !dexEntry.caughtAttr) {
@ -881,6 +883,22 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
return this.scene.candyUpgradeNotification !== 0 && this.scene.candyUpgradeDisplay === 1; return this.scene.candyUpgradeNotification !== 0 && this.scene.candyUpgradeDisplay === 1;
} }
getStarterSpeciesId(speciesId): number {
if (this.scene.gameData.starterData.hasOwnProperty(speciesId)) {
return speciesId;
} else {
return pokemonStarters[speciesId];
}
}
getStarterSpecies(species): PokemonSpecies {
if (this.scene.gameData.starterData.hasOwnProperty(species.speciesId)) {
return species;
} else {
return allSpecies.find(sp => sp.speciesId === pokemonStarters[species.speciesId]);
}
}
/** /**
* Determines if a passive upgrade is available for the given species ID * Determines if a passive upgrade is available for the given species ID
* @param speciesId The ID of the species to check the passive of * @param speciesId The ID of the species to check the passive of
@ -888,9 +906,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
*/ */
isPassiveAvailable(speciesId: number): boolean { isPassiveAvailable(speciesId: number): boolean {
// Get this species ID's starter data // Get this species ID's starter data
const starterData = this.scene.gameData.starterData[speciesId]; const starterData = this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)];
return starterData.candyCount >= getPassiveCandyCount(speciesStarterCosts[speciesId]) return starterData.candyCount >= getPassiveCandyCount(speciesStarterCosts[this.getStarterSpeciesId(speciesId)])
&& !(starterData.passiveAttr & PassiveAttr.UNLOCKED); && !(starterData.passiveAttr & PassiveAttr.UNLOCKED);
} }
@ -901,9 +919,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
*/ */
isValueReductionAvailable(speciesId: number): boolean { isValueReductionAvailable(speciesId: number): boolean {
// Get this species ID's starter data // Get this species ID's starter data
const starterData = this.scene.gameData.starterData[speciesId]; const starterData = this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)];
return starterData.candyCount >= getValueReductionCandyCounts(speciesStarterCosts[speciesId])[starterData.valueReduction] return starterData.candyCount >= getValueReductionCandyCounts(speciesStarterCosts[this.getStarterSpeciesId(speciesId)])[starterData.valueReduction]
&& starterData.valueReduction < valueReductionMax; && starterData.valueReduction < valueReductionMax;
} }
@ -914,9 +932,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
*/ */
isSameSpeciesEggAvailable(speciesId: number): boolean { isSameSpeciesEggAvailable(speciesId: number): boolean {
// Get this species ID's starter data // Get this species ID's starter data
const starterData = this.scene.gameData.starterData[speciesId]; const starterData = this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)];
return starterData.candyCount >= getSameSpeciesEggCandyCounts(speciesStarterCosts[speciesId]); return starterData.candyCount >= getSameSpeciesEggCandyCounts(speciesStarterCosts[this.getStarterSpeciesId(speciesId)]);
} }
/** /**
@ -1044,9 +1062,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
} else { } else {
let starterContainer; let starterContainer;
const starterData = this.scene.gameData.starterData[this.lastSpecies.speciesId]; const starterData = this.scene.gameData.starterData[this.getStarterSpeciesId(this.lastSpecies.speciesId)];
// prepare persistent starter data to store changes // prepare persistent starter data to store changes
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; let starterAttributes = this.starterPreferences[this.getStarterSpeciesId(this.lastSpecies.speciesId)];
if (button === Button.ACTION) { if (button === Button.ACTION) {
@ -1115,35 +1133,35 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.moveInfoOverlay.show(allMoves[this.eggMoves[0]]); this.moveInfoOverlay.show(allMoves[this.eggMoves[0]]);
ui.setModeWithoutClear(Mode.LOCKABLE_SELECT, { ui.setModeWithoutClear(Mode.OPTION_SELECT, {
options: [ options: [
// Add the "Common" title option // Add the "Common" title option
{ {
label: "Common", label: "Common:",
title: true, // Marks it as a title skip: true,
locked: false, // Titles are not lockable color: "#ccbe00",
handler: () => false, // Non-selectable, but handler is required handler: () => false, // Non-selectable, but handler is required
onHover: () => {} // No hover behavior for titles onHover: () => this.moveInfoOverlay.clear() // No hover behavior for titles
}, },
// Add the first 3 egg moves // Add the first 3 egg moves
...this.eggMoves.slice(0, 3).map((m, i) => ({ ...this.eggMoves.slice(0, 3).map((m, i) => ({
label: allMoves[m].name, label: allMoves[m].name,
locked: !this.hasEggMoves[i], color: this.hasEggMoves[i] ? "#ffffff" : "#6b5a73",
handler: () => false, handler: () => false,
onHover: () => this.moveInfoOverlay.show(allMoves[m]) onHover: () => this.moveInfoOverlay.show(allMoves[m])
})), })),
// Add the "Rare" title option // Add the "Rare" title option
{ {
label: "Rare", label: "Rare:",
title: true, skip: true,
locked: false, color: "#ccbe00",
handler: () => false, handler: () => false,
onHover: () => {} onHover: () => this.moveInfoOverlay.clear()
}, },
// Add the remaining egg moves (4th onwards) // Add the remaining egg moves (4th onwards)
{ {
label: allMoves[this.eggMoves[3]].name, label: allMoves[this.eggMoves[3]].name,
locked: !this.hasEggMoves[3], color: this.hasEggMoves[3] ? "#ffffff" : "#6b5a73",
handler: () => false, handler: () => false,
onHover: () => this.moveInfoOverlay.show(allMoves[this.eggMoves[3]]) onHover: () => this.moveInfoOverlay.show(allMoves[this.eggMoves[3]])
}, },
@ -1256,7 +1274,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
handler: () => { handler: () => {
// update default nature in starter save data // update default nature in starter save data
if (!starterAttributes) { if (!starterAttributes) {
starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] = {}; starterAttributes = this.starterPreferences[this.getStarterSpeciesId(this.lastSpecies.speciesId)] = {};
} }
starterAttributes.nature = n; starterAttributes.nature = n;
this.clearText(); this.clearText();
@ -1301,9 +1319,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
// Unlock passive option // Unlock passive option
if (!(passiveAttr & PassiveAttr.UNLOCKED)) { if (!(passiveAttr & PassiveAttr.UNLOCKED)) {
const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.lastSpecies.speciesId]); const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.getStarterSpeciesId(this.lastSpecies.speciesId)]);
options.push({ options.push({
label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")} (${allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name})`, label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")} (${allAbilities[starterPassiveAbilities[this.getStarterSpeciesId(this.lastSpecies.speciesId)]].name})`,
handler: () => { handler: () => {
if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) { if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) {
starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED; starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED;
@ -1323,21 +1341,21 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
// update the passive background and icon/animation for available upgrade // update the passive background and icon/animation for available upgrade
if (starterContainer) { if (starterContainer) {
this.updateCandyUpgradeDisplay(starterContainer); this.updateCandyUpgradeDisplay(starterContainer);
starterContainer.starterPassiveBgs.setVisible(!!this.scene.gameData.starterData[this.lastSpecies.speciesId].passiveAttr); starterContainer.starterPassiveBgs.setVisible(!!this.scene.gameData.starterData[this.getStarterSpeciesId(this.lastSpecies.speciesId)].passiveAttr);
} }
return true; return true;
} }
return false; return false;
}, },
item: "candy", item: "candy",
itemArgs: starterColors[this.lastSpecies.speciesId] itemArgs: starterColors[this.getStarterSpeciesId(this.lastSpecies.speciesId)]
}); });
} }
// Reduce cost option // Reduce cost option
const valueReduction = starterData.valueReduction; const valueReduction = starterData.valueReduction;
if (valueReduction < valueReductionMax) { if (valueReduction < valueReductionMax) {
const reductionCost = getValueReductionCandyCounts(speciesStarterCosts[this.lastSpecies.speciesId])[valueReduction]; const reductionCost = getValueReductionCandyCounts(speciesStarterCosts[this.getStarterSpeciesId(this.lastSpecies.speciesId)])[valueReduction];
options.push({ options.push({
label: `x${reductionCost} ${i18next.t("starterSelectUiHandler:reduceCost")}`, label: `x${reductionCost} ${i18next.t("starterSelectUiHandler:reduceCost")}`,
handler: () => { handler: () => {
@ -1364,12 +1382,12 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
return false; return false;
}, },
item: "candy", item: "candy",
itemArgs: starterColors[this.lastSpecies.speciesId] itemArgs: starterColors[this.getStarterSpeciesId(this.lastSpecies.speciesId)]
}); });
} }
// Same species egg menu option. // Same species egg menu option.
const sameSpeciesEggCost = getSameSpeciesEggCandyCounts(speciesStarterCosts[this.lastSpecies.speciesId]); const sameSpeciesEggCost = getSameSpeciesEggCandyCounts(speciesStarterCosts[this.getStarterSpeciesId(this.lastSpecies.speciesId)]);
options.push({ options.push({
label: `x${sameSpeciesEggCost} ${i18next.t("starterSelectUiHandler:sameSpeciesEgg")}`, label: `x${sameSpeciesEggCost} ${i18next.t("starterSelectUiHandler:sameSpeciesEgg")}`,
handler: () => { handler: () => {
@ -1405,7 +1423,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
return false; return false;
}, },
item: "candy", item: "candy",
itemArgs: starterColors[this.lastSpecies.speciesId] itemArgs: starterColors[this.getStarterSpeciesId(this.lastSpecies.speciesId)]
}); });
options.push({ options.push({
label: i18next.t("menu:cancel"), label: i18next.t("menu:cancel"),
@ -1502,11 +1520,12 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
let newFormIndex = props.formIndex; let newFormIndex = props.formIndex;
do { do {
newFormIndex = (newFormIndex + 1) % formCount; newFormIndex = (newFormIndex + 1) % formCount;
if (this.lastSpecies.forms[newFormIndex].isStarterSelectable && this.speciesStarterDexEntry!.caughtAttr! & this.scene.gameData.getFormAttr(newFormIndex)) { // TODO: are those bangs correct? if (this.speciesStarterDexEntry!.caughtAttr! & this.scene.gameData.getFormAttr(newFormIndex)) { // TODO: are those bangs correct?
break; break;
} }
} while (newFormIndex !== props.formIndex); } while (newFormIndex !== props.formIndex);
starterAttributes.form = newFormIndex; // store the selected form starterAttributes.form = newFormIndex; // store the selected form
this.levelMoves = pokemonFormLevelMoves[this.lastSpecies.speciesId][newFormIndex];
this.setSpeciesDetails(this.lastSpecies, { formIndex: newFormIndex }); this.setSpeciesDetails(this.lastSpecies, { formIndex: newFormIndex });
success = true; success = true;
} }
@ -1521,7 +1540,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
case Button.CYCLE_ABILITY: case Button.CYCLE_ABILITY:
if (this.canCycleAbility) { if (this.canCycleAbility) {
const abilityCount = this.lastSpecies.getAbilityCount(); const abilityCount = this.lastSpecies.getAbilityCount();
const abilityAttr = this.scene.gameData.starterData[this.lastSpecies.speciesId].abilityAttr; const abilityAttr = this.scene.gameData.starterData[this.getStarterSpeciesId(this.lastSpecies.speciesId)].abilityAttr;
const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1; const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1;
let newAbilityIndex = this.abilityCursor; let newAbilityIndex = this.abilityCursor;
do { do {
@ -1608,25 +1627,25 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
// species has different forms // species has different forms
if (pokemonFormLevelMoves.hasOwnProperty(speciesId)) { if (pokemonFormLevelMoves.hasOwnProperty(speciesId)) {
// starterMoveData doesn't have base form moves or is using the single form format // starterMoveData doesn't have base form moves or is using the single form format
if (!this.scene.gameData.starterData[speciesId].moveset || Array.isArray(this.scene.gameData.starterData[speciesId].moveset)) { if (!this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)].moveset || Array.isArray(this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)].moveset)) {
this.scene.gameData.starterData[speciesId].moveset = { [props.formIndex]: this.starterMoveset?.slice(0) as StarterMoveset }; this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)].moveset = { [props.formIndex]: this.starterMoveset?.slice(0) as StarterMoveset };
} }
const starterMoveData = this.scene.gameData.starterData[speciesId].moveset; const starterMoveData = this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)].moveset;
// starterMoveData doesn't have active form moves // starterMoveData doesn't have active form moves
if (!starterMoveData.hasOwnProperty(props.formIndex)) { if (!starterMoveData.hasOwnProperty(props.formIndex)) {
this.scene.gameData.starterData[speciesId].moveset[props.formIndex] = this.starterMoveset?.slice(0) as StarterMoveset; this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)].moveset[props.formIndex] = this.starterMoveset?.slice(0) as StarterMoveset;
} }
// does the species' starter move data have its form's starter moves and has it been updated // does the species' starter move data have its form's starter moves and has it been updated
if (starterMoveData.hasOwnProperty(props.formIndex)) { if (starterMoveData.hasOwnProperty(props.formIndex)) {
// active form move hasn't been updated // active form move hasn't been updated
if (starterMoveData[props.formIndex][existingMoveIndex] !== newMove) { if (starterMoveData[props.formIndex][existingMoveIndex] !== newMove) {
this.scene.gameData.starterData[speciesId].moveset[props.formIndex] = this.starterMoveset?.slice(0) as StarterMoveset; this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)].moveset[props.formIndex] = this.starterMoveset?.slice(0) as StarterMoveset;
} }
} }
} else { } else {
this.scene.gameData.starterData[speciesId].moveset = this.starterMoveset?.slice(0) as StarterMoveset; this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)].moveset = this.starterMoveset?.slice(0) as StarterMoveset;
} }
this.setSpeciesDetails(this.lastSpecies, { forSeen: false }); this.setSpeciesDetails(this.lastSpecies, { forSeen: false });
@ -1792,12 +1811,12 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
getFriendship(speciesId: number) { getFriendship(speciesId: number) {
let currentFriendship = this.scene.gameData.starterData[speciesId].friendship; let currentFriendship = this.scene.gameData.starterData[this.getStarterSpeciesId(speciesId)].friendship;
if (!currentFriendship || currentFriendship === undefined) { if (!currentFriendship || currentFriendship === undefined) {
currentFriendship = 0; currentFriendship = 0;
} }
const friendshipCap = getStarterValueFriendshipCap(speciesStarterCosts[speciesId]); const friendshipCap = getStarterValueFriendshipCap(speciesStarterCosts[this.getStarterSpeciesId(speciesId)]);
return { currentFriendship, friendshipCap }; return { currentFriendship, friendshipCap };
} }
@ -1805,8 +1824,8 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
setSpecies(species: PokemonSpecies | null) { setSpecies(species: PokemonSpecies | null) {
this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null; this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null;
this.dexAttrCursor = species ? this.getCurrentDexProps(species.speciesId) : 0n; this.dexAttrCursor = species ? this.getCurrentDexProps(species.speciesId) : 0n;
this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0; this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(this.getStarterSpecies(species)) : 0;
this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(species) : 0; this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(this.getStarterSpecies(species)) : 0;
if (!species && this.scene.ui.getTooltip().visible) { if (!species && this.scene.ui.getTooltip().visible) {
this.scene.ui.hideTooltip(); this.scene.ui.hideTooltip();
@ -1837,19 +1856,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
} }
} }
if (this.lastSpecies) {
const dexAttr = this.getCurrentDexProps(this.lastSpecies.speciesId);
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr);
const speciesIndex = this.allSpecies.indexOf(this.lastSpecies);
const lastSpeciesIcon = this.starterContainers[speciesIndex].icon;
this.checkIconId(lastSpeciesIcon, this.lastSpecies, props.female, props.formIndex, props.shiny, props.variant);
this.iconAnimHandler.addOrUpdate(lastSpeciesIcon, PokemonIconAnimMode.NONE);
// Resume the animation for the previously selected species
const icon = this.starterContainers[speciesIndex].icon;
this.scene.tweens.getTweensOf(icon).forEach(tween => tween.resume());
}
this.lastSpecies = species!; // TODO: is this bang correct? this.lastSpecies = species!; // TODO: is this bang correct?
if (species && (this.speciesStarterDexEntry?.seenAttr || this.speciesStarterDexEntry?.caughtAttr)) { if (species && (this.speciesStarterDexEntry?.seenAttr || this.speciesStarterDexEntry?.caughtAttr)) {
@ -1918,7 +1924,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.pokemonShinyIcon.setY(117); this.pokemonShinyIcon.setY(117);
this.pokemonCandyIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[0]))); this.pokemonCandyIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[0])));
this.pokemonCandyOverlayIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[1]))); this.pokemonCandyOverlayIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[1])));
this.pokemonCandyCountText.setText(`x${this.scene.gameData.starterData[species.speciesId].candyCount}`); this.pokemonCandyCountText.setText(`x${this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].candyCount}`);
this.pokemonCandyContainer.setVisible(true); this.pokemonCandyContainer.setVisible(true);
this.pokemonFormText.setY(42); this.pokemonFormText.setY(42);
this.pokemonHatchedIcon.setVisible(true); this.pokemonHatchedIcon.setVisible(true);
@ -1939,21 +1945,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
} }
// Pause the animation when the species is selected
const speciesIndex = this.allSpecies.indexOf(species);
const icon = this.starterContainers[speciesIndex].icon;
if (this.isUpgradeAnimationEnabled()) {
this.scene.tweens.getTweensOf(icon).forEach(tween => tween.pause());
// Reset the position of the icon
icon.x = -2;
icon.y = 2;
}
// Initiates the small up and down idle animation
this.iconAnimHandler.addOrUpdate(icon, PokemonIconAnimMode.PASSIVE);
const starterIndex = this.starterSpecies.indexOf(species); const starterIndex = this.starterSpecies.indexOf(species);
let props: DexAttrProps; let props: DexAttrProps;
@ -1970,9 +1961,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
}); });
} else { } else {
const defaultDexAttr = this.getCurrentDexProps(species.speciesId); const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(this.getStarterSpecies(species));
// load default nature from stater save data, if set // load default nature from stater save data, if set
const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(species); const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(this.getStarterSpecies(species));
props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
if (starterAttributes?.variant && !isNaN(starterAttributes.variant)) { if (starterAttributes?.variant && !isNaN(starterAttributes.variant)) {
if (props.shiny) { if (props.shiny) {
@ -2016,8 +2007,8 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.pokemonFormText.setVisible(false); this.pokemonFormText.setVisible(false);
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, true, true); const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, true, true);
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(this.getStarterSpecies(species));
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species); const defaultNature = this.scene.gameData.getSpeciesDefaultNature(this.getStarterSpecies(species));
const props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); const props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
this.setSpeciesDetails(species, { this.setSpeciesDetails(species, {
@ -2065,8 +2056,8 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
let { shiny, formIndex, female, variant, abilityIndex, natureIndex } = options; let { shiny, formIndex, female, variant, abilityIndex, natureIndex } = options;
const forSeen: boolean = options.forSeen ?? false; const forSeen: boolean = options.forSeen ?? false;
const oldProps = species ? this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null; const oldProps = species ? this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null;
const oldAbilityIndex = this.abilityCursor > -1 ? this.abilityCursor : this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); const oldAbilityIndex = this.abilityCursor > -1 ? this.abilityCursor : this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(this.getStarterSpecies(species));
const oldNatureIndex = this.natureCursor > -1 ? this.natureCursor : this.scene.gameData.getSpeciesDefaultNature(species); const oldNatureIndex = this.natureCursor > -1 ? this.natureCursor : this.scene.gameData.getSpeciesDefaultNature(this.getStarterSpecies(species));
this.dexAttrCursor = 0n; this.dexAttrCursor = 0n;
this.abilityCursor = -1; this.abilityCursor = -1;
this.natureCursor = -1; this.natureCursor = -1;
@ -2118,14 +2109,14 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
if (species) { if (species) {
const dexEntry = this.scene.gameData.dexData[species.speciesId]; const dexEntry = this.scene.gameData.dexData[species.speciesId];
const abilityAttr = this.scene.gameData.starterData[species.speciesId].abilityAttr; const abilityAttr = this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].abilityAttr;
const caughtAttr = this.scene.gameData.dexData[species.speciesId]?.caughtAttr || BigInt(0); const caughtAttr = this.scene.gameData.dexData[species.speciesId]?.caughtAttr || BigInt(0);
if (!dexEntry.caughtAttr) { if (!dexEntry.caughtAttr) {
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)); const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId));
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(this.getStarterSpecies(species));
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species); const defaultNature = this.scene.gameData.getSpeciesDefaultNature(this.getStarterSpecies(species));
if (shiny === undefined || shiny !== props.shiny) { if (shiny === undefined || shiny !== props.shiny) {
shiny = props.shiny; shiny = props.shiny;
@ -2240,8 +2231,8 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.pokemonAbilityText.setColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD)); this.pokemonAbilityText.setColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD));
this.pokemonAbilityText.setShadowColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true)); this.pokemonAbilityText.setShadowColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true));
const passiveAttr = this.scene.gameData.starterData[species.speciesId].passiveAttr; const passiveAttr = this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].passiveAttr;
const passiveAbility = allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]]; const passiveAbility = allAbilities[starterPassiveAbilities[this.getStarterSpeciesId(this.lastSpecies.speciesId)]];
if (this.pokemonAbilityText.visible) { if (this.pokemonAbilityText.visible) {
if (this.activeTooltip === "ABILITY") { if (this.activeTooltip === "ABILITY") {
@ -2314,19 +2305,19 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.speciesStarterMoves.push(...levelMoves.filter(lm => lm[0] > 0 && lm[0] <= 5).map(lm => lm[1])); this.speciesStarterMoves.push(...levelMoves.filter(lm => lm[0] > 0 && lm[0] <= 5).map(lm => lm[1]));
if (speciesEggMoves.hasOwnProperty(species.speciesId)) { if (speciesEggMoves.hasOwnProperty(species.speciesId)) {
for (let em = 0; em < 4; em++) { for (let em = 0; em < 4; em++) {
if (this.scene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) { if (this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].eggMoves & (1 << em)) {
this.speciesStarterMoves.push(speciesEggMoves[species.speciesId][em]); this.speciesStarterMoves.push(speciesEggMoves[species.speciesId][em]);
} }
} }
} }
const speciesMoveData = this.scene.gameData.starterData[species.speciesId].moveset; const speciesMoveData = this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].moveset;
const moveData: StarterMoveset | null = speciesMoveData const moveData: StarterMoveset | null = speciesMoveData
? Array.isArray(speciesMoveData) ? Array.isArray(speciesMoveData)
? speciesMoveData ? speciesMoveData
: speciesMoveData[formIndex!] // TODO: is this bang correct? : speciesMoveData[formIndex!] // TODO: is this bang correct?
: null; : null;
const availableStarterMoves = this.speciesStarterMoves.concat(speciesEggMoves.hasOwnProperty(species.speciesId) ? speciesEggMoves[species.speciesId].filter((_, em: integer) => this.scene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) : []); const availableStarterMoves = this.speciesStarterMoves.concat(speciesEggMoves.hasOwnProperty(species.speciesId) ? speciesEggMoves[species.speciesId].filter((_, em: integer) => this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].eggMoves & (1 << em)) : []);
this.starterMoveset = (moveData || (this.speciesStarterMoves.slice(0, 4) as StarterMoveset)).filter(m => availableStarterMoves.find(sm => sm === m)) as StarterMoveset; this.starterMoveset = (moveData || (this.speciesStarterMoves.slice(0, 4) as StarterMoveset)).filter(m => availableStarterMoves.find(sm => sm === m)) as StarterMoveset;
// Consolidate move data if it contains an incompatible move // Consolidate move data if it contains an incompatible move
if (this.starterMoveset.length < 4 && this.starterMoveset.length < availableStarterMoves.length) { if (this.starterMoveset.length < 4 && this.starterMoveset.length < availableStarterMoves.length) {
@ -2383,7 +2374,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
for (let em = 0; em < 4; em++) { for (let em = 0; em < 4; em++) {
const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null; const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null;
const eggMoveUnlocked = eggMove && this.scene.gameData.starterData[species.speciesId].eggMoves & (1 << em); const eggMoveUnlocked = eggMove && this.scene.gameData.starterData[this.getStarterSpeciesId(species.speciesId)].eggMoves & (1 << em);
this.pokemonEggMoveBgs[em].setFrame(Type[eggMove ? eggMove.type : Type.UNKNOWN].toString().toLowerCase()); this.pokemonEggMoveBgs[em].setFrame(Type[eggMove ? eggMove.type : Type.UNKNOWN].toString().toLowerCase());
this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : "???"); this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : "???");
} }

View File

@ -131,6 +131,7 @@ export default class PokedexScanUiHandler extends FormModalUiHandler {
} }
// args[2] is an index of FilterTextRow // args[2] is an index of FilterTextRow
//TODO: This logic is probably way more complex than we need, and actually messes things up for moves and abilities with a space like "Leech Seed"
show(args: any[]): boolean { show(args: any[]): boolean {
const ui = this.getUi(); const ui = this.getUi();
const hasTitle = !!this.getModalTitle(); const hasTitle = !!this.getModalTitle();