mirror of
https://github.com/IvarK/AntimatterDimensionsSourceCode.git
synced 2024-09-20 11:01:45 +00:00
G420/misc 20190908 (#876)
* spoilers * spoilers * spoilers * Make effarig and ra use bits for their unlocks * switch glyphs to using faster RNG, fix up seed to be 32 bit * move tt autobuyer out of dumb place * clean up rng code a bit * switch other celestials to using bits for unlocks * add progress bar for long amplified reality could also be used for offline progress * add documentation to async-utils
This commit is contained in:
parent
7f5dcb98cf
commit
fe7f30b8fd
|
@ -91,6 +91,7 @@
|
|||
<script type="text/javascript" src="javascripts/core/format.js"></script>
|
||||
<script type="text/javascript" src="javascripts/core/constants.js"></script>
|
||||
<script type="text/javascript" src="javascripts/core/math.js"></script>
|
||||
<script type="text/javascript" src="javascripts/core/async-utils.js"></script>
|
||||
|
||||
<script type="text/javascript" src="javascripts/core/automator/automator-backend.js"></script>
|
||||
<script type="text/javascript" src="javascripts/core/secret-formula/effects.js"></script>
|
||||
|
@ -332,6 +333,7 @@
|
|||
<script type="text/javascript" src="javascripts/components/modals/modal-import-tree.js"></script>
|
||||
<script type="text/javascript" src="javascripts/components/modals/modal-load-game.js"></script>
|
||||
<script type="text/javascript" src="javascripts/components/modals/modal-h2p.js"></script>
|
||||
<script type="text/javascript" src="javascripts/components/modals/modal-progress-bar.js"></script>
|
||||
<script type="text/javascript" src="javascripts/components/modals/options/modal-options.js"></script>
|
||||
<script type="text/javascript" src="javascripts/components/modals/options/modal-animation-options.js"></script>
|
||||
<script type="text/javascript" src="javascripts/components/modals/options/modal-confirmation-options.js"></script>
|
||||
|
|
|
@ -11,7 +11,6 @@ Vue.component("ra-tab", {
|
|||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.unlocks = player.celestials.ra.unlocks;
|
||||
this.expMults = this.pets.map(obj => obj.pet.expBoost);
|
||||
this.currentExpGain = Ra.pets.teresa.baseExp;
|
||||
this.showReality = Ra.pets.teresa.level > 2;
|
||||
|
|
|
@ -27,6 +27,7 @@ Vue.component("game-ui", {
|
|||
</component>
|
||||
<modal-popup v-if="view.modal.current" />
|
||||
<modal-glyph-selection v-if="view.modal.glyphSelection" />
|
||||
<modal-progress-bar v-if="view.modal.progressBar" />
|
||||
<link v-if="view.theme !== 'Normal'" type="text/css" rel="stylesheet" :href="themeCss">
|
||||
<div id="notification-container" class="l-notification-container" />
|
||||
<help-me />
|
||||
|
|
29
javascripts/components/modals/modal-progress-bar.js
Normal file
29
javascripts/components/modals/modal-progress-bar.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
"use strict";
|
||||
|
||||
Vue.component("modal-progress-bar", {
|
||||
computed: {
|
||||
progress() {
|
||||
return this.$viewModel.modal.progressBar;
|
||||
},
|
||||
foregroundStyle() {
|
||||
return {
|
||||
width: `${this.progress.current / this.progress.max * 100}%`,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
template: `
|
||||
<div class="l-modal-overlay c-modal-overlay">
|
||||
<div class="l-modal-progress-bar c-modal">
|
||||
<div class="c-modal-progress-bar__label"> {{progress.label}} </div>
|
||||
<div class="l-modal-progress-bar__hbox">
|
||||
<span>0</span>
|
||||
<div class="l-modal-progress-bar__bg c-modal-progress-bar__bg">
|
||||
<div class="l-modal-progress-bar__fg c-modal-progress-bar__fg" :style="foregroundStyle"/>
|
||||
</div>
|
||||
<span>{{progress.max}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>`,
|
||||
});
|
|
@ -9,6 +9,7 @@ let ui = {
|
|||
callback: undefined,
|
||||
closeButton: false,
|
||||
glyphSelection: false,
|
||||
progressBar: undefined,
|
||||
},
|
||||
tabs: {
|
||||
dimensions: {
|
||||
|
|
56
javascripts/core/async-utils.js
Normal file
56
javascripts/core/async-utils.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* Async is used for making a big pile of computation into a manageable
|
||||
* set of batches that don't lock up the UI.
|
||||
* run() is the nominal entry point.
|
||||
*/
|
||||
const Async = {
|
||||
runForTime(fun, maxIter, config) {
|
||||
const batchSize = config.batchSize || 1;
|
||||
const maxTime = config.maxTime;
|
||||
const t0 = Date.now();
|
||||
for (let remaining = maxIter; remaining > 0;) {
|
||||
for (let j = 0; j < Math.min(remaining, batchSize); ++j) {
|
||||
fun();
|
||||
--remaining;
|
||||
}
|
||||
if (Date.now() - t0 >= maxTime) return remaining;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
sleepPromise: ms => new Promise(resolve => setTimeout(resolve, ms)),
|
||||
/**
|
||||
* Asynchronously run the specified function maxIter times, letting the event
|
||||
* loop run periodically. The function is run in chunks of config.batchSize;
|
||||
* when the elapsed time reaches a specified amount, execution will pause for
|
||||
* config.sleepTime
|
||||
* @param {function} fun Function to run (e.g. do some computation)
|
||||
* @param {number} maxIter Total number of times to run the function
|
||||
* @param {Object} config Options for how to do the calculation
|
||||
* @param {Number} config.maxTime Max time, ms, over which to run continuously
|
||||
* @param {Number} [config.batchSize] Number of times to run fun between time checks. Since Date.now() takes
|
||||
* non-zero time to execute, you don't necessarily want to check every iteration
|
||||
* @param {Number} [config.sleepTime] Amount of time to suspend between computing
|
||||
* @param {function(Number)} [config.asyncEntry] IF CALCULATION ISN'T DONE IN ONE BATCH, then this
|
||||
* gets called before the first sleep. Use this to set up a progress bar, for example. The function will
|
||||
* get passed the number of iterations run so far.
|
||||
* @param {function(Number)} [config.asyncProgress] Called after the second and subsequent batches, with the
|
||||
* total number of iterations done thus far
|
||||
* @param {function} [config.asyncExit] If more than one batch was done, this will be called. For example, can
|
||||
* be used to hide a progress bar.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async run(fun, maxIter, config) {
|
||||
let remaining = this.runForTime(fun, maxIter, config);
|
||||
const sleepTime = config.sleepTime || 1;
|
||||
if (!remaining) return;
|
||||
if (config.asyncEntry) config.asyncEntry(maxIter - remaining);
|
||||
do {
|
||||
await this.sleepPromise(sleepTime);
|
||||
remaining = this.runForTime(fun, remaining, config);
|
||||
if (config.asyncProgress) config.asyncProgress(maxIter - remaining);
|
||||
} while (remaining > 0);
|
||||
if (config.asyncExit) config.asyncExit()
|
||||
}
|
||||
};
|
|
@ -28,12 +28,12 @@ class VRunUnlockState extends GameMechanicState {
|
|||
set completions(value) {
|
||||
player.celestials.v.runUnlocks[this.id] = value;
|
||||
}
|
||||
|
||||
|
||||
tryComplete() {
|
||||
if (this.completions === 6 || !this.config.condition(this.conditionValue)) return;
|
||||
this.completions++;
|
||||
GameUI.notify.success(`You have unlocked V achievement '${this.config.name}' tier ${this.completions}`);
|
||||
V.updateTotalRunUnlocks()
|
||||
V.updateTotalRunUnlocks();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,6 @@ const V_UNLOCKS = {
|
|||
if (player.dilation.dilatedTime.lt(db.dilatedTime)) return false;
|
||||
if (player.replicanti.amount.lt(db.replicanti)) return false;
|
||||
if (player.reality.realityMachines.lt(db.rm)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
@ -99,14 +98,16 @@ const V = {
|
|||
checkForUnlocks() {
|
||||
|
||||
if (!V.has(V_UNLOCKS.MAIN_UNLOCK) && V_UNLOCKS.MAIN_UNLOCK.requirement()) {
|
||||
player.celestials.v.unlocks.push(V_UNLOCKS.MAIN_UNLOCK.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.celestials.v.unlockBits |= (1 << V_UNLOCKS.MAIN_UNLOCK.id);
|
||||
GameUI.notify.success(V_UNLOCKS.MAIN_UNLOCK.description);
|
||||
}
|
||||
|
||||
for (let i = 0; i<V_UNLOCKS.RUN_UNLOCK_THRESHOLDS.length; i++) {
|
||||
const unl = V_UNLOCKS.RUN_UNLOCK_THRESHOLDS[i];
|
||||
if (unl.requirement() && !this.has(unl)) {
|
||||
player.celestials.v.unlocks.push(unl.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.celestials.v.unlockBits |= (1 << unl.id);
|
||||
GameUI.notify.success(unl.description);
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +119,8 @@ const V = {
|
|||
}
|
||||
},
|
||||
has(info) {
|
||||
return player.celestials.v.unlocks.includes(info.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return Boolean(player.celestials.v.unlockBits & (1 << info.id));
|
||||
},
|
||||
startRun() {
|
||||
player.celestials.v.run = startRealityOver() || player.celestials.v.run;
|
||||
|
|
|
@ -28,18 +28,23 @@ const EFFARIG_STAGES = {
|
|||
};
|
||||
|
||||
class EffarigUnlockState extends GameMechanicState {
|
||||
get cost() {
|
||||
return this.config.cost;
|
||||
constructor(config) {
|
||||
super(config);
|
||||
if (this.id < 0 || this.id > 31) throw new Error(`Id ${this.id} out of bit range`);
|
||||
}
|
||||
|
||||
get cost() {
|
||||
return this.config.cost;
|
||||
}
|
||||
|
||||
get isUnlocked() {
|
||||
return player.celestials.effarig.unlocks.includes(this.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return Boolean(player.celestials.effarig.unlockBits & (1 << this.id));
|
||||
}
|
||||
|
||||
unlock() {
|
||||
if (!this.isUnlocked) {
|
||||
player.celestials.effarig.unlocks.push(this.id);
|
||||
}
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.celestials.effarig.unlockBits |= (1 << this.id);
|
||||
}
|
||||
|
||||
purchase() {
|
||||
|
|
|
@ -49,11 +49,12 @@ const Laitela = {
|
|||
d.amount = new Decimal(1);
|
||||
d.timeSinceLastUpdate = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
has(info) {
|
||||
return player.celestials.laitela.unlocks.includes(info.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return Boolean(player.celestials.laitela.unlockBits & (1 << info.id));
|
||||
},
|
||||
canBuyUnlock(info) {
|
||||
if (this.matter.lt(info.price)) return false;
|
||||
|
@ -62,7 +63,8 @@ const Laitela = {
|
|||
buyUnlock(info) {
|
||||
if (!this.canBuyUnlock) return false;
|
||||
this.matter = this.matter.minus(info.price);
|
||||
player.celestials.laitela.unlocks.push(info.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.celestials.laitela.unlockBits |= (1 << info.id);
|
||||
return true;
|
||||
},
|
||||
startRun() {
|
||||
|
|
|
@ -193,7 +193,7 @@ const Ra = {
|
|||
// Dev/debug function for easier testing
|
||||
reset() {
|
||||
const data = player.celestials.ra;
|
||||
data.unlocks = [];
|
||||
data.unlockBits = 0;
|
||||
data.run = false;
|
||||
data.charged = new Set();
|
||||
data.quoteIdx = 0;
|
||||
|
@ -217,15 +217,18 @@ const Ra = {
|
|||
},
|
||||
checkForUnlocks() {
|
||||
for (const unl of Object.values(RA_UNLOCKS)) {
|
||||
if (unl.pet.level >= unl.level && !this.has(unl)) player.celestials.ra.unlocks.push(unl.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
if (unl.pet.level >= unl.level && !this.has(unl)) player.celestials.ra.unlockBits |= (1 << unl.id);
|
||||
}
|
||||
if (this.petList.every(pet => pet.level >= 20) && !this.has(RA_LAITELA_UNLOCK)) {
|
||||
player.celestials.ra.unlocks.push(24);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.celestials.ra.unlockBits |= (1 << 24);
|
||||
MatterDimension(1).amount = new Decimal(1);
|
||||
}
|
||||
},
|
||||
has(info) {
|
||||
return player.celestials.ra.unlocks.includes(info.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return Boolean(player.celestials.ra.unlockBits & (1 << info.id));
|
||||
},
|
||||
startRun() {
|
||||
player.celestials.ra.run = startRealityOver() || player.celestials.ra.run;
|
||||
|
|
|
@ -52,13 +52,15 @@ const Teresa = {
|
|||
checkForUnlocks() {
|
||||
for (const info of Object.values(Teresa.unlockInfo)) {
|
||||
if (!this.has(info) && this.rmStore >= info.price) {
|
||||
player.celestials.teresa.unlocks.push(info.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.celestials.teresa.unlockBits |= (1 << info.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
has(info) {
|
||||
if (!info.hasOwnProperty("id")) throw "Pass in the whole TERESA UNLOCK object";
|
||||
return player.celestials.teresa.unlocks.includes(info.id);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return Boolean(player.celestials.teresa.unlockBits & (1 << info.id));
|
||||
},
|
||||
startRun() {
|
||||
player.celestials.teresa.run = startRealityOver() || player.celestials.teresa.run;
|
||||
|
@ -85,9 +87,10 @@ const Teresa = {
|
|||
return teresaQuotes[player.celestials.teresa.quoteIdx];
|
||||
},
|
||||
nextQuote() {
|
||||
if (player.celestials.teresa.quoteIdx < 4 + player.celestials.teresa.unlocks.length) {
|
||||
//if (player.celestials.teresa.quoteIdx < 4 + player.celestials.teresa.unlocks.length) {
|
||||
// FIXME: redo quote system
|
||||
player.celestials.teresa.quoteIdx++;
|
||||
}
|
||||
//}
|
||||
},
|
||||
get isRunning() {
|
||||
return player.celestials.teresa.run;
|
||||
|
|
|
@ -405,17 +405,24 @@ const logFactorial = (function() {
|
|||
}());
|
||||
|
||||
/** 32 bit XORSHIFT generator */
|
||||
function xorshift32Update(state) {
|
||||
/* eslint-disable no-bitwise */
|
||||
/* eslint-disable no-param-reassign */
|
||||
state ^= state << 13;
|
||||
state ^= state >>> 17;
|
||||
state ^= state << 5;
|
||||
/* eslint-enable no-param-reassign */
|
||||
/* eslint-enable no-bitwise */
|
||||
return state;
|
||||
}
|
||||
|
||||
const fastRandom = (function() {
|
||||
let state = Math.floor(Date.now()) % Math.pow(2, 32);
|
||||
const scale = 1 / (Math.pow(2, 32));
|
||||
/* eslint-disable no-bitwise */
|
||||
return () => {
|
||||
state ^= state << 13;
|
||||
state ^= state >>> 17;
|
||||
state ^= state << 5;
|
||||
state = xorshift32Update(state);
|
||||
return state * scale + 0.5;
|
||||
};
|
||||
/* eslint-enable no-bitwise */
|
||||
}());
|
||||
|
||||
// Normal distribution with specified mean and standard deviation
|
||||
|
|
|
@ -125,6 +125,7 @@ let player = {
|
|||
infDimTimer: 0,
|
||||
repUpgradeTimer: 0,
|
||||
dilUpgradeTimer: 0,
|
||||
ttTimer: 0,
|
||||
},
|
||||
infinityPoints: new Decimal(0),
|
||||
infinitied: new Decimal(0),
|
||||
|
@ -321,14 +322,14 @@ let player = {
|
|||
teresa: {
|
||||
rmStore: 0,
|
||||
quoteIdx: 0,
|
||||
unlocks: [],
|
||||
unlockBits: 0,
|
||||
run: false,
|
||||
bestRunAM: new Decimal(1),
|
||||
perkShop: Array.repeat(0, 4)
|
||||
},
|
||||
effarig: {
|
||||
relicShards: 0,
|
||||
unlocks: [],
|
||||
unlocksBits: 0,
|
||||
run: false,
|
||||
quoteIdx: 0,
|
||||
glyphWeights: {
|
||||
|
@ -364,7 +365,7 @@ let player = {
|
|||
maxQuotes: 6
|
||||
},
|
||||
v: {
|
||||
unlocks: [],
|
||||
unlockBits: 0,
|
||||
quoteIdx: 0,
|
||||
run: false,
|
||||
runUnlocks: [0, 0, 0, 0, 0, 0],
|
||||
|
@ -398,7 +399,7 @@ let player = {
|
|||
amount: 0,
|
||||
reaction: false
|
||||
})),
|
||||
unlocks: [],
|
||||
unlocksBits: 0,
|
||||
run: false,
|
||||
charged: new Set(),
|
||||
quoteIdx: 0,
|
||||
|
@ -414,7 +415,7 @@ let player = {
|
|||
laitela: {
|
||||
matter: new Decimal(0),
|
||||
run: false,
|
||||
unlocks: [],
|
||||
unlockBits: 0,
|
||||
dimensions: Array.range(0, 4).map(() =>
|
||||
({
|
||||
amount: new Decimal(0),
|
||||
|
|
|
@ -148,9 +148,9 @@ function requestManualReality() {
|
|||
function triggerManualReality() {
|
||||
if (player.options.animations.reality) {
|
||||
runRealityAnimation();
|
||||
setTimeout(completeReality, 3000, false, false);
|
||||
setTimeout(beginProcessReality, 3000, false, false);
|
||||
} else {
|
||||
completeReality();
|
||||
beginProcessReality();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,21 +199,17 @@ function autoReality() {
|
|||
Enslaved.lockedInGlyphLevel = gainedLevel;
|
||||
Enslaved.lockedInRealityMachines = gainedRealityMachines();
|
||||
Enslaved.lockedInShardsGained = Effarig.shardsGained;
|
||||
completeReality(false, false, true);
|
||||
beginProcessReality(false, false);
|
||||
return;
|
||||
}
|
||||
processAutoGlyph(gainedLevel);
|
||||
completeReality(false, false, true);
|
||||
beginProcessReality(false, false);
|
||||
}
|
||||
|
||||
// The ratio is the amount on top of the regular reality amount.
|
||||
function boostedRealityRewards(ratio) {
|
||||
player.reality.realityMachines = player.reality.realityMachines
|
||||
.plus(Enslaved.lockedInRealityMachines.times(ratio));
|
||||
// No glyph reward was given earlier
|
||||
for (let glyphCount = 0; glyphCount < ratio + 1; ++glyphCount) {
|
||||
processAutoGlyph(Enslaved.lockedInGlyphLevel);
|
||||
}
|
||||
player.realities += ratio;
|
||||
player.reality.pp += ratio;
|
||||
if (Teresa.has(TERESA_UNLOCKS.EFFARIG)) {
|
||||
|
@ -234,13 +230,46 @@ function boostedRealityRewards(ratio) {
|
|||
}
|
||||
}
|
||||
|
||||
function completeReality(force, reset, auto = false) {
|
||||
if (!reset) {
|
||||
EventHub.dispatch(GameEvent.REALITY_RESET_BEFORE);
|
||||
const simulatedRealities = simulatedRealityCount(true);
|
||||
if (simulatedRealities > 0) {
|
||||
// Due to simulated realities taking a long time in late game, this function might not immediately
|
||||
// reality, but start an update loop that shows a progress bar.
|
||||
function beginProcessReality(force, reset) {
|
||||
if (reset) {
|
||||
finishProcessReality(force, reset);
|
||||
return;
|
||||
}
|
||||
EventHub.dispatch(GameEvent.REALITY_RESET_BEFORE);
|
||||
const simulatedRealities = simulatedRealityCount(true);
|
||||
// No glyph reward was given earlier
|
||||
const glyphsToProcess = simulatedRealities + 1;
|
||||
Async.run(() => processAutoGlyph(Enslaved.lockedInGlyphLevel),
|
||||
glyphsToProcess,
|
||||
{
|
||||
batchSize: 100,
|
||||
maxTime: 33,
|
||||
sleepTime: 1,
|
||||
asyncEntry: doneSoFar => {
|
||||
GameIntervals.stop();
|
||||
ui.$viewModel.modal.progressBar = {
|
||||
label: "Processing new glyphs...",
|
||||
current: doneSoFar,
|
||||
max: glyphsToProcess,
|
||||
};
|
||||
},
|
||||
asyncProgress: doneSoFar => {
|
||||
ui.$viewModel.modal.progressBar.current = doneSoFar;
|
||||
},
|
||||
asyncExit: () => {
|
||||
ui.$viewModel.modal.progressBar = undefined;
|
||||
GameIntervals.start();
|
||||
}
|
||||
}).then(() => {
|
||||
boostedRealityRewards(simulatedRealities);
|
||||
}
|
||||
finishProcessReality(force, reset);
|
||||
});
|
||||
}
|
||||
|
||||
function finishProcessReality(force, reset) {
|
||||
if (!reset) {
|
||||
if (player.thisReality < player.bestReality) {
|
||||
player.bestReality = player.thisReality;
|
||||
}
|
||||
|
@ -485,7 +514,7 @@ function handleCelestialRuns(force) {
|
|||
|
||||
function startRealityOver() {
|
||||
if (confirm("This will put you at the start of your reality and reset your progress in this reality. Are you sure you want to do this?")) {
|
||||
completeReality(true, true);
|
||||
beginProcessReality(true, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -239,8 +239,9 @@ const GlyphGenerator = {
|
|||
},
|
||||
|
||||
random() {
|
||||
const x = Math.sin(player.reality.seed++) * 10000;
|
||||
return x - Math.floor(x);
|
||||
const state = xorshift32Update(player.reality.seed);
|
||||
player.reality.seed = state;
|
||||
return state * 2.3283064365386963e-10 + 0.5;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -335,25 +335,29 @@ GameDatabase.reality.perks = {
|
|||
id: 104,
|
||||
label: "TT1",
|
||||
family: PerkFamily.AUTOMATION,
|
||||
description: "Autobuy max TT every 10 seconds."
|
||||
description: "Autobuy max TT every 10 seconds.",
|
||||
effect: () => 10000,
|
||||
},
|
||||
autobuyerTT2: {
|
||||
id: 105,
|
||||
label: "TT2",
|
||||
family: PerkFamily.AUTOMATION,
|
||||
description: "Autobuy max TT every 5 seconds."
|
||||
description: "Autobuy max TT every 5 seconds.",
|
||||
effect: () => 5000,
|
||||
},
|
||||
autobuyerTT3: {
|
||||
id: 106,
|
||||
label: "TT3",
|
||||
family: PerkFamily.AUTOMATION,
|
||||
description: "Autobuy max TT every 3 seconds."
|
||||
description: "Autobuy max TT every 3 seconds.",
|
||||
effect: () => 3000,
|
||||
},
|
||||
autobuyerTT4: {
|
||||
id: 107,
|
||||
label: "TT4",
|
||||
family: PerkFamily.AUTOMATION,
|
||||
description: "Autobuy max TT every second."
|
||||
description: "Autobuy max TT every second.",
|
||||
effect: () => 1000,
|
||||
},
|
||||
achievementRowGroup1: {
|
||||
id: 201,
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
"use strict";
|
||||
|
||||
function arrayToBits(array) {
|
||||
let bits = 0;
|
||||
// eslint-disable-next-line no-bitwise
|
||||
for (const id of array) bits |= (1 << id);
|
||||
return bits;
|
||||
}
|
||||
|
||||
// WARNING: Don't use state accessors and functions from global scope here, that's not safe in long-term
|
||||
GameStorage.devMigrations = {
|
||||
patches: [
|
||||
|
@ -275,10 +282,7 @@ GameStorage.devMigrations = {
|
|||
player.celestials.teresa.rmStore = Teresa.rmStoreMax;
|
||||
}
|
||||
if (player.reality.upg) {
|
||||
for (const upg of player.reality.upg) {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
player.reality.upgradeBits |= (1 << upg);
|
||||
}
|
||||
player.reality.upgradeBits = arrayToBits(player.reality.upg);
|
||||
delete player.reality.upg;
|
||||
}
|
||||
// eslint-disable-next-line no-bitwise
|
||||
|
@ -442,7 +446,22 @@ GameStorage.devMigrations = {
|
|||
},
|
||||
GameStorage.migrations.renameNewsOption,
|
||||
GameStorage.migrations.removeDimensionCosts,
|
||||
GameStorage.migrations.renameTickspeedPurchaseBumps
|
||||
GameStorage.migrations.renameTickspeedPurchaseBumps,
|
||||
player => {
|
||||
player.celestials.teresa.unlockBits = arrayToBits(player.celestials.teresa.unlocks);
|
||||
delete player.celestials.teresa.unlocks;
|
||||
player.celestials.effarig.unlockBits = arrayToBits(player.celestials.effarig.unlocks);
|
||||
delete player.celestials.effarig.unlocks;
|
||||
player.celestials.v.unlockBits = arrayToBits(player.celestials.v.unlocks);
|
||||
delete player.celestials.v.unlocks;
|
||||
player.celestials.ra.unlockBits = arrayToBits(player.celestials.ra.unlocks);
|
||||
delete player.celestials.ra.unlocks;
|
||||
player.celestials.laitela.unlockBits = arrayToBits(player.celestials.laitela.unlocks);
|
||||
delete player.celestials.laitela.unlocks;
|
||||
},
|
||||
player => {
|
||||
player.reality.seed = Math.floor(Math.abs(player.reality.seed)) % 0xFFFFFFFF;
|
||||
}
|
||||
],
|
||||
|
||||
patch(player) {
|
||||
|
|
|
@ -78,7 +78,7 @@ const GameStorage = {
|
|||
},
|
||||
|
||||
save(silent = false) {
|
||||
if (GlyphSelection.active) return;
|
||||
if (GlyphSelection.active || ui.$viewModel.modal.progressBar !== undefined) return;
|
||||
if (++this.saved > 99) SecretAchievement(12).unlock();
|
||||
const root = {
|
||||
current: this.currentSlot,
|
||||
|
|
|
@ -102,16 +102,19 @@ const TimeTheorems = {
|
|||
}
|
||||
};
|
||||
|
||||
function autoBuyMaxTheorems() {
|
||||
if (!player.ttbuyer) return false;
|
||||
if (Perk.autobuyerTT4.isBought ||
|
||||
(Perk.autobuyerTT3.isBought && ttMaxTimer >= 3) ||
|
||||
(Perk.autobuyerTT2.isBought && ttMaxTimer >= 5) ||
|
||||
(Perk.autobuyerTT1.isBought && ttMaxTimer >= 10)) {
|
||||
function autoBuyMaxTheorems(realDiff) {
|
||||
if (!player.ttbuyer) return;
|
||||
player.auto.ttTimer += realDiff;
|
||||
const period = Effects.min(
|
||||
Number.POSITIVE_INFINITY,
|
||||
Perk.autobuyerTT1,
|
||||
Perk.autobuyerTT2,
|
||||
Perk.autobuyerTT3,
|
||||
Perk.autobuyerTT4);
|
||||
if (player.auto.ttTimer > period) {
|
||||
TimeTheorems.buyMax(true);
|
||||
return true;
|
||||
player.auto.ttTimer = Math.min(player.auto.ttTimer - period, period);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function calculateTimeStudiesCost() {
|
||||
|
|
|
@ -293,17 +293,12 @@ function kongLog10StatSubmission() {
|
|||
|
||||
setInterval(kongLog10StatSubmission, 10000)
|
||||
|
||||
var ttMaxTimer = 0;
|
||||
|
||||
function randomStuffThatShouldBeRefactored() {
|
||||
// document.getElementById("kongip").textContent = "Double your IP gain from all sources (additive). Forever. Currently: x"+kongIPMult+", next: x"+(kongIPMult==1? 2: kongIPMult+2)
|
||||
// document.getElementById("kongep").textContent = "Triple your EP gain from all sources (additive). Forever. Currently: x"+kongEPMult+", next: x"+(kongEPMult==1? 3: kongEPMult+3)
|
||||
// document.getElementById("kongdim").textContent = "Double all your normal dimension multipliers (multiplicative). Forever. Currently: x"+kongDimMult+", next: x"+(kongDimMult*2)
|
||||
// document.getElementById("kongalldim").textContent = "Double ALL the dimension multipliers (Normal, Infinity, Time) (multiplicative until 32x). Forever. Currently: x"+kongAllDimMult+", next: x"+((kongAllDimMult < 32) ? kongAllDimMult * 2 : kongAllDimMult + 32)
|
||||
|
||||
ttMaxTimer++;
|
||||
if (autoBuyMaxTheorems()) ttMaxTimer = 0;
|
||||
|
||||
if (!Teresa.has(TERESA_UNLOCKS.EFFARIG)) player.celestials.teresa.rmStore *= Math.pow(0.98, 1/60) // Teresa container leak, 2% every minute, only works online.
|
||||
}
|
||||
|
||||
|
@ -910,6 +905,7 @@ function slowerAutobuyers(realDiff) {
|
|||
player.auto.dilUpgradeTimer = Math.min(player.auto.dilUpgradeTimer - dilUpgradePeriod, dilUpgradePeriod);
|
||||
autoBuyDilationUpgrades();
|
||||
}
|
||||
autoBuyMaxTheorems(realDiff);
|
||||
}
|
||||
|
||||
setInterval(function () {
|
||||
|
|
|
@ -5065,6 +5065,47 @@ kbd {
|
|||
|
||||
/*#endregion c-modal-shortcuts*/
|
||||
|
||||
.l-modal-progress-bar {
|
||||
position: fixed;
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
left: 50vw;
|
||||
top: 50vh;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.l-modal-progress-bar__hbox {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.c-modal-progress-bar__label {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.l-modal-progress-bar__bg {
|
||||
width: 20rem;
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.c-modal-progress-bar__bg {
|
||||
background: black;
|
||||
}
|
||||
|
||||
.l-modal-progress-bar__fg {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.c-modal-progress-bar__fg {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
/*#endregion Modals*/
|
||||
|
||||
.l-notification-container {
|
||||
|
|
Loading…
Reference in New Issue
Block a user