mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 06:18:42 +02:00
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useRef, useMemo } from "react";
|
||||
import { ProgressBar } from "../../ui/React/Progress";
|
||||
import { clampNumber } from "../../utils/helpers/clampNumber";
|
||||
|
||||
type GameTimerProps = {
|
||||
endTimestamp: number;
|
||||
@@ -14,7 +15,7 @@ export function GameTimer({ endTimestamp }: GameTimerProps): React.ReactElement
|
||||
// actually begin it until later. We're using a ref to keep this updated in
|
||||
// a very low-overhead way.
|
||||
const state = changeRef.current;
|
||||
if (state?.endTimestamp !== endTimestamp) {
|
||||
if (state.endTimestamp !== endTimestamp) {
|
||||
state.endTimestamp = endTimestamp;
|
||||
state.startTimestamp = performance.now();
|
||||
}
|
||||
@@ -24,10 +25,12 @@ export function GameTimer({ endTimestamp }: GameTimerProps): React.ReactElement
|
||||
const ele = ref.current?.firstElementChild;
|
||||
const startTimestamp = changeRef.current.startTimestamp;
|
||||
if (!ele) return;
|
||||
// The delay will be negative. This is because the animation starts
|
||||
// partway completed, due to the time taken to invoke the effect.
|
||||
ele.animate([{ transform: "translateX(0%)" }, { transform: "translateX(-100%)" }], {
|
||||
duration: endTimestamp - startTimestamp,
|
||||
// If duration is negative, ele.animate will throw "TypeError: duration must be non-negative or auto". It may
|
||||
// happen when the player uses the debugger.
|
||||
duration: clampNumber(endTimestamp - startTimestamp, 0),
|
||||
// The delay will be negative. This is because the animation starts
|
||||
// partway completed, due to the time taken to invoke the effect.
|
||||
delay: startTimestamp - performance.now(),
|
||||
});
|
||||
}, [endTimestamp]);
|
||||
|
||||
@@ -33,7 +33,7 @@ interface StageProps {
|
||||
}
|
||||
|
||||
// The extra cast here is needed because otherwise it sees the more-specific
|
||||
// types of the components, and gets grumpy that they are not interconvertable.
|
||||
// types of the components, and gets grumpy that they are not interconvertible.
|
||||
const stages = new Map([
|
||||
[IntroModel, Intro],
|
||||
[CountdownModel, Countdown],
|
||||
@@ -51,6 +51,7 @@ const stages = new Map([
|
||||
function Progress({ results }: { results: string }): React.ReactElement {
|
||||
return (
|
||||
<Typography variant="h4">
|
||||
{/* Only show the last 14 results instead of the full history. */}
|
||||
<span style={{ color: "gray" }}>{results.slice(-15, -1)}</span>
|
||||
{results[results.length - 1]}
|
||||
</Typography>
|
||||
@@ -106,7 +107,7 @@ export function InfiltrationRoot(): React.ReactElement {
|
||||
return (
|
||||
<div style={{ display: "flex", alignItems: "center", height: "calc(100vh - 16px)" }}>
|
||||
{state.stage instanceof IntroModel ? (
|
||||
<Intro state={state} stage={state.stage} />
|
||||
<Intro state={state} />
|
||||
) : (
|
||||
<Container>
|
||||
<Paper sx={{ p: 1, mb: 1, display: "grid", justifyItems: "center", gap: 1 }}>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Settings } from "../../Settings/Settings";
|
||||
import { formatHp, formatMoney, formatNumberNoSuffix, formatPercent, formatReputation } from "../../ui/formatNumber";
|
||||
import { Player } from "@player";
|
||||
import type { Infiltration } from "../Infiltration";
|
||||
import type { IntroModel } from "../model/IntroModel";
|
||||
import { calculateDamageAfterFailingInfiltration } from "../utils";
|
||||
import {
|
||||
calculateInfiltratorsRepReward,
|
||||
@@ -18,7 +17,6 @@ import { useRerender } from "../../ui/React/hooks";
|
||||
|
||||
interface IProps {
|
||||
state: Infiltration;
|
||||
stage: IntroModel;
|
||||
}
|
||||
|
||||
function arrowPart(color: string, length: number): JSX.Element {
|
||||
|
||||
@@ -18,7 +18,7 @@ export function MinesweeperGame({ stage }: IProps): React.ReactElement {
|
||||
const flatGrid: { flagged?: boolean; current?: boolean; marked?: boolean }[] = [];
|
||||
|
||||
stage.minefield.map((line, y) =>
|
||||
line.map((cell, x) => {
|
||||
line.map((_cell, x) => {
|
||||
if (stage.memoryPhase) {
|
||||
flatGrid.push({ flagged: Boolean(stage.minefield[y][x]) });
|
||||
return;
|
||||
|
||||
@@ -63,7 +63,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
|
||||
return;
|
||||
}
|
||||
|
||||
Player.startInfiltration(location);
|
||||
Player.initInfiltration(location);
|
||||
Router.toPage(Page.Infiltration);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ export class PlayerObject extends Person implements IPlayer {
|
||||
activeSourceFileLvl = generalMethods.activeSourceFileLvl;
|
||||
applyEntropy = augmentationMethods.applyEntropy;
|
||||
focusPenalty = generalMethods.focusPenalty;
|
||||
startInfiltration = generalMethods.startInfiltration;
|
||||
initInfiltration = generalMethods.initInfiltration;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -603,7 +603,7 @@ export function focusPenalty(this: PlayerObject): number {
|
||||
}
|
||||
|
||||
/** This doesn't change the current page; that is up to the caller. */
|
||||
export function startInfiltration(this: PlayerObject, location: Location): void {
|
||||
export function initInfiltration(this: PlayerObject, location: Location): void {
|
||||
if (!location.infiltrationData)
|
||||
throw new Error(`trying to start infiltration at ${location.name} but the infiltrationData is null`);
|
||||
this.infiltration = new Infiltration(location);
|
||||
|
||||
Reference in New Issue
Block a user