Merge branch 'pagefaultgames:main' into MovesTS-Comments
10817
public/images/items.json
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 400 B |
|
After Width: | Height: | Size: 408 B |
|
After Width: | Height: | Size: 408 B |
|
After Width: | Height: | Size: 407 B |
|
After Width: | Height: | Size: 406 B |
|
After Width: | Height: | Size: 285 B |
|
After Width: | Height: | Size: 285 B |
|
|
@ -1826,6 +1826,19 @@ function getAnticipationCondition(): AbAttrCondition {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an ability condition that causes the ability to fail if that ability
|
||||||
|
* has already been used by that pokemon that battle. It requires an ability to
|
||||||
|
* be specified due to current limitations in how conditions on abilities work.
|
||||||
|
* @param {Abilities} ability The ability to check if it's already been applied
|
||||||
|
* @returns {AbAttrCondition} The condition
|
||||||
|
*/
|
||||||
|
function getOncePerBattleCondition(ability: Abilities): AbAttrCondition {
|
||||||
|
return (pokemon: Pokemon) => {
|
||||||
|
return !pokemon.battleData?.abilitiesApplied.includes(ability);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class ForewarnAbAttr extends PostSummonAbAttr {
|
export class ForewarnAbAttr extends PostSummonAbAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true);
|
super(true);
|
||||||
|
|
@ -2522,6 +2535,9 @@ function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any
|
||||||
return applyNextAbAttr();
|
return applyNextAbAttr();
|
||||||
pokemon.scene.setPhaseQueueSplice();
|
pokemon.scene.setPhaseQueueSplice();
|
||||||
const onApplySuccess = () => {
|
const onApplySuccess = () => {
|
||||||
|
if (pokemon.battleData && !pokemon.battleData.abilitiesApplied.includes(ability.id)) {
|
||||||
|
pokemon.battleData.abilitiesApplied.push(ability.id);
|
||||||
|
}
|
||||||
if (attr.showAbility && !quiet) {
|
if (attr.showAbility && !quiet) {
|
||||||
if (showAbilityInstant)
|
if (showAbilityInstant)
|
||||||
pokemon.scene.abilityBar.showAbility(pokemon, passive);
|
pokemon.scene.abilityBar.showAbility(pokemon, passive);
|
||||||
|
|
@ -3379,9 +3395,11 @@ export function initAbilities() {
|
||||||
new Ability(Abilities.NEUROFORCE, 7)
|
new Ability(Abilities.NEUROFORCE, 7)
|
||||||
.attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 1.25),
|
.attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 1.25),
|
||||||
new Ability(Abilities.INTREPID_SWORD, 8)
|
new Ability(Abilities.INTREPID_SWORD, 8)
|
||||||
.attr(PostSummonStatChangeAbAttr, BattleStat.ATK, 1, true),
|
.attr(PostSummonStatChangeAbAttr, BattleStat.ATK, 1, true)
|
||||||
|
.condition(getOncePerBattleCondition(Abilities.INTREPID_SWORD)),
|
||||||
new Ability(Abilities.DAUNTLESS_SHIELD, 8)
|
new Ability(Abilities.DAUNTLESS_SHIELD, 8)
|
||||||
.attr(PostSummonStatChangeAbAttr, BattleStat.DEF, 1, true),
|
.attr(PostSummonStatChangeAbAttr, BattleStat.DEF, 1, true)
|
||||||
|
.condition(getOncePerBattleCondition(Abilities.DAUNTLESS_SHIELD)),
|
||||||
new Ability(Abilities.LIBERO, 8)
|
new Ability(Abilities.LIBERO, 8)
|
||||||
.unimplemented(),
|
.unimplemented(),
|
||||||
new Ability(Abilities.BALL_FETCH, 8)
|
new Ability(Abilities.BALL_FETCH, 8)
|
||||||
|
|
@ -3590,7 +3608,8 @@ export function initAbilities() {
|
||||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
|
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
|
||||||
.ignorable(), // TODO: evasiveness bypass should not be ignored, but accuracy immunity should
|
.ignorable(), // TODO: evasiveness bypass should not be ignored, but accuracy immunity should
|
||||||
new Ability(Abilities.SUPERSWEET_SYRUP, 9)
|
new Ability(Abilities.SUPERSWEET_SYRUP, 9)
|
||||||
.unimplemented(),
|
.attr(PostSummonStatChangeAbAttr, BattleStat.EVA, -1)
|
||||||
|
.condition(getOncePerBattleCondition(Abilities.SUPERSWEET_SYRUP)),
|
||||||
new Ability(Abilities.HOSPITALITY, 9)
|
new Ability(Abilities.HOSPITALITY, 9)
|
||||||
.attr(PostSummonAllyHealAbAttr, 4, true),
|
.attr(PostSummonAllyHealAbAttr, 4, true),
|
||||||
new Ability(Abilities.TOXIC_CHAIN, 9)
|
new Ability(Abilities.TOXIC_CHAIN, 9)
|
||||||
|
|
|
||||||
|
|
@ -4305,12 +4305,12 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||||
[Species.GROVYLE]: [
|
[Species.GROVYLE]: [
|
||||||
[ 1, Moves.POUND ],
|
[ 1, Moves.POUND ],
|
||||||
[ 1, Moves.LEER ],
|
[ 1, Moves.LEER ],
|
||||||
|
[ 1, Moves.LEAFAGE ],
|
||||||
[ 1, Moves.QUICK_ATTACK ],
|
[ 1, Moves.QUICK_ATTACK ],
|
||||||
[ 1, Moves.FALSE_SWIPE ],
|
[ 1, Moves.FALSE_SWIPE ],
|
||||||
[ 1, Moves.FURY_CUTTER ],
|
[ 1, Moves.FURY_CUTTER ],
|
||||||
[ 1, Moves.X_SCISSOR ],
|
[ 1, Moves.X_SCISSOR ],
|
||||||
[ 1, Moves.ENERGY_BALL ],
|
[ 1, Moves.ENERGY_BALL ],
|
||||||
[ 1, Moves.LEAFAGE ],
|
|
||||||
[ 9, Moves.MEGA_DRAIN ],
|
[ 9, Moves.MEGA_DRAIN ],
|
||||||
[ 12, Moves.DETECT ],
|
[ 12, Moves.DETECT ],
|
||||||
[ 15, Moves.QUICK_GUARD ],
|
[ 15, Moves.QUICK_GUARD ],
|
||||||
|
|
@ -4324,15 +4324,16 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||||
[ 55, Moves.LEAF_STORM ],
|
[ 55, Moves.LEAF_STORM ],
|
||||||
],
|
],
|
||||||
[Species.SCEPTILE]: [
|
[Species.SCEPTILE]: [
|
||||||
[ 0, Moves.DUAL_CHOP ],
|
[ 0, Moves.LEAF_BLADE ],
|
||||||
[ 1, Moves.POUND ],
|
[ 1, Moves.POUND ],
|
||||||
[ 1, Moves.LEER ],
|
[ 1, Moves.LEER ],
|
||||||
|
[ 1, Moves.LEAFAGE ],
|
||||||
[ 1, Moves.QUICK_ATTACK ],
|
[ 1, Moves.QUICK_ATTACK ],
|
||||||
[ 1, Moves.FALSE_SWIPE ],
|
[ 1, Moves.FALSE_SWIPE ],
|
||||||
[ 1, Moves.FURY_CUTTER ],
|
[ 1, Moves.FURY_CUTTER ],
|
||||||
[ 1, Moves.X_SCISSOR ],
|
[ 1, Moves.X_SCISSOR ],
|
||||||
[ 1, Moves.ENERGY_BALL ],
|
[ 1, Moves.ENERGY_BALL ],
|
||||||
[ 1, Moves.LEAFAGE ],
|
[ 1, Moves.SHED_TAIL ],
|
||||||
[ 5, Moves.MEGA_DRAIN ],
|
[ 5, Moves.MEGA_DRAIN ],
|
||||||
[ 12, Moves.DETECT ],
|
[ 12, Moves.DETECT ],
|
||||||
[ 15, Moves.QUICK_GUARD ],
|
[ 15, Moves.QUICK_GUARD ],
|
||||||
|
|
@ -4340,10 +4341,9 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||||
[ 25, Moves.GIGA_DRAIN ],
|
[ 25, Moves.GIGA_DRAIN ],
|
||||||
[ 30, Moves.SLAM ],
|
[ 30, Moves.SLAM ],
|
||||||
[ 35, Moves.DOUBLE_TEAM ],
|
[ 35, Moves.DOUBLE_TEAM ],
|
||||||
[ 42, Moves.LEAF_BLADE ],
|
[ 42, Moves.SCREECH ],
|
||||||
[ 49, Moves.SCREECH ],
|
[ 49, Moves.ENDEAVOR ],
|
||||||
[ 56, Moves.ENDEAVOR ],
|
[ 56, Moves.LEAF_STORM ],
|
||||||
[ 63, Moves.LEAF_STORM ],
|
|
||||||
],
|
],
|
||||||
[Species.TORCHIC]: [
|
[Species.TORCHIC]: [
|
||||||
[ 1, Moves.SCRATCH ],
|
[ 1, Moves.SCRATCH ],
|
||||||
|
|
@ -4367,9 +4367,9 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||||
[ 1, Moves.SCRATCH ],
|
[ 1, Moves.SCRATCH ],
|
||||||
[ 1, Moves.GROWL ],
|
[ 1, Moves.GROWL ],
|
||||||
[ 1, Moves.EMBER ],
|
[ 1, Moves.EMBER ],
|
||||||
|
[ 1, Moves.QUICK_ATTACK ],
|
||||||
[ 1, Moves.FLAMETHROWER ],
|
[ 1, Moves.FLAMETHROWER ],
|
||||||
[ 1, Moves.QUICK_ATTACK ],
|
[ 1, Moves.FEATHER_DANCE ],
|
||||||
[ 1, Moves.FEATHER_DANCE ],
|
|
||||||
[ 9, Moves.FLAME_CHARGE ],
|
[ 9, Moves.FLAME_CHARGE ],
|
||||||
[ 12, Moves.DETECT ],
|
[ 12, Moves.DETECT ],
|
||||||
[ 15, Moves.SAND_ATTACK ],
|
[ 15, Moves.SAND_ATTACK ],
|
||||||
|
|
@ -4399,10 +4399,10 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||||
[ 25, Moves.SLASH ],
|
[ 25, Moves.SLASH ],
|
||||||
[ 30, Moves.BOUNCE ],
|
[ 30, Moves.BOUNCE ],
|
||||||
[ 35, Moves.FOCUS_ENERGY ],
|
[ 35, Moves.FOCUS_ENERGY ],
|
||||||
[ 42, Moves.BLAZE_KICK ],
|
[ 42, Moves.BULK_UP ],
|
||||||
[ 49, Moves.BULK_UP ],
|
[ 49, Moves.REVERSAL ],
|
||||||
[ 56, Moves.REVERSAL ],
|
[ 56, Moves.FLARE_BLITZ ],
|
||||||
[ 63, Moves.FLARE_BLITZ ],
|
[ 63, Moves.BRAVE_BIRD ],
|
||||||
],
|
],
|
||||||
[Species.MUDKIP]: [
|
[Species.MUDKIP]: [
|
||||||
[ 1, Moves.TACKLE ],
|
[ 1, Moves.TACKLE ],
|
||||||
|
|
@ -4426,8 +4426,6 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||||
[ 1, Moves.TACKLE ],
|
[ 1, Moves.TACKLE ],
|
||||||
[ 1, Moves.GROWL ],
|
[ 1, Moves.GROWL ],
|
||||||
[ 1, Moves.WATER_GUN ],
|
[ 1, Moves.WATER_GUN ],
|
||||||
[ 1, Moves.SURF ],
|
|
||||||
[ 1, Moves.EARTHQUAKE ],
|
|
||||||
[ 1, Moves.ROCK_SMASH ],
|
[ 1, Moves.ROCK_SMASH ],
|
||||||
[ 9, Moves.ROCK_THROW ],
|
[ 9, Moves.ROCK_THROW ],
|
||||||
[ 12, Moves.PROTECT ],
|
[ 12, Moves.PROTECT ],
|
||||||
|
|
@ -4442,13 +4440,13 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||||
[ 55, Moves.HYDRO_PUMP ],
|
[ 55, Moves.HYDRO_PUMP ],
|
||||||
],
|
],
|
||||||
[Species.SWAMPERT]: [
|
[Species.SWAMPERT]: [
|
||||||
|
[ 1, Moves.MUD_SHOT ],
|
||||||
[ 1, Moves.TACKLE ],
|
[ 1, Moves.TACKLE ],
|
||||||
[ 1, Moves.GROWL ],
|
[ 1, Moves.GROWL ],
|
||||||
[ 1, Moves.WATER_GUN ],
|
[ 1, Moves.WATER_GUN ],
|
||||||
[ 1, Moves.SURF ],
|
[ 1, Moves.SURF ],
|
||||||
[ 1, Moves.EARTHQUAKE ],
|
[ 1, Moves.EARTHQUAKE ],
|
||||||
[ 1, Moves.ROCK_SMASH ],
|
[ 1, Moves.ROCK_SMASH ],
|
||||||
[ 1, Moves.MUD_SHOT ],
|
|
||||||
[ 1, Moves.HAMMER_ARM ],
|
[ 1, Moves.HAMMER_ARM ],
|
||||||
[ 9, Moves.ROCK_THROW ],
|
[ 9, Moves.ROCK_THROW ],
|
||||||
[ 12, Moves.PROTECT ],
|
[ 12, Moves.PROTECT ],
|
||||||
|
|
|
||||||
|
|
@ -1708,18 +1708,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cry(soundConfig?: Phaser.Types.Sound.SoundConfig): AnySound {
|
cry(soundConfig?: Phaser.Types.Sound.SoundConfig, sceneOverride?: BattleScene): AnySound {
|
||||||
const cry = this.getSpeciesForm().cry(this.scene, soundConfig);
|
const scene = sceneOverride || this.scene;
|
||||||
|
const cry = this.getSpeciesForm().cry(scene, soundConfig);
|
||||||
let duration = cry.totalDuration * 1000;
|
let duration = cry.totalDuration * 1000;
|
||||||
if (this.fusionSpecies) {
|
if (this.fusionSpecies) {
|
||||||
let fusionCry = this.getFusionSpeciesForm().cry(this.scene, soundConfig, true);
|
let fusionCry = this.getFusionSpeciesForm().cry(scene, soundConfig, true);
|
||||||
duration = Math.min(duration, fusionCry.totalDuration * 1000);
|
duration = Math.min(duration, fusionCry.totalDuration * 1000);
|
||||||
fusionCry.destroy();
|
fusionCry.destroy();
|
||||||
this.scene.time.delayedCall(Utils.fixedInt(Math.ceil(duration * 0.4)), () => {
|
scene.time.delayedCall(Utils.fixedInt(Math.ceil(duration * 0.4)), () => {
|
||||||
try {
|
try {
|
||||||
SoundFade.fadeOut(this.scene, cry, Utils.fixedInt(Math.ceil(duration * 0.2)));
|
SoundFade.fadeOut(scene, cry, Utils.fixedInt(Math.ceil(duration * 0.2)));
|
||||||
fusionCry = this.getFusionSpeciesForm().cry(this.scene, Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0) }, soundConfig));
|
fusionCry = this.getFusionSpeciesForm().cry(scene, Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0) }, soundConfig));
|
||||||
SoundFade.fadeIn(this.scene, fusionCry, Utils.fixedInt(Math.ceil(duration * 0.2)), this.scene.masterVolume * this.scene.seVolume, 0);
|
SoundFade.fadeIn(scene, fusionCry, Utils.fixedInt(Math.ceil(duration * 0.2)), scene.masterVolume * scene.seVolume, 0);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|
@ -3133,6 +3134,7 @@ export class PokemonBattleData {
|
||||||
public hitCount: integer = 0;
|
public hitCount: integer = 0;
|
||||||
public endured: boolean = false;
|
public endured: boolean = false;
|
||||||
public berriesEaten: BerryType[] = [];
|
public berriesEaten: BerryType[] = [];
|
||||||
|
public abilitiesApplied: Abilities[] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonBattleSummonData {
|
export class PokemonBattleSummonData {
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ export class LoadingScene extends SceneBase {
|
||||||
this.loadImage('shiny_star_small_1', 'ui', 'shiny_small_1.png');
|
this.loadImage('shiny_star_small_1', 'ui', 'shiny_small_1.png');
|
||||||
this.loadImage('shiny_star_small_2', 'ui', 'shiny_small_2.png');
|
this.loadImage('shiny_star_small_2', 'ui', 'shiny_small_2.png');
|
||||||
this.loadImage('ha_capsule', 'ui', 'ha_capsule.png');
|
this.loadImage('ha_capsule', 'ui', 'ha_capsule.png');
|
||||||
|
this.loadImage('champion_ribbon', 'ui', 'champion_ribbon.png');
|
||||||
this.loadImage('icon_spliced', 'ui');
|
this.loadImage('icon_spliced', 'ui');
|
||||||
this.loadImage('icon_tera', 'ui');
|
this.loadImage('icon_tera', 'ui');
|
||||||
this.loadImage('type_tera', 'ui');
|
this.loadImage('type_tera', 'ui');
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,7 @@ export class PokemonNatureChangeModifierType extends PokemonModifierType {
|
||||||
protected nature: Nature;
|
protected nature: Nature;
|
||||||
|
|
||||||
constructor(nature: Nature) {
|
constructor(nature: Nature) {
|
||||||
super(`${getNatureName(nature)} Mint`, `Changes a Pokémon\'s nature to ${getNatureName(nature, true, true, true)}`, ((_type, args) => new Modifiers.PokemonNatureChangeModifier(this, (args[0] as PlayerPokemon).id, this.nature)),
|
super(`${getNatureName(nature)} Mint`, `Changes a Pokémon\'s nature to ${getNatureName(nature, true, true, true)} and permanently unlocks the nature for the starter.`, ((_type, args) => new Modifiers.PokemonNatureChangeModifier(this, (args[0] as PlayerPokemon).id, this.nature)),
|
||||||
((pokemon: PlayerPokemon) => {
|
((pokemon: PlayerPokemon) => {
|
||||||
if (pokemon.getNature() === this.nature)
|
if (pokemon.getNature() === this.nature)
|
||||||
return PartyUiHandler.NoEffectMessage;
|
return PartyUiHandler.NoEffectMessage;
|
||||||
|
|
@ -1004,7 +1004,7 @@ const modifierPool: ModifierPool = {
|
||||||
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
|
||||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||||
return faintedPartyMemberCount * 9;
|
return faintedPartyMemberCount * 9;
|
||||||
}, 3),
|
}, 27),
|
||||||
new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => {
|
||||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||||
return faintedPartyMemberCount * 3;
|
return faintedPartyMemberCount * 3;
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,14 @@ import { Stat } from "../data/pokemon-stat";
|
||||||
import { addTextObject, TextStyle } from "../ui/text";
|
import { addTextObject, TextStyle } from "../ui/text";
|
||||||
import { Type } from '../data/type';
|
import { Type } from '../data/type';
|
||||||
import { EvolutionPhase } from '../evolution-phase';
|
import { EvolutionPhase } from '../evolution-phase';
|
||||||
import { FusionSpeciesFormEvolution, pokemonEvolutions } from '../data/pokemon-evolutions';
|
import { FusionSpeciesFormEvolution, pokemonEvolutions, pokemonPrevolutions } from '../data/pokemon-evolutions';
|
||||||
import { getPokemonMessage } from '../messages';
|
import { getPokemonMessage } from '../messages';
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import { TempBattleStat } from '../data/temp-battle-stat';
|
import { TempBattleStat } from '../data/temp-battle-stat';
|
||||||
import { BerryType, getBerryEffectFunc, getBerryPredicate } from '../data/berry';
|
import { BerryType, getBerryEffectFunc, getBerryPredicate } from '../data/berry';
|
||||||
import { StatusEffect, getStatusEffectHealText } from '../data/status-effect';
|
import { StatusEffect, getStatusEffectHealText } from '../data/status-effect';
|
||||||
import { MoneyAchv, achvs } from '../system/achv';
|
import { achvs } from '../system/achv';
|
||||||
import { VoucherType } from '../system/voucher';
|
import { VoucherType } from '../system/voucher';
|
||||||
import { PreventBerryUseAbAttr, applyAbAttrs } from '../data/ability';
|
|
||||||
import { FormChangeItem, SpeciesFormChangeItemTrigger } from '../data/pokemon-forms';
|
import { FormChangeItem, SpeciesFormChangeItemTrigger } from '../data/pokemon-forms';
|
||||||
import { Nature } from '#app/data/nature';
|
import { Nature } from '#app/data/nature';
|
||||||
import { BattlerTagType } from '#app/data/enums/battler-tag-type';
|
import { BattlerTagType } from '#app/data/enums/battler-tag-type';
|
||||||
|
|
@ -1090,6 +1089,13 @@ export class PokemonNatureChangeModifier extends ConsumablePokemonModifier {
|
||||||
apply(args: any[]): boolean {
|
apply(args: any[]): boolean {
|
||||||
const pokemon = args[0] as Pokemon;
|
const pokemon = args[0] as Pokemon;
|
||||||
pokemon.natureOverride = this.nature;
|
pokemon.natureOverride = this.nature;
|
||||||
|
let speciesId = pokemon.species.speciesId;
|
||||||
|
pokemon.scene.gameData.dexData[speciesId].natureAttr |= Math.pow(2, this.nature + 1);
|
||||||
|
|
||||||
|
while (pokemonPrevolutions.hasOwnProperty(speciesId)) {
|
||||||
|
speciesId = pokemonPrevolutions[speciesId];
|
||||||
|
pokemon.scene.gameData.dexData[speciesId].natureAttr |= Math.pow(2, this.nature + 1);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import BattleScene, { bypassLogin, startingWave } from "./battle-scene";
|
import BattleScene, { AnySound, bypassLogin, startingWave } from "./battle-scene";
|
||||||
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon";
|
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon";
|
||||||
import * as Utils from './utils';
|
import * as Utils from './utils';
|
||||||
import { Moves } from "./data/enums/moves";
|
import { Moves } from "./data/enums/moves";
|
||||||
|
|
@ -55,7 +55,7 @@ import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select
|
||||||
import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler";
|
import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler";
|
||||||
import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run";
|
import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run";
|
||||||
import { GameModes, gameModes } from "./game-mode";
|
import { GameModes, gameModes } from "./game-mode";
|
||||||
import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species";
|
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./data/pokemon-species";
|
||||||
import i18next from './plugins/i18n';
|
import i18next from './plugins/i18n';
|
||||||
import { Abilities } from "./data/enums/abilities";
|
import { Abilities } from "./data/enums/abilities";
|
||||||
import { STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE } from './overrides';
|
import { STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE } from './overrides';
|
||||||
|
|
@ -3472,8 +3472,40 @@ export class GameOverModifierRewardPhase extends ModifierRewardPhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class RibbonModifierRewardPhase extends ModifierRewardPhase {
|
||||||
|
private species: PokemonSpecies;
|
||||||
|
|
||||||
|
constructor(scene: BattleScene, modifierTypeFunc: ModifierTypeFunc, species: PokemonSpecies) {
|
||||||
|
super(scene, modifierTypeFunc);
|
||||||
|
|
||||||
|
this.species = species;
|
||||||
|
}
|
||||||
|
|
||||||
|
doReward(): Promise<void> {
|
||||||
|
return new Promise<void>(resolve => {
|
||||||
|
const newModifier = this.modifierType.newModifier();
|
||||||
|
this.scene.addModifier(newModifier).then(() => {
|
||||||
|
this.scene.gameData.saveSystem().then(success => {
|
||||||
|
if (success) {
|
||||||
|
this.scene.playSound('level_up_fanfare');
|
||||||
|
this.scene.ui.setMode(Mode.MESSAGE);
|
||||||
|
this.scene.arenaBg.setVisible(false);
|
||||||
|
this.scene.ui.fadeIn(250).then(() => {
|
||||||
|
this.scene.ui.showText(`${this.species.name} beat ${this.scene.gameMode.getName()} Mode for the first time!\nYou received ${newModifier.type.name}!`, null, () => {
|
||||||
|
resolve();
|
||||||
|
}, null, true, 1500);
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
this.scene.reset(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class GameOverPhase extends BattlePhase {
|
export class GameOverPhase extends BattlePhase {
|
||||||
private victory: boolean;
|
private victory: boolean;
|
||||||
|
private firstRibbons: PokemonSpecies[] = [];
|
||||||
|
|
||||||
constructor(scene: BattleScene, victory?: boolean) {
|
constructor(scene: BattleScene, victory?: boolean) {
|
||||||
super(scene);
|
super(scene);
|
||||||
|
|
@ -3525,6 +3557,13 @@ export class GameOverPhase extends BattlePhase {
|
||||||
if (this.scene.gameMode.isClassic) {
|
if (this.scene.gameMode.isClassic) {
|
||||||
firstClear = this.scene.validateAchv(achvs.CLASSIC_VICTORY);
|
firstClear = this.scene.validateAchv(achvs.CLASSIC_VICTORY);
|
||||||
this.scene.gameData.gameStats.sessionsWon++;
|
this.scene.gameData.gameStats.sessionsWon++;
|
||||||
|
for (let pokemon of this.scene.getParty()) {
|
||||||
|
this.awardRibbon(pokemon);
|
||||||
|
|
||||||
|
if (pokemon.species.getRootSpeciesId() != pokemon.species.getRootSpeciesId(true)) {
|
||||||
|
this.awardRibbon(pokemon, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (this.scene.gameMode.isDaily && success[1])
|
} else if (this.scene.gameMode.isDaily && success[1])
|
||||||
this.scene.gameData.gameStats.dailyRunSessionsWon++;
|
this.scene.gameData.gameStats.dailyRunSessionsWon++;
|
||||||
}
|
}
|
||||||
|
|
@ -3536,8 +3575,12 @@ export class GameOverPhase extends BattlePhase {
|
||||||
this.scene.clearPhaseQueue();
|
this.scene.clearPhaseQueue();
|
||||||
this.scene.ui.clearText();
|
this.scene.ui.clearText();
|
||||||
this.handleUnlocks();
|
this.handleUnlocks();
|
||||||
if (this.victory && !firstClear && success[1])
|
if (this.victory && success[1]) {
|
||||||
this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM));
|
for (let species of this.firstRibbons)
|
||||||
|
this.scene.unshiftPhase(new RibbonModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PLUS, species));
|
||||||
|
if (!firstClear)
|
||||||
|
this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM));
|
||||||
|
}
|
||||||
this.scene.reset();
|
this.scene.reset();
|
||||||
this.scene.unshiftPhase(new TitlePhase(this.scene));
|
this.scene.unshiftPhase(new TitlePhase(this.scene));
|
||||||
this.end();
|
this.end();
|
||||||
|
|
@ -3556,6 +3599,15 @@ export class GameOverPhase extends BattlePhase {
|
||||||
this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.MINI_BLACK_HOLE));
|
this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.MINI_BLACK_HOLE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
awardRibbon(pokemon: Pokemon, forStarter: boolean = false): void {
|
||||||
|
const speciesId = getPokemonSpecies(pokemon.species.speciesId)
|
||||||
|
const speciesRibbonCount = this.scene.gameData.incrementRibbonCount(speciesId, forStarter);
|
||||||
|
// first time classic win, award voucher
|
||||||
|
if (speciesRibbonCount === 1) {
|
||||||
|
this.firstRibbons.push(getPokemonSpecies(pokemon.species.getRootSpeciesId(forStarter)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UnlockPhase extends Phase {
|
export class UnlockPhase extends Phase {
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,9 @@ export class Achv {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTier(): AchvTier {
|
getTier(): AchvTier {
|
||||||
if (this.score >= 150)
|
|
||||||
return AchvTier.MASTER;
|
|
||||||
if (this.score >= 100)
|
if (this.score >= 100)
|
||||||
|
return AchvTier.MASTER;
|
||||||
|
if (this.score >= 75)
|
||||||
return AchvTier.ROGUE;
|
return AchvTier.ROGUE;
|
||||||
if (this.score >= 50)
|
if (this.score >= 50)
|
||||||
return AchvTier.ULTRA;
|
return AchvTier.ULTRA;
|
||||||
|
|
@ -73,6 +73,16 @@ export class MoneyAchv extends Achv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class RibbonAchv extends Achv {
|
||||||
|
private ribbonAmount: integer;
|
||||||
|
|
||||||
|
constructor(name: string, ribbonAmount: integer, iconImage: string, score: integer) {
|
||||||
|
super(name, `Accumulate a total of ${ribbonAmount.toLocaleString('en-US')} Ribbons`, iconImage, score, (scene: BattleScene, _args: any[]) => scene.gameData.gameStats.ribbonsOwned >= this.ribbonAmount);
|
||||||
|
|
||||||
|
this.ribbonAmount = ribbonAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class DamageAchv extends Achv {
|
export class DamageAchv extends Achv {
|
||||||
private damageAmount: integer;
|
private damageAmount: integer;
|
||||||
|
|
||||||
|
|
@ -125,6 +135,11 @@ export const achvs = {
|
||||||
LV_100: new LevelAchv('But Wait, There\'s More!', 100, 'rare_candy', 25).setSecret(),
|
LV_100: new LevelAchv('But Wait, There\'s More!', 100, 'rare_candy', 25).setSecret(),
|
||||||
LV_250: new LevelAchv('Elite', 250, 'rarer_candy', 50).setSecret(true),
|
LV_250: new LevelAchv('Elite', 250, 'rarer_candy', 50).setSecret(true),
|
||||||
LV_1000: new LevelAchv('To Go Even Further Beyond', 1000, 'candy_jar', 100).setSecret(true),
|
LV_1000: new LevelAchv('To Go Even Further Beyond', 1000, 'candy_jar', 100).setSecret(true),
|
||||||
|
_10_RIBBONS: new RibbonAchv('Pokémon League Champion', 10, 'bronze_ribbon', 10),
|
||||||
|
_25_RIBBONS: new RibbonAchv('Great League Champion', 25, 'great_ribbon', 25).setSecret(true),
|
||||||
|
_50_RIBBONS: new RibbonAchv('Ultra League Champion', 50, 'ultra_ribbon', 50).setSecret(true),
|
||||||
|
_75_RIBBONS: new RibbonAchv('Rogue League Champion', 75, 'rogue_ribbon', 75).setSecret(true),
|
||||||
|
_100_RIBBONS: new RibbonAchv('Master League Champion', 100, 'master_ribbon', 100).setSecret(true),
|
||||||
TRANSFER_MAX_BATTLE_STAT: new Achv('Teamwork', 'Baton pass to another party member with at least one stat maxed out', 'stick', 20),
|
TRANSFER_MAX_BATTLE_STAT: new Achv('Teamwork', 'Baton pass to another party member with at least one stat maxed out', 'stick', 20),
|
||||||
MAX_FRIENDSHIP: new Achv('Friendmaxxing', 'Reach max friendship on a Pokémon', 'soothe_bell', 25),
|
MAX_FRIENDSHIP: new Achv('Friendmaxxing', 'Reach max friendship on a Pokémon', 'soothe_bell', 25),
|
||||||
MEGA_EVOLVE: new Achv('Megamorph', 'Mega evolve a Pokémon', 'mega_bracelet', 50),
|
MEGA_EVOLVE: new Achv('Megamorph', 'Mega evolve a Pokémon', 'mega_bracelet', 50),
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ export interface StarterDataEntry {
|
||||||
abilityAttr: integer;
|
abilityAttr: integer;
|
||||||
passiveAttr: integer;
|
passiveAttr: integer;
|
||||||
valueReduction: integer;
|
valueReduction: integer;
|
||||||
|
classicWinCount: integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StarterData {
|
export interface StarterData {
|
||||||
|
|
@ -194,7 +195,8 @@ const systemShortKeys = {
|
||||||
eggMoves: '$em',
|
eggMoves: '$em',
|
||||||
candyCount: '$x',
|
candyCount: '$x',
|
||||||
passive: '$p',
|
passive: '$p',
|
||||||
valueReduction: '$vr'
|
valueReduction: '$vr',
|
||||||
|
classicWinCount: '$wc'
|
||||||
};
|
};
|
||||||
|
|
||||||
export class GameData {
|
export class GameData {
|
||||||
|
|
@ -248,58 +250,52 @@ export class GameData {
|
||||||
public saveSystem(): Promise<boolean> {
|
public saveSystem(): Promise<boolean> {
|
||||||
return new Promise<boolean>(resolve => {
|
return new Promise<boolean>(resolve => {
|
||||||
this.scene.ui.savingIcon.show();
|
this.scene.ui.savingIcon.show();
|
||||||
updateUserInfo().then(response => {
|
const data: SystemSaveData = {
|
||||||
if (!response[0]) {
|
trainerId: this.trainerId,
|
||||||
this.scene.ui.savingIcon.hide();
|
secretId: this.secretId,
|
||||||
return resolve(false);
|
gender: this.gender,
|
||||||
}
|
dexData: this.dexData,
|
||||||
const data: SystemSaveData = {
|
starterData: this.starterData,
|
||||||
trainerId: this.trainerId,
|
gameStats: this.gameStats,
|
||||||
secretId: this.secretId,
|
unlocks: this.unlocks,
|
||||||
gender: this.gender,
|
achvUnlocks: this.achvUnlocks,
|
||||||
dexData: this.dexData,
|
voucherUnlocks: this.voucherUnlocks,
|
||||||
starterData: this.starterData,
|
voucherCounts: this.voucherCounts,
|
||||||
gameStats: this.gameStats,
|
eggs: this.eggs.map(e => new EggData(e)),
|
||||||
unlocks: this.unlocks,
|
gameVersion: this.scene.game.config.gameVersion,
|
||||||
achvUnlocks: this.achvUnlocks,
|
timestamp: new Date().getTime()
|
||||||
voucherUnlocks: this.voucherUnlocks,
|
};
|
||||||
voucherCounts: this.voucherCounts,
|
|
||||||
eggs: this.eggs.map(e => new EggData(e)),
|
|
||||||
gameVersion: this.scene.game.config.gameVersion,
|
|
||||||
timestamp: new Date().getTime()
|
|
||||||
};
|
|
||||||
|
|
||||||
const maxIntAttrValue = Math.pow(2, 31);
|
const maxIntAttrValue = Math.pow(2, 31);
|
||||||
const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v);
|
const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v);
|
||||||
|
|
||||||
if (!bypassLogin) {
|
if (!bypassLogin) {
|
||||||
Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData, undefined, true)
|
Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData, undefined, true)
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(error => {
|
.then(error => {
|
||||||
this.scene.ui.savingIcon.hide();
|
this.scene.ui.savingIcon.hide();
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error.startsWith('client version out of date')) {
|
if (error.startsWith('client version out of date')) {
|
||||||
this.scene.clearPhaseQueue();
|
this.scene.clearPhaseQueue();
|
||||||
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
|
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
|
||||||
} else if (error.startsWith('session out of date')) {
|
} else if (error.startsWith('session out of date')) {
|
||||||
this.scene.clearPhaseQueue();
|
this.scene.clearPhaseQueue();
|
||||||
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
|
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
|
||||||
}
|
|
||||||
console.error(error);
|
|
||||||
return resolve(false);
|
|
||||||
}
|
}
|
||||||
resolve(true);
|
console.error(error);
|
||||||
});
|
return resolve(false);
|
||||||
} else {
|
}
|
||||||
localStorage.setItem('data_bak', localStorage.getItem('data'));
|
resolve(true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
localStorage.setItem('data_bak', localStorage.getItem('data'));
|
||||||
|
|
||||||
localStorage.setItem('data', btoa(systemData));
|
localStorage.setItem('data', btoa(systemData));
|
||||||
|
|
||||||
this.scene.ui.savingIcon.hide();
|
this.scene.ui.savingIcon.hide();
|
||||||
|
|
||||||
resolve(true);
|
resolve(true);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -995,7 +991,8 @@ export class GameData {
|
||||||
friendship: 0,
|
friendship: 0,
|
||||||
abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0,
|
abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0,
|
||||||
passiveAttr: 0,
|
passiveAttr: 0,
|
||||||
valueReduction: 0
|
valueReduction: 0,
|
||||||
|
classicWinCount: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1089,6 +1086,32 @@ export class GameData {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
incrementRibbonCount(species: PokemonSpecies, forStarter: boolean = false): integer {
|
||||||
|
const speciesIdToIncrement: Species = species.getRootSpeciesId(forStarter);
|
||||||
|
|
||||||
|
if (!this.starterData[speciesIdToIncrement].classicWinCount) {
|
||||||
|
this.starterData[speciesIdToIncrement].classicWinCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.starterData[speciesIdToIncrement].classicWinCount)
|
||||||
|
this.scene.gameData.gameStats.ribbonsOwned++;
|
||||||
|
|
||||||
|
const ribbonsInStats: integer = this.scene.gameData.gameStats.ribbonsOwned;
|
||||||
|
|
||||||
|
if (ribbonsInStats >= 100)
|
||||||
|
this.scene.validateAchv(achvs._100_RIBBONS);
|
||||||
|
if (ribbonsInStats >= 75)
|
||||||
|
this.scene.validateAchv(achvs._75_RIBBONS);
|
||||||
|
if (ribbonsInStats >= 50)
|
||||||
|
this.scene.validateAchv(achvs._50_RIBBONS);
|
||||||
|
if (ribbonsInStats >= 25)
|
||||||
|
this.scene.validateAchv(achvs._25_RIBBONS);
|
||||||
|
if (ribbonsInStats >= 10)
|
||||||
|
this.scene.validateAchv(achvs._10_RIBBONS);
|
||||||
|
|
||||||
|
return ++this.starterData[speciesIdToIncrement].classicWinCount;
|
||||||
|
}
|
||||||
|
|
||||||
addStarterCandy(species: PokemonSpecies, count: integer): void {
|
addStarterCandy(species: PokemonSpecies, count: integer): void {
|
||||||
this.scene.candyBar.showStarterSpeciesCandy(species.speciesId, count);
|
this.scene.candyBar.showStarterSpeciesCandy(species.speciesId, count);
|
||||||
this.starterData[species.speciesId].candyCount += count;
|
this.starterData[species.speciesId].candyCount += count;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ export class GameStats {
|
||||||
public battles: integer;
|
public battles: integer;
|
||||||
public classicSessionsPlayed: integer;
|
public classicSessionsPlayed: integer;
|
||||||
public sessionsWon: integer;
|
public sessionsWon: integer;
|
||||||
|
public ribbonsOwned: integer;
|
||||||
public dailyRunSessionsPlayed: integer;
|
public dailyRunSessionsPlayed: integer;
|
||||||
public dailyRunSessionsWon: integer;
|
public dailyRunSessionsWon: integer;
|
||||||
public endlessSessionsPlayed: integer;
|
public endlessSessionsPlayed: integer;
|
||||||
|
|
@ -43,6 +44,7 @@ export class GameStats {
|
||||||
this.battles = source?.battles || 0;
|
this.battles = source?.battles || 0;
|
||||||
this.classicSessionsPlayed = source?.classicSessionsPlayed || 0;
|
this.classicSessionsPlayed = source?.classicSessionsPlayed || 0;
|
||||||
this.sessionsWon = source?.sessionsWon || 0;
|
this.sessionsWon = source?.sessionsWon || 0;
|
||||||
|
this.ribbonsOwned = source?.ribbonsOwned || 0;
|
||||||
this.dailyRunSessionsPlayed = source?.dailyRunSessionsPlayed || 0;
|
this.dailyRunSessionsPlayed = source?.dailyRunSessionsPlayed || 0;
|
||||||
this.dailyRunSessionsWon = source?.dailyRunSessionsWon || 0;
|
this.dailyRunSessionsWon = source?.dailyRunSessionsWon || 0;
|
||||||
this.endlessSessionsPlayed = source?.endlessSessionsPlayed || 0;
|
this.endlessSessionsPlayed = source?.endlessSessionsPlayed || 0;
|
||||||
|
|
@ -64,7 +66,7 @@ export class GameStats {
|
||||||
this.legendaryPokemonHatched = source?.legendaryPokemonHatched || 0;
|
this.legendaryPokemonHatched = source?.legendaryPokemonHatched || 0;
|
||||||
this.mythicalPokemonSeen = source?.mythicalPokemonSeen || 0;
|
this.mythicalPokemonSeen = source?.mythicalPokemonSeen || 0;
|
||||||
this.mythicalPokemonCaught = source?.mythicalPokemonCaught || 0;
|
this.mythicalPokemonCaught = source?.mythicalPokemonCaught || 0;
|
||||||
this.mythicalPokemonHatched = source?.mythicalPokemonCaught || 0;
|
this.mythicalPokemonHatched = source?.mythicalPokemonHatched || 0;
|
||||||
this.shinyPokemonSeen = source?.shinyPokemonSeen || 0;
|
this.shinyPokemonSeen = source?.shinyPokemonSeen || 0;
|
||||||
this.shinyPokemonCaught = source?.shinyPokemonCaught || 0;
|
this.shinyPokemonCaught = source?.shinyPokemonCaught || 0;
|
||||||
this.shinyPokemonHatched = source?.shinyPokemonHatched || 0;
|
this.shinyPokemonHatched = source?.shinyPokemonHatched || 0;
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ const displayStats: DisplayStats = {
|
||||||
return `${caughtCount} (${Math.floor((caughtCount / Object.keys(gameData.dexData).length) * 1000) / 10}%)`;
|
return `${caughtCount} (${Math.floor((caughtCount / Object.keys(gameData.dexData).length) * 1000) / 10}%)`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ribbonsOwned: 'Ribbons Owned',
|
||||||
classicSessionsPlayed: 'Classic Runs',
|
classicSessionsPlayed: 'Classic Runs',
|
||||||
sessionsWon: 'Classic Wins',
|
sessionsWon: 'Classic Wins',
|
||||||
dailyRunSessionsPlayed: 'Daily Run Attempts',
|
dailyRunSessionsPlayed: 'Daily Run Attempts',
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
private starterValueLabels: Phaser.GameObjects.Text[];
|
private starterValueLabels: Phaser.GameObjects.Text[];
|
||||||
private shinyIcons: Phaser.GameObjects.Image[][];
|
private shinyIcons: Phaser.GameObjects.Image[][];
|
||||||
private hiddenAbilityIcons: Phaser.GameObjects.Image[];
|
private hiddenAbilityIcons: Phaser.GameObjects.Image[];
|
||||||
|
private classicWinIcons: Phaser.GameObjects.Image[];
|
||||||
|
|
||||||
private iconAnimHandler: PokemonIconAnimHandler;
|
private iconAnimHandler: PokemonIconAnimHandler;
|
||||||
|
|
||||||
|
|
@ -410,6 +411,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.classicWinIcons = new Array(81).fill(null).map((_, i) => {
|
||||||
|
const x = (i % 9) * 18;
|
||||||
|
const y = Math.floor(i / 9) * 18;
|
||||||
|
const ret = this.scene.add.image(x + 152, y + 16, 'champion_ribbon');
|
||||||
|
ret.setOrigin(0, 0);
|
||||||
|
ret.setScale(0.5);
|
||||||
|
ret.setVisible(false);
|
||||||
|
this.starterSelectContainer.add(ret);
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
this.pokemonSprite = this.scene.add.sprite(53, 63, `pkmn__sub`);
|
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.pokemonSprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true });
|
||||||
this.starterSelectContainer.add(this.pokemonSprite);
|
this.starterSelectContainer.add(this.pokemonSprite);
|
||||||
|
|
@ -1192,6 +1204,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.shinyIcons[s][v].setTint(getVariantTint(speciesVariants[v] === DexAttr.DEFAULT_VARIANT ? 0 : speciesVariants[v] === DexAttr.VARIANT_2 ? 1 : 2));
|
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));
|
this.hiddenAbilityIcons[s].setVisible(slotVisible && !!this.scene.gameData.dexData[speciesId].caughtAttr && !!(this.scene.gameData.starterData[speciesId].abilityAttr & 4));
|
||||||
|
this.classicWinIcons[s].setVisible(slotVisible && this.scene.gameData.starterData[speciesId].classicWinCount > 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
changed = super.setCursor(cursor);
|
changed = super.setCursor(cursor);
|
||||||
|
|
|
||||||
31
src/utils.ts
|
|
@ -222,7 +222,8 @@ export function executeIf<T>(condition: boolean, promiseFunc: () => Promise<T>):
|
||||||
export const sessionIdKey = 'pokerogue_sessionId';
|
export const sessionIdKey = 'pokerogue_sessionId';
|
||||||
export const isLocal = window.location.hostname === 'localhost';
|
export const isLocal = window.location.hostname === 'localhost';
|
||||||
export const serverUrl = isLocal ? 'http://localhost:8001' : '';
|
export const serverUrl = isLocal ? 'http://localhost:8001' : '';
|
||||||
export const apiUrl = isLocal ? serverUrl : 'api';
|
export const apiUrl = isLocal ? serverUrl : 'https://api.pokerogue.net';
|
||||||
|
export const fallbackApiUrl = isLocal ? serverUrl : 'api';
|
||||||
|
|
||||||
export function setCookie(cName: string, cValue: string): void {
|
export function setCookie(cName: string, cValue: string): void {
|
||||||
const expiration = new Date();
|
const expiration = new Date();
|
||||||
|
|
@ -243,7 +244,7 @@ export function getCookie(cName: string): string {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function apiFetch(path: string, authed: boolean = false): Promise<Response> {
|
export function apiFetch(path: string, authed: boolean = false, fallback: boolean = false): Promise<Response> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const request = {};
|
const request = {};
|
||||||
if (authed) {
|
if (authed) {
|
||||||
|
|
@ -251,13 +252,22 @@ export function apiFetch(path: string, authed: boolean = false): Promise<Respons
|
||||||
if (sId)
|
if (sId)
|
||||||
request['headers'] = { 'Authorization': sId };
|
request['headers'] = { 'Authorization': sId };
|
||||||
}
|
}
|
||||||
fetch(`${apiUrl}/${path}`, request)
|
fetch(`${!fallback ? apiUrl : fallbackApiUrl}/${path}`, request)
|
||||||
.then(response => resolve(response))
|
.then(response => {
|
||||||
.catch(err => reject(err));
|
if (!response.ok && response.status === 404 && !fallback)
|
||||||
|
return apiFetch(path, authed, true).then(res => resolve(res));
|
||||||
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (fallback)
|
||||||
|
reject(err);
|
||||||
|
else
|
||||||
|
apiFetch(path, authed, true).then(res => resolve(res));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function apiPost(path: string, data?: any, contentType: string = 'application/json', authed: boolean = false): Promise<Response> {
|
export function apiPost(path: string, data?: any, contentType: string = 'application/json', authed: boolean = false, fallback: boolean = false): Promise<Response> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const headers = {
|
const headers = {
|
||||||
'Accept': contentType,
|
'Accept': contentType,
|
||||||
|
|
@ -268,9 +278,14 @@ export function apiPost(path: string, data?: any, contentType: string = 'applica
|
||||||
if (sId)
|
if (sId)
|
||||||
headers['Authorization'] = sId;
|
headers['Authorization'] = sId;
|
||||||
}
|
}
|
||||||
fetch(`${apiUrl}/${path}`, { method: 'POST', headers: headers, body: data })
|
fetch(`${!fallback ? apiUrl : fallbackApiUrl}/${path}`, { method: 'POST', headers: headers, body: data })
|
||||||
.then(response => resolve(response))
|
.then(response => resolve(response))
|
||||||
.catch(err => reject(err));
|
.catch(err => {
|
||||||
|
if (fallback)
|
||||||
|
reject(err);
|
||||||
|
else
|
||||||
|
apiPost(path, data, contentType, authed, true).then(res => resolve(res));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||