diff --git a/src/components/system/TPS.vue b/src/components/system/TPS.vue index ca96f10..7626b3e 100644 --- a/src/components/system/TPS.vue +++ b/src/components/system/TPS.vue @@ -1,18 +1,18 @@ <template> - <div class="tpsDisplay"> + <div class="tpsDisplay" v-if="tps !== 'NaN'"> TPS: {{ tps }} </div> </template> <script> -import Decimal, { format } from '../../util/bignum'; +import Decimal, { formatWhole } from '../../util/bignum'; +import { player } from '../../store/proxies'; export default { name: 'TPS', computed: { tps() { - const lastTenTicks = this.$store.state.lastTenTicks; - return format(Decimal.div(lastTenTicks.length, lastTenTicks.reduce((acc, curr) => acc + curr, 0))) + return formatWhole(Decimal.div(player.lastTenTicks.length, player.lastTenTicks.reduce((acc, curr) => acc + curr, 0))) } } }; diff --git a/src/data/mod.js b/src/data/mod.js index c23bb03..5fe86a4 100644 --- a/src/data/mod.js +++ b/src/data/mod.js @@ -1,4 +1,4 @@ -import { hasMilestone, hasUpgrade, inChallenge, getBuyableAmount } from '../util/features'; +import { hasUpgrade, upgradeEffect } from '../util/features'; import { layers } from '../store/layers'; import { player } from '../store/proxies'; import Decimal from '../util/bignum'; @@ -44,53 +44,27 @@ const main = { export const initialLayers = [ main, f, c, a, g, h, spook ]; -export function update(delta) { - let gain = new Decimal(3.19) - if (hasMilestone("p",0))gain=gain.plus(0.01) - if (hasMilestone("p",4)){ - if (hasUpgrade("p",12))gain=gain.plus(0.1) - if (hasUpgrade("p",13))gain=gain.plus(0.1) - if (hasUpgrade("p",14))gain=gain.plus(0.1) - if (hasUpgrade("p",21))gain=gain.plus(0.1) - if (hasUpgrade("p",22))gain=gain.plus(0.1) - if (hasUpgrade("p",23))gain=gain.plus(0.1) - if (hasUpgrade("p",31))gain=gain.plus(0.1) - if (hasUpgrade("p",32))gain=gain.plus(0.1) - if (hasUpgrade("p",33))gain=gain.plus(0.1) - } - if (hasUpgrade("p",11))gain=gain.plus(hasUpgrade("p",34)?(new Decimal(1).plus(layers.p.upgrades[34].effect)):1) - if (hasUpgrade("p",12))gain=gain.times(hasUpgrade("p",34)?(new Decimal(1).plus(layers.p.upgrades[34].effect)):1) - if (hasUpgrade("p",13))gain=gain.pow(hasUpgrade("p",34)?(new Decimal(1).plus(layers.p.upgrades[34].effect)):1) - if (hasUpgrade("p",14))gain=gain.tetrate(hasUpgrade("p",34)?(new Decimal(1).plus(layers.p.upgrades[34].effect)):1) - - if (hasUpgrade("p",71)) gain=gain.plus(1.1) - if (hasUpgrade("p",72)) gain=gain.times(1.1) - if (hasUpgrade("p",73)) gain=gain.pow(1.1) - if (hasUpgrade("p",74)) gain=gain.tetrate(1.1) - if (hasMilestone("p",5)&&!inChallenge("p",22)){ - let asdf = (hasUpgrade("p",132)?player.p.gp.plus(1).pow(new Decimal(1).div(2)):hasUpgrade("p",101)?player.p.gp.plus(1).pow(new Decimal(1).div(3)):hasUpgrade("p",93)?player.p.gp.plus(1).pow(0.2):player.p.gp.plus(1).log10()) - gain=gain.plus(asdf) - if (hasUpgrade("p",213))gain=gain.mul(asdf.plus(1)) - } - if (hasUpgrade("p",104)) gain=gain.times(player.p.points.plus(1).pow(0.5)) - if (hasUpgrade("p",142))gain=gain.times(5) - if (player.i.unlocked)gain=gain.times(player.i.points.plus(1).pow(hasUpgrade("p",235)?6.9420:1)) - if (inChallenge("p",11)||inChallenge("p",21))gain=new Decimal(10).pow(gain.log10().pow(0.75)) - if (inChallenge("p",12)||inChallenge("p",21))gain=gain.pow(new Decimal(1).sub(new Decimal(1).div(getBuyableAmount("p",11).plus(1)))) - if (hasUpgrade("p",211))gain=gain.times(getBuyableAmount("p",21).plus(1)) - if (hasMilestone("p",13))gain=gain.times(layers.p.buyables[31].effect) - if (hasMilestone("p",13))gain=gain.pow(layers.p.buyables[42].effect) - gain.times(delta); -} - export function getStartingData() { return { points: new Decimal(10), } } -export function hasWon() { - return false; +export const getters = { + hasWon() { + return false + }, + pointGain() { + if(!hasUpgrade("c", 11)) + return new Decimal(0); + let gain = new Decimal(1) + if (hasUpgrade("c", 12)) gain = gain.times(upgradeEffect("c", 12)) + return gain; + } +}; + +/* eslint-disable-next-line no-unused-vars */ +export function update(delta) { } /* eslint-disable-next-line no-unused-vars */ diff --git a/src/data/modInfo.json b/src/data/modInfo.json index 53d4469..e006906 100644 --- a/src/data/modInfo.json +++ b/src/data/modInfo.json @@ -16,5 +16,6 @@ "logo": null, "initialTabs": [ "main", "c" ], - "maxTickLength": 3600 + "maxTickLength": 3600, + "offlineLimit": 1 } diff --git a/src/main.js b/src/main.js index 7fca680..f93c405 100644 --- a/src/main.js +++ b/src/main.js @@ -3,6 +3,7 @@ import App from './App'; import store from './store'; import { addLayer} from './store/layers'; import { setVue } from './util/vue'; +import { startGameLoop } from './store/game'; import './components/index'; // Setup @@ -21,5 +22,5 @@ requestAnimationFrame(async () => { setVue(vue); vue.$mount('#app'); - // Start game loop + startGameLoop(); }); diff --git a/src/store/game.js b/src/store/game.js new file mode 100644 index 0000000..b05c434 --- /dev/null +++ b/src/store/game.js @@ -0,0 +1,117 @@ +import { update as modUpdate } from '../data/mod'; +import Decimal from '../util/bignum'; +import modInfo from '../data/modInfo.json'; +import store from './index'; +import { layers } from './layers'; +import { player } from './proxies'; + +function updatePopups(/* diff */) { + // TODO +} + +function updateParticles(/* diff */) { + // TODO +} + +function update() { + let now = Date.now(); + let diff = (now - player.time) / 1e3; + player.time = now; + let trueDiff = diff; + + // Always update UI + updatePopups(trueDiff); + updateParticles(trueDiff); + player.lastTenTicks.push(trueDiff); + if (player.lastTenTicks.length > 10) { + player.lastTenTicks = player.lastTenTicks.slice(1); + } + + // Stop here if the game is paused on the win screen + if (store.getters.hasWon && !player.keepGoing) { + return; + } + + diff = new Decimal(diff).max(0); + + // Add offline time if any + 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 = diff.add(offlineDiff); + } + if (!player.offlineProd || player.offTime.remain <= 0) { + player.offTime = undefined; + } + } + + // Cap at max tick length + diff = Decimal.min(diff, modInfo.maxTickLength); + + // Apply dev speed + if (player.devSpeed != undefined) { + diff = diff.times(player.devSpeed); + } + + // Update + if (diff.eq(0)) { + return; + } + player.timePlayed = player.timePlayed.add(diff); + if (player.points != undefined) { + player.points = player.points.add(Decimal.times(store.getters.pointGain, diff)); + } + modUpdate(diff); + // Update each active layer + const activeLayers = Object.keys(layers).filter(layer => !layers[layer].deactivated); + activeLayers.forEach(layer => { + if (player[layer].resetTime != undefined) { + player[layer].resetTime = player[layer].resetTime.add(diff); + } + if (layers[layer].passiveGeneration) { + player[layer].points = + player[layer].points.add(Decimal.times(layers[layer].resetGain, layers[layer].passiveGeneration).times(diff)); + } + layers[layer].update?.(diff); + }); + // Automate each active layer + activeLayers.forEach(layer => { + if (layers[layer].autoReset && layers[layer].canReset) { + layers[layer].reset(); + } + layers[layer].automate?.(); + if (layers[layer].upgrades && layers[layer].autoUpgrade) { + Object.values(layers[layer].upgrades).forEach(upgrade => upgrade.buy()); + } + }); + // Check each active layer for newly unlocked achievements or milestones + activeLayers.forEach(layer => { + if (layers[layer].milestones) { + Object.values(layers[layer].milestones).forEach(milestone => { + if (milestone.unlocked !== false && !milestone.earned && milestone.done) { + player[layer].milestones.push(milestone.id); + milestone.onComplete?.(); + // TODO popup notification + player[layer].lastMilestone = milestone.id; + } + }); + } + if (layers[layer].achievements) { + Object.values(layers[layer].achievements).forEach(achievement => { + if (achievement.unlocked !== false && !achievement.earned && achievement.done) { + player[layer].achievements.push(achievement.id); + achievement.onComplete?.(); + // TODO popup notification + } + }); + } + }); +} + +export function startGameLoop() { + setInterval(update, 50); +} diff --git a/src/store/index.js b/src/store/index.js index cdb944c..6a71852 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,9 +1,11 @@ import Vue from 'vue' import Vuex from 'vuex' import { getInitialStore } from '../util/load'; +import { getters } from '../data/mod'; Vue.use(Vuex); export default new Vuex.Store({ - state: getInitialStore() + state: getInitialStore(), + getters }); diff --git a/src/store/layers.js b/src/store/layers.js index 605c035..9423e5a 100644 --- a/src/store/layers.js +++ b/src/store/layers.js @@ -34,6 +34,9 @@ export function addLayer(layer) { if (layer.onClick != undefined) { layer.onClick.forceCached = false; } + if (layer.update != undefined) { + layer.update.forceCached = false; + } const getters = {}; @@ -55,7 +58,7 @@ export function addLayer(layer) { for (let id in layer.upgrades) { if (isPlainObject(layer.upgrades[id])) { layer.upgrades[id].bought = function() { - return !this.deactivated && player[layer.id].upgrades.some(upgrade => upgrade == id); + return !layer.deactivated && player[layer.id].upgrades.some(upgrade => upgrade == id); } if (layer.upgrades[id].canAfford == undefined) { layer.upgrades[id].canAfford = function() { @@ -130,7 +133,7 @@ export function addLayer(layer) { for (let id in layer.achievements) { if (isPlainObject(layer.achievements[id])) { layer.achievements[id].earned = function() { - return !this.deactivated && player[layer.id].achievements.some(achievement => achievement == id); + return !layer.deactivated && player[layer.id].achievements.some(achievement => achievement == id); } } } @@ -142,13 +145,13 @@ export function addLayer(layer) { for (let id in layer.challenges) { if (isPlainObject(layer.challenges[id])) { layer.challenges[id].completed = function() { - return !this.deactivated && !!player[layer.id].challenges[id]; + return !layer.deactivated && !!player[layer.id].challenges[id]; } layer.challenges[id].completions = function() { return player[layer.id].challenges[id]; } layer.challenges[id].maxed = function() { - return !this.deactivated && Decimal.gte(player[layer.id].challenges[id], this.completionLimit); + return !layer.deactivated && Decimal.gte(player[layer.id].challenges[id], this.completionLimit); } if (layer.challenges[id].mark == undefined) { layer.challenges[id].mark = function() { @@ -156,7 +159,7 @@ export function addLayer(layer) { } } layer.challenges[id].active = function() { - return !this.deactivated && player[layer.id].activeChallenge === id; + return !layer.deactivated && player[layer.id].activeChallenge === id; } if (layer.challenges[id].canComplete == undefined) { layer.challenges[id].canComplete = function() { @@ -227,7 +230,7 @@ export function addLayer(layer) { player[layer.id].buyables[id] = amount; } layer.buyables[id].canBuy = function() { - return !this.deactivated && this.unlocked !== false && this.canAfford !== false && + return !layer.deactivated && this.unlocked !== false && this.canAfford !== false && Decimal.lt(player[layer.id].buyables[id], this.purchaseLimit); } if (layer.buyables[id].purchaseLimit == undefined) { @@ -292,7 +295,7 @@ export function addLayer(layer) { } } layer.milestones[id].earned = function() { - return !this.deactivated && player[layer.id].milestones.some(milestone => milestone == id); + return !layer.deactivated && player[layer.id].milestones.some(milestone => milestone == id); } } } @@ -572,6 +575,12 @@ export const defaultLayerProperties = { return this.canReset && this.resetGain.gte(player[this.layer].points.div(10)); } return false; + }, + reset(force = false) { + console.warn("Not yet implemented!", force); + }, + resetData(keep = []) { + console.warn("Not yet implemented!", keep); } }; const gridProperties = [ 'upgrades', 'achievements', 'challenges', 'buyables', 'clickables' ]; diff --git a/src/store/proxies.js b/src/store/proxies.js index 5436fb9..8e8ee5c 100644 --- a/src/store/proxies.js +++ b/src/store/proxies.js @@ -16,7 +16,7 @@ export const tmp = new Proxy({}, { const playerHandler = { get(target, key) { - if (key == 'isProxy') { + if (key === 'isProxy') { return true; } @@ -35,6 +35,17 @@ const playerHandler = { }, set(target, property, value) { Vue.set(target, property, value); + if (property === 'points') { + if (target.best != undefined) { + target.best = Decimal.max(target.best, value); + } + if (target.total != undefined) { + const diff = Decimal.sub(value, target.points); + if (diff.gt(0)) { + target.total = target.total.add(diff); + } + } + } return true; } }; @@ -80,7 +91,7 @@ function travel(callback, object, objectProxy, getters, prefix) { function getHandler(prefix) { return { get(target, key, receiver) { - if (key == 'isProxy') { + if (key === 'isProxy') { return true; } @@ -119,7 +130,7 @@ function getHandler(prefix) { function getGridHandler(prefix) { return { get(target, key, receiver) { - if (key == 'isProxy') { + if (key === 'isProxy') { return true; } @@ -157,7 +168,7 @@ function getGridHandler(prefix) { function getCellHandler(id) { return { get(target, key, receiver) { - if (key == 'isProxy') { + if (key === 'isProxy') { return true; } diff --git a/src/util/layers.js b/src/util/layers.js index 91b48d1..c91f2a7 100644 --- a/src/util/layers.js +++ b/src/util/layers.js @@ -1,14 +1,13 @@ import Decimal from './bignum'; import { isPlainObject } from './common'; +import { layers } from '../store/layers'; -// TODO make layer.reset(force = false) export function resetLayer(layer, force = false) { - console.warn("Not yet implemented!", layer, force); + layers[layer].reset(force); } -// TODO make layer.resetData(keep = []) export function resetLayerData(layer, keep = []) { - console.warn("Not yet implemented!", layer, keep); + layers[layer].resetData(keep); } export function cache(func) { diff --git a/src/util/load.js b/src/util/load.js index 58ee98d..9faf04d 100644 --- a/src/util/load.js +++ b/src/util/load.js @@ -1,6 +1,7 @@ import modInfo from '../data/modInfo'; import { getStartingData, initialLayers } from '../data/mod'; import { getStartingBuyables, getStartingClickables, getStartingChallenges } from './layers'; +import Decimal from './bignum'; export function getInitialStore() { return { @@ -8,7 +9,7 @@ export function getInitialStore() { time: Date.now(), autosave: true, offlineProd: true, - timePlayed: 0, + timePlayed: new Decimal(0), keepGoing: false, hasNaN: false, lastTenTicks: [],