diff --git a/index.html b/index.html
index a5c136b..ac0fdd7 100644
--- a/index.html
+++ b/index.html
@@ -19,6 +19,10 @@
+
+
+
+
diff --git a/js/utils.js b/js/utils.js
index 8a61a6a..dbf5c78 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -1,454 +1,3 @@
-// ************ Number formatting ************
-
-function exponentialFormat(num, precision, mantissa = true) {
- let e = num.log10().floor()
- let m = num.div(Decimal.pow(10, e))
- if(m.toStringWithDecimalPlaces(precision) == 10) {
- m = new Decimal(1)
- e = e.add(1)
- }
- e = (e.gte(10000) ? commaFormat(e, 0) : e.toStringWithDecimalPlaces(0))
- if (mantissa)
- return m.toStringWithDecimalPlaces(precision)+"e"+e
- else return "e"+e
- }
-
-function commaFormat(num, precision) {
- if (num === null || num === undefined) return "NaN"
- if (num.mag < 0.001) return (0).toFixed(precision)
- return num.toStringWithDecimalPlaces(precision).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")
-}
-
-
-function regularFormat(num, precision) {
- if (num === null || num === undefined) return "NaN"
- if (num.mag < 0.001) return (0).toFixed(precision)
- return num.toStringWithDecimalPlaces(precision)
-}
-
-function fixValue(x, y = 0) {
- return x || new Decimal(y)
-}
-
-function sumValues(x) {
- x = Object.values(x)
- if (!x[0]) return new Decimal(0)
- return x.reduce((a, b) => Decimal.add(a, b))
-}
-
-function format(decimal, precision=2,) {
- decimal = new Decimal(decimal)
- if (isNaN(decimal.sign)||isNaN(decimal.layer)||isNaN(decimal.mag)) {
- player.hasNaN = true;
- return "NaN"
- }
- if (decimal.sign<0) return "-"+format(decimal.neg(), precision)
- if (decimal.mag == Number.POSITIVE_INFINITY) return "Infinity"
- if (decimal.gte("eeee1000")) {
- var slog = decimal.slog()
- if (slog.gte(1e6)) return "F" + format(slog.floor())
- else return Decimal.pow(10, slog.sub(slog.floor())).toStringWithDecimalPlaces(3) + "F" + commaFormat(slog.floor(), 0)
- }
- else if (decimal.gte("1e100000")) return exponentialFormat(decimal, 0, false)
- else if (decimal.gte("1e1000")) return exponentialFormat(decimal, 0)
- else if (decimal.gte(1e9)) return exponentialFormat(decimal, precision)
- else if (decimal.gte(1e3)) return commaFormat(decimal, 0)
- else return regularFormat(decimal, precision)
-}
-
-function formatWhole(decimal) {
- decimal = new Decimal(decimal)
- if (decimal.gte(1e9)) return format(decimal, 2)
- if (decimal.lte(0.98) && !decimal.eq(0)) return format(decimal, 2)
- return format(decimal, 0)
-}
-
-function formatTime(s) {
- if (s<60) return format(s)+"s"
- else if (s<3600) return formatWhole(Math.floor(s/60))+"m "+format(s%60)+"s"
- else if (s<86400) return formatWhole(Math.floor(s/3600))+"h "+formatWhole(Math.floor(s/60)%60)+"m "+format(s%60)+"s"
- else if (s<31536000) return formatWhole(Math.floor(s/84600)%365)+"d " + formatWhole(Math.floor(s/3600)%24)+"h "+formatWhole(Math.floor(s/60)%60)+"m "+format(s%60)+"s"
- else return formatWhole(Math.floor(s/31536000))+"y "+formatWhole(Math.floor(s/84600)%365)+"d " + formatWhole(Math.floor(s/3600)%24)+"h "+formatWhole(Math.floor(s/60)%60)+"m "+format(s%60)+"s"
-}
-
-function toPlaces(x, precision, maxAccepted) {
- x = new Decimal(x)
- let result = x.toStringWithDecimalPlaces(precision)
- if (new Decimal(result).gte(maxAccepted)) {
- result = new Decimal(maxAccepted-Math.pow(0.1, precision)).toStringWithDecimalPlaces(precision)
- }
- return result
-}
-// ************ 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,
- points: modInfo.initialStartPoints,
- subtabs: {},
- lastSafeTab: (layoutInfo.showTree ? "none" : layoutInfo.startTab)
- }
-}
-
-function getStartPlayer() {
- playerdata = startPlayerBase()
-
- if (addedPlayerData) {
- extradata = addedPlayerData()
- for (thing in extradata)
- playerdata[thing] = extradata[thing]
- }
-
- playerdata.infoboxes = {}
- for (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){
- layerdata = {}
- if (layers[layer].startData)
- layerdata = layers[layer].startData()
-
- if (layerdata.unlocked === undefined) layerdata.unlocked = true
- if (layerdata.total === undefined) layerdata.total = new Decimal(0)
- if (layerdata.best === undefined) layerdata.best = new Decimal(0)
- if (layerdata.resetTime === undefined) layerdata.resetTime = 0
-
- layerdata.buyables = getStartBuyables(layer)
- if(layerdata.clickables == undefined) layerdata.clickables = getStartClickables(layer)
- layerdata.spentOnBuyables = new Decimal(0)
- layerdata.upgrades = []
- layerdata.milestones = []
- layerdata.achievements = []
- layerdata.challenges = getStartChallenges(layer)
- return layerdata
-}
-
-
-function getStartBuyables(layer){
- let data = {}
- if (layers[layer].buyables) {
- for (id in layers[layer].buyables)
- if (isPlainObject(layers[layer].buyables[id]))
- data[id] = new Decimal(0)
- }
- return data
-}
-
-function getStartClickables(layer){
- let data = {}
- if (layers[layer].clickables) {
- for (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 (id in layers[layer].challenges)
- if (isPlainObject(layers[layer].challenges[id]))
- data[id] = 0
- }
- return data
-}
-
-function fixSave() {
- defaultData = getStartPlayer()
- fixData(defaultData, player)
-
- for(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 (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 (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]
- else
- 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(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();
- 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)
-}
-
-function NaNcheck(data) {
- for (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 {
- 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) {
- return;
- }
-}
-
-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
- }
-}
-
-var saveInterval = setInterval(function() {
- if (player===undefined) return;
- if (gameEnded&&!player.keepGoing) return;
- if (player.autosave) save();
-}, 5000)
-
-// ************ Themes ************
-
-const themes = {
- 1: "aqua"
-}
-const theme_names = {
- aqua: "Aqua"
-}
-
-function changeTheme() {
- let aqua = player.theme == "aqua"
- colors_theme = colors[player.theme || "default"]
- document.body.style.setProperty('--background', aqua ? "#001f3f" : "#0f0f0f")
- document.body.style.setProperty('--background_tooltip', aqua ? "rgba(0, 15, 31, 0.75)" : "rgba(0, 0, 0, 0.75)")
- document.body.style.setProperty('--color', aqua ? "#bfdfff" : "#dfdfdf")
- document.body.style.setProperty('--points', aqua ? "#dfefff" : "#ffffff")
- document.body.style.setProperty("--locked", aqua ? "#c4a7b3" : "#bf8f8f")
-}
-
-function getThemeName() {
- return player.theme ? theme_names[player.theme] : "Default"
-}
-
-function switchTheme() {
- if (player.theme === undefined) player.theme = themes[1]
- else {
- player.theme = themes[Object.keys(themes)[player.theme] + 1]
- if (!player.theme) delete player.theme
- }
- changeTheme()
- resizeCanvas()
-}
-
-// ************ Options ************
-
-function toggleOpt(name) {
- if (name == "oldStyle" && styleCooldown>0) return;
-
- player[name] = !player[name]
- if (name == "hqTree") changeTreeQuality()
- if (name == "oldStyle") updateStyle()
-}
-
-var styleCooldown = 0;
-
-
-function updateStyle() {
- styleCooldown = 1;
- let css = document.getElementById("styleStuff")
- css.href = player.oldStyle?"oldStyle.css":"style.css"
- needCanvasUpdate = true;
-}
-
-function changeTreeQuality() {
- var on = player.hqTree
- document.body.style.setProperty('--hqProperty1', on ? "2px solid" : "4px solid")
- document.body.style.setProperty('--hqProperty2a', on ? "-4px -4px 4px rgba(0, 0, 0, 0.25) inset" : "-4px -4px 4px rgba(0, 0, 0, 0) inset")
- document.body.style.setProperty('--hqProperty2b', on ? "0px 0px 20px var(--background)" : "")
- document.body.style.setProperty('--hqProperty3', on ? "2px 2px 4px rgba(0, 0, 0, 0.25)" : "none")
-}
-
-function toggleAuto(toggle) {
- player[toggle[0]][toggle[1]] = !player[toggle[0]][toggle[1]]
-}
-
-function adjustMSDisp() {
- let displays = ["always", "automation", "incomplete", "never"];
- player.msDisplay = displays[(displays.indexOf(player.msDisplay)+1)%4]
-}
-
-function milestoneShown(layer, id) {
- complete = player[layer].milestones.includes(id)
- auto = layers[layer].milestones[id].toggles
-
- switch(player.msDisplay) {
- case "always":
- return true;
- break;
- case "automation":
- return (auto)||!complete
- break;
- case "incomplete":
- return !complete
- break;
- case "never":
- return false;
- break;
- }
- return false;
-}
-
-
-
// ************ Big Feature related ************
function respecBuyables(layer) {
@@ -464,79 +13,79 @@ function canAffordUpgrade(layer, id) {
let upg = tmp[layer].upgrades[id]
if (tmp[layer].upgrades[id].canAfford !== undefined) return tmp[layer].upgrades[id].canAfford
let cost = tmp[layer].upgrades[id].cost
- return canAffordPurchase(layer, upg, cost)
+ return canAffordPurchase(layer, upg, cost)
}
-function hasUpgrade(layer, id){
+function hasUpgrade(layer, id) {
return (player[layer].upgrades.includes(toNumber(id)) || player[layer].upgrades.includes(id.toString()))
}
-function hasMilestone(layer, id){
+function hasMilestone(layer, id) {
return (player[layer].milestones.includes(toNumber(id)) || player[layer].milestones.includes(id.toString()))
}
-function hasAchievement(layer, id){
+function hasAchievement(layer, id) {
return (player[layer].achievements.includes(toNumber(id)) || player[layer].achievements.includes(id.toString()))
}
-function hasChallenge(layer, id){
+function hasChallenge(layer, id) {
return (player[layer].challenges[id])
}
-function maxedChallenge(layer, id){
+function maxedChallenge(layer, id) {
return (player[layer].challenges[id] >= tmp[layer].challenges[id].completionLimit)
}
-function challengeCompletions(layer, id){
+function challengeCompletions(layer, id) {
return (player[layer].challenges[id])
}
-function getBuyableAmount(layer, id){
+function getBuyableAmount(layer, id) {
return (player[layer].buyables[id])
}
-function setBuyableAmount(layer, id, amt){
+function setBuyableAmount(layer, id, amt) {
player[layer].buyables[id] = amt
}
-function getClickableState(layer, id){
+function getClickableState(layer, id) {
return (player[layer].clickables[id])
}
-function setClickableState(layer, id, state){
+function setClickableState(layer, id, state) {
player[layer].clickables[id] = state
}
-function upgradeEffect(layer, id){
+function upgradeEffect(layer, id) {
return (tmp[layer].upgrades[id].effect)
}
-function challengeEffect(layer, id){
+function challengeEffect(layer, id) {
return (tmp[layer].challenges[id].rewardEffect)
}
-function buyableEffect(layer, id){
+function buyableEffect(layer, id) {
return (tmp[layer].buyables[id].effect)
}
-function clickableEffect(layer, id){
+function clickableEffect(layer, id) {
return (tmp[layer].clickables[id].effect)
}
-function achievementEffect(layer, id){
+function achievementEffect(layer, id) {
return (tmp[layer].achievements[id].effect)
}
function canAffordPurchase(layer, thing, cost) {
- if (thing.currencyInternalName){
+ if (thing.currencyInternalName) {
let name = thing.currencyInternalName
- if (thing.currencyLocation){
- return !(thing.currencyLocation[name].lt(cost))
+ if (thing.currencyLocation) {
+ return !(thing.currencyLocation[name].lt(cost))
}
- else if (thing.currencyLayer){
+ else if (thing.currencyLayer) {
let lr = thing.currencyLayer
- return !(player[lr][name].lt(cost))
+ return !(player[lr][name].lt(cost))
}
else {
return !(player[name].lt(cost))
@@ -561,17 +110,16 @@ function buyUpg(layer, id) {
let pay = layers[layer].upgrades[id].pay
if (pay !== undefined)
run(pay, layers[layer].upgrades[id])
- else
- {
+ else {
let cost = tmp[layer].upgrades[id].cost
- if (upg.currencyInternalName){
+ if (upg.currencyInternalName) {
let name = upg.currencyInternalName
- if (upg.currencyLocation){
+ if (upg.currencyLocation) {
if (upg.currencyLocation[name].lt(cost)) return
upg.currencyLocation[name] = upg.currencyLocation[name].sub(cost)
}
- else if (upg.currencyLayer){
+ else if (upg.currencyLayer) {
let lr = upg.currencyLayer
if (player[lr][name].lt(cost)) return
player[lr][name] = player[lr][name].sub(cost)
@@ -583,7 +131,7 @@ function buyUpg(layer, id) {
}
else {
if (player[layer].points.lt(cost)) return
- player[layer].points = player[layer].points.sub(cost)
+ player[layer].points = player[layer].points.sub(cost)
}
}
player[layer].upgrades.push(id);
@@ -620,11 +168,11 @@ function clickClickable(layer, id) {
}
// Function to determine if the player is in a challenge
-function inChallenge(layer, id){
+function inChallenge(layer, id) {
let challenge = player[layer].activeChallenge
if (!challenge) return false
id = toNumber(id)
- if (challenge==id) return true
+ if (challenge == id) return true
if (layers[layer].challenges[challenge].countsAs)
return tmp[layer].challenges[challenge].countsAs.includes(id)
@@ -681,7 +229,7 @@ function notifyLayer(name) {
player.notify[name] = 1
}
-function subtabShouldNotify(layer, family, id){
+function subtabShouldNotify(layer, family, id) {
let subtab = {}
if (family == "mainTabs") subtab = tmp[layer].tabFormat[id]
else subtab = tmp[layer].microtabs[family][id]
@@ -690,7 +238,7 @@ function subtabShouldNotify(layer, family, id){
else return subtab.shouldNotify
}
-function subtabResetNotify(layer, family, id){
+function subtabResetNotify(layer, family, id) {
let subtab = {}
if (family == "mainTabs") subtab = tmp[layer].tabFormat[id]
else subtab = tmp[layer].microtabs[family][id]
@@ -700,7 +248,7 @@ function subtabResetNotify(layer, family, id){
function nodeShown(layer) {
if (layerShown(layer)) return true
- switch(layer) {
+ switch (layer) {
case "idk":
return player.idk.unlocked
break;
@@ -724,17 +272,17 @@ function toNumber(x) {
return x
}
-function updateMilestones(layer){
- for (id in layers[layer].milestones){
- if (!(hasMilestone(layer, id)) && layers[layer].milestones[id].done()){
+function updateMilestones(layer) {
+ for (id in layers[layer].milestones) {
+ if (!(hasMilestone(layer, id)) && layers[layer].milestones[id].done()) {
player[layer].milestones.push(id)
if (tmp[layer].milestonePopups || tmp[layer].milestonePopups === undefined) doPopup("milestone", tmp[layer].milestones[id].requirementDescription, "Milestone Gotten!", 3, tmp[layer].color);
}
}
}
-function updateAchievements(layer){
- for (id in layers[layer].achievements){
+function updateAchievements(layer) {
+ for (id in layers[layer].achievements) {
if (isPlainObject(layers[layer].achievements[id]) && !(hasAchievement(layer, id)) && layers[layer].achievements[id].done()) {
player[layer].achievements.push(id)
if (layers[layer].achievements[id].onComplete) layers[layer].achievements[id].onComplete()
@@ -767,16 +315,16 @@ function addTime(diff, layer) {
else data.timePlayed = time
}
-document.onkeydown = function(e) {
- if (player===undefined) return;
- if (gameEnded&&!player.keepGoing) return;
+document.onkeydown = function (e) {
+ if (player === undefined) return;
+ if (gameEnded && !player.keepGoing) return;
let shiftDown = e.shiftKey
let ctrlDown = e.ctrlKey
let key = e.key
if (ctrlDown) key = "ctrl+" + key
if (onFocused) return
if (ctrlDown && hotkeys[key]) e.preventDefault()
- if(hotkeys[key]){
+ if (hotkeys[key]) {
if (player[hotkeys[key].layer].unlocked)
hotkeys[key].onPress()
}
@@ -787,16 +335,15 @@ function focused(x) {
onFocused = x
}
-function prestigeButtonText(layer)
-{
+function prestigeButtonText(layer) {
if (layers[layer].prestigeButtonText !== undefined)
return layers[layer].prestigeButtonText()
- else if(tmp[layer].type == "normal")
- return `${ player[layer].points.lt(1e3) ? (tmp[layer].resetDescription !== undefined ? tmp[layer].resetDescription : "Reset for ") : ""}+${formatWhole(tmp[layer].resetGain)} ${tmp[layer].resource} ${tmp[layer].resetGain.lt(100) && player[layer].points.lt(1e3) ? `
Next at ${ (tmp[layer].roundUpCost ? formatWhole(tmp[layer].nextAt) : format(tmp[layer].nextAt))} ${ tmp[layer].baseResource }` : ""}`
- else if(tmp[layer].type== "static")
- return `${tmp[layer].resetDescription !== undefined ? tmp[layer].resetDescription : "Reset for "}+${formatWhole(tmp[layer].resetGain)} ${tmp[layer].resource}
${player[layer].points.lt(30) ? (tmp[layer].baseAmount.gte(tmp[layer].nextAt)&&(tmp[layer].canBuyMax !== undefined) && tmp[layer].canBuyMax?"Next:":"Req:") : ""} ${formatWhole(tmp[layer].baseAmount)} / ${(tmp[layer].roundUpCost ? formatWhole(tmp[layer].nextAtDisp) : format(tmp[layer].nextAtDisp))} ${ tmp[layer].baseResource }
+ else if (tmp[layer].type == "normal")
+ return `${player[layer].points.lt(1e3) ? (tmp[layer].resetDescription !== undefined ? tmp[layer].resetDescription : "Reset for ") : ""}+${formatWhole(tmp[layer].resetGain)} ${tmp[layer].resource} ${tmp[layer].resetGain.lt(100) && player[layer].points.lt(1e3) ? `
Next at ${(tmp[layer].roundUpCost ? formatWhole(tmp[layer].nextAt) : format(tmp[layer].nextAt))} ${tmp[layer].baseResource}` : ""}`
+ else if (tmp[layer].type == "static")
+ return `${tmp[layer].resetDescription !== undefined ? tmp[layer].resetDescription : "Reset for "}+${formatWhole(tmp[layer].resetGain)} ${tmp[layer].resource}
${player[layer].points.lt(30) ? (tmp[layer].baseAmount.gte(tmp[layer].nextAt) && (tmp[layer].canBuyMax !== undefined) && tmp[layer].canBuyMax ? "Next:" : "Req:") : ""} ${formatWhole(tmp[layer].baseAmount)} / ${(tmp[layer].roundUpCost ? formatWhole(tmp[layer].nextAtDisp) : format(tmp[layer].nextAtDisp))} ${tmp[layer].baseResource}
`
- else if(tmp[layer].type == "none")
+ else if (tmp[layer].type == "none")
return ""
else
return "You need prestige button text"
@@ -804,7 +351,7 @@ function prestigeButtonText(layer)
function isFunction(obj) {
return !!(obj && obj.constructor && obj.call && obj.apply);
- };
+};
function isPlainObject(obj) {
return (!!obj) && (obj.constructor === Object)
@@ -819,8 +366,8 @@ var activePopups = [];
var popupID = 0;
// Function to show popups
-function doPopup(type="none",text="This is a test popup.",title="",timer=3, color="") {
- switch(type) {
+function doPopup(type = "none", text = "This is a test popup.", title = "", timer = 3, color = "") {
+ switch (type) {
case "achievement":
popupTitle = "Achievement Unlocked!";
popupType = "achievement-popup"
@@ -834,28 +381,28 @@ function doPopup(type="none",text="This is a test popup.",title="",timer=3, colo
popupType = "default-popup"
break;
}
- if(title != "") popupTitle = title;
+ if (title != "") popupTitle = title;
popupMessage = text;
- popupTimer = timer;
+ popupTimer = timer;
- activePopups.push({"time":popupTimer,"type":popupType,"title":popupTitle,"message":(popupMessage+"\n"),"id":popupID, "color":color})
+ activePopups.push({ "time": popupTimer, "type": popupType, "title": popupTitle, "message": (popupMessage + "\n"), "id": popupID, "color": color })
popupID++;
}
//Function to reduce time on active popups
function adjustPopupTime(diff) {
- for(popup in activePopups) {
+ for (popup in activePopups) {
activePopups[popup].time -= diff;
- if(activePopups[popup]["time"] < 0) {
- activePopups.splice(popup,1); // Remove popup when time hits 0
+ if (activePopups[popup]["time"] < 0) {
+ activePopups.splice(popup, 1); // Remove popup when time hits 0
}
}
}
-function run(func, target, args=null){
- if (!!(func && func.constructor && func.call && func.apply)){
- let bound = func.bind(target)
+function run(func, target, args = null) {
+ if (!!(func && func.constructor && func.call && func.apply)) {
+ let bound = func.bind(target)
return bound(args)
}
else
diff --git a/js/utils/NumberFormating.js b/js/utils/NumberFormating.js
new file mode 100644
index 0000000..c01d98c
--- /dev/null
+++ b/js/utils/NumberFormating.js
@@ -0,0 +1,80 @@
+
+function exponentialFormat(num, precision, mantissa = true) {
+ let e = num.log10().floor()
+ let m = num.div(Decimal.pow(10, e))
+ if (m.toStringWithDecimalPlaces(precision) == 10) {
+ m = new Decimal(1)
+ e = e.add(1)
+ }
+ e = (e.gte(10000) ? commaFormat(e, 0) : e.toStringWithDecimalPlaces(0))
+ if (mantissa)
+ return m.toStringWithDecimalPlaces(precision) + "e" + e
+ else return "e" + e
+}
+
+function commaFormat(num, precision) {
+ if (num === null || num === undefined) return "NaN"
+ if (num.mag < 0.001) return (0).toFixed(precision)
+ return num.toStringWithDecimalPlaces(precision).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")
+}
+
+
+function regularFormat(num, precision) {
+ if (num === null || num === undefined) return "NaN"
+ if (num.mag < 0.001) return (0).toFixed(precision)
+ return num.toStringWithDecimalPlaces(precision)
+}
+
+function fixValue(x, y = 0) {
+ return x || new Decimal(y)
+}
+
+function sumValues(x) {
+ x = Object.values(x)
+ if (!x[0]) return new Decimal(0)
+ return x.reduce((a, b) => Decimal.add(a, b))
+}
+
+function format(decimal, precision = 2,) {
+ decimal = new Decimal(decimal)
+ if (isNaN(decimal.sign) || isNaN(decimal.layer) || isNaN(decimal.mag)) {
+ player.hasNaN = true;
+ return "NaN"
+ }
+ if (decimal.sign < 0) return "-" + format(decimal.neg(), precision)
+ if (decimal.mag == Number.POSITIVE_INFINITY) return "Infinity"
+ if (decimal.gte("eeee1000")) {
+ var slog = decimal.slog()
+ if (slog.gte(1e6)) return "F" + format(slog.floor())
+ else return Decimal.pow(10, slog.sub(slog.floor())).toStringWithDecimalPlaces(3) + "F" + commaFormat(slog.floor(), 0)
+ }
+ else if (decimal.gte("1e100000")) return exponentialFormat(decimal, 0, false)
+ else if (decimal.gte("1e1000")) return exponentialFormat(decimal, 0)
+ else if (decimal.gte(1e9)) return exponentialFormat(decimal, precision)
+ else if (decimal.gte(1e3)) return commaFormat(decimal, 0)
+ else return regularFormat(decimal, precision)
+}
+
+function formatWhole(decimal) {
+ decimal = new Decimal(decimal)
+ if (decimal.gte(1e9)) return format(decimal, 2)
+ if (decimal.lte(0.98) && !decimal.eq(0)) return format(decimal, 2)
+ return format(decimal, 0)
+}
+
+function formatTime(s) {
+ if (s < 60) return format(s) + "s"
+ else if (s < 3600) return formatWhole(Math.floor(s / 60)) + "m " + format(s % 60) + "s"
+ else if (s < 86400) return formatWhole(Math.floor(s / 3600)) + "h " + formatWhole(Math.floor(s / 60) % 60) + "m " + format(s % 60) + "s"
+ else if (s < 31536000) return formatWhole(Math.floor(s / 84600) % 365) + "d " + formatWhole(Math.floor(s / 3600) % 24) + "h " + formatWhole(Math.floor(s / 60) % 60) + "m " + format(s % 60) + "s"
+ else return formatWhole(Math.floor(s / 31536000)) + "y " + formatWhole(Math.floor(s / 84600) % 365) + "d " + formatWhole(Math.floor(s / 3600) % 24) + "h " + formatWhole(Math.floor(s / 60) % 60) + "m " + format(s % 60) + "s"
+}
+
+function toPlaces(x, precision, maxAccepted) {
+ x = new Decimal(x)
+ let result = x.toStringWithDecimalPlaces(precision)
+ if (new Decimal(result).gte(maxAccepted)) {
+ result = new Decimal(maxAccepted - Math.pow(0.1, precision)).toStringWithDecimalPlaces(precision)
+ }
+ return result
+}
diff --git a/js/utils/options.js b/js/utils/options.js
new file mode 100644
index 0000000..01e03be
--- /dev/null
+++ b/js/utils/options.js
@@ -0,0 +1,52 @@
+// ************ Options ************
+function toggleOpt(name) {
+ if (name == "oldStyle" && styleCooldown > 0)
+ return;
+
+ player[name] = !player[name];
+ if (name == "hqTree")
+ changeTreeQuality();
+ if (name == "oldStyle")
+ updateStyle();
+}
+var styleCooldown = 0;
+function updateStyle() {
+ styleCooldown = 1;
+ let css = document.getElementById("styleStuff");
+ css.href = player.oldStyle ? "oldStyle.css" : "style.css";
+ needCanvasUpdate = true;
+}
+function changeTreeQuality() {
+ var on = player.hqTree;
+ document.body.style.setProperty('--hqProperty1', on ? "2px solid" : "4px solid");
+ document.body.style.setProperty('--hqProperty2a', on ? "-4px -4px 4px rgba(0, 0, 0, 0.25) inset" : "-4px -4px 4px rgba(0, 0, 0, 0) inset");
+ document.body.style.setProperty('--hqProperty2b', on ? "0px 0px 20px var(--background)" : "");
+ document.body.style.setProperty('--hqProperty3', on ? "2px 2px 4px rgba(0, 0, 0, 0.25)" : "none");
+}
+function toggleAuto(toggle) {
+ player[toggle[0]][toggle[1]] = !player[toggle[0]][toggle[1]];
+}
+function adjustMSDisp() {
+ let displays = ["always", "automation", "incomplete", "never"];
+ player.msDisplay = displays[(displays.indexOf(player.msDisplay) + 1) % 4];
+}
+function milestoneShown(layer, id) {
+ complete = player[layer].milestones.includes(id);
+ auto = layers[layer].milestones[id].toggles;
+
+ switch (player.msDisplay) {
+ case "always":
+ return true;
+ break;
+ case "automation":
+ return (auto) || !complete;
+ break;
+ case "incomplete":
+ return !complete;
+ break;
+ case "never":
+ return false;
+ break;
+ }
+ return false;
+}
diff --git a/js/utils/save.js b/js/utils/save.js
new file mode 100644
index 0000000..7f9ced2
--- /dev/null
+++ b/js/utils/save.js
@@ -0,0 +1,278 @@
+// ************ 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,
+ points: modInfo.initialStartPoints,
+ subtabs: {},
+ lastSafeTab: (layoutInfo.showTree ? "none" : layoutInfo.startTab)
+ };
+}
+function getStartPlayer() {
+ playerdata = startPlayerBase();
+
+ if (addedPlayerData) {
+ extradata = addedPlayerData();
+ for (thing in extradata)
+ playerdata[thing] = extradata[thing];
+ }
+
+ playerdata.infoboxes = {};
+ for (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) {
+ layerdata = {};
+ if (layers[layer].startData)
+ layerdata = layers[layer].startData();
+
+ if (layerdata.unlocked === undefined)
+ layerdata.unlocked = true;
+ if (layerdata.total === undefined)
+ layerdata.total = new Decimal(0);
+ if (layerdata.best === undefined)
+ layerdata.best = new Decimal(0);
+ if (layerdata.resetTime === undefined)
+ layerdata.resetTime = 0;
+
+ layerdata.buyables = getStartBuyables(layer);
+ if (layerdata.clickables == undefined)
+ layerdata.clickables = getStartClickables(layer);
+ layerdata.spentOnBuyables = new Decimal(0);
+ layerdata.upgrades = [];
+ layerdata.milestones = [];
+ layerdata.achievements = [];
+ layerdata.challenges = getStartChallenges(layer);
+ return layerdata;
+}
+function getStartBuyables(layer) {
+ let data = {};
+ if (layers[layer].buyables) {
+ for (id in layers[layer].buyables)
+ if (isPlainObject(layers[layer].buyables[id]))
+ data[id] = new Decimal(0);
+ }
+ return data;
+}
+function getStartClickables(layer) {
+ let data = {};
+ if (layers[layer].clickables) {
+ for (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 (id in layers[layer].challenges)
+ if (isPlainObject(layers[layer].challenges[id]))
+ data[id] = 0;
+ }
+ return data;
+}
+function fixSave() {
+ defaultData = getStartPlayer();
+ fixData(defaultData, player);
+
+ for (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 (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 (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];
+
+ else
+ 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(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();
+ 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);
+}
+function NaNcheck(data) {
+ for (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 {
+ 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) {
+ return;
+ }
+}
+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;
+ }
+}
+var saveInterval = setInterval(function () {
+ if (player === undefined)
+ return;
+ if (gameEnded && !player.keepGoing)
+ return;
+ if (player.autosave)
+ save();
+}, 5000);
diff --git a/js/utils/themes.js b/js/utils/themes.js
new file mode 100644
index 0000000..b72e50b
--- /dev/null
+++ b/js/utils/themes.js
@@ -0,0 +1,30 @@
+// ************ Themes ************
+const themes = {
+ 1: "aqua"
+};
+const theme_names = {
+ aqua: "Aqua"
+};
+function changeTheme() {
+ let aqua = player.theme == "aqua";
+ colors_theme = colors[player.theme || "default"];
+ document.body.style.setProperty('--background', aqua ? "#001f3f" : "#0f0f0f");
+ document.body.style.setProperty('--background_tooltip', aqua ? "rgba(0, 15, 31, 0.75)" : "rgba(0, 0, 0, 0.75)");
+ document.body.style.setProperty('--color', aqua ? "#bfdfff" : "#dfdfdf");
+ document.body.style.setProperty('--points', aqua ? "#dfefff" : "#ffffff");
+ document.body.style.setProperty("--locked", aqua ? "#c4a7b3" : "#bf8f8f");
+}
+function getThemeName() {
+ return player.theme ? theme_names[player.theme] : "Default";
+}
+function switchTheme() {
+ if (player.theme === undefined)
+ player.theme = themes[1];
+ else {
+ player.theme = themes[Object.keys(themes)[player.theme] + 1];
+ if (!player.theme)
+ delete player.theme;
+ }
+ changeTheme();
+ resizeCanvas();
+}