Merge branch 'pagefaultgames:main' into main
@ -7,8 +7,11 @@ PokéRogue is a browser based Pokémon fangame heavily inspired by the roguelite
|
||||
If you have the motivation and experience with Typescript/Javascript (or are willing to learn) please feel free to fork the repository and make pull requests with contributions. If you don't know what to work on but want to help, reference the below **To-Do** section or the **#vote** channel in the discord.
|
||||
|
||||
### 💻 Environment Setup
|
||||
node: 18.3.0
|
||||
#### Prerequisites
|
||||
- node: 18.3.0
|
||||
- npm: [how to install](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
|
||||
|
||||
#### Running Locally
|
||||
1. Clone the repo and in the root directory run `npm install`
|
||||
- *if you run into any errors, reach out in the **#dev-corner** channel in discord*
|
||||
2. Run `npm run start:dev` to locally run the project in `localhost:8000`
|
||||
|
BIN
public/audio/cry/669-white.m4a
Normal file
BIN
public/audio/cry/670-white.m4a
Normal file
BIN
public/audio/cry/671-white.m4a
Normal file
@ -4,30 +4,30 @@
|
||||
"image": "1024-stellar.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 96,
|
||||
"h": 96
|
||||
"w": 119,
|
||||
"h": 119
|
||||
},
|
||||
"scale": 0.5,
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 96,
|
||||
"h": 96
|
||||
"w": 119,
|
||||
"h": 119
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 9,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 78,
|
||||
"h": 96
|
||||
"w": 115,
|
||||
"h": 119
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 78,
|
||||
"h": 96
|
||||
"w": 115,
|
||||
"h": 119
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -36,6 +36,6 @@
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:c9ee64bda72f2dadb06109338796ccac:1313f1218b7da2c57ad9f290d1323840:c1508f3b01ae78a28a1267fd6caa4f7b$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:bc663acf2e62803fce6c3a525dc8dd98:ccd7d0de8a487235cfbd6f372afa931f:c1508f3b01ae78a28a1267fd6caa4f7b$"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.7 KiB |
@ -4,30 +4,30 @@
|
||||
"image": "1024-stellar.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 96,
|
||||
"h": 96
|
||||
"w": 119,
|
||||
"h": 119
|
||||
},
|
||||
"scale": 0.333,
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 96,
|
||||
"h": 96
|
||||
"w": 119,
|
||||
"h": 119
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 86,
|
||||
"h": 96
|
||||
"w": 115,
|
||||
"h": 119
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 86,
|
||||
"h": 96
|
||||
"w": 115,
|
||||
"h": 119
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -36,6 +36,6 @@
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:ac5e775f77477eeabd029932804747c4:f7a112a87c35dc81cb0da88b7cbb39e8:c1508f3b01ae78a28a1267fd6caa4f7b$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:210ba1c2e6e58501571ae226d073a3c5:f12bdf191842f7ec3a4be98a43fb8121:c1508f3b01ae78a28a1267fd6caa4f7b$"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.3 KiB |
@ -4,30 +4,30 @@
|
||||
"image": "1024-stellar.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 96,
|
||||
"h": 96
|
||||
"w": 119,
|
||||
"h": 119
|
||||
},
|
||||
"scale": 0.333,
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 96,
|
||||
"h": 96
|
||||
"w": 119,
|
||||
"h": 119
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 5,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 86,
|
||||
"h": 96
|
||||
"w": 115,
|
||||
"h": 119
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 86,
|
||||
"h": 96
|
||||
"w": 115,
|
||||
"h": 119
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -36,6 +36,6 @@
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:2bd25bae0fabcfbc35e24bd578a7b4b5:aec60788a0d77f38fb599d721e41a0d6:c1508f3b01ae78a28a1267fd6caa4f7b$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:210ba1c2e6e58501571ae226d073a3c5:f12bdf191842f7ec3a4be98a43fb8121:c1508f3b01ae78a28a1267fd6caa4f7b$"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.3 KiB |
@ -4,30 +4,30 @@
|
||||
"image": "1024-stellar.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 96,
|
||||
"h": 96
|
||||
"w": 119,
|
||||
"h": 119
|
||||
},
|
||||
"scale": 0.5,
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 96,
|
||||
"h": 96
|
||||
"w": 119,
|
||||
"h": 119
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 9,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 78,
|
||||
"h": 96
|
||||
"w": 115,
|
||||
"h": 119
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 78,
|
||||
"h": 96
|
||||
"w": 115,
|
||||
"h": 119
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -36,6 +36,6 @@
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:a7e89af07a22475413df24b510c193f7:45261af90c4a51e3dc73cccb894a2aad:c1508f3b01ae78a28a1267fd6caa4f7b$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:3510deaf42eaa3ee2fdfa22c00a2b30b:3beb6b12ca1bb50ad260593b41939f27:c1508f3b01ae78a28a1267fd6caa4f7b$"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.7 KiB |
@ -17,7 +17,7 @@ import { TextStyle, addTextObject } from './ui/text';
|
||||
import { Moves } from "./data/enums/moves";
|
||||
import { allMoves } from "./data/move";
|
||||
import { initMoves } from './data/move';
|
||||
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type';
|
||||
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getModifierPoolForType } from './modifier/modifier-type';
|
||||
import AbilityBar from './ui/ability-bar';
|
||||
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability';
|
||||
import { Abilities } from "./data/enums/abilities";
|
||||
@ -795,7 +795,10 @@ export default class BattleScene extends SceneBase {
|
||||
this.trainer.setVisible(true);
|
||||
|
||||
if (reloadI18n) {
|
||||
const localizable: Localizable[] = [ ...allMoves ];
|
||||
const localizable: Localizable[] = [
|
||||
...allMoves,
|
||||
...Utils.getEnumValues(ModifierPoolType).map(mpt => getModifierPoolForType(mpt)).map(mp => Object.values(mp).flat().map(mt => mt.modifierType).filter(mt => 'localize' in mt).map(lpb => lpb as unknown as Localizable)).flat()
|
||||
];
|
||||
for (let item of localizable)
|
||||
item.localize();
|
||||
}
|
||||
@ -975,6 +978,9 @@ export default class BattleScene extends SceneBase {
|
||||
case Species.DEERLING:
|
||||
case Species.SAWSBUCK:
|
||||
case Species.VIVILLON:
|
||||
case Species.FLABEBE:
|
||||
case Species.FLOETTE:
|
||||
case Species.FLORGES:
|
||||
case Species.ORICORIO:
|
||||
case Species.SQUAWKABILLY:
|
||||
case Species.TATSUGIRI:
|
||||
|
@ -2134,6 +2134,9 @@ export class SuppressFieldAbilitiesAbAttr extends AbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AlwaysHitAbAttr extends AbAttr { }
|
||||
|
||||
export class UncopiableAbilityAbAttr extends AbAttr {
|
||||
constructor() {
|
||||
super(false);
|
||||
@ -2615,7 +2618,9 @@ export function initAbilities() {
|
||||
new Ability(Abilities.SNIPER, "Sniper (N)", "Powers up moves if they become critical hits when attacking.", 4),
|
||||
new Ability(Abilities.MAGIC_GUARD, "Magic Guard", "The Pokémon only takes damage from attacks.", 4)
|
||||
.attr(BlockNonDirectDamageAbAttr),
|
||||
new Ability(Abilities.NO_GUARD, "No Guard (N)", "The Pokémon employs no-guard tactics to ensure incoming and outgoing attacks always land.", 4),
|
||||
new Ability(Abilities.NO_GUARD, "No Guard", "The Pokémon employs no-guard tactics to ensure incoming and outgoing attacks always land.", 4)
|
||||
.attr(AlwaysHitAbAttr)
|
||||
.attr(DoubleBattleChanceAbAttr),
|
||||
new Ability(Abilities.STALL, "Stall (N)", "The Pokémon moves after all other Pokémon do.", 4),
|
||||
new Ability(Abilities.TECHNICIAN, "Technician", "Powers up the Pokémon's weaker moves.", 4)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.power <= 60, 1.5),
|
||||
|
@ -1024,6 +1024,39 @@ export class SaltCuredTag extends BattlerTag {
|
||||
}
|
||||
}
|
||||
|
||||
export class CursedTag extends BattlerTag {
|
||||
private sourceIndex: integer;
|
||||
|
||||
constructor(sourceId: integer) {
|
||||
super(BattlerTagType.CURSED, BattlerTagLapseType.TURN_END, 1, Moves.CURSE, sourceId);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' has been cursed!'));
|
||||
this.sourceIndex = pokemon.scene.getPokemonById(this.sourceId).getBattlerIndex();
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
|
||||
|
||||
if (ret) {
|
||||
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.SALT_CURE));
|
||||
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
|
||||
|
||||
if (!cancelled.value) {
|
||||
pokemon.damageAndUpdate(Math.floor(pokemon.getMaxHp() / 4));
|
||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is hurt by the ${this.getMoveName()}!`));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves, sourceId: integer): BattlerTag {
|
||||
switch (tagType) {
|
||||
case BattlerTagType.RECHARGING:
|
||||
@ -1121,6 +1154,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount - 1, sourceMove);
|
||||
case BattlerTagType.SALT_CURED:
|
||||
return new SaltCuredTag(sourceId);
|
||||
case BattlerTagType.CURSED:
|
||||
return new CursedTag(sourceId);
|
||||
case BattlerTagType.CHARGED:
|
||||
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
|
||||
case BattlerTagType.NONE:
|
||||
|
@ -49,6 +49,7 @@ export enum BattlerTagType {
|
||||
BYPASS_SLEEP = "BYPASS_SLEEP",
|
||||
IGNORE_FLYING = "IGNORE_FLYING",
|
||||
SALT_CURED = "SALT_CURED",
|
||||
CURSED = "CURSED",
|
||||
CHARGED = "CHARGED",
|
||||
GROUNDED = "GROUNDED"
|
||||
}
|
||||
|
@ -2493,6 +2493,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
||||
return -5;
|
||||
case BattlerTagType.SEEDED:
|
||||
case BattlerTagType.SALT_CURED:
|
||||
case BattlerTagType.CURSED:
|
||||
case BattlerTagType.FRENZY:
|
||||
case BattlerTagType.TRAPPED:
|
||||
case BattlerTagType.BIND:
|
||||
@ -2527,6 +2528,34 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
||||
}
|
||||
}
|
||||
|
||||
export class CurseAttr extends MoveEffectAttr {
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move:Move, args: any[]): boolean {
|
||||
// Determine the correct target based on the user's type
|
||||
if (!user.getTypes(true).includes(Type.GHOST)) {
|
||||
// For non-Ghost types, target the user itself
|
||||
target = user;
|
||||
}
|
||||
|
||||
if (user.getTypes(true).includes(Type.GHOST)) {
|
||||
if (target.getTag(BattlerTagType.CURSED)) {
|
||||
user.scene.queueMessage('But it failed!');
|
||||
return false;
|
||||
}
|
||||
let curseRecoilDamage = Math.floor(user.getMaxHp() / 2);
|
||||
user.damageAndUpdate(curseRecoilDamage, HitResult.OTHER, false, true, true);
|
||||
user.scene.queueMessage(getPokemonMessage(user, ' cut its own HP!'));
|
||||
target.addTag(BattlerTagType.CURSED, 0, move.id, user.id);
|
||||
return true;
|
||||
} else {
|
||||
target = user;
|
||||
user.scene.unshiftPhase(new StatChangePhase(user.scene, user.getBattlerIndex(), this.selfTarget, [BattleStat.ATK, BattleStat.DEF], 1));
|
||||
user.scene.unshiftPhase(new StatChangePhase(user.scene, user.getBattlerIndex(), this.selfTarget, [BattleStat.SPD], -1));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class LapseBattlerTagAttr extends MoveEffectAttr {
|
||||
public tagTypes: BattlerTagType[];
|
||||
|
||||
@ -5132,6 +5161,7 @@ export function initMoves() {
|
||||
.attr(StatChangeAttr, BattleStat.SPATK, 1, true)
|
||||
.danceMove(),
|
||||
new AttackMove(Moves.FREEZE_SHOCK, Type.ICE, MoveCategory.PHYSICAL, 140, 90, 5, 30, 0, 5)
|
||||
.attr(ChargeAttr, ChargeAnim.FREEZE_SHOCK_CHARGING, 'became cloaked\nin a freezing light!')
|
||||
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
|
||||
.makesContact(false),
|
||||
new AttackMove(Moves.ICE_BURN, Type.ICE, MoveCategory.SPECIAL, 140, 90, 5, 30, 0, 5)
|
||||
|
@ -1,4 +1,5 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import i18next from '../plugins/i18n';
|
||||
|
||||
export enum PokeballType {
|
||||
POKEBALL,
|
||||
@ -30,22 +31,22 @@ export function getPokeballName(type: PokeballType): string {
|
||||
let ret: string;
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
ret = 'Poké Ball';
|
||||
ret = i18next.t('pokeball:pokeBall');
|
||||
break;
|
||||
case PokeballType.GREAT_BALL:
|
||||
ret = 'Great Ball';
|
||||
ret = i18next.t('pokeball:greatBall');
|
||||
break;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
ret = 'Ultra Ball';
|
||||
ret = i18next.t('pokeball:ultraBall');
|
||||
break;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
ret = 'Rogue Ball';
|
||||
ret = i18next.t('pokeball:rogueBall');
|
||||
break;
|
||||
case PokeballType.MASTER_BALL:
|
||||
ret = 'Master Ball';
|
||||
ret = i18next.t('pokeball:masterBall');
|
||||
break;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
ret = 'Luxury Ball';
|
||||
ret = i18next.t('pokeball:luxuryBall');
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
|
@ -917,7 +917,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
|
||||
new SpeciesEvolution(Species.TRUMBEAK, 14, null, null)
|
||||
],
|
||||
[Species.TRUMBEAK]: [
|
||||
new SpeciesEvolution(Species.TOUCANNON, 36, null, null)
|
||||
new SpeciesEvolution(Species.TOUCANNON, 28, null, null)
|
||||
],
|
||||
[Species.YUNGOOS]: [
|
||||
new SpeciesEvolution(Species.GUMSHOOS, 20, null, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), SpeciesWildEvolutionDelay.SHORT)
|
||||
|
@ -10919,8 +10919,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||
],
|
||||
[Species.CHESPIN]: [
|
||||
[ 1, Moves.TACKLE ],
|
||||
[ 1, Moves.VINE_WHIP ],
|
||||
[ 1, Moves.GROWL ],
|
||||
[ 1, Moves.VINE_WHIP ],
|
||||
[ 8, Moves.ROLLOUT ],
|
||||
[ 11, Moves.BITE ],
|
||||
[ 15, Moves.LEECH_SEED ],
|
||||
@ -10934,8 +10934,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = {
|
||||
],
|
||||
[Species.QUILLADIN]: [
|
||||
[ 1, Moves.TACKLE ],
|
||||
[ 1, Moves.VINE_WHIP ],
|
||||
[ 1, Moves.GROWL ],
|
||||
[ 1, Moves.VINE_WHIP ],
|
||||
[ 8, Moves.ROLLOUT ],
|
||||
[ 11, Moves.BITE ],
|
||||
[ 15, Moves.LEECH_SEED ],
|
||||
|
@ -1473,7 +1473,7 @@ export function initSpecies() {
|
||||
new PokemonSpecies(Species.PORYGON_Z, "Porygon-Z", 4, false, false, false, "Virtual Pokémon", Type.NORMAL, null, 0.9, 34, Abilities.ADAPTABILITY, Abilities.DOWNLOAD, Abilities.ANALYTIC, 535, 85, 80, 70, 135, 75, 90, 30, 50, 268, GrowthRate.MEDIUM_FAST, null, false),
|
||||
new PokemonSpecies(Species.GALLADE, "Gallade", 4, false, false, false, "Blade Pokémon", Type.PSYCHIC, Type.FIGHTING, 1.6, 52, Abilities.STEADFAST, Abilities.SHARPNESS, Abilities.JUSTIFIED, 518, 68, 125, 65, 65, 115, 80, 45, 35, 259, GrowthRate.SLOW, 100, false, true,
|
||||
new PokemonForm("Normal", "", Type.PSYCHIC, Type.FIGHTING, 1.6, 52, Abilities.STEADFAST, Abilities.SHARPNESS, Abilities.JUSTIFIED, 518, 68, 125, 65, 65, 115, 80, 45, 35, 259),
|
||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.PSYCHIC, Type.FIGHTING, 1.6, 56.4, Abilities.INNER_FOCUS, Abilities.INNER_FOCUS, Abilities.INNER_FOCUS, 618, 68, 165, 95, 65, 115, 110, 45, 35, 259),
|
||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.PSYCHIC, Type.FIGHTING, 1.6, 56.4, Abilities.SHARPNESS, Abilities.SHARPNESS, Abilities.SHARPNESS, 618, 68, 165, 95, 65, 115, 110, 45, 35, 259),
|
||||
),
|
||||
new PokemonSpecies(Species.PROBOPASS, "Probopass", 4, false, false, false, "Compass Pokémon", Type.ROCK, Type.STEEL, 1.4, 340, Abilities.STURDY, Abilities.MAGNET_PULL, Abilities.SAND_FORCE, 525, 60, 55, 145, 75, 150, 40, 60, 70, 184, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(Species.DUSKNOIR, "Dusknoir", 4, false, false, false, "Gripper Pokémon", Type.GHOST, null, 2.2, 106.6, Abilities.PRESSURE, Abilities.NONE, Abilities.FRISK, 525, 45, 100, 135, 65, 135, 45, 45, 35, 263, GrowthRate.FAST, 50, false),
|
||||
@ -3058,7 +3058,7 @@ export const speciesStarters = {
|
||||
[Species.FUECOCO]: 3,
|
||||
[Species.QUAXLY]: 3,
|
||||
[Species.LECHONK]: 2,
|
||||
[Species.TAROUNTULA]: 2,
|
||||
[Species.TAROUNTULA]: 1,
|
||||
[Species.NYMBLE]: 3,
|
||||
[Species.PAWMI]: 3,
|
||||
[Species.TANDEMAUS]: 4,
|
||||
|
@ -697,9 +697,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerType.GIOVANNI]: new TrainerConfig(++t).initForGymLeader([ Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F ], Type.DARK).setBattleBgm('battle_kanto_gym'),
|
||||
[TrainerType.FALKNER]: new TrainerConfig(++t).initForGymLeader([ Species.PIDGEY, Species.HOOTHOOT, Species.DODUO ], Type.FLYING).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.BUGSY]: new TrainerConfig(++t).initForGymLeader([ Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR ], Type.BUG).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader([ Species.CLEFAIRY, Species.MILTANK ], Type.NORMAL).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader([ Species.GIRAFARIG, Species.MILTANK ], Type.NORMAL).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.MORTY]: new TrainerConfig(++t).initForGymLeader([ Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE ], Type.GHOST).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader([ Species.POLIWRATH, ], Type.FIGHTING).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader([ Species.POLIWRATH, Species.MANKEY ], Type.FIGHTING).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.JASMINE]: new TrainerConfig(++t).initForGymLeader([ Species.MAGNEMITE, Species.STEELIX ], Type.STEEL).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.PRYCE]: new TrainerConfig(++t).initForGymLeader([ Species.SEEL, Species.SWINUB ], Type.ICE).setBattleBgm('battle_johto_gym'),
|
||||
[TrainerType.CLAIR]: new TrainerConfig(++t).initForGymLeader([ Species.DRATINI, Species.HORSEA, Species.GYARADOS ], Type.DRAGON).setBattleBgm('battle_johto_gym'),
|
||||
|
@ -82,7 +82,11 @@ export class EggHatchPhase extends Phase {
|
||||
this.eggContainer.add(this.eggLightraysOverlay);
|
||||
this.eggHatchContainer.add(this.eggContainer);
|
||||
|
||||
const getPokemonSprite = () => this.scene.add.sprite(this.eggHatchBg.displayWidth / 2, this.eggHatchBg.displayHeight / 2, `pkmn__sub`);
|
||||
const getPokemonSprite = () => {
|
||||
const ret = this.scene.add.sprite(this.eggHatchBg.displayWidth / 2, this.eggHatchBg.displayHeight / 2, `pkmn__sub`);
|
||||
ret.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true });
|
||||
return ret;
|
||||
};
|
||||
|
||||
this.eggHatchContainer.add((this.pokemonSprite = getPokemonSprite()));
|
||||
|
||||
@ -245,7 +249,7 @@ export class EggHatchPhase extends Phase {
|
||||
this.scene.validateAchv(achvs.HATCH_SHINY);
|
||||
this.eggContainer.setVisible(false);
|
||||
this.pokemonSprite.play(this.pokemon.getSpriteKey(true));
|
||||
this.pokemonSprite.pipelineData['ignoreTimeTint'] = true;
|
||||
this.pokemonSprite.setPipelineData('ignoreTimeTint', true);
|
||||
this.pokemonSprite.setPipelineData('spriteKey', this.pokemon.getSpriteKey());
|
||||
this.pokemonSprite.setPipelineData('shiny', this.pokemon.shiny);
|
||||
this.pokemonSprite.setPipelineData('variant', this.pokemon.variant);
|
||||
|
@ -71,7 +71,11 @@ export class EvolutionPhase extends Phase {
|
||||
this.evolutionBgOverlay.setAlpha(0);
|
||||
this.evolutionContainer.add(this.evolutionBgOverlay);
|
||||
|
||||
const getPokemonSprite = () => this.scene.addPokemonSprite(this.pokemon, this.evolutionBaseBg.displayWidth / 2, this.evolutionBaseBg.displayHeight / 2, `pkmn__sub`);
|
||||
const getPokemonSprite = () => {
|
||||
const ret = this.scene.addPokemonSprite(this.pokemon, this.evolutionBaseBg.displayWidth / 2, this.evolutionBaseBg.displayHeight / 2, `pkmn__sub`);
|
||||
ret.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true });
|
||||
return ret;
|
||||
};
|
||||
|
||||
this.evolutionContainer.add((this.pokemonSprite = getPokemonSprite()));
|
||||
this.evolutionContainer.add((this.pokemonTintSprite = getPokemonSprite()));
|
||||
@ -92,7 +96,10 @@ export class EvolutionPhase extends Phase {
|
||||
[ this.pokemonSprite, this.pokemonTintSprite, this.pokemonEvoSprite, this.pokemonEvoTintSprite ].map(sprite => {
|
||||
sprite.play(this.pokemon.getSpriteKey(true));
|
||||
sprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(this.pokemon.getTeraType()) });
|
||||
sprite.pipelineData['ignoreTimeTint'] = true;
|
||||
sprite.setPipelineData('ignoreTimeTint', true);
|
||||
sprite.setPipelineData('spriteKey', this.pokemon.getSpriteKey());
|
||||
sprite.setPipelineData('shiny', this.pokemon.shiny);
|
||||
sprite.setPipelineData('variant', this.pokemon.variant);
|
||||
[ 'spriteColors', 'fusionSpriteColors' ].map(k => {
|
||||
if (this.pokemon.summonData?.speciesForm)
|
||||
k += 'Base';
|
||||
|
@ -1832,7 +1832,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return false;
|
||||
break;
|
||||
case StatusEffect.FREEZE:
|
||||
if (this.isOfType(Type.ICE))
|
||||
if (this.isOfType(Type.ICE) || [WeatherType.SUNNY, WeatherType.HARSH_SUN].includes(this.scene?.arena.weather?.weatherType))
|
||||
return false;
|
||||
break;
|
||||
case StatusEffect.BURN:
|
||||
|
8
src/locales/en/pokeball.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export const pokeball = {
|
||||
"pokeBall": "Poké Ball",
|
||||
"greatBall": "Great Ball",
|
||||
"ultraBall": "Ultra Ball",
|
||||
"rogueBall": "Rogue Ball",
|
||||
"masterBall": "Master Ball",
|
||||
"luxuryBall": "Luxury Ball",
|
||||
} as const;
|
@ -1443,7 +1443,7 @@ export const move: MoveTranslations = {
|
||||
},
|
||||
"healingWish": {
|
||||
name: "Voeu Soin",
|
||||
effect: "Un soin qui permet au lanceur de récupérer jusqu’à la moitié de ses PV max."
|
||||
effect: "Le lanceur tombe K.O. pour soigner les altérations de statut et les PV du Pokémon qui viendra le remplacer sur le terrain."
|
||||
},
|
||||
"brine": {
|
||||
name: "Saumure",
|
||||
|
8
src/locales/fr/pokeball.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export const pokeball = {
|
||||
"pokeBall": "Poké Ball",
|
||||
"greatBall": "Super Ball",
|
||||
"ultraBall": "Hyper Ball",
|
||||
"rogueBall": "Rogue Ball",
|
||||
"masterBall": "Master Ball",
|
||||
"luxuryBall": "Luxe Ball",
|
||||
} as const;
|
@ -19,6 +19,7 @@ import { VoucherType, getVoucherTypeIcon, getVoucherTypeName } from '../system/v
|
||||
import { FormChangeItem, SpeciesFormChangeItemTrigger, pokemonFormChanges } from '../data/pokemon-forms';
|
||||
import { ModifierTier } from './modifier-tier';
|
||||
import { Nature, getNatureName, getNatureStatMultiplier } from '#app/data/nature';
|
||||
import { Localizable } from '#app/plugins/i18n';
|
||||
|
||||
const outputModifierData = false;
|
||||
const useMaxWeightForOutput = false;
|
||||
@ -131,10 +132,19 @@ export interface GeneratedPersistentModifierType {
|
||||
getPregenArgs(): any[];
|
||||
}
|
||||
|
||||
class AddPokeballModifierType extends ModifierType {
|
||||
class AddPokeballModifierType extends ModifierType implements Localizable {
|
||||
private pokeballType: PokeballType;
|
||||
private count: integer;
|
||||
|
||||
constructor(pokeballType: PokeballType, count: integer, iconImage?: string) {
|
||||
super(`${count}x ${getPokeballName(pokeballType)}`, `Receive ${getPokeballName(pokeballType)} x${count}\nCatch Rate: ${getPokeballCatchMultiplier(pokeballType) > -1 ? `${getPokeballCatchMultiplier(pokeballType)}x` : 'Certain'}`,
|
||||
(_type, _args) => new Modifiers.AddPokeballModifier(this, pokeballType, count), iconImage, 'pb', 'pb_bounce_1');
|
||||
super('', '', (_type, _args) => new Modifiers.AddPokeballModifier(this, pokeballType, count), iconImage, 'pb', 'pb_bounce_1');
|
||||
this.pokeballType = pokeballType;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
localize() {
|
||||
this.name = `${this.count}x ${getPokeballName(this.pokeballType)}`;
|
||||
this.description = `Receive ${getPokeballName(this.pokeballType)} x${this.count}\nCatch Rate: ${getPokeballCatchMultiplier(this.pokeballType) > -1 ? `${getPokeballCatchMultiplier(this.pokeballType)}x` : 'Certain'}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get
|
||||
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 { 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, AlwaysHitAbAttr } from "./data/ability";
|
||||
import { Unlockables, getUnlockableName } from "./system/unlockables";
|
||||
import { getBiomeKey } from "./field/arena";
|
||||
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
||||
@ -379,6 +379,33 @@ export class UnavailablePhase extends Phase {
|
||||
}
|
||||
}
|
||||
|
||||
export class ReloadSessionPhase extends Phase {
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
}
|
||||
|
||||
start(): void {
|
||||
this.scene.ui.setMode(Mode.SESSION_RELOAD);
|
||||
|
||||
let delayElapsed = false;
|
||||
let loaded = false;
|
||||
|
||||
this.scene.time.delayedCall(Utils.fixedInt(1500), () => {
|
||||
if (loaded)
|
||||
this.end();
|
||||
else
|
||||
delayElapsed = true;
|
||||
});
|
||||
|
||||
this.scene.gameData.loadSystem().then(() => {
|
||||
if (delayElapsed)
|
||||
this.end();
|
||||
else
|
||||
loaded = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class OutdatedPhase extends Phase {
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
@ -767,6 +794,7 @@ export class EncounterPhase extends BattlePhase {
|
||||
pokemon.resetBattleData();
|
||||
}
|
||||
|
||||
if (!this.loaded)
|
||||
this.scene.arena.trySetWeather(getRandomWeatherType(this.scene.arena), false);
|
||||
|
||||
const enemyField = this.scene.getEnemyField();
|
||||
@ -2173,7 +2201,7 @@ export class MovePhase extends BattlePhase {
|
||||
const targets = this.scene.getField(true).filter(p => {
|
||||
if (this.targets.indexOf(p.getBattlerIndex()) > -1) {
|
||||
const hiddenTag = p.getTag(HiddenTag);
|
||||
if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length)
|
||||
if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length && !p.hasAbilityWithAttr(AlwaysHitAbAttr) && !this.pokemon.hasAbilityWithAttr(AlwaysHitAbAttr))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -2467,6 +2495,9 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
if (user.turnData.hitsLeft < user.turnData.hitCount)
|
||||
return true;
|
||||
|
||||
if (user.hasAbilityWithAttr(AlwaysHitAbAttr) || target.hasAbilityWithAttr(AlwaysHitAbAttr))
|
||||
return true;
|
||||
|
||||
const hiddenTag = target.getTag(HiddenTag);
|
||||
if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length)
|
||||
return false;
|
||||
@ -3389,6 +3420,8 @@ export class GameOverPhase extends BattlePhase {
|
||||
|
||||
handleClearSession(): void {
|
||||
this.scene.gameData.tryClearSession(this.scene, this.scene.sessionSlotId).then((success: boolean | [boolean, boolean]) => {
|
||||
if (!success[0])
|
||||
return this.scene.reset(true);
|
||||
this.scene.time.delayedCall(1000, () => {
|
||||
let firstClear = false;
|
||||
if (this.victory && success[1]) {
|
||||
@ -4296,7 +4329,7 @@ export class EggLapsePhase extends Phase {
|
||||
|
||||
const eggsToHatch: Egg[] = this.scene.gameData.eggs.filter((egg: Egg) => {
|
||||
return --egg.hatchWaves < 1
|
||||
})
|
||||
});
|
||||
|
||||
if (eggsToHatch.length) {
|
||||
this.scene.queueMessage('Oh?');
|
||||
|
@ -6,6 +6,9 @@ import { menu as frMenu } from '../locales/fr/menu';
|
||||
import { move as enMove } from '../locales/en/move';
|
||||
import { move as frMove } from '../locales/fr/move';
|
||||
|
||||
import { pokeball as enPokeball } from '../locales/en/pokeball';
|
||||
import { pokeball as frPokeball } from '../locales/fr/pokeball';
|
||||
|
||||
export interface MoveTranslationEntry {
|
||||
name: string,
|
||||
effect: string
|
||||
@ -50,6 +53,7 @@ export function initI18n(): void {
|
||||
en: {
|
||||
menu: enMenu,
|
||||
move: enMove,
|
||||
pokeball: enPokeball,
|
||||
},
|
||||
it: {
|
||||
menu: itMenu,
|
||||
@ -57,6 +61,7 @@ export function initI18n(): void {
|
||||
fr: {
|
||||
menu: frMenu,
|
||||
move: frMove,
|
||||
pokeball: frPokeball,
|
||||
}
|
||||
},
|
||||
});
|
||||
@ -68,6 +73,7 @@ declare module 'i18next' {
|
||||
resources: {
|
||||
menu: typeof enMenu;
|
||||
move: typeof enMove;
|
||||
pokeball: typeof enPokeball;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import BattleScene, { PokeballCounts, bypassLogin } from "../battle-scene";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon } from "../field/pokemon";
|
||||
import { pokemonEvolutions, pokemonPrevolutions } from "../data/pokemon-evolutions";
|
||||
import PokemonSpecies, { SpeciesFormKey, allSpecies, getPokemonSpecies, noStarterFormKeys, speciesStarters } from "../data/pokemon-species";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpecies, noStarterFormKeys, speciesStarters } from "../data/pokemon-species";
|
||||
import { Species, defaultStarterSpecies } from "../data/enums/species";
|
||||
import * as Utils from "../utils";
|
||||
import PokemonData from "./pokemon-data";
|
||||
@ -27,7 +27,7 @@ import { Moves } from "../data/enums/moves";
|
||||
import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { allMoves } from "../data/move";
|
||||
import { TrainerVariant } from "../field/trainer";
|
||||
import { OutdatedPhase, UnavailablePhase } from "#app/phases";
|
||||
import { OutdatedPhase, ReloadSessionPhase } from "#app/phases";
|
||||
import { Variant, variantData } from "#app/data/variant";
|
||||
|
||||
const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary
|
||||
@ -280,6 +280,9 @@ export class GameData {
|
||||
if (error.startsWith('client version out of date')) {
|
||||
this.scene.clearPhaseQueue();
|
||||
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
|
||||
} else if (error.startsWith('session out of date')) {
|
||||
this.scene.clearPhaseQueue();
|
||||
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
|
||||
}
|
||||
console.error(error);
|
||||
return resolve(false);
|
||||
@ -340,7 +343,7 @@ export class GameData {
|
||||
this.starterData[s].eggMoves = starterEggMoveData[s];
|
||||
}
|
||||
|
||||
this.migrateStarterAbilities(systemData);
|
||||
this.migrateStarterAbilities(systemData, this.starterData);
|
||||
} else {
|
||||
if ([ '1.0.0', '1.0.1' ].includes(systemData.gameVersion))
|
||||
this.migrateStarterAbilities(systemData);
|
||||
@ -551,6 +554,10 @@ export class GameData {
|
||||
.then(response => response.text())
|
||||
.then(error => {
|
||||
if (error) {
|
||||
if (error.startsWith('session out of date')) {
|
||||
this.scene.clearPhaseQueue();
|
||||
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
|
||||
}
|
||||
console.error(error);
|
||||
return resolve(false);
|
||||
}
|
||||
@ -715,9 +722,19 @@ export class GameData {
|
||||
Utils.apiFetch(`savedata/delete?datatype=${GameDataType.SESSION}&slot=${slotId}`, true).then(response => {
|
||||
if (response.ok) {
|
||||
loggedInUser.lastSessionSlot = -1;
|
||||
return resolve(true);
|
||||
resolve(true);
|
||||
}
|
||||
return response.text();
|
||||
}).then(error => {
|
||||
if (error) {
|
||||
if (error.startsWith('session out of date')) {
|
||||
this.scene.clearPhaseQueue();
|
||||
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
|
||||
}
|
||||
console.error(error);
|
||||
resolve(false);
|
||||
}
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -735,12 +752,19 @@ export class GameData {
|
||||
return resolve([false, false]);
|
||||
const sessionData = this.getSessionSaveData(scene);
|
||||
Utils.apiPost(`savedata/clear?slot=${slotId}`, JSON.stringify(sessionData)).then(response => {
|
||||
if (response.ok) {
|
||||
if (response.ok)
|
||||
loggedInUser.lastSessionSlot = -1;
|
||||
return response.json();
|
||||
}).then(jsonResponse => {
|
||||
if (!jsonResponse.error)
|
||||
return resolve([true, jsonResponse.success as boolean]);
|
||||
if (jsonResponse && jsonResponse.error.startsWith('session out of date')) {
|
||||
this.scene.clearPhaseQueue();
|
||||
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
|
||||
}
|
||||
console.error(jsonResponse);
|
||||
resolve([false, false]);
|
||||
}).then(jsonResponse => resolve([true, jsonResponse.success as boolean]));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -1207,9 +1231,9 @@ export class GameData {
|
||||
}
|
||||
}
|
||||
|
||||
migrateStarterAbilities(systemData: SystemSaveData): void {
|
||||
migrateStarterAbilities(systemData: SystemSaveData, initialStarterData?: StarterData): void {
|
||||
const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species);
|
||||
const starterData = systemData.starterData;
|
||||
const starterData = initialStarterData || systemData.starterData;
|
||||
const dexData = systemData.dexData;
|
||||
for (let s of starterIds) {
|
||||
const dexAttr = dexData[s].caughtAttr;
|
||||
|
@ -336,10 +336,14 @@ export default class MenuUiHandler extends MessageUiHandler {
|
||||
case Button.UP:
|
||||
if (this.cursor)
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
else
|
||||
success = this.setCursor(this.menuOptions.length - 1);
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor + 1 < this.menuOptions.length)
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
else
|
||||
success = this.setCursor(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
47
src/ui/session-reload-modal-ui-handler.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import { ModalConfig, ModalUiHandler } from "./modal-ui-handler";
|
||||
import { addTextObject, TextStyle } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
|
||||
export default class SessionReloadModalUiHandler extends ModalUiHandler {
|
||||
constructor(scene: BattleScene, mode?: Mode) {
|
||||
super(scene, mode);
|
||||
}
|
||||
|
||||
getModalTitle(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
getWidth(): number {
|
||||
return 160;
|
||||
}
|
||||
|
||||
getHeight(): number {
|
||||
return 32;
|
||||
}
|
||||
|
||||
getMargin(): [number, number, number, number] {
|
||||
return [ 0, 0, 48, 0 ];
|
||||
}
|
||||
|
||||
getButtonLabels(): string[] {
|
||||
return [ ];
|
||||
}
|
||||
|
||||
setup(): void {
|
||||
super.setup();
|
||||
|
||||
const label = addTextObject(this.scene, this.getWidth() / 2, this.getHeight() / 2, 'Your session is out of date.\nYour data will be reloaded…', TextStyle.WINDOW, { fontSize: '48px', align: 'center' });
|
||||
label.setOrigin(0.5, 0.5);
|
||||
|
||||
this.modalContainer.add(label);
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
const config: ModalConfig = {
|
||||
buttonActions: []
|
||||
};
|
||||
|
||||
return super.show([ config ]);
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ import TitleUiHandler from './title-ui-handler';
|
||||
import SavingIconHandler from './saving-icon-handler';
|
||||
import UnavailableModalUiHandler from './unavailable-modal-ui-handler';
|
||||
import OutdatedModalUiHandler from './outdated-modal-ui-handler';
|
||||
import SessionReloadModalUiHandler from './session-reload-modal-ui-handler';
|
||||
|
||||
export enum Mode {
|
||||
MESSAGE,
|
||||
@ -62,6 +63,7 @@ export enum Mode {
|
||||
LOGIN_FORM,
|
||||
REGISTRATION_FORM,
|
||||
LOADING,
|
||||
SESSION_RELOAD,
|
||||
UNAVAILABLE,
|
||||
OUTDATED
|
||||
};
|
||||
@ -90,6 +92,7 @@ const noTransitionModes = [
|
||||
Mode.LOGIN_FORM,
|
||||
Mode.REGISTRATION_FORM,
|
||||
Mode.LOADING,
|
||||
Mode.SESSION_RELOAD,
|
||||
Mode.UNAVAILABLE,
|
||||
Mode.OUTDATED
|
||||
];
|
||||
@ -141,6 +144,7 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
new LoginFormUiHandler(scene),
|
||||
new RegistrationFormUiHandler(scene),
|
||||
new LoadingModalUiHandler(scene),
|
||||
new SessionReloadModalUiHandler(scene),
|
||||
new UnavailableModalUiHandler(scene),
|
||||
new OutdatedModalUiHandler(scene)
|
||||
];
|
||||
|