Add candy system for passives and value reductions
parent
ccf956a63c
commit
824a73ef71
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Binary file not shown.
After Width: | Height: | Size: 402 B |
Binary file not shown.
After Width: | Height: | Size: 263 B |
Binary file not shown.
After Width: | Height: | Size: 252 B |
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,7 @@ import Phaser, { Time } from 'phaser';
|
|||
import UI, { Mode } from './ui/ui';
|
||||
import { NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, TurnInitPhase, ReturnPhase, LevelCapPhase, ShowTrainerPhase, LoginPhase, MovePhase, TitlePhase, SwitchPhase } from './phases';
|
||||
import Pokemon, { PlayerPokemon, EnemyPokemon } from './field/pokemon';
|
||||
import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies, initSpecies } from './data/pokemon-species';
|
||||
import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies, initSpecies, speciesStarters } from './data/pokemon-species';
|
||||
import * as Utils from './utils';
|
||||
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier } from './modifier/modifier';
|
||||
import { PokeballType } from './data/pokeball';
|
||||
|
@ -57,6 +57,7 @@ import { initTouchControls } from './touch-controls';
|
|||
import { UiTheme } from './enums/ui-theme';
|
||||
import CacheBustedLoaderPlugin from './plugins/cache-busted-loader-plugin';
|
||||
import { SceneBase } from './scene-base';
|
||||
import CandyBar from './ui/candy-bar';
|
||||
|
||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||
|
||||
|
@ -81,6 +82,11 @@ export const startingWave = STARTING_WAVE_OVERRIDE || 1;
|
|||
const expSpriteKeys: string[] = [];
|
||||
const repeatInputDelayMillis = 250;
|
||||
|
||||
export let starterColors: StarterColors;
|
||||
interface StarterColors {
|
||||
[key: string]: [string, string]
|
||||
}
|
||||
|
||||
export enum Button {
|
||||
UP,
|
||||
DOWN,
|
||||
|
@ -142,6 +148,7 @@ export default class BattleScene extends SceneBase {
|
|||
public pbTrayEnemy: PokeballTray;
|
||||
public abilityBar: AbilityBar;
|
||||
public partyExpBar: PartyExpBar;
|
||||
public candyBar: CandyBar;
|
||||
public arenaBg: Phaser.GameObjects.Sprite;
|
||||
public arenaBgTransition: Phaser.GameObjects.Sprite;
|
||||
public arenaPlayer: ArenaBase;
|
||||
|
@ -359,6 +366,10 @@ export default class BattleScene extends SceneBase {
|
|||
this.partyExpBar.setup();
|
||||
this.fieldUI.add(this.partyExpBar);
|
||||
|
||||
this.candyBar = new CandyBar(this);
|
||||
this.candyBar.setup();
|
||||
this.fieldUI.add(this.candyBar);
|
||||
|
||||
this.waveCountText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, startingWave.toString(), TextStyle.BATTLE_INFO);
|
||||
this.waveCountText.setOrigin(1, 0);
|
||||
this.fieldUI.add(this.waveCountText);
|
||||
|
@ -440,7 +451,8 @@ export default class BattleScene extends SceneBase {
|
|||
Promise.all([
|
||||
Promise.all(loadPokemonAssets),
|
||||
initCommonAnims().then(() => loadCommonAnimAssets(this, true)),
|
||||
Promise.all([ Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE ].map(m => initMoveAnim(m))).then(() => loadMoveAnimAssets(this, defaultMoves, true))
|
||||
Promise.all([ Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE ].map(m => initMoveAnim(m))).then(() => loadMoveAnimAssets(this, defaultMoves, true)),
|
||||
this.initStarterColors()
|
||||
]).then(() => {
|
||||
this.pushPhase(new LoginPhase(this));
|
||||
this.pushPhase(new TitlePhase(this));
|
||||
|
@ -472,12 +484,53 @@ export default class BattleScene extends SceneBase {
|
|||
this.updateScoreText();
|
||||
}
|
||||
|
||||
initExpSprites(): void {
|
||||
if (expSpriteKeys.length)
|
||||
return;
|
||||
fetch('./exp_sprites.json').then(res => res.json()).then(keys => {
|
||||
if (Array.isArray(keys))
|
||||
expSpriteKeys.push(...keys);
|
||||
initExpSprites(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (expSpriteKeys.length)
|
||||
return resolve();
|
||||
fetch('./exp-sprites.json').then(res => res.json()).then(keys => {
|
||||
if (Array.isArray(keys))
|
||||
expSpriteKeys.push(...keys);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initStarterColors(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (starterColors)
|
||||
return resolve();
|
||||
|
||||
fetch('./starter-colors.json').then(res => res.json()).then(sc => {
|
||||
starterColors = {};
|
||||
Object.keys(sc).forEach(key => {
|
||||
starterColors[key] = sc[key];
|
||||
});
|
||||
|
||||
/*const loadPokemonAssets: Promise<void>[] = [];
|
||||
|
||||
for (let s of Object.keys(speciesStarters)) {
|
||||
const species = getPokemonSpecies(parseInt(s));
|
||||
loadPokemonAssets.push(species.loadAssets(this, false, 0, false));
|
||||
}
|
||||
|
||||
Promise.all(loadPokemonAssets).then(() => {
|
||||
const starterCandyColors = {};
|
||||
const rgbaToHexFunc = (r, g, b) => [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
for (let s of Object.keys(speciesStarters)) {
|
||||
const species = getPokemonSpecies(parseInt(s));
|
||||
|
||||
starterCandyColors[species.speciesId] = species.generateCandyColors(this).map(c => rgbaToHexFunc(c[0], c[1], c[2]));
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(starterCandyColors));
|
||||
|
||||
resolve();
|
||||
});*/
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1075,6 +1128,7 @@ export default class BattleScene extends SceneBase {
|
|||
this.scoreText.setY(this.moneyText.y + 10);
|
||||
const offsetY = (this.scoreText.visible ? this.scoreText : this.moneyText).y + 15;
|
||||
this.partyExpBar.setY(offsetY);
|
||||
this.candyBar.setY(offsetY + 15);
|
||||
this.ui?.achvBar.setY(this.game.canvas.height / 6 + offsetY);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,8 @@ function getDailyRunStarter(scene: BattleScene, starterSpeciesForm: PokemonSpeci
|
|||
const starter: Starter = {
|
||||
species: starterSpecies,
|
||||
dexAttr: pokemon.getDexAttr(),
|
||||
passive: false,
|
||||
variant: 0,
|
||||
nature: pokemon.getNature(),
|
||||
pokerus: pokemon.pokerus
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@ import { StarterMoveset } from '../system/game-data';
|
|||
import { speciesEggMoves } from './egg-moves';
|
||||
import { PartyMemberStrength } from "./enums/party-member-strength";
|
||||
import { GameMode } from '../game-mode';
|
||||
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
|
||||
|
||||
export enum Region {
|
||||
NORMAL,
|
||||
|
@ -381,6 +382,55 @@ export abstract class PokemonSpeciesForm {
|
|||
cry.stop();
|
||||
return cry;
|
||||
}
|
||||
|
||||
generateCandyColors(scene: BattleScene): integer[][] {
|
||||
const sourceTexture = scene.textures.get(this.getSpriteKey(false));
|
||||
|
||||
const sourceFrame = sourceTexture.frames[sourceTexture.firstFrame];
|
||||
const sourceImage = sourceTexture.getSourceImage() as HTMLImageElement;
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
|
||||
const spriteColors: integer[][] = [];
|
||||
|
||||
const context = canvas.getContext('2d');
|
||||
const frame = sourceFrame;
|
||||
canvas.width = frame.width;
|
||||
canvas.height = frame.height;
|
||||
context.drawImage(sourceImage, frame.cutX, frame.cutY, frame.width, frame.height, 0, 0, frame.width, frame.height);
|
||||
const imageData = context.getImageData(frame.cutX, frame.cutY, frame.width, frame.height);
|
||||
const pixelData = imageData.data;
|
||||
|
||||
for (let i = 0; i < pixelData.length; i += 4) {
|
||||
if (pixelData[i + 3]) {
|
||||
const pixel = pixelData.slice(i, i + 4);
|
||||
const [ r, g, b, a ] = pixel;
|
||||
if (!spriteColors.find(c => c[0] === r && c[1] === g && c[2] === b))
|
||||
spriteColors.push([ r, g, b, a ]);
|
||||
}
|
||||
}
|
||||
|
||||
const pixelColors = [];
|
||||
for (let i = 0; i < pixelData.length; i += 4) {
|
||||
const total = pixelData.slice(i, i + 3).reduce((total: integer, value: integer) => total + value, 0);
|
||||
if (!total)
|
||||
continue;
|
||||
pixelColors.push(argbFromRgba({ r: pixelData[i], g: pixelData[i + 1], b: pixelData[i + 2], a: pixelData[i + 3] }));
|
||||
}
|
||||
|
||||
let paletteColors: Map<number, number>;
|
||||
|
||||
const originalRandom = Math.random;
|
||||
Math.random = () => Phaser.Math.RND.realInRange(0, 1);
|
||||
|
||||
scene.executeWithSeedOffset(() => {
|
||||
paletteColors = QuantizerCelebi.quantize(pixelColors, 2);
|
||||
}, 0, 'This result should not vary');
|
||||
|
||||
Math.random = originalRandom;
|
||||
|
||||
return Array.from(paletteColors.keys()).map(c => Object.values(rgbaFromArgb(c)) as integer[]);
|
||||
}
|
||||
}
|
||||
|
||||
export default class PokemonSpecies extends PokemonSpeciesForm {
|
||||
|
@ -3058,8 +3108,8 @@ export const starterPassiveAbilities = {
|
|||
[Species.CHARMANDER]: Abilities.INTIMIDATE,
|
||||
[Species.SQUIRTLE]: Abilities.DAUNTLESS_SHIELD,
|
||||
[Species.CATERPIE]: Abilities.MAGICIAN,
|
||||
[Species.WEEDLE]: Abilities.POISON_TOUCH,
|
||||
[Species.PIDGEY]: Abilities.TECHNICIAN,
|
||||
[Species.WEEDLE]: Abilities.TECHNICIAN,
|
||||
[Species.PIDGEY]: Abilities.GALE_WINGS,
|
||||
[Species.RATTATA]: Abilities.STRONG_JAW,
|
||||
[Species.SPEAROW]: Abilities.MOXIE,
|
||||
[Species.EKANS]: Abilities.ROUGH_SKIN,
|
||||
|
@ -3070,14 +3120,14 @@ export const starterPassiveAbilities = {
|
|||
[Species.ZUBAT]: Abilities.WIND_RIDER,
|
||||
[Species.ODDISH]: Abilities.LINGERING_AROMA,
|
||||
[Species.PARAS]: Abilities.POISON_HEAL,
|
||||
[Species.VENONAT]: Abilities.TECHNICIAN,
|
||||
[Species.VENONAT]: Abilities.SWARM,
|
||||
[Species.DIGLETT]: Abilities.STURDY,
|
||||
[Species.MEOWTH]: Abilities.NORMALIZE,
|
||||
[Species.PSYDUCK]: Abilities.SIMPLE,
|
||||
[Species.MANKEY]: Abilities.STAMINA,
|
||||
[Species.GROWLITHE]: Abilities.BALL_FETCH,
|
||||
[Species.MANKEY]: Abilities.IRON_FIST,
|
||||
[Species.GROWLITHE]: Abilities.SPEED_BOOST,
|
||||
[Species.POLIWAG]: Abilities.WATER_BUBBLE,
|
||||
[Species.ABRA]: Abilities.TECHNICIAN,
|
||||
[Species.ABRA]: Abilities.OPPORTUNIST,
|
||||
[Species.MACHOP]: Abilities.IRON_FIST,
|
||||
[Species.BELLSPROUT]: Abilities.CORROSION,
|
||||
[Species.TENTACOOL]: Abilities.INNARDS_OUT,
|
||||
|
@ -3103,7 +3153,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.TANGELA]: Abilities.TANGLING_HAIR,
|
||||
[Species.KANGASKHAN]: Abilities.IRON_FIST,
|
||||
[Species.HORSEA]: Abilities.DRIZZLE,
|
||||
[Species.GOLDEEN]: Abilities.VOLT_ABSORB,
|
||||
[Species.GOLDEEN]: Abilities.MULTISCALE,
|
||||
[Species.STARYU]: Abilities.REGENERATOR,
|
||||
[Species.SCYTHER]: Abilities.SPEED_BOOST,
|
||||
[Species.PINSIR]: Abilities.SAP_SIPPER,
|
||||
|
@ -3139,7 +3189,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.HOPPIP]: Abilities.PRANKSTER,
|
||||
[Species.AIPOM]: Abilities.SCRAPPY,
|
||||
[Species.SUNKERN]: Abilities.DROUGHT,
|
||||
[Species.YANMA]: Abilities.TECHNICIAN,
|
||||
[Species.YANMA]: Abilities.INFILTRATOR,
|
||||
[Species.WOOPER]: Abilities.SIMPLE,
|
||||
[Species.MURKROW]: Abilities.DEFIANT,
|
||||
[Species.MISDREAVUS]: Abilities.DAZZLING,
|
||||
|
@ -3154,7 +3204,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.HERACROSS]: Abilities.QUICK_FEET,
|
||||
[Species.SNEASEL]: Abilities.MOXIE,
|
||||
[Species.TEDDIURSA]: Abilities.GLUTTONY,
|
||||
[Species.SLUGMA]: Abilities.DESOLATE_LAND,
|
||||
[Species.SLUGMA]: Abilities.DROUGHT,
|
||||
[Species.SWINUB]: Abilities.SLUSH_RUSH,
|
||||
[Species.CORSOLA]: Abilities.STORM_DRAIN,
|
||||
[Species.REMORAID]: Abilities.SKILL_LINK,
|
||||
|
@ -3166,7 +3216,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.SMEARGLE]: Abilities.TRACE,
|
||||
[Species.TYROGUE]: Abilities.STAMINA,
|
||||
[Species.SMOOCHUM]: Abilities.CUTE_CHARM,
|
||||
[Species.ELEKID]: Abilities.ADAPTABILITY,
|
||||
[Species.ELEKID]: Abilities.IRON_FIST,
|
||||
[Species.MAGBY]: Abilities.CONTRARY,
|
||||
[Species.MILTANK]: Abilities.GLUTTONY,
|
||||
[Species.RAIKOU]: Abilities.FLARE_BOOST,
|
||||
|
@ -3192,7 +3242,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.SLAKOTH]: Abilities.GUTS,
|
||||
[Species.NINCADA]: Abilities.OVERCOAT,
|
||||
[Species.WHISMUR]: Abilities.PUNK_ROCK,
|
||||
[Species.MAKUHITA]: Abilities.CONTRARY,
|
||||
[Species.MAKUHITA]: Abilities.STAMINA,
|
||||
[Species.AZURILL]: Abilities.UNNERVE,
|
||||
[Species.NOSEPASS]: Abilities.LEVITATE,
|
||||
[Species.SKITTY]: Abilities.SCRAPPY,
|
||||
|
@ -3217,10 +3267,10 @@ export const starterPassiveAbilities = {
|
|||
[Species.SWABLU]: Abilities.WHITE_SMOKE,
|
||||
[Species.ZANGOOSE]: Abilities.SUPER_LUCK,
|
||||
[Species.SEVIPER]: Abilities.MOLD_BREAKER,
|
||||
[Species.LUNATONE]: Abilities.SHADOW_SHIELD,
|
||||
[Species.SOLROCK]: Abilities.FULL_METAL_BODY,
|
||||
[Species.LUNATONE]: Abilities.FAIRY_AURA,
|
||||
[Species.SOLROCK]: Abilities.DROUGHT,
|
||||
[Species.BARBOACH]: Abilities.BALL_FETCH,
|
||||
[Species.CORPHISH]: Abilities.WATER_BUBBLE,
|
||||
[Species.CORPHISH]: Abilities.TOUGH_CLAWS,
|
||||
[Species.BALTOY]: Abilities.OWN_TEMPO,
|
||||
[Species.LILEEP]: Abilities.WATER_ABSORB,
|
||||
[Species.ANORITH]: Abilities.WATER_ABSORB,
|
||||
|
@ -3237,7 +3287,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.CLAMPERL]: Abilities.SIMPLE,
|
||||
[Species.RELICANTH]: Abilities.SOLID_ROCK,
|
||||
[Species.LUVDISC]: Abilities.PICKUP,
|
||||
[Species.BAGON]: Abilities.GALE_WINGS,
|
||||
[Species.BAGON]: Abilities.BERSERK,
|
||||
[Species.BELDUM]: Abilities.IRON_FIST,
|
||||
[Species.REGIROCK]: Abilities.REGENERATOR,
|
||||
[Species.REGICE]: Abilities.ICE_SCALES,
|
||||
|
@ -3251,7 +3301,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.DEOXYS]: Abilities.STICKY_HOLD,
|
||||
[Species.TURTWIG]: Abilities.HARVEST,
|
||||
[Species.CHIMCHAR]: Abilities.DEFIANT,
|
||||
[Species.PIPLUP]: Abilities.BATTLE_ARMOR,
|
||||
[Species.PIPLUP]: Abilities.SLUSH_RUSH,
|
||||
[Species.STARLY]: Abilities.ROCK_HEAD,
|
||||
[Species.BIDOOF]: Abilities.NEUROFORCE,
|
||||
[Species.KRICKETOT]: Abilities.SOUNDPROOF,
|
||||
|
@ -3304,7 +3354,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.VICTINI]: Abilities.SUPER_LUCK,
|
||||
[Species.SNIVY]: Abilities.MULTISCALE,
|
||||
[Species.TEPIG]: Abilities.SAND_RUSH,
|
||||
[Species.OSHAWOTT]: Abilities.LIGHTNING_ROD,
|
||||
[Species.OSHAWOTT]: Abilities.MOLD_BREAKER,
|
||||
[Species.PATRAT]: Abilities.STAKEOUT,
|
||||
[Species.LILLIPUP]: Abilities.BALL_FETCH,
|
||||
[Species.PURRLOIN]: Abilities.DEFIANT,
|
||||
|
@ -3325,8 +3375,8 @@ export const starterPassiveAbilities = {
|
|||
[Species.SEWADDLE]: Abilities.SHARPNESS,
|
||||
[Species.VENIPEDE]: Abilities.INTIMIDATE,
|
||||
[Species.COTTONEE]: Abilities.MISTY_SURGE,
|
||||
[Species.PETILIL]: Abilities.ORICHALCUM_PULSE,
|
||||
[Species.BASCULIN]: Abilities.ROCK_HEAD,
|
||||
[Species.PETILIL]: Abilities.DROUGHT,
|
||||
[Species.BASCULIN]: Abilities.OPPORTUNIST,
|
||||
[Species.SANDILE]: Abilities.STRONG_JAW,
|
||||
[Species.DARUMAKA]: Abilities.IRON_FIST,
|
||||
[Species.MARACTUS]: Abilities.IRON_BARBS,
|
||||
|
@ -3346,14 +3396,14 @@ export const starterPassiveAbilities = {
|
|||
[Species.DEERLING]: Abilities.JUSTIFIED,
|
||||
[Species.EMOLGA]: Abilities.WIND_POWER,
|
||||
[Species.KARRABLAST]: Abilities.NO_GUARD,
|
||||
[Species.FOONGUS]: Abilities.ADAPTABILITY,
|
||||
[Species.FOONGUS]: Abilities.MIMICRY,
|
||||
[Species.FRILLISH]: Abilities.MUMMY,
|
||||
[Species.ALOMOMOLA]: Abilities.MULTISCALE,
|
||||
[Species.JOLTIK]: Abilities.VOLT_ABSORB,
|
||||
[Species.FERROSEED]: Abilities.SKILL_LINK,
|
||||
[Species.KLINK]: Abilities.STEELWORKER,
|
||||
[Species.TYNAMO]: Abilities.SWIFT_SWIM,
|
||||
[Species.ELGYEM]: Abilities.COMMANDER,
|
||||
[Species.ELGYEM]: Abilities.SHADOW_TAG,
|
||||
[Species.LITWICK]: Abilities.SOUL_HEART,
|
||||
[Species.AXEW]: Abilities.SHEER_FORCE,
|
||||
[Species.CUBCHOO]: Abilities.INTIMIDATE,
|
||||
|
@ -3362,7 +3412,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.STUNFISK]: Abilities.STORM_DRAIN,
|
||||
[Species.MIENFOO]: Abilities.NO_GUARD,
|
||||
[Species.DRUDDIGON]: Abilities.INTIMIDATE,
|
||||
[Species.GOLETT]: Abilities.JUSTIFIED,
|
||||
[Species.GOLETT]: Abilities.SHADOW_SHIELD,
|
||||
[Species.PAWNIARD]: Abilities.SHARPNESS,
|
||||
[Species.BOUFFALANT]: Abilities.THICK_FAT,
|
||||
[Species.RUFFLET]: Abilities.RECKLESS,
|
||||
|
@ -3380,7 +3430,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.ZEKROM]: Abilities.HADRON_ENGINE,
|
||||
[Species.LANDORUS]: Abilities.PRANKSTER,
|
||||
[Species.KYUREM]: Abilities.SNOW_WARNING,
|
||||
[Species.KELDEO]: Abilities.HUGE_POWER,
|
||||
[Species.KELDEO]: Abilities.SHARPNESS,
|
||||
[Species.MELOETTA]: Abilities.PUNK_ROCK,
|
||||
[Species.GENESECT]: Abilities.MEGA_LAUNCHER,
|
||||
[Species.CHESPIN]: Abilities.IRON_BARBS,
|
||||
|
@ -3425,7 +3475,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.POPPLIO]: Abilities.PUNK_ROCK,
|
||||
[Species.PIKIPEK]: Abilities.ANGER_POINT,
|
||||
[Species.YUNGOOS]: Abilities.HUGE_POWER,
|
||||
[Species.GRUBBIN]: Abilities.GALVANIZE,
|
||||
[Species.GRUBBIN]: Abilities.SPEED_BOOST,
|
||||
[Species.CRABRAWLER]: Abilities.REFRIGERATE,
|
||||
[Species.ORICORIO]: Abilities.ADAPTABILITY,
|
||||
[Species.CUTIEFLY]: Abilities.FRIEND_GUARD,
|
||||
|
@ -3442,7 +3492,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.COMFEY]: Abilities.FRIEND_GUARD,
|
||||
[Species.ORANGURU]: Abilities.HOSPITALITY,
|
||||
[Species.PASSIMIAN]: Abilities.COSTAR,
|
||||
[Species.WIMPOD]: Abilities.BATTLE_ARMOR,
|
||||
[Species.WIMPOD]: Abilities.TINTED_LENS,
|
||||
[Species.SANDYGAST]: Abilities.DAUNTLESS_SHIELD,
|
||||
[Species.PYUKUMUKU]: Abilities.IRON_BARBS,
|
||||
[Species.TYPE_NULL]: Abilities.ADAPTABILITY,
|
||||
|
@ -3465,7 +3515,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.PHEROMOSA]: Abilities.MOXIE,
|
||||
[Species.XURKITREE]: Abilities.LIGHTNING_ROD,
|
||||
[Species.CELESTEELA]: Abilities.CHLOROPHYLL,
|
||||
[Species.KARTANA]: Abilities.INTREPID_SWORD,
|
||||
[Species.KARTANA]: Abilities.SHARPNESS,
|
||||
[Species.GUZZLORD]: Abilities.GLUTTONY,
|
||||
[Species.NECROZMA]: Abilities.BEAST_BOOST,
|
||||
[Species.MAGEARNA]: Abilities.STEELY_SPIRIT,
|
||||
|
@ -3479,7 +3529,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.SCORBUNNY]: Abilities.RECKLESS,
|
||||
[Species.SOBBLE]: Abilities.MIMICRY,
|
||||
[Species.SKWOVET]: Abilities.HONEY_GATHER,
|
||||
[Species.ROOKIDEE]: Abilities.JUSTIFIED,
|
||||
[Species.ROOKIDEE]: Abilities.IRON_BARBS,
|
||||
[Species.BLIPBUG]: Abilities.TINTED_LENS,
|
||||
[Species.NICKIT]: Abilities.INTIMIDATE,
|
||||
[Species.GOSSIFLEUR]: Abilities.STORM_DRAIN,
|
||||
|
@ -3512,7 +3562,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.ARCTOVISH]: Abilities.STRONG_JAW,
|
||||
[Species.DURALUDON]: Abilities.MEGA_LAUNCHER,
|
||||
[Species.DREEPY]: Abilities.PARENTAL_BOND,
|
||||
[Species.ZACIAN]: Abilities.SHARPNESS,
|
||||
[Species.ZACIAN]: Abilities.GUARD_DOG,
|
||||
[Species.ZAMAZENTA]: Abilities.GUARD_DOG,
|
||||
[Species.ETERNATUS]: Abilities.SUPREME_OVERLORD,
|
||||
[Species.KUBFU]: Abilities.IRON_FIST,
|
||||
|
@ -3535,7 +3585,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.SMOLIV]: Abilities.RIPEN,
|
||||
[Species.SQUAWKABILLY]: Abilities.GALE_WINGS,
|
||||
[Species.NACLI]: Abilities.EARTH_EATER,
|
||||
[Species.CHARCADET]: Abilities.CONTRARY,
|
||||
[Species.CHARCADET]: Abilities.MIRROR_ARMOR,
|
||||
[Species.TADBULB]: Abilities.TRANSISTOR,
|
||||
[Species.WATTREL]: Abilities.GALE_WINGS,
|
||||
[Species.MASCHIFF]: Abilities.STRONG_JAW,
|
||||
|
@ -3562,15 +3612,15 @@ export const starterPassiveAbilities = {
|
|||
[Species.TATSUGIRI]: Abilities.WATER_BUBBLE,
|
||||
[Species.GREAT_TUSK]: Abilities.INTIMIDATE,
|
||||
[Species.SCREAM_TAIL]: Abilities.PIXILATE,
|
||||
[Species.BRUTE_BONNET]: Abilities.ADAPTABILITY,
|
||||
[Species.BRUTE_BONNET]: Abilities.BEAST_BOOST,
|
||||
[Species.FLUTTER_MANE]: Abilities.DAZZLING,
|
||||
[Species.SLITHER_WING]: Abilities.SCRAPPY,
|
||||
[Species.SLITHER_WING]: Abilities.MOXIE,
|
||||
[Species.SANDY_SHOCKS]: Abilities.EARTH_EATER,
|
||||
[Species.IRON_TREADS]: Abilities.STEAM_ENGINE,
|
||||
[Species.IRON_TREADS]: Abilities.BULLETPROOF,
|
||||
[Species.IRON_BUNDLE]: Abilities.SNOW_WARNING,
|
||||
[Species.IRON_HANDS]: Abilities.IRON_FIST,
|
||||
[Species.IRON_JUGULIS]: Abilities.NO_GUARD,
|
||||
[Species.IRON_MOTH]: Abilities.TINTED_LENS,
|
||||
[Species.IRON_MOTH]: Abilities.LEVITATE,
|
||||
[Species.IRON_THORNS]: Abilities.SAND_STREAM,
|
||||
[Species.FRIGIBAX]: Abilities.THICK_FAT,
|
||||
[Species.GIMMIGHOUL]: Abilities.SUPER_LUCK,
|
||||
|
@ -3585,7 +3635,7 @@ export const starterPassiveAbilities = {
|
|||
[Species.WALKING_WAKE]: Abilities.BEAST_BOOST,
|
||||
[Species.IRON_LEAVES]: Abilities.SHARPNESS,
|
||||
[Species.POLTCHAGEIST]: Abilities.FLAME_BODY,
|
||||
[Species.OKIDOGI]: Abilities.STICKY_HOLD,
|
||||
[Species.OKIDOGI]: Abilities.INTIMIDATE,
|
||||
[Species.MUNKIDORI]: Abilities.PRANKSTER,
|
||||
[Species.FEZANDIPITI]: Abilities.DAZZLING,
|
||||
[Species.OGERPON]: Abilities.DISGUISE,
|
||||
|
|
|
@ -2,7 +2,7 @@ export function getData() {
|
|||
const dataStr = localStorage.getItem('data');
|
||||
if (!dataStr)
|
||||
return null;
|
||||
return JSON.parse(atob(dataStr), (k, v) => k.endsWith('Attr') ? BigInt(v) : v);
|
||||
return JSON.parse(atob(dataStr), (k, v) => k.endsWith('Attr') && ![ 'natureAttr', 'passiveAttr', 'variantAttr' ].includes(k) ? BigInt(v) : v);
|
||||
}
|
||||
|
||||
export function getSession() {
|
||||
|
|
|
@ -55,7 +55,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
public species: PokemonSpecies;
|
||||
public formIndex: integer;
|
||||
public abilityIndex: integer;
|
||||
public passive: boolean;
|
||||
public shiny: boolean;
|
||||
public variant: integer;
|
||||
public pokeball: PokeballType;
|
||||
protected battleInfo: BattleInfo;
|
||||
public level: integer;
|
||||
|
@ -127,6 +129,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.hp = dataSource.hp;
|
||||
this.stats = dataSource.stats;
|
||||
this.ivs = dataSource.ivs;
|
||||
this.passive = !!dataSource.passive;
|
||||
this.variant = dataSource.variant || 0;
|
||||
this.nature = dataSource.nature || 0 as Nature;
|
||||
this.natureOverride = dataSource.natureOverride !== undefined ? dataSource.natureOverride : -1;
|
||||
this.moveset = dataSource.moveset;
|
||||
|
@ -727,7 +731,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
canApplyPassive(): boolean {
|
||||
return this.isBoss();
|
||||
return this.passive || this.isBoss();
|
||||
}
|
||||
|
||||
canApplyAbility(passive: boolean = false): boolean {
|
||||
|
@ -1237,8 +1241,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && type === Type.DRAGON)
|
||||
damage.value = Math.floor(damage.value / 2);
|
||||
|
||||
applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage);
|
||||
|
||||
const fixedDamage = new Utils.IntegerHolder(0);
|
||||
applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage);
|
||||
if (!isTypeImmune && fixedDamage.value) {
|
||||
|
@ -1247,8 +1249,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
result = HitResult.EFFECTIVE;
|
||||
}
|
||||
|
||||
console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef);
|
||||
|
||||
if (!result) {
|
||||
if (!typeMultiplier.value)
|
||||
result = HitResult.NO_EFFECT;
|
||||
|
@ -1275,6 +1275,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.scene.applyModifiers(EnemyDamageReducerModifier, false, damage);
|
||||
}
|
||||
|
||||
applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage);
|
||||
|
||||
console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef);
|
||||
|
||||
if (damage.value) {
|
||||
if (this.getHpRatio() === 1)
|
||||
applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, battlerMove, cancelled, damage);
|
||||
|
@ -2156,7 +2160,7 @@ export class PlayerPokemon extends Pokemon {
|
|||
}
|
||||
|
||||
tryPopulateMoveset(moveset: StarterMoveset): boolean {
|
||||
if (!this.getSpeciesForm().validateStarterMoveset(moveset, this.scene.gameData.starterEggMoveData[this.species.getRootSpeciesId()]))
|
||||
if (!this.getSpeciesForm().validateStarterMoveset(moveset, this.scene.gameData.starterData[this.species.getRootSpeciesId()].eggMoves))
|
||||
return false;
|
||||
|
||||
this.moveset = moveset.map(m => new PokemonMove(m));
|
||||
|
|
|
@ -44,7 +44,7 @@ import { EggHatchPhase } from "./egg-hatch-phase";
|
|||
import { Egg } from "./data/egg";
|
||||
import { vouchers } from "./system/voucher";
|
||||
import { loggedInUser, updateUserInfo } from "./account";
|
||||
import { GameDataType, PlayerGender, SessionSaveData } from "./system/game-data";
|
||||
import { DexAttr, GameDataType, PlayerGender, SessionSaveData } from "./system/game-data";
|
||||
import { addPokeballCaptureStars, addPokeballOpenParticles } from "./field/anims";
|
||||
import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger } from "./data/pokemon-forms";
|
||||
import { battleSpecDialogue, getCharVariantFromDialogue } from "./data/dialogue";
|
||||
|
@ -175,7 +175,10 @@ export class TitlePhase extends Phase {
|
|||
if (loggedInUser.lastSessionSlot > -1) {
|
||||
options.push({
|
||||
label: i18next.t('menu:continue'),
|
||||
handler: () => this.loadSaveSlot(this.lastSessionData ? -1 : loggedInUser.lastSessionSlot)
|
||||
handler: () => {
|
||||
this.loadSaveSlot(this.lastSessionData ? -1 : loggedInUser.lastSessionSlot);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
options.push({
|
||||
|
@ -188,20 +191,29 @@ export class TitlePhase extends Phase {
|
|||
this.end();
|
||||
};
|
||||
if (this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]) {
|
||||
const options = [
|
||||
const options: OptionSelectItem[] = [
|
||||
{
|
||||
label: gameModes[GameModes.CLASSIC].getName(),
|
||||
handler: () => setModeAndEnd(GameModes.CLASSIC)
|
||||
handler: () => {
|
||||
setModeAndEnd(GameModes.CLASSIC);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: gameModes[GameModes.ENDLESS].getName(),
|
||||
handler: () => setModeAndEnd(GameModes.ENDLESS)
|
||||
handler: () => {
|
||||
setModeAndEnd(GameModes.ENDLESS);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
];
|
||||
if (this.scene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE]) {
|
||||
options.push({
|
||||
label: gameModes[GameModes.SPLICED_ENDLESS].getName(),
|
||||
handler: () => setModeAndEnd(GameModes.SPLICED_ENDLESS)
|
||||
handler: () => {
|
||||
setModeAndEnd(GameModes.SPLICED_ENDLESS);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
options.push({
|
||||
|
@ -210,6 +222,7 @@ export class TitlePhase extends Phase {
|
|||
this.scene.clearPhaseQueue();
|
||||
this.scene.pushPhase(new TitlePhase(this.scene));
|
||||
super.end();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
this.scene.ui.showText(i18next.t("menu:selectGameMode"), null, () => this.scene.ui.setOverlayMode(Mode.OPTION_SELECT, { options: options }));
|
||||
|
@ -219,21 +232,27 @@ export class TitlePhase extends Phase {
|
|||
this.scene.ui.clearText();
|
||||
this.end();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: i18next.t('menu:loadGame'),
|
||||
handler: () => this.scene.ui.setOverlayMode(Mode.SAVE_SLOT, SaveSlotUiMode.LOAD,
|
||||
(slotId: integer) => {
|
||||
if (slotId === -1)
|
||||
return this.showOptions();
|
||||
this.loadSaveSlot(slotId);
|
||||
}
|
||||
)
|
||||
handler: () => {
|
||||
this.scene.ui.setOverlayMode(Mode.SAVE_SLOT, SaveSlotUiMode.LOAD,
|
||||
(slotId: integer) => {
|
||||
if (slotId === -1)
|
||||
return this.showOptions();
|
||||
this.loadSaveSlot(slotId);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: i18next.t('menu:dailyRun'),
|
||||
handler: () => this.initDailyRun(),
|
||||
handler: () => {
|
||||
this.initDailyRun();
|
||||
return true;
|
||||
},
|
||||
keepOpen: true
|
||||
});
|
||||
const config: OptionSelectConfig = {
|
||||
|
@ -377,6 +396,7 @@ export class SelectGenderPhase extends Phase {
|
|||
this.scene.gameData.gender = PlayerGender.MALE;
|
||||
this.scene.gameData.saveSetting(Setting.Player_Gender, 0);
|
||||
this.scene.gameData.saveSystem().then(() => this.end());
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -385,6 +405,7 @@ export class SelectGenderPhase extends Phase {
|
|||
this.scene.gameData.gender = PlayerGender.FEMALE;
|
||||
this.scene.gameData.saveSetting(Setting.Player_Gender, 1);
|
||||
this.scene.gameData.saveSystem().then(() => this.end());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -437,6 +458,10 @@ export class SelectStarterPhase extends Phase {
|
|||
const starterIvs = this.scene.gameData.dexData[starter.species.speciesId].ivs.slice(0);
|
||||
const starterPokemon = this.scene.addPlayerPokemon(starter.species, this.scene.gameMode.getStartingLevel(), starterProps.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterIvs, starter.nature);
|
||||
starterPokemon.tryPopulateMoveset(starter.moveset);
|
||||
if (starter.passive)
|
||||
starterPokemon.passive = true;
|
||||
if (starter.variant && starter.dexAttr & DexAttr.SHINY)
|
||||
starterPokemon.variant = starter.variant;
|
||||
if (starter.pokerus)
|
||||
starterPokemon.pokerus = true;
|
||||
if (this.scene.gameMode.isSplicedOnly)
|
||||
|
|
|
@ -43,6 +43,11 @@ export enum PlayerGender {
|
|||
FEMALE
|
||||
}
|
||||
|
||||
export enum Passive {
|
||||
UNLOCKED = 1,
|
||||
ENABLED = 2
|
||||
}
|
||||
|
||||
export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): string {
|
||||
switch (dataType) {
|
||||
case GameDataType.SYSTEM:
|
||||
|
@ -64,8 +69,7 @@ interface SystemSaveData {
|
|||
secretId: integer;
|
||||
gender: PlayerGender;
|
||||
dexData: DexData;
|
||||
starterMoveData: StarterMoveData;
|
||||
starterEggMoveData: StarterEggMoveData;
|
||||
starterData: StarterData;
|
||||
gameStats: GameStats;
|
||||
unlocks: Unlocks;
|
||||
achvUnlocks: AchvUnlocks;
|
||||
|
@ -145,16 +149,25 @@ export interface DexAttrProps {
|
|||
|
||||
export type StarterMoveset = [ Moves ] | [ Moves, Moves ] | [ Moves, Moves, Moves ] | [ Moves, Moves, Moves, Moves ];
|
||||
|
||||
export interface StarterMoveData {
|
||||
[key: integer]: StarterMoveset | StarterFormMoveData
|
||||
}
|
||||
|
||||
export interface StarterFormMoveData {
|
||||
[key: integer]: StarterMoveset
|
||||
}
|
||||
|
||||
export interface StarterEggMoveData {
|
||||
[key: integer]: integer
|
||||
export interface StarterMoveData {
|
||||
[key: integer]: StarterMoveset | StarterFormMoveData
|
||||
}
|
||||
|
||||
export interface StarterDataEntry {
|
||||
moveset: StarterMoveset | StarterFormMoveData;
|
||||
eggMoves: integer;
|
||||
candyCount: integer;
|
||||
passiveAttr: integer;
|
||||
variantAttr: integer;
|
||||
valueReduction: integer;
|
||||
}
|
||||
|
||||
export interface StarterData {
|
||||
[key: integer]: StarterDataEntry
|
||||
}
|
||||
|
||||
export interface TutorialFlags {
|
||||
|
@ -167,7 +180,12 @@ const systemShortKeys = {
|
|||
natureAttr: '$na',
|
||||
seenCount: '$s' ,
|
||||
caughtCount: '$c',
|
||||
ivs: '$i'
|
||||
ivs: '$i',
|
||||
moveset: '$m',
|
||||
eggMoves: '$em',
|
||||
candyCount: '$cc',
|
||||
passive: '$p',
|
||||
valueReduction: '$vr'
|
||||
};
|
||||
|
||||
export class GameData {
|
||||
|
@ -181,9 +199,7 @@ export class GameData {
|
|||
public dexData: DexData;
|
||||
private defaultDexData: DexData;
|
||||
|
||||
public starterMoveData: StarterMoveData;
|
||||
|
||||
public starterEggMoveData: StarterEggMoveData;
|
||||
public starterData: StarterData;
|
||||
|
||||
public gameStats: GameStats;
|
||||
|
||||
|
@ -200,8 +216,7 @@ export class GameData {
|
|||
this.loadSettings();
|
||||
this.trainerId = Utils.randSeedInt(65536);
|
||||
this.secretId = Utils.randSeedInt(65536);
|
||||
this.starterMoveData = {};
|
||||
this.starterEggMoveData = {};
|
||||
this.starterData = {};
|
||||
this.gameStats = new GameStats();
|
||||
this.unlocks = {
|
||||
[Unlockables.ENDLESS_MODE]: false,
|
||||
|
@ -218,7 +233,7 @@ export class GameData {
|
|||
};
|
||||
this.eggs = [];
|
||||
this.initDexData();
|
||||
this.initEggMoveData();
|
||||
this.initStarterData();
|
||||
}
|
||||
|
||||
public saveSystem(): Promise<boolean> {
|
||||
|
@ -234,8 +249,7 @@ export class GameData {
|
|||
secretId: this.secretId,
|
||||
gender: this.gender,
|
||||
dexData: this.dexData,
|
||||
starterMoveData: this.starterMoveData,
|
||||
starterEggMoveData: this.starterEggMoveData,
|
||||
starterData: this.starterData,
|
||||
gameStats: this.gameStats,
|
||||
unlocks: this.unlocks,
|
||||
achvUnlocks: this.achvUnlocks,
|
||||
|
@ -297,17 +311,24 @@ export class GameData {
|
|||
|
||||
this.saveSetting(Setting.Player_Gender, systemData.gender === PlayerGender.FEMALE ? 1 : 0);
|
||||
|
||||
this.starterMoveData = systemData.starterMoveData || {};
|
||||
const initStarterData = !systemData.starterData;
|
||||
|
||||
this.starterEggMoveData = {};
|
||||
this.initEggMoveData();
|
||||
if (initStarterData) {
|
||||
this.initStarterData();
|
||||
|
||||
if (systemData.starterEggMoveData) {
|
||||
for (let key of Object.keys(systemData.starterEggMoveData)) {
|
||||
if (this.starterEggMoveData.hasOwnProperty(key))
|
||||
this.starterEggMoveData[key] = systemData.starterEggMoveData[key];
|
||||
if (systemData['starterMoveData']) {
|
||||
const starterMoveData = systemData['starterMoveData'];
|
||||
for (let s of Object.keys(starterMoveData))
|
||||
this.starterData[s].moveset = starterMoveData[s];
|
||||
}
|
||||
}
|
||||
|
||||
if (systemData['starterEggMoveData']) {
|
||||
const starterEggMoveData = systemData['starterEggMoveData'];
|
||||
for (let s of Object.keys(starterEggMoveData))
|
||||
this.starterData[s].eggMoves = starterEggMoveData[s];
|
||||
}
|
||||
} else
|
||||
this.starterData = systemData.starterData;
|
||||
|
||||
if (systemData.gameStats)
|
||||
this.gameStats = systemData.gameStats;
|
||||
|
@ -348,6 +369,16 @@ export class GameData {
|
|||
this.consolidateDexData(this.dexData);
|
||||
this.defaultDexData = null;
|
||||
|
||||
if (initStarterData) {
|
||||
const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species);
|
||||
for (let s of starterIds) {
|
||||
this.starterData[s].candyCount += this.dexData[s].caughtCount;
|
||||
this.starterData[s].candyCount += this.dexData[s].hatchedCount * 2;
|
||||
if (this.dexData[s].caughtAttr & DexAttr.SHINY)
|
||||
this.starterData[s].candyCount += 4;
|
||||
}
|
||||
}
|
||||
|
||||
resolve(true);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
@ -388,7 +419,7 @@ export class GameData {
|
|||
return ret;
|
||||
}
|
||||
|
||||
return k.endsWith('Attr') && k !== 'natureAttr' ? BigInt(v) : v;
|
||||
return k.endsWith('Attr') && ![ 'natureAttr', 'passiveAttr', 'variantAttr' ].includes(k) ? BigInt(v) : v;
|
||||
}) as SystemSaveData;
|
||||
}
|
||||
|
||||
|
@ -906,15 +937,23 @@ export class GameData {
|
|||
this.dexData = data;
|
||||
}
|
||||
|
||||
private initEggMoveData(): void {
|
||||
const data: StarterEggMoveData = {};
|
||||
private initStarterData(): void {
|
||||
const starterData: StarterData = {};
|
||||
|
||||
const starterSpeciesIds = Object.keys(speciesEggMoves).map(k => parseInt(k) as Species);
|
||||
const starterSpeciesIds = Object.keys(speciesStarters).map(k => parseInt(k) as Species);
|
||||
|
||||
for (let speciesId of starterSpeciesIds)
|
||||
data[speciesId] = 0;
|
||||
for (let speciesId of starterSpeciesIds) {
|
||||
starterData[speciesId] = {
|
||||
moveset: null,
|
||||
eggMoves: 0,
|
||||
candyCount: 0,
|
||||
passiveAttr: 0,
|
||||
variantAttr: 0,
|
||||
valueReduction: 0
|
||||
};
|
||||
}
|
||||
|
||||
this.starterEggMoveData = data;
|
||||
this.starterData = starterData;
|
||||
}
|
||||
|
||||
setPokemonSeen(pokemon: Pokemon, incrementCount: boolean = true): void {
|
||||
|
@ -943,6 +982,10 @@ export class GameData {
|
|||
pokemon.formIndex = formIndex;
|
||||
dexEntry.caughtAttr |= dexAttr;
|
||||
dexEntry.natureAttr |= Math.pow(2, pokemon.nature + 1);
|
||||
|
||||
const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId);
|
||||
const newCatch = !caughtAttr;
|
||||
|
||||
if (incrementCount) {
|
||||
if (!fromEgg) {
|
||||
dexEntry.caughtCount++;
|
||||
|
@ -963,10 +1006,10 @@ export class GameData {
|
|||
if (pokemon.isShiny())
|
||||
this.gameStats.shinyPokemonHatched++;
|
||||
}
|
||||
}
|
||||
|
||||
const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId);
|
||||
const newCatch = !caughtAttr;
|
||||
if (!hasPrevolution)
|
||||
this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1));
|
||||
}
|
||||
|
||||
const checkPrevolution = () => {
|
||||
if (hasPrevolution) {
|
||||
|
@ -984,6 +1027,11 @@ export class GameData {
|
|||
});
|
||||
}
|
||||
|
||||
addStarterCandy(species: PokemonSpecies, count: integer): void {
|
||||
this.scene.candyBar.showStarterSpeciesCandy(species.speciesId, count);
|
||||
this.starterData[species.speciesId].candyCount += count;
|
||||
}
|
||||
|
||||
setEggMoveUnlocked(species: PokemonSpecies, eggMoveIndex: integer): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
const speciesId = species.speciesId;
|
||||
|
@ -992,17 +1040,17 @@ export class GameData {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!this.starterEggMoveData.hasOwnProperty(speciesId))
|
||||
this.starterEggMoveData[speciesId] = 0;
|
||||
if (!this.starterData[speciesId].eggMoves)
|
||||
this.starterData[speciesId].eggMoves = 0;
|
||||
|
||||
const value = Math.pow(2, eggMoveIndex);
|
||||
|
||||
if (this.starterEggMoveData[speciesId] & value) {
|
||||
if (this.starterData[speciesId].eggMoves & value) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
this.starterEggMoveData[speciesId] |= value;
|
||||
this.starterData[speciesId].eggMoves |= value;
|
||||
|
||||
this.scene.playSound('level_up_fanfare');
|
||||
this.scene.ui.showText(`${eggMoveIndex === 3 ? 'Rare ' : ''}Egg Move unlocked: ${allMoves[speciesEggMoves[speciesId][eggMoveIndex]].name}`, null, () => resolve(true), null, true);
|
||||
|
@ -1094,7 +1142,6 @@ export class GameData {
|
|||
getSpeciesStarterValue(speciesId: Species): number {
|
||||
const baseValue = speciesStarters[speciesId];
|
||||
let value = baseValue;
|
||||
const caughtHatchedCount = this.dexData[speciesId].caughtCount + this.dexData[speciesId].hatchedCount;
|
||||
|
||||
const decrementValue = (value: number) => {
|
||||
if (value > 1)
|
||||
|
@ -1104,44 +1151,8 @@ export class GameData {
|
|||
return value;
|
||||
}
|
||||
|
||||
let thresholdA: integer;
|
||||
let thresholdB: integer;
|
||||
|
||||
switch (baseValue) {
|
||||
case 1:
|
||||
[ thresholdA, thresholdB ] = [ 25, 100 ];
|
||||
break;
|
||||
case 2:
|
||||
[ thresholdA, thresholdB ] = [ 20, 70 ];
|
||||
break;
|
||||
case 3:
|
||||
[ thresholdA, thresholdB ] = [ 15, 50 ];
|
||||
break;
|
||||
case 4:
|
||||
[ thresholdA, thresholdB ] = [ 10, 30 ];
|
||||
break;
|
||||
case 5:
|
||||
[ thresholdA, thresholdB ] = [ 8, 25 ];
|
||||
break;
|
||||
case 6:
|
||||
[ thresholdA, thresholdB ] = [ 5, 15 ];
|
||||
break;
|
||||
case 7:
|
||||
[ thresholdA, thresholdB ] = [ 4, 12 ];
|
||||
break;
|
||||
case 8:
|
||||
[ thresholdA, thresholdB ] = [ 3, 10 ];
|
||||
break;
|
||||
default:
|
||||
[ thresholdA, thresholdB ] = [ 2, 5 ];
|
||||
break;
|
||||
}
|
||||
|
||||
if (caughtHatchedCount >= thresholdA) {
|
||||
for (let v = 0; v < this.starterData[speciesId].valueReduction; v++)
|
||||
value = decrementValue(value);
|
||||
if (caughtHatchedCount >= thresholdB)
|
||||
value = decrementValue(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@ export default class PokemonData {
|
|||
public species: Species;
|
||||
public formIndex: integer;
|
||||
public abilityIndex: integer;
|
||||
public passive: boolean;
|
||||
public shiny: boolean;
|
||||
public variant: integer;
|
||||
public pokeball: PokeballType;
|
||||
public level: integer;
|
||||
public exp: integer;
|
||||
|
@ -53,7 +55,9 @@ export default class PokemonData {
|
|||
this.species = sourcePokemon ? sourcePokemon.species.speciesId : source.species;
|
||||
this.formIndex = Math.max(Math.min(source.formIndex, getPokemonSpecies(this.species).forms.length - 1), 0);
|
||||
this.abilityIndex = source.abilityIndex;
|
||||
this.passive = source.passive;
|
||||
this.shiny = source.shiny;
|
||||
this.variant = source.variant;
|
||||
this.pokeball = source.pokeball;
|
||||
this.level = source.level;
|
||||
this.exp = source.exp;
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Mode } from "./ui";
|
|||
import UiHandler from "./ui-handler";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import * as Utils from "../utils";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
|
||||
export interface OptionSelectConfig {
|
||||
xOffset?: number;
|
||||
|
@ -16,9 +17,11 @@ export interface OptionSelectConfig {
|
|||
|
||||
export interface OptionSelectItem {
|
||||
label: string;
|
||||
handler: Function;
|
||||
handler: () => boolean;
|
||||
keepOpen?: boolean;
|
||||
overrideSound?: boolean;
|
||||
item?: string;
|
||||
itemArgs?: any[]
|
||||
}
|
||||
|
||||
const scrollUpLabel = '↑';
|
||||
|
@ -28,6 +31,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||
protected optionSelectContainer: Phaser.GameObjects.Container;
|
||||
protected optionSelectBg: Phaser.GameObjects.NineSlice;
|
||||
protected optionSelectText: Phaser.GameObjects.Text;
|
||||
protected optionSelectIcons: Phaser.GameObjects.Sprite[];
|
||||
|
||||
protected config: OptionSelectConfig;
|
||||
|
||||
|
@ -58,6 +62,8 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||
this.optionSelectBg.setOrigin(1, 1);
|
||||
this.optionSelectContainer.add(this.optionSelectBg);
|
||||
|
||||
this.optionSelectIcons = [];
|
||||
|
||||
this.setCursor(0);
|
||||
}
|
||||
|
||||
|
@ -66,8 +72,12 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||
|
||||
if (this.optionSelectText)
|
||||
this.optionSelectText.destroy();
|
||||
if (this.optionSelectIcons?.length) {
|
||||
this.optionSelectIcons.map(i => i.destroy());
|
||||
this.optionSelectIcons.splice(0, this.optionSelectIcons.length);
|
||||
}
|
||||
|
||||
this.optionSelectText = addTextObject(this.scene, 0, 0, options.map(o => o.label).join('\n'), TextStyle.WINDOW, { maxLines: options.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.setLineSpacing(12);
|
||||
this.optionSelectContainer.add(this.optionSelectText);
|
||||
this.optionSelectContainer.setPosition((this.scene.game.canvas.width / 6) - 1 - (this.config?.xOffset || 0), -48 + (this.config?.yOffset || 0));
|
||||
|
@ -80,6 +90,31 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||
this.optionSelectBg.height = this.getWindowHeight();
|
||||
|
||||
this.optionSelectText.setPositionRelative(this.optionSelectBg, 16, 9);
|
||||
|
||||
options.forEach((option: OptionSelectItem, i: integer) => {
|
||||
if (option.item) {
|
||||
const itemIcon = this.scene.add.sprite(0, 0, 'items', option.item);
|
||||
itemIcon.setScale(0.5);
|
||||
this.optionSelectIcons.push(itemIcon);
|
||||
|
||||
this.optionSelectContainer.add(itemIcon);
|
||||
|
||||
itemIcon.setPositionRelative(this.optionSelectText, 6, 7 + 16 * i);
|
||||
|
||||
if (option.item === 'candy') {
|
||||
const itemOverlayIcon = this.scene.add.sprite(0, 0, 'items', 'candy_overlay');
|
||||
itemOverlayIcon.setScale(0.5);
|
||||
this.optionSelectIcons.push(itemOverlayIcon);
|
||||
|
||||
this.optionSelectContainer.add(itemOverlayIcon);
|
||||
|
||||
itemOverlayIcon.setPositionRelative(this.optionSelectText, 6, 7 + 16 * i);
|
||||
|
||||
itemIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(option.itemArgs[0])));
|
||||
itemOverlayIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(option.itemArgs[1])));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
|
@ -132,10 +167,12 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||
return false;
|
||||
}
|
||||
const option = this.config.options[this.cursor + (this.scrollCursor - (this.scrollCursor ? 1 : 0))];
|
||||
option.handler();
|
||||
if (!option.keepOpen)
|
||||
this.clear();
|
||||
playSound = !option.overrideSound;
|
||||
if (option.handler()) {
|
||||
if (!option.keepOpen)
|
||||
this.clear();
|
||||
playSound = !option.overrideSound;
|
||||
} else
|
||||
ui.playError();
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
|
@ -182,12 +219,12 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||
if (optionStartIndex)
|
||||
options.unshift({
|
||||
label: scrollUpLabel,
|
||||
handler: () => { }
|
||||
handler: () => true
|
||||
});
|
||||
if (optionEndIndex < optionsScrollTotal)
|
||||
options.push({
|
||||
label: scrollDownLabel,
|
||||
handler: () => { }
|
||||
handler: () => true
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
import BattleScene, { starterColors } from "../battle-scene";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import * as Utils from "../utils";
|
||||
import { Species } from "#app/data/enums/species";
|
||||
|
||||
export default class CandyBar extends Phaser.GameObjects.Container {
|
||||
private bg: Phaser.GameObjects.NineSlice;
|
||||
private candyIcon: Phaser.GameObjects.Sprite;
|
||||
private candyOverlayIcon: Phaser.GameObjects.Sprite;
|
||||
private countText: Phaser.GameObjects.Text;
|
||||
private speciesId: Species;
|
||||
|
||||
private tween: Phaser.Tweens.Tween;
|
||||
private autoHideTimer: number;
|
||||
|
||||
public shown: boolean;
|
||||
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene, (scene.game.canvas.width / 6), -((scene.game.canvas.height) / 6) + 15);
|
||||
}
|
||||
|
||||
setup(): void {
|
||||
this.bg = this.scene.add.nineslice(0, 0, 'party_exp_bar', null, 8, 18, 21, 5, 6, 4);
|
||||
this.bg.setOrigin(0, 0);
|
||||
|
||||
this.add(this.bg);
|
||||
|
||||
this.candyIcon = this.scene.add.sprite(14, 0, 'items', 'candy');
|
||||
this.candyIcon.setOrigin(0.5, 0);
|
||||
this.candyIcon.setScale(0.5);
|
||||
|
||||
this.add(this.candyIcon);
|
||||
|
||||
this.candyOverlayIcon = this.scene.add.sprite(14, 0, 'items', 'candy_overlay');
|
||||
this.candyOverlayIcon.setOrigin(0.5, 0);
|
||||
this.candyOverlayIcon.setScale(0.5);
|
||||
|
||||
this.add(this.candyOverlayIcon);
|
||||
|
||||
this.countText = addTextObject(this.scene, 22, 4, '', TextStyle.BATTLE_INFO);
|
||||
this.countText.setOrigin(0, 0);
|
||||
this.add(this.countText);
|
||||
|
||||
this.setVisible(false);
|
||||
this.shown = false;
|
||||
}
|
||||
|
||||
showStarterSpeciesCandy(starterSpeciesId: Species, count: integer): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
if (this.shown) {
|
||||
if (this.speciesId === starterSpeciesId)
|
||||
return resolve();
|
||||
else
|
||||
return this.hide().then(() => this.showStarterSpeciesCandy(starterSpeciesId, count)).then(() => resolve());
|
||||
}
|
||||
|
||||
const colorScheme = starterColors[starterSpeciesId];
|
||||
|
||||
this.candyIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[0])));
|
||||
this.candyOverlayIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[1])));
|
||||
|
||||
this.countText.setText(`${(this.scene as BattleScene).gameData.starterData[starterSpeciesId].candyCount + count} (+${count.toString()})`);
|
||||
|
||||
this.bg.width = this.countText.displayWidth + 28;
|
||||
|
||||
(this.scene as BattleScene).fieldUI.bringToTop(this);
|
||||
|
||||
if (this.tween)
|
||||
this.tween.stop();
|
||||
|
||||
this.tween = this.scene.tweens.add({
|
||||
targets: this,
|
||||
x: (this.scene.game.canvas.width / 6) - (this.bg.width - 5),
|
||||
duration: 500,
|
||||
ease: 'Sine.easeOut',
|
||||
onComplete: () => {
|
||||
this.tween = null;
|
||||
this.resetAutoHideTimer();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
this.setVisible(true);
|
||||
this.shown = true;
|
||||
});
|
||||
}
|
||||
|
||||
hide(): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
if (!this.shown)
|
||||
return resolve();
|
||||
|
||||
if (this.autoHideTimer)
|
||||
clearInterval(this.autoHideTimer);
|
||||
|
||||
if (this.tween)
|
||||
this.tween.stop();
|
||||
|
||||
this.tween = this.scene.tweens.add({
|
||||
targets: this,
|
||||
x: (this.scene.game.canvas.width / 6),
|
||||
duration: 500,
|
||||
ease: 'Sine.easeIn',
|
||||
onComplete: () => {
|
||||
this.tween = null;
|
||||
this.shown = false;
|
||||
this.setVisible(false);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
resetAutoHideTimer(): void {
|
||||
if (this.autoHideTimer)
|
||||
clearInterval(this.autoHideTimer);
|
||||
this.autoHideTimer = setTimeout(() => {
|
||||
this.hide();
|
||||
this.autoHideTimer = null;
|
||||
}, 2500);
|
||||
}
|
||||
}
|
|
@ -20,11 +20,17 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
|
|||
options: [
|
||||
{
|
||||
label: 'Yes',
|
||||
handler: args[0]
|
||||
handler: () => {
|
||||
args[0]();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'No',
|
||||
handler: args[1]
|
||||
handler: () => {
|
||||
args[1]();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
],
|
||||
delay: args.length >= 6 && args[5] !== null ? args[5] as integer : 0
|
||||
|
|
|
@ -5,7 +5,7 @@ import * as Utils from "../utils";
|
|||
import { addWindow } from "./ui-theme";
|
||||
import MessageUiHandler from "./message-ui-handler";
|
||||
import { GameDataType } from "../system/game-data";
|
||||
import { OptionSelectConfig } from "./abstact-option-select-ui-handler";
|
||||
import { OptionSelectConfig, OptionSelectItem } from "./abstact-option-select-ui-handler";
|
||||
import { Tutorial, handleTutorial } from "../tutorial";
|
||||
import { updateUserInfo } from "../account";
|
||||
|
||||
|
@ -99,6 +99,7 @@ export default class MenuUiHandler extends MessageUiHandler {
|
|||
callback(i);
|
||||
ui.revertMode();
|
||||
ui.showText(null, 0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}).concat([{
|
||||
|
@ -106,6 +107,7 @@ export default class MenuUiHandler extends MessageUiHandler {
|
|||
handler: () => {
|
||||
ui.revertMode();
|
||||
ui.showText(null, 0);
|
||||
return true;
|
||||
}
|
||||
}]),
|
||||
xOffset: 98
|
||||
|
@ -117,7 +119,10 @@ export default class MenuUiHandler extends MessageUiHandler {
|
|||
if (Utils.isLocal) {
|
||||
manageDataOptions.push({
|
||||
label: 'Import Session',
|
||||
handler: () => confirmSlot('Select a slot to import to.', () => true, slotId => this.scene.gameData.importData(GameDataType.SESSION, slotId)),
|
||||
handler: () => {
|
||||
confirmSlot('Select a slot to import to.', () => true, slotId => this.scene.gameData.importData(GameDataType.SESSION, slotId));
|
||||
return true;
|
||||
},
|
||||
keepOpen: true
|
||||
});
|
||||
}
|
||||
|
@ -137,25 +142,35 @@ export default class MenuUiHandler extends MessageUiHandler {
|
|||
i => dataSlots.indexOf(i) > -1,
|
||||
slotId => this.scene.gameData.tryExportData(GameDataType.SESSION, slotId));
|
||||
});
|
||||
return true;
|
||||
},
|
||||
keepOpen: true
|
||||
});
|
||||
if (Utils.isLocal) {
|
||||
manageDataOptions.push({
|
||||
label: 'Import Data',
|
||||
handler: () => this.scene.gameData.importData(GameDataType.SYSTEM),
|
||||
handler: () => {
|
||||
this.scene.gameData.importData(GameDataType.SYSTEM);
|
||||
return true;
|
||||
},
|
||||
keepOpen: true
|
||||
});
|
||||
}
|
||||
manageDataOptions.push(
|
||||
{
|
||||
label: 'Export Data',
|
||||
handler: () => this.scene.gameData.tryExportData(GameDataType.SYSTEM),
|
||||
handler: () => {
|
||||
this.scene.gameData.tryExportData(GameDataType.SYSTEM);
|
||||
return true;
|
||||
},
|
||||
keepOpen: true
|
||||
},
|
||||
{
|
||||
label: 'Cancel',
|
||||
handler: () => this.scene.ui.revertMode()
|
||||
handler: () => {
|
||||
this.scene.ui.revertMode();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -164,25 +179,37 @@ export default class MenuUiHandler extends MessageUiHandler {
|
|||
options: manageDataOptions
|
||||
};
|
||||
|
||||
const communityOptions = [
|
||||
const communityOptions: OptionSelectItem[] = [
|
||||
{
|
||||
label: 'Wiki',
|
||||
handler: () => window.open(wikiUrl, '_blank').focus(),
|
||||
handler: () => {
|
||||
window.open(wikiUrl, '_blank').focus();
|
||||
return true;
|
||||
},
|
||||
keepOpen: true
|
||||
},
|
||||
{
|
||||
label: 'Discord',
|
||||
handler: () => window.open(discordUrl, '_blank').focus(),
|
||||
handler: () => {
|
||||
window.open(discordUrl, '_blank').focus();
|
||||
return true;
|
||||
},
|
||||
keepOpen: true
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
handler: () => window.open(githubUrl, '_blank').focus(),
|
||||
handler: () => {
|
||||
window.open(githubUrl, '_blank').focus();
|
||||
return true;
|
||||
},
|
||||
keepOpen: true
|
||||
},
|
||||
{
|
||||
label: 'Cancel',
|
||||
handler: () => this.scene.ui.revertMode()
|
||||
handler: () => {
|
||||
this.scene.ui.revertMode();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import BattleScene, { Button } from "../battle-scene";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "../data/pokemon-species";
|
||||
import BattleScene, { Button, starterColors } from "../battle-scene";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species";
|
||||
import { Species } from "../data/enums/species";
|
||||
import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text";
|
||||
import { TextStyle, addBBCodeTextObject, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
import MessageUiHandler from "./message-ui-handler";
|
||||
import { Gender, getGenderColor, getGenderSymbol } from "../data/gender";
|
||||
import { allAbilities } from "../data/ability";
|
||||
import { GameMode, GameModes, gameModes } from "../game-mode";
|
||||
import { Unlockables } from "../system/unlockables";
|
||||
import { GameModes, gameModes } from "../game-mode";
|
||||
import { GrowthRate, getGrowthRateColor } from "../data/exp";
|
||||
import { DexAttr, DexAttrProps, DexEntry, StarterFormMoveData, StarterMoveset } from "../system/game-data";
|
||||
import { DexAttr, DexAttrProps, DexEntry, Passive as PassiveAttr, StarterFormMoveData, StarterMoveset } from "../system/game-data";
|
||||
import * as Utils from "../utils";
|
||||
import PokemonIconAnimHandler, { PokemonIconAnimMode } from "./pokemon-icon-anim-handler";
|
||||
import { StatsContainer } from "./stats-container";
|
||||
|
@ -24,17 +23,65 @@ import { Type } from "../data/type";
|
|||
import { Moves } from "../data/enums/moves";
|
||||
import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { TitlePhase } from "../phases";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import { OptionSelectItem } from "./abstact-option-select-ui-handler";
|
||||
|
||||
export type StarterSelectCallback = (starters: Starter[]) => void;
|
||||
|
||||
export interface Starter {
|
||||
species: PokemonSpecies;
|
||||
dexAttr: bigint;
|
||||
passive: boolean;
|
||||
variant: integer;
|
||||
nature: Nature;
|
||||
moveset?: StarterMoveset;
|
||||
pokerus: boolean;
|
||||
}
|
||||
|
||||
function getPassiveCandyCount(baseValue: integer): integer {
|
||||
switch (baseValue) {
|
||||
case 1:
|
||||
return 100;
|
||||
case 2:
|
||||
return 75;
|
||||
case 3:
|
||||
return 50;
|
||||
case 4:
|
||||
return 40
|
||||
case 5:
|
||||
return 30;
|
||||
case 6:
|
||||
return 20;
|
||||
case 7:
|
||||
return 15;
|
||||
default:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
function getValueReductionCandyCounts(baseValue: integer): [integer, integer] {
|
||||
switch (baseValue) {
|
||||
case 1:
|
||||
return [ 50, 150 ];
|
||||
case 2:
|
||||
return [ 30, 100 ];
|
||||
case 3:
|
||||
return [ 25, 75 ];
|
||||
case 4:
|
||||
return [ 20, 60 ];
|
||||
case 5:
|
||||
return [ 15, 50 ];
|
||||
case 6:
|
||||
return [ 10, 30 ];
|
||||
case 7:
|
||||
return [ 8, 20 ];
|
||||
case 8:
|
||||
return [ 5, 15 ];
|
||||
default:
|
||||
return [ 3, 10 ];
|
||||
}
|
||||
}
|
||||
|
||||
const gens = [ 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' ];
|
||||
|
||||
export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
@ -52,10 +99,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
private pokemonUncaughtText: Phaser.GameObjects.Text;
|
||||
private pokemonAbilityLabelText: Phaser.GameObjects.Text;
|
||||
private pokemonAbilityText: Phaser.GameObjects.Text;
|
||||
private pokemonPassiveLabelText: Phaser.GameObjects.Text;
|
||||
private pokemonPassiveText: Phaser.GameObjects.Text;
|
||||
private pokemonNatureLabelText: Phaser.GameObjects.Text;
|
||||
private pokemonNatureText: BBCodeText;
|
||||
private pokemonCaughtCountLabelText: Phaser.GameObjects.Text;
|
||||
private pokemonCaughtCountText: Phaser.GameObjects.Text;
|
||||
private pokemonMovesContainer: Phaser.GameObjects.Container;
|
||||
private pokemonMoveContainers: Phaser.GameObjects.Container[];
|
||||
private pokemonMoveBgs: Phaser.GameObjects.NineSlice[];
|
||||
|
@ -65,6 +112,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
private pokemonEggMoveContainers: Phaser.GameObjects.Container[];
|
||||
private pokemonEggMoveBgs: Phaser.GameObjects.NineSlice[];
|
||||
private pokemonEggMoveLabels: Phaser.GameObjects.Text[];
|
||||
private pokemonCandyIcon: Phaser.GameObjects.Sprite;
|
||||
private pokemonCandyOverlayIcon: Phaser.GameObjects.Sprite;
|
||||
private pokemonCandyCountText: Phaser.GameObjects.Text;
|
||||
private pokemonCaughtHatchedContainer: Phaser.GameObjects.Container;
|
||||
private pokemonCaughtCountText: Phaser.GameObjects.Text;
|
||||
private pokemonHatchedCountText: Phaser.GameObjects.Text;
|
||||
private genOptionsText: Phaser.GameObjects.Text;
|
||||
private instructionsText: Phaser.GameObjects.Text;
|
||||
private starterSelectMessageBox: Phaser.GameObjects.NineSlice;
|
||||
|
@ -179,41 +232,77 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.type2Icon.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.type2Icon);
|
||||
|
||||
this.pokemonCandyIcon = this.scene.add.sprite(1, 12, 'items', 'candy');
|
||||
this.pokemonCandyIcon.setScale(0.5);
|
||||
this.pokemonCandyIcon.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonCandyIcon);
|
||||
|
||||
this.pokemonCandyOverlayIcon = this.scene.add.sprite(1, 12, 'items', 'candy_overlay');
|
||||
this.pokemonCandyOverlayIcon.setScale(0.5);
|
||||
this.pokemonCandyOverlayIcon.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonCandyOverlayIcon);
|
||||
|
||||
this.pokemonCandyCountText = addTextObject(this.scene, 14, 18, 'x0', TextStyle.WINDOW_ALT, { fontSize: '56px' });
|
||||
this.pokemonCandyCountText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonCandyCountText);
|
||||
|
||||
this.pokemonCaughtHatchedContainer = this.scene.add.container(2, 25);
|
||||
this.pokemonCaughtHatchedContainer.setScale(0.5);
|
||||
this.starterSelectContainer.add(this.pokemonCaughtHatchedContainer);
|
||||
|
||||
const pokemonCaughtIcon = this.scene.add.sprite(1, 0, 'items', 'pb');
|
||||
pokemonCaughtIcon.setOrigin(0, 0);
|
||||
pokemonCaughtIcon.setScale(0.75);
|
||||
this.pokemonCaughtHatchedContainer.add(pokemonCaughtIcon);
|
||||
|
||||
this.pokemonCaughtCountText = addTextObject(this.scene, 24, 4, '0', TextStyle.SUMMARY_ALT);
|
||||
this.pokemonCaughtCountText.setOrigin(0, 0);
|
||||
this.pokemonCaughtHatchedContainer.add(this.pokemonCaughtCountText);
|
||||
|
||||
const pokemonHatchedIcon = this.scene.add.sprite(1, 14, 'items', 'mystery_egg');
|
||||
pokemonHatchedIcon.setOrigin(0, 0);
|
||||
pokemonHatchedIcon.setScale(0.75);
|
||||
this.pokemonCaughtHatchedContainer.add(pokemonHatchedIcon);
|
||||
|
||||
this.pokemonHatchedCountText = addTextObject(this.scene, 24, 19, '0', TextStyle.SUMMARY_ALT);
|
||||
this.pokemonHatchedCountText.setOrigin(0, 0);
|
||||
this.pokemonCaughtHatchedContainer.add(this.pokemonHatchedCountText);
|
||||
|
||||
this.pokemonGenderText = addTextObject(this.scene, 96, 112, '', TextStyle.SUMMARY_ALT);
|
||||
this.pokemonGenderText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonGenderText);
|
||||
|
||||
this.pokemonUncaughtText = addTextObject(this.scene, 6, 126, 'Uncaught', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonUncaughtText = addTextObject(this.scene, 6, 127, 'Uncaught', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonUncaughtText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonUncaughtText);
|
||||
|
||||
this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 126, 'Ability:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 127, 'Ability:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonAbilityLabelText.setOrigin(0, 0);
|
||||
this.pokemonAbilityLabelText.setVisible(false);
|
||||
this.starterSelectContainer.add(this.pokemonAbilityLabelText);
|
||||
|
||||
this.pokemonAbilityText = addTextObject(this.scene, 30, 126, '', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonAbilityText = addTextObject(this.scene, 31, 127, '', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonAbilityText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonAbilityText);
|
||||
|
||||
this.pokemonNatureLabelText = addTextObject(this.scene, 6, 135, 'Nature:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonPassiveLabelText = addTextObject(this.scene, 6, 136, 'Passive:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonPassiveLabelText.setOrigin(0, 0);
|
||||
this.pokemonPassiveLabelText.setVisible(false);
|
||||
this.starterSelectContainer.add(this.pokemonPassiveLabelText);
|
||||
|
||||
this.pokemonPassiveText = addTextObject(this.scene, 31, 136, '', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonPassiveText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonPassiveText);
|
||||
|
||||
this.pokemonNatureLabelText = addTextObject(this.scene, 6, 145, 'Nature:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonNatureLabelText.setOrigin(0, 0);
|
||||
this.pokemonNatureLabelText.setVisible(false);
|
||||
this.starterSelectContainer.add(this.pokemonNatureLabelText);
|
||||
|
||||
this.pokemonNatureText = addBBCodeTextObject(this.scene, 30, 135, '', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonNatureText = addBBCodeTextObject(this.scene, 31, 145, '', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonNatureText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonNatureText);
|
||||
|
||||
this.pokemonCaughtCountLabelText = addTextObject(this.scene, 6, 144, 'Caught/Hatched:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonCaughtCountLabelText.setOrigin(0, 0);
|
||||
this.pokemonCaughtCountLabelText.setVisible(false);
|
||||
this.starterSelectContainer.add(this.pokemonCaughtCountLabelText);
|
||||
|
||||
this.pokemonCaughtCountText = addTextObject(this.scene, 58, 144, '0/0 (0)', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
|
||||
this.pokemonCaughtCountText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonCaughtCountText);
|
||||
|
||||
this.pokemonMoveContainers = [];
|
||||
this.pokemonMoveBgs = [];
|
||||
this.pokemonMoveLabels = [];
|
||||
|
@ -373,7 +462,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.pokemonEggMovesContainer = this.scene.add.container(102, 85);
|
||||
this.pokemonEggMovesContainer.setScale(0.375);
|
||||
|
||||
const eggMovesLabel = addTextObject(this.scene, -46, 0, 'Egg Moves', TextStyle.SUMMARY_ALT);
|
||||
const eggMovesLabel = addTextObject(this.scene, -46, 0, 'Egg Moves', TextStyle.WINDOW_ALT);
|
||||
eggMovesLabel.setOrigin(0.5, 0);
|
||||
|
||||
this.pokemonEggMovesContainer.add(eggMovesLabel);
|
||||
|
@ -622,6 +711,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
ui.playSelect();
|
||||
} else
|
||||
ui.playError();
|
||||
return true;
|
||||
},
|
||||
overrideSound: true
|
||||
},
|
||||
|
@ -630,6 +720,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
handler: () => {
|
||||
this.toggleStatsMode();
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -639,7 +730,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
ui.showText('Select a move to swap out.', null, () => {
|
||||
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||
options: moveset.map((m: Moves, i: number) => {
|
||||
return {
|
||||
const option: OptionSelectItem = {
|
||||
label: allMoves[m].name,
|
||||
handler: () => {
|
||||
ui.setMode(Mode.STARTER_SELECT).then(() => {
|
||||
|
@ -647,29 +738,37 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||
options: this.speciesStarterMoves.filter((sm: Moves) => sm !== m).map(sm => {
|
||||
// make an option for each available starter move
|
||||
return {
|
||||
const option = {
|
||||
label: allMoves[sm].name,
|
||||
handler: () => {
|
||||
this.switchMoveHandler(i, sm, m)
|
||||
showSwapOptions(this.starterMoveset);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return option;
|
||||
}).concat({
|
||||
label: 'Cancel',
|
||||
handler: () => showSwapOptions(this.starterMoveset)
|
||||
handler: () => {
|
||||
showSwapOptions(this.starterMoveset);
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
maxOptions: 8,
|
||||
yOffset: 19
|
||||
});
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
return option;
|
||||
}).concat({
|
||||
label: 'Cancel',
|
||||
handler: () => {
|
||||
this.clearText();
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
maxOptions: 8,
|
||||
|
@ -682,6 +781,103 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
label: 'Manage Moves',
|
||||
handler: () => {
|
||||
showSwapOptions(this.starterMoveset);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
const starterData = this.scene.gameData.starterData[this.lastSpecies.speciesId];
|
||||
const candyCount = starterData.candyCount;
|
||||
const passiveAttr = starterData.passiveAttr;
|
||||
if (passiveAttr & PassiveAttr.UNLOCKED) {
|
||||
if (!(passiveAttr & PassiveAttr.ENABLED)) {
|
||||
options.push({
|
||||
label: 'Enable Passive',
|
||||
handler: () => {
|
||||
starterData.passiveAttr |= PassiveAttr.ENABLED;
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
options.push({
|
||||
label: 'Disable Passive',
|
||||
handler: () => {
|
||||
starterData.passiveAttr ^= PassiveAttr.ENABLED;
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
const showUseCandies = () => {
|
||||
const options = [];
|
||||
if (!(passiveAttr & PassiveAttr.UNLOCKED)) {
|
||||
const passiveCost = getPassiveCandyCount(speciesStarters[this.lastSpecies.speciesId]);
|
||||
options.push({
|
||||
label: `x${passiveCost} Unlock Passive (${allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name})`,
|
||||
handler: () => {
|
||||
if (candyCount >= passiveCost) {
|
||||
starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED;
|
||||
starterData.candyCount -= passiveCost;
|
||||
this.pokemonCandyCountText.setText(`x${starterData.candyCount}`);
|
||||
this.scene.gameData.saveSystem().then(success => {
|
||||
if (!success)
|
||||
return this.scene.reset(true);
|
||||
});
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
item: 'candy',
|
||||
itemArgs: starterColors[this.lastSpecies.speciesId]
|
||||
});
|
||||
}
|
||||
const valueReduction = starterData.valueReduction;
|
||||
if (valueReduction < 2) {
|
||||
const reductionCost = getValueReductionCandyCounts(speciesStarters[this.lastSpecies.speciesId])[valueReduction];
|
||||
options.push({
|
||||
label: `x${reductionCost} Reduce Cost`,
|
||||
handler: () => {
|
||||
if (candyCount >= reductionCost) {
|
||||
starterData.valueReduction++;
|
||||
starterData.candyCount -= reductionCost;
|
||||
this.pokemonCandyCountText.setText(`x${starterData.candyCount}`);
|
||||
this.scene.gameData.saveSystem().then(success => {
|
||||
if (!success)
|
||||
return this.scene.reset(true);
|
||||
});
|
||||
this.updateStarterValueLabel(this.cursor);
|
||||
this.tryUpdateValue(0);
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
this.scene.playSound('buy');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
item: 'candy',
|
||||
itemArgs: starterColors[this.lastSpecies.speciesId]
|
||||
});
|
||||
}
|
||||
options.push({
|
||||
label: 'Cancel',
|
||||
handler: () => {
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||
options: options,
|
||||
yOffset: 47
|
||||
});
|
||||
};
|
||||
options.push({
|
||||
label: 'Use Candies',
|
||||
handler: () => {
|
||||
ui.setMode(Mode.STARTER_SELECT).then(() => showUseCandies());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -689,6 +885,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
label: 'Cancel',
|
||||
handler: () => {
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||
|
@ -809,22 +1006,22 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
// species has different forms
|
||||
if (pokemonFormLevelMoves.hasOwnProperty(speciesId)) {
|
||||
// starterMoveData doesn't have base form moves or is using the single form format
|
||||
if (!this.scene.gameData.starterMoveData.hasOwnProperty(speciesId) || Array.isArray(this.scene.gameData.starterMoveData[speciesId]))
|
||||
this.scene.gameData.starterMoveData[speciesId] = { [props.formIndex]: this.starterMoveset.slice(0) as StarterMoveset };
|
||||
const starterMoveData = this.scene.gameData.starterMoveData[speciesId][props.formIndex];
|
||||
if (!this.scene.gameData.starterData[speciesId].moveset || Array.isArray(this.scene.gameData.starterData[speciesId].moveset))
|
||||
this.scene.gameData.starterData[speciesId].moveset = { [props.formIndex]: this.starterMoveset.slice(0) as StarterMoveset };
|
||||
const starterMoveData = this.scene.gameData.starterData[speciesId].moveset[props.formIndex];
|
||||
|
||||
// starterMoveData doesn't have active form moves
|
||||
if (!starterMoveData.hasOwnProperty(props.formIndex))
|
||||
this.scene.gameData.starterMoveData[speciesId][props.formIndex] = this.starterMoveset.slice(0) as StarterMoveset;
|
||||
this.scene.gameData.starterData[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
|
||||
if (starterMoveData.hasOwnProperty(props.formIndex)) {
|
||||
// active form move hasn't been updated
|
||||
if (starterMoveData[props.formIndex][existingMoveIndex] !== newMove)
|
||||
this.scene.gameData.starterMoveData[speciesId][props.formIndex] = this.starterMoveset.slice(0) as StarterMoveset;
|
||||
this.scene.gameData.starterData[speciesId].moveset[props.formIndex] = this.starterMoveset.slice(0) as StarterMoveset;
|
||||
}
|
||||
} else
|
||||
this.scene.gameData.starterMoveData[speciesId] = this.starterMoveset.slice(0) as StarterMoveset;
|
||||
this.scene.gameData.starterData[speciesId].moveset = this.starterMoveset.slice(0) as StarterMoveset;
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, false);
|
||||
}
|
||||
|
||||
|
@ -902,29 +1099,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
for (let s = 0; s < 81; s++) {
|
||||
const speciesId = s < genLimit ? this.genSpecies[genCursorWithScroll][s].speciesId : 0 as Species;
|
||||
const slotVisible = !!speciesId;
|
||||
if (slotVisible) {
|
||||
const baseStarterValue = speciesStarters[speciesId];
|
||||
const starterValue = slotVisible ? this.scene.gameData.getSpeciesStarterValue(speciesId) : 0;
|
||||
let valueStr = starterValue.toString();
|
||||
if (valueStr.startsWith('0.'))
|
||||
valueStr = valueStr.slice(1);
|
||||
this.starterValueLabels[s].setText(valueStr);
|
||||
let textStyle: TextStyle;
|
||||
switch (baseStarterValue - starterValue) {
|
||||
case 0:
|
||||
textStyle = TextStyle.WINDOW;
|
||||
break;
|
||||
case 1:
|
||||
case 0.5:
|
||||
textStyle = TextStyle.SUMMARY_BLUE;
|
||||
break;
|
||||
default:
|
||||
textStyle = TextStyle.SUMMARY_GOLD;
|
||||
break;
|
||||
}
|
||||
this.starterValueLabels[s].setColor(this.getTextColor(textStyle));
|
||||
this.starterValueLabels[s].setShadowColor(this.getTextColor(textStyle, true));
|
||||
}
|
||||
if (slotVisible)
|
||||
this.updateStarterValueLabel(s);
|
||||
this.starterValueLabels[s].setVisible(slotVisible);
|
||||
this.shinyIcons[s].setVisible(slotVisible && !!this.scene.gameData.dexData[speciesId].caughtAttr && !!(this.scene.gameData.dexData[speciesId].caughtAttr & DexAttr.SHINY));
|
||||
}
|
||||
|
@ -1007,16 +1183,25 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.pokemonNameText.setText(species.name);
|
||||
|
||||
if (this.speciesStarterDexEntry?.caughtAttr) {
|
||||
const colorScheme = starterColors[species.speciesId];
|
||||
|
||||
this.pokemonGrowthRateText.setText(Utils.toReadableString(GrowthRate[species.growthRate]));
|
||||
this.pokemonGrowthRateText.setColor(getGrowthRateColor(species.growthRate));
|
||||
this.pokemonGrowthRateText.setShadowColor(getGrowthRateColor(species.growthRate, true));
|
||||
this.pokemonGrowthRateLabelText.setVisible(true);
|
||||
this.pokemonUncaughtText.setVisible(false);
|
||||
this.pokemonAbilityLabelText.setVisible(true);
|
||||
this.pokemonPassiveLabelText.setVisible(true);
|
||||
this.pokemonNatureLabelText.setVisible(true);
|
||||
this.pokemonCaughtCountLabelText.setVisible(true);
|
||||
this.pokemonCaughtCountText.setText(`${this.speciesStarterDexEntry.caughtCount}/${this.speciesStarterDexEntry.hatchedCount} (${this.speciesStarterDexEntry.caughtCount + this.speciesStarterDexEntry.hatchedCount})`);
|
||||
this.pokemonCaughtCountText.setVisible(true);
|
||||
this.pokemonCaughtCountText.setText(`${this.speciesStarterDexEntry.caughtCount}`);
|
||||
this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry.hatchedCount}`);
|
||||
this.pokemonCaughtHatchedContainer.setVisible(true);
|
||||
this.pokemonCandyIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[0])));
|
||||
this.pokemonCandyIcon.setVisible(true);
|
||||
this.pokemonCandyOverlayIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[1])));
|
||||
this.pokemonCandyOverlayIcon.setVisible(true);
|
||||
this.pokemonCandyCountText.setText(`x${this.scene.gameData.starterData[species.speciesId].candyCount}`);
|
||||
this.pokemonCandyCountText.setVisible(true);
|
||||
this.iconAnimHandler.addOrUpdate(this.starterSelectGenIconContainers[species.generation - 1].getAt(this.genSpecies[species.generation - 1].indexOf(species)) as Phaser.GameObjects.Sprite, PokemonIconAnimMode.PASSIVE);
|
||||
|
||||
let starterIndex = -1;
|
||||
|
@ -1056,9 +1241,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.type2Icon.setVisible(false);
|
||||
this.pokemonUncaughtText.setVisible(true);
|
||||
this.pokemonAbilityLabelText.setVisible(false);
|
||||
this.pokemonPassiveLabelText.setVisible(false);
|
||||
this.pokemonNatureLabelText.setVisible(false);
|
||||
this.pokemonCaughtCountLabelText.setVisible(false);
|
||||
this.pokemonCaughtCountText.setVisible(false);
|
||||
this.pokemonCaughtHatchedContainer.setVisible(false);
|
||||
this.pokemonCandyIcon.setVisible(false);
|
||||
this.pokemonCandyOverlayIcon.setVisible(false);
|
||||
this.pokemonCandyCountText.setVisible(false);
|
||||
|
||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, true);
|
||||
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
|
||||
|
@ -1076,9 +1264,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.type2Icon.setVisible(false);
|
||||
this.pokemonUncaughtText.setVisible(!!species);
|
||||
this.pokemonAbilityLabelText.setVisible(false);
|
||||
this.pokemonPassiveLabelText.setVisible(false);
|
||||
this.pokemonNatureLabelText.setVisible(false);
|
||||
this.pokemonCaughtCountLabelText.setVisible(false);
|
||||
this.pokemonCaughtCountText.setVisible(false);
|
||||
this.pokemonCaughtHatchedContainer.setVisible(false);
|
||||
this.pokemonCandyIcon.setVisible(false);
|
||||
this.pokemonCandyOverlayIcon.setVisible(false);
|
||||
this.pokemonCandyCountText.setVisible(false);
|
||||
|
||||
this.setSpeciesDetails(species, false, 0, false, 0, 0);
|
||||
this.pokemonSprite.clearTint();
|
||||
|
@ -1185,6 +1376,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
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));
|
||||
|
||||
const passiveAttr = this.scene.gameData.starterData[species.speciesId].passiveAttr;
|
||||
this.pokemonPassiveText.setText(passiveAttr & PassiveAttr.UNLOCKED ? passiveAttr & PassiveAttr.ENABLED ? allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name : 'Disabled' : 'Locked');
|
||||
this.pokemonPassiveText.setColor(this.getTextColor(passiveAttr === (PassiveAttr.UNLOCKED | PassiveAttr.ENABLED) ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GRAY));
|
||||
this.pokemonPassiveText.setShadowColor(this.getTextColor(passiveAttr === (PassiveAttr.UNLOCKED | PassiveAttr.ENABLED) ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GRAY, true));
|
||||
|
||||
this.pokemonNatureText.setText(getNatureName(natureIndex as unknown as Nature, true, true, false, this.scene.uiTheme));
|
||||
|
||||
let levelMoves: LevelMoves;
|
||||
|
@ -1195,18 +1391,18 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.speciesStarterMoves.push(...levelMoves.filter(lm => lm[0] <= 5).map(lm => lm[1]));
|
||||
if (speciesEggMoves.hasOwnProperty(species.speciesId)) {
|
||||
for (let em = 0; em < 4; em++) {
|
||||
if (this.scene.gameData.starterEggMoveData[species.speciesId] & Math.pow(2, em))
|
||||
if (this.scene.gameData.starterData[species.speciesId].eggMoves & Math.pow(2, em))
|
||||
this.speciesStarterMoves.push(speciesEggMoves[species.speciesId][em]);
|
||||
}
|
||||
}
|
||||
|
||||
const speciesMoveData = this.scene.gameData.starterMoveData[species.speciesId];
|
||||
const speciesMoveData = this.scene.gameData.starterData[species.speciesId].moveset;
|
||||
let moveData: StarterMoveset = speciesMoveData
|
||||
? Array.isArray(speciesMoveData)
|
||||
? speciesMoveData as StarterMoveset
|
||||
: (speciesMoveData as StarterFormMoveData)[formIndex]
|
||||
: null;
|
||||
const availableStarterMoves = this.speciesStarterMoves.concat(speciesEggMoves.hasOwnProperty(species.speciesId) ? speciesEggMoves[species.speciesId].filter((_, em: integer) => this.scene.gameData.starterEggMoveData[species.speciesId] & Math.pow(2, em)) : []);
|
||||
const availableStarterMoves = this.speciesStarterMoves.concat(speciesEggMoves.hasOwnProperty(species.speciesId) ? speciesEggMoves[species.speciesId].filter((_, em: integer) => this.scene.gameData.starterData[species.speciesId].eggMoves & Math.pow(2, em)) : []);
|
||||
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
|
||||
if (this.starterMoveset.length < 4 && this.starterMoveset.length < availableStarterMoves.length)
|
||||
|
@ -1216,6 +1412,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.setTypeIcons(speciesForm.type1, speciesForm.type2);
|
||||
} else {
|
||||
this.pokemonAbilityText.setText('');
|
||||
this.pokemonPassiveText.setText('');
|
||||
this.pokemonNatureText.setText('');
|
||||
this.setTypeIcons(null, null);
|
||||
}
|
||||
|
@ -1225,6 +1422,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.pokemonNumberText.setShadowColor(this.getTextColor(TextStyle.SUMMARY, true));
|
||||
this.pokemonGenderText.setText('');
|
||||
this.pokemonAbilityText.setText('');
|
||||
this.pokemonPassiveText.setText('');
|
||||
this.pokemonNatureText.setText('');
|
||||
this.setTypeIcons(null, null);
|
||||
}
|
||||
|
@ -1243,7 +1441,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
|
||||
for (let em = 0; em < 4; em++) {
|
||||
const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null;
|
||||
const eggMoveUnlocked = eggMove && this.scene.gameData.starterEggMoveData.hasOwnProperty(species.speciesId) && this.scene.gameData.starterEggMoveData[species.speciesId] & Math.pow(2, em);
|
||||
const eggMoveUnlocked = eggMove && this.scene.gameData.starterData[species.speciesId].eggMoves & Math.pow(2, em);
|
||||
this.pokemonEggMoveBgs[em].setFrame(Type[eggMove ? eggMove.type : Type.UNKNOWN].toString().toLowerCase());
|
||||
this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : '???');
|
||||
}
|
||||
|
@ -1281,6 +1479,31 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.tryUpdateValue();
|
||||
}
|
||||
|
||||
updateStarterValueLabel(cursor: integer): void {
|
||||
const speciesId = this.genSpecies[this.genCursor][cursor].speciesId;
|
||||
const baseStarterValue = speciesStarters[speciesId];
|
||||
const starterValue = this.scene.gameData.getSpeciesStarterValue(speciesId);
|
||||
let valueStr = starterValue.toString();
|
||||
if (valueStr.startsWith('0.'))
|
||||
valueStr = valueStr.slice(1);
|
||||
this.starterValueLabels[cursor].setText(valueStr);
|
||||
let textStyle: TextStyle;
|
||||
switch (baseStarterValue - starterValue) {
|
||||
case 0:
|
||||
textStyle = TextStyle.WINDOW;
|
||||
break;
|
||||
case 1:
|
||||
case 0.5:
|
||||
textStyle = TextStyle.SUMMARY_BLUE;
|
||||
break;
|
||||
default:
|
||||
textStyle = TextStyle.SUMMARY_GOLD;
|
||||
break;
|
||||
}
|
||||
this.starterValueLabels[cursor].setColor(this.getTextColor(textStyle));
|
||||
this.starterValueLabels[cursor].setShadowColor(this.getTextColor(textStyle, true));
|
||||
}
|
||||
|
||||
tryUpdateValue(add?: integer): boolean {
|
||||
const value = this.starterGens.reduce((total: integer, gen: integer, i: integer) => total += this.scene.gameData.getSpeciesStarterValue(this.genSpecies[gen][this.starterCursors[i]].speciesId), 0);
|
||||
const newValue = value + (add || 0);
|
||||
|
@ -1331,6 +1554,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
return {
|
||||
species: starterSpecies,
|
||||
dexAttr: thisObj.starterAttr[i],
|
||||
passive: !(thisObj.scene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^ (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)),
|
||||
variant: 0,
|
||||
nature: thisObj.starterNatures[i] as Nature,
|
||||
moveset: thisObj.starterMovesets[i],
|
||||
pokerus: !![ 0, 1, 2 ].filter(n => thisObj.pokerusGens[n] === starterSpecies.generation - 1 && thisObj.pokerusCursors[n] === thisObj.genSpecies[starterSpecies.generation - 1].indexOf(starterSpecies)).length
|
||||
|
|
|
@ -18,6 +18,7 @@ export enum TextStyle {
|
|||
SUMMARY_BLUE,
|
||||
SUMMARY_PINK,
|
||||
SUMMARY_GOLD,
|
||||
SUMMARY_GRAY,
|
||||
MONEY,
|
||||
SETTINGS_LABEL,
|
||||
SETTINGS_SELECTED,
|
||||
|
@ -75,10 +76,14 @@ function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptio
|
|||
|
||||
switch (style) {
|
||||
case TextStyle.SUMMARY:
|
||||
case TextStyle.SUMMARY_ALT:
|
||||
case TextStyle.SUMMARY_BLUE:
|
||||
case TextStyle.SUMMARY_RED:
|
||||
case TextStyle.SUMMARY_PINK:
|
||||
case TextStyle.SUMMARY_GOLD:
|
||||
case TextStyle.SUMMARY_GRAY:
|
||||
case TextStyle.WINDOW:
|
||||
case TextStyle.WINDOW_ALT:
|
||||
case TextStyle.MESSAGE:
|
||||
case TextStyle.SETTINGS_LABEL:
|
||||
case TextStyle.SETTINGS_SELECTED:
|
||||
|
@ -152,7 +157,9 @@ export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: Ui
|
|||
return !shadow ? '#f89890' : '#984038';
|
||||
case TextStyle.SUMMARY_GOLD:
|
||||
case TextStyle.MONEY:
|
||||
return !shadow ? '#e8e8a8' : '#a0a060'
|
||||
return !shadow ? '#e8e8a8' : '#a0a060';
|
||||
case TextStyle.SUMMARY_GRAY:
|
||||
return !shadow ? '#a0a0a0' : '#636363';
|
||||
case TextStyle.SETTINGS_LABEL:
|
||||
return !shadow ? '#f8b050' : '#c07800';
|
||||
case TextStyle.SETTINGS_SELECTED:
|
||||
|
|
10
src/utils.ts
10
src/utils.ts
|
@ -312,3 +312,13 @@ export function deltaRgb(rgb1: integer[], rgb2: integer[]): integer {
|
|||
|
||||
return Math.ceil(Math.sqrt(2 * drp2 + 4 * dgp2 + 3 * dbp2 + t * (drp2 - dbp2) / 256));
|
||||
}
|
||||
|
||||
export function rgbHexToRgba(hex: string) {
|
||||
const color = hex.match(/^([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);
|
||||
return {
|
||||
r: parseInt(color[1], 16),
|
||||
g: parseInt(color[2], 16),
|
||||
b: parseInt(color[3], 16),
|
||||
a: 255
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue