Set up initialization and basic UI widget for speedrun mode

This commit is contained in:
SpectralFlame 2022-01-05 00:05:56 -06:00 committed by cyip92
parent f6e012a62a
commit 64d13bc4f0
11 changed files with 153 additions and 1 deletions

View File

@ -1,6 +1,7 @@
import "./old-ui/old-ui.js";
import "./new-ui/new-ui.js";
import "./save-timer.js";
import "./speedrun-status.js";
import "./help-me.js";
import "./tt-shop.js";
import "./new-ui/sidebar.js";
@ -50,5 +51,6 @@ Vue.component("game-ui", {
<tt-shop v-if="view.subtab === 'studies'" class="l-time-studies-tab__tt-shop" />
<sidebar v-if="view.newUI" />
<save-timer />
<speedrun-status />
</div>`
});

View File

@ -0,0 +1,63 @@
Vue.component("speedrun-status", {
data() {
return {
isActive: false,
isImported: false,
hasStarted: false,
startDate: 0,
saveName: "",
timePlayedStr: "",
offlineProgress: false,
offlineFraction: 0,
mostRecent: {},
};
},
computed: {
statusText() {
return this.hasStarted
? `<span style="color: var(--color-good)">Running!</span>`
: `<span style="color: var(--color-bad)">Not Started Yet</span>`;
},
segmentText() {
return this.isImported ? "Segmented Speedrun (imported save)" : "Single-segment Speedrun (no save import)";
},
offlineText() {
const stateText = this.offlineProgress
? `<span style="color: var(--color-good)">Enabled</span>`
: `<span style="color: var(--color-bad)">Disabled</span>`;
const fractionText = this.offlineFraction === 0
? "(No offline time used)"
: `(${formatPercents(this.offlineFraction, 2)} time spent offline)`;
return `${stateText} ${fractionText}`;
}
},
methods: {
update() {
const speedrun = player.speedrun;
this.isActive = speedrun.isActive;
this.isImported = speedrun.isImported;
this.hasStarted = speedrun.hasStarted;
this.startDate = speedrun.startDate;
this.saveName = speedrun.name;
this.timePlayedStr = Time.totalTimePlayed.toStringShort();
this.offlineProgress = player.options.offlineProgress;
this.offlineFraction = speedrun.offlineTimeUsed / Math.clampMin(player.records.totalTimePlayed, 1);
this.mostRecent = speedrun.mostRecentMilestone;
},
},
template: `
<div v-if="isActive" class="o-speedrun-status">
<b>Speedrun Status (<span v-html="statusText" />)</b>
<br>
Player Name: {{ saveName }}
<br>
<i>{{ segmentText }}</i>
<br>
Time since start: {{ timePlayedStr }}
<br>
Offline Progress: <span v-html="offlineText" />
<br>
Most Recent Milestone: {{ mostRecent }}
</div>`
});

View File

@ -601,3 +601,13 @@ dev.devMode = function() {
dev.unlockAutomator = function() {
player.reality.automator.forceUnlock = true;
};
dev.startSpeedrun = function(name) {
GameStorage.hardReset();
player.speedrun.isActive = true;
// If a name isn't given, choose a somewhat-likely-to-be-unique big number instead
if (name) player.speedrun.name = name;
else player.speedrun.name = `AD Player #${Math.floor(1e7 * Math.random())}`;
// "Fake News" Achievement, given for free to partially mitigate promoting weird strategies at the beginning of runs
Achievement(22).unlock();
};

View File

@ -173,6 +173,8 @@ function onBuyDimension(tier) {
Achievement(10 + tier).unlock();
Achievement(23).tryUnlock();
if (player.speedrun.isActive && !player.speedrun.hasStarted) Speedrun.startRun();
if (NormalChallenge(2).isRunning) player.chall2Pow = 0;
if (NormalChallenge(4).isRunning || InfinityChallenge(1).isRunning) {
AntimatterDimensions.resetAmountUpToTier(tier - 1);

View File

@ -78,5 +78,6 @@ export * from "./news-ticker.js";
export * from "./kong.js";
export * from "./ui/tabs.js";
export * from "./ui/tab-notifications.js";
export * from "./speedrun.js";
export * from "./automator/script-templates.js";

View File

@ -277,6 +277,7 @@ GameKeyboard.bind(
GameKeyboard.bind("enter up up down down left right left right b a", () => {
SecretAchievement(17).unlock();
Currency.antimatter.bumpTo(30);
Speedrun.startRun();
});

View File

@ -286,6 +286,44 @@ window.player = {
laitelaSet: [],
},
},
speedrun: {
isActive: false,
isImported: false,
hasStarted: false,
startDate: 0,
name: "",
offlineTimeUsed: 0,
records: {
firstBoost: 0,
firstGalaxy: 0,
firstInfinity: 0,
completeC9: 0,
completeAllNC: 0,
breakInfinity: 0,
upgrade5e11IP: 0,
completeIC5: 0,
unlockReplicanti: 0,
firstEternity: 0,
allEternityMilestones: 0,
completeFirstEC: 0,
upgradeTS181: 0,
completeEC10: 0,
completeAllEC: 0,
firstDilation: 0,
upgradeTTgen: 0,
firstReality: 0,
upgradeBlackHole: 0,
allRealityUpgrades: 0,
completeTeresaReality: 0,
completeEffarigReality: 0,
completeEnslavedReality: 0,
complete36VAchievement: 0,
completeRaMemories: 0,
completeFullDestabilize: 0,
completeFullGame: 0,
},
mostRecentMilestone: "None",
},
infMult: 0,
version: 13,
infinityPower: DC.D1,

View File

@ -0,0 +1,13 @@
export const Speedrun = {
// Speedruns are initially paused until startRun is called, which happens as soon as the player purchases a AD or
// uses the Konami code. Until then, they're free to do whatever they want with the UI
startRun() {
if (player.speedrun.hasStarted) return;
player.speedrun.hasStarted = true;
player.speedrun.startDate = Date.now();
player.lastUpdate = Date.now();
},
isPausedAtStart() {
return player.speedrun.isActive && !player.speedrun.hasStarted;
},
};

View File

@ -216,8 +216,9 @@ export const GameStorage = {
if (overrideLastUpdate) {
player.lastUpdate = overrideLastUpdate;
}
if (player.options.offlineProgress) {
if (player.options.offlineProgress && !Speedrun.isPausedAtStart()) {
let diff = Date.now() - player.lastUpdate;
player.speedrun.offlineTimeUsed += diff;
if (diff > 5 * 60 * 1000 && player.celestials.enslaved.autoStoreReal) {
diff = Enslaved.autoStoreRealTime(diff);
}

View File

@ -360,6 +360,13 @@ export function gameLoop(passDiff, options = {}) {
? Math.clamp(thisUpdate - player.lastUpdate, 1, 21600000)
: diff;
// We want to allow for a speedrunner to be able to adjust their visual settings before actually starting the run,
// which means that we need to effectively halt the game loop until the official start
if (Speedrun.isPausedAtStart()) {
GameUI.update();
return;
}
// Ra memory generation bypasses stored real time, but memory chunk generation is disabled when storing real time.
// This is in order to prevent players from using time inside of Ra's reality for amplification as well
Ra.memoryTick(realDiff, !Enslaved.isStoringRealTime);

View File

@ -571,6 +571,20 @@ button:focus {
z-index: 5;
}
.o-speedrun-status {
font-size: 1.2rem;
color: var(--color-text);
position: fixed;
right: 1rem;
bottom: 1rem;
background-color: var(--color-base);
white-space: nowrap;
border: 0.2rem solid var(--color-accent);
user-select: none;
padding: 0.8rem 2rem;
z-index: 5;
}
.l-reality-button {
display: block;
width: 50%;