mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-26 17:29:30 +02:00
Logger UI
This commit is contained in:
parent
a7d28e1ee7
commit
4f4d107b21
69
src/logger.ts
Normal file
69
src/logger.ts
Normal file
@ -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();
|
||||
}
|
261
src/phases.ts
261
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<Array<any>> = [];
|
||||
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();
|
||||
|
@ -122,6 +122,8 @@ export interface SessionSaveData {
|
||||
gameVersion: string;
|
||||
timestamp: integer;
|
||||
challenges: ChallengeData[];
|
||||
slot: integer;
|
||||
description: string;
|
||||
}
|
||||
|
||||
interface Unlocks {
|
||||
|
Loading…
Reference in New Issue
Block a user