Implemented resetting layers and associated features/fixes
This commit is contained in:
parent
232e628daa
commit
95cc29664b
20 changed files with 451 additions and 252 deletions
|
@ -20,7 +20,7 @@
|
|||
<button @click="buyable.sellOne" v-if="buyable.sellOne !== undefined && buyable.canSellOne !== false"
|
||||
:class="{ 'buyable-button': true, can: buyable.unlocked, locked: !buyable.unlocked, feature: true }"
|
||||
:style="{ 'background-color': buyable.canSellOne ? layerColor : '' }">
|
||||
Sell All
|
||||
Sell One
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
<template>
|
||||
<div v-if="shown" :style="style" :class="{ challenge: true, [challengeClass]: true }">
|
||||
<div v-if="shown" :style="style"
|
||||
:class="{
|
||||
feature: true,
|
||||
challenge: true,
|
||||
resetNotify: challenge.active,
|
||||
notify: challenge.active && challenge.canComplete,
|
||||
done: challenge.completed,
|
||||
maxed: challenge.maxed
|
||||
}">
|
||||
<div v-if="title"><component :is="title" /></div>
|
||||
<button :class="{ [layer || tab.layer]: true, longUpg: true, can: true }" :style="{ backgroundColor: buttonColor }"
|
||||
@click="toggle">
|
||||
<button :style="{ backgroundColor: challenge.maxed ? null : buttonColor }" @click="toggle">
|
||||
{{ buttonText }}
|
||||
</button>
|
||||
<component v-if="fullDisplay" :is="fullDisplay" />
|
||||
|
@ -32,15 +39,6 @@ export default {
|
|||
shown() {
|
||||
return this.challenge.unlocked && !(player.hideChallenges && this.challenge.maxes);
|
||||
},
|
||||
challengeClass() {
|
||||
if (this.challenge.canComplete) {
|
||||
return "canComplete";
|
||||
}
|
||||
if (this.challenge.completed) {
|
||||
return "done";
|
||||
}
|
||||
return "locked";
|
||||
},
|
||||
style() {
|
||||
return [
|
||||
layers[this.layer || this.tab.layer].componentStyles?.challenge,
|
||||
|
@ -48,8 +46,11 @@ export default {
|
|||
];
|
||||
},
|
||||
title() {
|
||||
if (this.challenge.title) {
|
||||
return coerceComponent(this.challenge.titleDisplay, 'h3');
|
||||
if (this.challenge.titleDisplay) {
|
||||
return coerceComponent(this.challenge.titleDisplay, 'div');
|
||||
}
|
||||
if (this.challenge.name) {
|
||||
return coerceComponent(this.challenge.name, 'h3');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
@ -82,6 +83,30 @@ export default {
|
|||
|
||||
<style scoped>
|
||||
.challenge {
|
||||
margin: var(--feature-margin);
|
||||
background-color: var(--locked);
|
||||
width: 250px;
|
||||
min-height: 250px;
|
||||
color: black;
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.challenge.done {
|
||||
background-color: var(--bought);
|
||||
}
|
||||
|
||||
.challenge button {
|
||||
min-height: 50px;
|
||||
width: 120px;
|
||||
border-radius: var(--border-radius);
|
||||
cursor: pointer;
|
||||
box-shadow: none !important;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.challenge.maxed button {
|
||||
cursor: unset;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -32,14 +32,11 @@ export default {
|
|||
return coerceComponent(`format(${this.goal}) ${this.currencyDisplayName || 'points'}`);
|
||||
},
|
||||
rewardDescription() {
|
||||
return coerceComponent(this.challenge.goalDescription);
|
||||
return coerceComponent(this.challenge.rewardDescription);
|
||||
},
|
||||
rewardDisplay() {
|
||||
if (this.challenge.rewardDisplay) {
|
||||
return coerceComponent(this.challenge.rewardDisplay);
|
||||
}
|
||||
if (this.challenge.rewardEffect) {
|
||||
return coerceComponent(`Currently: ${this.challenge.rewardEffect}`);
|
||||
return coerceComponent(`Currently: ${this.challenge.rewardDisplay}`);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
|
|
@ -58,7 +58,13 @@ export default {
|
|||
|
||||
return `${prefix} ${baseAmount} / ${nextAt} ${baseResource}`;
|
||||
} else {
|
||||
return `Next at ${formatWhole(layers[this.layer || this.tab.layer].baseAmount)} ${layers[this.layer || this.tab.layer].baseResource}`;
|
||||
let amount;
|
||||
if (layers[this.layer || this.tab.layer].roundUpCost) {
|
||||
amount = formatWhole(layers[this.layer || this.tab.layer].nextAt);
|
||||
} else {
|
||||
amount = format(layers[this.layer || this.tab.layer].nextAt);
|
||||
}
|
||||
return `Next at ${amount} ${layers[this.layer || this.tab.layer].baseResource}`;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div v-if="milestone.shown" :style="style" :class="{ feature: true, milestone: !milestone.earned, milestoneDone: milestone.earned }">
|
||||
<div v-if="milestone.shown" :style="style" :class="{ feature: true, milestone: true, done: milestone.earned }">
|
||||
<div v-if="requirementDisplay"><component :is="requirementDisplay" /></div>
|
||||
<div v-if="effectDisplay"><component :is="effectDisplay" /></div>
|
||||
<component v-if="optionsDisplay" :is="optionsDisplay" />
|
||||
|
@ -42,7 +42,7 @@ export default {
|
|||
return null;
|
||||
},
|
||||
optionsDisplay() {
|
||||
if (this.milestone.optionsDisplay) {
|
||||
if (this.milestone.optionsDisplay && this.milestone.earned) {
|
||||
return coerceComponent(this.milestone.optionsDisplay, 'div');
|
||||
}
|
||||
return null;
|
||||
|
@ -62,5 +62,11 @@ export default {
|
|||
border-width: 4px;
|
||||
border-radius: 5px;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.milestone.done {
|
||||
background-color: var(--bought);
|
||||
cursor: default;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
import { layers } from '../../store/layers';
|
||||
import { resetLayer } from '../../util/layers';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
import './features.css'
|
||||
|
||||
export default {
|
||||
name: 'prestige-button',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.feature,
|
||||
.feature button {
|
||||
position: relative;
|
||||
padding-top: 5px;
|
||||
padding: 5px;
|
||||
border-radius: var(--border-radius);
|
||||
border: 2px solid rgba(0, 0, 0, 0.125);
|
||||
margin: var(--feature-margin);
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<template>
|
||||
<div class="field">
|
||||
<span class="field-title" v-if="title">{{ title }}</span>
|
||||
<input type="range" :value="value" @input="e => $emit('change', e.target.value)" :min="min" :max="max" />
|
||||
<tooltip :text="`${value}`">
|
||||
<input type="range" :value="value" @input="e => $emit('change', parseInt(e.target.value))" :min="min" :max="max" />
|
||||
</tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -9,7 +11,7 @@
|
|||
import './fields.css';
|
||||
|
||||
export default {
|
||||
name: 'TextField',
|
||||
name: 'Slider',
|
||||
props: {
|
||||
title: String,
|
||||
value: Number,
|
||||
|
@ -20,4 +22,11 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
input {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.value {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<default-layer-tab v-else />
|
||||
</branches>
|
||||
</div>
|
||||
<button v-if="!disableMinimize" class="minimize" @click="toggleMinimized">▼</button>
|
||||
<button v-if="minimizable" class="minimize" @click="toggleMinimized">▼</button>
|
||||
</div>
|
||||
</LayerProvider>
|
||||
</template>
|
||||
|
@ -32,7 +32,7 @@ export default {
|
|||
layer: String,
|
||||
index: Number,
|
||||
forceFirstTab: Boolean,
|
||||
disableMinimize: Boolean,
|
||||
minimizable: Boolean,
|
||||
tab: Function
|
||||
},
|
||||
data() {
|
||||
|
@ -40,7 +40,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
minimized() {
|
||||
return !this.disableMinimize && player.minimized[this.layer];
|
||||
return this.minimizable && player.minimized[this.layer];
|
||||
},
|
||||
name() {
|
||||
return layers[this.layer].name;
|
||||
|
@ -91,6 +91,9 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
minimized(newValue) {
|
||||
if (this.tab == undefined) {
|
||||
return;
|
||||
}
|
||||
const tab = this.tab();
|
||||
if (tab != undefined) {
|
||||
if (newValue) {
|
||||
|
@ -108,6 +111,9 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.tab == undefined) {
|
||||
return;
|
||||
}
|
||||
const tab = this.tab();
|
||||
if (tab != undefined) {
|
||||
if (this.minimized) {
|
||||
|
@ -152,7 +158,7 @@ export default {
|
|||
}
|
||||
|
||||
.layer-tab:not(.minimized) {
|
||||
padding-top: 50px;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
min-height: 100%;
|
||||
flex-grow: 1;
|
||||
|
@ -160,6 +166,10 @@ export default {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.inner-tab > .layer-container > .layer-tab:not(.minimized) {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.layer-tab.minimized {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -207,6 +217,11 @@ export default {
|
|||
padding-left: 14px;
|
||||
}
|
||||
|
||||
.subtabs.floating {
|
||||
justify-content: center;
|
||||
margin-top: -25px;
|
||||
}
|
||||
|
||||
.modal-body .layer-tab {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
<template>
|
||||
<div v-if="microtabs" class="microtabs">
|
||||
<LayerProvider :layer="layer || tab.layer" :index="tab.index">
|
||||
<component :is="display" />
|
||||
<div v-if="microtabs" class="tabs" :class="{ floating }">
|
||||
<tab-button v-for="(microtab, id) in microtabs" @selectTab="selectMicrotab(id)" :key="id"
|
||||
:activeTab="id === activeMicrotab.id" :options="microtab" :text="id" />
|
||||
</div>
|
||||
<layer-tab v-if="embed" :layer="embed" />
|
||||
<component v-else :is="display" />
|
||||
</LayerProvider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { layers } from '../../store/layers';
|
||||
import { player } from '../../store/proxies';
|
||||
import { coerceComponent } from '../../util/vue';
|
||||
import themes from '../../data/themes';
|
||||
|
||||
export default {
|
||||
name: 'microtab',
|
||||
|
@ -17,13 +26,50 @@ export default {
|
|||
id: String
|
||||
},
|
||||
computed: {
|
||||
floating() {
|
||||
return themes[player.theme].floatingTabs;
|
||||
},
|
||||
tabFamily() {
|
||||
return layers[this.layer || this.tab.layer].microtabs[this.family];
|
||||
},
|
||||
microtabs() {
|
||||
return Object.keys(this.tabFamily)
|
||||
.filter(microtab => microtab !== 'activeMicrotab' && this.tabFamily[microtab].unlocked !== false)
|
||||
.reduce((acc, curr) => {
|
||||
acc[curr] = this.tabFamily[curr];
|
||||
return acc;
|
||||
}, {});
|
||||
},
|
||||
activeMicrotab() {
|
||||
return this.id != undefined ? this.tabFamily[this.id] : this.tabFamily.activeMicrotab;
|
||||
},
|
||||
embed() {
|
||||
return this.activeMicrotab.embedLayer;
|
||||
},
|
||||
display() {
|
||||
const family = layers[this.layer || this.tab.layer].microtabs[this.family];
|
||||
return coerceComponent((this.id !== undefined ? family[this.id] : family.activeMicrotab).display);
|
||||
return coerceComponent(this.activeMicrotab.display);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectMicrotab(tab) {
|
||||
player.subtabs[this.layer || this.tab.layer][this.family] = tab;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.microtabs {
|
||||
margin: var(--feature-margin) -11px;
|
||||
position: relative;
|
||||
border: solid 4px var(--separator);
|
||||
}
|
||||
|
||||
.tabs:not(.floating) {
|
||||
text-align: left;
|
||||
border-bottom: inherit;
|
||||
border-width: 4px;
|
||||
box-sizing: border-box;
|
||||
height: 50px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<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"
|
||||
<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>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</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" :disableMinimize="true" />
|
||||
<layer-tab slot="body" v-if="modal" :layer="modal" :index="tab.index" :forceFirstTab="true" />
|
||||
</modal>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -73,7 +73,7 @@ export default {
|
|||
done() {return player[this.layer].best.gte(4)},
|
||||
effectDisplay: "You can toggle beep and boop (which do nothing)",
|
||||
optionsDisplay: `
|
||||
<div>
|
||||
<div style="display: flex; justify-content: center">
|
||||
<Toggle :value="player.c.beep" @change="value => player.c.beep = value" />
|
||||
<Toggle :value="player.f.boop" @change="value => player.f.boop = value" />
|
||||
</div>
|
||||
|
@ -160,21 +160,23 @@ export default {
|
|||
},
|
||||
buyables: {
|
||||
showRespec: true,
|
||||
respec() { // Optional, reset things and give back your currency. Having this function makes a respec button appear
|
||||
reset() { // Optional, reset things and give back your currency. Having this function makes a respec button appear
|
||||
player[this.layer].points = player[this.layer].points.add(player[this.layer].spentOnBuyables) // A built-in thing to keep track of this but only keeps a single value
|
||||
this.reset;
|
||||
this.reset();
|
||||
resetLayer(this.layer, true) // Force a reset
|
||||
},
|
||||
respecText: "Respec Thingies", // Text on Respec button, optional
|
||||
respecMessage: "Are you sure? Respeccing these doesn't accomplish much.",
|
||||
11: {
|
||||
title: "Exhancers", // Optional, displayed at the top in a larger font
|
||||
cost(x) { // cost for buying xth buyable, can be an object if there are multiple currencies
|
||||
cost() { // cost for buying xth buyable, can be an object if there are multiple currencies
|
||||
let x = this.amount;
|
||||
if (x.gte(25)) x = x.pow(2).div(25)
|
||||
let cost = Decimal.pow(2, x.pow(1.5))
|
||||
return cost.floor()
|
||||
},
|
||||
effect(x) { // Effects of owning x of the items, x is a decimal
|
||||
effect() { // Effects of owning x of the items, x is a decimal
|
||||
let x = this.amount;
|
||||
let eff = {}
|
||||
if (x.gte(0)) eff.first = Decimal.pow(25, x.pow(1.1))
|
||||
else eff.first = Decimal.pow(1/25, x.times(-1).pow(1.1))
|
||||
|
@ -212,7 +214,6 @@ export default {
|
|||
doReset(resettingLayer){ // Triggers when this layer is being reset, along with the layer doing the resetting. Not triggered by lower layers resetting, but is by layers on the same row.
|
||||
if(layers[resettingLayer].row > this.row) resetLayerData(this.layer, ["points"]) // This is actually the default behavior
|
||||
},
|
||||
layerShown() {return true}, // Condition for when layer appears on the tree
|
||||
automate() {
|
||||
}, // Do any automation inherent to this layer if appropriate
|
||||
resetsNothing() {return false},
|
||||
|
@ -229,15 +230,13 @@ export default {
|
|||
microtabs: {
|
||||
stuff: {
|
||||
first: {
|
||||
content: ["upgrades", ["display-text", function() {return "confirmed"}]]
|
||||
display: `<div v-frag>
|
||||
<upgrades />
|
||||
<div>confirmed</div>
|
||||
</div>`
|
||||
},
|
||||
second: {
|
||||
embedLayer: "f",
|
||||
|
||||
content: [["upgrade", 11],
|
||||
["row", [["upgrade", 11], "blank", "blank", ["upgrade", 11],]],
|
||||
|
||||
["display-text", function() {return "double confirmed"}]]
|
||||
embedLayer: "f"
|
||||
},
|
||||
},
|
||||
otherStuff: {
|
||||
|
@ -377,7 +376,7 @@ export default {
|
|||
<div v-frag>
|
||||
<h1> C O N F I R M E D </h1>
|
||||
<spacer />
|
||||
<microtab family="stuff" style="width: 600px; height: 350px; background-color: brown; border-style: solid" />
|
||||
<microtab family="stuff" style="width: 660px; height: 370px; background-color: 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>
|
||||
|
|
|
@ -33,7 +33,6 @@ export default {
|
|||
//directMult() {return new Decimal(player.c.otherThingy)},
|
||||
|
||||
row: 1,
|
||||
layerShown() {return true},
|
||||
branches: [{ target: "c", 'stroke-width': '25px', 'stroke': 'blue', style: 'filter: blur(5px)' }], // When this layer appears, a branch will appear from this layer to any layers here. Each entry can be a pair consisting of a layer id and a color.
|
||||
|
||||
tooltipLocked() { // Optional, tooltip displays when the layer is locked
|
||||
|
|
|
@ -13,7 +13,7 @@ const g = {
|
|||
symbol: "TH",
|
||||
branches: ["c"],
|
||||
color: '#6d3678',
|
||||
layerShown: true,
|
||||
shown: true,
|
||||
canClick() {return player.points.gte(10)},
|
||||
tooltip: "Thanos your points",
|
||||
onClick() {
|
||||
|
@ -23,8 +23,7 @@ const g = {
|
|||
};
|
||||
const h = {
|
||||
id: "h",
|
||||
branches: ["g", { target: 'flatBoi', featureType: 'bar', endOffset: { x: () => -50 + 100 * layers.c.bars.flatBoi.progress.toNumber() } }],
|
||||
layerShown: true,
|
||||
branches: ["g", () => ({ target: 'flatBoi', featureType: 'bar', endOffset: { x: -50 + 100 * layers.c.bars.flatBoi.progress.toNumber() } })],
|
||||
tooltip() {return "Restore your points to " + player.c.otherThingy},
|
||||
row: "side",
|
||||
canClick() {return player.points.lt(player.c.otherThingy)},
|
||||
|
@ -49,6 +48,7 @@ const main = {
|
|||
<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>
|
||||
<spacer />
|
||||
<tree :append="true" />
|
||||
</div>`,
|
||||
name: "Tree"
|
||||
|
|
|
@ -26,6 +26,10 @@ h1, h2, h3, b, input {
|
|||
display: inline;
|
||||
}
|
||||
|
||||
button {
|
||||
color: black;
|
||||
}
|
||||
|
||||
a,
|
||||
.button,
|
||||
.link {
|
||||
|
|
|
@ -17,11 +17,13 @@ function updateOOMPS(diff) {
|
|||
if (player.points != undefined) {
|
||||
player.oompsMag = 0;
|
||||
if (player.points.lte(new Decimal(1e100))) {
|
||||
player.lastPoints = player.points;
|
||||
return;
|
||||
}
|
||||
|
||||
let curr = new Decimal(player.points);
|
||||
let curr = player.points;
|
||||
let prev = player.lastPoints || new Decimal(0);
|
||||
player.lastPoints = curr;
|
||||
if (curr.gt(prev)) {
|
||||
if (curr.gte("10^^8")) {
|
||||
curr = curr.slog(1e10);
|
||||
|
|
|
@ -2,7 +2,7 @@ import { isFunction, isPlainObject } from '../util/common';
|
|||
import { createProxy, createGridProxy, player } from './proxies';
|
||||
import Decimal from '../util/bignum';
|
||||
import store from './index';
|
||||
import { resetLayer, noCache, getStartingBuyables, getStartingClickables, getStartingChallenges } from '../util/layers';
|
||||
import { noCache, getStartingBuyables, getStartingClickables, getStartingChallenges, defaultLayerProperties } from '../util/layers';
|
||||
|
||||
export const layers = {};
|
||||
export const hotkeys = [];
|
||||
|
@ -28,19 +28,15 @@ export function addLayer(layer) {
|
|||
// Set default property values
|
||||
layer = Object.assign({}, defaultLayerProperties, layer);
|
||||
layer.layer = layer.id;
|
||||
if (layer.shown == undefined) {
|
||||
layer.shown = true;
|
||||
}
|
||||
if (layer.onClick != undefined) {
|
||||
layer.onClick.forceCached = false;
|
||||
}
|
||||
if (layer.update != undefined) {
|
||||
layer.update.forceCached = false;
|
||||
}
|
||||
|
||||
const getters = {};
|
||||
|
||||
// Process each feature
|
||||
for (let property of uncachedProperties) {
|
||||
if (layer[property]) {
|
||||
layer[property].forceCached = false;
|
||||
}
|
||||
}
|
||||
for (let property of gridProperties) {
|
||||
if (layer[property]) {
|
||||
setRowCol(layer[property]);
|
||||
|
@ -144,8 +140,17 @@ export function addLayer(layer) {
|
|||
}
|
||||
for (let id in layer.challenges) {
|
||||
if (isPlainObject(layer.challenges[id])) {
|
||||
if (layer.challenges[id].onComplete != undefined) {
|
||||
layer.challenges[id].onComplete.forceCached = false;
|
||||
}
|
||||
if (layer.challenges[id].onEnter != undefined) {
|
||||
layer.challenges[id].onEnter.forceCached = false;
|
||||
}
|
||||
if (layer.challenges[id].onExit != undefined) {
|
||||
layer.challenges[id].onExit.forceCached = false;
|
||||
}
|
||||
layer.challenges[id].completed = function() {
|
||||
return !layer.deactivated && !!player[layer.id].challenges[id];
|
||||
return !layer.deactivated && player[layer.id].challenges[id]?.gt(0);
|
||||
}
|
||||
layer.challenges[id].completions = function() {
|
||||
return player[layer.id].challenges[id];
|
||||
|
@ -185,7 +190,7 @@ export function addLayer(layer) {
|
|||
if (layer.challenges[id].completionLimit == undefined) {
|
||||
layer.challenges[id].completionLimit = new Decimal(1);
|
||||
}
|
||||
layer.challenges[id].toggle = function() {
|
||||
layer.challenges[id].toggle = noCache(function() {
|
||||
let exiting = player[layer.id].activeChallenge === id;
|
||||
if (exiting) {
|
||||
if (this.canComplete && !this.maxed) {
|
||||
|
@ -199,18 +204,21 @@ export function addLayer(layer) {
|
|||
}
|
||||
player[layer.id].activeChallenge = null;
|
||||
this.onExit?.();
|
||||
resetLayer(layer.id, true);
|
||||
layer.reset(true);
|
||||
} else if (!exiting && this.canStart) {
|
||||
resetLayer(layer.id, true);
|
||||
layer.reset(true);
|
||||
player[layer.id].activeChallenge = id;
|
||||
this.onEnter?.();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (layer.challenges[id].canStart == undefined) {
|
||||
layer.challenges[id].canStart = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
layer.activeChallenge = function() {
|
||||
return Object.values(this.challenges).find(challenge => challenge.active);
|
||||
}
|
||||
}
|
||||
if (layer.buyables) {
|
||||
if (player[layer.id].buyables == undefined) {
|
||||
|
@ -220,6 +228,8 @@ export function addLayer(layer) {
|
|||
layer.buyables.reset = noCache(function() {
|
||||
player[this.layer].buyables = getStartingBuyables(layer);
|
||||
});
|
||||
} else {
|
||||
layer.buyables.reset.forceCached = false;
|
||||
}
|
||||
for (let id in layer.buyables) {
|
||||
if (isPlainObject(layer.buyables[id])) {
|
||||
|
@ -366,11 +376,18 @@ export function addLayer(layer) {
|
|||
}
|
||||
}
|
||||
layer.microtabs[family].activeMicrotab = function() {
|
||||
if (this[player.subtabs[layer.id][family]]?.unlocked !== false) {
|
||||
if (this[player.subtabs[layer.id][family]] && this[player.subtabs[layer.id][family]].unlocked !== false) {
|
||||
return this[player.subtabs[layer.id][family]];
|
||||
}
|
||||
// Default to first unlocked tab
|
||||
return Object.values(this).find(microtab => microtab.unlocked !== false);
|
||||
return this[Object.keys(this).find(microtab => microtab !== 'activeMicrotab' && this[microtab].unlocked !== false)];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (layer.hotkeys) {
|
||||
for (let id in layer.hotkeys) {
|
||||
if (layer.hotkeys[id].onPress) {
|
||||
layer.hotkeys[id].onPress.forceCached = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -409,180 +426,7 @@ export function reloadLayer(layer) {
|
|||
addLayer(layer);
|
||||
}
|
||||
|
||||
export const defaultLayerProperties = {
|
||||
type: "none",
|
||||
layerShown: true,
|
||||
glowColor: "red",
|
||||
minWidth: 640,
|
||||
displayRow() {
|
||||
return this.row;
|
||||
},
|
||||
symbol() {
|
||||
return this.id;
|
||||
},
|
||||
unlocked() {
|
||||
if (player[this.id].unlocked) {
|
||||
return true;
|
||||
}
|
||||
if (this.type !== "none" && this.canReset && this.layerShown) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
trueGlowColor() {
|
||||
if (this.subtabs) {
|
||||
for (let subtab of Object.values(this.subtabs)) {
|
||||
if (subtab.notify) {
|
||||
return subtab.glowColor || "red";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.microtabs) {
|
||||
for (let microtab of Object.values(this.microtabs)) {
|
||||
if (microtab.notify) {
|
||||
return microtab.glowColor || "red";
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.glowColor || "red";
|
||||
},
|
||||
resetGain() {
|
||||
if (this.type === "none" || this.type === "custom") {
|
||||
return new Decimal(0);
|
||||
}
|
||||
if (this.gainExp?.eq(0)) {
|
||||
return new Decimal(0);
|
||||
}
|
||||
if (this.baseAmount.lt(this.requires)) {
|
||||
return new Decimal(0);
|
||||
}
|
||||
if (this.type === "static") {
|
||||
if (!this.canBuyMax) {
|
||||
return new Decimal(1);
|
||||
}
|
||||
let gain = this.baseAmount.div(this.requires).div(this.gainMult || 1).max(1).log(this.base)
|
||||
.times(this.gainExp || 1).pow(Decimal.pow(this.exponent || 1, -1));
|
||||
gain = gain.times(this.directMult || 1);
|
||||
return gain.floor().sub(player[this.layer].points).add(1).max(1);
|
||||
}
|
||||
if (this.type === "normal") {
|
||||
let gain = this.baseAmount.div(this.requires).pow(this.exponent || 1).times(this.gainMult || 1)
|
||||
.pow(this.gainExp || 1);
|
||||
if (this.softcap && gain.gte(this.softcap)) {
|
||||
gain = gain.pow(this.softcapPower).times(this.softcap.pow(Decimal.sub(1, this.softcapPower)));
|
||||
}
|
||||
gain = gain.times(this.directMult || 1);
|
||||
return gain.floor().max(0);
|
||||
}
|
||||
// Unknown prestige type
|
||||
return new Decimal(0);
|
||||
},
|
||||
nextAt() {
|
||||
if (this.type === "none" || this.type === "custom") {
|
||||
return new Decimal(Infinity);
|
||||
}
|
||||
if (this.gainMult?.lte(0) || this.gainExp?.lte(0)) {
|
||||
return new Decimal(Infinity);
|
||||
}
|
||||
if (this.type === "static") {
|
||||
const amount = player[this.layer].points.div(this.directMult || 1);
|
||||
const extraCost = Decimal.pow(this.base, amount.pow(this.exponent || 1).div(this.gainExp || 1))
|
||||
.times(this.gainMult || 1);
|
||||
let cost = extraCost.times(this.requires).max(this.requires);
|
||||
if (this.roundUpCost) {
|
||||
cost = cost.ceil();
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
if (this.type === "normal") {
|
||||
let next = this.resetGain.div(this.directMult || 1);
|
||||
if (this.softcap && next.gte(this.softcap)) {
|
||||
next = next.div(this.softcap.pow(Decimal.sub(1, this.softcapPower)))
|
||||
.pow(Decimal.div(1, this.softcapPower));
|
||||
}
|
||||
next = next.root(this.gainExp || 1).div(this.gainMult || 1).root(this.exponent || 1)
|
||||
.times(this.requires).max(this.requires);
|
||||
if (this.roundUpCost) {
|
||||
next = next.ceil();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
// Unknown prestige type
|
||||
return new Decimal(0);
|
||||
},
|
||||
nextAtMax() {
|
||||
if (!this.canBuyMax || this.type !== "static") {
|
||||
return this.nextAt;
|
||||
}
|
||||
const amount = player[this.layer].points.plus(this.resetGain).div(this.directMult || 1);
|
||||
const extraCost = Decimal.pow(this.base, amount.pow(this.exponent || 1).div(this.gainExp || 1))
|
||||
.times(this.gainMult || 1);
|
||||
let cost = extraCost.times(this.requires).max(this.requires);
|
||||
if (this.roundUpCost) {
|
||||
cost = cost.ceil();
|
||||
}
|
||||
return cost;
|
||||
},
|
||||
canReset() {
|
||||
if (this.type === "normal") {
|
||||
return this.baseAmount.gte(this.requires);
|
||||
}
|
||||
if (this.type === "static") {
|
||||
return this.baseAmount.gte(this.nextAt);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
notify() {
|
||||
if (this.upgrades) {
|
||||
if (Object.values(this.upgrades).some(upgrade => upgrade.canAfford && !upgrade.bought && upgrade.unlocked)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (player[this.layer].activeChallenge && this.challenges[player[this.layer].activeChallenge].canComplete) {
|
||||
return true;
|
||||
}
|
||||
if (this.subtabs) {
|
||||
if (Object.values(this.subtabs).some(subtab => subtab.notify)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.microtabs) {
|
||||
if (Object.values(this.microtabs).some(subtab => subtab.notify)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
resetNotify() {
|
||||
if (this.subtabs) {
|
||||
if (Object.values(this.subtabs).some(subtab => subtab.prestigeNotify)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.microtabs) {
|
||||
if (Object.values(this.microtabs).some(microtab => microtab.prestigeNotify)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.autoPrestige || this.passiveGeneration) {
|
||||
return false;
|
||||
}
|
||||
if (this.type === "static") {
|
||||
return this.canReset;
|
||||
}
|
||||
if (this.type === "normal") {
|
||||
return this.canReset && this.resetGain.gte(player[this.layer].points.div(10));
|
||||
}
|
||||
return false;
|
||||
},
|
||||
reset(force = false) {
|
||||
console.warn("Not yet implemented!", force);
|
||||
},
|
||||
resetData(keep = []) {
|
||||
console.warn("Not yet implemented!", keep);
|
||||
}
|
||||
};
|
||||
const uncachedProperties = [ 'startData', 'onClick', 'update', 'reset', 'hardReset' ];
|
||||
const gridProperties = [ 'upgrades', 'achievements', 'challenges', 'buyables', 'clickables' ];
|
||||
const featureProperties = [ 'upgrades', 'achievements', 'challenges', 'buyables', 'clickables', 'milestones', 'bars',
|
||||
'infoboxes', 'grids', 'hotkeys', 'subtabs' ];
|
||||
|
|
|
@ -20,7 +20,7 @@ const playerHandler = {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (typeof target[key] == "undefined") {
|
||||
if (target[key] == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ function getHandler(prefix) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (typeof target[key] == "undefined") {
|
||||
if (target[key] == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import Decimal from './bignum';
|
||||
import { isPlainObject } from './common';
|
||||
import { layers } from '../store/layers';
|
||||
import { player } from '../store/proxies';
|
||||
|
||||
export function resetLayer(layer, force = false) {
|
||||
layers[layer].reset(force);
|
||||
}
|
||||
|
||||
export function resetLayerData(layer, keep = []) {
|
||||
layers[layer].resetData(keep);
|
||||
export function hardReset(layer, keep = []) {
|
||||
layers[layer].hardReset(keep);
|
||||
}
|
||||
|
||||
export function cache(func) {
|
||||
|
@ -46,3 +47,248 @@ export function getStartingChallenges(layer) {
|
|||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
export function resetLayerData(layer, keep = []) {
|
||||
keep.push('unlocked', 'forceTooltip', 'noRespecConfirm');
|
||||
const keptData = keep.reduce((acc, curr) => {
|
||||
acc[curr] = player[layer][curr];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
player.upgrades = [];
|
||||
player.achievements = [];
|
||||
player.milestones = [];
|
||||
player.infoboxes = {};
|
||||
|
||||
player[layer].buyables = getStartingBuyables(layers[layer]);
|
||||
player[layer].clickables = getStartingClickables(layers[layer]);
|
||||
player[layer].challenges = getStartingChallenges(layers[layer]);
|
||||
|
||||
Object.assign(player[layer], layers[layer].startData?.());
|
||||
|
||||
for (let item in keptData) {
|
||||
player[layer][item] = keptData[item];
|
||||
}
|
||||
}
|
||||
|
||||
export function resetRow(row, ignore) {
|
||||
Object.values(layers).filter(layer => layer.row === row && layer.layer !== ignore).forEach(layer => layer.hardReset());
|
||||
}
|
||||
|
||||
export const defaultLayerProperties = {
|
||||
type: "none",
|
||||
shown: true,
|
||||
layerShown: true,
|
||||
glowColor: "red",
|
||||
minWidth: 640,
|
||||
displayRow() {
|
||||
return this.row;
|
||||
},
|
||||
symbol() {
|
||||
return this.id;
|
||||
},
|
||||
unlocked() {
|
||||
if (player[this.id].unlocked) {
|
||||
return true;
|
||||
}
|
||||
if (this.type !== "none" && this.canReset && this.layerShown) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
trueGlowColor() {
|
||||
if (this.subtabs) {
|
||||
for (let subtab of Object.values(this.subtabs)) {
|
||||
if (subtab.notify) {
|
||||
return subtab.glowColor || "red";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.microtabs) {
|
||||
for (let microtab of Object.values(this.microtabs)) {
|
||||
if (microtab.notify) {
|
||||
return microtab.glowColor || "red";
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.glowColor || "red";
|
||||
},
|
||||
resetGain() {
|
||||
if (this.type === "none" || this.type === "custom") {
|
||||
return new Decimal(0);
|
||||
}
|
||||
if (this.gainExp?.eq(0)) {
|
||||
return new Decimal(0);
|
||||
}
|
||||
if (this.baseAmount.lt(this.requires)) {
|
||||
return new Decimal(0);
|
||||
}
|
||||
if (this.type === "static") {
|
||||
if (!this.canBuyMax) {
|
||||
return new Decimal(1);
|
||||
}
|
||||
let gain = this.baseAmount.div(this.requires).div(this.gainMult || 1).max(1).log(this.base)
|
||||
.times(this.gainExp || 1).pow(Decimal.pow(this.exponent || 1, -1));
|
||||
gain = gain.times(this.directMult || 1);
|
||||
return gain.floor().sub(player[this.layer].points).add(1).max(1);
|
||||
}
|
||||
if (this.type === "normal") {
|
||||
let gain = this.baseAmount.div(this.requires).pow(this.exponent || 1).times(this.gainMult || 1)
|
||||
.pow(this.gainExp || 1);
|
||||
if (this.softcap && gain.gte(this.softcap)) {
|
||||
gain = gain.pow(this.softcapPower).times(this.softcap.pow(Decimal.sub(1, this.softcapPower)));
|
||||
}
|
||||
gain = gain.times(this.directMult || 1);
|
||||
return gain.floor().max(0);
|
||||
}
|
||||
// Unknown prestige type
|
||||
return new Decimal(0);
|
||||
},
|
||||
nextAt() {
|
||||
if (this.type === "none" || this.type === "custom") {
|
||||
return new Decimal(Infinity);
|
||||
}
|
||||
if (this.gainMult?.lte(0) || this.gainExp?.lte(0)) {
|
||||
return new Decimal(Infinity);
|
||||
}
|
||||
if (this.type === "static") {
|
||||
const amount = player[this.layer].points.div(this.directMult || 1);
|
||||
const extraCost = Decimal.pow(this.base, amount.pow(this.exponent || 1).div(this.gainExp || 1))
|
||||
.times(this.gainMult || 1);
|
||||
let cost = extraCost.times(this.requires).max(this.requires);
|
||||
if (this.roundUpCost) {
|
||||
cost = cost.ceil();
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
if (this.type === "normal") {
|
||||
let next = this.resetGain.add(1).div(this.directMult || 1);
|
||||
if (this.softcap && next.gte(this.softcap)) {
|
||||
next = next.div(this.softcap.pow(Decimal.sub(1, this.softcapPower)))
|
||||
.pow(Decimal.div(1, this.softcapPower));
|
||||
}
|
||||
next = next.root(this.gainExp || 1).div(this.gainMult || 1).root(this.exponent || 1)
|
||||
.times(this.requires).max(this.requires);
|
||||
if (this.roundUpCost) {
|
||||
next = next.ceil();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
// Unknown prestige type
|
||||
return new Decimal(0);
|
||||
},
|
||||
nextAtMax() {
|
||||
if (!this.canBuyMax || this.type !== "static") {
|
||||
return this.nextAt;
|
||||
}
|
||||
const amount = player[this.layer].points.plus(this.resetGain).div(this.directMult || 1);
|
||||
const extraCost = Decimal.pow(this.base, amount.pow(this.exponent || 1).div(this.gainExp || 1))
|
||||
.times(this.gainMult || 1);
|
||||
let cost = extraCost.times(this.requires).max(this.requires);
|
||||
if (this.roundUpCost) {
|
||||
cost = cost.ceil();
|
||||
}
|
||||
return cost;
|
||||
},
|
||||
canReset() {
|
||||
if (this.type === "normal") {
|
||||
return this.baseAmount.gte(this.requires);
|
||||
}
|
||||
if (this.type === "static") {
|
||||
return this.baseAmount.gte(this.nextAt);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
notify() {
|
||||
if (this.upgrades) {
|
||||
if (Object.values(this.upgrades).some(upgrade => upgrade.canAfford && !upgrade.bought && upgrade.unlocked)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.activeChallenge?.canComplete) {
|
||||
return true;
|
||||
}
|
||||
if (this.subtabs) {
|
||||
if (Object.values(this.subtabs).some(subtab => subtab.notify)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.microtabs) {
|
||||
if (Object.values(this.microtabs).some(subtab => subtab.notify)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
resetNotify() {
|
||||
if (this.subtabs) {
|
||||
if (Object.values(this.subtabs).some(subtab => subtab.prestigeNotify)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.microtabs) {
|
||||
if (Object.values(this.microtabs).some(microtab => microtab.prestigeNotify)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.autoPrestige || this.passiveGeneration) {
|
||||
return false;
|
||||
}
|
||||
if (this.type === "static") {
|
||||
return this.canReset;
|
||||
}
|
||||
if (this.type === "normal") {
|
||||
return this.canReset && this.resetGain.gte(player[this.layer].points.div(10));
|
||||
}
|
||||
return false;
|
||||
},
|
||||
reset(force = false) {
|
||||
if (this.type === 'none') {
|
||||
return;
|
||||
}
|
||||
if (!force) {
|
||||
if (!this.canReset) {
|
||||
return;
|
||||
}
|
||||
this.onPrestige?.(this.resetGain);
|
||||
if (player[this.layer].points != undefined) {
|
||||
player[this.layer].points = player[this.layer].points.add(this.resetGain);
|
||||
}
|
||||
if (!player[this.layer].unlocked) {
|
||||
player[this.layer].unlocked = true;
|
||||
if (this.increaseUnlockOrder) {
|
||||
for (let layer in this.increaseUnlockOrder) {
|
||||
player[layer].unlockOrder = (player[layer].unlockOrder || 0) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.resetsNothing) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object.values(layers).forEach(layer => {
|
||||
if (this.row >= layer.row && (!force || this !== layer)) {
|
||||
this.activeChallenge?.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
player.points = new Decimal(0);
|
||||
|
||||
for (let row = this.row; row >= 0; row--) {
|
||||
resetRow(row, this.layer);
|
||||
}
|
||||
resetRow('side', this.layer);
|
||||
|
||||
if (player[this.layer].resetTime != undefined) {
|
||||
player[this.layer].resetTime = 0;
|
||||
}
|
||||
},
|
||||
hardReset(keep = []) {
|
||||
if (!isNaN(this.row)) {
|
||||
resetLayerData(this.layer, keep);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue