mirror of
https://github.com/IvarK/AntimatterDimensionsSourceCode.git
synced 2024-09-20 11:01:45 +00:00
Merge branch 'master' into earth/add-unsupported-browser-message
This commit is contained in:
commit
56c2712dc6
|
@ -33,11 +33,11 @@
|
|||
}
|
||||
],
|
||||
|
||||
"vue/one-component-per-file": "off",
|
||||
"vue/component-definition-name-casing": "off",
|
||||
"vue/order-in-components": "off",
|
||||
"vue/require-prop-type-constructor": "off",
|
||||
"vue/require-default-prop": "off",
|
||||
"vue/one-component-per-file": "error",
|
||||
"vue/component-definition-name-casing": "warn",
|
||||
"vue/order-in-components": "warn",
|
||||
"vue/require-prop-type-constructor": "warn",
|
||||
"vue/require-default-prop": "warn",
|
||||
"vue/html-comment-content-newline": "warn",
|
||||
"vue/html-comment-content-spacing": "warn",
|
||||
"vue/html-comment-indent": "warn",
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
import "./blob-snowflake";
|
||||
import "./blob-background";
|
||||
|
||||
Vue.component("blob-snowflakes", {
|
||||
data() {
|
||||
return {
|
||||
animateBackground: false,
|
||||
count: 0,
|
||||
initialized: false,
|
||||
bounds: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.updateSize();
|
||||
window.addEventListener("resize", this.updateSize);
|
||||
this.initialized = true;
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener("resize", this.updateSize);
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.animateBackground = player.options.animations.background;
|
||||
this.count = player.options.animations.blobSnowflakes;
|
||||
},
|
||||
updateSize() {
|
||||
this.bounds.x = this.$el.clientWidth;
|
||||
this.bounds.y = this.$el.clientHeight;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<svg v-if="animateBackground" class="c-blob-snowflake-container">
|
||||
<blob-snowflake
|
||||
v-for="i in count"
|
||||
v-if="initialized"
|
||||
:key="i"
|
||||
:bounds="bounds"
|
||||
/>
|
||||
</svg>
|
||||
<svg v-else class="c-blob-background-container">
|
||||
<blob-background
|
||||
v-for="i in count"
|
||||
v-if="initialized"
|
||||
:key="i"
|
||||
:bounds="bounds"
|
||||
/>
|
||||
</svg>`
|
||||
});
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
import "./old-ui/old-ui.js";
|
||||
import "./new-ui/new-ui.js";
|
||||
import "./save-timer.js";
|
||||
import "./speedrun-status.js";
|
||||
import "./help-me.js";
|
||||
import "./tt-shop.js";
|
||||
import "./new-ui/sidebar.js";
|
||||
import "./background-animations";
|
||||
import TabComponents from "@/components/tabs";
|
||||
import PopupModal from "@/components/modals/PopupModal";
|
||||
import FadeToBlack from "@/components/tabs/celestial-pelle/FadeToBlack";
|
||||
import CreditsContainer from "@/components/tabs/celestial-pelle/CreditsContainer";
|
||||
import NewGame from "@/components/tabs/celestial-pelle/NewGame";
|
||||
|
||||
Vue.component("game-ui", {
|
||||
components: {
|
||||
...TabComponents,
|
||||
PopupModal,
|
||||
FadeToBlack,
|
||||
CreditsContainer,
|
||||
NewGame
|
||||
},
|
||||
computed: {
|
||||
view() {
|
||||
return this.$viewModel;
|
||||
},
|
||||
uiLayout() {
|
||||
return this.view.newUI ? "new-ui" : "old-ui";
|
||||
},
|
||||
containerClass() {
|
||||
return this.view.newUI ? "new-ui" : "old-ui";
|
||||
},
|
||||
page() {
|
||||
const subtab = Tabs.current[this.$viewModel.subtab];
|
||||
return subtab.config.component;
|
||||
},
|
||||
themeCss() {
|
||||
return `stylesheets/theme-${this.view.theme}.css`;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div
|
||||
v-if="view.initialized"
|
||||
id="ui-container"
|
||||
:class="containerClass"
|
||||
style="display: flex; justify-content: center;"
|
||||
>
|
||||
<div id="ui" class="c-game-ui">
|
||||
<component :is="uiLayout">
|
||||
<component :is="page" />
|
||||
</component>
|
||||
<PopupModal v-if="view.modal.current" :modal="view.modal.current" />
|
||||
<modal-progress-bar v-if="view.modal.progressBar" />
|
||||
<link v-if="view.theme !== 'Normal'" type="text/css" rel="stylesheet" :href="themeCss">
|
||||
<help-me />
|
||||
<background-animations />
|
||||
</div>
|
||||
<div id="notification-container" class="l-notification-container" />
|
||||
<tt-shop v-if="view.subtab === 'studies'" class="l-time-studies-tab__tt-shop" />
|
||||
<sidebar v-if="view.newUI" />
|
||||
<save-timer />
|
||||
<speedrun-status />
|
||||
<FadeToBlack />
|
||||
<CreditsContainer />
|
||||
<NewGame />
|
||||
</div>`
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
Vue.component("help-me", {
|
||||
template: `<div onclick="Modal.h2p.show()" class="o-tab-btn l-help-me">?</div>`
|
||||
});
|
|
@ -1,4 +0,0 @@
|
|||
import "./shop/shop-tab.js";
|
||||
|
||||
import "./modals/index.js";
|
||||
import "./game-ui.js";
|
|
@ -1 +0,0 @@
|
|||
import "./modal-progress-bar.js";
|
|
@ -1,91 +0,0 @@
|
|||
import PrimaryButton from "@/components/PrimaryButton";
|
||||
|
||||
Vue.component("modal-progress-bar", {
|
||||
components: {
|
||||
"offline-speedup-button": {
|
||||
components: {
|
||||
PrimaryButton
|
||||
},
|
||||
props: {
|
||||
button: Object,
|
||||
progress: Object,
|
||||
},
|
||||
computed: {
|
||||
canBeClicked() {
|
||||
return this.button.condition(this.progress.current, this.progress.max);
|
||||
},
|
||||
buttonClass() {
|
||||
return {
|
||||
"o-primary-btn--width-medium": true,
|
||||
"o-primary-btn--disabled": !this.canBeClicked,
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buttonClicked() {
|
||||
if (!this.canBeClicked) return;
|
||||
this.button.click();
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<PrimaryButton
|
||||
:class="buttonClass"
|
||||
@click="buttonClicked"
|
||||
>
|
||||
{{ button.text }}
|
||||
</PrimaryButton>`
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
progress() {
|
||||
return this.$viewModel.modal.progressBar;
|
||||
},
|
||||
foregroundStyle() {
|
||||
return {
|
||||
width: `${this.progress.current / this.progress.max * 100}%`,
|
||||
};
|
||||
},
|
||||
remaining() {
|
||||
const timeSinceStart = Date.now() - this.progress.startTime;
|
||||
return formatFloat(
|
||||
TimeSpan.fromMilliseconds(timeSinceStart / (this.progress.current / this.progress.max)).totalSeconds -
|
||||
TimeSpan.fromMilliseconds(timeSinceStart).totalSeconds
|
||||
, 1);
|
||||
},
|
||||
buttons() {
|
||||
return this.progress.buttons || [];
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="l-modal-overlay c-modal-overlay" style="z-index: 8">
|
||||
<div class="l-modal-progress-bar c-modal">
|
||||
<div class="c-modal-progress-bar__label">
|
||||
{{ progress.label }}
|
||||
</div>
|
||||
<div>
|
||||
{{ progress.info() }}
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
{{ progress.progressName }}: {{ formatInt(progress.current) }}/{{ formatInt(progress.max) }}
|
||||
</div>
|
||||
<div>
|
||||
Remaining: {{ remaining }} seconds
|
||||
</div>
|
||||
<div class="l-modal-progress-bar__hbox">
|
||||
<div class="l-modal-progress-bar__bg c-modal-progress-bar__bg">
|
||||
<div class="l-modal-progress-bar__fg c-modal-progress-bar__fg" :style="foregroundStyle" />
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="l-modal-progress-bar__buttons">
|
||||
<offline-speedup-button
|
||||
v-for="(button, id) in buttons"
|
||||
:key="id"
|
||||
:button="button"
|
||||
:progress="progress"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>`,
|
||||
});
|
|
@ -1,81 +0,0 @@
|
|||
Vue.component("sidebar-currency", {
|
||||
data() {
|
||||
return {
|
||||
AM: new Decimal(0),
|
||||
IP: new Decimal(0),
|
||||
EP: new Decimal(0),
|
||||
RM: new Decimal(0),
|
||||
IM: 0,
|
||||
RS: new Decimal(0),
|
||||
machineStr: "",
|
||||
showIP: false,
|
||||
showEP: false,
|
||||
showRM: false,
|
||||
showRS: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.AM.copyFrom(Currency.antimatter);
|
||||
this.IP.copyFrom(Currency.infinityPoints);
|
||||
this.EP.copyFrom(Currency.eternityPoints);
|
||||
this.RM.copyFrom(Currency.realityMachines);
|
||||
this.IM = Currency.imaginaryMachines.value;
|
||||
this.RS.copyFrom(Currency.realityShards);
|
||||
this.machineStr = formatMachines(this.RM, this.IM);
|
||||
this.showIP = PlayerProgress.infinityUnlocked();
|
||||
this.showEP = PlayerProgress.eternityUnlocked();
|
||||
this.showRM = PlayerProgress.realityUnlocked();
|
||||
this.showRS = Pelle.isDoomed;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="resource">
|
||||
<template v-if="showRS">
|
||||
<h2 class="o-sidebar-currency--pelle">{{ format(RS, 2) }}</h2>
|
||||
<div class="resource-information">
|
||||
<span class="resource-name">{{ pluralize("Reality Shard", RS) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="showRM">
|
||||
<template v-if="IM === 0">
|
||||
<h2 class="o-sidebar-currency--reality">{{ format(RM, 2) }}</h2>
|
||||
<div class="resource-information">
|
||||
<span class="resource-name">{{ pluralize("Reality Machine", RM) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<h3 class="o-sidebar-currency--reality">
|
||||
{{ machineStr }}
|
||||
</h3>
|
||||
<div class="resource-information">
|
||||
<span class="resource-name">Machines</span>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else-if="showEP">
|
||||
<h2 class="o-sidebar-currency--eternity">
|
||||
{{ format(EP, 2) }}
|
||||
</h2>
|
||||
<div class="resource-information">
|
||||
<span class="resource-name">{{ pluralize("Eternity Point", EP) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="showIP">
|
||||
<h2 class="o-sidebar-currency--infinity">
|
||||
{{ format(IP, 2) }}
|
||||
</h2>
|
||||
<div class="resource-information">
|
||||
<span class="resource-name">{{ pluralize("Infinity Point", IP) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<h2 class="o-sidebar-currency--antimatter">
|
||||
{{ format(AM, 2, 1) }}
|
||||
</h2>
|
||||
<div class="resource-information">
|
||||
<span class="resource-name">Antimatter</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>`
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
import "./sidebar-resources/sidebar-currency.js";
|
||||
import "./tab-button.js";
|
||||
|
||||
Vue.component("sidebar", {
|
||||
data() {
|
||||
return {
|
||||
isHidden: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tabs: () => Tabs.newUI
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.isHidden = AutomatorData.isEditorFullscreen;
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div class="sidebar" v-if="!isHidden">
|
||||
<sidebar-currency />
|
||||
<tab-button
|
||||
v-for="(tab, tabPosition) in tabs"
|
||||
:key="tab.name"
|
||||
:tab="tab"
|
||||
:tabPosition="tabPosition"
|
||||
/>
|
||||
</div>`
|
||||
});
|
|
@ -1,72 +0,0 @@
|
|||
import "./game-header-eternity-button.js";
|
||||
import "./game-header-new-dim-button.js";
|
||||
import "./game-header-big-crunch-button.js";
|
||||
import "./game-header-tickspeed-row.js";
|
||||
import "./game-header-amounts-line.js";
|
||||
import "../../header-challenge-display.js";
|
||||
import BlackHoleHeaderRow from "@/components/BlackHoleHeaderRow";
|
||||
|
||||
Vue.component("game-header", {
|
||||
components: {
|
||||
BlackHoleHeaderRow
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isInEffarig: false,
|
||||
effarigMultNerfText: "",
|
||||
effarigTickNerfText: "",
|
||||
isInLaitela: false,
|
||||
laitelaTimer: 0,
|
||||
laitelaEntropy: "",
|
||||
antimatter: new Decimal(0),
|
||||
antimatterPerSec: new Decimal(0)
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.isInEffarig = Effarig.isRunning;
|
||||
if (this.isInEffarig) {
|
||||
this.effarigMultNerfText = `${formatPow(0.25 + 0.25 * Effarig.nerfFactor(Currency.infinityPower.value), 0, 5)}`;
|
||||
this.effarigTickNerfText = `${formatPow(0.7 + 0.1 * Effarig.nerfFactor(Currency.timeShards.value), 0, 5)}`;
|
||||
}
|
||||
this.isInLaitela = Laitela.isRunning;
|
||||
if (this.isInLaitela) {
|
||||
if (player.celestials.laitela.entropy > 0) {
|
||||
this.laitelaEntropy = `${formatPercents(player.celestials.laitela.entropy, 2, 2)}`;
|
||||
this.laitelaTimer = Time.thisRealityRealTime.toStringShort();
|
||||
} else {
|
||||
this.laitelaEntropy = `${formatPercents(1, 2, 2)}`;
|
||||
this.laitelaTimer = TimeSpan.fromSeconds(player.celestials.laitela.thisCompletion).toStringShort();
|
||||
}
|
||||
}
|
||||
this.antimatter.copyFrom(Currency.antimatter);
|
||||
this.antimatterPerSec.copyFrom(Currency.antimatter.productionPerSecond);
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<header-challenge-display />
|
||||
<div v-if="isInEffarig">
|
||||
Gamespeed and multipliers are Dilated {{ effarigMultNerfText }}
|
||||
<br>
|
||||
Tickspeed is Dilated {{ effarigTickNerfText }}
|
||||
</div>
|
||||
<div v-if="isInLaitela">
|
||||
Entropy: {{ laitelaEntropy }} ({{ laitelaTimer }})
|
||||
</div>
|
||||
<game-header-amounts-line />
|
||||
<div>
|
||||
<p>
|
||||
You have <span class="c-game-header__antimatter">{{ format(antimatter, 2, 1) }}</span> antimatter.
|
||||
</p>
|
||||
</div>
|
||||
<div class="l-game-header__buttons-line">
|
||||
<game-header-big-crunch-button />
|
||||
<game-header-new-dim-button />
|
||||
<game-header-eternity-button />
|
||||
</div>
|
||||
<div>You are getting {{ format(antimatterPerSec, 2, 0) }} antimatter per second.</div>
|
||||
<game-header-tickspeed-row />
|
||||
<BlackHoleHeaderRow />
|
||||
</div>`
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
import "./old-ui-subtab-button.js";
|
||||
|
||||
Vue.component("old-ui-subtab-bar", {
|
||||
data() {
|
||||
return {
|
||||
isVisible: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tab: () => Tabs.current,
|
||||
subtabs() {
|
||||
return this.tab.subtabs;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.isVisible = this.subtabs.countWhere(subtab => subtab.isAvailable) > 1;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="c-subtab-button-container" v-if="isVisible">
|
||||
<old-ui-subtab-button v-for="(subtab, i) in subtabs" :key="i" :subtab="subtab" />
|
||||
</div>`
|
||||
});
|
|
@ -1,26 +0,0 @@
|
|||
Vue.component("old-ui-subtab-button", {
|
||||
props: {
|
||||
subtab: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isAvailable: false,
|
||||
hasNotification: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.isAvailable = this.subtab.isAvailable;
|
||||
this.hasNotification = this.subtab.hasNotification;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<button
|
||||
v-if="isAvailable"
|
||||
@click="subtab.show(true)"
|
||||
class="o-tab-btn o-tab-btn--secondary"
|
||||
>
|
||||
{{ subtab.name }}
|
||||
<i v-if="hasNotification" class="fas fa-exclamation"></i>
|
||||
</button>`
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
import "./old-ui-tab-button.js";
|
||||
|
||||
Vue.component("old-ui-tab-bar", {
|
||||
computed: {
|
||||
tabs: () => Tabs.oldUI
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<old-ui-tab-button v-for="(tab, i) in tabs" :key="i" :tabPosition="i" :tab="tab" />
|
||||
</div>`
|
||||
});
|
|
@ -1,66 +0,0 @@
|
|||
import "./old-ui-subtab-bar.js";
|
||||
import "./old-ui-tab-bar.js";
|
||||
import "./header/game-header.js";
|
||||
import NewsTicker from "@/components/NewsTicker";
|
||||
import FooterLinks from "@/components/FooterLinks";
|
||||
import InfinityPointsHeader from "@/components/InfinityPointsHeader";
|
||||
import EternityPointsHeader from "@/components/EternityPointsHeader";
|
||||
import RealityMachinesHeader from "@/components/RealityMachinesHeader";
|
||||
|
||||
Vue.component("old-ui", {
|
||||
components: {
|
||||
"big-crunch-button": {
|
||||
template: `<button class="o-tab-btn o-big-crunch-btn" onclick="bigCrunchResetRequest()">Big Crunch</button>`
|
||||
},
|
||||
NewsTicker,
|
||||
FooterLinks,
|
||||
InfinityPointsHeader,
|
||||
EternityPointsHeader,
|
||||
RealityMachinesHeader
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
bigCrunch: false,
|
||||
smallCrunch: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tab: () => Tabs.current,
|
||||
news() {
|
||||
return this.$viewModel.news;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
const crunchButtonVisible = !player.break && Player.canCrunch;
|
||||
const reachedInfinityInMinute = Time.bestInfinityRealTime.totalMinutes <= 1;
|
||||
this.bigCrunch = crunchButtonVisible && !reachedInfinityInMinute;
|
||||
this.smallCrunch = crunchButtonVisible && reachedInfinityInMinute;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div id="container" class="container c-old-ui l-old-ui">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/old-ui.css">
|
||||
<template v-if="bigCrunch">
|
||||
<big-crunch-button class="l-old-ui__big-crunch-btn" />
|
||||
<div class="o-emptiness">
|
||||
The world has collapsed on itself due to excess of antimatter.
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<NewsTicker class="l-old-ui__news-bar" v-if="news" />
|
||||
<game-header class="l-old-ui__header" />
|
||||
<old-ui-tab-bar />
|
||||
<component v-if="tab.config.before" :is="tab.config.before" />
|
||||
<old-ui-subtab-bar />
|
||||
<big-crunch-button
|
||||
v-show="smallCrunch"
|
||||
class="l-old-ui__big-crunch-btn l-old-ui__big-crunch-btn--overlay"
|
||||
/>
|
||||
<div class="l-old-ui-page l-old-ui__page">
|
||||
<slot />
|
||||
</div>
|
||||
<FooterLinks class="l-old-ui__footer" />
|
||||
</template>
|
||||
</div>`
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
Vue.component("save-timer", {
|
||||
data() {
|
||||
return {
|
||||
currentTime: 0,
|
||||
lastSave: 0,
|
||||
showTimeSinceSave: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
time() {
|
||||
return timeDisplayShort(this.currentTime - this.lastSave);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.lastSave = GameStorage.lastSaveTime;
|
||||
this.currentTime = Date.now();
|
||||
this.showTimeSinceSave = player.options.showTimeSinceSave;
|
||||
},
|
||||
save() {
|
||||
GameStorage.save();
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="o-save-timer" v-if="showTimeSinceSave" @click="save">
|
||||
Time since last save: {{ time }}
|
||||
</div>`
|
||||
});
|
|
@ -1,34 +0,0 @@
|
|||
Vue.component("shop-button", {
|
||||
props: {
|
||||
purchase: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentMult: 0,
|
||||
nextMult: 0
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.currentMult = this.purchase.currentMult;
|
||||
this.nextMult = this.purchase.nextMult;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="c-shop-button-container">
|
||||
<div class="o-shop-button-description">
|
||||
{{ purchase.description }}
|
||||
<br>
|
||||
<span class="o-shop-button-multiplier">
|
||||
Currently {{ formatX(currentMult, 2, 0) }}, next: {{ formatX(nextMult, 2, 0) }}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
@click="purchase.purchase()"
|
||||
class="o-shop-button-button"
|
||||
>
|
||||
Cost: {{ purchase.cost }}
|
||||
<img src="images/std_coin.png" height="40">
|
||||
</button>
|
||||
</div>`
|
||||
});
|
|
@ -1,71 +0,0 @@
|
|||
import "./shop-button.js";
|
||||
|
||||
Vue.component("shop-tab", {
|
||||
data() {
|
||||
return {
|
||||
STD: 0,
|
||||
kongEnabled: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
purchases() {
|
||||
return ShopPurchase.all;
|
||||
},
|
||||
buySTDText() {
|
||||
return this.kongEnabled ? "Buy More" : "Play in Kongregate to buy STDs";
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.STD = player.IAP.totalSTD - player.IAP.spentSTD;
|
||||
this.kongEnabled = kong.enabled;
|
||||
},
|
||||
showStore() {
|
||||
if (!this.kongEnabled) return;
|
||||
Modal.shop.show();
|
||||
},
|
||||
buyTimeSkip() {
|
||||
kong.purchaseTimeSkip(10);
|
||||
},
|
||||
buyLongerTimeSkip() {
|
||||
kong.purchaseLongerTimeSkip(20);
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div id="shop" class="tab">
|
||||
<div class="c-shop-disclaimer">
|
||||
Disclaimer: These are not required to progress in the game, they are just for supporting the developer.
|
||||
The game is balanced without the use of any microtranactions.
|
||||
</div>
|
||||
<div class="c-shop-header">
|
||||
<span>You have {{ STD }}</span>
|
||||
<img src="images/std_coin.png" height="40">
|
||||
<button class="o-shop-button-button" @click="showStore()">{{ buySTDText }}</button>
|
||||
</div>
|
||||
<div class="l-shop-buttons-container">
|
||||
<shop-button v-for="purchase in purchases" :purchase="purchase" :key="purchase.key"></shop-button>
|
||||
<div class="c-shop-button-container">
|
||||
<div class="o-shop-button-description">
|
||||
Get 6 hours worth of offline production. (Autobuyers don't work full speed)
|
||||
</div>
|
||||
<button
|
||||
@click="buyTimeSkip()"
|
||||
class="o-shop-button-button"
|
||||
>
|
||||
Cost: 10 <img src="images/std_coin.png" height="40">
|
||||
</button>
|
||||
</div>
|
||||
<div class="c-shop-button-container">
|
||||
<div class="o-shop-button-description">
|
||||
Get 24 hours worth of offline production. (Autobuyers don't work full speed)
|
||||
</div>
|
||||
<button
|
||||
@click="buyLongerTimeSkip()"
|
||||
class="o-shop-button-button"
|
||||
>
|
||||
Cost: 20 <img src="images/std_coin.png" height="40">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
});
|
|
@ -1,292 +0,0 @@
|
|||
import "./hover-menu.js";
|
||||
import PrimaryToggleButton from "@/components/PrimaryToggleButton";
|
||||
|
||||
Vue.component("tt-shop", {
|
||||
components: {
|
||||
PrimaryToggleButton
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
theoremAmount: new Decimal(0),
|
||||
theoremGeneration: new Decimal(0),
|
||||
totalTimeTheorems: new Decimal(0),
|
||||
shopMinimized: false,
|
||||
minimizeAvailable: false,
|
||||
hasTTAutobuyer: false,
|
||||
isAutobuyerOn: false,
|
||||
budget: {
|
||||
am: new Decimal(0),
|
||||
ip: new Decimal(0),
|
||||
ep: new Decimal(0)
|
||||
},
|
||||
costs: {
|
||||
am: new Decimal(0),
|
||||
ip: new Decimal(0),
|
||||
ep: new Decimal(0)
|
||||
},
|
||||
showST: false,
|
||||
STamount: 0,
|
||||
showTTGen: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
isAutobuyerOn(newValue) {
|
||||
Autobuyer.timeTheorem.isActive = newValue;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
minimized() {
|
||||
return this.minimizeAvailable && this.shopMinimized;
|
||||
},
|
||||
formatTimeTheoremType() {
|
||||
if (this.theoremAmount.gte(1e6)) {
|
||||
return format;
|
||||
}
|
||||
if (!(Teresa.isRunning || Enslaved.isRunning) &&
|
||||
getAdjustedGlyphEffect("dilationTTgen") > 0 && !DilationUpgrade.ttGenerator.isBought) {
|
||||
return formatFloat;
|
||||
}
|
||||
return formatInt;
|
||||
},
|
||||
TTgenRateText() {
|
||||
if (this.theoremGeneration.lt(1 / 3600)) {
|
||||
return `one TT every ${TimeSpan.fromSeconds(
|
||||
this.theoremGeneration.reciprocal().toNumber()).toStringShort(false)}`;
|
||||
}
|
||||
if (this.theoremGeneration.lt(0.1)) {
|
||||
return `${format(this.theoremGeneration.times(3600), 2, 2)} TT/hour`;
|
||||
}
|
||||
return `${format(this.theoremGeneration, 2, 2)} TT/sec`;
|
||||
},
|
||||
totalTimeTheoremText() {
|
||||
return `${quantify("total Time Theorem", this.totalTimeTheorems, 2, 2)}`;
|
||||
},
|
||||
minimizeArrowStyle() {
|
||||
return {
|
||||
transform: this.minimized ? "rotateX(180deg)" : "",
|
||||
};
|
||||
},
|
||||
saveLoadText() {
|
||||
return this.$viewModel.shiftDown ? "save:" : "load:";
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
minimize() {
|
||||
player.timestudy.shopMinimized = !player.timestudy.shopMinimized;
|
||||
},
|
||||
formatAM(am) {
|
||||
return `${format(am)} AM`;
|
||||
},
|
||||
buyWithAM() {
|
||||
TimeTheorems.buyOne(false, "am");
|
||||
},
|
||||
formatIP(ip) {
|
||||
return `${format(ip)} IP`;
|
||||
},
|
||||
buyWithIP() {
|
||||
TimeTheorems.buyOne(false, "ip");
|
||||
},
|
||||
formatEP(ep) {
|
||||
return `${format(ep, 2, 0)} EP`;
|
||||
},
|
||||
buyWithEP() {
|
||||
TimeTheorems.buyOne(false, "ep");
|
||||
},
|
||||
buyMaxTheorems() {
|
||||
TimeTheorems.buyMax(false);
|
||||
},
|
||||
update() {
|
||||
this.theoremAmount.copyFrom(Currency.timeTheorems);
|
||||
this.theoremGeneration.copyFrom(getTTPerSecond().times(getGameSpeedupFactor()));
|
||||
this.totalTimeTheorems.copyFrom(Currency.timeTheorems.max);
|
||||
this.shopMinimized = player.timestudy.shopMinimized;
|
||||
this.hasTTAutobuyer = Autobuyer.timeTheorem.isUnlocked;
|
||||
this.isAutobuyerOn = Autobuyer.timeTheorem.isActive;
|
||||
this.minimizeAvailable = DilationUpgrade.ttGenerator.isBought || this.hasTTAutobuyer;
|
||||
const budget = this.budget;
|
||||
budget.am.copyFrom(TimeTheoremPurchaseType.am.currency);
|
||||
budget.ip.copyFrom(TimeTheoremPurchaseType.ip.currency);
|
||||
budget.ep.copyFrom(TimeTheoremPurchaseType.ep.currency);
|
||||
const costs = this.costs;
|
||||
costs.am.copyFrom(TimeTheoremPurchaseType.am.cost);
|
||||
costs.ip.copyFrom(TimeTheoremPurchaseType.ip.cost);
|
||||
costs.ep.copyFrom(TimeTheoremPurchaseType.ep.cost);
|
||||
this.showST = V.spaceTheorems > 0 && !Pelle.isDoomed;
|
||||
this.STamount = V.availableST;
|
||||
this.showTTGen = this.theoremGeneration.gt(0) && !ui.view.shiftDown;
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div id="TTbuttons">
|
||||
<div class="ttshop-container ttshop-background">
|
||||
<div data-role="page" class="ttbuttons-row ttbuttons-top-row">
|
||||
<button
|
||||
class="l-tt-save-load-btn c-tt-buy-button c-tt-buy-button--unlocked"
|
||||
onClick="Modal.preferredTree.show()"
|
||||
>
|
||||
<i class='fas fa-cog'></i>
|
||||
</button>
|
||||
<p id="timetheorems">
|
||||
<span class="c-tt-amount">
|
||||
{{ quantify("Time Theorem", theoremAmount, 2, 0, formatTimeTheoremType) }}
|
||||
</span>
|
||||
<span v-if="showST">
|
||||
<br>
|
||||
{{ quantifyInt("Space Theorem", STamount) }}
|
||||
</span>
|
||||
</p>
|
||||
<div style="display: flex; flex-direction: column; align-items: left;">
|
||||
<div style="display: flex; flex-direction: row; align-items: center;">
|
||||
<span class="c-ttshop__save-load-text">{{ saveLoadText }}</span>
|
||||
<tt-save-load-button v-for="saveslot in 6" :key="saveslot" :saveslot="saveslot"></tt-save-load-button>
|
||||
</div>
|
||||
<span v-if="showTTGen">
|
||||
You are gaining {{ TTgenRateText }}.
|
||||
</span>
|
||||
<span v-else>
|
||||
You have {{ totalTimeTheoremText }}.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ttbuttons-row" v-if="!minimized">
|
||||
<tt-buy-button :budget="budget.am" :cost="costs.am" :formatCost="formatAM" :action="buyWithAM" />
|
||||
<tt-buy-button :budget="budget.ip" :cost="costs.ip" :formatCost="formatIP" :action="buyWithIP" />
|
||||
<tt-buy-button :budget="budget.ep" :cost="costs.ep" :formatCost="formatEP" :action="buyWithEP" />
|
||||
<div class="l-tt-buy-max-vbox">
|
||||
<button
|
||||
v-if="!minimized"
|
||||
class="o-tt-top-row-button c-tt-buy-button c-tt-buy-button--unlocked"
|
||||
@click="buyMaxTheorems"
|
||||
>
|
||||
Buy max
|
||||
</button>
|
||||
<PrimaryToggleButton
|
||||
v-if="!minimized && hasTTAutobuyer"
|
||||
v-model="isAutobuyerOn"
|
||||
class="o-tt-autobuyer-button c-tt-buy-button c-tt-buy-button--unlocked"
|
||||
label="Auto:"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button v-if="minimizeAvailable" class="ttshop-minimize-btn ttshop-background" @click="minimize">
|
||||
<span id="minimizeArrow" :style="minimizeArrowStyle">▼</span>
|
||||
</button>
|
||||
</div>`
|
||||
});
|
||||
|
||||
Vue.component("tt-save-load-button", {
|
||||
props: {
|
||||
saveslot: Number
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
name: player.timestudy.presets[this.saveslot - 1].name,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
preset() {
|
||||
return player.timestudy.presets[this.saveslot - 1];
|
||||
},
|
||||
displayName() {
|
||||
return this.name === "" ? this.saveslot : this.name;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
nicknameBlur(event) {
|
||||
this.preset.name = event.target.value.slice(0, 4);
|
||||
this.name = this.preset.name;
|
||||
},
|
||||
hideContextMenu() {
|
||||
this.$viewModel.currentContextMenu = null;
|
||||
},
|
||||
save() {
|
||||
this.hideContextMenu();
|
||||
this.preset.studies = TimeStudyTree.formatStudyList(GameCache.currentStudyTree.value.exportString);
|
||||
const presetName = this.name ? `Study preset "${this.name}"` : "Study preset";
|
||||
GameUI.notify.eternity(`${presetName} saved in slot ${this.saveslot}`);
|
||||
},
|
||||
load() {
|
||||
this.hideContextMenu();
|
||||
if (this.preset.studies) {
|
||||
// We need to use a combined tree for committing to the game state, or else it won't buy studies in the imported
|
||||
// tree are only reachable if the current tree is already bought
|
||||
const combinedTree = new TimeStudyTree();
|
||||
combinedTree.attemptBuyArray(TimeStudyTree.currentStudies, false);
|
||||
combinedTree.attemptBuyArray(combinedTree.parseStudyImport(this.preset.studies), true);
|
||||
TimeStudyTree.commitToGameState(combinedTree.purchasedStudies);
|
||||
|
||||
const presetName = this.name ? `Study preset "${this.name}"` : "Study preset";
|
||||
GameUI.notify.eternity(`${presetName} loaded from slot ${this.saveslot}`);
|
||||
} else {
|
||||
Modal.message.show("This Time Study list currently contains no Time Studies.");
|
||||
}
|
||||
},
|
||||
handleExport() {
|
||||
this.hideContextMenu();
|
||||
copyToClipboard(this.preset.studies);
|
||||
const presetName = this.name ? `Study preset "${this.name}"` : "Study preset";
|
||||
GameUI.notify.eternity(`${presetName} exported from slot ${this.saveslot} to your clipboard`);
|
||||
},
|
||||
edit() {
|
||||
Modal.studyString.show({ id: this.saveslot - 1 });
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<hover-menu class="l-tt-save-load-btn__wrapper">
|
||||
<template #object>
|
||||
<button
|
||||
class="l-tt-save-load-btn c-tt-buy-button c-tt-buy-button--unlocked"
|
||||
@click.shift.exact="save"
|
||||
@click.exact="load"
|
||||
>
|
||||
{{ displayName }}
|
||||
</button>
|
||||
</template>
|
||||
<template #menu>
|
||||
<div class="l-tt-save-load-btn__menu c-tt-save-load-btn__menu">
|
||||
<span ach-tooltip="Set a custom name (up to 4 characters)">
|
||||
<input
|
||||
type="text"
|
||||
size="4"
|
||||
maxlength="4"
|
||||
class="l-tt-save-load-btn__menu-rename c-tt-save-load-btn__menu-rename"
|
||||
:value="name"
|
||||
@keyup.esc="hideContextMenu"
|
||||
@blur="nicknameBlur"
|
||||
/>
|
||||
</span>
|
||||
<div class="l-tt-save-load-btn__menu-item c-tt-save-load-btn__menu-item" @click="edit">Edit</div>
|
||||
<div class="l-tt-save-load-btn__menu-item c-tt-save-load-btn__menu-item" @click="handleExport">Export</div>
|
||||
<div class="l-tt-save-load-btn__menu-item c-tt-save-load-btn__menu-item" @click="save">Save</div>
|
||||
<div class="l-tt-save-load-btn__menu-item c-tt-save-load-btn__menu-item" @click="load">Load</div>
|
||||
</div>
|
||||
</template>
|
||||
</hover-menu>`
|
||||
});
|
||||
|
||||
Vue.component("tt-buy-button", {
|
||||
props: ["budget", "cost", "formatCost", "action"],
|
||||
computed: {
|
||||
isEnabled() {
|
||||
if (Pelle.isDoomed && player.eternities.eq(0)) return false;
|
||||
return this.budget.gte(this.cost);
|
||||
},
|
||||
enabledClass() {
|
||||
if (!this.isEnabled || this.isLimitedByPelle) return "c-tt-buy-button--locked";
|
||||
|
||||
return "c-tt-buy-button--unlocked";
|
||||
},
|
||||
isLimitedByPelle() {
|
||||
return Pelle.isDoomed && player.eternities.eq(0)
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<button
|
||||
class="l-tt-buy-button c-tt-buy-button"
|
||||
:class="enabledClass"
|
||||
@click="action"
|
||||
>
|
||||
{{ isLimitedByPelle ? "Locked in Doomed before Eternity" : formatCost(cost) }}
|
||||
</button>`
|
||||
});
|
|
@ -39,6 +39,7 @@ import PurgeAllUnprotectedGlyphsModal from "@/components/modals/glyph-management
|
|||
import PurgeAllRejectedGlyphsModal from "@/components/modals/glyph-management/PurgeAllRejectedGlyphsModal";
|
||||
|
||||
import H2PModal from "@/components/modals/H2PModal";
|
||||
import InformationModal from "@/components/modals/InformationModal";
|
||||
import GlyphShowcasePanelModal from "@/components/modals/GlyphShowcasePanelModal";
|
||||
import UndoGlyphModal from "@/components/modals/UndoGlyphModal";
|
||||
import ReplaceGlyphModal from "@/components/modals/ReplaceGlyphModal";
|
||||
|
@ -170,6 +171,7 @@ Modal.realityGlyph = new Modal(RealityGlyphCreationModal);
|
|||
Modal.glyphSetSaveDelete = new Modal(GlyphSetSaveDeleteModal);
|
||||
Modal.uiChoice = new Modal(UiChoiceModal);
|
||||
Modal.h2p = new Modal(H2PModal);
|
||||
Modal.information = new Modal(InformationModal);
|
||||
Modal.awayProgress = new Modal(AwayProgressModal);
|
||||
Modal.loadGame = new Modal(LoadGameModal);
|
||||
Modal.import = new Modal(ImportSaveModal);
|
||||
|
|
|
@ -11,6 +11,9 @@ export class GameOptions {
|
|||
static toggleUI() {
|
||||
player.options.newUI = !player.options.newUI;
|
||||
ui.view.newUI = player.options.newUI;
|
||||
// This is needed because .s-base--dark is on newUI/normal but not on oldUI/normal
|
||||
// So the classes on body need to be updated
|
||||
Themes.find(player.options.theme).set();
|
||||
GameStorage.save(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ export const Themes = {
|
|||
Theme.create("S4", { secret: true, }),
|
||||
Theme.create("S5", { secret: true, }),
|
||||
Theme.create("S6", { dark: true, animated: true, secret: true, }),
|
||||
Theme.create("S7", { secret: true, }),
|
||||
Theme.create("S7", { metro: true, secret: true, }),
|
||||
Theme.create("S8", { metro: true, secret: true, }),
|
||||
Theme.create("S9", { secret: true, }),
|
||||
Theme.create("S10", { dark: true, metro: true, animated: true, secret: true, }),
|
||||
|
|
|
@ -3,6 +3,7 @@ import { state } from "./ui.init.js";
|
|||
import VTooltip from "v-tooltip";
|
||||
import { useLongPress, useRepeatingClick } from "./longpress";
|
||||
import VueGtag from "vue-gtag";
|
||||
import GameUIComponent from "@/components/GameUIComponent";
|
||||
|
||||
Vue.mixin({
|
||||
computed: {
|
||||
|
@ -10,6 +11,29 @@ Vue.mixin({
|
|||
return state.view;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.update) {
|
||||
this.on$(GAME_EVENT.UPDATE, this.update);
|
||||
if (GameUI.initialized) {
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
// Following is used to force the recomputation of computed values
|
||||
// from this fiddle https://codepen.io/sirlancelot/pen/JBeXeV
|
||||
const recomputed = Object.create(null);
|
||||
const watchers = this._computedWatchers;
|
||||
|
||||
if (!watchers) return;
|
||||
|
||||
for (const key in watchers) makeRecomputable(watchers[key], key, recomputed);
|
||||
|
||||
this.$recompute = key => recomputed[key] = !recomputed[key];
|
||||
Vue.observable(recomputed);
|
||||
},
|
||||
destroyed() {
|
||||
EventHub.ui.offAll(this);
|
||||
},
|
||||
methods: {
|
||||
emitClick() {
|
||||
this.$emit("click");
|
||||
|
@ -47,30 +71,6 @@ Vue.mixin({
|
|||
pluralize,
|
||||
quantify,
|
||||
quantifyInt
|
||||
},
|
||||
created() {
|
||||
if (this.update) {
|
||||
this.on$(GAME_EVENT.UPDATE, this.update);
|
||||
if (GameUI.initialized) {
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
// Following is used to force the recomputation of computed values
|
||||
// from this fiddle https://codepen.io/sirlancelot/pen/JBeXeV
|
||||
const recomputed = Object.create(null);
|
||||
const watchers = this._computedWatchers;
|
||||
|
||||
if (!watchers) return;
|
||||
|
||||
for (const key in watchers)
|
||||
makeRecomputable(watchers[key], key, recomputed);
|
||||
|
||||
this.$recompute = key => recomputed[key] = !recomputed[key];
|
||||
Vue.observable(recomputed);
|
||||
},
|
||||
destroyed() {
|
||||
EventHub.ui.offAll(this);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -185,6 +185,9 @@ Vue.use(VueGtag, {
|
|||
|
||||
export const ui = new Vue({
|
||||
el: "#ui",
|
||||
components: {
|
||||
GameUIComponent
|
||||
},
|
||||
data: state,
|
||||
computed: {
|
||||
notation() {
|
||||
|
@ -200,15 +203,6 @@ export const ui = new Vue({
|
|||
return this.view.newUI;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
scroll(t) {
|
||||
const now = Date.now();
|
||||
if (this.view.scrollWindow) {
|
||||
window.scrollBy(0, this.view.scrollWindow * (now - t) / 2);
|
||||
setTimeout(() => this.scroll(now), 20);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentGlyphTooltip(newVal) {
|
||||
if (newVal !== -1 && !GameUI.globalClickListener) {
|
||||
|
@ -229,5 +223,14 @@ export const ui = new Vue({
|
|||
}
|
||||
},
|
||||
},
|
||||
template: "<game-ui />"
|
||||
methods: {
|
||||
scroll(t) {
|
||||
const now = Date.now();
|
||||
if (this.view.scrollWindow) {
|
||||
window.scrollBy(0, this.view.scrollWindow * (now - t) / 2);
|
||||
setTimeout(() => this.scroll(now), 20);
|
||||
}
|
||||
}
|
||||
},
|
||||
template: "<GameUIComponent />"
|
||||
});
|
||||
|
|
|
@ -93,7 +93,7 @@ class AntimatterDimensionAutobuyerState extends UpgradeableAutobuyerState {
|
|||
buyOneDimension(tier);
|
||||
break;
|
||||
case AUTOBUYER_MODE.BUY_10:
|
||||
buyMaxDimension(tier, player.auto.bulkOn ? this.bulk : 1);
|
||||
buyMaxDimension(tier, this.bulk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -129,9 +129,10 @@ class AntimatterDimensionAutobuyerState extends UpgradeableAutobuyerState {
|
|||
static createAccessor() {
|
||||
const accessor = super.createAccessor();
|
||||
/** @returns {boolean} */
|
||||
accessor.allBought = () => accessor.zeroIndexed.some(x => x.isBought);
|
||||
accessor.allBought = () => accessor.zeroIndexed.every(x => x.isBought);
|
||||
/** @returns {boolean} */
|
||||
accessor.allUnlimitedBulk = () => accessor.zeroIndexed.some(x => x.hasUnlimitedBulk);
|
||||
// We can get away with this since allUnlimitedBulk is the same for all AD autos
|
||||
accessor.allUnlimitedBulk = () => accessor.zeroIndexed[0].hasUnlimitedBulk;
|
||||
accessor.bulkCap = accessor.zeroIndexed[0].bulkCap;
|
||||
return accessor;
|
||||
}
|
||||
|
|
|
@ -88,25 +88,23 @@ Autobuyer.bigCrunch = new class BigCrunchAutobuyerState extends UpgradeableAutob
|
|||
return PRESTIGE_EVENT.ETERNITY;
|
||||
}
|
||||
|
||||
get willInfinity() {
|
||||
if (!player.break || Player.isInAntimatterChallenge) return true;
|
||||
|
||||
switch (this.mode) {
|
||||
case AUTO_CRUNCH_MODE.AMOUNT:
|
||||
return gainedInfinityPoints().gte(this.amount);
|
||||
case AUTO_CRUNCH_MODE.TIME:
|
||||
return Time.thisInfinityRealTime.totalSeconds > this.time;
|
||||
case AUTO_CRUNCH_MODE.X_HIGHEST:
|
||||
default:
|
||||
return gainedInfinityPoints().gte(player.records.thisEternity.maxIP.times(this.xHighest));
|
||||
}
|
||||
}
|
||||
|
||||
tick() {
|
||||
super.tick();
|
||||
let proc = !player.break || Player.isInAntimatterChallenge;
|
||||
if (!proc) {
|
||||
switch (this.mode) {
|
||||
case AUTO_CRUNCH_MODE.AMOUNT:
|
||||
proc = gainedInfinityPoints().gte(this.amount);
|
||||
break;
|
||||
case AUTO_CRUNCH_MODE.TIME:
|
||||
proc = Time.thisInfinityRealTime.totalSeconds > this.time;
|
||||
break;
|
||||
case AUTO_CRUNCH_MODE.X_HIGHEST:
|
||||
proc = gainedInfinityPoints().gte(player.records.thisEternity.maxIP.times(this.xHighest));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (proc) {
|
||||
bigCrunchResetRequest(true);
|
||||
}
|
||||
if (this.willInfinity) bigCrunchResetRequest(true);
|
||||
}
|
||||
|
||||
reset() {
|
||||
|
|
|
@ -70,20 +70,23 @@ Autobuyer.eternity = new class EternityAutobuyerState extends AutobuyerState {
|
|||
}
|
||||
}
|
||||
|
||||
tick() {
|
||||
let proc = false;
|
||||
get willEternity() {
|
||||
// We Eternity asap if we're in an Eternity Challenge and can't reach more completions.
|
||||
if (EternityChallenge.current?.gainedCompletionStatus.hasMoreCompletions === false) return true;
|
||||
|
||||
switch (this.mode) {
|
||||
case AUTO_ETERNITY_MODE.AMOUNT:
|
||||
proc = EternityChallenge.isRunning || gainedEternityPoints().gte(this.amount);
|
||||
break;
|
||||
return gainedEternityPoints().gte(this.amount);
|
||||
case AUTO_ETERNITY_MODE.TIME:
|
||||
proc = Time.thisEternityRealTime.totalSeconds > this.time;
|
||||
break;
|
||||
return Time.thisEternityRealTime.totalSeconds > this.time;
|
||||
case AUTO_ETERNITY_MODE.X_HIGHEST:
|
||||
proc = gainedEternityPoints().gte(player.records.thisReality.maxEP.times(this.xHighest));
|
||||
break;
|
||||
default:
|
||||
return gainedEternityPoints().gte(player.records.thisReality.maxEP.times(this.xHighest));
|
||||
}
|
||||
if (proc) eternity(false, true);
|
||||
}
|
||||
|
||||
tick() {
|
||||
if (this.willEternity) eternity(false, true);
|
||||
}
|
||||
|
||||
reset() {
|
||||
|
|
|
@ -163,7 +163,6 @@ export class AutomatorScript {
|
|||
}
|
||||
|
||||
export const AutomatorData = {
|
||||
documentationSubpage: 0,
|
||||
// Used for getting the correct EC count in event log
|
||||
lastECCompletionCount: 0,
|
||||
// Used as a flag to make sure that wait commands only add one entry to the log instead of every execution attempt
|
||||
|
|
|
@ -94,6 +94,7 @@ import { AutomatorLexer } from "./lexer.js";
|
|||
{ regex: /t[1-4]/ui, token: "number" },
|
||||
{ regex: /(antimatter|infinity|time)(?=[\s,]|$)/ui, token: "variable-2" },
|
||||
{ regex: /(active|passive|idle)(?=[\s,]|$)/ui, token: "variable-2" },
|
||||
{ regex: /(light|dark)(?=[\s,]|$)/ui, token: "variable-2" },
|
||||
{ regex: /[a-zA-Z_][a-zA-Z_0-9]*/u, token: "variable", next: "commandDone" },
|
||||
{ regex: /[1-9][0-9]+/ui, token: "number" },
|
||||
],
|
||||
|
@ -146,6 +147,7 @@ import { AutomatorLexer } from "./lexer.js";
|
|||
{ regex: /(preset|eternity|reality|use)(\s|$)/ui, token: "variable-2" },
|
||||
{ regex: /(antimatter|infinity|time)(\s|$|(?=,))/ui, token: "variable-2" },
|
||||
{ regex: /(active|passive|idle)(\s|$|(?=,))/ui, token: "variable-2" },
|
||||
{ regex: /(light|dark)(\s|$|(?=,))/ui, token: "variable-2" },
|
||||
{ regex: /x[\t ]+highest(\s|$)/ui, token: "variable-2" },
|
||||
{ regex: /pending[\t ]+(completions|ip|ep|tp|rm|glyph[\t ]+level)(\s|$)/ui, token: "variable-2" },
|
||||
{ regex: /total[\t ]+(completions|tt)(\s|$)/ui, token: "variable-2" },
|
||||
|
|
|
@ -625,25 +625,31 @@ export const AutomatorCommands = ((() => {
|
|||
compile: ctx => {
|
||||
const studies = ctx.$studies;
|
||||
if (ctx.Nowait === undefined) return () => {
|
||||
let prePurchasedStudies = 0;
|
||||
let purchasedStudies = 0;
|
||||
let finalPurchasedTS;
|
||||
for (const tsNumber of studies.normal) {
|
||||
if (TimeStudy(tsNumber).isBought) continue;
|
||||
if (!TimeStudy(tsNumber).purchase()) {
|
||||
if (purchasedStudies > 0) {
|
||||
AutomatorData.logCommandEvent(`Purchased ${quantifyInt("Time Study", purchasedStudies)}
|
||||
and stopped at study ${tsNumber}, waiting to attempt to purchase more studies`, ctx.startLine);
|
||||
}
|
||||
return AUTOMATOR_COMMAND_STATUS.NEXT_TICK_SAME_INSTRUCTION;
|
||||
if (TimeStudy(tsNumber).isBought) prePurchasedStudies++;
|
||||
else if (TimeStudy(tsNumber).purchase()) purchasedStudies++;
|
||||
else finalPurchasedTS = finalPurchasedTS ?? tsNumber;
|
||||
}
|
||||
if (prePurchasedStudies + purchasedStudies < studies.normal.length) {
|
||||
if (prePurchasedStudies + purchasedStudies === 0) {
|
||||
AutomatorData.logCommandEvent(`Could not purchase any of the specified Time Studies`, ctx.startLine);
|
||||
}
|
||||
purchasedStudies++;
|
||||
if (purchasedStudies > 0 && finalPurchasedTS) {
|
||||
AutomatorData.logCommandEvent(`Purchased ${quantifyInt("Time Study", purchasedStudies)} and stopped at
|
||||
Time Study ${finalPurchasedTS}, waiting to attempt to purchase more Time Studies`, ctx.startLine);
|
||||
}
|
||||
return AUTOMATOR_COMMAND_STATUS.NEXT_TICK_SAME_INSTRUCTION;
|
||||
}
|
||||
if (!studies.ec || TimeStudy.eternityChallenge(studies.ec).isBought) {
|
||||
AutomatorData.logCommandEvent(`Purchased all specified time studies`, ctx.startLine);
|
||||
AutomatorData.logCommandEvent(`Purchased all specified Time Studies`, ctx.startLine);
|
||||
return AUTOMATOR_COMMAND_STATUS.NEXT_INSTRUCTION;
|
||||
}
|
||||
const unlockedEC = TimeStudy.eternityChallenge(studies.ec).purchase(true);
|
||||
if (unlockedEC) {
|
||||
AutomatorData.logCommandEvent(`Purchased all specified time studies and unlocked Eternity Challenge
|
||||
AutomatorData.logCommandEvent(`Purchased all specified Time Studies and unlocked Eternity Challenge
|
||||
${studies.ec}`, ctx.startLine);
|
||||
return AUTOMATOR_COMMAND_STATUS.NEXT_INSTRUCTION;
|
||||
}
|
||||
|
|
|
@ -230,6 +230,8 @@ export const AutomatorLexer = (() => {
|
|||
createInCategory(StudyPath, "Active", /active/i, { $studyPath: TIME_STUDY_PATH.ACTIVE });
|
||||
createInCategory(StudyPath, "Antimatter", /antimatter/i, { $studyPath: TIME_STUDY_PATH.ANTIMATTER_DIM });
|
||||
createInCategory(StudyPath, "Time", /time/i, { $studyPath: TIME_STUDY_PATH.TIME_DIM });
|
||||
createInCategory(StudyPath, "Light", /light/i, { $studyPath: TIME_STUDY_PATH.LIGHT });
|
||||
createInCategory(StudyPath, "Dark", /dark/i, { $studyPath: TIME_STUDY_PATH.DARK });
|
||||
|
||||
createInCategory(TimeUnit, "Milliseconds", /ms/i, {
|
||||
$autocomplete: "ms",
|
||||
|
|
|
@ -38,7 +38,13 @@ class PelleStrikeState extends GameMechanicState {
|
|||
if (this.id === 5) {
|
||||
Pelle.cel.records.totalAntimatter = new Decimal("1e180000");
|
||||
Pelle.cel.records.totalInfinityPoints = new Decimal("1e60000");
|
||||
Pelle.cel.records.totalEternityPoints = new Decimal("1e400");
|
||||
Currency.eternityPoints.reset();
|
||||
// Oddly specific number? Yes, it's roughly the amount of EP you have
|
||||
// when starting dilation for the first time
|
||||
// Since 5th strike previously did not reset your current EP the previous reset value was kind of useless which
|
||||
// lead to some balancing problems, this hopefully prevents people starting dilation too early and getting
|
||||
// softlocked, or starting it too late and getting not-softlocked.
|
||||
Pelle.cel.records.totalEternityPoints = new Decimal("1e1050");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +1,38 @@
|
|||
import { GameMechanicState } from "../../utils.js";
|
||||
import { CelestialQuotes } from "../quotes.js";
|
||||
|
||||
class RaPetState {
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
get data() { throw new NotImplementedError(); }
|
||||
class RaPetState extends GameMechanicState {
|
||||
get data() {
|
||||
return player.celestials.ra.pets[this.id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
get name() { throw new NotImplementedError(); }
|
||||
get name() {
|
||||
return this.config.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
get chunkGain() { throw new NotImplementedError(); }
|
||||
get chunkGain() {
|
||||
return this.config.chunkGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
get memoryGain() { throw new NotImplementedError(); }
|
||||
get memoryGain() {
|
||||
return this.config.memoryGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
get requiredUnlock() { throw new NotImplementedError(); }
|
||||
get color() {
|
||||
return this.config.color;
|
||||
}
|
||||
|
||||
get requiredUnlock() {
|
||||
return this.config.requiredUnlock?.();
|
||||
}
|
||||
|
||||
get rawMemoryChunksPerSecond() {
|
||||
return this.config.rawMemoryChunksPerSecond();
|
||||
}
|
||||
|
||||
get memoryProductionMultiplier() {
|
||||
return this.config.memoryProductionMultiplier();
|
||||
}
|
||||
|
||||
get isUnlocked() {
|
||||
return this.requiredUnlock === undefined || Ra.has(this.requiredUnlock);
|
||||
|
@ -62,16 +70,6 @@ class RaPetState {
|
|||
return Ra.requiredMemoriesForLevel(this.level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
get rawMemoryChunksPerSecond() { throw new NotImplementedError(); }
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
get color() { throw new NotImplementedError(); }
|
||||
|
||||
get memoryChunksPerSecond() {
|
||||
let res = this.canGetMemoryChunks ? this.rawMemoryChunksPerSecond : 0;
|
||||
res *= RA_UNLOCKS.TT_BOOST.effect.memoryChunks();
|
||||
|
@ -94,7 +92,6 @@ class RaPetState {
|
|||
|
||||
get chunkUpgradeCurrentMult() {
|
||||
return Math.pow(1.5, this.data.chunkUpgrades);
|
||||
|
||||
}
|
||||
|
||||
get memoryUpgradeCost() {
|
||||
|
@ -167,64 +164,10 @@ class RaPetState {
|
|||
|
||||
export const Ra = {
|
||||
displayName: "Ra",
|
||||
pets: {
|
||||
teresa: new class TeresaRaPetState extends RaPetState {
|
||||
get name() { return "Teresa"; }
|
||||
get chunkGain() { return "Eternity Points"; }
|
||||
get memoryGain() { return "current Reality Machines"; }
|
||||
get data() { return player.celestials.ra.pets.teresa; }
|
||||
get requiredUnlock() { return undefined; }
|
||||
get rawMemoryChunksPerSecond() { return 4 * Math.pow(Currency.eternityPoints.value.pLog10() / 1e4, 3); }
|
||||
get color() { return "#8596ea"; }
|
||||
get memoryProductionMultiplier() {
|
||||
return Ra.has(RA_UNLOCKS.TERESA_XP)
|
||||
? 1 + Math.pow(Currency.realityMachines.value.pLog10() / 100, 0.5)
|
||||
: 1;
|
||||
}
|
||||
}(),
|
||||
effarig: new class EffarigRaPetState extends RaPetState {
|
||||
get name() { return "Effarig"; }
|
||||
get chunkGain() { return "Relic Shards gained"; }
|
||||
get memoryGain() { return "best Glyph level"; }
|
||||
get data() { return player.celestials.ra.pets.effarig; }
|
||||
get requiredUnlock() { return RA_UNLOCKS.EFFARIG_UNLOCK; }
|
||||
get rawMemoryChunksPerSecond() { return 4 * Math.pow(Effarig.shardsGained, 0.1); }
|
||||
get color() { return "#ea8585"; }
|
||||
get memoryProductionMultiplier() {
|
||||
return Ra.has(RA_UNLOCKS.EFFARIG_XP)
|
||||
? 1 + player.records.bestReality.glyphLevel / 7000
|
||||
: 1;
|
||||
}
|
||||
}(),
|
||||
enslaved: new class EnslavedRaPetState extends RaPetState {
|
||||
get name() { return "Enslaved"; }
|
||||
get chunkGain() { return "Time Shards"; }
|
||||
get memoryGain() { return "total time played"; }
|
||||
get data() { return player.celestials.ra.pets.enslaved; }
|
||||
get requiredUnlock() { return RA_UNLOCKS.ENSLAVED_UNLOCK; }
|
||||
get rawMemoryChunksPerSecond() { return 4 * Math.pow(Currency.timeShards.value.pLog10() / 3e5, 2); }
|
||||
get color() { return "#f1aa7f"; }
|
||||
get memoryProductionMultiplier() {
|
||||
return Ra.has(RA_UNLOCKS.ENSLAVED_XP)
|
||||
? 1 + Math.log10(player.records.totalTimePlayed) / 200
|
||||
: 1;
|
||||
}
|
||||
}(),
|
||||
v: new class VRaPetState extends RaPetState {
|
||||
get name() { return "V"; }
|
||||
get chunkGain() { return "Infinity Power"; }
|
||||
get memoryGain() { return "total Memory levels"; }
|
||||
get data() { return player.celestials.ra.pets.v; }
|
||||
get requiredUnlock() { return RA_UNLOCKS.V_UNLOCK; }
|
||||
get rawMemoryChunksPerSecond() { return 4 * Math.pow(Currency.infinityPower.value.pLog10() / 1e7, 1.5); }
|
||||
get color() { return "#ead584"; }
|
||||
get memoryProductionMultiplier() {
|
||||
return Ra.has(RA_UNLOCKS.V_XP)
|
||||
? 1 + Ra.totalPetLevel / 50
|
||||
: 1;
|
||||
}
|
||||
}(),
|
||||
},
|
||||
pets: mapGameDataToObject(
|
||||
GameDatabase.celestials.ra,
|
||||
config => new RaPetState(config)
|
||||
),
|
||||
// Dev/debug function for easier testing
|
||||
reset() {
|
||||
const data = player.celestials.ra;
|
||||
|
@ -575,11 +518,6 @@ export const GlyphAlteration = {
|
|||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {RaPetState[]}
|
||||
*/
|
||||
Ra.pets.all = [Ra.pets.teresa, Ra.pets.effarig, Ra.pets.enslaved, Ra.pets.v];
|
||||
|
||||
export const RA_UNLOCKS = {
|
||||
AUTO_TP: {
|
||||
id: 0,
|
||||
|
|
|
@ -3,17 +3,22 @@ import { GameDatabase } from "./secret-formula/game-database";
|
|||
class ConfirmationState {
|
||||
constructor(config) {
|
||||
this.name = config.name;
|
||||
this.confirmationSetting = config.option;
|
||||
this._confirmationSetting = config.option;
|
||||
this.isUnlocked = config.isUnlocked;
|
||||
}
|
||||
|
||||
get option() {
|
||||
return player.options.confirmations[this.confirmationSetting];
|
||||
return player.options.confirmations[this._confirmationSetting];
|
||||
}
|
||||
|
||||
set option(value) {
|
||||
player.options.confirmations[this.confirmationSetting] = value;
|
||||
player.options.confirmations[this._confirmationSetting] = value;
|
||||
}
|
||||
}
|
||||
|
||||
export const ConfirmationTypes = GameDatabase.confirmationTypes.map(entry => new ConfirmationState(entry));
|
||||
export const ConfirmationTypes = GameDatabase.confirmationTypes.mapToObject(
|
||||
config => config.option,
|
||||
config => new ConfirmationState(config)
|
||||
);
|
||||
|
||||
ConfirmationTypes.index = Object.values(ConfirmationTypes);
|
||||
|
|
|
@ -108,7 +108,7 @@ dev.spin4d = function() {
|
|||
|
||||
dev.cancerize = function() {
|
||||
Theme.tryUnlock("Cancer");
|
||||
Notation.cancer.setAsCurrent();
|
||||
Notation.emoji.setAsCurrent();
|
||||
};
|
||||
|
||||
dev.fixSave = function() {
|
||||
|
|
|
@ -34,7 +34,8 @@ function giveEternityRewards(auto) {
|
|||
AutomatorData.lastECCompletionCount = completionCount;
|
||||
if (Enslaved.isRunning && completionCount > 5) EnslavedProgress.ec1.giveProgress();
|
||||
}
|
||||
player.etercreq = 0;
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.challenge.eternity.requirementBits &= ~(1 << challenge.id);
|
||||
respecTimeStudies(auto);
|
||||
}
|
||||
|
||||
|
@ -189,6 +190,9 @@ export class EternityMilestoneState {
|
|||
}
|
||||
|
||||
get isReached() {
|
||||
if (Pelle.isDoomed && this.config.pelleObsolete) {
|
||||
return this.config.pelleObsolete();
|
||||
}
|
||||
return Currency.eternities.gte(this.config.eternities);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ export class EternityChallengeState extends GameMechanicState {
|
|||
get gainedCompletionStatus() {
|
||||
const status = {
|
||||
gainedCompletions: 0,
|
||||
hasMoreCompletions: false,
|
||||
totalCompletions: this.completions,
|
||||
};
|
||||
if (this.isFullyCompleted) return status;
|
||||
|
|
|
@ -123,7 +123,7 @@ function galaxyReset() {
|
|||
player.galaxies++;
|
||||
if (!Achievement(143).isUnlocked) player.dimensionBoosts = 0;
|
||||
softReset(0);
|
||||
if (Notations.current === Notation.cancer) player.requirementChecks.permanent.cancerGalaxies++;
|
||||
if (Notations.current === Notation.emoji) player.requirementChecks.permanent.emojiGalaxies++;
|
||||
// This is specifically reset here because the check is actually per-galaxy and not per-infinity
|
||||
player.requirementChecks.infinity.noSacrifice = true;
|
||||
EventHub.dispatch(GAME_EVENT.GALAXY_RESET_AFTER);
|
||||
|
@ -145,8 +145,8 @@ function maxBuyGalaxies(limit = Number.MAX_VALUE) {
|
|||
const newGalaxies = Math.clampMax(
|
||||
Galaxy.buyableGalaxies(Math.round(dim.totalAmount.toNumber())),
|
||||
limit);
|
||||
if (Notations.current === Notation.cancer) {
|
||||
player.requirementChecks.permanent.cancerGalaxies += newGalaxies - player.galaxies;
|
||||
if (Notations.current === Notation.emoji) {
|
||||
player.requirementChecks.permanent.emojiGalaxies += newGalaxies - player.galaxies;
|
||||
}
|
||||
// Galaxy count is incremented by galaxyReset(), so add one less than we should:
|
||||
player.galaxies = newGalaxies - 1;
|
||||
|
|
|
@ -687,12 +687,12 @@ export function getRarity(x) {
|
|||
return GlyphRarities.find(e => x >= e.minStrength);
|
||||
}
|
||||
|
||||
export function getAdjustedGlyphLevel(glyph) {
|
||||
export function getAdjustedGlyphLevel(glyph, realityGlyphBoost = Glyphs.levelBoost) {
|
||||
const level = glyph.level;
|
||||
if (Pelle.isDoomed) return Math.min(level, Pelle.glyphMaxLevel);
|
||||
if (Enslaved.isRunning) return Math.max(level, Enslaved.glyphLevelMin);
|
||||
if (Effarig.isRunning) return Math.min(level, Effarig.glyphLevelCap);
|
||||
if (BASIC_GLYPH_TYPES.includes(glyph.type)) return level + Glyphs.levelBoost;
|
||||
if (BASIC_GLYPH_TYPES.includes(glyph.type)) return level + realityGlyphBoost;
|
||||
return level;
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ export const shortcuts = [
|
|||
},
|
||||
visible: true
|
||||
}, {
|
||||
name: "Open the shortcut list",
|
||||
name: "Open Hotkey List Modal",
|
||||
keys: ["?"],
|
||||
type: "bind",
|
||||
function: () => {
|
||||
|
@ -167,7 +167,7 @@ export const shortcuts = [
|
|||
},
|
||||
visible: true
|
||||
}, {
|
||||
name: "Open \"How to Play\" pop-up",
|
||||
name: "Open How To Play Modal",
|
||||
keys: ["h"],
|
||||
type: "bind",
|
||||
function: () => {
|
||||
|
@ -194,7 +194,7 @@ export const shortcuts = [
|
|||
},
|
||||
visible: true
|
||||
}, {
|
||||
name: "Close pop-up or open options",
|
||||
name: "Close Modal or open Options",
|
||||
keys: ["esc"],
|
||||
type: "bind",
|
||||
function: () => {
|
||||
|
|
|
@ -46,13 +46,13 @@ window.player = {
|
|||
eternity: {
|
||||
current: 0,
|
||||
unlocked: 0,
|
||||
requirementBits: 0,
|
||||
}
|
||||
},
|
||||
infinity: {
|
||||
upgradeBits: 0
|
||||
},
|
||||
auto: {
|
||||
bulkOn: true,
|
||||
autobuyersOn: true,
|
||||
disableContinuum: false,
|
||||
reality: {
|
||||
|
@ -232,7 +232,7 @@ window.player = {
|
|||
slowestBH: 1,
|
||||
},
|
||||
permanent: {
|
||||
cancerGalaxies: 0,
|
||||
emojiGalaxies: 0,
|
||||
singleTickspeed: 0,
|
||||
perkTreeDragging: 0
|
||||
}
|
||||
|
@ -378,7 +378,6 @@ window.player = {
|
|||
}),
|
||||
},
|
||||
eternityChalls: {},
|
||||
etercreq: 0,
|
||||
respec: false,
|
||||
eterc8ids: 50,
|
||||
eterc8repl: 40,
|
||||
|
@ -425,6 +424,7 @@ window.player = {
|
|||
glyphs: [],
|
||||
}),
|
||||
protectedRows: 2,
|
||||
createdRealityGlyph: false,
|
||||
},
|
||||
seed: Math.floor(Date.now() * Math.random() + 1),
|
||||
secondGaussian: 1e6,
|
||||
|
@ -798,7 +798,6 @@ window.player = {
|
|||
challenges: true,
|
||||
eternity: true,
|
||||
dilation: true,
|
||||
reality: true,
|
||||
resetReality: true,
|
||||
glyphReplace: true,
|
||||
glyphSacrifice: true,
|
||||
|
@ -835,7 +834,8 @@ window.player = {
|
|||
darkEnergy: true,
|
||||
singularities: true,
|
||||
celestialMemories: true,
|
||||
blackHole: true
|
||||
blackHole: true,
|
||||
realityShards: true
|
||||
},
|
||||
hiddenTabBits: 0,
|
||||
hiddenSubtabBits: Array.repeat(0, 11),
|
||||
|
|
|
@ -108,7 +108,7 @@ export function simulatedRealityCount(advancePartSimCounters) {
|
|||
*/
|
||||
export function requestManualReality() {
|
||||
if (GlyphSelection.active || !isRealityAvailable()) return;
|
||||
if (player.options.confirmations.reality || player.options.confirmations.glyphSelection) {
|
||||
if (player.options.confirmations.glyphSelection) {
|
||||
Modal.reality.show();
|
||||
return;
|
||||
}
|
||||
|
@ -577,7 +577,7 @@ export function finishProcessReality(realityProps) {
|
|||
player.reality.lastAutoEC = 0;
|
||||
player.challenge.eternity.current = 0;
|
||||
if (!PelleUpgrade.timeStudiesNoReset.canBeApplied) player.challenge.eternity.unlocked = 0;
|
||||
player.etercreq = 0;
|
||||
player.challenge.eternity.requirementBits = 0;
|
||||
player.respec = false;
|
||||
player.eterc8ids = 50;
|
||||
player.eterc8repl = 40;
|
||||
|
|
|
@ -57,8 +57,8 @@ GameDatabase.achievements.secret = [
|
|||
{
|
||||
id: 22,
|
||||
name: "Deep fried",
|
||||
get description() { return `Buy ${formatInt(1e5)} Antimatter Galaxies in total while using cancer notation.`; },
|
||||
checkRequirement: () => player.requirementChecks.permanent.cancerGalaxies >= 1e5,
|
||||
get description() { return `Buy ${formatInt(1e5)} Antimatter Galaxies in total while using emoji notation.`; },
|
||||
checkRequirement: () => player.requirementChecks.permanent.emojiGalaxies >= 1e5,
|
||||
checkEvent: GAME_EVENT.GALAXY_RESET_AFTER
|
||||
},
|
||||
{
|
||||
|
|
|
@ -123,5 +123,9 @@ GameDatabase.awayProgressTypes = [
|
|||
name: "singularities",
|
||||
reference: ["celestials", "laitela", "singularities"],
|
||||
isUnlocked: () => Laitela.isUnlocked,
|
||||
}, {
|
||||
name: "realityShards",
|
||||
reference: ["celestials", "pelle", "realityShards"],
|
||||
isUnlocked: () => Pelle.isDoomed,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -566,7 +566,7 @@ GameDatabase.celestials.navigation = (function() {
|
|||
clickAction: () => Tab.celestials.v.show(true),
|
||||
incompleteClass: "c-celestial-nav__test-incomplete",
|
||||
symbol: "⌬",
|
||||
symbolOffset: "0.25",
|
||||
symbolOffset: "2",
|
||||
fill: "#ffe066",
|
||||
position: Positions.vUnlockAchievement,
|
||||
ring: {
|
||||
|
@ -992,7 +992,7 @@ GameDatabase.celestials.navigation = (function() {
|
|||
clickAction: () => Tab.celestials.ra.show(true),
|
||||
incompleteClass: "c-celestial-nav__test-incomplete",
|
||||
symbol: "\uf185",
|
||||
symbolOffset: "0.25",
|
||||
symbolOffset: "2",
|
||||
fill: "#9063de",
|
||||
position: Positions.raReality,
|
||||
ring: {
|
||||
|
@ -1300,7 +1300,7 @@ GameDatabase.celestials.navigation = (function() {
|
|||
incompleteClass: "c-celestial-nav__test-incomplete",
|
||||
symbol: "ᛝ",
|
||||
symbolScale: 1.6,
|
||||
symbolOffset: "0.1",
|
||||
symbolOffset: "0.6",
|
||||
fill: "white",
|
||||
position: Positions.laitelaFirstCenter,
|
||||
ring: {
|
||||
|
@ -1384,7 +1384,7 @@ GameDatabase.celestials.navigation = (function() {
|
|||
if (upgrade.isAvailableForPurchase) return [
|
||||
dmdText,
|
||||
`Imaginary Machines
|
||||
${format(upgrade.currency.value.min(upgrade.cost), upgrade.canBeBought ? 0 : 2)}
|
||||
${format(Math.min(upgrade.currency.value, upgrade.cost), upgrade.canBeBought ? 0 : 2)}
|
||||
/ ${format(upgrade.cost)}`
|
||||
];
|
||||
|
||||
|
@ -1455,7 +1455,7 @@ GameDatabase.celestials.navigation = (function() {
|
|||
const upgrade = DarkMatterDimension(3).unlockUpgrade;
|
||||
if (upgrade.canBeBought || upgrade.isBought) return 1;
|
||||
if (upgrade.isAvailableForPurchase) return upgrade.currency.value / upgrade.cost;
|
||||
if (!player.celestials.laitela.automation.singularity) return 0.5;
|
||||
if (!player.auto.singularity.isActive) return 0.5;
|
||||
return Math.clampMax(0.999, Singularity.singularitiesGained / 20);
|
||||
},
|
||||
node: {
|
||||
|
@ -1482,11 +1482,11 @@ GameDatabase.celestials.navigation = (function() {
|
|||
if (upgrade.isAvailableForPurchase) return [
|
||||
dmdText,
|
||||
`Imaginary Machines
|
||||
${format(upgrade.currency.value.min(upgrade.cost), upgrade.canBeBought ? 0 : 2)}
|
||||
${format(Math.min(upgrade.currency.value, upgrade.cost), upgrade.canBeBought ? 0 : 2)}
|
||||
/ ${format(upgrade.cost)}`
|
||||
];
|
||||
|
||||
if (!player.celestials.laitela.automation.singularity) return [
|
||||
if (!player.auto.singularity.isActive) return [
|
||||
dmdText,
|
||||
"Unlock Automatic Singularities",
|
||||
`${format(Currency.singularities.value)} / ${format(SingularityMilestone.autoCondense.start)}`
|
||||
|
@ -1554,7 +1554,7 @@ GameDatabase.celestials.navigation = (function() {
|
|||
if (upgrade.isAvailableForPurchase) return [
|
||||
dmdText,
|
||||
`Imaginary Machines
|
||||
${format(upgrade.currency.value.min(upgrade.cost), upgrade.canBeBought ? 0 : 2)}
|
||||
${format(Math.min(upgrade.currency.value, upgrade.cost), upgrade.canBeBought ? 0 : 2)}
|
||||
/ ${format(upgrade.cost)}`
|
||||
];
|
||||
|
||||
|
@ -1623,7 +1623,7 @@ GameDatabase.celestials.navigation = (function() {
|
|||
incompleteClass: "c-celestial-nav__test-incomplete",
|
||||
symbol: "ᛝ",
|
||||
symbolScale: 1.6,
|
||||
symbolOffset: "0.1",
|
||||
symbolOffset: "0.6",
|
||||
fill: "white",
|
||||
position: Positions.laitelaThirdCenter,
|
||||
ring: {
|
||||
|
|
|
@ -168,16 +168,16 @@ GameDatabase.celestials.pelle.upgrades = (function() {
|
|||
cost: 1e26,
|
||||
formatCost,
|
||||
},
|
||||
dilationUpgradesNoReset: {
|
||||
dimBoostResetsNothing: {
|
||||
id: 18,
|
||||
description: "Keep Dilation Upgrades on Armageddon",
|
||||
cost: 1e45,
|
||||
description: "Dimension Boosts no longer reset anything",
|
||||
cost: 1e30,
|
||||
formatCost,
|
||||
},
|
||||
dimBoostResetsNothing: {
|
||||
dilationUpgradesNoReset: {
|
||||
id: 19,
|
||||
description: "Dimension Boosts no longer reset anything",
|
||||
cost: 1e50,
|
||||
description: "Keep Dilation Upgrades on Armageddon",
|
||||
cost: 1e45,
|
||||
formatCost,
|
||||
},
|
||||
tachyonParticlesNoReset: {
|
||||
|
|
52
javascripts/core/secret-formula/celestials/ra.js
Normal file
52
javascripts/core/secret-formula/celestials/ra.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { GameDatabase } from "../game-database.js";
|
||||
|
||||
GameDatabase.celestials.ra = {
|
||||
teresa: {
|
||||
id: "teresa",
|
||||
name: "Teresa",
|
||||
color: "#8596ea",
|
||||
chunkGain: "Eternity Points",
|
||||
memoryGain: "current Reality Machines",
|
||||
requiredUnlock: () => undefined,
|
||||
rawMemoryChunksPerSecond: () => 4 * Math.pow(Currency.eternityPoints.value.pLog10() / 1e4, 3),
|
||||
memoryProductionMultiplier: () => (Ra.has(RA_UNLOCKS.TERESA_XP)
|
||||
? 1 + Math.pow(Currency.realityMachines.value.pLog10() / 100, 0.5)
|
||||
: 1)
|
||||
},
|
||||
effarig: {
|
||||
id: "effarig",
|
||||
name: "Effarig",
|
||||
color: "#ea8585",
|
||||
chunkGain: "Relic Shards gained",
|
||||
memoryGain: "best Glyph level",
|
||||
requiredUnlock: () => RA_UNLOCKS.EFFARIG_UNLOCK,
|
||||
rawMemoryChunksPerSecond: () => 4 * Math.pow(Effarig.shardsGained, 0.1),
|
||||
memoryProductionMultiplier: () => (Ra.has(RA_UNLOCKS.EFFARIG_XP)
|
||||
? 1 + player.records.bestReality.glyphLevel / 7000
|
||||
: 1)
|
||||
},
|
||||
enslaved: {
|
||||
id: "enslaved",
|
||||
name: "Enslaved",
|
||||
color: "#f1aa7f",
|
||||
chunkGain: "Time Shards",
|
||||
memoryGain: "total time played",
|
||||
requiredUnlock: () => RA_UNLOCKS.ENSLAVED_UNLOCK,
|
||||
rawMemoryChunksPerSecond: () => 4 * Math.pow(Currency.timeShards.value.pLog10() / 3e5, 2),
|
||||
memoryProductionMultiplier: () => (Ra.has(RA_UNLOCKS.ENSLAVED_XP)
|
||||
? 1 + Math.log10(player.records.totalTimePlayed) / 200
|
||||
: 1)
|
||||
},
|
||||
v: {
|
||||
id: "v",
|
||||
name: "V",
|
||||
color: "#ead584",
|
||||
chunkGain: "Infinity Power",
|
||||
memoryGain: "total Memory levels",
|
||||
requiredUnlock: () => RA_UNLOCKS.V_UNLOCK,
|
||||
rawMemoryChunksPerSecond: () => 4 * Math.pow(Currency.infinityPower.value.pLog10() / 1e7, 1.5),
|
||||
memoryProductionMultiplier: () => (Ra.has(RA_UNLOCKS.V_XP)
|
||||
? 1 + Ra.totalPetLevel / 50
|
||||
: 1)
|
||||
}
|
||||
};
|
|
@ -76,10 +76,9 @@ GameDatabase.celestials.pelle.rifts = {
|
|||
{
|
||||
resource: "pestilence",
|
||||
requirement: 0.6,
|
||||
effectCondition: () => Replicanti.amount.gt(DC.E1300),
|
||||
description: () => `When Replicanti exceeds ${format(DC.E1300)},
|
||||
all Galaxies are ${formatPercents(0.1)} more effective`,
|
||||
effect: 1.1
|
||||
effect: () => (Replicanti.amount.gt(DC.E1300) ? 1.1 : 1)
|
||||
},
|
||||
{
|
||||
resource: "pestilence",
|
||||
|
|
|
@ -33,10 +33,6 @@ GameDatabase.confirmationTypes = [
|
|||
name: "Dilation",
|
||||
option: "dilation",
|
||||
isUnlocked: () => PlayerProgress.realityUnlocked() || !Currency.tachyonParticles.eq(0),
|
||||
}, {
|
||||
name: "Reality",
|
||||
option: "reality",
|
||||
isUnlocked: () => PlayerProgress.realityUnlocked(),
|
||||
}, {
|
||||
name: "Reset Reality",
|
||||
option: "resetReality",
|
||||
|
|
|
@ -143,7 +143,7 @@ GameDatabase.eternity.dilation = (function() {
|
|||
initialCost: 1e14,
|
||||
increment: 100,
|
||||
pelleOnly: true,
|
||||
description: () => `Multiply Dilated Time gain by ${format(5)}`,
|
||||
description: () => `${formatX(5)} Dilated Time gain`,
|
||||
effect: bought => Decimal.pow(5, bought),
|
||||
formatEffect: value => formatX(value, 2),
|
||||
formatCost: value => format(value, 2),
|
||||
|
|
|
@ -6,8 +6,9 @@ GameDatabase.eternity.timeStudies.dilation = [
|
|||
description: "Unlock Time Dilation",
|
||||
cost: 5000,
|
||||
requirement: () => {
|
||||
const ttRequirement = Currency.timeTheorems.max.gte(TimeStudy.dilation.totalTimeTheoremRequirement);
|
||||
if (Ra.has(RA_UNLOCKS.AUTO_DILATION_UNLOCK) &&
|
||||
Currency.timeTheorems.max.gte(TimeStudy.dilation.totalTimeTheoremRequirement) &&
|
||||
ttRequirement &&
|
||||
!isInCelestialReality() && !Pelle.isDoomed
|
||||
) {
|
||||
return true;
|
||||
|
@ -15,7 +16,6 @@ GameDatabase.eternity.timeStudies.dilation = [
|
|||
const tsRequirement = [231, 232, 233, 234].some(id => TimeStudy(id).isBought);
|
||||
if (Perk.bypassECDilation.isBought && !Pelle.isDoomed) return tsRequirement;
|
||||
const ecRequirement = EternityChallenge(11).isFullyCompleted && EternityChallenge(12).isFullyCompleted;
|
||||
const ttRequirement = Currency.timeTheorems.max.gte(TimeStudy.dilation.totalTimeTheoremRequirement);
|
||||
return tsRequirement && ecRequirement && ttRequirement;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1559,6 +1559,8 @@ Galaxies. Replicanti- or Tachyon Galaxies can't be spent for purchasing those up
|
|||
const tab = GameDatabase.h2p.tabs[i];
|
||||
tab.id = i;
|
||||
if (tab.alias === undefined) tab.alias = tab.name;
|
||||
|
||||
tab.searchTermsRelevance = {};
|
||||
}
|
||||
|
||||
const searchIndex = {};
|
||||
|
@ -1576,7 +1578,13 @@ Galaxies. Replicanti- or Tachyon Galaxies can't be spent for purchasing those up
|
|||
const addWord = (word, tab) => {
|
||||
const lowerCase = word.toLowerCase();
|
||||
for (let i = 0; i < lowerCase.length; i++) {
|
||||
addTerm(lowerCase.slice(0, i + 1), tab);
|
||||
const term = lowerCase.slice(0, i + 1);
|
||||
addTerm(term, tab);
|
||||
if (tab.searchTermsRelevance[term] === undefined) {
|
||||
tab.searchTermsRelevance[term] = ((i + 1) / lowerCase.length) ** 0.65;
|
||||
} else {
|
||||
tab.searchTermsRelevance[term] = Math.max(tab.searchTermsRelevance[term], ((i + 1) / lowerCase.length) ** 0.65);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1599,21 +1607,121 @@ Galaxies. Replicanti- or Tachyon Galaxies can't be spent for purchasing those up
|
|||
addPhrase(tab.alias, tab);
|
||||
}
|
||||
|
||||
GameDatabase.h2p.search = query => {
|
||||
if (query === "") return GameDatabase.h2p.tabs;
|
||||
const words = query.toLowerCase().split(" ").filter(str => str !== "");
|
||||
/* eslint-disable-next-line no-unused-vars*/
|
||||
const searchTerms = words.map((_word, i, arr) => arr.slice(0, arr.length - i).join(" "));
|
||||
const result = new Set();
|
||||
for (const searchWord of searchTerms) {
|
||||
const matches = searchIndex[searchWord];
|
||||
if (matches === undefined) continue;
|
||||
for (const match of matches) {
|
||||
result.add(match);
|
||||
const map2dToObject = function(arr, keyFun, valueFun) {
|
||||
const out = {};
|
||||
for (let idx1 = 0; idx1 < arr.length; idx1++) {
|
||||
for (let idx2 = 0; idx2 < arr[idx1].length; idx2++) {
|
||||
out[keyFun(arr[idx1][idx2], idx1, idx2)] = valueFun(arr[idx1][idx2], idx1, idx2);
|
||||
}
|
||||
}
|
||||
const results = Array.from(result);
|
||||
results.sort((a, b) => a.id - b.id);
|
||||
return out;
|
||||
};
|
||||
|
||||
// Very suboptimal code coming up. If anybody has a better solution, PLEASE, implement it.
|
||||
const keyboardify = keybrd => map2dToObject(keybrd.split(",").map(str => str.split("")),
|
||||
key => key, (_key, x, y) => ({ x, y }));
|
||||
|
||||
const qwerty = keyboardify(`1234567890,qwertyuiop,asdfghjkl,zxcvbnm`);
|
||||
const qwertz = keyboardify(`1234567890,qwertzuiop,asdfghjkl,yxcvbnm`);
|
||||
const azerty = keyboardify(`1234567890,azertyuiop,qsdfghjklm,wxcvbn`);
|
||||
const dvorak = keyboardify(`1234567890,'<>pyfgcrl,aoeuidhtns,;qjkxbmwvz`);
|
||||
const colemak = keyboardify(`1234567890,qwfpgjluy,arstdhneio,zxcvbkm`);
|
||||
const workman = keyboardify(`1234567890,qdrwbjfup,ashtgyneoi,zxmcvkl`);
|
||||
const qwprf = keyboardify(`1234567890,qwprfyukl,asdtghnioe,zxcvbjm`);
|
||||
|
||||
const keyboards = [qwerty, qwertz, azerty, dvorak, colemak, workman, qwprf];
|
||||
|
||||
const keyboardDist = function(a, b, keyboard) {
|
||||
const aPos = keyboard[a], bPos = keyboard[b];
|
||||
if (!aPos || !bPos) return 100;
|
||||
return Math.max(Math.abs(aPos.x - bPos.x), Math.abs(aPos.y - bPos.y));
|
||||
};
|
||||
|
||||
// I copied this code based on OSA distance off wikipedia, with a few added changes.
|
||||
// The cost for "substitution" (third item of the first Math.min) is replaced from a static value
|
||||
// to a function which roughly estimates how likely the user is to mispress the key based on its
|
||||
// minimum distance from several common keyboard layouts.
|
||||
// I have no idea how the actual "distance" calculation works but as long as it does don't touch it.
|
||||
const howBadlyTypoedWithKeyboard = function(a, b, keyboard) {
|
||||
// If they're the same, skip all calculations
|
||||
if (a === b) return 0;
|
||||
const aLen = a.length;
|
||||
const bLen = b.length;
|
||||
// If they're way too different, don't bother
|
||||
if (Math.abs(aLen - bLen) > 3) return 100;
|
||||
// 2d Array with dimensions aLen + 1 x bLen + 1
|
||||
const d = new Array(aLen + 1).fill(0).map(() => new Array(bLen + 1).fill(0));
|
||||
|
||||
for (let i = 0; i <= aLen; i++) {
|
||||
d[i][0] = i;
|
||||
}
|
||||
for (let i = 0; i <= bLen; i++) {
|
||||
d[0][i] = i;
|
||||
}
|
||||
|
||||
for (let i = 1; i <= aLen; i++) {
|
||||
for (let j = 1; j <= bLen; j++) {
|
||||
const distance = keyboardDist(a[i - 1], b[j - 1], keyboard);
|
||||
const cost = distance === 0 ? 0 : 0.3 + distance * distance * 0.25;
|
||||
d[i][j] = Math.min(
|
||||
d[i - 1][j] + 0.55,
|
||||
d[i][j - 1] + 0.7,
|
||||
d[i - 1][j - 1] + cost
|
||||
);
|
||||
}
|
||||
}
|
||||
return d[aLen][bLen];
|
||||
};
|
||||
|
||||
const howBadlyTypoed = function(a, b) {
|
||||
// Arbitrarily large number
|
||||
let minTypoed = 1e10;
|
||||
for (const keyboard of keyboards) {
|
||||
minTypoed = Math.min(minTypoed, howBadlyTypoedWithKeyboard(a, b, keyboard));
|
||||
}
|
||||
return minTypoed;
|
||||
};
|
||||
|
||||
const specialChars = ["'", "\"", ",", "-", ".", "_"];
|
||||
|
||||
const replaceSpecialChars = function(str) {
|
||||
let result = str;
|
||||
for (const i of specialChars) {
|
||||
result = result.replaceAll(i, "");
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// There are a LOT of magic numbers in this code, mostly from arbitrary choices for "What number is large enough to
|
||||
// act as a placeholder for 'basically not found'?"
|
||||
// This will need some cleanup if possible.
|
||||
GameDatabase.h2p.search = query => {
|
||||
const truncatedQuery = replaceSpecialChars(query);
|
||||
if (truncatedQuery === "") return GameDatabase.h2p.tabs.map(x => ({ tab: x, relevance: 1.5 }));
|
||||
const searchTerms = truncatedQuery.toLowerCase().split(" ").filter(str => str !== "");
|
||||
|
||||
// A higher "Relevance" value actually means it's further away from the search, important to keep in mind
|
||||
const relevances = Array.repeat(1e4, GameDatabase.h2p.tabs.length);
|
||||
for (const searchWord of searchTerms) {
|
||||
const minimumRequirement = Math.min(searchWord.length - 0.9, 3) * 0.5;
|
||||
for (const searchIndexStr in searchIndex) {
|
||||
const typoThreshold = howBadlyTypoed(replaceSpecialChars(searchIndexStr), searchWord);
|
||||
if (typoThreshold < minimumRequirement) {
|
||||
for (const tab of searchIndex[searchIndexStr]) {
|
||||
const maxRelevance = tab.searchTermsRelevance[searchIndexStr];
|
||||
const decrease = Math.max(maxRelevance * 1.6 - 0.9, 0);
|
||||
relevances[tab.id] = Math.min(relevances[tab.id], Math.max(typoThreshold, 1 - maxRelevance) - decrease);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const results = GameDatabase.h2p.tabs.filter(x => relevances[x.id] < 0.9)
|
||||
.map(x => ({ tab: x, relevance: relevances[x.id] }));
|
||||
// Provide both the relevance and the tab itself
|
||||
|
||||
// Sort by id first, then push more relevant results to top.
|
||||
results.sort((a, b) => a.tab.id - b.tab.id).sort((a, b) => a.relevance - b.relevance);
|
||||
// Provide both the relevance and the tab itself
|
||||
return results;
|
||||
};
|
||||
}());
|
||||
|
|
|
@ -29,6 +29,7 @@ import "./celestials/pelle-upgrades.js";
|
|||
import "./celestials/strikes.js";
|
||||
import "./celestials/rifts.js";
|
||||
import "./celestials/galaxy-generator.js";
|
||||
import "./celestials/ra.js";
|
||||
import "./celestials/pelle-quotes.js";
|
||||
import "./celestials/enslaved.js";
|
||||
export * from "./celestials/v.js";
|
||||
|
|
|
@ -2476,7 +2476,7 @@ GameDatabase.news = [
|
|||
{
|
||||
id: "l8",
|
||||
text: "A new group for the standardisation of numbers have come forward with a novel new format involving emoji's.",
|
||||
get unlocked() { return player.requirementChecks.permanent.cancerGalaxies > 0; }
|
||||
get unlocked() { return player.requirementChecks.permanent.emojiGalaxies > 0; }
|
||||
},
|
||||
{
|
||||
id: "l9",
|
||||
|
@ -2592,7 +2592,7 @@ GameDatabase.news = [
|
|||
{
|
||||
id: "l22",
|
||||
text: "Anti Emoji Movie a huge hit!",
|
||||
get unlocked() { return player.requirementChecks.permanent.cancerGalaxies >= 5; }
|
||||
get unlocked() { return player.requirementChecks.permanent.emojiGalaxies >= 5; }
|
||||
},
|
||||
{
|
||||
id: "l23",
|
||||
|
@ -2717,7 +2717,7 @@ GameDatabase.news = [
|
|||
{
|
||||
id: "l45",
|
||||
text: "Anti Emoji Movie MMMCMXCIX is a major hit!",
|
||||
get unlocked() { return player.requirementChecks.permanent.cancerGalaxies >= 3999; }
|
||||
get unlocked() { return player.requirementChecks.permanent.emojiGalaxies >= 3999; }
|
||||
},
|
||||
{
|
||||
id: "l46",
|
||||
|
|
|
@ -359,7 +359,7 @@ GameDatabase.reality.automator = {
|
|||
for example 71, 72, and 73 before the Dimension Split Dilation upgrade is purchased.<br>
|
||||
The Time Study list here has more flexibility and can consist of Time Study numbers, separated by
|
||||
spaces or commas, ranges of studies (for example, <i>11-62</i>) and the following aliases:<br>
|
||||
<blockquote><b>antimatter, infinity, time, active, passive, idle</b></blockquote>
|
||||
<blockquote><b>antimatter, infinity, time, active, passive, idle, light, dark</b></blockquote>
|
||||
A variable name may be used in place of Time Study list, see <b>define</b>.`,
|
||||
examples: [
|
||||
"studies nowait 11,21,31",
|
||||
|
|
|
@ -47,7 +47,7 @@ GameDatabase.speedrunMilestones = [
|
|||
name: "Break Infinity",
|
||||
description: "Break Infinity for the first time",
|
||||
checkRequirement: () => player.break,
|
||||
checkEverokennt: GAME_EVENT.BREAK_INFINITY,
|
||||
checkEvent: GAME_EVENT.BREAK_INFINITY,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
|
@ -199,7 +199,7 @@ GameDatabase.speedrunMilestones = [
|
|||
key: "completeFullGame",
|
||||
name: "Game Completed!",
|
||||
description: "Complete the entire game",
|
||||
checkRequirement: () => true,
|
||||
checkEvent: GAME_EVENT.ACHIEVEMENT_EVENT_OTHER,
|
||||
checkRequirement: () => Achievement(188).isUnlocked,
|
||||
checkEvent: GAME_EVENT.ACHIEVEMENT_UNLOCKED,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -475,7 +475,7 @@ GameDatabase.tabs = [
|
|||
key: "shop",
|
||||
name: "Shop",
|
||||
symbol: "$",
|
||||
component: "shop-tab",
|
||||
component: "ShopTab",
|
||||
id: 0,
|
||||
hidable: true
|
||||
}
|
||||
|
|
|
@ -1292,6 +1292,25 @@ GameStorage.devMigrations = {
|
|||
delete player.celestials.laitela.darkAutobuyerTimer;
|
||||
delete player.celestials.laitela.autoAnnihilationSetting;
|
||||
},
|
||||
GameStorage.migrations.etercreqConversion,
|
||||
player => {
|
||||
delete player.options.confirmations.reality;
|
||||
},
|
||||
player => {
|
||||
const hasDimboost = player.celestials.pelle.upgrades.has(19);
|
||||
const hasDilUpg = player.celestials.pelle.upgrades.has(18);
|
||||
player.celestials.pelle.upgrades.delete(18);
|
||||
player.celestials.pelle.upgrades.delete(19);
|
||||
if (hasDimboost) player.celestials.pelle.upgrades.add(18);
|
||||
if (hasDilUpg) player.celestials.pelle.upgrades.add(19);
|
||||
},
|
||||
player => {
|
||||
delete player.auto.bulkOn;
|
||||
},
|
||||
player => {
|
||||
player.requirementChecks.permanent.emojiGalaxies = player.requirementChecks.permanent.cancerGalaxies;
|
||||
delete player.requirementChecks.permanent.cancerGalaxies;
|
||||
}
|
||||
],
|
||||
|
||||
patch(player) {
|
||||
|
|
|
@ -147,6 +147,7 @@ GameStorage.migrations = {
|
|||
GameStorage.migrations.deleteFloatingTextOption(player);
|
||||
GameStorage.migrations.refactorDoubleIPRebuyable(player);
|
||||
GameStorage.migrations.convertNews(player);
|
||||
GameStorage.migrations.etercreqConversion(player);
|
||||
|
||||
kong.migratePurchases();
|
||||
}
|
||||
|
@ -364,6 +365,8 @@ GameStorage.migrations = {
|
|||
player.challenge.eternity.unlocked !== 0
|
||||
) player.requirementChecks.reality.noPurchasedTT = false;
|
||||
if (player.sacrificed.gt(0)) player.requirementChecks.infinity.noSacrifice = false;
|
||||
player.requirementChecks.permanent.emojiGalaxies = player.spreadingCancer;
|
||||
delete player.spreadingCancer;
|
||||
},
|
||||
|
||||
adjustThemes(player) {
|
||||
|
@ -815,7 +818,6 @@ GameStorage.migrations = {
|
|||
},
|
||||
|
||||
migrateAutobuyers(player) {
|
||||
player.auto.bulkOn = player.options.bulkOn;
|
||||
player.auto.autobuyerOn = player.options.autobuyerOn;
|
||||
|
||||
delete player.options.bulkOn;
|
||||
|
@ -901,6 +903,12 @@ GameStorage.migrations = {
|
|||
delete player.infMult;
|
||||
},
|
||||
|
||||
etercreqConversion(player) {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
if (player.etercreq) player.challenge.eternity.requirementBits |= 1 << player.etercreq;
|
||||
delete player.etercreq;
|
||||
},
|
||||
|
||||
prePatch(saveData) {
|
||||
// Initialize all possibly undefined properties that were not present in
|
||||
// previous versions and which could be overwritten by deepmerge
|
||||
|
|
|
@ -33,7 +33,8 @@ export class ECTimeStudyState extends TimeStudyState {
|
|||
if (!auto) {
|
||||
Tab.challenges.eternity.show();
|
||||
}
|
||||
player.etercreq = this.id;
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.challenge.eternity.requirementBits |= 1 << this.id;
|
||||
Currency.timeTheorems.subtract(this.cost);
|
||||
TimeStudyTree.commitToGameState([TimeStudy.eternityChallenge(this.id)]);
|
||||
return true;
|
||||
|
@ -47,15 +48,18 @@ export class ECTimeStudyState extends TimeStudyState {
|
|||
171, 171, 171,
|
||||
143, 42, 121,
|
||||
111, 123, 151,
|
||||
181, 212, 214
|
||||
181, 181, 181
|
||||
];
|
||||
TimeStudyTree.commitToGameState(buyStudiesUntil(studiesToBuy[this.id]));
|
||||
// For EC 11 and 12, we can't choose between light and dark, but we can buy the
|
||||
// pair of row 21 things
|
||||
// If the player shift clicks an EC study that is immediately buyable, we try to
|
||||
// buy it first - in case buying studies up to that point renders it unaffordable.
|
||||
this.purchase();
|
||||
TimeStudyTree.commitToGameState(buyStudiesUntil(studiesToBuy[this.id], this.id));
|
||||
// For EC 11 and 12, we can't choose between light and dark,
|
||||
// but we can buy the 191/193
|
||||
if (this.id === 11) {
|
||||
TimeStudy(211).purchase();
|
||||
TimeStudy(191).purchase();
|
||||
} else if (this.id === 12) {
|
||||
TimeStudy(213).purchase();
|
||||
TimeStudy(193).purchase();
|
||||
}
|
||||
this.purchase();
|
||||
}
|
||||
|
@ -105,13 +109,18 @@ export class ECTimeStudyState extends TimeStudyState {
|
|||
}
|
||||
|
||||
get isEntryGoalMet() {
|
||||
if (player.etercreq === this.id) return true;
|
||||
if (this.wasRequirementPreviouslyMet) return true;
|
||||
if (this.config.secondary.forbiddenStudies) return true;
|
||||
const current = this.requirementCurrent;
|
||||
const total = this.requirementTotal;
|
||||
return typeof current === "number" ? current >= total : current.gte(total);
|
||||
}
|
||||
|
||||
get wasRequirementPreviouslyMet() {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return (player.challenge.eternity.requirementBits & (1 << this.id)) !== 0;
|
||||
}
|
||||
|
||||
invalidateRequirement() {
|
||||
this.cachedCurrentRequirement = undefined;
|
||||
}
|
||||
|
|
|
@ -116,25 +116,34 @@ TimeStudy.boughtNormalTS = function() {
|
|||
};
|
||||
|
||||
TimeStudy.preferredPaths = {
|
||||
get dimensionPath() {
|
||||
return {
|
||||
path: player.timestudy.preferredPaths[0],
|
||||
studies: player.timestudy.preferredPaths[0].reduce((acc, path) =>
|
||||
acc.concat(NormalTimeStudies.paths[path]), [])
|
||||
};
|
||||
dimension: {
|
||||
get path() {
|
||||
return player.timestudy.preferredPaths[0];
|
||||
},
|
||||
set path(value) {
|
||||
const options = [1, 2, 3];
|
||||
player.timestudy.preferredPaths[0] = value.filter(id => options.includes(id));
|
||||
},
|
||||
get studies() {
|
||||
return player.timestudy.preferredPaths[0].flatMap(path => NormalTimeStudies.paths[path]);
|
||||
},
|
||||
get usePriority() {
|
||||
return this.path.length > 1 ||
|
||||
TimeStudy(201).isBought ||
|
||||
DilationUpgrade.timeStudySplit.isBought ||
|
||||
PlayerProgress.realityUnlocked();
|
||||
}
|
||||
},
|
||||
set dimensionPath(value) {
|
||||
const options = [1, 2, 3];
|
||||
player.timestudy.preferredPaths[0] = value.filter(id => options.includes(id));
|
||||
},
|
||||
get pacePath() {
|
||||
return {
|
||||
path: player.timestudy.preferredPaths[1],
|
||||
studies: NormalTimeStudies.paths[player.timestudy.preferredPaths[1]]
|
||||
};
|
||||
},
|
||||
set pacePath(value) {
|
||||
const options = [4, 5, 6];
|
||||
player.timestudy.preferredPaths[1] = options.includes(value) ? value : 0;
|
||||
pace: {
|
||||
get path() {
|
||||
return player.timestudy.preferredPaths[1];
|
||||
},
|
||||
set path(value) {
|
||||
const options = [4, 5, 6];
|
||||
player.timestudy.preferredPaths[1] = options.includes(value) ? value : 0;
|
||||
},
|
||||
get studies() {
|
||||
return NormalTimeStudies.paths[player.timestudy.preferredPaths[1]];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import { GameMechanicState } from "../game-mechanics/index.js";
|
||||
|
||||
// This is only ever called from manual player actions, which means we can immediately commit them to the game state
|
||||
export function buyStudiesUntil(id, repeatFor201 = true) {
|
||||
const studyArray = [];
|
||||
// eslint-disable-next-line complexity
|
||||
export function buyStudiesUntil(id, ec = -1) {
|
||||
let studyArray = [];
|
||||
const lastInPrevRow = Math.floor(id / 10) * 10 - 1;
|
||||
const requestedPath = TimeStudy(id).path;
|
||||
const currTree = GameCache.currentStudyTree.value;
|
||||
// Makes an array [start, start+1, ... , end], empty if end < start
|
||||
const range = (start, end) => [...Array(Math.clampMin(end - start + 1, 0)).keys()].map(i => i + start);
|
||||
const ecHasRequirement = !Perk.studyECRequirement.isBought;
|
||||
|
||||
// If the player tries to buy a study which is immediately buyable, we try to buy it first in case buying other
|
||||
// studies up to that point renders it unaffordable. Effectively the clicked study is higher priority than all others
|
||||
|
@ -17,34 +19,43 @@ export function buyStudiesUntil(id, repeatFor201 = true) {
|
|||
// split, then we're done and don't need to attempt to buy any more
|
||||
studyArray.push(...range(11, Math.min(lastInPrevRow, 70)));
|
||||
studyArray.push(id);
|
||||
|
||||
if (id < 71) return studyArray;
|
||||
|
||||
// Priority for behavior when buying in the Dimension split; we follow only the first applicable entry below:
|
||||
// - If we're buying a study within the split, we first buy just the requested path up to the requested study.
|
||||
// If we still have additional available paths at this point, we also buy others in order specified first by the
|
||||
// player's chosen priority and then numerically (stops buying)
|
||||
// - If we can't buy any additional paths or have 3 paths available, we attempt to buy everything here. With less
|
||||
// than 3 paths available, this only purchases the rest of any unfinished paths (continues onward)
|
||||
// - If we want to buy EC11 or EC12 we only buy the required dimension path unless we have the EC requirement perk
|
||||
// (continues onward)
|
||||
// - If we can't buy any additional paths or have 3 paths available, we attempt to buy everything here, prioritizing
|
||||
// preferred paths. With less than 3 paths available, this only purchases the rest of any unfinished paths
|
||||
// (continues onward)
|
||||
// - If the player has a preferred path, we attempt to buy it (continues onward)
|
||||
// - If the player doesn't have a preferred path, we say so and do nothing (stops buying)
|
||||
if (id < 111) {
|
||||
studyArray.push(...NormalTimeStudies.paths[requestedPath].filter(s => s <= id));
|
||||
studyArray.push(...NormalTimeStudies.paths[requestedPath].filter(s => (s <= id)));
|
||||
// The purchasing logic is doing the heavy lifting here; studies can't be double-bought, nor can they be bought
|
||||
// if we don't have another available path
|
||||
const pathBuyOrder = TimeStudy.preferredPaths.dimensionPath.path
|
||||
const pathBuyOrder = TimeStudy.preferredPaths.dimension.path
|
||||
.concat([TIME_STUDY_PATH.ANTIMATTER_DIM, TIME_STUDY_PATH.INFINITY_DIM, TIME_STUDY_PATH.TIME_DIM]);
|
||||
for (const path of pathBuyOrder) {
|
||||
studyArray.push(...NormalTimeStudies.paths[path].filter(s => s <= lastInPrevRow));
|
||||
}
|
||||
return studyArray;
|
||||
}
|
||||
if (currTree.currDimPathCount === currTree.allowedDimPathCount || currTree.allowedDimPathCount === 3) {
|
||||
studyArray.push(...TimeStudy.preferredPaths.dimensionPath.studies);
|
||||
studyArray.push(...range(71, 120));
|
||||
} else if (TimeStudy.preferredPaths.dimensionPath.path.length > 0) {
|
||||
studyArray.push(...TimeStudy.preferredPaths.dimensionPath.studies);
|
||||
|
||||
if (ec === 11 && ecHasRequirement) {
|
||||
studyArray.push(...NormalTimeStudies.paths[TIME_STUDY_PATH.ANTIMATTER_DIM].filter(s => (s <= id)));
|
||||
} else if (ec === 12 && ecHasRequirement) {
|
||||
studyArray.push(...NormalTimeStudies.paths[TIME_STUDY_PATH.TIME_DIM].filter(s => (s <= id)));
|
||||
} else if (currTree.currDimPathCount === currTree.allowedDimPathCount || currTree.allowedDimPathCount === 3) {
|
||||
studyArray.push(...TimeStudy.preferredPaths.dimension.studies);
|
||||
studyArray.push(...range(71, 103));
|
||||
} else if (TimeStudy.preferredPaths.dimension.path.length > 0) {
|
||||
studyArray.push(...TimeStudy.preferredPaths.dimension.studies);
|
||||
} else {
|
||||
GameUI.notify.error("You haven't selected a preferred Dimension path!");
|
||||
GameUI.notify.error("You haven't selected a preferred Dimension path.");
|
||||
return studyArray;
|
||||
}
|
||||
|
||||
|
@ -61,12 +72,14 @@ export function buyStudiesUntil(id, repeatFor201 = true) {
|
|||
// - If we have a preferred path, we buy it all (continues onward)
|
||||
// - If we don't have any pace paths at this point, there's no way to objectively choose one (stops buying)
|
||||
// - Fallback case: we have more than one path and intentionally do nothing here (continues onward)
|
||||
const pacePaths = currTree.pacePaths
|
||||
.map(pathName => NormalTimeStudies.pathList.find(p => p.name === pathName).path);
|
||||
|
||||
if (id < 151) {
|
||||
studyArray.push(...NormalTimeStudies.paths[TimeStudy(id).path].filter(s => s <= id));
|
||||
studyArray.push(...NormalTimeStudies.paths[TimeStudy(id).path].filter(s => (s <= id)));
|
||||
return studyArray;
|
||||
}
|
||||
|
||||
const pacePaths = currTree.pacePaths
|
||||
.map(pathName => NormalTimeStudies.pathList.find(p => p.name === pathName).path);
|
||||
if (V.isFullyCompleted && !Pelle.isDoomed) {
|
||||
const allPace = NormalTimeStudies.paths[TIME_STUDY_PATH.ACTIVE]
|
||||
.concat(NormalTimeStudies.paths[TIME_STUDY_PATH.PASSIVE])
|
||||
|
@ -74,23 +87,38 @@ export function buyStudiesUntil(id, repeatFor201 = true) {
|
|||
studyArray.push(...allPace);
|
||||
} else if (pacePaths.length === 1) {
|
||||
studyArray.push(...NormalTimeStudies.paths[pacePaths[0]]);
|
||||
} else if (TimeStudy.preferredPaths.pacePath.path !== 0) {
|
||||
studyArray.push(...TimeStudy.preferredPaths.pacePath.studies);
|
||||
} else if (TimeStudy.preferredPaths.pace.path !== 0) {
|
||||
studyArray.push(...TimeStudy.preferredPaths.pace.studies);
|
||||
} else if (pacePaths.length === 0) {
|
||||
GameUI.notify.error("You haven't selected a preferred Pace path!");
|
||||
GameUI.notify.error("You haven't selected a preferred Pace path.");
|
||||
return studyArray;
|
||||
}
|
||||
|
||||
// Buy up to 201, then if applicable we commit what we have to the game state and recursively call this function
|
||||
// again in order to attempt to buy another path
|
||||
// First we buy up to 201 so we can buy the second preferred path if needed
|
||||
studyArray.push(...range(151, Math.min(id, 201)));
|
||||
if (id >= 201 && repeatFor201) {
|
||||
TimeStudyTree.commitToGameState(studyArray);
|
||||
return buyStudiesUntil(id, false);
|
||||
}
|
||||
if (id < 201) return studyArray;
|
||||
studyArray.push(...range(211, Math.min(id, 214)));
|
||||
studyArray.push(id);
|
||||
|
||||
// If we want to buy EC11 or EC12 we don't want 201 unless we have the EC study requirement perk
|
||||
if (!(ecHasRequirement && (ec === 11 || ec === 12))) {
|
||||
// We need to commit what we have to the game state, because the check for priorityRequirement
|
||||
// requires us knowing if we have actually purchased 201.
|
||||
TimeStudyTree.commitToGameState(studyArray);
|
||||
studyArray = [];
|
||||
|
||||
// Buy the second preferred dimension path if we have one, otherwise show a warning if
|
||||
// the player can choose the second preferred dimension path and hasn't yet done so.
|
||||
if (TimeStudy.preferredPaths.dimension.path.length > 1) {
|
||||
studyArray.push(...TimeStudy.preferredPaths.dimension.studies.filter(s => (s <= id)));
|
||||
} else if (GameCache.currentStudyTree.value.allowedDimPathCount === 2) {
|
||||
GameUI.notify.error("You haven't selected a second preferred Dimension path.");
|
||||
}
|
||||
|
||||
studyArray.push(...range(211, Math.min(lastInPrevRow, 214)));
|
||||
|
||||
// If the user clicked on a study in rows 19-22, we've tried to buy up to the previous
|
||||
// row. Try to buy that study now:
|
||||
studyArray.push(id);
|
||||
}
|
||||
|
||||
// Don't bother buying any more studies at or below row 22 unless the player has fully finished V, in which case just
|
||||
// brute-force all of them up to the specified study. This buys all pre-triads, then triads sequentially up to the id
|
||||
|
|
|
@ -57,7 +57,9 @@ export class TimeStudyTree {
|
|||
if (input.trim() === "") {
|
||||
return false;
|
||||
}
|
||||
return /^(,?(\d+(-\d+)?|antimatter|infinity|time|active|passive|idle))*(\|\d+)?$/iu.test(input);
|
||||
let test = input.replaceAll(/ +/gu, "");
|
||||
TimeStudyTree.sets.forEach((_, x) => test = test.replaceAll(new RegExp(`${x},?`, "gu"), ""));
|
||||
return /^,?((\d{2,3}(-\d{2,3})?)\b,?)*(\|\d{0,2})?$/iu.test(test);
|
||||
}
|
||||
|
||||
// Getter for all the studies in the current game state
|
||||
|
@ -80,6 +82,46 @@ export class TimeStudyTree {
|
|||
GameCache.currentStudyTree.invalidate();
|
||||
}
|
||||
|
||||
static get sets() {
|
||||
// Grouping of studies. The key followed by an array of the studies the key is a shorthand for.
|
||||
return new Map([
|
||||
["antimatter", [71, 81, 91, 101]],
|
||||
["infinity", [72, 82, 92, 102]],
|
||||
["time", [73, 83, 93, 103]],
|
||||
["active", [121, 131, 141]],
|
||||
["passive", [122, 132, 142]],
|
||||
["idle", [123, 133, 143]],
|
||||
["light", [221, 223, 225, 227, 231, 233]],
|
||||
["dark", [222, 224, 226, 228, 232, 234]],
|
||||
]);
|
||||
}
|
||||
|
||||
static truncateInput(input) {
|
||||
let internal = input.toLowerCase();
|
||||
// Convert every name into the ids it is a shorthand for
|
||||
this.sets.forEach((ids, name) => (internal = internal.replace(name, ids.join())));
|
||||
return internal
|
||||
.replace(/[|,]$/u, "")
|
||||
.replaceAll(" ", "");
|
||||
}
|
||||
|
||||
static formatStudyList(input) {
|
||||
let internal = input.toLowerCase().replaceAll(" ", "");
|
||||
// \\b means 0-width word boundry, meaning "target = 11" doesnt match 111
|
||||
const testRegex = target => new RegExp(`\\b${target}\\b,?`, "gu");
|
||||
// If the studylist has all IDs, replace the first instance with the shorthand, then remove the rest
|
||||
this.sets.forEach((ids, name) => {
|
||||
const hasAllIds = ids.every(x => testRegex(x).test(internal));
|
||||
if (hasAllIds) {
|
||||
internal = internal.replace(testRegex(ids[0]), `${name},`);
|
||||
for (const i of ids) {
|
||||
internal = internal.replace(testRegex(i), "");
|
||||
}
|
||||
}
|
||||
});
|
||||
return internal.replaceAll(",", ", ");
|
||||
}
|
||||
|
||||
// This reads off all the studies in the import string and splits them into invalid and valid study IDs. We hold on
|
||||
// to invalid studies for additional information to present to the player
|
||||
parseStudyImport(input) {
|
||||
|
@ -119,33 +161,6 @@ export class TimeStudyTree {
|
|||
return output;
|
||||
}
|
||||
|
||||
static truncateInput(input) {
|
||||
return input
|
||||
.toLowerCase()
|
||||
.replaceAll("antimatter", "71,81,91,101")
|
||||
.replaceAll("infinity", "72,82,92,102")
|
||||
.replaceAll("time", "73,83,93,103")
|
||||
.replaceAll("active", "121,131,141")
|
||||
.replaceAll("passive", "122,132,142")
|
||||
.replaceAll("idle", "123,133,143")
|
||||
.replace(/[|,]$/u, "")
|
||||
.replaceAll(" ", "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
static formatStudyList(input) {
|
||||
return input
|
||||
.toLowerCase()
|
||||
.replaceAll("71,81,91,101", "antimatter")
|
||||
.replaceAll("72,82,92,102", "infinity")
|
||||
.replaceAll("73,83,93,103", "time")
|
||||
.replaceAll("121,131,141", "active")
|
||||
.replaceAll("122,132,142", "passive")
|
||||
.replaceAll("123,133,143", "idle")
|
||||
.replaceAll(",", ", ")
|
||||
.replace(/ +/gu, " ");
|
||||
}
|
||||
|
||||
studyRangeToArray(firstNumber, lastNumber) {
|
||||
const studiesArray = [];
|
||||
const first = this.checkTimeStudyNumber(firstNumber);
|
||||
|
|
|
@ -118,17 +118,20 @@ export function gainedInfinityPoints() {
|
|||
}
|
||||
|
||||
function totalEPMult() {
|
||||
return new Decimal(getAdjustedGlyphEffect("cursedEP"))
|
||||
.times(ShopPurchase.EPPurchases.currentMult)
|
||||
.timesEffectsOf(
|
||||
EternityUpgrade.epMult,
|
||||
TimeStudy(61),
|
||||
TimeStudy(122),
|
||||
TimeStudy(121),
|
||||
TimeStudy(123),
|
||||
RealityUpgrade(12),
|
||||
GlyphEffect.epMult
|
||||
);
|
||||
const totalMult = new Decimal(NG.multiplier);
|
||||
return Pelle.isDisabled("EPMults")
|
||||
? totalMult.times(Pelle.specialGlyphEffect.time.timesEffectOf(PelleRifts.famine.milestones[2]))
|
||||
: totalMult.times(getAdjustedGlyphEffect("cursedEP"))
|
||||
.times(ShopPurchase.EPPurchases.currentMult)
|
||||
.timesEffectsOf(
|
||||
EternityUpgrade.epMult,
|
||||
TimeStudy(61),
|
||||
TimeStudy(122),
|
||||
TimeStudy(121),
|
||||
TimeStudy(123),
|
||||
RealityUpgrade(12),
|
||||
GlyphEffect.epMult
|
||||
);
|
||||
}
|
||||
|
||||
export function gainedEternityPoints() {
|
||||
|
@ -136,14 +139,6 @@ export function gainedEternityPoints() {
|
|||
let ep = DC.D5.pow(player.records.thisEternity.maxIP.plus(
|
||||
gainedInfinityPoints()).log10() / (308 - PelleRifts.war.effectValue.toNumber()) - 0.7).times(totalEPMult());
|
||||
|
||||
ep = ep.times(NG.multiplier);
|
||||
|
||||
const pelleMults = Pelle.specialGlyphEffect.time.timesEffectOf(
|
||||
PelleRifts.famine.milestones[2]
|
||||
);
|
||||
|
||||
if (Pelle.isDisabled("EPMults")) return ep.dividedBy(totalEPMult()).times(pelleMults).pow(pow).floor();
|
||||
|
||||
if (Teresa.isRunning) {
|
||||
ep = ep.pow(0.55);
|
||||
} else if (V.isRunning) {
|
||||
|
@ -155,17 +150,11 @@ export function gainedEternityPoints() {
|
|||
ep = ep.pow(getSecondaryGlyphEffect("timeEP"));
|
||||
}
|
||||
|
||||
ep = ep.pow(pow);
|
||||
return ep.floor();
|
||||
return ep.pow(pow).floor();
|
||||
}
|
||||
|
||||
export function requiredIPForEP(epAmount) {
|
||||
const pelleMults = Pelle.specialGlyphEffect.time.timesEffectOf(PelleRifts.famine.milestones[2]);
|
||||
|
||||
if (Pelle.isDoomed) return Decimal.pow10(308 * (Decimal.log(pelleMults.dividedBy(epAmount).reciprocal(), 5) + 0.7))
|
||||
.clampMin(Number.MAX_VALUE);
|
||||
|
||||
return Decimal.pow10(308 * (Decimal.log(totalEPMult().dividedBy(epAmount).reciprocal(), 5) + 0.7))
|
||||
return Decimal.pow10(308 * (Decimal.log(Decimal.divide(Math.pow(epAmount, 1 / NG.power), totalEPMult()), 5) + 0.7))
|
||||
.clampMin(Number.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
|
15660
package-lock.json
generated
15660
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -8,6 +8,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@antimatter-dimensions/notations": "^2.2.0",
|
||||
"@fortawesome/fontawesome-free": "^6.1.1",
|
||||
"break_infinity.js": "^1.3.0",
|
||||
"chevrotain": "^4.8.1",
|
||||
"codemirror": "^5.65.1",
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 693 KiB |
|
@ -7,14 +7,13 @@
|
|||
<meta name="Antimatter Dimensions" content="A game about huge numbers and watching them go up." >
|
||||
<script type="text/javascript" src='https://cdn1.kongregate.com/javascripts/kongregate_api.js'></script>
|
||||
<link href="https://fonts.googleapis.com/css?family=PT+Mono" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css" integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/fontawesome/css/all.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/codemirror/codemirror.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/codemirror/show-hint.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/codemirror/lint.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/codemirror/panda-syntax.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/codemirror/liquibyte.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/vue-sfc-classes.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/components.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/ad-slider-component.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/glyphs.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/styles.css?3">
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/*
|
||||
This file is for styles that are part of Vue components.
|
||||
If your component is huge; it may want its own css file.
|
||||
Things more directly related to the game and its theming should also be separated if possible.
|
||||
*/
|
||||
|
||||
.l-hover-menu__wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fa-compress-arrows-alt {
|
||||
cursor: pointer;
|
||||
}
|
7831
public/stylesheets/fontawesome/css/all.css
vendored
Normal file
7831
public/stylesheets/fontawesome/css/all.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/stylesheets/fontawesome/webfonts/fa-brands-400.ttf
Normal file
BIN
public/stylesheets/fontawesome/webfonts/fa-brands-400.ttf
Normal file
Binary file not shown.
BIN
public/stylesheets/fontawesome/webfonts/fa-brands-400.woff2
Normal file
BIN
public/stylesheets/fontawesome/webfonts/fa-brands-400.woff2
Normal file
Binary file not shown.
BIN
public/stylesheets/fontawesome/webfonts/fa-regular-400.ttf
Normal file
BIN
public/stylesheets/fontawesome/webfonts/fa-regular-400.ttf
Normal file
Binary file not shown.
BIN
public/stylesheets/fontawesome/webfonts/fa-regular-400.woff2
Normal file
BIN
public/stylesheets/fontawesome/webfonts/fa-regular-400.woff2
Normal file
Binary file not shown.
BIN
public/stylesheets/fontawesome/webfonts/fa-solid-900.ttf
Normal file
BIN
public/stylesheets/fontawesome/webfonts/fa-solid-900.ttf
Normal file
Binary file not shown.
BIN
public/stylesheets/fontawesome/webfonts/fa-solid-900.woff2
Normal file
BIN
public/stylesheets/fontawesome/webfonts/fa-solid-900.woff2
Normal file
Binary file not shown.
BIN
public/stylesheets/fontawesome/webfonts/fa-v4compatibility.ttf
Normal file
BIN
public/stylesheets/fontawesome/webfonts/fa-v4compatibility.ttf
Normal file
Binary file not shown.
BIN
public/stylesheets/fontawesome/webfonts/fa-v4compatibility.woff2
Normal file
BIN
public/stylesheets/fontawesome/webfonts/fa-v4compatibility.woff2
Normal file
Binary file not shown.
|
@ -208,6 +208,18 @@
|
|||
color: var(--color-reality-light);
|
||||
}
|
||||
|
||||
.l-glyph-inventory-management {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.o-glyph-inventory-management-group {
|
||||
width: 20rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.c-auto-sac-type-tab__input {
|
||||
width: 2.5em;
|
||||
height: 1.5em;
|
||||
|
@ -585,8 +597,9 @@
|
|||
.c-glyph-set-save-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
margin: 1rem 7rem 0;
|
||||
justify-content: center;
|
||||
margin: 1rem auto 0;
|
||||
max-width: 30rem;
|
||||
}
|
||||
|
||||
.c-glyph-single-set-save {
|
||||
|
@ -594,7 +607,7 @@
|
|||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
height: 7.5rem;
|
||||
margin: 0 0 1.5rem;
|
||||
}
|
||||
|
||||
.c-glyph-single-set-save-flexbox {
|
||||
|
@ -610,7 +623,7 @@
|
|||
}
|
||||
|
||||
.c-glyph-sets-save-name__input {
|
||||
width: 20rem;
|
||||
width: 16rem;
|
||||
height: 1.5em;
|
||||
font-size: 1.35rem;
|
||||
background-color: black;
|
||||
|
@ -634,7 +647,7 @@
|
|||
color: var(--color-reality-light);
|
||||
border: 0.2rem solid var(--color-reality);
|
||||
border-radius: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
margin: 0 0.4rem 1rem;
|
||||
transition-duration: 0.2s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -977,7 +990,7 @@
|
|||
}
|
||||
|
||||
.c-glyph-inventory-option {
|
||||
width: auto;
|
||||
width: 19rem;
|
||||
height: auto;
|
||||
padding: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
|
@ -1018,11 +1031,11 @@
|
|||
font-family: Typewriter;
|
||||
color: var(--color-reality);
|
||||
background: black;
|
||||
width: 200%;
|
||||
left: -50%;
|
||||
width: 100%;
|
||||
left: 0%;
|
||||
line-height: 1.8rem;
|
||||
padding: 0.3rem;
|
||||
z-index: 2;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
|
|
|
@ -134,6 +134,11 @@ body.t-s9 {
|
|||
color: var(--color-reality)
|
||||
}
|
||||
|
||||
.t-dark .o-sidebar-currency--reality,
|
||||
.t-dark-metro .o-sidebar-currency--reality {
|
||||
color: var(--color-reality)
|
||||
}
|
||||
|
||||
.o-sidebar-currency--pelle {
|
||||
color: var(--color-pelle--base)
|
||||
}
|
||||
|
@ -898,6 +903,10 @@ body.t-s9 {
|
|||
transition-delay: 0s;
|
||||
}
|
||||
|
||||
.l-information {
|
||||
top: 7rem;
|
||||
}
|
||||
|
||||
.s-base--metro .l-help-me {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
|
|
@ -34,11 +34,6 @@
|
|||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.l-old-ui__footer {
|
||||
padding-bottom: 1rem;
|
||||
padding-top: 2.5rem;
|
||||
}
|
||||
|
||||
.l-old-ui-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
@ -54,9 +54,6 @@ html {
|
|||
|
||||
--color-v--base: #ead584;
|
||||
|
||||
--color-pelle--base: crimson;
|
||||
--color-pelle-secondary: #00bcd4;
|
||||
|
||||
--color-ra-base: #9575cd;
|
||||
--color-ra-pet-teresa: #8596ea;
|
||||
--color-ra-pet-effarig: #ea8585;
|
||||
|
@ -65,6 +62,9 @@ html {
|
|||
|
||||
--color-laitela--base: white;
|
||||
--color-laitela--accent: black;
|
||||
|
||||
--color-pelle--base: crimson;
|
||||
--color-pelle-secondary: #00bcd4;
|
||||
}
|
||||
|
||||
.t-metro #ui-container, /* csslint allow: empty-rules */
|
||||
|
@ -254,7 +254,7 @@ button:focus {
|
|||
|
||||
/*#region TT shop*/
|
||||
|
||||
#TTbuttons {
|
||||
.TTbuttons {
|
||||
color: var(--color-text);
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
|
@ -304,7 +304,7 @@ button:focus {
|
|||
background: #652F2F;
|
||||
}
|
||||
|
||||
#timetheorems {
|
||||
.timetheorems {
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
flex: 1 0 auto;
|
||||
|
@ -592,40 +592,6 @@ button:focus {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.o-save-timer {
|
||||
color: var(--color-text);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--color-base);
|
||||
white-space: nowrap;
|
||||
border-top: 0.1rem solid var(--color-accent);
|
||||
border-right: 0.1rem solid var(--color-accent);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 0 .5rem;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.o-speedrun-status {
|
||||
font-size: 1.2rem;
|
||||
color: var(--color-text);
|
||||
position: fixed;
|
||||
right: 1rem;
|
||||
bottom: 1rem;
|
||||
background-color: var(--color-base);
|
||||
white-space: nowrap;
|
||||
border: 0.2rem solid var(--color-accent);
|
||||
user-select: none;
|
||||
padding: 0.8rem 2rem;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.o-speedrun-collapse {
|
||||
cursor: pointer;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
|
||||
.l-reality-button {
|
||||
display: block;
|
||||
width: 50%;
|
||||
|
@ -1302,7 +1268,7 @@ screen and (max-width: 480px) {
|
|||
|
||||
.o-primary-btn--subtab-option {
|
||||
border: 0.2rem solid var(--color-accent);
|
||||
margin: 0 0.8rem;
|
||||
margin: 0.4rem 0.8rem;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
|
@ -1313,6 +1279,7 @@ screen and (max-width: 480px) {
|
|||
.o-primary-btn--tickspeed {
|
||||
width: 17rem;
|
||||
font-size: 1.2rem;
|
||||
margin-right: 0.4rem;
|
||||
}
|
||||
|
||||
.o-primary-btn--buy-max {
|
||||
|
@ -1343,13 +1310,13 @@ screen and (max-width: 480px) {
|
|||
.o-primary-btn--dimboost {
|
||||
font-size: 0.9rem;
|
||||
width: 21rem;
|
||||
height: 4rem;
|
||||
height: 4.5rem;
|
||||
}
|
||||
|
||||
.o-primary-btn--galaxy {
|
||||
font-size: 0.9rem;
|
||||
width: 21rem;
|
||||
height: 4rem;
|
||||
height: 4.5rem;
|
||||
}
|
||||
|
||||
.o-primary-btn--new-dim {
|
||||
|
@ -1943,7 +1910,7 @@ screen and (max-width: 480px) {
|
|||
|
||||
.c-game-header__infinity-points {
|
||||
font-size: 1.2rem;
|
||||
width: 21rem;
|
||||
width: 22rem;
|
||||
}
|
||||
|
||||
.c-game-header__tesseract-available {
|
||||
|
@ -2005,7 +1972,7 @@ screen and (max-width: 480px) {
|
|||
|
||||
.c-game-header__eternity-points {
|
||||
font-size: 1.2rem;
|
||||
width: 21rem;
|
||||
width: 22rem;
|
||||
}
|
||||
|
||||
.c-game-header__ep-amount {
|
||||
|
@ -2785,7 +2752,7 @@ screen and (max-width: 480px) {
|
|||
|
||||
.s-base--dark .o-achievement__tooltip {
|
||||
border: 0.1rem solid var(--color-text);
|
||||
background: #111111;
|
||||
background-color: #111111;
|
||||
}
|
||||
|
||||
.s-base--dark .o-achievement__tooltip:after {
|
||||
|
@ -5165,56 +5132,6 @@ screen and (max-width: 480px) {
|
|||
fill: white;
|
||||
}
|
||||
|
||||
.c-blob-snowflake-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9999;
|
||||
overflow: visible;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.c-blob-background-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -9999;
|
||||
overflow: visible;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.o-blob-snowflake {
|
||||
fill: #fbc21b;
|
||||
text-shadow: 0 0 5px #000,
|
||||
0 0 5px #000,
|
||||
0 0 5px #000;
|
||||
opacity: 0.9;
|
||||
overflow: visible;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.o-blob-background {
|
||||
fill: #fbc21b;
|
||||
text-shadow: 0 0 5px #000,
|
||||
0 0 5px #000,
|
||||
0 0 5px #000;
|
||||
opacity: 0.3;
|
||||
overflow: visible;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*#endregion Dilation*/
|
||||
|
||||
/*#region Modals*/
|
||||
|
@ -5257,7 +5174,12 @@ screen and (max-width: 480px) {
|
|||
font-size: 1.4rem;
|
||||
padding: 1rem;
|
||||
transition-duration: 0.2s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.c-modal__title {
|
||||
width: 50rem;
|
||||
font-size: 1.6rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.c-modal__close-btn {
|
||||
|
@ -5272,6 +5194,113 @@ screen and (max-width: 480px) {
|
|||
right: -0.5rem;
|
||||
}
|
||||
|
||||
.l-modal-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.c-modal__confirmation-toggle {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: var(--color-gh-purple);
|
||||
font-size: 1.9rem;
|
||||
height: 3rem;
|
||||
width: 3rem;
|
||||
border: 0.3rem solid black;
|
||||
border-top-right-radius: 0.3rem;
|
||||
border-bottom-left-radius: 1rem;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition-duration: 0.2s;
|
||||
position: absolute;
|
||||
top: -0.3rem;
|
||||
right: -0.3rem;
|
||||
}
|
||||
|
||||
.c-modal__confirmation-toggle:hover {
|
||||
transform: scale(1.1) translate(-0.15rem, 0.15rem);
|
||||
}
|
||||
|
||||
.s-base--metro .c-modal__confirmation-toggle {
|
||||
border-radius: 0;
|
||||
border-width: 0.1rem;
|
||||
top: -0.1rem;
|
||||
right: -0.1rem;
|
||||
}
|
||||
|
||||
.t-s6 .c-modal__confirmation-toggle,
|
||||
.t-s10 .c-modal__confirmation-toggle {
|
||||
border: 0.1rem solid #1b5e20;
|
||||
top: -0.1rem;
|
||||
right: -0.1rem;
|
||||
}
|
||||
|
||||
.c-modal__confirmation-toggle--active {
|
||||
background: var(--color-good);
|
||||
}
|
||||
|
||||
.c-modal__confirmation-toggle__tooltip {
|
||||
opacity: 0;
|
||||
transition-duration: 0.2s;
|
||||
font-size: 1.4rem;
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-base);
|
||||
border: 0.3rem solid black;
|
||||
border-radius: 0.8rem;
|
||||
min-width: 20rem;
|
||||
margin-left: 0;
|
||||
padding: 0.4rem;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
.s-base--metro .c-modal__confirmation-toggle__tooltip {
|
||||
border-radius: 0;
|
||||
border-width: 0.1rem;
|
||||
}
|
||||
|
||||
.t-s6 .c-modal__confirmation-toggle__tooltip,
|
||||
.t-s10 .c-modal__confirmation-toggle__tooltip {
|
||||
border: 0.1rem solid #1b5e20;
|
||||
}
|
||||
|
||||
.c-modal__confirmation-toggle__tooltip:after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
margin-left: -0.7rem;
|
||||
margin-bottom: 0;
|
||||
width: 0;
|
||||
border-top: 0 solid black;
|
||||
border-right: 0.7rem solid transparent;
|
||||
border-left: 0.7rem solid transparent;
|
||||
content: " ";
|
||||
transition-duration: 0.2s;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.c-modal__confirmation-toggle:hover .c-modal__confirmation-toggle__tooltip {
|
||||
opacity: 1;
|
||||
bottom: calc(100% + 0.8rem);
|
||||
}
|
||||
|
||||
.s-base--metro .c-modal__confirmation-toggle:hover .c-modal__confirmation-toggle__tooltip {
|
||||
bottom: calc(100% + 0.7rem);
|
||||
}
|
||||
|
||||
.c-modal__confirmation-toggle:hover .c-modal__confirmation-toggle__tooltip:after {
|
||||
border-top-width: 0.6rem;
|
||||
margin-bottom: -0.8rem;
|
||||
}
|
||||
|
||||
.s-base--metro .c-modal__confirmation-toggle:hover .c-modal__confirmation-toggle__tooltip:after {
|
||||
margin-bottom: -0.7rem;
|
||||
}
|
||||
|
||||
.c-modal__confirm-btn {
|
||||
background-color: var(--color-good) !important;
|
||||
}
|
||||
|
@ -5390,11 +5419,14 @@ screen and (max-width: 480px) {
|
|||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-width: 40rem;
|
||||
}
|
||||
|
||||
.t-dark .c-modal-away-progress {
|
||||
text-shadow:
|
||||
0 0 0.2rem black,
|
||||
0 0 0.2rem black,
|
||||
0 0 0.2rem black,
|
||||
0 0 0.2rem black;
|
||||
0 0 0.2rem black,
|
||||
0 0 0.2rem black,
|
||||
0 0 0.2rem black,
|
||||
0 0 0.2rem black;
|
||||
}
|
||||
|
||||
.c-modal-away-progress__header {
|
||||
|
@ -5408,6 +5440,7 @@ screen and (max-width: 480px) {
|
|||
margin-bottom: 0.2rem;
|
||||
padding-bottom: 0.2rem;
|
||||
border-bottom: 0.1rem solid var(--color-text);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.c-modal-away-progress__resources div:last-child {
|
||||
|
@ -5449,6 +5482,13 @@ screen and (max-width: 480px) {
|
|||
.c-modal-away-progress__tachyon-galaxies,
|
||||
.c-modal-away-progress__dilated-time {
|
||||
color: var(--color-dilation);
|
||||
filter: brightness(0.8)
|
||||
}
|
||||
|
||||
.t-dark .c-modal-away-progress__tachyon-particles,
|
||||
.t-dark .c-modal-away-progress__tachyon-galaxies,
|
||||
.t-dark .c-modal-away-progress__dilated-time {
|
||||
filter: none
|
||||
}
|
||||
|
||||
.c-modal-away-progress__realities,
|
||||
|
@ -5494,6 +5534,20 @@ screen and (max-width: 480px) {
|
|||
color: var(--color-ra-pet-v);
|
||||
}
|
||||
|
||||
.c-modal-away-progress__teresa-memories,
|
||||
.c-modal-away-progress__effarig-memories,
|
||||
.c-modal-away-progress__enslaved-memories,
|
||||
.c-modal-away-progress__v-memories {
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
|
||||
.t-dark .c-modal-away-progress__teresa-memories,
|
||||
.t-dark .c-modal-away-progress__effarig-memories,
|
||||
.t-dark .c-modal-away-progress__enslaved-memories,
|
||||
.t-dark .c-modal-away-progress__v-memories {
|
||||
filter: none
|
||||
}
|
||||
|
||||
.c-modal-away-progress__black-hole b,
|
||||
.c-modal-away-progress__black-hole {
|
||||
color: black;
|
||||
|
@ -5502,6 +5556,10 @@ screen and (max-width: 480px) {
|
|||
0 0 0.3rem #e67919;
|
||||
}
|
||||
|
||||
.c-modal-away-progress__reality-shards {
|
||||
color: var(--color-pelle--base);
|
||||
}
|
||||
|
||||
.c-modal-away-progress__disabled b,
|
||||
.c-modal-away-progress__disabled {
|
||||
text-decoration: line-through;
|
||||
|
@ -5720,63 +5778,12 @@ kbd {
|
|||
|
||||
/*#endregion c-modal-hotkeys*/
|
||||
|
||||
.l-modal-progress-bar {
|
||||
position: fixed;
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 40rem;
|
||||
left: 50vw;
|
||||
top: 50vh;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.l-modal-progress-bar__hbox {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.l-modal-split-preferences {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c-modal-progress-bar__label {
|
||||
font-size: large;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.l-modal-progress-bar__buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 25rem;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.l-modal-progress-bar__bg {
|
||||
width: 20rem;
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.c-modal-progress-bar__bg {
|
||||
background: black;
|
||||
}
|
||||
|
||||
.l-modal-progress-bar__fg {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.c-modal-progress-bar__fg {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
.l-modal-celestial-quote {
|
||||
position: fixed;
|
||||
z-index: 3;
|
||||
|
@ -7765,7 +7772,7 @@ kbd {
|
|||
}
|
||||
|
||||
.o-alchemy-node--locked {
|
||||
opacity: 0.1;
|
||||
opacity: 0.25;
|
||||
z-index: 4;
|
||||
}
|
||||
.o-alchemy-node--base {
|
||||
|
@ -9076,7 +9083,7 @@ input.o-automator-block-input {
|
|||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
margin: 0.5rem;
|
||||
flex: 1 0.8 40rem;
|
||||
}
|
||||
|
@ -9125,7 +9132,7 @@ input.o-automator-block-input {
|
|||
position: absolute;
|
||||
top: 1rem;
|
||||
width: 2rem;
|
||||
right: 1rem;
|
||||
right: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: 50%;
|
||||
line-height: 1.9rem;
|
||||
|
@ -9134,6 +9141,10 @@ input.o-automator-block-input {
|
|||
font-weight: 500;
|
||||
}
|
||||
|
||||
.l-information {
|
||||
top: 3.1rem;
|
||||
}
|
||||
|
||||
.l-hide-modal-tab-container {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
@ -9366,96 +9377,6 @@ input.o-automator-block-input {
|
|||
/* background: #1a1a1a; */
|
||||
}
|
||||
|
||||
/* STD-shop */
|
||||
|
||||
#shop {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c-shop-disclaimer {
|
||||
color: black;
|
||||
background: var(--color-bad);
|
||||
width: 100rem;
|
||||
font-size: 1.8rem;
|
||||
font-weight: bold;
|
||||
border: 0.2rem solid black;
|
||||
border-radius: 1rem;
|
||||
margin-top: 0.8rem;
|
||||
}
|
||||
|
||||
.s-base--metro .c-shop-disclaimer {
|
||||
border-width: 0.1rem;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.t-s1 .c-shop-disclaimer,
|
||||
.t-s6 .c-shop-disclaimer,
|
||||
.t-s10 .c-shop-disclaimer {
|
||||
color: var(--color-bad);
|
||||
background: black;
|
||||
border-color: var(--color-bad);
|
||||
}
|
||||
|
||||
.c-shop-header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 2rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.c-shop-header img {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.l-shop-buttons-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 62rem;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.c-shop-button-container {
|
||||
width: 30rem;
|
||||
padding: 1rem;
|
||||
border: .2rem solid #1f7d1f;
|
||||
border-radius: .5rem;
|
||||
margin: .5rem;
|
||||
background: #3c3c3c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.o-shop-button-button {
|
||||
background: turquoise;
|
||||
border: none;
|
||||
border-radius: .5rem;
|
||||
display: flex;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
font-family: Typewriter;
|
||||
padding: .5rem 2rem;
|
||||
margin-top: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.c-shop-header .o-shop-button-button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.o-shop-button-button img {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.o-shop-button-multiplier {
|
||||
font-weight: bold;
|
||||
font-size: 1.5rem;
|
||||
margin: 0.5rem 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c-autobuyer-buy-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
|
@ -8,7 +8,6 @@ body.t-inverted-metro {
|
|||
.t-inverted-metro .c-modal,
|
||||
.t-inverted-metro #TTbuttons,
|
||||
.t-inverted-metro .sidebar,
|
||||
.t-inverted-metro .o-save-timer,
|
||||
.t-inverted-metro .c-glyph-tooltip {
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ body.t-inverted {
|
|||
.t-inverted .c-modal,
|
||||
.t-inverted #TTbuttons,
|
||||
.t-inverted .sidebar,
|
||||
.t-inverted .o-save-timer,
|
||||
.t-inverted .c-glyph-tooltip {
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ body {
|
|||
.t-s2 .c-modal,
|
||||
.t-s2 #TTbuttons,
|
||||
.t-s2 .sidebar,
|
||||
.t-s2 .o-save-timer,
|
||||
.t-s2 .c-glyph-tooltip {
|
||||
filter: sepia(100%) hue-rotate(180deg) saturate(250%);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ body {
|
|||
.t-s3 .c-modal,
|
||||
.t-s3 #TTbuttons,
|
||||
.t-s3 .sidebar,
|
||||
.t-s3 .o-save-timer,
|
||||
.t-s3 .c-glyph-tooltip {
|
||||
animation: glasses 7s infinite;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ body.t-s5 {
|
|||
.t-s5 .l-notification-container,
|
||||
.t-s5 .c-modal,
|
||||
.t-s5 #TTbuttons,
|
||||
.t-s5 .sidebar,
|
||||
.t-inverted-metro .o-save-timer {
|
||||
.t-s5 .sidebar {
|
||||
filter: sepia(100%) hue-rotate(0deg) saturate(100%);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
/* Temporary inlined css classes from SFCs to prevent conflicts with old classes from styles.css */
|
||||
|
||||
/* FooterLinks.vue */
|
||||
|
||||
.o-footer {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
/* HintText.vue */
|
||||
|
||||
.o-hint-text {
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import "./blob-snowflakes";
|
||||
<script>
|
||||
import BlobSnowflakes from "@/components/BlobSnowflakes";
|
||||
|
||||
Vue.component("background-animations", {
|
||||
export default {
|
||||
name: "BackgroundAnimations",
|
||||
components: {
|
||||
BlobSnowflakes,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
animateBackground: false,
|
||||
|
@ -13,6 +18,9 @@ Vue.component("background-animations", {
|
|||
this.blob = player.options.theme === "S11";
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<blob-snowflakes v-if="blob" />`
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BlobSnowflakes v-if="blob" />
|
||||
</template>
|
|
@ -1,6 +1,11 @@
|
|||
Vue.component("blob-background", {
|
||||
<script>
|
||||
export default {
|
||||
name: "BlobBackground",
|
||||
props: {
|
||||
bounds: Object
|
||||
bounds: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.drop();
|
||||
|
@ -31,7 +36,23 @@ Vue.component("blob-background", {
|
|||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
template:
|
||||
`<text class="o-blob-background"></text>`
|
||||
});
|
||||
<template>
|
||||
<text class="o-blob-background" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.o-blob-background {
|
||||
fill: #fbc21b;
|
||||
text-shadow: 0 0 5px #000,
|
||||
0 0 5px #000,
|
||||
0 0 5px #000;
|
||||
opacity: 0.3;
|
||||
overflow: visible;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
</style>
|
|
@ -1,8 +1,13 @@
|
|||
<script>
|
||||
import TWEEN from "tween.js";
|
||||
|
||||
Vue.component("blob-snowflake", {
|
||||
export default {
|
||||
name: "BlobSnowflake",
|
||||
props: {
|
||||
bounds: Object
|
||||
bounds: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fly();
|
||||
|
@ -82,7 +87,24 @@ Vue.component("blob-snowflake", {
|
|||
return SNOW[Math.floor(Math.random() * SNOW.length)];
|
||||
}
|
||||
},
|
||||
},
|
||||
template:
|
||||
`<text class="o-blob-snowflake"></text>`
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<text class="o-blob-snowflake" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.o-blob-snowflake {
|
||||
fill: #fbc21b;
|
||||
text-shadow: 0 0 5px #000,
|
||||
0 0 5px #000,
|
||||
0 0 5px #000;
|
||||
opacity: 0.9;
|
||||
overflow: visible;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
</style>
|
94
src/components/BlobSnowflakes.vue
Normal file
94
src/components/BlobSnowflakes.vue
Normal file
|
@ -0,0 +1,94 @@
|
|||
<script>
|
||||
import BlobSnowflake from "@/components/BlobSnowflake";
|
||||
import BlobBackground from "@/components/BlobBackground";
|
||||
|
||||
export default {
|
||||
name: "BlobSnowflakes",
|
||||
components: {
|
||||
BlobSnowflake,
|
||||
BlobBackground,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
animateBackground: false,
|
||||
count: 0,
|
||||
initialized: false,
|
||||
bounds: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.updateSize();
|
||||
window.addEventListener("resize", this.updateSize);
|
||||
this.initialized = true;
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener("resize", this.updateSize);
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.animateBackground = player.options.animations.background;
|
||||
this.count = player.options.animations.blobSnowflakes;
|
||||
},
|
||||
updateSize() {
|
||||
this.bounds.x = document.getElementById("ui").clientWidth;
|
||||
this.bounds.y = document.getElementById("ui").clientHeight;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="initialized">
|
||||
<svg
|
||||
v-if="animateBackground"
|
||||
class="c-blob-snowflake-container"
|
||||
>
|
||||
<BlobSnowflake
|
||||
v-for="i in count"
|
||||
:key="i"
|
||||
:bounds="bounds"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
v-else
|
||||
class="c-blob-background-container"
|
||||
>
|
||||
<BlobBackground
|
||||
v-for="i in count"
|
||||
:key="i"
|
||||
:bounds="bounds"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.c-blob-snowflake-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9999;
|
||||
overflow: visible;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.c-blob-background-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -9999;
|
||||
overflow: visible;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
</style>
|
|
@ -76,7 +76,7 @@ export default {
|
|||
if (this.downButtonEnabled) this.lastVisibleIndex++;
|
||||
},
|
||||
removeQuoteSyntax(x) {
|
||||
return Modal.celestialQuote.removeOverrideCel(x).replace("*", "");
|
||||
return Modal.celestialQuote.removeOverrideCel(x);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script>
|
||||
|
||||
import { isDecimal, isFunction, isNumber } from "@/utility";
|
||||
|
||||
/* eslint-disable no-empty-function */
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<script>
|
||||
export default {
|
||||
name: "FooterLink"
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a target="_newtab">
|
||||
<slot />
|
||||
</a>
|
||||
</template>
|
|
@ -1,45 +0,0 @@
|
|||
<script>
|
||||
import FooterLink from "@/components/FooterLink";
|
||||
|
||||
export default {
|
||||
name: "FooterLinks",
|
||||
components: {
|
||||
FooterLink
|
||||
},
|
||||
computed: {
|
||||
isVisible() {
|
||||
return this.$viewModel.subtab !== Tab.eternity.studies.key;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="isVisible"
|
||||
class="o-footer"
|
||||
>
|
||||
<FooterLink href="https://example.com">
|
||||
Example
|
||||
</FooterLink>
|
||||
|
|
||||
<FooterLink
|
||||
href="about.html"
|
||||
onclick="SecretAchievement(33).unlock()"
|
||||
>
|
||||
Donate
|
||||
</FooterLink>
|
||||
|
|
||||
<FooterLink href="changelog.html">
|
||||
Changelog
|
||||
</FooterLink>
|
||||
|
|
||||
<FooterLink href="https://discord.gg/ST9NaXa">
|
||||
Discord
|
||||
</FooterLink>
|
||||
|
|
||||
<FooterLink href="https://www.reddit.com/r/AntimatterDimensions/">
|
||||
Subreddit
|
||||
</FooterLink>
|
||||
</div>
|
||||
</template>
|
109
src/components/GameUIComponent.vue
Normal file
109
src/components/GameUIComponent.vue
Normal file
|
@ -0,0 +1,109 @@
|
|||
<script>
|
||||
import ClassicUi from "@/components/ui-modes/classic/ClassicUi";
|
||||
import ModernUi from "@/components/ui-modes/modern/ModernUi";
|
||||
import ModernSidebar from "@/components/ui-modes/modern/ModernSidebar";
|
||||
import TabComponents from "@/components/tabs";
|
||||
import PopupModal from "@/components/modals/PopupModal";
|
||||
import FadeToBlack from "@/components/tabs/celestial-pelle/FadeToBlack";
|
||||
import CreditsContainer from "@/components/tabs/celestial-pelle/CreditsContainer";
|
||||
import NewGame from "@/components/tabs/celestial-pelle/NewGame";
|
||||
import SaveTimer from "@/components/SaveTimer";
|
||||
import SpeedrunStatus from "@/components/SpeedrunStatus";
|
||||
import BackgroundAnimations from "@/components/BackgroundAnimations";
|
||||
import ModalProgressBar from "@/components/modals/ModalProgressBar";
|
||||
import HowToPlay from "@/components/HowToPlay";
|
||||
import InfoButton from "@/components/InfoButton";
|
||||
import TimeTheoremShop from "@/components/tabs/time-studies/tt-shop/TimeTheoremShop";
|
||||
|
||||
export default {
|
||||
name: "GameUIComponent",
|
||||
components: {
|
||||
...TabComponents,
|
||||
ClassicUi,
|
||||
ModernUi,
|
||||
ModernSidebar,
|
||||
PopupModal,
|
||||
FadeToBlack,
|
||||
CreditsContainer,
|
||||
NewGame,
|
||||
SaveTimer,
|
||||
SpeedrunStatus,
|
||||
BackgroundAnimations,
|
||||
ModalProgressBar,
|
||||
HowToPlay,
|
||||
InfoButton,
|
||||
TimeTheoremShop
|
||||
},
|
||||
computed: {
|
||||
view() {
|
||||
return this.$viewModel;
|
||||
},
|
||||
uiLayout() {
|
||||
return this.view.newUI ? "ModernUi" : "ClassicUi";
|
||||
},
|
||||
containerClass() {
|
||||
return this.view.newUI ? "new-ui" : "old-ui";
|
||||
},
|
||||
page() {
|
||||
const subtab = Tabs.current[this.$viewModel.subtab];
|
||||
return subtab.config.component;
|
||||
},
|
||||
themeCss() {
|
||||
return `stylesheets/theme-${this.view.theme}.css`;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="view.initialized"
|
||||
id="ui-container"
|
||||
:class="containerClass"
|
||||
class="ui-wrapper"
|
||||
>
|
||||
<div
|
||||
id="ui"
|
||||
class="c-game-ui"
|
||||
>
|
||||
<component :is="uiLayout">
|
||||
<component :is="page" />
|
||||
</component>
|
||||
<PopupModal
|
||||
v-if="view.modal.current"
|
||||
:modal="view.modal.current"
|
||||
/>
|
||||
<ModalProgressBar v-if="view.modal.progressBar" />
|
||||
<link
|
||||
v-if="view.theme !== 'Normal'"
|
||||
type="text/css"
|
||||
rel="stylesheet"
|
||||
:href="themeCss"
|
||||
>
|
||||
<HowToPlay />
|
||||
<InfoButton />
|
||||
<BackgroundAnimations />
|
||||
</div>
|
||||
<div
|
||||
id="notification-container"
|
||||
class="l-notification-container"
|
||||
/>
|
||||
<TimeTheoremShop
|
||||
v-if="view.subtab === 'studies'"
|
||||
class="l-time-studies-tab__tt-shop"
|
||||
/>
|
||||
<ModernSidebar v-if="view.newUI" />
|
||||
<SaveTimer />
|
||||
<SpeedrunStatus />
|
||||
<FadeToBlack />
|
||||
<CreditsContainer />
|
||||
<NewGame />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.ui-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
|
@ -106,7 +106,7 @@ export default {
|
|||
<GlyphComponent
|
||||
v-for="(g, idx) in glyphs"
|
||||
:key="idx"
|
||||
style="margin: 0.2rem;"
|
||||
class="l-preview"
|
||||
:glyph="g"
|
||||
:show-sacrifice="showSacrifice"
|
||||
:draggable="false"
|
||||
|
@ -127,3 +127,9 @@ export default {
|
|||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.l-preview {
|
||||
margin: 0.2rem;
|
||||
}
|
||||
</style>
|
||||
|
|
23
src/components/HelpMe.vue
Normal file
23
src/components/HelpMe.vue
Normal file
|
@ -0,0 +1,23 @@
|
|||
<script>
|
||||
export default {
|
||||
name: "HelpMe",
|
||||
methods: {
|
||||
showModal() {
|
||||
Modal.h2p.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="o-tab-btn l-help-me"
|
||||
@click="showModal"
|
||||
>
|
||||
?
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
23
src/components/HowToPlay.vue
Normal file
23
src/components/HowToPlay.vue
Normal file
|
@ -0,0 +1,23 @@
|
|||
<script>
|
||||
export default {
|
||||
name: "HowToPlay",
|
||||
methods: {
|
||||
showModal() {
|
||||
Modal.h2p.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="o-tab-btn l-help-me"
|
||||
@click="showModal"
|
||||
>
|
||||
?
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user