mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-24 08:33:50 +01:00
commit
f359fe661e
@ -6,7 +6,6 @@
|
||||
|
||||
.active-scripts-container {
|
||||
> p {
|
||||
width: 70%;
|
||||
margin: 6px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
.augmentations-content {
|
||||
> p {
|
||||
font-size: $defaultFontSize * 0.875;
|
||||
width: 70%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
.hacknet-general-info {
|
||||
margin: 10px;
|
||||
width: 70vw;
|
||||
}
|
||||
|
||||
#hacknet-nodes-container li {
|
||||
|
1
src/Augmentation/AugmentationHelpers.d.ts
vendored
1
src/Augmentation/AugmentationHelpers.d.ts
vendored
@ -1 +1,2 @@
|
||||
export declare function isRepeatableAug(aug: Augmentation): boolean;
|
||||
export declare function installAugmentations(): void;
|
||||
|
@ -1,16 +1,17 @@
|
||||
import React from "react";
|
||||
import { hackWorldDaemon } from "../../RedPill";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
router: IRouter;
|
||||
popupId: string;
|
||||
}
|
||||
|
||||
export function BitFlumePopup(props: IProps): React.ReactElement {
|
||||
function flume(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN, true, false);
|
||||
props.router.toBitVerse(true, false);
|
||||
removePopup(props.popupId);
|
||||
}
|
||||
return (
|
||||
|
@ -1,18 +1,22 @@
|
||||
import React, { useState } from "react";
|
||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { BitNodes } from "../BitNode";
|
||||
import { enterBitNode } from "../../RedPill";
|
||||
import { PortalPopup } from "./PortalPopup";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { CinematicText } from "../../ui/React/CinematicText";
|
||||
import { use } from "../../ui/Context";
|
||||
|
||||
interface IPortalProps {
|
||||
n: number;
|
||||
level: number;
|
||||
destroyedBitNode: number;
|
||||
flume: boolean;
|
||||
enter: (flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||
enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||
}
|
||||
function BitNodePortal(props: IPortalProps): React.ReactElement {
|
||||
const router = use.Router();
|
||||
const bitNode = BitNodes[`BitNode${props.n}`];
|
||||
if (bitNode == null) {
|
||||
return <>O</>;
|
||||
@ -32,6 +36,7 @@ function BitNodePortal(props: IPortalProps): React.ReactElement {
|
||||
n: props.n,
|
||||
level: props.level,
|
||||
enter: props.enter,
|
||||
router: router,
|
||||
destroyedBitNode: props.destroyedBitNode,
|
||||
flume: props.flume,
|
||||
popupId: popupId,
|
||||
@ -57,18 +62,20 @@ function BitNodePortal(props: IPortalProps): React.ReactElement {
|
||||
|
||||
interface IProps {
|
||||
flume: boolean;
|
||||
destroyedBitNodeNum: number;
|
||||
quick: boolean;
|
||||
enter: (flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||
enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||
}
|
||||
|
||||
export function BitverseRoot(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const enter = enterBitNode;
|
||||
const destroyed = player.bitNodeN;
|
||||
const [destroySequence, setDestroySequence] = useState(true && !props.quick);
|
||||
|
||||
// Update NextSourceFileFlags
|
||||
const nextSourceFileFlags = SourceFileFlags.slice();
|
||||
if (!props.flume) {
|
||||
if (nextSourceFileFlags[props.destroyedBitNodeNum] < 3) ++nextSourceFileFlags[props.destroyedBitNodeNum];
|
||||
if (nextSourceFileFlags[destroyed] < 3) ++nextSourceFileFlags[destroyed];
|
||||
}
|
||||
|
||||
if (destroySequence) {
|
||||
@ -84,7 +91,7 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
||||
"0020 7124696B 0000FF69 74652E6F FFFF1111",
|
||||
"----------------------------------------",
|
||||
"Failsafe initiated...",
|
||||
`Restarting BitNode-${props.destroyedBitNodeNum}...`,
|
||||
`Restarting BitNode-${destroyed}...`,
|
||||
"...........",
|
||||
"...........",
|
||||
"[ERROR] FAILED TO AUTOMATICALLY REBOOT BITNODE",
|
||||
@ -96,6 +103,7 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
||||
"..............................................",
|
||||
]}
|
||||
onDone={() => setDestroySequence(false)}
|
||||
auto={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -116,16 +124,16 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
||||
<pre> \| O | |_/ |\| \ O \__| \_| | O |/ </pre>
|
||||
<pre> | | |_/ | | \| / | \_| | | </pre>
|
||||
<pre> \| / \| | / / \ |/ </pre>
|
||||
<pre> | <BitNodePortal n={10} level={nextSourceFileFlags[10]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> | | / | <BitNodePortal n={11} level={nextSourceFileFlags[11]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> | </pre>
|
||||
<pre> <BitNodePortal n={9} level={nextSourceFileFlags[9]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> | | | | | | | <BitNodePortal n={12} level={nextSourceFileFlags[12]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> </pre>
|
||||
<pre> | <BitNodePortal n={10} level={nextSourceFileFlags[10]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | / | <BitNodePortal n={11} level={nextSourceFileFlags[11]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | </pre>
|
||||
<pre> <BitNodePortal n={9} level={nextSourceFileFlags[9]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | | | | | | <BitNodePortal n={12} level={nextSourceFileFlags[12]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> </pre>
|
||||
<pre> | | | / / \ \ | | | </pre>
|
||||
<pre> \| | / <BitNodePortal n={7} level={nextSourceFileFlags[7]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> / \ <BitNodePortal n={8} level={nextSourceFileFlags[8]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> \ | |/ </pre>
|
||||
<pre> \| | / <BitNodePortal n={7} level={nextSourceFileFlags[7]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> / \ <BitNodePortal n={8} level={nextSourceFileFlags[8]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \ | |/ </pre>
|
||||
<pre> \ | / / | | \ \ | / </pre>
|
||||
<pre> \ \JUMP <BitNodePortal n={5} level={nextSourceFileFlags[5]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} />3R | | | | | | R3<BitNodePortal n={6} level={nextSourceFileFlags[6]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> PMUJ/ / </pre>
|
||||
<pre> \ \JUMP <BitNodePortal n={5} level={nextSourceFileFlags[5]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} />3R | | | | | | R3<BitNodePortal n={6} level={nextSourceFileFlags[6]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> PMUJ/ / </pre>
|
||||
<pre> \|| | | | | | | | | ||/ </pre>
|
||||
<pre> \| \_ | | | | | | _/ |/ </pre>
|
||||
<pre> \ \| / \ / \ |/ / </pre>
|
||||
<pre> <BitNodePortal n={1} level={nextSourceFileFlags[1]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> |/ <BitNodePortal n={2} level={nextSourceFileFlags[2]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> | | <BitNodePortal n={3} level={nextSourceFileFlags[3]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> \| <BitNodePortal n={4} level={nextSourceFileFlags[4]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> </pre>
|
||||
<pre> <BitNodePortal n={1} level={nextSourceFileFlags[1]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> |/ <BitNodePortal n={2} level={nextSourceFileFlags[2]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | <BitNodePortal n={3} level={nextSourceFileFlags[3]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \| <BitNodePortal n={4} level={nextSourceFileFlags[4]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> </pre>
|
||||
<pre> | | | | | | | | </pre>
|
||||
<pre> \JUMP3R|JUMP|3R| |R3|PMUJ|R3PMUJ/ </pre>
|
||||
<br />
|
||||
|
@ -1,13 +1,15 @@
|
||||
import React from "react";
|
||||
|
||||
import { BitNodes } from "../BitNode";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
interface IProps {
|
||||
n: number;
|
||||
level: number;
|
||||
destroyedBitNode: number;
|
||||
flume: boolean;
|
||||
enter: (flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||
router: IRouter;
|
||||
enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||
popupId: string;
|
||||
}
|
||||
|
||||
@ -33,7 +35,7 @@ export function PortalPopup(props: IProps): React.ReactElement {
|
||||
<button
|
||||
className="std-button"
|
||||
onClick={() => {
|
||||
props.enter(props.flume, props.destroyedBitNode, props.n);
|
||||
props.enter(props.router, props.flume, props.destroyedBitNode, props.n);
|
||||
removePopup(props.popupId);
|
||||
}}
|
||||
>
|
||||
|
@ -15,6 +15,7 @@ import { Skill } from "./Skill";
|
||||
import { City } from "./City";
|
||||
import { IAction } from "./IAction";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { ConsoleHelpText } from "./data/Help";
|
||||
import { exceptionAlert } from "../../utils/helpers/exceptionAlert";
|
||||
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
||||
@ -25,7 +26,7 @@ import { addOffset } from "../../utils/helpers/addOffset";
|
||||
import { Faction } from "../Faction/Faction";
|
||||
import { Factions, factionExists } from "../Faction/Factions";
|
||||
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
||||
import { hackWorldDaemon, redPillFlag } from "../RedPill";
|
||||
import { redPillFlag } from "../RedPill";
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
@ -1203,7 +1204,7 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
}
|
||||
|
||||
completeAction(player: IPlayer): void {
|
||||
completeAction(router: IRouter, player: IPlayer): void {
|
||||
switch (this.action.type) {
|
||||
case ActionTypes["Contract"]:
|
||||
case ActionTypes["Operation"]: {
|
||||
@ -1338,7 +1339,7 @@ export class Bladeburner implements IBladeburner {
|
||||
// Operation Daedalus
|
||||
if (action.name === "Operation Daedalus") {
|
||||
this.resetAction();
|
||||
return hackWorldDaemon(player.bitNodeN);
|
||||
return router.toBitVerse(false, false);
|
||||
}
|
||||
|
||||
if (this.logging.blackops) {
|
||||
@ -1540,7 +1541,7 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
}
|
||||
|
||||
processAction(player: IPlayer, seconds: number): void {
|
||||
processAction(router: IRouter, player: IPlayer, seconds: number): void {
|
||||
if (this.action.type === ActionTypes["Idle"]) return;
|
||||
if (this.actionTimeToComplete <= 0) {
|
||||
throw new Error(`Invalid actionTimeToComplete value: ${this.actionTimeToComplete}, type; ${this.action.type}`);
|
||||
@ -1555,7 +1556,7 @@ export class Bladeburner implements IBladeburner {
|
||||
this.actionTimeOverflow = 0;
|
||||
if (this.actionTimeCurrent >= this.actionTimeToComplete) {
|
||||
this.actionTimeOverflow = this.actionTimeCurrent - this.actionTimeToComplete;
|
||||
return this.completeAction(player);
|
||||
return this.completeAction(router, player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1888,10 +1889,10 @@ export class Bladeburner implements IBladeburner {
|
||||
});
|
||||
}
|
||||
|
||||
process(player: IPlayer): void {
|
||||
process(router: IRouter, player: IPlayer): void {
|
||||
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
||||
if (redPillFlag === false && this.blackops.hasOwnProperty("Operation Daedalus")) {
|
||||
return hackWorldDaemon(player.bitNodeN);
|
||||
return router.toBitVerse(false, false);
|
||||
}
|
||||
|
||||
// If the Player starts doing some other actions, set action to idle and alert
|
||||
@ -1958,7 +1959,7 @@ export class Bladeburner implements IBladeburner {
|
||||
this.randomEventCounter += getRandomInt(240, 600);
|
||||
}
|
||||
|
||||
this.processAction(player, seconds);
|
||||
this.processAction(router, player, seconds);
|
||||
|
||||
// Automation
|
||||
if (this.automateEnabled) {
|
||||
|
@ -3,6 +3,7 @@ import { City } from "./City";
|
||||
import { Skill } from "./Skill";
|
||||
import { IAction } from "./IAction";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
|
||||
export interface IBladeburner {
|
||||
@ -103,11 +104,11 @@ export interface IBladeburner {
|
||||
completeOperation(success: boolean): void;
|
||||
getActionObject(actionId: IActionIdentifier): IAction | null;
|
||||
completeContract(success: boolean): void;
|
||||
completeAction(player: IPlayer): void;
|
||||
completeAction(router: IRouter, player: IPlayer): void;
|
||||
changeRank(player: IPlayer, change: number): void;
|
||||
processAction(player: IPlayer, seconds: number): void;
|
||||
processAction(router: IRouter, player: IPlayer, seconds: number): void;
|
||||
calculateStaminaGainPerSecond(player: IPlayer): number;
|
||||
calculateMaxStamina(player: IPlayer): void;
|
||||
create(): void;
|
||||
process(player: IPlayer): void;
|
||||
process(router: IRouter, player: IPlayer): void;
|
||||
}
|
||||
|
42
src/Bladeburner/ui/BladeburnerCinematic.tsx
Normal file
42
src/Bladeburner/ui/BladeburnerCinematic.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import React from "react";
|
||||
import { use } from "../../ui/Context";
|
||||
import { CinematicText } from "../../ui/React/CinematicText";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
|
||||
export function BladeburnerCinematic(): React.ReactElement {
|
||||
const router = use.Router();
|
||||
return (
|
||||
<CinematicText
|
||||
lines={[
|
||||
"In the middle of the 21st century, OmniTek Incorporated advanced robot evolution ",
|
||||
"with their Synthoids (synthetic androids), a being virtually identical to a human.",
|
||||
"------",
|
||||
"Their sixth-generation Synthoids, called MK-VI, were stronger, faster, and more ",
|
||||
"intelligent than humans. Many argued that the MK-VI Synthoids were the first ",
|
||||
"example of sentient AI.",
|
||||
"------",
|
||||
"Unfortunately, in 2070 a terrorist group called Ascendis Totalis hacked into OmniTek and ",
|
||||
"uploaded a rogue AI into their Synthoid manufacturing facilities.",
|
||||
"------",
|
||||
"The MK-VI Synthoids infected by the rogue AI turned hostile toward humanity, initiating ",
|
||||
"the deadliest conflict in human history. This dark chapter is now known as the Synthoid Uprising.",
|
||||
"------",
|
||||
"In the aftermath of the Uprising, further manufacturing of Synthoids with advanced AI ",
|
||||
"was banned. MK-VI Synthoids that did not have the rogue Ascendis Totalis AI were ",
|
||||
"allowed to continue their existence.",
|
||||
"------",
|
||||
"The intelligence community believes that not all of the rogue MK-VI Synthoids from the Uprising were ",
|
||||
"found and destroyed, and that many of them are blending in as normal humans in society today. ",
|
||||
"As a result, many nations have created Bladeburner divisions, special units that are tasked with ",
|
||||
"investigating and dealing with Synthoid threats.",
|
||||
]}
|
||||
onDone={() => {
|
||||
router.toTerminal();
|
||||
dialogBoxCreate(
|
||||
"Visit the National Security Agency (NSA) to apply for their Bladeburner " +
|
||||
"division! You will need 100 of each combat stat before doing this.",
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
@ -3,17 +3,16 @@ import { Stats } from "./Stats";
|
||||
import { Console } from "./Console";
|
||||
import { AllPages } from "./AllPages";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { use } from "../../ui/Context";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
engine: IEngine;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Root(props: IProps): React.ReactElement {
|
||||
export function BladeburnerRoot(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
return (
|
||||
<div className="bladeburner-container">
|
||||
<div style={{ height: "60%", display: "block", position: "relative" }}>
|
||||
@ -25,9 +24,9 @@ export function Root(props: IProps): React.ReactElement {
|
||||
border: "1px solid white",
|
||||
}}
|
||||
>
|
||||
<Stats bladeburner={props.bladeburner} player={props.player} engine={props.engine} />
|
||||
<Stats bladeburner={props.bladeburner} player={player} router={router} />
|
||||
</div>
|
||||
<Console bladeburner={props.bladeburner} player={props.player} />
|
||||
<Console bladeburner={props.bladeburner} player={player} />
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
@ -39,7 +38,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<AllPages bladeburner={props.bladeburner} player={props.player} />
|
||||
<AllPages bladeburner={props.bladeburner} player={player} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
@ -2,21 +2,21 @@ import React, { useState, useEffect } from "react";
|
||||
import { formatNumber, convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
|
||||
import { BladeburnerConstants } from "../data/Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { StatsTable } from "../../ui/React/StatsTable";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { joinFaction, displayFactionContent } from "../../Faction/FactionHelpers";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { joinFaction } from "../../Faction/FactionHelpers";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
|
||||
import { TravelPopup } from "./TravelPopup";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
@ -72,8 +72,7 @@ export function Stats(props: IProps): React.ReactElement {
|
||||
function openFaction(): void {
|
||||
const faction = Factions["Bladeburners"];
|
||||
if (faction.isMember) {
|
||||
props.engine.loadFactionContent();
|
||||
displayFactionContent("Bladeburners");
|
||||
props.router.toFaction(faction);
|
||||
} else {
|
||||
if (props.bladeburner.rank >= BladeburnerConstants.RankNeededForFaction) {
|
||||
joinFaction(faction);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||
import { IEngine } from "./IEngine";
|
||||
import { IRouter } from "./ui/Router";
|
||||
|
||||
import React from "react";
|
||||
import { TTheme as Theme } from "./ui/React/Theme";
|
||||
@ -24,6 +25,7 @@ import { TimeSkip } from "./DevMenu/ui/TimeSkip";
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
}
|
||||
|
||||
export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
@ -31,7 +33,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
<Theme>
|
||||
<>
|
||||
<h1>Development Menu - Only meant to be used for testing/debugging</h1>
|
||||
<General player={props.player} />
|
||||
<General player={props.player} router={props.router} />
|
||||
<Stats player={props.player} />
|
||||
<Factions player={props.player} />
|
||||
<Augmentations player={props.player} />
|
||||
|
@ -8,10 +8,11 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { hackWorldDaemon } from "../../RedPill";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
router: IRouter;
|
||||
}
|
||||
|
||||
export function General(props: IProps): React.ReactElement {
|
||||
@ -26,19 +27,19 @@ export function General(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function quickB1tFlum3(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN, true, true);
|
||||
props.router.toBitVerse(true, true);
|
||||
}
|
||||
|
||||
function b1tflum3(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN, true);
|
||||
props.router.toBitVerse(true, false);
|
||||
}
|
||||
|
||||
function quickHackW0r1dD43m0n(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN, false, true);
|
||||
props.router.toBitVerse(false, true);
|
||||
}
|
||||
|
||||
function hackW0r1dD43m0n(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN);
|
||||
props.router.toBitVerse(false, false);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -30,7 +30,7 @@ export function TimeSkip(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Accordion>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<h2>Sleeves</h2>
|
||||
<h2>Time skip</h2>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Button onClick={timeskip(60 * 1000)}>1 minute</Button>
|
||||
|
2
src/Faction/FactionHelpers.d.ts
vendored
2
src/Faction/FactionHelpers.d.ts
vendored
@ -4,5 +4,5 @@ import { Faction } from "../Faction/Faction";
|
||||
export declare function getNextNeurofluxLevel(): number;
|
||||
export declare function hasAugmentationPrereqs(aug: Augmentation): boolean;
|
||||
export declare function purchaseAugmentation(aug: Augmentation, fac: Faction, sing?: boolean): void;
|
||||
export declare function displayFactionContent(factionName: string, initiallyOnAugmentationsPage: boolean = false);
|
||||
export declare function joinFaction(faction: Faction): void;
|
||||
export declare function startHackingMission(faction: Faction): void;
|
||||
|
@ -1,14 +1,9 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
import { FactionRoot } from "./ui/Root";
|
||||
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { Engine } from "../engine";
|
||||
|
||||
import { Faction } from "./Faction";
|
||||
import { Factions } from "./Factions";
|
||||
import { HackingMission, setInMission } from "../Missions";
|
||||
@ -65,29 +60,6 @@ export function startHackingMission(faction) {
|
||||
mission.init();
|
||||
}
|
||||
|
||||
//Displays the HTML content for a specific faction
|
||||
export function displayFactionContent(factionName, initiallyOnAugmentationsPage = false) {
|
||||
const faction = Factions[factionName];
|
||||
if (faction == null) {
|
||||
throw new Error(`Invalid factionName passed into displayFactionContent(): ${factionName}`);
|
||||
}
|
||||
|
||||
if (!faction.isMember) {
|
||||
throw new Error(`Not a member of this faction. Cannot display faction information`);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<FactionRoot
|
||||
engine={Engine}
|
||||
initiallyOnAugmentationsPage={initiallyOnAugmentationsPage}
|
||||
faction={faction}
|
||||
p={Player}
|
||||
startHackingMissionFn={startHackingMission}
|
||||
/>,
|
||||
Engine.Display.content,
|
||||
);
|
||||
}
|
||||
|
||||
//Returns a boolean indicating whether the player has the prerequisites for the
|
||||
//specified Augmentation
|
||||
export function hasAugmentationPrereqs(aug) {
|
||||
@ -187,9 +159,6 @@ export function purchaseAugmentation(aug, fac, sing = false) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Force a rerender of the Augmentations page
|
||||
displayFactionContent(fac.name, true);
|
||||
} else {
|
||||
dialogBoxCreate(
|
||||
"Hmm, something went wrong when trying to purchase an Augmentation. " +
|
||||
|
@ -1,52 +1,37 @@
|
||||
/**
|
||||
* Root React Component for displaying a faction's "Purchase Augmentations" page
|
||||
*/
|
||||
import * as React from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { PurchaseableAugmentation } from "./PurchaseableAugmentation";
|
||||
|
||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { use } from "../../ui/Context";
|
||||
|
||||
type IProps = {
|
||||
faction: Faction;
|
||||
p: IPlayer;
|
||||
routeToMainPage: () => void;
|
||||
};
|
||||
|
||||
type IState = {
|
||||
rerenderFlag: boolean;
|
||||
sortOrder: PurchaseAugmentationsOrderSetting;
|
||||
};
|
||||
|
||||
const infoStyleMarkup = {
|
||||
width: "70%",
|
||||
};
|
||||
|
||||
export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
// Flag for whether the player has a gang with this faction
|
||||
isPlayersGang: boolean;
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
const isPlayersGang = player.inGang() && player.getGangName() === props.faction.name;
|
||||
|
||||
this.isPlayersGang = props.p.inGang() && props.p.getGangName() === props.faction.name;
|
||||
const setRerender = useState(false)[1];
|
||||
|
||||
this.state = {
|
||||
rerenderFlag: false,
|
||||
sortOrder: PurchaseAugmentationsOrderSetting.Default,
|
||||
};
|
||||
|
||||
this.rerender = this.rerender.bind(this);
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
|
||||
getAugs(): string[] {
|
||||
if (this.isPlayersGang) {
|
||||
function getAugs(): string[] {
|
||||
if (isPlayersGang) {
|
||||
const augs: string[] = [];
|
||||
for (const augName in Augmentations) {
|
||||
const aug = Augmentations[augName];
|
||||
@ -57,25 +42,25 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
|
||||
return augs;
|
||||
} else {
|
||||
return this.props.faction.augmentations.slice();
|
||||
return props.faction.augmentations.slice();
|
||||
}
|
||||
}
|
||||
|
||||
getAugsSorted(): string[] {
|
||||
function getAugsSorted(): string[] {
|
||||
switch (Settings.PurchaseAugmentationsOrder) {
|
||||
case PurchaseAugmentationsOrderSetting.Cost: {
|
||||
return this.getAugsSortedByCost();
|
||||
return getAugsSortedByCost();
|
||||
}
|
||||
case PurchaseAugmentationsOrderSetting.Reputation: {
|
||||
return this.getAugsSortedByReputation();
|
||||
return getAugsSortedByReputation();
|
||||
}
|
||||
default:
|
||||
return this.getAugsSortedByDefault();
|
||||
return getAugsSortedByDefault();
|
||||
}
|
||||
}
|
||||
|
||||
getAugsSortedByCost(): string[] {
|
||||
const augs = this.getAugs();
|
||||
function getAugsSortedByCost(): string[] {
|
||||
const augs = getAugs();
|
||||
augs.sort((augName1, augName2) => {
|
||||
const aug1 = Augmentations[augName1],
|
||||
aug2 = Augmentations[augName2];
|
||||
@ -89,8 +74,8 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
return augs;
|
||||
}
|
||||
|
||||
getAugsSortedByReputation(): string[] {
|
||||
const augs = this.getAugs();
|
||||
function getAugsSortedByReputation(): string[] {
|
||||
const augs = getAugs();
|
||||
augs.sort((augName1, augName2) => {
|
||||
const aug1 = Augmentations[augName1],
|
||||
aug2 = Augmentations[augName2];
|
||||
@ -103,88 +88,70 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
return augs;
|
||||
}
|
||||
|
||||
getAugsSortedByDefault(): string[] {
|
||||
return this.getAugs();
|
||||
function getAugsSortedByDefault(): string[] {
|
||||
return getAugs();
|
||||
}
|
||||
|
||||
switchSortOrder(newOrder: PurchaseAugmentationsOrderSetting): void {
|
||||
function switchSortOrder(newOrder: PurchaseAugmentationsOrderSetting): void {
|
||||
Settings.PurchaseAugmentationsOrder = newOrder;
|
||||
this.rerender();
|
||||
rerender();
|
||||
}
|
||||
|
||||
rerender(): void {
|
||||
this.setState((prevState) => {
|
||||
return {
|
||||
rerenderFlag: !prevState.rerenderFlag,
|
||||
};
|
||||
});
|
||||
}
|
||||
const augs = getAugsSorted();
|
||||
const purchasable = augs.filter(
|
||||
(aug: string) =>
|
||||
aug === AugmentationNames.NeuroFluxGovernor ||
|
||||
(!player.augmentations.some((a) => a.name === aug) && !player.queuedAugmentations.some((a) => a.name === aug)),
|
||||
);
|
||||
|
||||
render(): React.ReactNode {
|
||||
const augs = this.getAugsSorted();
|
||||
const purchasable = augs.filter(
|
||||
(aug: string) => aug === AugmentationNames.NeuroFluxGovernor ||
|
||||
(!this.props.p.augmentations.some((a) => a.name === aug) &&
|
||||
!this.props.p.queuedAugmentations.some((a) => a.name === aug)),
|
||||
);
|
||||
const purchaseableAugmentation = (aug: string): React.ReactNode => {
|
||||
return <PurchaseableAugmentation augName={aug} faction={props.faction} key={aug} p={player} rerender={rerender} />;
|
||||
};
|
||||
|
||||
const purchaseableAugmentation = (aug: string): React.ReactNode => {
|
||||
return (
|
||||
<PurchaseableAugmentation
|
||||
augName={aug}
|
||||
faction={this.props.faction}
|
||||
key={aug}
|
||||
p={this.props.p}
|
||||
rerender={this.rerender}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const augListElems = purchasable.map((aug) => purchaseableAugmentation(aug));
|
||||
|
||||
const augListElems = purchasable.map((aug) => purchaseableAugmentation(aug));
|
||||
|
||||
let ownedElem = <></>;
|
||||
const owned = augs.filter((aug: string) => !purchasable.includes(aug));
|
||||
if (owned.length !== 0) {
|
||||
ownedElem = (
|
||||
<>
|
||||
<br />
|
||||
<h2>Purchased Augmentations</h2>
|
||||
<p style={infoStyleMarkup}>This factions also offers these augmentations but you already own them.</p>
|
||||
{owned.map((aug) => purchaseableAugmentation(aug))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<StdButton onClick={this.props.routeToMainPage} text={"Back"} />
|
||||
<h1>Faction Augmentations</h1>
|
||||
<p style={infoStyleMarkup}>
|
||||
These are all of the Augmentations that are available to purchase from {this.props.faction.name}.
|
||||
Augmentations are powerful upgrades that will enhance your abilities.
|
||||
</p>
|
||||
<StdButton onClick={() => this.switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)} text={"Sort by Cost"} />
|
||||
<StdButton
|
||||
onClick={() => this.switchSortOrder(PurchaseAugmentationsOrderSetting.Reputation)}
|
||||
text={"Sort by Reputation"}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={() => this.switchSortOrder(PurchaseAugmentationsOrderSetting.Default)}
|
||||
text={"Sort by Default Order"}
|
||||
/>
|
||||
let ownedElem = <></>;
|
||||
const owned = augs.filter((aug: string) => !purchasable.includes(aug));
|
||||
if (owned.length !== 0) {
|
||||
ownedElem = (
|
||||
<>
|
||||
<br />
|
||||
{augListElems}
|
||||
{ownedElem}
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
<h2>Purchased Augmentations</h2>
|
||||
<p>This factions also offers these augmentations but you already own them.</p>
|
||||
{owned.map((aug) => purchaseableAugmentation(aug))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<StdButton onClick={props.routeToMainPage} text={"Back"} />
|
||||
<h1>Faction Augmentations</h1>
|
||||
<p>
|
||||
These are all of the Augmentations that are available to purchase from {props.faction.name}. Augmentations are
|
||||
powerful upgrades that will enhance your abilities.
|
||||
</p>
|
||||
<StdButton onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)} text={"Sort by Cost"} />
|
||||
<StdButton
|
||||
onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Reputation)}
|
||||
text={"Sort by Reputation"}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Default)}
|
||||
text={"Sort by Default Order"}
|
||||
/>
|
||||
<br />
|
||||
{augListElems}
|
||||
{ownedElem}
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,58 +1,66 @@
|
||||
/**
|
||||
* React Component for the popup used to create a new gang.
|
||||
*/
|
||||
import React from "react";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import React from "react";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { use } from "../../ui/Context";
|
||||
|
||||
interface ICreateGangPopupProps {
|
||||
popupId: string;
|
||||
facName: string;
|
||||
p: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
interface ICreateGangPopupProps {
|
||||
popupId: string;
|
||||
facName: string;
|
||||
}
|
||||
|
||||
export function CreateGangPopup(props: ICreateGangPopupProps): React.ReactElement {
|
||||
|
||||
const combatGangText = "This is a COMBAT gang. Members in this gang will have different tasks than HACKING gangs. " +
|
||||
export function CreateGangPopup(props: ICreateGangPopupProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const combatGangText =
|
||||
"This is a COMBAT gang. Members in this gang will have different tasks than HACKING gangs. " +
|
||||
"Compared to hacking gangs, progression with combat gangs can be more difficult as territory management " +
|
||||
"is more important. However, well-managed combat gangs can progress faster than hacking ones.";
|
||||
|
||||
const hackingGangText = "This is a HACKING gang. Members in this gang will have different tasks than COMBAT gangs. " +
|
||||
const hackingGangText =
|
||||
"This is a HACKING gang. Members in this gang will have different tasks than COMBAT gangs. " +
|
||||
"Compared to combat gangs, progression with hacking gangs is more straightforward as territory warfare " +
|
||||
"is not as important.";
|
||||
|
||||
function isHacking(): boolean {
|
||||
return ["NiteSec", "The Black Hand"].includes(props.facName);
|
||||
}
|
||||
function isHacking(): boolean {
|
||||
return ["NiteSec", "The Black Hand"].includes(props.facName);
|
||||
}
|
||||
|
||||
function createGang(): void {
|
||||
props.p.startGang(props.facName, isHacking());
|
||||
removePopup(props.popupId);
|
||||
props.engine.loadGangContent();
|
||||
}
|
||||
function createGang(): void {
|
||||
player.startGang(props.facName, isHacking());
|
||||
removePopup(props.popupId);
|
||||
router.toGang();
|
||||
}
|
||||
|
||||
function onKeyUp(event: React.KeyboardEvent): void {
|
||||
if (event.keyCode === 13) createGang();
|
||||
}
|
||||
function onKeyUp(event: React.KeyboardEvent): void {
|
||||
if (event.keyCode === 13) createGang();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Would you like to create a new Gang with {props.facName}?
|
||||
<br/>
|
||||
<br/>
|
||||
Note that this will prevent you from creating a Gang with any other Faction until this BitNode is destroyed. It also resets your reputation with this faction.
|
||||
<br/>
|
||||
<br/>
|
||||
{ (isHacking()) ? hackingGangText : combatGangText }
|
||||
<br/>
|
||||
<br/>
|
||||
Other than hacking vs combat, there are NO differences between the Factions you can create a Gang with, and each of these Factions have all Augmentations available.
|
||||
<div className="popup-box-input-div" >
|
||||
<StdButton onClick={createGang} onKeyUp={onKeyUp} text="Create Gang" style={{float: "right"}} autoFocus={true}/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
Would you like to create a new Gang with {props.facName}?
|
||||
<br />
|
||||
<br />
|
||||
Note that this will prevent you from creating a Gang with any other Faction until this BitNode is destroyed. It
|
||||
also resets your reputation with this faction.
|
||||
<br />
|
||||
<br />
|
||||
{isHacking() ? hackingGangText : combatGangText}
|
||||
<br />
|
||||
<br />
|
||||
Other than hacking vs combat, there are NO differences between the Factions you can create a Gang with, and each
|
||||
of these Factions have all Augmentations available.
|
||||
<div className="popup-box-input-div">
|
||||
<StdButton
|
||||
onClick={createGang}
|
||||
onKeyUp={onKeyUp}
|
||||
text="Create Gang"
|
||||
style={{ float: "right" }}
|
||||
autoFocus={true}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
* This is the component for displaying a single faction's UI, not the list of all
|
||||
* accessible factions
|
||||
*/
|
||||
import * as React from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { AugmentationsPage } from "./AugmentationsPage";
|
||||
import { DonateOption } from "./DonateOption";
|
||||
@ -11,30 +11,21 @@ import { Info } from "./Info";
|
||||
import { Option } from "./Option";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IEngine } from "../../IEngine";
|
||||
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { createSleevePurchasesFromCovenantPopup } from "../../PersonObjects/Sleeve/SleeveCovenantPurchases";
|
||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { use } from "../../ui/Context";
|
||||
import { CreateGangPopup } from "./CreateGangPopup";
|
||||
|
||||
type IProps = {
|
||||
engine: IEngine;
|
||||
initiallyOnAugmentationsPage?: boolean;
|
||||
faction: Faction;
|
||||
p: IPlayer;
|
||||
faction: Faction | null;
|
||||
startHackingMissionFn: (faction: Faction) => void;
|
||||
};
|
||||
|
||||
type IState = {
|
||||
rerenderFlag: boolean;
|
||||
purchasingAugs: boolean;
|
||||
};
|
||||
|
||||
// Info text for all options on the UI
|
||||
const gangInfo = "Create and manage a gang for this Faction. Gangs will earn you money and " + "faction reputation";
|
||||
const hackingMissionInfo =
|
||||
@ -72,89 +63,68 @@ const GangNames = [
|
||||
"The Black Hand",
|
||||
];
|
||||
|
||||
export class FactionRoot extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
export function FactionRoot(props: IProps): React.ReactElement {
|
||||
const faction = props.faction;
|
||||
if (faction === null) throw new Error("Trying to render the Faction page with null faction");
|
||||
|
||||
this.state = {
|
||||
rerenderFlag: false,
|
||||
purchasingAugs: props.initiallyOnAugmentationsPage ? props.initiallyOnAugmentationsPage : false,
|
||||
};
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const [, setRerenderFlag] = useState(false);
|
||||
const [purchasingAugs, setPurchasingAugs] = useState(false);
|
||||
|
||||
this.manageGang = this.manageGang.bind(this);
|
||||
this.rerender = this.rerender.bind(this);
|
||||
this.routeToMain = this.routeToMain.bind(this);
|
||||
this.routeToPurchaseAugs = this.routeToPurchaseAugs.bind(this);
|
||||
this.sleevePurchases = this.sleevePurchases.bind(this);
|
||||
this.startFieldWork = this.startFieldWork.bind(this);
|
||||
this.startHackingContracts = this.startHackingContracts.bind(this);
|
||||
this.startHackingMission = this.startHackingMission.bind(this);
|
||||
this.startSecurityWork = this.startSecurityWork.bind(this);
|
||||
}
|
||||
|
||||
manageGang(): void {
|
||||
function manageGang(faction: Faction): void {
|
||||
// If player already has a gang, just go to the gang UI
|
||||
if (this.props.p.inGang()) {
|
||||
return this.props.engine.loadGangContent();
|
||||
if (player.inGang()) {
|
||||
return router.toGang();
|
||||
}
|
||||
|
||||
const popupId = "create-gang-popup";
|
||||
createPopup(popupId, CreateGangPopup, {
|
||||
popupId: popupId,
|
||||
facName: this.props.faction.name,
|
||||
p: this.props.p,
|
||||
engine: this.props.engine,
|
||||
facName: faction.name,
|
||||
});
|
||||
}
|
||||
|
||||
rerender(): void {
|
||||
this.setState((prevState) => {
|
||||
return {
|
||||
rerenderFlag: !prevState.rerenderFlag,
|
||||
};
|
||||
});
|
||||
function rerender(): void {
|
||||
setRerenderFlag((old) => !old);
|
||||
}
|
||||
|
||||
// Route to the main faction page
|
||||
routeToMain(): void {
|
||||
this.setState({ purchasingAugs: false });
|
||||
function routeToMain(): void {
|
||||
setPurchasingAugs(false);
|
||||
}
|
||||
|
||||
// Route to the purchase augmentation UI for this faction
|
||||
routeToPurchaseAugs(): void {
|
||||
this.setState({ purchasingAugs: true });
|
||||
function routeToPurchaseAugs(): void {
|
||||
setPurchasingAugs(true);
|
||||
}
|
||||
|
||||
sleevePurchases(): void {
|
||||
createSleevePurchasesFromCovenantPopup(this.props.p);
|
||||
function sleevePurchases(): void {
|
||||
createSleevePurchasesFromCovenantPopup(player);
|
||||
}
|
||||
|
||||
startFieldWork(): void {
|
||||
this.props.p.startFactionFieldWork(this.props.faction);
|
||||
function startFieldWork(faction: Faction): void {
|
||||
player.startFactionFieldWork(faction);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
startHackingContracts(): void {
|
||||
this.props.p.startFactionHackWork(this.props.faction);
|
||||
function startHackingContracts(faction: Faction): void {
|
||||
player.startFactionHackWork(faction);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
startHackingMission(): void {
|
||||
const fac = this.props.faction;
|
||||
this.props.p.singularityStopWork();
|
||||
this.props.engine.loadMissionContent();
|
||||
this.props.startHackingMissionFn(fac);
|
||||
function startHackingMission(faction: Faction): void {
|
||||
player.singularityStopWork();
|
||||
props.startHackingMissionFn(faction);
|
||||
}
|
||||
|
||||
startSecurityWork(): void {
|
||||
this.props.p.startFactionSecurityWork(this.props.faction);
|
||||
function startSecurityWork(faction: Faction): void {
|
||||
player.startFactionSecurityWork(faction);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return this.state.purchasingAugs ? this.renderAugmentationsPage() : this.renderMainPage();
|
||||
}
|
||||
|
||||
renderMainPage(): React.ReactNode {
|
||||
const p = this.props.p;
|
||||
const faction = this.props.faction;
|
||||
function MainPage({ faction }: { faction: Faction }): React.ReactElement {
|
||||
const p = player;
|
||||
const factionInfo = faction.getInfo();
|
||||
|
||||
// We have a special flag for whether the player this faction is the player's
|
||||
@ -181,49 +151,51 @@ export class FactionRoot extends React.Component<IProps, IState> {
|
||||
<div className="faction-container">
|
||||
<h1>{faction.name}</h1>
|
||||
<Info faction={faction} factionInfo={factionInfo} />
|
||||
{canAccessGang && <Option buttonText={"Manage Gang"} infoText={gangInfo} onClick={this.manageGang} />}
|
||||
{canAccessGang && <Option buttonText={"Manage Gang"} infoText={gangInfo} onClick={() => manageGang(faction)} />}
|
||||
{!isPlayersGang && factionInfo.offerHackingMission && (
|
||||
<Option buttonText={"Hacking Mission"} infoText={hackingMissionInfo} onClick={this.startHackingMission} />
|
||||
<Option
|
||||
buttonText={"Hacking Mission"}
|
||||
infoText={hackingMissionInfo}
|
||||
onClick={() => startHackingMission(faction)}
|
||||
/>
|
||||
)}
|
||||
{!isPlayersGang && factionInfo.offerHackingWork && (
|
||||
<Option
|
||||
buttonText={"Hacking Contracts"}
|
||||
infoText={hackingContractsInfo}
|
||||
onClick={this.startHackingContracts}
|
||||
onClick={() => startHackingContracts(faction)}
|
||||
/>
|
||||
)}
|
||||
{!isPlayersGang && factionInfo.offerFieldWork && (
|
||||
<Option buttonText={"Field Work"} infoText={fieldWorkInfo} onClick={this.startFieldWork} />
|
||||
<Option buttonText={"Field Work"} infoText={fieldWorkInfo} onClick={() => startFieldWork(faction)} />
|
||||
)}
|
||||
{!isPlayersGang && factionInfo.offerSecurityWork && (
|
||||
<Option buttonText={"Security Work"} infoText={securityWorkInfo} onClick={this.startSecurityWork} />
|
||||
<Option buttonText={"Security Work"} infoText={securityWorkInfo} onClick={() => startSecurityWork(faction)} />
|
||||
)}
|
||||
{!isPlayersGang && factionInfo.offersWork() && (
|
||||
<DonateOption
|
||||
faction={this.props.faction}
|
||||
p={this.props.p}
|
||||
rerender={this.rerender}
|
||||
faction={faction}
|
||||
p={player}
|
||||
rerender={rerender}
|
||||
favorToDonate={favorToDonate}
|
||||
disabled={!canDonate}
|
||||
/>
|
||||
)}
|
||||
<Option buttonText={"Purchase Augmentations"} infoText={augmentationsInfo} onClick={this.routeToPurchaseAugs} />
|
||||
<Option buttonText={"Purchase Augmentations"} infoText={augmentationsInfo} onClick={routeToPurchaseAugs} />
|
||||
{canPurchaseSleeves && (
|
||||
<Option
|
||||
buttonText={"Purchase & Upgrade Duplicate Sleeves"}
|
||||
infoText={sleevePurchasesInfo}
|
||||
onClick={this.sleevePurchases}
|
||||
onClick={sleevePurchases}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderAugmentationsPage(): React.ReactNode {
|
||||
return (
|
||||
<>
|
||||
<AugmentationsPage faction={this.props.faction} p={this.props.p} routeToMainPage={this.routeToMain} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
return purchasingAugs ? (
|
||||
<AugmentationsPage faction={faction} routeToMainPage={routeToMain} />
|
||||
) : (
|
||||
<MainPage faction={faction} />
|
||||
);
|
||||
}
|
@ -1,20 +1,20 @@
|
||||
import React, { useState } from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { Factions } from "../Factions";
|
||||
import { displayFactionContent, joinFaction } from "../FactionHelpers";
|
||||
import { Faction } from "../Faction";
|
||||
import { joinFaction } from "../FactionHelpers";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
}
|
||||
|
||||
export function FactionList(props: IProps): React.ReactElement {
|
||||
export function FactionsRoot(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
|
||||
function openFaction(faction: string): void {
|
||||
props.engine.loadFactionContent();
|
||||
displayFactionContent(faction);
|
||||
function openFaction(faction: Faction): void {
|
||||
props.router.toFaction(faction);
|
||||
}
|
||||
|
||||
function acceptInvitation(event: React.MouseEvent<HTMLElement>, faction: string): void {
|
||||
@ -33,7 +33,7 @@ export function FactionList(props: IProps): React.ReactElement {
|
||||
<li key={faction}>
|
||||
<a
|
||||
className="a-link-button"
|
||||
onClick={() => openFaction(faction)}
|
||||
onClick={() => openFaction(Factions[faction])}
|
||||
style={{ padding: "4px", margin: "4px", display: "inline-block" }}
|
||||
>
|
||||
{faction}
|
@ -12,6 +12,7 @@ interface IProps {
|
||||
player: IPlayer;
|
||||
faction: Faction;
|
||||
aug: Augmentation;
|
||||
rerender: () => void;
|
||||
popupId: string;
|
||||
}
|
||||
|
||||
@ -24,6 +25,7 @@ export function PurchaseAugmentationPopup(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
purchaseAugmentation(props.aug, props.faction);
|
||||
props.rerender();
|
||||
removePopup(props.popupId);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ import * as React from "react";
|
||||
import { getNextNeurofluxLevel, hasAugmentationPrereqs, purchaseAugmentation } from "../FactionHelpers";
|
||||
import { PurchaseAugmentationPopup } from "./PurchaseAugmentationPopup";
|
||||
|
||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
@ -28,63 +27,56 @@ type IProps = {
|
||||
rerender: () => void;
|
||||
};
|
||||
|
||||
export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
||||
aug: Augmentation;
|
||||
export function PurchaseableAugmentation(props: IProps): React.ReactElement {
|
||||
const aug = Augmentations[props.augName];
|
||||
if (aug == null) throw new Error(`aug ${props.augName} does not exists`);
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
const aug = Augmentations[this.props.augName];
|
||||
if (aug == null) throw new Error(`aug ${this.props.augName} does not exists`);
|
||||
this.aug = aug;
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
function getMoneyCost(): number {
|
||||
return aug.baseCost * props.faction.getInfo().augmentationPriceMult;
|
||||
}
|
||||
|
||||
getMoneyCost(): number {
|
||||
return this.aug.baseCost * this.props.faction.getInfo().augmentationPriceMult;
|
||||
function getRepCost(): number {
|
||||
return aug.baseRepRequirement * props.faction.getInfo().augmentationRepRequirementMult;
|
||||
}
|
||||
|
||||
getRepCost(): number {
|
||||
return this.aug.baseRepRequirement * this.props.faction.getInfo().augmentationRepRequirementMult;
|
||||
}
|
||||
|
||||
handleClick(): void {
|
||||
function handleClick(): void {
|
||||
if (!Settings.SuppressBuyAugmentationConfirmation) {
|
||||
const popupId = "purchase-augmentation-popup";
|
||||
createPopup(popupId, PurchaseAugmentationPopup, {
|
||||
aug: this.aug,
|
||||
faction: this.props.faction,
|
||||
player: this.props.p,
|
||||
aug: aug,
|
||||
faction: props.faction,
|
||||
player: props.p,
|
||||
rerender: props.rerender,
|
||||
popupId: popupId,
|
||||
});
|
||||
} else {
|
||||
purchaseAugmentation(this.aug, this.props.faction);
|
||||
purchaseAugmentation(aug, props.faction);
|
||||
props.rerender();
|
||||
}
|
||||
}
|
||||
|
||||
// Whether the player has the prerequisite Augmentations
|
||||
hasPrereqs(): boolean {
|
||||
return hasAugmentationPrereqs(this.aug);
|
||||
function hasPrereqs(): boolean {
|
||||
return hasAugmentationPrereqs(aug);
|
||||
}
|
||||
|
||||
// Whether the player has enough rep for this Augmentation
|
||||
hasReputation(): boolean {
|
||||
return this.props.faction.playerReputation >= this.getRepCost();
|
||||
function hasReputation(): boolean {
|
||||
return props.faction.playerReputation >= getRepCost();
|
||||
}
|
||||
|
||||
// Whether the player has this augmentations (purchased OR installed)
|
||||
owned(): boolean {
|
||||
function owned(): boolean {
|
||||
let owned = false;
|
||||
for (const queuedAug of this.props.p.queuedAugmentations) {
|
||||
if (queuedAug.name === this.props.augName) {
|
||||
for (const queuedAug of props.p.queuedAugmentations) {
|
||||
if (queuedAug.name === props.augName) {
|
||||
owned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const installedAug of this.props.p.augmentations) {
|
||||
if (installedAug.name === this.props.augName) {
|
||||
for (const installedAug of props.p.augmentations) {
|
||||
if (installedAug.name === props.augName) {
|
||||
owned = true;
|
||||
break;
|
||||
}
|
||||
@ -93,96 +85,94 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
||||
return owned;
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
if (this.aug == null) {
|
||||
console.error(
|
||||
`Invalid Augmentation when trying to create PurchaseableAugmentation display element: ${this.props.augName}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const moneyCost = this.getMoneyCost();
|
||||
const repCost = this.getRepCost();
|
||||
|
||||
// Determine UI properties
|
||||
let disabled = false;
|
||||
let status: JSX.Element = <></>;
|
||||
let color = "";
|
||||
if (!this.hasPrereqs()) {
|
||||
disabled = true;
|
||||
status = <>LOCKED (Requires {this.aug.prereqs.map((aug) => AugFormat(aug))} as prerequisite)</>;
|
||||
color = "red";
|
||||
} else if (this.aug.name !== AugmentationNames.NeuroFluxGovernor && (this.aug.owned || this.owned())) {
|
||||
disabled = true;
|
||||
} else if (this.hasReputation()) {
|
||||
status = (
|
||||
<>
|
||||
UNLOCKED (at {Reputation(repCost)} faction reputation) - <Money money={moneyCost} player={this.props.p} />
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
disabled = true;
|
||||
status = (
|
||||
<>
|
||||
LOCKED (Requires {Reputation(repCost)} faction reputation - <Money money={moneyCost} player={this.props.p} />)
|
||||
</>
|
||||
);
|
||||
color = "red";
|
||||
}
|
||||
|
||||
const txtStyle: IMap<string> = {
|
||||
display: "inline-block",
|
||||
};
|
||||
if (color !== "") {
|
||||
txtStyle.color = color;
|
||||
}
|
||||
|
||||
// Determine button txt
|
||||
let btnTxt = this.aug.name;
|
||||
if (this.aug.name === AugmentationNames.NeuroFluxGovernor) {
|
||||
btnTxt += ` - Level ${getNextNeurofluxLevel()}`;
|
||||
}
|
||||
|
||||
let tooltip = <></>;
|
||||
if (typeof this.aug.info === "string")
|
||||
tooltip = (
|
||||
<>
|
||||
<span dangerouslySetInnerHTML={{ __html: this.aug.info }} />
|
||||
<br />
|
||||
<br />
|
||||
{this.aug.stats}
|
||||
</>
|
||||
);
|
||||
else
|
||||
tooltip = (
|
||||
<>
|
||||
{this.aug.info}
|
||||
<br />
|
||||
<br />
|
||||
{this.aug.stats}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<li key={this.aug.name}>
|
||||
<span
|
||||
style={{
|
||||
margin: "4px",
|
||||
padding: "4px",
|
||||
}}
|
||||
>
|
||||
<StdButton
|
||||
disabled={disabled}
|
||||
onClick={this.handleClick}
|
||||
style={{
|
||||
display: "inline-block",
|
||||
}}
|
||||
text={btnTxt}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
<p style={txtStyle}>{status}</p>
|
||||
</span>
|
||||
</li>
|
||||
if (aug == null) {
|
||||
console.error(
|
||||
`Invalid Augmentation when trying to create PurchaseableAugmentation display element: ${props.augName}`,
|
||||
);
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const moneyCost = getMoneyCost();
|
||||
const repCost = getRepCost();
|
||||
|
||||
// Determine UI properties
|
||||
let disabled = false;
|
||||
let status: JSX.Element = <></>;
|
||||
let color = "";
|
||||
if (!hasPrereqs()) {
|
||||
disabled = true;
|
||||
status = <>LOCKED (Requires {aug.prereqs.map((aug) => AugFormat(aug))} as prerequisite)</>;
|
||||
color = "red";
|
||||
} else if (aug.name !== AugmentationNames.NeuroFluxGovernor && (aug.owned || owned())) {
|
||||
disabled = true;
|
||||
} else if (hasReputation()) {
|
||||
status = (
|
||||
<>
|
||||
UNLOCKED (at {Reputation(repCost)} faction reputation) - <Money money={moneyCost} player={props.p} />
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
disabled = true;
|
||||
status = (
|
||||
<>
|
||||
LOCKED (Requires {Reputation(repCost)} faction reputation - <Money money={moneyCost} player={props.p} />)
|
||||
</>
|
||||
);
|
||||
color = "red";
|
||||
}
|
||||
|
||||
const txtStyle: IMap<string> = {
|
||||
display: "inline-block",
|
||||
};
|
||||
if (color !== "") {
|
||||
txtStyle.color = color;
|
||||
}
|
||||
|
||||
// Determine button txt
|
||||
let btnTxt = aug.name;
|
||||
if (aug.name === AugmentationNames.NeuroFluxGovernor) {
|
||||
btnTxt += ` - Level ${getNextNeurofluxLevel()}`;
|
||||
}
|
||||
|
||||
let tooltip = <></>;
|
||||
if (typeof aug.info === "string")
|
||||
tooltip = (
|
||||
<>
|
||||
<span dangerouslySetInnerHTML={{ __html: aug.info }} />
|
||||
<br />
|
||||
<br />
|
||||
{aug.stats}
|
||||
</>
|
||||
);
|
||||
else
|
||||
tooltip = (
|
||||
<>
|
||||
{aug.info}
|
||||
<br />
|
||||
<br />
|
||||
{aug.stats}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<li key={aug.name}>
|
||||
<span
|
||||
style={{
|
||||
margin: "4px",
|
||||
padding: "4px",
|
||||
}}
|
||||
>
|
||||
<StdButton
|
||||
disabled={disabled}
|
||||
onClick={handleClick}
|
||||
style={{
|
||||
display: "inline-block",
|
||||
}}
|
||||
text={btnTxt}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
<p style={txtStyle}>{status}</p>
|
||||
</span>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { GangMemberUpgrade } from "./GangMemberUpgrade";
|
||||
import { GangMember } from "./GangMember";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IAscensionResult } from "./IAscensionResult";
|
||||
|
||||
export interface IGang {
|
||||
facName: string;
|
||||
@ -37,8 +38,9 @@ export interface IGang {
|
||||
getWantedPenalty(): number;
|
||||
calculatePower(): number;
|
||||
killMember(member: GangMember): void;
|
||||
ascendMember(member: GangMember, workerScript: WorkerScript): void;
|
||||
ascendMember(member: GangMember, workerScript: WorkerScript): IAscensionResult;
|
||||
getDiscount(): number;
|
||||
getAllTaskNames(): string[];
|
||||
getUpgradeCost(upg: GangMemberUpgrade): number;
|
||||
toJSON(): any;
|
||||
}
|
||||
|
@ -2,20 +2,19 @@
|
||||
* React Component for all the gang stuff.
|
||||
*/
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { ManagementSubpage } from "./ManagementSubpage";
|
||||
import { TerritorySubpage } from "./TerritorySubpage";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { use } from "../../ui/Context";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { Gang } from "../Gang";
|
||||
import { displayFactionContent } from "../../Faction/FactionHelpers";
|
||||
|
||||
interface IProps {
|
||||
gang: Gang;
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
|
||||
export function Root(props: IProps): React.ReactElement {
|
||||
export function GangRoot(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const [management, setManagement] = useState(true);
|
||||
const setRerender = useState(false)[1];
|
||||
|
||||
@ -25,8 +24,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
}, []);
|
||||
|
||||
function back(): void {
|
||||
props.engine.loadFactionContent();
|
||||
displayFactionContent(props.gang.facName);
|
||||
router.toFaction(Factions[props.gang.facName]);
|
||||
}
|
||||
|
||||
return (
|
||||
@ -48,11 +46,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
>
|
||||
Gang Territory
|
||||
</a>
|
||||
{management ? (
|
||||
<ManagementSubpage gang={props.gang} player={props.player} />
|
||||
) : (
|
||||
<TerritorySubpage gang={props.gang} />
|
||||
)}
|
||||
{management ? <ManagementSubpage gang={props.gang} player={player} /> : <TerritorySubpage gang={props.gang} />}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
import { Page, routing } from ".././ui/navigationTracking";
|
||||
import { Root } from "./ui/Root";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../IEngine";
|
||||
import * as React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
|
||||
let container: HTMLElement;
|
||||
|
||||
(function () {
|
||||
function setContainer(): void {
|
||||
const c = document.getElementById("infiltration-container");
|
||||
if (c === null) throw new Error("huh?");
|
||||
container = c;
|
||||
document.removeEventListener("DOMContentLoaded", setContainer);
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", setContainer);
|
||||
})();
|
||||
|
||||
function calcDifficulty(player: IPlayer, startingDifficulty: number): number {
|
||||
const totalStats = player.strength + player.defense + player.dexterity + player.agility + player.charisma;
|
||||
const difficulty = startingDifficulty - Math.pow(totalStats, 0.9) / 250 - player.intelligence / 1600;
|
||||
if (difficulty < 0) return 0;
|
||||
if (difficulty > 3) return 3;
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
export function displayInfiltrationContent(
|
||||
engine: IEngine,
|
||||
player: IPlayer,
|
||||
location: string,
|
||||
startingDifficulty: number,
|
||||
maxLevel: number,
|
||||
): void {
|
||||
if (!routing.isOn(Page.Infiltration)) return;
|
||||
|
||||
const difficulty = calcDifficulty(player, startingDifficulty);
|
||||
|
||||
ReactDOM.render(
|
||||
<Root
|
||||
Engine={engine}
|
||||
Player={player}
|
||||
Location={location}
|
||||
StartingDifficulty={startingDifficulty}
|
||||
Difficulty={difficulty}
|
||||
MaxLevel={maxLevel}
|
||||
/>,
|
||||
container,
|
||||
);
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { use } from "../../ui/Context";
|
||||
import React, { useState } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Countdown } from "./Countdown";
|
||||
@ -14,8 +13,6 @@ import { WireCuttingGame } from "./WireCuttingGame";
|
||||
import { Victory } from "./Victory";
|
||||
|
||||
interface IProps {
|
||||
Player: IPlayer;
|
||||
Engine: IEngine;
|
||||
StartingDifficulty: number;
|
||||
Difficulty: number;
|
||||
MaxLevel: number;
|
||||
@ -40,6 +37,8 @@ const minigames = [
|
||||
];
|
||||
|
||||
export function Game(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const [level, setLevel] = useState(1);
|
||||
const [stage, setStage] = useState(Stage.Countdown);
|
||||
const [results, setResults] = useState("");
|
||||
@ -89,12 +88,10 @@ export function Game(props: IProps): React.ReactElement {
|
||||
pushResult(false);
|
||||
// Kill the player immediately if they use automation, so
|
||||
// it's clear they're not meant to
|
||||
const damage = options?.automated ? props.Player.hp : props.StartingDifficulty * 3;
|
||||
if (props.Player.takeDamage(damage)) {
|
||||
const menu = document.getElementById("mainmenu-container");
|
||||
if (menu === null) throw new Error("mainmenu-container not found");
|
||||
menu.style.visibility = "visible";
|
||||
props.Engine.loadLocationContent();
|
||||
const damage = options?.automated ? player.hp : props.StartingDifficulty * 3;
|
||||
if (player.takeDamage(damage)) {
|
||||
router.toCity();
|
||||
return;
|
||||
}
|
||||
setupNextGame();
|
||||
}
|
||||
@ -112,8 +109,6 @@ export function Game(props: IProps): React.ReactElement {
|
||||
case Stage.Sell:
|
||||
stageComponent = (
|
||||
<Victory
|
||||
Player={props.Player}
|
||||
Engine={props.Engine}
|
||||
StartingDifficulty={props.StartingDifficulty}
|
||||
Difficulty={props.Difficulty}
|
||||
MaxLevel={props.MaxLevel}
|
||||
|
53
src/Infiltration/ui/InfiltrationRoot.tsx
Normal file
53
src/Infiltration/ui/InfiltrationRoot.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import React, { useState } from "react";
|
||||
import { Intro } from "./Intro";
|
||||
import { Game } from "./Game";
|
||||
import { LocationName } from "../../Locations/data/LocationNames";
|
||||
import { Locations } from "../../Locations/Locations";
|
||||
import { use } from "../../ui/Context";
|
||||
|
||||
interface IProps {
|
||||
location: LocationName;
|
||||
}
|
||||
function calcDifficulty(player: IPlayer, startingDifficulty: number): number {
|
||||
const totalStats = player.strength + player.defense + player.dexterity + player.agility + player.charisma;
|
||||
const difficulty = startingDifficulty - Math.pow(totalStats, 0.9) / 250 - player.intelligence / 1600;
|
||||
if (difficulty < 0) return 0;
|
||||
if (difficulty > 3) return 3;
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
export function InfiltrationRoot(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const [start, setStart] = useState(false);
|
||||
|
||||
const loc = Locations[props.location];
|
||||
if (loc.infiltrationData === undefined) throw new Error("Trying to do infiltration on invalid location.");
|
||||
const startingDifficulty = loc.infiltrationData.startingSecurityLevel;
|
||||
const difficulty = calcDifficulty(player, startingDifficulty);
|
||||
|
||||
function cancel(): void {
|
||||
router.toCity();
|
||||
}
|
||||
|
||||
if (!start) {
|
||||
return (
|
||||
<Intro
|
||||
Location={props.location}
|
||||
Difficulty={difficulty}
|
||||
MaxLevel={loc.infiltrationData.maxClearanceLevel}
|
||||
start={() => setStart(true)}
|
||||
cancel={cancel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Game
|
||||
StartingDifficulty={startingDifficulty}
|
||||
Difficulty={difficulty}
|
||||
MaxLevel={loc.infiltrationData.maxClearanceLevel}
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,12 +1,8 @@
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import React from "react";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import Grid from "@mui/material/Grid";
|
||||
|
||||
interface IProps {
|
||||
Player: IPlayer;
|
||||
Engine: IEngine;
|
||||
Location: string;
|
||||
Difficulty: number;
|
||||
MaxLevel: number;
|
||||
|
@ -1,49 +0,0 @@
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import React, { useState } from "react";
|
||||
import { Intro } from "./Intro";
|
||||
import { Game } from "./Game";
|
||||
|
||||
interface IProps {
|
||||
Player: IPlayer;
|
||||
Engine: IEngine;
|
||||
Location: string;
|
||||
StartingDifficulty: number;
|
||||
Difficulty: number;
|
||||
MaxLevel: number;
|
||||
}
|
||||
|
||||
export function Root(props: IProps): React.ReactElement {
|
||||
const [start, setStart] = useState(false);
|
||||
|
||||
function cancel(): void {
|
||||
const menu = document.getElementById("mainmenu-container");
|
||||
if (menu === null) throw new Error("mainmenu-container not found");
|
||||
menu.style.visibility = "visible";
|
||||
props.Engine.loadLocationContent();
|
||||
}
|
||||
|
||||
if (!start) {
|
||||
return (
|
||||
<Intro
|
||||
Player={props.Player}
|
||||
Engine={props.Engine}
|
||||
Location={props.Location}
|
||||
Difficulty={props.Difficulty}
|
||||
MaxLevel={props.MaxLevel}
|
||||
start={() => setStart(true)}
|
||||
cancel={cancel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Game
|
||||
Player={props.Player}
|
||||
Engine={props.Engine}
|
||||
StartingDifficulty={props.StartingDifficulty}
|
||||
Difficulty={props.Difficulty}
|
||||
MaxLevel={props.MaxLevel}
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import React, { useState } from "react";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
@ -7,23 +5,21 @@ import Grid from "@mui/material/Grid";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { use } from "../../ui/Context";
|
||||
|
||||
interface IProps {
|
||||
Player: IPlayer;
|
||||
Engine: IEngine;
|
||||
StartingDifficulty: number;
|
||||
Difficulty: number;
|
||||
MaxLevel: number;
|
||||
}
|
||||
|
||||
export function Victory(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const [faction, setFaction] = useState("none");
|
||||
|
||||
function quitInfiltration(): void {
|
||||
const menu = document.getElementById("mainmenu-container");
|
||||
if (!menu) throw new Error("mainmenu-container somehow null");
|
||||
menu.style.visibility = "visible";
|
||||
props.Engine.loadLocationContent();
|
||||
router.toCity();
|
||||
}
|
||||
|
||||
const levelBonus = props.MaxLevel * Math.pow(1.01, props.MaxLevel);
|
||||
@ -43,8 +39,8 @@ export function Victory(props: IProps): React.ReactElement {
|
||||
BitNodeMultipliers.InfiltrationMoney;
|
||||
|
||||
function sell(): void {
|
||||
props.Player.gainMoney(moneyGain);
|
||||
props.Player.recordMoneySource(moneyGain, "infiltration");
|
||||
player.gainMoney(moneyGain);
|
||||
player.recordMoneySource(moneyGain, "infiltration");
|
||||
quitInfiltration();
|
||||
}
|
||||
|
||||
@ -70,7 +66,7 @@ export function Victory(props: IProps): React.ReactElement {
|
||||
<option key={"none"} value={"none"}>
|
||||
{"none"}
|
||||
</option>
|
||||
{props.Player.factions
|
||||
{player.factions
|
||||
.filter((f) => Factions[f].getInfo().offersWork())
|
||||
.map((f) => (
|
||||
<option key={f} value={f}>
|
||||
|
@ -63,8 +63,6 @@ function iTutorialStart() {
|
||||
ITutorial.stepIsDone[i] = false;
|
||||
}
|
||||
|
||||
Engine.loadTerminalContent();
|
||||
|
||||
// Don't autosave during this interactive tutorial
|
||||
Engine.Counters.autoSaveCounter = Infinity;
|
||||
ITutorial.currStep = 0;
|
||||
@ -120,7 +118,6 @@ function iTutorialEvaluateStep() {
|
||||
|
||||
switch (ITutorial.currStep) {
|
||||
case iTutorialSteps.Start:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"Welcome to Bitburner, a cyberpunk-themed incremental RPG! " +
|
||||
"The game takes place in a dark, dystopian future... The year is 2077...<br><br>" +
|
||||
@ -130,7 +127,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.GoToCharacterPage:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"Let's start by heading to the Stats page. Click the <code class='interactive-tutorial-tab flashing-button'>Stats</code> tab on " +
|
||||
"the main navigation menu (left-hand side of the screen)",
|
||||
@ -138,7 +134,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none";
|
||||
break;
|
||||
case iTutorialSteps.CharacterPage:
|
||||
Engine.loadCharacterContent();
|
||||
iTutorialSetText(
|
||||
"The <code class='interactive-tutorial-tab'>Stats</code> page shows a lot of important information about your progress, " +
|
||||
"such as your skills, money, and bonuses. ",
|
||||
@ -146,7 +141,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.CharacterGoToTerminalPage:
|
||||
Engine.loadCharacterContent();
|
||||
iTutorialSetText(
|
||||
"Let's head to your computer's terminal by clicking the <code class='interactive-tutorial-tab flashing-button'>Terminal</code> tab on the " +
|
||||
"main navigation menu.",
|
||||
@ -154,7 +148,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none";
|
||||
break;
|
||||
case iTutorialSteps.TerminalIntro:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"The <code class='interactive-tutorial-tab'>Terminal</code> is used to interface with your home computer as well as " +
|
||||
"all of the other machines around the world.",
|
||||
@ -162,7 +155,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.TerminalHelp:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"Let's try it out. Start by entering the <code class='interactive-tutorial-command'>help</code> command into the <code class='interactive-tutorial-tab'>Terminal</code> " +
|
||||
"(Don't forget to press Enter after typing the command)",
|
||||
@ -170,7 +162,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalLs:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"The <code class='interactive-tutorial-command'>help</code> command displays a list of all available <code class='interactive-tutorial-tab'>Terminal</code> commands, how to use them, " +
|
||||
"and a description of what they do. <br><br>Let's try another command. Enter the <code class='interactive-tutorial-command'>ls</code> command.",
|
||||
@ -178,7 +169,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalScan:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
" <code class='interactive-tutorial-command'>ls</code> is a basic command that shows files " +
|
||||
"on the computer. Right now, it shows that you have a program called <code class='interactive-tutorial-command'>NUKE.exe</code> on your computer. " +
|
||||
@ -189,7 +179,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalScanAnalyze1:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"The <code class='interactive-tutorial-command'>scan</code> command shows all available network connections. In other words, " +
|
||||
"it displays a list of all servers that can be connected to from your " +
|
||||
@ -201,7 +190,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalScanAnalyze2:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"You just ran <code class='interactive-tutorial-command'>scan-analyze</code> with a depth of one. This command shows more detailed " +
|
||||
"information about each server that you can connect to (servers that are a distance of " +
|
||||
@ -211,7 +199,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalConnect:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"Now you can see information about all servers that are up to two nodes away, as well " +
|
||||
"as figure out how to navigate to those servers through the network. You can only connect to " +
|
||||
@ -222,7 +209,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalAnalyze:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"You are now connected to another machine! What can you do now? You can hack it!<br><br> In the year 2077, currency has " +
|
||||
"become digital and decentralized. People and corporations store their money " +
|
||||
@ -233,7 +219,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalNuke:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"When the <code class='interactive-tutorial-command'>analyze</code> command finishes running it will show useful information " +
|
||||
"about hacking the server. <br><br> For this server, the required hacking skill is only <span class='character-hack-cell'>1</span>, " +
|
||||
@ -247,7 +232,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalManualHack:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"You now have root access! You can hack the server using the <code class='interactive-tutorial-command'>hack</code> command. " +
|
||||
"Try doing that now.",
|
||||
@ -255,7 +239,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalHackingMechanics:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"You are now attempting to hack the server. Performing a hack takes time and " +
|
||||
"only has a certain percentage chance " +
|
||||
@ -270,7 +253,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.TerminalCreateScript:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"Hacking is the core mechanic of the game and is necessary for progressing. However, " +
|
||||
"you don't want to be hacking manually the entire time. You can automate your hacking " +
|
||||
@ -282,7 +264,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalTypeScript:
|
||||
Engine.loadScriptEditorContent("n00dles.script", "");
|
||||
iTutorialSetText(
|
||||
"This is the script editor. You can use it to program your scripts. Scripts are " +
|
||||
"written in a simplified version of javascript. Copy and paste the following code into the script editor: <br><br>" +
|
||||
@ -297,7 +278,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered in saveAndCloseScriptEditor() (Script.js)
|
||||
break;
|
||||
case iTutorialSteps.TerminalFree:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"Now we'll run the script. Scripts require a certain amount of RAM to run, and can be " +
|
||||
"run on any machine which you have root access to. Different servers have different " +
|
||||
@ -307,7 +287,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal commmand
|
||||
break;
|
||||
case iTutorialSteps.TerminalRunScript:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"We have 4GB of free RAM on this machine, which is enough to run our " +
|
||||
"script. Let's run our script using <code class='interactive-tutorial-command'>run n00dles.script</code>.",
|
||||
@ -315,7 +294,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal commmand
|
||||
break;
|
||||
case iTutorialSteps.TerminalGoToActiveScriptsPage:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"Your script is now running! " +
|
||||
"It will continuously run in the background and will automatically stop if " +
|
||||
@ -329,7 +307,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none";
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsPage:
|
||||
Engine.loadActiveScriptsContent();
|
||||
iTutorialSetText(
|
||||
"This page displays information about all of your scripts that are " +
|
||||
"running across every server. You can use this to gauge how well " +
|
||||
@ -338,7 +315,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none";
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsToTerminal:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"One last thing about scripts, each active script contains logs that detail " +
|
||||
"what it's doing. We can check these logs using the <code class='interactive-tutorial-command'>tail</code> command. Do that " +
|
||||
@ -347,7 +323,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none"; // next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalTailScript:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"The log for this script won't show much right now (it might show nothing at all) because it " +
|
||||
"just started running...but check back again in a few minutes! <br><br>" +
|
||||
@ -361,7 +336,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.GoToHacknetNodesPage:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText(
|
||||
"Hacking is not the only way to earn money. One other way to passively " +
|
||||
"earn money is by purchasing and upgrading Hacknet Nodes. Let's go to " +
|
||||
@ -370,14 +344,12 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none";
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesIntroduction:
|
||||
Engine.loadHacknetNodesContent();
|
||||
iTutorialSetText(
|
||||
"here you can purchase new Hacknet Nodes and upgrade your " + "existing ones. Let's purchase a new one now.",
|
||||
);
|
||||
nextBtn.style.display = "none"; // Next step triggered by purchaseHacknet() (HacknetNode.js)
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesGoToWorldPage:
|
||||
Engine.loadHacknetNodesContent();
|
||||
iTutorialSetText(
|
||||
"You just purchased a Hacknet Node! This Hacknet Node will passively " +
|
||||
"earn you money over time, both online and offline. When you get enough " +
|
||||
@ -388,7 +360,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none";
|
||||
break;
|
||||
case iTutorialSteps.WorldDescription:
|
||||
Engine.loadLocationContent();
|
||||
iTutorialSetText(
|
||||
"This page lists all of the different locations you can currently " +
|
||||
"travel to. Each location has something that you can do. " +
|
||||
@ -399,7 +370,6 @@ function iTutorialEvaluateStep() {
|
||||
nextBtn.style.display = "none";
|
||||
break;
|
||||
case iTutorialSteps.TutorialPageInfo:
|
||||
Engine.loadTutorialContent();
|
||||
iTutorialSetText(
|
||||
"This page contains a lot of different documentation about the game's " +
|
||||
"content and mechanics. <strong style='background-color:#444;'> I know it's a lot, but I highly suggest you read " +
|
||||
|
@ -3,418 +3,347 @@
|
||||
*
|
||||
* This subcomponent renders all of the buttons for applying to jobs at a company
|
||||
*/
|
||||
import * as React from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { ApplyToJobButton } from "./ApplyToJobButton";
|
||||
|
||||
import { Location } from "../Location";
|
||||
import { Locations } from "../Locations";
|
||||
import { LocationName } from "../data/LocationNames";
|
||||
|
||||
import { IEngine } from "../../IEngine";
|
||||
|
||||
import { Companies } from "../../Company/Companies";
|
||||
import { Company } from "../../Company/Company";
|
||||
import { CompanyPosition } from "../../Company/CompanyPosition";
|
||||
import { CompanyPositions } from "../../Company/CompanyPositions";
|
||||
import * as posNames from "../../Company/data/companypositionnames";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { use } from "../../ui/Context";
|
||||
import { QuitJobPopup } from "../../Company/ui/QuitJobPopup";
|
||||
|
||||
type IProps = {
|
||||
engine: IEngine;
|
||||
locName: LocationName;
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
type IState = {
|
||||
employedHere: boolean;
|
||||
};
|
||||
|
||||
const blockStyleMarkup = {
|
||||
display: "block",
|
||||
};
|
||||
|
||||
export class CompanyLocation extends React.Component<IProps, IState> {
|
||||
export function CompanyLocation(props: IProps): React.ReactElement {
|
||||
const p = use.Player();
|
||||
const router = use.Router();
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
/**
|
||||
* We'll keep a reference to the Company that this component is being rendered for,
|
||||
* so we don't have to look it up every time
|
||||
*/
|
||||
company: Company;
|
||||
const company = Companies[props.locName];
|
||||
if (company == null) throw new Error(`CompanyLocation component constructed with invalid company: ${props.locName}`);
|
||||
|
||||
/**
|
||||
* Reference to the Location that this component is being rendered for
|
||||
*/
|
||||
const location = Locations[props.locName];
|
||||
if (location == null) {
|
||||
throw new Error(`CompanyLocation component constructed with invalid location: ${props.locName}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of company position that player holds, if applicable
|
||||
*/
|
||||
const jobTitle = p.jobs[props.locName] ? p.jobs[props.locName] : null;
|
||||
|
||||
/**
|
||||
* CompanyPosition object for the job that the player holds at this company
|
||||
* (if he has one)
|
||||
*/
|
||||
companyPosition: CompanyPosition | null = null;
|
||||
const companyPosition = jobTitle ? CompanyPositions[jobTitle] : null;
|
||||
|
||||
/**
|
||||
* Stores button styling that sets them all to block display
|
||||
*/
|
||||
btnStyle: any;
|
||||
p.location = props.locName;
|
||||
|
||||
/**
|
||||
* Reference to the Location that this component is being rendered for
|
||||
*/
|
||||
location: Location;
|
||||
|
||||
/**
|
||||
* Name of company position that player holds, if applicable
|
||||
*/
|
||||
jobTitle: string | null = null;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.btnStyle = { display: "block" };
|
||||
|
||||
this.quit = this.quit.bind(this);
|
||||
this.applyForAgentJob = this.applyForAgentJob.bind(this);
|
||||
this.applyForBusinessConsultantJob = this.applyForBusinessConsultantJob.bind(this);
|
||||
this.applyForBusinessJob = this.applyForBusinessJob.bind(this);
|
||||
this.applyForEmployeeJob = this.applyForEmployeeJob.bind(this);
|
||||
this.applyForItJob = this.applyForItJob.bind(this);
|
||||
this.applyForPartTimeEmployeeJob = this.applyForPartTimeEmployeeJob.bind(this);
|
||||
this.applyForPartTimeWaiterJob = this.applyForPartTimeWaiterJob.bind(this);
|
||||
this.applyForSecurityJob = this.applyForSecurityJob.bind(this);
|
||||
this.applyForSoftwareConsultantJob = this.applyForSoftwareConsultantJob.bind(this);
|
||||
this.applyForSoftwareJob = this.applyForSoftwareJob.bind(this);
|
||||
this.applyForWaiterJob = this.applyForWaiterJob.bind(this);
|
||||
this.startInfiltration = this.startInfiltration.bind(this);
|
||||
this.work = this.work.bind(this);
|
||||
|
||||
this.location = Locations[props.locName];
|
||||
if (this.location == null) {
|
||||
throw new Error(`CompanyLocation component constructed with invalid location: ${props.locName}`);
|
||||
}
|
||||
|
||||
this.company = Companies[props.locName];
|
||||
if (this.company == null) {
|
||||
throw new Error(`CompanyLocation component constructed with invalid company: ${props.locName}`);
|
||||
}
|
||||
|
||||
this.state = {
|
||||
employedHere: false,
|
||||
};
|
||||
|
||||
this.props.p.location = props.locName;
|
||||
|
||||
this.checkIfEmployedHere(false);
|
||||
}
|
||||
|
||||
applyForAgentJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForAgentJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForAgentJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForAgentJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForBusinessConsultantJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForBusinessConsultantJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForBusinessConsultantJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForBusinessConsultantJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForBusinessJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForBusinessJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForBusinessJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForBusinessJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForEmployeeJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForEmployeeJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForEmployeeJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForEmployeeJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForItJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForItJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForItJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForItJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForPartTimeEmployeeJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForPartTimeEmployeeJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForPartTimeEmployeeJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForPartTimeEmployeeJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForPartTimeWaiterJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForPartTimeWaiterJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForPartTimeWaiterJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForPartTimeWaiterJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForSecurityJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForSecurityJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForSecurityJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForSecurityJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForSoftwareConsultantJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForSoftwareConsultantJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForSoftwareConsultantJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForSoftwareConsultantJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForSoftwareJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForSoftwareJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForSoftwareJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForSoftwareJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
applyForWaiterJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
function applyForWaiterJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
this.props.p.applyForWaiterJob();
|
||||
this.checkIfEmployedHere(true);
|
||||
p.applyForWaiterJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
checkIfEmployedHere(updateState = false): void {
|
||||
this.jobTitle = this.props.p.jobs[this.props.locName];
|
||||
if (this.jobTitle != null) {
|
||||
this.companyPosition = CompanyPositions[this.jobTitle];
|
||||
}
|
||||
|
||||
if (updateState) {
|
||||
this.setState({
|
||||
employedHere: this.jobTitle != null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
startInfiltration(e: React.MouseEvent<HTMLElement>): void {
|
||||
function startInfiltration(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
const loc = this.location;
|
||||
if (!loc.infiltrationData) {
|
||||
console.error(`trying to start infiltration at ${this.props.locName} but the infiltrationData is null`);
|
||||
return;
|
||||
}
|
||||
const loc = location;
|
||||
if (!loc.infiltrationData)
|
||||
throw new Error(`trying to start infiltration at ${props.locName} but the infiltrationData is null`);
|
||||
|
||||
this.props.engine.loadInfiltrationContent(
|
||||
this.props.locName,
|
||||
loc.infiltrationData.startingSecurityLevel,
|
||||
loc.infiltrationData.maxClearanceLevel,
|
||||
);
|
||||
|
||||
const data = loc.infiltrationData;
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
router.toInfiltration(props.locName);
|
||||
}
|
||||
|
||||
work(e: React.MouseEvent<HTMLElement>): void {
|
||||
function work(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pos = this.companyPosition;
|
||||
const pos = companyPosition;
|
||||
if (pos instanceof CompanyPosition) {
|
||||
if (pos.isPartTimeJob() || pos.isSoftwareConsultantJob() || pos.isBusinessConsultantJob()) {
|
||||
this.props.p.startWorkPartTime(this.props.locName);
|
||||
p.startWorkPartTime(props.locName);
|
||||
} else {
|
||||
this.props.p.startWork(this.props.locName);
|
||||
p.startWork(props.locName);
|
||||
}
|
||||
router.toWork();
|
||||
}
|
||||
}
|
||||
|
||||
quit(e: React.MouseEvent<HTMLElement>): void {
|
||||
function quit(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) return;
|
||||
const popupId = `quit-job-popup`;
|
||||
createPopup(popupId, QuitJobPopup, {
|
||||
locName: this.props.locName,
|
||||
company: this.company,
|
||||
player: this.props.p,
|
||||
onQuit: () => this.checkIfEmployedHere(true),
|
||||
locName: props.locName,
|
||||
company: company,
|
||||
player: p,
|
||||
onQuit: rerender,
|
||||
popupId: popupId,
|
||||
});
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
const isEmployedHere = this.jobTitle != null;
|
||||
const favorGain = this.company.getFavorGain();
|
||||
const isEmployedHere = jobTitle != null;
|
||||
const favorGain = company.getFavorGain();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isEmployedHere && (
|
||||
<div>
|
||||
<p>Job Title: {this.jobTitle}</p>
|
||||
<br />
|
||||
<p style={blockStyleMarkup}>-------------------------</p>
|
||||
<br />
|
||||
<p className={"tooltip"}>
|
||||
Company reputation: {Reputation(this.company.playerReputation)}
|
||||
<span className={"tooltiptext"}>
|
||||
You will earn {Favor(favorGain[0])} company favor upon resetting after installing Augmentations
|
||||
</span>
|
||||
</p>
|
||||
<br />
|
||||
<br />
|
||||
<p style={blockStyleMarkup}>-------------------------</p>
|
||||
<br />
|
||||
<p className={"tooltip"}>
|
||||
Company Favor: {Favor(this.company.favor)}
|
||||
<span className={"tooltiptext"}>
|
||||
Company favor increases the rate at which you earn reputation for this company by 1% per favor. Company
|
||||
favor is gained whenever you reset after installing Augmentations. The amount of favor you gain depends
|
||||
on how much reputation you have with the comapny.
|
||||
</span>
|
||||
</p>
|
||||
<br />
|
||||
<br />
|
||||
<p style={blockStyleMarkup}>-------------------------</p>
|
||||
<br />
|
||||
<StdButton onClick={this.work} text={"Work"} />
|
||||
|
||||
<StdButton onClick={this.quit} text={"Quit"} />
|
||||
</div>
|
||||
)}
|
||||
{this.company.hasAgentPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.AgentCompanyPositions[0]]}
|
||||
onClick={this.applyForAgentJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply for Agent Job"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasBusinessConsultantPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]]}
|
||||
onClick={this.applyForBusinessConsultantJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply for Business Consultant Job"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasBusinessPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.BusinessCompanyPositions[0]]}
|
||||
onClick={this.applyForBusinessJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply for Business Job"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasEmployeePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[1]]}
|
||||
onClick={this.applyForEmployeeJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply to be an Employee"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasEmployeePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[1]]}
|
||||
onClick={this.applyForPartTimeEmployeeJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply to be a part-time Employee"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasITPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.ITCompanyPositions[0]]}
|
||||
onClick={this.applyForItJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply for IT Job"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasSecurityPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.SecurityCompanyPositions[2]]}
|
||||
onClick={this.applyForSecurityJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply for Security Job"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasSoftwareConsultantPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]]}
|
||||
onClick={this.applyForSoftwareConsultantJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply for Software Consultant Job"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasSoftwarePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.SoftwareCompanyPositions[0]]}
|
||||
onClick={this.applyForSoftwareJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply for Software Job"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasWaiterPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[0]]}
|
||||
onClick={this.applyForWaiterJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply to be a Waiter"}
|
||||
/>
|
||||
)}
|
||||
{this.company.hasWaiterPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={this.company}
|
||||
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[0]]}
|
||||
onClick={this.applyForPartTimeWaiterJob}
|
||||
p={this.props.p}
|
||||
style={this.btnStyle}
|
||||
text={"Apply to be a part-time Waiter"}
|
||||
/>
|
||||
)}
|
||||
{this.location.infiltrationData != null && (
|
||||
<StdButton onClick={this.startInfiltration} style={this.btnStyle} text={"Infiltrate Company"} />
|
||||
)}
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{isEmployedHere && (
|
||||
<div>
|
||||
<p>Job Title: {jobTitle}</p>
|
||||
<br />
|
||||
<p style={{ display: "block" }}>-------------------------</p>
|
||||
<br />
|
||||
<p className={"tooltip"}>
|
||||
Company reputation: {Reputation(company.playerReputation)}
|
||||
<span className={"tooltiptext"}>
|
||||
You will earn {Favor(favorGain[0])} company favor upon resetting after installing Augmentations
|
||||
</span>
|
||||
</p>
|
||||
<br />
|
||||
<br />
|
||||
<p style={{ display: "block" }}>-------------------------</p>
|
||||
<br />
|
||||
<p className={"tooltip"}>
|
||||
Company Favor: {Favor(company.favor)}
|
||||
<span className={"tooltiptext"}>
|
||||
Company favor increases the rate at which you earn reputation for this company by 1% per favor. Company
|
||||
favor is gained whenever you reset after installing Augmentations. The amount of favor you gain depends on
|
||||
how much reputation you have with the comapny.
|
||||
</span>
|
||||
</p>
|
||||
<br />
|
||||
<br />
|
||||
<p style={{ display: "block" }}>-------------------------</p>
|
||||
<br />
|
||||
<StdButton onClick={work} text={"Work"} />
|
||||
|
||||
<StdButton onClick={quit} text={"Quit"} />
|
||||
</div>
|
||||
)}
|
||||
{company.hasAgentPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.AgentCompanyPositions[0]]}
|
||||
onClick={applyForAgentJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply for Agent Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasBusinessConsultantPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]]}
|
||||
onClick={applyForBusinessConsultantJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply for Business Consultant Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasBusinessPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.BusinessCompanyPositions[0]]}
|
||||
onClick={applyForBusinessJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply for Business Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasEmployeePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[1]]}
|
||||
onClick={applyForEmployeeJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply to be an Employee"}
|
||||
/>
|
||||
)}
|
||||
{company.hasEmployeePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[1]]}
|
||||
onClick={applyForPartTimeEmployeeJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply to be a part-time Employee"}
|
||||
/>
|
||||
)}
|
||||
{company.hasITPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.ITCompanyPositions[0]]}
|
||||
onClick={applyForItJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply for IT Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasSecurityPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.SecurityCompanyPositions[2]]}
|
||||
onClick={applyForSecurityJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply for Security Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasSoftwareConsultantPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]]}
|
||||
onClick={applyForSoftwareConsultantJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply for Software Consultant Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasSoftwarePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.SoftwareCompanyPositions[0]]}
|
||||
onClick={applyForSoftwareJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply for Software Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasWaiterPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[0]]}
|
||||
onClick={applyForWaiterJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply to be a Waiter"}
|
||||
/>
|
||||
)}
|
||||
{company.hasWaiterPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[0]]}
|
||||
onClick={applyForPartTimeWaiterJob}
|
||||
p={p}
|
||||
style={{ display: "block" }}
|
||||
text={"Apply to be a part-time Waiter"}
|
||||
/>
|
||||
)}
|
||||
{location.infiltrationData != null && (
|
||||
<StdButton onClick={startInfiltration} style={{ display: "block" }} text={"Infiltrate Company"} />
|
||||
)}
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import { HospitalLocation } from "./HospitalLocation";
|
||||
import { SlumsLocation } from "./SlumsLocation";
|
||||
import { SpecialLocation } from "./SpecialLocation";
|
||||
import { TechVendorLocation } from "./TechVendorLocation";
|
||||
import { TravelAgencyLocation } from "./TravelAgencyLocation";
|
||||
import { TravelAgencyRoot } from "./TravelAgencyRoot";
|
||||
import { UniversityLocation } from "./UniversityLocation";
|
||||
import { CasinoLocation } from "./CasinoLocation";
|
||||
|
||||
@ -21,6 +21,7 @@ import { LocationType } from "../LocationTypeEnum";
|
||||
import { CityName } from "../data/CityNames";
|
||||
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
|
||||
@ -32,6 +33,7 @@ import { CorruptableText } from "../../ui/React/CorruptableText";
|
||||
|
||||
type IProps = {
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
loc: Location;
|
||||
p: IPlayer;
|
||||
returnToCity: () => void;
|
||||
@ -58,14 +60,7 @@ export class GenericLocation extends React.Component<IProps, any> {
|
||||
const content: React.ReactNode[] = [];
|
||||
|
||||
if (this.props.loc.types.includes(LocationType.Company)) {
|
||||
content.push(
|
||||
<CompanyLocation
|
||||
engine={this.props.engine}
|
||||
key={"companylocation"}
|
||||
locName={this.props.loc.name}
|
||||
p={this.props.p}
|
||||
/>,
|
||||
);
|
||||
content.push(<CompanyLocation key={"companylocation"} locName={this.props.loc.name} />);
|
||||
}
|
||||
|
||||
if (this.props.loc.types.includes(LocationType.Gym)) {
|
||||
@ -77,7 +72,7 @@ export class GenericLocation extends React.Component<IProps, any> {
|
||||
}
|
||||
|
||||
if (this.props.loc.types.includes(LocationType.Slums)) {
|
||||
content.push(<SlumsLocation key={"slumslocation"} p={this.props.p} />);
|
||||
content.push(<SlumsLocation key={"slumslocation"} />);
|
||||
}
|
||||
|
||||
if (this.props.loc.types.includes(LocationType.Special)) {
|
||||
@ -91,11 +86,11 @@ export class GenericLocation extends React.Component<IProps, any> {
|
||||
}
|
||||
|
||||
if (this.props.loc.types.includes(LocationType.TravelAgency)) {
|
||||
content.push(<TravelAgencyLocation key={"travelagencylocation"} p={this.props.p} travel={this.props.travel} />);
|
||||
content.push(<TravelAgencyRoot key={"travelagencylocation"} p={this.props.p} router={this.props.router} />);
|
||||
}
|
||||
|
||||
if (this.props.loc.types.includes(LocationType.University)) {
|
||||
content.push(<UniversityLocation key={"universitylocation"} loc={this.props.loc} p={this.props.p} />);
|
||||
content.push(<UniversityLocation key={"universitylocation"} loc={this.props.loc} />);
|
||||
}
|
||||
|
||||
if (this.props.loc.types.includes(LocationType.Casino)) {
|
||||
|
@ -15,6 +15,7 @@ import { LocationName } from "../data/LocationNames";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
@ -22,6 +23,7 @@ import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
type IProps = {
|
||||
initiallyInCity?: boolean;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
@ -47,6 +49,10 @@ export class LocationRoot extends React.Component<IProps, IState> {
|
||||
}
|
||||
|
||||
enterLocation(to: LocationName): void {
|
||||
if (to == LocationName.TravelAgency) {
|
||||
this.props.router.toTravel();
|
||||
return;
|
||||
}
|
||||
this.props.p.gotoLocation(to);
|
||||
this.setState({
|
||||
inCity: false,
|
||||
@ -98,6 +104,7 @@ export class LocationRoot extends React.Component<IProps, IState> {
|
||||
return (
|
||||
<GenericLocation
|
||||
engine={this.props.engine}
|
||||
router={this.props.router}
|
||||
loc={loc}
|
||||
p={this.props.p}
|
||||
returnToCity={this.returnToCity}
|
||||
|
@ -6,225 +6,209 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { Crimes } from "../../Crime/Crimes";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
|
||||
import { use } from "../../ui/Context";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
export class SlumsLocation extends React.Component<IProps, any> {
|
||||
/**
|
||||
* Stores button styling that sets them all to block display
|
||||
*/
|
||||
btnStyle: any;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.btnStyle = { display: "block" };
|
||||
|
||||
this.shoplift = this.shoplift.bind(this);
|
||||
this.robStore = this.robStore.bind(this);
|
||||
this.mug = this.mug.bind(this);
|
||||
this.larceny = this.larceny.bind(this);
|
||||
this.dealDrugs = this.dealDrugs.bind(this);
|
||||
this.bondForgery = this.bondForgery.bind(this);
|
||||
this.traffickArms = this.traffickArms.bind(this);
|
||||
this.homicide = this.homicide.bind(this);
|
||||
this.grandTheftAuto = this.grandTheftAuto.bind(this);
|
||||
this.kidnap = this.kidnap.bind(this);
|
||||
this.assassinate = this.assassinate.bind(this);
|
||||
this.heist = this.heist.bind(this);
|
||||
}
|
||||
|
||||
shoplift(e: React.MouseEvent<HTMLElement>): void {
|
||||
export function SlumsLocation(): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
function shoplift(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Shoplift.commit(this.props.p);
|
||||
Crimes.Shoplift.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
robStore(e: React.MouseEvent<HTMLElement>): void {
|
||||
function robStore(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.RobStore.commit(this.props.p);
|
||||
Crimes.RobStore.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
mug(e: React.MouseEvent<HTMLElement>): void {
|
||||
function mug(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Mug.commit(this.props.p);
|
||||
Crimes.Mug.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
larceny(e: React.MouseEvent<HTMLElement>): void {
|
||||
function larceny(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Larceny.commit(this.props.p);
|
||||
Crimes.Larceny.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
dealDrugs(e: React.MouseEvent<HTMLElement>): void {
|
||||
function dealDrugs(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.DealDrugs.commit(this.props.p);
|
||||
Crimes.DealDrugs.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
bondForgery(e: React.MouseEvent<HTMLElement>): void {
|
||||
function bondForgery(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.BondForgery.commit(this.props.p);
|
||||
Crimes.BondForgery.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
traffickArms(e: React.MouseEvent<HTMLElement>): void {
|
||||
function traffickArms(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.TraffickArms.commit(this.props.p);
|
||||
Crimes.TraffickArms.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
homicide(e: React.MouseEvent<HTMLElement>): void {
|
||||
function homicide(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Homicide.commit(this.props.p);
|
||||
Crimes.Homicide.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
grandTheftAuto(e: React.MouseEvent<HTMLElement>): void {
|
||||
function grandTheftAuto(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.GrandTheftAuto.commit(this.props.p);
|
||||
Crimes.GrandTheftAuto.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
kidnap(e: React.MouseEvent<HTMLElement>): void {
|
||||
function kidnap(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Kidnap.commit(this.props.p);
|
||||
Crimes.Kidnap.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
assassinate(e: React.MouseEvent<HTMLElement>): void {
|
||||
function assassinate(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Assassination.commit(this.props.p);
|
||||
Crimes.Assassination.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
heist(e: React.MouseEvent<HTMLElement>): void {
|
||||
function heist(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Heist.commit(this.props.p);
|
||||
Crimes.Heist.commit(player);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
const shopliftChance = Crimes.Shoplift.successRate(this.props.p);
|
||||
const robStoreChance = Crimes.RobStore.successRate(this.props.p);
|
||||
const mugChance = Crimes.Mug.successRate(this.props.p);
|
||||
const larcenyChance = Crimes.Larceny.successRate(this.props.p);
|
||||
const drugsChance = Crimes.DealDrugs.successRate(this.props.p);
|
||||
const bondChance = Crimes.BondForgery.successRate(this.props.p);
|
||||
const armsChance = Crimes.TraffickArms.successRate(this.props.p);
|
||||
const homicideChance = Crimes.Homicide.successRate(this.props.p);
|
||||
const gtaChance = Crimes.GrandTheftAuto.successRate(this.props.p);
|
||||
const kidnapChance = Crimes.Kidnap.successRate(this.props.p);
|
||||
const assassinateChance = Crimes.Assassination.successRate(this.props.p);
|
||||
const heistChance = Crimes.Heist.successRate(this.props.p);
|
||||
const shopliftChance = Crimes.Shoplift.successRate(player);
|
||||
const robStoreChance = Crimes.RobStore.successRate(player);
|
||||
const mugChance = Crimes.Mug.successRate(player);
|
||||
const larcenyChance = Crimes.Larceny.successRate(player);
|
||||
const drugsChance = Crimes.DealDrugs.successRate(player);
|
||||
const bondChance = Crimes.BondForgery.successRate(player);
|
||||
const armsChance = Crimes.TraffickArms.successRate(player);
|
||||
const homicideChance = Crimes.Homicide.successRate(player);
|
||||
const gtaChance = Crimes.GrandTheftAuto.successRate(player);
|
||||
const kidnapChance = Crimes.Kidnap.successRate(player);
|
||||
const assassinateChance = Crimes.Assassination.successRate(player);
|
||||
const heistChance = Crimes.Heist.successRate(player);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.shoplift}
|
||||
style={this.btnStyle}
|
||||
text={`Shoplift (${numeralWrapper.formatPercentage(shopliftChance)} chance of success)`}
|
||||
tooltip={"Attempt to shoplift from a low-end retailer"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.robStore}
|
||||
style={this.btnStyle}
|
||||
text={`Rob store (${numeralWrapper.formatPercentage(robStoreChance)} chance of success)`}
|
||||
tooltip={"Attempt to commit armed robbery on a high-end store"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.mug}
|
||||
style={this.btnStyle}
|
||||
text={`Mug someone (${numeralWrapper.formatPercentage(mugChance)} chance of success)`}
|
||||
tooltip={"Attempt to mug a random person on the street"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.larceny}
|
||||
style={this.btnStyle}
|
||||
text={`Larceny (${numeralWrapper.formatPercentage(larcenyChance)} chance of success)`}
|
||||
tooltip={"Attempt to rob property from someone's house"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.dealDrugs}
|
||||
style={this.btnStyle}
|
||||
text={`Deal Drugs (${numeralWrapper.formatPercentage(drugsChance)} chance of success)`}
|
||||
tooltip={"Attempt to deal drugs"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.bondForgery}
|
||||
style={this.btnStyle}
|
||||
text={`Bond Forgery (${numeralWrapper.formatPercentage(bondChance)} chance of success)`}
|
||||
tooltip={"Attempt to forge corporate bonds"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.traffickArms}
|
||||
style={this.btnStyle}
|
||||
text={`Traffick illegal Arms (${numeralWrapper.formatPercentage(armsChance)} chance of success)`}
|
||||
tooltip={"Attempt to smuggle illegal arms into the city"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.homicide}
|
||||
style={this.btnStyle}
|
||||
text={`Homicide (${numeralWrapper.formatPercentage(homicideChance)} chance of success)`}
|
||||
tooltip={"Attempt to murder a random person on the street"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.grandTheftAuto}
|
||||
style={this.btnStyle}
|
||||
text={`Grand theft Auto (${numeralWrapper.formatPercentage(gtaChance)} chance of success)`}
|
||||
tooltip={"Attempt to commit grand theft auto"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.kidnap}
|
||||
style={this.btnStyle}
|
||||
text={`Kidnap and Ransom (${numeralWrapper.formatPercentage(kidnapChance)} chance of success)`}
|
||||
tooltip={"Attempt to kidnap and ransom a high-profile-target"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.assassinate}
|
||||
style={this.btnStyle}
|
||||
text={`Assassinate (${numeralWrapper.formatPercentage(assassinateChance)} chance of success)`}
|
||||
tooltip={"Attempt to assassinate a high-profile target"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={this.heist}
|
||||
style={this.btnStyle}
|
||||
text={`Heist (${numeralWrapper.formatPercentage(heistChance)} chance of success)`}
|
||||
tooltip={"Attempt to pull off the ultimate heist"}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={shoplift}
|
||||
style={{ display: "block" }}
|
||||
text={`Shoplift (${numeralWrapper.formatPercentage(shopliftChance)} chance of success)`}
|
||||
tooltip={"Attempt to shoplift from a low-end retailer"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={robStore}
|
||||
style={{ display: "block" }}
|
||||
text={`Rob store (${numeralWrapper.formatPercentage(robStoreChance)} chance of success)`}
|
||||
tooltip={"Attempt to commit armed robbery on a high-end store"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={mug}
|
||||
style={{ display: "block" }}
|
||||
text={`Mug someone (${numeralWrapper.formatPercentage(mugChance)} chance of success)`}
|
||||
tooltip={"Attempt to mug a random person on the street"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={larceny}
|
||||
style={{ display: "block" }}
|
||||
text={`Larceny (${numeralWrapper.formatPercentage(larcenyChance)} chance of success)`}
|
||||
tooltip={"Attempt to rob property from someone's house"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={dealDrugs}
|
||||
style={{ display: "block" }}
|
||||
text={`Deal Drugs (${numeralWrapper.formatPercentage(drugsChance)} chance of success)`}
|
||||
tooltip={"Attempt to deal drugs"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={bondForgery}
|
||||
style={{ display: "block" }}
|
||||
text={`Bond Forgery (${numeralWrapper.formatPercentage(bondChance)} chance of success)`}
|
||||
tooltip={"Attempt to forge corporate bonds"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={traffickArms}
|
||||
style={{ display: "block" }}
|
||||
text={`Traffick illegal Arms (${numeralWrapper.formatPercentage(armsChance)} chance of success)`}
|
||||
tooltip={"Attempt to smuggle illegal arms into the city"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={homicide}
|
||||
style={{ display: "block" }}
|
||||
text={`Homicide (${numeralWrapper.formatPercentage(homicideChance)} chance of success)`}
|
||||
tooltip={"Attempt to murder a random person on the street"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={grandTheftAuto}
|
||||
style={{ display: "block" }}
|
||||
text={`Grand theft Auto (${numeralWrapper.formatPercentage(gtaChance)} chance of success)`}
|
||||
tooltip={"Attempt to commit grand theft auto"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={kidnap}
|
||||
style={{ display: "block" }}
|
||||
text={`Kidnap and Ransom (${numeralWrapper.formatPercentage(kidnapChance)} chance of success)`}
|
||||
tooltip={"Attempt to kidnap and ransom a high-profile-target"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={assassinate}
|
||||
style={{ display: "block" }}
|
||||
text={`Assassinate (${numeralWrapper.formatPercentage(assassinateChance)} chance of success)`}
|
||||
tooltip={"Attempt to assassinate a high-profile target"}
|
||||
/>
|
||||
<AutoupdatingStdButton
|
||||
intervalTime={5e3}
|
||||
onClick={heist}
|
||||
style={{ display: "block" }}
|
||||
text={`Heist (${numeralWrapper.formatPercentage(heistChance)} chance of success)`}
|
||||
tooltip={"Attempt to pull off the ultimate heist"}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -10,28 +10,43 @@ import { TravelConfirmationPopup } from "./TravelConfirmationPopup";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { WorldMap } from "../../ui/React/WorldMap";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
travel: (to: CityName) => void;
|
||||
router: IRouter;
|
||||
};
|
||||
|
||||
function createTravelPopup(p: IPlayer, city: string, travel: () => void): void {
|
||||
function travel(p: IPlayer, router: IRouter, to: CityName): void {
|
||||
const cost = CONSTANTS.TravelCost;
|
||||
if (!p.canAfford(cost)) {
|
||||
dialogBoxCreate(`You cannot afford to travel to ${to}`);
|
||||
return;
|
||||
}
|
||||
|
||||
p.loseMoney(cost);
|
||||
p.travel(to);
|
||||
dialogBoxCreate(<span className="noselect">You are now in {to}!</span>);
|
||||
router.toCity();
|
||||
}
|
||||
|
||||
function createTravelPopup(p: IPlayer, router: IRouter, city: CityName): void {
|
||||
if (Settings.SuppressTravelConfirmation) {
|
||||
travel();
|
||||
travel(p, router, city);
|
||||
return;
|
||||
}
|
||||
const popupId = `travel-confirmation`;
|
||||
createPopup(popupId, TravelConfirmationPopup, {
|
||||
player: p,
|
||||
city: city,
|
||||
travel: travel,
|
||||
travel: () => travel(p, router, city),
|
||||
popupId: popupId,
|
||||
});
|
||||
}
|
||||
@ -45,7 +60,7 @@ function ASCIIWorldMap(props: IProps): React.ReactElement {
|
||||
</p>
|
||||
<WorldMap
|
||||
currentCity={props.p.city}
|
||||
onTravel={(city: CityName) => createTravelPopup(props.p, city, () => props.travel(city))}
|
||||
onTravel={(city: CityName) => createTravelPopup(props.p, props.router, city)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -66,7 +81,7 @@ function ListWorldMap(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<StdButton
|
||||
key={city}
|
||||
onClick={() => createTravelPopup(props.p, city, () => props.travel(match[1]))}
|
||||
onClick={() => createTravelPopup(props.p, props.router, city as CityName)}
|
||||
style={{ display: "block" }}
|
||||
text={`Travel to ${city}`}
|
||||
/>
|
||||
@ -76,10 +91,15 @@ function ListWorldMap(props: IProps): React.ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
export function TravelAgencyLocation(props: IProps): React.ReactElement {
|
||||
if (Settings.DisableASCIIArt) {
|
||||
return <ListWorldMap p={props.p} travel={props.travel} />;
|
||||
} else {
|
||||
return <ASCIIWorldMap p={props.p} travel={props.travel} />;
|
||||
}
|
||||
export function TravelAgencyRoot(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<h1>Travel Agency</h1>
|
||||
{Settings.DisableASCIIArt ? (
|
||||
<ListWorldMap p={props.p} router={props.router} />
|
||||
) : (
|
||||
<ASCIIWorldMap p={props.p} router={props.router} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -8,154 +8,134 @@ import * as React from "react";
|
||||
import { Location } from "../Location";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { getServer } from "../../Server/ServerHelpers";
|
||||
import { Server } from "../../Server/Server";
|
||||
import { SpecialServerIps } from "../../Server/SpecialServerIps";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { use } from "../../ui/Context";
|
||||
|
||||
type IProps = {
|
||||
loc: Location;
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
export class UniversityLocation extends React.Component<IProps, any> {
|
||||
/**
|
||||
* Stores button styling that sets them all to block display
|
||||
*/
|
||||
btnStyle: any;
|
||||
export function UniversityLocation(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.btnStyle = { display: "block" };
|
||||
|
||||
this.take = this.take.bind(this);
|
||||
this.study = this.study.bind(this);
|
||||
this.dataStructures = this.dataStructures.bind(this);
|
||||
this.networks = this.networks.bind(this);
|
||||
this.algorithms = this.algorithms.bind(this);
|
||||
this.management = this.management.bind(this);
|
||||
this.leadership = this.leadership.bind(this);
|
||||
|
||||
this.calculateCost = this.calculateCost.bind(this);
|
||||
}
|
||||
|
||||
calculateCost(): number {
|
||||
const ip = SpecialServerIps.getIp(this.props.loc.name);
|
||||
function calculateCost(): number {
|
||||
const ip = SpecialServerIps.getIp(props.loc.name);
|
||||
const server = getServer(ip);
|
||||
if (server == null || !server.hasOwnProperty("backdoorInstalled")) return this.props.loc.costMult;
|
||||
if (server == null || !server.hasOwnProperty("backdoorInstalled")) return props.loc.costMult;
|
||||
const discount = (server as Server).backdoorInstalled ? 0.9 : 1;
|
||||
return this.props.loc.costMult * discount;
|
||||
return props.loc.costMult * discount;
|
||||
}
|
||||
|
||||
take(stat: string): void {
|
||||
const loc = this.props.loc;
|
||||
this.props.p.startClass(this.calculateCost(), loc.expMult, stat);
|
||||
function take(stat: string): void {
|
||||
const loc = props.loc;
|
||||
player.startClass(calculateCost(), loc.expMult, stat);
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
study(): void {
|
||||
this.take(CONSTANTS.ClassStudyComputerScience);
|
||||
function study(): void {
|
||||
take(CONSTANTS.ClassStudyComputerScience);
|
||||
}
|
||||
|
||||
dataStructures(): void {
|
||||
this.take(CONSTANTS.ClassDataStructures);
|
||||
function dataStructures(): void {
|
||||
take(CONSTANTS.ClassDataStructures);
|
||||
}
|
||||
|
||||
networks(): void {
|
||||
this.take(CONSTANTS.ClassNetworks);
|
||||
function networks(): void {
|
||||
take(CONSTANTS.ClassNetworks);
|
||||
}
|
||||
|
||||
algorithms(): void {
|
||||
this.take(CONSTANTS.ClassAlgorithms);
|
||||
function algorithms(): void {
|
||||
take(CONSTANTS.ClassAlgorithms);
|
||||
}
|
||||
|
||||
management(): void {
|
||||
this.take(CONSTANTS.ClassManagement);
|
||||
function management(): void {
|
||||
take(CONSTANTS.ClassManagement);
|
||||
}
|
||||
|
||||
leadership(): void {
|
||||
this.take(CONSTANTS.ClassLeadership);
|
||||
function leadership(): void {
|
||||
take(CONSTANTS.ClassLeadership);
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
const costMult: number = this.calculateCost();
|
||||
const costMult: number = calculateCost();
|
||||
|
||||
const dataStructuresCost = CONSTANTS.ClassDataStructuresBaseCost * costMult;
|
||||
const networksCost = CONSTANTS.ClassNetworksBaseCost * costMult;
|
||||
const algorithmsCost = CONSTANTS.ClassAlgorithmsBaseCost * costMult;
|
||||
const managementCost = CONSTANTS.ClassManagementBaseCost * costMult;
|
||||
const leadershipCost = CONSTANTS.ClassLeadershipBaseCost * costMult;
|
||||
const dataStructuresCost = CONSTANTS.ClassDataStructuresBaseCost * costMult;
|
||||
const networksCost = CONSTANTS.ClassNetworksBaseCost * costMult;
|
||||
const algorithmsCost = CONSTANTS.ClassAlgorithmsBaseCost * costMult;
|
||||
const managementCost = CONSTANTS.ClassManagementBaseCost * costMult;
|
||||
const leadershipCost = CONSTANTS.ClassLeadershipBaseCost * costMult;
|
||||
|
||||
const earnHackingExpTooltip = `Gain hacking experience!`;
|
||||
const earnCharismaExpTooltip = `Gain charisma experience!`;
|
||||
const earnHackingExpTooltip = `Gain hacking experience!`;
|
||||
const earnCharismaExpTooltip = `Gain charisma experience!`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<StdButton
|
||||
onClick={this.study}
|
||||
style={this.btnStyle}
|
||||
text={`Study Computer Science (free)`}
|
||||
tooltip={earnHackingExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={this.dataStructures}
|
||||
style={this.btnStyle}
|
||||
text={
|
||||
<>
|
||||
Take Data Structures course (
|
||||
<Money money={dataStructuresCost} player={this.props.p} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnHackingExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={this.networks}
|
||||
style={this.btnStyle}
|
||||
text={
|
||||
<>
|
||||
Take Networks course (
|
||||
<Money money={networksCost} player={this.props.p} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnHackingExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={this.algorithms}
|
||||
style={this.btnStyle}
|
||||
text={
|
||||
<>
|
||||
Take Algorithms course (
|
||||
<Money money={algorithmsCost} player={this.props.p} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnHackingExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={this.management}
|
||||
style={this.btnStyle}
|
||||
text={
|
||||
<>
|
||||
Take Management course (
|
||||
<Money money={managementCost} player={this.props.p} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnCharismaExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={this.leadership}
|
||||
style={this.btnStyle}
|
||||
text={
|
||||
<>
|
||||
Take Leadership course (
|
||||
<Money money={leadershipCost} player={this.props.p} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnCharismaExpTooltip}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<StdButton
|
||||
onClick={study}
|
||||
style={{ display: "block" }}
|
||||
text={`Study Computer Science (free)`}
|
||||
tooltip={earnHackingExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={dataStructures}
|
||||
style={{ display: "block" }}
|
||||
text={
|
||||
<>
|
||||
Take Data Structures course (
|
||||
<Money money={dataStructuresCost} player={player} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnHackingExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={networks}
|
||||
style={{ display: "block" }}
|
||||
text={
|
||||
<>
|
||||
Take Networks course (
|
||||
<Money money={networksCost} player={player} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnHackingExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={algorithms}
|
||||
style={{ display: "block" }}
|
||||
text={
|
||||
<>
|
||||
Take Algorithms course (
|
||||
<Money money={algorithmsCost} player={player} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnHackingExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={management}
|
||||
style={{ display: "block" }}
|
||||
text={
|
||||
<>
|
||||
Take Management course (
|
||||
<Money money={managementCost} player={player} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnCharismaExpTooltip}
|
||||
/>
|
||||
<StdButton
|
||||
onClick={leadership}
|
||||
style={{ display: "block" }}
|
||||
text={
|
||||
<>
|
||||
Take Leadership course (
|
||||
<Money money={leadershipCost} player={player} /> / sec)
|
||||
</>
|
||||
}
|
||||
tooltip={earnCharismaExpTooltip}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { Engine } from "./engine";
|
||||
import { displayFactionContent } from "./Faction/FactionHelpers";
|
||||
import { Player } from "./Player";
|
||||
|
||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
@ -1187,7 +1185,7 @@ HackingMission.prototype.process = function (numCycles = 1) {
|
||||
});
|
||||
|
||||
// Update timer and check if player lost
|
||||
this.time -= storedCycles * Engine._idleSpeed;
|
||||
this.time -= storedCycles * CONSTANTS._idleSpeed;
|
||||
if (this.time <= 0) {
|
||||
this.finishMission(false);
|
||||
return;
|
||||
@ -1595,18 +1593,6 @@ HackingMission.prototype.finishMission = function (win) {
|
||||
} else {
|
||||
dialogBoxCreate("Mission lost/forfeited! You did not gain any faction reputation.");
|
||||
}
|
||||
|
||||
// Clear mission container
|
||||
var container = document.getElementById("mission-container");
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
// Return to Faction page
|
||||
document.getElementById("mainmenu-container").style.visibility = "visible";
|
||||
document.getElementById("character-overview").style.visibility = "visible";
|
||||
Engine.loadFactionContent();
|
||||
displayFactionContent(this.faction.name);
|
||||
};
|
||||
|
||||
export { HackingMission, inMission, setInMission, currMission };
|
||||
|
@ -119,13 +119,7 @@ import { SpecialServerIps } from "./Server/SpecialServerIps";
|
||||
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||
import { buyStock, sellStock, shortStock, sellShort } from "./StockMarket/BuyingAndSelling";
|
||||
import { influenceStockThroughServerHack, influenceStockThroughServerGrow } from "./StockMarket/PlayerInfluencing";
|
||||
import {
|
||||
StockMarket,
|
||||
SymbolToStockMap,
|
||||
placeOrder,
|
||||
cancelOrder,
|
||||
displayStockMarketContent,
|
||||
} from "./StockMarket/StockMarket";
|
||||
import { StockMarket, SymbolToStockMap, placeOrder, cancelOrder } from "./StockMarket/StockMarket";
|
||||
import { getBuyTransactionCost, getSellTransactionGain } from "./StockMarket/StockMarketHelpers";
|
||||
import { OrderTypes } from "./StockMarket/data/OrderTypes";
|
||||
import { PositionTypes } from "./StockMarket/data/PositionTypes";
|
||||
@ -1964,18 +1958,14 @@ function NetscriptFunctions(workerScript) {
|
||||
updateDynamicRam("buyStock", getRamCost("buyStock"));
|
||||
checkTixApiAccess("buyStock");
|
||||
const stock = getStockFromSymbol(symbol, "buyStock");
|
||||
const res = buyStock(stock, shares, workerScript, {
|
||||
rerenderFn: displayStockMarketContent,
|
||||
});
|
||||
const res = buyStock(stock, shares, workerScript, {});
|
||||
return res ? stock.price : 0;
|
||||
},
|
||||
sellStock: function (symbol, shares) {
|
||||
updateDynamicRam("sellStock", getRamCost("sellStock"));
|
||||
checkTixApiAccess("sellStock");
|
||||
const stock = getStockFromSymbol(symbol, "sellStock");
|
||||
const res = sellStock(stock, shares, workerScript, {
|
||||
rerenderFn: displayStockMarketContent,
|
||||
});
|
||||
const res = sellStock(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.price : 0;
|
||||
},
|
||||
@ -1991,9 +1981,7 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "shortStock");
|
||||
const res = shortStock(stock, shares, workerScript, {
|
||||
rerenderFn: displayStockMarketContent,
|
||||
});
|
||||
const res = shortStock(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.price : 0;
|
||||
},
|
||||
@ -2009,9 +1997,7 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "sellShort");
|
||||
const res = sellShort(stock, shares, workerScript, {
|
||||
rerenderFn: displayStockMarketContent,
|
||||
});
|
||||
const res = sellShort(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.price : 0;
|
||||
},
|
||||
@ -2168,7 +2154,6 @@ function NetscriptFunctions(workerScript) {
|
||||
Player.has4SData = true;
|
||||
Player.loseMoney(getStockMarket4SDataCost());
|
||||
workerScript.log("purchase4SMarketData", "Purchased 4S Market Data");
|
||||
displayStockMarketContent();
|
||||
return true;
|
||||
},
|
||||
purchase4SMarketDataTixApi: function () {
|
||||
@ -2188,7 +2173,6 @@ function NetscriptFunctions(workerScript) {
|
||||
Player.has4SDataTixApi = true;
|
||||
Player.loseMoney(getStockMarket4STixApiCost());
|
||||
workerScript.log("purchase4SMarketDataTixApi", "Purchased 4S Market Data TIX API");
|
||||
displayStockMarketContent();
|
||||
return true;
|
||||
},
|
||||
getPurchasedServerLimit: function () {
|
||||
|
@ -121,8 +121,33 @@ export interface IPlayer {
|
||||
bladeburner_analysis_mult: number;
|
||||
bladeburner_success_chance_mult: number;
|
||||
|
||||
workRepGained: number;
|
||||
createProgramName: string;
|
||||
timeWorkedCreateProgram: number;
|
||||
crimeType: string;
|
||||
timeNeededToCompleteWork: number;
|
||||
focus: boolean;
|
||||
className: string;
|
||||
currentWorkFactionName: string;
|
||||
workType: string;
|
||||
currentWorkFactionDescription: string;
|
||||
timeWorked: number;
|
||||
workMoneyGained: number;
|
||||
workMoneyGainRate: number;
|
||||
workRepGained: number;
|
||||
workRepGainRate: number;
|
||||
workHackExpGained: number;
|
||||
workHackExpGainRate: number;
|
||||
workStrExpGained: number;
|
||||
workStrExpGainRate: number;
|
||||
workDefExpGained: number;
|
||||
workDefExpGainRate: number;
|
||||
workDexExpGained: number;
|
||||
workDexExpGainRate: number;
|
||||
workAgiExpGained: number;
|
||||
workAgiExpGainRate: number;
|
||||
workChaExpGained: number;
|
||||
workChaExpGainRate: number;
|
||||
workMoneyLossRate: number;
|
||||
|
||||
// Methods
|
||||
applyForAgentJob(sing?: boolean): boolean | void;
|
||||
@ -209,4 +234,12 @@ export interface IPlayer {
|
||||
receiveInvite(factionName: string): void;
|
||||
updateSkillLevels(): void;
|
||||
gainCodingContractReward(reward: ICodingContractReward, difficulty?: number): string;
|
||||
stopFocusing(): void;
|
||||
finishFactionWork(cancelled: boolean, sing?: boolean): void;
|
||||
finishClass(sing?: boolean): void;
|
||||
finishWork(cancelled: boolean, sing?: boolean): void;
|
||||
cancelationPenalty(): number;
|
||||
finishWorkPartTime(sing?: boolean): void;
|
||||
finishCrime(cancelled: boolean): void;
|
||||
finishCreateProgramWork(cancelled: boolean): void;
|
||||
}
|
||||
|
@ -14,10 +14,8 @@ import { CONSTANTS } from "../../Constants";
|
||||
import { Programs } from "../../Programs/Programs";
|
||||
import { determineCrimeSuccess } from "../../Crime/CrimeHelpers";
|
||||
import { Crimes } from "../../Crime/Crimes";
|
||||
import { Engine } from "../../engine";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { displayFactionContent } from "../../Faction/FactionHelpers";
|
||||
import { resetGangs } from "../../Gang/AllGangs";
|
||||
import { hasHacknetServers } from "../../Hacknet/HacknetHelpers";
|
||||
import { Cities } from "../../Locations/Cities";
|
||||
@ -48,18 +46,12 @@ import Decimal from "decimal.js";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
|
||||
import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
|
||||
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||
import { ReputationRate } from "../../ui/React/ReputationRate";
|
||||
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
|
||||
|
||||
export function init() {
|
||||
/* Initialize Player's home computer */
|
||||
@ -518,8 +510,6 @@ export function resetWorkStatus(generalType, group, workType) {
|
||||
this.currentWorkFactionDescription = "";
|
||||
this.createProgramName = "";
|
||||
this.className = "";
|
||||
|
||||
ReactDOM.unmountComponentAtNode(document.getElementById("work-in-progress-text"));
|
||||
}
|
||||
|
||||
export function processWorkEarnings(numCycles = 1) {
|
||||
@ -573,25 +563,6 @@ export function startWork(companyName) {
|
||||
this.workMoneyGainRate = this.getWorkMoneyGain();
|
||||
|
||||
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
|
||||
|
||||
//Remove all old event listeners from Cancel button
|
||||
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
|
||||
newCancelButton.innerHTML = "Cancel Work";
|
||||
newCancelButton.addEventListener("click", () => {
|
||||
this.finishWork(true);
|
||||
return false;
|
||||
});
|
||||
|
||||
const focusButton = clearEventListeners("work-in-progress-something-else-button");
|
||||
focusButton.style.visibility = "visible";
|
||||
focusButton.innerHTML = "Do something else simultaneously";
|
||||
focusButton.addEventListener("click", () => {
|
||||
this.stopFocusing();
|
||||
return false;
|
||||
});
|
||||
|
||||
//Display Work In Progress Screen
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
export function cancelationPenalty() {
|
||||
@ -607,11 +578,11 @@ export function work(numCycles) {
|
||||
// Cap the number of cycles being processed to whatever would put you at
|
||||
// the work time limit (8 hours)
|
||||
var overMax = false;
|
||||
if (this.timeWorked + Engine._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / Engine._idleSpeed);
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
||||
}
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
||||
|
||||
this.workRepGainRate = this.getWorkRepGain();
|
||||
this.processWorkEarnings(numCycles);
|
||||
@ -622,63 +593,7 @@ export function work(numCycles) {
|
||||
}
|
||||
|
||||
const comp = Companies[this.companyName];
|
||||
let companyRep = "0";
|
||||
if (comp == null || !(comp instanceof Company)) {
|
||||
console.error(`Could not find Company: ${this.companyName}`);
|
||||
} else {
|
||||
companyRep = comp.playerReputation;
|
||||
}
|
||||
|
||||
influenceStockThroughCompanyWork(comp, this.workRepGainRate, numCycles);
|
||||
|
||||
const position = this.jobs[this.companyName];
|
||||
|
||||
const penalty = this.cancelationPenalty();
|
||||
|
||||
const penaltyString = penalty === 0.5 ? "half" : "three-quarters";
|
||||
|
||||
var elem = document.getElementById("work-in-progress-text");
|
||||
ReactDOM.render(
|
||||
<>
|
||||
You are currently working as a {position} at {this.companyName} (Current Company Reputation:{" "}
|
||||
{Reputation(companyRep)})<br />
|
||||
<br />
|
||||
You have been working for {convertTimeMsToTimeElapsedString(this.timeWorked)}
|
||||
<br />
|
||||
<br />
|
||||
You have earned: <br />
|
||||
<br />
|
||||
<Money money={this.workMoneyGained} /> ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br />
|
||||
<br />
|
||||
{Reputation(this.workRepGained)} ({ReputationRate(this.workRepGainRate * CYCLES_PER_SEC)}) reputation for this
|
||||
company <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workHackExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) hacking exp <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workStrExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) strength exp <br />
|
||||
{numeralWrapper.formatExp(this.workDefExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workDefExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) defense exp <br />
|
||||
{numeralWrapper.formatExp(this.workDexExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workDexExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) dexterity exp <br />
|
||||
{numeralWrapper.formatExp(this.workAgiExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) agility exp <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workChaExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workChaExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) charisma exp <br />
|
||||
<br />
|
||||
You will automatically finish after working for 8 hours. You can cancel earlier if you wish, but you will only
|
||||
gain {penaltyString} of the reputation you've earned so far.
|
||||
</>,
|
||||
elem,
|
||||
);
|
||||
}
|
||||
|
||||
export function finishWork(cancelled, sing = false) {
|
||||
@ -731,10 +646,7 @@ export function finishWork(cancelled, sing = false) {
|
||||
dialogBoxCreate(content);
|
||||
}
|
||||
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
this.isWorking = false;
|
||||
Engine.loadLocationContent(false);
|
||||
|
||||
if (sing) {
|
||||
var res =
|
||||
@ -781,27 +693,17 @@ export function startWorkPartTime(companyName) {
|
||||
this.workMoneyGainRate = this.getWorkMoneyGain();
|
||||
|
||||
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
|
||||
|
||||
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
|
||||
newCancelButton.innerHTML = "Stop Working";
|
||||
newCancelButton.addEventListener("click", () => {
|
||||
this.finishWorkPartTime();
|
||||
return false;
|
||||
});
|
||||
|
||||
//Display Work In Progress Screen
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
export function workPartTime(numCycles) {
|
||||
//Cap the number of cycles being processed to whatever would put you at the
|
||||
//work time limit (8 hours)
|
||||
var overMax = false;
|
||||
if (this.timeWorked + Engine._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / Engine._idleSpeed);
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
||||
}
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
||||
|
||||
this.workRepGainRate = this.getWorkRepGain();
|
||||
this.processWorkEarnings(numCycles);
|
||||
@ -810,60 +712,6 @@ export function workPartTime(numCycles) {
|
||||
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
return this.finishWorkPartTime();
|
||||
}
|
||||
|
||||
var comp = Companies[this.companyName],
|
||||
companyRep = "0";
|
||||
if (comp == null || !(comp instanceof Company)) {
|
||||
console.error(`Could not find Company: ${this.companyName}`);
|
||||
} else {
|
||||
companyRep = comp.playerReputation;
|
||||
}
|
||||
|
||||
const position = this.jobs[this.companyName];
|
||||
|
||||
const elem = document.getElementById("work-in-progress-text");
|
||||
ReactDOM.render(
|
||||
<>
|
||||
You are currently working as a {position} at {this.companyName} (Current Company Reputation:{" "}
|
||||
{Reputation(companyRep)})<br />
|
||||
<br />
|
||||
You have been working for {convertTimeMsToTimeElapsedString(this.timeWorked)}
|
||||
<br />
|
||||
<br />
|
||||
You have earned: <br />
|
||||
<br />
|
||||
<Money money={this.workMoneyGained} /> ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br />
|
||||
<br />
|
||||
{Reputation(this.workRepGained)} (
|
||||
{Reputation(`${numeralWrapper.formatExp(this.workRepGainRate * CYCLES_PER_SEC)} / sec`)}
|
||||
) reputation for this company <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workHackExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) hacking exp <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workStrExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) strength exp <br />
|
||||
{numeralWrapper.formatExp(this.workDefExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workDefExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) defense exp <br />
|
||||
{numeralWrapper.formatExp(this.workDexExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workDexExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) dexterity exp <br />
|
||||
{numeralWrapper.formatExp(this.workAgiExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) agility exp <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workChaExpGained)} (
|
||||
{`${numeralWrapper.formatExp(this.workChaExpGainRate * CYCLES_PER_SEC)} / sec`}
|
||||
) charisma exp <br />
|
||||
<br />
|
||||
You will automatically finish after working for 8 hours. You can cancel earlier if you wish, and there will be no
|
||||
penalty because this is a part-time job.
|
||||
</>,
|
||||
elem,
|
||||
);
|
||||
}
|
||||
|
||||
export function finishWorkPartTime(sing = false) {
|
||||
@ -894,10 +742,7 @@ export function finishWorkPartTime(sing = false) {
|
||||
dialogBoxCreate(content);
|
||||
}
|
||||
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
this.isWorking = false;
|
||||
Engine.loadLocationContent(false);
|
||||
if (sing) {
|
||||
var res =
|
||||
"You worked for " +
|
||||
@ -928,17 +773,11 @@ export function finishWorkPartTime(sing = false) {
|
||||
}
|
||||
|
||||
export function startFocusing() {
|
||||
const mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
this.focus = true;
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
export function stopFocusing() {
|
||||
const mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
this.focus = false;
|
||||
Engine.loadTerminalContent();
|
||||
}
|
||||
|
||||
/* Working for Faction */
|
||||
@ -957,24 +796,6 @@ export function startFactionWork(faction) {
|
||||
this.currentWorkFactionName = faction.name;
|
||||
|
||||
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours;
|
||||
|
||||
const cancelButton = clearEventListeners("work-in-progress-cancel-button");
|
||||
cancelButton.innerHTML = "Stop Faction Work";
|
||||
cancelButton.addEventListener("click", () => {
|
||||
this.finishFactionWork(true);
|
||||
return false;
|
||||
});
|
||||
|
||||
const focusButton = clearEventListeners("work-in-progress-something-else-button");
|
||||
focusButton.style.visibility = "visible";
|
||||
focusButton.innerHTML = "Do something else simultaneously";
|
||||
focusButton.addEventListener("click", () => {
|
||||
this.stopFocusing();
|
||||
return false;
|
||||
});
|
||||
|
||||
//Display Work In Progress Screen
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
export function startFactionHackWork(faction) {
|
||||
@ -1046,11 +867,11 @@ export function workForFaction(numCycles) {
|
||||
|
||||
//Cap the number of cycles being processed to whatever would put you at limit (20 hours)
|
||||
var overMax = false;
|
||||
if (this.timeWorked + Engine._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer20Hours) {
|
||||
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer20Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer20Hours - this.timeWorked) / Engine._idleSpeed);
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer20Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
||||
}
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
||||
|
||||
this.processWorkEarnings(numCycles);
|
||||
|
||||
@ -1058,44 +879,6 @@ export function workForFaction(numCycles) {
|
||||
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer20Hours) {
|
||||
return this.finishFactionWork(false);
|
||||
}
|
||||
|
||||
const elem = document.getElementById("work-in-progress-text");
|
||||
ReactDOM.render(
|
||||
<>
|
||||
You are currently {this.currentWorkFactionDescription} for your faction {faction.name}
|
||||
<br />
|
||||
(Current Faction Reputation: {Reputation(faction.playerReputation)}). <br />
|
||||
You have been doing this for {convertTimeMsToTimeElapsedString(this.timeWorked)}
|
||||
<br />
|
||||
<br />
|
||||
You have earned: <br />
|
||||
<br />
|
||||
<Money money={this.workMoneyGained} /> ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br />
|
||||
<br />
|
||||
{Reputation(this.workRepGained)} ({ReputationRate(this.workRepGainRate * CYCLES_PER_SEC)}) reputation for this
|
||||
faction <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workHackExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workStrExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br />
|
||||
{numeralWrapper.formatExp(this.workDefExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br />
|
||||
{numeralWrapper.formatExp(this.workDexExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br />
|
||||
{numeralWrapper.formatExp(this.workAgiExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br />
|
||||
<br />
|
||||
{numeralWrapper.formatExp(this.workChaExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br />
|
||||
<br />
|
||||
You will automatically finish after working for 20 hours. You can cancel earlier if you wish.
|
||||
<br />
|
||||
There is no penalty for cancelling earlier.
|
||||
</>,
|
||||
elem,
|
||||
);
|
||||
}
|
||||
|
||||
export function finishFactionWork(cancelled, sing = false) {
|
||||
@ -1125,13 +908,8 @@ export function finishFactionWork(cancelled, sing = false) {
|
||||
);
|
||||
}
|
||||
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
|
||||
this.isWorking = false;
|
||||
|
||||
Engine.loadFactionContent();
|
||||
displayFactionContent(faction.name);
|
||||
if (sing) {
|
||||
var res =
|
||||
"You worked for your faction " +
|
||||
@ -1419,19 +1197,6 @@ export function startCreateProgramWork(programName, time, reqLevel) {
|
||||
}
|
||||
|
||||
this.createProgramName = programName;
|
||||
|
||||
var cancelButton = clearEventListeners("work-in-progress-cancel-button");
|
||||
cancelButton.innerHTML = "Cancel work on creating program";
|
||||
cancelButton.addEventListener("click", () => {
|
||||
this.finishCreateProgramWork(true);
|
||||
return false;
|
||||
});
|
||||
|
||||
const focusButton = clearEventListeners("work-in-progress-something-else-button");
|
||||
focusButton.style.visibility = "hidden";
|
||||
|
||||
//Display Work In Progress Screen
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
export function createProgramWork(numCycles) {
|
||||
@ -1441,28 +1206,12 @@ export function createProgramWork(numCycles) {
|
||||
skillMult = 1 + (skillMult - 1) / 5; //The divider constant can be adjusted as necessary
|
||||
|
||||
//Skill multiplier directly applied to "time worked"
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
this.timeWorkedCreateProgram += Engine._idleSpeed * numCycles * skillMult;
|
||||
var programName = this.createProgramName;
|
||||
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
||||
this.timeWorkedCreateProgram += CONSTANTS._idleSpeed * numCycles * skillMult;
|
||||
|
||||
if (this.timeWorkedCreateProgram >= this.timeNeededToCompleteWork) {
|
||||
this.finishCreateProgramWork(false);
|
||||
}
|
||||
|
||||
const elem = document.getElementById("work-in-progress-text");
|
||||
ReactDOM.render(
|
||||
<>
|
||||
You are currently working on coding {programName}.<br />
|
||||
<br />
|
||||
You have been working for {convertTimeMsToTimeElapsedString(this.timeWorked)}
|
||||
<br />
|
||||
<br />
|
||||
The program is {((this.timeWorkedCreateProgram / this.timeNeededToCompleteWork) * 100).toFixed(2)}
|
||||
% complete. <br />
|
||||
If you cancel, your work will be saved and you can come back to complete the program later.
|
||||
</>,
|
||||
elem,
|
||||
);
|
||||
}
|
||||
|
||||
export function finishCreateProgramWork(cancelled) {
|
||||
@ -1483,12 +1232,8 @@ export function finishCreateProgramWork(cancelled) {
|
||||
this.gainIntelligenceExp(this.createProgramReqLvl / CONSTANTS.IntelligenceProgramBaseExpGain);
|
||||
}
|
||||
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
|
||||
this.isWorking = false;
|
||||
|
||||
Engine.loadTerminalContent();
|
||||
this.resetWorkStatus();
|
||||
}
|
||||
|
||||
@ -1501,7 +1246,7 @@ export function startClass(costMult, expMult, className) {
|
||||
|
||||
this.className = className;
|
||||
|
||||
const gameCPS = 1000 / Engine._idleSpeed;
|
||||
const gameCPS = 1000 / CONSTANTS._idleSpeed;
|
||||
|
||||
//Find cost and exp gain per game cycle
|
||||
var cost = 0;
|
||||
@ -1564,62 +1309,11 @@ export function startClass(costMult, expMult, className) {
|
||||
this.workDexExpGainRate = dexExp * this.dexterity_exp_mult * BitNodeMultipliers.ClassGymExpGain;
|
||||
this.workAgiExpGainRate = agiExp * this.agility_exp_mult * BitNodeMultipliers.ClassGymExpGain;
|
||||
this.workChaExpGainRate = chaExp * this.charisma_exp_mult * BitNodeMultipliers.ClassGymExpGain;
|
||||
|
||||
var cancelButton = clearEventListeners("work-in-progress-cancel-button");
|
||||
if (
|
||||
className == CONSTANTS.ClassGymStrength ||
|
||||
className == CONSTANTS.ClassGymDefense ||
|
||||
className == CONSTANTS.ClassGymDexterity ||
|
||||
className == CONSTANTS.ClassGymAgility
|
||||
) {
|
||||
cancelButton.innerHTML = "Stop training at gym";
|
||||
} else {
|
||||
cancelButton.innerHTML = "Stop taking course";
|
||||
}
|
||||
cancelButton.addEventListener("click", () => {
|
||||
this.finishClass();
|
||||
return false;
|
||||
});
|
||||
|
||||
const focusButton = clearEventListeners("work-in-progress-something-else-button");
|
||||
focusButton.style.visibility = "hidden";
|
||||
|
||||
//Display Work In Progress Screen
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
export function takeClass(numCycles) {
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
var className = this.className;
|
||||
|
||||
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
||||
this.processWorkEarnings(numCycles);
|
||||
|
||||
const elem = document.getElementById("work-in-progress-text");
|
||||
ReactDOM.render(
|
||||
<>
|
||||
You have been {className} for {convertTimeMsToTimeElapsedString(this.timeWorked)}
|
||||
<br />
|
||||
<br />
|
||||
This has cost you: <br />
|
||||
<Money money={-this.workMoneyGained} /> ({MoneyRate(this.workMoneyLossRate * CYCLES_PER_SEC)}) <br />
|
||||
<br />
|
||||
You have gained: <br />
|
||||
{numeralWrapper.formatExp(this.workHackExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br />
|
||||
{numeralWrapper.formatExp(this.workStrExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br />
|
||||
{numeralWrapper.formatExp(this.workDefExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br />
|
||||
{numeralWrapper.formatExp(this.workDexExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br />
|
||||
{numeralWrapper.formatExp(this.workAgiExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br />
|
||||
{numeralWrapper.formatExp(this.workChaExpGained)} (
|
||||
{numeralWrapper.formatExp(this.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br />
|
||||
You may cancel at any time
|
||||
</>,
|
||||
elem,
|
||||
);
|
||||
}
|
||||
|
||||
//The 'sing' argument defines whether or not this function was called
|
||||
@ -1650,12 +1344,8 @@ export function finishClass(sing = false) {
|
||||
);
|
||||
}
|
||||
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
|
||||
this.isWorking = false;
|
||||
|
||||
Engine.loadLocationContent(false);
|
||||
if (sing) {
|
||||
var res =
|
||||
"After " +
|
||||
@ -1708,49 +1398,12 @@ export function startCrime(crimeType, hackExp, strExp, defExp, dexExp, agiExp, c
|
||||
this.workMoneyGained = money * this.crime_money_mult * BitNodeMultipliers.CrimeMoney;
|
||||
|
||||
this.timeNeededToCompleteWork = time;
|
||||
|
||||
//Remove all old event listeners from Cancel button
|
||||
const newCancelButton = clearEventListeners("work-in-progress-cancel-button");
|
||||
newCancelButton.innerHTML = "Cancel crime";
|
||||
newCancelButton.addEventListener("click", () => {
|
||||
this.finishCrime(true);
|
||||
return false;
|
||||
});
|
||||
|
||||
const focusButton = clearEventListeners("work-in-progress-something-else-button");
|
||||
focusButton.style.visibility = "hidden";
|
||||
|
||||
//Display Work In Progress Screen
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
export function commitCrime(numCycles) {
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
||||
|
||||
if (this.timeWorked >= this.timeNeededToCompleteWork) {
|
||||
this.finishCrime(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var percent = Math.round((this.timeWorked / this.timeNeededToCompleteWork) * 100);
|
||||
var numBars = Math.round(percent / 5);
|
||||
if (numBars < 0) {
|
||||
numBars = 0;
|
||||
}
|
||||
if (numBars > 20) {
|
||||
numBars = 20;
|
||||
}
|
||||
var progressBar = "[" + Array(numBars + 1).join("|") + Array(20 - numBars + 1).join(" ") + "]";
|
||||
|
||||
var txt = document.getElementById("work-in-progress-text");
|
||||
txt.innerHTML =
|
||||
"You are attempting to " +
|
||||
this.crimeType +
|
||||
".<br>" +
|
||||
"Time remaining: " +
|
||||
convertTimeMsToTimeElapsedString(this.timeNeededToCompleteWork - this.timeWorked) +
|
||||
"<br>" +
|
||||
progressBar.replace(/ /g, " ");
|
||||
if (this.timeWorked >= this.timeNeededToCompleteWork) this.finishCrime(false);
|
||||
}
|
||||
|
||||
export function finishCrime(cancelled) {
|
||||
@ -1892,11 +1545,9 @@ export function finishCrime(cancelled) {
|
||||
}
|
||||
this.committingCrimeThruSingFn = false;
|
||||
this.singFnCrimeWorkerScript = null;
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
this.isWorking = false;
|
||||
this.crimeType = "";
|
||||
this.resetWorkStatus();
|
||||
Engine.loadLocationContent(false);
|
||||
}
|
||||
|
||||
//Cancels the player's current "work" assignment and gives the proper rewards
|
||||
|
@ -20,7 +20,7 @@ export function SleeveRoot(props: IProps): React.ReactElement {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ width: "70%" }}>
|
||||
<>
|
||||
<h1>Sleeves</h1>
|
||||
<p>
|
||||
Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciousness has been copied. In
|
||||
@ -50,6 +50,6 @@ export function SleeveRoot(props: IProps): React.ReactElement {
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
2
src/Prestige.d.ts
vendored
Normal file
2
src/Prestige.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export declare function prestigeAugmentation(): void;
|
||||
export declare function prestigeSourceFile(flume: boolean): void;
|
@ -3,7 +3,6 @@ import { augmentationExists, initAugmentations } from "./Augmentation/Augmentati
|
||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
||||
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||
import { writeCinematicText } from "./CinematicText";
|
||||
import { Companies, initCompanies } from "./Company/Companies";
|
||||
import { resetIndustryResearchTrees } from "./Corporation/IndustryData";
|
||||
import { Programs } from "./Programs/Programs";
|
||||
@ -25,13 +24,7 @@ import { SpecialServerIps, prestigeSpecialServerIps, SpecialServerNames } from "
|
||||
import { deleteStockMarket, initStockMarket, initSymbolToStockMap } from "./StockMarket/StockMarket";
|
||||
import { Terminal } from "./Terminal";
|
||||
|
||||
import { Page, routing } from "./ui/navigationTracking";
|
||||
|
||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
|
||||
@ -39,9 +32,6 @@ const BitNode8StartingMoney = 250e6;
|
||||
|
||||
// Prestige by purchasing augmentation
|
||||
function prestigeAugmentation() {
|
||||
// Set Navigation to Terminal screen, for any logic that depends on it
|
||||
routing.navigateTo(Page.Terminal);
|
||||
|
||||
initBitNodeMultipliers(Player);
|
||||
|
||||
const megaCorpFactions = [
|
||||
@ -62,9 +52,6 @@ function prestigeAugmentation() {
|
||||
});
|
||||
Player.prestigeAugmentation();
|
||||
|
||||
Terminal.clear();
|
||||
Engine.loadTerminalContent();
|
||||
|
||||
// Delete all Worker Scripts objects
|
||||
prestigeWorkerScripts();
|
||||
|
||||
@ -244,11 +231,6 @@ function prestigeSourceFile(flume) {
|
||||
// Messages
|
||||
initMessages();
|
||||
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
Terminal.clear();
|
||||
Engine.loadTerminalContent();
|
||||
|
||||
// BitNode 3: Corporatocracy
|
||||
if (Player.bitNodeN === 3) {
|
||||
homeComp.messages.push(LiteratureNames.CorporationManagementHandbook);
|
||||
@ -258,56 +240,6 @@ function prestigeSourceFile(flume) {
|
||||
);
|
||||
}
|
||||
|
||||
// BitNode 6: Bladeburner
|
||||
if (Player.bitNodeN === 6) {
|
||||
var cinematicText = [
|
||||
"In the middle of the 21st century, OmniTek Incorporated advanced robot evolution " +
|
||||
"with their Synthoids (synthetic androids), a being virtually identical to a human.",
|
||||
"------",
|
||||
"Their sixth-generation Synthoids, called MK-VI, were stronger, faster, and more " +
|
||||
"intelligent than humans. Many argued that the MK-VI Synthoids were the first " +
|
||||
"example of sentient AI.",
|
||||
"------",
|
||||
"Unfortunately, in 2070 a terrorist group called Ascendis Totalis hacked into OmniTek and " +
|
||||
"uploaded a rogue AI into their Synthoid manufacturing facilities.",
|
||||
"------",
|
||||
"The MK-VI Synthoids infected by the rogue AI turned hostile toward humanity, initiating " +
|
||||
"the deadliest conflict in human history. This dark chapter is now known as the Synthoid Uprising.",
|
||||
"------",
|
||||
"In the aftermath of the Uprising, further manufacturing of Synthoids with advanced AI " +
|
||||
"was banned. MK-VI Synthoids that did not have the rogue Ascendis Totalis AI were " +
|
||||
"allowed to continue their existence.",
|
||||
"------",
|
||||
"The intelligence community believes that not all of the rogue MK-VI Synthoids from the Uprising were " +
|
||||
"found and destroyed, and that many of them are blending in as normal humans in society today. " +
|
||||
"As a result, many nations have created Bladeburner divisions, special units that are tasked with " +
|
||||
"investigating and dealing with Synthoid threats.",
|
||||
];
|
||||
writeCinematicText(cinematicText)
|
||||
.then(function () {
|
||||
var popupId = "bladeburner-bitnode-start-nsa-notification";
|
||||
var txt = createElement("p", {
|
||||
innerText:
|
||||
"Visit the National Security Agency (NSA) to apply for their Bladeburner " +
|
||||
"division! You will need 100 of each combat stat before doing this.",
|
||||
});
|
||||
var brEl = createElement("br");
|
||||
var okBtn = createElement("a", {
|
||||
class: "a-link-button",
|
||||
innerText: "Got it!",
|
||||
padding: "8px",
|
||||
clickListener: () => {
|
||||
removeElementById(popupId);
|
||||
return false;
|
||||
},
|
||||
});
|
||||
createPopup(popupId, [txt, brEl, okBtn]);
|
||||
})
|
||||
.catch(function (e) {
|
||||
exceptionAlert(e);
|
||||
});
|
||||
}
|
||||
|
||||
// BitNode 8: Ghost of Wall Street
|
||||
if (Player.bitNodeN === 8) {
|
||||
Player.money = new Decimal(BitNode8StartingMoney);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { BaseServer } from "../Server/BaseServer";
|
||||
import { ITerminal } from "../Terminal/ITerminal";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../ui/Router";
|
||||
|
||||
export interface IProgramCreate {
|
||||
level: number;
|
||||
@ -12,12 +13,12 @@ export interface IProgramCreate {
|
||||
export class Program {
|
||||
name = "";
|
||||
create: IProgramCreate | null;
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void;
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void;
|
||||
|
||||
constructor(
|
||||
name: string,
|
||||
create: IProgramCreate | null,
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void,
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void,
|
||||
) {
|
||||
this.name = name;
|
||||
this.create = create;
|
||||
|
@ -3,6 +3,7 @@ import { CONSTANTS } from "../../Constants";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { Server } from "../../Server/Server";
|
||||
import { ITerminal } from "../../Terminal/ITerminal";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { HacknetServer } from "../../Hacknet/HacknetServer";
|
||||
import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
|
||||
@ -30,7 +31,7 @@ export interface IProgramCreationParams {
|
||||
key: string;
|
||||
name: string;
|
||||
create: IProgramCreate | null;
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void;
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void;
|
||||
}
|
||||
|
||||
export const programsMetadata: IProgramCreationParams[] = [
|
||||
@ -43,7 +44,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(1),
|
||||
time: CONSTANTS.MillisecondsPerFiveMinutes,
|
||||
},
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
if (!(server instanceof Server)) {
|
||||
terminal.error("Cannot nuke this kind of server.");
|
||||
return;
|
||||
@ -72,7 +73,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(50),
|
||||
time: CONSTANTS.MillisecondsPerFiveMinutes * 2,
|
||||
},
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
if (!(server instanceof Server)) {
|
||||
terminal.error("Cannot run BruteSSH.exe on this kind of server.");
|
||||
return;
|
||||
@ -96,7 +97,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(100),
|
||||
time: CONSTANTS.MillisecondsPerHalfHour,
|
||||
},
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
if (!(server instanceof Server)) {
|
||||
terminal.error("Cannot run FTPCrack.exe on this kind of server.");
|
||||
return;
|
||||
@ -120,7 +121,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(250),
|
||||
time: CONSTANTS.MillisecondsPer2Hours,
|
||||
},
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
if (!(server instanceof Server)) {
|
||||
terminal.error("Cannot run relaySMTP.exe on this kind of server.");
|
||||
return;
|
||||
@ -144,7 +145,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(500),
|
||||
time: CONSTANTS.MillisecondsPer4Hours,
|
||||
},
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
if (!(server instanceof Server)) {
|
||||
terminal.error("Cannot run HTTPWorm.exe on this kind of server.");
|
||||
return;
|
||||
@ -168,7 +169,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(750),
|
||||
time: CONSTANTS.MillisecondsPer8Hours,
|
||||
},
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||
if (!(server instanceof Server)) {
|
||||
terminal.error("Cannot run SQLInject.exe on this kind of server.");
|
||||
return;
|
||||
@ -192,7 +193,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(75),
|
||||
time: CONSTANTS.MillisecondsPerQuarterHour,
|
||||
},
|
||||
run: (terminal: ITerminal): void => {
|
||||
run: (router: IRouter, terminal: ITerminal): void => {
|
||||
terminal.print("This executable cannot be run.");
|
||||
terminal.print("DeepscanV1.exe lets you run 'scan-analyze' with a depth up to 5.");
|
||||
},
|
||||
@ -206,7 +207,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(400),
|
||||
time: CONSTANTS.MillisecondsPer2Hours,
|
||||
},
|
||||
run: (terminal: ITerminal): void => {
|
||||
run: (router: IRouter, terminal: ITerminal): void => {
|
||||
terminal.print("This executable cannot be run.");
|
||||
terminal.print("DeepscanV2.exe lets you run 'scan-analyze' with a depth up to 10.");
|
||||
},
|
||||
@ -220,7 +221,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(75),
|
||||
time: CONSTANTS.MillisecondsPerHalfHour,
|
||||
},
|
||||
run: (terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]): void => {
|
||||
if (args.length !== 1) {
|
||||
terminal.print("Must pass a server hostname or IP as an argument for ServerProfiler.exe");
|
||||
return;
|
||||
@ -270,7 +271,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: requireHackingLevel(25),
|
||||
time: CONSTANTS.MillisecondsPerQuarterHour,
|
||||
},
|
||||
run: (terminal: ITerminal): void => {
|
||||
run: (router: IRouter, terminal: ITerminal): void => {
|
||||
terminal.print("This executable cannot be run.");
|
||||
terminal.print("AutoLink.exe lets you automatically connect to other servers when using 'scan-analyze'.");
|
||||
terminal.print("When using scan-analyze, click on a server's hostname to connect to it.");
|
||||
@ -285,10 +286,11 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
req: bitFlumeRequirements(),
|
||||
time: CONSTANTS.MillisecondsPerFiveMinutes / 20,
|
||||
},
|
||||
run: (terminal: ITerminal, player: IPlayer): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer): void => {
|
||||
const popupId = "bitflume-popup";
|
||||
createPopup(popupId, BitFlumePopup, {
|
||||
player: player,
|
||||
router: router,
|
||||
popupId: popupId,
|
||||
});
|
||||
},
|
||||
@ -297,7 +299,7 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
key: "Flight",
|
||||
name: "fl1ght.exe",
|
||||
create: null,
|
||||
run: (terminal: ITerminal, player: IPlayer): void => {
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer): void => {
|
||||
const numAugReq = Math.round(BitNodeMultipliers.DaedalusAugsRequirement * 30);
|
||||
const fulfilled =
|
||||
player.augmentations.length >= numAugReq && player.money.gt(1e11) && player.hacking_skill >= 2500;
|
||||
|
@ -1,15 +1,13 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { use } from "../../ui/Context";
|
||||
import { getAvailableCreatePrograms } from "../ProgramHelpers";
|
||||
|
||||
import { Box, ButtonGroup, Tooltip, Typography } from "@mui/material";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function ProgramsRoot(props: IProps): React.ReactElement {
|
||||
export function ProgramsRoot(): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
@ -25,26 +23,31 @@ export function ProgramsRoot(props: IProps): React.ReactElement {
|
||||
<div>
|
||||
<Box>
|
||||
<Typography>
|
||||
This page displays any programs that you are able to create. Writing the code for a program takes time, which
|
||||
can vary based on how complex the program is. If you are working on creating a program you can cancel at any
|
||||
time. Your progress will be saved and you can continue later.
|
||||
This page displays any programs that you are able to create. Writing the code for a program takes time,
|
||||
which can vary based on how complex the program is. If you are working on creating a program you can cancel
|
||||
at any time. Your progress will be saved and you can continue later.
|
||||
</Typography>
|
||||
</Box>
|
||||
<ButtonGroup>
|
||||
{getAvailableCreatePrograms(props.player).map((program) => {
|
||||
{getAvailableCreatePrograms(player).map((program) => {
|
||||
const create = program.create;
|
||||
if (create === null) return <></>;
|
||||
|
||||
return (
|
||||
<Tooltip title={create.tooltip}>
|
||||
<Button onClick={() => props.player.startCreateProgramWork(program.name, create.time, create.level)}>
|
||||
{program.name}
|
||||
<Tooltip key={program.name} title={create.tooltip}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
player.startCreateProgramWork(program.name, create.time, create.level);
|
||||
router.toWork();
|
||||
}}
|
||||
>
|
||||
{program.name}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
6
src/RedPill.d.ts
vendored
6
src/RedPill.d.ts
vendored
@ -1,6 +1,2 @@
|
||||
export declare let redPillFlag: boolean;
|
||||
export declare function hackWorldDaemon(
|
||||
currentNodeNumber: number,
|
||||
flume: boolean = false,
|
||||
quick: boolean = false,
|
||||
): void;
|
||||
export declare function enterBitNode(router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number);
|
||||
|
@ -1,7 +1,6 @@
|
||||
/**
|
||||
* Implementation for what happens when you destroy a BitNode
|
||||
*/
|
||||
import { Engine } from "./engine";
|
||||
import { Player } from "./Player";
|
||||
import { prestigeSourceFile } from "./Prestige";
|
||||
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
|
||||
@ -9,20 +8,10 @@ import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||
import { SourceFiles } from "./SourceFile/SourceFiles";
|
||||
|
||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
import { BitverseRoot } from "./BitNode/ui/BitverseRoot";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
let redPillFlag = false;
|
||||
function hackWorldDaemon(currentNodeNumber, flume = false, quick = false) {
|
||||
// Clear the screen
|
||||
const container = document.getElementById("red-pill-container");
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
Engine.loadRedPillContent();
|
||||
ReactDOM.render(
|
||||
<BitverseRoot destroyedBitNodeNum={currentNodeNumber} flume={flume} enter={enterBitNode} quick={quick} />,
|
||||
container,
|
||||
);
|
||||
function hackWorldDaemon(router, flume = false, quick = false) {
|
||||
router.toBitVerse(flume, quick);
|
||||
redPillFlag = true;
|
||||
}
|
||||
|
||||
@ -68,12 +57,12 @@ function giveSourceFile(bitNodeNumber) {
|
||||
Player.intelligence = 1;
|
||||
}
|
||||
dialogBoxCreate(
|
||||
"You received a Source-File for destroying a Bit Node!<br><br>" + sourceFile.name + "<br><br>" + sourceFile.info,
|
||||
"You received a Source-File for destroying a BitNode!<br><br>" + sourceFile.name + "<br><br>" + sourceFile.info,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function enterBitNode(flume, destroyedBitNode, newBitNode) {
|
||||
export function enterBitNode(router, flume, destroyedBitNode, newBitNode) {
|
||||
if (!flume) {
|
||||
giveSourceFile(destroyedBitNode);
|
||||
} else {
|
||||
@ -86,12 +75,14 @@ function enterBitNode(flume, destroyedBitNode, newBitNode) {
|
||||
Player.intelligence = 1;
|
||||
}
|
||||
redPillFlag = false;
|
||||
const container = document.getElementById("red-pill-container");
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
|
||||
// Set new Bit Node
|
||||
Player.bitNodeN = newBitNode;
|
||||
|
||||
if (newBitNode === 6) {
|
||||
router.toBladeburnerCinematic();
|
||||
} else {
|
||||
router.toTerminal();
|
||||
}
|
||||
prestigeSourceFile(flume);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
*/
|
||||
import { calculateRamUsage } from "./RamCalculations";
|
||||
import { ScriptUrl } from "./ScriptUrl";
|
||||
import { Page, routing } from "../ui/navigationTracking";
|
||||
|
||||
import { setTimeoutRef } from "../utils/SetTimeoutRef";
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
|
||||
@ -93,22 +92,18 @@ export class Script {
|
||||
* @param {Script[]} otherScripts - Other scripts on the server. Used to process imports
|
||||
*/
|
||||
saveScript(code: string, serverIp: string, otherScripts: Script[]): void {
|
||||
if (routing.isOn(Page.ScriptEditor)) {
|
||||
// Update code and filename
|
||||
this.code = code.replace(/^\s+|\s+$/g, "");
|
||||
// Update code and filename
|
||||
this.code = code.replace(/^\s+|\s+$/g, "");
|
||||
|
||||
const filenameElem: HTMLInputElement | null = document.getElementById(
|
||||
"script-editor-filename",
|
||||
) as HTMLInputElement;
|
||||
if (filenameElem == null) {
|
||||
console.error(`Failed to get Script filename DOM element`);
|
||||
return;
|
||||
}
|
||||
this.filename = filenameElem.value;
|
||||
this.server = serverIp;
|
||||
this.updateRamUsage(otherScripts);
|
||||
this.markUpdated();
|
||||
const filenameElem: HTMLInputElement | null = document.getElementById("script-editor-filename") as HTMLInputElement;
|
||||
if (filenameElem == null) {
|
||||
console.error(`Failed to get Script filename DOM element`);
|
||||
return;
|
||||
}
|
||||
this.filename = filenameElem.value;
|
||||
this.server = serverIp;
|
||||
this.updateRamUsage(otherScripts);
|
||||
this.markUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,7 @@ import { Options } from "./Options";
|
||||
import { js_beautify as beautifyCode } from "js-beautify";
|
||||
import { isValidFilePath } from "../../Terminal/DirectoryHelpers";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { parseFconfSettings } from "../../Fconf/Fconf";
|
||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
@ -53,7 +53,7 @@ interface IProps {
|
||||
filename: string;
|
||||
code: string;
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -103,7 +103,6 @@ export function Root(props: IProps): React.ReactElement {
|
||||
}
|
||||
lastPosition = null;
|
||||
|
||||
// TODO(hydroflame): re-enable the tutorial.
|
||||
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
||||
//Make sure filename + code properly follow tutorial
|
||||
if (filename !== "n00dles.script") {
|
||||
@ -121,7 +120,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(code, props.player.currentServer, server.scripts);
|
||||
props.engine.loadTerminalContent();
|
||||
props.router.toTerminal();
|
||||
return iTutorialNextStep();
|
||||
}
|
||||
}
|
||||
@ -160,7 +159,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(code, props.player.currentServer, server.scripts);
|
||||
props.engine.loadTerminalContent();
|
||||
props.router.toTerminal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -173,7 +172,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
if (server.textFiles[i].fn === filename) {
|
||||
server.textFiles[i].write(code);
|
||||
props.engine.loadTerminalContent();
|
||||
props.router.toTerminal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -183,7 +182,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
dialogBoxCreate("Invalid filename. Must be either a script (.script, .js, or .ns) or " + " or text file (.txt)");
|
||||
return;
|
||||
}
|
||||
props.engine.loadTerminalContent();
|
||||
props.router.toTerminal();
|
||||
}
|
||||
|
||||
function beautify(): void {
|
||||
@ -308,7 +307,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="script-editor-wrapper">
|
||||
<>
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag" className="noselect">
|
||||
{" "}
|
||||
@ -328,7 +327,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
beforeMount={beforeMount}
|
||||
onMount={onMount}
|
||||
loading={<p>Loading script editor!</p>}
|
||||
height="80%"
|
||||
height="90%"
|
||||
defaultLanguage="javascript"
|
||||
defaultValue={code}
|
||||
onChange={updateCode}
|
||||
@ -352,6 +351,6 @@ export function Root(props: IProps): React.ReactElement {
|
||||
Netscript Documentation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import clsx from "clsx";
|
||||
import { styled, useTheme, Theme, CSSObject } from "@mui/material/styles";
|
||||
import { styled, Theme, CSSObject } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import MuiDrawer from "@mui/material/Drawer";
|
||||
@ -15,8 +15,6 @@ import Typography from "@mui/material/Typography";
|
||||
import Collapse from "@mui/material/Collapse";
|
||||
import Badge from "@mui/material/Badge";
|
||||
|
||||
import { TTheme as BBTheme, colors } from "../../ui/React/Theme";
|
||||
|
||||
import ComputerIcon from "@mui/icons-material/Computer";
|
||||
import LastPageIcon from "@mui/icons-material/LastPage"; // Terminal
|
||||
import CreateIcon from "@mui/icons-material/Create"; // Create Script
|
||||
@ -44,7 +42,7 @@ import LiveHelpIcon from "@mui/icons-material/LiveHelp";
|
||||
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter, Page } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../../InteractiveTutorial";
|
||||
@ -56,9 +54,6 @@ import { inMission } from "../../Missions";
|
||||
import { cinematicTextFlag } from "../../CinematicText";
|
||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||
import { FconfSettings } from "../../Fconf/FconfSettings";
|
||||
import { Page, routing } from "../../ui/navigationTracking";
|
||||
|
||||
const drawerWidth = 240;
|
||||
|
||||
const openedMixin = (theme: Theme): CSSObject => ({
|
||||
width: theme.spacing(31),
|
||||
@ -83,7 +78,6 @@ const closedMixin = (theme: Theme): CSSObject => ({
|
||||
|
||||
const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== "open" })(({ theme, open }) => ({
|
||||
width: theme.spacing(31),
|
||||
flexShrink: 0,
|
||||
whiteSpace: "nowrap",
|
||||
boxSizing: "border-box",
|
||||
...(open && {
|
||||
@ -99,7 +93,7 @@ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== "open"
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
active: {
|
||||
borderLeft: "3px solid " + colors.primary,
|
||||
borderLeft: "3px solid " + theme.palette.primary.main,
|
||||
},
|
||||
listitem: {},
|
||||
}),
|
||||
@ -107,7 +101,8 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
page: Page;
|
||||
}
|
||||
|
||||
export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
@ -121,7 +116,6 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
const [activeTab, setActiveTab] = useState("Terminal");
|
||||
const [hackingOpen, setHackingOpen] = useState(true);
|
||||
const [characterOpen, setCharacterOpen] = useState(true);
|
||||
const [worldOpen, setWorldOpen] = useState(true);
|
||||
@ -173,108 +167,88 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
const canBladeburner = !!(props.player.bladeburner as any);
|
||||
|
||||
function clickTerminal(): void {
|
||||
setActiveTab("Terminal");
|
||||
props.engine.loadTerminalContent();
|
||||
props.router.toTerminal();
|
||||
if (flashTerminal) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickCreateScripts(): void {
|
||||
setActiveTab("CreateScripts");
|
||||
props.engine.loadScriptEditorContent();
|
||||
props.router.toScriptEditor();
|
||||
}
|
||||
|
||||
function clickStats(): void {
|
||||
setActiveTab("Stats");
|
||||
props.engine.loadCharacterContent();
|
||||
props.router.toCharacterInfo();
|
||||
if (flashStats) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickActiveScripts(): void {
|
||||
setActiveTab("ActiveScripts");
|
||||
props.engine.loadActiveScriptsContent();
|
||||
props.router.toActiveScripts();
|
||||
if (flashActiveScripts) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickCreateProgram(): void {
|
||||
setActiveTab("CreateProgram");
|
||||
props.engine.loadCreateProgramContent();
|
||||
props.router.toCreateProgram();
|
||||
}
|
||||
|
||||
function clickFactions(): void {
|
||||
setActiveTab("Factions");
|
||||
props.engine.loadFactionsContent();
|
||||
props.router.toFactions();
|
||||
}
|
||||
|
||||
function clickAugmentations(): void {
|
||||
setActiveTab("Augmentations");
|
||||
props.engine.loadAugmentationsContent();
|
||||
props.router.toAugmentations();
|
||||
}
|
||||
|
||||
function clickSleeves(): void {
|
||||
setActiveTab("Sleeves");
|
||||
props.engine.loadSleevesContent();
|
||||
props.router.toSleeves();
|
||||
}
|
||||
|
||||
function clickHacknet(): void {
|
||||
setActiveTab("Hacknet");
|
||||
props.engine.loadHacknetNodesContent();
|
||||
props.router.toHacknetNodes();
|
||||
if (flashHacknet) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickCity(): void {
|
||||
setActiveTab("City");
|
||||
props.engine.loadLocationContent();
|
||||
props.router.toCity();
|
||||
if (flashCity) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickTravel(): void {
|
||||
setActiveTab("Travel");
|
||||
props.engine.loadTravelContent();
|
||||
props.router.toTravel();
|
||||
}
|
||||
|
||||
function clickJob(): void {
|
||||
setActiveTab("Job");
|
||||
props.engine.loadJobContent();
|
||||
props.router.toJob();
|
||||
}
|
||||
|
||||
function clickStockMarket(): void {
|
||||
setActiveTab("StockMarket");
|
||||
props.engine.loadStockMarketContent();
|
||||
props.router.toStockMarket();
|
||||
}
|
||||
|
||||
function clickBladeburner(): void {
|
||||
setActiveTab("Bladeburner");
|
||||
props.engine.loadBladeburnerContent();
|
||||
props.router.toBladeburner();
|
||||
}
|
||||
|
||||
function clickCorp(): void {
|
||||
setActiveTab("Corp");
|
||||
props.engine.loadCorporationContent();
|
||||
props.router.toCorporation();
|
||||
}
|
||||
|
||||
function clickGang(): void {
|
||||
setActiveTab("Gang");
|
||||
props.engine.loadGangContent();
|
||||
props.router.toGang();
|
||||
}
|
||||
|
||||
function clickTutorial(): void {
|
||||
setActiveTab("Tutorial");
|
||||
props.engine.loadTutorialContent();
|
||||
props.router.toTutorial();
|
||||
if (flashTutorial) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickMilestones(): void {
|
||||
setActiveTab("Milestones");
|
||||
props.engine.loadMilestonesContent();
|
||||
props.router.toMilestones();
|
||||
}
|
||||
function clickOptions(): void {
|
||||
setActiveTab("Options");
|
||||
props.engine.loadGameOptionsContent();
|
||||
props.router.toGameOptions();
|
||||
}
|
||||
|
||||
function clickDev(): void {
|
||||
setActiveTab("Dev");
|
||||
props.engine.loadDevMenuContent();
|
||||
props.router.toDevMenu();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -324,7 +298,7 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
clickCreateProgram();
|
||||
} else if (event.keyCode === KEY.F && event.altKey) {
|
||||
// Overriden by Fconf
|
||||
if (routing.isOn(Page.Terminal) && FconfSettings.ENABLE_BASH_HOTKEYS) {
|
||||
if (props.page == Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
@ -356,421 +330,427 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
const [open, setOpen] = useState(true);
|
||||
const toggleDrawer = (): void => setOpen((old) => !old);
|
||||
return (
|
||||
<BBTheme>
|
||||
<Drawer open={open} anchor="left" variant="permanent">
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={toggleDrawer}>
|
||||
<Drawer open={open} anchor="left" variant="permanent">
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={toggleDrawer}>
|
||||
<ListItemIcon>
|
||||
{!open ? <ChevronRightIcon color={"primary"} /> : <ChevronLeftIcon color={"primary"} />}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">Bitburner v{CONSTANTS.Version}</Typography>} />
|
||||
</ListItem>
|
||||
<Divider />
|
||||
<List>
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={() => setHackingOpen((old) => !old)}>
|
||||
<ListItemIcon>
|
||||
{!open ? <ChevronRightIcon color={"primary"} /> : <ChevronLeftIcon color={"primary"} />}
|
||||
<ComputerIcon color={"primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">Bitburner v{CONSTANTS.Version}</Typography>} />
|
||||
<ListItemText primary={<Typography color="primary">Hacking</Typography>} />
|
||||
{hackingOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />}
|
||||
</ListItem>
|
||||
<Divider />
|
||||
<List>
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={() => setHackingOpen((old) => !old)}>
|
||||
<ListItemIcon>
|
||||
<ComputerIcon color={"primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">Hacking</Typography>} />
|
||||
{hackingOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />}
|
||||
</ListItem>
|
||||
<Collapse in={hackingOpen} timeout="auto" unmountOnExit>
|
||||
<List>
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Terminal"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Terminal",
|
||||
})}
|
||||
onClick={clickTerminal}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<LastPageIcon color={flashTerminal ? "error" : activeTab !== "Terminal" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={flashTerminal ? "error" : activeTab !== "Terminal" ? "secondary" : "primary"}>
|
||||
Terminal
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Create Scripts"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "CreateScripts",
|
||||
})}
|
||||
onClick={clickCreateScripts}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<CreateIcon color={activeTab !== "CreateScripts" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "CreateScripts" ? "secondary" : "primary"}>Create Script</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Active Scripts"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "ActiveScripts",
|
||||
})}
|
||||
onClick={clickActiveScripts}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<StorageIcon
|
||||
color={flashActiveScripts ? "error" : activeTab !== "ActiveScripts" ? "secondary" : "primary"}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
color={flashActiveScripts ? "error" : activeTab !== "ActiveScripts" ? "secondary" : "primary"}
|
||||
>
|
||||
Active Scripts
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{canCreateProgram && (
|
||||
<ListItem
|
||||
button
|
||||
key={"Create Program"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "CreateProgram",
|
||||
})}
|
||||
onClick={clickCreateProgram}
|
||||
<Collapse in={hackingOpen} timeout="auto" unmountOnExit>
|
||||
<List>
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Terminal"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Terminal,
|
||||
})}
|
||||
onClick={clickTerminal}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<LastPageIcon
|
||||
color={flashTerminal ? "error" : props.page !== Page.Terminal ? "secondary" : "primary"}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={flashTerminal ? "error" : props.page !== Page.Terminal ? "secondary" : "primary"}>
|
||||
Terminal
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Create Scripts"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.CreateScript,
|
||||
})}
|
||||
onClick={clickCreateScripts}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<CreateIcon color={props.page !== Page.CreateScript ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={props.page !== Page.CreateScript ? "secondary" : "primary"}>
|
||||
Create Script
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Active Scripts"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.ActiveScripts,
|
||||
})}
|
||||
onClick={clickActiveScripts}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<StorageIcon
|
||||
color={flashActiveScripts ? "error" : props.page !== Page.ActiveScripts ? "secondary" : "primary"}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
color={flashActiveScripts ? "error" : props.page !== Page.ActiveScripts ? "secondary" : "primary"}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Badge badgeContent={programCount > 0 ? programCount : undefined} color="error">
|
||||
<BugReportIcon color={activeTab !== "CreateProgram" ? "secondary" : "primary"} />
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "CreateProgram" ? "secondary" : "primary"}>
|
||||
Create Program
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
</List>
|
||||
</Collapse>
|
||||
|
||||
<Divider />
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={() => setCharacterOpen((old) => !old)}>
|
||||
<ListItemIcon>
|
||||
<AccountBoxIcon color={"primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">Character</Typography>} />
|
||||
{characterOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />}
|
||||
</ListItem>
|
||||
<Collapse in={characterOpen} timeout="auto" unmountOnExit>
|
||||
<ListItem
|
||||
button
|
||||
key={"Stats"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Stats",
|
||||
})}
|
||||
onClick={clickStats}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<EqualizerIcon color={flashStats ? "error" : activeTab !== "Stats" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={flashStats ? "error" : activeTab !== "Stats" ? "secondary" : "primary"}>
|
||||
Stats
|
||||
Active Scripts
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{canOpenFactions && (
|
||||
{canCreateProgram && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Factions"}
|
||||
key={"Create Program"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Factions",
|
||||
[classes.active]: props.page === Page.CreateProgram,
|
||||
})}
|
||||
onClick={clickFactions}
|
||||
onClick={clickCreateProgram}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Badge badgeContent={invitationsCount !== 0 ? invitationsCount : undefined} color="error">
|
||||
<ContactsIcon color={activeTab !== "Factions" ? "secondary" : "primary"} />
|
||||
<Badge badgeContent={programCount > 0 ? programCount : undefined} color="error">
|
||||
<BugReportIcon color={props.page !== Page.CreateProgram ? "secondary" : "primary"} />
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Factions" ? "secondary" : "primary"}>Factions</Typography>
|
||||
<Typography color={props.page !== Page.CreateProgram ? "secondary" : "primary"}>
|
||||
Create Program
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canOpenAugmentations && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Augmentations"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Augmentations",
|
||||
})}
|
||||
onClick={clickAugmentations}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Badge badgeContent={augmentationCount !== 0 ? augmentationCount : undefined} color="error">
|
||||
<DoubleArrowIcon
|
||||
style={{ transform: "rotate(-90deg)" }}
|
||||
color={activeTab !== "Augmentations" ? "secondary" : "primary"}
|
||||
/>
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Augmentations" ? "secondary" : "primary"}>Augmentations</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
<ListItem
|
||||
button
|
||||
key={"Hacknet"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Hacknet",
|
||||
})}
|
||||
onClick={clickHacknet}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<AccountTreeIcon color={flashHacknet ? "error" : activeTab !== "Hacknet" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={flashHacknet ? "error" : activeTab !== "Hacknet" ? "secondary" : "primary"}>
|
||||
Hacknet
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{canOpenSleeves && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Sleeves"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Sleeves",
|
||||
})}
|
||||
onClick={clickSleeves}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<PeopleAltIcon color={activeTab !== "Sleeves" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Sleeves" ? "secondary" : "primary"}>Sleeves</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
</Collapse>
|
||||
</List>
|
||||
</Collapse>
|
||||
|
||||
<Divider />
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={() => setWorldOpen((old) => !old)}>
|
||||
<Divider />
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={() => setCharacterOpen((old) => !old)}>
|
||||
<ListItemIcon>
|
||||
<AccountBoxIcon color={"primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">Character</Typography>} />
|
||||
{characterOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />}
|
||||
</ListItem>
|
||||
<Collapse in={characterOpen} timeout="auto" unmountOnExit>
|
||||
<ListItem
|
||||
button
|
||||
key={"Stats"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Stats,
|
||||
})}
|
||||
onClick={clickStats}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<PublicIcon color={"primary"} />
|
||||
<EqualizerIcon color={flashStats ? "error" : props.page !== Page.Stats ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">World</Typography>} />
|
||||
{worldOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />}
|
||||
<ListItemText>
|
||||
<Typography color={flashStats ? "error" : props.page !== Page.Stats ? "secondary" : "primary"}>
|
||||
Stats
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<Collapse in={worldOpen} timeout="auto" unmountOnExit>
|
||||
{canOpenFactions && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"City"}
|
||||
key={"Factions"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "City",
|
||||
[classes.active]: [Page.Factions, Page.Faction].includes(props.page),
|
||||
})}
|
||||
onClick={clickCity}
|
||||
onClick={clickFactions}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<LocationCityIcon color={flashCity ? "error" : activeTab !== "City" ? "secondary" : "primary"} />
|
||||
<Badge badgeContent={invitationsCount !== 0 ? invitationsCount : undefined} color="error">
|
||||
<ContactsIcon color={![Page.Factions, Page.Faction].includes(props.page) ? "secondary" : "primary"} />
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={flashCity ? "error" : activeTab !== "City" ? "secondary" : "primary"}>
|
||||
City
|
||||
<Typography color={![Page.Factions, Page.Faction].includes(props.page) ? "secondary" : "primary"}>
|
||||
Factions
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canOpenAugmentations && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Travel"}
|
||||
key={"Augmentations"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Travel",
|
||||
[classes.active]: props.page === Page.Augmentations,
|
||||
})}
|
||||
onClick={clickTravel}
|
||||
onClick={clickAugmentations}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<AirplanemodeActiveIcon color={activeTab !== "Travel" ? "secondary" : "primary"} />
|
||||
<Badge badgeContent={augmentationCount !== 0 ? augmentationCount : undefined} color="error">
|
||||
<DoubleArrowIcon
|
||||
style={{ transform: "rotate(-90deg)" }}
|
||||
color={props.page !== Page.Augmentations ? "secondary" : "primary"}
|
||||
/>
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Travel" ? "secondary" : "primary"}>Travel</Typography>
|
||||
<Typography color={props.page !== Page.Augmentations ? "secondary" : "primary"}>
|
||||
Augmentations
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{canJob && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Job"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Job",
|
||||
})}
|
||||
onClick={clickJob}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<WorkIcon color={activeTab !== "Job" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Job" ? "secondary" : "primary"}>Job</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canStockMarket && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Stock Market"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "StockMarket",
|
||||
})}
|
||||
onClick={clickStockMarket}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<TrendingUpIcon color={activeTab !== "StockMarket" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "StockMarket" ? "secondary" : "primary"}>Stock Market</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canBladeburner && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Bladeburner"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Bladeburner",
|
||||
})}
|
||||
onClick={clickBladeburner}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<FormatBoldIcon color={activeTab !== "Bladeburner" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Bladeburner" ? "secondary" : "primary"}>Bladeburner</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canCorporation && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Corp"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Corp",
|
||||
})}
|
||||
onClick={clickCorp}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<BusinessIcon color={activeTab !== "Corp" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Corp" ? "secondary" : "primary"}>Corp</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canGang && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Gang"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Gang",
|
||||
})}
|
||||
onClick={clickGang}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<SportsMmaIcon color={activeTab !== "Gang" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Gang" ? "secondary" : "primary"}>Gang</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
</Collapse>
|
||||
)}
|
||||
<ListItem
|
||||
button
|
||||
key={"Hacknet"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Hacknet,
|
||||
})}
|
||||
onClick={clickHacknet}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<AccountTreeIcon color={flashHacknet ? "error" : props.page !== Page.Hacknet ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={flashHacknet ? "error" : props.page !== Page.Hacknet ? "secondary" : "primary"}>
|
||||
Hacknet
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{canOpenSleeves && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Sleeves"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Sleeves,
|
||||
})}
|
||||
onClick={clickSleeves}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<PeopleAltIcon color={props.page !== Page.Sleeves ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={props.page !== Page.Sleeves ? "secondary" : "primary"}>Sleeves</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
</Collapse>
|
||||
|
||||
<Divider />
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={() => setHelpOpen((old) => !old)}>
|
||||
<Divider />
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={() => setWorldOpen((old) => !old)}>
|
||||
<ListItemIcon>
|
||||
<PublicIcon color={"primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">World</Typography>} />
|
||||
{worldOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />}
|
||||
</ListItem>
|
||||
<Collapse in={worldOpen} timeout="auto" unmountOnExit>
|
||||
<ListItem
|
||||
button
|
||||
key={"City"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.City,
|
||||
})}
|
||||
onClick={clickCity}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<LiveHelpIcon color={"primary"} />
|
||||
<LocationCityIcon color={flashCity ? "error" : props.page !== Page.City ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">Help</Typography>} />
|
||||
{helpOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />}
|
||||
<ListItemText>
|
||||
<Typography color={flashCity ? "error" : props.page !== Page.City ? "secondary" : "primary"}>
|
||||
City
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<Collapse in={helpOpen} timeout="auto" unmountOnExit>
|
||||
<ListItem
|
||||
button
|
||||
key={"Travel"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Travel,
|
||||
})}
|
||||
onClick={clickTravel}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<AirplanemodeActiveIcon color={props.page !== Page.Travel ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={props.page !== Page.Travel ? "secondary" : "primary"}>Travel</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{canJob && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Milestones"}
|
||||
key={"Job"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Milestones",
|
||||
[classes.active]: props.page === Page.Job,
|
||||
})}
|
||||
onClick={clickMilestones}
|
||||
onClick={clickJob}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<CheckIcon color={activeTab !== "Milestones" ? "secondary" : "primary"} />
|
||||
<WorkIcon color={props.page !== Page.Job ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Milestones" ? "secondary" : "primary"}>Milestones</Typography>
|
||||
<Typography color={props.page !== Page.Job ? "secondary" : "primary"}>Job</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canStockMarket && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Tutorial"}
|
||||
key={"Stock Market"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Tutorial",
|
||||
[classes.active]: props.page === Page.StockMarket,
|
||||
})}
|
||||
onClick={clickTutorial}
|
||||
onClick={clickStockMarket}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<HelpIcon color={flashTutorial ? "error" : activeTab !== "Tutorial" ? "secondary" : "primary"} />
|
||||
<TrendingUpIcon color={props.page !== Page.StockMarket ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={flashTutorial ? "error" : activeTab !== "Tutorial" ? "secondary" : "primary"}>
|
||||
Tutorial
|
||||
</Typography>
|
||||
<Typography color={props.page !== Page.StockMarket ? "secondary" : "primary"}>Stock Market</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canBladeburner && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Options"}
|
||||
key={"Bladeburner"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Options",
|
||||
[classes.active]: props.page === Page.Bladeburner,
|
||||
})}
|
||||
onClick={clickOptions}
|
||||
onClick={clickBladeburner}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<SettingsIcon color={activeTab !== "Options" ? "secondary" : "primary"} />
|
||||
<FormatBoldIcon color={props.page !== Page.Bladeburner ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Options" ? "secondary" : "primary"}>Options</Typography>
|
||||
<Typography color={props.page !== Page.Bladeburner ? "secondary" : "primary"}>Bladeburner</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{process.env.NODE_ENV === "development" && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Dev"}
|
||||
className={clsx({
|
||||
[classes.active]: activeTab === "Dev",
|
||||
})}
|
||||
onClick={clickDev}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<DeveloperBoardIcon color={activeTab !== "Dev" ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={activeTab !== "Dev" ? "secondary" : "primary"}>Dev</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
</Collapse>
|
||||
</List>
|
||||
</Drawer>
|
||||
</BBTheme>
|
||||
)}
|
||||
{canCorporation && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Corp"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Corporation,
|
||||
})}
|
||||
onClick={clickCorp}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<BusinessIcon color={props.page !== Page.Corporation ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={props.page !== Page.Corporation ? "secondary" : "primary"}>Corp</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
{canGang && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Gang"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Gang,
|
||||
})}
|
||||
onClick={clickGang}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<SportsMmaIcon color={props.page !== Page.Gang ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={props.page !== Page.Gang ? "secondary" : "primary"}>Gang</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
</Collapse>
|
||||
|
||||
<Divider />
|
||||
<ListItem classes={{ root: classes.listitem }} button onClick={() => setHelpOpen((old) => !old)}>
|
||||
<ListItemIcon>
|
||||
<LiveHelpIcon color={"primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography color="primary">Help</Typography>} />
|
||||
{helpOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />}
|
||||
</ListItem>
|
||||
<Collapse in={helpOpen} timeout="auto" unmountOnExit>
|
||||
<ListItem
|
||||
button
|
||||
key={"Milestones"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Milestones,
|
||||
})}
|
||||
onClick={clickMilestones}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<CheckIcon color={props.page !== Page.Milestones ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={props.page !== Page.Milestones ? "secondary" : "primary"}>Milestones</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
button
|
||||
key={"Tutorial"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Tutorial,
|
||||
})}
|
||||
onClick={clickTutorial}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<HelpIcon color={flashTutorial ? "error" : props.page !== Page.Tutorial ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={flashTutorial ? "error" : props.page !== Page.Tutorial ? "secondary" : "primary"}>
|
||||
Tutorial
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
button
|
||||
key={"Options"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.Options,
|
||||
})}
|
||||
onClick={clickOptions}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<SettingsIcon color={props.page !== Page.Options ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={props.page !== Page.Options ? "secondary" : "primary"}>Options</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
{process.env.NODE_ENV === "development" && (
|
||||
<ListItem
|
||||
classes={{ root: classes.listitem }}
|
||||
button
|
||||
key={"Dev"}
|
||||
className={clsx({
|
||||
[classes.active]: props.page === Page.DevMenu,
|
||||
})}
|
||||
onClick={clickDev}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<DeveloperBoardIcon color={props.page !== Page.DevMenu ? "secondary" : "primary"} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
<Typography color={props.page !== Page.DevMenu ? "secondary" : "primary"}>Dev</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
)}
|
||||
</Collapse>
|
||||
</List>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import * as React from "react";
|
||||
|
||||
export interface IProcessOrderRefs {
|
||||
rerenderFn: () => void;
|
||||
stockMarket: IStockMarket;
|
||||
symbolToStockMap: IMap<Stock>;
|
||||
}
|
||||
@ -116,7 +115,6 @@ function executeOrder(order: Order, refs: IProcessOrderRefs): void {
|
||||
// When orders are executed, the buying and selling functions shouldn't
|
||||
// emit popup dialog boxes. This options object configures the functions for that
|
||||
const opts = {
|
||||
rerenderFn: refs.rerenderFn,
|
||||
suppressDialog: true,
|
||||
};
|
||||
|
||||
@ -158,7 +156,6 @@ function executeOrder(order: Order, refs: IProcessOrderRefs): void {
|
||||
{numeralWrapper.formatShares(Math.round(order.shares))} shares)
|
||||
</>,
|
||||
);
|
||||
refs.rerenderFn();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { buyStock, sellStock, shortStock, sellShort } from "./BuyingAndSelling";
|
||||
import { IOrderBook } from "./IOrderBook";
|
||||
import { IStockMarket } from "./IStockMarket";
|
||||
import { Order } from "./Order";
|
||||
@ -9,24 +8,23 @@ import { InitStockMetadata } from "./data/InitStockMetadata";
|
||||
import { OrderTypes } from "./data/OrderTypes";
|
||||
import { PositionTypes } from "./data/PositionTypes";
|
||||
import { StockSymbols } from "./data/StockSymbols";
|
||||
import { StockMarketRoot } from "./ui/Root";
|
||||
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { Player } from "../Player";
|
||||
import { IMap } from "../types";
|
||||
import { EventEmitter } from "../utils/EventEmitter";
|
||||
|
||||
import { Page, routing } from ".././ui/navigationTracking";
|
||||
import { numeralWrapper } from ".././ui/numeralFormat";
|
||||
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import { Reviver } from "../../utils/JSONReviver";
|
||||
|
||||
import * as React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
|
||||
export let StockMarket: IStockMarket | IMap<any> = {}; // Maps full stock name -> Stock object
|
||||
export let StockMarket: IStockMarket = {
|
||||
lastUpdate: 0,
|
||||
Orders: {},
|
||||
storedCycles: 0,
|
||||
ticksUntilCycle: 0,
|
||||
} as IStockMarket; // Maps full stock name -> Stock object
|
||||
export const SymbolToStockMap: IMap<Stock> = {}; // Maps symbol -> Stock object
|
||||
|
||||
export function placeOrder(
|
||||
@ -70,12 +68,10 @@ export function placeOrder(
|
||||
|
||||
// Process to see if it should be executed immediately
|
||||
const processOrderRefs = {
|
||||
rerenderFn: displayStockMarketContent,
|
||||
stockMarket: StockMarket as IStockMarket,
|
||||
symbolToStockMap: SymbolToStockMap,
|
||||
};
|
||||
processOrders(stock, order.type, order.pos, processOrderRefs);
|
||||
displayStockMarketContent();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -100,7 +96,6 @@ export function cancelOrder(params: ICancelOrderParams, workerScript: WorkerScri
|
||||
for (let i = 0; i < stockOrders.length; ++i) {
|
||||
if (order == stockOrders[i]) {
|
||||
stockOrders.splice(i, 1);
|
||||
displayStockMarketContent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -125,7 +120,6 @@ export function cancelOrder(params: ICancelOrderParams, workerScript: WorkerScri
|
||||
params.pos === order.pos
|
||||
) {
|
||||
stockOrders.splice(i, 1);
|
||||
displayStockMarketContent();
|
||||
if (workerScript) {
|
||||
workerScript.scriptRef.log("Successfully cancelled order: " + orderTxt);
|
||||
}
|
||||
@ -142,14 +136,24 @@ export function cancelOrder(params: ICancelOrderParams, workerScript: WorkerScri
|
||||
|
||||
export function loadStockMarket(saveString: string): void {
|
||||
if (saveString === "") {
|
||||
StockMarket = {};
|
||||
StockMarket = {
|
||||
lastUpdate: 0,
|
||||
Orders: {},
|
||||
storedCycles: 0,
|
||||
ticksUntilCycle: 0,
|
||||
} as IStockMarket;
|
||||
} else {
|
||||
StockMarket = JSON.parse(saveString, Reviver);
|
||||
}
|
||||
}
|
||||
|
||||
export function deleteStockMarket(): void {
|
||||
StockMarket = {};
|
||||
StockMarket = {
|
||||
lastUpdate: 0,
|
||||
Orders: {},
|
||||
storedCycles: 0,
|
||||
ticksUntilCycle: 0,
|
||||
} as IStockMarket;
|
||||
}
|
||||
|
||||
export function initStockMarket(): void {
|
||||
@ -269,8 +273,7 @@ export function processStockPrices(numCycles = 1): void {
|
||||
|
||||
const c = Math.random();
|
||||
const processOrderRefs = {
|
||||
rerenderFn: displayStockMarketContent,
|
||||
stockMarket: StockMarket as IStockMarket,
|
||||
stockMarket: StockMarket,
|
||||
symbolToStockMap: SymbolToStockMap,
|
||||
};
|
||||
if (c < chc) {
|
||||
@ -301,48 +304,11 @@ export function processStockPrices(numCycles = 1): void {
|
||||
// Shares required for price movement gradually approaches max over time
|
||||
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovement + 10, stock.shareTxForMovement);
|
||||
}
|
||||
|
||||
displayStockMarketContent();
|
||||
}
|
||||
|
||||
let stockMarketContainer: HTMLElement | null = null;
|
||||
function setStockMarketContainer(): void {
|
||||
stockMarketContainer = document.getElementById("generic-react-container");
|
||||
document.removeEventListener("DOMContentLoaded", setStockMarketContainer);
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", setStockMarketContainer);
|
||||
|
||||
function initStockMarketFnForReact(): void {
|
||||
export function initStockMarketFnForReact(): void {
|
||||
initStockMarket();
|
||||
initSymbolToStockMap();
|
||||
}
|
||||
|
||||
const eventEmitterForUiReset = new EventEmitter();
|
||||
|
||||
export function displayStockMarketContent(): void {
|
||||
if (!routing.isOn(Page.StockMarket)) {
|
||||
return;
|
||||
}
|
||||
|
||||
eventEmitterForUiReset.emitEvent();
|
||||
|
||||
if (stockMarketContainer instanceof HTMLElement) {
|
||||
const castedStockMarket = StockMarket as IStockMarket;
|
||||
ReactDOM.render(
|
||||
<StockMarketRoot
|
||||
buyStockLong={buyStock}
|
||||
buyStockShort={shortStock}
|
||||
cancelOrder={cancelOrder}
|
||||
eventEmitterForReset={eventEmitterForUiReset}
|
||||
initStockMarket={initStockMarketFnForReact}
|
||||
p={Player}
|
||||
placeOrder={placeOrder}
|
||||
sellStockLong={sellStock}
|
||||
sellStockShort={sellShort}
|
||||
stockMarket={castedStockMarket}
|
||||
/>,
|
||||
stockMarketContainer,
|
||||
);
|
||||
}
|
||||
}
|
||||
export const eventEmitterForUiReset = new EventEmitter();
|
||||
|
@ -1,82 +0,0 @@
|
||||
/**
|
||||
* Root React component for the Stock Market UI
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
import { InfoAndPurchases } from "./InfoAndPurchases";
|
||||
import { StockTickers } from "./StockTickers";
|
||||
|
||||
import { IStockMarket } from "../IStockMarket";
|
||||
import { Stock } from "../Stock";
|
||||
import { OrderTypes } from "../data/OrderTypes";
|
||||
import { PositionTypes } from "../data/PositionTypes";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { EventEmitter } from "../../utils/EventEmitter";
|
||||
|
||||
type txFn = (stock: Stock, shares: number) => boolean;
|
||||
export type placeOrderFn = (
|
||||
stock: Stock,
|
||||
shares: number,
|
||||
price: number,
|
||||
ordType: OrderTypes,
|
||||
posType: PositionTypes,
|
||||
) => boolean;
|
||||
|
||||
type IProps = {
|
||||
buyStockLong: txFn;
|
||||
buyStockShort: txFn;
|
||||
cancelOrder: (params: any) => void;
|
||||
eventEmitterForReset?: EventEmitter;
|
||||
initStockMarket: () => void;
|
||||
p: IPlayer;
|
||||
placeOrder: placeOrderFn;
|
||||
sellStockLong: txFn;
|
||||
sellStockShort: txFn;
|
||||
stockMarket: IStockMarket;
|
||||
};
|
||||
|
||||
type IState = {
|
||||
rerenderFlag: boolean;
|
||||
};
|
||||
|
||||
export class StockMarketRoot extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
rerenderFlag: false,
|
||||
};
|
||||
|
||||
this.rerender = this.rerender.bind(this);
|
||||
}
|
||||
|
||||
rerender(): void {
|
||||
this.setState((prevState) => {
|
||||
return {
|
||||
rerenderFlag: !prevState.rerenderFlag,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<div className="stock-market-container">
|
||||
<InfoAndPurchases initStockMarket={this.props.initStockMarket} p={this.props.p} rerender={this.rerender} />
|
||||
{this.props.p.hasWseAccount && (
|
||||
<StockTickers
|
||||
buyStockLong={this.props.buyStockLong}
|
||||
buyStockShort={this.props.buyStockShort}
|
||||
cancelOrder={this.props.cancelOrder}
|
||||
eventEmitterForReset={this.props.eventEmitterForReset}
|
||||
p={this.props.p}
|
||||
placeOrder={this.props.placeOrder}
|
||||
sellStockLong={this.props.sellStockLong}
|
||||
sellStockShort={this.props.sellStockShort}
|
||||
stockMarket={this.props.stockMarket}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
67
src/StockMarket/ui/StockMarketRoot.tsx
Normal file
67
src/StockMarket/ui/StockMarketRoot.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Root React component for the Stock Market UI
|
||||
*/
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { InfoAndPurchases } from "./InfoAndPurchases";
|
||||
import { StockTickers } from "./StockTickers";
|
||||
|
||||
import { IStockMarket } from "../IStockMarket";
|
||||
import { Stock } from "../Stock";
|
||||
import { OrderTypes } from "../data/OrderTypes";
|
||||
import { PositionTypes } from "../data/PositionTypes";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { EventEmitter } from "../../utils/EventEmitter";
|
||||
|
||||
type txFn = (stock: Stock, shares: number) => boolean;
|
||||
export type placeOrderFn = (
|
||||
stock: Stock,
|
||||
shares: number,
|
||||
price: number,
|
||||
ordType: OrderTypes,
|
||||
posType: PositionTypes,
|
||||
) => boolean;
|
||||
|
||||
type IProps = {
|
||||
buyStockLong: txFn;
|
||||
buyStockShort: txFn;
|
||||
cancelOrder: (params: any) => void;
|
||||
eventEmitterForReset?: EventEmitter;
|
||||
initStockMarket: () => void;
|
||||
p: IPlayer;
|
||||
placeOrder: placeOrderFn;
|
||||
sellStockLong: txFn;
|
||||
sellStockShort: txFn;
|
||||
stockMarket: IStockMarket;
|
||||
};
|
||||
|
||||
export function StockMarketRoot(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 200);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
return (
|
||||
<div className="stock-market-container">
|
||||
<InfoAndPurchases initStockMarket={props.initStockMarket} p={props.p} rerender={rerender} />
|
||||
{props.p.hasWseAccount && (
|
||||
<StockTickers
|
||||
buyStockLong={props.buyStockLong}
|
||||
buyStockShort={props.buyStockShort}
|
||||
cancelOrder={props.cancelOrder}
|
||||
eventEmitterForReset={props.eventEmitterForReset}
|
||||
p={props.p}
|
||||
placeOrder={props.placeOrder}
|
||||
sellStockLong={props.sellStockLong}
|
||||
sellStockShort={props.sellStockShort}
|
||||
stockMarket={props.stockMarket}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { TextFile } from "../TextFile";
|
||||
import { Script } from "../Script/Script";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../IEngine";
|
||||
import { IRouter } from "../ui/Router";
|
||||
|
||||
export class Output {
|
||||
text: string;
|
||||
@ -56,10 +56,10 @@ export interface ITerminal {
|
||||
startAnalyze(): void;
|
||||
startBackdoor(player: IPlayer): void;
|
||||
startHack(player: IPlayer): void;
|
||||
finishHack(player: IPlayer, cancelled?: boolean): void;
|
||||
finishBackdoor(player: IPlayer, cancelled?: boolean): void;
|
||||
finishHack(router: IRouter, player: IPlayer, cancelled?: boolean): void;
|
||||
finishBackdoor(router: IRouter, player: IPlayer, cancelled?: boolean): void;
|
||||
finishAnalyze(player: IPlayer, cancelled?: boolean): void;
|
||||
finishAction(player: IPlayer, cancelled?: boolean): void;
|
||||
finishAction(router: IRouter, player: IPlayer, cancelled?: boolean): void;
|
||||
getFilepath(filename: string): string;
|
||||
getFile(player: IPlayer, filename: string): Script | TextFile | string | null;
|
||||
getScript(player: IPlayer, filename: string): Script | null;
|
||||
@ -70,11 +70,11 @@ export interface ITerminal {
|
||||
runContract(player: IPlayer, name: string): void;
|
||||
executeScanAnalyzeCommand(player: IPlayer, depth?: number, all?: boolean): void;
|
||||
connectToServer(player: IPlayer, server: string): void;
|
||||
executeCommand(engine: IEngine, player: IPlayer, command: string): void;
|
||||
executeCommands(engine: IEngine, player: IPlayer, commands: string): void;
|
||||
executeCommand(router: IRouter, player: IPlayer, command: string): void;
|
||||
executeCommands(router: IRouter, player: IPlayer, commands: string): void;
|
||||
// If there was any changes, will return true, once.
|
||||
pollChanges(): boolean;
|
||||
process(player: IPlayer, cycles: number): void;
|
||||
process(router: IRouter, player: IPlayer, cycles: number): void;
|
||||
prestige(): void;
|
||||
getProgressText(): string;
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { ITerminal, Output, Link, TTimer } from "./ITerminal";
|
||||
import { IEngine } from "../IEngine";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||
import { BaseServer } from "../Server/BaseServer";
|
||||
import { hackWorldDaemon } from "../RedPill";
|
||||
import { Programs } from "../Programs/Programs";
|
||||
import { CodingContractResult } from "../CodingContracts";
|
||||
|
||||
@ -86,11 +85,11 @@ export class Terminal implements ITerminal {
|
||||
// Excludes the trailing forward slash
|
||||
currDir = "/";
|
||||
|
||||
process(player: IPlayer, cycles: number): void {
|
||||
process(router: IRouter, player: IPlayer, cycles: number): void {
|
||||
if (this.action === null) return;
|
||||
this.action.timeLeft -= (CONSTANTS._idleSpeed * cycles) / 1000;
|
||||
this.hasChanges = true;
|
||||
if (this.action.timeLeft < 0) this.finishAction(player, false);
|
||||
if (this.action.timeLeft < 0) this.finishAction(router, player, false);
|
||||
}
|
||||
|
||||
pollChanges(): boolean {
|
||||
@ -138,7 +137,7 @@ export class Terminal implements ITerminal {
|
||||
}
|
||||
|
||||
// Complete the hack/analyze command
|
||||
finishHack(player: IPlayer, cancelled = false): void {
|
||||
finishHack(router: IRouter, player: IPlayer, cancelled = false): void {
|
||||
if (cancelled) return;
|
||||
const server = player.getCurrentServer();
|
||||
|
||||
@ -156,7 +155,7 @@ export class Terminal implements ITerminal {
|
||||
if (player.bitNodeN == null) {
|
||||
player.bitNodeN = 1;
|
||||
}
|
||||
hackWorldDaemon(player.bitNodeN);
|
||||
router.toBitVerse(false, false);
|
||||
return;
|
||||
}
|
||||
server.backdoorInstalled = true;
|
||||
@ -190,7 +189,7 @@ export class Terminal implements ITerminal {
|
||||
}
|
||||
}
|
||||
|
||||
finishBackdoor(player: IPlayer, cancelled = false): void {
|
||||
finishBackdoor(router: IRouter, player: IPlayer, cancelled = false): void {
|
||||
if (!cancelled) {
|
||||
const server = player.getCurrentServer();
|
||||
if (
|
||||
@ -200,7 +199,7 @@ export class Terminal implements ITerminal {
|
||||
if (player.bitNodeN == null) {
|
||||
player.bitNodeN = 1;
|
||||
}
|
||||
hackWorldDaemon(player.bitNodeN);
|
||||
router.toBitVerse(false, false);
|
||||
return;
|
||||
}
|
||||
server.backdoorInstalled = true;
|
||||
@ -238,16 +237,16 @@ export class Terminal implements ITerminal {
|
||||
}
|
||||
}
|
||||
|
||||
finishAction(player: IPlayer, cancelled = false): void {
|
||||
finishAction(router: IRouter, player: IPlayer, cancelled = false): void {
|
||||
if (this.action === null) {
|
||||
if (!cancelled) throw new Error("Finish action called when there was no action");
|
||||
return;
|
||||
}
|
||||
this.print(this.getProgressText());
|
||||
if (this.action.action === "h") {
|
||||
this.finishHack(player, cancelled);
|
||||
this.finishHack(router, player, cancelled);
|
||||
} else if (this.action.action === "b") {
|
||||
this.finishBackdoor(player, cancelled);
|
||||
this.finishBackdoor(router, player, cancelled);
|
||||
} else if (this.action.action === "a") {
|
||||
this.finishAnalyze(player, cancelled);
|
||||
}
|
||||
@ -468,7 +467,7 @@ export class Terminal implements ITerminal {
|
||||
}
|
||||
}
|
||||
|
||||
executeCommands(engine: IEngine, player: IPlayer, commands: string): void {
|
||||
executeCommands(router: IRouter, player: IPlayer, commands: string): void {
|
||||
// Sanitize input
|
||||
commands = commands.trim();
|
||||
commands = commands.replace(/\s\s+/g, " "); // Replace all extra whitespace in command with a single space
|
||||
@ -484,7 +483,7 @@ export class Terminal implements ITerminal {
|
||||
const allCommands = ParseCommands(commands);
|
||||
|
||||
for (let i = 0; i < allCommands.length; i++) {
|
||||
this.executeCommand(engine, player, allCommands[i]);
|
||||
this.executeCommand(router, player, allCommands[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,7 +498,7 @@ export class Terminal implements ITerminal {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
executeCommand(engine: IEngine, player: IPlayer, command: string): void {
|
||||
executeCommand(router: IRouter, player: IPlayer, command: string): void {
|
||||
if (this.action !== null) {
|
||||
this.error(`Cannot execute command (${command}) while an action is in progress`);
|
||||
return;
|
||||
@ -532,7 +531,7 @@ export class Terminal implements ITerminal {
|
||||
break;
|
||||
case iTutorialSteps.TerminalLs:
|
||||
if (commandArray.length === 1 && commandArray[0] == "ls") {
|
||||
ls(this, engine, player, s, commandArray.slice(1));
|
||||
ls(this, router, player, s, commandArray.slice(1));
|
||||
iTutorialNextStep();
|
||||
} else {
|
||||
this.print("Bad command. Please follow the tutorial");
|
||||
@ -540,7 +539,7 @@ export class Terminal implements ITerminal {
|
||||
break;
|
||||
case iTutorialSteps.TerminalScan:
|
||||
if (commandArray.length === 1 && commandArray[0] == "scan") {
|
||||
scan(this, engine, player, s, commandArray.slice(1));
|
||||
scan(this, router, player, s, commandArray.slice(1));
|
||||
iTutorialNextStep();
|
||||
} else {
|
||||
this.print("Bad command. Please follow the tutorial");
|
||||
@ -609,7 +608,7 @@ export class Terminal implements ITerminal {
|
||||
break;
|
||||
case iTutorialSteps.TerminalCreateScript:
|
||||
if (commandArray.length == 2 && commandArray[0] == "nano" && commandArray[1] == "n00dles.script") {
|
||||
engine.loadScriptEditorContent("n00dles.script", "");
|
||||
router.toScriptEditor("n00dles.script", "");
|
||||
iTutorialNextStep();
|
||||
} else {
|
||||
this.print("Bad command. Please follow the tutorial");
|
||||
@ -617,7 +616,7 @@ export class Terminal implements ITerminal {
|
||||
break;
|
||||
case iTutorialSteps.TerminalFree:
|
||||
if (commandArray.length == 1 && commandArray[0] == "free") {
|
||||
free(this, engine, player, s, commandArray.slice(1));
|
||||
free(this, router, player, s, commandArray.slice(1));
|
||||
iTutorialNextStep();
|
||||
} else {
|
||||
this.print("Bad command. Please follow the tutorial");
|
||||
@ -625,7 +624,7 @@ export class Terminal implements ITerminal {
|
||||
break;
|
||||
case iTutorialSteps.TerminalRunScript:
|
||||
if (commandArray.length == 2 && commandArray[0] == "run" && commandArray[1] == "n00dles.script") {
|
||||
run(this, engine, player, s, commandArray.slice(1));
|
||||
run(this, router, player, s, commandArray.slice(1));
|
||||
iTutorialNextStep();
|
||||
} else {
|
||||
this.print("Bad command. Please follow the tutorial");
|
||||
@ -662,7 +661,7 @@ export class Terminal implements ITerminal {
|
||||
const commands: {
|
||||
[key: string]: (
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
@ -713,7 +712,7 @@ export class Terminal implements ITerminal {
|
||||
return;
|
||||
}
|
||||
|
||||
f(this, engine, player, s, commandArray.slice(1));
|
||||
f(this, router, player, s, commandArray.slice(1));
|
||||
}
|
||||
|
||||
getProgressText(): string {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { parseAliasDeclaration, printAliases } from "../../Alias";
|
||||
|
||||
export function alias(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
export function analyze(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { Server } from "../../Server/Server";
|
||||
@ -7,7 +7,7 @@ import { HacknetServer } from "../../Hacknet/HacknetServer";
|
||||
|
||||
export function backdoor(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { listAllDarkwebItems, buyDarkwebItem } from "../../DarkWeb/DarkWeb";
|
||||
@ -7,7 +7,7 @@ import { SpecialServerIps } from "../../Server/SpecialServerIps";
|
||||
|
||||
export function buy(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { showMessage } from "../../Message/MessageHelpers";
|
||||
@ -8,7 +8,7 @@ import { showLiterature } from "../../Literature/LiteratureHelpers";
|
||||
|
||||
export function cat(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
@ -7,7 +7,7 @@ import { evaluateDirectoryPath, removeTrailingSlash } from "../DirectoryHelpers"
|
||||
|
||||
export function cd(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { findRunningScript } from "../../Script/ScriptHelpers";
|
||||
@ -7,7 +7,7 @@ import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
|
||||
export function check(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { getServerOnNetwork } from "../../Server/ServerHelpers";
|
||||
|
||||
export function connect(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
@ -8,7 +8,7 @@ import JSZip from "jszip";
|
||||
|
||||
export function download(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
export function expr(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
export function free(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { Server } from "../../Server/Server";
|
||||
|
||||
export function hack(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { TerminalHelpText, HelpTexts } from "../HelpText";
|
||||
|
||||
export function help(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
export function home(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
export function hostname(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
export function ifconfig(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { killWorkerScript } from "../../Netscript/killWorkerScript";
|
||||
|
||||
export function kill(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { killWorkerScript } from "../../Netscript/killWorkerScript";
|
||||
import { WorkerScriptStartStopEventEmitter } from "../../Netscript/WorkerScriptStartStopEventEmitter";
|
||||
|
||||
export function killall(terminal: ITerminal, engine: IEngine, player: IPlayer, server: BaseServer): void {
|
||||
export function killall(terminal: ITerminal, router: IRouter, player: IPlayer, server: BaseServer): void {
|
||||
for (let i = server.runningScripts.length - 1; i >= 0; --i) {
|
||||
killWorkerScript(server.runningScripts[i], server.ip, false);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { Message } from "../../Message/Message";
|
||||
@ -7,7 +7,7 @@ import { getFirstParentDirectory, isValidDirectoryPath, evaluateDirectoryPath }
|
||||
|
||||
export function ls(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
export function lscpu(terminal: ITerminal, engine: IEngine, player: IPlayer): void {
|
||||
export function lscpu(terminal: ITerminal, router: IRouter, player: IPlayer): void {
|
||||
terminal.print(player.getCurrentServer().cpuCores + " Core(s)");
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
export function mem(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
@ -8,7 +8,7 @@ import { Script } from "../../Script/Script";
|
||||
|
||||
export function mv(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
@ -7,7 +7,7 @@ import { createFconf } from "../../Fconf/Fconf";
|
||||
|
||||
export function nano(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
@ -21,7 +21,7 @@ export function nano(
|
||||
const filename = args[0] + "";
|
||||
if (filename === ".fconf") {
|
||||
const text = createFconf();
|
||||
engine.loadScriptEditorContent(filename, text);
|
||||
router.toScriptEditor(filename, text);
|
||||
return;
|
||||
} else if (isScriptFilename(filename)) {
|
||||
const filepath = terminal.getFilepath(filename);
|
||||
@ -33,17 +33,17 @@ export function nano(
|
||||
|
||||
}`;
|
||||
}
|
||||
engine.loadScriptEditorContent(filepath, code);
|
||||
router.toScriptEditor(filepath, code);
|
||||
} else {
|
||||
engine.loadScriptEditorContent(filepath, script.code);
|
||||
router.toScriptEditor(filepath, script.code);
|
||||
}
|
||||
} else if (filename.endsWith(".txt")) {
|
||||
const filepath = terminal.getFilepath(filename);
|
||||
const txt = terminal.getTextFile(player, filename);
|
||||
if (txt == null) {
|
||||
engine.loadScriptEditorContent(filepath);
|
||||
router.toScriptEditor(filepath);
|
||||
} else {
|
||||
engine.loadScriptEditorContent(filepath, txt.text);
|
||||
router.toScriptEditor(filepath, txt.text);
|
||||
}
|
||||
} else {
|
||||
terminal.error(
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
export function ps(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { IReturnStatus } from "../../types";
|
||||
|
||||
export function rm(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
@ -8,7 +8,7 @@ import { runProgram } from "./runProgram";
|
||||
|
||||
export function run(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
@ -30,11 +30,11 @@ export function run(
|
||||
|
||||
// Check if its a script or just a program/executable
|
||||
if (isScriptFilename(executableName)) {
|
||||
runScript(terminal, engine, player, server, args);
|
||||
runScript(terminal, router, player, server, args);
|
||||
} else if (executableName.endsWith(".cct")) {
|
||||
terminal.runContract(player, executableName);
|
||||
} else {
|
||||
runProgram(terminal, engine, player, server, args);
|
||||
runProgram(terminal, router, player, server, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { Programs } from "../../Programs/Programs";
|
||||
|
||||
export function runProgram(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
@ -31,6 +31,7 @@ export function runProgram(
|
||||
for (const program of Object.values(Programs)) {
|
||||
if (program.name === programName) {
|
||||
program.run(
|
||||
router,
|
||||
terminal,
|
||||
player,
|
||||
server,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { logBoxCreate } from "../../../utils/LogBox";
|
||||
@ -10,7 +10,7 @@ import * as libarg from "arg";
|
||||
|
||||
export function runScript(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
commandArgs: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { getServerOnNetwork } from "../../Server/ServerHelpers";
|
||||
|
||||
export function scan(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { Programs } from "../../Programs/Programs";
|
||||
|
||||
export function scananalyze(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { Message } from "../../Message/Message";
|
||||
@ -8,7 +8,7 @@ import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
|
||||
export function scp(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
export function sudov(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { logBoxCreate } from "../../../utils/LogBox";
|
||||
@ -9,7 +9,7 @@ import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
|
||||
export function tail(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
commandArray: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { FconfSettings } from "../../Fconf/FconfSettings";
|
||||
|
||||
export function theme(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { getRamUsageFromRunningScript } from "../../Script/RunningScriptHelpers";
|
||||
@ -7,7 +7,7 @@ import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
export function top(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { removeAlias } from "../../Alias";
|
||||
|
||||
export function unalias(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||
|
||||
export function wget(
|
||||
terminal: ITerminal,
|
||||
engine: IEngine,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
|
@ -8,7 +8,7 @@ import Paper from "@mui/material/Paper";
|
||||
|
||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { determineAllPossibilitiesForTabCompletion } from "../determineAllPossibilitiesForTabCompletion";
|
||||
import { tabCompletion } from "../tabCompletion";
|
||||
@ -17,21 +17,21 @@ import { FconfSettings } from "../../Fconf/FconfSettings";
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
textfield: {
|
||||
margin: 0,
|
||||
margin: theme.spacing(0),
|
||||
width: "100%",
|
||||
},
|
||||
input: {
|
||||
backgroundColor: "#000",
|
||||
},
|
||||
nopadding: {
|
||||
padding: 0,
|
||||
padding: theme.spacing(0),
|
||||
},
|
||||
preformatted: {
|
||||
whiteSpace: "pre-wrap",
|
||||
margin: 0,
|
||||
margin: theme.spacing(0),
|
||||
},
|
||||
list: {
|
||||
padding: 0,
|
||||
padding: theme.spacing(0),
|
||||
height: "100%",
|
||||
},
|
||||
}),
|
||||
@ -39,11 +39,11 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
|
||||
interface IProps {
|
||||
terminal: ITerminal;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function TerminalInput({ terminal, engine, player }: IProps): React.ReactElement {
|
||||
export function TerminalInput({ terminal, router, player }: IProps): React.ReactElement {
|
||||
const terminalInput = useRef<HTMLInputElement>(null);
|
||||
|
||||
const [value, setValue] = useState("");
|
||||
@ -147,7 +147,7 @@ export function TerminalInput({ terminal, engine, player }: IProps): React.React
|
||||
if (ref) ref.focus();
|
||||
// Cancel action
|
||||
if (event.keyCode === KEY.C && event.ctrlKey) {
|
||||
terminal.finishAction(player, true);
|
||||
terminal.finishAction(router, player, true);
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", keyDown);
|
||||
@ -159,7 +159,7 @@ export function TerminalInput({ terminal, engine, player }: IProps): React.React
|
||||
if (event.keyCode === KEY.ENTER && value !== "") {
|
||||
event.preventDefault();
|
||||
terminal.print(`[${player.getCurrentServer().hostname} ~${terminal.cwd()}]> ${value}`);
|
||||
terminal.executeCommands(engine, player, value);
|
||||
terminal.executeCommands(router, player, value);
|
||||
setValue("");
|
||||
return;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import makeStyles from "@mui/styles/makeStyles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import Box from "@mui/material/Box";
|
||||
import { ITerminal, Output, Link } from "../ITerminal";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { TerminalInput } from "./TerminalInput";
|
||||
|
||||
@ -42,11 +42,11 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
|
||||
interface IProps {
|
||||
terminal: ITerminal;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactElement {
|
||||
export function TerminalRoot({ terminal, router, player }: IProps): React.ReactElement {
|
||||
const scrollHook = useRef<HTMLDivElement>(null);
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
@ -76,7 +76,7 @@ export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactE
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
<Box width="100%" minHeight="100vh" px={1} display={"flex"} alignItems={"flex-end"}>
|
||||
<Box width="100%" minHeight="100vh" display={"flex"} alignItems={"flex-end"}>
|
||||
<List classes={{ root: classes.list }}>
|
||||
{terminal.outputHistory.map((item, i) => {
|
||||
if (item instanceof Output)
|
||||
@ -110,8 +110,8 @@ export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactE
|
||||
</List>
|
||||
<div ref={scrollHook}></div>
|
||||
</Box>
|
||||
<Box position="sticky" bottom={0} width="100%" px={1}>
|
||||
<TerminalInput player={player} engine={engine} terminal={terminal} />
|
||||
<Box position="sticky" bottom={0} width="100%" px={0}>
|
||||
<TerminalInput player={player} router={router} terminal={terminal} />
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
|
510
src/engine.jsx
510
src/engine.jsx
@ -1,73 +1,44 @@
|
||||
/**
|
||||
* Game engine. Handles the main game loop as well as the main UI pages
|
||||
*
|
||||
* TODO: Separate UI functionality into its own component
|
||||
* Game engine. Handles the main game loop.
|
||||
*/
|
||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
import { Augmentations } from "./Augmentation/Augmentations";
|
||||
import { initAugmentations, installAugmentations } from "./Augmentation/AugmentationHelpers";
|
||||
import { onExport } from "./ExportBonus";
|
||||
import { AugmentationsRoot } from "./Augmentation/ui/Root";
|
||||
import { initAugmentations } from "./Augmentation/AugmentationHelpers";
|
||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
||||
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||
import { CharacterOverview } from "./ui/React/CharacterOverview";
|
||||
import { generateRandomContract } from "./CodingContractGenerator";
|
||||
import { initCompanies } from "./Company/Companies";
|
||||
import { Corporation } from "./Corporation/Corporation";
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { DevMenuRoot } from "./DevMenu";
|
||||
import { Factions, initFactions } from "./Faction/Factions";
|
||||
import { processPassiveFactionRepGain, inviteToFaction } from "./Faction/FactionHelpers";
|
||||
import { FactionList } from "./Faction/ui/FactionList";
|
||||
import { Root as BladeburnerRoot } from "./Bladeburner/ui/Root";
|
||||
import { Root as GangRoot } from "./Gang/ui/Root";
|
||||
import { SidebarRoot } from "./Sidebar/ui/SidebarRoot";
|
||||
import { CorporationRoot } from "./Corporation/ui/CorporationRoot";
|
||||
import { ResleeveRoot } from "./PersonObjects/Resleeving/ui/ResleeveRoot";
|
||||
import { GameOptionsRoot } from "./ui/React/GameOptionsRoot";
|
||||
import { GameRoot, Router } from "./ui/GameRoot";
|
||||
import { TTheme as Theme } from "./ui/React/Theme";
|
||||
import { SleeveRoot } from "./PersonObjects/Sleeve/ui/SleeveRoot";
|
||||
import { displayInfiltrationContent } from "./Infiltration/Helper";
|
||||
import {
|
||||
getHackingWorkRepGain,
|
||||
getFactionSecurityWorkRepGain,
|
||||
getFactionFieldWorkRepGain,
|
||||
} from "./PersonObjects/formulas/reputation";
|
||||
import { hasHacknetServers, processHacknetEarnings } from "./Hacknet/HacknetHelpers";
|
||||
import { HacknetRoot } from "./Hacknet/ui/HacknetRoot";
|
||||
import { iTutorialStart } from "./InteractiveTutorial";
|
||||
import { LocationName } from "./Locations/data/LocationNames";
|
||||
import { LocationRoot } from "./Locations/ui/Root";
|
||||
import { checkForMessagesToSend, initMessages } from "./Message/MessageHelpers";
|
||||
import { inMission, currMission } from "./Missions";
|
||||
import { workerScripts } from "./Netscript/WorkerScripts";
|
||||
import { loadAllRunningScripts, updateOnlineScriptTimes } from "./NetscriptWorker";
|
||||
import { Player } from "./Player";
|
||||
import { prestigeAugmentation } from "./Prestige";
|
||||
import { ProgramsRoot } from "./Programs/ui/ProgramsRoot";
|
||||
import { saveObject, loadGame } from "./SaveObject";
|
||||
import { Root as ScriptEditorRoot } from "./ScriptEditor/ui/Root";
|
||||
import { initForeignServers, AllServers } from "./Server/AllServers";
|
||||
import { initForeignServers } from "./Server/AllServers";
|
||||
import { Settings } from "./Settings/Settings";
|
||||
import { updateSourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||
import { initSpecialServerIps } from "./Server/SpecialServerIps";
|
||||
import { initSymbolToStockMap, processStockPrices, displayStockMarketContent } from "./StockMarket/StockMarket";
|
||||
import { MilestonesRoot } from "./Milestones/ui/MilestonesRoot";
|
||||
import { TerminalRoot } from "./Terminal/ui/TerminalRoot";
|
||||
import { initSymbolToStockMap, processStockPrices } from "./StockMarket/StockMarket";
|
||||
import { Terminal } from "./Terminal";
|
||||
import { TutorialRoot } from "./Tutorial/ui/TutorialRoot";
|
||||
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
||||
|
||||
import { CharacterInfo } from "./ui/CharacterInfo";
|
||||
import { Page, routing } from "./ui/navigationTracking";
|
||||
import { Money } from "./ui/React/Money";
|
||||
import { Hashes } from "./ui/React/Hashes";
|
||||
import { Reputation } from "./ui/React/Reputation";
|
||||
|
||||
import { ActiveScriptsRoot } from "./ui/ActiveScripts/Root";
|
||||
import { MainMenuLinks } from "./ui/MainMenu/Links";
|
||||
|
||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { removeLoadingScreen } from "../utils/uiHelpers/removeLoadingScreen";
|
||||
@ -78,367 +49,19 @@ import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
const Engine = {
|
||||
// Clickable objects
|
||||
Clickables: {
|
||||
// Main menu buttons
|
||||
saveMainMenuButton: null,
|
||||
deleteMainMenuButton: null,
|
||||
},
|
||||
|
||||
// Display objects
|
||||
// TODO-Refactor this into its own component
|
||||
Display: {
|
||||
// Generic page that most react loads into.
|
||||
content: null,
|
||||
// Main menu content
|
||||
infiltrationContent: null,
|
||||
workInProgressContent: null,
|
||||
redPillContent: null,
|
||||
cinematicTextContent: null,
|
||||
missionContent: null,
|
||||
overview: null,
|
||||
},
|
||||
|
||||
indexedDb: undefined,
|
||||
|
||||
// Time variables (milliseconds unix epoch time)
|
||||
_lastUpdate: new Date().getTime(),
|
||||
_idleSpeed: 200, // Speed (in ms) at which the main loop is updated
|
||||
|
||||
loadTerminalContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.CharacterInfo);
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
<TerminalRoot terminal={Terminal} engine={this} player={Player} />
|
||||
</Theme>,
|
||||
Engine.Display.content,
|
||||
);
|
||||
MainMenuLinks.Stats.classList.add("active");
|
||||
},
|
||||
|
||||
loadCharacterContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.CharacterInfo);
|
||||
ReactDOM.render(<CharacterInfo player={Player} />, Engine.Display.content);
|
||||
MainMenuLinks.Stats.classList.add("active");
|
||||
},
|
||||
|
||||
loadScriptEditorContent: function (filename = "", code = "") {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.ScriptEditor);
|
||||
MainMenuLinks.ScriptEditor.classList.add("active");
|
||||
ReactDOM.render(
|
||||
<ScriptEditorRoot filename={filename} code={code} player={Player} engine={this} />,
|
||||
Engine.Display.content,
|
||||
);
|
||||
},
|
||||
|
||||
loadActiveScriptsContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.ActiveScripts);
|
||||
MainMenuLinks.ActiveScripts.classList.add("active");
|
||||
ReactDOM.render(<ActiveScriptsRoot p={Player} workerScripts={workerScripts} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadHacknetNodesContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.HacknetNodes);
|
||||
MainMenuLinks.HacknetNodes.classList.add("active");
|
||||
ReactDOM.render(<HacknetRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadCreateProgramContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.CreateProgram);
|
||||
MainMenuLinks.CreateProgram.classList.add("active");
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
<ProgramsRoot player={Player} />
|
||||
</Theme>,
|
||||
Engine.Display.content,
|
||||
);
|
||||
},
|
||||
|
||||
loadFactionsContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Factions);
|
||||
MainMenuLinks.Factions.classList.add("active");
|
||||
ReactDOM.render(<FactionList player={Player} engine={this} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadFactionContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Faction);
|
||||
},
|
||||
|
||||
loadAugmentationsContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Augmentations);
|
||||
MainMenuLinks.Augmentations.classList.add("active");
|
||||
|
||||
function backup() {
|
||||
saveObject.exportGame();
|
||||
onExport(Player);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<AugmentationsRoot exportGameFn={backup} installAugmentationsFn={installAugmentations} />,
|
||||
Engine.Display.content,
|
||||
);
|
||||
},
|
||||
|
||||
loadMilestonesContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Milestones);
|
||||
MainMenuLinks.Milestones.classList.add("active");
|
||||
ReactDOM.render(<MilestonesRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadTutorialContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Tutorial);
|
||||
MainMenuLinks.Tutorial.classList.add("active");
|
||||
ReactDOM.render(<TutorialRoot />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadDevMenuContent: function () {
|
||||
Engine.hideAllContent();
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
throw new Error("Cannot create Dev Menu because you are not in a dev build");
|
||||
}
|
||||
Engine.Display.content.style.display = "block";
|
||||
ReactDOM.render(<DevMenuRoot player={Player} engine={this} />, Engine.Display.content);
|
||||
routing.navigateTo(Page.DevMenu);
|
||||
MainMenuLinks.DevMenu.classList.add("active");
|
||||
},
|
||||
|
||||
loadLocationContent: function (initiallyInCity = true) {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Location);
|
||||
MainMenuLinks.City.classList.add("active");
|
||||
ReactDOM.render(
|
||||
<LocationRoot initiallyInCity={initiallyInCity} engine={Engine} p={Player} />,
|
||||
Engine.Display.content,
|
||||
);
|
||||
},
|
||||
|
||||
loadTravelContent: function () {
|
||||
// Same as loadLocationContent() except first set the location to the travel agency,
|
||||
// and make sure that the 'City' main menu link doesnt become 'active'
|
||||
Engine.hideAllContent();
|
||||
Player.gotoLocation(LocationName.TravelAgency);
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Location);
|
||||
MainMenuLinks.Travel.classList.add("active");
|
||||
ReactDOM.render(<LocationRoot initiallyInCity={false} engine={Engine} p={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadJobContent: function () {
|
||||
// Same as loadLocationContent(), except first set the location to the job.
|
||||
// Make sure that the 'City' main menu link doesnt become 'active'
|
||||
if (Player.companyName == "") {
|
||||
dialogBoxCreate(
|
||||
"You do not currently have a job! You can visit various companies " + "in the city and try to find a job.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
Engine.hideAllContent();
|
||||
Player.gotoLocation(Player.companyName);
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Location);
|
||||
MainMenuLinks.Job.classList.add("active");
|
||||
ReactDOM.render(<LocationRoot initiallyInCity={false} engine={Engine} p={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadWorkInProgressContent: function () {
|
||||
Engine.hideAllContent();
|
||||
const mainMenu = document.getElementById("mainmenu-container");
|
||||
console.log("hiding loadWorkInProgressContent");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.workInProgressContent.style.display = "block";
|
||||
console.log(Engine.Display.workInProgressContent);
|
||||
routing.navigateTo(Page.WorkInProgress);
|
||||
},
|
||||
|
||||
loadRedPillContent: function () {
|
||||
Engine.hideAllContent();
|
||||
const mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.redPillContent.style.display = "block";
|
||||
routing.navigateTo(Page.RedPill);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadCinematicTextContent: function () {
|
||||
Engine.hideAllContent();
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.cinematicTextContent.style.display = "block";
|
||||
routing.navigateTo(Page.CinematicText);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadInfiltrationContent: function (name, difficulty, maxLevel) {
|
||||
Engine.hideAllContent();
|
||||
const mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.infiltrationContent.style.display = "block";
|
||||
routing.navigateTo(Page.Infiltration);
|
||||
displayInfiltrationContent(this, Player, name, difficulty, maxLevel);
|
||||
},
|
||||
|
||||
loadStockMarketContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.StockMarket);
|
||||
MainMenuLinks.StockMarket.classList.add("active");
|
||||
displayStockMarketContent();
|
||||
},
|
||||
|
||||
loadGangContent: function () {
|
||||
if (!Player.inGang()) return;
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Gang);
|
||||
MainMenuLinks.Gang.classList.add("active");
|
||||
ReactDOM.render(<GangRoot engine={this} gang={Player.gang} player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadMissionContent: function () {
|
||||
Engine.hideAllContent();
|
||||
document.getElementById("mainmenu-container").style.visibility = "hidden";
|
||||
document.getElementById("character-overview").style.visibility = "hidden";
|
||||
Engine.Display.missionContent.style.display = "block";
|
||||
routing.navigateTo(Page.Mission);
|
||||
},
|
||||
|
||||
loadCorporationContent: function () {
|
||||
if (!(Player.corporation instanceof Corporation)) return;
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Corporation);
|
||||
MainMenuLinks.Corporation.classList.add("active");
|
||||
ReactDOM.render(<CorporationRoot corp={Player.corporation} player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadBladeburnerContent: function () {
|
||||
if (!(Player.bladeburner instanceof Bladeburner)) return;
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Bladeburner);
|
||||
MainMenuLinks.Bladeburner.classList.add("active");
|
||||
ReactDOM.render(
|
||||
<BladeburnerRoot bladeburner={Player.bladeburner} player={Player} engine={this} />,
|
||||
Engine.Display.content,
|
||||
);
|
||||
},
|
||||
|
||||
loadSleevesContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Sleeves);
|
||||
ReactDOM.render(<SleeveRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadResleevingContent: function () {
|
||||
Engine.hideAllContent();
|
||||
routing.navigateTo(Page.Resleeves);
|
||||
Engine.Display.content.style.display = "block";
|
||||
MainMenuLinks.City.classList.add("active");
|
||||
ReactDOM.render(<ResleeveRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadGameOptionsContent: function () {
|
||||
Engine.hideAllContent();
|
||||
routing.navigateTo(Page.GameOptions);
|
||||
Engine.Display.content.style.display = "block";
|
||||
MainMenuLinks.City.classList.add("active");
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
<GameOptionsRoot
|
||||
player={Player}
|
||||
save={() => saveObject.saveGame(Engine.indexedDb)}
|
||||
delete={() => saveObject.deleteGame(Engine.indexedDb)}
|
||||
export={() => saveObject.exportGame()}
|
||||
import={() => saveObject.importGame()}
|
||||
forceKill={() => {
|
||||
for (const hostname of Object.keys(AllServers)) {
|
||||
AllServers[hostname].runningScripts = [];
|
||||
}
|
||||
dialogBoxCreate("Forcefully deleted all running scripts. Please save and refresh page.");
|
||||
}}
|
||||
softReset={() => {
|
||||
dialogBoxCreate("Soft Reset!");
|
||||
prestigeAugmentation();
|
||||
}}
|
||||
/>
|
||||
</Theme>,
|
||||
Engine.Display.content,
|
||||
);
|
||||
},
|
||||
|
||||
// Helper function that hides all content
|
||||
hideAllContent: function () {
|
||||
Engine.Display.content.style.display = "none";
|
||||
Engine.Display.content.scrollTop = 0;
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.content);
|
||||
|
||||
Engine.Display.infiltrationContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.infiltrationContent);
|
||||
|
||||
Engine.Display.workInProgressContent.style.display = "none";
|
||||
Engine.Display.redPillContent.style.display = "none";
|
||||
Engine.Display.cinematicTextContent.style.display = "none";
|
||||
Engine.Display.missionContent.style.display = "none";
|
||||
},
|
||||
|
||||
displayCharacterOverviewInfo: function () {
|
||||
console.log("rendering");
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
<CharacterOverview player={Player} save={() => saveObject.saveGame(Engine.indexedDb)} />
|
||||
</Theme>,
|
||||
document.getElementById("character-overview"),
|
||||
);
|
||||
},
|
||||
|
||||
// Main Game Loop
|
||||
idleTimer: function () {
|
||||
// Get time difference
|
||||
const _thisUpdate = new Date().getTime();
|
||||
let diff = _thisUpdate - Engine._lastUpdate;
|
||||
const offset = diff % Engine._idleSpeed;
|
||||
|
||||
// Divide this by cycle time to determine how many cycles have elapsed since last update
|
||||
diff = Math.floor(diff / Engine._idleSpeed);
|
||||
|
||||
if (diff > 0) {
|
||||
// Update the game engine by the calculated number of cycles
|
||||
Engine._lastUpdate = _thisUpdate - offset;
|
||||
Player.lastUpdate = _thisUpdate - offset;
|
||||
Engine.updateGame(diff);
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(Engine.idleTimer);
|
||||
},
|
||||
|
||||
updateGame: function (numCycles = 1) {
|
||||
const time = numCycles * Engine._idleSpeed;
|
||||
const time = numCycles * CONSTANTS._idleSpeed;
|
||||
if (Player.totalPlaytime == null) {
|
||||
Player.totalPlaytime = 0;
|
||||
}
|
||||
@ -452,7 +75,7 @@ const Engine = {
|
||||
Player.playtimeSinceLastAug += time;
|
||||
Player.playtimeSinceLastBitnode += time;
|
||||
|
||||
Terminal.process(Player, numCycles);
|
||||
Terminal.process(Router, Player, numCycles);
|
||||
|
||||
// Working
|
||||
if (Player.isWorking) {
|
||||
@ -600,7 +223,7 @@ const Engine = {
|
||||
}
|
||||
if (Player.bladeburner instanceof Bladeburner) {
|
||||
try {
|
||||
Player.bladeburner.process(Player);
|
||||
Player.bladeburner.process(Router, Player);
|
||||
} catch (e) {
|
||||
exceptionAlert("Exception caught in Bladeburner.process(): " + e);
|
||||
}
|
||||
@ -617,42 +240,11 @@ const Engine = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Used in game when clicking on a main menu header (NOT used for initialization)
|
||||
* @param open {boolean} Whether header is being opened or closed
|
||||
* @param elems {HTMLElement[]} li Elements under header
|
||||
* @param links {HTMLElement[]} a elements under header
|
||||
*/
|
||||
toggleMainMenuHeader: function (open, elems, links) {
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
if (open) {
|
||||
elems[i].style.opacity = 1;
|
||||
elems[i].style.maxHeight = elems[i].scrollHeight + "px";
|
||||
} else {
|
||||
elems[i].style.opacity = 0;
|
||||
elems[i].style.maxHeight = null;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < links.length; ++i) {
|
||||
if (open) {
|
||||
links[i].style.opacity = 1;
|
||||
links[i].style.maxHeight = links[i].scrollHeight + "px";
|
||||
links[i].style.pointerEvents = "auto";
|
||||
} else {
|
||||
links[i].style.opacity = 0;
|
||||
links[i].style.maxHeight = null;
|
||||
links[i].style.pointerEvents = "none";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
load: function (saveString) {
|
||||
// Load game from save or create new game
|
||||
if (loadGame(saveString)) {
|
||||
initBitNodeMultipliers(Player);
|
||||
Engine.setDisplayElements(); // Sets variables for important DOM elements
|
||||
Engine.init(); // Initialize buttons, work, etc.
|
||||
updateSourceFileFlags(Player);
|
||||
initAugmentations(); // Also calls Player.reapplyAllAugmentations()
|
||||
Player.reapplyAllSourceFiles();
|
||||
@ -664,7 +256,7 @@ const Engine = {
|
||||
Engine._lastUpdate = new Date().getTime();
|
||||
const lastUpdate = Player.lastUpdate;
|
||||
const timeOffline = Engine._lastUpdate - lastUpdate;
|
||||
const numCyclesOffline = Math.floor(timeOffline / Engine._idleSpeed);
|
||||
const numCyclesOffline = Math.floor(timeOffline / CONSTANTS._idleSpeed);
|
||||
|
||||
let offlineReputation = 0;
|
||||
const offlineHackingIncome = (Player.moneySourceA.hacking / Player.playtimeSinceLastAug) * timeOffline * 0.75;
|
||||
@ -686,6 +278,7 @@ const Engine = {
|
||||
} else {
|
||||
Player.work(numCyclesOffline);
|
||||
}
|
||||
Player.focus = false;
|
||||
} else {
|
||||
for (let i = 0; i < Player.factions.length; i++) {
|
||||
const facName = Player.factions[i];
|
||||
@ -760,7 +353,7 @@ const Engine = {
|
||||
}
|
||||
|
||||
// Update total playtime
|
||||
var time = numCyclesOffline * Engine._idleSpeed;
|
||||
var time = numCyclesOffline * CONSTANTS._idleSpeed;
|
||||
if (Player.totalPlaytime == null) {
|
||||
Player.totalPlaytime = 0;
|
||||
}
|
||||
@ -806,79 +399,34 @@ const Engine = {
|
||||
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
<SidebarRoot engine={this} player={Player} />
|
||||
<GameRoot terminal={Terminal} engine={this} player={Player} />
|
||||
</Theme>,
|
||||
document.getElementById("sidebar"),
|
||||
document.getElementById("mainmenu-container"),
|
||||
);
|
||||
},
|
||||
|
||||
setDisplayElements: function () {
|
||||
Engine.Display.content = document.getElementById("generic-react-container");
|
||||
Engine.Display.content.style.display = "none";
|
||||
|
||||
Engine.Display.missionContent = document.getElementById("mission-container");
|
||||
Engine.Display.missionContent.style.display = "none";
|
||||
|
||||
// Work In Progress
|
||||
Engine.Display.workInProgressContent = document.getElementById("work-in-progress-container");
|
||||
Engine.Display.workInProgressContent.style.display = "none";
|
||||
|
||||
// Red Pill / Hack World Daemon
|
||||
Engine.Display.redPillContent = document.getElementById("red-pill-container");
|
||||
Engine.Display.redPillContent.style.display = "none";
|
||||
|
||||
Engine.Display.infiltrationContent = document.getElementById("infiltration-container");
|
||||
Engine.Display.infiltrationContent.style.display = "none";
|
||||
|
||||
// Cinematic Text
|
||||
Engine.Display.cinematicTextContent = document.getElementById("cinematic-text-container");
|
||||
Engine.Display.cinematicTextContent.style.display = "none";
|
||||
|
||||
Engine.Display.overview = document.getElementById("character-overview");
|
||||
},
|
||||
|
||||
// Initialization
|
||||
init: function () {
|
||||
// Player was working cancel button
|
||||
|
||||
Engine.displayCharacterOverviewInfo();
|
||||
if (Player.isWorking) {
|
||||
var cancelButton = document.getElementById("work-in-progress-cancel-button");
|
||||
cancelButton.addEventListener("click", function () {
|
||||
if (Player.workType == CONSTANTS.WorkTypeFaction) {
|
||||
Player.finishFactionWork(true);
|
||||
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
|
||||
Player.finishCreateProgramWork(true);
|
||||
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
|
||||
Player.finishClass();
|
||||
} else if (Player.workType == CONSTANTS.WorkTypeCrime) {
|
||||
Player.finishCrime(true);
|
||||
} else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) {
|
||||
Player.finishWorkPartTime();
|
||||
} else {
|
||||
Player.finishWork(true);
|
||||
}
|
||||
});
|
||||
|
||||
const focusButton = document.getElementById("work-in-progress-something-else-button");
|
||||
focusButton.style.visibility = "hidden";
|
||||
const focusable = [CONSTANTS.WorkTypeFaction, CONSTANTS.WorkTypeCompanyPartTime, CONSTANTS.WorkTypeCompany];
|
||||
if (focusable.includes(Player.workType)) {
|
||||
focusButton.style.visibility = "visible";
|
||||
focusButton.addEventListener("click", function () {
|
||||
Player.stopFocusing();
|
||||
});
|
||||
}
|
||||
|
||||
Engine.loadWorkInProgressContent();
|
||||
} else {
|
||||
Engine.loadTerminalContent();
|
||||
}
|
||||
},
|
||||
|
||||
start: function () {
|
||||
// Run main loop
|
||||
Engine.idleTimer();
|
||||
// Get time difference
|
||||
const _thisUpdate = new Date().getTime();
|
||||
let diff = _thisUpdate - Engine._lastUpdate;
|
||||
const offset = diff % CONSTANTS._idleSpeed;
|
||||
|
||||
// Divide this by cycle time to determine how many cycles have elapsed since last update
|
||||
diff = Math.floor(diff / CONSTANTS._idleSpeed);
|
||||
|
||||
if (diff > 0) {
|
||||
// Update the game engine by the calculated number of cycles
|
||||
Engine._lastUpdate = _thisUpdate - offset;
|
||||
Player.lastUpdate = _thisUpdate - offset;
|
||||
Engine.updateGame(diff);
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(Engine.start);
|
||||
},
|
||||
};
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user