Merge branch 'master' into Fix-Pelle-Stuff
@ -142,12 +142,6 @@ export const Achievements = {
|
||||
return;
|
||||
}
|
||||
if (Achievements.preReality.every(a => a.isUnlocked)) return;
|
||||
if (Perk.achievementGroup5.isBought) {
|
||||
for (const achievement of Achievements.preReality) {
|
||||
achievement.unlock(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
player.reality.achTimer += diff;
|
||||
if (player.reality.achTimer < this.period) return;
|
||||
|
@ -72,6 +72,8 @@ import SwitchAutomatorEditorModal from "@/components/modals/SwitchAutomatorEdito
|
||||
import UiChoiceModal from "@/components/modals/UiChoiceModal";
|
||||
import UndoGlyphModal from "@/components/modals/UndoGlyphModal";
|
||||
|
||||
import S12GamesModal from "@/components/modals/secret-themes/S12GamesModal";
|
||||
|
||||
let nextModalID = 0;
|
||||
export class Modal {
|
||||
constructor(component, priority = 0, closeEvent) {
|
||||
@ -255,6 +257,8 @@ Modal.sacrifice = new Modal(SacrificeModal, 1, GAME_EVENT.DIMBOOST_AFTER);
|
||||
Modal.breakInfinity = new Modal(BreakInfinityModal, 1, GAME_EVENT.ETERNITY_RESET_AFTER);
|
||||
Modal.respecIAP = new Modal(RespecIAPModal);
|
||||
|
||||
Modal.s12Games = new Modal(S12GamesModal);
|
||||
|
||||
function getSaveInfo(save) {
|
||||
const resources = {
|
||||
realTimePlayed: 0,
|
||||
|
@ -4,7 +4,7 @@ export const Theme = function Theme(name, config) {
|
||||
this.name = name;
|
||||
|
||||
this.isDark = function() {
|
||||
return this.isDefault()
|
||||
return (this.isDefault() || name === "S12")
|
||||
? player.options.newUI
|
||||
: config.isDark;
|
||||
};
|
||||
@ -88,6 +88,7 @@ Theme.secretThemeIndex = function(name) {
|
||||
"dba8336cd3224649d07952b00045a6ec3c8df277aa8a0a0e3e7c2aaa77f1fbb9",
|
||||
"73de8a7f9efa1cbffc80a8effc9891a799127cd204b3a8b023bea8f513ed4753",
|
||||
"f3a71114261b4af6517a53f89bf0c6b56bb81b6f0e931d0e0d71249eb196628c",
|
||||
"1248689171faaa0abb68279199a8d2eb232dba10d2dacb79a705f680b6862c0e",
|
||||
];
|
||||
const sha = sha512_256(name.toUpperCase());
|
||||
return secretThemes.indexOf(sha);
|
||||
@ -153,6 +154,7 @@ export const Themes = {
|
||||
Theme.create("S9", { secret: true, }),
|
||||
Theme.create("S10", { dark: true, metro: true, animated: true, secret: true, }),
|
||||
Theme.create("S11", { dark: true, animated: true, secret: true, }),
|
||||
Theme.create("S12", { secret: true, }),
|
||||
/* eslint-enable no-multi-spaces */
|
||||
],
|
||||
|
||||
|
@ -40,6 +40,11 @@ Autobuyer.epMult = new class EPMultAutobuyerState extends AutobuyerState {
|
||||
}
|
||||
|
||||
tick() {
|
||||
// While the active check is normally automatically handled with the global autobuyer ticking method, we also
|
||||
// call this from the TD autobuyers in order to make sure this is executed before TDs are purchased. Simply
|
||||
// reordering the autobuyer call order is undesirable because much of the codebase relies on autobuyers being
|
||||
// grouped as they are, and many other autobuyers in the 5xEP group must execute *after* dimensions
|
||||
if (!this.isActive) return;
|
||||
applyEU2();
|
||||
EternityUpgrade.epMult.buyMax();
|
||||
}
|
||||
|
@ -41,12 +41,30 @@ Autobuyer.reality = new class RealityAutobuyerState extends AutobuyerState {
|
||||
this.data.glyph = value;
|
||||
}
|
||||
|
||||
get time() {
|
||||
return this.data.time;
|
||||
}
|
||||
|
||||
set time(value) {
|
||||
this.data.time = value;
|
||||
}
|
||||
|
||||
get shard() {
|
||||
return this.data.shard;
|
||||
}
|
||||
|
||||
set shard(value) {
|
||||
this.data.shard = value;
|
||||
}
|
||||
|
||||
toggleMode() {
|
||||
this.mode = [
|
||||
AUTO_REALITY_MODE.RM,
|
||||
AUTO_REALITY_MODE.GLYPH,
|
||||
AUTO_REALITY_MODE.EITHER,
|
||||
AUTO_REALITY_MODE.BOTH
|
||||
AUTO_REALITY_MODE.BOTH,
|
||||
AUTO_REALITY_MODE.TIME,
|
||||
AUTO_REALITY_MODE.RELIC_SHARD
|
||||
]
|
||||
.nextSibling(this.mode);
|
||||
}
|
||||
@ -74,6 +92,12 @@ Autobuyer.reality = new class RealityAutobuyerState extends AutobuyerState {
|
||||
case AUTO_REALITY_MODE.BOTH:
|
||||
proc = rmProc && glyphProc;
|
||||
break;
|
||||
case AUTO_REALITY_MODE.TIME:
|
||||
proc = player.records.thisReality.realTime / 1000 > this.time;
|
||||
break;
|
||||
case AUTO_REALITY_MODE.RELIC_SHARD:
|
||||
proc = Effarig.shardsGained > this.shard;
|
||||
break;
|
||||
}
|
||||
if (proc) autoReality();
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class TimeDimensionAutobuyerState extends IntervaledAutobuyerState {
|
||||
|
||||
tick() {
|
||||
applyEU2();
|
||||
Autobuyer.epMult.tick();
|
||||
const tier = this.tier;
|
||||
if (!TimeDimension(tier).isAvailableForPurchase) return;
|
||||
super.tick();
|
||||
|
@ -856,6 +856,8 @@ export const AutomatorBackend = {
|
||||
},
|
||||
|
||||
start(scriptID = this.state.topLevelScript, initialMode = AUTOMATOR_MODE.RUN, compile = true) {
|
||||
// Automator execution behaves oddly across new games, so we explicitly stop it from running if not unlocked
|
||||
if (!Player.automatorUnlocked) return;
|
||||
this.hasJustCompleted = false;
|
||||
this.state.topLevelScript = scriptID;
|
||||
const scriptObject = this.findScript(scriptID);
|
||||
|
@ -57,15 +57,15 @@ export const AutomatorCommands = ((() => {
|
||||
let addedECs, gainedEP;
|
||||
switch (layer) {
|
||||
case "INFINITY":
|
||||
return `${format(player.records.lastTenInfinities[0][1], 2)} IP`;
|
||||
return `${format(player.records.recentInfinities[0][1], 2)} IP`;
|
||||
case "ETERNITY":
|
||||
addedECs = AutomatorData.lastECCompletionCount;
|
||||
gainedEP = `${format(player.records.lastTenEternities[0][1], 2)} EP`;
|
||||
gainedEP = `${format(player.records.recentEternities[0][1], 2)} EP`;
|
||||
return addedECs === 0
|
||||
? `${gainedEP}`
|
||||
: `${gainedEP}, ${addedECs} completions`;
|
||||
case "REALITY":
|
||||
return `${format(player.records.lastTenRealities[0][1], 2)} RM`;
|
||||
return `${format(player.records.recentRealities[0][1], 2)} RM`;
|
||||
default:
|
||||
throw Error(`Unrecognized prestige ${layer} in Automator event log`);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { GameDatabase } from "./secret-formula/game-database";
|
||||
class AwayProgress {
|
||||
constructor(config) {
|
||||
this.name = config.name;
|
||||
this.forcedName = config.forcedName;
|
||||
this.isUnlocked = config.isUnlocked;
|
||||
this.awayOption = config.awayOption ?? this.name;
|
||||
this.showOption = config.showOption ?? true;
|
||||
@ -32,6 +33,7 @@ class AwayProgress {
|
||||
}
|
||||
|
||||
get formatName() {
|
||||
if (this.forcedName) return this.forcedName;
|
||||
// Format the camelCase name to Title Case, with spaces added before the capital letters
|
||||
return this.name
|
||||
.replace(/[A-Z]/gu, match => ` ${match}`)
|
||||
|
@ -27,7 +27,9 @@ function handleChallengeCompletion() {
|
||||
export function manualBigCrunchResetRequest() {
|
||||
if (!Player.canCrunch) return;
|
||||
if (GameEnd.creditsEverClosed) return;
|
||||
if (player.options.confirmations.bigCrunch && player.break) {
|
||||
// We show the modal under two conditions - on the first ever infinity (to explain the mechanic) and
|
||||
// post-break (to show total IP and infinities gained)
|
||||
if (player.options.confirmations.bigCrunch && (!PlayerProgress.infinityUnlocked() || player.break)) {
|
||||
Modal.bigCrunch.show();
|
||||
} else {
|
||||
bigCrunchResetRequest();
|
||||
@ -177,7 +179,7 @@ export function preProductionGenerateIP(diff) {
|
||||
genCount = Math.floor(player.partInfinityPoint);
|
||||
player.partInfinityPoint -= genCount;
|
||||
}
|
||||
let gainedPerGen = InfinityUpgrade.ipGen.effectValue;
|
||||
let gainedPerGen = player.records.bestInfinity.time >= 999999999999 ? DC.D0 : InfinityUpgrade.ipGen.effectValue;
|
||||
if (Laitela.isRunning) gainedPerGen = dilatedValueOf(gainedPerGen);
|
||||
const gainedThisTick = new Decimal(genCount).times(gainedPerGen);
|
||||
Currency.infinityPoints.add(gainedThisTick);
|
||||
|
@ -48,14 +48,14 @@ export const GameCache = {
|
||||
worstChallengeTime: new Lazy(() => player.challenge.normal.bestTimes.max()),
|
||||
|
||||
bestRunIPPM: new Lazy(() =>
|
||||
player.records.lastTenInfinities
|
||||
.map(run => ratePerMinute(run[1], run[0]))
|
||||
player.records.recentInfinities
|
||||
.map(run => ratePerMinute(run[2], run[0]))
|
||||
.reduce(Decimal.maxReducer)
|
||||
),
|
||||
|
||||
averageRealTimePerEternity: new Lazy(() => player.records.lastTenEternities
|
||||
.map(run => run[3])
|
||||
.reduce(Number.sumReducer) / (1000 * player.records.lastTenEternities.length)),
|
||||
averageRealTimePerEternity: new Lazy(() => player.records.recentEternities
|
||||
.map(run => run[1])
|
||||
.reduce(Number.sumReducer) / (1000 * player.records.recentEternities.length)),
|
||||
|
||||
tickSpeedMultDecrease: new Lazy(() => 10 - Effects.sum(
|
||||
BreakInfinityUpgrade.tickspeedCostMult,
|
||||
@ -76,8 +76,7 @@ export const GameCache = {
|
||||
Perk.achievementGroup1,
|
||||
Perk.achievementGroup2,
|
||||
Perk.achievementGroup3,
|
||||
Perk.achievementGroup4,
|
||||
Perk.achievementGroup5
|
||||
Perk.achievementGroup4
|
||||
)).totalMilliseconds),
|
||||
|
||||
buyablePerks: new Lazy(() => Perks.all.filter(p => p.canBeBought)),
|
||||
|
@ -82,7 +82,8 @@ class VRunUnlockState extends GameMechanicState {
|
||||
Decimal.gte(playerData.runRecords[this.id], this.conditionValue)) {
|
||||
if (!V.isFlipped && this.config.isHard) continue;
|
||||
this.completions++;
|
||||
GameUI.notify.success(`You have unlocked V-Achievement '${this.config.name}' tier ${this.completions}`);
|
||||
GameUI.notify.success(`You have unlocked V-Achievement
|
||||
'${this.config.name}' tier ${formatInt(this.completions)}`);
|
||||
|
||||
V.updateTotalRunUnlocks();
|
||||
|
||||
|
@ -248,7 +248,7 @@ export const Pelle = {
|
||||
case undefined:
|
||||
return "No Glyph equipped!";
|
||||
default:
|
||||
return "";
|
||||
return "You cannot equip this Glyph while Doomed!";
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -67,7 +67,7 @@ class AlchemyResourceState extends GameMechanicState {
|
||||
}
|
||||
|
||||
get lockText() {
|
||||
return `${this.unlockedWith.name} Level ${this.unlockedAt}`;
|
||||
return `${this.unlockedWith.name} Level ${formatInt(this.unlockedAt)}`;
|
||||
}
|
||||
|
||||
get isCustomEffect() {
|
||||
|
@ -215,7 +215,9 @@ window.AUTO_REALITY_MODE = {
|
||||
RM: 0,
|
||||
GLYPH: 1,
|
||||
EITHER: 2,
|
||||
BOTH: 3
|
||||
BOTH: 3,
|
||||
TIME: 4,
|
||||
RELIC_SHARD: 5,
|
||||
};
|
||||
|
||||
// Free tickspeed multiplier with TS171. Shared here because formatting glyph effects depends on it
|
||||
|
@ -9,11 +9,11 @@ export function animateAndDilate() {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-empty-function
|
||||
export function animateAndUndilate(callback = () => {}) {
|
||||
export function animateAndUndilate(callback) {
|
||||
FullScreenAnimationHandler.display("a-undilate", 2);
|
||||
setTimeout(() => {
|
||||
eternity(false, false, { switchingDilation: true });
|
||||
callback();
|
||||
if (callback) callback();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
@ -176,8 +176,8 @@ export function getTP(antimatter, requireEternity) {
|
||||
return getBaseTP(antimatter, requireEternity).times(tachyonGainMultiplier());
|
||||
}
|
||||
|
||||
// Returns the amount of TP gained, subtracting out current TP; used only for displaying gained TP
|
||||
// and for "exit dilation" button (saying whether you need more antimatter)
|
||||
// Returns the amount of TP gained, subtracting out current TP; used for displaying gained TP, text on the
|
||||
// "exit dilation" button (saying whether you need more antimatter), and in last 10 eternities
|
||||
export function getTachyonGain(requireEternity) {
|
||||
return getTP(Currency.antimatter.value, requireEternity).minus(Currency.tachyonParticles.value).clampMin(0);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ export function eternity(force, auto, specialConditions = {}) {
|
||||
if (!force) {
|
||||
if (!Player.canEternity) return false;
|
||||
EventHub.dispatch(GAME_EVENT.ETERNITY_RESET_BEFORE);
|
||||
if (!player.dilation.active) giveEternityRewards(auto);
|
||||
giveEternityRewards(auto);
|
||||
player.requirementChecks.reality.noEternities = false;
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ export function eternity(force, auto, specialConditions = {}) {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-empty-function
|
||||
export function animateAndEternity(callback = () => {}) {
|
||||
export function animateAndEternity(callback) {
|
||||
if (!Player.canEternity) return false;
|
||||
const hasAnimation = !FullScreenAnimationHandler.isDisplaying &&
|
||||
((player.dilation.active && player.options.animations.dilation) ||
|
||||
@ -151,12 +151,12 @@ export function animateAndEternity(callback = () => {}) {
|
||||
eternityAnimation();
|
||||
setTimeout(() => {
|
||||
eternity();
|
||||
callback();
|
||||
if (callback) callback();
|
||||
}, 2250);
|
||||
}
|
||||
} else {
|
||||
eternity();
|
||||
callback();
|
||||
if (callback) callback();
|
||||
}
|
||||
return hasAnimation;
|
||||
}
|
||||
|
@ -188,10 +188,11 @@ export class EternityChallengeState extends GameMechanicState {
|
||||
// If dilation is active, the { enteringEC: true } parameter will cause
|
||||
// dilation to not be disabled. We still don't force-eternity, though;
|
||||
// this causes TP to still be gained.
|
||||
const enteringGamespeed = getGameSpeedupFactor();
|
||||
if (Player.canEternity) eternity(false, auto, { enteringEC: true });
|
||||
player.challenge.eternity.current = this.id;
|
||||
if (this.id === 12) {
|
||||
if (player.requirementChecks.reality.slowestBH < 1) {
|
||||
if (enteringGamespeed < 0.001) {
|
||||
SecretAchievement(42).unlock();
|
||||
}
|
||||
player.requirementChecks.reality.slowestBH = 1;
|
||||
|
@ -449,13 +449,13 @@ export const Glyphs = {
|
||||
if (player.reality.autoCollapse) this.collapseEmptySlots();
|
||||
},
|
||||
sortByLevel() {
|
||||
this.sort((a, b) => -a.level + b.level);
|
||||
this.sort((a, b) => b.level - a.level);
|
||||
},
|
||||
sortByPower() {
|
||||
this.sort((a, b) => -a.level * a.strength + b.level * b.strength);
|
||||
this.sort((a, b) => b.level * b.strength - a.level * a.strength);
|
||||
},
|
||||
sortByScore() {
|
||||
this.sort((a, b) => -AutoGlyphProcessor.filterValue(a) + AutoGlyphProcessor.filterValue(b));
|
||||
this.sort((a, b) => AutoGlyphProcessor.filterValue(b) - AutoGlyphProcessor.filterValue(a));
|
||||
},
|
||||
sortByEffect() {
|
||||
function reverseBitstring(eff) {
|
||||
@ -463,7 +463,7 @@ export const Glyphs = {
|
||||
}
|
||||
// The bitwise reversal is so that the effects with the LOWER id are valued higher in the sorting.
|
||||
// This primarily meant for effarig glyph effect sorting, which makes it prioritize timespeed pow highest.
|
||||
this.sort((a, b) => -reverseBitstring(a.effects) + reverseBitstring(b.effects));
|
||||
this.sort((a, b) => reverseBitstring(b.effects) - reverseBitstring(a.effects));
|
||||
},
|
||||
// If there are enough glyphs that are better than the specified glyph, in every way, then
|
||||
// the glyph is objectively a useless piece of garbage.
|
||||
|
@ -18,17 +18,22 @@ export const NG = {
|
||||
const automatorConstants = JSON.stringify(player.reality.automator.constants);
|
||||
const automatorScripts = JSON.stringify(player.reality.automator.scripts);
|
||||
const fullCompletions = player.records.fullGameCompletions;
|
||||
const fullTimePlayed = player.records.previousRunRealTime + player.records.realTimePlayed;
|
||||
GlyphAppearanceHandler.unlockSet();
|
||||
const glyphCosmetics = JSON.stringify(player.reality.glyphs.cosmetics);
|
||||
Modal.hideAll();
|
||||
Quote.clearAll();
|
||||
GameStorage.hardReset();
|
||||
player.options = JSON.parse(backUpOptions);
|
||||
// We need to force this one to be true because otherwise the player will be unable to select their glyphs
|
||||
// until they can auto-reality
|
||||
player.options.confirmations.glyphSelection = true;
|
||||
player.secretUnlocks = secretUnlocks;
|
||||
player.secretAchievementBits = JSON.parse(secretAchievements);
|
||||
player.reality.automator.constants = JSON.parse(automatorConstants);
|
||||
player.reality.automator.scripts = JSON.parse(automatorScripts);
|
||||
player.records.fullGameCompletions = fullCompletions + 1;
|
||||
player.records.previousRunRealTime = fullTimePlayed;
|
||||
ui.view.newUI = player.options.newUI;
|
||||
ui.view.news = player.options.news.enabled;
|
||||
player.reality.glyphs.cosmetics = JSON.parse(glyphCosmetics);
|
||||
|
@ -23,6 +23,7 @@ export const NewsHandler = {
|
||||
// we pad the array with zeroes until we can fit the new ID in before actually adding it.
|
||||
while (this.BITS_PER_MASK * player.news.seen[type].length <= number) player.news.seen[type].push(0);
|
||||
player.news.seen[type][Math.floor(number / this.BITS_PER_MASK)] |= 1 << (number % this.BITS_PER_MASK);
|
||||
player.news.totalSeen++;
|
||||
},
|
||||
|
||||
hasSeenNews(id) {
|
||||
|
@ -48,6 +48,12 @@ class PerkState extends SetPurchasableMechanicState {
|
||||
onPurchased() {
|
||||
if (this.config.bumpCurrency !== undefined) this.config.bumpCurrency();
|
||||
if (this.label === "EU1" && Currency.eternities.gt(0)) applyEU1();
|
||||
if (this.label === "ACHNR") {
|
||||
if (Achievements.preReality.some(a => !a.isUnlocked)) player.reality.gainedAutoAchievements = true;
|
||||
for (const achievement of Achievements.preReality) {
|
||||
achievement.unlock(true);
|
||||
}
|
||||
}
|
||||
GameCache.achievementPeriod.invalidate();
|
||||
GameCache.buyablePerks.invalidate();
|
||||
EventHub.dispatch(GAME_EVENT.PERK_BOUGHT);
|
||||
|
@ -62,6 +62,8 @@ window.player = {
|
||||
mode: 0,
|
||||
rm: DC.D1,
|
||||
glyph: 0,
|
||||
time: 0,
|
||||
shard: 0,
|
||||
isActive: false
|
||||
},
|
||||
eternity: {
|
||||
@ -271,19 +273,21 @@ window.player = {
|
||||
realTimePlayed: 0,
|
||||
realTimeDoomed: 0,
|
||||
fullGameCompletions: 0,
|
||||
previousRunRealTime: 0,
|
||||
totalAntimatter: DC.E1,
|
||||
lastTenInfinities: Array.range(0, 10).map(() =>
|
||||
[Number.MAX_VALUE, DC.D1, DC.D1, Number.MAX_VALUE]),
|
||||
lastTenEternities: Array.range(0, 10).map(() =>
|
||||
[Number.MAX_VALUE, DC.D1, DC.D1, Number.MAX_VALUE]),
|
||||
lastTenRealities: Array.range(0, 10).map(() =>
|
||||
[Number.MAX_VALUE, DC.D1, 1, Number.MAX_VALUE, 0]),
|
||||
recentInfinities: Array.range(0, 10).map(() =>
|
||||
[Number.MAX_VALUE, Number.MAX_VALUE, DC.D1, DC.D1, ""]),
|
||||
recentEternities: Array.range(0, 10).map(() =>
|
||||
[Number.MAX_VALUE, Number.MAX_VALUE, DC.D1, DC.D1, "", DC.D0]),
|
||||
recentRealities: Array.range(0, 10).map(() =>
|
||||
[Number.MAX_VALUE, Number.MAX_VALUE, DC.D1, 1, "", 0, 0]),
|
||||
thisInfinity: {
|
||||
time: 0,
|
||||
realTime: 0,
|
||||
lastBuyTime: 0,
|
||||
maxAM: DC.D0,
|
||||
bestIPmin: DC.D0,
|
||||
bestIPminVal: DC.D0,
|
||||
},
|
||||
bestInfinity: {
|
||||
time: Number.MAX_VALUE,
|
||||
@ -298,6 +302,7 @@ window.player = {
|
||||
maxIP: DC.D0,
|
||||
bestIPMsWithoutMaxAll: DC.D0,
|
||||
bestEPmin: DC.D0,
|
||||
bestEPminVal: DC.D0,
|
||||
bestInfinitiesPerMs: DC.D0,
|
||||
},
|
||||
bestEternity: {
|
||||
@ -314,6 +319,8 @@ window.player = {
|
||||
bestEternitiesPerMs: DC.D0,
|
||||
maxReplicanti: DC.D0,
|
||||
maxDT: DC.D0,
|
||||
bestRSmin: 0,
|
||||
bestRSminVal: 0,
|
||||
},
|
||||
bestReality: {
|
||||
time: Number.MAX_VALUE,
|
||||
@ -521,7 +528,7 @@ window.player = {
|
||||
},
|
||||
constants: {},
|
||||
execTimer: 0,
|
||||
type: AUTOMATOR_TYPE.BLOCK,
|
||||
type: AUTOMATOR_TYPE.TEXT,
|
||||
forceUnlock: false,
|
||||
currentInfoPane: AutomatorPanels.INTRO_PAGE,
|
||||
},
|
||||
@ -791,8 +798,8 @@ window.player = {
|
||||
offlineProgress: true,
|
||||
automaticTabSwitching: true,
|
||||
respecIntoProtected: false,
|
||||
offlineTicks: 1000,
|
||||
showLastTenResourceGain: true,
|
||||
offlineTicks: 1e5,
|
||||
showRecentRate: true,
|
||||
autosaveInterval: 30000,
|
||||
showTimeSinceSave: true,
|
||||
saveFileName: "",
|
||||
@ -888,7 +895,8 @@ window.player = {
|
||||
maxEntries: 200,
|
||||
clearOnReality: true,
|
||||
clearOnRestart: true,
|
||||
}
|
||||
},
|
||||
invertTTgenDisplay: false,
|
||||
},
|
||||
IAP: {
|
||||
enabled: false,
|
||||
|
@ -340,6 +340,30 @@ export function beginProcessReality(realityProps) {
|
||||
// Do this before processing glyphs so that we don't try to reality again while async is running.
|
||||
finishProcessReality(realityProps);
|
||||
|
||||
// If we have less than a certain amount of simulated realities, then we just shortcut the heavier async and
|
||||
// sampling code in order to just directly give all the glyphs. The later code is a fixed amount of overhead
|
||||
// which is large enough that quick realities can cause it to softlock the game due to lag on slower devices
|
||||
// Note: This is mostly a copy-paste of a code block in processManualReality() with slight modifications
|
||||
if (glyphsToProcess < 100) {
|
||||
for (let glyphNum = 0; glyphNum < glyphsToProcess; glyphNum++) {
|
||||
if (EffarigUnlock.glyphFilter.isUnlocked) {
|
||||
const glyphChoices = GlyphSelection.glyphList(GlyphSelection.choiceCount,
|
||||
realityProps.gainedGlyphLevel, { rng });
|
||||
const newGlyph = AutoGlyphProcessor.pick(glyphChoices);
|
||||
if (!AutoGlyphProcessor.wouldKeep(newGlyph) || GameCache.glyphInventorySpace.value === 0) {
|
||||
AutoGlyphProcessor.getRidOfGlyph(newGlyph);
|
||||
} else {
|
||||
Glyphs.addToInventory(newGlyph);
|
||||
}
|
||||
} else {
|
||||
GlyphSelection.select(Math.floor(Math.random() * GlyphSelection.choiceCount), false);
|
||||
}
|
||||
}
|
||||
rng.finalize();
|
||||
Glyphs.processSortingAfterReality();
|
||||
return;
|
||||
}
|
||||
|
||||
// We need these variables in this scope in order to modify the behavior of the Async loop while it's running
|
||||
const progress = {};
|
||||
let fastToggle = false;
|
||||
@ -409,7 +433,7 @@ export function beginProcessReality(realityProps) {
|
||||
if (VUnlocks.autoAutoClean.canBeApplied && player.reality.autoAutoClean) Glyphs.autoClean();
|
||||
}
|
||||
};
|
||||
const glyphsToSample = 10000;
|
||||
const glyphsToSample = Math.min(glyphsToProcess, 10000);
|
||||
Async.run(glyphFunction,
|
||||
glyphsToProcess,
|
||||
{
|
||||
|
@ -765,8 +765,8 @@ GameDatabase.achievements.normal = [
|
||||
${format(Decimal.NUMBER_MAX_VALUE, 1, 0)} times higher Infinity Points than the previous one.`;
|
||||
},
|
||||
checkRequirement: () => {
|
||||
if (player.records.lastTenInfinities.some(i => i[0] === Number.MAX_VALUE)) return false;
|
||||
const infinities = player.records.lastTenInfinities.map(run => run[1]);
|
||||
if (player.records.recentInfinities.some(i => i[0] === Number.MAX_VALUE)) return false;
|
||||
const infinities = player.records.recentInfinities.map(run => run[2]);
|
||||
for (let i = 0; i < infinities.length - 1; i++) {
|
||||
if (infinities[i].lt(infinities[i + 1].times(Decimal.NUMBER_MAX_VALUE))) return false;
|
||||
}
|
||||
@ -933,8 +933,8 @@ GameDatabase.achievements.normal = [
|
||||
id: 132,
|
||||
name: "Unique snowflakes",
|
||||
get description() {
|
||||
return `Have ${formatInt(569)} Antimatter Galaxies without getting any
|
||||
Replicanti Galaxies in your current Eternity.`;
|
||||
return `Have ${formatInt(569)} Antimatter Galaxies without gaining any
|
||||
Replicanti Galaxies in your current Eternity.`;
|
||||
},
|
||||
checkRequirement: () => player.galaxies >= 569 && player.requirementChecks.eternity.noRG,
|
||||
checkEvent: GAME_EVENT.GALAXY_RESET_AFTER,
|
||||
@ -1041,8 +1041,8 @@ GameDatabase.achievements.normal = [
|
||||
${format(Decimal.NUMBER_MAX_VALUE, 1, 0)} times higher Eternity Points than the previous one.`;
|
||||
},
|
||||
checkRequirement: () => {
|
||||
if (player.records.lastTenEternities.some(i => i[0] === Number.MAX_VALUE)) return false;
|
||||
const eternities = player.records.lastTenEternities.map(run => run[1]);
|
||||
if (player.records.recentEternities.some(i => i[0] === Number.MAX_VALUE)) return false;
|
||||
const eternities = player.records.recentEternities.map(run => run[2]);
|
||||
for (let i = 0; i < eternities.length - 1; i++) {
|
||||
if (eternities[i].lt(eternities[i + 1].times(Decimal.NUMBER_MAX_VALUE))) return false;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ GameDatabase.achievements.secret = [
|
||||
checkRequirement: () =>
|
||||
Time.bestInfinity.totalMilliseconds <= 1 ||
|
||||
Time.bestEternity.totalMilliseconds <= 1,
|
||||
checkEvent: [GAME_EVENT.BIG_CRUNCH_BEFORE, GAME_EVENT.ETERNITY_RESET_BEFORE]
|
||||
checkEvent: [GAME_EVENT.BIG_CRUNCH_AFTER, GAME_EVENT.ETERNITY_RESET_AFTER]
|
||||
},
|
||||
{
|
||||
id: 33,
|
||||
|
@ -97,6 +97,7 @@ GameDatabase.awayProgressTypes = [
|
||||
showOption: false,
|
||||
}, {
|
||||
name: "enslavedMemories",
|
||||
forcedName: "Nameless Memories",
|
||||
awayOption: "celestialMemories",
|
||||
reference: ["celestials", "ra", "pets", "enslaved", "memories"],
|
||||
isUnlocked: () => Ra.pets.enslaved.isUnlocked && !Ra.pets.enslaved.isCapped,
|
||||
|
@ -140,7 +140,7 @@ function pelleRiftFill(name, index, textAngle, fillType) {
|
||||
visibleCheck = () => riftFillStage(name) === FILL_STATE.FILL;
|
||||
progressFn = () => Math.clamp(0.1 + PelleRifts[name.toLowerCase()].realPercentage / 0.9, 1e-6, 1);
|
||||
legendFn = () => false;
|
||||
percentFn = x => (x - 0.1) / 0.9;
|
||||
percentFn = () => PelleRifts[name.toLowerCase()].realPercentage;
|
||||
incompleteClass = "c-celestial-nav__test-incomplete";
|
||||
nodeFill = "crimson";
|
||||
connectorFill = "crimson";
|
||||
@ -153,7 +153,7 @@ function pelleRiftFill(name, index, textAngle, fillType) {
|
||||
visibleCheck = () => riftFillStage(name) >= FILL_STATE.DRAIN;
|
||||
progressFn = () => Math.clamp(Math.sqrt(PelleRifts[name.toLowerCase()].reducedTo), 1e-6, 1);
|
||||
legendFn = () => riftFillStage(name) === FILL_STATE.DRAIN && PelleRifts[name.toLowerCase()].reducedTo < 1;
|
||||
percentFn = x => x;
|
||||
percentFn = () => PelleRifts[name.toLowerCase()].reducedTo;
|
||||
incompleteClass = "c-celestial-nav__drained-rift";
|
||||
nodeFill = "crimson";
|
||||
connectorFill = "#550919";
|
||||
@ -161,7 +161,7 @@ function pelleRiftFill(name, index, textAngle, fillType) {
|
||||
case FILL_STATE.OVERFILL:
|
||||
visibleCheck = () => riftFillStage(name) === FILL_STATE.OVERFILL;
|
||||
progressFn = () => Math.clamp(PelleRifts[name.toLowerCase()].percentage - 1, 1e-6, 1);
|
||||
percentFn = x => x + 1;
|
||||
percentFn = () => PelleRifts[name.toLowerCase()].percentage;
|
||||
legendFn = () => true;
|
||||
incompleteClass = undefined;
|
||||
nodeFill = "#ff7700";
|
||||
@ -182,8 +182,8 @@ function pelleRiftFill(name, index, textAngle, fillType) {
|
||||
},
|
||||
forceLegend: () => legendFn(),
|
||||
legend: {
|
||||
text: complete => [
|
||||
`${formatPercents(percentFn(complete), 1)} ${wordShift.wordCycle(PelleRifts[name.toLowerCase()].name)}`
|
||||
text: () => [
|
||||
`${formatPercents(percentFn(), 1)} ${wordShift.wordCycle(PelleRifts[name.toLowerCase()].name)}`
|
||||
],
|
||||
angle: textAngle,
|
||||
diagonal: 30,
|
||||
@ -586,7 +586,7 @@ GameDatabase.celestials.navigation = {
|
||||
},
|
||||
legend: {
|
||||
text: complete => {
|
||||
if (complete >= 1) return "Broken the chain with Glyph level";
|
||||
if (complete >= 1) return "Glyph level chain has been broken";
|
||||
const goal = 5000;
|
||||
return [
|
||||
"Break a chain",
|
||||
@ -631,7 +631,7 @@ GameDatabase.celestials.navigation = {
|
||||
},
|
||||
legend: {
|
||||
text: complete => {
|
||||
if (complete >= 1) return "Broken the chain with Glyph rarity";
|
||||
if (complete >= 1) return "Glyph rarity chain has been broken";
|
||||
const goal = 100;
|
||||
return [
|
||||
"Break a chain",
|
||||
@ -1527,8 +1527,8 @@ GameDatabase.celestials.navigation = {
|
||||
if (upgrade.isAvailableForPurchase) return [
|
||||
dmdText,
|
||||
`Imaginary Machines
|
||||
${format(Math.min(upgrade.currency.value, upgrade.cost), upgrade.canBeBought ? 0 : 2)}
|
||||
/ ${format(upgrade.cost)}`
|
||||
${format(Math.min(upgrade.currency.value, upgrade.cost), upgrade.canBeBought ? 1 : 2)}
|
||||
/ ${format(upgrade.cost, 1)}`
|
||||
];
|
||||
|
||||
if (player.celestials.laitela.fastestCompletion > 30 && Laitela.difficultyTier < 0) return [
|
||||
|
@ -174,7 +174,7 @@ GameDatabase.celestials.pelle.rifts = {
|
||||
{
|
||||
resource: "recursion",
|
||||
requirement: 1,
|
||||
description: "Unlock the Galaxy Generator",
|
||||
description: "Permanently unlock the Galaxy Generator",
|
||||
},
|
||||
],
|
||||
galaxyGeneratorText: "Creating more Galaxies is unsustainable, you must focus the $value to allow more"
|
||||
|
@ -37,7 +37,7 @@ GameDatabase.celestials.pelle.strikes = {
|
||||
id: 5,
|
||||
requirementDescription: "Dilate Time",
|
||||
penaltyDescription: "Time Dilation is permanently active",
|
||||
rewardDescription: () => `Keep access to Time Dilation upgrades across Armageddon and unlock
|
||||
rewardDescription: () => `Keep the Time Dilation study across Armageddon, boost Remnant gain, and unlock
|
||||
${wordShift.wordCycle(PelleRifts.paradox.name)}`,
|
||||
rift: () => PelleRifts.paradox
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ GameDatabase.celestials.v = {
|
||||
},
|
||||
autoAutoClean: {
|
||||
id: 4,
|
||||
reward: "Unlock the ability to Automatically Purge on Reality.",
|
||||
reward: "Unlock the ability to Automatically Purge Glyphs on Reality.",
|
||||
description: () => `Have ${formatInt(16)} V-Achievements`,
|
||||
requirement: () => V.spaceTheorems >= 16
|
||||
},
|
||||
|
@ -63,8 +63,8 @@ GameDatabase.challenges.infinity = [
|
||||
{
|
||||
id: 5,
|
||||
description:
|
||||
`buying Antimatter Dimensions 1-4 causes all smaller Antimatter Dimension costs to increase.
|
||||
Buying Antimatter Dimensions 5-8 causes all larger Antimatter Dimension costs to increase.`,
|
||||
`buying Antimatter Dimensions 1-4 causes all cheaper AD costs to increase.
|
||||
Buying Antimatter Dimensions 5-8 causes all more expensive AD costs to increase.`,
|
||||
goal: DC.E16500,
|
||||
isQuickResettable: true,
|
||||
reward: {
|
||||
@ -104,7 +104,7 @@ GameDatabase.challenges.infinity = [
|
||||
TimeStudy(81)
|
||||
);
|
||||
return `you cannot buy Antimatter Galaxies. Base Dimension Boost multiplier is increased to a maximum
|
||||
of ${formatX(10)}. (Current base multiplier: ${formatX(mult)})`;
|
||||
of ${formatX(10)}. (Current base multiplier: ${formatX(mult, 2, 1)})`;
|
||||
},
|
||||
goal: DC.E10000,
|
||||
isQuickResettable: false,
|
||||
|
@ -128,8 +128,8 @@ GameDatabase.challenges.normal = [
|
||||
legacyId: 7,
|
||||
isQuickResettable: false,
|
||||
description: () => `each Antimatter Dimension produces the Dimension ${formatInt(2)} tiers below it
|
||||
instead of ${formatInt(1)}. The 1st Dimension still produces antimatter, and the 2nd, 4th, and 6th
|
||||
Dimensions are made stronger to compensate.`,
|
||||
instead of ${formatInt(1)}. Both 1st and 2nd Dimensions produce antimatter.
|
||||
The 2nd, 4th, and 6th Dimensions are made stronger to compensate.`,
|
||||
name: "Automated Big Crunches",
|
||||
reward: "Big Crunches Autobuyer",
|
||||
lockedAt: DC.D16,
|
||||
|
@ -229,6 +229,9 @@ GameDatabase.credits = {
|
||||
}, {
|
||||
name: "Anthios",
|
||||
roles: 13
|
||||
}, {
|
||||
name: "Aubrey",
|
||||
roles: 13
|
||||
}, {
|
||||
name: "Auti",
|
||||
name2: "Lucia Tolle",
|
||||
@ -321,9 +324,6 @@ GameDatabase.credits = {
|
||||
}, {
|
||||
name: "Pavlxiiv",
|
||||
roles: 13
|
||||
}, {
|
||||
name: "Porygon-Z",
|
||||
roles: 13
|
||||
}, {
|
||||
name: "PotatoTIAB",
|
||||
roles: 13
|
||||
|
@ -59,7 +59,7 @@ GameDatabase.eternity.upgrades = {
|
||||
? "Time Dimensions are multiplied by days played in this Armageddon"
|
||||
: "Time Dimensions are multiplied by days played"
|
||||
),
|
||||
effect: () => (Pelle.isDoomed ? 1 + Time.thisReality.totalDays : Time.totalTimePlayed.totalDays),
|
||||
effect: () => (Pelle.isDoomed ? 1 + Time.thisReality.totalDays : Math.max(Time.totalTimePlayed.totalDays, 1)),
|
||||
formatEffect: value => formatX(value, 2, 1)
|
||||
}
|
||||
};
|
||||
|
@ -55,8 +55,16 @@ GameDatabase.eternity.timeStudies.normal = [
|
||||
requirement: [11],
|
||||
reqType: TS_REQUIREMENT_TYPE.AT_LEAST_ONE,
|
||||
description: () => `Improve Replicanti multiplier formula to
|
||||
(log2(x)${formatPow(2)})+x${formatPow(0.032, 3, 3)}`,
|
||||
effect: () => Replicanti.amount.pow(0.032)
|
||||
(log2(x)${formatPow(2)})+x${formatPow(0.032, 3, 3)}`,
|
||||
effect: () => Replicanti.amount.pow(0.032),
|
||||
// This is a special case because the study itself is *added* to the existing formula, but it makes more sense
|
||||
// to display a multiplicative increase just like every other study. We need to do the calculation in here in order
|
||||
// to properly show only the effect of this study and nothing else
|
||||
formatEffect: value => {
|
||||
const oldVal = Decimal.pow(Decimal.log2(Replicanti.amount.clampMin(1)), 2);
|
||||
const newVal = oldVal.plus(value);
|
||||
return formatX(newVal.div(oldVal).clampMin(1), 2, 2);
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
@ -81,7 +89,7 @@ GameDatabase.eternity.timeStudies.normal = [
|
||||
reqType: TS_REQUIREMENT_TYPE.AT_LEAST_ONE,
|
||||
description: `You gain more Infinities based on Dimension Boosts`,
|
||||
effect: () => Math.max(DimBoost.totalBoosts, 1),
|
||||
formatEffect: value => formatX(value)
|
||||
formatEffect: value => formatX(value, 2)
|
||||
},
|
||||
{
|
||||
id: 33,
|
||||
|
@ -223,8 +223,8 @@ ${Laitela.isUnlocked ? "- <b>DE</b>: Dark Energy<br>" : ""}
|
||||
}, {
|
||||
name: "Antimatter Dimensions",
|
||||
info: () => `
|
||||
Antimatter is a resource that is throughout the entire game for purchasing various things as you progress. You start
|
||||
with ${formatInt(10)} antimatter when you first open the game. And you can
|
||||
Antimatter is a resource that is used throughout the entire game for purchasing various things as you progress. You
|
||||
start with ${formatInt(10)} antimatter when you first open the game, and you can
|
||||
spend it to buy the 1st Antimatter Dimension to start the game.
|
||||
<br>
|
||||
<br>
|
||||
@ -337,7 +337,7 @@ available, but will increase the effect of your Tickspeed Upgrades by +${format(
|
||||
Galaxies. As you get more Galaxies, the multiplier will continue becoming stronger and stronger.
|
||||
<br>
|
||||
<br>
|
||||
Though it will have very little impact for the first few purchases,
|
||||
Though it will have very little impact for the first few Tickspeed purchases,
|
||||
the increase is multiplicative and won't take long to be visible.
|
||||
<br>
|
||||
<br>
|
||||
@ -1142,6 +1142,10 @@ Unlocking or defeating a Celestial has different conditions depending on the Cel
|
||||
<br>
|
||||
All Celestials have their own Celestial Reality, but how the Reality is relevant to each Celestial and the rest of
|
||||
the game will depend on the Celestial.
|
||||
<br>
|
||||
<br>
|
||||
Celestials are timeless entities. Unless otherwise stated, any new mechanics introduced by Celestials are not affected
|
||||
by game speed multipliers and instead refer specifically to real time instead of game time.
|
||||
`,
|
||||
isUnlocked: () => Teresa.isUnlocked,
|
||||
tags: ["reality", "challenges", "endgame", "lategame"],
|
||||
|
@ -165,11 +165,8 @@ GameDatabase.infinity.upgrades = {
|
||||
formatEffect: value => {
|
||||
if (Teresa.isRunning || V.isRunning) return "Disabled in this reality";
|
||||
if (Pelle.isDoomed) return "Disabled";
|
||||
const income = format(value, 2, 0);
|
||||
const period = player.records.bestInfinity.time >= 999999999999
|
||||
? "∞"
|
||||
: Time.bestInfinity.times(10).toStringShort();
|
||||
return `${income} every ${period}`;
|
||||
if (player.records.bestInfinity.time >= 999999999999) return "Too slow to generate";
|
||||
return `${format(value, 2)} every ${Time.bestInfinity.times(10).toStringShort()}`;
|
||||
},
|
||||
charged: {
|
||||
description: () =>
|
||||
|
@ -223,7 +223,9 @@ GameDatabase.news = [
|
||||
},
|
||||
{
|
||||
id: "a49",
|
||||
text: "Can we get 1e169 likes on this video??? Smash that like button!!"
|
||||
get text() {
|
||||
return `Can we get ${format(1e169)} likes on this video??? Smash that like button!!`;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "a50",
|
||||
@ -317,7 +319,7 @@ GameDatabase.news = [
|
||||
},
|
||||
{
|
||||
id: "a70",
|
||||
text: "If you can't read this you disabled the news."
|
||||
text: "If you can't read this, you disabled the news."
|
||||
},
|
||||
{
|
||||
id: "a71",
|
||||
@ -511,7 +513,8 @@ GameDatabase.news = [
|
||||
id: "a103",
|
||||
text:
|
||||
`Antimatter... antimatter never changes... until you get to quantum physics of antimatter,
|
||||
but we don't have enough tachyon particles for that.`
|
||||
but we don't have enough tachyon particles for that.`,
|
||||
get unlocked() { return PlayerProgress.realityUnlocked() || PlayerProgress.dilationUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a104",
|
||||
@ -601,7 +604,8 @@ GameDatabase.news = [
|
||||
Sacrifice' is moving away. You have to give up a lot of the things you had that made you happy, but there is
|
||||
new opportunity in where you move to. And that new opportunity gives you more happiness than you ever had.
|
||||
'Tickspeed' is how easy it is to make you happy, and 'Time Dimensions' make it even easier to be happy.
|
||||
Antimatter Dimensions is a metaphor for a depressed man's successful battle against his illness.`
|
||||
Antimatter Dimensions is a metaphor for a depressed man's successful battle against his illness.`,
|
||||
get unlocked() { return PlayerProgress.eternityUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a114",
|
||||
@ -719,7 +723,8 @@ GameDatabase.news = [
|
||||
},
|
||||
{
|
||||
id: "a134",
|
||||
text: "Because of this game I can now use the word \"infinity\" as a verb."
|
||||
text: "Because of this game I can now use the word \"infinity\" as a verb.",
|
||||
get unlocked() { return PlayerProgress.infinityUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a135",
|
||||
@ -845,7 +850,8 @@ GameDatabase.news = [
|
||||
id: "a159",
|
||||
text:
|
||||
`What does it mean when you "bank" Infinities? Is there a bank somewhere that you just deposit these
|
||||
infinities? Does having a lot of banked Infinities improve your credit score? Do you get a credit card?`
|
||||
infinities? Does having a lot of banked Infinities improve your credit score? Do you get a credit card?`,
|
||||
get unlocked() { return PlayerProgress.eternityUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a160",
|
||||
@ -1281,7 +1287,8 @@ GameDatabase.news = [
|
||||
},
|
||||
{
|
||||
id: "a223",
|
||||
text: "If you find your infinity lasting longer than 5 hours please contact a medical professional."
|
||||
text: "If you find your infinity lasting longer than 5 hours please contact a medical professional.",
|
||||
get unlocked() { return PlayerProgress.infinityUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a224",
|
||||
@ -1436,6 +1443,9 @@ GameDatabase.news = [
|
||||
${BLOB} are just blobbling and bouncing around, occasionally merging and dividing. Only ${BLOB} know where
|
||||
they are from or where they are going to go. Still, ${BLOB} are there, always with me.
|
||||
You love ${BLOB}, so ${BLOB} loves you too.`,
|
||||
S12:
|
||||
`it makes you feel warm and comfortable, as if you were right at home. However, it is highly recommended
|
||||
to update your theme to the newest theme for the best user experience.`,
|
||||
};
|
||||
const reason = reasons[Theme.current().name.replace(/\s/gu, "")];
|
||||
return `Ah, a fellow ${theme} theme user. I see that you have impeccable taste.
|
||||
@ -1511,6 +1521,7 @@ GameDatabase.news = [
|
||||
get text() {
|
||||
return `<span style='animation: a-text-stretch ${newsAnimSpd(35)}s 1 forwards'>This message is dilated.</span>`;
|
||||
},
|
||||
get unlocked() { return PlayerProgress.realityUnlocked() || PlayerProgress.dilationUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a253",
|
||||
@ -1574,7 +1585,8 @@ GameDatabase.news = [
|
||||
id: "a260",
|
||||
text:
|
||||
`It seems that the Replicanti have a very divide-and-conquer method of doing things.
|
||||
Well, everything at this rate.`
|
||||
Well, everything at this rate.`,
|
||||
get unlocked() { return PlayerProgress.eternityUnlocked() || PlayerProgress.replicantiUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a261",
|
||||
@ -2283,8 +2295,8 @@ GameDatabase.news = [
|
||||
}
|
||||
};
|
||||
}()),
|
||||
// Blob from the blob font
|
||||
{
|
||||
// Blob from the blob font
|
||||
id: "a354",
|
||||
text:
|
||||
`<span style='color: #FBC21B; text-shadow: 0px 1px 0px black, 1px 0px 0px black, 1px 1px 0px black,
|
||||
@ -2320,13 +2332,13 @@ GameDatabase.news = [
|
||||
id: "a360",
|
||||
text: `Press "Choose save" to explore the other 2 parallel universes.`
|
||||
},
|
||||
// Discord contest winner #1
|
||||
{
|
||||
// Discord contest winner #1
|
||||
id: "a361",
|
||||
text: "We're having a sale of top quality waterproof towels! Be sure to get some on your way out!"
|
||||
},
|
||||
// Discord contest winner #2
|
||||
{
|
||||
// Discord contest winner #2
|
||||
id: "a362",
|
||||
text:
|
||||
`Hevipelle Incorporated is proud to present a new brand of cereal: The Big Crunch! This nutritious breakfast
|
||||
@ -2334,7 +2346,8 @@ GameDatabase.news = [
|
||||
Replicanti, and Eternity-flavored Marshmallows. Now you can experience Antimatter Dimensions inside of your
|
||||
stomach! Warning: Side effects may include spontaneous combustion, nausea, vomiting, diarrhea,
|
||||
dematerialization, vaporization, heart failure, the end of the world, or death. If you are not made out of
|
||||
antimatter, consult an educated professional on Antimatter Consumption before eating 'The Big Crunch'.`
|
||||
antimatter, consult an educated professional on Antimatter Consumption before eating 'The Big Crunch'.`,
|
||||
get unlocked() { return PlayerProgress.eternityUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a363",
|
||||
@ -2372,7 +2385,8 @@ GameDatabase.news = [
|
||||
},
|
||||
{
|
||||
id: "a365",
|
||||
text: "I don't like Replicanti. They're coarse and rough and irritating and they replicate everywhere."
|
||||
text: "I don't like Replicanti. They're coarse and rough and irritating and they replicate everywhere.",
|
||||
get unlocked() { return PlayerProgress.eternityUnlocked() || PlayerProgress.replicantiUnlocked(); }
|
||||
},
|
||||
{
|
||||
id: "a366",
|
||||
@ -2457,8 +2471,8 @@ GameDatabase.news = [
|
||||
{
|
||||
id: "a372",
|
||||
text:
|
||||
`If you’re ever lost in a forest, look at the trees around you. It’s said that moss grows north, so by the
|
||||
time you’ve finished looking at a tree, a roaming guitarist will run up to you and ask if you want to hear
|
||||
`If you're ever lost in a forest, look at the trees around you. It's said that moss grows north, so by the
|
||||
time you've finished looking at a tree, a roaming guitarist will run up to you and ask if you want to hear
|
||||
wonderwall`
|
||||
},
|
||||
{
|
||||
@ -2500,7 +2514,7 @@ GameDatabase.news = [
|
||||
has been revealed. The first codename, as it currently stands, is “antimatter”. This conveniently works well
|
||||
with the predicted generation of phones that will use Android 20 - these phones will be the most explosive
|
||||
ever due to their annihilation-based power source. Sources tell us that a billion dollar research unit is
|
||||
working on a name for android 21, by tradition to start with B, “that doesn’t sound too bad when you think
|
||||
working on a name for android 21, by tradition to start with B, “that doesn't sound too bad when you think
|
||||
about it”. `
|
||||
},
|
||||
{
|
||||
|
@ -146,6 +146,7 @@ GameDatabase.reality.imaginaryUpgrades = [
|
||||
name: "Recollection of Intrusion",
|
||||
id: 14,
|
||||
cost: 3.5e8,
|
||||
formatCost: x => format(x, 1),
|
||||
requirement: () => `Reach a tickspeed of ${format("1e75000000000")} / sec within Eternity Challenge 5`,
|
||||
hasFailed: () => false,
|
||||
checkRequirement: () => EternityChallenge(5).isRunning && Tickspeed.perSecond.exponent >= 7.5e10,
|
||||
|
@ -143,14 +143,14 @@ GameDatabase.reality.perks = {
|
||||
},
|
||||
autounlockDilation1: {
|
||||
id: 42,
|
||||
label: "UD1",
|
||||
label: "DU1",
|
||||
family: PERK_FAMILY.DILATION,
|
||||
description: "After unlocking Dilation, automatically unlock the second row of Dilation Upgrades for free.",
|
||||
defaultPosition: new Vector(165, 565)
|
||||
},
|
||||
autounlockDilation2: {
|
||||
id: 43,
|
||||
label: "UD2",
|
||||
label: "DU2",
|
||||
family: PERK_FAMILY.DILATION,
|
||||
description: "After unlocking Dilation, automatically unlock the third row of Dilation Upgrades for free.",
|
||||
defaultPosition: new Vector(310, 605)
|
||||
@ -482,8 +482,10 @@ GameDatabase.reality.perks = {
|
||||
id: 205,
|
||||
label: "ACHNR",
|
||||
family: PERK_FAMILY.ACHIEVEMENT,
|
||||
description: "Reality no longer resets your Achievements.",
|
||||
effect: 2,
|
||||
get description() {
|
||||
return `Immediately unlock the first ${formatInt(13)} rows of Achievements
|
||||
and Reality no longer resets them.`;
|
||||
},
|
||||
automatorPoints: 10,
|
||||
shortDescription: () => "Keep Achievements on Reality",
|
||||
defaultPosition: new Vector(-195, -630)
|
||||
|
@ -311,7 +311,8 @@ GameDatabase.reality.upgrades = [
|
||||
name: "Replicative Rapidity",
|
||||
id: 23,
|
||||
cost: 100000,
|
||||
requirement: () => `Reality in under ${formatInt(15)} minutes (Best: ${Time.bestReality.toStringShort()})`,
|
||||
requirement: () => `Reality in under ${formatInt(15)} minutes of game time
|
||||
(Fastest: ${Time.bestReality.toStringShort()})`,
|
||||
hasFailed: () => Time.thisReality.totalMinutes >= 15,
|
||||
checkRequirement: () => Time.thisReality.totalMinutes < 15,
|
||||
checkEvent: GAME_EVENT.REALITY_RESET_BEFORE,
|
||||
|
@ -6,7 +6,8 @@ GameDatabase.shopPurchases = {
|
||||
key: "dimPurchases",
|
||||
cost: 30,
|
||||
description: "Double all your Antimatter Dimension multipliers. Forever.",
|
||||
multiplier: purchases => Math.pow(2, purchases)
|
||||
multiplier: purchases => Math.pow(2, purchases),
|
||||
formatEffect: x => `×${Notation.scientific.formatDecimal(new Decimal(x))}`,
|
||||
},
|
||||
allDimPurchases: {
|
||||
key: "allDimPurchases",
|
||||
@ -18,12 +19,14 @@ GameDatabase.shopPurchases = {
|
||||
return `Double ALL Dimension multipliers (${makeEnumeration(dims)}; multiplicative until 32x). Forever.`;
|
||||
},
|
||||
multiplier: purchases => (purchases > 4 ? 32 + (purchases - 5) * 2 : Math.pow(2, purchases)),
|
||||
formatEffect: x => `×${x.toFixed(0)}`,
|
||||
},
|
||||
IPPurchases: {
|
||||
key: "IPPurchases",
|
||||
cost: 40,
|
||||
description: "Double your Infinity Point gain from all sources. (additive)",
|
||||
multiplier: purchases => (purchases === 0 ? 1 : 2 * purchases),
|
||||
formatEffect: x => `×${x.toFixed(0)}`,
|
||||
isUnlocked: () => PlayerProgress.infinityUnlocked(),
|
||||
lockText: "Infinity",
|
||||
},
|
||||
@ -32,7 +35,7 @@ GameDatabase.shopPurchases = {
|
||||
cost: 60,
|
||||
description: "Increase your Replicanti gain by 50%. (additive)",
|
||||
multiplier: purchases => (purchases === 0 ? 1 : 1 + 0.5 * purchases),
|
||||
formatEffect: x => formatX(x, 2, 1),
|
||||
formatEffect: x => `×${x.toFixed(1)}`,
|
||||
isUnlocked: () => Replicanti.areUnlocked || PlayerProgress.eternityUnlocked(),
|
||||
lockText: "Replicanti",
|
||||
},
|
||||
@ -41,6 +44,7 @@ GameDatabase.shopPurchases = {
|
||||
cost: 50,
|
||||
description: "Triple your Eternity Point gain from all sources. (additive)",
|
||||
multiplier: purchases => (purchases === 0 ? 1 : 3 * purchases),
|
||||
formatEffect: x => `×${x.toFixed(0)}`,
|
||||
isUnlocked: () => PlayerProgress.eternityUnlocked(),
|
||||
lockText: "Eternity",
|
||||
},
|
||||
@ -49,7 +53,7 @@ GameDatabase.shopPurchases = {
|
||||
cost: 40,
|
||||
description: "Increase your Dilated Time gain by 50%. (additive)",
|
||||
multiplier: purchases => (purchases === 0 ? 1 : 1 + 0.5 * purchases),
|
||||
formatEffect: x => formatX(x, 2, 1),
|
||||
formatEffect: x => `×${x.toFixed(1)}`,
|
||||
isUnlocked: () => PlayerProgress.dilationUnlocked() || PlayerProgress.realityUnlocked(),
|
||||
lockText: "Dilation",
|
||||
},
|
||||
@ -58,7 +62,7 @@ GameDatabase.shopPurchases = {
|
||||
cost: 60,
|
||||
description: "Increase your Reality Machine gain by 100%. (additive)",
|
||||
multiplier: purchases => purchases + 1,
|
||||
formatEffect: x => formatX(x, 2),
|
||||
formatEffect: x => `×${x.toFixed(0)}`,
|
||||
isUnlocked: () => PlayerProgress.realityUnlocked(),
|
||||
lockText: "Reality",
|
||||
},
|
||||
|
@ -124,11 +124,14 @@ class ShopPurchaseState extends RebuyableMechanicState {
|
||||
return typeof cost === "function" ? cost() : cost;
|
||||
}
|
||||
|
||||
// ShopPurchaseData for any particular key is undefined in between page load and STD load,
|
||||
// so we need to guard against that causing NaNs to propagate through the save
|
||||
get purchases() {
|
||||
return ShopPurchaseData[this.config.key];
|
||||
return ShopPurchaseData[this.config.key] ?? 0;
|
||||
}
|
||||
|
||||
set purchases(value) {
|
||||
if (!Number.isFinite(value)) return;
|
||||
ShopPurchaseData[this.config.key] = value;
|
||||
}
|
||||
|
||||
|
@ -160,11 +160,69 @@ GameStorage.migrations = {
|
||||
},
|
||||
14: player => {
|
||||
GameStorage.migrations.reworkBHPulsing(player);
|
||||
|
||||
// Added glyph auto-sort by level; in order to keep the button state cycling consistent with the sort buttons' UI
|
||||
// order, AUTO_SORT_MODE had to be changed to insert LEVEL mode at the top and shift the others down. This
|
||||
// makes sure that older saves maintain the same settings after this shift
|
||||
if (player.reality.autoSort !== 0) player.reality.autoSort++;
|
||||
},
|
||||
15: player => {
|
||||
// Added glyph auto-sort by level; in order to keep the button state cycling consistent with the sort buttons' UI
|
||||
// order, AUTO_SORT_MODE had to be changed to insert LEVEL mode at the top and shift the others down
|
||||
if (player.reality.autoSort !== 0) player.reality.autoSort++;
|
||||
// Added additional resource tracking in last 10 prestige records and adjusted data format to be more consistent
|
||||
// by reordering to be [game time, real time, prestige currency, prestige count, challenge, ...(other resources)]
|
||||
// Also fixes a migration bug where values could be undefined or null by assigning defaults when necessary
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (player.records.lastTenInfinities) {
|
||||
const infRec = player.records.lastTenInfinities[i];
|
||||
player.records.recentInfinities[i] = [
|
||||
infRec[0] ?? Number.MAX_VALUE,
|
||||
Number(infRec[3] ?? Number.MAX_VALUE),
|
||||
new Decimal(infRec[1] ?? 1),
|
||||
new Decimal(infRec[2] ?? 1),
|
||||
""
|
||||
];
|
||||
}
|
||||
|
||||
if (player.records.lastTenEternities) {
|
||||
const eterRec = player.records.lastTenEternities[i];
|
||||
player.records.recentEternities[i] = [
|
||||
eterRec[0] ?? Number.MAX_VALUE,
|
||||
Number(eterRec[3] ?? Number.MAX_VALUE),
|
||||
new Decimal(eterRec[1] ?? 1),
|
||||
new Decimal(eterRec[2] ?? 1),
|
||||
"",
|
||||
new Decimal(0)
|
||||
];
|
||||
}
|
||||
|
||||
if (player.records.lastTenRealities) {
|
||||
const realRec = player.records.lastTenRealities[i];
|
||||
player.records.recentRealities[i] = [
|
||||
realRec[0] ?? Number.MAX_VALUE,
|
||||
Number(realRec[3] ?? Number.MAX_VALUE),
|
||||
new Decimal(realRec[1] ?? 1),
|
||||
realRec[2] ?? 1,
|
||||
"",
|
||||
0,
|
||||
0
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
delete player.records.lastTenInfinities;
|
||||
delete player.records.lastTenEternities;
|
||||
delete player.records.lastTenRealities;
|
||||
delete player.options.showLastTenResourceGain;
|
||||
|
||||
// Fixes a desync which occasionally causes unique > total seen due to total not being updated properly
|
||||
if (player.news.seen) {
|
||||
let unique = 0;
|
||||
for (const bitmaskArray of Object.values(player.news.seen)) {
|
||||
for (const bitmask of bitmaskArray) {
|
||||
unique += countValuesFromBitmask(bitmask);
|
||||
}
|
||||
}
|
||||
player.news.totalSeen = Math.max(player.news.totalSeen, unique);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -71,6 +71,16 @@ function findLastOpenSubtab(tabId, subtabs) {
|
||||
return subtabs.find(s => s.id === player.options.lastOpenSubtab[tabId]) ?? subtabs[0];
|
||||
}
|
||||
|
||||
function cycleThroughSubtabs(subtabs, currentSubtab) {
|
||||
const availableTabs = subtabs.filter(tab => tab.isAvailable);
|
||||
const currentIndex = availableTabs.indexOf(currentSubtab);
|
||||
const direction = ui.view.shiftDown ? -1 : 1;
|
||||
let newIndex = currentIndex + direction;
|
||||
newIndex = newIndex < 0 ? availableTabs.length - 1 : newIndex;
|
||||
newIndex = newIndex > availableTabs.length - 1 ? 0 : newIndex;
|
||||
return availableTabs[newIndex];
|
||||
}
|
||||
|
||||
class TabState {
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
@ -129,17 +139,19 @@ class TabState {
|
||||
|
||||
show(manual, subtab = undefined) {
|
||||
if (!manual && !player.options.automaticTabSwitching || Quote.isOpen) return;
|
||||
ui.view.tab = this.key;
|
||||
if (subtab === undefined) {
|
||||
this._currentSubtab = findLastOpenSubtab(this.id, this.subtabs);
|
||||
} else {
|
||||
if (subtab !== undefined) {
|
||||
if (!Enslaved.isRunning) subtab.unhideTab();
|
||||
this._currentSubtab = subtab;
|
||||
} else if (ui.view.tab === this.key && ui.view.initialized) {
|
||||
this._currentSubtab = cycleThroughSubtabs(this.subtabs, this._currentSubtab);
|
||||
} else {
|
||||
this._currentSubtab = findLastOpenSubtab(this.id, this.subtabs);
|
||||
}
|
||||
|
||||
if (!this._currentSubtab.isUnlocked) this.resetToUnlocked();
|
||||
if (!this._currentSubtab.isAvailable) this.resetToAvailable();
|
||||
|
||||
ui.view.tab = this.key;
|
||||
ui.view.subtab = this._currentSubtab.key;
|
||||
const tabNotificationKey = this.key + this._currentSubtab.key;
|
||||
if (player.tabNotifications.has(tabNotificationKey)) player.tabNotifications.delete(tabNotificationKey);
|
||||
|
@ -179,42 +179,20 @@ export function ratePerMinute(amount, time) {
|
||||
return Decimal.divide(amount, time / (60 * 1000));
|
||||
}
|
||||
|
||||
export function averageRun(allRuns, name) {
|
||||
// Filter out all runs which have the default infinite value for time, but if we're left with no valid runs then we
|
||||
// take just one entry so that the averages also have the same value and we don't get division by zero.
|
||||
let runs = allRuns.filter(run => run[0] !== Number.MAX_VALUE);
|
||||
if (runs.length === 0) runs = [allRuns[0]];
|
||||
const totalTime = runs.map(run => run[0]).sum();
|
||||
const totalAmount = runs
|
||||
.map(run => run[1])
|
||||
.reduce(Decimal.sumReducer);
|
||||
const totalPrestigeGain = runs
|
||||
.map(run => run[2])
|
||||
.reduce(name === "Reality" ? Number.sumReducer : Decimal.sumReducer);
|
||||
const realTime = runs.map(run => run[3]).sum();
|
||||
const average = [
|
||||
totalTime / runs.length,
|
||||
totalAmount.dividedBy(runs.length),
|
||||
(name === "Reality") ? totalPrestigeGain / runs.length : totalPrestigeGain.dividedBy(runs.length),
|
||||
realTime / runs.length
|
||||
];
|
||||
if (name === "Reality") {
|
||||
average.push(runs.map(x => x[4]).sum() / runs.length);
|
||||
}
|
||||
return average;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line max-params
|
||||
export function addInfinityTime(time, realTime, ip, infinities) {
|
||||
player.records.lastTenInfinities.pop();
|
||||
player.records.lastTenInfinities.unshift([time, ip, infinities, realTime]);
|
||||
let challenge = "";
|
||||
if (player.challenge.normal.current) challenge = `Normal Challenge ${player.challenge.normal.current}`;
|
||||
if (player.challenge.infinity.current) challenge = `Infinity Challenge ${player.challenge.infinity.current}`;
|
||||
player.records.recentInfinities.pop();
|
||||
player.records.recentInfinities.unshift([time, realTime, ip, infinities, challenge]);
|
||||
GameCache.bestRunIPPM.invalidate();
|
||||
}
|
||||
|
||||
export function resetInfinityRuns() {
|
||||
player.records.lastTenInfinities = Array.from(
|
||||
player.records.recentInfinities = Array.from(
|
||||
{ length: 10 },
|
||||
() => [Number.MAX_VALUE, DC.D1, DC.D1, Number.MAX_VALUE]
|
||||
() => [Number.MAX_VALUE, Number.MAX_VALUE, DC.D1, DC.D1, ""]
|
||||
);
|
||||
GameCache.bestRunIPPM.invalidate();
|
||||
}
|
||||
@ -229,15 +207,24 @@ export function getInfinitiedMilestoneReward(ms, considerMilestoneReached) {
|
||||
|
||||
// eslint-disable-next-line max-params
|
||||
export function addEternityTime(time, realTime, ep, eternities) {
|
||||
player.records.lastTenEternities.pop();
|
||||
player.records.lastTenEternities.unshift([time, ep, eternities, realTime]);
|
||||
let challenge = "";
|
||||
if (player.challenge.eternity.current) {
|
||||
const currEC = player.challenge.eternity.current;
|
||||
const ec = EternityChallenge(currEC);
|
||||
const challText = player.dilation.active ? "Dilated EC" : "Eternity Challenge";
|
||||
challenge = `${challText} ${currEC} (${formatInt(ec.completions)}/${formatInt(ec.maxCompletions)})`;
|
||||
} else if (player.dilation.active) challenge = "Time Dilation";
|
||||
// If we call this function outside of dilation, it uses the existing AM and produces an erroneous number
|
||||
const gainedTP = player.dilation.active ? getTachyonGain() : DC.D0;
|
||||
player.records.recentEternities.pop();
|
||||
player.records.recentEternities.unshift([time, realTime, ep, eternities, challenge, gainedTP]);
|
||||
GameCache.averageRealTimePerEternity.invalidate();
|
||||
}
|
||||
|
||||
export function resetEternityRuns() {
|
||||
player.records.lastTenEternities = Array.from(
|
||||
player.records.recentEternities = Array.from(
|
||||
{ length: 10 },
|
||||
() => [Number.MAX_VALUE, DC.D1, DC.D1, Number.MAX_VALUE]
|
||||
() => [Number.MAX_VALUE, Number.MAX_VALUE, DC.D1, DC.D1, "", DC.D0]
|
||||
);
|
||||
GameCache.averageRealTimePerEternity.invalidate();
|
||||
}
|
||||
@ -262,8 +249,14 @@ export function getOfflineEPGain(ms) {
|
||||
|
||||
// eslint-disable-next-line max-params
|
||||
export function addRealityTime(time, realTime, rm, level, realities) {
|
||||
player.records.lastTenRealities.pop();
|
||||
player.records.lastTenRealities.unshift([time, rm, realities, realTime, level]);
|
||||
let reality = "";
|
||||
const celestials = [Teresa, Effarig, Enslaved, V, Ra, Laitela];
|
||||
for (const cel of celestials) {
|
||||
if (cel.isRunning) reality = cel.displayName;
|
||||
}
|
||||
const shards = Effarig.shardsGained;
|
||||
player.records.recentRealities.pop();
|
||||
player.records.recentRealities.unshift([time, realTime, rm, realities, reality, level, shards]);
|
||||
}
|
||||
|
||||
export function gainedInfinities() {
|
||||
@ -547,21 +540,13 @@ export function gameLoop(passDiff, options = {}) {
|
||||
const gain = Math.clampMin(FreeTickspeed.fromShards(Currency.timeShards.value).newAmount - player.totalTickGained, 0);
|
||||
player.totalTickGained += gain;
|
||||
|
||||
const currentIPmin = gainedInfinityPoints().dividedBy(Math.clampMin(0.0005, Time.thisInfinityRealTime.totalMinutes));
|
||||
if (currentIPmin.gt(player.records.thisInfinity.bestIPmin) && Player.canCrunch)
|
||||
player.records.thisInfinity.bestIPmin = currentIPmin;
|
||||
|
||||
updatePrestigeRates();
|
||||
tryCompleteInfinityChallenges();
|
||||
|
||||
EternityChallenges.autoComplete.tick();
|
||||
|
||||
replicantiLoop(diff);
|
||||
|
||||
|
||||
const currentEPmin = gainedEternityPoints().dividedBy(Math.clampMin(0.0005, Time.thisEternityRealTime.totalMinutes));
|
||||
if (currentEPmin.gt(player.records.thisEternity.bestEPmin) && Player.canEternity)
|
||||
player.records.thisEternity.bestEPmin = currentEPmin;
|
||||
|
||||
if (PlayerProgress.dilationUnlocked()) {
|
||||
Currency.dilatedTime.add(getDilationGainPerSecond().times(diff / 1000));
|
||||
}
|
||||
@ -631,6 +616,26 @@ export function gameLoop(passDiff, options = {}) {
|
||||
PerformanceStats.end("Game Update");
|
||||
}
|
||||
|
||||
function updatePrestigeRates() {
|
||||
const currentIPmin = gainedInfinityPoints().dividedBy(Math.clampMin(0.0005, Time.thisInfinityRealTime.totalMinutes));
|
||||
if (currentIPmin.gt(player.records.thisInfinity.bestIPmin) && Player.canCrunch) {
|
||||
player.records.thisInfinity.bestIPmin = currentIPmin;
|
||||
player.records.thisInfinity.bestIPminVal = gainedInfinityPoints();
|
||||
}
|
||||
|
||||
const currentEPmin = gainedEternityPoints().dividedBy(Math.clampMin(0.0005, Time.thisEternityRealTime.totalMinutes));
|
||||
if (currentEPmin.gt(player.records.thisEternity.bestEPmin) && Player.canEternity) {
|
||||
player.records.thisEternity.bestEPmin = currentEPmin;
|
||||
player.records.thisEternity.bestEPminVal = gainedEternityPoints();
|
||||
}
|
||||
|
||||
const currentRSmin = Effarig.shardsGained / Math.clampMin(0.0005, Time.thisRealityRealTime.totalMinutes);
|
||||
if (currentRSmin > player.records.thisReality.bestRSmin && isRealityAvailable()) {
|
||||
player.records.thisReality.bestRSmin = currentRSmin;
|
||||
player.records.thisReality.bestRSminVal = Effarig.shardsGained;
|
||||
}
|
||||
}
|
||||
|
||||
function passivePrestigeGen() {
|
||||
let eternitiedGain = 0;
|
||||
if (RealityUpgrade(14).isBought) {
|
||||
|
BIN
public/audio/s12-startup.mp3
Normal file
BIN
public/images/s12-bg.jpg
Normal file
After Width: | Height: | Size: 628 KiB |
BIN
public/images/s12/achievements.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/images/s12/automation.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/images/s12/celestials.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
public/images/s12/challenges.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
public/images/s12/desktop--discord-logo.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
public/images/s12/desktop--games.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
public/images/s12/desktop--windows-media-player.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
public/images/s12/dimensions.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
public/images/s12/eternity.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
public/images/s12/game--alkahistorian.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/images/s12/game--anti-idle.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
public/images/s12/game--hex-game.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
1
public/images/s12/game--melvor-idle.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 465.39 513.15"><defs><style>.cls-1{fill:#bd1818;}.cls-2{fill:#e52320;}.cls-3{fill:#dc9f12;}.cls-4{fill:#f4df61;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="20.21 115.95 32.02 124.19 32.02 135.2 20.21 139.25 20.21 115.95"/><polygon class="cls-2" points="349.47 473.5 319.37 451.96 319.37 120.21 349.47 106.41 349.47 473.5"/><polygon class="cls-1" points="64.88 101.04 76.69 109.47 76.69 119.87 64.88 123.92 64.88 101.04"/><polygon class="cls-2" points="349.47 84.33 319.37 105.56 319.37 120.21 349.47 120.05 349.47 84.33"/><polygon class="cls-2" points="445.18 115.95 433.38 123.92 433.38 135.2 445.18 139.25 445.18 115.95"/><polygon class="cls-2" points="400.51 101.04 388.7 109.19 388.7 119.87 400.51 123.92 400.51 101.04"/><polygon class="cls-2" points="349.47 148.97 319.44 148.97 232.73 209.23 232.73 233.27 349.47 148.97"/><polygon class="cls-1" points="146.02 148.97 145.87 148.98 145.87 120.21 145.87 106.17 115.91 84.33 115.91 106.41 115.91 120.05 115.91 473.5 145.87 452.03 145.87 171.27 232.73 233.27 232.73 209.23 146.02 148.97"/><polygon class="cls-2" points="232.73 233.27 115.92 149.89 115.92 120.05 115.92 120.05 115.92 84.33 85.82 93.64 85.82 116.74 64.88 123.92 64.88 101.04 41.37 108.9 41.37 131.99 20.21 139.25 20.21 115.95 0 122.66 0 146.19 0 146.19 0 205.18 26.54 224.19 26.54 458.69 115.92 473.5 115.92 310.95 232.73 399.41 232.73 233.27"/><polygon class="cls-1" points="445.18 115.95 445.18 139.25 424.02 131.99 424.02 108.89 400.51 101.04 400.51 123.92 379.57 116.74 379.57 93.64 349.47 84.33 349.47 106.41 349.47 120.05 349.47 148.97 232.73 233.27 232.73 399.41 349.47 309.54 349.47 473.5 438.17 462.82 438.17 224.19 465.39 205.16 465.39 148.97 465.39 146.19 465.39 122.66 445.18 115.95"/><path class="cls-3" d="M232.7,416.27h0v96.89l.8-1.1,31.12-44.37c-4.5-8.09-6.84-40.89-8.06-70.72Z"/><path class="cls-3" d="M241.18,23.83l5.26,60,40.82,0,14.06,14.64-16.44,15.93-10.69-11.06h-8.71c-4.14,4.34-7.3,9.8-7.53,16.46v54.11L232.7,193.84h0V0a12.73,12.73,0,0,1,11.65,12.66Z"/><path class="cls-4" d="M232.68,416.27h0v96.89l-.81-1.1-31.11-44.37c4.49-8.09,6.84-40.89,8-70.72Z"/><path class="cls-4" d="M224,23.83l-5.07,60-40.82,0L164.07,98.48l16.44,15.93,10.69-11.06h8.71c4.14,4.34,7.3,9.8,7.53,16.46v54.11l25.25,19.92h0V0a12.73,12.73,0,0,0-11.64,12.66Z"/></g></g></svg>
|
After Width: | Height: | Size: 2.4 KiB |
BIN
public/images/s12/game--mine-defense.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
public/images/s12/game--monies2.png
Normal file
After Width: | Height: | Size: 766 B |
BIN
public/images/s12/game--synergism.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/images/s12/game--trimps.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
public/images/s12/game--universal-paperclips.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
public/images/s12/game--wami.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/images/s12/infinity.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
public/images/s12/options.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/images/s12/reality.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
public/images/s12/shop.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
public/images/s12/statistics.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
public/images/s12/win7-start-menu-inactive.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
public/images/s12/xmark.png
Normal file
After Width: | Height: | Size: 323 B |
@ -14,8 +14,13 @@
|
||||
--color-eternity--bg: #b341e04d;
|
||||
}
|
||||
|
||||
:root .t-s12 {
|
||||
--sidebar-width: 0;
|
||||
}
|
||||
|
||||
:root .t-normal,
|
||||
:root .t-s9 {
|
||||
:root .t-s9,
|
||||
:root .t-s12 {
|
||||
--color-text: #ffffff;
|
||||
--color-text-inverted: black;
|
||||
--color-base: #1d1b22;
|
||||
@ -41,7 +46,8 @@
|
||||
}
|
||||
|
||||
body.t-normal,
|
||||
body.t-s9 {
|
||||
body.t-s9,
|
||||
body.t-s12 {
|
||||
color: white;
|
||||
background-color: #111014;
|
||||
}
|
||||
@ -549,7 +555,8 @@ body.t-s9 {
|
||||
background-color: var(--color-infinity);
|
||||
}
|
||||
|
||||
.t-normal .c-game-header__tesseract-available {
|
||||
.t-normal .c-game-header__tesseract-available,
|
||||
.t-s12 .c-game-header__tesseract-available {
|
||||
background: #eeeeee;
|
||||
animation: a-tesseract-shift-dark 5s infinite;
|
||||
}
|
||||
@ -570,12 +577,14 @@ body.t-s9 {
|
||||
margin: 0.6rem 0.4rem;
|
||||
}
|
||||
|
||||
.t-normal .o-achievement__tooltip {
|
||||
.t-normal .o-achievement__tooltip,
|
||||
.t-s12 .o-achievement__tooltip {
|
||||
background: var(--color-base);
|
||||
border: 0.1rem solid var(--color-accent);
|
||||
}
|
||||
|
||||
.t-normal .o-achievement__tooltip::after {
|
||||
.t-normal .o-achievement__tooltip::after,
|
||||
.t-s12 .o-achievement__tooltip::after {
|
||||
border-top-color: var(--color-accent);
|
||||
}
|
||||
|
||||
@ -891,11 +900,13 @@ body.t-s9 {
|
||||
color: var(--color-eternity);
|
||||
}
|
||||
|
||||
.t-normal .c-game-header__antimatter {
|
||||
.t-normal .c-game-header__antimatter,
|
||||
.t-s12 .c-game-header__antimatter {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.t-normal .c-credits-header {
|
||||
.t-normal .c-credits-header,
|
||||
.t-s12 .c-credits-header {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
@ -924,17 +935,20 @@ body.t-s9 {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.t-normal .c-sacrificed-glyphs--dragover {
|
||||
.t-normal .c-sacrificed-glyphs--dragover,
|
||||
.t-s12 .c-sacrificed-glyphs--dragover {
|
||||
border-color: rgb(255, 255, 255);
|
||||
box-shadow: 0 0 0.1rem 0.1rem rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.t-normal .c-glyph-choice-icon {
|
||||
.t-normal .c-glyph-choice-icon,
|
||||
.t-s12 .c-glyph-choice-icon {
|
||||
background-color: rgba(0, 0, 0, 30%);
|
||||
border: var(--var-border-width, 0.2rem) solid rgba(0, 0, 0, 40%);
|
||||
}
|
||||
|
||||
.t-normal .c-glyph-choice-effect-list {
|
||||
.t-normal .c-glyph-choice-effect-list,
|
||||
.t-s12 .c-glyph-choice-effect-list {
|
||||
background-color: rgba(0, 0, 0, 30%);
|
||||
border: var(--var-border-width, 0.2rem) solid rgba(0, 0, 0, 40%);
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
@font-face {
|
||||
font-family: Typewriter;
|
||||
src: url("MonospaceTypewriter.ttf");
|
||||
}
|
||||
|
||||
#ui {
|
||||
scrollbar-gutter: stable both-edges;
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ body {
|
||||
|
||||
@font-face {
|
||||
font-family: Typewriter;
|
||||
src: url("MonospaceTypewriter.ttf");
|
||||
src: url("BlobEmoji-Bold.ttf"), url("MonospaceTypewriter.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -304,11 +304,6 @@ body {
|
||||
src: url("fa-solid-900.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Typewriter;
|
||||
src: url("BlobEmoji-Bold.ttf"), url("MonospaceTypewriter.ttf");
|
||||
}
|
||||
|
||||
/* Background for s6 and s10 is not displayed by default */
|
||||
#stars {
|
||||
display: none;
|
||||
@ -2754,8 +2749,10 @@ br {
|
||||
overflow: hidden;
|
||||
background-color: var(--color-base);
|
||||
border: 0.1rem var(--color-good);
|
||||
border-style: none solid solid;
|
||||
border-style: solid;
|
||||
border-radius: var(--var-border-radius, 0.4rem);
|
||||
/* May be removed if it makes things to blurry */
|
||||
transform: translateY(-0.1rem);
|
||||
}
|
||||
|
||||
/* We need scrollbar-color in this rule as well as identical color specifications in the following two; some
|
||||
@ -5361,7 +5358,7 @@ properly on certain themes. */
|
||||
border: var(--var-border-width, 0.3rem) solid black;
|
||||
border-radius: var(--var-border-radius, 0.6rem);
|
||||
padding: 1rem;
|
||||
transition-duration: 0.2s;
|
||||
transition: all 0.2s, left 0s, top 0s, transform 0s;
|
||||
}
|
||||
|
||||
.c-modal--short {
|
||||
@ -7496,6 +7493,10 @@ kbd {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.c-ra-pet-remembrance-button:hover {
|
||||
box-shadow: 0 0 1rem inset var(--color-ra--base);
|
||||
}
|
||||
|
||||
.s-base--metro .c-ra-pet-remembrance-button {
|
||||
border-color: black;
|
||||
}
|
||||
@ -8075,7 +8076,7 @@ kbd {
|
||||
}
|
||||
|
||||
.o-laitela-run-button {
|
||||
width: 22rem;
|
||||
width: 24rem;
|
||||
height: 84rem;
|
||||
font-family: Typewriter;
|
||||
font-size: 1.1rem;
|
||||
@ -8276,7 +8277,7 @@ kbd {
|
||||
|
||||
.c-laitela-singularity-container {
|
||||
display: flex;
|
||||
width: 96rem;
|
||||
width: 98rem;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
color: var(--color-laitela--accent);
|
||||
@ -8877,39 +8878,40 @@ kbd {
|
||||
}
|
||||
|
||||
.c-reality-upgrade-btn--possible {
|
||||
color: black;
|
||||
/* Text color gets inherited from other pseudo-classes; so we use !important here in order to ensure good contrast
|
||||
specifically on reality and imaginary upgrades, the only upgrades which use this and the related --locked below */
|
||||
color: black !important;
|
||||
background:
|
||||
repeating-linear-gradient(
|
||||
-45deg,
|
||||
#979729,
|
||||
#979729 3rem,
|
||||
#777722 3rem,
|
||||
#777722 6rem
|
||||
#A2A229,
|
||||
#A2A229 3rem,
|
||||
#919122 3rem,
|
||||
#919122 6rem
|
||||
);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.c-reality-upgrade-btn--possible:hover {
|
||||
color: black;
|
||||
background-color: #8b8529;
|
||||
/* This is actually a solid color, but it flickers on hover if we don't make it a linear-gradient */
|
||||
background: linear-gradient(0deg, #919122, #919122);
|
||||
}
|
||||
|
||||
.c-reality-upgrade-btn--locked {
|
||||
color: black;
|
||||
background: #954040;
|
||||
color: white !important;
|
||||
background: #952020;
|
||||
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%);
|
||||
linear-gradient(45deg, #802222 25%, transparent 25%),
|
||||
linear-gradient(135deg, #802222 25%, transparent 25%),
|
||||
linear-gradient(45deg, transparent 75%, #802222 75%),
|
||||
linear-gradient(135deg, transparent 75%, #802222 75%);
|
||||
background-position: 0 0, 2rem 0, 2rem -2rem, 0 2rem;
|
||||
background-size: 4rem 4rem;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.c-reality-upgrade-btn--locked:hover {
|
||||
color: var(--color-reality-light);
|
||||
background-color: #a53939;
|
||||
background-color: #802222;
|
||||
}
|
||||
|
||||
.c-reality-upgrade-btn--black-hole-unlock {
|
||||
@ -8922,11 +8924,6 @@ kbd {
|
||||
background-color: #37474f;
|
||||
}
|
||||
|
||||
.t-dark .c-reality-upgrade-btn--locked {
|
||||
color: var(--color-reality-light);
|
||||
background-color: var(--color-bad);
|
||||
}
|
||||
|
||||
.t-s6.c-reality-upgrade-btn:hover,
|
||||
.t-s10.c-reality-upgrade-btn:hover {
|
||||
background-color: var(--color-reality-light);
|
||||
@ -9257,6 +9254,11 @@ input.o-automator-block-input {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.t-s12 .l-h2p-body {
|
||||
font-size: 1.3rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.l-h2p-body::-webkit-scrollbar {
|
||||
width: 1rem;
|
||||
}
|
||||
@ -9318,6 +9320,10 @@ input.o-automator-block-input {
|
||||
border-bottom: 0.1rem solid white;
|
||||
}
|
||||
|
||||
.t-s12 .o-h2p-tab-button {
|
||||
border-bottom: 0.1rem solid black;
|
||||
}
|
||||
|
||||
.l-help-me {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
|
@ -1,8 +1,3 @@
|
||||
@font-face {
|
||||
font-family: Typewriter;
|
||||
src: url("BlobEmoji-Bold.ttf"), url("MonospaceTypewriter.ttf");
|
||||
}
|
||||
|
||||
body.t-s11 {
|
||||
color: #999999;
|
||||
background: black;
|
||||
|
326
public/stylesheets/theme-S12.css
Normal file
@ -0,0 +1,326 @@
|
||||
body.t-s12 {
|
||||
--s12-taskbar-height: 4.5rem;
|
||||
--s12-border-color: #27221e;
|
||||
--s12-background-gradient:
|
||||
repeating-linear-gradient(
|
||||
50deg,
|
||||
rgba(170, 170, 170, 10%),
|
||||
rgba(170, 170, 170, 10%) 2rem,
|
||||
rgba(255, 255, 255, 10%) 4rem,
|
||||
rgba(255, 255, 255, 10%) 5rem,
|
||||
rgba(170, 170, 170, 10%) 6rem,
|
||||
rgba(170, 170, 170, 10%) 8rem
|
||||
),
|
||||
linear-gradient(
|
||||
-50deg,
|
||||
rgba(60, 60, 60, 30%),
|
||||
transparent 20%,
|
||||
transparent 80%,
|
||||
rgba(60, 60, 60, 30%)
|
||||
);
|
||||
|
||||
height: 100%;
|
||||
background: url("../images/s12-bg.jpg") no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-color: #1bb9ee;
|
||||
|
||||
/* Center and scale the image nicely */
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.t-s12 .container {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.t-s12 #ui {
|
||||
justify-content: flex-start;
|
||||
/* stylelint-disable-next-line unit-allowed-list */
|
||||
perspective: 200vh;
|
||||
|
||||
scrollbar-gutter: auto;
|
||||
}
|
||||
|
||||
.t-s12 .ui-wrapper {
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.c-s12-close-button,
|
||||
.t-s12 .c-modal .c-modal__close-btn {
|
||||
display: flex;
|
||||
width: 5rem;
|
||||
height: 1.8rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 1rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 0;
|
||||
background-image:
|
||||
url("../images/s12/xmark.png"),
|
||||
linear-gradient(to bottom, rgba(255, 255, 255, 40%) 40%, transparent 60%),
|
||||
radial-gradient(#b43721, #844740);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
border: 0.15rem solid var(--s12-border-color);
|
||||
border-top: none;
|
||||
border-radius: 0 0 0.5rem 0.5rem;
|
||||
box-shadow: inset 0 0 0.2rem 0.1rem rgba(255, 255, 255, 80%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.c-modal__close-btn--disabled {
|
||||
filter: grayscale(1);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.c-s12-close-button::before,
|
||||
.t-s12 .c-modal .c-modal__close-btn:not(.c-modal__close-btn--disabled)::before {
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
background-image:
|
||||
url("../images/s12/xmark.png"),
|
||||
linear-gradient(to bottom, transparent 50%, rgba(224, 178, 64, 60%));
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: inherit;
|
||||
box-shadow: 0 0 1rem 0.3rem #d35532;
|
||||
transition: opacity 0.4s;
|
||||
}
|
||||
|
||||
.c-s12-close-button:hover::before,
|
||||
.c-modal__close-btn:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal {
|
||||
--color-text: black;
|
||||
--color-text-inverted: white;
|
||||
max-width: calc(100% - 10rem);
|
||||
font-family: "Segoe UI", Typewriter;
|
||||
font-weight: normal;
|
||||
background-color: rgba(187, 216, 242, 75%);
|
||||
background-image: var(--s12-background-gradient);
|
||||
border: 0.1rem solid var(--s12-border-color);
|
||||
padding: 2.4rem 1rem 1rem;
|
||||
|
||||
-webkit-backdrop-filter: blur(1rem);
|
||||
backdrop-filter: blur(1rem);
|
||||
}
|
||||
|
||||
.t-s12 .c-modal__inner:not(.c-credits-modal),
|
||||
.t-s12 .c-modal-message,
|
||||
.t-s12 .l-h2p-modal,
|
||||
.t-s12 .c-information-modal,
|
||||
.t-s12 .l-changelog-modal,
|
||||
.t-s12 .c-modal-away-progress {
|
||||
align-items: flex-start;
|
||||
text-align: left;
|
||||
font-size: 1.3rem;
|
||||
color: black;
|
||||
background-color: #f0f0f0;
|
||||
border: 0.1rem solid var(--s12-border-color);
|
||||
margin: 0;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.t-s12 .modal-progress-bar,
|
||||
.t-s12 .c-credits-modal {
|
||||
color: black;
|
||||
background-color: #f0f0f0;
|
||||
border: 0.1rem solid var(--s12-border-color);
|
||||
box-sizing: border-box;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal-options__large {
|
||||
width: 53rem;
|
||||
}
|
||||
|
||||
.t-s12 .l-singularity-milestone-modal-container-inner .c-laitela-milestone {
|
||||
text-align: center;
|
||||
font-family: Typewriter;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal__title,
|
||||
.t-s12 .l-h2p-header,
|
||||
.t-s12 .l-changelog-header {
|
||||
display: flex;
|
||||
width: auto;
|
||||
height: 2.2rem;
|
||||
position: absolute;
|
||||
top: 0.2rem;
|
||||
left: 0;
|
||||
align-items: center;
|
||||
font-size: 1.3rem;
|
||||
font-weight: normal;
|
||||
text-shadow: 0 0 0.7rem white;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.c-credits-modal .c-modal__title {
|
||||
display: inline;
|
||||
position: static;
|
||||
}
|
||||
|
||||
.c-credits-modal .c-game-header__antimatter {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.t-s12 .c-h2p-title,
|
||||
.t-s12 .c-changelog-title {
|
||||
font-size: 1.3rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal__confirmation-toggle {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal__confirmation-toggle__checkbox {
|
||||
width: 1.6rem;
|
||||
height: 1.6rem;
|
||||
color: #4b6192;
|
||||
background: linear-gradient(-45deg, #ffffffff, #aeb2b5);
|
||||
border: 0.2rem solid white;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 0.1rem 0.1rem var(--s12-border-color), inset 0 0 0.1rem 0.1rem #a0a0a0;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal__confirmation-toggle:hover .c-modal__confirmation-toggle__checkbox {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn:not(.c-modal__close-btn, .c-autobuyer-box__mode-select),
|
||||
.t-s12 .c-new-game-button {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
align-self: flex-end;
|
||||
text-align: center;
|
||||
font-family: "Segoe UI", Typewriter;
|
||||
font-weight: normal;
|
||||
color: black;
|
||||
background-image: linear-gradient(to bottom, white 45%, #d7d7d7 55%);
|
||||
border: 0.16rem solid #747474;
|
||||
box-shadow: inset 0 0 0.2rem 0.1rem white;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
transition: box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.t-s12 .c-new-game-button {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn.c-select-notation__item,
|
||||
.t-s12 .c-modal .o-primary-btn.c-select-theme__item {
|
||||
background-color: white;
|
||||
background-image: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn.c-select-notation__item::before,
|
||||
.t-s12 .c-modal .o-primary-btn.c-select-theme__item::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn.c-dropdown-btn {
|
||||
z-index: 1;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .l-select-notation,
|
||||
.t-s12 .c-modal .l-select-theme {
|
||||
scrollbar-color: #747474 white;
|
||||
border-color: #747474;
|
||||
}
|
||||
|
||||
.l-select-notation__inner::-webkit-scrollbar,
|
||||
.l-select-theme__inner::-webkit-scrollbar {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .l-select-notation__inner::-webkit-scrollbar-thumb,
|
||||
.t-s12 .c-modal .l-select-theme__inner::-webkit-scrollbar-thumb {
|
||||
background-color: #747474;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn--disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn:not(.c-modal__close-btn, .c-autobuyer-box__mode-select)::after,
|
||||
.t-s12 .c-new-game-button::after {
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
background-color: transparent;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn:not(.c-modal__close-btn):hover,
|
||||
.t-s12 .c-new-game-button:hover {
|
||||
box-shadow: inset 0 0 0.2rem 0.1rem #52d9fb;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn:not(.c-modal__close-btn):hover::after,
|
||||
.t-s12 .c-new-game-button:hover::after {
|
||||
background-color: rgba(46, 210, 255, 30%);
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .o-primary-btn.o-primary-btn.c-select-notation__item:hover,
|
||||
.t-s12 .c-modal .o-primary-btn.o-primary-btn.c-select-theme__item:hover {
|
||||
color: white;
|
||||
background-color: #2a90ff;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.t-s12 .l-modal-buttons {
|
||||
align-self: flex-end;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.t-s12 .c-modal__confirmation-toggle__tooltip {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.t-s12 .l-modal-options__save-record {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.t-s12 .modal-progress-bar__bg {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-image: linear-gradient(to right, #cbcbcb 90%, #c0c0c0);
|
||||
border: 0.1rem solid var(--s12-border-color);
|
||||
border-radius: 0.2rem;
|
||||
box-shadow: inset 0 0 0.2rem 0.1rem white;
|
||||
}
|
||||
|
||||
.t-s12 .modal-progress-bar__bg::before {
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: linear-gradient(rgba(255, 255, 255, 70%) 30%, transparent 40%);
|
||||
}
|
||||
|
||||
.t-s12 .modal-progress-bar__fg {
|
||||
background: linear-gradient(to right, #0cb826, #20da3e 20%, #20da3e 80%, #0cb826);
|
||||
}
|
||||
|
||||
.t-s12 .c-modal .c-autobuyer-box-row {
|
||||
text-align: center;
|
||||
background-color: transparent;
|
||||
}
|
@ -11,6 +11,7 @@ export default {
|
||||
computed: {
|
||||
people() { return GameDatabase.credits.people; },
|
||||
roles() { return GameDatabase.credits.roles; },
|
||||
isS12EndDisplay() { return this.$viewModel.theme === "S12" && !this.isModal; },
|
||||
},
|
||||
methods: {
|
||||
relevantPeople(role) {
|
||||
@ -23,7 +24,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div :class="{ 'c-credits-s12-end': isS12EndDisplay }">
|
||||
<h1
|
||||
v-if="!isModal"
|
||||
class="c-credits-header"
|
||||
@ -60,6 +61,11 @@ export default {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.c-credits-s12-end {
|
||||
--color-text: white;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.c-credits-header {
|
||||
color: black;
|
||||
}
|
||||
@ -70,6 +76,10 @@ export default {
|
||||
animation: a-credits-header--glow 25s infinite;
|
||||
}
|
||||
|
||||
.t-s12 .c-credits-header {
|
||||
color: var(--color-antimatter);
|
||||
}
|
||||
|
||||
@keyframes a-credits-header--glow {
|
||||
0% { color: #2196f3; }
|
||||
33% { color: #673ab7; }
|
||||
|
@ -5,6 +5,10 @@ import GameUiComponentFixed from "@/components/GameUiComponentFixed";
|
||||
import ModernUi from "@/components/ui-modes/modern/ModernUi";
|
||||
import TabComponents from "@/components/tabs";
|
||||
|
||||
import S12DesktopIcons from "@/components/ui-modes/s12/DesktopIcons";
|
||||
import S12Ui from "@/components/ui-modes/s12/S12Ui";
|
||||
import S12UiFixed from "@/components/ui-modes/s12/S12UiFixed";
|
||||
|
||||
export default {
|
||||
name: "GameUIComponent",
|
||||
components: {
|
||||
@ -13,12 +17,19 @@ export default {
|
||||
ModernUi,
|
||||
GameUiComponentFixed,
|
||||
BackgroundAnimations,
|
||||
S12Ui,
|
||||
S12UiFixed,
|
||||
S12DesktopIcons,
|
||||
},
|
||||
computed: {
|
||||
view() {
|
||||
return this.$viewModel;
|
||||
},
|
||||
isThemeS12() {
|
||||
return this.view.theme === "S12";
|
||||
},
|
||||
uiLayout() {
|
||||
if (this.isThemeS12) return "S12Ui";
|
||||
return this.view.newUI ? "ModernUi" : "ClassicUi";
|
||||
},
|
||||
containerClass() {
|
||||
@ -52,6 +63,7 @@ export default {
|
||||
class="c-game-tab"
|
||||
/>
|
||||
</component>
|
||||
<S12DesktopIcons v-if="isThemeS12" />
|
||||
<link
|
||||
v-if="view.theme !== 'Normal'"
|
||||
type="text/css"
|
||||
@ -59,8 +71,9 @@ export default {
|
||||
:href="themeCss"
|
||||
>
|
||||
</div>
|
||||
<GameUiComponentFixed />
|
||||
<BackgroundAnimations />
|
||||
<GameUiComponentFixed v-if="!isThemeS12" />
|
||||
<BackgroundAnimations v-if="!isThemeS12" />
|
||||
<S12UiFixed v-if="isThemeS12" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -73,29 +73,31 @@ export default {
|
||||
class="l-time-studies-tab__tt-shop"
|
||||
/>
|
||||
<ModernSidebar
|
||||
v-if="view.newUI"
|
||||
v-if="view.newUI && view.theme !== 'S12'"
|
||||
:style="hideIfMatoFullscreen"
|
||||
/>
|
||||
<SaveTimer :style="hideIfMatoFullscreen" />
|
||||
<SpeedrunStatus :style="hideIfMatoFullscreen" />
|
||||
<ModalProgressBar v-if="view.modal.progressBar" />
|
||||
<CelestialQuoteModal
|
||||
v-else-if="view.quotes.current"
|
||||
:quote="view.quotes.current"
|
||||
/>
|
||||
<CelestialQuoteHistoryDisplay
|
||||
v-else-if="view.quotes.history"
|
||||
:quotes="view.quotes.history"
|
||||
/>
|
||||
<PopupModal
|
||||
v-else-if="view.modal.current"
|
||||
:modal="view.modal.current"
|
||||
/>
|
||||
<ModalProgressBar v-if="view.modal.progressBar" />
|
||||
<FadeAway v-if="ending" />
|
||||
<CreditsContainer v-if="ending" />
|
||||
<NewGame v-if="ending" />
|
||||
<SpectateGame />
|
||||
<template v-if="view.theme !== 'S12'">
|
||||
<ModalProgressBar v-if="view.modal.progressBar" />
|
||||
<CelestialQuoteModal
|
||||
v-else-if="view.quotes.current"
|
||||
:quote="view.quotes.current"
|
||||
/>
|
||||
<CelestialQuoteHistoryDisplay
|
||||
v-else-if="view.quotes.history"
|
||||
:quotes="view.quotes.history"
|
||||
/>
|
||||
<PopupModal
|
||||
v-else-if="view.modal.current"
|
||||
:modal="view.modal.current"
|
||||
/>
|
||||
<ModalProgressBar v-if="view.modal.progressBar" />
|
||||
<FadeAway v-if="ending" />
|
||||
<CreditsContainer v-if="ending" />
|
||||
<NewGame v-if="ending" />
|
||||
<SpectateGame />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -111,4 +113,8 @@ export default {
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.t-s12 .c-game-ui--fixed {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
|
@ -30,7 +30,7 @@ export default {
|
||||
this.saveDisabled = GameEnd.endState >= END_STATE_MARKERS.INTERACTIVITY_DISABLED;
|
||||
},
|
||||
save() {
|
||||
GameStorage.save(false);
|
||||
GameStorage.save(false, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -53,8 +53,8 @@ export default {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
text-align: left;
|
||||
z-index: 5;
|
||||
text-align: left;
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-base);
|
||||
border-top: 0.1rem solid var(--color-accent);
|
||||
|
@ -127,6 +127,11 @@ export default {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.t-s12 .l-changelog-body {
|
||||
font-size: 1.3rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.l-changelog-body::-webkit-scrollbar {
|
||||
width: 1rem;
|
||||
}
|
||||
@ -187,6 +192,10 @@ export default {
|
||||
.s-base--dark .o-changelog-tab-button {
|
||||
border-bottom: 0.1rem solid white;
|
||||
}
|
||||
|
||||
.t-s12 .o-changelog-tab-button {
|
||||
border-bottom: 0.1rem solid black;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
|
@ -117,4 +117,8 @@ export default {
|
||||
.s-base--dark .o-h2p-tab-button--first-irrelevant {
|
||||
border-top-color: white;
|
||||
}
|
||||
|
||||
.t-s12 .o-h2p-tab-button--first-irrelevant {
|
||||
border-top-color: black;
|
||||
}
|
||||
</style>
|
||||
|
@ -89,7 +89,7 @@ export default {
|
||||
},
|
||||
willLoseCosmetics() {
|
||||
const currSets = player.reality.glyphs.cosmetics.unlockedFromNG;
|
||||
const importedSets = this.player.reality?.glyphs.cosmetics.unlockedFromNG ?? [];
|
||||
const importedSets = this.player.reality?.glyphs.cosmetics?.unlockedFromNG ?? [];
|
||||
return currSets.filter(set => !importedSets.includes(set)).length > 0;
|
||||
},
|
||||
willLoseSpeedrun() {
|
||||
|
@ -87,6 +87,11 @@ export default {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.t-s12 .c-info-body {
|
||||
font-size: 1.3rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.c-socials {
|
||||
font-size: 7.5rem;
|
||||
}
|
||||
@ -96,4 +101,9 @@ export default {
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.t-s12 .l-socials {
|
||||
width: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
||||
|
@ -17,6 +17,9 @@ export default {
|
||||
modal() {
|
||||
return this.$viewModel.modal.current;
|
||||
},
|
||||
isThemeS12() {
|
||||
return this.$viewModel.theme === "S12";
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.on$(GAME_EVENT.ENTER_PRESSED, this.handleClick);
|
||||
@ -41,9 +44,13 @@ export default {
|
||||
<div class="c-modal-message l-modal-content--centered">
|
||||
<ModalCloseButton
|
||||
v-if="modal.closeButton"
|
||||
class="c-modal__close-btn--tiny"
|
||||
:class="isThemeS12 ? 'c-modal__close-btn' : 'c-modal__close-btn--tiny'"
|
||||
@click="emitClose"
|
||||
/>
|
||||
<ModalCloseButton
|
||||
v-else-if="isThemeS12"
|
||||
class="c-modal__close-btn c-modal__close-btn--disabled"
|
||||
/>
|
||||
<div
|
||||
class="c-modal-message__text"
|
||||
v-html="message"
|
||||
@ -54,5 +61,11 @@ export default {
|
||||
>
|
||||
Okay
|
||||
</PrimaryButton>
|
||||
<div
|
||||
v-if="isThemeS12"
|
||||
class="c-modal__title"
|
||||
>
|
||||
Message
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -31,36 +31,38 @@ export default {
|
||||
<div
|
||||
class="l-modal-overlay c-modal-overlay progress-bar-modal"
|
||||
>
|
||||
<div class="modal-progress-bar c-modal">
|
||||
<div class="modal-progress-bar__label">
|
||||
{{ progress.label }}
|
||||
</div>
|
||||
<div>
|
||||
{{ progress.info() }}
|
||||
</div>
|
||||
<div class="modal-progress-bar__margin">
|
||||
<div>
|
||||
{{ progress.progressName }}: {{ formatInt(progress.current) }}/{{ formatInt(progress.max) }}
|
||||
<div class="c-modal">
|
||||
<div class="modal-progress-bar">
|
||||
<div class="modal-progress-bar__label">
|
||||
{{ progress.label }}
|
||||
</div>
|
||||
<div>
|
||||
Remaining: {{ remainingTime }}
|
||||
{{ progress.info() }}
|
||||
</div>
|
||||
<div class="modal-progress-bar__hbox">
|
||||
<div class="modal-progress-bar__bg">
|
||||
<div
|
||||
class="modal-progress-bar__fg"
|
||||
:style="foregroundStyle"
|
||||
/>
|
||||
<div class="modal-progress-bar__margin">
|
||||
<div>
|
||||
{{ progress.progressName }}: {{ formatInt(progress.current) }}/{{ formatInt(progress.max) }}
|
||||
</div>
|
||||
<div>
|
||||
Remaining: {{ remainingTime }}
|
||||
</div>
|
||||
<div class="modal-progress-bar__hbox">
|
||||
<div class="modal-progress-bar__bg">
|
||||
<div
|
||||
class="modal-progress-bar__fg"
|
||||
:style="foregroundStyle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-progress-bar__buttons">
|
||||
<OfflineSpeedupButton
|
||||
v-for="(button, id) in buttons"
|
||||
:key="id"
|
||||
:button="button"
|
||||
:progress="progress"
|
||||
/>
|
||||
<div class="modal-progress-bar__buttons">
|
||||
<OfflineSpeedupButton
|
||||
v-for="(button, id) in buttons"
|
||||
:key="id"
|
||||
:button="button"
|
||||
:progress="progress"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -71,19 +73,22 @@ export default {
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
.modal-progress-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 40rem;
|
||||
.c-modal {
|
||||
position: fixed;
|
||||
/* stylelint-disable-next-line unit-allowed-list */
|
||||
top: 50vh;
|
||||
/* stylelint-disable-next-line unit-allowed-list */
|
||||
left: 50vw;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.modal-progress-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 40rem;
|
||||
z-index: 3;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.modal-progress-bar__hbox {
|
||||
|
@ -15,7 +15,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="c-modal__inner">
|
||||
<div class="c-modal__header">
|
||||
<ModalCloseButton @click="closeModal" />
|
||||
<span
|
||||
|
@ -9,21 +9,43 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showModal: false
|
||||
showModal: false,
|
||||
positionStyle: {},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.on$(GAME_EVENT.CLOSE_MODAL, this.hide);
|
||||
},
|
||||
mounted() {
|
||||
this.updatePositionStyles();
|
||||
},
|
||||
destroyed() {
|
||||
document.activeElement.blur();
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
const oldShowModal = this.showModal;
|
||||
// 2.5 is the cutoff point where the screen starts fading (interactivity disabled). However, we specifically
|
||||
// want to allow glyph customization to appear at the very end (and nothing else)
|
||||
this.showModal = GameEnd.endState <= END_STATE_MARKERS.INTERACTIVITY_DISABLED ||
|
||||
this.modal.component.name === "CosmeticSetChoiceModal";
|
||||
if (this.showModal !== oldShowModal) this.$nextTick(() => this.updatePositionStyles());
|
||||
this.updatePositionStyles();
|
||||
},
|
||||
updatePositionStyles() {
|
||||
if (!this.$refs.modal) return;
|
||||
if (!this.showModal || this.$viewModel.theme !== "S12") {
|
||||
this.positionStyle = {};
|
||||
return;
|
||||
}
|
||||
const w = this.$refs.modal.offsetWidth, h = this.$refs.modal.offsetHeight;
|
||||
// We need to set position style specifically for S12 because using a transform messes things up and
|
||||
// makes everything really blurry
|
||||
this.positionStyle = {
|
||||
left: `${Math.round(innerWidth / 2 - w / 2)}px`,
|
||||
top: `${Math.round(innerHeight / 2 - h / 2)}px`,
|
||||
transform: "none",
|
||||
};
|
||||
},
|
||||
hide() {
|
||||
if (!this.modal.isOpen) return;
|
||||
@ -37,7 +59,9 @@ export default {
|
||||
<template>
|
||||
<div
|
||||
v-if="showModal"
|
||||
ref="modal"
|
||||
class="c-modal l-modal"
|
||||
:style="positionStyle"
|
||||
>
|
||||
<component
|
||||
:is="modal.component"
|
||||
|
@ -262,13 +262,13 @@ export default {
|
||||
/>
|
||||
</template>
|
||||
<StudyStringPreview
|
||||
v-if="!deleting"
|
||||
v-if="!deleting && inputIsValidTree"
|
||||
:show-preview="inputIsValidTree"
|
||||
:new-studies="!isImporting || (canEternity && respecAndLoad) ? importedTree.newStudiesArray
|
||||
: combinedTree.newStudiesArray"
|
||||
:disregard-current-studies="!isImporting || (canEternity && respecAndLoad)"
|
||||
/>
|
||||
<div v-else-if="hasInput">
|
||||
<div v-else-if="!deleting && hasInput">
|
||||
Not a valid tree
|
||||
</div>
|
||||
</div>
|
||||
@ -276,7 +276,7 @@ export default {
|
||||
<br>
|
||||
<PrimaryButton
|
||||
v-if="!deleting"
|
||||
ach-tooltip="This will format the study preset text, for example, changing 'a,b,c|d' to 'a, b, c | d'."
|
||||
v-tooltip="'This will format the study preset text, for example, changing \'a,b,c|d\' to \'a, b, c | d\'.'"
|
||||
@click="convertInputShorthands"
|
||||
>
|
||||
Format Preset Text
|
||||
|
@ -81,7 +81,7 @@ export default {
|
||||
text-align: left;
|
||||
border: 0.1rem solid var(--color-text);
|
||||
border-radius: var(--var-border-radius, 0.4rem);
|
||||
margin: 1rem;
|
||||
margin: 1rem 0;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
|
@ -130,8 +130,13 @@ export default {
|
||||
.c-center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 38rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.t-s12 .c-center {
|
||||
width: 50rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.c-dropdown-btn {
|
||||
@ -141,8 +146,8 @@ export default {
|
||||
}
|
||||
|
||||
.c-dropdown-header {
|
||||
padding: 0.5rem;
|
||||
height: 5rem;
|
||||
padding: 0.5rem;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
@ -63,4 +63,8 @@ export default {
|
||||
.l-wrapper {
|
||||
width: 62rem;
|
||||
}
|
||||
|
||||
.t-s12 .l-wrapper {
|
||||
width: 65rem;
|
||||
}
|
||||
</style>
|
@ -25,7 +25,8 @@ export default {
|
||||
simRealities: 0,
|
||||
realityMachines: new Decimal(),
|
||||
shardsGained: 0,
|
||||
effarigUnlocked: false
|
||||
effarigUnlocked: false,
|
||||
willAutoPurge: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -89,6 +90,7 @@ export default {
|
||||
const simRMGained = MachineHandler.gainedRealityMachines.times(this.simRealities);
|
||||
this.realityMachines.copyFrom(simRMGained.clampMax(MachineHandler.distanceToRMCap));
|
||||
this.shardsGained = Effarig.shardsGained * (simulatedRealityCount(false) + 1);
|
||||
this.willAutoPurge = player.reality.autoAutoClean;
|
||||
if (this.firstReality) return;
|
||||
for (let i = 0; i < this.glyphs.length; ++i) {
|
||||
const currentGlyph = this.glyphs[i];
|
||||
@ -172,6 +174,12 @@ export default {
|
||||
automatically choosing another {{ quantifyInt("Glyph", simRealities - 1) }}
|
||||
based on your Glyph filter settings.
|
||||
</div>
|
||||
<div v-if="willAutoPurge">
|
||||
<br>
|
||||
Auto-purge is currently enabled; your selected Glyph
|
||||
<br>
|
||||
may not appear in your inventory after it triggers.
|
||||
</div>
|
||||
<div
|
||||
v-if="!hasSpace"
|
||||
class="o-warning"
|
||||
|
146
src/components/modals/secret-themes/S12GameEntries.vue
Normal file
@ -0,0 +1,146 @@
|
||||
<script>
|
||||
import S12Games from "./s12-games";
|
||||
|
||||
let isSelectingGame = false;
|
||||
export default {
|
||||
name: "S12Games",
|
||||
data() {
|
||||
return {
|
||||
S12Games
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
document.body.addEventListener("click", this.clearSelected);
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.body.removeEventListener("click", this.clearSelected);
|
||||
this.clearSelected();
|
||||
},
|
||||
methods: {
|
||||
clearSelected() {
|
||||
if (isSelectingGame) return;
|
||||
S12Games.selected = -1;
|
||||
},
|
||||
handleClick(idx) {
|
||||
// This makes what everything is doing clearer
|
||||
// eslint-disable-next-line no-negated-condition
|
||||
if (S12Games.selected !== idx) {
|
||||
S12Games.selected = idx;
|
||||
isSelectingGame = true;
|
||||
setTimeout(() => isSelectingGame = false, 0);
|
||||
} else {
|
||||
window.open(S12Games.entries[idx].link);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="c-s12-games-container">
|
||||
<div
|
||||
v-for="(game, idx) in S12Games.entries"
|
||||
:key="game.name"
|
||||
class="c-s12-game"
|
||||
:class="{ 'c-s12-game--selected': S12Games.selected === idx, }"
|
||||
@click="handleClick(idx)"
|
||||
>
|
||||
<div class="c-s12-game__inner">
|
||||
<img
|
||||
:src="`images/s12/${game.image}`"
|
||||
class="c-s12-game__img"
|
||||
>
|
||||
<div class="c-s12-game__text">
|
||||
{{ game.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.c-s12-games-container {
|
||||
--icon-font-size: 1.1rem;
|
||||
--icon-line-height: 1.1;
|
||||
--icon-size: 8rem;
|
||||
--icon-margin: 0.4rem;
|
||||
--icon-inner-padding: 0.5rem;
|
||||
--total-icon-height: calc(
|
||||
var(--icon-size) + var(--icon-margin) * 2 +
|
||||
var(--icon-font-size) * var(--icon-line-height) * 2 +
|
||||
var(--icon-inner-padding) * 2
|
||||
);
|
||||
--total-game-width: 10rem;
|
||||
--game-margin: 0.2rem;
|
||||
|
||||
display: flex;
|
||||
overflow-y: auto;
|
||||
flex: 1 0 auto;
|
||||
flex-wrap: wrap;
|
||||
width: calc(4 * (var(--total-game-width) + var(--game-margin) * 2));
|
||||
height: 40rem;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.c-s12-game {
|
||||
overflow: hidden;
|
||||
width: var(--total-game-width);
|
||||
height: var(--total-icon-height);
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
margin: var(--game-margin);
|
||||
}
|
||||
|
||||
.c-s12-game__inner {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
padding: var(--icon-inner-padding);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.c-s12-game--selected {
|
||||
overflow: visible;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.c-s12-game__inner::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
background-image: linear-gradient(rgba(13, 120, 242, 0.2), rgba(13, 120, 242, 0.25));
|
||||
border: 0.1rem solid #82a5d0;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: inset 0 0 0.2rem 0.1rem rgba(255, 255, 255, 0.7);
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.c-s12-game:hover .c-s12-game__inner::before {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.c-s12-game.c-s12-game--selected .c-s12-game__inner::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.c-s12-game__img {
|
||||
height: var(--icon-size);
|
||||
margin: var(--icon-margin);
|
||||
}
|
||||
|
||||
.c-s12-game__text {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-family: "Segoe UI", Typewriter;
|
||||
font-size: var(--icon-font-size);
|
||||
font-weight: normal;
|
||||
line-height: var(--icon-line-height);
|
||||
color: black;
|
||||
}
|
||||
</style>
|
64
src/components/modals/secret-themes/S12GamesModal.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<script>
|
||||
import ModalWrapper from "@/components/modals/ModalWrapper";
|
||||
import S12GameEntries from "./S12GameEntries";
|
||||
|
||||
import S12Games from "./s12-games";
|
||||
|
||||
export default {
|
||||
name: "S12GamesModal",
|
||||
components: {
|
||||
ModalWrapper,
|
||||
S12GameEntries,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
S12Games,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
if (this.$viewModel.theme !== "S12") EventHub.dispatch(GAME_EVENT.CLOSE_MODAL);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ModalWrapper class="c-modal-s12-games">
|
||||
<div class="c-modal__title">
|
||||
Games
|
||||
</div>
|
||||
<S12GameEntries />
|
||||
<div class="c-modal-s12-games__magnified-display">
|
||||
<template v-if="S12Games.selected !== -1">
|
||||
<img
|
||||
class="c-modal-s12-games__magnified-display__img"
|
||||
:src="`images/s12/${S12Games.entries[S12Games.selected].image}`"
|
||||
>
|
||||
<b class="c-modal-s12-games__magnified-display__text">
|
||||
{{ S12Games.entries[S12Games.selected].name }}
|
||||
</b>
|
||||
</template>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.c-modal-s12-games {
|
||||
display: flex;
|
||||
width: 64rem;
|
||||
}
|
||||
|
||||
.c-modal-s12-games__magnified-display {
|
||||
width: 100%;
|
||||
align-self: stretch;
|
||||
text-align: center;
|
||||
border-left: 0.1rem solid #86b2df;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.c-modal-s12-games__magnified-display__img {
|
||||
width: 100%;
|
||||
margin: 2rem 0 6rem;
|
||||
}
|
||||
</style>
|