// ************ Save stuff ************ function save() { localStorage.setItem(modInfo.id, btoa(JSON.stringify(player))); } function startPlayerBase() { return { tab: layoutInfo.startTab, navTab: (layoutInfo.showTree ? "tree-tab" : "none"), time: Date.now(), autosave: true, notify: {}, msDisplay: "always", offlineProd: true, versionType: modInfo.id, version: VERSION.num, beta: VERSION.beta, timePlayed: 0, keepGoing: false, hasNaN: false, hideChallenges: false, showStory: true, forceOneTab: false, points: modInfo.initialStartPoints, subtabs: {}, lastSafeTab: (layoutInfo.showTree ? "none" : layoutInfo.startTab) }; } function getStartPlayer() { let playerdata = startPlayerBase(); if (addedPlayerData) { let extradata = addedPlayerData(); for (let thing in extradata) { playerdata[thing] = extradata[thing]; } } playerdata.infoboxes = {}; for (let layer in layers) { playerdata[layer] = getStartLayerData(layer); if (layers[layer].tabFormat && !Array.isArray(layers[layer].tabFormat)) { playerdata.subtabs[layer] = {}; playerdata.subtabs[layer].mainTabs = Object.keys(layers[layer].tabFormat)[0]; } if (layers[layer].microtabs) { if (playerdata.subtabs[layer] === undefined) { playerdata.subtabs[layer] = {}; } for (item in layers[layer].microtabs) { playerdata.subtabs[layer][item] = Object.keys(layers[layer].microtabs[item])[0]; } } if (layers[layer].infoboxes) { if (playerdata.infoboxes[layer] === undefined) { playerdata.infoboxes[layer] = {}; } for (item in layers[layer].infoboxes) { playerdata.infoboxes[layer][item] = false; } } } return playerdata; } function getStartLayerData(layer) { let layerdata = {}; if (layers[layer].startData) { layerdata = layers[layer].startData(); } if (layerdata.unlocked === undefined) { layerdata.unlocked = true; } if (layerdata.total === undefined) { layerdata.total = decimalZero; } if (layerdata.best === undefined) { layerdata.best = decimalZero; } if (layerdata.resetTime === undefined) { layerdata.resetTime = 0; } if (layerdata.forceTooltip === undefined) { layerdata.forceTooltip = false; } layerdata.buyables = getStartBuyables(layer); if (layerdata.noRespecConfirm === undefined) { layerdata.noRespecConfirm = false; } if (layerdata.clickables === undefined) { layerdata.clickables = getStartClickables(layer); } layerdata.spentOnBuyables = decimalZero; layerdata.upgrades = []; layerdata.milestones = []; layerdata.lastMilestone = null; layerdata.achievements = []; layerdata.challenges = getStartChallenges(layer); layerdata.grid = getStartGrid(layer); return layerdata; } function getStartBuyables(layer) { let data = {}; if (layers[layer].buyables) { for (let id in layers[layer].buyables) { if (isPlainObject(layers[layer].buyables[id])) { data[id] = decimalZero; } } } return data; } function getStartClickables(layer) { let data = {}; if (layers[layer].clickables) { for (let id in layers[layer].clickables) { if (isPlainObject(layers[layer].clickables[id])) { data[id] = ""; } } } return data; } function getStartChallenges(layer) { let data = {}; if (layers[layer].challenges) { for (let id in layers[layer].challenges) { if (isPlainObject(layers[layer].challenges[id])) { data[id] = 0; } } } return data; } function getStartGrid(layer) { let data = {}; if (! layers[layer].grid) return data if (layers[layer].grid.maxRows === undefined) layers[layer].grid.maxRows=layers[layer].grid.rows if (layers[layer].grid.maxCols === undefined) layers[layer].grid.maxCols=layers[layer].grid.cols for (let y = 1; y <= layers[layer].grid.maxRows; y++) { for (let x = 1; x <= layers[layer].grid.maxCols; x++) { data[100*y + x] = layers[layer].grid.getStartData(100*y + x) } } return data; } function fixSave() { let defaultData = getStartPlayer(); fixData(defaultData, player); setBuyableAmount("distill", "retort", (getBuyableAmount("distill", "retort") || decimalZero).max(5)); player.sands.chipping = false; player.rituals.rituals = getRituals(); for (let layer in layers) { if (player[layer].best !== undefined) { player[layer].best = new Decimal(player[layer].best); } if (player[layer].total !== undefined) { player[layer].total = new Decimal(player[layer].total); } if (layers[layer].tabFormat && !Array.isArray(layers[layer].tabFormat)) { if (!Object.keys(layers[layer].tabFormat).includes(player.subtabs[layer].mainTabs)) { player.subtabs[layer].mainTabs = Object.keys(layers[layer].tabFormat)[0]; } } if (layers[layer].microtabs) { for (let item in layers[layer].microtabs) { if (!Object.keys(layers[layer].microtabs[item]).includes(player.subtabs[layer][item])) { player.subtabs[layer][item] = Object.keys(layers[layer].microtabs[item])[0]; } } } } } function fixData(defaultData, newData) { for (let item in defaultData) { if (defaultData[item] == null) { if (newData[item] === undefined) { newData[item] = null; } } else if (Array.isArray(defaultData[item])) { if (newData[item] === undefined) { newData[item] = defaultData[item]; } else { fixData(defaultData[item], newData[item]); } } else if (defaultData[item] instanceof Decimal) { // Convert to Decimal if (newData[item] === undefined) { newData[item] = defaultData[item]; } else { newData[item] = new Decimal(newData[item]); } } else if ((!!defaultData[item]) && (typeof defaultData[item] === "object")) { if (newData[item] === undefined || (typeof defaultData[item] !== "object")) { newData[item] = defaultData[item]; // Note: Dangerously ignoring "cards" here, because player.study.cards was re-adding any cards // from the starter deck that got completely removed by the player } else if (item !== "cards") { fixData(defaultData[item], newData[item]); } } else { if (newData[item] === undefined) { newData[item] = defaultData[item]; } } } } function load() { let get = localStorage.getItem(modInfo.id); if (get === null || get === undefined) { player = getStartPlayer(); } else { player = Object.assign(getStartPlayer(), JSON.parse(decodeURIComponent(escape(atob(get))))); } fixSave(); if (player.offlineProd) { if (player.offTime === undefined) { player.offTime = { remain: 0 }; } player.offTime.remain += (Date.now() - player.time) / 1000; } player.time = Date.now(); versionCheck(); changeTheme(); changeTreeQuality(); updateLayers(); setupModInfo(); setupTemp(); updateTemp(); updateTemp(); updateTabFormats(); loadVue(); } function setupModInfo() { modInfo.changelog = changelog; modInfo.winText = winText ? winText : "Congratulations! You have reached the end and beaten this game, but for now..."; } function fixNaNs() { NaNcheck(player); } // noinspection SpellCheckingInspection function NaNcheck(data) { for (let item in data) { if (data[item] == null) { } else if (Array.isArray(data[item])) { NaNcheck(data[item]); } else if (data[item] !== data[item] || data[item] === decimalNaN) { if (NaNalert === true || confirm("Invalid value found in player, named '" + item + "'. Please let the creator of this mod know! Would you like to try to auto-fix the save and keep going?")) { NaNalert = true; data[item] = (data[item] !== data[item] ? 0 : decimalZero); } else { clearInterval(interval); player.autosave = false; NaNalert = true; } } else if (data[item] instanceof Decimal) { // Convert to Decimal } else if ((!!data[item]) && (data[item].constructor === Object)) { NaNcheck(data[item]); } } } function exportSave() { let str = btoa(JSON.stringify(player)); const el = document.createElement("textarea"); el.value = str; document.body.appendChild(el); el.select(); el.setSelectionRange(0, 99999); document.execCommand("copy"); document.body.removeChild(el); } function importSave(imported = undefined, forced = false) { if (imported === undefined) { imported = prompt("Paste your save here"); } try { let tempPlr = Object.assign(getStartPlayer(), JSON.parse(atob(imported))); if (tempPlr.versionType !== modInfo.id && !forced && !confirm("This save appears to be for a different mod! Are you sure you want to import?")) // Wrong save (use "Forced" to force it to accept.) { return; } player = tempPlr; player.versionType = modInfo.id; fixSave(); versionCheck(); save(); window.location.reload(); } catch (e) { } } function versionCheck() { let setVersion = true; if (player.versionType === undefined || player.version === undefined) { player.versionType = modInfo.id; player.version = 0; } if (setVersion) { if (player.versionType === modInfo.id && VERSION.num > player.version) { player.keepGoing = false; if (fixOldSave) { fixOldSave(player.version); } } player.versionType = getStartPlayer().versionType; player.version = VERSION.num; player.beta = VERSION.beta; } } // noinspection JSUnusedGlobalSymbols const saveInterval = setInterval(function () { if (player === undefined) { return; } if (gameEnded && !player.keepGoing) { return; } if (player.autosave) { save(); } }, 5000);