Merge branch 'master' into Steam-Webpack

# Conflicts:
#	javascripts/core/app/options.js
#	javascripts/core/secret-formula/shop-purchases.js
#	src/components/tabs/shop/ShopTab.vue
This commit is contained in:
Andrei Andreev 2022-12-20 00:49:08 +01:00
commit 4a024c3ae9
25 changed files with 201 additions and 102 deletions

View File

@ -9,7 +9,7 @@ export class GameOptions {
static toggleNews() {
player.options.news.enabled = !player.options.news.enabled;
ui.view.news = player.options.news.enabled;
GameStorage.save(true);
GameStorage.save();
}
static toggleUI() {
@ -19,7 +19,7 @@ export class GameOptions {
// So the classes on body need to be updated
Themes.find(Theme.currentName()).set();
SteamFunctions.UIZoom()
GameStorage.save(true);
GameStorage.save();
}
static cloudSave() {

View File

@ -47,6 +47,11 @@ Autobuyer.bigCrunch = new class BigCrunchAutobuyerState extends UpgradeableAutob
return this.data.amount;
}
// This is unused mechanically, but should be zero to suppress the "Current bulk:" text
get bulk() {
return 0;
}
set amount(value) {
this.data.amount = value;
}

View File

@ -56,7 +56,7 @@ GameDatabase.catchupResources = [
features which persist through Infinity resets.`
},
{
name: "Challenges",
name: "Normal Challenges",
id: 7,
openH2pEntry: "Normal Challenges",
requiredStage: PROGRESS_STAGE.EARLY_INFINITY,
@ -104,7 +104,7 @@ GameDatabase.catchupResources = [
id: 13,
openH2pEntry: "Eternity",
requiredStage: PROGRESS_STAGE.EARLY_ETERNITY,
description: `Infinity Points are the primary resource after completing your first Eternity, and scale based on your
description: `Eternity Points are the primary resource after completing your first Eternity, and scale based on your
Infinity Points at the time you complete the Eternity.`
},
{

View File

@ -28,7 +28,7 @@ GameDatabase.changelog = [
<li>Added a How to Play modal with much more detail compared to the old How to Play.</li>
<li>Added 5 new rows of achievements.</li>
<li>Added a Multiplier Breakdown subtab.</li>
<li>Added more Nicholas Cage.</li>
<li>Added more Nicolas Cage.</li>
<li>Cloud saving is now available to everyone. This needs your Google account.</li>
<li>Shop tab is now available to everyone.</li>
<li>Redesigned overall UI styling.</li>
@ -102,6 +102,8 @@ Wording and Layout Changes:
<li>Added colors to the Crunch/Eternity buttons when you have more than e50 of IP/EP; the color shows if you gain less
(red), around same (white), or more (green) IP/EP than you currently have.</li>
<li>Moved study 33 to right side.</li>
<li>Changed "Normal Dimensions" to "Antimatter Dimensions".</li>
<li>Changed "Challenges" to "Normal Challenges".</li>
<li>Fixed some tpyos.</li>
</ul>
<br>
@ -134,6 +136,7 @@ Balance Changes:
<li>The 20-eternities milestone was moved to 8-eternities.</li>
<li>Increased cost scaling for Time Dimensions after 1e6000.</li>
<li>TS 83 has been hard capped.</li>
<li>EC10 reward for less than 5 completions has been nerfed (reward at 5 completions is the same).</li>
<li>Lowered the Dilation unlock requirement from 13000 to 12900 total TT.</li>
<li>TP gain amount in Dilation is now calculated based on the highest AM reached.</li>
<li>Purchasing the study to unlock Dilation now requires a 23rd row study purchase.</li>
@ -192,6 +195,7 @@ Removed features:
Bugfixes:
<ul>
<li>ID and replicanti autobuyer buttons are now hidden in EC8.</li>
<li>Fixed next Sacrifice multiplier not properly displaying NC8's effect.</li>
<li>Fixed a bug where IC5's cost increment was applied 2 times.</li>
<li>Fixed a bug where inverted themes were broken.</li>
<li>Fixed a bug where resetting the game unlocks a secret achievement.</li>

View File

@ -32,7 +32,9 @@ GameDatabase.eternity.upgrades = {
id: 3,
cost: 5e4,
description: "Infinity Dimensions multiplier based on sum of Infinity Challenge times",
effect: () => DC.D2.pow(30 / Time.infinityChallengeSum.totalSeconds),
// The cap limits this at a lower value, but we also need an explicit cap here because very old versions have
// allowed EC12 to make all the challenge records sum to zero (causing a division by zero here)
effect: () => DC.D2.pow(30 / Math.clampMin(Time.infinityChallengeSum.totalSeconds, 0.1)),
cap: DC.D2P30D0_61,
formatEffect: value => formatX(value, 2, 1)
},

View File

@ -19,10 +19,13 @@ GameDatabase.h2p = {
{
name: "Your savefile",
info: () => `
Your game's save data is stored on your computer's browser data, which means that clearing your browser's cache and
cookies will also delete your save file. Similarly, if you are playing in a private or incognito window, your save
Your game's save data is stored on your computer's browser data if you are playing on a web browser, or in your Steam
installation folder if you are playing on Steam. This means that clearing your browser's cache or cookies, or fully
uninstalling the game from Steam will also delete your save file.
Similarly, if you are playing in a private or incognito window, your save
won't be there the next time you open up your browser. The saves are browser-specific as well, so for example
if you play the game on Chrome, you won't find your save on Firefox.
if you play the game on Chrome, you won't find your save on Firefox. Lastly, any saves you have on the web version and
the Steam version will also be completely independent from each other.
<br>
<br>
You can transfer your save between places by using the export function, which will copy a <i>very</i> long string of
@ -41,7 +44,7 @@ and export from text files as well.
<br>
You can use the "Choose save" button to pick between three separate saves on your browser. These saves are, for most
intents and purposes, completely separate from each other. Importing and exporting will only affect the current save
slot. <b>The only exception is clearing your broswer data, in which case all three saves will be reset.</b>
slot. <b>The only exception is clearing your browser or Steam data, in which case all three saves will be reset.</b>
<br>
<br>
The game automatically saves periodically, by default once every ${formatInt(30)} seconds, and it will notify you in
@ -52,7 +55,7 @@ length of the autosave interval is adjustable.
<br>
You can also connect a Google Account to the game, allowing you to save your progress online. This allows you to play
with the same save on any device which is also logged into the same account. Cloud saving is only compatable with other
saves on the web version of the game; saves from the Android app of the game won't be automatically linked via
saves on the web or Steam versions of the game; saves from the Android app of the game won't be automatically linked via
Cloud saving. Saving and loading from the Cloud will
automatically overwrite the other save unless the other save is either older or has noticeably more progression, in
which case a modal will appear which asks you which save you want to keep.
@ -421,7 +424,9 @@ Antimatter Dimension Autobuyers and the Tickspeed Upgrade Autobuyer can be unloc
but most other autobuyers require upgrades to be purchased or challenges to be beaten.
<br>
<br>
Most Autobuyers have similar stats:
Most Autobuyers have similar attributes:
<br>
<br>
<b>Autobuyer Interval:</b> The cooldown period before the autobuyer attempts to make another purchase.
Antimatter Dimension Autobuyers and the Tickspeed Upgrade Autobuyer require their respective challenges to be beaten
before their interval can be upgraded.
@ -455,6 +460,11 @@ If you reach your specified Galaxy threshold, the autobuyer will ignore your max
<b>Sacrifice Autobuyer:</b> This autobuyer starts with a maxed interval, potentially triggering every tick.
<br>
<br>
<b>Dynamic Amount:</b> Upgraded prestige autobuyers have a mode that triggers a prestige when a specified threshold
is passed. Turning on "Dynamic Amount" will allow this threshold value to be automatically increased when unlocking
certain upgrades or achievements which apply a multiplier to this value.
<br>
<br>
<b>Pause/Resume Autobuyers:</b> This button will pause or resume autobuyers which are turned on.
It does not change individual autobuyer settings. Think of it like a master switch.
<br>
@ -466,7 +476,7 @@ It does not change individual autobuyer settings. Think of it like a master swit
Additionally, holding <b>Alt</b> when pressing a hotkey associated with an upgrade, dimension, or prestige will
toggle the associated autobuyer.
`,
isUnlocked: () => PlayerProgress.infinityUnlocked(),
isUnlocked: () => true,
tags: ["infinity", "automation", "challenges", "rewards", "interval", "earlygame"],
tab: "automation/autobuyers"
}, {

View File

@ -138,7 +138,8 @@ GameDatabase.news = [
},
{
id: "a29",
text: "If you are not playing on Kongregate or ivark.github.io, the site is bootleg."
text: `If you are not playing on Kongregate, Steam, or https://ivark.github.io/AntimatterDimensions/,
the site is bootleg.`
},
{
id: "a30",
@ -436,7 +437,7 @@ GameDatabase.news = [
},
{
name: "Synergism",
link: "https://pseudonian.github.io/SynergismOfficial/"
link: "https://pseudo-corp.github.io/SynergismOfficial/"
},
{
name: "Universal Paperclips",

View File

@ -8,30 +8,24 @@ GameDatabase.shopPurchases = {
description: "Double all your Antimatter Dimension multipliers. Forever.",
multiplier: purchases => Math.pow(2, purchases)
},
allDimPurchases: {
key: "allDimPurchases",
cost: 60,
description: () => {
const dims = ["Antimatter"];
if (InfinityDimension(1).isUnlocked || PlayerProgress.eternityUnlocked()) dims.push("Infinity");
if (PlayerProgress.eternityUnlocked()) dims.push("Time");
return `Double ALL Dimension multipliers (${makeEnumeration(dims)}; multiplicative until 32x). Forever.`;
},
multiplier: purchases => (purchases > 4 ? 32 + (purchases - 5) * 2 : Math.pow(2, purchases)),
},
IPPurchases: {
key: "IPPurchases",
cost: 40,
description: "Double your Infinity Point gain from all sources. (additive)",
multiplier: purchases => (purchases === 0 ? 1 : 2 * purchases),
},
EPPurchases: {
key: "EPPurchases",
cost: 50,
description: "Triple your Eternity Point gain from all sources. (additive)",
multiplier: purchases => (purchases === 0 ? 1 : 3 * purchases),
},
RMPurchases: {
key: "RMPurchases",
cost: 60,
description: "Increase your Reality Machine gain by 100%. (additive)",
multiplier: purchases => purchases + 1,
formatEffect: x => formatX(x, 2),
},
allDimPurchases: {
key: "allDimPurchases",
cost: 60,
description: "Double ALL Dimension multipliers (Antimatter, Infinity, Time) (multiplicative until 32x). Forever.",
multiplier: purchases => (purchases > 4 ? 32 + (purchases - 5) * 2 : Math.pow(2, purchases)),
isUnlocked: () => PlayerProgress.infinityUnlocked(),
lockText: "Infinity",
},
replicantiPurchases: {
key: "replicantiPurchases",
@ -39,6 +33,16 @@ GameDatabase.shopPurchases = {
description: "Increase your Replicanti gain by 50%. (additive)",
multiplier: purchases => (purchases === 0 ? 1 : 1 + 0.5 * purchases),
formatEffect: x => formatX(x, 2, 1),
isUnlocked: () => Replicanti.areUnlocked || PlayerProgress.eternityUnlocked(),
lockText: "Replicanti",
},
EPPurchases: {
key: "EPPurchases",
cost: 50,
description: "Triple your Eternity Point gain from all sources. (additive)",
multiplier: purchases => (purchases === 0 ? 1 : 3 * purchases),
isUnlocked: () => PlayerProgress.eternityUnlocked(),
lockText: "Eternity",
},
dilatedTimePurchases: {
key: "dilatedTimePurchases",
@ -46,24 +50,17 @@ GameDatabase.shopPurchases = {
description: "Increase your Dilated Time gain by 50%. (additive)",
multiplier: purchases => (purchases === 0 ? 1 : 1 + 0.5 * purchases),
formatEffect: x => formatX(x, 2, 1),
isUnlocked: () => PlayerProgress.dilationUnlocked() || PlayerProgress.realityUnlocked(),
lockText: "Dilation",
},
smallTimeSkip: {
key: "smallTimeSkip",
cost: 10,
description: "Get 6 hours worth of offline production. (Autobuyers don't work at full speed)",
instantPurchase: true,
onPurchase: () => {
shop.purchaseTimeSkip();
}
},
bigTimeSkip: {
key: "bigTimeSkip",
cost: 20,
description: "Get 24 hours worth of offline production. (Autobuyers don't work at full speed)",
instantPurchase: true,
onPurchase: () => {
shop.purchaseLongerTimeSkip();
}
RMPurchases: {
key: "RMPurchases",
cost: 60,
description: "Increase your Reality Machine gain by 100%. (additive)",
multiplier: purchases => purchases + 1,
formatEffect: x => formatX(x, 2),
isUnlocked: () => PlayerProgress.realityUnlocked(),
lockText: "Reality",
},
singleCosmeticSet: {
key: "singleCosmeticSet",
@ -77,7 +74,9 @@ GameDatabase.shopPurchases = {
10000);
GlyphAppearanceHandler.chosenFromModal = null;
GlyphAppearanceHandler.applyNotification();
}
},
isUnlocked: () => PlayerProgress.realityUnlocked(),
lockText: "Reality",
},/*
allCosmeticSets: {
key: "allCosmeticSets",
@ -97,6 +96,26 @@ GameDatabase.shopPurchases = {
// The actual unlocks are handled in the ShopPurchaseData object, so we just show notifications here
GameUI.notify.info(`You have unlocked all sets for Glyph cosmetics!`, 15000);
GlyphAppearanceHandler.applyNotification();
},
isUnlocked: () => PlayerProgress.realityUnlocked(),
lockText: "Reality",
},
smallTimeSkip: {
key: "smallTimeSkip",
cost: 10,
description: "Get 6 hours worth of offline production. (Autobuyers don't work at full speed)",
instantPurchase: true,
onPurchase: () => {
shop.purchaseTimeSkip();
}
},
bigTimeSkip: {
key: "bigTimeSkip",
cost: 20,
description: "Get 24 hours worth of offline production. (Autobuyers don't work at full speed)",
instantPurchase: true,
onPurchase: () => {
shop.purchaseLongerTimeSkip();
}
},*/
};

View File

@ -13,6 +13,10 @@ GameDatabase.tabNotifications = {
{
parent: "challenges",
tab: "normal"
},
{
parent: "statistics",
tab: "multipliers"
}
],
condition: () => !PlayerProgress.realityUnlocked() &&

View File

@ -115,7 +115,8 @@ class ShopPurchaseState extends RebuyableMechanicState {
}
get description() {
return this.config.description;
const desc = this.config.description;
return typeof desc === "function" ? desc() : desc;
}
get cost() {
@ -131,6 +132,14 @@ class ShopPurchaseState extends RebuyableMechanicState {
ShopPurchaseData[this.config.key] = value;
}
isUnlocked() {
return player.records.fullGameCompletions > 0 || (this.config.isUnlocked?.() ?? true);
}
get lockText() {
return this.config.lockText;
}
get shouldDisplayMult() {
return Boolean(this.config.multiplier);
}

View File

@ -642,6 +642,11 @@ GameStorage.migrations = {
},
convertNews(player) {
if (player.newsArray === undefined) {
player.newsArray = [];
} else {
player.newsArray = player.newsArray.map(x => (typeof(x) === "number" ? `a${x}` : x));
}
const oldNewsArray = new Set(player.newsArray);
player.news = {};
player.news.seen = {};

View File

@ -153,13 +153,9 @@ export const GameStorage = {
${invalidProps.join(", ")}`;
},
save(silent = false, manual = false) {
save(silent = true, manual = false) {
if (GameEnd.endState >= END_STATE_MARKERS.SAVE_DISABLED && !GameEnd.removeAdditionalEnd) return;
if (GameEnd.endState >= END_STATE_MARKERS.INTERACTIVITY_DISABLED) {
// Fade-out starts at 2.5
GameUI.notify.error("There is nothing left to save");
return;
}
if (GameEnd.endState >= END_STATE_MARKERS.INTERACTIVITY_DISABLED) return;
if (GlyphSelection.active || ui.$viewModel.modal.progressBar !== undefined) return;
this.lastSaveTime = Date.now();
GameIntervals.save.restart();

View File

@ -287,7 +287,7 @@ export function gainedInfinities() {
}
export function updateRefresh() {
GameStorage.save(true);
GameStorage.save();
location.reload(true);
}

View File

@ -9,6 +9,9 @@
:root {
--sidebar-width: 12.8rem;
--color-antimatter--bg: #df50504d;
--color-infinity--bg: #b67f334d;
--color-eternity--bg: #b341e04d;
}
:root .t-normal,
@ -721,14 +724,16 @@ body.t-s9 {
align-content: center;
}
.c-dimension-row:nth-child(even) {
background-color: rgba(223, 80, 80, 30%);
.l-dimension-row-antimatter-dim:nth-child(even) {
background-color: var(--color-antimatter--bg);
}
.t-metro .c-dimension-row:nth-child(even),
.t-inverted-metro .c-dimension-row:nth-child(even),
.t-s8 .c-dimension-row:nth-child(even) {
background-color: rgba(33, 150, 243, 30%);
.l-dimension-row-infinity-dim:nth-child(even) {
background-color: var(--color-infinity--bg);
}
.l-dimension-row-time-dim:nth-child(even) {
background-color: var(--color-eternity--bg);
}
.c-infinity-dim-description__accent {

View File

@ -1805,7 +1805,7 @@ br {
}
.t-dark .o-primary-btn--disabled {
background-color: #37474f;
background-color: #752626;
}
.t-dark .o-primary-btn--disabled:hover {
@ -1829,7 +1829,7 @@ br {
}
.t-dark-metro .o-primary-btn--disabled {
background-color: #37474f;
background-color: #752626;
}
.t-dark-metro .o-primary-btn--disabled:hover {
@ -8888,7 +8888,12 @@ kbd {
.c-reality-upgrade-btn--possible {
color: black;
background-color: #8b8529;
background: repeating-linear-gradient(
-45deg,
#979729,
#979729 3rem,
#777722 3rem,
#777722 6rem);
cursor: default;
}
@ -8898,7 +8903,15 @@ kbd {
}
.c-reality-upgrade-btn--locked {
background-color: #a53939;
color: black;
background: #954040;
background-image:
linear-gradient(45deg, #a55252 25%, transparent 25%),
linear-gradient(135deg, #a55252 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #a55252 75%),
linear-gradient(135deg, transparent 75%, #a55252 75%);
background-size: 4rem 4rem;
background-position: 0 0, 2rem 0, 2rem -2rem, 0 2rem;
cursor: default;
}

View File

@ -35,7 +35,7 @@ export default {
: "";
},
showPercentage() {
return player.options.showHintText.showPercentage;
return player.options.showHintText.showPercentage || ui.view.shiftDown;
},
},

View File

@ -7,7 +7,8 @@ export default {
cloudSaveEnabled: false,
lastLocalSave: 0,
lastCloudSave: 0,
showTimeSinceSave: false
showTimeSinceSave: false,
saveDisabled: false,
};
},
computed: {
@ -26,9 +27,10 @@ export default {
this.lastLocalSave = GameStorage.lastSaveTime;
this.lastCloudSave = GameStorage.lastCloudSave;
this.showTimeSinceSave = player.options.showTimeSinceSave;
this.saveDisabled = GameEnd.endState >= END_STATE_MARKERS.INTERACTIVITY_DISABLED;
},
save() {
GameStorage.save();
GameStorage.save(false);
}
}
};
@ -40,7 +42,8 @@ export default {
class="o-save-timer"
@click="save"
>
Time since last save: {{ timeString }}
<b v-if="saveDisabled">There is nothing left to save.</b>
<span v-else>Time since last save: {{ timeString }}</span>
</div>
</template>

View File

@ -133,7 +133,7 @@ export default {
<template>
<div
v-show="showRow"
class="c-dimension-row c-antimatter-dim-row l-dimension-single-row"
class="c-dimension-row l-dimension-row-antimatter-dim c-antimatter-dim-row l-dimension-single-row"
:class="{ 'c-dim-row--not-reached': !isUnlocked }"
>
<GenericDimensionRowText

View File

@ -116,7 +116,7 @@ export default {
<template>
<div
v-show="showRow"
class="c-dimension-row l-dimension-single-row"
class="c-dimension-row l-dimension-row-infinity-dim l-dimension-single-row"
:class="{ 'c-dim-row--not-reached': !isUnlocked && !canUnlock }"
>
<GenericDimensionRowText

View File

@ -29,7 +29,7 @@ export default {
<br>
These requirements, once completed, permanently unlock the ability to purchase the upgrades at any point.
<br>
Red upgrades are impossible to unlock this Reality, while yellow upgrades are still possible.
Checkered upgrades are impossible to unlock this Reality, while striped upgrades are still possible.
<br>
Locked upgrades show their requirement and effect by default; unlocked ones show
their effect, current bonus, and cost.

View File

@ -53,8 +53,7 @@ export default {
purchaseButtonObject() {
return {
"o-shop-button-button": true,
"o-shop-button-button--disabled": !this.canAfford ||
(this.isSingleCosmeticSet && !this.hasChosen)
"o-shop-button-button--disabled": !this.canAfford || (this.isSingleCosmeticSet && !this.hasChosen)
};
}
},
@ -74,27 +73,37 @@ export default {
Currently {{ purchase.formatEffect(currentMult) }}, next: {{ purchase.formatEffect(nextMult) }}
</span>
</div>
<div v-if="isSingleCosmeticSet && lockedCount">
<br>
<button
class="o-shop-button-button"
@click="openSelectionModal"
<div>
<div v-if="isSingleCosmeticSet">
<div
v-if="allSetsUnlocked"
class="o-shop-button-multiplier"
>
All Sets unlocked!
</div>
<div v-else>
<button
class="o-shop-button-button"
@click="openSelectionModal"
>
Choose Set
</button>
Chosen Set: {{ chosenSet }}
</div>
</div>
<div
v-if="isAllCosmeticSets"
class="o-shop-button-multiplier"
>
Choose Set
</button>
Chosen Set: {{ chosenSet }}
</div>
<div v-if="isAllCosmeticSets && lockedCount">
Will unlock {{ quantify("set", lockedCount) }}
</div>
<div
v-if="allSetsUnlocked"
class="o-shop-button-multiplier"
>
All Sets unlocked!
<div v-if="allSetsUnlocked">
All Sets unlocked!
</div>
<div v-else>
Will unlock {{ quantify("set", lockedCount) }}
</div>
</div>
</div>
<button
v-else
:class="purchaseButtonObject()"
@click="SteamPurchase()"
>
@ -104,6 +113,12 @@ export default {
class="o-shop-button-button__img"
>
</button>
<div
v-if="!purchase.isUnlocked()"
class="o-shop-button-locked-text"
>
This affects a feature you have not unlocked yet ({{ purchase.lockText }})
</div>
</div>
</template>
@ -112,7 +127,7 @@ export default {
display: flex;
flex-direction: column;
width: 30rem;
height: 16rem;
height: 18rem;
justify-content: space-between;
color: white;
background: #3c3c3c;
@ -155,4 +170,11 @@ export default {
color: red;
text-decoration: line-through;
}
.o-shop-button-locked-text {
display: block;
font-size: 1.2rem;
font-weight: bold;
color: var(--color-bad);
}
</style>

View File

@ -120,7 +120,7 @@ export default {
Respec Shop
</PrimaryButton-->
</div>
<!--div v-if="!canRespec">
<!--div v-if="loggedIn && !canRespec">
Time until respec available: {{ respecTimeStr }}
</div-->
<div
@ -243,6 +243,7 @@ export default {
.l-shop-buttons-container {
display: flex;
justify-content: center;
flex-wrap: wrap;
width: 93rem;
margin: auto;

View File

@ -366,7 +366,7 @@ export default {
</div>
</div>
</div>
<div v-if="resource === 'AD_total'">
<div v-if="resource.key === 'AD_total'">
<br>
"Base AD Production" is the amount of Antimatter that you would be producing with your current AD upgrades
as if you had waited a fixed amount of time ({{ formatInt(10) }}-{{ formatInt(40) }} seconds depending on

View File

@ -125,7 +125,7 @@ export default {
<template>
<div
v-show="showRow"
class="c-dimension-row l-dimension-single-row"
class="c-dimension-row l-dimension-row-time-dim l-dimension-single-row"
:class="{ 'c-dim-row--not-reached': !isUnlocked && !requirementReached }"
>
<GenericDimensionRowText

View File

@ -42,6 +42,6 @@ export default {
:class="enabledClass"
@click="action"
>
{{ isLocked ? "Requires Eternity to unlock" : formatCost(cost) }}
{{ isLocked ? "Requires an Eternity to unlock" : formatCost(cost) }}
</button>
</template>