forked from profectus/Profectus
Vue 3 Migration
This commit is contained in:
parent
8103377ab0
commit
8fe91e88c9
75 changed files with 40190 additions and 28102 deletions
66531
package-lock.json
generated
66531
package-lock.json
generated
File diff suppressed because it is too large
Load diff
100
package.json
100
package.json
|
@ -1,55 +1,49 @@
|
|||
{
|
||||
"name": "the-modding-tree-x",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"portal-vue": "^2.1.7",
|
||||
"simplebar-vue": "^1.6.4",
|
||||
"vue": "^2.6.11",
|
||||
"vue-frag": "^1.1.5",
|
||||
"vue-reactive-provide": "^0.3.0",
|
||||
"vue-select": "^3.11.2",
|
||||
"vue-sortable": "github:Netbel/vue-sortable#master-fix",
|
||||
"vue-textarea-autosize": "^1.1.1",
|
||||
"vue-transition-expand": "^0.1.0",
|
||||
"vuex": "^3.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/vue-select": "^3.11.1",
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-vuex": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"raw-loader": "^4.0.2",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"rules": {}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
"name": "the-modding-tree-x",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ivanv/vue-collapse-transition": "^1.0.2",
|
||||
"core-js": "^3.6.5",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"vue": "^3.1.4",
|
||||
"vue-next-select": "^2.7.0",
|
||||
"vue-sortable": "github:Netbel/vue-sortable#master-fix",
|
||||
"vue-textarea-autosize": "^1.1.1",
|
||||
"vue-transition-expand": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0-beta.1",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^7.0.0-alpha.0",
|
||||
"raw-loader": "^4.0.2"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"rules": {}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
}
|
||||
|
|
24
src/App.vue
24
src/App.vue
|
@ -1,29 +1,23 @@
|
|||
<template>
|
||||
<div id="app" @mousemove="updateMouse" :style="theme" :class="{ useHeader }">
|
||||
<div id="modal-root" :style="theme" />
|
||||
<div class="app" @mousemove="updateMouse" :style="theme" :class="{ useHeader }">
|
||||
<Nav v-if="useHeader" />
|
||||
<Tabs />
|
||||
<TPS v-if="showTPS" />
|
||||
<GameOverScreen />
|
||||
<NaNScreen />
|
||||
<portal-target name="modal-root" multiple />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Nav from './components/system/Nav';
|
||||
import Tabs from './components/system/Tabs';
|
||||
import TPS from './components/system/TPS';
|
||||
import themes from './data/themes';
|
||||
import { mapState } from 'vuex';
|
||||
import { player } from './store/proxies';
|
||||
import player from './game/player';
|
||||
import modInfo from './data/modInfo.json';
|
||||
import { mapState } from './util/vue';
|
||||
import './main.css';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Nav, Tabs, TPS
|
||||
},
|
||||
data() {
|
||||
return { useHeader: modInfo.useHeader };
|
||||
},
|
||||
|
@ -42,10 +36,18 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
#app {
|
||||
.app {
|
||||
background-color: var(--background);
|
||||
color: var(--color);
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#modal-root {
|
||||
position: absolute;
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
.field {
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-height: 2em;
|
||||
margin: 10px 0;
|
||||
min-height: 2em;
|
||||
margin: 10px 0;
|
||||
user-select: none;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.field > * {
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#app .simplebar-scrollbar:before {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.simplebar-horizontal.simplebar-hover,
|
||||
.simplebar-horizontal.simplebar-hover .simplebar-scrollbar {
|
||||
height: 22px;
|
||||
}
|
||||
.simplebar-vertical.simplebar-hover {
|
||||
width: 22px;
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<template>
|
||||
<div v-if="filteredAchievements" class="table">
|
||||
<div v-frag v-if="filteredAchievements.rows && filteredAchievements.cols">
|
||||
<template v-if="filteredAchievements.rows && filteredAchievements.cols">
|
||||
<div v-for="row in filteredAchievements.rows" class="row" :key="row">
|
||||
<div v-for="col in filteredAchievements.cols" :key="col">
|
||||
<achievement v-if="filteredAchievements[row * 10 + col] !== undefined" class="align" :id="row * 10 + col" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-frag v-else>
|
||||
</template>
|
||||
<template v-frag v-else>
|
||||
<achievement v-for="(achievement, id) in filteredAchievements" :key="id" :id="id" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { getFiltered } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { UP, DOWN, LEFT, RIGHT, DEFAULT, coerceComponent } from '../../util/vue';
|
||||
import Decimal from '../../util/bignum';
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
<div v-if="filteredBuyables" class="table">
|
||||
<respec-button v-if="showRespec" style="margin-bottom: 12px;" :confirmRespec="confirmRespec"
|
||||
@set-confirm-respec="setConfirmRespec" @respec="respec" />
|
||||
<div v-frag v-if="filteredBuyables.rows && filteredBuyables.cols">
|
||||
<template v-if="filteredBuyables.rows && filteredBuyables.cols">
|
||||
<div v-for="row in filteredBuyables.rows" class="row" :key="row">
|
||||
<div v-for="col in filteredBuyables.cols" :key="col">
|
||||
<buyable v-if="filteredBuyables[row * 10 + col] !== undefined" class="align buyable-container" :style="{ height }"
|
||||
:id="row * 10 + col" :size="height === 'inherit' ? null : height" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<row v-frag v-else>
|
||||
</template>
|
||||
<row v-else>
|
||||
<buyable v-for="(buyable, id) in filteredBuyables" :key="id" class="align buyable-container"
|
||||
:style="{ height }" :id="id" :size="height === 'inherit' ? null : height" />
|
||||
</row>
|
||||
|
@ -18,8 +18,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { getFiltered } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
@ -33,6 +33,7 @@ export default {
|
|||
default: "inherit"
|
||||
}
|
||||
},
|
||||
emits: [ 'set-confirm-respec' ],
|
||||
computed: {
|
||||
filteredBuyables() {
|
||||
return getFiltered(layers[this.layer || this.tab.layer].buyables, this.buyables);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<template>
|
||||
<div v-if="filteredChallenges" class="table">
|
||||
<div v-frag v-if="filteredChallenges.rows && filteredChallenges.cols">
|
||||
<template v-if="filteredChallenges.rows && filteredChallenges.cols">
|
||||
<div v-for="row in filteredChallenges.rows" class="row" :key="row">
|
||||
<div v-for="col in filteredChallenges.cols" :key="col">
|
||||
<challenge v-if="filteredChallenges[row * 10 + col] !== undefined" :id="row * 10 + col" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-frag v-else>
|
||||
</template>
|
||||
<row v-else>
|
||||
<challenge v-for="(challenge, id) in filteredChallenges" :key="id" :id="id" />
|
||||
</div>
|
||||
</row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { getFiltered } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<template>
|
||||
<div v-if="filteredClickables" class="table">
|
||||
<master-button v-if="showMasterButton" style="margin-bottom: 12px;" @press="press" />
|
||||
<div v-frag v-if="filteredClickables.rows && filteredClickables.cols">
|
||||
<template v-if="filteredClickables.rows && filteredClickables.cols">
|
||||
<div v-for="row in filteredClickables.rows" class="row" :key="row">
|
||||
<div v-for="col in filteredClickables.cols" :key="col">
|
||||
<clickable v-if="filteredClickables[row * 10 + col] !== undefined" class="align clickable-container"
|
||||
:style="{ height }" :id="row * 10 + col" :size="height === 'inherit' ? null : height" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-frag v-else>
|
||||
</template>
|
||||
<row v-else>
|
||||
<clickable v-for="(clickable, id) in filteredClickables" :key="id" class="align clickable-container" :style="{ height }"
|
||||
:id="id" :size="height === 'inherit' ? null : height" />
|
||||
</div>
|
||||
</row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { getFiltered } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
<template>
|
||||
<div v-frag>
|
||||
<component :is="challengeDescription" />
|
||||
<div>Goal: <component :is="goalDescription" /></div>
|
||||
<div>Reward: <component :is="rewardDescription" /></div>
|
||||
<component v-if="rewardDisplay" :is="rewardDisplay" />
|
||||
</div>
|
||||
<component :is="challengeDescription" v-bind="$attrs" />
|
||||
<div>Goal: <component :is="goalDescription" /></div>
|
||||
<div>Reward: <component :is="rewardDescription" /></div>
|
||||
<component v-if="rewardDisplay" :is="rewardDisplay" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
@ -29,7 +27,7 @@ export default {
|
|||
if (this.challenge.goalDescription) {
|
||||
return coerceComponent(this.challenge.goalDescription);
|
||||
}
|
||||
return coerceComponent(`{{ format(${this.challenge.goal}) }} ${this.currencyDisplayName || 'points'}`);
|
||||
return coerceComponent(`{{ format(${this.challenge.goal}) }} ${this.challenge.currencyDisplayName || 'points'}`);
|
||||
},
|
||||
rewardDescription() {
|
||||
return coerceComponent(this.challenge.rewardDescription);
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { format, formatWhole } from '../../util/bignum';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
import { formatWhole } from '../../util/bignum';
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
|
||||
export default {
|
||||
name: 'grid',
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -4,18 +4,18 @@
|
|||
<span class="toggle">▼</span>
|
||||
<component :is="title" />
|
||||
</button>
|
||||
<transition-expand>
|
||||
<div v-if="!collapsed" class="body" :style="{ backgroundColor: this.borderColor }">
|
||||
<collapse-transition>
|
||||
<div v-if="!collapsed" class="body" :style="{ backgroundColor: borderColor }">
|
||||
<component :is="body" :style="bodyStyle" />
|
||||
</div>
|
||||
</transition-expand>
|
||||
</collapse-transition>
|
||||
<branch-node :branches="infobox.branches" :id="id" featureType="infobox" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
import themes from '../../data/themes';
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<span v-if="showPrefix">You have</span>
|
||||
<span v-if="showPrefix">You have </span>
|
||||
<resource :amount="amount" :color="color" />
|
||||
{{ resource }}<!-- remove whitespace -->
|
||||
<span v-if="effectDisplay">, <component :is="effectDisplay" /></span>
|
||||
|
@ -9,8 +9,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../store/layers';
|
||||
import player from '../../game/player';
|
||||
import { layers } from '../../game/layers';
|
||||
import { format, formatWhole } from '../../util/bignum';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
@ -16,6 +16,7 @@ export default {
|
|||
layer: String,
|
||||
display: [ String, Object ]
|
||||
},
|
||||
emits: [ 'press' ],
|
||||
computed: {
|
||||
style() {
|
||||
return [
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { getFiltered } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { resetLayer } from '../../util/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import Decimal, { formatWhole } from '../../util/bignum';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -8,26 +8,28 @@
|
|||
<component :is="respecButtonDisplay" />
|
||||
</button>
|
||||
<Modal :show="confirming" @close="cancel">
|
||||
<div slot="header">
|
||||
<template v-slot:header>
|
||||
<h2>Confirm Respec</h2>
|
||||
</div>
|
||||
<slot name="respec-warning" slot="body">
|
||||
<div>Are you sure you want to respec? This will force you to do a {{ name }} respec as well!</div>
|
||||
</slot>
|
||||
<div slot="footer">
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<slot name="respec-warning">
|
||||
<div>Are you sure you want to respec? This will force you to do a {{ name }} respec as well!</div>
|
||||
</slot>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<div class="modal-footer">
|
||||
<div class="modal-flex-grow"></div>
|
||||
<danger-button class="button modal-button" @click="confirm" skipConfirm>Yes</danger-button>
|
||||
<button class="button modal-button" @click="cancel">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
@ -43,6 +45,7 @@ export default {
|
|||
confirmRespec: Boolean,
|
||||
display: [ String, Object ]
|
||||
},
|
||||
emits: [ 'set-confirm-respec', 'respec' ],
|
||||
computed: {
|
||||
style() {
|
||||
return [
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<template>
|
||||
<div v-if="filteredUpgrades" class="table">
|
||||
<div v-frag v-if="filteredUpgrades.rows && filteredUpgrades.cols">
|
||||
<template v-if="filteredUpgrades.rows && filteredUpgrades.cols">
|
||||
<div v-for="row in filteredUpgrades.rows" class="row" :key="row">
|
||||
<div v-for="col in filteredUpgrades.cols" :key="col">
|
||||
<upgrade v-if="filteredUpgrades[row * 10 + col] !== undefined" class="align" :id="row * 10 + col" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-frag v-else>
|
||||
</template>
|
||||
<row v-else>
|
||||
<upgrade v-for="(upgrade, id) in filteredUpgrades" :key="id" class="align" :id="id" />
|
||||
</div>
|
||||
</row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { getFiltered } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<span class="container">
|
||||
<span class="container" :class="{ confirming }">
|
||||
<span v-if="confirming">Are you sure?</span>
|
||||
<button @click.stop="click" class="button danger" :disabled="disabled">
|
||||
<span v-if="confirming">Yes</span>
|
||||
|
@ -21,6 +21,7 @@ export default {
|
|||
disabled: Boolean,
|
||||
skipConfirm: Boolean
|
||||
},
|
||||
emits: [ 'click', 'confirmingChanged' ],
|
||||
watch: {
|
||||
confirming(newValue) {
|
||||
this.$emit('confirmingChanged', newValue);
|
||||
|
@ -50,6 +51,10 @@ export default {
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.container.confirming button {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.container > * {
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ export default {
|
|||
props: {
|
||||
left: Boolean
|
||||
},
|
||||
emits: [ 'click' ],
|
||||
methods: {
|
||||
click() {
|
||||
this.$emit('click');
|
||||
|
|
|
@ -1,64 +1,62 @@
|
|||
<template>
|
||||
<div class="field">
|
||||
<span class="field-title" v-if="title">{{ title }}</span>
|
||||
<v-select :options="options" :value="value" @input="setSelected" />
|
||||
<vue-select :options="options" :model-value="value" @update:modelValue="setSelected" label-by="label" :value-by="getValue" :placeholder="placeholder" :close-on-select="closeOnSelect" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vSelect from 'vue-select';
|
||||
import 'vue-select/dist/vue-select.css';
|
||||
|
||||
export default {
|
||||
name: 'Select',
|
||||
props: {
|
||||
title: String,
|
||||
options: Array, // https://vue-select.org/guide/options.html#options-prop
|
||||
value: [ String, Object ],
|
||||
default: [ String, Object ]
|
||||
},
|
||||
components: {
|
||||
vSelect
|
||||
default: [ String, Object ],
|
||||
placeholder: String,
|
||||
closeOnSelect: Boolean
|
||||
},
|
||||
emits: [ 'change' ],
|
||||
methods: {
|
||||
setSelected(option) {
|
||||
const value = option?.value || this.default;
|
||||
setSelected(value) {
|
||||
value = value || this.default;
|
||||
this.$emit('change', value);
|
||||
},
|
||||
getValue(item) {
|
||||
return item?.value;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.v-select {
|
||||
.vue-select {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.v-select .vs__dropdown-toggle {
|
||||
.field-buttons .vue-select {
|
||||
width: unset;
|
||||
}
|
||||
|
||||
.vue-select,
|
||||
.vue-dropdown {
|
||||
border-color: rgba(var(--color), .26);
|
||||
margin: -1px 0;
|
||||
}
|
||||
|
||||
.v-select .vs__selected {
|
||||
.vue-dropdown {
|
||||
background: var(--secondary-background);
|
||||
}
|
||||
|
||||
.vue-dropdown-item {
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
.v-select .vs__clear,
|
||||
.v-select .vs__open-indicator {
|
||||
fill: var(--color);
|
||||
opacity: .5;
|
||||
.vue-dropdown-item.highlighted {
|
||||
background-color: var(--background-tooltip);
|
||||
}
|
||||
|
||||
.v-select .vs__dropdown-menu {
|
||||
background: var(--background);
|
||||
border-color: rgba(var(--color), .26);
|
||||
}
|
||||
|
||||
.v-select .vs__dropdown-option {
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
.v-select .vs__open-indicator {
|
||||
cursor: pointer;
|
||||
.vue-dropdown-item.selected,
|
||||
.vue-dropdown-item.highlighted.selected {
|
||||
background-color: var(--bought);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -15,7 +15,8 @@ export default {
|
|||
value: Number,
|
||||
min: Number,
|
||||
max: Number
|
||||
}
|
||||
},
|
||||
emits: [ 'change' ]
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<span class="field-title" v-if="title">{{ title }}</span>
|
||||
<textarea-autosize v-if="textarea" :placeholder="placeholder" :value="value" :maxHeight="maxHeight"
|
||||
@input="value => $emit('change', value)" ref="field" />
|
||||
<input v-else type="text" :value="value" @input="e => $emit('input', e.target.value)" :placeholder="placeholder" ref="field"
|
||||
<input v-else type="text" :value="value" @input="e => $emit('change', e.target.value)" :placeholder="placeholder" ref="field"
|
||||
:class="{ fullWidth: !title }" />
|
||||
</div>
|
||||
</form>
|
||||
|
@ -20,6 +20,7 @@ export default {
|
|||
placeholder: String,
|
||||
maxHeight: Number
|
||||
},
|
||||
emits: [ 'change', 'submit', 'input' ],
|
||||
mounted() {
|
||||
this.$refs.field.focus();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ export default {
|
|||
title: String,
|
||||
value: Boolean
|
||||
},
|
||||
emits: [ 'change' ],
|
||||
methods: {
|
||||
handleInput(e) {
|
||||
this.$emit('change', e.target.checked);
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
// Import and register all components,
|
||||
// which will allow us to use them in any template strings anywhere in the project
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
/* from files */
|
||||
const componentsContext = require.context('./');
|
||||
componentsContext.keys().forEach(path => {
|
||||
const component = componentsContext(path).default;
|
||||
if (component) {
|
||||
Vue.component(component.name, component);
|
||||
}
|
||||
});
|
||||
|
||||
/* from packages */
|
||||
import frag from 'vue-frag';
|
||||
Vue.directive('frag', frag);
|
||||
import TransitionExpand from 'vue-transition-expand';
|
||||
import 'vue-transition-expand/dist/vue-transition-expand.css';
|
||||
Vue.use(TransitionExpand);
|
||||
//import TransitionExpand from 'vue-transition-expand';
|
||||
//import 'vue-transition-expand/dist/vue-transition-expand.css';
|
||||
import CollapseTransition from '@ivanv/vue-collapse-transition/src/CollapseTransition.vue';
|
||||
import VueTextareaAutosize from 'vue-textarea-autosize';
|
||||
Vue.use(VueTextareaAutosize);
|
||||
import PortalVue from 'portal-vue';
|
||||
Vue.use(PortalVue);
|
||||
import Sortable from 'vue-sortable';
|
||||
Vue.use(Sortable);
|
||||
import simplebar from 'simplebar-vue';
|
||||
import 'simplebar/dist/simplebar.min.css';
|
||||
Vue.component('simplebar', simplebar);
|
||||
import VueNextSelect from 'vue-next-select';
|
||||
import 'vue-next-select/dist/index.css';
|
||||
|
||||
export function registerComponents(vue) {
|
||||
/* from files */
|
||||
const componentsContext = require.context('./');
|
||||
componentsContext.keys().forEach(path => {
|
||||
const component = componentsContext(path).default;
|
||||
if (component && !(component.name in vue._context.components)) {
|
||||
vue.component(component.name, component);
|
||||
}
|
||||
});
|
||||
|
||||
/* from packages */
|
||||
//vue.use(TransitionExpand);
|
||||
vue.component('collapse-transition', CollapseTransition);
|
||||
vue.use(VueTextareaAutosize);
|
||||
vue.use(Sortable);
|
||||
vue.component('vue-select', VueNextSelect);
|
||||
}
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
<template>
|
||||
<div v-frag>
|
||||
<infobox v-if="infobox != undefined" :id="infobox" />
|
||||
<main-display />
|
||||
<sticky v-if="showPrestigeButton"><prestige-button /></sticky>
|
||||
<resource-display />
|
||||
<milestones />
|
||||
<component v-if="midsection" :is="midsection" />
|
||||
<clickables />
|
||||
<buyables />
|
||||
<upgrades />
|
||||
<challenges />
|
||||
<achievements />
|
||||
</div>
|
||||
<infobox v-if="infobox != undefined" :id="infobox" />
|
||||
<main-display />
|
||||
<sticky v-if="showPrestigeButton"><prestige-button /></sticky>
|
||||
<resource-display />
|
||||
<milestones />
|
||||
<component v-if="midsection" :is="midsection" />
|
||||
<clickables />
|
||||
<buyables />
|
||||
<upgrades />
|
||||
<challenges />
|
||||
<achievements />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<template>
|
||||
<Modal :show="show">
|
||||
<div slot="header" class="game-over-modal-header">
|
||||
<img class="game-over-modal-logo" v-if="logo" :src="logo" :alt="modInfo" />
|
||||
<div class="game-over-modal-title">
|
||||
<h2>Congratulations!</h2>
|
||||
<h4>You've beaten {{ title }} v{{ versionNumber }}: {{ versionTitle }}</h4>
|
||||
<template v-slot:header>
|
||||
<div class="game-over-modal-header">
|
||||
<img class="game-over-modal-logo" v-if="logo" :src="logo" :alt="modInfo" />
|
||||
<div class="game-over-modal-title">
|
||||
<h2>Congratulations!</h2>
|
||||
<h4>You've beaten {{ title }} v{{ versionNumber }}: {{ versionTitle }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:body="{ shown }">
|
||||
<div v-if="shown">
|
||||
<div>It took you {{ timePlayed }} to beat the game.</div>
|
||||
|
@ -21,17 +23,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div slot="footer" class="game-over-footer">
|
||||
<button @click="keepGoing" class="button">Keep Going</button>
|
||||
<button @click="playAgain" class="button danger">Play Again</button>
|
||||
</div>
|
||||
<template v-slot:footer>
|
||||
<div class="game-over-footer">
|
||||
<button @click="keepGoing" class="button">Keep Going</button>
|
||||
<button @click="playAgain" class="button danger">Play Again</button>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modInfo from '../../data/modInfo.json';
|
||||
import { hasWon } from '../../data/mod';
|
||||
import { formatTime } from '../../util/bignum';
|
||||
import { player } from '../../store/proxies';
|
||||
import player from '../../game/player';
|
||||
|
||||
export default {
|
||||
name: 'GameOverScreen',
|
||||
|
@ -44,7 +49,7 @@ export default {
|
|||
return formatTime(player.timePlayed);
|
||||
},
|
||||
show() {
|
||||
return this.$store.getters.hasWon && !player.keepGoing;
|
||||
return hasWon.value && !player.keepGoing;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<template>
|
||||
<Modal :show="show" @close="$emit('closeDialog', 'Info')">
|
||||
<div slot="header" class="info-modal-header">
|
||||
<img class="info-modal-logo" v-if="logo" :src="logo" :alt="title" />
|
||||
<div class="info-modal-title">
|
||||
<h2>{{ title }}</h2>
|
||||
<h4>v{{ versionNumber}}: {{ versionTitle }}</h4>
|
||||
<template v-slot:header>
|
||||
<div class="info-modal-header">
|
||||
<img class="info-modal-logo" v-if="logo" :src="logo" :alt="title" />
|
||||
<div class="info-modal-title">
|
||||
<h2>{{ title }}</h2>
|
||||
<h4>v{{ versionNumber}}: {{ versionTitle }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:body="{ shown }">
|
||||
<div v-if="shown">
|
||||
<div v-if="author">
|
||||
|
@ -59,7 +61,8 @@
|
|||
<script>
|
||||
import modInfo from '../../data/modInfo.json';
|
||||
import { formatTime } from '../../util/bignum';
|
||||
import { hotkeys } from '../../store/layers';
|
||||
import { hotkeys } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
|
||||
export default {
|
||||
name: 'Info',
|
||||
|
@ -70,9 +73,10 @@ export default {
|
|||
props: {
|
||||
show: Boolean
|
||||
},
|
||||
emits: [ 'closeDialog', 'openDialog' ],
|
||||
computed: {
|
||||
timePlayed() {
|
||||
return formatTime(this.$store.state.timePlayed);
|
||||
return formatTime(player.timePlayed);
|
||||
},
|
||||
hotkeys() {
|
||||
return Object.keys(hotkeys).reduce((acc, curr) => {
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
<template>
|
||||
<div v-frag>
|
||||
<slot />
|
||||
</div>
|
||||
<slot />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ReactiveProvideMixin } from 'vue-reactive-provide';
|
||||
|
||||
export default {
|
||||
name: 'LayerProvider',
|
||||
mixins: [
|
||||
ReactiveProvideMixin({
|
||||
name: 'tab',
|
||||
props: true
|
||||
})
|
||||
],
|
||||
provide() {
|
||||
return {
|
||||
'tab': {
|
||||
layer: this.layer,
|
||||
index: this.index
|
||||
}
|
||||
};
|
||||
},
|
||||
props: {
|
||||
layer: String,
|
||||
index: Number
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
import { isPlainObject } from '../../util/common';
|
||||
import modInfo from '../../data/modInfo.json';
|
||||
|
@ -81,7 +81,7 @@ export default {
|
|||
return null;
|
||||
},
|
||||
activeSubtab() {
|
||||
return layers[this.layer].activeSubtab.id;
|
||||
return layers[this.layer].activeSubtab?.id;
|
||||
},
|
||||
firstTab() {
|
||||
if (this.forceFirstTab != undefined) {
|
||||
|
@ -101,13 +101,13 @@ export default {
|
|||
tab.style.flexGrow = 0;
|
||||
tab.style.flexShrink = 0;
|
||||
tab.style.width = "60px";
|
||||
tab.style.minWidth = null;
|
||||
tab.style.minWidth = tab.style.flexBasis = null;
|
||||
tab.style.margin = 0;
|
||||
} else {
|
||||
tab.style.flexGrow = null;
|
||||
tab.style.flexShrink = null;
|
||||
tab.style.width = null;
|
||||
tab.style.minWidth = `${layers[this.layer].minWidth}px`;
|
||||
tab.style.minWidth = tab.style.flexBasis = `${layers[this.layer].minWidth}px`;
|
||||
tab.style.margin = null;
|
||||
}
|
||||
}
|
||||
|
@ -123,13 +123,13 @@ export default {
|
|||
tab.style.flexGrow = 0;
|
||||
tab.style.flexShrink = 0;
|
||||
tab.style.width = "60px";
|
||||
tab.style.minWidth = null;
|
||||
tab.style.minWidth = tab.style.flexBasis = null;
|
||||
tab.style.margin = 0;
|
||||
} else {
|
||||
tab.style.flexGrow = null;
|
||||
tab.style.flexShrink = null;
|
||||
tab.style.width = null;
|
||||
tab.style.minWidth = `${layers[this.layer].minWidth}px`;
|
||||
tab.style.minWidth = tab.style.flexBasis = `${layers[this.layer].minWidth}px`;
|
||||
tab.style.margin = null;
|
||||
}
|
||||
} else {
|
||||
|
@ -180,7 +180,7 @@ export default {
|
|||
bottom: 0;
|
||||
display: flex;
|
||||
padding: 0;
|
||||
padding-top: 50px;
|
||||
padding-top: 55px;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
font-size: 40px;
|
||||
|
@ -299,3 +299,9 @@ export default {
|
|||
text-shadow: 0 0 7px var(--color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.subtabs-container + * {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
import themes from '../../data/themes';
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<portal to="modal-root">
|
||||
<teleport to="#modal-root">
|
||||
<transition name="modal" @before-enter="setAnimating(true)" @after-leave="setAnimating(false)">
|
||||
<div class="modal-mask" v-show="show" v-on:pointerdown.self="$emit('close')">
|
||||
<div class="modal-mask" v-show="show" v-on:pointerdown.self="$emit('close')" v-bind="$attrs">
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
|
@ -9,13 +9,13 @@
|
|||
default header
|
||||
</slot>
|
||||
</div>
|
||||
<simplebar class="modal-body">
|
||||
<div class="modal-body">
|
||||
<branches>
|
||||
<slot name="body" :shown="isVisible">
|
||||
default body
|
||||
</slot>
|
||||
</branches>
|
||||
</simplebar>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<slot name="footer" :shown="isVisible">
|
||||
<div class="modal-default-footer">
|
||||
|
@ -30,7 +30,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</portal>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -44,6 +44,7 @@ export default {
|
|||
props: {
|
||||
show: Boolean
|
||||
},
|
||||
emits: [ 'close' ],
|
||||
computed: {
|
||||
isVisible() {
|
||||
return this.show || this.isAnimating;
|
||||
|
@ -96,7 +97,6 @@ export default {
|
|||
}
|
||||
|
||||
.modal-body {
|
||||
display: flex;
|
||||
margin: 20px 0;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
|
@ -115,7 +115,7 @@ export default {
|
|||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.modal-enter {
|
||||
.modal-enter-from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ export default {
|
|||
opacity: 0;
|
||||
}
|
||||
|
||||
.modal-enter .modal-container,
|
||||
.modal-enter-from .modal-container,
|
||||
.modal-leave-active .modal-container {
|
||||
-webkit-transform: scale(1.1);
|
||||
transform: scale(1.1);
|
||||
|
|
|
@ -1,38 +1,41 @@
|
|||
<template>
|
||||
<div v-frag>
|
||||
<Modal :show="show">
|
||||
<div slot="header" class="nan-modal-header">
|
||||
<Modal :show="hasNaN" v-bind="$attrs">
|
||||
<template v-slot:header>
|
||||
<div class="nan-modal-header">
|
||||
<h2>NaN value detected!</h2>
|
||||
</div>
|
||||
<div slot="body">
|
||||
<div>Attempted to assign NaN value to "{{ property }}" (previously {{ format(previous) }}). Auto-saving has been {{ autosave ? 'enabled' : 'disabled' }}. Check the console for more details, and consider sharing it with the developers on discord.</div>
|
||||
<br>
|
||||
<div>
|
||||
<a :href="discordLink" class="nan-modal-discord-link">
|
||||
<img src="images/discord.png" class="nan-modal-discord" />
|
||||
{{ discordName }}
|
||||
</a>
|
||||
</div>
|
||||
<br>
|
||||
<Toggle title="Autosave" :value="autosave" @change="setAutosave" />
|
||||
<Toggle title="Pause game" :value="paused" @change="togglePaused" />
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<div>Attempted to assign "{{ path }}" to NaN (previously {{ format(previous) }}). Auto-saving has been {{ autosave ? 'enabled' : 'disabled' }}. Check the console for more details, and consider sharing it with the developers on discord.</div>
|
||||
<br>
|
||||
<div>
|
||||
<a :href="discordLink" class="nan-modal-discord-link">
|
||||
<img src="images/discord.png" class="nan-modal-discord" />
|
||||
{{ discordName }}
|
||||
</a>
|
||||
</div>
|
||||
<div slot="footer" class="nan-footer">
|
||||
<br>
|
||||
<Toggle title="Autosave" :value="autosave" @change="setAutosave" />
|
||||
<Toggle title="Pause game" :value="paused" @change="togglePaused" />
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<div class="nan-footer">
|
||||
<button @click="toggleSavesManager" class="button">Open Saves Manager</button>
|
||||
<button @click="setZero" class="button">Set to 0</button>
|
||||
<button @click="setOne" class="button">Set to 1</button>
|
||||
<button @click="setPrev" class="button" v-if="previous && previous.neq(0) && previous.neq(1)">Set to previous</button>
|
||||
<button @click="ignore" class="button danger">Ignore</button>
|
||||
</div>
|
||||
</Modal>
|
||||
<SavesManager :show="showSaves" @closeDialog="toggleSavesManager" />
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
<SavesManager :show="showSaves" @closeDialog="toggleSavesManager" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modInfo from '../../data/modInfo.json';
|
||||
import Decimal, { format } from '../../util/bignum';
|
||||
import { player } from '../../store/proxies';
|
||||
import { mapState } from '../../util/vue';
|
||||
import player from '../../game/player';
|
||||
|
||||
export default {
|
||||
name: 'NaNScreen',
|
||||
|
@ -41,36 +44,34 @@ export default {
|
|||
return { discordName, discordLink, format, showSaves: false };
|
||||
},
|
||||
computed: {
|
||||
show() {
|
||||
return player.hasNaN;
|
||||
},
|
||||
property() {
|
||||
return player.NaNProperty;
|
||||
},
|
||||
autosave() {
|
||||
return player.autosave;
|
||||
...mapState([ 'hasNaN', 'autosave' ]),
|
||||
path() {
|
||||
return player.NaNPath.join('.');
|
||||
},
|
||||
previous() {
|
||||
return player.NaNPrevious;
|
||||
return player.NaNReceiver?.[this.property];
|
||||
},
|
||||
paused() {
|
||||
return player.devSpeed === 0;
|
||||
},
|
||||
property() {
|
||||
return player.NaNPath.slice(-1)[0];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setZero() {
|
||||
player.NaNReceiver[player.NaNProperty] = new Decimal(0);
|
||||
player.NaNReceiver[this.property] = new Decimal(0);
|
||||
player.hasNaN = false;
|
||||
},
|
||||
setOne() {
|
||||
player.NaNReceiver[player.NaNProperty] = new Decimal(1);
|
||||
player.NaNReceiver[this.property] = new Decimal(1);
|
||||
player.hasNaN = false;
|
||||
},
|
||||
setPrev() {
|
||||
player.NaNReceiver[player.NaNProperty] = player.NaNPrevious;
|
||||
player.hasNaN = false;
|
||||
},
|
||||
ignore() {
|
||||
player.NaNReceiver[this.property] = new Decimal(NaN);
|
||||
player.hasNaN = false;
|
||||
},
|
||||
setAutosave(autosave) {
|
||||
|
|
|
@ -1,66 +1,64 @@
|
|||
<template>
|
||||
<div v-frag>
|
||||
<div class="nav" v-if="useHeader">
|
||||
<img v-if="banner" :src="banner" height="100%" :alt="title" />
|
||||
<div v-else class="title">{{ title }}</div>
|
||||
<div @click="openDialog('Changelog')" class="version-container">
|
||||
<tooltip display="Changelog" bottom class="version"><span>v{{ version }}</span></tooltip>
|
||||
</div>
|
||||
<div style="flex-grow: 1; cursor: unset;"></div>
|
||||
<div class="discord">
|
||||
<img src="images/discord.png" @click="window.open(discordLink, 'mywindow')" />
|
||||
<ul class="discord-links">
|
||||
<li v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
||||
<a :href="discordLink" target="_blank">{{ discordName }}</a>
|
||||
</li>
|
||||
<li><a href="https://discord.gg/WzejVAx" target="_blank">The Paper Pilot Community</a></li>
|
||||
<li><a href="https://discord.gg/F3xveHV" target="_blank">The Modding Tree</a></li>
|
||||
<li><a href="http://discord.gg/wwQfgPa" target="_blank">Jacorb's Games</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div @click="openDialog('Info')">
|
||||
<tooltip display="<span>Info</span>" bottom class="info"><span>i</span></tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Saves')">
|
||||
<tooltip display="Saves" bottom class="saves" xoffset="-20px">
|
||||
<span class="material-icons">library_books</span>
|
||||
</tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Options')">
|
||||
<tooltip display="<span>Options</span>" bottom class="options" xoffset="-70px">
|
||||
<img src="images/options_wheel.png" />
|
||||
</tooltip>
|
||||
</div>
|
||||
<div class="nav" v-if="useHeader" v-bind="$attrs">
|
||||
<img v-if="banner" :src="banner" height="100%" :alt="title" />
|
||||
<div v-else class="title">{{ title }}</div>
|
||||
<div @click="openDialog('Changelog')" class="version-container">
|
||||
<tooltip display="Changelog" bottom class="version"><span>v{{ version }}</span></tooltip>
|
||||
</div>
|
||||
<div v-else class="overlay-nav">
|
||||
<div @click="openDialog('Changelog')" class="version-container">
|
||||
<tooltip display="Changelog" right xoffset="25%" class="version"><span>v{{ version }}</span></tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Saves')">
|
||||
<tooltip display="Saves" right class="saves"><span class="material-icons">library_books</span></tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Options')">
|
||||
<tooltip display="<span>Options</span>" right class="options"><img src="images/options_wheel.png" /></tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Info')">
|
||||
<tooltip display="<span>Info</span>" right class="info"><span>i</span></tooltip>
|
||||
</div>
|
||||
<div class="discord">
|
||||
<img src="images/discord.png" @click="openDiscord" />
|
||||
<ul class="discord-links">
|
||||
<li v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
||||
<a :href="discordLink" target="_blank">{{ discordName }}</a>
|
||||
</li>
|
||||
<li><a href="https://discord.gg/WzejVAx" target="_blank">The Paper Pilot Community</a></li>
|
||||
<li><a href="https://discord.gg/F3xveHV" target="_blank">The Modding Tree</a></li>
|
||||
<li><a href="http://discord.gg/wwQfgPa" target="_blank">Jacorb's Games</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="flex-grow: 1; cursor: unset;"></div>
|
||||
<div class="discord">
|
||||
<img src="images/discord.png" @click="window.open(discordLink, 'mywindow')" />
|
||||
<ul class="discord-links">
|
||||
<li v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
||||
<a :href="discordLink" target="_blank">{{ discordName }}</a>
|
||||
</li>
|
||||
<li><a href="https://discord.gg/WzejVAx" target="_blank">The Paper Pilot Community</a></li>
|
||||
<li><a href="https://discord.gg/F3xveHV" target="_blank">The Modding Tree</a></li>
|
||||
<li><a href="http://discord.gg/wwQfgPa" target="_blank">Jacorb's Games</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div @click="openDialog('Info')">
|
||||
<tooltip display="<span>Info</span>" bottom class="info"><span>i</span></tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Saves')">
|
||||
<tooltip display="Saves" bottom class="saves" xoffset="-20px">
|
||||
<span class="material-icons">library_books</span>
|
||||
</tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Options')">
|
||||
<tooltip display="<span>Options</span>" bottom class="options" xoffset="-70px">
|
||||
<img src="images/options_wheel.png" />
|
||||
</tooltip>
|
||||
</div>
|
||||
<Info :show="showInfo" @openDialog="openDialog" @closeDialog="closeDialog" />
|
||||
<SavesManager :show="showSaves" @closeDialog="closeDialog" />
|
||||
<Options :show="showOptions" @closeDialog="closeDialog" />
|
||||
</div>
|
||||
<div v-else class="overlay-nav" v-bind="$attrs">
|
||||
<div @click="openDialog('Changelog')" class="version-container">
|
||||
<tooltip display="Changelog" right xoffset="25%" class="version"><span>v{{ version }}</span></tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Saves')">
|
||||
<tooltip display="Saves" right class="saves"><span class="material-icons">library_books</span></tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Options')">
|
||||
<tooltip display="<span>Options</span>" right class="options"><img src="images/options_wheel.png" /></tooltip>
|
||||
</div>
|
||||
<div @click="openDialog('Info')">
|
||||
<tooltip display="<span>Info</span>" right class="info"><span>i</span></tooltip>
|
||||
</div>
|
||||
<div class="discord">
|
||||
<img src="images/discord.png" @click="openDiscord" />
|
||||
<ul class="discord-links">
|
||||
<li v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
||||
<a :href="discordLink" target="_blank">{{ discordName }}</a>
|
||||
</li>
|
||||
<li><a href="https://discord.gg/WzejVAx" target="_blank">The Paper Pilot Community</a></li>
|
||||
<li><a href="https://discord.gg/F3xveHV" target="_blank">The Modding Tree</a></li>
|
||||
<li><a href="http://discord.gg/wwQfgPa" target="_blank">Jacorb's Games</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<Info :show="showInfo" @openDialog="openDialog" @closeDialog="closeDialog" />
|
||||
<SavesManager :show="showSaves" @closeDialog="closeDialog" />
|
||||
<Options :show="showOptions" @closeDialog="closeDialog" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -173,7 +171,7 @@ export default {
|
|||
width: 200px;
|
||||
transition: right .25s ease;
|
||||
background: var(--secondary-background);
|
||||
z-index: 1;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.overlay-nav .discord-links {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<template>
|
||||
<Modal :show="show" @close="$emit('closeDialog', 'Options')">
|
||||
<div slot="header" class="header">
|
||||
<h2>Options</h2>
|
||||
</div>
|
||||
<div slot="body">
|
||||
<template v-slot:header>
|
||||
<div class="header">
|
||||
<h2>Options</h2>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<Select title="Theme" :options="themes" :value="theme" @change="setTheme" default="classic" />
|
||||
<Select title="Show Milestones" :options="msDisplayOptions" :value="msDisplay" @change="setMSDisplay" default="all" />
|
||||
<Toggle title="Offline Production" :value="offlineProd" @change="toggleOption('offlineProd')" />
|
||||
|
@ -11,21 +13,22 @@
|
|||
<Toggle title="Pause game" :value="paused" @change="togglePaused" />
|
||||
<Toggle title="Show TPS" :value="showTPS" @change="toggleOption('showTPS')" />
|
||||
<Toggle title="Hide Maxed Challenges" :value="hideChallenges" @change="toggleOption('hideChallenges')" />
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import themes from '../../data/themes';
|
||||
import { camelToTitle } from '../../util/common';
|
||||
import { mapState } from 'vuex';
|
||||
import { player } from '../../store/proxies';
|
||||
import { mapState } from '../../util/vue';
|
||||
import player from '../../game/player';
|
||||
|
||||
export default {
|
||||
name: 'Options',
|
||||
props: {
|
||||
show: Boolean
|
||||
},
|
||||
emits: [ 'closeDialog' ],
|
||||
data() {
|
||||
return {
|
||||
themes: Object.keys(themes).map(theme => ({ label: camelToTitle(theme), value: theme })),
|
||||
|
@ -34,13 +37,7 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState([ "autosave", "offlineProd", "showTPS", "hideChallenges" ]),
|
||||
theme() {
|
||||
return { label: camelToTitle(player.theme), value: player.theme };
|
||||
},
|
||||
msDisplay() {
|
||||
return { label: camelToTitle(player.msDisplay), value: player.msDisplay };
|
||||
},
|
||||
...mapState([ "autosave", "offlineProd", "showTPS", "hideChallenges", "theme", "msDisplay" ]),
|
||||
paused() {
|
||||
return player.devSpeed === 0;
|
||||
}
|
||||
|
|
|
@ -40,13 +40,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { player } from '../../store/proxies';
|
||||
import player from '../../game/player';
|
||||
|
||||
export default {
|
||||
name: 'save',
|
||||
props: {
|
||||
save: Object
|
||||
},
|
||||
emits: [ 'export', 'open', 'duplicate', 'delete', 'editSave' ],
|
||||
data() {
|
||||
return {
|
||||
dateFormat: new Intl.DateTimeFormat('en-US', {
|
||||
|
@ -161,8 +162,7 @@ export default {
|
|||
.save .button.danger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
padding-left: 6px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.save .field {
|
||||
|
|
|
@ -1,37 +1,38 @@
|
|||
<template>
|
||||
<Modal :show="show" @close="$emit('closeDialog', 'Saves')">
|
||||
<div slot="header">
|
||||
<template v-slot:header>
|
||||
<h2>Saves Manager</h2>
|
||||
</div>
|
||||
<div slot="body" v-sortable="{ update, handle: '.handle' }">
|
||||
</template>
|
||||
<template v-slot:body v-sortable="{ update, handle: '.handle' }">
|
||||
<save v-for="(save, index) in saves" :key="index" :save="save" @open="openSave(save.id)" @export="exportSave(save.id)"
|
||||
@editSave="name => editSave(save.id, name)" @duplicate="duplicateSave(save.id)" @delete="deleteSave(save.id)" />
|
||||
</div>
|
||||
<div slot="footer" class="modal-footer">
|
||||
<TextField :value="saveToImport" @submit="importSave" @input="importSave"
|
||||
title="Import Save" placeholder="Paste your save here!" :class="{ importingFailed }" />
|
||||
<div class="field">
|
||||
<span class="field-title">Create Save</span>
|
||||
<div class="field-buttons">
|
||||
<button class="button" @click="newSave">New Game</button>
|
||||
<Select v-if="Object.keys(bank).length > 0" :value="{ label: 'Select preset' }" :options="bank"
|
||||
@change="newFromPreset" />
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<div class="modal-footer">
|
||||
<TextField :value="saveToImport" @submit="importSave" @input="importSave"
|
||||
title="Import Save" placeholder="Paste your save here!" :class="{ importingFailed }" />
|
||||
<div class="field">
|
||||
<span class="field-title">Create Save</span>
|
||||
<div class="field-buttons">
|
||||
<button class="button" @click="newSave">New Game</button>
|
||||
<Select v-if="Object.keys(bank).length > 0" :options="bank" closeOnSelect
|
||||
@change="newFromPreset" placeholder="Select preset" class="presets" :value="[]" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div style="flex-grow: 1"></div>
|
||||
<button class="button modal-default-button" @click="$emit('closeDialog', 'Saves')">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div style="flex-grow: 1"></div>
|
||||
<button class="button modal-default-button" @click="$emit('closeDialog', 'Saves')">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import { newSave, getUniqueID, loadSave, save } from '../../util/save';
|
||||
import { player } from '../../store/proxies';
|
||||
import player from '../../game/player';
|
||||
import modInfo from '../../data/modInfo.json';
|
||||
|
||||
export default {
|
||||
|
@ -39,6 +40,7 @@ export default {
|
|||
props: {
|
||||
show: Boolean
|
||||
},
|
||||
emits: [ 'closeDialog' ],
|
||||
data() {
|
||||
let bankContext = require.context('raw-loader!../../../saves', true, /\.txt$/);
|
||||
let bank = bankContext.keys().reduce((acc, curr) => {
|
||||
|
@ -109,14 +111,14 @@ export default {
|
|||
const modData = JSON.parse(decodeURIComponent(escape(atob(localStorage.getItem(modInfo.id)))));
|
||||
modData.saves.push(playerData.id);
|
||||
localStorage.setItem(modInfo.id, btoa(unescape(encodeURIComponent(JSON.stringify(modData)))));
|
||||
Vue.set(this.saves, playerData.id, playerData);
|
||||
this.saves[playerData.id] = playerData;
|
||||
},
|
||||
deleteSave(id) {
|
||||
const modData = JSON.parse(decodeURIComponent(escape(atob(localStorage.getItem(modInfo.id)))));
|
||||
modData.saves = modData.saves.filter(save => save !== id);
|
||||
localStorage.removeItem(id);
|
||||
localStorage.setItem(modInfo.id, btoa(unescape(encodeURIComponent(JSON.stringify(modData)))));
|
||||
Vue.delete(this.saves, id);
|
||||
delete this.saves[id];
|
||||
},
|
||||
openSave(id) {
|
||||
this.saves[player.id].time = player.time;
|
||||
|
@ -127,7 +129,7 @@ export default {
|
|||
},
|
||||
async newSave() {
|
||||
const playerData = await newSave();
|
||||
Vue.set(this.saves, playerData.id, playerData);
|
||||
this.saves[playerData.id] = playerData;
|
||||
},
|
||||
newFromPreset(preset) {
|
||||
const playerData = JSON.parse(decodeURIComponent(escape(atob(preset))));
|
||||
|
@ -137,7 +139,7 @@ export default {
|
|||
const modData = JSON.parse(decodeURIComponent(escape(atob(localStorage.getItem(modInfo.id)))));
|
||||
modData.saves.push(playerData.id);
|
||||
localStorage.setItem(modInfo.id, btoa(unescape(encodeURIComponent(JSON.stringify(modData)))));
|
||||
Vue.set(this.saves, playerData.id, playerData);
|
||||
this.saves[playerData.id] = playerData;
|
||||
},
|
||||
editSave(id, newName) {
|
||||
this.saves[id].name = newName;
|
||||
|
@ -157,7 +159,7 @@ export default {
|
|||
const id = getUniqueID();
|
||||
playerData.id = id;
|
||||
localStorage.setItem(id, btoa(unescape(encodeURIComponent(JSON.stringify(playerData)))));
|
||||
Vue.set(this.saves, id, playerData);
|
||||
this.saves[id] = playerData;
|
||||
this.saveToImport = "";
|
||||
this.importingFailed = false;
|
||||
|
||||
|
@ -217,4 +219,12 @@ export default {
|
|||
.field-buttons .v-select {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.presets .vue-dropdown {
|
||||
|
||||
}
|
||||
|
||||
.presets .vue-select[aria-expanded='true'] vue-dropdown {
|
||||
visibility: hidden;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<script>
|
||||
import Decimal, { formatWhole } from '../../util/bignum';
|
||||
import { player } from '../../store/proxies';
|
||||
import player from '../../game/player';
|
||||
|
||||
export default {
|
||||
name: 'TPS',
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import themes from '../../data/themes';
|
||||
|
||||
export default {
|
||||
|
@ -18,6 +18,7 @@ export default {
|
|||
options: Object,
|
||||
activeTab: Boolean
|
||||
},
|
||||
emits: [ 'selectTab' ],
|
||||
inject: [ 'tab' ],
|
||||
computed: {
|
||||
floating() {
|
||||
|
|
|
@ -1,26 +1,24 @@
|
|||
<template>
|
||||
<simplebar class="tabs-container">
|
||||
<div class="tabs-container">
|
||||
<div v-for="(tab, index) in tabs" :key="index" class="tab" :ref="`tab-${index}`">
|
||||
<Nav v-if="index === 0 && !useHeader" />
|
||||
<simplebar>
|
||||
<div class="inner-tab">
|
||||
<LayerProvider :layer="tab" :index="index" v-if="tab in components && components[tab]">
|
||||
<component :is="components[tab]" />
|
||||
</LayerProvider>
|
||||
<layer-tab :layer="tab" :index="index" v-else-if="tab in components" :minimizable="true"
|
||||
:tab="() => $refs[`tab-${index}`] && $refs[`tab-${index}`][0]" />
|
||||
<component :is="tab" :index="index" v-else />
|
||||
</div>
|
||||
</simplebar>
|
||||
<div class="inner-tab">
|
||||
<LayerProvider :layer="tab" :index="index" v-if="tab in components && components[tab]">
|
||||
<component :is="components[tab]" />
|
||||
</LayerProvider>
|
||||
<layer-tab :layer="tab" :index="index" v-else-if="tab in components" :minimizable="true"
|
||||
:tab="() => $refs[`tab-${index}`]" />
|
||||
<component :is="tab" :index="index" v-else />
|
||||
</div>
|
||||
<div class="separator" v-if="index !== tabs.length - 1"></div>
|
||||
</div>
|
||||
</simplebar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modInfo from '../../data/modInfo.json';
|
||||
import { mapState } from 'vuex';
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
import { mapState } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
name: 'Tabs',
|
||||
|
@ -45,6 +43,7 @@ export default {
|
|||
flex-grow: 1;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
|
@ -77,11 +76,6 @@ export default {
|
|||
background: var(--separator);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tab > [data-simplebar] {
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
|
@ -95,23 +89,4 @@ export default {
|
|||
.tab .modal-body hr {
|
||||
margin: 7px 0;
|
||||
}
|
||||
|
||||
.tabs-container > .simplebar-wrapper > .simplebar-mask > .simplebar-offset > .simplebar-content-wrapper > .simplebar-content {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.useHeader .tabs-container > .simplebar-wrapper > .simplebar-mask > .simplebar-offset > .simplebar-content-wrapper > .simplebar-content {
|
||||
height: calc(100vh - 50px);
|
||||
}
|
||||
|
||||
.tab > [data-simplebar] > .simplebar-wrapper > .simplebar-mask > .simplebar-offset > .simplebar-content-wrapper {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.tab > [data-simplebar] > .simplebar-wrapper > .simplebar-mask > .simplebar-offset > .simplebar-content-wrapper > .simplebar-content {
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
<template>
|
||||
<div class="tooltip-container" :class="{ shown }" @mouseenter="setHover(true)" @mouseleave="setHover(false)">
|
||||
<slot />
|
||||
<!-- Make sure slot is *before* the transition in case the slot uses v-frag, which messes up the tooltip -->
|
||||
<transition name="fade">
|
||||
<div v-if="shown" class="tooltip" :class="{ top, left, right, bottom }"
|
||||
:style="{ '--xoffset': xoffset, '--yoffset': yoffset }">
|
||||
:style="{ '--xoffset': xoffset || '0px', '--yoffset': yoffset || '0px' }">
|
||||
<component :is="tooltipDisplay" />
|
||||
</div>
|
||||
</transition>
|
||||
|
@ -81,7 +80,7 @@ export default {
|
|||
}
|
||||
|
||||
.shown {
|
||||
z-index: 1;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.fade-enter, .fade-leave-to {
|
||||
|
|
|
@ -20,7 +20,7 @@ export default {
|
|||
this.branches?.map(this.handleBranch).forEach(branch => this.registerBranch(id, branch));
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
beforeUnmount() {
|
||||
const id = `${this.featureType}@${this.id}`;
|
||||
if (this.unregisterNode) {
|
||||
this.unregisterNode(id);
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
<template>
|
||||
<div v-frag>
|
||||
<slot />
|
||||
<div ref="resizeListener" class="resize-listener" />
|
||||
<svg>
|
||||
<branch-line v-for="(branch, index) in branches" :key="index"
|
||||
:startNode="nodes[branch.start]" :endNode="nodes[branch.end]" :options="branch.options" />
|
||||
</svg>
|
||||
</div>
|
||||
<slot />
|
||||
<div ref="resizeListener" class="resize-listener" />
|
||||
<svg v-bind="$attrs">
|
||||
<branch-line v-for="(branch, index) in branches" :key="index"
|
||||
:startNode="nodes[branch.start]" :endNode="nodes[branch.end]" :options="branch.options" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
|
||||
const observerOptions = {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
|
@ -57,12 +53,12 @@ export default {
|
|||
},
|
||||
updateNode(id, containerRect) {
|
||||
const linkStartRect = this.nodes[id].element.getBoundingClientRect();
|
||||
Vue.set(this.nodes[id], 'x', linkStartRect.x + linkStartRect.width / 2 - containerRect.x);
|
||||
Vue.set(this.nodes[id], 'y', linkStartRect.y + linkStartRect.height / 2 - containerRect.y);
|
||||
this.nodes[id].x = linkStartRect.x + linkStartRect.width / 2 - containerRect.x;
|
||||
this.nodes[id].y = linkStartRect.y + linkStartRect.height / 2 - containerRect.y;
|
||||
},
|
||||
registerNode(id, component) {
|
||||
const element = component.$el.parentElement;
|
||||
Vue.set(this.nodes, id, { component, element });
|
||||
this.nodes[id] = { component, element };
|
||||
this.observer.observe(element, observerOptions);
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.resizeListener != undefined) {
|
||||
|
@ -71,17 +67,15 @@ export default {
|
|||
});
|
||||
},
|
||||
unregisterNode(id) {
|
||||
Vue.delete(this.nodes, id);
|
||||
delete this.nodes[id];
|
||||
},
|
||||
registerBranch(start, options) {
|
||||
const end = typeof options === 'string' ? options : options.target;
|
||||
this.links.push({ start, end, options });
|
||||
Vue.set(this, 'links', this.links);
|
||||
},
|
||||
unregisterBranch(start, options) {
|
||||
const index = this.links.findIndex(l => l.start === start && l.options === options);
|
||||
this.links.splice(index, 1);
|
||||
Vue.set(this, 'links', this.links);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
<template>
|
||||
<div v-frag>
|
||||
<span class="row" v-for="(row, index) in rows" :key="index">
|
||||
<tree-node v-for="(node, nodeIndex) in row" :key="nodeIndex" :id="node" @show-modal="openModal" :append="append" />
|
||||
</span>
|
||||
<span class="side-nodes" v-if="rows.side">
|
||||
<tree-node v-for="(node, nodeIndex) in rows.side" :key="nodeIndex" :id="node" @show-modal="openModal" :append="append" small />
|
||||
</span>
|
||||
<modal :show="showModal" @close="closeModal">
|
||||
<div slot="header"><h2 v-if="modalHeader">{{ modalHeader }}</h2></div>
|
||||
<layer-tab slot="body" v-if="modal" :layer="modal" :index="tab.index" :forceFirstTab="true" />
|
||||
</modal>
|
||||
</div>
|
||||
<span class="row" v-for="(row, index) in rows" :key="index">
|
||||
<tree-node v-for="(node, nodeIndex) in row" :key="nodeIndex" :id="node" @show-modal="openModal" :append="append" />
|
||||
</span>
|
||||
<span class="side-nodes" v-if="rows.side">
|
||||
<tree-node v-for="(node, nodeIndex) in rows.side" :key="nodeIndex" :id="node" @show-modal="openModal" :append="append" small />
|
||||
</span>
|
||||
<modal :show="showModal" @close="closeModal">
|
||||
<template v-slot:header><h2 v-if="modalHeader">{{ modalHeader }}</h2></template>
|
||||
<template v-slot:body><layer-tab v-if="modal" :layer="modal" :index="tab.index" :forceFirstTab="true" /></template>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { layers } from '../../game/layers';
|
||||
|
||||
export default {
|
||||
name: 'tree',
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../game/layers';
|
||||
import player from '../../game/player';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
|
||||
export default {
|
||||
|
@ -32,6 +32,7 @@ export default {
|
|||
small: Boolean,
|
||||
append: Boolean
|
||||
},
|
||||
emits: [ 'show-modal' ],
|
||||
inject: [ 'tab' ],
|
||||
computed: {
|
||||
layer() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Decimal from '../../../util/bignum';
|
||||
import { player } from '../../../store/proxies';
|
||||
import player from '../../../game/player';
|
||||
|
||||
export default {
|
||||
id: "a",
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import Decimal, { format, formatWhole } from '../../../util/bignum';
|
||||
import { player, tmp } from '../../../store/proxies';
|
||||
import { layers } from '../../../store/layers';
|
||||
import player from '../../../game/player';
|
||||
import { layers } from '../../../game/layers';
|
||||
import { hasUpgrade, hasMilestone, getBuyableAmount, setBuyableAmount, upgradeEffect, buyableEffect, challengeCompletions } from '../../../util/features';
|
||||
import { resetLayer, resetLayerData } from '../../../util/layers';
|
||||
import { UP, RIGHT } from '../../../util/vue';
|
||||
|
||||
const tmp = layers;
|
||||
|
||||
export default {
|
||||
id: "c", // This is assigned automatically, both to the layer and all upgrades, etc. Shown here so you know about it
|
||||
name: "Candies", // This is optional, only used in a few places, If absent it just uses the layer id.
|
||||
|
@ -230,10 +232,9 @@ export default {
|
|||
microtabs: {
|
||||
stuff: {
|
||||
first: {
|
||||
display: `<div v-frag>
|
||||
display: `
|
||||
<upgrades />
|
||||
<div>confirmed</div>
|
||||
</div>`
|
||||
<div>confirmed</div>`
|
||||
},
|
||||
second: {
|
||||
embedLayer: "f"
|
||||
|
@ -304,22 +305,19 @@ export default {
|
|||
buttonStyle() {return {'color': 'orange'}},
|
||||
notify: true,
|
||||
display: `
|
||||
<div v-frag>
|
||||
<main-display />
|
||||
<sticky><prestige-button /></sticky>
|
||||
<resource-display />
|
||||
<spacer height="5px" />
|
||||
<button onclick='console.log("yeet")'>'HI'</button>
|
||||
<div>Name your points!</div>
|
||||
<TextField :value="player.c.thingy" @input="value => player.c.thingy = value" :field="false" />
|
||||
<sticky style="color: red; font-size: 32px; font-family: Comic Sans MS;">I have {{ format(player.points) }} {{ player.c.thingy }} points!</sticky>
|
||||
<hr />
|
||||
<milestones />
|
||||
<spacer />
|
||||
<upgrades />
|
||||
<challenges />
|
||||
</div>
|
||||
`,
|
||||
<main-display />
|
||||
<sticky><prestige-button /></sticky>
|
||||
<resource-display />
|
||||
<spacer height="5px" />
|
||||
<button onclick='console.log("yeet")'>'HI'</button>
|
||||
<div>Name your points!</div>
|
||||
<TextField :value="player.c.thingy" @input="value => player.c.thingy = value" :field="false" />
|
||||
<sticky style="color: red; font-size: 32px; font-family: Comic Sans MS;">I have {{ format(player.points) }} {{ player.c.thingy }} points!</sticky>
|
||||
<hr />
|
||||
<milestones />
|
||||
<spacer />
|
||||
<upgrades />
|
||||
<challenges />`,
|
||||
glowColor: "blue",
|
||||
|
||||
},
|
||||
|
@ -328,59 +326,50 @@ export default {
|
|||
style() {return {'background-color': '#222222', '--background': '#222222'}},
|
||||
buttonStyle() {return {'border-color': 'orange'}},
|
||||
display: `
|
||||
<div v-frag>
|
||||
<buyables />
|
||||
<buyables />
|
||||
<spacer />
|
||||
<row style="width: 600px; height: 350px; background-color: green; border-style: solid;">
|
||||
<Toggle :value="player.c.beep" @change="value => player.c.beep = value" />
|
||||
<spacer width="30px" height="10px" />
|
||||
<div>Beep</div>
|
||||
<spacer />
|
||||
<row style="width: 600px; height: 350px; background-color: green; border-style: solid;">
|
||||
<Toggle :value="player.c.beep" @change="value => player.c.beep = value" />
|
||||
<spacer width="30px" height="10px" />
|
||||
<div>Beep</div>
|
||||
<spacer />
|
||||
<vr height="200px"/>
|
||||
<column>
|
||||
<prestige-button style="width: 150px; height: 80px" />
|
||||
<prestige-button style="width: 100px; height: 150px" />
|
||||
</column>
|
||||
</row>
|
||||
<spacer />
|
||||
<img src="https://unsoftcapped2.github.io/The-Modding-Tree-2/discord.png" />
|
||||
</div>
|
||||
`
|
||||
<vr height="200px"/>
|
||||
<column>
|
||||
<prestige-button style="width: 150px; height: 80px" />
|
||||
<prestige-button style="width: 100px; height: 150px" />
|
||||
</column>
|
||||
</row>
|
||||
<spacer />
|
||||
<img src="https://unsoftcapped2.github.io/The-Modding-Tree-2/discord.png" />`
|
||||
},
|
||||
jail: {
|
||||
display: `
|
||||
<div v-frag>
|
||||
<infobox id="coolInfo" />
|
||||
<bar id="longBoi" />
|
||||
<infobox id="coolInfo" />
|
||||
<bar id="longBoi" />
|
||||
<spacer />
|
||||
<row>
|
||||
<column style="background-color: #555555; padding: 15px">
|
||||
<div style="color: teal">Sugar level:</div><spacer /><bar id="tallBoi" />
|
||||
</column>
|
||||
<spacer />
|
||||
<row>
|
||||
<column style="background-color: #555555; padding: 15px">
|
||||
<div style="color: teal">Sugar level:</div><spacer /><bar id="tallBoi" />
|
||||
</column>
|
||||
<spacer />
|
||||
<column>
|
||||
<div>idk</div>
|
||||
<spacer width="0" height="50px" />
|
||||
<bar id="flatBoi" />
|
||||
</column>
|
||||
</row>
|
||||
<spacer />
|
||||
<div>It's jail because "bars"! So funny! Ha ha!</div>
|
||||
<tree :nodes="[['f', 'c'], ['g', 'spook', 'h']]" />
|
||||
</div>
|
||||
`
|
||||
<column>
|
||||
<div>idk</div>
|
||||
<spacer width="0" height="50px" />
|
||||
<bar id="flatBoi" />
|
||||
</column>
|
||||
</row>
|
||||
<spacer />
|
||||
<div>It's jail because "bars"! So funny! Ha ha!</div>
|
||||
<tree :nodes="[['f', 'c'], ['g', 'spook', 'h']]" />`
|
||||
},
|
||||
illuminati: {
|
||||
unlocked() {return (hasUpgrade("c", 13))},
|
||||
display: `
|
||||
<div v-frag>
|
||||
<h1> C O N F I R M E D </h1>
|
||||
<spacer />
|
||||
<microtab family="stuff" style="width: 660px; height: 370px; background-color: brown; --background: brown; border: solid white; margin: auto" />
|
||||
<div>Adjust how many points H gives you!</div>
|
||||
<Slider :value="player.c.otherThingy" @change="value => player.c.otherThingy = value" :min="1" :max="30" />
|
||||
</div>
|
||||
`
|
||||
<h1> C O N F I R M E D </h1>
|
||||
<spacer />
|
||||
<microtab family="stuff" style="width: 660px; height: 370px; background-color: brown; --background: brown; border: solid white; margin: auto" />
|
||||
<div>Adjust how many points H gives you!</div>
|
||||
<Slider :value="player.c.otherThingy" @change="value => player.c.otherThingy = value" :min="1" :max="30" />`
|
||||
}
|
||||
|
||||
},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Decimal, { formatWhole } from '../../../util/bignum';
|
||||
import { player, tmp } from '../../../store/proxies';
|
||||
import player from '../../../game/player';
|
||||
import { layers as tmp } from '../../../game/layers';
|
||||
import { getClickableState } from '../../../util/features';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Decimal, { format } from '../../util/bignum';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../store/layers';
|
||||
import player from '../../game/player';
|
||||
import { layers } from '../../game/layers';
|
||||
import { hasUpgrade, hasMilestone, getBuyableAmount, setBuyableAmount, hasChallenge } from '../../util/features';
|
||||
import { resetLayer } from '../../util/layers';
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Decimal, { format } from '../../util/bignum';
|
||||
import { player } from '../../store/proxies';
|
||||
import { layers } from '../../store/layers';
|
||||
import player from '../../game/player';
|
||||
import { layers } from '../../game/layers';
|
||||
import { hasUpgrade, hasMilestone, getBuyableAmount, setBuyableAmount, hasChallenge } from '../../util/features';
|
||||
import { resetLayer } from '../../util/layers';
|
||||
|
||||
|
@ -871,38 +871,35 @@ challenges:{
|
|||
},
|
||||
subtabs: {
|
||||
"Upgrades": {
|
||||
display: `<div v-frag>
|
||||
display: `
|
||||
<main-display />
|
||||
<spacer />
|
||||
<prestige-button display="" />
|
||||
<spacer />
|
||||
<spacer />
|
||||
<upgrades />
|
||||
</div>`
|
||||
<upgrades />`
|
||||
},
|
||||
"Challenges": {
|
||||
unlocked() { return hasUpgrade("p", 51) || hasMilestone("p", 0); },
|
||||
display: `<div v-frag>
|
||||
display: `
|
||||
<spacer />
|
||||
<spacer />
|
||||
<challenges />
|
||||
</div>`
|
||||
<challenges />`
|
||||
},
|
||||
"Buyables and Milestones": {
|
||||
unlocked(){return hasUpgrade("p",74)||hasMilestone("p",0)},
|
||||
display: `<div v-frag>
|
||||
display: `
|
||||
<spacer />
|
||||
<spacer />
|
||||
<row><buyable id="11" /></row>
|
||||
<spacer />
|
||||
<div v-if="hasMilestone('p', 0)">Your boosts are making the point challenge {{ getBuyableAmount('p', 11).plus(1) }}x less pointy</div>
|
||||
<spacer />
|
||||
<milestones />
|
||||
</div>`
|
||||
<milestones />`
|
||||
},
|
||||
"Generators": {
|
||||
unlocked(){return hasMilestone("p",5)||player.i.points.gte(1)},
|
||||
display: `<div v-frag>
|
||||
display: `
|
||||
<spacer />
|
||||
<div>You have {{ format(player.p.gp) }} generator points, adding {{ format(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()) }} to point gain</div>
|
||||
<div>You have {{ format(player.p.g) }} generators, generating {{ format(player.p.g.times(player.p.geff)) }} generator points per second</div>
|
||||
|
@ -910,12 +907,11 @@ challenges:{
|
|||
<spacer />
|
||||
<spacer />
|
||||
<buyables :buyables="[12, 13, 14]" />
|
||||
<row><clickable id="11" /></row>
|
||||
</div>`
|
||||
<row><clickable id="11" /></row>`
|
||||
},
|
||||
"Pointy Points": {
|
||||
unlocked(){return hasUpgrade("p",104)||player.i.points.gte(1)},
|
||||
display: `<div v-frag>
|
||||
display: `
|
||||
<div style="color: red; font-size: 32px; font-family: Comic Sans MS">{{ format(player.p.buyables[21]) }} pointy points</div>
|
||||
<div style="color: red; font-size: 32px; font-family: Comic Sans MS">My pointy points are multiplying generator efficiency by {{ format(new Decimal(player.p.buyables[21]).plus(1)) }}</div>
|
||||
<spacer />
|
||||
|
@ -932,15 +928,13 @@ challenges:{
|
|||
<spacer />
|
||||
<spacer />
|
||||
<div v-if="hasMilestone('p', 11)" style="font-size: 24px">Booster upgrades</div>
|
||||
<upgrades :upgrades="[231, 232, 233, 234, 235]" />
|
||||
</div>`
|
||||
<upgrades :upgrades="[231, 232, 233, 234, 235]" />`
|
||||
},
|
||||
"Buyables": {
|
||||
unlocked(){return hasMilestone("p",13)},
|
||||
display: `<div v-frag>
|
||||
display: `
|
||||
<buyables :buyables="[31, 32, 33]" />
|
||||
<buyables :buyables="[41, 42, 43]" />
|
||||
</div>`
|
||||
<buyables :buyables="[41, 42, 43]" />`
|
||||
}
|
||||
}
|
||||
}
|
104
src/data/mod.js
104
src/data/mod.js
|
@ -1,8 +1,8 @@
|
|||
import { computed } from 'vue';
|
||||
import { hasUpgrade, upgradeEffect, hasMilestone, inChallenge, getBuyableAmount } from '../util/features';
|
||||
import { layers } from '../store/layers';
|
||||
import { player } from '../store/proxies';
|
||||
import { layers } from '../game/layers';
|
||||
import player from '../game/player';
|
||||
import Decimal from '../util/bignum';
|
||||
import modInfo from './modInfo';
|
||||
|
||||
// Import initial layers
|
||||
import f from './layers/aca/f.js';
|
||||
|
@ -40,7 +40,7 @@ const spook = {
|
|||
|
||||
const main = {
|
||||
id: 'main',
|
||||
display: `<div v-frag>
|
||||
display: `
|
||||
<div v-if="player.devSpeed === 0">Game Paused</div>
|
||||
<div v-else-if="player.devSpeed && player.devSpeed !== 1">Dev Speed: {{ format(player.devSpeed) }}x</div>
|
||||
<div v-if="player.offTime != undefined">Offline Time: {{ formatTime(player.offTime.remain) }}</div>
|
||||
|
@ -49,12 +49,11 @@ const main = {
|
|||
<h2>{{ format(player.points) }}</h2>
|
||||
<span v-if="player.points.lt('1e1e6')"> points</span>
|
||||
</div>
|
||||
<div v-if="Decimal.gt($store.getters.pointGain, 0)">
|
||||
({{ player.oompsMag != 0 ? format(player.oomps) + " OOM" + (player.oompsMag < 0 ? "^OOM" : player.oompsMag > 1 ? "^" + player.oompsMag : "") + "s" : formatSmall($store.getters.pointGain) }}/sec)
|
||||
<div v-if="Decimal.gt(pointGain, 0)">
|
||||
({{ player.oompsMag != 0 ? format(player.oomps) + " OOM" + (player.oompsMag < 0 ? "^OOM" : player.oompsMag > 1 ? "^" + player.oompsMag : "") + "s" : formatSmall(pointGain) }}/sec)
|
||||
</div>
|
||||
<spacer />
|
||||
<tree :append="true" />
|
||||
</div>`,
|
||||
<tree :append="true" />`,
|
||||
name: "Tree"
|
||||
};
|
||||
|
||||
|
@ -66,52 +65,51 @@ export function getStartingData() {
|
|||
}
|
||||
}
|
||||
|
||||
export const getters = {
|
||||
hasWon() {
|
||||
return false;
|
||||
},
|
||||
pointGain() {
|
||||
if(!hasUpgrade("c", 11))
|
||||
return new Decimal(0);
|
||||
let gain = new Decimal(3.19)
|
||||
if (hasUpgrade("c", 12)) gain = gain.times(upgradeEffect("c", 12))
|
||||
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)
|
||||
export const hasWon = computed(() => {
|
||||
return false;
|
||||
});
|
||||
|
||||
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)
|
||||
return gain;
|
||||
export const pointGain = computed(() => {
|
||||
if(!hasUpgrade("c", 11))
|
||||
return new Decimal(0);
|
||||
let gain = new Decimal(3.19)
|
||||
if (hasUpgrade("c", 12)) gain = gain.times(upgradeEffect("c", 12))
|
||||
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)
|
||||
return gain;
|
||||
});
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
export function update(delta) {
|
||||
|
@ -120,5 +118,3 @@ export function update(delta) {
|
|||
/* eslint-disable-next-line no-unused-vars */
|
||||
export function fixOldSave(oldVersion, playerData) {
|
||||
}
|
||||
|
||||
document.title = modInfo.title;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { update as modUpdate } from '../data/mod';
|
||||
import { update as modUpdate, hasWon, pointGain } 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';
|
||||
import player from './player';
|
||||
|
||||
function updatePopups(/* diff */) {
|
||||
// TODO
|
||||
|
@ -104,7 +103,7 @@ function update() {
|
|||
}
|
||||
|
||||
// Stop here if the game is paused on the win screen
|
||||
if (store.getters.hasWon && !player.keepGoing) {
|
||||
if (hasWon.value && !player.keepGoing) {
|
||||
return;
|
||||
}
|
||||
// Stop here if the player had a NaN value
|
||||
|
@ -145,13 +144,13 @@ function update() {
|
|||
}
|
||||
player.timePlayed = player.timePlayed.add(diff);
|
||||
if (player.points != undefined) {
|
||||
player.points = player.points.add(Decimal.times(store.getters.pointGain, diff));
|
||||
player.points = player.points.add(Decimal.times(pointGain.value, diff));
|
||||
}
|
||||
modUpdate(diff);
|
||||
updateOOMPS(trueDiff);
|
||||
updateLayers(diff);
|
||||
}
|
||||
|
||||
export function startGameLoop() {
|
||||
export default function startGameLoop() {
|
||||
setInterval(update, 50);
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
import Vue from 'vue';
|
||||
import clone from 'lodash.clonedeep';
|
||||
import { isFunction, isPlainObject } from '../util/common';
|
||||
import { createProxy, createGridProxy, player as playerProxy } from './proxies';
|
||||
import { createProxy, createGridProxy } from '../util/proxies';
|
||||
import playerProxy from './player';
|
||||
import Decimal from '../util/bignum';
|
||||
import store from './index';
|
||||
import { noCache, getStartingBuyables, getStartingClickables, getStartingChallenges, defaultLayerProperties } from '../util/layers';
|
||||
import { applyPlayerData } from '../util/save';
|
||||
import { isRef } from 'vue';
|
||||
|
||||
export const layers = {};
|
||||
export const hotkeys = [];
|
||||
|
@ -49,11 +49,9 @@ export function addLayer(layer, player = null) {
|
|||
layer.base = 2;
|
||||
}
|
||||
|
||||
const getters = {};
|
||||
|
||||
// Process each feature
|
||||
for (let property of uncachedProperties) {
|
||||
if (layer[property]) {
|
||||
if (layer[property] && !isRef(layer.property)) {
|
||||
layer[property].forceCached = false;
|
||||
}
|
||||
}
|
||||
|
@ -312,21 +310,20 @@ export function addLayer(layer, player = null) {
|
|||
setDefault(layer.grids[id], 'hold', null, false);
|
||||
setDefault(layer.grids[id], 'getTitle', null, false);
|
||||
setDefault(layer.grids[id], 'getDisplay', null, false);
|
||||
layer.grids[id] = createGridProxy(layer.grids[id], getters, `${layer.id}/grids-${id}-`);
|
||||
layer.grids[id] = createGridProxy(layer.grids[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (layer.subtabs) {
|
||||
layer.activeSubtab = function() {
|
||||
if (this.subtabs != undefined) {
|
||||
if (this.subtabs[player.subtabs[layer.id].mainTabs] &&
|
||||
this.subtabs[player.subtabs[layer.id].mainTabs].unlocked !== false) {
|
||||
return this.subtabs[player.subtabs[layer.id].mainTabs];
|
||||
}
|
||||
// Default to first unlocked tab
|
||||
return Object.values(this.subtabs).find(subtab => subtab.unlocked !== false);
|
||||
if (layer.subtabs[playerProxy.subtabs[layer.id].mainTabs] &&
|
||||
layer.subtabs[playerProxy.subtabs[layer.id].mainTabs].unlocked !== false) {
|
||||
return layer.subtabs[playerProxy.subtabs[layer.id].mainTabs];
|
||||
}
|
||||
// Default to first unlocked tab
|
||||
return Object.values(layer.subtabs).find(subtab => subtab.unlocked !== false);
|
||||
}
|
||||
setDefault(player, 'subtabs', {});
|
||||
setDefault(player.subtabs, layer.id, {});
|
||||
setDefault(player.subtabs[layer.id], 'mainTabs', Object.keys(layer.subtabs)[0]);
|
||||
for (let id in layer.subtabs) {
|
||||
|
@ -338,16 +335,17 @@ export function addLayer(layer, player = null) {
|
|||
}
|
||||
}
|
||||
if (layer.microtabs) {
|
||||
setDefault(player, 'subtabs', {});
|
||||
setDefault(player.subtabs, layer.id, {});
|
||||
for (let family in layer.microtabs) {
|
||||
layer.microtabs[family].activeMicrotab = function() {
|
||||
if (this[player.subtabs[this.layer]?.[family]] && this[player.subtabs[this.layer][family]].unlocked !== false) {
|
||||
return this[player.subtabs[this.layer][family]];
|
||||
if (this[playerProxy.subtabs[this.layer][family]] && this[playerProxy.subtabs[this.layer][family]].unlocked !== false) {
|
||||
return this[playerProxy.subtabs[this.layer][family]];
|
||||
}
|
||||
// Default to first unlocked tab
|
||||
return this[Object.keys(this).find(microtab => microtab !== 'activeMicrotab' && this[microtab].unlocked !== false)];
|
||||
}
|
||||
setDefault(player.subtabs[layer.id], family, Object.keys(layer.microtabs[family])[0]);
|
||||
setDefault(player.subtabs[layer.id], family, Object.keys(layer.microtabs[family]).find(tab => tab !== 'activeMicrotab'));
|
||||
layer.microtabs[family].layer = layer.id;
|
||||
layer.microtabs[family].family = family;
|
||||
for (let id in layer.microtabs[family]) {
|
||||
|
@ -356,7 +354,7 @@ export function addLayer(layer, player = null) {
|
|||
layer.microtabs[family][id].family = family;
|
||||
layer.microtabs[family][id].id = id;
|
||||
layer.microtabs[family][id].active = function() {
|
||||
return player.subtabs[this.layer]?.[this.family] === this.id;
|
||||
return playerProxy.subtabs[this.layer][this.family] === this.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,11 +372,10 @@ export function addLayer(layer, player = null) {
|
|||
}
|
||||
|
||||
// Create layer proxy
|
||||
layer = createProxy(layer, getters, `${layer.id}/`);
|
||||
layer = createProxy(layer);
|
||||
|
||||
// Register layer
|
||||
layers[layer.id] = layer;
|
||||
store.registerModule(`layer-${layer.id}`, { getters });
|
||||
|
||||
// Register hotkeys
|
||||
if (layer.hotkeys) {
|
||||
|
@ -392,12 +389,11 @@ export function removeLayer(layer) {
|
|||
// Un-set hotkeys
|
||||
if (layers[layer].hotkeys) {
|
||||
for (let id in layers[layer].hotkeys) {
|
||||
Vue.delete(hotkeys, id);
|
||||
delete hotkeys[id];
|
||||
}
|
||||
}
|
||||
|
||||
// Un-register layer
|
||||
store.unregisterModule(`layer-${layer}`);
|
||||
delete layers[layer];
|
||||
}
|
||||
|
||||
export function reloadLayer(layer) {
|
52
src/game/player.js
Normal file
52
src/game/player.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { reactive } from 'vue';
|
||||
import { isPlainObject } from '../util/common';
|
||||
import Decimal from '../util/bignum';
|
||||
|
||||
const state = reactive({});
|
||||
|
||||
const playerHandler = {
|
||||
get(target, key) {
|
||||
if (key === '__state' || key === '__path') {
|
||||
return target[key];
|
||||
}
|
||||
if (target.__state[key] == undefined) {
|
||||
return;
|
||||
}
|
||||
if (isPlainObject(target.__state[key]) && !(target.__state[key] instanceof Decimal)) {
|
||||
if (target.__state[key] !== target[key]?.__state) {
|
||||
const path = [ ...target.__path, key ];
|
||||
target[key] = new Proxy({ __state: target.__state[key], __path: path }, playerHandler);
|
||||
}
|
||||
return target[key];
|
||||
}
|
||||
|
||||
return target.__state[key];
|
||||
},
|
||||
set(target, property, value, receiver) {
|
||||
if (!state.hasNaN && ((typeof value === 'number' && isNaN(value)) || (value instanceof Decimal && (isNaN(value.sign) || isNaN(value.layer) || isNaN(value.mag))))) {
|
||||
const currentValue = target.__state[property];
|
||||
if (!((typeof currentValue === 'number' && isNaN(currentValue)) || (currentValue instanceof Decimal && (isNaN(currentValue.sign) || isNaN(currentValue.layer) || isNaN(currentValue.mag))))) {
|
||||
state.autosave = false;
|
||||
state.hasNaN = true;
|
||||
state.NaNPath = [ ...target.__path, property ];
|
||||
state.NaNReceiver = receiver;
|
||||
console.error(`Attempted to set NaN value`, [ ...target.__path, property ], target.__state);
|
||||
throw 'Attempted to set NaN value. See above for details';
|
||||
}
|
||||
}
|
||||
target.__state[property] = value;
|
||||
if (property === 'points') {
|
||||
if (target.__state.best != undefined) {
|
||||
target.__state.best = Decimal.max(target.__state.best, value);
|
||||
}
|
||||
if (target.__state.total != undefined) {
|
||||
const diff = Decimal.sub(value, target.__state.points);
|
||||
if (diff.gt(0)) {
|
||||
target.__state.total = target.__state.total.add(diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
export default window.player = new Proxy({ __state: state, __path: [ 'player' ] }, playerHandler);
|
|
@ -1,3 +1,7 @@
|
|||
:root {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
* {
|
||||
transition-duration: 0.5s;
|
||||
font-family: "Roboto Mono", monospace;
|
||||
|
|
22
src/main.js
22
src/main.js
|
@ -1,24 +1,22 @@
|
|||
import Vue from 'vue';
|
||||
import { createApp } from 'vue';
|
||||
import App from './App';
|
||||
import store from './store';
|
||||
import { load } from './util/save';
|
||||
import { setVue } from './util/vue';
|
||||
import { startGameLoop } from './store/game';
|
||||
import './components/index';
|
||||
|
||||
// Setup
|
||||
Vue.config.productionTip = false;
|
||||
import gameLoop from './game/gameLoop';
|
||||
import { registerComponents } from './components/index';
|
||||
import modInfo from './data/modInfo.json';
|
||||
|
||||
requestAnimationFrame(async () => {
|
||||
await load();
|
||||
|
||||
// Create Vue
|
||||
const vue = window.vue = new Vue({
|
||||
store,
|
||||
render: h => h(App)
|
||||
const vue = window.vue = createApp({
|
||||
...App
|
||||
});
|
||||
setVue(vue);
|
||||
vue.$mount('#app');
|
||||
registerComponents(vue);
|
||||
vue.mount('#app');
|
||||
document.title = modInfo.title;
|
||||
|
||||
startGameLoop();
|
||||
gameLoop();
|
||||
});
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import { getInitialStore } from '../util/save';
|
||||
import { getters } from '../data/mod';
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: getInitialStore(),
|
||||
getters
|
||||
});
|
|
@ -1,223 +0,0 @@
|
|||
import { layers } from './layers';
|
||||
import { isFunction, isPlainObject } from '../util/common';
|
||||
import Decimal from '../util/bignum';
|
||||
import store from './index';
|
||||
import Vue from 'vue';
|
||||
|
||||
export const tmp = new Proxy({}, {
|
||||
get(target, property) {
|
||||
if (property in layers) {
|
||||
return layers[property];
|
||||
}
|
||||
// TODO implement other tmp values for backwards compatibility
|
||||
console.error(`No getter for "${property}"`, target);
|
||||
}
|
||||
});
|
||||
|
||||
const playerHandler = {
|
||||
get(target, key) {
|
||||
if (key === 'isProxy') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target[key] == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!target[key].isProxy && !(target[key] instanceof Decimal) && (isPlainObject(target[key]) || Array.isArray(target[key]))) {
|
||||
// Note that player isn't pre-created since it (shouldn't) have functions or getters
|
||||
// so creating proxies as they're requested is A-OK
|
||||
target[key] = new Proxy(target[key], playerHandler);
|
||||
return target[key];
|
||||
}
|
||||
|
||||
return target[key];
|
||||
},
|
||||
set(target, property, value, receiver) {
|
||||
if (!player.hasNaN && value instanceof Decimal && (isNaN(value.sign) || isNaN(value.layer) || isNaN(value.mag))) {
|
||||
player.autosave = false;
|
||||
player.hasNaN = true;
|
||||
player.NaNProperty = property;
|
||||
player.NaNReceiver = receiver;
|
||||
player.NaNPrevious = target[property];
|
||||
Vue.set(target, property, value);
|
||||
console.error(`Attempted to set NaN value`, target, property);
|
||||
throw 'Attempted to set NaN value. See above for details';
|
||||
}
|
||||
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;
|
||||
},
|
||||
deleteProperty(target, prop) {
|
||||
Vue.delete(target, prop);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
export const player = window.player = new Proxy(store.state, playerHandler);
|
||||
|
||||
export function createProxy(object, getters, prefix) {
|
||||
if (object.isProxy) {
|
||||
console.warn("Creating a proxy out of a proxy! This may cause unintentional function calls and stack overflows.");
|
||||
}
|
||||
const objectProxy = new Proxy(object, getHandler(prefix));
|
||||
travel(createProxy, object, objectProxy, getters, prefix);
|
||||
return objectProxy;
|
||||
}
|
||||
|
||||
// TODO cache grid values? Currently they'll be calculated every render they're visible
|
||||
export function createGridProxy(object, getters, prefix) {
|
||||
if (object.isProxy) {
|
||||
console.warn("Creating a proxy out of a proxy! This may cause unintentional function calls and stack overflows.");
|
||||
}
|
||||
const objectProxy = new Proxy(object, getGridHandler(prefix));
|
||||
travel(createGridProxy, object, objectProxy, getters, prefix);
|
||||
return objectProxy;
|
||||
}
|
||||
|
||||
function travel(callback, object, objectProxy, getters, prefix) {
|
||||
for (let key in object) {
|
||||
if (object[key].isProxy) {
|
||||
continue;
|
||||
}
|
||||
if (isFunction(object[key])) {
|
||||
if ((object[key].length !== 0 && object[key].forceCached !== true) || object[key].forceCached === false) {
|
||||
continue;
|
||||
}
|
||||
getters[`${prefix}${key}`] = () => {
|
||||
return object[key].call(objectProxy);
|
||||
}
|
||||
} else if ((isPlainObject(object[key]) || Array.isArray(object[key])) && !(object[key] instanceof Decimal)) {
|
||||
object[key] = callback(object[key], getters, `${prefix}${key}-`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getHandler(prefix) {
|
||||
return {
|
||||
get(target, key, receiver) {
|
||||
if (key === 'isProxy') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target[key] == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target[key].isProxy || target[key] instanceof Decimal) {
|
||||
return target[key];
|
||||
} else if ((isPlainObject(target[key]) || Array.isArray(target[key])) && key.slice(0, 2) !== '__') {
|
||||
console.warn("Creating proxy outside `createProxy`. This may cause issues when calling proxied functions.",
|
||||
target, key);
|
||||
target[key] = new Proxy(target[key], getHandler(`${prefix}${key}-`));
|
||||
return target[key];
|
||||
} else if (isFunction(target[key])) {
|
||||
const getterID = `${prefix}${key}`;
|
||||
if (getterID in store.getters) {
|
||||
return store.getters[getterID];
|
||||
} else {
|
||||
return target[key].bind(receiver);
|
||||
}
|
||||
}
|
||||
return target[key];
|
||||
},
|
||||
set(target, key, value, receiver) {
|
||||
if (`${key}Set` in target && isFunction(target[`${key}Set`]) && target[`${key}Set`].length < 2) {
|
||||
target[`${key}Set`].call(receiver, value);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(`No setter for "${key}".`, target);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getGridHandler(prefix) {
|
||||
return {
|
||||
get(target, key) {
|
||||
if (key === 'isProxy') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target[key] && (target[key].isProxy || target[key] instanceof Decimal)) {
|
||||
return target[key];
|
||||
} else if (isPlainObject(target[key]) || Array.isArray(target[key])) {
|
||||
console.warn("Creating proxy outside `createProxy`. This may cause issues when calling proxied functions.",
|
||||
target, key);
|
||||
target[key] = new Proxy(target[key], getHandler(`${prefix}${key}-`));
|
||||
return target[key];
|
||||
} else if (isFunction(target[key])) {
|
||||
const getterID = `${prefix}${key}`;
|
||||
if (getterID in store.getters) {
|
||||
return store.getters[getterID];
|
||||
}
|
||||
// Non-cached functions are going to be cell-specific, so don't call them with the grid handler
|
||||
}
|
||||
if (typeof key !== 'symbol' && !isNaN(key)) {
|
||||
target[key] = new Proxy(target, getCellHandler(key));
|
||||
}
|
||||
return target[key];
|
||||
},
|
||||
set(target, key, value, receiver) {
|
||||
if (`${key}Set` in target && isFunction(target[`${key}Set`]) && target[`${key}Set`].length < 2) {
|
||||
target[`${key}Set`].call(receiver, value);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(`No setter for "${key}".`, target);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getCellHandler(id) {
|
||||
return {
|
||||
get(target, key, receiver) {
|
||||
if (key === 'isProxy') {
|
||||
return true;
|
||||
}
|
||||
|
||||
let prop = target[key];
|
||||
|
||||
if (isFunction(prop) && prop.forceCached === false) {
|
||||
return () => prop.call(receiver, id, target.getData(id));
|
||||
}
|
||||
if (prop != undefined || key.slice == undefined) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
key = key.slice(0, 1).toUpperCase() + key.slice(1);
|
||||
prop = target[`get${key}`];
|
||||
if (isFunction(prop)) {
|
||||
return prop.call(receiver, id, target.getData(id));
|
||||
} else if (prop != undefined) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
prop = target[`on${key}`];
|
||||
if (isFunction(prop)) {
|
||||
return () => prop.call(receiver, id, target.getData(id));
|
||||
} else if (prop != undefined) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
return target[key];
|
||||
},
|
||||
set(target, key, value, receiver) {
|
||||
if (`${key}Set` in target && isFunction(target[`${key}Set`]) && target[`${key}Set`].length < 3) {
|
||||
target[`${key}Set`].call(receiver, id, value);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(`No setter for "${key}".`, target);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { layers } from '../store/layers';
|
||||
import { layers } from '../game/layers';
|
||||
|
||||
export function hasUpgrade(layer, id) {
|
||||
return layers[layer]?.upgrades?.[id]?.bought;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Decimal from './bignum';
|
||||
import { isPlainObject } from './common';
|
||||
import { layers, hotkeys } from '../store/layers';
|
||||
import { player } from '../store/proxies';
|
||||
import { layers, hotkeys } from '../game/layers';
|
||||
import player from '../game/player';
|
||||
|
||||
export function resetLayer(layer, force = false) {
|
||||
layers[layer].reset(force);
|
||||
|
@ -72,7 +72,6 @@ export function resetLayerData(layer, keep = []) {
|
|||
}
|
||||
|
||||
export function resetRow(row, ignore) {
|
||||
console.log(row, ignore);
|
||||
Object.values(layers).filter(layer => layer.row === row && layer.layer !== ignore).forEach(layer => layer.hardReset());
|
||||
}
|
||||
|
||||
|
|
149
src/util/proxies.js
Normal file
149
src/util/proxies.js
Normal file
|
@ -0,0 +1,149 @@
|
|||
import { isFunction, isPlainObject } from './common';
|
||||
import Decimal from './bignum';
|
||||
import { isRef, computed } from 'vue';
|
||||
|
||||
export function createProxy(object) {
|
||||
if (object.isProxy) {
|
||||
console.warn("Creating a proxy out of a proxy! This may cause unintentional function calls and stack overflows.");
|
||||
}
|
||||
const objectProxy = new Proxy(object, mainHandler);
|
||||
travel(createProxy, object, objectProxy);
|
||||
return objectProxy;
|
||||
}
|
||||
|
||||
// TODO cache grid values? Currently they'll be calculated every render they're visible
|
||||
export function createGridProxy(object) {
|
||||
if (object.isProxy) {
|
||||
console.warn("Creating a proxy out of a proxy! This may cause unintentional function calls and stack overflows.");
|
||||
}
|
||||
const objectProxy = new Proxy(object, gridHandler);
|
||||
travel(createGridProxy, object, objectProxy);
|
||||
return objectProxy;
|
||||
}
|
||||
|
||||
function travel(callback, object, objectProxy) {
|
||||
for (let key in object) {
|
||||
if (object[key].isProxy) {
|
||||
continue;
|
||||
}
|
||||
if (isFunction(object[key])) {
|
||||
if ((object[key].length !== 0 && object[key].forceCached !== true) || object[key].forceCached === false) {
|
||||
continue;
|
||||
}
|
||||
object[key] = computed(object[key].bind(objectProxy));
|
||||
} else if ((isPlainObject(object[key]) || Array.isArray(object[key])) && !(object[key] instanceof Decimal)) {
|
||||
object[key] = callback(object[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mainHandler = {
|
||||
get(target, key, receiver) {
|
||||
if (key === 'isProxy') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target[key] == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRef(target[key])) {
|
||||
return target[key].value;
|
||||
} else if (target[key].isProxy || target[key] instanceof Decimal) {
|
||||
return target[key];
|
||||
} else if ((isPlainObject(target[key]) || Array.isArray(target[key])) && key.slice(0, 2) !== '__') {
|
||||
console.warn("Creating proxy outside `createProxy`. This may cause issues when calling proxied functions.",
|
||||
target, key);
|
||||
target[key] = new Proxy(target[key], mainHandler);
|
||||
return target[key];
|
||||
} else if (isFunction(target[key])) {
|
||||
return target[key].bind(receiver);
|
||||
}
|
||||
return target[key];
|
||||
},
|
||||
set(target, key, value, receiver) {
|
||||
if (`${key}Set` in target && isFunction(target[`${key}Set`]) && target[`${key}Set`].length < 2) {
|
||||
target[`${key}Set`].call(receiver, value);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(`No setter for "${key}".`, target);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const gridHandler = {
|
||||
get(target, key, receiver) {
|
||||
if (key === 'isProxy') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isRef(target[key])) {
|
||||
return target[key].value;
|
||||
} else if (target[key] && (target[key].isProxy || target[key] instanceof Decimal)) {
|
||||
return target[key];
|
||||
} else if (isPlainObject(target[key]) || Array.isArray(target[key])) {
|
||||
console.warn("Creating proxy outside `createProxy`. This may cause issues when calling proxied functions.",
|
||||
target, key);
|
||||
target[key] = new Proxy(target[key], mainHandler);
|
||||
return target[key];
|
||||
} else if (isFunction(target[key])) {
|
||||
return target[key].bind(receiver);
|
||||
}
|
||||
if (typeof key !== 'symbol' && !isNaN(key)) {
|
||||
target[key] = new Proxy(target, getCellHandler(key));
|
||||
}
|
||||
return target[key];
|
||||
},
|
||||
set(target, key, value, receiver) {
|
||||
if (`${key}Set` in target && isFunction(target[`${key}Set`]) && target[`${key}Set`].length < 2) {
|
||||
target[`${key}Set`].call(receiver, value);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(`No setter for "${key}".`, target);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function getCellHandler(id) {
|
||||
return {
|
||||
get(target, key, receiver) {
|
||||
if (key === 'isProxy') {
|
||||
return true;
|
||||
}
|
||||
|
||||
let prop = target[key];
|
||||
|
||||
if (isFunction(prop) && prop.forceCached === false) {
|
||||
return () => prop.call(receiver, id, target.getData(id));
|
||||
}
|
||||
if (prop != undefined || key.slice == undefined) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
key = key.slice(0, 1).toUpperCase() + key.slice(1);
|
||||
prop = target[`get${key}`];
|
||||
if (isFunction(prop)) {
|
||||
return prop.call(receiver, id, target.getData(id));
|
||||
} else if (prop != undefined) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
prop = target[`on${key}`];
|
||||
if (isFunction(prop)) {
|
||||
return () => prop.call(receiver, id, target.getData(id));
|
||||
} else if (prop != undefined) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
return target[key];
|
||||
},
|
||||
set(target, key, value, receiver) {
|
||||
if (`${key}Set` in target && isFunction(target[`${key}Set`]) && target[`${key}Set`].length < 3) {
|
||||
target[`${key}Set`].call(receiver, id, value);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(`No setter for "${key}".`, target);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import modInfo from '../data/modInfo';
|
||||
import { getStartingData, getInitialLayers, fixOldSave } from '../data/mod';
|
||||
import { player } from '../store/proxies';
|
||||
import player from '../game/player';
|
||||
import Decimal from './bignum';
|
||||
|
||||
export const NOT_IMPORTING = false;
|
||||
|
@ -32,9 +32,8 @@ export function getInitialStore(playerData = {}) {
|
|||
|
||||
// Values that don't get loaded/saved
|
||||
hasNaN: false,
|
||||
NaNProperty: "",
|
||||
NaNPath: [],
|
||||
NaNReceiver: null,
|
||||
NaNPrevious: null,
|
||||
importing: NOT_IMPORTING,
|
||||
saveToImport: "",
|
||||
saveToExport: ""
|
||||
|
@ -43,7 +42,7 @@ export function getInitialStore(playerData = {}) {
|
|||
|
||||
export function save() {
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
let { hasNaN, NaNProperty, NaNReceiver, NaNPrevious, importing, saveToImport, saveToExport, ...playerData } = player;
|
||||
let { hasNaN, NaNPath, NaNReceiver, importing, saveToImport, saveToExport, ...playerData } = player.__state;
|
||||
player.saveToExport = btoa(unescape(encodeURIComponent(JSON.stringify(playerData))));
|
||||
|
||||
localStorage.setItem(player.id, player.saveToExport);
|
||||
|
@ -67,6 +66,7 @@ export async function load() {
|
|||
await loadSave(newSave());
|
||||
return;
|
||||
}
|
||||
playerData.id = modData.active;
|
||||
await loadSave(playerData);
|
||||
} catch (e) {
|
||||
await loadSave(newSave());
|
||||
|
@ -99,7 +99,7 @@ export function getUniqueID() {
|
|||
}
|
||||
|
||||
export async function loadSave(playerData) {
|
||||
const { layers, removeLayer, addLayer } = await import('../store/layers');
|
||||
const { layers, removeLayer, addLayer } = await import('../game/layers');
|
||||
|
||||
for (let layer in layers) {
|
||||
removeLayer(layer);
|
||||
|
@ -119,7 +119,7 @@ export async function loadSave(playerData) {
|
|||
|
||||
Object.assign(player, playerData);
|
||||
for (let prop in player) {
|
||||
if (!(prop in playerData) && !(prop in layers)) {
|
||||
if (!(prop in playerData) && !(prop in layers) && prop !== '__state' && prop !== '__path') {
|
||||
delete player[prop];
|
||||
}
|
||||
}
|
||||
|
@ -157,3 +157,4 @@ window.onbeforeunload = () => {
|
|||
save();
|
||||
}
|
||||
};
|
||||
window.save = save;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { player } from '../store/proxies';
|
||||
import { layers } from '../store/layers';
|
||||
import player from '../game/player';
|
||||
import { layers } from '../game/layers';
|
||||
import { hasWon, pointGain } from '../data/mod';
|
||||
import { hasUpgrade, hasMilestone, hasAchievement, hasChallenge, maxedChallenge, challengeCompletions, inChallenge, getBuyableAmount, setBuyableAmount, getClickableState, setClickableState, getGridData, setGridData, upgradeEffect, challengeEffect, buyableEffect, clickableEffect, achievementEffect, gridEffect } from './features';
|
||||
import Decimal, * as numberUtils from './bignum';
|
||||
|
||||
|
@ -9,12 +10,8 @@ export function setVue(vm) {
|
|||
}
|
||||
|
||||
// Pass in various data that the template could potentially use
|
||||
const computed = {
|
||||
player() { return player; },
|
||||
layers() { return layers; }
|
||||
};
|
||||
const data = function() {
|
||||
return { Decimal, ...numberUtils };
|
||||
return { Decimal, player, layers, hasWon, pointGain, ...numberUtils };
|
||||
}
|
||||
export function coerceComponent(component, defaultWrapper = 'span') {
|
||||
if (typeof component === 'number') {
|
||||
|
@ -22,12 +19,12 @@ export function coerceComponent(component, defaultWrapper = 'span') {
|
|||
}
|
||||
if (typeof component === 'string') {
|
||||
component = component.trim();
|
||||
if (!(component in vue.$options.components)) {
|
||||
if (!(component in vue._context.components)) {
|
||||
if (component.charAt(0) !== '<') {
|
||||
component = `<${defaultWrapper}>${component}</${defaultWrapper}>`;
|
||||
}
|
||||
|
||||
return { template: component, computed, data, inject: [ 'tab' ], methods: { hasUpgrade, hasMilestone, hasAchievement, hasChallenge, maxedChallenge, challengeCompletions, inChallenge, getBuyableAmount, setBuyableAmount, getClickableState, setClickableState, getGridData, setGridData, upgradeEffect, challengeEffect, buyableEffect, clickableEffect, achievementEffect, gridEffect } };
|
||||
return { template: component, data, inject: [ 'tab' ], methods: { hasUpgrade, hasMilestone, hasAchievement, hasChallenge, maxedChallenge, challengeCompletions, inChallenge, getBuyableAmount, setBuyableAmount, getClickableState, setClickableState, getGridData, setGridData, upgradeEffect, challengeEffect, buyableEffect, clickableEffect, achievementEffect, gridEffect } };
|
||||
}
|
||||
}
|
||||
return component;
|
||||
|
@ -46,6 +43,13 @@ export function getFiltered(objects, filter = null) {
|
|||
return objects;
|
||||
}
|
||||
|
||||
export function mapState(properties = []) {
|
||||
return properties.reduce((acc, curr) => {
|
||||
acc[curr] = () => player[curr];
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
export const UP = 'UP';
|
||||
export const DOWN = 'DOWN';
|
||||
export const LEFT = 'LEFT';
|
||||
|
|
Loading…
Reference in a new issue