mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-20 05:05:47 +01:00
commit
b55318706a
4
dist/main.bundle.js
vendored
4
dist/main.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/main.bundle.js.map
vendored
2
dist/main.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
64
dist/vendor.bundle.js
vendored
64
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/vendor.bundle.js.map
vendored
2
dist/vendor.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
@ -1686,9 +1686,6 @@ export class Bladeburner implements IBladeburner {
|
||||
// Operation Daedalus
|
||||
if (action == null) {
|
||||
throw new Error("Failed to get BlackOperation Object for: " + this.action.name);
|
||||
} else if (action.name === BlackOperationNames.OperationDaedalus && this.blackops[action.name]) {
|
||||
this.resetAction();
|
||||
router.toBitVerse(false, false);
|
||||
} else if (this.action.type != ActionTypes["BlackOperation"] && this.action.type != ActionTypes["BlackOp"]) {
|
||||
this.startAction(player, this.action); // Repeat action
|
||||
}
|
||||
@ -1991,11 +1988,6 @@ export class Bladeburner implements IBladeburner {
|
||||
// Edge race condition when the engine checks the processing counters and attempts to route before the router is initialized.
|
||||
if (!router.isInitialized) return;
|
||||
|
||||
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
||||
if (router.page() !== Page.BitVerse && this.blackops.hasOwnProperty(BlackOperationNames.OperationDaedalus)) {
|
||||
return router.toBitVerse(false, false);
|
||||
}
|
||||
|
||||
// If the Player starts doing some other actions, set action to idle and alert
|
||||
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true) && player.isWorking) {
|
||||
if (this.action.type !== ActionTypes["Idle"]) {
|
||||
|
@ -4,6 +4,10 @@ import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
import { use } from "../../ui/Context";
|
||||
import { BlackOperationNames } from "../data/BlackOperationNames";
|
||||
import { Button } from "@mui/material";
|
||||
import { CorruptableText } from "../../ui/React/CorruptableText";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
@ -11,6 +15,7 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function BlackOpPage(props: IProps): React.ReactElement {
|
||||
const router = use.Router();
|
||||
return (
|
||||
<>
|
||||
<Typography>
|
||||
@ -27,7 +32,13 @@ export function BlackOpPage(props: IProps): React.ReactElement {
|
||||
Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank
|
||||
losses.
|
||||
</Typography>
|
||||
<BlackOpList bladeburner={props.bladeburner} player={props.player} />
|
||||
{props.bladeburner.blackops[BlackOperationNames.OperationDaedalus] ? (
|
||||
<Button sx={{ my: 1, p: 1 }} onClick={() => router.toBitVerse(false, false)}>
|
||||
<CorruptableText content="Destroy w0rld_d34mon"></CorruptableText>
|
||||
</Button>
|
||||
) : (
|
||||
<BlackOpList bladeburner={props.bladeburner} player={props.player} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ export const CONSTANTS: {
|
||||
|
||||
InfiniteLoopLimit: 2000,
|
||||
|
||||
Donations: 7,
|
||||
Donations: 20,
|
||||
|
||||
LatestUpdate: `
|
||||
## [draft] v1.7.0 - 2022-04-13 to 2022-05-20
|
||||
|
@ -66,7 +66,7 @@ export function ActiveFragmentSummary(props: IProps): React.ReactElement {
|
||||
</TableRow>
|
||||
{summary.map((entry) => {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableRow key={entry.type}>
|
||||
<TableCell sx={{ borderBottom: "none", p: 0, m: 0 }}>
|
||||
<Typography>
|
||||
{entry.coordinate.map((coord) => {
|
||||
|
@ -3,7 +3,7 @@ import * as React from "react";
|
||||
import { ActiveFragment } from "../ActiveFragment";
|
||||
import { DummyGift } from "../DummyGift";
|
||||
import { Grid } from "./Grid";
|
||||
import { calculateGrid, zeros } from "../Helper";
|
||||
import { zeros } from "../Helper";
|
||||
|
||||
interface IProps {
|
||||
width: number;
|
||||
@ -13,7 +13,6 @@ interface IProps {
|
||||
|
||||
export function DummyGrid(props: IProps): React.ReactElement {
|
||||
const gift = new DummyGift(props.width, props.height, props.fragments);
|
||||
const activeGrid = calculateGrid(gift);
|
||||
const ghostGrid = zeros([props.width, props.height]);
|
||||
return (
|
||||
<Box>
|
||||
@ -21,7 +20,6 @@ export function DummyGrid(props: IProps): React.ReactElement {
|
||||
<Grid
|
||||
width={props.width}
|
||||
height={props.height}
|
||||
activeGrid={activeGrid}
|
||||
ghostGrid={ghostGrid}
|
||||
gift={gift}
|
||||
enter={() => undefined}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { TableBody, TableRow } from "@mui/material";
|
||||
import * as React from "react";
|
||||
import { ActiveFragment } from "../ActiveFragment";
|
||||
import { calculateGrid } from "../Helper";
|
||||
import { IStaneksGift } from "../IStaneksGift";
|
||||
import { Cell } from "./Cell";
|
||||
|
||||
interface IProps {
|
||||
width: number;
|
||||
height: number;
|
||||
activeGrid: number[][];
|
||||
ghostGrid: number[][];
|
||||
gift: IStaneksGift;
|
||||
enter(i: number, j: number): void;
|
||||
@ -32,11 +32,13 @@ function randomColor(fragment: ActiveFragment): string {
|
||||
}
|
||||
|
||||
export function Grid(props: IProps): React.ReactElement {
|
||||
const activeGrid = calculateGrid(props.gift);
|
||||
|
||||
function color(worldX: number, worldY: number): string {
|
||||
if (props.ghostGrid[worldX][worldY] && props.activeGrid[worldX][worldY]) return "red";
|
||||
if (props.ghostGrid[worldX][worldY] && activeGrid[worldX][worldY]) return "red";
|
||||
if (props.ghostGrid[worldX][worldY]) return "white";
|
||||
|
||||
if (props.activeGrid[worldX][worldY]) {
|
||||
if (activeGrid[worldX][worldY]) {
|
||||
const fragment = props.gift.fragmentAt(worldX, worldY);
|
||||
if (!fragment) throw new Error("ActiveFragment should not be null");
|
||||
return randomColor(fragment);
|
||||
|
@ -8,7 +8,7 @@ import Box from "@mui/material/Box";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Table } from "../../ui/React/Table";
|
||||
import { Grid } from "./Grid";
|
||||
import { zeros, calculateGrid } from "../Helper";
|
||||
import { zeros } from "../Helper";
|
||||
import { ActiveFragmentSummary } from "./ActiveFragmentSummary";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
@ -18,7 +18,6 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function MainBoard(props: IProps): React.ReactElement {
|
||||
const [grid, setGrid] = React.useState(calculateGrid(props.gift));
|
||||
const [ghostGrid, setGhostGrid] = React.useState(zeros([props.gift.width(), props.gift.height()]));
|
||||
const [pos, setPos] = React.useState([0, 0]);
|
||||
const [rotation, setRotation] = React.useState(0);
|
||||
@ -54,12 +53,10 @@ export function MainBoard(props: IProps): React.ReactElement {
|
||||
if (!props.gift.canPlace(worldX, worldY, rotation, selectedFragment)) return;
|
||||
props.gift.place(worldX, worldY, rotation, selectedFragment);
|
||||
}
|
||||
setGrid(calculateGrid(props.gift));
|
||||
}
|
||||
|
||||
function clear(): void {
|
||||
props.gift.clear();
|
||||
setGrid(zeros([props.gift.width(), props.gift.height()]));
|
||||
}
|
||||
|
||||
function updateSelectedFragment(fragment: Fragment): void {
|
||||
@ -92,7 +89,6 @@ export function MainBoard(props: IProps): React.ReactElement {
|
||||
<Grid
|
||||
width={props.gift.width()}
|
||||
height={props.gift.height()}
|
||||
activeGrid={grid}
|
||||
ghostGrid={ghostGrid}
|
||||
gift={props.gift}
|
||||
enter={(i, j) => moveGhost(i, j, rotation)}
|
||||
|
@ -20,7 +20,7 @@ import { MathJaxWrapper } from "../../MathJaxWrapper";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Button from "@mui/material/Button";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { NumberInput } from "../../ui/React/NumberInput";
|
||||
|
||||
type IProps = {
|
||||
faction: Faction;
|
||||
@ -31,26 +31,20 @@ type IProps = {
|
||||
};
|
||||
|
||||
export function DonateOption(props: IProps): React.ReactElement {
|
||||
const [donateAmt, setDonateAmt] = useState<number | null>(null);
|
||||
const [donateAmt, setDonateAmt] = useState<number>(NaN);
|
||||
const digits = (CONSTANTS.DonateMoneyToRepDivisor + "").length - 1;
|
||||
|
||||
function canDonate(): boolean {
|
||||
if (donateAmt === null) return false;
|
||||
if (isNaN(donateAmt)) return false;
|
||||
if (isNaN(donateAmt) || donateAmt <= 0) return false;
|
||||
if (props.p.money < donateAmt) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
const amt = numeralWrapper.parseMoney(event.target.value);
|
||||
if (event.target.value === "" || isNaN(amt)) setDonateAmt(null);
|
||||
else setDonateAmt(amt);
|
||||
}
|
||||
|
||||
function donate(): void {
|
||||
const fac = props.faction;
|
||||
const amt = donateAmt;
|
||||
if (amt === null) return;
|
||||
if (isNaN(amt)) return;
|
||||
if (!canDonate()) return;
|
||||
props.p.loseMoney(amt, "other");
|
||||
const repGain = repFromDonation(amt, props.p);
|
||||
@ -85,8 +79,8 @@ export function DonateOption(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
) : (
|
||||
<>
|
||||
<TextField
|
||||
onChange={onChange}
|
||||
<NumberInput
|
||||
onChange={setDonateAmt}
|
||||
placeholder={"Donation amount"}
|
||||
disabled={props.disabled}
|
||||
InputProps={{
|
||||
|
@ -277,14 +277,6 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
||||
>
|
||||
Reddit
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<Public />}
|
||||
href="https://plaza.dsolver.ca/games/bitburner"
|
||||
target="_blank"
|
||||
sx={{ gridArea: "plaza" }}
|
||||
>
|
||||
Incremental game plaza
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
{!location.href.startsWith("file://") && (
|
||||
|
@ -95,7 +95,7 @@ function wrapFunction(
|
||||
boolean: helpers.boolean,
|
||||
getServer: (hostname: string) => helpers.getServer(hostname, ctx),
|
||||
checkSingularityAccess: () => helpers.checkSingularityAccess(functionName),
|
||||
hack: helpers.hack,
|
||||
hack: (hostname: any, manual: any, extra?: any) => helpers.hack(ctx, hostname, manual, extra),
|
||||
getValidPort: (port: any) => helpers.getValidPort(functionPath, port),
|
||||
},
|
||||
};
|
||||
|
@ -539,8 +539,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
stock: NetscriptStockMarket(Player, workerScript),
|
||||
grafting: NetscriptGrafting(Player),
|
||||
hacknet: NetscriptHacknet(Player, workerScript),
|
||||
sprintf: sprintf,
|
||||
vsprintf: vsprintf,
|
||||
sprintf: () => sprintf,
|
||||
vsprintf: () => vsprintf,
|
||||
scan:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_hostname: unknown = workerScript.hostname): string[] => {
|
||||
|
@ -725,7 +725,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
||||
const employeeName = ctx.helper.string("employeeName", _employeeName);
|
||||
const job = ctx.helper.string("job", _job);
|
||||
const employee = getEmployee(divisionName, cityName, employeeName);
|
||||
return netscriptDelay(1000, workerScript).then(function () {
|
||||
return netscriptDelay(["Training", "Unassigned"].includes(employee.pos) ? 0 : 1000, workerScript).then(function () {
|
||||
return Promise.resolve(AssignJob(employee, job));
|
||||
});
|
||||
},
|
||||
|
@ -598,38 +598,37 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
||||
const server = player.getCurrentServer();
|
||||
return _ctx.helper.hack(server.hostname, true);
|
||||
},
|
||||
installBackdoor: (_ctx: NetscriptContext) =>
|
||||
function (): Promise<void> {
|
||||
_ctx.helper.checkSingularityAccess();
|
||||
const baseserver = player.getCurrentServer();
|
||||
if (!(baseserver instanceof Server)) {
|
||||
_ctx.log(() => "cannot backdoor this kind of server");
|
||||
return Promise.resolve();
|
||||
installBackdoor: (_ctx: NetscriptContext) => async (): Promise<void> => {
|
||||
_ctx.helper.checkSingularityAccess();
|
||||
const baseserver = player.getCurrentServer();
|
||||
if (!(baseserver instanceof Server)) {
|
||||
_ctx.log(() => "cannot backdoor this kind of server");
|
||||
return Promise.resolve();
|
||||
}
|
||||
const server = baseserver;
|
||||
const installTime = (calculateHackingTime(server, player) / 4) * 1000;
|
||||
|
||||
// No root access or skill level too low
|
||||
const canHack = netscriptCanHack(server, player);
|
||||
if (!canHack.res) {
|
||||
throw _ctx.helper.makeRuntimeErrorMsg(canHack.msg || "");
|
||||
}
|
||||
|
||||
_ctx.log(
|
||||
() => `Installing backdoor on '${server.hostname}' in ${convertTimeMsToTimeElapsedString(installTime, true)}`,
|
||||
);
|
||||
|
||||
return netscriptDelay(installTime, workerScript).then(function () {
|
||||
_ctx.log(() => `Successfully installed backdoor on '${server.hostname}'`);
|
||||
|
||||
server.backdoorInstalled = true;
|
||||
|
||||
if (SpecialServers.WorldDaemon === server.hostname) {
|
||||
Router.toBitVerse(false, false);
|
||||
}
|
||||
const server = baseserver ;
|
||||
const installTime = (calculateHackingTime(server, player) / 4) * 1000;
|
||||
|
||||
// No root access or skill level too low
|
||||
const canHack = netscriptCanHack(server, player);
|
||||
if (!canHack.res) {
|
||||
throw _ctx.helper.makeRuntimeErrorMsg(canHack.msg || "");
|
||||
}
|
||||
|
||||
_ctx.log(
|
||||
() => `Installing backdoor on '${server.hostname}' in ${convertTimeMsToTimeElapsedString(installTime, true)}`,
|
||||
);
|
||||
|
||||
return netscriptDelay(installTime, workerScript).then(function () {
|
||||
_ctx.log(() => `Successfully installed backdoor on '${server.hostname}'`);
|
||||
|
||||
server.backdoorInstalled = true;
|
||||
|
||||
if (SpecialServers.WorldDaemon === server.hostname) {
|
||||
Router.toBitVerse(false, false);
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
},
|
||||
return Promise.resolve();
|
||||
});
|
||||
},
|
||||
isFocused: (_ctx: NetscriptContext) =>
|
||||
function (): boolean {
|
||||
_ctx.helper.checkSingularityAccess();
|
||||
|
@ -1854,7 +1854,11 @@ export function getNextCompanyPosition(
|
||||
}
|
||||
|
||||
export function quitJob(this: IPlayer, company: string, _sing = false): void {
|
||||
if (this.isWorking == true && this.workType !== WorkType.Company && this.companyName == company) {
|
||||
if (
|
||||
this.isWorking === true &&
|
||||
[WorkType.Company, WorkType.CompanyPartTime].includes(this.workType) &&
|
||||
this.companyName === company
|
||||
) {
|
||||
this.finishWork(true);
|
||||
}
|
||||
delete this.jobs[company];
|
||||
@ -2287,7 +2291,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!fulcrumsecrettechonologiesFac.isMember &&
|
||||
!fulcrumsecrettechonologiesFac.alreadyInvited &&
|
||||
fulcrumSecretServer.backdoorInstalled &&
|
||||
checkMegacorpRequirements(LocationName.AevumFulcrumTechnologies, 250e3)
|
||||
checkMegacorpRequirements(LocationName.AevumFulcrumTechnologies)
|
||||
) {
|
||||
invitedFactions.push(fulcrumsecrettechonologiesFac);
|
||||
}
|
||||
|
4
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
4
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -3257,7 +3257,7 @@ export interface Bladeburner {
|
||||
* @remarks
|
||||
* RAM cost: 0 GB
|
||||
*
|
||||
* Returns the amount of accumulated “bonus time” (seconds) for the Bladeburner mechanic.
|
||||
* Returns the amount of accumulated “bonus time” (milliseconds) for the Bladeburner mechanic.
|
||||
*
|
||||
* “Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.
|
||||
*
|
||||
@ -3594,7 +3594,7 @@ export interface Gang {
|
||||
* @remarks
|
||||
* RAM cost: 0 GB
|
||||
*
|
||||
* Returns the amount of accumulated “bonus time” (seconds) for the Gang mechanic.
|
||||
* Returns the amount of accumulated “bonus time” (milliseconds) for the Gang mechanic.
|
||||
*
|
||||
* “Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.
|
||||
*
|
||||
|
@ -272,18 +272,20 @@ const Engine: {
|
||||
const numCyclesOffline = Math.floor(timeOffline / CONSTANTS._idleSpeed);
|
||||
|
||||
// Generate coding contracts
|
||||
let numContracts = 0;
|
||||
if (numCyclesOffline < 3000 * 100) {
|
||||
// if we have less than 100 rolls, just roll them exactly.
|
||||
for (let i = 0; i < numCyclesOffline / 3000; i++) {
|
||||
if (Math.random() < 0.25) numContracts++;
|
||||
if (Player.sourceFiles.length > 0) {
|
||||
let numContracts = 0;
|
||||
if (numCyclesOffline < 3000 * 100) {
|
||||
// if we have less than 100 rolls, just roll them exactly.
|
||||
for (let i = 0; i < numCyclesOffline / 3000; i++) {
|
||||
if (Math.random() < 0.25) numContracts++;
|
||||
}
|
||||
} else {
|
||||
// just average it.
|
||||
numContracts = (numCyclesOffline / 3000) * 0.25;
|
||||
}
|
||||
for (let i = 0; i < numContracts; i++) {
|
||||
generateRandomContract();
|
||||
}
|
||||
} else {
|
||||
// just average it.
|
||||
numContracts = (numCyclesOffline / 3000) * 0.25;
|
||||
}
|
||||
for (let i = 0; i < numContracts; i++) {
|
||||
generateRandomContract();
|
||||
}
|
||||
|
||||
let offlineReputation = 0;
|
||||
|
19
src/ui/React/NumberInput.tsx
Normal file
19
src/ui/React/NumberInput.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { TextField, StandardTextFieldProps } from "@mui/material";
|
||||
import React from "react";
|
||||
import { numeralWrapper } from "../numeralFormat";
|
||||
|
||||
interface IProps extends Omit<StandardTextFieldProps, "onChange"> {
|
||||
onChange: (v: number) => void;
|
||||
}
|
||||
|
||||
export function NumberInput(props: IProps): React.ReactElement {
|
||||
const textProps = {
|
||||
...props,
|
||||
onChange: (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const amt = numeralWrapper.parseMoney(event.target.value);
|
||||
if (event.target.value === "" || isNaN(amt)) props.onChange(NaN);
|
||||
else props.onChange(amt);
|
||||
},
|
||||
};
|
||||
return <TextField {...textProps} />;
|
||||
}
|
Loading…
Reference in New Issue
Block a user