let player; let needCanvasUpdate = true; let gameEnded = false; // Don't change this const TMT_VERSION = { tmtNum: "2.5.9.2", tmtName: "Dreams Really Do Come True" } function getResetGain(layer, useType = null) { let type = useType; if (!useType) { type = tmp[layer].type; if (layers[layer].getResetGain !== undefined) { return layers[layer].getResetGain(); } } if (tmp[layer].type === "none") { return decimalZero; } if (tmp[layer].gainExp.eq(0)) { return decimalZero; } if (type === "static") { if ((!tmp[layer].canBuyMax) || tmp[layer].baseAmount.lt(tmp[layer].requires)) { return decimalOne; } let gain = tmp[layer].baseAmount.div(tmp[layer].requires).div(tmp[layer].gainMult).max(1).log(tmp[layer].base).times(tmp[layer].gainExp).pow(Decimal.pow(tmp[layer].exponent, -1)); gain = gain.times(tmp[layer].directMult); return gain.floor().sub(player[layer].points).add(1).max(1); } else if (type === "normal") { if (tmp[layer].baseAmount.lt(tmp[layer].requires)) { return decimalZero; } let gain = tmp[layer].baseAmount.div(tmp[layer].requires).pow(tmp[layer].exponent).times(tmp[layer].gainMult).pow(tmp[layer].gainExp); if (gain.gte(tmp[layer].softcap)) { gain = gain.pow(tmp[layer].softcapPower).times(tmp[layer].softcap.pow(decimalOne.sub(tmp[layer].softcapPower))); } gain = gain.times(tmp[layer].directMult); return gain.floor().max(0); } else if (type === "custom") { return layers[layer].getResetGain(); } else { return decimalZero; } } function getNextAt(layer, canMax = false, useType = null) { let type = useType; if (!useType) { type = tmp[layer].type; if (layers[layer].getNextAt !== undefined) { return layers[layer].getNextAt(canMax); } } if (tmp[layer].type === "none") { return new Decimal(Infinity); } if (tmp[layer].gainMult.lte(0)) { return new Decimal(Infinity); } if (tmp[layer].gainExp.lte(0)) { return new Decimal(Infinity); } if (type === "static") { if (!tmp[layer].canBuyMax) { canMax = false; } let amt = player[layer].points.plus((canMax && tmp[layer].baseAmount.gte(tmp[layer].nextAt)) ? tmp[layer].resetGain : 0).div(tmp[layer].directMult); let extraCost = Decimal.pow(tmp[layer].base, amt.pow(tmp[layer].exponent).div(tmp[layer].gainExp)).times(tmp[layer].gainMult); let cost = extraCost.times(tmp[layer].requires).max(tmp[layer].requires); if (tmp[layer].roundUpCost) { cost = cost.ceil(); } return cost; } else if (type === "normal") { let next = tmp[layer].resetGain.add(1).div(tmp[layer].directMult); if (next.gte(tmp[layer].softcap)) { next = next.div(tmp[layer].softcap.pow(decimalOne.sub(tmp[layer].softcapPower))).pow(decimalOne.div(tmp[layer].softcapPower)); } next = next.root(tmp[layer].gainExp).div(tmp[layer].gainMult).root(tmp[layer].exponent).times(tmp[layer].requires).max(tmp[layer].requires); if (tmp[layer].roundUpCost) { next = next.ceil(); } return next; } else if (type === "custom") { return layers[layer].getNextAt(canMax); } else { return decimalZero; } } function softcap(value, cap, power = 0.5) { if (value.lte(cap)) { return value; } else { return value.pow(power).times(cap.pow(decimalOne.sub(power))); } } // Return true if the layer should be highlighted. By default checks for upgrades only. function shouldNotify(layer) { for (let id in tmp[layer].upgrades) { if (isPlainObject(layers[layer].upgrades[id])) { if (canAffordUpgrade(layer, id) && !hasUpgrade(layer, id) && tmp[layer].upgrades[id].unlocked) { return true; } } } if (player[layer].activeChallenge && canCompleteChallenge(layer, player[layer].activeChallenge)) { return true; } if (tmp[layer].shouldNotify) return true if (isPlainObject(tmp[layer].tabFormat)) { for (let subtab in tmp[layer].tabFormat) { if (subtabShouldNotify(layer, "mainTabs", subtab)) { tmp[layer].trueGlowColor = tmp[layer].tabFormat[subtab].glowColor return true; } } } for (let family in tmp[layer].microtabs) { for (let subtab in tmp[layer].microtabs[family]) { if (subtabShouldNotify(layer, family, subtab)) { tmp[layer].trueGlowColor = tmp[layer].microtabs[family][subtab].glowColor return true; } } } return false; } function canReset(layer) { if (layers[layer].canReset !== undefined) { return run(layers[layer].canReset, layers[layer]); } else if (tmp[layer].type === "normal") { return tmp[layer].baseAmount.gte(tmp[layer].requires); } else if (tmp[layer].type === "static") { return tmp[layer].baseAmount.gte(tmp[layer].nextAt); } else { return false; } } function rowReset(row, layer) { for (let lr in ROW_LAYERS[row]) { if (layers[lr].doReset) { player[lr].activeChallenge = null; // Exit challenges on any row reset on an equal or higher row run(layers[lr].doReset, layers[lr], layer); } else if (tmp[layer].row > tmp[lr].row && row !== "side" && !isNaN(row)) { layerDataReset(lr); } } } function layerDataReset(layer, keep = []) { let storedData = {unlocked: player[layer].unlocked, forceTooltip: player[layer].forceTooltip, noRespecConfirm: player[layer].noRespecConfirm} // Always keep these for (let thing in keep) { if (player[layer][keep[thing]] !== undefined) { storedData[keep[thing]] = player[layer][keep[thing]]; } } Vue.set(player[layer], "buyables", getStartBuyables(layer)); Vue.set(player[layer], "clickables", getStartClickables(layer)); Vue.set(player[layer], "challenges", getStartChallenges(layer)); layOver(player[layer], getStartLayerData(layer)); player[layer].upgrades = []; player[layer].milestones = []; player[layer].achievements = []; player[layer].challenges = getStartChallenges(layer); resetBuyables(layer); if (layers[layer].clickables && !player[layer].clickables) { player[layer].clickables = getStartClickables(layer); } for (let thing in storedData) { player[layer][thing] = storedData[thing]; } } function resetBuyables(layer) { if (layers[layer].buyables) { player[layer].buyables = getStartBuyables(layer); } player[layer].spentOnBuyables = decimalZero; } function addPoints(layer, gain) { if (isFunction(layers[layer].onAddPoints)) { layers[layer].onAddPoints(gain); } player[layer].points = player[layer].points.add(gain).max(0); if (player[layer].best) { player[layer].best = player[layer].best.max(player[layer].points); } if (player[layer].total) { player[layer].total = player[layer].total.add(gain); } } function generatePoints(layer, diff) { addPoints(layer, tmp[layer].resetGain.times(diff)); } let prevOnReset; function doReset(layer, force = false) { if (tmp[layer].type === "none") { return; } let row = tmp[layer].row; if (!force) { if (tmp[layer].baseAmount.lt(tmp[layer].requires)) { return; } let gain = tmp[layer].resetGain; if (tmp[layer].type === "static") { if (tmp[layer].baseAmount.lt(tmp[layer].nextAt)) { return; } gain = (tmp[layer].canBuyMax ? gain : 1); } if (tmp[layer].type === "custom") { if (!tmp[layer].canReset) { return; } } if (layers[layer].onPrestige) { run(layers[layer].onPrestige, layers[layer], gain); } addPoints(layer, gain); updateMilestones(layer); updateAchievements(layer); if (!player[layer].unlocked) { player[layer].unlocked = true; needCanvasUpdate = true; if (tmp[layer].increaseUnlockOrder) { let lrs = tmp[layer].increaseUnlockOrder; for (let lr in lrs) { if (!player[lrs[lr]].unlocked) { player[lrs[lr]].unlockOrder++; } } } } tmp[layer].baseAmount = decimalZero; // quick fix } if (tmp[layer].resetsNothing) { return; } for (let layerResetting in layers) { if (row >= layers[layerResetting].row && (!force || layerResetting !== layer)) { completeChallenge(layerResetting); } } prevOnReset = {...player}; //Deep Copy player.points = (row === 0 ? decimalZero : getStartPoints()); for (let x = row; x >= 0; x--) { rowReset(x, layer); } rowReset("side", layer); prevOnReset = undefined; player[layer].resetTime = 0; updateTemp(); updateTemp(); } function startChallenge(layer, x) { let enter = false; if (!player[layer].unlocked) { return; } if (player[layer].activeChallenge === x) { completeChallenge(layer, x); player[layer].activeChallenge = null; } else { enter = true; } doReset(layer, true); if (enter) { player[layer].activeChallenge = x; run(layers[layer].challenges[x].onEnter, layers[layer].challenges[x]); } updateChallengeTemp(layer); } function canCompleteChallenge(layer, x) { if (x !== player[layer].activeChallenge) { return; } let challenge = tmp[layer].challenges[x]; if (challenge.canComplete !== undefined) { return challenge.canComplete; } if (challenge.currencyInternalName) { let name = challenge.currencyInternalName; if (challenge.currencyLocation) { return !(challenge.currencyLocation[name].lt(challenge.goal)); } else if (challenge.currencyLayer) { let lr = challenge.currencyLayer; return !(player[lr][name].lt(challenge.goal)); } else { return !(player[name].lt(challenge.goal)); } } else { return !(player.points.lt(challenge.goal)); } } function completeChallenge(layer) { let x = player[layer].activeChallenge; if (!x) { return; } let completions = canCompleteChallenge(layer, x); if (!completions) { player[layer].activeChallenge = null; run(layers[layer].challenges[x].onExit, layers[layer].challenges[x]); return; } if (player[layer].challenges[x] < tmp[layer].challenges[x].completionLimit) { needCanvasUpdate = true; player[layer].challenges[x] += completions; player[layer].challenges[x] = Math.min(player[layer].challenges[x], tmp[layer].challenges[x].completionLimit); if (layers[layer].challenges[x].onComplete) { run(layers[layer].challenges[x].onComplete, layers[layer].challenges[x]); } } player[layer].activeChallenge = null; run(layers[layer].challenges[x].onExit, layers[layer].challenges[x]); updateChallengeTemp(layer); } VERSION.withoutName = "v" + VERSION.num + (VERSION.pre ? " Pre-Release " + VERSION.pre : VERSION.pre ? " Beta " + VERSION.beta : ""); VERSION.withName = VERSION.withoutName + (VERSION.name ? ": " + VERSION.name : ""); function autobuyUpgrades(layer) { if (!tmp[layer].upgrades) { return; } for (let id in tmp[layer].upgrades) { if (isPlainObject(tmp[layer].upgrades[id]) && (layers[layer].upgrades[id].canAfford === undefined || layers[layer].upgrades[id].canAfford() === true)) { buyUpg(layer, id); } } } function gameLoop(diff) { if (isEndgame() || gameEnded) { gameEnded = 1; } if (isNaN(diff)) { diff = 0; } if (gameEnded && !player.keepGoing) { diff = 0; player.tab = "gameEnded"; clearParticles(); } if (maxTickLength) { let limit = maxTickLength(); if (diff > limit) { diff = limit; } } addTime(diff); const modifiedDiff = diff * ritualEffect("speed").toNumber(); player.points = player.points.add(tmp.pointGen.times(modifiedDiff)).max(0); for (let x = 0; x <= maxRow; x++) { for (let item in TREE_LAYERS[x]) { let layer = TREE_LAYERS[x][item]; player[layer].resetTime += diff; if (tmp[layer].passiveGeneration) { generatePoints(layer, modifiedDiff * tmp[layer].passiveGeneration); } if (layers[layer].update) { layers[layer].update(modifiedDiff); } } } for (let row in OTHER_LAYERS) { for (let item in OTHER_LAYERS[row]) { let layer = OTHER_LAYERS[row][item]; player[layer].resetTime += diff; if (tmp[layer].passiveGeneration) { generatePoints(layer, modifiedDiff * tmp[layer].passiveGeneration); } if (layers[layer].update) { layers[layer].update(modifiedDiff); } } } for (let x = maxRow; x >= 0; x--) { for (let item in TREE_LAYERS[x]) { let layer = TREE_LAYERS[x][item]; if (tmp[layer].autoPrestige && tmp[layer].canReset) { doReset(layer); } if (layers[layer].automate) { layers[layer].automate(); } if (tmp[layer].autoUpgrade) { autobuyUpgrades(layer); } } } for (let row in OTHER_LAYERS) { for (let item in OTHER_LAYERS[row]) { let layer = OTHER_LAYERS[row][item]; if (tmp[layer].autoPrestige && tmp[layer].canReset) { doReset(layer); } if (layers[layer].automate) { layers[layer].automate(); } player[layer].best = player[layer].best.max(player[layer].points); if (tmp[layer].autoUpgrade) { autobuyUpgrades(layer); } } } for (let layer in layers) { if (layers[layer].milestones) { updateMilestones(layer); } if (layers[layer].achievements) { updateAchievements(layer); } } } function hardReset(override = false) { if (!(override || confirm("Are you sure you want to do this? You will lose all your progress!"))) { return; } player = null; save(); window.location.reload(); } let ticking = false; let lastTenTicks = []; const interval = setInterval(function () { if (player === undefined || tmp === undefined) { return; } if (ticking) { return; } if (gameEnded && !player.keepGoing) { return; } ticking = true; let now = Date.now(); let diff = (now - player.time) / 1e3; let trueDiff = diff; if (player.offTime !== undefined) { if (player.offTime.remain > modInfo.offlineLimit * 3600) { player.offTime.remain = modInfo.offlineLimit * 3600; } if (player.offTime.remain > 0) { let offlineDiff = Math.max(player.offTime.remain / 10, diff); player.offTime.remain -= offlineDiff; diff += offlineDiff; } if (!player.offlineProd || player.offTime.remain <= 0) { player.offTime = undefined; } } if (player.devSpeed != null) { diff *= player.devSpeed; } player.time = now; if (needCanvasUpdate) { resizeCanvas(); needCanvasUpdate = false; } tmp.scrolled = document.getElementById("treeTab")?.scrollTop > 30; updateTemp(); updateOomps(diff); updateWidth() updateTabFormats() gameLoop(diff); fixNaNs(); adjustPopupTime(trueDiff); updateParticles(trueDiff); lastTenTicks.push(trueDiff); if (lastTenTicks.length > 10) { lastTenTicks = lastTenTicks.slice(1); } Vue.set(app, "lastTenTicks", lastTenTicks); ticking = false; }, 50); setInterval(function () { needCanvasUpdate = true; }, 500);