From 4f4d107b2184c6c4d1fd03e9304ad1cf20bbe9d6 Mon Sep 17 00:00:00 2001 From: RedstonewolfX <108761527+RedstonewolfX@users.noreply.github.com> Date: Sun, 7 Jul 2024 14:04:53 -0400 Subject: [PATCH 1/3] Logger UI --- src/logger.ts | 69 +++++++++++ src/phases.ts | 261 +++++++++++++++++++++++++++++++++++++++- src/system/game-data.ts | 2 + 3 files changed, 327 insertions(+), 5 deletions(-) create mode 100644 src/logger.ts diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 00000000000..9ac47f0702a --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,69 @@ +import i18next from "i18next"; +import * as Utils from "./utils"; + +/** + * All logs. + * + * Format: [filename, localStorage key, name, header] + */ +export const logs: string[][] = [ + ["instructions.txt", "path_log", "Steps", "Run Steps", "wide_lens"], + ["encounters.csv", "enc_log", "Encounters", "Encounter Data"], + ["log.txt", "debug_log", "Debug", "Debug Log"], +] +export var logKeys: string[] = [ + "i", // Instructions/steps + "e", // Encounters + "d", // Debug +]; + +export const byteSize = str => new Blob([str]).size +const filesizes = ["b", "kb", "mb", "gb", "tb"] +export function getSize(str: string) { + var d = byteSize(str) + var unit = 0 + while (d > 1000 && unit < filesizes.length - 1) { + d = Math.round(d/100)/10 + unit++ + } + return d.toString() + filesizes[unit] +} + +/** + * Writes data to a new line. + * @param keyword The identifier key for the log you're writing to + * @param data The string you're writing to the given log + */ +export function toLog(keyword: string, data: string) { + localStorage.setItem(logs[logKeys.indexOf(keyword)][1], localStorage.getItem(logs[logKeys.indexOf(keyword)][1] + "\n" + data)) +} +/** + * Writes data on the same line you were on. + * @param keyword The identifier key for the log you're writing to + * @param data The string you're writing to the given log + */ +export function appendLog(keyword: string, data: string) { + localStorage.setItem(logs[logKeys.indexOf(keyword)][1], localStorage.getItem(logs[logKeys.indexOf(keyword)][1] + data)) +} +/** + * + * Clears all data from a log. + * @param keyword The identifier key for the log you want to reste + */ +export function clearLog(keyword: string) { + localStorage.setItem(logs[logKeys.indexOf(keyword)][1], "---- " + logs[logKeys.indexOf(keyword)][3] + " ----") +} +/** + * Saves a log to your device. + * @param keyword The identifier key for the log you want to reste + */ +export function downloadLog(keyword: string) { + var d = localStorage.getItem(logs[logKeys.indexOf(keyword)][1]) + // logs[logKeys.indexOf(keyword)][1] + const blob = new Blob([ d ], {type: "text/json"}); + const link = document.createElement("a"); + link.href = window.URL.createObjectURL(blob); + link.download = `${logs[logKeys.indexOf(keyword)][0]}`; + link.click(); + link.remove(); +} \ No newline at end of file diff --git a/src/phases.ts b/src/phases.ts index 51391971308..8b8602b5d5c 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -36,7 +36,7 @@ import { EggHatchPhase } from "./egg-hatch-phase"; import { Egg } from "./data/egg"; import { vouchers } from "./system/voucher"; import { clientSessionId, loggedInUser, updateUserInfo } from "./account"; -import { SessionSaveData } from "./system/game-data"; +import { SessionSaveData, decrypt } from "./system/game-data"; import { addPokeballCaptureStars, addPokeballOpenParticles } from "./field/anims"; import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger } from "./data/pokemon-forms"; import { battleSpecDialogue, getCharVariantFromDialogue, miscDialogue } from "./data/dialogue"; @@ -65,9 +65,171 @@ import { Moves } from "#enums/moves"; import { PlayerGender } from "#enums/player-gender"; import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; +import TrainerData from "./system/trainer-data"; +import PersistentModifierData from "./system/modifier-data"; +import ArenaData from "./system/arena-data"; +import ChallengeData from "./system/challenge-data"; +import { Challenges } from "./enums/challenges" +import PokemonData from "./system/pokemon-data" +import * as LoggerTools from "./logger" const { t } = i18next; +export function parseSlotData(slotId: integer): SessionSaveData { + var S = localStorage.getItem(`sessionData${slotId ? slotId : ""}_${loggedInUser.username}`) + if (S == null) { + // No data in this slot + return undefined; + } + var dataStr = decrypt(S, true) + var Save = JSON.parse(dataStr, (k: string, v: any) => { + /*const versions = [ scene.game.config.gameVersion, sessionData.gameVersion || '0.0.0' ]; + + if (versions[0] !== versions[1]) { + const [ versionNumbers, oldVersionNumbers ] = versions.map(ver => ver.split('.').map(v => parseInt(v))); + }*/ + + if (k === "party" || k === "enemyParty") { + const ret: PokemonData[] = []; + if (v === null) { + v = []; + } + for (const pd of v) { + ret.push(new PokemonData(pd)); + } + return ret; + } + + if (k === "trainer") { + return v ? new TrainerData(v) : null; + } + + if (k === "modifiers" || k === "enemyModifiers") { + const player = k === "modifiers"; + const ret: PersistentModifierData[] = []; + if (v === null) { + v = []; + } + for (const md of v) { + if (md?.className === "ExpBalanceModifier") { // Temporarily limit EXP Balance until it gets reworked + md.stackCount = Math.min(md.stackCount, 4); + } + if (md instanceof EnemyAttackStatusEffectChanceModifier && md.effect === StatusEffect.FREEZE || md.effect === StatusEffect.SLEEP) { + continue; + } + ret.push(new PersistentModifierData(md, player)); + } + return ret; + } + + if (k === "arena") { + return new ArenaData(v); + } + + if (k === "challenges") { + const ret: ChallengeData[] = []; + if (v === null) { + v = []; + } + for (const c of v) { + ret.push(new ChallengeData(c)); + } + return ret; + } + + return v; + }) as SessionSaveData; + Save.slot = slotId + Save.description = slotId + " - " + var challengeParts: ChallengeData[] = new Array(5) + var nameParts: string[] = new Array(5) + if (Save.challenges != undefined) { + for (var i = 0; i < Save.challenges.length; i++) { + switch (Save.challenges[i].id) { + case Challenges.SINGLE_TYPE: + challengeParts[0] = Save.challenges[i] + nameParts[1] = Save.challenges[i].toChallenge().getValue() + nameParts[1] = nameParts[1][0].toUpperCase() + nameParts[1].substring(1) + if (nameParts[1] == "unknown") { + nameParts[1] = undefined + challengeParts[1] = undefined + } + break; + case Challenges.SINGLE_GENERATION: + challengeParts[1] = Save.challenges[i] + nameParts[0] = "Gen " + Save.challenges[i].value + if (nameParts[0] == "Gen 0") { + nameParts[0] = undefined + challengeParts[0] = undefined + } + break; + case Challenges.LOWER_MAX_STARTER_COST: + challengeParts[2] = Save.challenges[i] + nameParts[3] = (10 - challengeParts[0].value) + "cost" + break; + case Challenges.LOWER_STARTER_POINTS: + challengeParts[3] = Save.challenges[i] + nameParts[4] = (10 - challengeParts[0].value) + "pt" + break; + case Challenges.FRESH_START: + challengeParts[4] = Save.challenges[i] + nameParts[2] = "FS" + break; + } + } + } + for (var i = 0; i < challengeParts.length; i++) { + if (challengeParts[i] == undefined || challengeParts[i] == null) { + challengeParts.splice(i, 1) + i-- + } + } + for (var i = 0; i < nameParts.length; i++) { + if (nameParts[i] == undefined || nameParts[i] == null || nameParts[i] == "") { + nameParts.splice(i, 1) + i-- + } + } + if (challengeParts.length == 1 && false) { + switch (challengeParts[0].id) { + case Challenges.SINGLE_TYPE: + Save.description += "Mono " + challengeParts[0].toChallenge().getValue() + break; + case Challenges.SINGLE_GENERATION: + Save.description += "Gen " + challengeParts[0].value + break; + case Challenges.LOWER_MAX_STARTER_COST: + Save.description += "Max cost " + (10 - challengeParts[0].value) + break; + case Challenges.LOWER_STARTER_POINTS: + Save.description += (10 - challengeParts[0].value) + "-point" + break; + case Challenges.FRESH_START: + Save.description += "Fresh Start" + break; + } + } else if (challengeParts.length == 0) { + switch (Save.gameMode) { + case GameModes.CLASSIC: + Save.description += "Classic"; + break; + case GameModes.ENDLESS: + Save.description += "Endless"; + break; + case GameModes.SPLICED_ENDLESS: + Save.description += "Endless+"; + break; + case GameModes.DAILY: + Save.description += "Daily"; + break; + } + } else { + Save.description += nameParts.join(" ") + } + Save.description += " (" + getBiomeName(Save.arena.biome) + " " + Save.waveIndex + ")" + return Save; +} + export class LoginPhase extends Phase { private showText: boolean; @@ -198,8 +360,25 @@ export class TitlePhase extends Phase { }); } + getLastSave(log?: boolean, dailyOnly?: boolean): SessionSaveData { + var saves: Array> = []; + for (var i = 0; i < 5; i++) { + var s = parseSlotData(i); + if (s != undefined) { + if (!dailyOnly || s.gameMode == GameModes.DAILY) { + saves.push([i, s, s.timestamp]); + } + } + } + saves.sort((a, b): integer => {return b[2] - a[2]}) + if (log) console.log(saves) + return saves[0][1] + } + showOptions(): void { + var hasFile = true const options: OptionSelectItem[] = []; + if (false) if (loggedInUser.lastSessionSlot > -1) { options.push({ label: i18next.t("continue", null, { ns: "menu"}), @@ -209,6 +388,34 @@ export class TitlePhase extends Phase { } }); } + // Replaces 'Continue' with the last Daily Run that the player completed a floor on + // If there are no daily runs, it instead shows the most recently saved run + // If this fails too, there are no saves, and the option does not appear + var lastsave = this.getLastSave(false, true); + if (lastsave != undefined) { + options.push({ + label: (this.getLastSave().description ? this.getLastSave().description : "[???]"), + handler: () => { + this.loadSaveSlot(this.getLastSave().slot); + return true; + } + }) + } else { + lastsave = this.getLastSave(false); + if (lastsave != undefined) { + options.push({ + label: (this.getLastSave().description ? this.getLastSave().description : "[???]"), + handler: () => { + this.loadSaveSlot(this.getLastSave().slot); + return true; + } + }) + } else { + console.log("Failed to get last save") + this.getLastSave(true) + hasFile = false + } + } options.push({ label: i18next.t("menu:newGame"), handler: () => { @@ -269,8 +476,52 @@ export class TitlePhase extends Phase { } return true; } - }, - { + }, { + label: "Manage Logs", + handler: () => { + const options: OptionSelectItem[] = []; + for (var i = 0; i < LoggerTools.logs.length; i++) { + if (localStorage.getItem(LoggerTools.logs[i][1]) != null) + options.push({ + label: `Export ${LoggerTools.logs[i][2]} (${LoggerTools.getSize(LoggerTools.logs[i][2])})`, + handler: () => { + LoggerTools.downloadLog(LoggerTools.logKeys[i]) + return true; + } + }) + } + options.push({ + label: `Export all (${options.length})`, + handler: () => { + for (var i = 0; i < LoggerTools.logKeys[i].length; i++) { + LoggerTools.downloadLog(LoggerTools.logKeys[i]) + } + return true; + } + }, { + label: `Reset all (${LoggerTools.logKeys[i].length})`, + handler: () => { + for (var i = 0; i < LoggerTools.logKeys[i].length; i++) { + LoggerTools.clearLog(LoggerTools.logKeys[i]) + } + return true; + } + }, { + label: i18next.t("menu:cancel"), + handler: () => { + this.scene.clearPhaseQueue(); + this.scene.pushPhase(new TitlePhase(this.scene)); + super.end(); + return true; + } + }); + this.scene.ui.showText("Export or clear game logs.", null, () => this.scene.ui.setOverlayMode(Mode.OPTION_SELECT, { options: options })); + return true; + } + }) + // If the player has no save data (as determined above), hide the "Load Game" button + if (hasFile) + options.push({ label: i18next.t("menu:loadGame"), handler: () => { this.scene.ui.setOverlayMode(Mode.SAVE_SLOT, SaveSlotUiMode.LOAD, @@ -282,8 +533,8 @@ export class TitlePhase extends Phase { }); return true; } - }, - { + }) + options.push({ label: i18next.t("menu:dailyRun"), handler: () => { this.initDailyRun(); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index ac54c942fc7..ff4b9fb686b 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -122,6 +122,8 @@ export interface SessionSaveData { gameVersion: string; timestamp: integer; challenges: ChallengeData[]; + slot: integer; + description: string; } interface Unlocks { From ab96325a825d49086ac8c2db09708dfc79016f6e Mon Sep 17 00:00:00 2001 From: RedstonewolfX <108761527+RedstonewolfX@users.noreply.github.com> Date: Sun, 7 Jul 2024 14:19:20 -0400 Subject: [PATCH 2/3] Add to GUI --- src/phases.ts | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 8b8602b5d5c..9002b9b0aa0 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -140,7 +140,7 @@ export function parseSlotData(slotId: integer): SessionSaveData { return v; }) as SessionSaveData; Save.slot = slotId - Save.description = slotId + " - " + Save.description = (slotId + 1) + " - " var challengeParts: ChallengeData[] = new Array(5) var nameParts: string[] = new Array(5) if (Save.challenges != undefined) { @@ -372,8 +372,25 @@ export class TitlePhase extends Phase { } saves.sort((a, b): integer => {return b[2] - a[2]}) if (log) console.log(saves) + if (saves == undefined) return undefined; + if (saves[0] == undefined) return undefined; return saves[0][1] } + getSaves(log?: boolean, dailyOnly?: boolean): SessionSaveData[] { + var saves: Array> = []; + for (var i = 0; i < 5; i++) { + var s = parseSlotData(i); + if (s != undefined) { + if (!dailyOnly || s.gameMode == GameModes.DAILY) { + saves.push([i, s, s.timestamp]); + } + } + } + saves.sort((a, b): integer => {return b[2] - a[2]}) + if (log) console.log(saves) + if (saves == undefined) return undefined; + return saves.map(f => f[1]); + } showOptions(): void { var hasFile = true @@ -388,25 +405,27 @@ export class TitlePhase extends Phase { } }); } - // Replaces 'Continue' with the last Daily Run that the player completed a floor on + // Replaces 'Continue' with all Daily Run saves, sorted by when they last saved // If there are no daily runs, it instead shows the most recently saved run // If this fails too, there are no saves, and the option does not appear - var lastsave = this.getLastSave(false, true); - if (lastsave != undefined) { - options.push({ - label: (this.getLastSave().description ? this.getLastSave().description : "[???]"), - handler: () => { - this.loadSaveSlot(this.getLastSave().slot); - return true; - } + var lastsaves = this.getSaves(false, true); + if (lastsaves != undefined) { + lastsaves.forEach(lastsave => { + options.push({ + label: (lastsave.description ? lastsave.description : "[???]"), + handler: () => { + this.loadSaveSlot(lastsave.slot); + return true; + } + }) }) } else { - lastsave = this.getLastSave(false); + var lastsave = this.getLastSave(false); if (lastsave != undefined) { options.push({ - label: (this.getLastSave().description ? this.getLastSave().description : "[???]"), + label: (lastsave.description ? lastsave.description : "[???]"), handler: () => { - this.loadSaveSlot(this.getLastSave().slot); + this.loadSaveSlot(lastsave.slot); return true; } }) From 9722264f1b25399c233179b4c724a547c023d6a4 Mon Sep 17 00:00:00 2001 From: RedstonewolfX <108761527+RedstonewolfX@users.noreply.github.com> Date: Sun, 7 Jul 2024 17:22:51 -0400 Subject: [PATCH 3/3] Log encounters --- src/logger.ts | 115 +++++++++++++++++++++++++++++++++++++++++++++++--- src/phases.ts | 21 +++++---- 2 files changed, 120 insertions(+), 16 deletions(-) diff --git a/src/logger.ts b/src/logger.ts index 9ac47f0702a..5d8a1970952 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,15 +1,21 @@ import i18next from "i18next"; import * as Utils from "./utils"; +import Pokemon from "./field/pokemon"; +import { PlayerPokemon, EnemyPokemon } from "./field/pokemon"; +import { Nature, getNatureName } from "./data/nature"; +import BattleScene from "./battle-scene"; +import { OptionSelectItem } from "./ui/abstact-option-select-ui-handler"; +import { TrainerType } from "#enums/trainer-type"; /** * All logs. * - * Format: [filename, localStorage key, name, header] + * Format: [filename, localStorage key, name, header, item sprite, header suffix] */ export const logs: string[][] = [ - ["instructions.txt", "path_log", "Steps", "Run Steps", "wide_lens"], - ["encounters.csv", "enc_log", "Encounters", "Encounter Data"], - ["log.txt", "debug_log", "Debug", "Debug Log"], + ["instructions.txt", "path_log", "Steps", "Run Steps", "wide_lens", ""], + ["encounters.csv", "enc_log", "Encounters", "Encounter Data", "", ",,,,,,,,,,,,,,,,"], + ["log.txt", "debug_log", "Debug", "Debug Log", "", ""], ] export var logKeys: string[] = [ "i", // Instructions/steps @@ -29,6 +35,16 @@ export function getSize(str: string) { return d.toString() + filesizes[unit] } +export function generateOption(i: integer): OptionSelectItem { + return { + label: `Export ${logs[i][2]} (${getSize(localStorage.getItem(logs[i][1]))})`, + handler: () => { + downloadLogByID(i) + return false; + } + } +} + /** * Writes data to a new line. * @param keyword The identifier key for the log you're writing to @@ -51,7 +67,7 @@ export function appendLog(keyword: string, data: string) { * @param keyword The identifier key for the log you want to reste */ export function clearLog(keyword: string) { - localStorage.setItem(logs[logKeys.indexOf(keyword)][1], "---- " + logs[logKeys.indexOf(keyword)][3] + " ----") + localStorage.setItem(logs[logKeys.indexOf(keyword)][1], "---- " + logs[logKeys.indexOf(keyword)][3] + " ----" + logs[logKeys.indexOf(keyword)][5]) } /** * Saves a log to your device. @@ -66,4 +82,93 @@ export function downloadLog(keyword: string) { link.download = `${logs[logKeys.indexOf(keyword)][0]}`; link.click(); link.remove(); +} +export function downloadLogByID(i: integer) { + console.log(i) + var d = localStorage.getItem(logs[i][1]) + const blob = new Blob([ d ], {type: "text/json"}); + const link = document.createElement("a"); + link.href = window.URL.createObjectURL(blob); + link.download = `${logs[i][0]}`; + link.click(); + link.remove(); +} +export function logTeam(scene: BattleScene, floor: integer = undefined) { + if (floor == undefined) floor = scene.currentBattle.waveIndex + var team = scene.getEnemyParty() + if (team[0].hasTrainer()) { + var sprite = scene.currentBattle.trainer.config.getSpriteKey() + var trainerCat = Utils.getEnumKeys(TrainerType)[Utils.getEnumValues(TrainerType).indexOf(scene.currentBattle.trainer.config.trainerType)] + setRow("e", floor + "," + team.length + "," + sprite + ",trainer," + trainerCat + ",,,,,,,,,,,,", floor, 0) + } else { + for (var i = 0; i < team.length; i++) { + logPokemon(scene, floor, i, team[i]) + } + if (team.length == 1) { + setRow("e", ",,,,,,,,,,,,,,,,", floor, 1) + } + } +} +export function logPokemon(scene: BattleScene, floor: integer = undefined, slot: integer, pokemon: EnemyPokemon) { + if (floor == undefined) floor = scene.currentBattle.waveIndex + var modifiers: string[] = [] + var mods = pokemon.getHeldItems() + for (var i = 0; i < mods.length; i++) { + modifiers.push(mods[i].type.name + (mods[i].getMaxStackCount(scene) == 1 ? "" : " x" + mods[i].getStackCount())) + } + var sprite = pokemon.getBattleSpriteAtlasPath() + // floor,party slot,encounter,species,ability,passive,level,gender,isBoss,nature,HP IV,Attack IV,Defense IV,Sp. Atk IV,Sp. Def IV,Speed IV,Items separated by slashes / + var newLine = floor + "," + + slot + "," + + sprite + "," + + (pokemon.hasTrainer() ? "trainer_pokemon" : "wild") + "," + + pokemon.species.getName(pokemon.formIndex) + (pokemon.getFormKey() == "" ? "" : " (" + pokemon.getFormKey() + ")") + "," + + pokemon.getAbility().name.toLowerCase() + "," + + pokemon.getPassiveAbility().name.toLowerCase() + "," + + pokemon.level + "," + + (pokemon.gender == 0 ? "M" : (pokemon.gender == 1 ? "F" : "")) + "," + + (pokemon.isBoss() ? "true" : "false") + "," + + getNatureName(pokemon.nature) + "," + + pokemon.ivs[0] + "," + + pokemon.ivs[1] + "," + + pokemon.ivs[2] + "," + + pokemon.ivs[3] + "," + + pokemon.ivs[4] + "," + + pokemon.ivs[5] + "," + + modifiers.join("/") + //console.log(idx, data.slice(0, idx), newLine, data.slice(idx)) + setRow("e", newLine, floor, slot) + //console.log(localStorage.getItem(logs[logKeys.indexOf("e")][1]).split("\n")) +} +export function setRow(keyword: string, newLine: string, floor: integer, slot: integer) { + var data = localStorage.getItem(logs[logKeys.indexOf(keyword)][1]).split("\n") + var idx = 1 + if (slot == -1) { + while (idx < data.length && (data[idx].split(",")[0] as any) * 1 < floor) { + idx++ + } + idx-- + slot = ((data[idx].split(",")[1] as any) * 1) + 1 + } else { + while (idx < data.length && (data[idx].split(",")[0] as any) * 1 <= floor && (data[idx].split(",")[1] as any) * 1 <= slot) { + idx++ + } + } + localStorage.setItem(logs[logKeys.indexOf(keyword)][1], data.slice(0, idx).join("\n") + "\n" + newLine + (data.slice(idx).length == 0 ? "" : "\n") + data.slice(idx).join("\n")); +} +export function setRowByID(key: integer, newLine: string, floor: integer, slot: integer) { + var data = localStorage.getItem(logs[key][1]).split("\n") + var idx = 1 + if (slot == -1) { + while (idx < data.length && (data[idx].split(",")[0] as any) * 1 < floor) { + idx++ + } + idx-- + slot = ((data[idx].split(",")[1] as any) * 1) + 1 + } else { + while (idx < data.length && (data[idx].split(",")[0] as any) * 1 <= floor && (data[idx].split(",")[1] as any) * 1 <= slot) { + idx++ + } + } + localStorage.setItem(logs[key][1], data.slice(0, idx).join("\n") + "\n" + newLine + (data.slice(idx).length == 0 ? "" : "\n") + data.slice(idx).join("\n")); } \ No newline at end of file diff --git a/src/phases.ts b/src/phases.ts index 9002b9b0aa0..18a5d112a08 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -501,28 +501,25 @@ export class TitlePhase extends Phase { const options: OptionSelectItem[] = []; for (var i = 0; i < LoggerTools.logs.length; i++) { if (localStorage.getItem(LoggerTools.logs[i][1]) != null) - options.push({ - label: `Export ${LoggerTools.logs[i][2]} (${LoggerTools.getSize(LoggerTools.logs[i][2])})`, - handler: () => { - LoggerTools.downloadLog(LoggerTools.logKeys[i]) - return true; - } - }) + options.push(LoggerTools.generateOption(i) as OptionSelectItem) } options.push({ label: `Export all (${options.length})`, handler: () => { - for (var i = 0; i < LoggerTools.logKeys[i].length; i++) { + for (var i = 0; i < LoggerTools.logKeys.length; i++) { LoggerTools.downloadLog(LoggerTools.logKeys[i]) } - return true; + return false; } }, { - label: `Reset all (${LoggerTools.logKeys[i].length})`, + label: `Reset all (${LoggerTools.logKeys.length})`, handler: () => { - for (var i = 0; i < LoggerTools.logKeys[i].length; i++) { + for (var i = 0; i < LoggerTools.logKeys.length; i++) { LoggerTools.clearLog(LoggerTools.logKeys[i]) } + this.scene.clearPhaseQueue(); + this.scene.pushPhase(new TitlePhase(this.scene)); + super.end(); return true; } }, { @@ -1250,6 +1247,8 @@ export class EncounterPhase extends BattlePhase { doEncounterCommon(showEncounterMessage: boolean = true) { const enemyField = this.scene.getEnemyField(); + LoggerTools.logTeam(this.scene, this.scene.currentBattle.waveIndex) + if (this.scene.currentBattle.battleType === BattleType.WILD) { enemyField.forEach(enemyPokemon => { enemyPokemon.untint(100, "Sine.easeOut");