Merge branch 'master' into Steam-Webpack

This commit is contained in:
ZackRhodes 2022-04-05 18:03:34 -04:00
commit 2dccac2466
24 changed files with 472 additions and 276 deletions

View File

@ -1,3 +1,4 @@
import { InfinityDimensions } from "../globals.js";
import { Autobuyer, IntervaledAutobuyerState } from "./autobuyer.js";
class InfinityDimensionAutobuyerState extends IntervaledAutobuyerState {
@ -5,8 +6,12 @@ class InfinityDimensionAutobuyerState extends IntervaledAutobuyerState {
return this.id;
}
get dimension() {
return InfinityDimension(this.tier);
}
get name() {
return InfinityDimension(this.tier).displayName;
return this.dimension.displayName;
}
get fullName() {
@ -33,9 +38,13 @@ class InfinityDimensionAutobuyerState extends IntervaledAutobuyerState {
return true;
}
get canTick() {
return InfinityDimensions.canAutobuy() && this.dimension.isAvailableForPurchase && super.canTick;
}
tick() {
if (EternityChallenge(8).isRunning) return;
if (buyMaxInfDims(this.tier)) super.tick();
super.tick();
this.dimension.buyMax();
}
static get entryCount() { return 8; }

View File

@ -30,57 +30,6 @@ export function infinityDimensionCommonMultiplier() {
return mult;
}
export function buyManyInfinityDimension(tier) {
if (!canBuyInfinityDimension(tier)) return false;
const dim = InfinityDimension(tier);
Currency.infinityPoints.subtract(dim.cost);
dim.cost = Decimal.round(dim.cost.times(dim.costMultiplier));
// Because each ID purchase gives 10 IDs
dim.amount = dim.amount.plus(10);
dim.baseAmount += 10;
if (EternityChallenge(8).isRunning) {
player.eterc8ids -= 1;
}
return true;
}
export function buyMaxInfDims(tier) {
if (!canBuyInfinityDimension(tier)) return false;
const dim = InfinityDimension(tier);
const costMult = dim.costMultiplier;
const exponentDifference = (Currency.infinityPoints.exponent - dim.cost.e);
let toBuy = exponentDifference === 0 ? 1 : Math.floor(exponentDifference / Math.log10(costMult));
const purchasesUntilHardcap = dim.purchaseCap - dim.purchases;
toBuy = Math.min(toBuy, purchasesUntilHardcap);
if (EternityChallenge(8).isRunning) {
toBuy = Math.clampMax(toBuy, player.eterc8ids);
player.eterc8ids -= toBuy;
}
dim.cost = dim.cost.times(Decimal.pow(costMult, toBuy - 1));
Currency.infinityPoints.subtract(dim.cost);
dim.cost = dim.cost.times(costMult);
// Because each ID purchase gives 10 IDs
dim.amount = dim.amount.plus(10 * toBuy);
dim.baseAmount += 10 * toBuy;
buyManyInfinityDimension(tier);
return true;
}
function canBuyInfinityDimension(tier) {
const dim = InfinityDimension(tier);
return !dim.isCapped && dim.isAvailableForPurchase && dim.isUnlocked;
}
export function buyMaxInfinityDimensions() {
if (EternityChallenge(8).isRunning) return;
for (const tier of Array.dimensionTiers) {
buyMaxInfDims(tier);
}
}
export function toggleAllInfDims() {
const areEnabled = Autobuyer.infinityDimension(1).isActive;
for (let i = 1; i < 9; i++) {
@ -109,6 +58,7 @@ class InfinityDimensionState extends DimensionState {
this._powerMultiplier = POWER_MULTS[tier];
const BASE_COSTS = [null, 1e8, 1e9, 1e10, 1e20, 1e140, 1e200, 1e250, 1e280];
this._baseCost = new Decimal(BASE_COSTS[tier]);
this.ipRequirement = BASE_COSTS[1];
}
/** @returns {Decimal} */
@ -132,16 +82,29 @@ class InfinityDimensionState extends DimensionState {
this.data.isUnlocked = value;
}
get requirement() {
get amRequirement() {
return this._unlockRequirement;
}
get requirementReached() {
return player.records.thisEternity.maxAM.gte(this.requirement);
get antimatterRequirementReached() {
return player.records.thisEternity.maxAM.gte(this.amRequirement);
}
get hasIPUnlock() {
return this.tier === 1 && !PlayerProgress.eternityUnlocked();
}
get ipRequirementReached() {
return !this.hasIPUnlock || Currency.infinityPoints.value.gte(this.ipRequirement);
}
get canUnlock() {
return ((Perk.bypassIDAntimatter.isBought && !Pelle.isDoomed) || this.antimatterRequirementReached) &&
this.ipRequirementReached;
}
get isAvailableForPurchase() {
return this.isAffordable && (player.eterc8ids > 0 || !EternityChallenge(8).isRunning);
return InfinityDimensions.canBuy() && this.isUnlocked && this.isAffordable && !this.isCapped;
}
get isAffordable() {
@ -272,14 +235,61 @@ class InfinityDimensionState extends DimensionState {
this.isUnlocked = false;
}
tryUnlock() {
if (
(!Perk.bypassIDAntimatter.isBought || Pelle.isDoomed) &&
!this.requirementReached
) return;
unlock() {
if (this.isUnlocked) return true;
if (!this.canUnlock) return false;
this.isUnlocked = true;
EventHub.dispatch(GAME_EVENT.INFINITY_DIMENSION_UNLOCKED, this.tier);
if (this.tier === 1 && !PlayerProgress.eternityUnlocked()) {
Tab.dimensions.infinity.show();
}
return true;
}
buySingle() {
if (!this.isUnlocked) return this.unlock();
if (!this.isAvailableForPurchase) return false;
Currency.infinityPoints.purchase(this.cost);
this.cost = Decimal.round(this.cost.times(this.costMultiplier));
// Because each ID purchase gives 10 IDs
this.amount = this.amount.plus(10);
this.baseAmount += 10;
if (EternityChallenge(8).isRunning) {
player.eterc8ids -= 1;
}
return true;
}
buyMax() {
if (!this.isAvailableForPurchase) return false;
let purchasesUntilHardcap = this.purchaseCap - this.purchases;
if (EternityChallenge(8).isRunning) {
purchasesUntilHardcap = Math.clampMax(purchasesUntilHardcap, player.eterc8ids);
}
const costScaling = new LinearCostScaling(
Currency.infinityPoints.value,
this.cost,
this.costMultiplier,
purchasesUntilHardcap
);
if (costScaling.purchases <= 0) return false;
Currency.infinityPoints.purchase(costScaling.totalCost);
this.cost = this.cost.times(costScaling.totalCostMultiplier);
// Because each ID purchase gives 10 IDs
this.amount = this.amount.plus(10 * costScaling.purchases);
this.baseAmount += 10 * costScaling.purchases;
if (EternityChallenge(8).isRunning) {
player.eterc8ids -= costScaling.purchases;
}
return true;
}
}
@ -297,16 +307,9 @@ export const InfinityDimensions = {
all: InfinityDimension.index.compact(),
HARDCAP_PURCHASES: 2000000,
unlockNext(switchTab) {
unlockNext() {
if (InfinityDimension(8).isUnlocked) return;
const next = InfinityDimensions.next();
if (
(!Perk.bypassIDAntimatter.isBought || Pelle.isDoomed) &&
player.records.thisEternity.maxAM.lt(next.requirement)
) return;
next.isUnlocked = true;
EventHub.dispatch(GAME_EVENT.INFINITY_DIMENSION_UNLOCKED, next.tier);
if (switchTab) Tab.dimensions.infinity.show();
this.next().unlock();
},
next() {
@ -336,6 +339,16 @@ export const InfinityDimensions = {
return this.HARDCAP_PURCHASES + this.capIncrease;
},
canBuy() {
return !EternityChallenge(2).isRunning &&
!EternityChallenge(10).isRunning &&
(!EternityChallenge(8).isRunning || player.eterc8ids > 0);
},
canAutobuy() {
return this.canBuy() && !EternityChallenge(8).isRunning;
},
tick(diff) {
for (let tier = 8; tier > 1; tier--) {
InfinityDimension(tier).produceDimensions(InfinityDimension(tier - 1), diff / 10);
@ -353,16 +366,29 @@ export const InfinityDimensions = {
.clampMin(InfinityDimension(1).amount);
},
tryAutoUnlock() {
if (!EternityMilestone.autoUnlockID.isReached || InfinityDimension(8).isUnlocked) return;
for (const dimension of this.all) {
// If we cannot unlock this one, we can't unlock the rest, either
if (!dimension.unlock()) break;
}
},
buyMax() {
// Try to unlock dimensions
const unlockedDimensions = this.all.filter(dimension => dimension.unlock());
// Try to buy single from the highest affordable new dimensions
unlockedDimensions.slice().reverse().forEach(dimension => {
if (dimension.purchases === 0) dimension.buySingle();
});
// Try to buy max from the lowest dimension (since lower dimensions have bigger multiplier per purchase)
unlockedDimensions.forEach(dimension => dimension.buyMax());
},
get powerConversionRate() {
const multiplier = PelleRifts.death.milestones[2].effectOrDefault(1);
return (7 + getAdjustedGlyphEffect("infinityrate") + PelleUpgrade.infConversion.effectOrDefault(0)) * multiplier;
}
};
export function tryUnlockInfinityDimensions(auto) {
if (auto && (!EternityMilestone.autoUnlockID.isReached || InfinityDimension(8).isUnlocked)) return;
for (let tier = 1; tier <= 8; ++tier) {
if (InfinityDimension(tier).isUnlocked) continue;
InfinityDimension(tier).tryUnlock();
}
}

View File

@ -250,6 +250,59 @@ window.findFirstInfiniteCostPurchase = function findFirstInfiniteCostPurchase(
return lower;
};
/**
* LinearCostScaling is a helper class for costs that scale linearly. If we
* know the available resources, initial cost, and cost multiplier, we can
* figure out the maximum amount of purchases, and also the resulting total
* cost and cost multiplier.
*
* i = initial cost
* m = cost multiplier
* p = purchases
* t = total cost
*
* t = i * (1 - m^p) / (1 - m)
* p = floor(log(1 + t * (m - 1) / i) / log(m))
*/
window.LinearCostScaling = class LinearCostScaling {
/**
* @param {Decimal} resourcesAvailable amount of available resources
* @param {Decimal} initialCost current cost
* @param {Number} costMultiplier current cost multiplier
* @param {Number} maxPurchases max amount of purchases
* @param {Boolean} free signifies if the purchase is free -> if we only need to consider the last cost
*/
constructor(resourcesAvailable, initialCost, costMultiplier, maxPurchases = Number.MAX_SAFE_INTEGER, free = false) {
if (free) {
this._purchases = Math.clampMax(Math.floor(
resourcesAvailable.div(initialCost).log10() /
Math.log10(costMultiplier) + 1), maxPurchases);
} else {
this._purchases = Math.clampMax(Math.floor(
resourcesAvailable.mul(costMultiplier - 1).div(initialCost).add(1).log10() /
Math.log10(costMultiplier)), maxPurchases);
}
this._totalCostMultiplier = Decimal.pow(costMultiplier, this._purchases);
if (free) {
this._totalCost = initialCost.mul(Decimal.pow(costMultiplier, this._purchases - 1));
} else {
this._totalCost = initialCost.mul(Decimal.sub(1, this._totalCostMultiplier)).div(1 - costMultiplier);
}
}
get purchases() {
return this._purchases;
}
get totalCostMultiplier() {
return this._totalCostMultiplier;
}
get totalCost() {
return this._totalCost;
}
};
/**
* ExponentialCostScaling provides both a max quantity and a price
* @typedef {Object} QuantityAndPrice

View File

@ -194,7 +194,6 @@ GameDatabase.speedrunMilestones = [
// Destabilization isn't a reality reset because it shortcuts gameLoop; this is checked in laitelaRealityTick
},
{
// TODO: At the time of implementing speedrun mode, full game completion is still unimplemented - update this entry
id: 25,
key: "completeFullGame",
name: "Game Completed!",

View File

@ -1192,7 +1192,7 @@ GameStorage.devMigrations = {
};
delete player.options.showCondenseToMilestone;
},
player => {
() => {
// This is just an empty patch because some orders got really messed up. Sorry -Scar
},
player => {
@ -1275,19 +1275,22 @@ GameStorage.devMigrations = {
},
player => {
const from = player.celestials.laitela;
player.auto.darkMatterDims.isActive = from.automation.dimensions;
player.auto.ascension.isActive = from.automation.ascension;
player.auto.annihilation.isActive = from.automation.singularity;
player.auto.singularity.isActive = from.automation.annihilation;
if (from.automation) {
player.auto.darkMatterDims.isActive = from.automation.dimensions;
player.auto.ascension.isActive = from.automation.ascension;
player.auto.annihilation.isActive = from.automation.singularity;
player.auto.singularity.isActive = from.automation.annihilation;
delete player.celestials.laitela.automation.dimensions;
delete player.celestials.laitela.automation.ascension;
delete player.celestials.laitela.automation.singularity;
delete player.celestials.laitela.automation.annihilation;
}
player.auto.darkMatterDims.lastTick = from.darkAutobuyerTimer;
player.auto.ascension.lastTick = from.darkAutobuyerTimer;
player.auto.annihilation.multiplier = from.autoAnnihilationSetting;
delete player.celestials.laitela.automation.dimensions;
delete player.celestials.laitela.automation.ascension;
delete player.celestials.laitela.automation.singularity;
delete player.celestials.laitela.automation.annihilation;
delete player.celestials.laitela.darkAutobuyerTimer;
delete player.celestials.laitela.darkAutobuyerTimer;
delete player.celestials.laitela.autoAnnihilationSetting;

View File

@ -16,11 +16,15 @@ class SubtabState {
return this.config.hideAt <= Pelle.endState;
}
get hidable() {
return this.config.hidable;
}
get isHidden() {
if (Enslaved.isRunning || Pelle.hasGalaxyGenerator) return false;
// eslint-disable-next-line no-bitwise
return ((player.options.hiddenSubtabBits[this._parent.id] & (1 << this.id)) !== 0) &&
this.config.hidable;
this.hidable;
}
get isUnlocked() {
@ -98,11 +102,15 @@ class TabState {
return this.config.hideAt <= Pelle.endState;
}
get hidable() {
return this.config.hidable;
}
get isHidden() {
if (Enslaved.isRunning || Pelle.isDoomed) return false;
const hasVisibleSubtab = this.subtabs.some(t => t.isAvailable);
// eslint-disable-next-line no-bitwise
return (((player.options.hiddenTabBits & (1 << this.id)) !== 0) || !hasVisibleSubtab) && this.config.hidable;
return (((player.options.hiddenTabBits & (1 << this.id)) !== 0) || !hasVisibleSubtab) && this.hidable;
}
get isUnlocked() {

View File

@ -576,7 +576,7 @@ export function gameLoop(passDiff, options = {}) {
updateTachyonGalaxies();
Currency.timeTheorems.add(getTTPerSecond().times(diff / 1000));
tryUnlockInfinityDimensions(true);
InfinityDimensions.tryAutoUnlock();
BlackHoles.updatePhases(blackHoleDiff);

View File

@ -89,7 +89,7 @@
border: 0.2rem solid;
transition-duration: 0.2s;
border-radius: 0.5rem;
width: 3rem;
width: 4.6rem;
height: 3rem;
}
@ -104,8 +104,9 @@
}
.c-glyph-sacrifice-options__option--active {
color: var(--color-reality-light);
color: black;
border-color: var(--color-reality-light);
background-color: var(--color-reality-light);
pointer-events: none;
}
@ -309,8 +310,9 @@
.c-auto-sac-type-tab__effect-desc {
border-radius: 0.5em;
border: 0.1rem solid;
padding: 0.25em 0.5em;
padding: 0.25em 1.5em;
min-height: 3em;
position: relative;
}
.c-auto-sac-type-tab__effect-desc--active {
@ -322,12 +324,12 @@
.c-auto-sac-type-tab__effect-desc--inactive {
cursor: pointer;
opacity: 0.6;
opacity: 0.7;
transition: opacity 0.2s;
}
.c-auto-sac-type-tab__effect-desc--inactive:hover {
opacity: 0.8;
opacity: 0.95;
text-shadow: 0 0 0.3rem;
}
@ -396,6 +398,7 @@
border-style: solid;
margin-bottom: -0.1rem;
transition: color 0.2s;
position: relative;
}
.s-base--metro .c-glyph-auto-pick-options__option {
@ -407,9 +410,11 @@
}
.c-glyph-auto-pick-options__option--active {
color: var(--color-reality-light);
border-color: var(--color-reality-light);
color: black;
background-color: var(--color-reality);
border-color: var(--color-reality);
z-index: 1;
pointer-events: none;
}
.c-glyph-auto-pick-options__option--inactive {

View File

@ -1319,12 +1319,6 @@ screen and (max-width: 480px) {
height: 4.5rem;
}
.o-primary-btn--new-dim {
font-weight: bold;
width: 22rem;
height: 7rem;
}
.o-primary-btn--quick-reset {
font-size: 1.2rem;
width: 20rem;
@ -6327,7 +6321,6 @@ kbd {
.c-effarig-run-button {
font-size: 10rem;
font-family: sans-serif;
font-weight: bold;
user-select: none;
cursor: pointer;
@ -6372,6 +6365,11 @@ kbd {
background: #400000;
}
.c-effarig-run-button__inner--running,
.c-effarig-run-button__inner--not-running {
margin-top: -3rem;
}
.c-effarig-run-button__inner--running {
background-image: url("../images/noise.png");
-webkit-background-clip: text;
@ -9157,13 +9155,16 @@ input.o-automator-block-input {
.l-hide-modal-subtab-container {
display: flex;
flex-wrap: wrap;
width: 62.6rem;
width: 70rem;
justify-content: center;
position: relative;
}
.c-hide-modal-all-subtab-container {
border-radius: 0.8rem;
border: 0.1rem solid black;
padding: 0.2rem;
cursor: pointer;
}
.s-base--metro .c-hide-modal-all-subtab-container {
@ -9208,12 +9209,14 @@ input.o-automator-block-input {
}
.c-hide-modal-button--always-visible {
color: var(--color-text-inverted);
background-color: var(--color-disabled);
pointer-events: none;
cursor: default;
}
.c-hide-modal-button--current {
text-shadow: 0 0 0.3rem;
.c-hide-modal-button--always-visible:hover {
color: var(--color-text-inverted);
background-color: var(--color-disabled);
}
.c-hide-modal-tab-button--infinity {

View File

@ -262,10 +262,10 @@
(Too many infinities for more)
</button>
</div>
<button class="o-primary-btn o-primary-btn--new-dim" style="position: static;">
<button class="o-prestige-button o-infinity-button" style="position: static;">
<b>Get 1e308 antimatter to unlock a new Dimension.</b>
</button>
<button class="o-primary-btn o-primary-btn--disabled o-primary-btn--new-dim" style="position: static;">
<button class="o-prestige-button o-infinity-button--unavailable o-infinity-button" style="position: static;">
<b>Get 1e308 antimatter to unlock a new Dimension.</b>
</button>
<button class="l-reality-button c-reality-button c-reality-button--bad">

View File

@ -1,10 +1,12 @@
<script>
import ModalWrapperChoice from "@/components/modals/ModalWrapperChoice";
import PrimaryButton from "@/components/PrimaryButton";
export default {
name: "ImportSaveModal",
components: {
ModalWrapperChoice
ModalWrapperChoice,
PrimaryButton
},
data() {
return {
@ -62,8 +64,7 @@ export default {
<template>
<ModalWrapperChoice
:show-cancel="!inputIsValid"
:show-confirm="inputIsValid"
@confirm="importSave"
:show-confirm="false"
>
<template #header>
Input your save
@ -101,8 +102,13 @@ export default {
{{ saveCheckString }}
</div>
</div>
<template #confirm-text>
<PrimaryButton
v-if="inputIsValid"
class="o-primary-btn--width-medium c-modal-message__okay-btn c-modal__confirm-btn"
@click="importSave"
>
Import
</template>
</PrimaryButton>
</ModalWrapperChoice>
</template>

View File

@ -13,6 +13,7 @@ export default {
},
data() {
return {
hidable: false,
hidden: false,
};
},
@ -26,15 +27,15 @@ export default {
"c-hide-modal-tab-button": true,
"c-hide-modal-button--active": !this.hidden,
"c-hide-modal-button--inactive": this.hidden,
"c-hide-modal-button--always-visible": !this.subtab.config.hidable || this.isCurrentSubtab,
"c-hide-modal-button--current": this.isCurrentSubtab,
"c-hide-modal-button--always-visible": !this.hidable || this.isCurrentSubtab,
[`c-hide-modal-tab-button--${this.tab.key}`]: !this.isCurrentSubtab,
};
},
},
methods: {
update() {
this.hidden = this.subtab.isHidden && this.subtab.config.hidable;
this.hidable = this.subtab.hidable;
this.hidden = this.subtab.isHidden && this.hidable;
},
toggleVisibility() {
this.subtab.toggleVisibility();
@ -45,8 +46,9 @@ export default {
<template>
<div
v-tooltip="hidable ? isCurrentSubtab ? 'You cannot hide the tab you are on' : '' : 'Options tabs cannot be hidden'"
:class="classObject"
@click="toggleVisibility()"
@click="toggleVisibility"
>
{{ subtab.name }}
</div>

View File

@ -14,51 +14,72 @@ export default {
},
data() {
return {
tabName: "",
subtabs: {},
hidden: false,
isVisible: false,
isHidable: false,
isHidden: false,
unlockedSubtabs: [],
};
},
computed: {
tabName() {
return this.tab.name;
},
subtabs() {
return this.tab.subtabs;
},
styleObjectRow() {
return {
"background-color": this.hidden ? "var(--color-bad)" : "var(--color-good)",
"background-color": this.isHidden ? "var(--color-gh-purple)" : "var(--color-good)",
};
},
isCurrentTab() {
return this.tab.id === Tabs.current.id;
},
classObjectButton() {
alwaysVisible() {
return !this.isHidable || this.isCurrentTab;
},
rowClass() {
return {
"c-hide-modal-tab-button": true,
"c-hide-modal-button--active": !this.hidden,
"c-hide-modal-button--inactive": this.hidden,
"c-hide-modal-button--always-visible": !this.tab.config.hidable || this.isCurrentTab,
"c-hide-modal-button--current": this.isCurrentTab,
[`c-hide-modal-tab-button--${this.tab.key}`]: !this.isCurrentTab,
"c-hide-modal-all-subtab-container": true,
"l-hide-modal-subtab-container": true,
"c-hidden-tabs-background__visible": !this.isHidden,
"c-hidden-tabs-background__hidden": this.isHidden,
"c-hidden-tabs-background__always-visible": this.alwaysVisible
};
},
unlockedSubtabs() {
return this.subtabs.filter(sub => sub.isUnlocked);
}
rowVisibleIndicatorClass() {
return {
"c-indicator-icon": true,
"fas": true,
"fa-check": !this.isHidden,
"fa-times": this.isHidden,
"fa-exclamation": this.alwaysVisible,
};
},
rowVisibleIndicatorTooltip() {
if (this.isHidden) return "Click to unhide tab";
if (!this.alwaysVisible) return "Click to hide tab";
return "This tab cannot be hidden";
},
},
methods: {
update() {
this.tabName = this.tab.config.name;
this.subtabs = this.tab.subtabs;
this.hidden = this.tab.isHidden && this.tab.config.hidable;
const tab = this.tab;
this.isVisible = tab.isUnlocked;
this.isHidable = tab.hidable;
this.isHidden = tab.isHidden && this.isHidable;
this.unlockedSubtabs = this.subtabs.filter(sub => sub.isUnlocked);
},
toggleVisibility() {
// If this tab and all subtabs are hidden, unhide all subtabs too
if (this.tab.isHidden && this.subtabs.every(t => t.isHidden || !t.isUnlocked)) {
for (const subtab of this.subtabs) {
if (subtab.isUnlocked) subtab.toggleVisibility();
// If this tab and all unlocked subtabs are hidden, unhide all subtabs in addition to the tab
if (this.tab.isHidden && this.unlockedSubtabs.every(t => t.isHidden)) {
for (const subtab of this.unlockedSubtabs) {
subtab.toggleVisibility();
}
this.tab.unhideTab();
} else this.tab.toggleVisibility();
},
getKey(subtab) {
return `${this.tab.id} ${subtab.id} ${subtab.isHidden}`;
} else {
this.tab.toggleVisibility();
}
}
},
};
@ -66,24 +87,44 @@ export default {
<template>
<div
v-if="tab.isUnlocked"
class="c-hide-modal-all-subtab-container l-hide-modal-subtab-container"
:style="styleObjectRow"
v-if="isVisible"
:class="rowClass"
@click.self="toggleVisibility"
>
<div
:class="classObjectButton"
@click="toggleVisibility()"
>
{{ tabName }}
<br>
(all subtabs)
</div>
<br>
<HiddenSubtabsButton
v-for="subtab in unlockedSubtabs"
:key="getKey(subtab)"
v-for="(subtab, i) in unlockedSubtabs"
:key="i"
:subtab="subtab"
:tab="tab"
/>
<div
v-tooltip="rowVisibleIndicatorTooltip"
:class="rowVisibleIndicatorClass"
@click="toggleVisibility"
/>
</div>
</template>
<style scoped>
.c-indicator-icon {
color: black;
position: absolute;
right: 0;
top: 0;
padding: 0.2rem;
text-shadow: none;
}
.c-hidden-tabs-background__visible {
background-color: var(--color-good);
}
.c-hidden-tabs-background__hidden {
background-color: var(--color-gh-purple);
}
.c-hidden-tabs-background__always-visible {
background-color: var(--color-disabled);
cursor: default;
}
</style>

View File

@ -10,15 +10,15 @@ export default {
},
data() {
return {
tabs: null,
isEnslaved: false,
isDoomed: false,
};
},
computed: {
tabs: () => Tabs.currentUIFormat,
},
methods: {
update() {
// TODO: This makes the entire Tab structure reactive. Fix this.
this.tabs = Tab;
this.isEnslaved = Enslaved.isRunning;
this.isDoomed = Pelle.isDoomed;
},
@ -35,6 +35,9 @@ export default {
<br>
Some tabs cannot be hidden, and you cannot hide your current tab.
<br>
Unhiding a tab in which all subtabs are hidden will also unhide all subtabs,
and hiding all subtabs will also hide the tab.
<br>
<div v-if="isDoomed">
You cannot hide your tabs within Doomed.
</div>
@ -44,13 +47,12 @@ export default {
<br>
(You cannot hide your tabs within this Reality)
</div>
<div
<HiddenTabGroup
v-for="(tab, index) in tabs"
:key="index"
:tab="tab"
class="l-hide-modal-tab-container"
>
<HiddenTabGroup :tab="tab" />
</div>
/>
</ModalWrapperOptions>
</template>

View File

@ -95,14 +95,16 @@ export default {
setProgress(Currency.eternityPoints.value, DC.E4000, "Percentage to Reality");
} else if (InfinityDimension(8).isUnlocked) {
setProgress(Currency.infinityPoints.value, Player.eternityGoal, "Percentage to Eternity");
} else if (InfinityDimension(1).isUnlocked) {
setProgress(Currency.antimatter.value,
InfinityDimensions.next().requirement,
"Percentage to unlock a new Infinity Dimension");
} else if (player.break) {
setProgress(Currency.antimatter.value,
InfinityDimensions.next().requirement,
"Percentage to unlock a new type of Dimension");
const text = `Percentage to unlock a new ${InfinityDimensions.next().hasIPUnlock
? "type of Dimension"
: "Infinity Dimension"}`;
const nextID = InfinityDimensions.next();
if (nextID.ipRequirementReached) {
setProgress(player.records.thisEternity.maxAM, nextID.amRequirement, text);
} else {
setProgress(player.infinityPoints, nextID.ipRequirement, text);
}
} else {
setProgress(Currency.antimatter.value, Decimal.NUMBER_MAX_VALUE, "Percentage to Infinity");
}

View File

@ -90,7 +90,7 @@ export default {
<AutobuyerIntervalButton :autobuyer="autobuyer" />
</template>
<template
v-else
v-else-if="postBreak"
#intervalSlot
>
<select

View File

@ -58,6 +58,9 @@ export default {
questionmarkTooltip() {
return "All Glyph choices are given a score based on the chosen option, and the Glyph with the highest score " +
"is picked. If this Glyph is below a mode-specific threshold, it will be Sacrificed instead.";
},
unlockedModes() {
return Object.values(this.modes).filter(idx => this.isUnlocked(idx));
}
},
methods: {
@ -187,8 +190,7 @@ export default {
<br>
<div class="c-glyph-filter-mode-container">
<div
v-for="index in modes"
v-if="isUnlocked(index)"
v-for="index in unlockedModes"
:key="index"
:class="optionClass(index)"
@click="setMode(index)"

View File

@ -14,10 +14,17 @@ export default {
data() {
return {
isActive: AutoGlyphProcessor.types[this.glyphType].effectChoices[this.effect.id],
isExcluded: false,
noExclude: false,
effarigSettings: {
effarigrm: false,
effarigglyph: false
}
};
},
computed: {
color() {
return GlyphTypes[this.glyphType].color;
},
description() {
return typeof this.effect.genericDesc === "function"
? this.effect.genericDesc()
@ -26,27 +33,12 @@ export default {
classObject() {
return this.isActive ? "c-auto-sac-type-tab__effect-desc--active" : "c-auto-sac-type-tab__effect-desc--inactive";
},
},
methods: {
update() {
this.isExcluded = this.exclusionTooltip() !== "";
},
toggleSelection() {
this.isActive = !AutoGlyphProcessor.types[this.glyphType].effectChoices[this.effect.id];
AutoGlyphProcessor.types[this.glyphType].effectChoices[this.effect.id] = this.isActive;
},
setEffectCount(event) {
const inputValue = event.target.value;
if (!isNaN(inputValue)) {
this.autoSacrificeSettings.effectCount = Math.clamp(inputValue, 0, 8);
}
},
// This is hardcoded here since there is only one case ever, and that adding generic dynamic support to multiple
// pairs/groups of effects is both out of design scope and an unacceptable performance hit to amplified realities
exclusionTooltip() {
if (Ra.has(RA_UNLOCKS.GLYPH_EFFECT_COUNT)) return "";
if (this.noExclude) return "";
const effarigSettings = AutoGlyphProcessor.types.effarig.effectChoices;
const effarigSettings = this.effarigSettings;
if (effarigSettings.effarigrm && effarigSettings.effarigglyph &&
(this.effect.id === "effarigrm" || this.effect.id === "effarigglyph")) {
return "RM multiplier and Glyph instability cannot occur together on the same Glyph!";
@ -59,27 +51,82 @@ export default {
}
return "";
},
isExcluded() {
return this.exclusionTooltip !== "";
}
},
methods: {
update() {
const effarigSettings = AutoGlyphProcessor.types.effarig.effectChoices;
this.effarigSettings.effarigrm = effarigSettings.effarigrm;
this.effarigSettings.effarigglyph = effarigSettings.effarigglyph;
this.noExclude = Ra.has(RA_UNLOCKS.GLYPH_EFFECT_COUNT);
},
toggleSelection() {
this.isActive = !AutoGlyphProcessor.types[this.glyphType].effectChoices[this.effect.id];
AutoGlyphProcessor.types[this.glyphType].effectChoices[this.effect.id] = this.isActive;
},
setEffectCount(event) {
const inputValue = event.target.value;
if (!isNaN(inputValue)) {
this.autoSacrificeSettings.effectCount = Math.clamp(inputValue, 0, 8);
}
},
}
};
</script>
<template>
<div
v-tooltip="exclusionTooltip"
:class="classObject"
@click="toggleSelection()"
>
<span
v-if="isExcluded"
v-tooltip="exclusionTooltip()"
>
<del>{{ description }}</del>
</span>
<span v-else>
<span>
<i
v-if="isExcluded"
class="fas fa-exclamation l-dock l-dock-left"
/>
{{ description }}
<i
v-if="isExcluded"
class="fas fa-exclamation l-dock l-dock-right"
/>
</span>
<i
v-if="isActive"
class="fas fa-check c-selected-effect-toggle-indicator--active"
:style="{ 'background-color': color }"
/>
</div>
</template>
<style scoped>
.c-selected-effect-toggle-indicator--active {
color: black;
font-size: 1rem;
position: absolute;
/* -0.1rem = -1px, needed because CSS renders a black border between the check and the border of the selector
otherwise */
top: -0.1rem;
right: -0.1rem;
border-radius: 0 0.4rem;
padding: 0.2rem;
text-shadow: none;
}
.l-dock {
position: absolute;
margin: 0 4rem;
top: 50%;
transform: translateY(-50%);
}
.l-dock-left {
left: 0;
}
.l-dock-right {
right: 0;
}
</style>

View File

@ -18,6 +18,7 @@ export default {
return {
hasPrevTier: false,
isUnlocked: false,
canUnlock: false,
multiplier: new Decimal(0),
baseAmount: 0,
amount: new Decimal(0),
@ -31,7 +32,6 @@ export default {
isAutobuyerOn: false,
isEC8Running: false,
hardcap: InfinityDimensions.HARDCAP_PURCHASES,
requirementReached: false,
eternityReached: false,
enslavedRunning: false,
};
@ -47,17 +47,16 @@ export default {
return ` (+${format(this.rateOfChange, 2, 2)}%/s)`;
},
costDisplay() {
const requirement = InfinityDimension(this.tier).requirement;
if (this.isUnlocked || this.shiftDown) {
if (this.isCapped) return "Capped";
return this.showCostTitle ? `Cost: ${format(this.cost)} IP` : `${format(this.cost)} IP`;
}
if (this.requirementReached) {
if (this.canUnlock) {
return "Unlock";
}
return `Reach ${formatPostBreak(requirement)} AM`;
return `Reach ${formatPostBreak(InfinityDimension(this.tier).amRequirement)} AM`;
},
hardcapPurchases() {
return format(this.hardcap, 1, 1);
@ -68,7 +67,7 @@ export default {
return `Purchased ${quantifyInt("time", this.purchases)}`;
},
showRow() {
return this.eternityReached || this.isUnlocked || this.requirementReached || this.amount.gt(0) ||
return this.eternityReached || this.isUnlocked || this.canUnlock || this.amount.gt(0) ||
this.hasPrevTier;
},
showCostTitle() {
@ -87,6 +86,7 @@ export default {
this.hasPrevTier = tier === 1 || InfinityDimension(tier - 1).isUnlocked;
const autobuyer = Autobuyer.infinityDimension(tier);
this.isUnlocked = dimension.isUnlocked;
this.canUnlock = dimension.canUnlock;
this.multiplier.copyFrom(dimension.multiplier);
this.baseAmount = dimension.baseAmount;
this.purchases = dimension.purchases;
@ -95,9 +95,6 @@ export default {
this.isAutobuyerUnlocked = autobuyer.isUnlocked;
this.cost.copyFrom(dimension.cost);
this.isAvailableForPurchase = dimension.isAvailableForPurchase;
if (!this.isUnlocked) {
this.isAvailableForPurchase = dimension.requirementReached;
}
this.isCapped = dimension.isCapped;
if (this.isCapped) {
this.capIP.copyFrom(dimension.hardcapIPAmount);
@ -105,23 +102,14 @@ export default {
}
this.isEC8Running = EternityChallenge(8).isRunning;
this.isAutobuyerOn = autobuyer.isActive;
this.requirementReached = dimension.requirementReached;
this.eternityReached = PlayerProgress.eternityUnlocked();
this.enslavedRunning = Enslaved.isRunning;
},
buyManyInfinityDimension() {
if (!this.isUnlocked) {
InfinityDimension(this.tier).tryUnlock();
return;
}
buyManyInfinityDimension(this.tier);
buySingleInfinityDimension() {
InfinityDimension(this.tier).buySingle();
},
buyMaxInfinityDimension() {
if (!this.isUnlocked) {
InfinityDimension(this.tier).tryUnlock();
return;
}
buyMaxInfDims(this.tier);
InfinityDimension(this.tier).buyMax();
},
}
};
@ -131,7 +119,7 @@ export default {
<div
v-show="showRow"
class="c-infinity-dim-row"
:class="{ 'c-dim-row--not-reached': !isUnlocked && !requirementReached }"
:class="{ 'c-dim-row--not-reached': !isUnlocked && !canUnlock }"
>
<div class="c-dim-row__label c-dim-row__name">
{{ name }} Infinity Dimension {{ formatX(multiplier, 2, 1) }}
@ -147,9 +135,9 @@ export default {
</div>
<PrimaryButton
v-tooltip="capTooltip"
:enabled="isAvailableForPurchase && !isCapped"
:enabled="isAvailableForPurchase || (!isUnlocked && canUnlock)"
class="o-primary-btn--buy-id l-dim-row__button"
@click="buyManyInfinityDimension"
@click="buySingleInfinityDimension"
>
{{ costDisplay }}
</PrimaryButton>

View File

@ -62,8 +62,7 @@ export default {
this.extraTesseracts = Tesseracts.extra;
},
maxAll() {
tryUnlockInfinityDimensions(false);
buyMaxInfinityDimensions();
InfinityDimensions.buyMax();
},
toggleAllAutobuyers() {
toggleAllInfDims();

View File

@ -18,6 +18,7 @@ export default {
return {
hasPrevTier: false,
isUnlocked: false,
canUnlock: false,
multiplier: new Decimal(0),
baseAmount: 0,
amount: new Decimal(0),
@ -31,7 +32,6 @@ export default {
isAutobuyerOn: false,
isEC8Running: false,
hardcap: InfinityDimensions.HARDCAP_PURCHASES,
requirementReached: false,
eternityReached: false,
enslavedRunning: false,
};
@ -47,17 +47,16 @@ export default {
return ` (+${format(this.rateOfChange, 2, 2)}%/s)`;
},
costDisplay() {
const requirement = InfinityDimension(this.tier).requirement;
if (this.isUnlocked || this.shiftDown) {
if (this.isCapped) return "Capped";
return this.showCostTitle ? `Cost: ${format(this.cost)} IP` : `${format(this.cost)} IP`;
}
if (this.requirementReached) {
if (this.canUnlock) {
return "Unlock";
}
return `Reach ${formatPostBreak(requirement)} AM`;
return `Reach ${formatPostBreak(InfinityDimension(this.tier).amRequirement)} AM`;
},
capTooltip() {
if (this.enslavedRunning) return `Enslaved prevents the purchase of more than ${format(10)} Infinity Dimensions`;
@ -65,7 +64,7 @@ export default {
return `Purchased ${quantifyInt("time", this.purchases)}`;
},
showRow() {
return this.eternityReached || this.isUnlocked || this.requirementReached || this.amount.gt(0) ||
return this.eternityReached || this.isUnlocked || this.canUnlock || this.amount.gt(0) ||
this.hasPrevTier;
},
showCostTitle() {
@ -83,6 +82,7 @@ export default {
const dimension = InfinityDimension(tier);
this.hasPrevTier = tier === 1 || InfinityDimension(tier - 1).isUnlocked;
this.isUnlocked = dimension.isUnlocked;
this.canUnlock = dimension.canUnlock;
this.multiplier.copyFrom(dimension.multiplier);
this.baseAmount = dimension.baseAmount;
this.purchases = dimension.purchases;
@ -91,9 +91,6 @@ export default {
this.isAutobuyerUnlocked = Autobuyer.infinityDimension(tier).isUnlocked;
this.cost.copyFrom(dimension.cost);
this.isAvailableForPurchase = dimension.isAvailableForPurchase;
if (!this.isUnlocked) {
this.isAvailableForPurchase = dimension.requirementReached;
}
this.isCapped = dimension.isCapped;
if (this.isCapped) {
this.capIP.copyFrom(dimension.hardcapIPAmount);
@ -101,23 +98,14 @@ export default {
}
this.isEC8Running = EternityChallenge(8).isRunning;
this.isAutobuyerOn = Autobuyer.infinityDimension(tier).isActive;
this.requirementReached = dimension.requirementReached;
this.eternityReached = PlayerProgress.eternityUnlocked();
this.enslavedRunning = Enslaved.isRunning;
},
buyManyInfinityDimension() {
if (!this.isUnlocked) {
InfinityDimension(this.tier).tryUnlock();
return;
}
buyManyInfinityDimension(this.tier);
buySingleInfinityDimension() {
InfinityDimension(this.tier).buySingle();
},
buyMaxInfinityDimension() {
if (!this.isUnlocked) {
InfinityDimension(this.tier).tryUnlock();
return;
}
buyMaxInfDims(this.tier);
InfinityDimension(this.tier).buyMax();
},
}
};
@ -127,7 +115,7 @@ export default {
<div
v-show="showRow"
class="c-infinity-dim-row"
:class="{ 'c-dim-row--not-reached': !isUnlocked && !requirementReached }"
:class="{ 'c-dim-row--not-reached': !isUnlocked && !canUnlock }"
>
<div class="c-dim-row__label c-dim-row__name">
{{ name }} Infinity D <span class="c-infinity-dim-row__multiplier">{{ formatX(multiplier, 2, 1) }}</span>
@ -143,9 +131,9 @@ export default {
</div>
<PrimaryButton
v-tooltip="capTooltip"
:enabled="isAvailableForPurchase && !isCapped"
:enabled="isAvailableForPurchase || (!isUnlocked && canUnlock)"
class="o-primary-btn--buy-id l-dim-row__button o-primary-btn o-primary-btn--new"
@click="buyManyInfinityDimension"
@click="buySingleInfinityDimension"
>
{{ costDisplay }}
</PrimaryButton>

View File

@ -68,8 +68,7 @@ export default {
this.extraTesseracts = Tesseracts.extra;
},
maxAll() {
tryUnlockInfinityDimensions(false);
buyMaxInfinityDimensions();
InfinityDimensions.buyMax();
},
toggleAllAutobuyers() {
toggleAllInfDims();

View File

@ -1,49 +1,63 @@
<script>
import PrimaryButton from "@/components/PrimaryButton";
export default {
name: "HeaderUnlockInfinityDimButton",
components: {
PrimaryButton
},
data() {
return {
isVisible: false,
requirement: new Decimal(0),
isAffordable: false,
anyInfinityDimensionUnlocked: false
canUnlock: false,
hasIPUnlock: true,
amRequirement: new Decimal(0),
ipRequirement: 0,
};
},
computed: {
text() {
const dimensionText = `a new ${this.hasIPUnlock ? "type of Dimension" : "Infinity Dimension"}.`;
if (this.canUnlock) {
return `Unlock ${dimensionText}`;
}
const amDisplay = format(this.amRequirement);
const ipDisplay = format(this.ipRequirement);
if (this.hasIPUnlock) {
return `Reach ${ipDisplay} Infinity Points and ${amDisplay} antimatter to unlock ${dimensionText}`;
}
return `Reach ${amDisplay} antimatter to unlock ${dimensionText}`;
},
buttonClassObject() {
return {
"o-prestige-button": true,
"o-infinity-button": true,
"l-game-header__new-dim-btn": true,
"o-infinity-button--unavailable": !this.canUnlock
};
},
},
methods: {
update() {
this.isVisible = player.break && !InfinityDimension(8).isUnlocked && !Player.canEternity &&
!EternityMilestone.autoUnlockID.isReached;
if (!this.isVisible) return;
const requirement = InfinityDimensions.next().requirement;
this.requirement.copyFrom(requirement);
this.isAffordable = player.records.thisEternity.maxAM.gte(requirement);
this.anyInfinityDimensionUnlocked = InfinityDimension(1).isUnlocked;
const nextDimension = InfinityDimensions.next();
this.canUnlock = nextDimension.canUnlock;
this.hasIPUnlock = nextDimension.hasIPUnlock;
this.amRequirement = nextDimension.amRequirement;
this.ipRequirement = nextDimension.ipRequirement;
},
tryUnlockNextInfinityDimension() {
InfinityDimensions.unlockNext(true);
InfinityDimensions.unlockNext();
}
},
};
</script>
<template>
<PrimaryButton
<button
v-if="isVisible"
:enabled="isAffordable"
class="o-primary-btn--new-dim l-game-header__new-dim-btn"
:class="buttonClassObject"
@click="tryUnlockNextInfinityDimension"
>
Get {{ format(requirement) }} antimatter
<br>
to unlock a new
<span v-if="anyInfinityDimensionUnlocked">Infinity Dimension</span>
<span v-else>type of Dimension</span>.
</PrimaryButton>
{{ text }}
</button>
</template>
<style scoped>