Add tiered shiny variants

This commit is contained in:
Flashfyre committed 2024-04-18 22:52:26 -04:00
1 parent a6ddda38ae
commit c76f8c5e7e
690 files changed
+94645 -199

No files matched your search

+42 -28
View File
@@ -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;
}
}
}
+3 -1
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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) {
+4
View File
@@ -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 => {
+18
View File
@@ -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;
}
}
+1 -1
View File
@@ -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
View File
@@ -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);
+9 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
}
}
}
+5 -2
View File
@@ -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
View File
@@ -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) {
+4 -2
View File
@@ -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);
}
+101 -47
View File
@@ -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
+22 -10
View File
@@ -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;
+4
View File
@@ -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];
}