Merge branch 'pagefaultgames:main' into flingImplementation

This commit is contained in:
AyushBarik 2024-06-17 15:59:50 +05:30 committed by GitHub
commit 18b8394cb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 416 additions and 158 deletions

View File

@ -7,6 +7,7 @@ export interface UserInfo {
}
export let loggedInUser: UserInfo = null;
// This is a random string that is used to identify the client session - unique per session (tab or window) so that the game will only save on the one that the server is expecting
export const clientSessionId = Utils.randomString(32);
export function initLoggedInUser(): void {

View File

@ -3166,10 +3166,8 @@ export class FriendshipPowerAttr extends VariablePowerAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const power = args[0] as Utils.NumberHolder;
if (user instanceof PlayerPokemon) {
const friendshipPower = Math.floor(Math.min(user.friendship, 255) / 2.5);
power.value = Math.max(!this.invert ? friendshipPower : 102 - friendshipPower, 1);
}
const friendshipPower = Math.floor(Math.min(user instanceof PlayerPokemon ? user.friendship : user.species.baseFriendship, 255) / 2.5);
power.value = Math.max(!this.invert ? friendshipPower : 102 - friendshipPower, 1);
return true;
}
@ -7710,6 +7708,7 @@ export function initMoves() {
new AttackMove(Moves.BADDY_BAD, Type.DARK, MoveCategory.SPECIAL, 80, 95, 15, -1, 0, 7)
.attr(AddArenaTagAttr, ArenaTagType.REFLECT, 5, false, true),
new AttackMove(Moves.SAPPY_SEED, Type.GRASS, MoveCategory.PHYSICAL, 100, 90, 10, 100, 0, 7)
.makesContact(false)
.attr(AddBattlerTagAttr, BattlerTagType.SEEDED),
new AttackMove(Moves.FREEZY_FROST, Type.ICE, MoveCategory.SPECIAL, 100, 90, 10, -1, 0, 7)
.attr(ResetStatsAttr),

View File

@ -3795,7 +3795,7 @@ export const starterPassiveAbilities = {
[Species.IRON_TREADS]: Abilities.STEELY_SPIRIT,
[Species.IRON_BUNDLE]: Abilities.SNOW_WARNING,
[Species.IRON_HANDS]: Abilities.IRON_FIST,
[Species.IRON_JUGULIS]: Abilities.AERILATE,
[Species.IRON_JUGULIS]: Abilities.LIGHTNING_ROD,
[Species.IRON_MOTH]: Abilities.LEVITATE,
[Species.IRON_THORNS]: Abilities.SAND_STREAM,
[Species.FRIGIBAX]: Abilities.SNOW_WARNING,

View File

@ -24,6 +24,8 @@ import { Biome } from "#enums/biome";
import { TrainerType } from "#enums/trainer-type";
export class LoadingScene extends SceneBase {
readonly LOAD_EVENTS = Phaser.Loader.Events;
constructor() {
super("loading");
@ -35,10 +37,6 @@ export class LoadingScene extends SceneBase {
Utils.localPing();
this.load["manifest"] = this.game["manifest"];
if (!isMobile()) {
this.load.video("intro_dark", "images/intro_dark.mp4", true);
}
this.loadImage("loading_bg", "arenas");
this.loadImage("logo", "");
this.loadImage("pride-update", "events");
@ -421,58 +419,46 @@ export class LoadingScene extends SceneBase {
});
disclaimerDescriptionText.setOrigin(0.5, 0.5);
disclaimerText.setVisible(false);
disclaimerDescriptionText.setVisible(false);
const intro = this.add.video(0, 0);
intro.setOrigin(0, 0);
intro.setScale(3);
this.load.on("progress", (value: string) => {
const parsedValue = parseFloat(value);
percentText.setText(`${Math.floor(parsedValue * 100)}%`);
progressBar.clear();
progressBar.fillStyle(0xffffff, 0.8);
progressBar.fillRect(midWidth - 320, 360, 640 * parsedValue, 64);
});
this.load.on("fileprogress", file => {
assetText.setText(i18next.t("menu:loadingAsset", { assetName: file.key }));
});
loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText);
loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText, disclaimerText, disclaimerDescriptionText);
if (!mobile) {
loadingGraphics.map(g => g.setVisible(false));
}
const destroyLoadingAssets = () => {
intro.destroy();
bg.destroy();
logo.destroy();
progressBar.destroy();
progressBox.destroy();
percentText.destroy();
assetText.destroy();
};
const intro = this.add.video(0, 0);
intro.on(Phaser.GameObjects.Events.VIDEO_COMPLETE, (video: Phaser.GameObjects.Video) => {
this.tweens.add({
targets: intro,
duration: 500,
alpha: 0,
ease: "Sine.easeIn",
onComplete: () => video.destroy(),
});
loadingGraphics.forEach(g => g.setVisible(true));
});
intro.setOrigin(0, 0);
intro.setScale(3);
this.load.on("filecomplete", key => {
this.load.once(this.LOAD_EVENTS.START, () => {
// videos do not need to be preloaded
intro.loadURL("images/intro_dark.mp4", true);
if (mobile) {
intro.video.setAttribute("webkit-playsinline", "webkit-playsinline");
intro.video.setAttribute("playsinline", "playsinline");
}
intro.play();
});
this.load.on(this.LOAD_EVENTS.PROGRESS , (progress: number) => {
percentText.setText(`${Math.floor(progress * 100)}%`);
progressBar.clear();
progressBar.fillStyle(0xffffff, 0.8);
progressBar.fillRect(midWidth - 320, 360, 640 * progress, 64);
});
this.load.on(this.LOAD_EVENTS.FILE_COMPLETE, (key: string) => {
assetText.setText(i18next.t("menu:loadingAsset", { assetName: key }));
switch (key) {
case "intro_dark":
intro.load("intro_dark");
intro.on("complete", () => {
this.tweens.add({
targets: intro,
duration: 500,
alpha: 0,
ease: "Sine.easeIn"
});
loadingGraphics.map(g => g.setVisible(true));
disclaimerText.setVisible(true);
disclaimerDescriptionText.setVisible(true);
});
intro.play();
break;
case "loading_bg":
bg.setTexture("loading_bg");
if (mobile) {
@ -488,7 +474,7 @@ export class LoadingScene extends SceneBase {
}
});
this.load.on("complete", () => destroyLoadingAssets());
this.load.on(this.LOAD_EVENTS.COMPLETE, () => loadingGraphics.forEach(go => go.destroy()));
}
get gameHeight() {

View File

@ -4,5 +4,5 @@ export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!",
"badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!",
"windPowerCharged": "Der Treffer durch {{moveName}} läd die Stärke von {{pokemonName}} auf!",
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!",
"iceFaceAvoidedDamage": "{{pokemonName}} wehrt Schaden\nmit {{abilityName}} ab!",
} as const;

View File

@ -62,12 +62,12 @@ export const battle: SimpleTranslationEntries = {
"drainMessage": "{{pokemonName}} wurde Energie abgesaugt",
"regainHealth": "KP von {{pokemonName}} wurden wieder aufgefrischt!",
"fainted": "{{pokemonNameWithAffix}} wurde besiegt!",
"statRose": "rose",
"statSharplyRose": "sharply rose",
"statRoseDrastically": "rose drastically",
"statWontGoAnyHigher": "won't go any higher",
"statFell": "fell",
"statHarshlyFell": "harshly fell",
"statSeverelyFell": "severely fell",
"statWontGoAnyLower": "won't go any lower",
"statRose": "steigt",
"statSharplyRose": "steigt stark",
"statRoseDrastically": "steigt drastisch",
"statWontGoAnyHigher": "kann nicht weiter erhöht werden",
"statFell": "sinkt",
"statHarshlyFell": "sinkt stark",
"statSeverelyFell": "sinkt drastisch",
"statWontGoAnyLower": "kann nicht weiter sinken",
} as const;

View File

@ -44,6 +44,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "Tägliche Rangliste",
"weeklyRankings": "Wöchentliche Rangliste",
"noRankings": "Keine Rangliste",
"positionIcon": "#",
"usernameScoreboard": "Benutzername",
"score": "Punkte",
"wave": "Welle",
"loading": "Lade…",
"loadingAsset": "Loading asset: {{assetName}}",
"playersOnline": "Spieler Online",

View File

@ -14,8 +14,8 @@ export const pokemonInfo: PokemonInfoTranslationEntries = {
"SPDEFshortened": "SpVert",
"SPD": "Initiative",
"SPDshortened": "Init",
"ACC": "Accuracy",
"EVA": "Evasiveness"
"ACC": "Genauigkeit",
"EVA": "Fluchtwert",
},
Type: {

View File

@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"addToParty": "Zum Team hinzufügen",
"toggleIVs": "DVs anzeigen/verbergen",
"manageMoves": "Attacken ändern",
"manageNature": "Wesen ändern",
"useCandies": "Bonbons verwenden",
"selectNature": "Wähle das neue Wesen.",
"selectMoveSwapOut": "Wähle die zu ersetzende Attacke.",
"selectMoveSwapWith": "Wähle die gewünschte Attacke.",
"unlockPassive": "Passiv-Skill freischalten",

View File

@ -44,6 +44,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "Daily Rankings",
"weeklyRankings": "Weekly Rankings",
"noRankings": "No Rankings",
"positionIcon": "#",
"usernameScoreboard": "Username",
"score": "Score",
"wave": "Wave",
"loading": "Loading…",
"loadingAsset": "Loading asset: {{assetName}}",
"playersOnline": "Players Online",

View File

@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"addToParty": "Add to Party",
"toggleIVs": "Toggle IVs",
"manageMoves": "Manage Moves",
"manageNature": "Manage Nature",
"useCandies": "Use Candies",
"selectNature": "Select nature.",
"selectMoveSwapOut": "Select a move to swap out.",
"selectMoveSwapWith": "Select a move to swap with",
"unlockPassive": "Unlock Passive",

View File

@ -44,6 +44,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "Rankings Diarios",
"weeklyRankings": "Rankings Semanales",
"noRankings": "Sin Rankings",
"positionIcon": "#",
"usernameScoreboard": "Username",
"score": "Score",
"wave": "Wave",
"loading": "Cargando…",
"loadingAsset": "Cargando recurso: {{assetName}}",
"playersOnline": "Jugadores en Línea",

View File

@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"addToParty": "Añadir a Equipo",
"toggleIVs": "Mostrar IVs",
"manageMoves": "Gestionar Movs.",
"manageNature": "Gestionar Natur",
"useCandies": "Usar Caramelos",
"selectNature": "Elige Natur.",
"selectMoveSwapOut": "Elige el movimiento que sustituir.",
"selectMoveSwapWith": "Elige el movimiento que sustituirá a",
"unlockPassive": "Añadir Pasiva",

View File

@ -39,6 +39,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "Classement du Jour",
"weeklyRankings": "Classement de la Semaine",
"noRankings": "Pas de Classement",
"positionIcon": "#",
"usernameScoreboard": "Username",
"score": "Score",
"wave": "Wave",
"loading": "Chargement…",
"loadingAsset": "Loading asset: {{assetName}}",
"playersOnline": "Joueurs Connectés",

View File

@ -23,9 +23,11 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"eggMoves": "Capacités Œuf",
"start": "Lancer",
"addToParty": "Ajouter à léquipe",
"toggleIVs": "Voir IVs",
"manageMoves": "Gérer Capacités",
"useCandies": "Utiliser Bonbons",
"toggleIVs": "Voir les IV",
"manageMoves": "Modifier les Capacités",
"manageNature": "Modifier la Nature",
"useCandies": "Utiliser des Bonbons",
"selectNature": "Sélectionnez une nature.",
"selectMoveSwapOut": "Sélectionnez la capacité à échanger.",
"selectMoveSwapWith": "Sélectionnez laquelle échanger avec",
"unlockPassive": "Débloquer Passif",

View File

@ -39,6 +39,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "Classifica giornaliera",
"weeklyRankings": "Classifica settimanale",
"noRankings": "Nessuna classifica",
"positionIcon": "#",
"usernameScoreboard": "Username",
"score": "Score",
"wave": "Wave",
"loading": "Caricamento…",
"loadingAsset": "Caricamento asset: {{assetName}}",
"playersOnline": "Giocatori online",

View File

@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"addToParty": "Aggiungi al gruppo",
"toggleIVs": "Vedi/Nascondi IV",
"manageMoves": "Gestisci mosse",
"manageNature": "Gestisci natura",
"useCandies": "Usa caramelle",
"selectNature": "Seleziona natura.",
"selectMoveSwapOut": "Seleziona una mossa da scambiare.",
"selectMoveSwapWith": "Seleziona una mossa da scambiare con",
"unlockPassive": "Sblocca passiva",

View File

@ -2,41 +2,41 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const tutorial: SimpleTranslationEntries = {
"intro": `Benvenuto in PokéRogue! Questo gioco si concentra sulle battaglie, con elementi roguelite.
$Questo gioco non è monetizzato e non siamo proprietari di Pokemon e Assets presenti nel gioco.
$Il gioco è work-in-progress ma giocabile al 100%.\nPer reportare eventuali bugs è possibile discuterne sul nostro Discord.
$Se il game risulta 'lento', assicurati di aver abilitato l'Accelerazione Hardware nelle impostazioni del tuo Browser`,
$Questo gioco non è monetizzato e non siamo proprietari di Pokémon ed assets presenti nel gioco.
$Il progetto è work-in-progress, ma giocabile al 100%.\nPer segnalare eventuali bug è possibile contattarci al nostro apposito Discord.
$Se il gioco risulta 'lento', assicurati di aver abilitato l'accelerazione hardware nelle impostazioni del tuo browser`,
"accessMenu": "Per accedere al menù, press M o Esc.\nDal menù puoi cambiare impostazioni, controllare la wiki e accedere a varie features.",
"accessMenu": "Per accedere al menu, premi M o esc.\nDal menu puoi modificare le impostazioni, controllare la wiki ed accedere a varie features.",
"menu": `Da questo menù puoi accedere alle impostazioni.
$Dalle impostazioni puoi cambiare velocità di gioco, stile di finestra e altre opzioni.
$Ci sono varie funzionalità, controlla bene e non perderti nulla!`,
"menu": `Da questo menu puoi accedere alle impostazioni.
$Esse ti permettono di cambiare velocità di gioco, stile delle finestre ed altre opzioni.
$Ci sono varie funzionalità: controlla bene e non perderti nulla!`,
"starterSelect": `Da questa schermata puoi selezionare il tuo starter.\nQuesti sono i membri iniziali del tuo parti.
"starterSelect": `Da questa schermata puoi selezionare il tuo starter.\nQuesti sono i membri iniziali della tua squadra.
$Ogni starter ha un valore. Puoi avere fino a \n6 Pokèmon, avendo a disposizione un massimo di 10 punti.
$Puoi anche selezionare Sesso, Abilità, e Forma a seconda delle\nvarianti che hai catturato o schiuso.
$Puoi anche selezionare genere, abilità, e forma a seconda delle\nvarianti che hai catturato o schiuso.
$Le IVs di una specie sono le migliori rispetto a tutte quelle che hai\ncatturato o schiuso, quindi prova a catturarne il piu possibile!`,
"pokerus": `Giornalmente 3 Starter casuali disponibili avranno il bordo viola.
$Se possiedi uno di questi starter,\nprova ad aggiungerlo al party. Ricorda di controllare le info!`,
"pokerus": `Giornalmente 3 starter casuali disponibili avranno il bordo viola.
$Se possiedi uno di questi starter,\nprova ad aggiungerlo alla squadra. Ricorda di controllarne le info!`,
"statChange": `I cambiamenti alle statistiche persistono fintanto che i tuoi pokèmon resteranno in campo.
"statChange": `I cambiamenti alle statistiche persistono fintanto che i tuoi pokèmon restano in campo.
$I tuoi pokemon verranno richiamati quando incontrerai un allenatore o al cambiamento di bioma.
$Puoi anche vedere i cambiamenti alle statistiche in corso tenendo premuto C o Shift`,
"selectItem": `Dopo ogni battaglia avrai disponibili tre item.\nPotrai prenderne solo uno.
$Questi spaziano tra consumabili, item tenuti da Pokèmon o con un effetto passivo permanente.
$La maggior parte degli Item non Consumabili possono stackare in diversi modi.
$Alcuni Item risulteranno disponibili solo se possono essere usati, come Item Evolutivi.
$Puoi anche passare un Item tenuto da un Pokèmon ad un altro attraverso l'opzione 'trasferisci strumento'.
$L'opzione 'trasferisci strumento' sarà disponibile solo dopo aver assegnato uno strumento ad un Pokèmon.
$Puoi acquistare consumabili con le monete, progredendo saranno poi disponibili ulteriori oggetti.
$Assicurati di fare un acquisto prima di selezionare un item casuale, poichè passerai subito alla lotta successiva.`,
"selectItem": `Dopo ogni battaglia potrai scegliere tra 3 oggetti.\nPotrai prenderne solo uno.
$Questi spaziano tra consumabili, oggetti tenuti da Pokèmon o con un effetto passivo permanente.
$La maggior parte degli oggetti non consumabili possono accumulare i loro effetti in diversi modi.
$Alcuni risulteranno inoltre disponibili solo se possono essere usati, come ad esempio gli oggetti evolutivi.
$Puoi anche passare un oggetto tenuto da un Pokèmon a un altro attraverso l'opzione 'trasferisci strumento'.
$Quest'ultima sarà disponibile solo dopo aver assegnato uno strumento ad un Pokèmon.
$Puoi acquistare consumabili con le monete; progredendo saranno poi disponibili ulteriori oggetti.
$Assicurati di fare un acquisto prima di selezionare un item casuale, poichè dopo aver fatto ciò passerai subito alla lotta successiva.`,
"eggGacha": `Da questa schermata, puoi riscattare i tuoi vouchers in cambio di\nuova Pokèmon.
$Le uova vanno schiuse e saranno sempre più vicine alla schiusura dopo\nogni battaglia. Le uova più rare impiegheranno più battaglie per la schiusura.
$I Pokémon schiusi non verranno aggiunti alla tua squadra, saranno\naggiunti ai tuoi starters.
$I Pokémon schiusi generalmente hanno IVs migliori rispetto ai\n Pokémon selvatici.
$Alcuni Pokémon possono essere ottenuti solo tramite uova.
"eggGacha": `Da questa schermata puoi riscattare i tuoi vouchers in cambio di\nuova Pokèmon.
$Le uova vanno schiuse, e saranno sempre più vicine alla schiusura dopo\nogni battaglia. Le uova più rare impiegheranno più battaglie per la schiusura.
$I Pokémon schiusi non verranno aggiunti alla tua squadra, ma saranno\ninvece aggiunti ai tuoi starters.
$I Pokémon schiusi hanno (generalmente) IVs migliori rispetto ai\n Pokémon selvatici.
$Inoltre, alcuni Pokémon possono essere ottenuti solo tramite uova.
$Ci sono 3 diversi macchinari con differenti\nbonus, scegli quello che preferisci!`,
} as const;

View File

@ -62,12 +62,12 @@ export const battle: SimpleTranslationEntries = {
"drainMessage": "{{pokemonName}}[[로]]부터\n체력을 흡수했다!",
"regainHealth": "{{pokemonName}}[[는]]\n기력을 회복했다!",
"fainted": "{{pokemonNameWithAffix}}[[는]] 쓰러졌다!",
"statRose": "상승했다",
"statSharplyRose": "약간 상승했다",
"statRoseDrastically": "대폭 상승했다",
"statWontGoAnyHigher": "더 이상 상승할 수 없다",
"statFell": "떨어졌다",
"statHarshlyFell": "약간 떨어졌다",
"statSeverelyFell": "대폭 떨어졌다",
"statWontGoAnyLower": "더 이상 떨어질 수 없다",
"statRose": "[[가]] 올라갔다!",
"statSharplyRose": "[[가]] 크게 올라갔다!",
"statRoseDrastically": "[[가]] 매우 크게 올라갔다!",
"statWontGoAnyHigher": "[[는]] 더 올라가지 않는다!",
"statFell": "[[가]] 떨어졌다!",
"statHarshlyFell": "[[가]] 크게 떨어졌다!",
"statSeverelyFell": "[[가]] 매우 크게 떨어졌다!",
"statWontGoAnyLower": "[[는]] 더 떨어지지 않는다!",
} as const;

View File

@ -44,6 +44,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "일간 랭킹",
"weeklyRankings": "주간 랭킹",
"noRankings": "랭킹 정보 없음",
"positionIcon": "#",
"usernameScoreboard": "이름",
"score": "점수",
"wave": "웨이브",
"loading": "로딩 중…",
"loadingAsset": "Loading asset: {{assetName}}",
"playersOnline": "플레이어 온라인",

View File

@ -44,6 +44,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "Classificação Diária",
"weeklyRankings": "Classificação Semanal",
"noRankings": "Sem Classificação",
"positionIcon": "#",
"usernameScoreboard": "Usuário",
"score": "Pontuação",
"wave": "Onda",
"loading": "Carregando…",
"loadingAsset": "Carregando recurso: {{assetName}}",
"playersOnline": "Jogadores Ativos",

View File

@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"addToParty": "Adicionar à equipe",
"toggleIVs": "Mostrar IVs",
"manageMoves": "Mudar Movimentos",
"manageNature": "Mudar Natureza",
"useCandies": "Usar Doces",
"selectNature": "Escolha Natureza.",
"selectMoveSwapOut": "Escolha um movimento para substituir.",
"selectMoveSwapWith": "Escolha o movimento que substituirá",
"unlockPassive": "Aprender Passiva",

View File

@ -2,7 +2,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力",
"badDreams": "{{pokemonName}} 被折磨着!",
"badDreams": "{{pokemonName}} 被折磨着",
"windPowerCharged": "受 {{moveName}} 的影响, {{pokemonName}} 提升了能力!",
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
"iceFaceAvoidedDamage": "{{pokemonName}} 因为 {{abilityName}}\n避免了伤害"
} as const;

View File

@ -56,18 +56,18 @@ export const battle: SimpleTranslationEntries = {
"skipItemQuestion": "你确定要跳过拾取道具吗?",
"eggHatching": "咦?",
"ivScannerUseQuestion": "对 {{pokemonName}} 使用个体值扫描仪?",
"wildPokemonWithAffix": "Wild {{pokemonName}}",
"foePokemonWithAffix": "Foe {{pokemonName}}",
"useMove": "{{pokemonNameWithAffix}} used {{moveName}}!",
"drainMessage": "{{pokemonName}} had its\nenergy drained!",
"regainHealth": "{{pokemonName}} regained\nhealth!",
"fainted": "{{pokemonNameWithAffix}} fainted!",
"statRose": "rose",
"statSharplyRose": "sharply rose",
"statRoseDrastically": "rose drastically",
"statWontGoAnyHigher": "won't go any higher",
"statFell": "fell",
"statHarshlyFell": "harshly fell",
"statSeverelyFell": "severely fell",
"statWontGoAnyLower": "won't go any lower",
"wildPokemonWithAffix": "野生的 {{pokemonName}}",
"foePokemonWithAffix": "对手 {{pokemonName}}",
"useMove": "{{pokemonNameWithAffix}} 使用了 {{moveName}}",
"drainMessage": "{{pokemonName}} 吸取了体力!",
"regainHealth": "{{pokemonName}} 回复了体力!",
"fainted": "{{pokemonNameWithAffix}} 倒下了!",
"statRose": "提高了!",
"statSharplyRose": "大幅提高了!",
"statRoseDrastically": "极大幅提高了!",
"statWontGoAnyHigher": "已经无法再提高了!",
"statFell": "降低了!",
"statHarshlyFell": "大幅降低了!",
"statSeverelyFell": "极大幅降低了!",
"statWontGoAnyLower": "已经无法再降低了!",
} as const;

View File

@ -4,6 +4,6 @@ export const fightUiHandler: SimpleTranslationEntries = {
"pp": "PP",
"power": "威力",
"accuracy": "命中",
"abilityFlyInText": " {{pokemonName}}'s {{passive}}{{abilityName}}",
"passive": "Passive ", // The space at the end is important
"abilityFlyInText": " {{pokemonName}} {{passive}}{{abilityName}}",
"passive": "被动 ", // The space at the end is important
} as const;

View File

@ -1,10 +1,10 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const gameMode: SimpleTranslationEntries = {
"classic": "Classic",
"endless": "Endless",
"endlessSpliced": "Endless (Spliced)",
"dailyRun": "Daily Run",
"unknown": "Unknown",
"challenge": "Challenge",
"classic": "经典模式",
"endless": "无尽模式",
"endlessSpliced": "融合无尽模式",
"dailyRun": "每日挑战",
"unknown": "未知",
"challenge": "挑战模式",
} as const;

View File

@ -1,10 +1,10 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const growth: SimpleTranslationEntries = {
"Erratic": "快",
"Fast": "快",
"Medium_Fast": "快",
"Medium_Slow": "慢",
"Slow": "慢",
"Fluctuating": "慢"
} as const;
"Erratic": "非常快",
"Fast": "快",
"Medium_Fast": "快",
"Medium_Slow": "慢",
"Slow": "慢",
"Fluctuating": "非常慢"
} as const;

View File

@ -44,6 +44,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "每日排名",
"weeklyRankings": "每周排名",
"noRankings": "无排名",
"positionIcon": "#",
"usernameScoreboard": "Username",
"score": "Score",
"wave": "Wave",
"loading": "加载中...",
"loadingAsset": "Loading asset: {{assetName}}",
"playersOnline": "在线玩家",

View File

@ -14,8 +14,8 @@ export const pokemonInfo: PokemonInfoTranslationEntries = {
"SPDEFshortened": "特防",
"SPD": "速度",
"SPDshortened": "速度",
"ACC": "Accuracy",
"EVA": "Evasiveness"
"ACC": "命中率",
"EVA": "回避率"
},
Type: {

View File

@ -1,9 +1,9 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const saveSlotSelectUiHandler: SimpleTranslationEntries = {
"overwriteData": "Overwrite the data in the selected slot?",
"overwriteData": "要覆盖该槽位的存档吗?",
"loading": "正在加载中...",
"wave": "Wave",
"wave": "层数",
"lv": "Lv",
"empty": "空",
} as const;

View File

@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"addToParty": "加入队伍",
"toggleIVs": "切换个体值",
"manageMoves": "管理招式",
"manageNature": "管理性格",
"useCandies": "使用糖果",
"selectNature": "选择性格",
"selectMoveSwapOut": "选择要替换的招式。",
"selectMoveSwapWith": "选择要替换成的招式",
"unlockPassive": "解锁被动",

View File

@ -48,7 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
"depot_agent": "铁路员工",
"doctor": "医生",
"doctor_female": "医生",
"firebreather": "Firebreather",
"firebreather": "吹火人",
"fisherman": "垂钓者",
"fisherman_female": "垂钓者",
"gentleman": "绅士",
@ -87,13 +87,13 @@ export const trainerClasses: SimpleTranslationEntries = {
"pokémon_rangers": "宝可梦巡护员组合",
"ranger": "巡护员",
"restaurant_staff": "服务生组合",
"rich": "Rich",
"rich_female": "Rich",
"rich": "富豪",
"rich_female": "富豪太太",
"rich_boy": "富家少爷",
"rich_couple": "富豪夫妇",
"rich_kid": "Rich Kid",
"rich_kid_female": "Rich Kid",
"rich_kids": "富二代组合",
"rich_kid": "富家小孩",
"rich_kid_female": "富家小孩",
"rich_kids": "富家小孩组合",
"roughneck": "光头男",
"sailor": "水手",
"scientist": "研究员",

View File

@ -44,6 +44,10 @@ export const menu: SimpleTranslationEntries = {
"dailyRankings": "每日排名",
"weeklyRankings": "每週排名",
"noRankings": "無排名",
"positionIcon": "#",
"usernameScoreboard": "Username",
"score": "Score",
"wave": "Wave",
"loading": "加載中…",
"loadingAsset": "Loading asset: {{assetName}}",
"playersOnline": "在線玩家",

View File

@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"addToParty": "加入隊伍",
"toggleIVs": "查看個體值",
"manageMoves": "管理技能",
"manageNature": "管理性格",
"useCandies": "使用糖果",
"selectNature": "選擇性格",
"selectMoveSwapOut": "選擇想要替換走的招式",
"selectMoveSwapWith": "選擇想要替換成的招式",
"unlockPassive": "解鎖被動",

View File

@ -1017,6 +1017,30 @@ export class EnemyEndureChanceModifierType extends ModifierType {
export type ModifierTypeFunc = () => ModifierType;
type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: integer) => integer;
/**
* High order function that returns a WeightedModifierTypeWeightFunc that will only be applied on
* classic and skip an ModifierType if current wave is greater or equal to the one passed down
* @param wave - Wave where we should stop showing the modifier
* @param defaultWeight - ModifierType default weight
* @returns A WeightedModifierTypeWeightFunc
*/
function skipInClassicAfterWave(wave: integer, defaultWeight: integer): WeightedModifierTypeWeightFunc {
return (party: Pokemon[]) => {
const gameMode = party[0].scene.gameMode;
const currentWave = party[0].scene.currentBattle.waveIndex;
return gameMode.isClassic && currentWave >= wave ? 0 : defaultWeight;
};
}
/**
* High order function that returns a WeightedModifierTypeWeightFunc that will only be applied on
* classic and it will skip a ModifierType if it is the last wave pull.
* @param defaultWeight ModifierType default weight
* @returns A WeightedModifierTypeWeightFunc
*/
function skipInLastClassicWaveOrDefault(defaultWeight: integer) : WeightedModifierTypeWeightFunc {
return skipInClassicAfterWave(199, defaultWeight);
}
class WeightedModifierType {
public modifierType: ModifierType;
public weight: integer | WeightedModifierTypeWeightFunc;
@ -1313,7 +1337,7 @@ const modifierPool: ModifierPool = {
}, 3),
new WeightedModifierType(modifierTypes.DIRE_HIT, 4),
new WeightedModifierType(modifierTypes.SUPER_LURE, 4),
new WeightedModifierType(modifierTypes.NUGGET, 5),
new WeightedModifierType(modifierTypes.NUGGET, skipInLastClassicWaveOrDefault(5)),
new WeightedModifierType(modifierTypes.EVOLUTION_ITEM, (party: Pokemon[]) => {
return Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15), 8);
}, 8),
@ -1336,7 +1360,7 @@ const modifierPool: ModifierPool = {
[ModifierTier.ULTRA]: [
new WeightedModifierType(modifierTypes.ULTRA_BALL, 24),
new WeightedModifierType(modifierTypes.MAX_LURE, 4),
new WeightedModifierType(modifierTypes.BIG_NUGGET, 12),
new WeightedModifierType(modifierTypes.BIG_NUGGET, skipInLastClassicWaveOrDefault(12)),
new WeightedModifierType(modifierTypes.PP_UP, 9),
new WeightedModifierType(modifierTypes.PP_MAX, 3),
new WeightedModifierType(modifierTypes.MINT, 4),
@ -1371,7 +1395,7 @@ const modifierPool: ModifierPool = {
}),
[ModifierTier.ROGUE]: [
new WeightedModifierType(modifierTypes.ROGUE_BALL, 24),
new WeightedModifierType(modifierTypes.RELIC_GOLD, 2),
new WeightedModifierType(modifierTypes.RELIC_GOLD, skipInLastClassicWaveOrDefault(2)),
new WeightedModifierType(modifierTypes.LEFTOVERS, 3),
new WeightedModifierType(modifierTypes.SHELL_BELL, 3),
new WeightedModifierType(modifierTypes.BERRY_POUCH, 4),

View File

@ -94,7 +94,14 @@ export class LoginPhase extends Phase {
this.scene.playSound("menu_open");
const loadData = () => {
updateUserInfo().then(() => this.scene.gameData.loadSystem().then(() => this.end()));
updateUserInfo().then(success => {
if (!success[0]) {
Utils.setCookie(Utils.sessionIdKey, "");
this.scene.reset(true, true);
return;
}
this.scene.gameData.loadSystem().then(() => this.end());
});
};
this.scene.ui.setMode(Mode.LOGIN_FORM, {
@ -108,7 +115,14 @@ export class LoginPhase extends Phase {
buttonActions: [
() => {
this.scene.ui.playSelect();
updateUserInfo().then(() => this.end());
updateUserInfo().then(success => {
if (!success[0]) {
Utils.setCookie(Utils.sessionIdKey, "");
this.scene.reset(true, true);
return;
}
this.end();
} );
}, () => {
this.scene.unshiftPhase(new LoginPhase(this.scene, false));
this.end();
@ -118,6 +132,9 @@ export class LoginPhase extends Phase {
}
]
});
} else if (statusCode === 401) {
Utils.setCookie(Utils.sessionIdKey, "");
this.scene.reset(true, true);
} else {
this.scene.unshiftPhase(new UnavailablePhase(this.scene));
super.end();
@ -4198,7 +4215,8 @@ export class GameOverPhase extends BattlePhase {
If Offline, execute offlineNewClear(), a localStorage implementation of newClear daily run checks */
if (this.victory) {
if (!Utils.isLocal) {
Utils.apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true) .then(response => response.json())
Utils.apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true)
.then(response => response.json())
.then(newClear => doGameOver(newClear));
} else {
this.scene.gameData.offlineNewClear(this.scene).then(result => {

View File

@ -136,7 +136,7 @@ interface VoucherUnlocks {
}
export interface VoucherCounts {
[type: string]: integer;
[type: string]: integer;
}
export interface DexData {
@ -187,6 +187,46 @@ export interface StarterMoveData {
[key: integer]: StarterMoveset | StarterFormMoveData
}
export interface StarterAttributes {
nature?: integer;
ability?: integer;
variant?: integer;
form?: integer;
female?: boolean;
}
export interface StarterPreferences {
[key: integer]: StarterAttributes;
}
// the latest data saved/loaded for the Starter Preferences. Required to reduce read/writes. Initialize as "{}", since this is the default value and no data needs to be stored if present.
// if they ever add private static variables, move this into StarterPrefs
const StarterPrefers_DEFAULT : string = "{}";
let StarterPrefers_private_latest : string = StarterPrefers_DEFAULT;
// This is its own class as StarterPreferences...
// - don't need to be loaded on startup
// - isn't stored with other data
// - don't require to be encrypted
// - shouldn't require calls outside of the starter selection
export class StarterPrefs {
// called on starter selection show once
static load(): StarterPreferences {
return JSON.parse(
StarterPrefers_private_latest = (localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT)
);
}
// called on starter selection clear, always
static save(prefs: StarterPreferences): void {
const pStr : string = JSON.stringify(prefs);
if (pStr !== StarterPrefers_private_latest) {
// something changed, store the update
localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr);
}
}
}
export interface StarterDataEntry {
moveset: StarterMoveset | StarterFormMoveData;
eggMoves: integer;
@ -1261,7 +1301,7 @@ export class GameData {
if (!bypassLogin && dataType < GameDataType.SETTINGS) {
updateUserInfo().then(success => {
if (!success) {
if (!success[0]) {
return displayError(`Could not contact the server. Your ${dataName} data could not be imported.`);
}
let url: string;

View File

@ -21,6 +21,7 @@ import { pokemonInfo as zhTwPokemonInfo } from "#app/locales/zh_TW/pokemon-info.
import { battle as zhTwBattleStat } from "#app/locales/zh_TW/battle.js";
import i18next, {initI18n} from "#app/plugins/i18n";
import { KoreanPostpositionProcessor } from "i18next-korean-postposition-processor";
interface BattleStatTestUnit {
stat: BattleStat,
@ -198,7 +199,9 @@ describe("Test for BattleStat Localization", () => {
it("Test getBattleStatLevelChangeDescription() in 한국어", async () => {
i18next.changeLanguage("ko", () => {
battleStatLevelUnits.forEach(unit => {
testBattleStatLevelChangeDescription(unit.levels, unit.up, koBattleStat[unit.key]);
const processor = new KoreanPostpositionProcessor();
const message = processor.process(koBattleStat[unit.key]);
testBattleStatLevelChangeDescription(unit.levels, unit.up, message);
});
});
});

View File

@ -1,8 +1,8 @@
import i18next from "i18next";
import BattleScene from "../battle-scene";
import * as Utils from "../utils";
import { TextStyle, addTextObject } from "./text";
import { WindowVariant, addWindow } from "./ui-theme";
import * as Utils from "../utils";
import i18next from "i18next";
interface RankingEntry {
rank: integer,
@ -154,7 +154,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container {
return entryContainer;
};
this.rankingsContainer.add(getEntry("#", "Username", "Score", "Wave"));
this.rankingsContainer.add(getEntry(i18next.t("menu:positionIcon"), i18next.t("menu:usernameScoreboard"), i18next.t("menu:score"), i18next.t("menu:wave")));
rankings.forEach((r: RankingEntry, i: integer) => {
const entryContainer = getEntry(r.rank.toString(), r.username, r.score.toString(), r.wave.toString());

View File

@ -17,7 +17,7 @@ import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, g
import { Type } from "../data/type";
import { GameModes } from "../game-mode";
import { SelectChallengePhase, TitlePhase } from "../phases";
import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, StarterFormMoveData, StarterMoveset } from "../system/game-data";
import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, StarterFormMoveData, StarterMoveset, StarterAttributes, StarterPreferences, StarterPrefs } from "../system/game-data";
import { Tutorial, handleTutorial } from "../tutorial";
import * as Utils from "../utils";
import { OptionSelectItem } from "./abstact-option-select-ui-handler";
@ -270,6 +270,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
private starterSelectCallback: StarterSelectCallback;
private starterPreferences: StarterPreferences;
protected blockInput: boolean = false;
constructor(scene: BattleScene) {
@ -780,6 +782,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
}
show(args: any[]): boolean {
if (!this.starterPreferences) {
// starterPreferences haven't been loaded yet
this.starterPreferences = StarterPrefs.load();
}
this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers
if (args.length >= 1 && args[0] instanceof Function) {
super.show(args);
@ -1223,6 +1229,54 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
});
}
const starterData = this.scene.gameData.starterData[this.lastSpecies.speciesId];
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
if (this.canCycleNature) {
// if we could cycle natures, enable the improved nature menu
const showNatureOptions = () => {
ui.setMode(Mode.STARTER_SELECT).then(() => {
ui.showText(i18next.t("starterSelectUiHandler:selectNature"), null, () => {
const natures = this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry.natureAttr);
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
options: natures.map((n: Nature, i: number) => {
const option: OptionSelectItem = {
label: getNatureName(n, true, true, true, this.scene.uiTheme),
handler: () => {
// update default nature in starter save data
if (!starterAttributes) {
starterAttributes=
this.starterPreferences[this.lastSpecies.speciesId] = {};
}
starterAttributes.nature = n as unknown as integer;
this.clearText();
ui.setMode(Mode.STARTER_SELECT);
// set nature for starter
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, n, undefined);
return true;
}
};
return option;
}).concat({
label: i18next.t("menu:cancel"),
handler: () => {
this.clearText();
ui.setMode(Mode.STARTER_SELECT);
return true;
}
}),
maxOptions: 8,
yOffset: 19
});
});
});
};
options.push({
label: i18next.t("starterSelectUiHandler:manageNature"),
handler: () => {
showNatureOptions();
return true;
}
});
}
const candyCount = starterData.candyCount;
const passiveAttr = starterData.passiveAttr;
if (passiveAttr & PassiveAttr.UNLOCKED) {
@ -1362,9 +1416,16 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
const rows = Math.ceil(genStarters / 9);
const row = Math.floor(this.cursor / 9);
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor);
// prepare persistent starter data to store changes
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
if (!starterAttributes) {
starterAttributes =
this.starterPreferences[this.lastSpecies.speciesId] = {};
}
switch (button) {
case Button.CYCLE_SHINY:
if (this.canCycleShiny) {
starterAttributes.variant = !props.shiny ? props.variant : -1; // update shiny setting
this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, props.shiny ? 0 : undefined, undefined, undefined);
if (this.dexAttrCursor & DexAttr.SHINY) {
this.scene.playSound("sparkle");
@ -1383,12 +1444,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
break;
}
} while (newFormIndex !== props.formIndex);
starterAttributes.form = newFormIndex; // store the selected form
this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined, undefined, undefined);
success = true;
}
break;
case Button.CYCLE_GENDER:
if (this.canCycleGender) {
starterAttributes.female = !props.female;
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined, undefined, undefined);
success = true;
}
@ -1414,6 +1477,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
}
}
} while (newAbilityIndex !== this.abilityCursor);
starterAttributes.ability = newAbilityIndex; // store the selected ability
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newAbilityIndex, undefined);
success = true;
}
@ -1423,6 +1487,8 @@ 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];
// store cycled nature as default
starterAttributes.nature = newNature as unknown as integer;
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, newNature, undefined);
success = true;
}
@ -1446,6 +1512,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
}
}
} while (newVariant !== props.variant);
starterAttributes.variant = newVariant; // store the selected variant
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant, undefined, undefined);
// Cycle tint based on current sprite tint
@ -1782,6 +1849,60 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0;
this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(species) : 0;
const starterAttributes : StarterAttributes = species ? {...this.starterPreferences[species.speciesId]} : null;
// validate starterAttributes
if (starterAttributes) {
// this may cause changes so we created a copy of the attributes before
if (!isNaN(starterAttributes.variant)) {
if (![
this.speciesStarterDexEntry.caughtAttr & DexAttr.NON_SHINY,
this.speciesStarterDexEntry.caughtAttr & DexAttr.DEFAULT_VARIANT,
this.speciesStarterDexEntry.caughtAttr & DexAttr.VARIANT_2,
this.speciesStarterDexEntry.caughtAttr & DexAttr.VARIANT_3
][starterAttributes.variant+1]) { // add 1 as -1 = non-shiny
// requested variant wasn't unlocked, purging setting
delete starterAttributes.variant;
}
}
if (typeof starterAttributes.female !== "boolean" || !(starterAttributes.female ?
this.speciesStarterDexEntry.caughtAttr & DexAttr.FEMALE :
this.speciesStarterDexEntry.caughtAttr & DexAttr.MALE
)) {
// requested gender wasn't unlocked, purging setting
delete starterAttributes.female;
}
const abilityAttr = this.scene.gameData.starterData[species.speciesId].abilityAttr;
if (![
abilityAttr & AbilityAttr.ABILITY_1,
species.ability2 ? (abilityAttr & AbilityAttr.ABILITY_2) : abilityAttr & AbilityAttr.ABILITY_HIDDEN,
species.ability2 && abilityAttr & AbilityAttr.ABILITY_HIDDEN
][starterAttributes.ability]) {
// requested ability wasn't unlocked, purging setting
delete starterAttributes.ability;
}
if (!(species.forms[starterAttributes.form]?.isStarterSelectable && this.speciesStarterDexEntry.caughtAttr & this.scene.gameData.getFormAttr(starterAttributes.form))) {
// requested form wasn't unlocked/isn't a starter form, purging setting
delete starterAttributes.form;
}
if (this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry.natureAttr).indexOf(starterAttributes.nature as unknown as Nature) < 0) {
// requested nature wasn't unlocked, purging setting
delete starterAttributes.nature;
}
}
if (starterAttributes?.nature) {
// load default nature from stater save data, if set
this.natureCursor = starterAttributes.nature;
}
if (!isNaN(starterAttributes?.ability)) {
// load default nature from stater save data, if set
this.abilityCursor = starterAttributes.ability;
}
if (this.statsMode) {
if (this.speciesStarterDexEntry?.caughtAttr) {
this.statsContainer.setVisible(true);
@ -1920,9 +2041,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
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, false, true);
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
// load default nature from stater save data, if set
const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(species);
props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
if (!isNaN(starterAttributes?.variant)) {
if (props.shiny = (starterAttributes.variant >= 0)) {
props.variant = starterAttributes.variant as Variant;
}
}
props.formIndex = starterAttributes?.form ?? props.formIndex;
props.female = starterAttributes?.female ?? props.female;
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, defaultAbilityIndex, defaultNature);
}
@ -2417,6 +2546,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
clear(): void {
super.clear();
StarterPrefs.save(this.starterPreferences);
this.cursor = -1;
this.hideInstructions();
this.starterSelectContainer.setVisible(false);

View File

@ -3,6 +3,7 @@ import { ModalConfig, ModalUiHandler } from "./modal-ui-handler";
import { addTextObject, TextStyle } from "./text";
import { Mode } from "./ui";
import { updateUserInfo } from "#app/account";
import * as Utils from "#app/utils";
export default class UnavailableModalUiHandler extends ModalUiHandler {
private reconnectTimer: NodeJS.Timeout;
@ -55,6 +56,9 @@ export default class UnavailableModalUiHandler extends ModalUiHandler {
this.reconnectDuration = this.minTime;
this.scene.playSound("pb_bounce_1");
this.reconnectCallback();
} else if (response[1] === 401) {
Utils.setCookie(Utils.sessionIdKey, "");
this.scene.reset(true, true);
} else {
this.reconnectDuration = Math.min(this.reconnectDuration * 2, this.maxTime); // Set a max delay so it isn't infinite
this.reconnectTimer =