Time compression (#651)

Time compression
This commit is contained in:
Andrei Andreev 2019-08-10 20:19:52 +03:00 committed by GitHub
commit f887650d93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 1335 additions and 563 deletions

View File

@ -164,6 +164,7 @@
<script type="text/javascript" src="javascripts/core/secret-formula/celestials/effarig.js"></script>
<script type="text/javascript" src="javascripts/core/secret-formula/celestials/v.js"></script>
<script type="text/javascript" src="javascripts/core/secret-formula/celestials/alchemy.js"></script>
<script type="text/javascript" src="javascripts/core/secret-formula/celestials/compression.js"></script>
<script type="text/javascript" src="javascripts/components/common/primary-button.js"></script>
<script type="text/javascript" src="javascripts/components/common/description-display.js"></script>
@ -246,6 +247,7 @@
<script type="text/javascript" src="javascripts/core/celestials/V.js"></script>
<script type="text/javascript" src="javascripts/core/celestials/ra/ra.js"></script>
<script type="text/javascript" src="javascripts/core/celestials/ra/alchemy.js"></script>
<script type="text/javascript" src="javascripts/core/celestials/ra/compression.js"></script>
<script type="text/javascript" src="javascripts/core/celestials/laitela.js"></script>
<script type="text/javascript" src="javascripts/components/challenges/challenge-box.js"></script>
@ -296,6 +298,9 @@
<script type="text/javascript" src="javascripts/components/eternity/dilation/dilation-button.js"></script>
<script type="text/javascript" src="javascripts/components/eternity/dilation/dilation-upgrade.js"></script>
<script type="text/javascript" src="javascripts/components/eternity/dilation/tachyon-particles.js"></script>
<script type="text/javascript" src="javascripts/components/celestials/subtabs/ra/time-compression-tab.js"></script>
<script type="text/javascript" src="javascripts/components/celestials/subtabs/ra/compression-upgrade.js"></script>
<script type="text/javascript" src="javascripts/components/celestials/subtabs/ra/compression-button.js"></script>
<script type="text/javascript" src="javascripts/components/reality/reality-machines-header.js"></script>
<script type="text/javascript" src="javascripts/components/reality/pp-label.js"></script>

View File

@ -6,10 +6,8 @@ Vue.component("enslaved-tab", {
isStoringReal: false,
autoStoreReal: false,
hasAmplifyStoredReal: false,
hasStoredTimeSpeedBoost: false,
canAdjustStoredTime: false,
storedFraction: 0,
storedTimeSpeedValue: 1,
inEnslaved: false,
completed: false,
storedBlackHole: 0,
@ -24,10 +22,7 @@ Vue.component("enslaved-tab", {
}),
computed: {
amplifiedGameDesc() {
return `^${RA_UNLOCKS.IMPROVED_STORED_TIME.effect.gameTimeAmplification().toFixed(2)}`;
},
storedTimeBoostDesc() {
return formatX(this.storedTimeSpeedValue, 2, 2);
return `${formatPow(RA_UNLOCKS.IMPROVED_STORED_TIME.effect.gameTimeAmplification(), 2, 2)}`;
},
storedRealEfficiencyDesc() {
return formatPercents(this.storedRealEffiency);
@ -35,9 +30,6 @@ Vue.component("enslaved-tab", {
storedRealCapDesc() {
return timeDisplayShort(this.storedRealCap);
},
autoReleaseSpeedup() {
return formatX(this.autoReleaseSpeed, 2, 2);
},
unlocksInfo() {
return ENSLAVED_UNLOCKS;
},
@ -67,9 +59,7 @@ Vue.component("enslaved-tab", {
this.isStoringReal = player.celestials.enslaved.isStoringReal;
this.autoStoreReal = player.celestials.enslaved.autoStoreReal;
this.hasAmplifyStoredReal = Ra.has(RA_UNLOCKS.IMPROVED_STORED_TIME);
this.hasStoredTimeSpeedBoost = Ra.has(RA_UNLOCKS.GAMESPEED_BOOST);
this.canAdjustStoredTime = Ra.has(RA_UNLOCKS.ADJUSTABLE_STORED_TIME);
this.storedTimeSpeedValue = Ra.gamespeedStoredTimeMult();
this.inEnslaved = Enslaved.isRunning;
this.completed = Enslaved.isCompleted;
this.storedReal = player.celestials.enslaved.storedReal;
@ -157,7 +147,6 @@ Vue.component("enslaved-tab", {
<p v-if="inEnslaved">{{timeDisplayShort(nerfedBlackHoleTime)}} in this reality</p>
</button>
<div v-if="hasAmplifyStoredReal"> Amplified: {{ amplifiedGameDesc }} </div>
<div v-if="hasStoredTimeSpeedBoost"> Game speed: {{ storedTimeBoostDesc }} </div>
</div>
<div class="l-enslaved-top-container__half">
<button :class="['o-enslaved-mechanic-button',
@ -190,7 +179,6 @@ Vue.component("enslaved-tab", {
:value="autoRelease"
@input="toggleAutoRelease()">
<label for="autoReleaseBox">Use 1% of stored time every 5 ticks</label>
<div>Effective game speed of last auto-released tick: {{ autoReleaseSpeedup }}</div>
</div>
<div class="l-enslaved-shop-container">
<button

View File

@ -23,7 +23,7 @@ Vue.component("alchemy-resource-info", {
const reagents = this.reaction.reagents
.map(r => `${r.cost}${r.resource.symbol}`)
.join(" + ");
return `${reagents}${this.reactionProduction}${this.resource.symbol}`;
return `${reagents}${this.reaction.reactionProduction.toFixed(2)}${this.resource.symbol}`;
},
realityReactionText() {
const reagents = this.reaction.reagents

View File

@ -0,0 +1,58 @@
"use strict";
Vue.component("compression-button", {
data() {
return {
timeShards: new Decimal(0),
isRunning: false,
requiredForGain: new Decimal(0),
entanglementGain: 0
};
},
computed: {
shardRequirement: () => TimeCompression.timeShardRequirement,
canCompress() {
return this.timeShards.gte(this.shardRequirement);
}
},
methods: {
update() {
this.timeShards.copyFrom(player.timeShards);
this.isRunning = player.celestials.ra.compression.active;
if (!this.isRunning) return;
this.entanglementGain = this.gainedEntanglement();
if (this.entanglementGain <= 0) {
this.requiredForGain.copyFrom(this.minAntimatterForEntanglement());
}
},
minAntimatterForEntanglement() {
if (TimeCompression.totalEntanglement === 308) {
return Decimal.pow10(9e15);
}
const entanglementMult = Effects.max(1, CompressionUpgrade.moreEntanglement);
return Decimal.pow10(2e5 * Math.pow(1 + TimeCompression.totalEntanglement / (30.8 * entanglementMult), 2.5));
},
gainedEntanglement() {
return Math.max(0, TimeCompression.entanglementThisRun - TimeCompression.totalEntanglement);
},
},
template:
`<button class="o-compression-btn" onclick="TimeCompression.toggle()">
<span v-if="!canCompress && !isRunning">
Time compression requires {{ shorten(shardRequirement) }} time shards to activate.
<br>
Currently: {{ shorten(timeShards) }} time shards
</span>
<span v-else-if="!isRunning">Compress time.</span>
<span v-else-if="entanglementGain > 0">
Disable compression.
<br>
Gain {{shorten(entanglementGain, 0, 2)}} Entanglement.
</span>
<span v-else>
Disable compression.
<br>
Reach {{shorten(requiredForGain, 2, 2)}} antimatter to gain more Entanglement.
</span>
</button>`
});

View File

@ -0,0 +1,56 @@
"use strict";
Vue.component("compression-upgrade", {
props: {
upgrade: Object
},
data() {
return {
isBought: false,
isActive: false,
isAffordable: false,
};
},
computed: {
classObject() {
return {
"o-compression-upgrade": true,
"o-compression-upgrade--active": this.isBought && this.isActive,
"o-compression-upgrade--inactive": this.isBought && !this.isActive,
"o-compression-upgrade--available": !this.isBought && this.isAffordable,
"o-compression-upgrade--unavailable": !this.isBought && !this.isAffordable
};
}
},
methods: {
update() {
this.isBought = this.upgrade.isBought;
this.isActive = this.upgrade.canBeApplied;
this.isAffordable = this.upgrade.isAffordable;
}
},
template:
`<div class="l-spoon-btn-group">
<button :class="classObject" @click="upgrade.purchase()">
<description-display
:config="upgrade.config"
:length="70"
name="o-compression-upgrade__description"
/>
<br><br>
<span>To activate: {{ upgrade.config.secondary() }}</span>
<br>
<span>(Currently {{ upgrade.config.currentDisplay() }})</span>
<br><br>
<effect-display :config="upgrade.config" />
<cost-display
v-if="!isBought"
:config="upgrade.config"
singular="Entanglement"
plural="Entanglement"
/>
<div v-else-if="isActive">Active! (Cost: {{ upgrade.config.cost }})</div>
<div v-else>Inactive (Cost: {{ upgrade.config.cost }})</div>
</button>
</div>`
});

View File

@ -32,12 +32,12 @@ Vue.component("reality-glyph-creation", {
return [
{
desc: `At least ${shortenSmallInteger(5000)} Reality consumed for this glyph (Currently ` +
`${AlchemyResource.reality.amount.toFixed(1)})`,
`${shortenSmallInteger(AlchemyResource.reality.amount)})`,
value: AlchemyResource.reality.amount >= 5000
},
{
desc: `${shortenSmallInteger(150000)} total of all other alchemy resources (Currently ` +
`${sumOfOtherAlchemyResources.toFixed(1)})`,
`${shortenSmallInteger(sumOfOtherAlchemyResources)})`,
value: sumOfOtherAlchemyResources >= 150000
},
{
@ -60,8 +60,9 @@ Vue.component("reality-glyph-creation", {
Glyphs.addToInventory(GlyphGenerator.realityGlyph(
{ actualLevel: this.realityGlyphLevel, rawLevel: this.realityGlyphLevel }, this.selectedEffects));
AlchemyResources.resetAmount();
if (player.celestials.effarig.relicShards >= 1e30) {
player.celestials.effarig.relicShards -= 1e30;
// If the player leaves a choice open, don't spend shards
if (player.celestials.effarig.relicShards >= 1e40 && (this.selectedEffects === this.calculateMaxEffects())) {
player.celestials.effarig.relicShards -= 1e40;
}
},
formatGlyphEffect(effect) {

View File

@ -0,0 +1,80 @@
"use strict";
Vue.component("time-compression-tab", {
data() {
return {
entanglement: 0,
totalEntanglement: 0,
respec: false,
};
},
watch: {
respec(newValue) {
player.celestials.ra.compression.respec = newValue;
}
},
computed: {
upgrades() {
return [
[
CompressionUpgrade.freeBoost,
CompressionUpgrade.improvedDTMult,
CompressionUpgrade.replicantiSpeedFromDB
],
[
CompressionUpgrade.strongerDilationGalaxies,
CompressionUpgrade.freeGalaxySoftcap,
CompressionUpgrade.freeGalaxyScaling
],
[
CompressionUpgrade.infDimSoftcap,
CompressionUpgrade.moreEntanglement,
CompressionUpgrade.matterBoost
],
];
},
respecClassObject() {
return {
"o-primary-btn--respec-options": true,
"o-primary-btn--respec-active": this.respec
};
}
},
methods: {
update() {
this.entanglement = TimeCompression.entanglement;
this.totalEntanglement = TimeCompression.totalEntanglement;
this.respec = player.celestials.ra.compression.respec;
}
},
template:
`<div class="l-dilation-tab">
<span>
You have
<span class="c-dilation-tab__tachyons">{{shorten(entanglement, 2, 2)}}</span>
Entanglement.
</span>
<span>
Your total entanglement is {{shorten(totalEntanglement, 2, 2)}}.
</span>
<compression-button />
<span>
Time compression is a stronger type of dilation which dilates values twice, <br>
disables time dimensions, and causes the game to run {{ shorten(1e100) }} times slower.
</span>
<div class="l-dilation-upgrades-grid">
<div v-for="row in upgrades" class="l-dilation-upgrades-grid__row">
<compression-upgrade
v-for="upgrade in row"
:key="upgrade.id"
:upgrade="upgrade"
class="l-dilation-upgrades-grid__cell"
/>
</div>
</div>
<primary-button
:class="respecClassObject"
@click="respec = !respec"
>Respec compression upgrades on Reality</primary-button>
</div>`
});

View File

@ -9,7 +9,7 @@ Vue.component("v-tab", {
achievementsPerAdditionalStudy: 0,
realities: 0,
infinities: new Decimal(0),
eternities: 0,
eternities: new Decimal(0),
dilatedTime: new Decimal(0),
replicanti: new Decimal(0),
rm: new Decimal(0)
@ -23,7 +23,7 @@ Vue.component("v-tab", {
this.achievementsPerAdditionalStudy = V.achievementsPerAdditionalStudy;
this.realities = player.realities;
this.infinities.copyFrom(player.infinitied);
this.eternities = player.eternities;
this.eternities.copyFrom(player.eternities);
this.dilatedTime.copyFrom(player.dilation.dilatedTime);
this.replicanti.copyFrom(player.replicanti.amount);
this.rm.copyFrom(player.reality.realityMachines);

View File

@ -9,18 +9,19 @@ Vue.component("infinity-dim-tab", {
incomeType: "",
isEC8Running: false,
EC8PurchasesLeft: 0,
isAnyAutobuyerUnlocked: false
isAnyAutobuyerUnlocked: false,
conversionRate: 0,
};
},
methods: {
update() {
const infinityPower = player.infinityPower;
this.infinityPower.copyFrom(infinityPower);
this.conversionRate = getInfinityConversionRate();
if (EternityChallenge(9).isRunning) {
this.dimMultiplier.copyFrom(Decimal.pow(Math.max(infinityPower.log2(), 1), 4).max(1));
} else {
const conversionRate = 7 + getAdjustedGlyphEffect("infinityrate");
this.dimMultiplier.copyFrom(infinityPower.pow(conversionRate).max(1));
this.dimMultiplier.copyFrom(infinityPower.pow(this.conversionRate).max(1));
}
this.powerPerSecond.copyFrom(InfinityDimension(1).productionPerSecond);
this.incomeType = EternityChallenge(7).isRunning ? "Seventh Dimensions" : "Infinity Power";
@ -45,7 +46,7 @@ Vue.component("infinity-dim-tab", {
<span class="c-infinity-dim-description__accent">{{shortenMoney(infinityPower)}}</span> infinity power,
translated to
<span class="c-infinity-dim-description__accent">{{shortenMoney(dimMultiplier)}}</span>x
multiplier on all dimensions
multiplier on all dimensions (^{{ conversionRate.toFixed(3) }}).
</p>
</div>
<div>You are getting {{shortenDimensions(powerPerSecond)}} {{incomeType}} per second.</div>

View File

@ -9,7 +9,8 @@ Vue.component("normal-dim-shift-row", {
},
isShift: false,
isBuyable: false,
resets: 0
purchasedBoosts: 0,
freeBoosts: 0
};
},
computed: {
@ -21,6 +22,17 @@ Vue.component("normal-dim-shift-row", {
},
buttonText() {
return `Reset the game for a ${this.isShift ? "new Dimension" : "boost"}`;
},
boostCountText() {
const parts = [this.purchasedBoosts];
if (this.freeBoosts !== 0) {
parts.push(this.freeBoosts);
}
const sum = parts.map(shortenSmallInteger).join(" + ");
if (parts.length >= 2) {
return `${sum} = ${shortenSmallInteger(parts.sum())}`;
}
return sum;
}
},
methods: {
@ -30,7 +42,8 @@ Vue.component("normal-dim-shift-row", {
this.requirement.amount = requirement.amount;
this.isBuyable = requirement.isSatisfied;
this.isShift = DimBoost.isShift;
this.resets = player.resets;
this.purchasedBoosts = DimBoost.purchasedBoosts;
this.freeBoosts = DimBoost.freeBoosts;
},
softReset() {
softResetBtnClick();
@ -41,7 +54,7 @@ Vue.component("normal-dim-shift-row", {
<div
class="c-normal-dim-row__label c-normal-dim-row__label--growable"
>
Dimension {{name}} ({{shortenSmallInteger(resets)}}):
Dimension {{name}} ({{boostCountText}}):
requires {{shortenSmallInteger(requirement.amount)}} {{dimName}} Dimensions
</div>
<primary-button

View File

@ -41,7 +41,7 @@ Vue.component("time-dilation-tab", {
update() {
this.tachyons.copyFrom(player.dilation.tachyonParticles);
this.dilatedTime.copyFrom(player.dilation.dilatedTime);
this.dilatedTimeIncome.copyFrom(getDilationGainPerSecond().times(getGameSpeedupFactor()));
this.dilatedTimeIncome.copyFrom(getDilationGainPerSecond().times(getGameSpeedupForDisplay()));
this.galaxyThreshold.copyFrom(player.dilation.nextThreshold);
this.galaxies = player.dilation.freeGalaxies;
this.animateTachyons = player.options.animations.tachyonParticles;

View File

@ -3,7 +3,7 @@
Vue.component("eternity-milestones-tab", {
data() {
return {
eternityCount: 0,
eternityCount: new Decimal(0),
};
},
computed: {
@ -18,7 +18,7 @@ Vue.component("eternity-milestones-tab", {
},
methods: {
update() {
this.eternityCount = player.eternities;
this.eternityCount.copyFrom(player.eternities);
},
getMilestone(row, column) {
return () => this.milestones[(row - 1) * 3 + column - 1];

View File

@ -10,11 +10,9 @@ Vue.component("replicanti-gain-text", {
update() {
const updateRateMs = player.options.updateRate;
const ticksPerSecond = 1000 / updateRateMs;
const storedTimeWeight = player.celestials.enslaved.storedFraction;
const gamespeedWithStoredTime = getGameSpeedupFactor() * (1 - storedTimeWeight) + storedTimeWeight;
const logGainFactorPerTick = Decimal.divide(gamespeedWithStoredTime * updateRateMs *
const logGainFactorPerTick = Decimal.divide(getGameSpeedupForDisplay() * updateRateMs *
(Math.log(player.replicanti.chance + 1)), getReplicantiInterval());
const log10GainFactorPerTick = logGainFactorPerTick.dividedBy(Math.LN10).toNumber();
const log10GainFactorPerTick = logGainFactorPerTick.dividedBy(Math.LN10);
const replicantiAmount = player.replicanti.amount;
if (TimeStudy(192).isBought && replicantiAmount.log10() > 308) {
const postScale = Math.log10(ReplicantiGrowth.scaleFactor) / ReplicantiGrowth.scaleLog10;
@ -35,18 +33,19 @@ Vue.component("replicanti-gain-text", {
` (${timeEstimateText} until ${shorten(nextThousandOOM)})`;
return;
}
if (log10GainFactorPerTick > 308) {
const galaxiesPerSecond = ticksPerSecond * log10GainFactorPerTick / 308;
if (log10GainFactorPerTick.gt(308)) {
const galaxiesPerSecond = log10GainFactorPerTick.times(ticksPerSecond / 308);
let baseGalaxiesPerSecond, effectiveMaxRG;
if (RealityUpgrade(6).isBought) {
baseGalaxiesPerSecond = galaxiesPerSecond / RealityUpgrade(6).effectValue;
baseGalaxiesPerSecond = galaxiesPerSecond.divide(RealityUpgrade(6).effectValue);
effectiveMaxRG = 50 * Math.log((Replicanti.galaxies.max + 49.5) / 49.5);
} else {
baseGalaxiesPerSecond = galaxiesPerSecond;
effectiveMaxRG = Replicanti.galaxies.max;
}
const allGalaxyTime = Decimal.divide(effectiveMaxRG, baseGalaxiesPerSecond).toNumber();
this.text = `You are gaining ${shorten(galaxiesPerSecond, 2, 1)} galaxies per second` +
` (all galaxies within ${TimeSpan.fromSeconds(effectiveMaxRG / baseGalaxiesPerSecond)})`;
` (all galaxies within ${TimeSpan.fromSeconds(allGalaxyTime)})`;
return;
}
const totalTime = LOG10_MAX_VALUE / (ticksPerSecond * log10GainFactorPerTick);

View File

@ -44,8 +44,8 @@ Vue.component("infinity-upgrades-tab", {
},
disChargeClassObject() {
return {
"o-primary-btn--discharge-options": true,
"o-primary-btn--discharge-active": this.disCharge
"o-primary-btn--respec-options": true,
"o-primary-btn--respec-active": this.disCharge
};
}
},

View File

@ -9,7 +9,8 @@ Vue.component("new-dim-shift-row", {
},
isShift: false,
isBuyable: false,
resets: 0
purchasedBoosts: 0,
freeBoosts: 0
};
},
computed: {
@ -21,6 +22,17 @@ Vue.component("new-dim-shift-row", {
},
buttonText() {
return `Reset the game for a ${this.isShift ? "new Dimension" : "boost"}`;
},
boostCountText() {
const parts = [this.purchasedBoosts];
if (this.freeBoosts !== 0) {
parts.push(this.freeBoosts);
}
const sum = parts.map(shortenSmallInteger).join(" + ");
if (parts.length >= 2) {
return `${sum} = ${shortenSmallInteger(parts.sum())}`;
}
return sum;
}
},
methods: {
@ -30,7 +42,8 @@ Vue.component("new-dim-shift-row", {
this.requirement.amount = requirement.amount;
this.isBuyable = requirement.isSatisfied;
this.isShift = DimBoost.isShift;
this.resets = player.resets;
this.purchasedBoosts = DimBoost.purchasedBoosts;
this.freeBoosts = DimBoost.freeBoosts;
},
softReset() {
softResetBtnClick();
@ -38,7 +51,7 @@ Vue.component("new-dim-shift-row", {
},
template:
`<div class="reset-container dimboost">
<h4>Dimensional {{name}} ({{shortenSmallInteger(resets)}})</h4>
<h4>Dimensional {{name}} ({{boostCountText}})</h4>
<span>Requires: {{shortenSmallInteger(requirement.amount)}} {{dimName}} D</span>
<button
class="storebtn" style="height: 56px;"

View File

@ -67,7 +67,7 @@ Vue.component("new-tickspeed-row", {
this.cost.copyFrom(player.tickSpeedCost);
this.isAffordable = !isEC9Running && canAfford(player.tickSpeedCost);
this.tickspeed.copyFrom(Tickspeed.current);
this.gameSpeedMult = getGameSpeedupFactor();
this.gameSpeedMult = getGameSpeedupForDisplay();
}
},
template:

View File

@ -11,7 +11,7 @@ Vue.component("sidebar", {
methods: {
update() {
this.ipVisible = player.infinitied.gt(0);
this.epVisible = player.eternities > 0;
this.epVisible = PlayerProgress.eternityUnlocked();
this.rmVisible = player.realities > 0;
}
},

View File

@ -11,11 +11,11 @@ Vue.component("game-header-amounts-line", {
},
methods: {
update() {
this.showInfinityPoints = Player.totalInfinitied.gt(0) || player.eternities > 0;
this.showInfinityPoints = Player.totalInfinitied.gt(0) || PlayerProgress.eternityUnlocked();
if (this.showInfinityPoints) {
this.infinityPoints.copyFrom(player.infinityPoints);
}
this.showEternityPoints = player.eternities > 0;
this.showEternityPoints = PlayerProgress.eternityUnlocked();
if (this.showEternityPoints) {
this.eternityPoints.copyFrom(player.eternityPoints);
}

View File

@ -30,7 +30,7 @@ Vue.component("game-header-eternity-button", {
update() {
this.isVisible = player.infinityPoints.gte(Player.eternityGoal) && InfinityDimension(8).isUnlocked;
if (!this.isVisible) return;
if (player.eternities === 0) {
if (!PlayerProgress.eternityUnlocked()) {
this.type = EPButtonDisplayType.FIRST_TIME;
return;
}

View File

@ -19,20 +19,21 @@ Vue.component("game-header-gamma-display", {
if (player.celestials.enslaved.isStoringReal) {
return "Stopped (storing real time)";
}
let speedMod = getGameSpeedupFactor();
const speedMod = getGameSpeedupForDisplay();
let storedTimeText = "";
if (player.celestials.enslaved.isStoring) {
if (Ra.has(RA_UNLOCKS.ADJUSTABLE_STORED_TIME)) {
const storedTimeWeight = player.celestials.enslaved.storedFraction;
speedMod = speedMod * (1 - storedTimeWeight) + storedTimeWeight;
if (storedTimeWeight !== 0) {
storedTimeText = ` (storing ${formatPercents(storedTimeWeight)})`;
}
} else {
speedMod = 1;
storedTimeText = ` (storing all game time)`;
}
}
if (Enslaved.isAutoReleasing) {
storedTimeText = ` (auto-releasing)`;
}
if (speedMod < 10000 && speedMod !== 1) {
return `${speedMod.toFixed(3)}${storedTimeText}`;
}

View File

@ -66,30 +66,7 @@ Vue.component("game-header-tickspeed-row", {
this.cost.copyFrom(player.tickSpeedCost);
this.isAffordable = !isEC9Running && canAfford(player.tickSpeedCost);
this.tickspeed.copyFrom(Tickspeed.current);
this.gameSpeedMult = getGameSpeedupFactor();
},
getGameSpeedupText() {
if (player.celestials.enslaved.isStoringReal) {
return "(γ = 0 | storing real time)";
}
let speedMod = getGameSpeedupFactor();
let storedTimeText = "";
if (player.celestials.enslaved.isStoring) {
if (Ra.has(RA_UNLOCKS.ADJUSTABLE_STORED_TIME)) {
const storedTimeWeight = player.celestials.enslaved.storedFraction;
speedMod = Math.pow(speedMod, 1 - storedTimeWeight);
if (storedTimeWeight !== 0) {
storedTimeText = ` | storing ${formatPercents(storedTimeWeight)} game time`;
}
} else {
speedMod = 1;
storedTimeText = ` | storing game time`;
}
}
if (speedMod < 10000 && speedMod !== 1) {
return `(γ = ${speedMod.toFixed(3)}${storedTimeText})`;
}
return `(γ = ${shorten(speedMod, 2)}${storedTimeText})`;
this.gameSpeedMult = getGameSpeedupForDisplay();
}
},
template:

View File

@ -15,7 +15,7 @@ Vue.component("game-header", {
// won't trigger display update if we, say, switch from one challenge to another
function celestialReality(celestial, name) {
return {
name: () => name,
name: () => `${name} Reality`,
isActive: token => token,
activityToken: () => celestial.isRunning
};
@ -32,6 +32,11 @@ Vue.component("game-header", {
isActive: token => token,
activityToken: () => player.dilation.active
},
{
name: () => "Time Compression",
isActive: token => token,
activityToken: () => TimeCompression.isActive
},
{
name: token => `${NormalChallenge(token).config.reward} Challenge`,
isActive: token => token > 0,

View File

@ -23,7 +23,7 @@ Vue.component("sacrificed-glyphs", {
return this.typeConfig.symbol;
},
formatAmount() {
return this.shorten(this.amount, 2);
return this.shorten(this.amount, 2, 2);
},
description() {
return this.sacConfig.description(this.effectValue);

View File

@ -4,7 +4,7 @@ Vue.component("statistics-tab", {
data() {
return {
totalAntimatter: new Decimal(0),
resets: 0,
boosts: 0,
galaxies: 0,
realTimePlayed: TimeSpan.zero,
infinity: {
@ -18,7 +18,7 @@ Vue.component("statistics-tab", {
},
eternity: {
isUnlocked: false,
count: 0,
count: new Decimal(0),
hasBest: false,
best: TimeSpan.zero,
this: TimeSpan.zero,
@ -38,7 +38,7 @@ Vue.component("statistics-tab", {
methods: {
update() {
this.totalAntimatter.copyFrom(player.totalAntimatter);
this.resets = player.resets;
this.boosts = DimBoost.purchasedBoosts;
this.galaxies = Math.round(player.galaxies);
this.realTimePlayed.setFrom(Date.now() - player.gameCreatedTime);
const progress = PlayerProgress.current;
@ -56,7 +56,7 @@ Vue.component("statistics-tab", {
const eternity = this.eternity;
eternity.isUnlocked = isEternityUnlocked;
if (isEternityUnlocked) {
eternity.count = player.eternities;
eternity.count.copyFrom(player.eternities);
eternity.hasBest = player.bestEternity < 999999999999;
eternity.best.setFrom(player.bestEternity);
eternity.this.setFrom(player.thisEternity);
@ -94,7 +94,7 @@ Vue.component("statistics-tab", {
<br>
<h3>General</h3>
<div>You have made a total of {{ shortenMoney(totalAntimatter) }} antimatter.</div>
<div>You have done {{ resets }} Dimension {{"Boost/Shift" | pluralize(resets, "Boosts/Shifts")}}.</div>
<div>You have purchased {{ boosts }} Dimension {{"Boost/Shift" | pluralize(boosts, "Boosts/Shifts")}}.</div>
<div>You have {{ galaxies }} Antimatter {{"Galaxy" | pluralize(galaxies, "Galaxies")}}.</div>
<div>You have played for {{ realTimePlayed }}.</div>
<div v-if="reality.isUnlocked">
@ -126,9 +126,9 @@ Vue.component("statistics-tab", {
</div>
<div v-if="eternity.isUnlocked">
<h3>Eternity</h3>
<div v-if="eternity.count > 0">
<div v-if="eternity.count.gt(0)">
You have Eternitied
{{ formatResetAmount(eternity.count) }}<span v-if="reality.isUnlocked"> this Reality</span>.
{{ formatDecimalResetAmount(eternity.count) }}<span v-if="reality.isUnlocked"> this Reality</span>.
</div>
<div v-else>You haven't Eternitied<span v-if="reality.isUnlocked"> this Reality</span>.</div>
<div v-if="eternity.hasBest">Your fastest Eternity was {{ eternity.best }}.</div>

View File

@ -10,7 +10,8 @@ class PlayerProgress {
}
get isEternityUnlocked() {
return this._player.eternities > 0 || this.isRealityUnlocked;
// This is some old-save-new-save number-to-Decimal conversion schenanigans (see below)
return new Decimal(this._player.eternities).gt(0) || this.isRealityUnlocked;
}
get isInfinityUnlocked() {

View File

@ -69,7 +69,7 @@ Autobuyer.dimboost = new class DimBoostAutobuyerState extends IntervaledAutobuye
maxBuyDimBoosts();
return;
}
if (player.resets >= this.maxDimBoosts && player.galaxies < this.galaxies) {
if (DimBoost.purchasedBoosts >= this.maxDimBoosts && player.galaxies < this.galaxies) {
return;
}
if (this.isBulkBuyUnlocked && !DimBoost.isShift) {

View File

@ -76,8 +76,11 @@ function bigCrunchReset() {
player.replicanti.galaxies = Math.floor(currentReplicantiGalaxies / 2);
}
if (player.eternities > 10 && !EternityChallenge(8).isRunning && !EternityChallenge(2).isRunning && !EternityChallenge(10).isRunning) {
for (let i = 1; i < player.eternities - 9 && i < 9; i++) {
if (player.eternities.gt(10) &&
!EternityChallenge(8).isRunning &&
!EternityChallenge(2).isRunning &&
!EternityChallenge(10).isRunning) {
for (let i = 1; i <= player.eternities.sub(10).clampMax(8).toNumber(); i++) {
if (player.infDimBuyers[i - 1]) {
buyMaxInfDims(i);
buyManyInfinityDimension(i)
@ -96,7 +99,7 @@ function bigCrunchReset() {
}
function secondSoftReset() {
player.resets = 0;
player.dimensionBoosts = 0;
player.galaxies = 0;
player.tickDecrease = 0.9;
resetAntimatter();

View File

@ -330,7 +330,8 @@ const BlackHoles = {
* starting from black hole 1 and black hole 0 being normal game.
*/
calculateSpeedups() {
const effectsToConsider = [GameSpeedEffect.EC12, GameSpeedEffect.TIMEGLYPH, GameSpeedEffect.BLACKHOLE];
const effectsToConsider = [GameSpeedEffect.FIXEDSPEED, GameSpeedEffect.TIMEGLYPH, GameSpeedEffect.BLACKHOLE,
GameSpeedEffect.MOMENTUM];
const speedupWithoutBlackHole = getGameSpeedupFactor(effectsToConsider, 1);
const speedups = [1];
for (const blackHole of this.list) {

View File

@ -59,7 +59,7 @@ const V_UNLOCKS = {
requirement: () => {
const db = GameDatabase.celestials.v.mainUnlock;
if (player.realities < db.realities) return false;
if (player.eternities < db.eternities) return false;
if (player.eternities.lt(db.eternities)) return false;
if (player.infinitied.plus(player.infinitiedBank).lt(db.infinities)) return false;
if (player.dilation.dilatedTime.lt(db.dilatedTime)) return false;
if (player.replicanti.amount.lt(db.replicanti)) return false;

View File

@ -98,11 +98,12 @@ const Enslaved = {
},
// "autoRelease" should only be true when called with the Ra upgrade
useStoredTime(autoRelease) {
if (TimeCompression.isActive) return;
if (this.maxQuoteIdx === 9) player.celestials.enslaved.maxQuotes += 4;
let release = player.celestials.enslaved.stored;
if (Enslaved.isRunning) release = Enslaved.storedTimeInsideEnslaved(release);
if (autoRelease) release *= 0.01;
gameLoop(0, { gameDiff: release });
nextTickDiff = release;
// Effective gamespeed from stored time assumes a "default" 50 ms update rate for consistency
const effectiveGamespeed = release / 50;
player.celestials.ra.peakGamespeed = Math.max(player.celestials.ra.peakGamespeed, effectiveGamespeed);

View File

@ -33,17 +33,6 @@ class AlchemyResourceState extends GameMechanicState {
return this.config.effect(this.amount);
}
get reactionText() {
if (this.reaction === null) return "Base Resource";
const isReality = this.reaction._product.id === ALCHEMY_RESOURCE.REALITY;
const reagentStrings = [];
for (const reagent of this.reaction._reagents) {
reagentStrings.push(`${isReality ? "" : reagent.cost}${reagent.resource.symbol}`);
}
const produced = `${Math.floor(100 * this.reaction.baseProduction * this.reaction.reactionEfficiency) / 100}`;
return `${reagentStrings.join(" + ")}${isReality ? "" : produced}${this.reaction._product.symbol}`;
}
get reaction() {
return AlchemyReactions.all[this.id];
}
@ -98,6 +87,10 @@ class AlchemyReaction {
return this.isReality ? 1 : AlchemyResource.synergism.effectValue;
}
get reactionProduction() {
return this.baseProduction * this.reactionEfficiency;
}
// Cap products at the minimum amount of all reagents before the reaction occurs, eg. 200Ξ and 350Ψ will not bring
// ω above 200. In fact, since some Ξ will be used during the reaction, the actual cap will be a bit lower.
combineReagents() {
@ -123,7 +116,7 @@ class AlchemyReaction {
for (const reagent of this._reagents) {
reagent.resource.amount -= cappedYield * reagent.cost;
}
this._product.amount += this.baseProduction * cappedYield * this.reactionEfficiency;
this._product.amount += cappedYield * this.reactionProduction;
}
}

View File

@ -0,0 +1,101 @@
"use strict";
const TimeCompression = {
get timeShardRequirement() {
return new Decimal("1e3500000");
},
toggle() {
if (player.timeShards.lt(this.timeShardRequirement) && !this.isActive) {
return;
}
if (this.isActive) {
this.rewardEntanglement();
}
eternity(false, false, { switchingDilation: true });
player.dilation.active = false;
this.isActive = !this.isActive;
},
get entanglement() {
return player.celestials.ra.compression.entanglement;
},
set entanglement(value) {
player.celestials.ra.compression.entanglement = value;
},
get totalEntanglement() {
return this.entanglement + this.spentEntanglement;
},
rewardEntanglement() {
this.entanglement = Math.max(this.entanglement, this.entanglementThisRun - this.spentEntanglement);
},
get spentEntanglement() {
return CompressionUpgrades.all
.filter(u => u.isBought)
.map(u => u.cost)
.sum();
},
get entanglementThisRun() {
if (!this.isActive) {
return 0;
}
const entanglementMult = Effects.max(1, CompressionUpgrade.moreEntanglement);
return 308 * Math.clamp((Math.pow(player.antimatter.log10() / 2e5, 0.4) - 1) / 10 * entanglementMult, 0, 1);
},
get compressionDepth() {
return 2;
},
get isActive() {
return player.celestials.ra.compression.active;
},
set isActive(value) {
player.celestials.ra.compression.active = value;
},
};
class CompressionUpgradeState extends BitPurchasableMechanicState {
get currency() {
return Currency.entanglement;
}
get bitIndex() {
return this.id;
}
get bits() {
return player.celestials.ra.compression.upgradeBits;
}
set bits(value) {
player.celestials.ra.compression.upgradeBits = value;
}
get canBeApplied() {
// eslint-disable-next-line no-bitwise
const requirementFulfilled = new Decimal(this.config.resource()).gte(this.config.threshold()) ^
this.config.invertedCondition;
return this.isBought && requirementFulfilled;
}
}
const CompressionUpgrade = (function() {
const db = GameDatabase.celestials.compression;
return {
freeBoost: new CompressionUpgradeState(db.freeBoost),
improvedDTMult: new CompressionUpgradeState(db.improvedDTMult),
replicantiSpeedFromDB: new CompressionUpgradeState(db.replicantiSpeedFromDB),
strongerDilationGalaxies: new CompressionUpgradeState(db.strongerDilationGalaxies),
freeGalaxySoftcap: new CompressionUpgradeState(db.freeGalaxySoftcap),
freeGalaxyScaling: new CompressionUpgradeState(db.freeGalaxyScaling),
infDimSoftcap: new CompressionUpgradeState(db.infDimSoftcap),
moreEntanglement: new CompressionUpgradeState(db.moreEntanglement),
matterBoost: new CompressionUpgradeState(db.matterBoost)
};
})();
const CompressionUpgrades = {
all: Object.values(CompressionUpgrade),
respec() {
TimeCompression.entanglement += TimeCompression.spentEntanglement;
player.celestials.ra.compression.upgradeBits = 0;
player.celestials.ra.compression.respec = false;
}
};

View File

@ -49,7 +49,7 @@ class RaPetState {
if (this.level < 25) {
return Math.floor(4000 * Math.pow(1.18, this.level + 30));
}
return Math.floor(4000 * Math.pow(1.18, 3 * this.level - 20));
return Math.floor(4000 * Math.pow(1.18, 7 * this.level - 120));
}
addGainedExp() {
@ -237,33 +237,6 @@ const Ra = {
if (!Ra.has(RA_UNLOCKS.PEAK_GAMESPEED)) return 1;
return Math.max(Math.pow(Math.log10(player.celestials.ra.peakGamespeed) - 90, 3), 1);
},
// In some sense we're cheating here for the sake of balance since gamespeed has historically been hard to keep
// under wraps. So the way we buff gamespeed in a relatively controlled way here is by manually calculating a
// sensible "maximum possible gamespeed" on top of the CURRENT black hole power based on a game state which is
// slightly farther than the player will be when first unlocking this upgrade (hence the "magic numbers"). The
// state in question is one with a glyph set with two time glyphs and effarig gamespeed pow + achievement pow
// (due to V), all level 10k with celestial rarity, and Lv20 Enslaved + all achievements. The boost is simply 2x
// for any stored time at all if it's below this threshold, but will start scaling up at gamespeeds higher than this.
// It should be a lot harder for this to cause an unchecked runaway since black hole scaling won't feed into this
// upgrade's scaling. There is also an eventual softcap of 1e10 just in case. If I did the math correctly, the
// speed boost should scale with (real time)^(effarig gamespeed pow) before the softcap and worse than that after.
gamespeedStoredTimeMult() {
let assumedBlackHoleBoost = 1;
for (const blackHole of BlackHoles.list) {
assumedBlackHoleBoost *= blackHole.power;
assumedBlackHoleBoost *= Math.pow(GameDatabase.achievements.normal.length, 2.69);
}
const assumedTimeGlyphBoost = Math.pow(2.79, 2);
const baselineGamespeed = Math.pow(assumedBlackHoleBoost * assumedTimeGlyphBoost, 1.22);
const baselineStoredTime = Math.pow(baselineGamespeed, 1.2);
const scaledStoredTime = player.celestials.enslaved.stored / baselineStoredTime;
if (player.celestials.enslaved.stored === 0) return 1;
const softcap = 1e10;
if (scaledStoredTime > softcap) {
return softcap * Math.pow(10, Math.pow(Math.log10(scaledStoredTime / softcap), 0.4));
}
return Math.max(2, scaledStoredTime);
},
// This gets widely used in lots of places since the relevant upgrade is "all forms of continuous non-dimension
// production", which in this case is infinities, eternities, replicanti, dilated time, and time theorem generation.
// It also includes the 1% IP time study, Teresa's 1% EP upgrade, and the charged RM generation upgrade. Note that
@ -422,10 +395,10 @@ const RA_UNLOCKS = {
pet: Ra.pets.enslaved,
level: 15
},
GAMESPEED_BOOST: {
TIME_COMPRESSION: {
id: 17,
description: "Get Enslaved to level 25",
reward: "Game speed increases based on current stored time",
reward: "Unlock Time Compression",
pet: Ra.pets.enslaved,
level: 25
},
@ -487,4 +460,4 @@ const RA_LAITELA_UNLOCK = {
id: 24,
description: "Get all celestials to level 20",
reward: "Unlock Lai'tela, the Celestial of Dimensions",
};
};

View File

@ -17,7 +17,7 @@ function tryUnlockInfinityChallenges() {
while (player.postChallUnlocked < 8 &&
player.antimatter.gte(InfinityChallenge(player.postChallUnlocked + 1).config.unlockAM)) {
++player.postChallUnlocked;
if (player.eternities > 6) {
if (player.eternities.gte(7)) {
InfinityChallenge(player.postChallUnlocked).complete();
}
}
@ -27,7 +27,7 @@ function updateNormalAndInfinityChallenges(diff) {
if (NormalChallenge(11).isRunning || InfinityChallenge(6).isRunning) {
if (NormalDimension(2).amount.neq(0)) {
player.matter = player.matter
.times(Decimal.pow((1.03 + player.resets / 200 + player.galaxies / 100), diff / 100));
.times(Decimal.pow((1.03 + DimBoost.totalBoosts / 200 + player.galaxies / 100), diff / 100));
}
if (player.matter.gt(player.antimatter) && NormalChallenge(11).isRunning) {
Modal.message.show(`Your ${shorten(player.antimatter, 2, 2)} antimatter was annhiliated by ` +

View File

@ -105,3 +105,8 @@ Currency.perkPoints = new class extends NumberCurrency {
get value() { return player.reality.pp; }
set value(value) { player.reality.pp = value; }
}();
Currency.entanglement = new class extends NumberCurrency {
get value() { return player.celestials.ra.compression.entanglement; }
set value(value) { player.celestials.ra.compression.entanglement = value; }
}();

View File

@ -245,8 +245,8 @@ dev.showProductionBreakdown = function() {
const totalCount = AGCount + RGCount + FGCount;
IC4pow = InfinityChallenge(4).isCompleted ? 1.05 : 1;
const IDComponent = player.infinityPower.pow(7 + getAdjustedGlyphEffect("infinityrate")).pow(8).pow(IC4pow);
const DBComponent = DimBoost.power.pow(player.resets).pow(8).pow(IC4pow);
const IDComponent = player.infinityPower.pow(getInfinityConversionRate()).pow(8).pow(IC4pow);
const DBComponent = DimBoost.power.pow(DimBoost.totalBoosts).pow(8).pow(IC4pow);
let buyTenComponent = new Decimal(1);
for (let i = 1; i <= 8; i++) {
buyTenComponent = buyTenComponent.times(new Decimal(getBuyTenMultiplier()).pow(NormalDimension(i).bought / 10));
@ -280,7 +280,7 @@ dev.showProductionBreakdown = function() {
if (player.timestudy.studies.includes(72)) TSmultToIDComponent = TSmultToIDComponent
.times(Sacrifice.totalBoost.pow(0.04).max(1).min("1e30000"));
if (player.timestudy.studies.includes(82)) TSmultToIDComponent = TSmultToIDComponent
.times(Decimal.pow(1.0000109, Math.pow(player.resets, 2)));
.times(Decimal.pow(1.0000109, Math.pow(DimBoost.totalBoosts, 2)));
const EU1Component = player.eternityPoints.plus(1).pow(8);
const IDPowComponent = powerpow === 0 ? 0 : (powerpow - 1) / infinitypow;
@ -305,7 +305,7 @@ dev.showProductionBreakdown = function() {
if (player.timestudy.studies.includes(73)) TSmultToTDComponent = TSmultToTDComponent
.times(Sacrifice.totalBoost.pow(0.005).min(new Decimal("1e1300")));
if (player.timestudy.studies.includes(221)) TSmultToTDComponent = TSmultToTDComponent
.times(Decimal.pow(1.0025, player.resets)).pow(8);
.times(Decimal.pow(1.0025, DimBoost.totalBoosts)).pow(8);
if (player.timestudy.studies.includes(227)) TSmultToTDComponent = TSmultToTDComponent
.times(Math.max(Math.pow(Sacrifice.totalBoost.log10(), 10), 1));
const TDPowComponent = timepow === 0 ? 0 : (timepow - 1) / timepow;
@ -403,3 +403,43 @@ dev.kongTest = function() {
page.style.marginTop = "";
}
};
// This should help for balancing different glyph types, strong rounding of values is intentional
dev.printResourceTotals = function() {
console.log(`Antimatter: e${player.antimatter.exponent.toPrecision(3)}`);
console.log(`RM: e${Math.round(gainedRealityMachines().log10())}`);
console.log(`Glyph level: ${100 * Math.floor(gainedGlyphLevel().actualLevel / 100 + 0.5)}`);
console.log(`Tickspeed: e${-Tickspeed.current.exponent.toPrecision(3)}`);
console.log(`Gamespeed: ${Math.pow(getGameSpeedupFactor(), 1.2).toPrecision(1)}`);
const aGalaxy = 100 * Math.floor(player.galaxies / 100 + 0.5);
const rGalaxy = 100 * Math.floor(Replicanti.galaxies.total / 100 + 0.5);
const dGalaxy = 100 * Math.floor(player.dilation.freeGalaxies / 100 + 0.5);
console.log(`Galaxies: ${aGalaxy}+${rGalaxy}+${dGalaxy} (${aGalaxy + rGalaxy + dGalaxy})`);
console.log(`Tick reduction: e${-Math.round(getTickSpeedMultiplier().log10())}`);
let NDmults = new Decimal(1);
for (let i = 1; i <= 8; i++) {
NDmults = NDmults.times(getDimensionFinalMultiplier(i));
}
console.log(`ND mults: e${NDmults.log10().toPrecision(3)}`);
let IDmults = new Decimal(1);
for (let i = 1; i <= 8; i++) {
IDmults = IDmults.times(InfinityDimension(i).multiplier);
}
console.log(`ID mults: e${IDmults.log10().toPrecision(3)}`);
let TDmults = new Decimal(1);
for (let i = 1; i <= 8; i++) {
TDmults = TDmults.times(TimeDimension(i).multiplier);
}
console.log(`TD mults: e${TDmults.log10().toPrecision(3)}`);
console.log(`Free tickspeed: ${formatWithCommas(1000 * Math.floor(player.totalTickGained / 1000 + 0.5))}`);
console.log(`Infinities: e${Math.round(player.infinitied.log10())}`);
console.log(`Eternities: e${Math.round(player.eternities.log10())}`);
console.log(`Replicanti: e${formatWithCommas(1e5 * Math.floor(player.replicanti.amount.log10() / 1e5 + 0.5))}`);
console.log(`TT: e${Math.round(player.timestudy.theorem.log10())}`);
console.log(`DT: e${Math.round(player.dilation.dilatedTime.log10())}`);
console.log(`TP: e${Math.round(player.dilation.tachyonParticles.log10())}`);
}

View File

@ -1,18 +1,19 @@
"use strict";
function startDilatedEternity(auto) {
if (!TimeStudy.dilation.isBought) return false
if (!TimeStudy.dilation.isBought) return false;
if (player.dilation.active) {
eternity(false, auto, { switchingDilation: true });
return false
return false;
}
if (player.options.confirmations.dilation && !confirm("Dilating time will start a new eternity, and all of your Dimension/Infinity Dimension/Time Dimension multiplier's exponents and tickspeed multiplier's exponent will be reduced to ^ 0.75. If you can eternity while dilated, you'll be rewarded with tachyon particles based on your antimatter and tachyon particles.")) {
return false
return false;
}
Achievement(136).unlock();
eternity(false, auto, { switchingDilation: true });
player.dilation.active = true;
return true
TimeCompression.isActive = false;
return true;
}
@ -77,11 +78,17 @@ function buyDilationUpgrade(id, bulk) {
return true
}
function getFreeGalaxyMult() {
// This two are separate to avoid an infinite loop as the compression unlock condition checks the free galaxy mult
function getFreeGalaxyMultBeforeCompression() {
const thresholdMult = 3.65 * DilationUpgrade.galaxyThreshold.effectValue + 0.35;
const glyphEffect = getAdjustedGlyphEffect("dilationgalaxyThreshold");
const glyphReduction = glyphEffect === 0 ? 1 : glyphEffect;
return thresholdMult * glyphReduction + 1;
return 1 + thresholdMult * glyphReduction;
}
function getFreeGalaxyMult() {
const compressionReduction = Effects.max(0, CompressionUpgrade.freeGalaxyScaling);
return getFreeGalaxyMultBeforeCompression() - compressionReduction;
}
function getDilationGainPerSecond() {
@ -144,12 +151,28 @@ function getTachyonReq() {
);
}
function dilatedValueOf(value) {
function dilatedValueOf(value, depth) {
if (depth !== undefined) {
return recursiveDilation(value, depth);
}
if (player.dilation.active) {
return recursiveDilation(value, 1);
}
if (TimeCompression.isActive) {
return recursiveDilation(value, TimeCompression.compressionDepth);
}
throw crash("Invald dilation depth");
}
function recursiveDilation(value, depth) {
if (depth === 0) {
return value;
}
const log10 = value.log10();
const basePenalty = 0.75 * Effects.product(DilationUpgrade.dilationPenalty);
const alchemyReduction = (player.replicanti.amount.log10() / 1e6) * AlchemyResource.alternation.effectValue;
const dilationPenalty = Math.min(1, basePenalty + (1 - basePenalty) * alchemyReduction);
return Decimal.pow10(Math.sign(log10) * Math.pow(Math.abs(log10), dilationPenalty));
return recursiveDilation(Decimal.pow10(Math.sign(log10) * Math.pow(Math.abs(log10), dilationPenalty)), depth - 1);
}
class DilationUpgradeState extends SetPurchasableMechanicState {

View File

@ -42,7 +42,7 @@ class DimBoost {
static get isShift() {
// Player starts with 4 unlocked dimensions,
// hence there are just 4 (or 2, if in Auto DimBoosts challenge) shifts
return player.resets + 4 < this.maxShiftTier;
return DimBoost.purchasedBoosts + 4 < this.maxShiftTier;
}
static get requirement() {
@ -50,14 +50,13 @@ class DimBoost {
}
static bulkRequirement(bulk) {
let targetResets = player.resets + bulk;
let tier = Math.min(targetResets + 3, this.maxShiftTier);
const targetResets = DimBoost.purchasedBoosts + bulk;
const tier = Math.min(targetResets + 3, this.maxShiftTier);
let amount = 20;
if (tier === 6 && NormalChallenge(10).isRunning) {
amount += Math.ceil((targetResets - 3) * 20);
}
else if (tier === 8) {
} else if (tier === 8) {
const mult = 15 - Effects.sum(
TimeStudy(211),
TimeStudy(222)
@ -77,20 +76,31 @@ class DimBoost {
return new DimBoostRequirement(tier, amount);
}
static get purchasedBoosts() {
return player.dimensionBoosts;
}
static get freeBoosts() {
return Math.floor(Effects.max(0, CompressionUpgrade.freeBoost));
}
static get totalBoosts() {
return this.purchasedBoosts + this.freeBoosts;
}
}
function applyDimensionBoost() {
const power = DimBoost.power;
for (let tier = 1; tier <= 8; tier++) {
NormalDimension(tier).power = power.pow(player.resets + 1 - tier).max(1);
NormalDimension(tier).power = power.pow(DimBoost.totalBoosts + 1 - tier).max(1);
}
}
function softReset(bulk) {
//if (bulk < 1) bulk = 1 (fixing issue 184)
if (!player.break && player.antimatter.gt(Decimal.MAX_NUMBER)) return;
EventHub.dispatch(GameEvent.DIMBOOST_BEFORE, bulk);
player.resets += bulk;
player.dimensionBoosts += bulk;
/**
* All reset stuff are in these functions now. (Hope this works)
@ -113,13 +123,13 @@ function skipResetsIfPossible() {
if (NormalChallenge.isRunning || InfinityChallenge.isRunning) {
return;
}
if (InfinityUpgrade.skipResetGalaxy.isBought && player.resets < 4) {
player.resets = 4;
if (InfinityUpgrade.skipResetGalaxy.isBought && player.dimensionBoosts < 4) {
player.dimensionBoosts = 4;
if (player.galaxies === 0) player.galaxies = 1;
}
else if (InfinityUpgrade.skipReset3.isBought && player.resets < 3) player.resets = 3;
else if (InfinityUpgrade.skipReset2.isBought && player.resets < 2) player.resets = 2;
else if (InfinityUpgrade.skipReset1.isBought && player.resets < 1) player.resets = 1;
else if (InfinityUpgrade.skipReset3.isBought && player.dimensionBoosts < 3) player.dimensionBoosts = 3;
else if (InfinityUpgrade.skipReset2.isBought && player.dimensionBoosts < 2) player.dimensionBoosts = 2;
else if (InfinityUpgrade.skipReset1.isBought && player.dimensionBoosts < 1) player.dimensionBoosts = 1;
}
function softResetBtnClick() {
@ -127,10 +137,10 @@ function softResetBtnClick() {
if (Ra.isRunning) return;
if (BreakInfinityUpgrade.bulkDimBoost.isBought) maxBuyDimBoosts(true);
else softReset(1)
for (let tier = 1; tier<9; tier++) {
const mult = DimBoost.power.pow(player.resets + 1 - tier);
if (mult.gt(1)) floatText(tier, "x" + shortenDimensions(mult));
for (let tier = 1; tier < 9; tier++) {
const mult = DimBoost.power.pow(DimBoost.totalBoosts + 1 - tier);
if (mult.gt(1)) floatText(tier, formatX(mult));
}
}

View File

@ -137,7 +137,7 @@ class InfinityDimensionState extends DimensionState {
}
get isAutobuyerUnlocked() {
return player.eternities >= 10 + this.tier;
return player.eternities.gte(10 + this.tier);
}
get isAvailableForPuchase() {
@ -161,7 +161,7 @@ class InfinityDimensionState extends DimensionState {
toGain = InfinityDimension(tier + 1).productionPerSecond;
}
const current = Decimal.max(this.amount, 1);
return toGain.times(10).dividedBy(current).times(getGameSpeedupFactor());
return toGain.times(10).dividedBy(current).times(getGameSpeedupForDisplay());
}
get productionPerSecond() {
@ -199,7 +199,7 @@ class InfinityDimensionState extends DimensionState {
mult = mult.clampMin(0);
if (player.dilation.active) {
if (player.dilation.active || TimeCompression.isActive) {
mult = dilatedValueOf(mult);
}
@ -240,10 +240,11 @@ class InfinityDimensionState extends DimensionState {
if (Enslaved.isRunning) {
return 1;
}
if (Enslaved.isCompleted) {
return this._purchaseCap + Math.floor(player.totalTickGained / 1000) * 1000;
}
return this._purchaseCap;
const enslavedBoost = Enslaved.isCompleted
? Math.floor(player.totalTickGained / 1000) * 1000
: 0;
const compressionBoost = Effects.max(0, CompressionUpgrade.infDimSoftcap);
return this._purchaseCap + enslavedBoost + compressionBoost;
}
get baseAmountCap() {
@ -311,7 +312,7 @@ const InfinityDimensions = {
};
function tryUnlockInfinityDimensions() {
if (player.eternities < 25 || InfinityDimension(8).isUnlocked) return;
if (player.eternities.lt(25) || InfinityDimension(8).isUnlocked) return;
for (let tier = 1; tier <= 8; ++tier) {
if (InfinityDimension(tier).isUnlocked) continue;
// If we cannot unlock this one, we can't unlock the rest, either
@ -324,3 +325,8 @@ function tryUnlockInfinityDimensions() {
}
}
}
function getInfinityConversionRate() {
const laitelaBoost = Laitela.has(LAITELA_UNLOCKS.ID) ? Laitela.idConversionEffect : 0;
return 7 + getAdjustedGlyphEffect("infinityrate") + laitelaBoost;
}

View File

@ -10,9 +10,7 @@ function normalDimensionCommonMultiplier() {
multiplier = multiplier.times(kongAllDimMult);
if (!EternityChallenge(9).isRunning) {
let glyphConversionRate = 7 + getAdjustedGlyphEffect("infinityrate");
if (Laitela.has(LAITELA_UNLOCKS.ID)) glyphConversionRate += Laitela.idConversionEffect
multiplier = multiplier.times(player.infinityPower.pow(glyphConversionRate).max(1));
multiplier = multiplier.times(player.infinityPower.pow(getInfinityConversionRate()).max(1));
}
multiplier = multiplier.timesEffectsOf(
BreakInfinityUpgrade.totalAMMult,
@ -55,26 +53,56 @@ function getDimensionFinalMultiplier(tier) {
function getDimensionFinalMultiplierUncached(tier) {
if (tier < 1 || tier > 8) throw crash(`Invalid tier ${tier}`);
if (NormalChallenge(10).isRunning && tier > 6) return new Decimal(1);
//if (player.currentEternityChall == "eterc3" && tier > 4) return new Decimal(0)
const dimension = NormalDimension(tier);
let multiplier = new Decimal(dimension.power);
let multiplier = new Decimal(NormalDimension(tier).power);
if (EternityChallenge(11).isRunning) return player.infinityPower.pow(7 + getAdjustedGlyphEffect("infinityrate")).max(1).times(DimBoost.power.pow(player.resets - tier + 1).max(1));
if (EternityChallenge(11).isRunning) {
return player.infinityPower.pow(getInfinityConversionRate())
.max(1)
.times(DimBoost.power.pow(DimBoost.totalBoosts - tier + 1).max(1));
}
if (NormalChallenge(12).isRunning) {
if (tier === 4) multiplier = multiplier.pow(1.4);
if (tier === 2) multiplier = multiplier.pow(1.7)
}
multiplier = multiplier.times(GameCache.normalDimensionCommonMultiplier.value);
multiplier = applyNDMultipliers(multiplier, tier);
multiplier = applyNDPowers(multiplier, tier);
const glyphPowMultiplier = getAdjustedGlyphEffect("powerpow");
const glyphEffarigPowMultiplier = getAdjustedGlyphEffect("effarigdimensions");
const glyphDilationPowMultiplier = getAdjustedGlyphEffect("dilationpow");
const laitelaPowMultiplier = Laitela.has(LAITELA_UNLOCKS.DIM_POW) ? Laitela.dimensionMultPowerEffect : 1;
if (player.dilation.active || TimeCompression.isActive) {
multiplier = dilatedValueOf(multiplier.pow(glyphDilationPowMultiplier, 1));
} else if (Enslaved.isRunning) {
multiplier = dilatedValueOf(multiplier);
}
multiplier = multiplier.timesEffectOf(DilationUpgrade.ndMultDT);
// The "unaffected by dilation" ND mult and ND dilation power effect only apply to the first layer of dilation
if (TimeCompression.isActive) {
multiplier = dilatedValueOf(multiplier, TimeCompression.compressionDepth - 1);
}
if (Effarig.isRunning) {
multiplier = Effarig.multiplier(multiplier);
} else if (V.isRunning) {
multiplier = multiplier.pow(0.5);
} else if (Laitela.isRunning) {
multiplier = multiplier.pow(Laitela.dimMultNerf);
}
// This power effect goes intentionally after all the nerf effects and shouldn't be moved before them
if (Ra.has(RA_UNLOCKS.GLYPH_ALCHEMY) && multiplier.gte(AlchemyResource.inflation.effectValue)) {
multiplier = multiplier.pow(1.05);
}
return multiplier;
}
function applyNDMultipliers(mult, tier) {
let multiplier = mult.times(GameCache.normalDimensionCommonMultiplier.value);
let infinitiedMult = new Decimal(1).timesEffectsOf(
dimension.infinityUpgrade,
NormalDimension(tier).infinityUpgrade,
BreakInfinityUpgrade.infinitiedMult
);
infinitiedMult = infinitiedMult.pow(Effects.product(TimeStudy(31)));
@ -95,9 +123,9 @@ function getDimensionFinalMultiplierUncached(tier) {
multiplier = multiplier.timesEffectsOf(
tier === 8 ? Achievement(23) : null,
tier !== 8 ? Achievement(34) : null,
tier < 8 ? Achievement(34) : null,
tier <= 4 ? Achievement(43) : null,
tier !== 8 ? TimeStudy(71) : null,
tier < 8 ? TimeStudy(71) : null,
tier === 8 ? TimeStudy(214) : null,
tier > 1 && tier < 8 ? InfinityChallenge(8).reward : null,
AlchemyResource.dimensionality
@ -111,6 +139,15 @@ function getDimensionFinalMultiplierUncached(tier) {
multiplier = multiplier.clampMin(1);
return multiplier;
}
function applyNDPowers(mult, tier) {
let multiplier = mult;
const glyphPowMultiplier = getAdjustedGlyphEffect("powerpow");
const glyphEffarigPowMultiplier = getAdjustedGlyphEffect("effarigdimensions");
const laitelaPowMultiplier = Laitela.has(LAITELA_UNLOCKS.DIM_POW) ? Laitela.dimensionMultPowerEffect : 1;
if (InfinityChallenge(4).isRunning && player.postC4Tier !== tier) {
multiplier = multiplier.pow(InfinityChallenge(4).effectValue);
}
@ -122,37 +159,25 @@ function getDimensionFinalMultiplierUncached(tier) {
multiplier = multiplier
.powEffectsOf(
dimension.infinityUpgrade.chargedEffect,
NormalDimension(tier).infinityUpgrade.chargedEffect,
InfinityUpgrade.totalTimeMult.chargedEffect,
InfinityUpgrade.thisInfinityTimeMult.chargedEffect,
AlchemyResource.power
);
if (player.dilation.active) {
multiplier = dilatedValueOf(multiplier.pow(glyphDilationPowMultiplier));
} else if (Enslaved.isRunning) {
multiplier = dilatedValueOf(multiplier);
}
multiplier = multiplier.timesEffectOf(DilationUpgrade.ndMultDT);
if (Effarig.isRunning) {
multiplier = Effarig.multiplier(multiplier);
} else if (V.isRunning) {
multiplier = multiplier.pow(0.5);
} else if (Laitela.isRunning) {
multiplier = multiplier.pow(Laitela.dimMultNerf);
}
// This power effect goes intentionally after all the nerf effects and shouldn't be moved before them
if (Ra.has(RA_UNLOCKS.GLYPH_ALCHEMY) && multiplier.gte(AlchemyResource.inflation.effectValue)) {
multiplier = multiplier.pow(1.05);
}
return multiplier;
}
function multiplySameCosts(cost) {
const tierCosts = [null, new Decimal(1e3), new Decimal(1e4), new Decimal(1e5), new Decimal(1e6), new Decimal(1e8), new Decimal(1e10), new Decimal(1e12), new Decimal(1e15)];
const tierCosts = [null,
new Decimal(1e3),
new Decimal(1e4),
new Decimal(1e5),
new Decimal(1e6),
new Decimal(1e8),
new Decimal(1e10),
new Decimal(1e12),
new Decimal(1e15)];
for (let i = 1; i <= 8; ++i) {
const dimension = NormalDimension(i);
@ -619,7 +644,7 @@ class NormalDimensionState extends DimensionState {
else {
toGain = getDimensionProductionPerSecond(tier + 1);
}
return toGain.times(10).dividedBy(this.amount.max(1)).times(getGameSpeedupFactor());
return toGain.times(10).dividedBy(this.amount.max(1)).times(getGameSpeedupForDisplay());
}
/**
@ -650,8 +675,8 @@ class NormalDimensionState extends DimensionState {
get isAvailable() {
if (!player.break && player.antimatter.gt(Decimal.MAX_NUMBER)) return false;
if (this.tier > player.resets + 4) return false;
if (this.tier > 1 && NormalDimension(this.tier - 1).amount.eq(0) && player.eternities < 30) return false;
if (this.tier > DimBoost.totalBoosts + 4) return false;
if (this.tier > 1 && NormalDimension(this.tier - 1).amount.eq(0) && player.eternities.lt(30)) return false;
return this.tier < 7 || !NormalChallenge(10).isRunning;
}

View File

@ -132,7 +132,7 @@ function timeDimensionCommonMultiplier() {
AlchemyResource.dimensionality
);
if (EternityChallenge(9).isRunning) {
mult = mult.times((Decimal.pow(Math.max(player.infinityPower.pow((7 + getAdjustedGlyphEffect("infinityrate")) / 7).log2(), 1), 4)).max(1));
mult = mult.times((Decimal.pow(Math.max(player.infinityPower.pow(getInfinityConversionRate() / 7).log2(), 1), 4)).max(1));
}
return mult;
}
@ -193,7 +193,7 @@ class TimeDimensionState extends DimensionState {
}
get productionPerSecond() {
if (EternityChallenge(1).isRunning || EternityChallenge(10).isRunning) {
if (EternityChallenge(1).isRunning || EternityChallenge(10).isRunning || TimeCompression.isActive) {
return new Decimal(0);
}
@ -214,7 +214,7 @@ class TimeDimensionState extends DimensionState {
}
const toGain = TimeDimension(tier + 1).productionPerSecond;
const current = Decimal.max(this.amount, 1);
return toGain.times(10).dividedBy(current).times(getGameSpeedupFactor());
return toGain.times(10).dividedBy(current).times(getGameSpeedupForDisplay());
}
get baseCost() {

View File

@ -21,7 +21,7 @@ function eternity(force, auto, specialConditions = {}) {
player.bestEternity = Math.min(player.thisEternity, player.bestEternity);
player.eternityPoints = player.eternityPoints.plus(gainedEternityPoints());
addEternityTime(player.thisEternity, player.thisEternityRealTime, gainedEternityPoints());
player.eternities += Effects.product(RealityUpgrade(3));
player.eternities = player.eternities.add(Effects.product(RealityUpgrade(3)));
}
if (EternityChallenge.isRunning) {
@ -65,7 +65,10 @@ function eternity(force, auto, specialConditions = {}) {
if (player.respec) respecTimeStudies(auto);
player.respec = false;
if (player.eternities === 1 || (player.reality.rebuyables[3] > 0 && player.eternities === RealityUpgrade(3).effectValue && player.eternityPoints.lte(10))) {
if (player.eternities.eq(1) ||
(player.reality.rebuyables[3] > 0 &&
player.eternities.eq(RealityUpgrade(3).effectValue) &&
player.eternityPoints.lte(10))) {
Tab.dimensions.time.show();
}
@ -82,7 +85,8 @@ function eternity(force, auto, specialConditions = {}) {
EPminpeak = new Decimal(0);
resetTimeDimensions();
try {
kong.submitStats('Eternities', player.eternities);
// FIXME: Eternity count is a Decimal and also why is this submitted in so many places?
// kong.submitStats('Eternities', player.eternities);
} catch (err) {
console.log("Couldn't load Kongregate API")
}
@ -116,8 +120,8 @@ function initializeResourcesAfterEternity() {
player.thisInfinityTime = 0;
player.thisInfinityLastBuyTime = 0;
player.thisInfinityRealTime = 0;
player.resets = (player.eternities >= 4) ? 4 : 0;
player.galaxies = (player.eternities >= 4) ? 1 : 0;
player.dimensionBoosts = player.eternities.gte(4) ? 4 : 0;
player.galaxies = player.eternities.gte(4) ? 1 : 0;
player.tickDecrease = 0.9;
player.partInfinityPoint = 0;
player.partInfinitied = 0;
@ -129,11 +133,11 @@ function initializeResourcesAfterEternity() {
player.thisEternity = 0;
player.thisEternityRealTime = 0;
player.totalTickGained = 0;
player.offlineProd = player.eternities >= 20 ? player.offlineProd : 0;
player.offlineProdCost = player.eternities >= 20 ? player.offlineProdCost : 1e7;
player.offlineProd = player.eternities.gte(20) ? player.offlineProd : 0;
player.offlineProdCost = player.eternities.gte(20) ? player.offlineProdCost : 1e7;
player.eterc8ids = 50;
player.eterc8repl = 40;
if (player.eternities < 20) {
if (player.eternities.lt(20)) {
player.infinityRebuyables = [0, 0];
GameCache.tickSpeedMultDecrease.invalidate();
GameCache.dimensionMultDecrease.invalidate();
@ -163,7 +167,7 @@ function applyRealityUpgrades() {
}
function eternityResetReplicanti() {
player.replicanti.unl = player.eternities >= 50;
player.replicanti.unl = player.eternities.gte(50);
player.replicanti.amount = player.replicanti.unl ? new Decimal(1) : new Decimal(0);
player.replicanti.chance = 0.01;
player.replicanti.chanceCost = new Decimal(1e150);
@ -172,7 +176,7 @@ function eternityResetReplicanti() {
player.replicanti.gal = 0;
player.replicanti.galaxies = 0;
player.replicanti.galCost = new Decimal(1e170);
if (player.eternities >= 3 && player.replicanti.galaxybuyer === undefined) player.replicanti.galaxybuyer = false;
if (player.eternities.gte(3) && player.replicanti.galaxybuyer === undefined) player.replicanti.galaxybuyer = false;
}
function askEternityConfirmation() {
@ -203,7 +207,7 @@ class EternityMilestoneState {
}
get isReached() {
return player.eternities >= this.config.eternities;
return player.eternities.gte(this.config.eternities);
}
}

View File

@ -14,7 +14,8 @@ function startEternityChallenge() {
IPminpeak = new Decimal(0);
EPminpeak = new Decimal(0);
resetTimeDimensions();
kong.submitStats("Eternities", player.eternities);
// FIXME: Eternity count is now a Decimal, also why is this submitted twice?
// kong.submitStats("Eternities", player.eternities);
resetTickspeed();
resetAntimatter();
playerInfinityUpgradesOnEternity();
@ -274,8 +275,6 @@ const EternityChallenges = {
}
return;
}
const isPostEc = RealityUpgrade(10).isBought ? player.eternities > 100 : player.eternities > 0;
if (!isPostEc) return;
const interval = this.interval;
let next = this.nextChallenge;
while (player.reality.lastAutoEC - interval > 0 && next !== undefined) {

View File

@ -63,5 +63,7 @@ function timeDisplayShort(ms) {
const commaRegexp = /\B(?=(\d{3})+(?!\d))/gu;
function formatWithCommas(value) {
return value.toString().replace(commaRegexp, ",");
const decimalPointSplit = value.toString().split(".");
decimalPointSplit[0] = decimalPointSplit[0].replace(commaRegexp, ",");
return decimalPointSplit.join(".");
}

View File

@ -141,7 +141,7 @@ function galaxyReset() {
EventHub.dispatch(GameEvent.GALAXY_RESET_BEFORE);
player.galaxies++;
player.tickDecrease -= 0.03;
player.resets = 0;
player.dimensionBoosts = 0;
softReset(0);
if (Notation.current === Notation.cancer) player.spreadingCancer += 1;
player.noSacrifices = true;
@ -149,7 +149,7 @@ function galaxyReset() {
}
function galaxyResetBtnClick() {
if (player.eternities >= 7 && !shiftDown) return maxBuyGalaxies(true);
if (player.eternities.gte(9) && !shiftDown) return maxBuyGalaxies(true);
if (!Galaxy.canBeBought || !Galaxy.requirement.isSatisfied) return false;
galaxyReset();
return true;

View File

@ -152,6 +152,8 @@ GameDatabase.reality.glyphEffects = [
effect: (level, strength) => 1.01 + Math.pow(level, 0.32) * Math.pow(strength, 0.45) / 75,
formatEffect: x => shorten(x, 3, 3),
combine: GlyphCombiner.multiply,
/** @type {function(number):number} */
softcap: value => (value > 4 ? 4 + 0.1 * (value - 4) : value),
}, {
id: "timespeed",
bitmaskIndex: 1,

View File

@ -3,6 +3,7 @@
const LOG10_MAX_VALUE = Math.log10(Number.MAX_VALUE);
const LN_SQRT_2_PI = 0.5 * Math.log(2 * Math.PI);
const LOG10_2 = Math.log10(2);
const LOG10_E = Math.log10(Math.E);
Math.PI_2 = Math.PI * 2;

View File

@ -29,7 +29,10 @@ class MatterDimensionState {
// In milliseconds
get interval() {
return Decimal.pow(0.89, this.dimension.intervalUpgrades).times(Decimal.pow(2, this._tier)).times(1000);
return Decimal.pow(0.89, this.dimension.intervalUpgrades)
.times(Decimal.pow(2, this._tier))
.times(1000)
.divide(Effects.max(1, CompressionUpgrade.matterBoost));
}
get power() {

View File

@ -131,7 +131,7 @@ let player = {
thisInfinityTime: 0,
thisInfinityRealTime: 0,
thisInfinityLastBuyTime: 0,
resets: 0,
dimensionBoosts: 0,
galaxies: 0,
tickDecrease: 0.9,
totalAntimatter: new Decimal(0),
@ -166,7 +166,7 @@ let player = {
postChallUnlocked: 0,
postC4Tier: 0,
eternityPoints: new Decimal(0),
eternities: 0,
eternities: new Decimal(0),
thisEternity: 0,
thisEternityRealTime: 0,
bestEternity: 999999999999,
@ -278,7 +278,7 @@ let player = {
pp: 0,
autoEC: true,
lastAutoEC: 0,
partEternitied: 0,
partEternitied: new Decimal(0),
automator: {
state: {
mode: AutomatorMode.STOP,
@ -393,6 +393,12 @@ let player = {
quoteIdx: 0,
disCharge: false,
peakGamespeed: 1,
compression: {
active: false,
entanglement: 0,
upgradeBits: 0,
respec: false
},
},
laitela: {
matter: new Decimal(0),
@ -456,7 +462,7 @@ const Player = {
},
get gainedEternities() {
return RealityUpgrade(10).isBought ? player.eternities - 100 : player.eternities;
return RealityUpgrade(10).isBought ? player.eternities.sub(100) : player.eternities;
},
get isInMatterChallenge() {
@ -481,7 +487,7 @@ const Player = {
if (NormalChallenge(12).isRunning) {
return basePerSecond.plus(getDimensionProductionPerSecond(2));
}
return basePerSecond.times(getGameSpeedupFactor());
return basePerSecond.times(getGameSpeedupForDisplay());
},
get bestRunIPPM() {

View File

@ -277,7 +277,7 @@ function completeReality(force, reset, auto = false) {
player.thisInfinityTime = 0;
player.thisInfinityLastBuyTime = 0;
player.thisInfinityRealTime = 0;
player.resets = isRUPG10Bought ? 4 : 0;
player.dimensionBoosts = isRUPG10Bought ? 4 : 0;
player.galaxies = isRUPG10Bought ? 1 : 0;
player.tickDecrease = 0.9;
player.interval = null;
@ -305,7 +305,7 @@ function completeReality(force, reset, auto = false) {
// This has to be reset before player.eternities to make the bumpLimit logic work
// correctly
EternityUpgrade.epMult.reset();
player.eternities = 0;
player.eternities = new Decimal(0);
player.thisEternity = 0;
player.thisEternityRealTime = 0;
player.bestEternity = 999999999999;
@ -356,6 +356,7 @@ function completeReality(force, reset, auto = false) {
Perk.startAM2
).toDecimal();
Enslaved.autoReleaseTick = 0;
player.celestials.ra.compression.freeDimboosts = 0;
resetInfinityRuns();
resetEternityRuns();
@ -366,9 +367,10 @@ function completeReality(force, reset, auto = false) {
NormalDimensions.reset();
secondSoftReset();
if (player.celestials.ra.disCharge) disChargeAll();
if (player.celestials.ra.compression.respec) CompressionUpgrades.respec();
player.celestials.ra.peakGamespeed = 1;
if (isRUPG10Bought) {
player.eternities = 100;
player.eternities = new Decimal(100);
if (Achievements.totalDisabledTime === 0) {
initializeChallengeCompletions();
}
@ -383,11 +385,12 @@ function completeReality(force, reset, auto = false) {
IPminpeak = new Decimal(0);
EPminpeak = new Decimal(0);
resetTimeDimensions();
kong.submitStats('Eternities', player.eternities);
if (player.eternities > 2 && player.replicanti.galaxybuyer === undefined) player.replicanti.galaxybuyer = false;
// FIXME: Eternity count is now a Decimal so this needs to be addressed
// kong.submitStats('Eternities', player.eternities);
if (player.eternities.gt(2) && player.replicanti.galaxybuyer === undefined) player.replicanti.galaxybuyer = false;
resetTickspeed();
playerInfinityUpgradesOnEternity();
if (player.eternities <= 1) {
if (player.eternities.lte(1)) {
Tab.dimensions.normal.show();
}
AchievementTimers.marathon2.reset();
@ -458,6 +461,10 @@ function handleCelestialRuns(force) {
player.celestials.ra.run = false;
}
if (TimeCompression.isActive) {
TimeCompression.isActive = false;
}
if (Laitela.isRunning) {
player.celestials.laitela.run = false;
if (!force && player.antimatter.gte(player.celestials.laitela.maxAmGained)) {

View File

@ -40,14 +40,23 @@ function replicantiGalaxy() {
}
// Produces replicanti quickly below e308, will auto-bulk-RG if production is fast enough
function fastReplicantiBelow308(gainFactor, isAutobuyerActive) {
function fastReplicantiBelow308(log10GainFactor, isAutobuyerActive) {
if (!isAutobuyerActive) {
player.replicanti.amount = Decimal.min(replicantiCap(), player.replicanti.amount.times(gainFactor));
player.replicanti.amount = Math.clampMax(player.replicanti.amount.exponent + log10GainFactor,
replicantiCap().log10());
return;
}
const replicantiExponent = gainFactor.log10() + player.replicanti.amount.log10();
// More than e308 galaxies per tick causes the game to die, and I don't think it's worth the performance hit of
// Decimalifying the entire calculation. And yes, this can and does actually happen super-lategame.
if (log10GainFactor.gt(Number.MAX_VALUE)) {
player.replicanti.galaxies += Replicanti.galaxies.max - player.replicanti.galaxies;
return;
}
const replicantiExponent = log10GainFactor.toNumber() + player.replicanti.amount.log10();
const toBuy = Math.floor(Math.min(replicantiExponent / 308, Replicanti.galaxies.max - player.replicanti.galaxies));
player.replicanti.amount = Decimal.min(replicantiCap(), Decimal.pow10(replicantiExponent - 308 * toBuy));
player.replicanti.amount = Decimal.pow10(replicantiExponent - 308 * toBuy).clampMax(replicantiCap());
player.replicanti.galaxies += toBuy;
}
@ -78,6 +87,7 @@ function getReplicantiInterval(noMod, intervalIn) {
interval = interval.divide(getAdjustedGlyphEffect("replicationspeed"));
interval = interval.divide(RA_UNLOCKS.TT_BOOST.effect.replicanti());
interval = interval.dividedByEffectOf(AlchemyResource.replication);
interval = interval.divide(Effects.max(1, CompressionUpgrade.replicantiSpeedFromDB));
if (V.isRunning) {
// This is a boost if interval < 1, but that only happens in EC12
// and handling it would make the replicanti code a lot more complicated.
@ -112,7 +122,7 @@ function replicantiLoop(diff) {
player.replicanti.amount =
Decimal.exp(logGainFactorPerTick.times(postScale).plus(1).log(Math.E) / postScale + logReplicanti);
} else {
fastReplicantiBelow308(Decimal.exp(logGainFactorPerTick), isRGAutobuyerEnabled);
fastReplicantiBelow308(logGainFactorPerTick.times(LOG10_E), isRGAutobuyerEnabled);
}
replicantiTicks = 0;
} else if (interval.lte(replicantiTicks)) {

View File

@ -2,7 +2,7 @@
function sacrificeReset(auto) {
if (!Sacrifice.isAffordable) return false;
if (player.resets < 5) return false;
if (DimBoost.totalBoosts < 5) return false;
if ((!player.break || (!InfinityChallenge.isRunning && NormalChallenge.isRunning)) &&
player.antimatter.gte(Decimal.MAX_NUMBER) && !Enslaved.isRunning) return false;
if (
@ -42,7 +42,7 @@ function sacrificeBtnClick() {
class Sacrifice {
static get isUnlocked() {
return player.infinitied.gt(0) || player.resets > 4;
return player.infinitied.gt(0) || DimBoost.totalBoosts > 4;
}
static get isAffordable() {

View File

@ -79,7 +79,7 @@ GameDatabase.achievements.normal = [
id: 25,
name: "Boosting to the max",
tooltip: "Buy 10 Dimension Boosts.",
checkRequirement: () => player.resets >= 10,
checkRequirement: () => DimBoost.purchasedBoosts >= 10,
checkEvent: GameEvent.DIMBOOST_AFTER
},
{
@ -190,7 +190,7 @@ GameDatabase.achievements.normal = [
id: 43,
name: "Zero Deaths",
tooltip: "Get to Infinity without Dimension shifts, boosts or Antimatter Galaxies in a challenge.",
checkRequirement: () => player.galaxies === 0 && player.resets === 0,
checkRequirement: () => player.galaxies === 0 && DimBoost.purchasedBoosts === 0,
checkEvent: GameEvent.BIG_CRUNCH_BEFORE,
reward: "Dimensions 1-4 are 25% stronger.",
effect: 1.25
@ -373,7 +373,7 @@ GameDatabase.achievements.normal = [
checkRequirement: () =>
NormalChallenge(11).isRunning &&
NormalDimension(1).amount.eq(1) &&
player.resets === 0 &&
DimBoost.purchasedBoosts === 0 &&
player.galaxies === 0,
checkEvent: GameEvent.BIG_CRUNCH_BEFORE,
reward: "1st Dimensions are 3 times stronger.",
@ -603,7 +603,7 @@ GameDatabase.achievements.normal = [
id: 102,
name: "This mile took an Eternity",
tooltip: "Get all Eternity milestones.",
checkRequirement: () => player.eternities >= 100,
checkRequirement: () => player.eternities.gte(100),
checkEvent: GameEvent.ETERNITY_RESET_AFTER
},
{
@ -766,7 +766,7 @@ GameDatabase.achievements.normal = [
player.infinityPoints.exponent >= 100 &&
NormalDimension(1).amount.eq(0) &&
player.infinitied.eq(0) &&
player.resets <= 4 &&
DimBoost.purchasedBoosts <= 4 &&
player.galaxies <= 1 &&
player.replicanti.galaxies === 0,
checkEvent: GameEvent.GAME_TICK_AFTER,

View File

@ -29,9 +29,9 @@ GameDatabase.achievements.secret = [
{
id: 16,
name: "Do you enjoy pain?",
tooltip: "Use standard, cancer, or bracket notation for 10 minutes with more than 1 eternity.",
tooltip: "Use a \"painful\" notation for 10 minutes with more than 1 eternity.",
checkRequirement: () => AchievementTimers.pain
.check(player.eternities >= 1 && Notation.current.isPainful, 600),
.check(player.eternities.gte(1) && Notation.current.isPainful, 600),
checkEvent: GameEvent.GAME_TICK_AFTER
},
{

View File

@ -195,8 +195,7 @@ GameDatabase.celestials.alchemy = {
effect: amount => 1 + amount / 2000000,
tier: 3,
uiOrder: 3,
formatEffect: value => `Game speed ${formatX(value, 5, 5)} for every real-time minute ` +
"spent in your current reality",
formatEffect: value => `Game speed ${formatX(value, 5, 5)} per real-time minute in this reality`,
reagents: [
{
resource: ALCHEMY_RESOURCE.EFFARIG,
@ -341,9 +340,9 @@ GameDatabase.celestials.alchemy = {
effect: amount => amount / 50000,
tier: 4,
uiOrder: 4,
formatEffect: value => (Ra.has(RA_UNLOCKS.LAITELA_UNLOCK)
? `Boost matter dimension generation chance by +${formatPercents(value, 2, 2)}`
: "?????"),
formatEffect: value => (player.celestials.laitela.matter === 0
? "?????"
: `Boost matter dimension generation chance by +${formatPercents(value, 2, 2)}`),
reagents: [
{
resource: ALCHEMY_RESOURCE.EFFARIG,

View File

@ -0,0 +1,105 @@
"use strict";
GameDatabase.celestials.compression = {
freeBoost: {
id: 0,
description: "Get free dimboosts based on free galaxy count",
secondary: () => `${shortenSmallInteger(10000)} free galaxies`,
cost: 2,
resource: () => player.dilation.freeGalaxies,
threshold: () => 10000,
currentDisplay: () => shortenSmallInteger(player.dilation.freeGalaxies),
invertedCondition: false,
effect: () => Math.pow(Math.clampMin(player.dilation.freeGalaxies - 10000, 0), 1.6) + 50000
},
improvedDTMult: {
id: 1,
description: "Improve the rebuyable DT multiplier to 2.2x",
secondary: () => `${shorten(new Decimal("1e1400"))} Dilated Time`,
cost: 21,
resource: () => player.dilation.dilatedTime,
threshold: () => new Decimal("1e1400"),
currentDisplay: () => shorten(player.dilation.dilatedTime, 2, 2),
invertedCondition: false,
effect: () => 2.2
},
replicantiSpeedFromDB: {
id: 2,
description: "Free dimboosts improve replicanti speed",
secondary: () => `${shorten(new Decimal("1e1500000"))} Replicanti`,
cost: 20,
resource: () => player.replicanti.amount,
threshold: () => new Decimal("1e1500000"),
currentDisplay: () => shorten(player.replicanti.amount),
invertedCondition: false,
effect: () => Math.pow(DimBoost.freeBoosts, 25)
},
strongerDilationGalaxies: {
id: 3,
// Note that this actually applies per level of dilation applied in compression
description: "Galaxies are twice as strong when dilated",
secondary: () => `${shortenSmallInteger(13000)} total galaxies`,
cost: 15,
resource: () => player.galaxies + Replicanti.galaxies.total + player.dilation.freeGalaxies,
threshold: () => 13000,
currentDisplay: () => shortenSmallInteger(player.galaxies + Replicanti.galaxies.total +
player.dilation.freeGalaxies),
invertedCondition: false,
effect: () => 2
},
freeGalaxySoftcap: {
id: 4,
description: "Increase the 2x free galaxy cap to 10,000 galaxies",
secondary: () => `${shorten(Decimal.pow10(5e11), 2, 2)} Antimatter`,
cost: 100,
resource: () => player.antimatter,
threshold: () => Decimal.pow10(5e11),
currentDisplay: () => shorten(player.antimatter, 2, 2),
invertedCondition: false,
effect: () => 10000
},
freeGalaxyScaling: {
id: 5,
description: "Improve the free galaxy threshold scaling",
secondary: () => "Free galaxy threshold below 1.325",
cost: 45,
resource: () => getFreeGalaxyMultBeforeCompression(),
threshold: () => 1.325,
currentDisplay: () => shorten(getFreeGalaxyMult(), 2, 3),
invertedCondition: true,
effect: () => 0.1 * Math.sqrt(player.dilation.baseFreeGalaxies / 20000)
},
infDimSoftcap: {
id: 6,
description: "ID softcap increases based on free galaxies past 10,000",
secondary: () => "^7.3 Infinity power conversion",
cost: 24,
resource: () => getInfinityConversionRate(),
threshold: () => 7.3,
currentDisplay: () => shorten(getInfinityConversionRate(), 2, 3),
invertedCondition: false,
effect: () => 100 * Math.clampMin(player.dilation.freeGalaxies - 10000, 0)
},
moreEntanglement: {
id: 7,
description: "Gain 40% more entanglement",
secondary: () => "No 8th time dimensions",
cost: 48,
resource: () => TimeDimension(8).amount,
threshold: () => 0.5,
currentDisplay: () => shortenSmallInteger(TimeDimension(8).amount),
invertedCondition: true,
effect: () => 1.4
},
matterBoost: {
id: 8,
description: "Dilated time improves matter dimension production speed",
secondary: () => "10 Matter",
cost: 33,
resource: () => Laitela.matter,
threshold: () => 10,
currentDisplay: () => shorten(Laitela.matter, 2, 1),
invertedCondition: false,
effect: () => Math.clampMin(player.dilation.dilatedTime.log10() / 1000, 1)
},
};

View File

@ -50,7 +50,7 @@ GameDatabase.celestials.v = {
name: "Matterception",
description: value => `Get ${value} Dimensional Boosts while dilating time, inside EC5.`,
values: [50, 52, 54, 56, 58, 60],
condition: x => player.dilation.active && EternityChallenge(5).isRunning && player.resets >= x
condition: x => player.dilation.active && EternityChallenge(5).isRunning && DimBoost.purchasedBoosts >= x
}
]
};

View File

@ -20,8 +20,11 @@ GameDatabase.eternity.dilation = (function() {
id: 1,
initialCost: 1e5,
increment: 10,
description: "Double Dilated Time gain.",
effect: bought => Decimal.pow(2, bought),
description: () =>
(CompressionUpgrade.improvedDTMult.canBeApplied
? "Multiply Dilated Time gain by 2.2x"
: "Double Dilated Time gain."),
effect: bought => Decimal.pow(Effects.max(2, CompressionUpgrade.improvedDTMult), bought),
formatEffect: value => formatX(value, 2, 0),
formatCost: value => shorten(value, 2, 0)
}),
@ -49,7 +52,7 @@ GameDatabase.eternity.dilation = (function() {
doubleGalaxies: {
id: 4,
cost: 5e6,
description: "Gain twice as many free galaxies.",
description: "Gain twice as many free galaxies, up to 1,000.",
effect: 2
},
tdMultReplicanti: {

View File

@ -7,7 +7,7 @@ GameDatabase.eternity.milestones = {
},
keepAutobuyers: {
eternities: 2,
reward: "You keep your autobuyers on Eternity"
reward: "You start Eternity with all normal autobuyers"
},
autobuyerReplicantiGalaxy: {
eternities: 3,
@ -15,7 +15,7 @@ GameDatabase.eternity.milestones = {
},
keepInfinityUpgrades: {
eternities: 4,
reward: "You keep your infinity upgrades on Eternity"
reward: "You start Eternity with all infinity upgrades"
},
bigCrunchModes: {
eternities: 5,

View File

@ -11,16 +11,18 @@ GameDatabase.eternity.upgrades = {
idMultEternities: {
id: 2,
cost: 10,
description: "Infinity Dimension multiplier based on Eternities ((x/200)^log4(2x))",
description: () => `Infinity Dimension multiplier based on Eternities ((x/200)^log4(2x), softcap at ${shorten(1e5)})`,
effect() {
const log4 = Math.log4;
const eternities = Math.min(player.eternities, 100000);
const base = eternities / 200 + 1;
const pow = Math.log(eternities * 2 + 1) / log4;
const mult1 = new Decimal((player.eternities - 100000) / 200 + 1);
const mult2 = Math.log((player.eternities - 100000) * 2 + 1) / log4;
const totalMult = mult1.times(mult2).clampMin(1);
return Decimal.pow(base, pow).times(totalMult);
const eterPreCap = player.eternities.clampMax(1e5).toNumber();
const base = eterPreCap / 200 + 1;
const pow = Math.log(eterPreCap * 2 + 1) / log4;
const multPreCap = Math.pow(base, pow);
const eterPostCap = player.eternities.sub(1e5);
const mult1 = eterPostCap.divide(200).plus(1);
const mult2 = eterPostCap.times(2).plus(1).log(Math.E) / log4;
const multPostCap = mult1.times(mult2).clampMin(1);
return multPostCap.times(multPreCap);
},
formatEffect: value => `${shortenMoney(value)}x`
},

View File

@ -7,7 +7,7 @@ GameDatabase.eternity.timeStudies.ec = [
requirement: {
resource: "Eternities",
current: () => player.eternities,
required: completions => 20000 + completions * 20000,
required: completions => new Decimal(20000 + completions * 20000),
formatValue: value => value.toString()
}
},

View File

@ -48,7 +48,7 @@ GameDatabase.eternity.timeStudies.normal = (function() {
cost: 2,
requirement: 22,
description: () => `You gain ${TimeStudy(32).effectValue}x more infinitied stat (based on Dimension Boosts)`,
effect: () => Math.max(player.resets, 1)
effect: () => Math.max(DimBoost.totalBoosts, 1)
},
{
id: 33,
@ -154,7 +154,8 @@ GameDatabase.eternity.timeStudies.normal = (function() {
cost: 6,
requirement: 72,
description: "Dimension Boosts affect Infinity Dimensions",
effect: () => Decimal.pow(1.0000109, Math.pow(player.resets, 2)),
effect: () => Decimal.pow(1.0000109, Math.pow(DimBoost.totalBoosts, 2)),
cap: new Decimal("1e10000000000"),
formatEffect: value => formatX(value, 2, 1)
},
{
@ -372,7 +373,12 @@ GameDatabase.eternity.timeStudies.normal = (function() {
cost: 300,
requirement: () => TimeStudy(181).isBought && EternityChallenge(10).completions > 0,
description: "Normal Dimension boost based on Eternities",
effect: () => Decimal.pow(1.0285, player.eternities),
// This effect is a bit wonky because 1.0285^eternities doesn't even fit in break_infinity once you have a bit
// past e308 eternities, and once this threshold is passed the formula actually just returns zero. Rewriting it
// to have an explicit conditional makes sure that this doesn't happen; in practice the cap hits just past 1e6.
effect: () => (player.eternities.gt(1e10)
? new Decimal("1e13000")
: Decimal.pow(1.0285, player.eternities)),
cap: new Decimal("1e13000"),
formatEffect: value => formatX(value, 2, 1)
},
@ -396,7 +402,7 @@ GameDatabase.eternity.timeStudies.normal = (function() {
description: "Galaxies are more effective based on your time shards",
effect: () => Math.pow(player.timeShards.clampMin(2).log2(), 0.005),
cap: 1.1,
formatEffect: value => "+" + formatPercents(value - 1, 3)
formatEffect: value => `+${formatPercents(value - 1, 3)}`
},
{
id: 213,
@ -425,7 +431,7 @@ GameDatabase.eternity.timeStudies.normal = (function() {
requirement: () => TimeStudy(211).isBought && !TimeStudy(222).isBought,
requirementV: () => TimeStudy(211).isBought && TimeStudy(222).isBought,
description: "Time Dimensions gain a multiplier based on Dimension Boosts",
effect: () => Decimal.pow(1 + 0.0025, player.resets),
effect: () => Decimal.pow(1 + 0.0025, DimBoost.totalBoosts),
formatEffect: value => formatX(value, 2, 1)
},
{
@ -454,7 +460,7 @@ GameDatabase.eternity.timeStudies.normal = (function() {
const noun = effect === 1 ? "galaxy" : "galaxies";
return `Galaxy cost scaling starts ${effect} ${noun} later (1 for every 2000 DimBoosts)`;
},
effect: () => Math.floor(player.resets / 2000)
effect: () => Math.floor(DimBoost.totalBoosts / 2000)
},
{
id: 225,
@ -497,7 +503,7 @@ GameDatabase.eternity.timeStudies.normal = (function() {
requirement: () => (TimeStudy(221).isBought || TimeStudy(222).isBought) && !TimeStudy(232).isBought,
requirementV: () => (TimeStudy(221).isBought || TimeStudy(222).isBought) && TimeStudy(232).isBought,
description: "Dimension Boosts are more effective based on their amount",
effect: () => Decimal.pow(player.resets, 0.3).clampMin(1),
effect: () => Decimal.pow(DimBoost.totalBoosts, 0.3).clampMin(1),
formatEffect: value => formatX(value, 2, 2)
},
{
@ -507,7 +513,7 @@ GameDatabase.eternity.timeStudies.normal = (function() {
requirementV: () => (TimeStudy(223).isBought || TimeStudy(224).isBought) && TimeStudy(231).isBought,
description: "Galaxies are more effective based on Antimatter Galaxies",
effect: () => Math.pow(1 + player.galaxies / 1000, 0.2),
formatEffect: value => "+" + formatPercents(value - 1, 3)
formatEffect: value => `+${formatPercents(value - 1, 3)}`
},
{
id: 233,

View File

@ -10,7 +10,8 @@ GameDatabase.infinity.breakUpgrades = (function() {
description: config.description,
effect: () => player.infinityRebuyables[config.id],
formatEffect: value => (value === maxUpgrades ? `10x ➜ ${10 - value}x` : `10x ➜ ${10 - value - 1}x`),
staticEffect: true
staticEffect: true,
formatCost: value => shorten(value, 2, 0)
};
}

View File

@ -1014,7 +1014,7 @@ GameDatabase.news = [
{
id: "c3",
text: "What do you mean, more than two dimensions??? We're on a screen, clearly there are only 2 dimensions.",
condition: () => NormalDimension(3).amount.gt(0) || player.resets > 0
condition: () => NormalDimension(3).amount.gt(0) || DimBoost.totalBoosts > 0
},
{
id: "c4",
@ -1036,7 +1036,7 @@ GameDatabase.news = [
{
id: "c7",
text: "To understand dimensional sacrifice, you do actually need a PhD in theoretical physics. Sorry!",
condition: () => player.sacrificed.e >= 10 || player.resets >= 6
condition: () => player.sacrificed.e >= 10 || DimBoost.totalBoosts >= 6
},
{
id: "c8",
@ -1059,50 +1059,50 @@ GameDatabase.news = [
id: "c11",
text: "9th Dimension is a lie.",
condition: () =>
player.resets >= 5 ||
DimBoost.totalBoost >= 5 ||
player.galaxies > 0 ||
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
id: "c12",
text: "The square root of 9 is 3, therefore the 9th dimension can't exist.",
condition: () =>
player.resets >= 5 ||
DimBoost.totalBoosts >= 5 ||
player.galaxies > 0 ||
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
id: "c13",
text: "You got assimilated by the 9th dimension? Just call your doctor for mental illness!",
condition: () =>
player.resets >= 5 ||
DimBoost.totalBoosts >= 5 ||
player.galaxies > 0 ||
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
id: "c14",
text: "Why is there no 9th dimension? Because 7 8 9.",
condition: () =>
player.resets >= 5 ||
DimBoost.totalBoosts >= 5 ||
player.galaxies > 0 ||
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
id: "c15",
text: "The 9th dimension cannot exist because the Nein-speaking nazis died in WW2.",
condition: () =>
player.resets >= 5 ||
DimBoost.totalBoosts >= 5 ||
player.galaxies > 0 ||
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
@ -1111,10 +1111,10 @@ GameDatabase.news = [
"If you break the fourth wall... well, there's still the fifth, sixth, seventh, and eighth to get through " +
"before you encounter bad things, so you should be fine",
condition: () =>
player.resets >= 5 ||
DimBoost.totalBoosts >= 5 ||
player.galaxies > 0 ||
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
@ -1125,20 +1125,20 @@ GameDatabase.news = [
"no one on the Discord can be on dimension 9. Only then can he rest, for up to 6 hours, before waking up " +
"forcefully to avoid getting the offline achievement.",
condition: () =>
player.resets >= 5 ||
DimBoost.totalBoosts >= 5 ||
player.galaxies > 0 ||
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
id: "c18",
text: "If the 9th dimension is all evil, then is 3 the root of all evil?",
condition: () =>
player.resets >= 5 ||
DimBoost.totalBoosts >= 5 ||
player.galaxies > 0 ||
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
@ -1148,13 +1148,13 @@ GameDatabase.news = [
"one with matter, and a large time vortex.",
condition: () =>
player.infinitied.gt(0) ||
player.eternities > 0 ||
PlayerProgress.eternityUnlocked() ||
player.realities > 0
},
{
id: "c20",
text: "Infinity: the one thing that's supposed to break.",
condition: () => player.infinitied.gt(0) || player.eternities > 0 || player.realities > 0
condition: () => player.infinitied.gt(0) || PlayerProgress.eternityUnlocked() || player.realities > 0
},
{
id: "c21",
@ -1186,7 +1186,7 @@ GameDatabase.news = [
text:
"Thanos is gonna be super dissapointed when he shows up with a fully powered infinity gauntlet, and Hevi " +
"has a fully powered eternity gauntlet",
condition: () => player.eternities > 0 || player.realities > 0
condition: () => PlayerProgress.eternityUnlocked() || player.realities > 0
},
{
id: "c27",
@ -1309,12 +1309,12 @@ GameDatabase.news = [
{
id: "c49",
text: "One day you will stop your incessant grind.",
condition: () => player.eternities > 50000
condition: () => player.eternities.gt(50000)
},
{
id: "c50",
text: "You can probably stop farming for eternities now...",
condition: () => player.eternities > 2000000
condition: () => player.eternities.gt(2000000)
},
{
id: "c51",
@ -1392,7 +1392,7 @@ GameDatabase.news = [
condition: () =>
Achievement(43).isUnlocked &&
player.infinitied.eq(1) &&
player.eternities === 0 &&
!PlayerProgress.eternityUnlocked() &&
player.realities === 0
},
{
@ -1401,7 +1401,7 @@ GameDatabase.news = [
condition: () =>
player.antimatter.e >= 41900 &&
!player.replicanti.unl &&
player.eternities === 0 &&
!PlayerProgress.eternityUnlocked() &&
player.realities === 0
},
{

View File

@ -138,7 +138,7 @@ GameDatabase.reality.upgrades = (function() {
id: 14,
cost: 50,
requirement: () => `${shorten(2e6)} Eternities`,
checkRequirement: () => player.eternities >= 2e6,
checkRequirement: () => player.eternities.gte(2e6),
checkEvent: GameEvent.ETERNITY_RESET_AFTER,
description: "Gain Eternities per second equal to your Realities",
effect: () => Math.pow(player.realities * RA_UNLOCKS.TT_BOOST.effect.eternity(),
@ -181,7 +181,7 @@ GameDatabase.reality.upgrades = (function() {
checkRequirement: () => Glyphs.activeList.countWhere(g => g.level >= 10) === 4,
checkEvent: GameEvent.REALITY_RESET_BEFORE,
description: "Eternities affect glyph level",
effect: () => Math.max(Math.sqrt(Math.log10(player.eternities)) * 0.45, 1),
effect: () => Math.max(Math.sqrt(player.eternities.log10()) * 0.45, 1),
formatCost: value => shorten(value, 1, 0)
},
{

View File

@ -18,7 +18,7 @@ GameDatabase.tabs = [
symbol: "∞",
component: "infinity-dim-tab",
newUIComponent: "new-inf-dimensions-tab",
condition: () => player.eternities > 0 || InfinityDimension(1).isUnlocked
condition: () => player.eternities.gt(0) || InfinityDimension(1).isUnlocked
},
{
key: "time",
@ -26,14 +26,14 @@ GameDatabase.tabs = [
symbol: "Δ",
component: "time-dim-tab",
newUIComponent: "new-time-dimensions-tab",
condition: () => player.eternities > 0
condition: () => player.eternities.gt(0)
},
{
key: "production",
name: "Production",
symbol: "📈",
component: "dim-production-tab",
condition: () => player.eternities > 0 || player.infinitied.gt(0)
condition: () => player.eternities.gt(0) || player.infinitied.gt(0)
}
]
},
@ -111,7 +111,7 @@ GameDatabase.tabs = [
{
key: "challenges",
name: "Challenges",
condition: () => player.eternities > 0 || player.infinitied.gt(0),
condition: () => player.eternities.gt(0) || player.infinitied.gt(0),
subtabs: [
{
key: "normal",
@ -146,7 +146,7 @@ GameDatabase.tabs = [
name: "Infinity",
oldUIClass: "infinitytabbtn",
newUIClass: "infinity",
condition: () => player.eternities > 0 || player.infinitied.gt(0),
condition: () => player.eternities.gt(0) || player.infinitied.gt(0),
before: "infinity-points-header",
subtabs: [
{
@ -180,7 +180,7 @@ GameDatabase.tabs = [
name: "Eternity",
oldUIClass: "eternitytabbtn",
newUIClass: "eternity",
condition: () => player.eternities > 0,
condition: () => player.eternities.gt(0),
subtabs: [
{
key: "studies",
@ -206,6 +206,13 @@ GameDatabase.tabs = [
symbol: "TD",
component: "time-dilation-tab",
condition: () => TimeStudy.dilation.isBought
},
{
key: "compression",
name: "Time compression",
symbol: "TC",
component: "time-compression-tab",
condition: () => Ra.pets.enslaved.level >= 25
}
],
},
@ -246,7 +253,14 @@ GameDatabase.tabs = [
name: "Black hole",
symbol: "BH",
component: "black-hole-tab",
}
},
{
key: "alchemy",
name: "Glyph alchemy",
symbol: "⛧",
component: "alchemy-tab",
condition: () => Ra.has(RA_UNLOCKS.GLYPH_ALCHEMY)
},
],
},
{
@ -290,13 +304,6 @@ GameDatabase.tabs = [
component: "ra-tab",
condition: () => V.has(V_UNLOCKS.RUN_UNLOCK_THRESHOLDS[1])
},
{
key: "alchemy",
name: "Glyph Alchemy",
symbol: "⛧",
component: "alchemy-tab",
condition: () => Ra.has(RA_UNLOCKS.GLYPH_ALCHEMY)
},
{
key: "laitela",
name: "Lai'tela",

View File

@ -174,6 +174,9 @@ GameStorage.devMigrations = {
// player.lastTenEternities[i][2] = undefined;
// player.lastTenRealities[i][3] = undefined;
// }
// For anyone who is looking at this part of the code for debugging purposes, note that GameSpeedEffect.EC12
// has been replaced by GameSpeedEffect.FIXEDSPEED since EC12 is no longer the only fixed-speed effect
},
GameStorage.migrations.fixChallengeIds,
GameStorage.migrations.adjustMultCosts,
@ -419,7 +422,9 @@ GameStorage.devMigrations = {
delete player.autoRealityMode;
delete player.autoEternityMode;
},
GameStorage.migrations.convertNewsToSet
GameStorage.migrations.convertNewsToSet,
GameStorage.migrations.convertEternityCountToDecimal,
GameStorage.migrations.renameDimboosts
],
patch(player) {

View File

@ -117,6 +117,8 @@ GameStorage.migrations = {
GameStorage.migrations.renameMoney(player);
GameStorage.migrations.moveAutobuyers(player);
GameStorage.migrations.convertNewsToSet(player);
GameStorage.migrations.convertEternityCountToDecimal(player);
GameStorage.migrations.renameDimboosts(player);
}
},
@ -569,6 +571,16 @@ GameStorage.migrations = {
delete player.newsArray;
},
convertEternityCountToDecimal(player) {
player.eternities = new Decimal(player.eternities);
player.reality.partEternitied = new Decimal(player.reality.partEternitied);
},
renameDimboosts(player) {
player.dimensionBoosts = player.resets;
delete player.resets;
},
prePatch(saveData) {
// Initialize all possibly undefined properties that were not present in
// previous versions and which could be overwritten by deepmerge

View File

@ -153,6 +153,7 @@ const GameStorage = {
if (diff > 1000 * 1000) {
simulateTime(diff / 1000);
}
nextTickDiff = player.options.updateRate;
GameUI.update();
}
};

View File

@ -7,21 +7,25 @@ function canBuyTickSpeed() {
function getTickSpeedMultiplier() {
if (InfinityChallenge(3).isRunning || Laitela.isRunning) return new Decimal(1);
if (Ra.isRunning) return new Decimal(0.89);
let replicantiGalaxies = player.replicanti.galaxies;
// Note that this already includes the "50% more" active path effect
let replicantiGalaxies = Replicanti.galaxies.bought;
replicantiGalaxies *= (1 + Effects.sum(
TimeStudy(132),
TimeStudy(133)
));
replicantiGalaxies += Effects.sum(
TimeStudy(225),
TimeStudy(226)
);
replicantiGalaxies += Effarig.bonusRG;
const nonActivePathReplicantiGalaxies = Math.min(player.replicanti.galaxies, player.replicanti.gal);
// "extra" galaxies unaffected by the passive/idle boosts come from studies 225/226 and Effarig Infinity
replicantiGalaxies += Replicanti.galaxies.extra;
const nonActivePathReplicantiGalaxies = Math.min(Replicanti.galaxies.bought,
ReplicantiUpgrade.galaxies.value);
// Effects.sum is intentional here - if EC8 is not completed,
// this value should not be contributed to total replicanti galaxies
replicantiGalaxies += nonActivePathReplicantiGalaxies * Effects.sum(EternityChallenge(8).reward);
let galaxies = player.galaxies + player.dilation.freeGalaxies + replicantiGalaxies;
if (TimeCompression.isActive) {
galaxies *= Math.pow(Effects.max(1, CompressionUpgrade.strongerDilationGalaxies), TimeCompression.compressionDepth);
} else if (player.dilation.active) {
galaxies *= Effects.max(1, CompressionUpgrade.strongerDilationGalaxies);
}
if (galaxies < 3) {
let baseMultiplier = 0.9;
if (player.galaxies === 0) baseMultiplier = 0.89;
@ -151,7 +155,7 @@ function resetTickspeed() {
const Tickspeed = {
get isUnlocked() {
return NormalDimension(2).amount.gt(0) || player.eternities >= 30;
return NormalDimension(2).amount.gt(0) || player.eternities.gte(30);
},
get multiplier() {
@ -162,7 +166,7 @@ const Tickspeed = {
const tickspeed = Effarig.isRunning
? Effarig.tickspeed
: this.baseValue;
return player.dilation.active ? dilatedValueOf(tickspeed) : tickspeed;
return (player.dilation.active || TimeCompression.isActive) ? dilatedValueOf(tickspeed) : tickspeed;
},
get baseValue() {
@ -180,8 +184,8 @@ const Tickspeed = {
const FreeTickspeed = {
BASE_SOFTCAP: 300000,
GROWTH_RATE: 4e-3,
GROWTH_EXP: 1.5,
GROWTH_RATE: 6e-6,
GROWTH_EXP: 2,
get amount() {
return player.totalTickGained;

View File

@ -109,8 +109,8 @@ function buyUntilTen(tier) {
}
function playerInfinityUpgradesOnEternity() {
if (player.eternities < 4) player.infinityUpgrades.clear();
else if (player.eternities < 20) {
if (player.eternities.lt(4)) player.infinityUpgrades.clear();
else if (player.eternities.lt(20)) {
player.infinityUpgrades = new Set(["timeMult", "dimMult", "timeMult2", "skipReset1", "skipReset2",
"unspentBonus", "27Mult", "18Mult", "36Mult", "resetMult", "skipReset3", "passiveGen",
"45Mult", "resetBoost", "galaxyBoost", "skipResetGalaxy"]);
@ -173,6 +173,15 @@ function gainedRealityMachines() {
let rmGain = Decimal.pow(1000, player.eternityPoints.plus(gainedEternityPoints()).e / 4000 - 1);
rmGain = rmGain.times(getRealityMachineMultiplier());
rmGain = rmGain.plusEffectOf(Perk.realityMachineGain);
// This happens around ee10 and is necessary to reach e9e15 antimatter without having to deal with the various
// potential problems associated with having ee9 RM, of which there are lots (both balance-wise and design-wise).
// The softcap here squishes every additional OoM in the exponent into another factor of e1000 RM, putting e9e15
// antimatter around e7000 RM instead of e1000000000 RM.
const softcapRM = new Decimal("1e1000");
if (rmGain.gt(softcapRM)) {
const exponentOOMAboveCap = Math.log10(rmGain.log10() / softcapRM.log10());
rmGain = softcapRM.pow(1 + exponentOOMAboveCap);
}
return Decimal.floor(rmGain);
}
@ -268,6 +277,7 @@ function gainedInfinities() {
RealityUpgrade(7)
);
infGain = infGain.times(getAdjustedGlyphEffect("infinityinfmult"));
infGain = infGain.times(RA_UNLOCKS.TT_BOOST.effect.infinity());
return infGain;
}
@ -353,23 +363,36 @@ var IPminpeak = new Decimal(0)
var EPminpeak = new Decimal(0)
var replicantiTicks = 0
const GameSpeedEffect = {EC12: 1, TIMEGLYPH: 2, BLACKHOLE: 3}
const GameSpeedEffect = { FIXEDSPEED: 1, TIMEGLYPH: 2, BLACKHOLE: 3, TIMESTORAGE: 4, MOMENTUM: 5 };
/**
* @param {number[]} effectsToConsider A list of various game speed changing effects to apply when calculating
* the game speed. If left undefined, all effects will be applied.
* @param {number} blackHoleOverride A numerical value that, if supplied, will replace the multiplier that would
* have been applied for black holes.
* @param {number} blackHolesActiveOverride A numerical value which forces all black holes up to its specified index
* to be active for the purposes of game speed calculation.
*/
function getGameSpeedupFactor(effectsToConsider, blackHoleOverride, blackHolesActiveOverride) {
let effects;
if (effectsToConsider === undefined) {
effectsToConsider = [GameSpeedEffect.EC12, GameSpeedEffect.TIMEGLYPH, GameSpeedEffect.BLACKHOLE];
}
let factor = 1;
if (EternityChallenge(12).isRunning && effectsToConsider.includes(GameSpeedEffect.EC12)) {
// If we're taking account of EC12 at all and we're in EC12, we'll never want to consider anything else,
// since part of the effect of EC12 is to disable all other things that affect gamespeed.
return 1 / 1000;
}
if (effectsToConsider.includes(GameSpeedEffect.TIMEGLYPH)) {
factor *= getAdjustedGlyphEffect("timespeed");
effects = [GameSpeedEffect.FIXEDSPEED, GameSpeedEffect.TIMEGLYPH, GameSpeedEffect.BLACKHOLE,
GameSpeedEffect.TIMESTORAGE, GameSpeedEffect.MOMENTUM];
} else {
effects = effectsToConsider;
}
if (effectsToConsider.includes(GameSpeedEffect.BLACKHOLE)) {
if (effects.includes(GameSpeedEffect.FIXEDSPEED)) {
if (TimeCompression.isActive) {
return 1e-100;
}
if (EternityChallenge(12).isRunning) {
return 1 / 1000;
}
}
let factor = 1;
if (effects.includes(GameSpeedEffect.BLACKHOLE)) {
if (blackHoleOverride !== undefined) {
factor *= blackHoleOverride;
} else if (!BlackHoles.arePaused) {
@ -387,13 +410,23 @@ function getGameSpeedupFactor(effectsToConsider, blackHoleOverride, blackHolesAc
}
}
if (Ra.has(RA_UNLOCKS.GAMESPEED_BOOST)) {
factor *= Ra.gamespeedStoredTimeMult();
if (effects.includes(GameSpeedEffect.TIMEGLYPH)) {
factor *= getAdjustedGlyphEffect("timespeed");
factor = Math.pow(factor, getAdjustedGlyphEffect("effarigblackhole"));
}
factor *= Math.pow(AlchemyResource.momentum.effectValue, Time.thisRealityRealTime.totalMinutes);
if (effects.includes(GameSpeedEffect.MOMENTUM)) {
const cappedTime = Math.min(Time.thisRealityRealTime.totalMinutes, 7 * 24 * 60);
factor *= Math.pow(AlchemyResource.momentum.effectValue, cappedTime);
}
factor = Math.pow(factor, getAdjustedGlyphEffect("effarigblackhole"));
// Time storage is linearly scaled because exponential scaling is pretty useless in practice
if (player.celestials.enslaved.isStoring && effects.includes(GameSpeedEffect.TIMESTORAGE)) {
const storedTimeWeight = player.celestials.enslaved.storedFraction;
factor = factor * (1 - storedTimeWeight) + storedTimeWeight;
}
// Effarig nerf and dev.goFast() will always be applied
if (Effarig.isRunning) {
factor = Effarig.multiplier(factor).toNumber();
}
@ -403,22 +436,59 @@ function getGameSpeedupFactor(effectsToConsider, blackHoleOverride, blackHolesAc
return factor;
}
function getGameSpeedupForDisplay() {
const speedFactor = getGameSpeedupFactor();
if (Enslaved.isAutoReleasing && !(EternityChallenge(12).isRunning || TimeCompression.isActive)) {
return Math.max(Enslaved.autoReleaseSpeed, speedFactor);
}
return speedFactor;
}
let autobuyerOnGameLoop = true;
// "diff" is in ms. When unspecified, it just uses the game update rate.
let nextTickDiff;
function gameLoop(diff, options = {}) {
// When storing real time, all we do is count time and update the UI. This ignores any logic
// that may have gone into diff or options.
PerformanceStats.start("Frame Time");
PerformanceStats.start("Game Update");
EventHub.dispatch(GameEvent.GAME_TICK_BEFORE);
const thisUpdate = Date.now();
const realDiff = diff === undefined
? Math.clamp(thisUpdate - player.lastUpdate, 1, 21600000)
: diff;
player.realTimePlayed += realDiff;
player.thisInfinityRealTime += realDiff;
player.thisEternityRealTime += realDiff;
player.thisRealityRealTime += realDiff;
// Matter dimensions bypass any kind of stored time mechanics
Laitela.handleMatterDimensionUnlocks();
matterDimensionLoop(realDiff);
// When storing real time, skip everything else having to do with production once stats are updated
if (Enslaved.isStoringRealTime) {
Enslaved.storeRealTime();
GameUI.update();
return;
}
PerformanceStats.start("Frame Time");
PerformanceStats.start("Game Update");
EventHub.dispatch(GameEvent.GAME_TICK_BEFORE);
const thisUpdate = Date.now();
if (diff === undefined) var diff = Math.min(thisUpdate - player.lastUpdate, 21600000);
if (diff < 0) diff = 1;
// Ra-Enslaved auto-release stored time (once every 5 ticks)
let isAutoReleaseTick;
if (Enslaved.isAutoReleasing) {
Enslaved.autoReleaseTick++;
}
if (Enslaved.autoReleaseTick >= 5) {
Enslaved.autoReleaseTick = 0;
Enslaved.useStoredTime(true);
isAutoReleaseTick = true;
} else {
nextTickDiff = player.options.updateRate;
isAutoReleaseTick = false;
}
if (diff === undefined) {
diff = nextTickDiff;
}
if (autobuyerOnGameLoop) {
Autobuyers.tick();
@ -431,41 +501,35 @@ function gameLoop(diff, options = {}) {
GameCache.timeDimensionCommonMultiplier.invalidate();
GameCache.totalIPMult.invalidate();
const realDiff = diff;
const blackHoleDiff = realDiff;
// Black hole is affected only by time glyphs.
let blackHoleDiff = realDiff * getGameSpeedupFactor([GameSpeedEffect.TIMEGLYPH]);
if (options.gameDiff === undefined) {
const fixedSpeedActive = EternityChallenge(12).isRunning || TimeCompression.isActive;
if (!isAutoReleaseTick && !fixedSpeedActive) {
let speedFactor;
if (options.blackHoleSpeedup === undefined) {
speedFactor = getGameSpeedupFactor();
} else {
// If we're in EC12, time shouldn't speed up at all, but options.blackHoleSpeedup will be 1 so we're fine.
speedFactor = getGameSpeedupFactor([GameSpeedEffect.EC12, GameSpeedEffect.TIMEGLYPH], 1) * options.blackHoleSpeedup;
// This is only called from simulateTime(), apply all effects but override black hole speed
speedFactor = getGameSpeedupFactor(undefined, options.blackHoleSpeedup);
}
if (player.celestials.enslaved.isStoring && !EternityChallenge(12).isRunning) {
// Explicitly disable storing game time in EC12
const timeFactor = speedFactor - 1;
// If you're storing time, time glyphs won't affect black holes
blackHoleDiff = realDiff;
// Note that if gameDiff is specified, we don't store enslaved time.
// Currently gameDiff is only specified in a tick where we're using all the enslaved time,
// but if it starts happening in other cases this will have to be reconsidered.
if (player.celestials.enslaved.isStoring && !fixedSpeedActive) {
// These variables are the actual game speed used and the game speed unaffected by time storage, respectively
const reducedTimeFactor = getGameSpeedupFactor();
const totalTimeFactor = getGameSpeedupFactor([GameSpeedEffect.FIXEDSPEED, GameSpeedEffect.TIMEGLYPH,
GameSpeedEffect.BLACKHOLE, GameSpeedEffect.MOMENTUM]);
const amplification = Ra.has(RA_UNLOCKS.IMPROVED_STORED_TIME)
? RA_UNLOCKS.IMPROVED_STORED_TIME.effect.gameTimeAmplification()
: 1;
const amplifiedTimeFactor = Math.pow(timeFactor, amplification);
const storedTimeWeight = player.celestials.enslaved.storedFraction;
player.celestials.enslaved.stored += diff * ((1 - storedTimeWeight) + amplifiedTimeFactor * storedTimeWeight);
speedFactor = timeFactor * (1 - storedTimeWeight) + storedTimeWeight;
player.celestials.enslaved.stored += diff * Math.pow(totalTimeFactor - reducedTimeFactor, amplification);
speedFactor = reducedTimeFactor;
}
diff *= speedFactor;
} else {
diff = options.gameDiff;
} else if (fixedSpeedActive) {
diff *= getGameSpeedupFactor();
}
player.celestials.ra.peakGamespeed = Math.max(player.celestials.ra.peakGamespeed, getGameSpeedupFactor());
DeltaTimeState.update(realDiff, diff);
updateNormalAndInfinityChallenges(diff);
@ -484,12 +548,13 @@ function gameLoop(diff, options = {}) {
RealityUpgrade(7)
);
infGen = infGen.times(getAdjustedGlyphEffect("infinityinfmult"));
infGen = infGen.times(RA_UNLOCKS.TT_BOOST.effect.infinity());
}
if (RealityUpgrade(11).isBought) {
infGen = infGen.plus(RealityUpgrade(11).effectValue.times(Time.deltaTime));
}
if (EffarigUnlock.eternity.isUnlocked) {
infGen = infGen.plus(gainedInfinities().times(player.eternities).times(Time.deltaTime).times(RA_UNLOCKS.TT_BOOST.effect.infinity()));
infGen = infGen.plus(gainedInfinities().times(player.eternities).times(Time.deltaTime));
}
infGen = infGen.plus(player.partInfinitied);
player.infinitied = player.infinitied.plus(infGen.floor());
@ -497,19 +562,21 @@ function gameLoop(diff, options = {}) {
}
if (RealityUpgrade(14).isBought) {
player.reality.partEternitied += Time.deltaTime * Effects.product(
RealityUpgrade(3),
RealityUpgrade(14)
);
player.eternities += Math.floor(player.reality.partEternitied);
player.reality.partEternitied -= Math.floor(player.reality.partEternitied);
player.reality.partEternitied = player.reality.partEternitied.plus(
new Decimal(Time.deltaTime)
.times(Effects.product(
RealityUpgrade(3),
RealityUpgrade(14)
)
)
);
player.eternities = player.eternities.plus(player.reality.partEternitied.floor());
player.reality.partEternitied = player.reality.partEternitied.sub(player.reality.partEternitied.floor());
}
if (Teresa.has(TERESA_UNLOCKS.EPGEN)) { // Teresa EP gen.
let isPostEc = RealityUpgrade(10).isBought ? player.eternities > 100 : player.eternities > 0
if (isPostEc) {
player.eternityPoints = player.eternityPoints.plus(EPminpeak.times(0.01).times(diff/1000).times(RA_UNLOCKS.TT_BOOST.effect.autoPrestige()))
}
player.eternityPoints = player.eternityPoints.plus(EPminpeak.times(0.01)
.times(diff / 1000).times(RA_UNLOCKS.TT_BOOST.effect.autoPrestige()));
}
const uncountabilityGain = AlchemyResource.uncountability.effectValue * Time.unscaledDeltaTime.totalSeconds;
@ -559,15 +626,11 @@ function gameLoop(diff, options = {}) {
}
}
player.realTimePlayed += realDiff;
if (Perk.autocompleteEC1.isBought && player.reality.autoEC) player.reality.lastAutoEC += realDiff;
player.totalTimePlayed += diff;
player.thisInfinityTime += diff;
player.thisInfinityRealTime += realDiff;
player.thisEternity += diff;
player.thisEternityRealTime += realDiff;
player.thisReality += diff;
player.thisRealityRealTime += realDiff;
EternityChallenge(12).tryFail();
@ -636,17 +699,22 @@ function gameLoop(diff, options = {}) {
if (TimeStudy.dilation.isBought) {
player.dilation.dilatedTime = player.dilation.dilatedTime.plus(getDilationGainPerSecond().times(diff / 1000));
}
// Free galaxies (2x doesn't apply past 1000)
let freeGalaxyMult = Effects.max(
// Free galaxies
const freeGalaxyMult = Effects.max(
1,
DilationUpgrade.doubleGalaxies
);
if (player.dilation.baseFreeGalaxies == undefined)
const freeGalaxyThreshold = Effects.max(1000, CompressionUpgrade.freeGalaxySoftcap);
if (player.dilation.baseFreeGalaxies === undefined)
player.dilation.baseFreeGalaxies = player.dilation.freeGalaxies / freeGalaxyMult;
let thresholdMult = getFreeGalaxyMult();
player.dilation.baseFreeGalaxies = Math.max(player.dilation.baseFreeGalaxies, 1 + Math.floor(Decimal.log(player.dilation.dilatedTime.dividedBy(1000), thresholdMult)));
player.dilation.nextThreshold = new Decimal(1000).times(new Decimal(thresholdMult).pow(player.dilation.baseFreeGalaxies));
player.dilation.freeGalaxies = Math.min(player.dilation.baseFreeGalaxies * freeGalaxyMult, 1000) + Math.max(player.dilation.baseFreeGalaxies * freeGalaxyMult - 1000, 0) / freeGalaxyMult;
const thresholdMult = getFreeGalaxyMult();
player.dilation.baseFreeGalaxies = Math.max(player.dilation.baseFreeGalaxies,
1 + Math.floor(Decimal.log(player.dilation.dilatedTime.dividedBy(1000), thresholdMult)));
player.dilation.nextThreshold = new Decimal(1000).times(new Decimal(thresholdMult)
.pow(player.dilation.baseFreeGalaxies));
player.dilation.freeGalaxies = Math.min(player.dilation.baseFreeGalaxies * freeGalaxyMult, freeGalaxyThreshold) +
Math.max(player.dilation.baseFreeGalaxies * freeGalaxyMult - freeGalaxyThreshold, 0) / freeGalaxyMult;
if (!Teresa.isRunning) {
let ttGain = getAdjustedGlyphEffect("dilationTTgen") * diff / 1000;
@ -679,18 +747,7 @@ function gameLoop(diff, options = {}) {
if (player.dilation.active && Ra.has(RA_UNLOCKS.AUTO_TP)) rewardTP();
// Ra-Enslaved auto-release stored time (once every 5 ticks)
if (Enslaved.isAutoReleasing && options.gameDiff === undefined) {
Enslaved.autoReleaseTick++;
if (Enslaved.autoReleaseTick >= 5) {
Enslaved.autoReleaseTick = 0;
Enslaved.useStoredTime(true);
}
}
V.checkForUnlocks();
Laitela.handleMatterDimensionUnlocks();
matterDimensionLoop(realDiff);
AutomatorBackend.update();
EventHub.dispatch(GameEvent.GAME_TICK_AFTER);
@ -702,10 +759,11 @@ function gameLoop(diff, options = {}) {
// Reducing boilerplate code a bit (runs a specified number of ticks with a specified length and triggers autobuyers after each tick)
function gameLoopWithAutobuyers(seconds, ticks, real) {
for (let ticksDone = 0; ticksDone < ticks; ticksDone++) {
gameLoop(1000 * seconds)
gameLoop(1000 * seconds);
Autobuyers.tick();
if (real)
console.log(ticksDone)
if (real) {
console.log(ticksDone);
}
}
}
@ -714,94 +772,84 @@ function simulateTime(seconds, real, fast) {
// into a higher diff per tick
// warning: do not call this function with real unless you know what you're doing
// calling it with fast will only simulate it with a max of 50 ticks
var ticks = seconds * 20;
var bonusDiff = 0;
var playerStart = deepmerge.all([{}, player]);
autobuyerOnGameLoop = false;
GameUI.notify.showBlackHoles = false;
let ticks = seconds * 20;
autobuyerOnGameLoop = false;
GameUI.notify.showBlackHoles = false;
// Upper-bound the number of ticks (this also applies if the black hole is unlocked)
if (ticks > 1000 && !real && !fast) {
bonusDiff = (ticks - 1000) / 20;
ticks = 1000;
} else if (ticks > 50 && fast) {
bonusDiff = (ticks - 50);
ticks = 50;
}
// Simulation code with black hole
if (BlackHoles.areUnlocked && !BlackHoles.arePaused) {
let remainingRealSeconds = seconds;
for (let numberOfTicksRemaining = ticks; numberOfTicksRemaining > 0; numberOfTicksRemaining--) {
let timeGlyphSpeedup = getGameSpeedupFactor([GameSpeedEffect.TIMEGLYPH]);
// The black hole is affected by time glyphs, but nothing else.
let remainingblackHoleSeconds = remainingRealSeconds * timeGlyphSpeedup;
let [realTickTime, blackHoleSpeedup] = BlackHoles.calculateOfflineTick(remainingblackHoleSeconds, numberOfTicksRemaining, 0.0001);
realTickTime /= timeGlyphSpeedup;
remainingRealSeconds -= realTickTime;
// As in gameLoopWithAutobuyers, we run autoBuyerTick after every game tick
// (it doesn't run in gameLoop).
gameLoop(1000 * realTickTime, {blackHoleSpeedup: blackHoleSpeedup});
Autobuyers.tick();
}
}
// This is pretty much the older simulation code
else {
gameLoopWithAutobuyers((50+bonusDiff) / 1000, ticks, real)
}
// Limit the tick count (this also applies if the black hole is unlocked)
if (ticks > 1000 && !real && !fast) {
ticks = 1000;
} else if (ticks > 50 && fast) {
ticks = 50;
}
const largeDiff = (1000 * seconds) / ticks;
const offlineIncreases = ["While you were away"];
// OoM increase
const oomVarNames = ["antimatter", "infinityPower", "timeShards"];
const oomResourceNames = ["antimatter", "infinity power", "time shards"];
for (let i = 0; i < oomVarNames.length; i++) {
const varName = oomVarNames[i];
const oomIncrease = player[varName].log10() - playerStart[varName].log10();
// Needs an isFinite check in case it's zero before or afterwards
if (player[varName].gt(playerStart[varName]) && Number.isFinite(oomIncrease)) {
offlineIncreases.push(`your ${oomResourceNames[i]} increased by ` +
`${shorten(oomIncrease, 2, 2)} orders of magnitude`);
}
}
// Linear increase
const linearVarNames = ["infinitied", "eternities"];
const linearResourceNames = ["infinities", "eternities"];
const prestigeReset = ["eternitied", "realitied"];
for (let i = 0; i < linearVarNames.length; i++) {
const varName = linearVarNames[i];
const linearIncrease = Decimal.sub(player[varName], playerStart[varName]);
if (linearIncrease.lessThan(0)) {
// This happens when a prestige autobuyer triggers offline and resets the value
offlineIncreases.push(`you ${prestigeReset[i]} and then generated ` +
`${shorten(player[varName], 2, 0)} more ${linearResourceNames[i]}`);
} else if (!Decimal.eq(player[varName], playerStart[varName])) {
offlineIncreases.push(`you generated ${shorten(linearIncrease, 2, 0)} ${linearResourceNames[i]}`);
}
}
// Black hole activations
for (let i = 0; i < player.blackHole.length; i++) {
const currentActivations = player.blackHole[i].activations;
const oldActivations = playerStart.blackHole[i].activations;
const activationsDiff = currentActivations - oldActivations;
const pluralSuffix = activationsDiff === 1 ? " time" : " times";
if (activationsDiff > 0 && !BlackHole(i + 1).isPermanent) {
offlineIncreases.push(`Black hole ${i + 1} activated ${activationsDiff} ${pluralSuffix}`);
}
}
let popupString = `${offlineIncreases.join(", <br>")}.`;
if (popupString === "While you were away.") {
popupString += ".. Nothing happened.";
SecretAchievement(36).unlock();
// Simulation code with black hole (doesn't use diff since it splits up based on real time instead)
const playerStart = deepmerge.all([{}, player]);
if (BlackHoles.areUnlocked && !BlackHoles.arePaused) {
let remainingRealSeconds = seconds;
for (let numberOfTicksRemaining = ticks; numberOfTicksRemaining > 0; numberOfTicksRemaining--) {
const [realTickTime, blackHoleSpeedup] = BlackHoles.calculateOfflineTick(remainingRealSeconds,
numberOfTicksRemaining, 0.0001);
remainingRealSeconds -= realTickTime;
gameLoop(1000 * realTickTime, { blackHoleSpeedup: blackHoleSpeedup });
Autobuyers.tick();
}
} else {
gameLoopWithAutobuyers(largeDiff / 1000, ticks, real);
}
Modal.message.show(popupString);
autobuyerOnGameLoop = true;
GameUI.notify.showBlackHoles = true;
const offlineIncreases = ["While you were away"];
// OoM increase
const oomVarNames = ["antimatter", "infinityPower", "timeShards"];
const oomResourceNames = ["antimatter", "infinity power", "time shards"];
for (let i = 0; i < oomVarNames.length; i++) {
const varName = oomVarNames[i];
const oomIncrease = player[varName].log10() - playerStart[varName].log10();
// Needs an isFinite check in case it's zero before or afterwards
if (player[varName].gt(playerStart[varName]) && Number.isFinite(oomIncrease)) {
offlineIncreases.push(`your ${oomResourceNames[i]} increased by ` +
`${shorten(oomIncrease, 2, 2)} orders of magnitude`);
}
}
// Linear increase
const linearVarNames = ["infinitied", "eternities"];
const linearResourceNames = ["infinities", "eternities"];
const prestigeReset = ["eternitied", "realitied"];
for (let i = 0; i < linearVarNames.length; i++) {
const varName = linearVarNames[i];
const linearIncrease = Decimal.sub(player[varName], playerStart[varName]);
if (linearIncrease.lessThan(0)) {
// This happens when a prestige autobuyer triggers offline and resets the value
offlineIncreases.push(`you ${prestigeReset[i]} and then generated ` +
`${shorten(player[varName], 2, 0)} more ${linearResourceNames[i]}`);
} else if (!Decimal.eq(player[varName], playerStart[varName])) {
offlineIncreases.push(`you generated ${shorten(linearIncrease, 2, 0)} ${linearResourceNames[i]}`);
}
}
// Black hole activations
for (let i = 0; i < player.blackHole.length; i++) {
const currentActivations = player.blackHole[i].activations;
const oldActivations = playerStart.blackHole[i].activations;
const activationsDiff = currentActivations - oldActivations;
const pluralSuffix = activationsDiff === 1 ? " time" : " times";
if (activationsDiff > 0 && !BlackHole(i + 1).isPermanent) {
offlineIncreases.push(`Black hole ${i + 1} activated ${activationsDiff} ${pluralSuffix}`);
}
}
let popupString = `${offlineIncreases.join(", <br>")}.`;
if (popupString === "While you were away.") {
popupString += ".. Nothing happened.";
SecretAchievement(36).unlock();
}
Modal.message.show(popupString);
autobuyerOnGameLoop = true;
GameUI.notify.showBlackHoles = true;
}
function updateChart(first) {
if (first !== true && (player.infinitied.gte(1) || player.eternities >= 1) && player.options.chart.on === true) {
if (first !== true && (player.infinitied.gte(1) || player.eternities.gte(1)) && player.options.chart.on === true) {
if (NormalChallenge(3).isRunning) {
addChartData(getDimensionProductionPerSecond(1).times(player.chall3Pow));
} else {
@ -827,8 +875,8 @@ function autoBuyDilationUpgrades() {
}
function autoBuyInfDims() {
if (player.eternities > 10 && !EternityChallenge(8).isRunning) {
for (var i = 1; i < player.eternities - 9 && i < 9; i++) {
if (player.eternities.gt(10) && !EternityChallenge(8).isRunning) {
for (let i = 1; i <= player.eternities.sub(10).clampMax(8).toNumber(); i++) {
if (player.infDimBuyers[i - 1]) {
buyMaxInfDims(i)
buyManyInfinityDimension(i)

View File

@ -49,72 +49,53 @@ function showspoilers() {
}
function updateSpoilers() {
var displayed = 0;
if (spoilers === 0) {
for (let i = 1; i < 25; i++) {
displayed = 0;
if (i === 5 && (player.resets >= 4 || player.infinitied.gte(1) || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
let displayed = 0;
if (i < 5) {
displayed = 1 - displayed;
}
if (i === 7 && (player.galaxies >= 1 || player.infinitied.gte(1) || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if (i === 5 && (DimBoost.totalBoosts >= 4 || player.infinitied.gte(1) || PlayerProgress.eternityUnlocked())) {
displayed = 1 - displayed;
}
if (i === 8 && (player.infinitied.gte(1) || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if (i === 7 && (player.galaxies >= 1 || player.infinitied.gte(1) || PlayerProgress.eternityUnlocked())) {
displayed = 1 - displayed;
}
if (i === 9 && (player.infinitied.gte(1) || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if ((i >= 8 && i <= 10) && (player.infinitied.gte(1) || PlayerProgress.eternityUnlocked())) {
displayed = 1 - displayed;
}
if (i === 10 && (player.infinitied.gte(1) || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if (i === 11 && (player.auto.bigCrunch.interval > 100 || PlayerProgress.eternityUnlocked())) {
displayed = 1 - displayed;
}
if (i === 11 && (player.auto.bigCrunch.interval>100 || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if (i === 12 && (player.infDimensionsUnlocked[0] || PlayerProgress.eternityUnlocked())) {
displayed = 1 - displayed;
}
if (i === 12 && (player.infDimensionsUnlocked[0] == true || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if (i === 13 && (player.postChallUnlocked >= 5 || PlayerProgress.eternityUnlocked())) {
displayed = 1 - displayed;
}
if (i === 13 && (player.postChallUnlocked >= 5 || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if ((i >= 14 && i <= 17) && (player.replicanti.unl || PlayerProgress.eternityUnlocked())) {
displayed = 1 - displayed;
}
if (i === 14 && (player.replicanti.unl || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
}
if (i === 15 && (player.replicanti.unl || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
}
if (i === 16 && (player.replicanti.unl || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
}
if (i === 17 && (player.replicanti.unl || player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
}
if (i === 18 && (player.eternities >= 1)) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if (i === 18 && (PlayerProgress.eternityUnlocked())) {
displayed = 1 - displayed;
}
if (i === 19 && player.eternityChalls.eterc11 === 5 || player.eternityChalls.eterc12 === 5) {
(displayed === 0) ? displayed = 1 : displayed = 0;
displayed = 1 - displayed;
}
if (i === 20 && player.dilation.studies.length === 5) {
(displayed === 0) ? displayed = 1 : displayed = 0;
displayed = 1 - displayed;
}
if (i === 21 && player.realities >= 1) {
(displayed === 0) ? displayed = 1 : displayed = 0;
}
if (i === 22 && player.realities >= 1) {
(displayed === 0) ? displayed = 1 : displayed = 0;
if ((i === 21 || i === 22) && player.realities >= 1) {
displayed = 1 - displayed;
}
if (i === 23 && player.realities >= 4) {
(displayed === 0) ? displayed = 1 : displayed = 0;
displayed = 1 - displayed;
}
if (i === 24 && player.reality.realityMachines >= 50 || player.reality.blackHole[0].unlocked) {
(displayed === 0) ? displayed = 1 : displayed = 0;
displayed = 1 - displayed;
}
if (i === 25 && RealityUpgrades.allBought) {
(displayed === 0) ? displayed = 1 : displayed = 0;
}
if (i < 5 || i === 7) {
(displayed === 0) ? displayed = 1 : displayed = 0;
displayed = 1 - displayed;
}
if (displayed === 1) {

View File

@ -1602,16 +1602,6 @@ screen and (max-width: 480px) {
font-size: 1rem;
}
.o-primary-btn--discharge-active {
background-color: #5ac467;
}
.o-primary-btn--discharge-active:hover {
background-color: #5ac467;
color: black;
cursor: default;
}
/*#endregion modifiers*/
/*#region themes*/
@ -4484,6 +4474,65 @@ screen and (max-width: 480px) {
/*#endregion o-dilation-btn*/
/*#region o-compression-btn*/
.o-compression-btn {
color: #5151ec;
background-color: black;
font-weight: bold;
font-size: 1.12rem;
border: .2rem solid #5151ec;
width: 19rem;
height: 9rem;
transition-duration: 0.2s;
cursor: pointer;
border-radius: .4rem;
font-family: Typewriter, serif;
animation: a-compression-btn-glow 5s infinite;
animation-timing-function: linear;
}
.o-compression-btn:hover {
background-color: white;
}
.t-dark .o-compression-btn {
color: #5151ec;
background-color: black;
}
.t-dark .o-compression-btn:hover,
.t-s6 .o-compression-btn:hover {
color: #5151ec;
background-color: white;
}
.t-s4 .o-compression-btn {
animation: a-compression-btn-glow 0.5s infinite;
}
.t-metro .o-compression-btn,
.t-dark-metro .o-compression-btn,
.t-inverted-metro .o-compression-btn,
.t-s8 .o-compression-btn {
border-radius: 0;
border-width: 0.1rem;
}
@keyframes a-compression-btn-glow {
0% { box-shadow: inset 0 0 2rem 0}
13% { box-shadow: inset 0 0 2rem 0.15rem}
25% { box-shadow: inset 0 0 2rem 0.4rem}
38% { box-shadow: inset 0 0 2rem 0.65rem}
50% { box-shadow: inset 0 0 2rem 0.8rem}
63% { box-shadow: inset 0 0 2rem 0.65rem}
75% { box-shadow: inset 0 0 2rem 0.4rem}
88% { box-shadow: inset 0 0 2rem 0.15rem}
100% { box-shadow: inset 0 0 2rem 0}
}
/*#endregion o-compression-btn*/
/*#region o-dilation-upgrade*/
.o-dilation-upgrade {
@ -4617,6 +4666,8 @@ screen and (max-width: 480px) {
/*#endregion o-dilation-upgrade*/
.c-tachyon-particle-container {
position: fixed;
top: 0;
@ -6050,6 +6101,140 @@ kbd {
background: #00e6ff
}
/*#region o-compression-upgrade*/
.o-compression-upgrade {
background: black;
font-weight: bold;
font-size: 1.05rem;
border: .1rem solid;
width: 20rem;
height: 12rem;
transition-duration: 0.2s;
border-radius: .4rem;
font-family: Typewriter, serif;
}
.o-compression-upgrade--available {
color: #5151ec;
border-color: #5151ec;
animation: a-compression-btn-glow 5s infinite;
animation-timing-function: linear;
cursor: pointer;
}
.o-compression-upgrade--available:hover {
background-color: white;
}
.o-compression-upgrade--inactive {
color: black;
background-color: #595779;
border-color: black;
animation: a-compression-btn-glow 5s infinite;
animation-timing-function: linear;
}
.o-compression-upgrade--active {
color: black;
background-color: #5151ec;
border-color: black;
}
.o-compression-upgrade--unavailable {
color: #181818;
background-color: #5f5f5f;
border-color: #3e8a0f;
}
.o-compression-upgrade--unavailable:hover {
color: #1d1d1d;
background-color: #660000;
}
.o-compression-upgrade__description--small-text {
font-size: 0.95rem;
}
.t-metro .o-compression-upgrade,
.t-dark-metro .o-compression-upgrade,
.t-inverted-metro .o-compression-upgrade,
.t-s8 .o-compression-upgrade {
border-radius: 0;
}
.t-metro .o-compression-upgrade--unavailable,
.t-dark-metro .o-compression-upgrade--unavailable,
.t-inverted-metro .o-compression-upgrade--unavailable,
.t-s1 .o-compression-upgrade--unavailable,
.t-s8 .o-compression-upgrade--unavailable {
color: black;
background-color: #9e9e9e;
box-shadow: .1rem .1rem .1rem 0 black;
border: none;
}
.t-metro .o-compression-upgrade--unavailable:hover,
.t-dark-metro .o-compression-upgrade--unavailable:hover,
.t-inverted-metro .o-compression-upgrade--unavailable:hover,
.t-s8 .o-compression-upgrade--unavailable:hover {
background-color: #ef5350;
}
.t-s1 .o-compression-upgrade--unavailable:hover {
background-color: #d72621;
}
.t-dark .o-compression-upgrade {
background-color: black;
}
.t-dark .o-compression-upgrade--available:hover,
.t-s6 .o-compression-upgrade--available:hover {
color: #64dd17;
background-color: white;
}
.t-dark .o-compression-upgrade--rebuyable.o-compression-upgrade--available:hover,
.t-s6 .o-compression-upgrade--rebuyable.o-compression-upgrade--available:hover {
color: #64ddad;
}
.t-dark .o-compression-upgrade--inactive,
.t-s6 .o-compression-upgrade--inactive {
background-color: #1d2049;
}
.t-dark .o-compression-upgrade--active,
.t-s6 .o-compression-upgrade--active {
background-color: #1100ff;
}
.t-s6 .o-compression-upgrade--unavailable {
color: gray;
}
.t-dark .o-compression-upgrade--unavailable {
color: black;
background-color: #23292a;
}
.t-dark .o-compression-upgrade--unavailable:hover,
.t-s6 .o-compression-upgrade--unavailable:hover {
color: black;
border-color: #b84b5f;
background-color: #b84b5f;
}
.t-s4 .o-compression-upgrade--available {
animation: a-compression-btn-glow 0.5s infinite;
}
.t-s6 .o-compression-upgrade--unavailable {
background-color: black;
}
/*#endregion o-compression-upgrade*/
/* #endregion ra tab*/