Add tiered shiny variants
This commit is contained in:
1 parent
a6ddda38ae
commit
c76f8c5e7e
690 files changed
+94645
-199
No files matched your search
+42
-28
@@ -57,6 +57,7 @@ import { initTouchControls } from './touch-controls';
|
||||
import { UiTheme } from './enums/ui-theme';
|
||||
import { SceneBase } from './scene-base';
|
||||
import CandyBar from './ui/candy-bar';
|
||||
import { Variant, variantData } from './data/variant';
|
||||
|
||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||
|
||||
@@ -100,6 +101,7 @@ export enum Button {
|
||||
CYCLE_GENDER,
|
||||
CYCLE_ABILITY,
|
||||
CYCLE_NATURE,
|
||||
CYCLE_VARIANT,
|
||||
SPEED_UP,
|
||||
SLOW_DOWN
|
||||
}
|
||||
@@ -217,6 +219,7 @@ export default class BattleScene extends SceneBase {
|
||||
[Button.CYCLE_GENDER]: 6, // LT
|
||||
[Button.CYCLE_ABILITY]: 7, // RT
|
||||
[Button.CYCLE_NATURE]: 2, // square
|
||||
[Button.CYCLE_VARIANT]: 3, // triangle
|
||||
[Button.SPEED_UP]: 10, // L3
|
||||
[Button.SLOW_DOWN]: 11 // R3
|
||||
};
|
||||
@@ -242,24 +245,15 @@ export default class BattleScene extends SceneBase {
|
||||
loadPokemonAtlas(key: string, atlasPath: string, experimental?: boolean) {
|
||||
if (experimental === undefined)
|
||||
experimental = this.experimentalSprites;
|
||||
if (experimental) {
|
||||
const keyMatch = /^pkmn__(back__)?(shiny__)?(female__)?(\d+)(\-.*?)?$/g.exec(key);
|
||||
let k = keyMatch[4];
|
||||
if (keyMatch[2])
|
||||
k += 's';
|
||||
if (keyMatch[1])
|
||||
k += 'b';
|
||||
if (keyMatch[3])
|
||||
k += 'f';
|
||||
if (keyMatch[5])
|
||||
k += keyMatch[5];
|
||||
if (!expSpriteKeys.includes(k))
|
||||
experimental = false;
|
||||
}
|
||||
this.load.atlas(key, `images/pokemon/${experimental ? 'exp/' : ''}${atlasPath}.png`, `images/pokemon/${experimental ? 'exp/' : ''}${atlasPath}.json`);
|
||||
let variant = atlasPath.includes('variant/');
|
||||
if (experimental)
|
||||
experimental = this.hasExpSprite(key);
|
||||
if (variant)
|
||||
atlasPath = atlasPath.replace('variant/', '');
|
||||
this.load.atlas(key, `images/pokemon/${variant ? 'variant/' : ''}${experimental ? 'exp/' : ''}${atlasPath}.png`, `images/pokemon/${variant ? 'variant/' : ''}${experimental ? 'exp/' : ''}${atlasPath}.json`);
|
||||
}
|
||||
|
||||
preload() {
|
||||
async preload() {
|
||||
if (DEBUG_RNG) {
|
||||
const scene = this;
|
||||
const originalRealInRange = Phaser.Math.RND.realInRange;
|
||||
@@ -275,6 +269,8 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
populateAnims();
|
||||
|
||||
await fetch('./images/pokemon/variant/_masterlist.json').then(res => res.json()).then(v => Object.keys(v).forEach(k => variantData[k] = v[k]));
|
||||
}
|
||||
|
||||
create() {
|
||||
@@ -505,15 +501,13 @@ export default class BattleScene extends SceneBase {
|
||||
this.updateScoreText();
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
async initExpSprites(): Promise<void> {
|
||||
if (expSpriteKeys.length)
|
||||
return;
|
||||
fetch('./exp-sprites.json').then(res => res.json()).then(keys => {
|
||||
if (Array.isArray(keys))
|
||||
expSpriteKeys.push(...keys);
|
||||
Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -555,6 +549,22 @@ export default class BattleScene extends SceneBase {
|
||||
});
|
||||
}
|
||||
|
||||
hasExpSprite(key: string): boolean {
|
||||
const keyMatch = /^pkmn__?(back__)?(shiny__)?(female__)?(\d+)(\-.*?)?(?:_[1-3])?$/g.exec(key);
|
||||
let k = keyMatch[4];
|
||||
if (keyMatch[2])
|
||||
k += 's';
|
||||
if (keyMatch[1])
|
||||
k += 'b';
|
||||
if (keyMatch[3])
|
||||
k += 'f';
|
||||
if (keyMatch[5])
|
||||
k += keyMatch[5];
|
||||
if (!expSpriteKeys.includes(k))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
setupControls() {
|
||||
const keyCodes = Phaser.Input.Keyboard.KeyCodes;
|
||||
const keyConfig = {
|
||||
@@ -571,6 +581,7 @@ export default class BattleScene extends SceneBase {
|
||||
[Button.CYCLE_GENDER]: [keyCodes.G],
|
||||
[Button.CYCLE_ABILITY]: [keyCodes.E],
|
||||
[Button.CYCLE_NATURE]: [keyCodes.N],
|
||||
[Button.CYCLE_VARIANT]: [keyCodes.V],
|
||||
[Button.SPEED_UP]: [keyCodes.PLUS],
|
||||
[Button.SLOW_DOWN]: [keyCodes.MINUS]
|
||||
};
|
||||
@@ -631,8 +642,8 @@ export default class BattleScene extends SceneBase {
|
||||
return findInParty(this.getParty()) || findInParty(this.getEnemyParty());
|
||||
}
|
||||
|
||||
addPlayerPokemon(species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender?: Gender, shiny?: boolean, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData, postProcess?: (playerPokemon: PlayerPokemon) => void): PlayerPokemon {
|
||||
const pokemon = new PlayerPokemon(this, species, level, abilityIndex, formIndex, gender, shiny, ivs, nature, dataSource);
|
||||
addPlayerPokemon(species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData, postProcess?: (playerPokemon: PlayerPokemon) => void): PlayerPokemon {
|
||||
const pokemon = new PlayerPokemon(this, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource);
|
||||
if (postProcess)
|
||||
postProcess(pokemon);
|
||||
pokemon.init();
|
||||
@@ -1285,6 +1296,9 @@ export default class BattleScene extends SceneBase {
|
||||
} else if (this.buttonJustPressed(Button.CYCLE_NATURE)) {
|
||||
inputSuccess = this.ui.processInput(Button.CYCLE_NATURE);
|
||||
this.setLastProcessedMovementTime(Button.CYCLE_NATURE);
|
||||
} else if (this.buttonJustPressed(Button.CYCLE_VARIANT)) {
|
||||
inputSuccess = this.ui.processInput(Button.CYCLE_VARIANT);
|
||||
this.setLastProcessedMovementTime(Button.CYCLE_VARIANT);
|
||||
} else
|
||||
return;
|
||||
} else if (this.buttonJustPressed(Button.SPEED_UP)) {
|
||||
@@ -1998,4 +2012,4 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -797,7 +797,9 @@ export abstract class BattleAnim {
|
||||
let sprite: Phaser.GameObjects.Sprite;
|
||||
sprite = scene.addPokemonSprite(isUser ? user : target, 0, 0, spriteSource.texture, spriteSource.frame.name, true);
|
||||
[ 'spriteColors', 'fusionSpriteColors' ].map(k => sprite.pipelineData[k] = (isUser ? user : target).getSprite().pipelineData[k]);
|
||||
sprite.pipelineData['ignoreFieldPos'] = true;
|
||||
sprite.setPipelineData('spriteKey', (isUser ? user : target).getSpriteKey());
|
||||
sprite.setPipelineData('variant', (isUser ? user : target).variant);
|
||||
sprite.setPipelineData('ignoreFieldPos', true);
|
||||
spriteSource.on('animationupdate', (_anim, frame) => sprite.setFrame(frame.textureFrame));
|
||||
scene.field.add(sprite);
|
||||
sprites.push(sprite);
|
||||
|
||||
@@ -60,12 +60,12 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
|
||||
function getDailyRunStarter(scene: BattleScene, starterSpeciesForm: PokemonSpeciesForm, startingLevel: integer): Starter {
|
||||
const starterSpecies = starterSpeciesForm instanceof PokemonSpecies ? starterSpeciesForm : getPokemonSpecies(starterSpeciesForm.speciesId);
|
||||
const formIndex = starterSpeciesForm instanceof PokemonSpecies ? undefined : starterSpeciesForm.formIndex;
|
||||
const pokemon = new PlayerPokemon(scene, starterSpecies, startingLevel, undefined, formIndex, undefined, undefined, undefined, undefined, undefined);
|
||||
const pokemon = new PlayerPokemon(scene, starterSpecies, startingLevel, undefined, formIndex, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
const starter: Starter = {
|
||||
species: starterSpecies,
|
||||
dexAttr: pokemon.getDexAttr(),
|
||||
abilityIndex: pokemon.abilityIndex,
|
||||
passive: false,
|
||||
variant: 0,
|
||||
nature: pokemon.getNature(),
|
||||
pokerus: pokemon.pokerus
|
||||
};
|
||||
|
||||
+55
-15
@@ -1,5 +1,7 @@
|
||||
import { Abilities } from "./enums/abilities";
|
||||
import BattleScene, { AnySound } from '../battle-scene';
|
||||
import { Variant, variantColorCache } from './variant';
|
||||
import { variantData } from './variant';
|
||||
import { GrowthRate } from './exp';
|
||||
import { SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from './pokemon-evolutions';
|
||||
import { Species } from './enums/species';
|
||||
@@ -12,6 +14,7 @@ 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";
|
||||
import { VariantSet } from './variant';
|
||||
|
||||
export enum Region {
|
||||
NORMAL,
|
||||
@@ -203,36 +206,48 @@ export abstract class PokemonSpeciesForm {
|
||||
return ret;
|
||||
}
|
||||
|
||||
getSpriteAtlasPath(female: boolean, formIndex?: integer, shiny?: boolean): string {
|
||||
return this.getSpriteId(female, formIndex, shiny).replace(/\_{2}/g, '/');
|
||||
getSpriteAtlasPath(female: boolean, formIndex?: integer, shiny?: boolean, variant?: integer): string {
|
||||
const spriteId = this.getSpriteId(female, formIndex, shiny, variant).replace(/\_{2}/g, '/');
|
||||
return `${/_[1-3]$/.test(spriteId) ? 'variant/' : ''}${spriteId}`;
|
||||
}
|
||||
|
||||
getSpriteId(female: boolean, formIndex?: integer, shiny?: boolean): string {
|
||||
getSpriteId(female: boolean, formIndex?: integer, shiny?: boolean, variant?: integer): string {
|
||||
if (formIndex === undefined || this instanceof PokemonForm)
|
||||
formIndex = this.formIndex;
|
||||
|
||||
const formSpriteKey = this.getFormSpriteKey(formIndex);
|
||||
const showGenderDiffs = this.genderDiffs && female && ![ SpeciesFormKey.MEGA, SpeciesFormKey.GIGANTAMAX ].find(k => formSpriteKey === k);
|
||||
return `${shiny ? 'shiny__' : ''}${showGenderDiffs ? 'female__' : ''}${this.speciesId}${formSpriteKey ? `-${formSpriteKey}` : ''}`;
|
||||
|
||||
const baseSpriteKey = `${showGenderDiffs ? 'female__' : ''}${this.speciesId}${formSpriteKey ? `-${formSpriteKey}` : ''}`;
|
||||
|
||||
let variantSet: VariantSet;
|
||||
let config = variantData;
|
||||
baseSpriteKey.split('__').map(p => config = variantData[p]);
|
||||
variantSet = config as VariantSet;
|
||||
|
||||
return `${shiny && (!variantSet || (!variant && !variantSet[variant || 0])) ? 'shiny__' : ''}${baseSpriteKey}${shiny && variantSet && variantSet[variant || 0] === 2 ? `_${variant + 1}` : ''}`;
|
||||
}
|
||||
|
||||
getSpriteKey(female: boolean, formIndex?: integer, shiny?: boolean): string {
|
||||
return `pkmn__${this.getSpriteId(female, formIndex, shiny)}`;
|
||||
getSpriteKey(female: boolean, formIndex?: integer, shiny?: boolean, variant?: integer): string {
|
||||
return `pkmn__${this.getSpriteId(female, formIndex, shiny, variant)}`;
|
||||
}
|
||||
|
||||
abstract getFormSpriteKey(formIndex?: integer): string;
|
||||
|
||||
getIconAtlasKey(formIndex?: integer): string {
|
||||
return `pokemon_icons_${this.generation}`;
|
||||
getIconAtlasKey(formIndex?: integer, shiny?: boolean, variant?: integer): string {
|
||||
const isVariant = shiny && variantData[this.speciesId] && variantData[this.speciesId][variant];
|
||||
return `pokemon_icons_${this.generation}${isVariant ? 'v' : ''}`;
|
||||
}
|
||||
|
||||
getIconId(female: boolean, formIndex?: integer, shiny?: boolean): string {
|
||||
getIconId(female: boolean, formIndex?: integer, shiny?: boolean, variant?: integer): string {
|
||||
if (formIndex === undefined)
|
||||
formIndex = this.formIndex;
|
||||
|
||||
let ret = this.speciesId.toString();
|
||||
|
||||
if (shiny)
|
||||
const isVariant = shiny && variantData[this.speciesId] && variantData[this.speciesId][variant];
|
||||
|
||||
if (shiny && !isVariant)
|
||||
ret += 's';
|
||||
|
||||
switch (this.speciesId) {
|
||||
@@ -260,6 +275,9 @@ export abstract class PokemonSpeciesForm {
|
||||
}
|
||||
}
|
||||
|
||||
if (isVariant)
|
||||
ret += `_${variant + 1}`;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -345,23 +363,45 @@ export abstract class PokemonSpeciesForm {
|
||||
return true;
|
||||
}
|
||||
|
||||
loadAssets(scene: BattleScene, female: boolean, formIndex?: integer, shiny?: boolean, startLoad?: boolean): Promise<void> {
|
||||
loadAssets(scene: BattleScene, female: boolean, formIndex?: integer, shiny?: boolean, variant?: Variant, startLoad?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const spriteKey = this.getSpriteKey(female, formIndex, shiny);
|
||||
const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant);
|
||||
scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`);
|
||||
scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny));
|
||||
scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant));
|
||||
scene.load.once(Phaser.Loader.Events.COMPLETE, () => {
|
||||
const originalWarn = console.warn;
|
||||
// Ignore warnings for missing frames, because there will be a lot
|
||||
console.warn = () => {};
|
||||
const frameNames = scene.anims.generateFrameNames(this.getSpriteKey(female, formIndex, shiny), { zeroPad: 4, suffix: ".png", start: 1, end: 400 });
|
||||
const frameNames = scene.anims.generateFrameNames(spriteKey, { zeroPad: 4, suffix: ".png", start: 1, end: 400 });
|
||||
console.warn = originalWarn;
|
||||
scene.anims.create({
|
||||
key: this.getSpriteKey(female, formIndex, shiny),
|
||||
key: this.getSpriteKey(female, formIndex, shiny, variant),
|
||||
frames: frameNames,
|
||||
frameRate: 12,
|
||||
repeat: -1
|
||||
});
|
||||
let spritePath = this.getSpriteAtlasPath(female, formIndex, shiny, variant);
|
||||
const useExpSprite = scene.experimentalSprites && scene.hasExpSprite(spriteKey);
|
||||
if (useExpSprite)
|
||||
spritePath = `exp/${spritePath}`;
|
||||
let variantSet: VariantSet;
|
||||
let config = variantData;
|
||||
spritePath.split('/').map(p => config = variantData[p]);
|
||||
variantSet = config as VariantSet;
|
||||
if (variantSet && variantSet[variant] === 1) {
|
||||
const populateVariantColors = (key: string): Promise<void> => {
|
||||
return new Promise(resolve => {
|
||||
if (variantColorCache.hasOwnProperty(key))
|
||||
return resolve();
|
||||
fetch(`./images/pokemon/variant/${spritePath}.json`).then(res => res.json()).then(c => {
|
||||
variantColorCache[key] = c;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
populateVariantColors(spriteKey).then(() => resolve());
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
if (startLoad) {
|
||||
|
||||
@@ -846,6 +846,8 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 3);
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
p.shiny = true;
|
||||
p.variant = 1;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const starter = party[0];
|
||||
@@ -862,6 +864,8 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
p.shiny = true;
|
||||
p.variant = 1;
|
||||
p.formIndex = 1;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
export type Variant = 0 | 1 | 2;
|
||||
|
||||
export type VariantSet = [Variant, Variant, Variant];
|
||||
|
||||
export const variantData: any = {};
|
||||
|
||||
export const variantColorCache = {};
|
||||
|
||||
export function getVariantTint(variant: Variant): integer {
|
||||
switch (variant) {
|
||||
case 0:
|
||||
return 0xf8c020;
|
||||
case 1:
|
||||
return 0x20f8f0;
|
||||
case 2:
|
||||
return 0xe81048;
|
||||
}
|
||||
}
|
||||
@@ -251,7 +251,7 @@ export class EggHatchPhase extends Phase {
|
||||
this.pokemon.cry();
|
||||
if (isShiny) {
|
||||
this.scene.time.delayedCall(Utils.fixedInt(500), () => {
|
||||
this.pokemonShinySparkle.play('sparkle');
|
||||
this.pokemonShinySparkle.play(`sparkle${this.pokemon.variant ? `_${this.pokemon.variant + 1}` : ''}`);
|
||||
this.scene.playSound('sparkle');
|
||||
});
|
||||
}
|
||||
|
||||
+134
-39
@@ -1,5 +1,7 @@
|
||||
import Phaser from 'phaser';
|
||||
import BattleScene, { ABILITY_OVERRIDE, AnySound, MOVE_OVERRIDE, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE } from '../battle-scene';
|
||||
import { Variant, VariantSet, variantColorCache } from '#app/data/variant';
|
||||
import { variantData } from '#app/data/variant';
|
||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info';
|
||||
import { Moves } from "../data/enums/moves";
|
||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move";
|
||||
@@ -42,7 +44,6 @@ import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMov
|
||||
import { TerrainType } from '../data/terrain';
|
||||
import { TrainerSlot } from '../data/trainer-config';
|
||||
|
||||
|
||||
export enum FieldPosition {
|
||||
CENTER,
|
||||
LEFT,
|
||||
@@ -57,7 +58,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
public abilityIndex: integer;
|
||||
public passive: boolean;
|
||||
public shiny: boolean;
|
||||
public variant: integer;
|
||||
public variant: Variant;
|
||||
public pokeball: PokeballType;
|
||||
protected battleInfo: BattleInfo;
|
||||
public level: integer;
|
||||
@@ -81,6 +82,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
public fusionFormIndex: integer;
|
||||
public fusionAbilityIndex: integer;
|
||||
public fusionShiny: boolean;
|
||||
public fusionVariant: Variant;
|
||||
public fusionGender: Gender;
|
||||
|
||||
private summonDataPrimer: PokemonSummonData;
|
||||
@@ -97,7 +99,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
private shinySparkle: Phaser.GameObjects.Sprite;
|
||||
|
||||
constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) {
|
||||
constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) {
|
||||
super(scene, x, y);
|
||||
|
||||
if (!species.isObtainable() && this.isPlayer())
|
||||
@@ -122,6 +124,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.gender = gender;
|
||||
if (shiny !== undefined)
|
||||
this.shiny = shiny;
|
||||
if (variant !== undefined)
|
||||
this.variant = variant;
|
||||
this.exp = dataSource?.exp || getLevelTotalExp(this.level, species.growthRate);
|
||||
this.levelExp = dataSource?.levelExp || 0;
|
||||
if (dataSource) {
|
||||
@@ -130,7 +134,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
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;
|
||||
@@ -144,6 +147,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.fusionFormIndex = dataSource.fusionFormIndex;
|
||||
this.fusionAbilityIndex = dataSource.fusionAbilityIndex;
|
||||
this.fusionShiny = dataSource.fusionShiny;
|
||||
this.fusionVariant = dataSource.fusionVariant;
|
||||
this.fusionGender = dataSource.fusionGender;
|
||||
} else {
|
||||
this.id = Utils.randSeedInt(4294967296);
|
||||
@@ -158,6 +162,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if (this.shiny === undefined)
|
||||
this.trySetShiny();
|
||||
|
||||
if (this.shiny && this.variant === undefined)
|
||||
this.variant = this.generateVariant();
|
||||
|
||||
if (nature !== undefined)
|
||||
this.setNature(nature);
|
||||
else
|
||||
@@ -240,7 +247,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
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.variant >= 2 ? DexAttr.VARIANT_3 : this.variant === 1 ? DexAttr.VARIANT_2 : DexAttr.DEFAULT_VARIANT;
|
||||
ret |= this.scene.gameData.getFormAttr(this.formIndex);
|
||||
return ret;
|
||||
}
|
||||
@@ -269,11 +276,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
Promise.allSettled(moveIds.map(m => initMoveAnim(m)))
|
||||
.then(() => {
|
||||
loadMoveAnimAssets(this.scene, moveIds);
|
||||
this.getSpeciesForm().loadAssets(this.scene, this.getGender() === Gender.FEMALE, this.formIndex, this.shiny);
|
||||
this.getSpeciesForm().loadAssets(this.scene, this.getGender() === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
|
||||
if (this.isPlayer() || this.getFusionSpeciesForm())
|
||||
this.scene.loadPokemonAtlas(this.getBattleSpriteKey(true, ignoreOverride), this.getBattleSpriteAtlasPath(true, ignoreOverride));
|
||||
if (this.getFusionSpeciesForm()) {
|
||||
this.getFusionSpeciesForm().loadAssets(this.scene, this.getFusionGender() === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny);
|
||||
this.getFusionSpeciesForm().loadAssets(this.scene, this.getFusionGender() === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
||||
this.scene.loadPokemonAtlas(this.getFusionBattleSpriteKey(true, ignoreOverride), this.getFusionBattleSpriteAtlasPath(true, ignoreOverride));
|
||||
}
|
||||
this.scene.load.once(Phaser.Loader.Events.COMPLETE, () => {
|
||||
@@ -291,10 +298,37 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
});
|
||||
}
|
||||
this.playAnim();
|
||||
this.updateFusionPalette();
|
||||
if (this.summonData?.speciesForm)
|
||||
this.updateFusionPalette(true);
|
||||
resolve();
|
||||
const updateFusionPaletteAndResolve = () => {
|
||||
this.updateFusionPalette();
|
||||
if (this.summonData?.speciesForm)
|
||||
this.updateFusionPalette(true);
|
||||
resolve();
|
||||
};
|
||||
if (this.isShiny()) {
|
||||
const populateVariantColors = (key: string, back: boolean = false): Promise<void> => {
|
||||
return new Promise(resolve => {
|
||||
const battleSpritePath = this.getBattleSpriteAtlasPath(back, ignoreOverride);
|
||||
let variantSet: VariantSet;
|
||||
let config = variantData;
|
||||
battleSpritePath.split('/').map(p => config = variantData[p]);
|
||||
variantSet = config as VariantSet;
|
||||
if (variantSet && variantSet[this.variant] === 1) {
|
||||
if (variantColorCache.hasOwnProperty(key))
|
||||
return resolve();
|
||||
fetch(`./images/pokemon/variant/${battleSpritePath}.json`).then(res => res.json()).then(c => {
|
||||
variantColorCache[key] = c;
|
||||
resolve();
|
||||
});
|
||||
} else
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
if (this.isPlayer())
|
||||
Promise.all([ populateVariantColors(this.getBattleSpriteKey()), populateVariantColors(this.getBattleSpriteKey(true)) ]).then(() => updateFusionPaletteAndResolve());
|
||||
else
|
||||
populateVariantColors(this.getBattleSpriteKey()).then(() => updateFusionPaletteAndResolve());
|
||||
} else
|
||||
updateFusionPaletteAndResolve();
|
||||
});
|
||||
if (!this.scene.load.isLoading())
|
||||
this.scene.load.start();
|
||||
@@ -317,15 +351,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
getSpriteAtlasPath(ignoreOverride?: boolean): string {
|
||||
return this.getSpriteId(ignoreOverride).replace(/\_{2}/g, '/');
|
||||
const spriteId = this.getSpriteId(ignoreOverride).replace(/\_{2}/g, '/');
|
||||
return `${/_[1-3]$/.test(spriteId) ? 'variant/' : ''}${spriteId}`;
|
||||
}
|
||||
|
||||
getBattleSpriteAtlasPath(back?: boolean, ignoreOverride?: boolean): string {
|
||||
return this.getBattleSpriteId(back, ignoreOverride).replace(/\_{2}/g, '/');
|
||||
const spriteId = this.getBattleSpriteId(back, ignoreOverride).replace(/\_{2}/g, '/');
|
||||
return `${/_[1-3]$/.test(spriteId) ? 'variant/' : ''}${spriteId}`;
|
||||
}
|
||||
|
||||
getSpriteId(ignoreOverride?: boolean): string {
|
||||
return this.getSpeciesForm(ignoreOverride).getSpriteId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny);
|
||||
return this.getSpeciesForm(ignoreOverride).getSpriteId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
|
||||
}
|
||||
|
||||
getBattleSpriteId(back?: boolean, ignoreOverride?: boolean): string {
|
||||
@@ -335,7 +371,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
getSpriteKey(ignoreOverride?: boolean): string {
|
||||
return this.getSpeciesForm(ignoreOverride).getSpriteKey(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny);
|
||||
return this.getSpeciesForm(ignoreOverride).getSpriteKey(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
|
||||
}
|
||||
|
||||
getBattleSpriteKey(back?: boolean, ignoreOverride?: boolean): string {
|
||||
@@ -343,7 +379,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
getFusionSpriteId(ignoreOverride?: boolean): string {
|
||||
return this.getFusionSpeciesForm(ignoreOverride).getSpriteId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny);
|
||||
return this.getFusionSpeciesForm(ignoreOverride).getSpriteId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
||||
}
|
||||
|
||||
getFusionBattleSpriteId(back?: boolean, ignoreOverride?: boolean): string {
|
||||
@@ -361,19 +397,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
getIconAtlasKey(ignoreOverride?: boolean): string {
|
||||
return this.getSpeciesForm(ignoreOverride).getIconAtlasKey(this.formIndex);
|
||||
return this.getSpeciesForm(ignoreOverride).getIconAtlasKey(this.formIndex, this.shiny, this.variant);
|
||||
}
|
||||
|
||||
getFusionIconAtlasKey(ignoreOverride?: boolean): string {
|
||||
return this.getFusionSpeciesForm(ignoreOverride).getIconAtlasKey(this.fusionFormIndex);
|
||||
return this.getFusionSpeciesForm(ignoreOverride).getIconAtlasKey(this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
||||
}
|
||||
|
||||
getIconId(ignoreOverride?: boolean): string {
|
||||
return this.getSpeciesForm(ignoreOverride).getIconId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.isShiny());
|
||||
return this.getSpeciesForm(ignoreOverride).getIconId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.isShiny(), this.variant);
|
||||
}
|
||||
|
||||
getFusionIconId(ignoreOverride?: boolean): string {
|
||||
return this.getFusionSpeciesForm(ignoreOverride).getIconId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.isShiny());
|
||||
return this.getFusionSpeciesForm(ignoreOverride).getIconId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.isShiny(), this.variant);
|
||||
}
|
||||
|
||||
getSpeciesForm(ignoreOverride?: boolean): PokemonSpeciesForm {
|
||||
@@ -419,12 +455,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
initShinySparkle(): void {
|
||||
const shinySparkle = this.scene.addFieldSprite(0, 0, 'shiny');
|
||||
const keySuffix = this.variant ? `_${this.variant + 1}` : '';
|
||||
const key = `shiny${keySuffix}`;
|
||||
const shinySparkle = this.scene.addFieldSprite(0, 0, key);
|
||||
shinySparkle.setVisible(false);
|
||||
shinySparkle.setOrigin(0.5, 1);
|
||||
const frameNames = this.scene.anims.generateFrameNames('shiny', { suffix: '.png', end: 34 });
|
||||
const frameNames = this.scene.anims.generateFrameNames(key, { suffix: '.png', end: 34 });
|
||||
this.scene.anims.create({
|
||||
key: 'sparkle',
|
||||
key: `sparkle${keySuffix}`,
|
||||
frames: frameNames,
|
||||
frameRate: 32,
|
||||
showOnStart: true,
|
||||
@@ -638,7 +676,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
isShiny(): boolean {
|
||||
return this.shiny || (this.fusionSpecies && this.fusionShiny);
|
||||
return this.shiny || (this.isFusion() && this.fusionShiny);
|
||||
}
|
||||
|
||||
getVariant(): Variant {
|
||||
return !this.isFusion() ? this.variant : Math.max(this.variant, this.fusionVariant) as Variant;
|
||||
}
|
||||
|
||||
isFusion(): boolean {
|
||||
@@ -957,6 +999,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return this.shiny;
|
||||
}
|
||||
|
||||
generateVariant(): Variant {
|
||||
if (!this.shiny || !variantData.hasOwnProperty(this.species.speciesId))
|
||||
return 0;
|
||||
const rand = Utils.randSeedInt(10);
|
||||
if (rand > 3)
|
||||
return 0;
|
||||
if (rand)
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
generateFusionSpecies(forStarter?: boolean): void {
|
||||
const hiddenAbilityChance = new Utils.IntegerHolder(256);
|
||||
if (!this.hasTrainer())
|
||||
@@ -979,6 +1032,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.fusionSpecies = this.scene.randomSpecies(this.scene.currentBattle?.waveIndex || 0, this.level, false, filter, true);
|
||||
this.fusionAbilityIndex = (this.fusionSpecies.abilityHidden && hasHiddenAbility ? this.fusionSpecies.ability2 ? 2 : 1 : this.fusionSpecies.ability2 ? randAbilityIndex : 0);
|
||||
this.fusionShiny = this.shiny;
|
||||
this.fusionVariant = this.variant;
|
||||
|
||||
if (this.fusionSpecies.malePercent === null)
|
||||
this.fusionGender = Gender.GENDERLESS;
|
||||
@@ -1933,7 +1987,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
sparkle(): void {
|
||||
if (this.shinySparkle) {
|
||||
this.shinySparkle.play('sparkle');
|
||||
this.shinySparkle.play(`sparkle${this.variant ? `_${this.variant + 1}` : ''}`);
|
||||
this.scene.playSound('sparkle');
|
||||
}
|
||||
}
|
||||
@@ -1950,10 +2004,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const speciesForm = this.getSpeciesForm(ignoreOveride);
|
||||
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOveride);
|
||||
|
||||
const sourceTexture = this.scene.textures.get(speciesForm.getSpriteKey(this.getGender(ignoreOveride) === Gender.FEMALE, speciesForm.formIndex, this.shiny));
|
||||
const sourceBackTexture = this.scene.textures.get(speciesForm.getSpriteKey(this.getGender(ignoreOveride) === Gender.FEMALE, speciesForm.formIndex, this.shiny).replace('pkmn__', 'pkmn__back__'));
|
||||
const fusionTexture = this.scene.textures.get(fusionSpeciesForm.getSpriteKey(this.getFusionGender(ignoreOveride) === Gender.FEMALE, fusionSpeciesForm.formIndex, this.fusionShiny));
|
||||
const fusionBackTexture = this.scene.textures.get(fusionSpeciesForm.getSpriteKey(this.getFusionGender(ignoreOveride) === Gender.FEMALE, fusionSpeciesForm.formIndex, this.fusionShiny).replace('pkmn__', 'pkmn__back__'));
|
||||
const spriteKey = speciesForm.getSpriteKey(this.getGender(ignoreOveride) === Gender.FEMALE, speciesForm.formIndex, this.shiny, this.variant);
|
||||
const backSpriteKey = speciesForm.getSpriteKey(this.getGender(ignoreOveride) === Gender.FEMALE, speciesForm.formIndex, this.shiny, this.variant).replace('pkmn__', 'pkmn__back__');
|
||||
const fusionSpriteKey = fusionSpeciesForm.getSpriteKey(this.getFusionGender(ignoreOveride) === Gender.FEMALE, fusionSpeciesForm.formIndex, this.fusionShiny, this.fusionVariant);
|
||||
const fusionBackSpriteKey = fusionSpeciesForm.getSpriteKey(this.getFusionGender(ignoreOveride) === Gender.FEMALE, fusionSpeciesForm.formIndex, this.fusionShiny, this.fusionVariant).replace('pkmn__', 'pkmn__back__');
|
||||
|
||||
const sourceTexture = this.scene.textures.get(spriteKey);
|
||||
const sourceBackTexture = this.scene.textures.get(backSpriteKey);
|
||||
const fusionTexture = this.scene.textures.get(fusionSpriteKey);
|
||||
const fusionBackTexture = this.scene.textures.get(fusionBackSpriteKey);
|
||||
|
||||
const [ sourceFrame, sourceBackFrame, fusionFrame, fusionBackFrame ] = [ sourceTexture, sourceBackTexture, fusionTexture, fusionBackTexture ].map(texture => texture.frames[texture.firstFrame]);
|
||||
const [ sourceImage, sourceBackImage, fusionImage, fusionBackImage ] = [ sourceTexture, sourceBackTexture, fusionTexture, fusionBackTexture ].map(i => i.getSourceImage() as HTMLImageElement);
|
||||
@@ -1977,10 +2036,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
});
|
||||
|
||||
for (let f = 0; f < 2; f++) {
|
||||
const variantColors = variantColorCache[!f ? spriteKey : backSpriteKey];
|
||||
let variantColorSet = new Map<integer, integer[]>();
|
||||
if (variantColors) {
|
||||
Object.keys(variantColors[this.variant]).forEach(k => {
|
||||
variantColorSet.set(Utils.rgbaToInt(Array.from(Object.values(Utils.rgbHexToRgba(k)))), Array.from(Object.values(Utils.rgbHexToRgba(variantColors[this.variant][k]))));
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < pixelData[f].length; i += 4) {
|
||||
if (pixelData[f][i + 3]) {
|
||||
const pixel = pixelData[f].slice(i, i + 4);
|
||||
const [ r, g, b, a ] = pixel;
|
||||
let [ r, g, b, a ] = pixel;
|
||||
if (variantColors) {
|
||||
const color = Utils.rgbaToInt([r, g, b, a]);
|
||||
if (variantColorSet.has(color)) {
|
||||
const mappedPixel = variantColorSet.get(color);
|
||||
[ r, g, b, a ] = mappedPixel;
|
||||
}
|
||||
}
|
||||
if (!spriteColors.find(c => c[0] === r && c[1] === g && c[2] === b))
|
||||
spriteColors.push([ r, g, b, a ]);
|
||||
}
|
||||
@@ -2001,11 +2075,27 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
const fusionPixelColors = [];
|
||||
for (let f = 0; f < 2; f++) {
|
||||
const variantColors = variantColorCache[!f ? fusionSpriteKey : fusionBackSpriteKey];
|
||||
let variantColorSet = new Map<integer, integer[]>();
|
||||
if (variantColors) {
|
||||
Object.keys(variantColors[this.fusionVariant]).forEach(k => {
|
||||
variantColorSet.set(Utils.rgbaToInt(Array.from(Object.values(Utils.rgbHexToRgba(k)))), Array.from(Object.values(Utils.rgbHexToRgba(variantColors[this.fusionVariant][k]))));
|
||||
});
|
||||
}
|
||||
for (let i = 0; i < pixelData[2 + f].length; i += 4) {
|
||||
const total = pixelData[2 + f].slice(i, i + 3).reduce((total: integer, value: integer) => total + value, 0);
|
||||
if (!total)
|
||||
continue;
|
||||
fusionPixelColors.push(argbFromRgba({ r: pixelData[2 + f][i], g: pixelData[2 + f][i + 1], b: pixelData[2 + f][i + 2], a: pixelData[2 + f][i + 3] }));
|
||||
let [ r, g, b, a ] = [ pixelData[2 + f][i], pixelData[2 + f][i + 1], pixelData[2 + f][i + 2], pixelData[2 + f][i + 3] ];
|
||||
if (variantColors) {
|
||||
const color = Utils.rgbaToInt([r, g, b, a]);
|
||||
if (variantColorSet.has(color)) {
|
||||
console.log(color);
|
||||
const mappedPixel = variantColorSet.get(color);
|
||||
[ r, g, b, a ] = mappedPixel;
|
||||
}
|
||||
}
|
||||
fusionPixelColors.push(argbFromRgba({ r, g, b, a }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2149,8 +2239,8 @@ export default interface Pokemon {
|
||||
export class PlayerPokemon extends Pokemon {
|
||||
public compatibleTms: Moves[];
|
||||
|
||||
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender: Gender, shiny: boolean, ivs: integer[], nature: Nature, dataSource: Pokemon | PokemonData) {
|
||||
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, ivs, nature, dataSource);
|
||||
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender: Gender, shiny: boolean, variant: Variant, ivs: integer[], nature: Nature, dataSource: Pokemon | PokemonData) {
|
||||
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource);
|
||||
|
||||
if (!dataSource)
|
||||
this.generateAndPopulateMoveset();
|
||||
@@ -2246,12 +2336,12 @@ export class PlayerPokemon extends Pokemon {
|
||||
const originalFusionFormIndex = this.fusionFormIndex;
|
||||
this.fusionSpecies = evolutionSpecies;
|
||||
this.fusionFormIndex = evolution.evoFormKey !== null ? Math.max(evolutionSpecies.forms.findIndex(f => f.formKey === evolution.evoFormKey), 0) : this.fusionFormIndex;
|
||||
ret = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.ivs, this.nature, this);
|
||||
ret = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this);
|
||||
this.fusionSpecies = originalFusionSpecies;
|
||||
this.fusionFormIndex = originalFusionFormIndex;
|
||||
} else {
|
||||
const formIndex = evolution.evoFormKey !== null && !isFusion ? Math.max(evolutionSpecies.forms.findIndex(f => f.formKey === evolution.evoFormKey), 0) : this.formIndex;
|
||||
ret = this.scene.addPlayerPokemon(!isFusion ? evolutionSpecies : this.species, this.level, this.abilityIndex, formIndex, this.gender, this.shiny, this.ivs, this.nature, this);
|
||||
ret = this.scene.addPlayerPokemon(!isFusion ? evolutionSpecies : this.species, this.level, this.abilityIndex, formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this);
|
||||
}
|
||||
ret.loadAssets().then(() => resolve(ret));
|
||||
});
|
||||
@@ -2305,13 +2395,14 @@ export class PlayerPokemon extends Pokemon {
|
||||
if ((!isFusion ? this.species : this.fusionSpecies).speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) {
|
||||
const newEvolution = pokemonEvolutions[this.species.speciesId][1];
|
||||
if (newEvolution.condition.predicate(this)) {
|
||||
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.ivs, this.nature);
|
||||
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, undefined, this.shiny, this.variant, this.ivs, this.nature);
|
||||
newPokemon.natureOverride = this.natureOverride;
|
||||
newPokemon.moveset = this.moveset.slice();
|
||||
newPokemon.fusionSpecies = this.fusionSpecies;
|
||||
newPokemon.fusionFormIndex = this.fusionFormIndex;
|
||||
newPokemon.fusionAbilityIndex = this.fusionAbilityIndex;
|
||||
newPokemon.fusionShiny = this.fusionShiny;
|
||||
newPokemon.fusionVariant = this.fusionVariant;
|
||||
newPokemon.fusionGender = this.fusionGender;
|
||||
this.scene.getParty().push(newPokemon);
|
||||
newPokemon.evolve(newEvolution);
|
||||
@@ -2330,7 +2421,7 @@ export class PlayerPokemon extends Pokemon {
|
||||
getPossibleForm(formChange: SpeciesFormChange): Promise<Pokemon> {
|
||||
return new Promise(resolve => {
|
||||
const formIndex = Math.max(this.species.forms.findIndex(f => f.formKey === formChange.formKey), 0);
|
||||
const ret = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, formIndex, this.gender, this.shiny, this.ivs, this.nature, this);
|
||||
const ret = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this);
|
||||
ret.loadAssets().then(() => resolve(ret));
|
||||
});
|
||||
}
|
||||
@@ -2370,6 +2461,7 @@ export class PlayerPokemon extends Pokemon {
|
||||
this.fusionFormIndex = pokemon.formIndex;
|
||||
this.fusionAbilityIndex = pokemon.abilityIndex;
|
||||
this.fusionShiny = pokemon.shiny;
|
||||
this.fusionVariant = pokemon.fusionVariant;
|
||||
this.fusionGender = pokemon.gender;
|
||||
|
||||
this.scene.validateAchv(achvs.SPLICE);
|
||||
@@ -2420,7 +2512,7 @@ export class EnemyPokemon extends Pokemon {
|
||||
|
||||
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean, dataSource: PokemonData) {
|
||||
super(scene, 236, 84, species, level, dataSource?.abilityIndex, dataSource?.formIndex,
|
||||
dataSource?.gender, dataSource ? dataSource.shiny : false, null, dataSource ? dataSource.nature : undefined, dataSource);
|
||||
dataSource?.gender, dataSource ? dataSource.shiny : false, dataSource ? dataSource.variant : undefined, null, dataSource ? dataSource.nature : undefined, dataSource);
|
||||
|
||||
this.trainerSlot = trainerSlot;
|
||||
if (boss)
|
||||
@@ -2431,6 +2523,9 @@ export class EnemyPokemon extends Pokemon {
|
||||
|
||||
this.trySetShiny();
|
||||
|
||||
if (this.shiny)
|
||||
this.variant = this.generateVariant();
|
||||
|
||||
let prevolution: Species;
|
||||
let speciesId = species.speciesId;
|
||||
while ((prevolution = pokemonPrevolutions[speciesId])) {
|
||||
@@ -2806,7 +2901,7 @@ export class EnemyPokemon extends Pokemon {
|
||||
this.pokeball = pokeballType;
|
||||
this.metLevel = this.level;
|
||||
this.metBiome = this.scene.arena.biomeType;
|
||||
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.ivs, this.nature, this);
|
||||
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this);
|
||||
party.push(newPokemon);
|
||||
ret = newPokemon;
|
||||
this.scene.triggerPokemonFormChange(newPokemon, SpeciesFormChangeActiveTrigger, true);
|
||||
|
||||
@@ -65,6 +65,7 @@ export class LoadingScene extends SceneBase {
|
||||
this.loadImage('achv_bar_3', 'ui');
|
||||
this.loadImage('achv_bar_4', 'ui');
|
||||
this.loadImage('shiny_star', 'ui', 'shiny.png');
|
||||
this.loadImage('shiny_star_small', 'ui', 'shiny_small.png');
|
||||
this.loadImage('ha_capsule', 'ui', 'ha_capsule.png');
|
||||
this.loadImage('icon_spliced', 'ui');
|
||||
this.loadImage('icon_tera', 'ui');
|
||||
@@ -162,6 +163,8 @@ export class LoadingScene extends SceneBase {
|
||||
this.loadImage(`pkmn__sub`, 'pokemon', 'sub.png');
|
||||
this.loadAtlas('battle_stats', 'effects');
|
||||
this.loadAtlas('shiny', 'effects');
|
||||
this.loadAtlas('shiny_2', 'effects');
|
||||
this.loadAtlas('shiny_3', 'effects');
|
||||
this.loadImage('tera', 'effects');
|
||||
this.loadAtlas('pb_particles', 'effects');
|
||||
this.loadImage('evo_sparkle', 'effects');
|
||||
@@ -191,8 +194,10 @@ export class LoadingScene extends SceneBase {
|
||||
|
||||
this.loadImage('egg_list_bg', 'ui');
|
||||
|
||||
for (let i = 0; i < 10; i++)
|
||||
for (let i = 0; i < 10; i++) {
|
||||
this.loadAtlas(`pokemon_icons_${i}`, '');
|
||||
this.loadAtlas(`pokemon_icons_${i}v`, '');
|
||||
}
|
||||
|
||||
this.loadSe('select');
|
||||
this.loadSe('menu_open');
|
||||
@@ -254,8 +259,6 @@ export class LoadingScene extends SceneBase {
|
||||
}
|
||||
|
||||
loadLoadingScreen() {
|
||||
const mobile = isMobile();
|
||||
|
||||
const loadingGraphics: any[] = [];
|
||||
|
||||
const bg = this.add.image(0, 0, '');
|
||||
@@ -320,8 +323,7 @@ export class LoadingScene extends SceneBase {
|
||||
|
||||
loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText);
|
||||
|
||||
if (!mobile)
|
||||
loadingGraphics.map(g => g.setVisible(false));
|
||||
loadingGraphics.map(g => g.setVisible(false));
|
||||
|
||||
const destroyLoadingAssets = () => {
|
||||
intro.destroy();
|
||||
@@ -350,13 +352,11 @@ export class LoadingScene extends SceneBase {
|
||||
break;
|
||||
case 'loading_bg':
|
||||
bg.setTexture('loading_bg');
|
||||
if (mobile)
|
||||
bg.setVisible(true);
|
||||
//bg.setVisible(true);
|
||||
break;
|
||||
case 'logo':
|
||||
logo.setTexture('logo');
|
||||
if (mobile)
|
||||
logo.setVisible(true);
|
||||
//logo.setVisible(true);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
+4
-6
@@ -31,7 +31,6 @@ import { TempBattleStat } from "./data/temp-battle-stat";
|
||||
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
|
||||
import { ArenaTagType } from "./data/enums/arena-tag-type";
|
||||
import { CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs } from "./data/ability";
|
||||
import { Abilities } from "./data/enums/abilities";
|
||||
import { Unlockables, getUnlockableName } from "./system/unlockables";
|
||||
import { getBiomeKey } from "./field/arena";
|
||||
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
||||
@@ -44,7 +43,7 @@ import { EggHatchPhase } from "./egg-hatch-phase";
|
||||
import { Egg } from "./data/egg";
|
||||
import { vouchers } from "./system/voucher";
|
||||
import { loggedInUser, updateUserInfo } from "./account";
|
||||
import { DexAttr, GameDataType, PlayerGender, SessionSaveData } from "./system/game-data";
|
||||
import { DexAttr, 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";
|
||||
@@ -159,6 +158,7 @@ export class TitlePhase extends Phase {
|
||||
this.scene.gameData.getSession(loggedInUser.lastSessionSlot).then(sessionData => {
|
||||
if (sessionData) {
|
||||
this.lastSessionData = sessionData;
|
||||
console.log(sessionData);
|
||||
const biomeKey = getBiomeKey(sessionData.arena.biome);
|
||||
const bgTexture = `${biomeKey}_bg`;
|
||||
this.scene.arenaBg.setTexture(bgTexture);
|
||||
@@ -306,7 +306,7 @@ export class TitlePhase extends Phase {
|
||||
const starterGender = starter.species.malePercent !== null
|
||||
? !starterProps.female ? Gender.MALE : Gender.FEMALE
|
||||
: Gender.GENDERLESS;
|
||||
const starterPokemon = this.scene.addPlayerPokemon(starter.species, startingLevel, starterProps.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, undefined, starter.nature);
|
||||
const starterPokemon = this.scene.addPlayerPokemon(starter.species, startingLevel, starter.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterProps.variant, undefined, starter.nature);
|
||||
starterPokemon.setVisible(false);
|
||||
party.push(starterPokemon);
|
||||
loadPokemonAssets.push(starterPokemon.loadAssets());
|
||||
@@ -466,12 +466,10 @@ export class SelectStarterPhase extends Phase {
|
||||
? !starterProps.female ? Gender.MALE : Gender.FEMALE
|
||||
: Gender.GENDERLESS;
|
||||
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);
|
||||
const starterPokemon = this.scene.addPlayerPokemon(starter.species, this.scene.gameMode.getStartingLevel(), starter.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterProps.variant, 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)
|
||||
|
||||
+60
-4
@@ -1,7 +1,9 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import { variantColorCache, variantData } from '#app/data/variant';
|
||||
import Pokemon from "../field/pokemon";
|
||||
import Trainer from "../field/trainer";
|
||||
import FieldSpritePipeline from "./field-sprite";
|
||||
import * as Utils from "../utils";
|
||||
|
||||
const spriteFragShader = `
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
@@ -36,6 +38,8 @@ uniform vec2 size;
|
||||
uniform vec2 texSize;
|
||||
uniform float yOffset;
|
||||
uniform vec4 tone;
|
||||
uniform vec4 baseVariantColors[32];
|
||||
uniform vec4 variantColors[32];
|
||||
uniform ivec4 spriteColors[32];
|
||||
uniform ivec4 fusionSpriteColors[32];
|
||||
|
||||
@@ -155,6 +159,15 @@ vec3 hsv2rgb(vec3 c) {
|
||||
void main() {
|
||||
vec4 texture = texture2D(uMainSampler[0], outTexCoord);
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (baseVariantColors[i][3] == 0.0)
|
||||
break;
|
||||
if (texture.a > 0.0 && texture.r == baseVariantColors[i].r && texture.g == baseVariantColors[i].g && texture.b == baseVariantColors[i].b) {
|
||||
texture.rgb = variantColors[i].rgb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (spriteColors[i][3] == 0)
|
||||
break;
|
||||
@@ -362,16 +375,17 @@ export default class SpritePipeline extends FieldSpritePipeline {
|
||||
this.set1f('yOffset', sprite.height - sprite.frame.height * (isEntityObj ? sprite.parentContainer.scale : sprite.scale));
|
||||
this.set4fv('tone', tone);
|
||||
this.bindTexture(this.game.textures.get('tera').source[0].glTexture, 1);
|
||||
|
||||
if ((gameObject.scene as BattleScene).fusionPaletteSwaps) {
|
||||
const spriteColors = (ignoreOverride && data['spriteColorsBase']) || data['spriteColors'] || [] as number[][];
|
||||
const fusionSpriteColors = (ignoreOverride && data['fusionSpriteColorsBase']) || data['fusionSpriteColors'] || [] as number[][];
|
||||
const spriteColors = ((ignoreOverride && data['spriteColorsBase']) || data['spriteColors'] || []) as number[][];
|
||||
const fusionSpriteColors = ((ignoreOverride && data['fusionSpriteColorsBase']) || data['fusionSpriteColors'] || []) as number[][];
|
||||
|
||||
const emptyColors = [ 0, 0, 0, 0 ];
|
||||
const flatSpriteColors: integer[] = [];
|
||||
const flatFusionSpriteColors: integer[] = [];
|
||||
for (let c = 0; c < 32; c++) {
|
||||
flatSpriteColors.splice(flatSpriteColors.length, 0, c < spriteColors.length ? spriteColors[c] : emptyColors);
|
||||
flatFusionSpriteColors.splice(flatFusionSpriteColors.length, 0, c < fusionSpriteColors.length ? fusionSpriteColors[c] : emptyColors);
|
||||
flatSpriteColors.splice(flatSpriteColors.length, 0, ...(c < spriteColors.length ? spriteColors[c] : emptyColors));
|
||||
flatFusionSpriteColors.splice(flatFusionSpriteColors.length, 0, ...(c < fusionSpriteColors.length ? fusionSpriteColors[c] : emptyColors));
|
||||
}
|
||||
|
||||
this.set4iv(`spriteColors`, flatSpriteColors.flat());
|
||||
@@ -379,6 +393,48 @@ export default class SpritePipeline extends FieldSpritePipeline {
|
||||
}
|
||||
}
|
||||
|
||||
onBatch(gameObject: Phaser.GameObjects.GameObject): void {
|
||||
if (gameObject) {
|
||||
const sprite = (gameObject as Phaser.GameObjects.Sprite);
|
||||
const data = sprite.pipelineData;
|
||||
|
||||
const variant: integer = data.hasOwnProperty('variant')
|
||||
? data['variant']
|
||||
: sprite.parentContainer instanceof Pokemon ? sprite.parentContainer.variant
|
||||
: 0;
|
||||
let variantColors;
|
||||
|
||||
const emptyColors = [ 0, 0, 0, 0 ];
|
||||
const flatBaseColors: number[] = [];
|
||||
const flatVariantColors: number[] = [];
|
||||
|
||||
if ((variantColors = variantColorCache[sprite.parentContainer instanceof Pokemon ? sprite.parentContainer.getSprite().texture.key : data['spriteKey']]) && variantColors.hasOwnProperty(variant)) {
|
||||
const baseColors = Object.keys(variantColors[variant]);
|
||||
for (let c = 0; c < 32; c++) {
|
||||
if (c < baseColors.length) {
|
||||
const baseColor = Array.from(Object.values(Utils.rgbHexToRgba(baseColors[c])));
|
||||
const variantColor = Array.from(Object.values(Utils.rgbHexToRgba(variantColors[variant][baseColors[c]])));
|
||||
flatBaseColors.splice(flatBaseColors.length, 0, ...baseColor.map(c => c / 255.0));
|
||||
flatVariantColors.splice(flatVariantColors.length, 0, ...variantColor.map(c => c / 255.0));
|
||||
} else {
|
||||
flatBaseColors.splice(flatBaseColors.length, 0, ...emptyColors);
|
||||
flatVariantColors.splice(flatVariantColors.length, 0, ...emptyColors);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let c = 0; c < 32; c++) {
|
||||
flatBaseColors.splice(flatBaseColors.length, 0, ...emptyColors);
|
||||
flatVariantColors.splice(flatVariantColors.length, 0, ...emptyColors);
|
||||
}
|
||||
}
|
||||
|
||||
this.set4fv('baseVariantColors', flatBaseColors.flat());
|
||||
this.set4fv('variantColors', flatVariantColors.flat());
|
||||
}
|
||||
|
||||
super.onBatch(gameObject);
|
||||
}
|
||||
|
||||
batchQuad(gameObject: Phaser.GameObjects.GameObject, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number,
|
||||
u0: number, v0: number, u1: number, v1: number, tintTL: number, tintTR: number, tintBL: number, tintBR: number, tintEffect: number | boolean,
|
||||
texture?: Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper, unit?: number): boolean {
|
||||
|
||||
+57
-15
@@ -28,6 +28,7 @@ import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { allMoves } from "../data/move";
|
||||
import { TrainerVariant } from "../field/trainer";
|
||||
import { OutdatedPhase, UnavailablePhase } from "#app/phases";
|
||||
import { Variant } from "#app/data/variant";
|
||||
|
||||
const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary
|
||||
|
||||
@@ -135,19 +136,25 @@ export const DexAttr = {
|
||||
SHINY: 2n,
|
||||
MALE: 4n,
|
||||
FEMALE: 8n,
|
||||
ABILITY_1: 16n,
|
||||
ABILITY_2: 32n,
|
||||
ABILITY_HIDDEN: 64n,
|
||||
DEFAULT_VARIANT: 16n,
|
||||
VARIANT_2: 32n,
|
||||
VARIANT_3: 64n,
|
||||
DEFAULT_FORM: 128n
|
||||
}
|
||||
|
||||
export interface DexAttrProps {
|
||||
shiny: boolean;
|
||||
female: boolean;
|
||||
abilityIndex: integer;
|
||||
variant: Variant;
|
||||
formIndex: integer;
|
||||
}
|
||||
|
||||
export const AbilityAttr = {
|
||||
ABILITY_1: 1,
|
||||
ABILITY_2: 2,
|
||||
ABILITY_HIDDEN: 4
|
||||
}
|
||||
|
||||
export type StarterMoveset = [ Moves ] | [ Moves, Moves ] | [ Moves, Moves, Moves ] | [ Moves, Moves, Moves, Moves ];
|
||||
|
||||
export interface StarterFormMoveData {
|
||||
@@ -162,8 +169,8 @@ export interface StarterDataEntry {
|
||||
moveset: StarterMoveset | StarterFormMoveData;
|
||||
eggMoves: integer;
|
||||
candyCount: integer;
|
||||
abilityAttr: integer;
|
||||
passiveAttr: integer;
|
||||
variantAttr: integer;
|
||||
valueReduction: integer;
|
||||
}
|
||||
|
||||
@@ -332,8 +339,11 @@ export class GameData {
|
||||
for (let s of Object.keys(starterEggMoveData))
|
||||
this.starterData[s].eggMoves = starterEggMoveData[s];
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
if ([ '1.0.0', '1.0.1' ].includes(systemData.gameVersion))
|
||||
this.migrateStarterAbilities(systemData);
|
||||
this.starterData = systemData.starterData;
|
||||
}
|
||||
|
||||
if (systemData.gameStats)
|
||||
this.gameStats = systemData.gameStats;
|
||||
@@ -424,7 +434,7 @@ export class GameData {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return k.endsWith('Attr') && ![ 'natureAttr', 'passiveAttr', 'variantAttr' ].includes(k) ? BigInt(v) : v;
|
||||
return k.endsWith('Attr') && ![ 'natureAttr', 'abilityAttr', 'passiveAttr' ].includes(k) ? BigInt(v) : v;
|
||||
}) as SystemSaveData;
|
||||
}
|
||||
|
||||
@@ -919,7 +929,7 @@ export class GameData {
|
||||
Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY
|
||||
];
|
||||
|
||||
const defaultStarterAttr = DexAttr.NON_SHINY | DexAttr.MALE | DexAttr.ABILITY_1 | DexAttr.DEFAULT_FORM;
|
||||
const defaultStarterAttr = DexAttr.NON_SHINY | DexAttr.MALE | DexAttr.DEFAULT_VARIANT | DexAttr.DEFAULT_FORM;
|
||||
|
||||
const defaultStarterNatures: Nature[] = [];
|
||||
|
||||
@@ -952,8 +962,8 @@ export class GameData {
|
||||
moveset: null,
|
||||
eggMoves: 0,
|
||||
candyCount: 0,
|
||||
abilityAttr: 0,
|
||||
passiveAttr: 0,
|
||||
variantAttr: 0,
|
||||
valueReduction: 0
|
||||
};
|
||||
}
|
||||
@@ -984,8 +994,11 @@ export class GameData {
|
||||
if (noStarterFormKeys.includes(pokemon.getFormKey()))
|
||||
pokemon.formIndex = 0;
|
||||
const dexAttr = pokemon.getDexAttr();
|
||||
console.log(dexAttr);
|
||||
pokemon.formIndex = formIndex;
|
||||
dexEntry.caughtAttr |= dexAttr;
|
||||
if (speciesStarters.hasOwnProperty(species.speciesId))
|
||||
this.starterData[species.speciesId].abilityAttr |= Math.pow(2, pokemon.abilityIndex);
|
||||
dexEntry.natureAttr |= Math.pow(2, pokemon.nature + 1);
|
||||
|
||||
const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId);
|
||||
@@ -1013,7 +1026,7 @@ export class GameData {
|
||||
}
|
||||
|
||||
if (!hasPrevolution)
|
||||
this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1));
|
||||
this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 * Math.pow(2, pokemon.variant) : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1));
|
||||
}
|
||||
|
||||
const checkPrevolution = () => {
|
||||
@@ -1097,13 +1110,17 @@ export class GameData {
|
||||
return starterCount;
|
||||
}
|
||||
|
||||
getSpeciesDefaultDexAttr(species: PokemonSpecies, forSeen: boolean = false): bigint {
|
||||
getSpeciesDefaultDexAttr(species: PokemonSpecies, forSeen: boolean = false, optimistic: boolean = false): bigint {
|
||||
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 |= optimistic
|
||||
? attr & DexAttr.SHINY ? DexAttr.SHINY : DexAttr.NON_SHINY
|
||||
: 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 |= optimistic
|
||||
? attr & DexAttr.SHINY ? attr & DexAttr.VARIANT_3 ? DexAttr.VARIANT_3 : attr & DexAttr.VARIANT_2 ? DexAttr.VARIANT_2 : DexAttr.DEFAULT_VARIANT : DexAttr.DEFAULT_VARIANT
|
||||
: attr & DexAttr.DEFAULT_VARIANT ? DexAttr.DEFAULT_VARIANT : attr & DexAttr.VARIANT_2 ? DexAttr.VARIANT_2 : attr & DexAttr.VARIANT_3 ? DexAttr.VARIANT_3 : DexAttr.DEFAULT_VARIANT;
|
||||
ret |= this.getFormAttr(this.getFormIndex(attr));
|
||||
return ret;
|
||||
}
|
||||
@@ -1111,17 +1128,22 @@ export class GameData {
|
||||
getSpeciesDexAttrProps(species: PokemonSpecies, dexAttr: bigint): DexAttrProps {
|
||||
const shiny = !(dexAttr & DexAttr.NON_SHINY);
|
||||
const female = !(dexAttr & DexAttr.MALE);
|
||||
const abilityIndex = dexAttr & DexAttr.ABILITY_1 ? 0 : !species.ability2 || dexAttr & DexAttr.ABILITY_2 ? 1 : 2;
|
||||
const variant = dexAttr & DexAttr.DEFAULT_VARIANT ? 0 : dexAttr & DexAttr.VARIANT_2 ? 1 : dexAttr & DexAttr.VARIANT_3 ? 2 : 0;
|
||||
const formIndex = this.getFormIndex(dexAttr);
|
||||
|
||||
return {
|
||||
shiny,
|
||||
female,
|
||||
abilityIndex,
|
||||
variant,
|
||||
formIndex
|
||||
};
|
||||
}
|
||||
|
||||
getStarterSpeciesDefaultAbilityIndex(species: PokemonSpecies): integer {
|
||||
const abilityAttr = this.starterData[species.speciesId].abilityAttr;
|
||||
return abilityAttr & AbilityAttr.ABILITY_1 ? 0 : !species.ability2 || abilityAttr & AbilityAttr.ABILITY_2 ? 1 : 2;
|
||||
}
|
||||
|
||||
getSpeciesDefaultNature(species: PokemonSpecies): Nature {
|
||||
const dexEntry = this.dexData[species.speciesId];
|
||||
for (let n = 0; n < 25; n++) {
|
||||
@@ -1184,4 +1206,24 @@ export class GameData {
|
||||
entry.natureAttr = this.defaultDexData[k].natureAttr || Math.pow(2, Utils.randInt(25, 1));
|
||||
}
|
||||
}
|
||||
|
||||
migrateStarterAbilities(systemData: SystemSaveData): void {
|
||||
const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species);
|
||||
const starterData = systemData.starterData;
|
||||
const dexData = systemData.dexData;
|
||||
for (let s of starterIds) {
|
||||
const dexAttr = dexData[s].caughtAttr;
|
||||
starterData[s].abilityAttr = (dexAttr & DexAttr.DEFAULT_VARIANT ? AbilityAttr.ABILITY_1 : 0)
|
||||
| (dexAttr & DexAttr.VARIANT_2 ? AbilityAttr.ABILITY_2 : 0)
|
||||
| (dexAttr & DexAttr.VARIANT_3 ? AbilityAttr.ABILITY_HIDDEN : 0);
|
||||
if (dexAttr) {
|
||||
if (!(dexAttr & DexAttr.DEFAULT_VARIANT))
|
||||
dexData[s].caughtAttr ^= DexAttr.DEFAULT_VARIANT;
|
||||
if (dexAttr & DexAttr.VARIANT_2)
|
||||
dexData[s].caughtAttr ^= DexAttr.VARIANT_2;
|
||||
if (dexAttr & DexAttr.VARIANT_3)
|
||||
dexData[s].caughtAttr ^= DexAttr.VARIANT_3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import { Status } from "../data/status-effect";
|
||||
import Pokemon, { EnemyPokemon, PokemonMove, PokemonSummonData } from "../field/pokemon";
|
||||
import { TrainerSlot } from "../data/trainer-config";
|
||||
import { Moves } from "../data/enums/moves";
|
||||
import { Variant } from "#app/data/variant";
|
||||
|
||||
export default class PokemonData {
|
||||
public id: integer;
|
||||
@@ -19,7 +20,7 @@ export default class PokemonData {
|
||||
public abilityIndex: integer;
|
||||
public passive: boolean;
|
||||
public shiny: boolean;
|
||||
public variant: integer;
|
||||
public variant: Variant;
|
||||
public pokeball: PokeballType;
|
||||
public level: integer;
|
||||
public exp: integer;
|
||||
@@ -42,6 +43,7 @@ export default class PokemonData {
|
||||
public fusionFormIndex: integer;
|
||||
public fusionAbilityIndex: integer;
|
||||
public fusionShiny: boolean;
|
||||
public fusionVariant: Variant;
|
||||
public fusionGender: Gender;
|
||||
|
||||
public boss: boolean;
|
||||
@@ -81,6 +83,7 @@ export default class PokemonData {
|
||||
this.fusionFormIndex = source.fusionFormIndex;
|
||||
this.fusionAbilityIndex = source.fusionAbilityIndex;
|
||||
this.fusionShiny = source.fusionShiny;
|
||||
this.fusionVariant = source.fusionVariant;
|
||||
this.fusionGender = source.fusionGender;
|
||||
|
||||
if (!forHistory)
|
||||
@@ -115,7 +118,7 @@ export default class PokemonData {
|
||||
toPokemon(scene: BattleScene, battleType?: BattleType, partyMemberIndex: integer = 0, double: boolean = false): Pokemon {
|
||||
const species = getPokemonSpecies(this.species);
|
||||
const ret: Pokemon = this.player
|
||||
? scene.addPlayerPokemon(species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.ivs, this.nature, this)
|
||||
? scene.addPlayerPokemon(species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this)
|
||||
: scene.addEnemyPokemon(species, this.level, battleType === BattleType.TRAINER ? !double || !(partyMemberIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER : TrainerSlot.NONE, this.boss, this);
|
||||
if (this.summonData)
|
||||
ret.primeSummonData(this.summonData);
|
||||
|
||||
+20
-12
@@ -6,6 +6,7 @@ import { getGenderSymbol, getGenderColor, Gender } from '../data/gender';
|
||||
import { StatusEffect } from '../data/status-effect';
|
||||
import BattleScene from '../battle-scene';
|
||||
import { Type, getTypeRgb } from '../data/type';
|
||||
import { getVariantTint } from '#app/data/variant';
|
||||
|
||||
export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
private player: boolean;
|
||||
@@ -29,8 +30,8 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
private genderText: Phaser.GameObjects.Text;
|
||||
private ownedIcon: Phaser.GameObjects.Sprite;
|
||||
private teraIcon: Phaser.GameObjects.Sprite;
|
||||
private splicedIcon: Phaser.GameObjects.Sprite;
|
||||
private shinyIcon: Phaser.GameObjects.Sprite;
|
||||
private splicedIcon: Phaser.GameObjects.Sprite;
|
||||
private statusIndicator: Phaser.GameObjects.Sprite;
|
||||
private levelContainer: Phaser.GameObjects.Container;
|
||||
private hpBar: Phaser.GameObjects.Image;
|
||||
@@ -91,6 +92,14 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
this.teraIcon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 12, 15), Phaser.Geom.Rectangle.Contains);
|
||||
this.add(this.teraIcon);
|
||||
|
||||
this.shinyIcon = this.scene.add.sprite(0, 0, 'shiny_star');
|
||||
this.shinyIcon.setVisible(false);
|
||||
this.shinyIcon.setOrigin(0, 0);
|
||||
this.shinyIcon.setScale(0.5)
|
||||
this.shinyIcon.setPositionRelative(this.nameText, 0, 2);
|
||||
this.shinyIcon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 12, 15), Phaser.Geom.Rectangle.Contains);
|
||||
this.add(this.shinyIcon);
|
||||
|
||||
this.splicedIcon = this.scene.add.sprite(0, 0, 'icon_spliced');
|
||||
this.splicedIcon.setVisible(false);
|
||||
this.splicedIcon.setOrigin(0, 0);
|
||||
@@ -111,12 +120,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
const levelOverlay = this.scene.add.image(0, 0, 'overlay_lv');
|
||||
this.levelContainer.add(levelOverlay);
|
||||
|
||||
this.shinyIcon = this.scene.add.sprite(0, 0, 'shiny_star');
|
||||
this.shinyIcon.setVisible(false);
|
||||
this.shinyIcon.setOrigin(0, 0);
|
||||
this.shinyIcon.setPositionRelative(this.levelContainer, -12, -5);
|
||||
this.add(this.shinyIcon);
|
||||
|
||||
this.hpBar = this.scene.add.image(player ? -61 : -71, player ? -1 : 4.5, 'overlay_hp');
|
||||
this.hpBar.setOrigin(0);
|
||||
this.add(this.hpBar);
|
||||
@@ -182,6 +185,14 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
this.splicedIcon.on('pointerout', () => (this.scene as BattleScene).ui.hideTooltip());
|
||||
}
|
||||
|
||||
this.shinyIcon.setPositionRelative(this.nameText, nameTextWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0) + (this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0), 2.5);
|
||||
this.shinyIcon.setVisible(!!pokemon.isShiny());
|
||||
this.shinyIcon.setTint(getVariantTint(pokemon.getVariant()));
|
||||
if (this.shinyIcon.visible) {
|
||||
this.shinyIcon.on('pointerover', () => (this.scene as BattleScene).ui.showTooltip(null, `Shiny${pokemon.getVariant() ? ` (${pokemon.getVariant() === 2 ? 'Epic' : 'Rare'})` : ''}`));
|
||||
this.shinyIcon.on('pointerout', () => (this.scene as BattleScene).ui.hideTooltip());
|
||||
}
|
||||
|
||||
if (!this.player) {
|
||||
const dexEntry = pokemon.scene.gameData.dexData[pokemon.species.speciesId];
|
||||
this.ownedIcon.setVisible(!!dexEntry.caughtAttr);
|
||||
@@ -235,7 +246,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
if (this.player)
|
||||
this.y -= 12 * (mini ? 1 : -1);
|
||||
|
||||
const offsetElements = [ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.statusIndicator, this.levelContainer ];
|
||||
const offsetElements = [ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.shinyIcon, this.statusIndicator, this.levelContainer ];
|
||||
offsetElements.forEach(el => el.y += 1.5 * (mini ? -1 : 1));
|
||||
|
||||
[ this.type1Icon, this.type2Icon ].forEach(el => {
|
||||
@@ -243,8 +254,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
el.y += -8 * (mini ? 1 : -1);
|
||||
});
|
||||
|
||||
this.shinyIcon.setPositionRelative(this.levelContainer, -12, -5);
|
||||
|
||||
const toggledElements = [ this.hpNumbersContainer, this.expBar ];
|
||||
toggledElements.forEach(el => el.setVisible(!mini));
|
||||
}
|
||||
@@ -255,7 +264,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
if (boss !== this.boss) {
|
||||
this.boss = boss;
|
||||
|
||||
[ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.ownedIcon, this.statusIndicator, this.levelContainer ].map(e => e.x += 48 * (boss ? -1 : 1));
|
||||
[ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.shinyIcon, this.ownedIcon, this.statusIndicator, this.levelContainer ].map(e => e.x += 48 * (boss ? -1 : 1));
|
||||
this.hpBar.x += 38 * (boss ? -1 : 1);
|
||||
this.hpBar.y += 2 * (this.boss ? -1 : 1);
|
||||
this.hpBar.setTexture(`overlay_hp${boss ? '_boss' : ''}`);
|
||||
@@ -478,7 +487,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
for (let i = 0; i < levelStr.length; i++)
|
||||
this.levelNumbersContainer.add(this.scene.add.image(i * 8, 0, `numbers${isCapped && this.player ? '_red' : ''}`, levelStr[i]));
|
||||
this.levelContainer.setX((this.player ? -41 : -50) - 8 * Math.max(levelStr.length - 3, 0));
|
||||
this.shinyIcon.setPositionRelative(this.levelContainer, -12, -5);
|
||||
}
|
||||
|
||||
setHpNumbers(hp: integer, maxHp: integer) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import PokemonIconAnimHandler, { PokemonIconAnimMode } from "./pokemon-icon-anim
|
||||
import { pokemonEvolutions } from "../data/pokemon-evolutions";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import { SpeciesFormChangeItemTrigger } from "../data/pokemon-forms";
|
||||
import { getVariantTint } from "#app/data/variant";
|
||||
|
||||
const defaultMessage = 'Choose a Pokémon.';
|
||||
|
||||
@@ -899,9 +900,10 @@ class PartySlot extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
if (this.pokemon.isShiny()) {
|
||||
const shinyStar = this.scene.add.image(0, 0, 'shiny_star');
|
||||
const shinyStar = this.scene.add.image(0, 0, 'shiny_star_small');
|
||||
shinyStar.setOrigin(0, 0);
|
||||
shinyStar.setPositionRelative(slotName, -8, 2);
|
||||
shinyStar.setPositionRelative(slotName, -9, 3);
|
||||
shinyStar.setTint(getVariantTint(this.pokemon.getVariant()));
|
||||
|
||||
slotInfoContainer.add(shinyStar);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Gender, getGenderColor, getGenderSymbol } from "../data/gender";
|
||||
import { allAbilities } from "../data/ability";
|
||||
import { GameModes, gameModes } from "../game-mode";
|
||||
import { GrowthRate, getGrowthRateColor } from "../data/exp";
|
||||
import { DexAttr, DexAttrProps, DexEntry, Passive as PassiveAttr, StarterFormMoveData, StarterMoveset } from "../system/game-data";
|
||||
import { AbilityAttr, 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";
|
||||
@@ -26,14 +26,15 @@ import { TitlePhase } from "../phases";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import { OptionSelectItem } from "./abstact-option-select-ui-handler";
|
||||
import { pokemonPrevolutions } from "#app/data/pokemon-evolutions";
|
||||
import { Variant, getVariantTint } from "#app/data/variant";
|
||||
|
||||
export type StarterSelectCallback = (starters: Starter[]) => void;
|
||||
|
||||
export interface Starter {
|
||||
species: PokemonSpecies;
|
||||
dexAttr: bigint;
|
||||
abilityIndex: integer,
|
||||
passive: boolean;
|
||||
variant: integer;
|
||||
nature: Nature;
|
||||
moveset?: StarterMoveset;
|
||||
pokerus: boolean;
|
||||
@@ -128,6 +129,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
private genMode: boolean;
|
||||
private statsMode: boolean;
|
||||
private dexAttrCursor: bigint = 0n;
|
||||
private abilityCursor: integer = -1;
|
||||
private natureCursor: integer = -1;
|
||||
private genCursor: integer = 0;
|
||||
private genScrollCursor: integer = 0;
|
||||
@@ -141,6 +143,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
private pokerusGens: integer[] = [];
|
||||
private pokerusCursors: integer[] = [];
|
||||
private starterAttr: bigint[] = [];
|
||||
private starterAbilityIndexes: integer[] = [];
|
||||
private starterNatures: Nature[] = [];
|
||||
private starterMovesets: StarterMoveset[] = [];
|
||||
private speciesStarterDexEntry: DexEntry;
|
||||
@@ -150,6 +153,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
private canCycleGender: boolean;
|
||||
private canCycleAbility: boolean;
|
||||
private canCycleNature: boolean;
|
||||
private canCycleVariant: boolean;
|
||||
private value: integer = 0;
|
||||
|
||||
private assetLoadCancelled: Utils.BooleanHolder;
|
||||
@@ -162,7 +166,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
private valueLimitLabel: Phaser.GameObjects.Text;
|
||||
private startCursorObj: Phaser.GameObjects.NineSlice;
|
||||
private starterValueLabels: Phaser.GameObjects.Text[];
|
||||
private shinyIcons: Phaser.GameObjects.Image[];
|
||||
private shinyIcons: Phaser.GameObjects.Image[][];
|
||||
private hiddenAbilityIcons: Phaser.GameObjects.Image[];
|
||||
|
||||
private iconAnimHandler: PokemonIconAnimHandler;
|
||||
@@ -338,14 +342,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
starterSpecies.push(species.speciesId);
|
||||
this.speciesLoaded.set(species.speciesId, false);
|
||||
this.genSpecies[g].push(species);
|
||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species);
|
||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
||||
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||
const x = (s % 9) * 18;
|
||||
const y = Math.floor(s / 9) * 18;
|
||||
const icon = this.scene.add.sprite(x - 2, y + 2, species.getIconAtlasKey(defaultProps.formIndex));
|
||||
const icon = this.scene.add.sprite(x - 2, y + 2, species.getIconAtlasKey(defaultProps.formIndex, defaultProps.shiny, defaultProps.variant));
|
||||
icon.setScale(0.5);
|
||||
icon.setOrigin(0, 0);
|
||||
icon.setFrame(species.getIconId(defaultProps.female, defaultProps.formIndex, defaultProps.shiny));
|
||||
icon.setFrame(species.getIconId(defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant));
|
||||
icon.setTint(0);
|
||||
this.starterSelectGenIconContainers[g].add(icon);
|
||||
this.iconAnimHandler.addOrUpdate(icon, PokemonIconAnimMode.NONE);
|
||||
@@ -374,15 +378,19 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
return ret;
|
||||
});
|
||||
|
||||
this.shinyIcons = new Array(81).fill(null).map((_, i) => {
|
||||
const x = (i % 9) * 18;
|
||||
const getShinyStar = (i: integer, v: integer): Phaser.GameObjects.Image => {
|
||||
const x = (i % 9) * 18 - v * 3;
|
||||
const y = Math.floor(i / 9) * 18;
|
||||
const ret = this.scene.add.image(x + 163, y + 11, 'shiny_star');
|
||||
const ret = this.scene.add.image(x + 163, y + 11, 'shiny_star_small');
|
||||
ret.setOrigin(0, 0);
|
||||
ret.setScale(0.5);
|
||||
ret.setVisible(false);
|
||||
this.starterSelectContainer.add(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
this.shinyIcons = new Array(81).fill(null).map((_, i) => {
|
||||
return new Array(3).fill(null).map((_, v) => getShinyStar(i, v));
|
||||
});
|
||||
|
||||
this.hiddenAbilityIcons = new Array(81).fill(null).map((_, i) => {
|
||||
@@ -397,6 +405,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
});
|
||||
|
||||
this.pokemonSprite = this.scene.add.sprite(53, 63, `pkmn__sub`);
|
||||
this.pokemonSprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true });
|
||||
this.starterSelectContainer.add(this.pokemonSprite);
|
||||
|
||||
this.type1Icon = this.scene.add.sprite(8, 98, 'types');
|
||||
@@ -715,8 +724,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
cursorObj.setVisible(true);
|
||||
cursorObj.setPosition(this.cursorObj.x, this.cursorObj.y);
|
||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor);
|
||||
this.starterIcons[this.starterCursors.length].setTexture(species.getIconAtlasKey(props.formIndex));
|
||||
this.starterIcons[this.starterCursors.length].setFrame(species.getIconId(props.female, props.formIndex, props.shiny));
|
||||
this.starterIcons[this.starterCursors.length].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant));
|
||||
this.starterIcons[this.starterCursors.length].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant));
|
||||
this.starterGens.push(this.getGenCursorWithScroll());
|
||||
this.starterCursors.push(this.cursor);
|
||||
this.starterAttr.push(this.dexAttrCursor);
|
||||
@@ -814,7 +823,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
handler: () => {
|
||||
starterData.passiveAttr |= PassiveAttr.ENABLED;
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -824,7 +833,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
handler: () => {
|
||||
starterData.passiveAttr ^= PassiveAttr.ENABLED;
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -846,7 +855,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
return this.scene.reset(true);
|
||||
});
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, undefined);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -923,7 +932,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
switch (button) {
|
||||
case Button.CYCLE_SHINY:
|
||||
if (this.canCycleShiny) {
|
||||
this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, undefined, undefined);
|
||||
this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, props.shiny ? 0 : undefined, undefined, undefined);
|
||||
if (this.dexAttrCursor & DexAttr.SHINY)
|
||||
this.scene.playSound('sparkle');
|
||||
else
|
||||
@@ -939,34 +948,35 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
if (this.speciesStarterDexEntry.caughtAttr & this.scene.gameData.getFormAttr(newFormIndex))
|
||||
break;
|
||||
} while (newFormIndex !== props.formIndex);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined, undefined);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined, undefined, undefined);
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
case Button.CYCLE_GENDER:
|
||||
if (this.canCycleGender) {
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined, undefined);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined, undefined, undefined);
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
case Button.CYCLE_ABILITY:
|
||||
if (this.canCycleAbility) {
|
||||
const abilityCount = this.lastSpecies.getAbilityCount();
|
||||
let newAbilityIndex = props.abilityIndex;
|
||||
const abilityAttr = this.scene.gameData.starterData[this.lastSpecies.speciesId].abilityAttr;
|
||||
let newAbilityIndex = this.abilityCursor;
|
||||
do {
|
||||
newAbilityIndex = (newAbilityIndex + 1) % abilityCount;
|
||||
if (!newAbilityIndex) {
|
||||
if (this.speciesStarterDexEntry.caughtAttr & DexAttr.ABILITY_1)
|
||||
if (abilityAttr & AbilityAttr.ABILITY_1)
|
||||
break;
|
||||
} else if (newAbilityIndex === 1) {
|
||||
if (this.speciesStarterDexEntry.caughtAttr & (this.lastSpecies.ability2 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN))
|
||||
if (abilityAttr & (this.lastSpecies.ability2 ? AbilityAttr.ABILITY_2 : AbilityAttr.ABILITY_HIDDEN))
|
||||
break;
|
||||
} else {
|
||||
if (this.speciesStarterDexEntry.caughtAttr & DexAttr.ABILITY_HIDDEN)
|
||||
if (abilityAttr & AbilityAttr.ABILITY_HIDDEN)
|
||||
break;
|
||||
}
|
||||
} while (newAbilityIndex !== props.abilityIndex);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newAbilityIndex, undefined);
|
||||
} while (newAbilityIndex !== this.abilityCursor);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newAbilityIndex, undefined);
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
@@ -975,7 +985,27 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
const natures = this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry.natureAttr);
|
||||
const natureIndex = natures.indexOf(this.natureCursor);
|
||||
const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0];
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newNature);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newNature, undefined);
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
case Button.CYCLE_VARIANT:
|
||||
if (this.canCycleVariant) {
|
||||
let newVariant = props.variant;
|
||||
do {
|
||||
newVariant = (newVariant + 1) % 3;
|
||||
if (!newVariant) {
|
||||
if (this.speciesStarterDexEntry.caughtAttr & DexAttr.DEFAULT_VARIANT)
|
||||
break;
|
||||
} else if (newVariant === 1) {
|
||||
if (this.speciesStarterDexEntry.caughtAttr & DexAttr.VARIANT_2)
|
||||
break;
|
||||
} else {
|
||||
if (this.speciesStarterDexEntry.caughtAttr & DexAttr.VARIANT_3)
|
||||
break;
|
||||
}
|
||||
} while (newVariant !== props.variant);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant, undefined, undefined);
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
@@ -1043,7 +1073,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
}
|
||||
} else
|
||||
this.scene.gameData.starterData[speciesId].moveset = this.starterMoveset.slice(0) as StarterMoveset;
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, false);
|
||||
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, undefined, false);
|
||||
}
|
||||
|
||||
updateInstructions(): void {
|
||||
@@ -1060,6 +1090,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
cycleInstructionLines.push('E: Cycle Ability');
|
||||
if (this.canCycleNature)
|
||||
cycleInstructionLines.push('N: Cycle Nature');
|
||||
if (this.canCycleVariant)
|
||||
cycleInstructionLines.push('V: Cycle Variant');
|
||||
}
|
||||
|
||||
if (cycleInstructionLines.length > 2) {
|
||||
@@ -1123,8 +1155,16 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
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));
|
||||
this.hiddenAbilityIcons[s].setVisible(slotVisible && !!this.scene.gameData.dexData[speciesId].caughtAttr && !!(this.scene.gameData.dexData[speciesId].caughtAttr & DexAttr.ABILITY_HIDDEN));
|
||||
const speciesVariants = speciesId && this.scene.gameData.dexData[speciesId].caughtAttr & DexAttr.SHINY
|
||||
? [ DexAttr.DEFAULT_VARIANT, DexAttr.VARIANT_2, DexAttr.VARIANT_3 ].filter(v => !!(this.scene.gameData.dexData[speciesId].caughtAttr & v))
|
||||
: [];
|
||||
for (let v = 0; v < 3; v++) {
|
||||
const hasVariant = speciesVariants.length > v;
|
||||
this.shinyIcons[s][v].setVisible(slotVisible && hasVariant);
|
||||
if (hasVariant)
|
||||
this.shinyIcons[s][v].setTint(getVariantTint(speciesVariants[v] === DexAttr.DEFAULT_VARIANT ? 0 : speciesVariants[v] === DexAttr.VARIANT_2 ? 1 : 2));
|
||||
}
|
||||
this.hiddenAbilityIcons[s].setVisible(slotVisible && !!this.scene.gameData.dexData[speciesId].caughtAttr && !!(this.scene.gameData.starterData[speciesId].abilityAttr & 4));
|
||||
}
|
||||
} else {
|
||||
changed = super.setCursor(cursor);
|
||||
@@ -1177,7 +1217,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
||||
setSpecies(species: PokemonSpecies) {
|
||||
this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null;
|
||||
this.dexAttrCursor = species ? this.scene.gameData.getSpeciesDefaultDexAttr(species) : 0n;
|
||||
this.dexAttrCursor = species ? this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true) : 0n;
|
||||
this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0;
|
||||
this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(species) : 0;
|
||||
|
||||
if (this.statsMode) {
|
||||
@@ -1191,10 +1232,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
}
|
||||
|
||||
if (this.lastSpecies) {
|
||||
const dexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(this.lastSpecies);
|
||||
const dexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(this.lastSpecies, false, true);
|
||||
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);
|
||||
lastSpeciesIcon.setFrame(this.lastSpecies.getIconId(props.female, props.formIndex, props.shiny));
|
||||
lastSpeciesIcon.setTexture(this.lastSpecies.getIconAtlasKey(props.formIndex, props.shiny, props.variant), this.lastSpecies.getIconId(props.female, props.formIndex, props.shiny, props.variant));
|
||||
this.iconAnimHandler.addOrUpdate(lastSpeciesIcon, PokemonIconAnimMode.NONE);
|
||||
}
|
||||
|
||||
@@ -1247,13 +1288,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
||||
if (starterIndex > -1) {
|
||||
props = this.scene.gameData.getSpeciesDexAttrProps(species, this.starterAttr[starterIndex]);
|
||||
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.abilityIndex, this.starterNatures[starterIndex]);
|
||||
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, this.starterAbilityIndexes[starterIndex], this.starterNatures[starterIndex]);
|
||||
} else {
|
||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species);
|
||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
||||
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
||||
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
|
||||
props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||
|
||||
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.abilityIndex, defaultNature);
|
||||
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, defaultAbilityIndex, defaultNature);
|
||||
}
|
||||
|
||||
const speciesForm = getPokemonSpeciesForm(species.speciesId, props.formIndex);
|
||||
@@ -1276,11 +1318,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
this.pokemonCandyOverlayIcon.setVisible(false);
|
||||
this.pokemonCandyCountText.setVisible(false);
|
||||
|
||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, true);
|
||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, true, true);
|
||||
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
||||
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
|
||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||
|
||||
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.abilityIndex, defaultNature, true);
|
||||
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, defaultAbilityIndex, defaultNature, true);
|
||||
this.pokemonSprite.setTint(0x808080);
|
||||
}
|
||||
} else {
|
||||
@@ -1299,15 +1342,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
this.pokemonCandyOverlayIcon.setVisible(false);
|
||||
this.pokemonCandyCountText.setVisible(false);
|
||||
|
||||
this.setSpeciesDetails(species, false, 0, false, 0, 0);
|
||||
this.setSpeciesDetails(species, false, 0, false, 0, 0, 0);
|
||||
this.pokemonSprite.clearTint();
|
||||
}
|
||||
}
|
||||
|
||||
setSpeciesDetails(species: PokemonSpecies, shiny: boolean, formIndex: integer, female: boolean, abilityIndex: integer, natureIndex: integer, forSeen: boolean = false): void {
|
||||
setSpeciesDetails(species: PokemonSpecies, shiny: boolean, formIndex: integer, female: boolean, variant: Variant, abilityIndex: integer, natureIndex: integer, forSeen: boolean = false): void {
|
||||
const oldProps = species ? this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null;
|
||||
const oldAbilityIndex = this.abilityCursor > -1 ? this.abilityCursor : this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
||||
const oldNatureIndex = this.natureCursor > -1 ? this.natureCursor : this.scene.gameData.getSpeciesDefaultNature(species);
|
||||
this.dexAttrCursor = 0n;
|
||||
this.abilityCursor = -1;
|
||||
this.natureCursor = -1;
|
||||
|
||||
if (species?.forms?.find(f => f.formKey === 'female')) {
|
||||
@@ -1320,8 +1365,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
if (species) {
|
||||
this.dexAttrCursor |= (shiny !== undefined ? !shiny : !(shiny = oldProps.shiny)) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||
this.dexAttrCursor |= (female !== undefined ? !female : !(female = oldProps.female)) ? DexAttr.MALE : DexAttr.FEMALE;
|
||||
this.dexAttrCursor |= (abilityIndex !== undefined ? !abilityIndex : !(abilityIndex = oldProps.abilityIndex)) ? DexAttr.ABILITY_1 : species.ability2 && abilityIndex === 1 ? DexAttr.ABILITY_2 : DexAttr.ABILITY_HIDDEN;
|
||||
this.dexAttrCursor |= (variant !== undefined ? !variant : !(variant = oldProps.variant)) ? DexAttr.DEFAULT_VARIANT : variant === 1 ? DexAttr.VARIANT_2 : DexAttr.VARIANT_3;
|
||||
this.dexAttrCursor |= this.scene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps.formIndex));
|
||||
this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex);
|
||||
this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex);
|
||||
}
|
||||
|
||||
@@ -1337,8 +1383,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
||||
if (species) {
|
||||
const dexEntry = this.scene.gameData.dexData[species.speciesId];
|
||||
const abilityAttr = this.scene.gameData.starterData[species.speciesId].abilityAttr;
|
||||
if (!dexEntry.caughtAttr) {
|
||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, forSeen));
|
||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, forSeen, !forSeen));
|
||||
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
||||
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
|
||||
if (shiny === undefined || shiny !== props.shiny)
|
||||
shiny = props.shiny;
|
||||
@@ -1346,8 +1394,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
formIndex = props.formIndex;
|
||||
if (female === undefined || female !== props.female)
|
||||
female = props.female;
|
||||
if (abilityIndex === undefined || abilityIndex !== props.abilityIndex)
|
||||
abilityIndex = props.abilityIndex;
|
||||
if (variant === undefined || variant !== props.variant)
|
||||
variant = props.variant;
|
||||
if (abilityIndex === undefined || abilityIndex !== defaultAbilityIndex)
|
||||
abilityIndex = defaultAbilityIndex;
|
||||
if (natureIndex === undefined || natureIndex !== defaultNature)
|
||||
natureIndex = defaultNature;
|
||||
}
|
||||
@@ -1376,23 +1426,27 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
const assetLoadCancelled = new Utils.BooleanHolder(false);
|
||||
this.assetLoadCancelled = assetLoadCancelled;
|
||||
|
||||
species.loadAssets(this.scene, female, formIndex, shiny, true).then(() => {
|
||||
species.loadAssets(this.scene, female, formIndex, shiny, variant, true).then(() => {
|
||||
if (assetLoadCancelled.value)
|
||||
return;
|
||||
this.assetLoadCancelled = null;
|
||||
this.speciesLoaded.set(species.speciesId, true);
|
||||
this.pokemonSprite.play(species.getSpriteKey(female, formIndex, shiny));
|
||||
this.pokemonSprite.play(species.getSpriteKey(female, formIndex, shiny, variant));
|
||||
this.pokemonSprite.setPipelineData('variant', variant);
|
||||
this.pokemonSprite.setPipelineData('spriteKey', species.getSpriteKey(female, formIndex, shiny, variant));
|
||||
this.pokemonSprite.setVisible(!this.statsMode);
|
||||
});
|
||||
|
||||
(this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite).setFrame(species.getIconId(female, formIndex, shiny));
|
||||
(this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite)
|
||||
.setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female, formIndex, shiny, variant));
|
||||
|
||||
this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY);
|
||||
this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE);
|
||||
this.canCycleAbility = [ dexEntry.caughtAttr & DexAttr.ABILITY_1, dexEntry.caughtAttr & DexAttr.ABILITY_2, dexEntry.caughtAttr & DexAttr.ABILITY_HIDDEN ].filter(a => a).length > 1;
|
||||
this.canCycleAbility = [ abilityAttr & AbilityAttr.ABILITY_1, abilityAttr & AbilityAttr.ABILITY_2, abilityAttr & AbilityAttr.ABILITY_HIDDEN ].filter(a => a).length > 1;
|
||||
this.canCycleForm = species.forms.filter(f => !f.formKey || !pokemonFormChanges[species.speciesId]?.find(fc => fc.formKey))
|
||||
.map((_, f) => dexEntry.caughtAttr & this.scene.gameData.getFormAttr(f)).filter(a => a).length > 1;
|
||||
.map((_, f) => dexEntry.caughtAttr & this.scene.gameData.getFormAttr(f)).filter(f => f).length > 1;
|
||||
this.canCycleNature = this.scene.gameData.getNaturesForAttr(dexEntry.natureAttr).length > 1;
|
||||
this.canCycleVariant = shiny && [ dexEntry.caughtAttr & DexAttr.DEFAULT_VARIANT, dexEntry.caughtAttr & DexAttr.VARIANT_2, dexEntry.caughtAttr & DexAttr.VARIANT_3].filter(v => v).length > 1;
|
||||
}
|
||||
|
||||
if (dexEntry.caughtAttr && species.malePercent !== null) {
|
||||
@@ -1589,8 +1643,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
return {
|
||||
species: starterSpecies,
|
||||
dexAttr: thisObj.starterAttr[i],
|
||||
abilityIndex: thisObj.starterAbilityIndexes[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
|
||||
|
||||
@@ -16,6 +16,7 @@ import { getBiomeName } from "../data/biomes";
|
||||
import { Nature, getNatureStatMultiplier } from "../data/nature";
|
||||
import { loggedInUser } from "../account";
|
||||
import { PlayerGender } from "../system/game-data";
|
||||
import { getVariantTint } from "#app/data/variant";
|
||||
|
||||
enum Page {
|
||||
PROFILE,
|
||||
@@ -41,7 +42,7 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
private pokeball: Phaser.GameObjects.Sprite;
|
||||
private levelText: Phaser.GameObjects.Text;
|
||||
private genderText: Phaser.GameObjects.Text;
|
||||
private shinyStar: Phaser.GameObjects.Image;
|
||||
private shinyIcon: Phaser.GameObjects.Image;
|
||||
private statusContainer: Phaser.GameObjects.Container;
|
||||
private status: Phaser.GameObjects.Image;
|
||||
private summaryPageContainer: Phaser.GameObjects.Container;
|
||||
@@ -116,6 +117,13 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.splicedIcon.setScale(0.75);
|
||||
this.splicedIcon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 12, 15), Phaser.Geom.Rectangle.Contains);
|
||||
this.summaryContainer.add(this.splicedIcon);
|
||||
|
||||
this.shinyIcon = this.scene.add.image(0, -54, 'shiny_star');
|
||||
this.shinyIcon.setVisible(false);
|
||||
this.shinyIcon.setOrigin(0, 0);
|
||||
this.shinyIcon.setScale(0.75);
|
||||
this.shinyIcon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 12, 15), Phaser.Geom.Rectangle.Contains);
|
||||
this.summaryContainer.add(this.shinyIcon);
|
||||
|
||||
this.pokeball = this.scene.add.sprite(6, -19, 'pb');
|
||||
this.pokeball.setOrigin(0, 1);
|
||||
@@ -129,10 +137,7 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.genderText.setOrigin(0, 1);
|
||||
this.summaryContainer.add(this.genderText);
|
||||
|
||||
this.shinyStar = this.scene.add.image(96, -19, 'shiny_star');
|
||||
this.shinyStar.setOrigin(0, 1);
|
||||
this.shinyStar.setVisible(false);
|
||||
this.summaryContainer.add(this.shinyStar);
|
||||
|
||||
|
||||
this.statusContainer = this.scene.add.container(-106, -16);
|
||||
|
||||
@@ -217,8 +222,10 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.numberText.setShadowColor(this.getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD, true));
|
||||
|
||||
this.pokemonSprite.play(this.pokemon.getSpriteKey(true));
|
||||
this.pokemonSprite.pipelineData['teraColor'] = getTypeRgb(this.pokemon.getTeraType());
|
||||
this.pokemonSprite.pipelineData['ignoreTimeTint'] = true;
|
||||
this.pokemonSprite.setPipelineData('teraColor', getTypeRgb(this.pokemon.getTeraType()));
|
||||
this.pokemonSprite.setPipelineData('ignoreTimeTint', true);
|
||||
this.pokemonSprite.setPipelineData('spriteKey', this.pokemon.getSpriteKey());
|
||||
this.pokemonSprite.setPipelineData('variant', this.pokemon.variant);
|
||||
[ 'spriteColors', 'fusionSpriteColors' ].map(k => {
|
||||
delete this.pokemonSprite.pipelineData[`${k}Base`];
|
||||
if (this.pokemon.summonData?.speciesForm)
|
||||
@@ -235,6 +242,14 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.splicedIcon.on('pointerover', () => (this.scene as BattleScene).ui.showTooltip(null, `${this.pokemon.species.getName(this.pokemon.formIndex)}/${this.pokemon.fusionSpecies.getName(this.pokemon.fusionFormIndex)}`, true));
|
||||
this.splicedIcon.on('pointerout', () => (this.scene as BattleScene).ui.hideTooltip());
|
||||
}
|
||||
|
||||
this.shinyIcon.setPositionRelative(this.nameText, this.nameText.displayWidth + (this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0) + 1, 3);
|
||||
this.shinyIcon.setTint(getVariantTint(this.pokemon.getVariant()));
|
||||
this.shinyIcon.setVisible(this.pokemon.isShiny());
|
||||
if (this.shinyIcon.visible) {
|
||||
this.shinyIcon.on('pointerover', () => (this.scene as BattleScene).ui.showTooltip(null, `Shiny${this.pokemon.getVariant() ? ` (${this.pokemon.getVariant() === 2 ? 'Epic' : 'Rare'})` : ''}`, true));
|
||||
this.shinyIcon.on('pointerout', () => (this.scene as BattleScene).ui.hideTooltip());
|
||||
}
|
||||
|
||||
this.pokeball.setFrame(getPokeballAtlasKey(this.pokemon.pokeball));
|
||||
this.levelText.setText(this.pokemon.level.toString());
|
||||
@@ -242,9 +257,6 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.genderText.setColor(getGenderColor(this.pokemon.getGender(true)));
|
||||
this.genderText.setShadowColor(getGenderColor(this.pokemon.getGender(true), true));
|
||||
|
||||
this.shinyStar.setX(96 - (this.genderText.text ? 10 : 0));
|
||||
this.shinyStar.setVisible(this.pokemon.isShiny());
|
||||
|
||||
switch (this.summaryUiMode) {
|
||||
case SummaryUiMode.DEFAULT:
|
||||
const page = args.length < 2 ? Page.PROFILE : args[2] as Page;
|
||||
|
||||
@@ -321,4 +321,8 @@ export function rgbHexToRgba(hex: string) {
|
||||
b: parseInt(color[3], 16),
|
||||
a: 255
|
||||
};
|
||||
}
|
||||
|
||||
export function rgbaToInt(rgba: integer[]): integer {
|
||||
return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3];
|
||||
}
|
||||
Reference in new issue
Block a user