Rework dex system and add starter IVs
parent
4f6f17e63e
commit
b4f2700a59
Binary file not shown.
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 292 B |
|
@ -106,10 +106,12 @@ export class SelectStarterPhase extends BattlePhase {
|
||||||
const party = this.scene.getParty();
|
const party = this.scene.getParty();
|
||||||
const loadPokemonAssets: Promise<void>[] = [];
|
const loadPokemonAssets: Promise<void>[] = [];
|
||||||
for (let starter of starters) {
|
for (let starter of starters) {
|
||||||
|
const starterProps = this.scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr);
|
||||||
const starterGender = starter.species.malePercent !== null
|
const starterGender = starter.species.malePercent !== null
|
||||||
? !starter.female ? Gender.MALE : Gender.FEMALE
|
? !starterProps.female ? Gender.MALE : Gender.FEMALE
|
||||||
: Gender.GENDERLESS;
|
: Gender.GENDERLESS;
|
||||||
const starterPokemon = new PlayerPokemon(this.scene, starter.species, startingLevel, starter.abilityIndex, starter.formIndex, starterGender, starter.shiny);
|
const starterIvs = this.scene.gameData.dexData[starter.species.speciesId].ivs.slice(0);
|
||||||
|
const starterPokemon = new PlayerPokemon(this.scene, starter.species, startingLevel, starterProps.abilityIndex, starterProps.formIndex, starterGender, starterProps.shiny, starterIvs);
|
||||||
if (starter.pokerus)
|
if (starter.pokerus)
|
||||||
starterPokemon.pokerus = true;
|
starterPokemon.pokerus = true;
|
||||||
if (this.scene.gameMode === GameMode.SPLICED_ENDLESS)
|
if (this.scene.gameMode === GameMode.SPLICED_ENDLESS)
|
||||||
|
@ -256,6 +258,7 @@ export class EncounterPhase extends BattlePhase {
|
||||||
if (e < (battle.double ? 2 : 1)) {
|
if (e < (battle.double ? 2 : 1)) {
|
||||||
enemyPokemon.setX(-66 + enemyPokemon.getFieldPositionOffset()[0]);
|
enemyPokemon.setX(-66 + enemyPokemon.getFieldPositionOffset()[0]);
|
||||||
enemyPokemon.resetSummonData();
|
enemyPokemon.resetSummonData();
|
||||||
|
if (!this.loaded)
|
||||||
this.scene.gameData.setPokemonSeen(enemyPokemon);
|
this.scene.gameData.setPokemonSeen(enemyPokemon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,8 +298,10 @@ export class EncounterPhase extends BattlePhase {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scene.ui.setMode(Mode.MESSAGE).then(() => {
|
this.scene.ui.setMode(Mode.MESSAGE).then(() => {
|
||||||
if (!this.loaded)
|
if (!this.loaded) {
|
||||||
this.scene.gameData.saveSession(this.scene);
|
this.scene.gameData.saveSession(this.scene);
|
||||||
|
this.scene.gameData.saveSystem();
|
||||||
|
}
|
||||||
this.doEncounter();
|
this.doEncounter();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2811,6 +2816,13 @@ export class AttemptCapturePhase extends PokemonPhase {
|
||||||
if (pokemon.ivs.filter(iv => iv === 31).length === 6)
|
if (pokemon.ivs.filter(iv => iv === 31).length === 6)
|
||||||
this.scene.validateAchv(achvs.PERFECT_IVS);
|
this.scene.validateAchv(achvs.PERFECT_IVS);
|
||||||
|
|
||||||
|
const dexEntry = this.scene.gameData.dexData[pokemon.species.speciesId];
|
||||||
|
const dexIvs = dexEntry.ivs;
|
||||||
|
for (let i = 0; i < dexIvs.length; i++) {
|
||||||
|
if (dexIvs[i] < pokemon.ivs[i])
|
||||||
|
dexIvs[i] = pokemon.ivs[i];
|
||||||
|
}
|
||||||
|
|
||||||
this.scene.ui.showText(`${pokemon.name} was caught!`, null, () => {
|
this.scene.ui.showText(`${pokemon.name} was caught!`, null, () => {
|
||||||
const end = () => {
|
const end = () => {
|
||||||
this.removePb();
|
this.removePb();
|
||||||
|
|
|
@ -1426,21 +1426,14 @@ export default class BattleScene extends Phaser.Scene {
|
||||||
validateAchvs(achvType: { new(...args: any[]): Achv }, ...args: any[]): void {
|
validateAchvs(achvType: { new(...args: any[]): Achv }, ...args: any[]): void {
|
||||||
const filteredAchvs = Object.values(achvs).filter(a => a instanceof achvType);
|
const filteredAchvs = Object.values(achvs).filter(a => a instanceof achvType);
|
||||||
let newAchv = false;
|
let newAchv = false;
|
||||||
for (let achv of filteredAchvs) {
|
for (let achv of filteredAchvs)
|
||||||
if (this.validateAchv(achv, args, false))
|
this.validateAchv(achv, args);
|
||||||
newAchv = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newAchv)
|
validateAchv(achv: Achv, args?: any[]): boolean {
|
||||||
this.gameData.saveSystem();
|
|
||||||
}
|
|
||||||
|
|
||||||
validateAchv(achv: Achv, args?: any[], save: boolean = true): boolean {
|
|
||||||
if (!this.gameData.achvUnlocks.hasOwnProperty(achv.id) && achv.validate(this, args)) {
|
if (!this.gameData.achvUnlocks.hasOwnProperty(achv.id) && achv.validate(this, args)) {
|
||||||
this.gameData.achvUnlocks[achv.id] = new Date().getTime();
|
this.gameData.achvUnlocks[achv.id] = new Date().getTime();
|
||||||
this.ui.achvBar.showAchv(achv);
|
this.ui.achvBar.showAchv(achv);
|
||||||
if (save)
|
|
||||||
this.gameData.saveSystem();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ function getData() {
|
||||||
const dataStr = localStorage.getItem('data');
|
const dataStr = localStorage.getItem('data');
|
||||||
if (!dataStr)
|
if (!dataStr)
|
||||||
return null;
|
return null;
|
||||||
return JSON.parse(atob(dataStr));
|
return JSON.parse(atob(dataStr), (k, v) => k.endsWith('Attr') ? BigInt(v) : v);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSession() {
|
function getSession() {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import SoundFade from 'phaser3-rex-plugins/plugins/soundfade';
|
||||||
import { GameMode } from './game-mode';
|
import { GameMode } from './game-mode';
|
||||||
import { LevelMoves } from './data/pokemon-level-moves';
|
import { LevelMoves } from './data/pokemon-level-moves';
|
||||||
import { DamageAchv, achvs } from './system/achv';
|
import { DamageAchv, achvs } from './system/achv';
|
||||||
|
import { DexAttr } from './system/game-data';
|
||||||
|
|
||||||
export enum FieldPosition {
|
export enum FieldPosition {
|
||||||
CENTER,
|
CENTER,
|
||||||
|
@ -82,7 +83,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
private shinySparkle: Phaser.GameObjects.Sprite;
|
private shinySparkle: Phaser.GameObjects.Sprite;
|
||||||
|
|
||||||
constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, dataSource?: Pokemon | PokemonData) {
|
constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, ivs?: integer[], dataSource?: Pokemon | PokemonData) {
|
||||||
super(scene, x, y);
|
super(scene, x, y);
|
||||||
|
|
||||||
if (!species.isObtainable() && this.isPlayer())
|
if (!species.isObtainable() && this.isPlayer())
|
||||||
|
@ -127,8 +128,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
} else {
|
} else {
|
||||||
this.generateAndPopulateMoveset();
|
this.generateAndPopulateMoveset();
|
||||||
|
|
||||||
this.id = Utils.randInt(4294967295);
|
this.id = Utils.randSeedInt(4294967295);
|
||||||
this.ivs = [
|
this.ivs = ivs || [
|
||||||
Utils.binToDec(Utils.decToBin(this.id).substring(0, 5)),
|
Utils.binToDec(Utils.decToBin(this.id).substring(0, 5)),
|
||||||
Utils.binToDec(Utils.decToBin(this.id).substring(5, 10)),
|
Utils.binToDec(Utils.decToBin(this.id).substring(5, 10)),
|
||||||
Utils.binToDec(Utils.decToBin(this.id).substring(10, 15)),
|
Utils.binToDec(Utils.decToBin(this.id).substring(10, 15)),
|
||||||
|
@ -221,6 +222,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
return !this.isFainted() && !!this.scene && (!onField || this.isOnField());
|
return !this.isFainted() && !!this.scene && (!onField || this.isOnField());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDexAttrs(): bigint {
|
||||||
|
let ret = 0n;
|
||||||
|
ret |= this.gender !== Gender.FEMALE ? DexAttr.MALE : DexAttr.FEMALE;
|
||||||
|
ret |= !this.shiny ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
ret |= !this.abilityIndex ? DexAttr.ABILITY_1 : this.species.ability2 && this.abilityIndex === 1 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
ret |= this.scene.gameData.getFormAttr(this.formIndex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
abstract isPlayer(): boolean;
|
abstract isPlayer(): boolean;
|
||||||
|
|
||||||
abstract hasTrainer(): boolean;
|
abstract hasTrainer(): boolean;
|
||||||
|
@ -413,7 +423,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
for (let s of stats) {
|
for (let s of stats) {
|
||||||
const isHp = s === Stat.HP;
|
const isHp = s === Stat.HP;
|
||||||
let baseStat = baseStats[s];
|
let baseStat = baseStats[s];
|
||||||
let value = Math.floor(((2 * baseStat + this.ivs[s] + (0 / 4)) * this.level) * 0.01);
|
let value = Math.floor(((2 * baseStat + this.ivs[s]) * this.level) * 0.01);
|
||||||
if (isHp) {
|
if (isHp) {
|
||||||
value = Math.min(value + this.level + 10, 99999);
|
value = Math.min(value + this.level + 10, 99999);
|
||||||
if (this.getAbility().hasAttr(NonSuperEffectiveImmunityAbAttr))
|
if (this.getAbility().hasAttr(NonSuperEffectiveImmunityAbAttr))
|
||||||
|
@ -1352,8 +1362,8 @@ export class PlayerPokemon extends Pokemon {
|
||||||
public metLevel: integer;
|
public metLevel: integer;
|
||||||
public compatibleTms: Moves[];
|
public compatibleTms: Moves[];
|
||||||
|
|
||||||
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender?: Gender, shiny?: boolean, dataSource?: Pokemon | PokemonData) {
|
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender?: Gender, shiny?: boolean, ivs?: integer[], dataSource?: Pokemon | PokemonData) {
|
||||||
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, dataSource);
|
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, ivs, dataSource);
|
||||||
|
|
||||||
this.metBiome = scene.arena?.biomeType || Biome.TOWN;
|
this.metBiome = scene.arena?.biomeType || Biome.TOWN;
|
||||||
this.metLevel = level;
|
this.metLevel = level;
|
||||||
|
@ -1422,8 +1432,8 @@ export class PlayerPokemon extends Pokemon {
|
||||||
this.getSpeciesForm().generateIconAnim(this.scene, this.gender === Gender.FEMALE, this.formIndex);
|
this.getSpeciesForm().generateIconAnim(this.scene, this.gender === Gender.FEMALE, this.formIndex);
|
||||||
this.compatibleTms.splice(0, this.compatibleTms.length);
|
this.compatibleTms.splice(0, this.compatibleTms.length);
|
||||||
this.generateCompatibleTms();
|
this.generateCompatibleTms();
|
||||||
this.scene.gameData.setPokemonSeen(this);
|
this.scene.gameData.setPokemonSeen(this, false);
|
||||||
this.scene.gameData.setPokemonCaught(this);
|
this.scene.gameData.setPokemonCaught(this, false);
|
||||||
this.loadAssets().then(() => {
|
this.loadAssets().then(() => {
|
||||||
this.calculateStats();
|
this.calculateStats();
|
||||||
this.updateInfo().then(() => resolve());
|
this.updateInfo().then(() => resolve());
|
||||||
|
@ -1508,7 +1518,7 @@ export class EnemyPokemon extends Pokemon {
|
||||||
|
|
||||||
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, trainer: boolean, dataSource?: PokemonData) {
|
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, trainer: boolean, dataSource?: PokemonData) {
|
||||||
super(scene, 236, 84, species, level, dataSource?.abilityIndex, dataSource ? dataSource.formIndex : scene.getSpeciesFormIndex(species),
|
super(scene, 236, 84, species, level, dataSource?.abilityIndex, dataSource ? dataSource.formIndex : scene.getSpeciesFormIndex(species),
|
||||||
dataSource?.gender, dataSource?.shiny, dataSource);
|
dataSource?.gender, dataSource?.shiny, null, dataSource);
|
||||||
|
|
||||||
this.trainer = trainer;
|
this.trainer = trainer;
|
||||||
|
|
||||||
|
@ -1681,7 +1691,7 @@ export class EnemyPokemon extends Pokemon {
|
||||||
let ret: PlayerPokemon = null;
|
let ret: PlayerPokemon = null;
|
||||||
|
|
||||||
if (party.length < 6) {
|
if (party.length < 6) {
|
||||||
const newPokemon = new PlayerPokemon(this.scene, this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this);
|
const newPokemon = new PlayerPokemon(this.scene, this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, null, this);
|
||||||
party.push(newPokemon);
|
party.push(newPokemon);
|
||||||
ret = newPokemon;
|
ret = newPokemon;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import BattleScene, { Button } from "../battle-scene";
|
||||||
import { ModifierTier, ModifierType, ModifierTypeOption, PokemonBaseStatBoosterModifierType, PokemonHpRestoreModifierType, PokemonReviveModifierType } from "../modifier/modifier-type";
|
import { ModifierTier, ModifierType, ModifierTypeOption, PokemonBaseStatBoosterModifierType, PokemonHpRestoreModifierType, PokemonReviveModifierType } from "../modifier/modifier-type";
|
||||||
import Pokemon, { AiType, EnemyPokemon, PlayerPokemon, PokemonMove } from "../pokemon";
|
import Pokemon, { AiType, EnemyPokemon, PlayerPokemon, PokemonMove } from "../pokemon";
|
||||||
import { Species } from "../data/species";
|
import { Species } from "../data/species";
|
||||||
import { getTypeDamageMultiplier } from "../data/type";
|
|
||||||
import BattleMessageUiHandler from "../ui/battle-message-ui-handler";
|
import BattleMessageUiHandler from "../ui/battle-message-ui-handler";
|
||||||
import CommandUiHandler from "../ui/command-ui-handler";
|
import CommandUiHandler from "../ui/command-ui-handler";
|
||||||
import FightUiHandler from "../ui/fight-ui-handler";
|
import FightUiHandler from "../ui/fight-ui-handler";
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import BattleScene, { PokeballCounts } from "../battle-scene";
|
import BattleScene, { PokeballCounts } from "../battle-scene";
|
||||||
import { Gender } from "../data/gender";
|
|
||||||
import Pokemon, { EnemyPokemon, PlayerPokemon } from "../pokemon";
|
import Pokemon, { EnemyPokemon, PlayerPokemon } from "../pokemon";
|
||||||
import { pokemonPrevolutions } from "../data/pokemon-evolutions";
|
import { pokemonPrevolutions } from "../data/pokemon-evolutions";
|
||||||
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "../data/pokemon-species";
|
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "../data/pokemon-species";
|
||||||
|
@ -51,29 +50,33 @@ interface AchvUnlocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DexData {
|
export interface DexData {
|
||||||
[key: integer]: DexData | DexEntry
|
[key: integer]: DexEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DexEntry {
|
export interface DexEntry {
|
||||||
seen: boolean;
|
seenAttr: bigint;
|
||||||
caught: boolean;
|
caughtAttr: bigint;
|
||||||
|
seenCount: integer;
|
||||||
|
caughtCount: integer;
|
||||||
|
ivs: integer[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DexEntryDetails {
|
export const DexAttr = {
|
||||||
|
NON_SHINY: 1n,
|
||||||
|
SHINY: 2n,
|
||||||
|
MALE: 4n,
|
||||||
|
FEMALE: 8n,
|
||||||
|
ABILITY_1: 16n,
|
||||||
|
ABILITY_2: 32n,
|
||||||
|
ABILITY_HIDDEN: 64n,
|
||||||
|
DEFAULT_FORM: 128n
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DexAttrProps {
|
||||||
shiny: boolean;
|
shiny: boolean;
|
||||||
formIndex: integer;
|
|
||||||
female: boolean;
|
female: boolean;
|
||||||
abilityIndex: integer;
|
abilityIndex: integer;
|
||||||
entry: DexEntry;
|
formIndex: integer;
|
||||||
}
|
|
||||||
|
|
||||||
export interface StarterDexUnlockTree {
|
|
||||||
shiny: boolean | Map<boolean, StarterDexUnlockTree>
|
|
||||||
formIndex: integer | Map<integer, StarterDexUnlockTree>
|
|
||||||
female: boolean | Map<boolean, StarterDexUnlockTree>
|
|
||||||
abilityIndex: integer | Map<integer, StarterDexUnlockTree>
|
|
||||||
key: string,
|
|
||||||
entry: DexEntry
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GameData {
|
export class GameData {
|
||||||
|
@ -107,8 +110,6 @@ export class GameData {
|
||||||
if (this.scene.quickStart)
|
if (this.scene.quickStart)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
console.log(this.achvUnlocks, "wah")
|
|
||||||
|
|
||||||
const data: SystemSaveData = {
|
const data: SystemSaveData = {
|
||||||
trainerId: this.trainerId,
|
trainerId: this.trainerId,
|
||||||
secretId: this.secretId,
|
secretId: this.secretId,
|
||||||
|
@ -118,7 +119,10 @@ export class GameData {
|
||||||
timestamp: new Date().getTime()
|
timestamp: new Date().getTime()
|
||||||
};
|
};
|
||||||
|
|
||||||
localStorage.setItem('data', btoa(JSON.stringify(data)));
|
localStorage.setItem('data_bak', localStorage.getItem('data'));
|
||||||
|
|
||||||
|
const maxIntAttrValue = Math.pow(2, 31);
|
||||||
|
localStorage.setItem('data', btoa(JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v)));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +131,8 @@ export class GameData {
|
||||||
if (!localStorage.hasOwnProperty('data'))
|
if (!localStorage.hasOwnProperty('data'))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const data = JSON.parse(atob(localStorage.getItem('data'))) as SystemSaveData;
|
const data = JSON.parse(atob(localStorage.getItem('data')), (k: string, v: any) => k.endsWith('Attr') ? BigInt(v) : v) as SystemSaveData;
|
||||||
|
|
||||||
console.debug(data);
|
console.debug(data);
|
||||||
|
|
||||||
this.trainerId = data.trainerId;
|
this.trainerId = data.trainerId;
|
||||||
|
@ -147,9 +152,9 @@ export class GameData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.timestamp === undefined)
|
if (data.dexData[1].hasOwnProperty(0))
|
||||||
this.convertDexData(data.dexData);
|
this.migrateLegacyDexData(this.dexData, data.dexData);
|
||||||
|
else
|
||||||
this.dexData = Object.assign(this.dexData, data.dexData);
|
this.dexData = Object.assign(this.dexData, data.dexData);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -322,39 +327,10 @@ export class GameData {
|
||||||
private initDexData(): void {
|
private initDexData(): void {
|
||||||
const data: DexData = {};
|
const data: DexData = {};
|
||||||
|
|
||||||
const initDexSubData = (dexData: DexData, count: integer): DexData[] => {
|
|
||||||
const ret: DexData[] = [];
|
|
||||||
for (let i = 0; i < count; i++) {
|
|
||||||
const newData: DexData = {};
|
|
||||||
dexData[i] = newData;
|
|
||||||
ret.push(newData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
const initDexEntries = (dexData: DexData, count: integer): DexEntry[] => {
|
|
||||||
const ret: DexEntry[] = [];
|
|
||||||
for (let i = 0; i < count; i++) {
|
|
||||||
const entry: DexEntry = { seen: false, caught: false };
|
|
||||||
dexData[i] = entry;
|
|
||||||
ret.push(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (let species of allSpecies) {
|
for (let species of allSpecies) {
|
||||||
data[species.speciesId] = {};
|
data[species.speciesId] = {
|
||||||
const abilityCount = species.getAbilityCount();
|
seenAttr: 0n, caughtAttr: 0n, seenCount: 0, caughtCount: 0, ivs: [ 0, 0, 0, 0, 0, 0 ]
|
||||||
if (species.forms?.length)
|
};
|
||||||
initDexSubData(data[species.speciesId] as DexData, 2).map(sd => species.malePercent !== null
|
|
||||||
? initDexSubData(sd, species.forms.length).map(fd => initDexSubData(fd, 2).map(gd => initDexEntries(gd, abilityCount)))
|
|
||||||
: initDexSubData(sd, species.forms.length).map(fd => initDexEntries(fd, abilityCount)));
|
|
||||||
else if (species.malePercent !== null)
|
|
||||||
initDexSubData(data[species.speciesId] as DexData, 2).map(sd => initDexSubData(sd, 2).map(gd => initDexEntries(gd, abilityCount)));
|
|
||||||
else
|
|
||||||
initDexSubData(data[species.speciesId] as DexData, 2).map(sd => initDexEntries(sd, abilityCount))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultStarters: Species[] = [
|
const defaultStarters: Species[] = [
|
||||||
|
@ -365,255 +341,196 @@ export class GameData {
|
||||||
Species.SNIVY, Species.TEPIG, Species.OSHAWOTT
|
Species.SNIVY, Species.TEPIG, Species.OSHAWOTT
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const defaultStarterAttr = DexAttr.NON_SHINY | DexAttr.MALE | DexAttr.ABILITY_1 | DexAttr.DEFAULT_FORM;
|
||||||
|
|
||||||
for (let ds of defaultStarters) {
|
for (let ds of defaultStarters) {
|
||||||
let entry = data[ds][0][Gender.MALE][0] as DexEntry;
|
let entry = data[ds] as DexEntry;
|
||||||
entry.seen = true;
|
entry.seenAttr = defaultStarterAttr;
|
||||||
entry.caught = true;
|
entry.caughtAttr = defaultStarterAttr;
|
||||||
|
for (let i in entry.ivs)
|
||||||
|
entry.ivs[i] = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dexData = data;
|
this.dexData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPokemonSeen(pokemon: Pokemon): void {
|
setPokemonSeen(pokemon: Pokemon, incrementCount: boolean = true): void {
|
||||||
const dexEntry = this.getPokemonDexEntry(pokemon);
|
const dexEntry = this.dexData[pokemon.species.speciesId];
|
||||||
if (!dexEntry.seen) {
|
dexEntry.seenAttr |= pokemon.getDexAttrs();
|
||||||
dexEntry.seen = true;
|
if (incrementCount)
|
||||||
this.saveSystem();
|
dexEntry.seenCount++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setPokemonCaught(pokemon: Pokemon): Promise<void> {
|
setPokemonCaught(pokemon: Pokemon, incrementCount: boolean = true): Promise<void> {
|
||||||
return this.setPokemonSpeciesCaught(pokemon, pokemon.species);
|
return this.setPokemonSpeciesCaught(pokemon, pokemon.species, incrementCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
setPokemonSpeciesCaught(pokemon: Pokemon, species: PokemonSpecies): Promise<void> {
|
setPokemonSpeciesCaught(pokemon: Pokemon, species: PokemonSpecies, incrementCount?: boolean): Promise<void> {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
const dexEntry = this.getDexEntry(species, pokemon.isShiny(), pokemon.formIndex, pokemon.gender === Gender.FEMALE, pokemon.abilityIndex);
|
const dexEntry = this.dexData[species.speciesId];
|
||||||
const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId);
|
const caughtAttr = dexEntry.caughtAttr;
|
||||||
if (!dexEntry.caught) {
|
dexEntry.caughtAttr |= pokemon.getDexAttrs();
|
||||||
const newCatch = !this.getDefaultDexEntry(species);
|
if (incrementCount)
|
||||||
|
dexEntry.seenCount++;
|
||||||
|
|
||||||
dexEntry.caught = true;
|
const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId);
|
||||||
this.saveSystem();
|
const newCatch = !caughtAttr;
|
||||||
|
|
||||||
if (newCatch && !hasPrevolution) {
|
if (newCatch && !hasPrevolution) {
|
||||||
this.scene.playSoundWithoutBgm('level_up_fanfare', 1500);
|
this.scene.playSoundWithoutBgm('level_up_fanfare', 1500);
|
||||||
this.scene.ui.showText(`${species.name} has been\nadded as a starter!`, null, () => resolve(), null, true);
|
this.scene.ui.showText(`${species.name} has been\nadded as a starter!`, null, () => resolve(), null, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (hasPrevolution) {
|
if (hasPrevolution) {
|
||||||
const prevolutionSpecies = pokemonPrevolutions[species.speciesId];
|
const prevolutionSpecies = pokemonPrevolutions[species.speciesId];
|
||||||
this.setPokemonSpeciesCaught(pokemon, getPokemonSpecies(prevolutionSpecies)).then(() => resolve());
|
return this.setPokemonSpeciesCaught(pokemon, getPokemonSpecies(prevolutionSpecies)).then(() => resolve());
|
||||||
} else
|
} else
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getPokemonDexEntry(pokemon: Pokemon) {
|
getSpeciesDefaultDexAttr(species: PokemonSpecies): bigint {
|
||||||
return this.getDexEntry(pokemon.species, pokemon.isShiny(), pokemon.formIndex, pokemon.gender === Gender.FEMALE, pokemon.abilityIndex);
|
let ret = 0n;
|
||||||
|
const dexEntry = this.dexData[species.speciesId];
|
||||||
|
const attr = dexEntry.caughtAttr;
|
||||||
|
ret |= attr & DexAttr.NON_SHINY || !(attr & DexAttr.SHINY) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
ret |= attr & DexAttr.MALE || !(attr & DexAttr.FEMALE) ? DexAttr.MALE : DexAttr.FEMALE;
|
||||||
|
ret |= attr & DexAttr.ABILITY_1 || (!(attr & DexAttr.ABILITY_2) && !(attr & DexAttr.ABILITY_HIDDEN)) ? DexAttr.ABILITY_1 : attr & DexAttr.ABILITY_2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
ret |= this.getFormAttr(this.getFormIndex(attr));
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDexEntry(species: PokemonSpecies, shiny: boolean, formIndex: integer, female: boolean, abilityIndex: integer): DexEntry {
|
getSpeciesDexAttrProps(species: PokemonSpecies, dexAttr: bigint): DexAttrProps {
|
||||||
const shinyIndex = !shiny ? 0 : 1;
|
const shiny = !(dexAttr & DexAttr.NON_SHINY);
|
||||||
const genderIndex = !female ? 0 : 1;
|
const female = !(dexAttr & DexAttr.MALE);
|
||||||
const data = this.dexData[species.speciesId];
|
const abilityIndex = dexAttr & DexAttr.ABILITY_1 ? 0 : !species.ability2 || dexAttr & DexAttr.ABILITY_2 ? 1 : 2;
|
||||||
if (species.forms?.length) {
|
const formIndex = this.getFormIndex(dexAttr);
|
||||||
const getEntry = () => {
|
|
||||||
if (species.malePercent !== null)
|
|
||||||
return data[shinyIndex][formIndex][genderIndex][abilityIndex];
|
|
||||||
return data[shinyIndex][formIndex][abilityIndex];
|
|
||||||
};
|
|
||||||
let entry: DexEntry;
|
|
||||||
try {
|
|
||||||
entry = getEntry();
|
|
||||||
} catch (err) { }
|
|
||||||
if (entry)
|
|
||||||
return entry;
|
|
||||||
else {
|
|
||||||
console.warn(`Form data not found for dex entry for ${species.name}: Restructuring dex entry`);
|
|
||||||
for (let s = 0; s < 2; s++) {
|
|
||||||
const oldData = Object.assign({}, data[s]);
|
|
||||||
data[s] = {};
|
|
||||||
for (let f = 0; f < species.forms.length; f++)
|
|
||||||
data[s][f] = oldData;
|
|
||||||
}
|
|
||||||
this.saveSystem();
|
|
||||||
}
|
|
||||||
return getEntry();
|
|
||||||
} else if (species.malePercent !== null)
|
|
||||||
return data[shinyIndex][genderIndex][abilityIndex];
|
|
||||||
return data[shinyIndex][abilityIndex] as DexEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultDexEntry(species: PokemonSpecies, forceShiny?: boolean, forceFormIndex?: integer, forceFemale?: boolean, forceAbilityIndex?: integer): DexEntryDetails {
|
|
||||||
const hasForms = !!species.forms?.length;
|
|
||||||
const hasGender = species.malePercent !== null;
|
|
||||||
let shiny = false;
|
|
||||||
let formIndex = 0;
|
|
||||||
let female = false;
|
|
||||||
let abilityIndex = 0;
|
|
||||||
let entry = null;
|
|
||||||
|
|
||||||
const traverseData = (data: DexData, level: integer) => {
|
|
||||||
const keys = Object.keys(data);
|
|
||||||
if ((!hasForms && level === 1) || (!hasGender && level === 2)) {
|
|
||||||
traverseData(data, level + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
keys.forEach((key: string, k: integer) => {
|
|
||||||
if (entry)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (level) {
|
|
||||||
case 0:
|
|
||||||
shiny = !!k;
|
|
||||||
if (forceShiny !== undefined && shiny !== forceShiny)
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
formIndex = k;
|
|
||||||
if (forceFormIndex !== undefined && formIndex !== forceFormIndex)
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
female = !!k;
|
|
||||||
if (forceFemale !== undefined && female !== forceFemale)
|
|
||||||
return
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
abilityIndex = k;
|
|
||||||
if (forceAbilityIndex !== undefined && abilityIndex !== forceAbilityIndex)
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('caught' in data[key]) {
|
|
||||||
if (data[key].caught)
|
|
||||||
entry = data[key] as DexEntry;
|
|
||||||
} else
|
|
||||||
traverseData(data[key] as DexData, level + 1);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
traverseData(this.dexData[species.speciesId] as DexData, 0);
|
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
return {
|
return {
|
||||||
shiny: shiny,
|
shiny,
|
||||||
formIndex: formIndex,
|
female,
|
||||||
female: female,
|
abilityIndex,
|
||||||
abilityIndex: abilityIndex,
|
formIndex
|
||||||
entry: entry
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
getFormIndex(attr: bigint): integer {
|
||||||
|
if (!attr || attr < DexAttr.DEFAULT_FORM)
|
||||||
|
return 0;
|
||||||
|
let f = 0;
|
||||||
|
while (!(attr & this.getFormAttr(f)))
|
||||||
|
f++;
|
||||||
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
getStarterDexUnlockTree(species: PokemonSpecies): StarterDexUnlockTree {
|
getFormAttr(formIndex: integer): bigint {
|
||||||
const hasForms = !!species.forms?.length;
|
return BigInt(Math.pow(2, 7 + formIndex));
|
||||||
const hasGender = species.malePercent !== null;
|
}
|
||||||
|
|
||||||
const getTreeOrValueMap = (key: string, parent?: StarterDexUnlockTree): (Map<any, any>) => {
|
// TODO: Remove
|
||||||
switch (key) {
|
migrateLegacyDexData(dexData: DexData, legacyDexData: object): DexData {
|
||||||
case 'shiny':
|
const newDexData: DexData = {};
|
||||||
const shinyMap = new Map<boolean, StarterDexUnlockTree>();
|
|
||||||
for (let s = 0; s < 2; s++) {
|
for (let s of Object.keys(legacyDexData)) {
|
||||||
const props = { shiny: !!s };
|
const species = getPokemonSpecies(parseInt(s));
|
||||||
shinyMap.set(!!s, {
|
const newEntry = dexData[parseInt(s)];
|
||||||
shiny: !!s,
|
let seenAttr = 0n;
|
||||||
formIndex: hasForms ? getTreeOrValueMap('formIndex', props as StarterDexUnlockTree) : null,
|
let caughtAttr = 0n;
|
||||||
female: !hasForms && hasGender ? getTreeOrValueMap('female', props as StarterDexUnlockTree) : null,
|
Object.keys(legacyDexData[s]).forEach(shinyIndex => {
|
||||||
abilityIndex: !hasForms && !hasGender ? getTreeOrValueMap('abilityIndex', props as StarterDexUnlockTree) : null,
|
const shinyData = legacyDexData[s][shinyIndex];
|
||||||
key: hasForms ? 'formIndex' : hasGender ? 'female' : 'abilityIndex',
|
if (species.forms?.length) {
|
||||||
entry: null,
|
Object.keys(shinyData).forEach(formIndex => {
|
||||||
|
const formData = shinyData[formIndex];
|
||||||
|
if (species.malePercent !== null) {
|
||||||
|
Object.keys(formData).forEach(genderIndex => {
|
||||||
|
const genderData = formData[genderIndex];
|
||||||
|
Object.keys(genderData).forEach(abilityIndex => {
|
||||||
|
const entry = genderData[abilityIndex];
|
||||||
|
if (entry.seen) {
|
||||||
|
seenAttr |= !parseInt(shinyIndex) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
seenAttr |= !parseInt(genderIndex) ? DexAttr.MALE : DexAttr.FEMALE;
|
||||||
|
seenAttr |= parseInt(abilityIndex) === 0 ? DexAttr.ABILITY_1 : parseInt(abilityIndex) === 1 && species.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
seenAttr |= this.getFormAttr(parseInt(formIndex));
|
||||||
|
}
|
||||||
|
if (entry.caught) {
|
||||||
|
if (!caughtAttr)
|
||||||
|
newEntry.ivs = [ 10, 10, 10, 10, 10, 10 ];
|
||||||
|
caughtAttr |= !parseInt(shinyIndex) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
caughtAttr |= !parseInt(genderIndex) ? DexAttr.MALE : DexAttr.FEMALE;
|
||||||
|
caughtAttr |= parseInt(abilityIndex) === 0 ? DexAttr.ABILITY_1 : parseInt(abilityIndex) === 1 && species.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
caughtAttr |= this.getFormAttr(parseInt(formIndex));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Object.keys(formData).forEach(abilityIndex => {
|
||||||
|
const entry = formData[abilityIndex];
|
||||||
|
if (entry.seen) {
|
||||||
|
seenAttr |= !parseInt(shinyIndex) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
seenAttr |= DexAttr.MALE;
|
||||||
|
seenAttr |= parseInt(abilityIndex) === 0 ? DexAttr.ABILITY_1 : parseInt(abilityIndex) === 1 && species.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
seenAttr |= this.getFormAttr(parseInt(formIndex));
|
||||||
|
}
|
||||||
|
if (entry.caught) {
|
||||||
|
if (!caughtAttr)
|
||||||
|
newEntry.ivs = [ 10, 10, 10, 10, 10, 10 ];
|
||||||
|
caughtAttr |= !parseInt(shinyIndex) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
caughtAttr |= DexAttr.MALE;
|
||||||
|
caughtAttr |= parseInt(abilityIndex) === 0 ? DexAttr.ABILITY_1 : parseInt(abilityIndex) === 1 && species.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
caughtAttr |= this.getFormAttr(parseInt(formIndex));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return shinyMap;
|
|
||||||
case 'formIndex':
|
|
||||||
const formMap = new Map<integer, StarterDexUnlockTree>();
|
|
||||||
for (let f = 0; f < species.forms.length; f++) {
|
|
||||||
const props = { shiny: parent.shiny, formIndex: f };
|
|
||||||
formMap.set(f, {
|
|
||||||
shiny: parent.shiny,
|
|
||||||
formIndex: f,
|
|
||||||
female: hasGender ? getTreeOrValueMap('female', props as StarterDexUnlockTree) : null,
|
|
||||||
abilityIndex: !hasGender ? getTreeOrValueMap('abilityIndex', props as StarterDexUnlockTree) : null,
|
|
||||||
key: hasGender ? 'female' : 'abilityIndex',
|
|
||||||
entry: null
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (species.malePercent !== null) {
|
||||||
|
Object.keys(shinyData).forEach(genderIndex => {
|
||||||
|
const genderData = shinyData[genderIndex];
|
||||||
|
Object.keys(genderData).forEach(abilityIndex => {
|
||||||
|
const entry = genderData[abilityIndex];
|
||||||
|
if (entry.seen) {
|
||||||
|
seenAttr |= !parseInt(shinyIndex) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
seenAttr |= !parseInt(genderIndex) ? DexAttr.MALE : DexAttr.FEMALE;
|
||||||
|
seenAttr |= parseInt(abilityIndex) === 0 ? DexAttr.ABILITY_1 : parseInt(abilityIndex) === 1 && species.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
seenAttr |= DexAttr.DEFAULT_FORM;
|
||||||
|
}
|
||||||
|
if (entry.caught) {
|
||||||
|
if (!caughtAttr)
|
||||||
|
newEntry.ivs = [ 10, 10, 10, 10, 10, 10 ];
|
||||||
|
caughtAttr |= !parseInt(shinyIndex) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
caughtAttr |= !parseInt(genderIndex) ? DexAttr.MALE : DexAttr.FEMALE;
|
||||||
|
caughtAttr |= parseInt(abilityIndex) === 0 ? DexAttr.ABILITY_1 : parseInt(abilityIndex) === 1 && species.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
caughtAttr |= DexAttr.DEFAULT_FORM;
|
||||||
}
|
}
|
||||||
return formMap;
|
|
||||||
case 'female':
|
|
||||||
const genderMap = new Map<boolean, StarterDexUnlockTree>();
|
|
||||||
for (let g = 0; g < 2; g++) {
|
|
||||||
const props = { shiny: parent.shiny, formIndex: parent.formIndex, female: !!g };
|
|
||||||
genderMap.set(!!g, {
|
|
||||||
shiny: parent.shiny,
|
|
||||||
formIndex: parent.formIndex,
|
|
||||||
female: !!g,
|
|
||||||
abilityIndex: getTreeOrValueMap('abilityIndex', props as StarterDexUnlockTree),
|
|
||||||
key: 'abilityIndex',
|
|
||||||
entry: null
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
return genderMap;
|
|
||||||
case 'abilityIndex':
|
|
||||||
const abilityMap = new Map<integer, StarterDexUnlockTree>();
|
|
||||||
const abilityCount = species.getAbilityCount();
|
|
||||||
for (let a = 0; a < abilityCount; a++) {
|
|
||||||
abilityMap.set(a, {
|
|
||||||
shiny: parent.shiny,
|
|
||||||
formIndex: parent.formIndex,
|
|
||||||
female: parent.female,
|
|
||||||
abilityIndex: a,
|
|
||||||
key: 'entry',
|
|
||||||
entry: hasForms
|
|
||||||
? hasGender
|
|
||||||
? this.dexData[species.speciesId][!parent.shiny ? 0 : 1][parent.formIndex as integer][!parent.female ? 0 : 1][a]
|
|
||||||
: this.dexData[species.speciesId][!parent.shiny ? 0 : 1][parent.formIndex as integer][a]
|
|
||||||
: hasGender
|
|
||||||
? this.dexData[species.speciesId][!parent.shiny ? 0 : 1][!parent.female ? 0 : 1][a]
|
|
||||||
: this.dexData[species.speciesId][!parent.shiny ? 0 : 1][a]
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
Object.keys(shinyData).forEach(abilityIndex => {
|
||||||
|
const entry = shinyData[abilityIndex];
|
||||||
|
if (entry.seen) {
|
||||||
|
seenAttr |= !parseInt(shinyIndex) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
seenAttr |= DexAttr.MALE;
|
||||||
|
seenAttr |= parseInt(abilityIndex) === 0 ? DexAttr.ABILITY_1 : parseInt(abilityIndex) === 1 && species.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
seenAttr |= DexAttr.DEFAULT_FORM;
|
||||||
}
|
}
|
||||||
return abilityMap;
|
if (entry.caught) {
|
||||||
|
if (!caughtAttr)
|
||||||
|
newEntry.ivs = [ 10, 10, 10, 10, 10, 10 ];
|
||||||
|
caughtAttr |= !parseInt(shinyIndex) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
|
caughtAttr |= DexAttr.MALE;
|
||||||
|
caughtAttr |= parseInt(abilityIndex) === 0 ? DexAttr.ABILITY_1 : parseInt(abilityIndex) === 1 && species.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
|
caughtAttr |= DexAttr.DEFAULT_FORM;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const root = {
|
|
||||||
shiny: getTreeOrValueMap('shiny'),
|
|
||||||
formIndex: null,
|
|
||||||
female: null,
|
|
||||||
abilityIndex: null,
|
|
||||||
key: 'shiny',
|
|
||||||
entry: null
|
|
||||||
};
|
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
convertDexData(dexData: DexData): void {
|
|
||||||
const traverseData = (speciesId: Species, data: DexData) => {
|
|
||||||
const keys = Object.keys(data);
|
|
||||||
keys.forEach((key: string, k: integer) => {
|
|
||||||
if ('caught' in data[key]) {
|
|
||||||
const abilityCount = getPokemonSpecies(speciesId).getAbilityCount();
|
|
||||||
data[key] = {
|
|
||||||
0: data[key]
|
|
||||||
};
|
|
||||||
for (let a = 1; a < abilityCount; a++)
|
|
||||||
data[key][a] = { seen: false, caught: false };
|
|
||||||
} else
|
|
||||||
traverseData(speciesId, data[key]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(dexData).forEach((species: string, s: integer) => {
|
|
||||||
const speciesId = parseInt(species);
|
|
||||||
traverseData(speciesId, dexData[species]);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
newEntry.seenAttr = seenAttr;
|
||||||
|
newEntry.caughtAttr = caughtAttr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newDexData;
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,7 +85,7 @@ export default class PokemonData {
|
||||||
toPokemon(scene: BattleScene, battleType?: BattleType): Pokemon {
|
toPokemon(scene: BattleScene, battleType?: BattleType): Pokemon {
|
||||||
const species = getPokemonSpecies(this.species);
|
const species = getPokemonSpecies(this.species);
|
||||||
if (this.player)
|
if (this.player)
|
||||||
return new PlayerPokemon(scene, species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this);
|
return new PlayerPokemon(scene, species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, null, this);
|
||||||
return new EnemyPokemon(scene, species, this.level, battleType === BattleType.TRAINER, this);
|
return new EnemyPokemon(scene, species, this.level, battleType === BattleType.TRAINER, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -129,9 +129,9 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.player) {
|
if (!this.player) {
|
||||||
const speciesOwned = !!pokemon.scene.gameData.getDefaultDexEntry(pokemon.species)?.entry?.caught;
|
const dexEntry = pokemon.scene.gameData.dexData[pokemon.species.speciesId];
|
||||||
this.ownedIcon.setVisible(speciesOwned);
|
this.ownedIcon.setVisible(!!dexEntry.caughtAttr);
|
||||||
if (!pokemon.scene.gameData.getPokemonDexEntry(pokemon)?.caught)
|
if (!(dexEntry.caughtAttr & pokemon.getDexAttrs()))
|
||||||
this.ownedIcon.setTint(0x808080);
|
this.ownedIcon.setTint(0x808080);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
||||||
|
|
||||||
getIvDescriptor(value: integer): string {
|
getIvDescriptor(value: integer): string {
|
||||||
if (value > 30)
|
if (value > 30)
|
||||||
return 'Perfect';
|
return 'Best';
|
||||||
if (value === 30)
|
if (value === 30)
|
||||||
return 'Fantastic';
|
return 'Fantastic';
|
||||||
if (value > 20)
|
if (value > 20)
|
||||||
|
|
|
@ -5,22 +5,19 @@ import { TextStyle, addTextObject, getTextColor } from "./text";
|
||||||
import { Mode } from "./ui";
|
import { Mode } from "./ui";
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import MessageUiHandler from "./message-ui-handler";
|
import MessageUiHandler from "./message-ui-handler";
|
||||||
import { DexEntryDetails, StarterDexUnlockTree } from "../system/game-data";
|
|
||||||
import { Gender, getGenderColor, getGenderSymbol } from "../data/gender";
|
import { Gender, getGenderColor, getGenderSymbol } from "../data/gender";
|
||||||
import { pokemonPrevolutions } from "../data/pokemon-evolutions";
|
import { pokemonPrevolutions } from "../data/pokemon-evolutions";
|
||||||
import { abilities } from "../data/ability";
|
import { abilities } from "../data/ability";
|
||||||
import { GameMode } from "../game-mode";
|
import { GameMode } from "../game-mode";
|
||||||
import { Unlockables } from "../system/unlockables";
|
import { Unlockables } from "../system/unlockables";
|
||||||
import { GrowthRate, getGrowthRateColor } from "../data/exp";
|
import { GrowthRate, getGrowthRateColor } from "../data/exp";
|
||||||
|
import { DexAttr, DexEntry } from "../system/game-data";
|
||||||
|
|
||||||
export type StarterSelectCallback = (starters: Starter[]) => void;
|
export type StarterSelectCallback = (starters: Starter[]) => void;
|
||||||
|
|
||||||
export interface Starter {
|
export interface Starter {
|
||||||
species: PokemonSpecies;
|
species: PokemonSpecies;
|
||||||
shiny: boolean;
|
dexAttr: bigint;
|
||||||
formIndex: integer;
|
|
||||||
female: boolean;
|
|
||||||
abilityIndex: integer;
|
|
||||||
pokerus: boolean;
|
pokerus: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,10 +36,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
private starterSelectMessageBoxContainer: Phaser.GameObjects.Container;
|
private starterSelectMessageBoxContainer: Phaser.GameObjects.Container;
|
||||||
|
|
||||||
private genMode: boolean;
|
private genMode: boolean;
|
||||||
private shinyCursor: integer = 0;
|
private dexAttrCursor: bigint = 0n;
|
||||||
private formCursor: integer = 0;
|
|
||||||
private genderCursor: integer = 0;
|
|
||||||
private abilityCursor: integer = 0;
|
|
||||||
private genCursor: integer = 0;
|
private genCursor: integer = 0;
|
||||||
|
|
||||||
private genSpecies: PokemonSpecies[][] = [];
|
private genSpecies: PokemonSpecies[][] = [];
|
||||||
|
@ -52,9 +46,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
private starterCursors: integer[] = [];
|
private starterCursors: integer[] = [];
|
||||||
private pokerusGens: integer[] = [];
|
private pokerusGens: integer[] = [];
|
||||||
private pokerusCursors: integer[] = [];
|
private pokerusCursors: integer[] = [];
|
||||||
private starterDetails: [boolean, integer, boolean, integer][] = [];
|
private starterAttr: bigint[] = [];
|
||||||
private speciesStarterDexEntry: DexEntryDetails;
|
private speciesStarterDexEntry: DexEntry;
|
||||||
private speciesStarterDexTree: StarterDexUnlockTree;
|
|
||||||
private canCycleShiny: boolean;
|
private canCycleShiny: boolean;
|
||||||
private canCycleForm: boolean;
|
private canCycleForm: boolean;
|
||||||
private canCycleGender: boolean;
|
private canCycleGender: boolean;
|
||||||
|
@ -175,14 +168,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
starterSpecies.push(species.speciesId);
|
starterSpecies.push(species.speciesId);
|
||||||
this.speciesLoaded.set(species.speciesId, false);
|
this.speciesLoaded.set(species.speciesId, false);
|
||||||
this.genSpecies[g].push(species);
|
this.genSpecies[g].push(species);
|
||||||
const dexEntry = this.scene.gameData.getDefaultDexEntry(species);
|
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species);
|
||||||
species.generateIconAnim(this.scene, dexEntry?.female, dexEntry?.formIndex);
|
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
|
species.generateIconAnim(this.scene, defaultProps.female, defaultProps.formIndex);
|
||||||
const x = (s % 9) * 18;
|
const x = (s % 9) * 18;
|
||||||
const y = Math.floor(s / 9) * 18;
|
const y = Math.floor(s / 9) * 18;
|
||||||
const icon = this.scene.add.sprite(x, y, species.getIconAtlasKey(dexEntry?.formIndex));
|
const icon = this.scene.add.sprite(x, y, species.getIconAtlasKey(defaultProps.formIndex));
|
||||||
icon.setScale(0.5);
|
icon.setScale(0.5);
|
||||||
icon.setOrigin(0, 0);
|
icon.setOrigin(0, 0);
|
||||||
icon.play(species.getIconKey(dexEntry?.female, dexEntry?.formIndex)).stop();
|
icon.play(species.getIconKey(defaultProps.female, defaultProps.formIndex)).stop();
|
||||||
icon.setTintFill(0);
|
icon.setTintFill(0);
|
||||||
this.starterSelectGenIconContainers[g].add(icon);
|
this.starterSelectGenIconContainers[g].add(icon);
|
||||||
s++;
|
s++;
|
||||||
|
@ -277,9 +271,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
|
|
||||||
for (let g = 0; g < this.genSpecies.length; g++) {
|
for (let g = 0; g < this.genSpecies.length; g++) {
|
||||||
this.genSpecies[g].forEach((species, s) => {
|
this.genSpecies[g].forEach((species, s) => {
|
||||||
const dexEntry = this.scene.gameData.getDefaultDexEntry(species);
|
const dexEntry = this.scene.gameData.dexData[species.speciesId];
|
||||||
const icon = this.starterSelectGenIconContainers[g].getAt(s) as Phaser.GameObjects.Sprite;
|
const icon = this.starterSelectGenIconContainers[g].getAt(s) as Phaser.GameObjects.Sprite;
|
||||||
if (dexEntry)
|
if (dexEntry.caughtAttr)
|
||||||
icon.clearTint();
|
icon.clearTint();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -323,7 +317,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (button === Button.ACTION) {
|
if (button === Button.ACTION) {
|
||||||
if (!this.speciesStarterDexEntry)
|
if (!this.speciesStarterDexEntry?.caughtAttr)
|
||||||
error = true;
|
error = true;
|
||||||
else if (this.starterCursors.length < 3) {
|
else if (this.starterCursors.length < 3) {
|
||||||
let isDupe = false;
|
let isDupe = false;
|
||||||
|
@ -338,10 +332,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
cursorObj.setVisible(true);
|
cursorObj.setVisible(true);
|
||||||
cursorObj.setPosition(this.cursorObj.x, this.cursorObj.y);
|
cursorObj.setPosition(this.cursorObj.x, this.cursorObj.y);
|
||||||
const species = this.genSpecies[this.genCursor][this.cursor];
|
const species = this.genSpecies[this.genCursor][this.cursor];
|
||||||
this.starterIcons[this.starterCursors.length].play(species.getIconKey(this.speciesStarterDexEntry?.female));
|
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species);
|
||||||
|
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
|
this.starterIcons[this.starterCursors.length].play(species.getIconKey(defaultProps.female, defaultProps.formIndex));
|
||||||
this.starterGens.push(this.genCursor);
|
this.starterGens.push(this.genCursor);
|
||||||
this.starterCursors.push(this.cursor);
|
this.starterCursors.push(this.cursor);
|
||||||
this.starterDetails.push([ !!this.shinyCursor, this.formCursor, !!this.genderCursor, this.abilityCursor ]);
|
this.starterAttr.push(this.dexAttrCursor);
|
||||||
if (this.speciesLoaded.get(species.speciesId))
|
if (this.speciesLoaded.get(species.speciesId))
|
||||||
species.cry(this.scene);
|
species.cry(this.scene);
|
||||||
if (this.starterCursors.length === 3) {
|
if (this.starterCursors.length === 3) {
|
||||||
|
@ -362,10 +358,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
const starterSpecies = thisObj.genSpecies[thisObj.starterGens[i]][thisObj.starterCursors[i]];
|
const starterSpecies = thisObj.genSpecies[thisObj.starterGens[i]][thisObj.starterCursors[i]];
|
||||||
return {
|
return {
|
||||||
species: starterSpecies,
|
species: starterSpecies,
|
||||||
shiny: thisObj.starterDetails[i][0],
|
dexAttr: thisObj.starterAttr[i],
|
||||||
formIndex: thisObj.starterDetails[i][1],
|
|
||||||
female: thisObj.starterDetails[i][2],
|
|
||||||
abilityIndex: thisObj.starterDetails[i][3],
|
|
||||||
pokerus: !![ 0, 1, 2 ].filter(n => thisObj.pokerusGens[n] === starterSpecies.generation - 1 && thisObj.pokerusCursors[n] === thisObj.genSpecies[starterSpecies.generation - 1].indexOf(starterSpecies)).length
|
pokerus: !![ 0, 1, 2 ].filter(n => thisObj.pokerusGens[n] === starterSpecies.generation - 1 && thisObj.pokerusCursors[n] === thisObj.genSpecies[starterSpecies.generation - 1].indexOf(starterSpecies)).length
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
@ -394,11 +387,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
const genStarters = this.starterSelectGenIconContainers[this.genCursor].getAll().length;
|
const genStarters = this.starterSelectGenIconContainers[this.genCursor].getAll().length;
|
||||||
const rows = Math.ceil(genStarters / 9);
|
const rows = Math.ceil(genStarters / 9);
|
||||||
const row = Math.floor(this.cursor / 9);
|
const row = Math.floor(this.cursor / 9);
|
||||||
|
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor);
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case Button.CYCLE_SHINY:
|
case Button.CYCLE_SHINY:
|
||||||
if (this.canCycleShiny) {
|
if (this.canCycleShiny) {
|
||||||
this.setSpeciesDetails(this.lastSpecies, !this.shinyCursor, undefined, undefined, undefined);
|
this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, undefined);
|
||||||
if (this.shinyCursor)
|
if (this.dexAttrCursor & DexAttr.SHINY)
|
||||||
this.scene.playSound('sparkle');
|
this.scene.playSound('sparkle');
|
||||||
else
|
else
|
||||||
success = true;
|
success = true;
|
||||||
|
@ -406,20 +400,41 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
break;
|
break;
|
||||||
case Button.CYCLE_FORM:
|
case Button.CYCLE_FORM:
|
||||||
if (this.canCycleForm) {
|
if (this.canCycleForm) {
|
||||||
this.setSpeciesDetails(this.lastSpecies, undefined, (this.formCursor + 1) % this.lastSpecies.forms.length, undefined, undefined);
|
const formCount = this.lastSpecies.forms.length;
|
||||||
|
let newFormIndex = props.formIndex;
|
||||||
|
do {
|
||||||
|
newFormIndex = (newFormIndex + 1) % formCount;
|
||||||
|
if (this.speciesStarterDexEntry.caughtAttr & this.scene.gameData.getFormAttr(newFormIndex))
|
||||||
|
break;
|
||||||
|
} while (newFormIndex !== props.formIndex);
|
||||||
|
this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Button.CYCLE_GENDER:
|
case Button.CYCLE_GENDER:
|
||||||
if (this.canCycleGender) {
|
if (this.canCycleGender) {
|
||||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !this.genderCursor, undefined);
|
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Button.CYCLE_ABILITY:
|
case Button.CYCLE_ABILITY:
|
||||||
if (this.canCycleAbility) {
|
if (this.canCycleAbility) {
|
||||||
const abilityCount = this.lastSpecies.getAbilityCount();
|
const abilityCount = this.lastSpecies.getAbilityCount();
|
||||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, (this.abilityCursor + 1) % abilityCount);
|
let newAbilityIndex = props.abilityIndex;
|
||||||
|
do {
|
||||||
|
newAbilityIndex = (newAbilityIndex + 1) % abilityCount;
|
||||||
|
if (!newAbilityIndex) {
|
||||||
|
if (this.speciesStarterDexEntry.caughtAttr & DexAttr.ABILITY_1)
|
||||||
|
break;
|
||||||
|
} else if (newAbilityIndex === 1) {
|
||||||
|
if (this.speciesStarterDexEntry.caughtAttr & (this.lastSpecies.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN))
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (this.speciesStarterDexEntry.caughtAttr & DexAttr.ABILITY_HIDDEN)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (newAbilityIndex !== props.abilityIndex);
|
||||||
|
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newAbilityIndex);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -462,7 +477,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
instructionLines.push('A/Space/Enter: Select');
|
instructionLines.push('A/Space/Enter: Select');
|
||||||
if (this.starterCursors.length)
|
if (this.starterCursors.length)
|
||||||
instructionLines.push('X/Backspace/Esc: Undo');
|
instructionLines.push('X/Backspace/Esc: Undo');
|
||||||
if (this.speciesStarterDexTree) {
|
if (this.speciesStarterDexEntry?.caughtAttr) {
|
||||||
if (this.canCycleShiny)
|
if (this.canCycleShiny)
|
||||||
cycleInstructionLines.push('R: Cycle Shiny');
|
cycleInstructionLines.push('R: Cycle Shiny');
|
||||||
if (this.canCycleForm)
|
if (this.canCycleForm)
|
||||||
|
@ -505,9 +520,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.pokerusCursorObjs[s].setVisible(this.pokerusGens[s] === cursor);
|
this.pokerusCursorObjs[s].setVisible(this.pokerusGens[s] === cursor);
|
||||||
|
|
||||||
const genLimit = this.genSpecies[this.genCursor].length;
|
const genLimit = this.genSpecies[this.genCursor].length;
|
||||||
for (let s = 0; s < 81; s++) {
|
for (let s = 0; s < 81; s++)
|
||||||
this.shinyIcons[s].setVisible(s < genLimit && !!this.scene.gameData.getDefaultDexEntry(this.genSpecies[this.genCursor][s], true));
|
this.shinyIcons[s].setVisible(s < genLimit && !!(this.scene.gameData.dexData[this.genSpecies[this.genCursor][s].speciesId].caughtAttr & DexAttr.SHINY));
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
changed = super.setCursor(cursor);
|
changed = super.setCursor(cursor);
|
||||||
|
|
||||||
|
@ -539,18 +553,19 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
setSpecies(species: PokemonSpecies) {
|
setSpecies(species: PokemonSpecies) {
|
||||||
this.speciesStarterDexEntry = species ? this.scene.gameData.getDefaultDexEntry(species) : null;
|
this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null;
|
||||||
this.speciesStarterDexTree = this.speciesStarterDexEntry ? this.scene.gameData.getStarterDexUnlockTree(species) : null;
|
this.dexAttrCursor = species ? this.scene.gameData.getSpeciesDefaultDexAttr(species) : 0n;
|
||||||
|
|
||||||
if (this.lastSpecies) {
|
if (this.lastSpecies) {
|
||||||
const defaultStarterDexEntry = this.scene.gameData.getDefaultDexEntry(this.lastSpecies);
|
const dexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(this.lastSpecies);
|
||||||
|
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr);
|
||||||
const lastSpeciesIcon = (this.starterSelectGenIconContainers[this.lastSpecies.generation - 1].getAt(this.genSpecies[this.lastSpecies.generation - 1].indexOf(this.lastSpecies)) as Phaser.GameObjects.Sprite);
|
const lastSpeciesIcon = (this.starterSelectGenIconContainers[this.lastSpecies.generation - 1].getAt(this.genSpecies[this.lastSpecies.generation - 1].indexOf(this.lastSpecies)) as Phaser.GameObjects.Sprite);
|
||||||
lastSpeciesIcon.play(this.lastSpecies.getIconKey(!!defaultStarterDexEntry?.female, defaultStarterDexEntry?.formIndex)).stop();
|
lastSpeciesIcon.play(this.lastSpecies.getIconKey(props.female, props.formIndex)).stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastSpecies = species;
|
this.lastSpecies = species;
|
||||||
|
|
||||||
if (species && this.speciesStarterDexEntry) {
|
if (species && this.speciesStarterDexEntry?.caughtAttr) {
|
||||||
this.pokemonNumberText.setText(Utils.padInt(species.speciesId, 3));
|
this.pokemonNumberText.setText(Utils.padInt(species.speciesId, 3));
|
||||||
this.pokemonNameText.setText(species.name);
|
this.pokemonNameText.setText(species.name);
|
||||||
this.pokemonGrowthRateText.setText(Utils.toReadableString(GrowthRate[species.growthRate]));
|
this.pokemonGrowthRateText.setText(Utils.toReadableString(GrowthRate[species.growthRate]));
|
||||||
|
@ -559,7 +574,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.pokemonGrowthRateLabelText.setVisible(true);
|
this.pokemonGrowthRateLabelText.setVisible(true);
|
||||||
this.pokemonAbilityLabelText.setVisible(true);
|
this.pokemonAbilityLabelText.setVisible(true);
|
||||||
|
|
||||||
this.setSpeciesDetails(species, !!this.speciesStarterDexEntry?.shiny, this.speciesStarterDexEntry?.formIndex, !!this.speciesStarterDexEntry?.female, this.speciesStarterDexEntry?.abilityIndex);
|
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species);
|
||||||
|
const props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
|
|
||||||
|
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.abilityIndex);
|
||||||
} else {
|
} else {
|
||||||
this.pokemonNumberText.setText(Utils.padInt(0, 3));
|
this.pokemonNumberText.setText(Utils.padInt(0, 3));
|
||||||
this.pokemonNameText.setText(species ? '???' : '');
|
this.pokemonNameText.setText(species ? '???' : '');
|
||||||
|
@ -572,14 +590,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
setSpeciesDetails(species: PokemonSpecies, shiny: boolean, formIndex: integer, female: boolean, abilityIndex: integer): void {
|
setSpeciesDetails(species: PokemonSpecies, shiny: boolean, formIndex: integer, female: boolean, abilityIndex: integer): void {
|
||||||
if (shiny !== undefined)
|
const oldProps = species ? this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null;
|
||||||
this.shinyCursor = !shiny ? 0 : 1;
|
this.dexAttrCursor = 0n;
|
||||||
if (formIndex !== undefined)
|
|
||||||
this.formCursor = formIndex;
|
if (species) {
|
||||||
if (female !== undefined)
|
this.dexAttrCursor |= (shiny !== undefined ? !shiny : !(shiny = oldProps.shiny)) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
this.genderCursor = !female ? 0 : 1;
|
this.dexAttrCursor |= (female !== undefined ? !female : !(female = oldProps.female)) ? DexAttr.MALE : DexAttr.FEMALE;
|
||||||
if (abilityIndex !== undefined)
|
this.dexAttrCursor |= (abilityIndex !== undefined ? !abilityIndex : !(abilityIndex = oldProps.abilityIndex)) ? DexAttr.ABILITY_1 : species.ability2 && abilityIndex === 1 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||||
this.abilityCursor = abilityIndex;
|
this.dexAttrCursor |= this.scene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps.formIndex));
|
||||||
|
}
|
||||||
|
|
||||||
this.pokemonSprite.setVisible(false);
|
this.pokemonSprite.setVisible(false);
|
||||||
|
|
||||||
|
@ -589,26 +608,20 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (species) {
|
if (species) {
|
||||||
const defaultDexEntry = this.scene.gameData.getDefaultDexEntry(species, shiny, formIndex, female, abilityIndex) || this.scene.gameData.getDefaultDexEntry(species);
|
const dexEntry = this.scene.gameData.dexData[species.speciesId];
|
||||||
const dexEntry = this.scene.gameData.getDexEntry(species, !!this.shinyCursor, this.formCursor, !!this.genderCursor, this.abilityCursor);
|
if (!dexEntry.caughtAttr) {
|
||||||
|
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species));
|
||||||
if (!dexEntry.caught) {
|
if (shiny === undefined || shiny !== props.shiny)
|
||||||
if (shiny === undefined || (defaultDexEntry && shiny !== defaultDexEntry.shiny))
|
shiny = props.shiny;
|
||||||
shiny = defaultDexEntry.shiny;
|
if (formIndex === undefined || formIndex !== props.formIndex)
|
||||||
if (formIndex === undefined || (defaultDexEntry && formIndex !== defaultDexEntry.formIndex))
|
formIndex = props.formIndex;
|
||||||
formIndex = defaultDexEntry.formIndex || 0;
|
if (female === undefined || female !== props.female)
|
||||||
if (female === undefined || (defaultDexEntry && female !== defaultDexEntry.female))
|
female = props.female;
|
||||||
female = defaultDexEntry.female;
|
if (abilityIndex === undefined || abilityIndex !== props.abilityIndex)
|
||||||
if (abilityIndex === undefined || (defaultDexEntry && abilityIndex !== defaultDexEntry.abilityIndex))
|
abilityIndex = props.abilityIndex;
|
||||||
abilityIndex = defaultDexEntry.abilityIndex;
|
|
||||||
} else {
|
|
||||||
shiny = !!this.shinyCursor;
|
|
||||||
formIndex = this.formCursor;
|
|
||||||
female = !!this.genderCursor;
|
|
||||||
abilityIndex = this.abilityCursor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.speciesStarterDexTree) {
|
if (this.speciesStarterDexEntry?.caughtAttr) {
|
||||||
const assetLoadCancelled = new Utils.BooleanHolder(false);
|
const assetLoadCancelled = new Utils.BooleanHolder(false);
|
||||||
this.assetLoadCancelled = assetLoadCancelled;
|
this.assetLoadCancelled = assetLoadCancelled;
|
||||||
|
|
||||||
|
@ -624,53 +637,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
species.generateIconAnim(this.scene, female, formIndex);
|
species.generateIconAnim(this.scene, female, formIndex);
|
||||||
(this.starterSelectGenIconContainers[this.genCursor].getAt(this.cursor) as Phaser.GameObjects.Sprite).play(species.getIconKey(female, formIndex));
|
(this.starterSelectGenIconContainers[this.genCursor].getAt(this.cursor) as Phaser.GameObjects.Sprite).play(species.getIconKey(female, formIndex));
|
||||||
|
|
||||||
let count: integer;
|
this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY);
|
||||||
let values: any[];
|
this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE);
|
||||||
const calcUnlockedCount = (tree: StarterDexUnlockTree, prop: string, root?: boolean) => {
|
this.canCycleAbility = [ dexEntry.caughtAttr & DexAttr.ABILITY_1, dexEntry.caughtAttr & DexAttr.ABILITY_2, dexEntry.caughtAttr & DexAttr.ABILITY_HIDDEN ].filter(a => a).length > 1;
|
||||||
if (root) {
|
this.canCycleForm = species.forms.map((_, f) => dexEntry.caughtAttr & this.scene.gameData.getFormAttr(f)).filter(a => a).length > 1;
|
||||||
count = 0;
|
|
||||||
values = [];
|
|
||||||
}
|
|
||||||
if (!tree.entry) {
|
|
||||||
if (!tree[tree.key])
|
|
||||||
console.log(tree, tree.key);
|
|
||||||
for (let key of tree[tree.key].keys())
|
|
||||||
calcUnlockedCount(tree[tree.key].get(key), prop);
|
|
||||||
} else if (tree.entry.caught) {
|
|
||||||
if (values.indexOf(tree[prop]) === -1) {
|
|
||||||
values.push(tree[prop]);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let tree = this.speciesStarterDexTree;
|
|
||||||
|
|
||||||
calcUnlockedCount(tree, 'shiny', true);
|
|
||||||
this.canCycleShiny = count > 1;
|
|
||||||
tree = (tree.shiny as Map<boolean, StarterDexUnlockTree>).get(!!this.shinyCursor);
|
|
||||||
|
|
||||||
if (this.lastSpecies.forms?.length) {
|
|
||||||
calcUnlockedCount(tree, 'formIndex', true);
|
|
||||||
this.canCycleForm = count > 1;
|
|
||||||
tree = (tree.formIndex as Map<integer, StarterDexUnlockTree>).get(this.formCursor);
|
|
||||||
} else
|
|
||||||
this.canCycleForm = false;
|
|
||||||
|
|
||||||
if (this.lastSpecies.malePercent !== null) {
|
|
||||||
calcUnlockedCount(tree, 'female', true);
|
|
||||||
this.canCycleGender = count > 1;
|
|
||||||
} else
|
|
||||||
this.canCycleGender = false;
|
|
||||||
|
|
||||||
if (this.lastSpecies.getAbilityCount() > 1) {
|
|
||||||
calcUnlockedCount(tree, 'abilityIndex', true);
|
|
||||||
this.canCycleAbility = count > 1;
|
|
||||||
} else
|
|
||||||
this.canCycleAbility = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultDexEntry && species.malePercent !== null) {
|
if (dexEntry.caughtAttr && species.malePercent !== null) {
|
||||||
const gender = !female ? Gender.MALE : Gender.FEMALE;
|
const gender = !female ? Gender.MALE : Gender.FEMALE;
|
||||||
this.pokemonGenderText.setText(getGenderSymbol(gender));
|
this.pokemonGenderText.setText(getGenderSymbol(gender));
|
||||||
this.pokemonGenderText.setColor(getGenderColor(gender));
|
this.pokemonGenderText.setColor(getGenderColor(gender));
|
||||||
|
@ -678,7 +651,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
} else
|
} else
|
||||||
this.pokemonGenderText.setText('');
|
this.pokemonGenderText.setText('');
|
||||||
|
|
||||||
if (defaultDexEntry) {
|
if (dexEntry.caughtAttr) {
|
||||||
const ability = this.lastSpecies.getAbility(abilityIndex);
|
const ability = this.lastSpecies.getAbility(abilityIndex);
|
||||||
this.pokemonAbilityText.setText(abilities[ability].name);
|
this.pokemonAbilityText.setText(abilities[ability].name);
|
||||||
|
|
||||||
|
@ -698,7 +671,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
popStarter(): void {
|
popStarter(): void {
|
||||||
this.starterGens.pop();
|
this.starterGens.pop();
|
||||||
this.starterCursors.pop();
|
this.starterCursors.pop();
|
||||||
this.starterDetails.pop();
|
this.starterAttr.pop();
|
||||||
this.starterCursorObjs[this.starterCursors.length].setVisible(false);
|
this.starterCursorObjs[this.starterCursors.length].setVisible(false);
|
||||||
this.starterIcons[this.starterCursors.length].play('pkmn_icon__000');
|
this.starterIcons[this.starterCursors.length].play('pkmn_icon__000');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue