mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-11 10:13:52 +01:00
Merge pull request #1376 from danielyxie/dev
Almost everything in typescript.
This commit is contained in:
commit
b5c105b6fe
38
dist/vendor.bundle.js
vendored
38
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -5,7 +5,7 @@ function createWindow() {
|
|||||||
const win = new BrowserWindow({
|
const win = new BrowserWindow({
|
||||||
show: false,
|
show: false,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
devTools: false,
|
devTools: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ function createWindow() {
|
|||||||
win.maximize();
|
win.maximize();
|
||||||
win.loadFile("index.html");
|
win.loadFile("index.html");
|
||||||
win.show();
|
win.show();
|
||||||
// win.webContents.openDevTools();
|
win.webContents.openDevTools();
|
||||||
globalShortcut.register("f5", function () {
|
globalShortcut.register("f5", function () {
|
||||||
win.loadFile("index.html");
|
win.loadFile("index.html");
|
||||||
});
|
});
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
11
package-lock.json
generated
11
package-lock.json
generated
@ -16,6 +16,7 @@
|
|||||||
"@mui/lab": "^5.0.0-alpha.46",
|
"@mui/lab": "^5.0.0-alpha.46",
|
||||||
"@mui/material": "^5.0.0-rc.1",
|
"@mui/material": "^5.0.0-rc.1",
|
||||||
"@mui/styles": "^5.0.0-rc.1",
|
"@mui/styles": "^5.0.0-rc.1",
|
||||||
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/js-beautify": "^1.13.2",
|
"@types/js-beautify": "^1.13.2",
|
||||||
"@types/numeral": "0.0.25",
|
"@types/numeral": "0.0.25",
|
||||||
"@types/react": "^17.0.21",
|
"@types/react": "^17.0.21",
|
||||||
@ -4522,6 +4523,11 @@
|
|||||||
"@babel/types": "^7.3.0"
|
"@babel/types": "^7.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/escodegen": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.7.tgz",
|
||||||
|
"integrity": "sha512-46oENdSRNEJXCNrPJoC3vRolZJpfeEm7yvATkd2bCncKFG0PUEyfBCaoacfpcXH4Y5RRuqdVj3J7TI+wwn2SbQ=="
|
||||||
|
},
|
||||||
"node_modules/@types/file-saver": {
|
"node_modules/@types/file-saver": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.3.tgz",
|
||||||
@ -31410,6 +31416,11 @@
|
|||||||
"@babel/types": "^7.3.0"
|
"@babel/types": "^7.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/escodegen": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.7.tgz",
|
||||||
|
"integrity": "sha512-46oENdSRNEJXCNrPJoC3vRolZJpfeEm7yvATkd2bCncKFG0PUEyfBCaoacfpcXH4Y5RRuqdVj3J7TI+wwn2SbQ=="
|
||||||
|
},
|
||||||
"@types/file-saver": {
|
"@types/file-saver": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.3.tgz",
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"@mui/lab": "^5.0.0-alpha.46",
|
"@mui/lab": "^5.0.0-alpha.46",
|
||||||
"@mui/material": "^5.0.0-rc.1",
|
"@mui/material": "^5.0.0-rc.1",
|
||||||
"@mui/styles": "^5.0.0-rc.1",
|
"@mui/styles": "^5.0.0-rc.1",
|
||||||
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/js-beautify": "^1.13.2",
|
"@types/js-beautify": "^1.13.2",
|
||||||
"@types/numeral": "0.0.25",
|
"@types/numeral": "0.0.25",
|
||||||
"@types/react": "^17.0.21",
|
"@types/react": "^17.0.21",
|
||||||
|
@ -10,7 +10,7 @@ import { Money } from "../ui/React/Money";
|
|||||||
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
|
||||||
|
|
||||||
interface IConstructorParams {
|
export interface IConstructorParams {
|
||||||
info: string | JSX.Element;
|
info: string | JSX.Element;
|
||||||
stats?: JSX.Element;
|
stats?: JSX.Element;
|
||||||
isSpecial?: boolean;
|
isSpecial?: boolean;
|
||||||
|
2
src/Augmentation/AugmentationHelpers.d.ts
vendored
2
src/Augmentation/AugmentationHelpers.d.ts
vendored
@ -1,2 +0,0 @@
|
|||||||
export declare function isRepeatableAug(aug: Augmentation): boolean;
|
|
||||||
export declare function installAugmentations(): void;
|
|
@ -1,6 +1,6 @@
|
|||||||
import { Augmentation } from "./Augmentation";
|
import { Augmentation, IConstructorParams } from "./Augmentation";
|
||||||
import { Augmentations } from "./Augmentations";
|
import { Augmentations } from "./Augmentations";
|
||||||
import { PlayerOwnedAugmentation } from "./PlayerOwnedAugmentation";
|
import { PlayerOwnedAugmentation, IPlayerOwnedAugmentation } from "./PlayerOwnedAugmentation";
|
||||||
import { AugmentationNames } from "./data/AugmentationNames";
|
import { AugmentationNames } from "./data/AugmentationNames";
|
||||||
|
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
@ -18,13 +18,13 @@ import { WHRNG } from "../Casino/RNG";
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
function AddToAugmentations(aug) {
|
function AddToAugmentations(aug: Augmentation): void {
|
||||||
var name = aug.name;
|
const name = aug.name;
|
||||||
Augmentations[name] = aug;
|
Augmentations[name] = aug;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandomBonus() {
|
function getRandomBonus(): any {
|
||||||
var bonuses = [
|
const bonuses = [
|
||||||
{
|
{
|
||||||
bonuses: {
|
bonuses: {
|
||||||
hacking_chance_mult: 1.25,
|
hacking_chance_mult: 1.25,
|
||||||
@ -124,7 +124,7 @@ function initAugmentations() {
|
|||||||
//Time-Based Augment Test
|
//Time-Based Augment Test
|
||||||
const randomBonuses = getRandomBonus();
|
const randomBonuses = getRandomBonus();
|
||||||
|
|
||||||
const UnstableCircadianModulatorParams = {
|
const UnstableCircadianModulatorParams: IConstructorParams = {
|
||||||
name: AugmentationNames.UnstableCircadianModulator,
|
name: AugmentationNames.UnstableCircadianModulator,
|
||||||
moneyCost: 5e9,
|
moneyCost: 5e9,
|
||||||
repCost: 3.625e5,
|
repCost: 3.625e5,
|
||||||
@ -133,7 +133,7 @@ function initAugmentations() {
|
|||||||
"unpredictable results based on your circadian rhythm.",
|
"unpredictable results based on your circadian rhythm.",
|
||||||
};
|
};
|
||||||
Object.keys(randomBonuses.bonuses).forEach(
|
Object.keys(randomBonuses.bonuses).forEach(
|
||||||
(key) => (UnstableCircadianModulatorParams[key] = randomBonuses.bonuses[key]),
|
(key) => ((UnstableCircadianModulatorParams as any)[key] = randomBonuses.bonuses[key]),
|
||||||
);
|
);
|
||||||
const UnstableCircadianModulator = new Augmentation(UnstableCircadianModulatorParams);
|
const UnstableCircadianModulator = new Augmentation(UnstableCircadianModulatorParams);
|
||||||
|
|
||||||
@ -2359,7 +2359,7 @@ function initAugmentations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Resets an Augmentation during (re-initizliation)
|
//Resets an Augmentation during (re-initizliation)
|
||||||
function resetAugmentation(newAugObject) {
|
function resetAugmentation(newAugObject: Augmentation): void {
|
||||||
if (!(newAugObject instanceof Augmentation)) {
|
if (!(newAugObject instanceof Augmentation)) {
|
||||||
throw new Error("Invalid argument 'newAugObject' passed into resetAugmentation");
|
throw new Error("Invalid argument 'newAugObject' passed into resetAugmentation");
|
||||||
}
|
}
|
||||||
@ -2370,18 +2370,15 @@ function resetAugmentation(newAugObject) {
|
|||||||
AddToAugmentations(newAugObject);
|
AddToAugmentations(newAugObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyAugmentation(aug, reapply = false) {
|
function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void {
|
||||||
Augmentations[aug.name].owned = true;
|
Augmentations[aug.name].owned = true;
|
||||||
|
|
||||||
const augObj = Augmentations[aug.name];
|
const augObj = Augmentations[aug.name];
|
||||||
|
|
||||||
// Apply multipliers
|
// Apply multipliers
|
||||||
for (const mult in augObj.mults) {
|
for (const mult in augObj.mults) {
|
||||||
if (Player[mult] == null) {
|
const v = Player.getMult(mult) * augObj.mults[mult];
|
||||||
console.warn(`Augmentation has unrecognized multiplier property: ${mult}`);
|
Player.setMult(mult, v);
|
||||||
} else {
|
|
||||||
Player[mult] *= augObj.mults[mult];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special logic for NeuroFlux Governor
|
// Special logic for NeuroFlux Governor
|
||||||
@ -2445,11 +2442,11 @@ function installAugmentations() {
|
|||||||
prestigeAugmentation();
|
prestigeAugmentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
function augmentationExists(name) {
|
function augmentationExists(name: string) {
|
||||||
return Augmentations.hasOwnProperty(name);
|
return Augmentations.hasOwnProperty(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isRepeatableAug(aug) {
|
export function isRepeatableAug(aug: Augmentation): boolean {
|
||||||
const augName = aug instanceof Augmentation ? aug.name : aug;
|
const augName = aug instanceof Augmentation ? aug.name : aug;
|
||||||
|
|
||||||
if (augName === AugmentationNames.NeuroFluxGovernor) {
|
if (augName === AugmentationNames.NeuroFluxGovernor) {
|
@ -6,13 +6,11 @@ import { AllPages } from "./AllPages";
|
|||||||
import { use } from "../../ui/Context";
|
import { use } from "../../ui/Context";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
|
||||||
interface IProps {
|
export function BladeburnerRoot(): React.ReactElement {
|
||||||
bladeburner: IBladeburner;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function BladeburnerRoot(props: IProps): React.ReactElement {
|
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
const router = use.Router();
|
const router = use.Router();
|
||||||
|
const bladeburner = player.bladeburner;
|
||||||
|
if (bladeburner === null) return <></>;
|
||||||
return (
|
return (
|
||||||
<div className="bladeburner-container">
|
<div className="bladeburner-container">
|
||||||
<div style={{ height: "60%", display: "block", position: "relative" }}>
|
<div style={{ height: "60%", display: "block", position: "relative" }}>
|
||||||
@ -24,9 +22,9 @@ export function BladeburnerRoot(props: IProps): React.ReactElement {
|
|||||||
border: "1px solid white",
|
border: "1px solid white",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Stats bladeburner={props.bladeburner} player={player} router={router} />
|
<Stats bladeburner={bladeburner} player={player} router={router} />
|
||||||
</div>
|
</div>
|
||||||
<Console bladeburner={props.bladeburner} player={player} />
|
<Console bladeburner={bladeburner} player={player} />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@ -38,7 +36,7 @@ export function BladeburnerRoot(props: IProps): React.ReactElement {
|
|||||||
position: "relative",
|
position: "relative",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AllPages bladeburner={props.bladeburner} player={player} />
|
<AllPages bladeburner={bladeburner} player={player} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -10,6 +10,7 @@ import { ICorporation } from "../ICorporation";
|
|||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { MainPanel } from "./MainPanel";
|
import { MainPanel } from "./MainPanel";
|
||||||
import { Industries } from "../IndustryData";
|
import { Industries } from "../IndustryData";
|
||||||
|
import { use } from "../../ui/Context";
|
||||||
|
|
||||||
interface IExpandButtonProps {
|
interface IExpandButtonProps {
|
||||||
corp: ICorporation;
|
corp: ICorporation;
|
||||||
@ -38,12 +39,10 @@ function ExpandButton(props: IExpandButtonProps): React.ReactElement {
|
|||||||
return <HeaderTab current={false} onClick={openNewIndustryPopup} text={"Expand into new Industry"} />;
|
return <HeaderTab current={false} onClick={openNewIndustryPopup} text={"Expand into new Industry"} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
export function CorporationRoot(): React.ReactElement {
|
||||||
corp: ICorporation;
|
const player = use.Player();
|
||||||
player: IPlayer;
|
const corporation = player.corporation;
|
||||||
}
|
if (corporation === null) return <></>;
|
||||||
|
|
||||||
export function CorporationRoot(props: IProps): React.ReactElement {
|
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
@ -62,9 +61,9 @@ export function CorporationRoot(props: IProps): React.ReactElement {
|
|||||||
current={divisionName === "Overview"}
|
current={divisionName === "Overview"}
|
||||||
key={"overview"}
|
key={"overview"}
|
||||||
onClick={() => setDivisionName("Overview")}
|
onClick={() => setDivisionName("Overview")}
|
||||||
text={props.corp.name}
|
text={corporation.name}
|
||||||
/>
|
/>
|
||||||
{props.corp.divisions.map((division: IIndustry) => (
|
{corporation.divisions.map((division: IIndustry) => (
|
||||||
<HeaderTab
|
<HeaderTab
|
||||||
current={division.name === divisionName}
|
current={division.name === divisionName}
|
||||||
key={division.name}
|
key={division.name}
|
||||||
@ -72,9 +71,9 @@ export function CorporationRoot(props: IProps): React.ReactElement {
|
|||||||
text={division.name}
|
text={division.name}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<ExpandButton corp={props.corp} setDivisionName={setDivisionName} />
|
<ExpandButton corp={corporation} setDivisionName={setDivisionName} />
|
||||||
</div>
|
</div>
|
||||||
<MainPanel rerender={rerender} corp={props.corp} divisionName={divisionName} player={props.player} />
|
<MainPanel rerender={rerender} corp={corporation} divisionName={divisionName} player={player} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { CONSTANTS } from "../Constants";
|
|||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { IPlayerOrSleeve } from "../PersonObjects/IPlayerOrSleeve";
|
import { IPlayerOrSleeve } from "../PersonObjects/IPlayerOrSleeve";
|
||||||
import { IRouter } from "../ui/Router";
|
import { IRouter } from "../ui/Router";
|
||||||
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
|
||||||
export interface IConstructorParams {
|
export interface IConstructorParams {
|
||||||
hacking_success_weight?: number;
|
hacking_success_weight?: number;
|
||||||
@ -86,7 +87,7 @@ export class Crime {
|
|||||||
this.kills = params.kills ? params.kills : 0;
|
this.kills = params.kills ? params.kills : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
commit(router: IRouter, p: IPlayer, div = 1, singParams: any = null): number {
|
commit(router: IRouter, p: IPlayer, div = 1, workerScript: WorkerScript | null = null): number {
|
||||||
if (div <= 0) {
|
if (div <= 0) {
|
||||||
div = 1;
|
div = 1;
|
||||||
}
|
}
|
||||||
@ -101,7 +102,7 @@ export class Crime {
|
|||||||
this.charisma_exp / div,
|
this.charisma_exp / div,
|
||||||
this.money / div,
|
this.money / div,
|
||||||
this.time,
|
this.time,
|
||||||
singParams,
|
workerScript,
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.time;
|
return this.time;
|
||||||
|
@ -14,7 +14,8 @@ export function checkIfConnectedToDarkweb(): void {
|
|||||||
if (!isValidIPAddress(darkwebIp)) {
|
if (!isValidIPAddress(darkwebIp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (darkwebIp == Player.getCurrentServer().ip) {
|
const server = Player.getCurrentServer();
|
||||||
|
if (server !== null && darkwebIp == server.ip) {
|
||||||
Terminal.print(
|
Terminal.print(
|
||||||
"You are now connected to the dark web. From the dark web you can purchase illegal items. " +
|
"You are now connected to the dark web. From the dark web you can purchase illegal items. " +
|
||||||
"Use the 'buy -l' command to display a list of all the items you can buy. Use 'buy [item-name] " +
|
"Use the 'buy -l' command to display a list of all the items you can buy. Use 'buy [item-name] " +
|
||||||
|
@ -15,43 +15,42 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Bladeburner(props: IProps): React.ReactElement {
|
export function Bladeburner(props: IProps): React.ReactElement {
|
||||||
|
const bladeburner = props.player.bladeburner;
|
||||||
|
if (bladeburner === null) return <></>;
|
||||||
function modifyBladeburnerRank(modify: number): (x: number) => void {
|
function modifyBladeburnerRank(modify: number): (x: number) => void {
|
||||||
return function (rank: number): void {
|
return function (rank: number): void {
|
||||||
if (props.player.bladeburner) {
|
if (!bladeburner) return;
|
||||||
props.player.bladeburner.changeRank(props.player, rank * modify);
|
bladeburner.changeRank(props.player, rank * modify);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetBladeburnerRank(): void {
|
function resetBladeburnerRank(): void {
|
||||||
props.player.bladeburner.rank = 0;
|
if (!bladeburner) return;
|
||||||
props.player.bladeburner.maxRank = 0;
|
bladeburner.rank = 0;
|
||||||
|
bladeburner.maxRank = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTonsBladeburnerRank(): void {
|
function addTonsBladeburnerRank(): void {
|
||||||
if (props.player.bladeburner) {
|
if (!bladeburner) return;
|
||||||
props.player.bladeburner.changeRank(props.player, bigNumber);
|
|
||||||
}
|
bladeburner.changeRank(props.player, bigNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
function modifyBladeburnerCycles(modify: number): (x: number) => void {
|
function modifyBladeburnerCycles(modify: number): (x: number) => void {
|
||||||
return function (cycles: number): void {
|
return function (cycles: number): void {
|
||||||
if (props.player.bladeburner) {
|
if (!bladeburner) return;
|
||||||
props.player.bladeburner.storedCycles += cycles * modify;
|
bladeburner.storedCycles += cycles * modify;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetBladeburnerCycles(): void {
|
function resetBladeburnerCycles(): void {
|
||||||
if (props.player.bladeburner) {
|
if (!bladeburner) return;
|
||||||
props.player.bladeburner.storedCycles = 0;
|
bladeburner.storedCycles = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTonsBladeburnerCycles(): void {
|
function addTonsBladeburnerCycles(): void {
|
||||||
if (props.player.bladeburner) {
|
if (!bladeburner) return;
|
||||||
props.player.bladeburner.storedCycles += bigNumber;
|
bladeburner.storedCycles += bigNumber;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -35,6 +35,6 @@ export function ExploitName(exploit: string): string {
|
|||||||
return names[exploit];
|
return names[exploit];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sanitizeExploits(exploits: string[]): string[] {
|
export function sanitizeExploits(exploits: Exploit[]): Exploit[] {
|
||||||
return exploits.filter((e: string) => Object.keys(Exploit).includes(e));
|
return exploits.filter((e: Exploit) => Object.keys(Exploit).includes(e));
|
||||||
}
|
}
|
||||||
|
8
src/Faction/FactionHelpers.d.ts
vendored
8
src/Faction/FactionHelpers.d.ts
vendored
@ -1,8 +0,0 @@
|
|||||||
import { Augmentation } from "../Augmentation/Augmentation";
|
|
||||||
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 joinFaction(faction: Faction): void;
|
|
||||||
export declare function startHackingMission(faction: Faction): void;
|
|
@ -1,4 +1,5 @@
|
|||||||
import { Augmentations } from "../Augmentation/Augmentations";
|
import { Augmentations } from "../Augmentation/Augmentations";
|
||||||
|
import { Augmentation } from "../Augmentation/Augmentation";
|
||||||
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
||||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
@ -20,7 +21,7 @@ import { dialogBoxCreate } from "../../utils/DialogBox";
|
|||||||
import { createPopup } from "../ui/React/createPopup";
|
import { createPopup } from "../ui/React/createPopup";
|
||||||
import { InvitationPopup } from "./ui/InvitationPopup";
|
import { InvitationPopup } from "./ui/InvitationPopup";
|
||||||
|
|
||||||
export function inviteToFaction(faction) {
|
export function inviteToFaction(faction: Faction): void {
|
||||||
Player.factionInvitations.push(faction.name);
|
Player.factionInvitations.push(faction.name);
|
||||||
faction.alreadyInvited = true;
|
faction.alreadyInvited = true;
|
||||||
if (!Settings.SuppressFactionInvites) {
|
if (!Settings.SuppressFactionInvites) {
|
||||||
@ -33,7 +34,7 @@ export function inviteToFaction(faction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function joinFaction(faction) {
|
export function joinFaction(faction: Faction): void {
|
||||||
if (faction.isMember) return;
|
if (faction.isMember) return;
|
||||||
faction.isMember = true;
|
faction.isMember = true;
|
||||||
Player.factions.push(faction.name);
|
Player.factions.push(faction.name);
|
||||||
@ -54,7 +55,7 @@ export function joinFaction(faction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function startHackingMission(faction) {
|
export function startHackingMission(faction: Faction): void {
|
||||||
const mission = new HackingMission(faction.playerReputation, faction);
|
const mission = new HackingMission(faction.playerReputation, faction);
|
||||||
setInMission(true, mission); //Sets inMission flag to true
|
setInMission(true, mission); //Sets inMission flag to true
|
||||||
mission.init();
|
mission.init();
|
||||||
@ -62,7 +63,7 @@ export function startHackingMission(faction) {
|
|||||||
|
|
||||||
//Returns a boolean indicating whether the player has the prerequisites for the
|
//Returns a boolean indicating whether the player has the prerequisites for the
|
||||||
//specified Augmentation
|
//specified Augmentation
|
||||||
export function hasAugmentationPrereqs(aug) {
|
export function hasAugmentationPrereqs(aug: Augmentation): boolean {
|
||||||
let hasPrereqs = true;
|
let hasPrereqs = true;
|
||||||
if (aug.prereqs && aug.prereqs.length > 0) {
|
if (aug.prereqs && aug.prereqs.length > 0) {
|
||||||
for (let i = 0; i < aug.prereqs.length; ++i) {
|
for (let i = 0; i < aug.prereqs.length; ++i) {
|
||||||
@ -88,7 +89,7 @@ export function hasAugmentationPrereqs(aug) {
|
|||||||
return hasPrereqs;
|
return hasPrereqs;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purchaseAugmentation(aug, fac, sing = false) {
|
export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = false): string {
|
||||||
const factionInfo = fac.getInfo();
|
const factionInfo = fac.getInfo();
|
||||||
var hasPrereqs = hasAugmentationPrereqs(aug);
|
var hasPrereqs = hasAugmentationPrereqs(aug);
|
||||||
if (!hasPrereqs) {
|
if (!hasPrereqs) {
|
||||||
@ -111,13 +112,6 @@ export function purchaseAugmentation(aug, fac, sing = false) {
|
|||||||
}
|
}
|
||||||
dialogBoxCreate(txt);
|
dialogBoxCreate(txt);
|
||||||
} else if (aug.baseCost === 0 || Player.money.gte(aug.baseCost * factionInfo.augmentationPriceMult)) {
|
} else if (aug.baseCost === 0 || Player.money.gte(aug.baseCost * factionInfo.augmentationPriceMult)) {
|
||||||
if (Player.firstAugPurchased === false) {
|
|
||||||
Player.firstAugPurchased = true;
|
|
||||||
document.getElementById("augmentations-tab").style.display = "list-item";
|
|
||||||
document.getElementById("character-menu-header").click();
|
|
||||||
document.getElementById("character-menu-header").click();
|
|
||||||
}
|
|
||||||
|
|
||||||
var queuedAugmentation = new PlayerOwnedAugmentation(aug.name);
|
var queuedAugmentation = new PlayerOwnedAugmentation(aug.name);
|
||||||
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
|
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
|
||||||
queuedAugmentation.level = getNextNeurofluxLevel();
|
queuedAugmentation.level = getNextNeurofluxLevel();
|
||||||
@ -166,9 +160,10 @@ export function purchaseAugmentation(aug, fac, sing = false) {
|
|||||||
"reproduce this.",
|
"reproduce this.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNextNeurofluxLevel() {
|
export function getNextNeurofluxLevel(): number {
|
||||||
// Get current Neuroflux level based on Player's augmentations
|
// Get current Neuroflux level based on Player's augmentations
|
||||||
let currLevel = 0;
|
let currLevel = 0;
|
||||||
for (var i = 0; i < Player.augmentations.length; ++i) {
|
for (var i = 0; i < Player.augmentations.length; ++i) {
|
||||||
@ -186,7 +181,7 @@ export function getNextNeurofluxLevel() {
|
|||||||
return currLevel + 1;
|
return currLevel + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function processPassiveFactionRepGain(numCycles) {
|
export function processPassiveFactionRepGain(numCycles: number): void {
|
||||||
for (const name in Factions) {
|
for (const name in Factions) {
|
||||||
if (name === Player.currentWorkFactionName) continue;
|
if (name === Player.currentWorkFactionName) continue;
|
||||||
if (!Factions.hasOwnProperty(name)) continue;
|
if (!Factions.hasOwnProperty(name)) continue;
|
2
src/Fconf/Fconf.d.ts
vendored
2
src/Fconf/Fconf.d.ts
vendored
@ -1,2 +0,0 @@
|
|||||||
export declare function parseFconfSettings(config: string): void;
|
|
||||||
export declare function createFconf(): string;
|
|
@ -1,268 +0,0 @@
|
|||||||
import { FconfSettings } from "./FconfSettings";
|
|
||||||
|
|
||||||
import { parse, Node } from "acorn";
|
|
||||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
|
||||||
|
|
||||||
var FconfComments = {
|
|
||||||
ENABLE_BASH_HOTKEYS:
|
|
||||||
"Improved Bash emulation mode. Setting this to 1 enables several\n" +
|
|
||||||
"new Terminal shortcuts and features that more closely resemble\n" +
|
|
||||||
"a real Bash-style shell. Note that when this mode is enabled,\n" +
|
|
||||||
"the default browser shortcuts are overriden by the new Bash\n" +
|
|
||||||
"shortcuts.\n\n" +
|
|
||||||
"To see a full list of the Terminal shortcuts that this enables, see:\n" +
|
|
||||||
"http://bitburner.readthedocs.io/en/latest/shortcuts.html",
|
|
||||||
ENABLE_TIMESTAMPS:
|
|
||||||
"Terminal commands and log entries will be timestamped. The timestamp\n" + "will have the format: M/D h:m",
|
|
||||||
MAIN_MENU_STYLE:
|
|
||||||
"Customize the main navigation menu on the left-hand side. Current options:\n\n" + "default, classic, compact",
|
|
||||||
THEME_BACKGROUND_COLOR:
|
|
||||||
"Sets the background color for not only the Terminal, but also for\n" +
|
|
||||||
"most of the game's UI.\n\n" +
|
|
||||||
"The color must be specified as a pound sign (#) followed by a \n" +
|
|
||||||
"3-digit or 6-digit hex color code (e.g. #123456). Default color: #000000",
|
|
||||||
THEME_FONT_COLOR:
|
|
||||||
"Sets the font color for not only the Terminal, but also for\n" +
|
|
||||||
"most of the game's UI.\n\n" +
|
|
||||||
"The color must be specified as a pound sign (#) followed by a \n" +
|
|
||||||
"3-digit or 6-digit hex color code (e.g. #123456). Default color: #66ff33",
|
|
||||||
THEME_HIGHLIGHT_COLOR:
|
|
||||||
"Sets the highlight color for not only the Terminal, but also for \n" +
|
|
||||||
"most of the game's UI.\n\n" +
|
|
||||||
"The color must be specified as a pound sign (#) followed by a \n" +
|
|
||||||
"3-digit or 6-digit hex color code (e.g. #123456). Default color: #ffffff",
|
|
||||||
THEME_PROMPT_COLOR:
|
|
||||||
"Sets the prompt color in the Terminal\n\n" +
|
|
||||||
"The color must be specified as a pound sign (#) followed by a \n" +
|
|
||||||
"3-digit or 6-digit hex color code (e.g. #123456). Default color: #f92672",
|
|
||||||
WRAP_INPUT:
|
|
||||||
"Wrap Terminal Input. If this is enabled, then when a Terminal command is\n" +
|
|
||||||
"too long and overflows, then it will wrap to the next line instead of\n" +
|
|
||||||
"side-scrolling\n\n" +
|
|
||||||
"Note that after you enable/disable this, you'll have to run a command\n" +
|
|
||||||
"before its effect takes place.",
|
|
||||||
};
|
|
||||||
|
|
||||||
const MainMenuStyleOptions = ["default", "classic", "compact"];
|
|
||||||
|
|
||||||
//Parse Fconf settings from the config text
|
|
||||||
//Throws an exception if parsing fails
|
|
||||||
function parseFconfSettings(config) {
|
|
||||||
var ast = parse(config, { sourceType: "module" });
|
|
||||||
var queue = [];
|
|
||||||
queue.push(ast);
|
|
||||||
while (queue.length != 0) {
|
|
||||||
var exp = queue.shift();
|
|
||||||
switch (exp.type) {
|
|
||||||
case "BlockStatement":
|
|
||||||
case "Program":
|
|
||||||
for (var i = 0; i < exp.body.length; ++i) {
|
|
||||||
if (exp.body[i] instanceof Node) {
|
|
||||||
queue.push(exp.body[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "AssignmentExpression":
|
|
||||||
var setting, value;
|
|
||||||
if (exp.left != null && exp.left.name != null) {
|
|
||||||
setting = exp.left.name;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (exp.right != null && exp.right.raw != null) {
|
|
||||||
value = exp.right.raw;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
parseFconfSetting(setting, value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var prop in exp) {
|
|
||||||
if (exp.hasOwnProperty(prop)) {
|
|
||||||
if (exp[prop] instanceof Node) {
|
|
||||||
queue.push(exp[prop]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setTheme();
|
|
||||||
setMainMenuStyle();
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseFconfSetting(setting, value) {
|
|
||||||
setting = String(setting);
|
|
||||||
value = String(value);
|
|
||||||
if (setting == null || value == null || FconfSettings[setting] == null) {
|
|
||||||
console.warn(`Invalid .fconf setting: ${setting}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sanitizeString(value) {
|
|
||||||
value = value.toLowerCase();
|
|
||||||
if (value.startsWith('"')) {
|
|
||||||
value = value.slice(1);
|
|
||||||
}
|
|
||||||
if (value.endsWith('"')) {
|
|
||||||
value = value.slice(0, -1);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (setting) {
|
|
||||||
case "ENABLE_BASH_HOTKEYS":
|
|
||||||
case "ENABLE_TIMESTAMPS":
|
|
||||||
case "WRAP_INPUT":
|
|
||||||
// Need to convert entered value to boolean/strings accordingly
|
|
||||||
var value = value.toLowerCase();
|
|
||||||
if (value === "1" || value === "true" || value === "y") {
|
|
||||||
value = true;
|
|
||||||
} else {
|
|
||||||
value = false;
|
|
||||||
}
|
|
||||||
FconfSettings[setting] = value;
|
|
||||||
break;
|
|
||||||
case "MAIN_MENU_STYLE":
|
|
||||||
var value = sanitizeString(value);
|
|
||||||
if (MainMenuStyleOptions.includes(value)) {
|
|
||||||
FconfSettings[setting] = value;
|
|
||||||
} else {
|
|
||||||
dialogBoxCreate(`Invalid option specified for ${setting}. Options: ${MainMenuStyleOptions.toString()}`);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "THEME_BACKGROUND_COLOR":
|
|
||||||
case "THEME_FONT_COLOR":
|
|
||||||
case "THEME_HIGHLIGHT_COLOR":
|
|
||||||
case "THEME_PROMPT_COLOR":
|
|
||||||
var value = sanitizeString(value);
|
|
||||||
if (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value)) {
|
|
||||||
FconfSettings[setting] = value;
|
|
||||||
} else {
|
|
||||||
dialogBoxCreate(`Invalid color specified for ${setting}. Must be a hex color code preceded by a pound (#)`);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create the .fconf file text from the settings
|
|
||||||
function createFconf() {
|
|
||||||
var res = "";
|
|
||||||
for (var setting in FconfSettings) {
|
|
||||||
if (FconfSettings.hasOwnProperty(setting)) {
|
|
||||||
//Setting comments (description)
|
|
||||||
var comment = FconfComments[setting];
|
|
||||||
if (comment == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var comment = comment.split("\n");
|
|
||||||
for (var i = 0; i < comment.length; ++i) {
|
|
||||||
res += "//" + comment[i] + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
var value = 0;
|
|
||||||
if (FconfSettings[setting] === true) {
|
|
||||||
value = "1";
|
|
||||||
} else if (FconfSettings[setting] === false) {
|
|
||||||
value = "0";
|
|
||||||
} else {
|
|
||||||
value = '"' + String(FconfSettings[setting]) + '"';
|
|
||||||
}
|
|
||||||
res += `${setting} = ${value}\n\n`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadFconf(saveString) {
|
|
||||||
let tempFconfSettings = JSON.parse(saveString);
|
|
||||||
for (var setting in tempFconfSettings) {
|
|
||||||
if (tempFconfSettings.hasOwnProperty(setting)) {
|
|
||||||
FconfSettings[setting] = tempFconfSettings[setting];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize themes/styles after loading
|
|
||||||
setTheme();
|
|
||||||
setMainMenuStyle();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTheme() {
|
|
||||||
if (
|
|
||||||
FconfSettings.THEME_HIGHLIGHT_COLOR == null ||
|
|
||||||
FconfSettings.THEME_FONT_COLOR == null ||
|
|
||||||
FconfSettings.THEME_BACKGROUND_COLOR == null ||
|
|
||||||
FconfSettings.THEME_PROMPT_COLOR == null
|
|
||||||
) {
|
|
||||||
console.error("Cannot find Theme Settings");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_HIGHLIGHT_COLOR) &&
|
|
||||||
/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_FONT_COLOR) &&
|
|
||||||
/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_BACKGROUND_COLOR) &&
|
|
||||||
/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_PROMPT_COLOR)
|
|
||||||
) {
|
|
||||||
// document.body.style.setProperty("--my-highlight-color", FconfSettings.THEME_HIGHLIGHT_COLOR);
|
|
||||||
// document.body.style.setProperty("--my-font-color", FconfSettings.THEME_FONT_COLOR);
|
|
||||||
// document.body.style.setProperty("--my-background-color", FconfSettings.THEME_BACKGROUND_COLOR);
|
|
||||||
// document.body.style.setProperty("--my-prompt-color", FconfSettings.THEME_PROMPT_COLOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMainMenuStyle() {
|
|
||||||
const mainMenu = document.getElementById("mainmenu");
|
|
||||||
const hackingMenuHdr = document.getElementById("hacking-menu-header");
|
|
||||||
const characterMenuHdr = document.getElementById("character-menu-header");
|
|
||||||
const worldMenuHdr = document.getElementById("world-menu-header");
|
|
||||||
const helpMenuHdr = document.getElementById("help-menu-header");
|
|
||||||
|
|
||||||
function removeAllAccordionHeaderClasses() {
|
|
||||||
hackingMenuHdr.classList.remove("mainmenu-accordion-header", "mainmenu-accordion-header-classic");
|
|
||||||
characterMenuHdr.classList.remove("mainmenu-accordion-header", "mainmenu-accordion-header-classic");
|
|
||||||
worldMenuHdr.classList.remove("mainmenu-accordion-header", "mainmenu-accordion-header-classic");
|
|
||||||
helpMenuHdr.classList.remove("mainmenu-accordion-header", "mainmenu-accordion-header-classic");
|
|
||||||
}
|
|
||||||
|
|
||||||
function addClassToAllAccordionHeaders(clsName) {
|
|
||||||
hackingMenuHdr.classList.add(clsName);
|
|
||||||
characterMenuHdr.classList.add(clsName);
|
|
||||||
worldMenuHdr.classList.add(clsName);
|
|
||||||
helpMenuHdr.classList.add(clsName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FconfSettings["MAIN_MENU_STYLE"] === "default") {
|
|
||||||
removeAllAccordionHeaderClasses();
|
|
||||||
mainMenu.classList.remove("classic");
|
|
||||||
mainMenu.classList.remove("compact");
|
|
||||||
addClassToAllAccordionHeaders("mainmenu-accordion-header");
|
|
||||||
} else if (FconfSettings["MAIN_MENU_STYLE"] === "classic") {
|
|
||||||
removeAllAccordionHeaderClasses();
|
|
||||||
mainMenu.classList.remove("compact");
|
|
||||||
mainMenu.classList.add("classic");
|
|
||||||
addClassToAllAccordionHeaders("mainmenu-accordion-header-classic");
|
|
||||||
} else if (FconfSettings["MAIN_MENU_STYLE"] === "compact") {
|
|
||||||
removeAllAccordionHeaderClasses();
|
|
||||||
mainMenu.classList.remove("classic");
|
|
||||||
mainMenu.classList.add("compact");
|
|
||||||
addClassToAllAccordionHeaders("mainmenu-accordion-header-compact");
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Click each header twice to reset lol
|
|
||||||
hackingMenuHdr.click();
|
|
||||||
hackingMenuHdr.click();
|
|
||||||
characterMenuHdr.click();
|
|
||||||
characterMenuHdr.click();
|
|
||||||
worldMenuHdr.click();
|
|
||||||
worldMenuHdr.click();
|
|
||||||
helpMenuHdr.click();
|
|
||||||
helpMenuHdr.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
export { FconfSettings, createFconf, parseFconfSettings, loadFconf };
|
|
@ -1,10 +0,0 @@
|
|||||||
export const FconfSettings = {
|
|
||||||
ENABLE_BASH_HOTKEYS: false,
|
|
||||||
ENABLE_TIMESTAMPS: false,
|
|
||||||
MAIN_MENU_STYLE: "default",
|
|
||||||
THEME_BACKGROUND_COLOR: "#000000",
|
|
||||||
THEME_FONT_COLOR: "#66ff33",
|
|
||||||
THEME_HIGHLIGHT_COLOR: "#ffffff",
|
|
||||||
THEME_PROMPT_COLOR: "#f92672",
|
|
||||||
WRAP_INPUT: false,
|
|
||||||
};
|
|
@ -8,13 +8,13 @@ import { use } from "../../ui/Context";
|
|||||||
import { Factions } from "../../Faction/Factions";
|
import { Factions } from "../../Faction/Factions";
|
||||||
import { Gang } from "../Gang";
|
import { Gang } from "../Gang";
|
||||||
|
|
||||||
interface IProps {
|
export function GangRoot(): React.ReactElement {
|
||||||
gang: Gang;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function GangRoot(props: IProps): React.ReactElement {
|
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
const router = use.Router();
|
const router = use.Router();
|
||||||
|
const gang = (function () {
|
||||||
|
if (player.gang === null) throw new Error("Gang should not be null");
|
||||||
|
return player.gang;
|
||||||
|
})();
|
||||||
const [management, setManagement] = useState(true);
|
const [management, setManagement] = useState(true);
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ export function GangRoot(props: IProps): React.ReactElement {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
function back(): void {
|
function back(): void {
|
||||||
router.toFaction(Factions[props.gang.facName]);
|
router.toFaction(Factions[gang.facName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -46,7 +46,7 @@ export function GangRoot(props: IProps): React.ReactElement {
|
|||||||
>
|
>
|
||||||
Gang Territory
|
Gang Territory
|
||||||
</a>
|
</a>
|
||||||
{management ? <ManagementSubpage gang={props.gang} player={player} /> : <TerritorySubpage gang={props.gang} />}
|
{management ? <ManagementSubpage gang={gang} player={player} /> : <TerritorySubpage gang={gang} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -479,13 +479,12 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Sell for Corporation Funds": {
|
case "Sell for Corporation Funds": {
|
||||||
// This will throw if player doesn't have a corporation
|
const corp = player.corporation;
|
||||||
try {
|
if (corp === null) {
|
||||||
player.corporation.funds = player.corporation.funds.plus(upg.value);
|
|
||||||
} catch (e) {
|
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
corp.funds = corp.funds.plus(upg.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Reduce Minimum Security": {
|
case "Reduce Minimum Security": {
|
||||||
@ -530,36 +529,35 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
}
|
}
|
||||||
case "Exchange for Corporation Research": {
|
case "Exchange for Corporation Research": {
|
||||||
// This will throw if player doesn't have a corporation
|
// This will throw if player doesn't have a corporation
|
||||||
try {
|
const corp = player.corporation;
|
||||||
for (const division of player.corporation.divisions) {
|
if (corp === null) {
|
||||||
division.sciResearch.qty += upg.value;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
for (const division of corp.divisions) {
|
||||||
|
division.sciResearch.qty += upg.value;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Exchange for Bladeburner Rank": {
|
case "Exchange for Bladeburner Rank": {
|
||||||
// This will throw if player isnt in Bladeburner
|
// This will throw if player isnt in Bladeburner
|
||||||
try {
|
const bladeburner = player.bladeburner;
|
||||||
player.bladeburner.changeRank(player, upg.value);
|
if (bladeburner === null) {
|
||||||
} catch (e) {
|
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bladeburner.changeRank(player, upg.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Exchange for Bladeburner SP": {
|
case "Exchange for Bladeburner SP": {
|
||||||
// This will throw if player isn't in Bladeburner
|
// This will throw if player isnt in Bladeburner
|
||||||
try {
|
const bladeburner = player.bladeburner;
|
||||||
// As long as we don't change `Bladeburner.totalSkillPoints`, this
|
if (bladeburner === null) {
|
||||||
// shouldn't affect anything else
|
|
||||||
player.bladeburner.skillPoints += upg.value;
|
|
||||||
} catch (e) {
|
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bladeburner.skillPoints += upg.value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Generate Coding Contract": {
|
case "Generate Coding Contract": {
|
||||||
|
@ -3,32 +3,25 @@
|
|||||||
* to TypeScript at the moment
|
* to TypeScript at the moment
|
||||||
*/
|
*/
|
||||||
export interface IEngine {
|
export interface IEngine {
|
||||||
indexedDb: any;
|
|
||||||
_lastUpdate: number;
|
_lastUpdate: number;
|
||||||
hideAllContent: () => void;
|
updateGame: (numCycles?: number) => void;
|
||||||
loadTerminalContent: () => void;
|
Counters: {
|
||||||
loadScriptEditorContent: (filename?: string, code?: string) => void;
|
[key: string]: number | undefined;
|
||||||
loadActiveScriptsContent: () => void;
|
autoSaveCounter: number;
|
||||||
loadCreateProgramContent: () => void;
|
updateSkillLevelsCounter: number;
|
||||||
loadCharacterContent: () => void;
|
updateDisplays: number;
|
||||||
loadFactionsContent: () => void;
|
updateDisplaysLong: number;
|
||||||
loadAugmentationsContent: () => void;
|
updateActiveScriptsDisplay: number;
|
||||||
loadHacknetNodesContent: () => void;
|
createProgramNotifications: number;
|
||||||
loadSleevesContent: () => void;
|
augmentationsNotifications: number;
|
||||||
loadLocationContent: () => void;
|
checkFactionInvitations: number;
|
||||||
loadTravelContent: () => void;
|
passiveFactionGrowth: number;
|
||||||
loadJobContent: () => void;
|
messages: number;
|
||||||
loadStockMarketContent: () => void;
|
mechanicProcess: number;
|
||||||
loadBladeburnerContent: () => void;
|
contractGeneration: number;
|
||||||
loadCorporationContent: () => void;
|
};
|
||||||
loadGangContent: () => void;
|
decrementAllCounters: (numCycles?: number) => void;
|
||||||
loadMilestonesContent: () => void;
|
checkCounters: () => void;
|
||||||
loadTutorialContent: () => void;
|
load: (saveString: string) => void;
|
||||||
loadDevMenuContent: () => void;
|
start: () => void;
|
||||||
loadFactionContent: () => void;
|
|
||||||
loadInfiltrationContent: (name: string, difficulty: number, maxLevel: number) => void;
|
|
||||||
loadMissionContent: () => void;
|
|
||||||
loadResleevingContent: () => void;
|
|
||||||
loadGameOptionsContent: () => void;
|
|
||||||
load: (save: string) => void;
|
|
||||||
}
|
}
|
||||||
|
1
src/Message/MessageHelpers.d.ts
vendored
1
src/Message/MessageHelpers.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
export declare function showMessage(msg: Message): void;
|
|
@ -11,7 +11,7 @@ import { dialogBoxCreate } from "../../utils/DialogBox";
|
|||||||
import { Reviver } from "../../utils/JSONReviver";
|
import { Reviver } from "../../utils/JSONReviver";
|
||||||
|
|
||||||
//Sends message to player, including a pop up
|
//Sends message to player, including a pop up
|
||||||
function sendMessage(msg, forced = false) {
|
function sendMessage(msg: Message, forced = false): void {
|
||||||
msg.recvd = true;
|
msg.recvd = true;
|
||||||
if (forced || !Settings.SuppressMessages) {
|
if (forced || !Settings.SuppressMessages) {
|
||||||
showMessage(msg);
|
showMessage(msg);
|
||||||
@ -19,7 +19,7 @@ function sendMessage(msg, forced = false) {
|
|||||||
addMessageToServer(msg, "home");
|
addMessageToServer(msg, "home");
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMessage(msg) {
|
function showMessage(msg: Message): void {
|
||||||
var txt =
|
var txt =
|
||||||
"Message received from unknown sender: <br><br>" +
|
"Message received from unknown sender: <br><br>" +
|
||||||
"<i>" +
|
"<i>" +
|
||||||
@ -32,14 +32,16 @@ function showMessage(msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Adds a message to a server
|
//Adds a message to a server
|
||||||
function addMessageToServer(msg, serverHostname) {
|
function addMessageToServer(msg: Message, serverHostname: string): void {
|
||||||
var server = GetServerByHostname(serverHostname);
|
var server = GetServerByHostname(serverHostname);
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
console.warn(`Could not find server ${serverHostname}`);
|
console.warn(`Could not find server ${serverHostname}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (var i = 0; i < server.messages.length; ++i) {
|
for (var i = 0; i < server.messages.length; ++i) {
|
||||||
if (server.messages[i].filename === msg.filename) {
|
const msg = server.messages[i];
|
||||||
|
if (typeof msg === "string") continue;
|
||||||
|
if (msg.filename === msg.filename) {
|
||||||
return; //Already exists
|
return; //Already exists
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,13 +97,13 @@ function checkForMessagesToSend() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddToAllMessages(msg) {
|
function AddToAllMessages(msg: Message): void {
|
||||||
Messages[msg.filename] = msg;
|
Messages[msg.filename] = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Messages = {};
|
let Messages: { [key: string]: Message | undefined } = {};
|
||||||
|
|
||||||
function loadMessages(saveString) {
|
function loadMessages(saveString: string): void {
|
||||||
Messages = JSON.parse(saveString, Reviver);
|
Messages = JSON.parse(saveString, Reviver);
|
||||||
}
|
}
|
||||||
|
|
7
src/Missions.d.ts
vendored
7
src/Missions.d.ts
vendored
@ -1 +1,8 @@
|
|||||||
export declare let inMission: boolean;
|
export declare let inMission: boolean;
|
||||||
|
export declare class HackingMission {
|
||||||
|
constructor(reputation: number, faction: Faction);
|
||||||
|
init(): void;
|
||||||
|
process(numCycles: number): void;
|
||||||
|
}
|
||||||
|
export declare function setInMission(inMission: boolean, mission: HackingMission): void;
|
||||||
|
export declare let currMission: HackingMission;
|
||||||
|
@ -68,7 +68,7 @@ export class WorkerScript {
|
|||||||
* Used for static RAM calculation. Stores names of all functions that have
|
* Used for static RAM calculation. Stores names of all functions that have
|
||||||
* already been checked by this script
|
* already been checked by this script
|
||||||
*/
|
*/
|
||||||
loadedFns: IMap<string> = {};
|
loadedFns: IMap<boolean> = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filename of script
|
* Filename of script
|
||||||
|
@ -2,8 +2,9 @@ import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
|||||||
|
|
||||||
import { isString } from "../utils/helpers/isString";
|
import { isString } from "../utils/helpers/isString";
|
||||||
import { AllServers } from "./Server/AllServers";
|
import { AllServers } from "./Server/AllServers";
|
||||||
|
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||||
|
|
||||||
export function netscriptDelay(time, workerScript) {
|
export function netscriptDelay(time: number, workerScript: WorkerScript): Promise<void> {
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
workerScript.delay = setTimeoutRef(() => {
|
workerScript.delay = setTimeoutRef(() => {
|
||||||
workerScript.delay = null;
|
workerScript.delay = null;
|
||||||
@ -13,7 +14,7 @@ export function netscriptDelay(time, workerScript) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeRuntimeRejectMsg(workerScript, msg, exp = null) {
|
export function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string, exp: any = null) {
|
||||||
var lineNum = "";
|
var lineNum = "";
|
||||||
if (exp != null) {
|
if (exp != null) {
|
||||||
var num = getErrorLineNumber(exp, workerScript);
|
var num = getErrorLineNumber(exp, workerScript);
|
||||||
@ -21,13 +22,17 @@ export function makeRuntimeRejectMsg(workerScript, msg, exp = null) {
|
|||||||
}
|
}
|
||||||
const server = AllServers[workerScript.serverIp];
|
const server = AllServers[workerScript.serverIp];
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
throw new Error(`WorkerScript constructed with invalid server ip: ${this.serverIp}`);
|
throw new Error(`WorkerScript constructed with invalid server ip: ${workerScript.serverIp}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "|" + server.hostname + "|" + workerScript.name + "|" + msg + lineNum;
|
return "|" + server.hostname + "|" + workerScript.name + "|" + msg + lineNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveNetscriptRequestedThreads(workerScript, functionName, requestedThreads) {
|
export function resolveNetscriptRequestedThreads(
|
||||||
|
workerScript: WorkerScript,
|
||||||
|
functionName: string,
|
||||||
|
requestedThreads: number,
|
||||||
|
) {
|
||||||
const threads = workerScript.scriptRef.threads;
|
const threads = workerScript.scriptRef.threads;
|
||||||
if (!requestedThreads) {
|
if (!requestedThreads) {
|
||||||
return isNaN(threads) || threads < 1 ? 1 : threads;
|
return isNaN(threads) || threads < 1 ? 1 : threads;
|
||||||
@ -48,19 +53,22 @@ export function resolveNetscriptRequestedThreads(workerScript, functionName, req
|
|||||||
return requestedThreadsAsInt;
|
return requestedThreadsAsInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getErrorLineNumber(exp, workerScript) {
|
export function getErrorLineNumber(exp: any, workerScript: WorkerScript): number {
|
||||||
var code = workerScript.scriptRef.codeCode();
|
return -1;
|
||||||
|
// TODO wtf is codeCode?
|
||||||
|
|
||||||
//Split code up to the start of the node
|
// var code = workerScript.scriptRef.codeCode();
|
||||||
try {
|
|
||||||
code = code.substring(0, exp.start);
|
// //Split code up to the start of the node
|
||||||
return (code.match(/\n/g) || []).length + 1;
|
// try {
|
||||||
} catch (e) {
|
// code = code.substring(0, exp.start);
|
||||||
return -1;
|
// return (code.match(/\n/g) || []).length + 1;
|
||||||
}
|
// } catch (e) {
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isScriptErrorMessage(msg) {
|
export function isScriptErrorMessage(msg: string): boolean {
|
||||||
if (!isString(msg)) {
|
if (!isString(msg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
@ -103,7 +103,8 @@ import { Player } from "./Player";
|
|||||||
import { Programs } from "./Programs/Programs";
|
import { Programs } from "./Programs/Programs";
|
||||||
import { Script } from "./Script/Script";
|
import { Script } from "./Script/Script";
|
||||||
import { findRunningScript, findRunningScriptByPid } from "./Script/ScriptHelpers";
|
import { findRunningScript, findRunningScriptByPid } from "./Script/ScriptHelpers";
|
||||||
import { isScriptFilename } from "./Script/ScriptHelpersTS";
|
import { isScriptFilename } from "./Script/isScriptFilename";
|
||||||
|
|
||||||
import { AllServers, AddToAllServers, createUniqueRandomIp } from "./Server/AllServers";
|
import { AllServers, AddToAllServers, createUniqueRandomIp } from "./Server/AllServers";
|
||||||
import { RunningScript } from "./Script/RunningScript";
|
import { RunningScript } from "./Script/RunningScript";
|
||||||
import {
|
import {
|
||||||
@ -132,7 +133,7 @@ import { NetscriptPorts, runScriptFromScript, startWorkerScript } from "./Netscr
|
|||||||
import { killWorkerScript } from "./Netscript/killWorkerScript";
|
import { killWorkerScript } from "./Netscript/killWorkerScript";
|
||||||
import { workerScripts } from "./Netscript/WorkerScripts";
|
import { workerScripts } from "./Netscript/WorkerScripts";
|
||||||
import { makeRuntimeRejectMsg, netscriptDelay, resolveNetscriptRequestedThreads } from "./NetscriptEvaluator";
|
import { makeRuntimeRejectMsg, netscriptDelay, resolveNetscriptRequestedThreads } from "./NetscriptEvaluator";
|
||||||
import { Interpreter } from "./JSInterpreter";
|
import { Interpreter } from "./ThirdParty/JSInterpreter";
|
||||||
import { NetscriptPort } from "./NetscriptPort";
|
import { NetscriptPort } from "./NetscriptPort";
|
||||||
import { SleeveTaskType } from "./PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
import { SleeveTaskType } from "./PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
||||||
import { findSleevePurchasableAugs } from "./PersonObjects/Sleeve/SleeveHelpers";
|
import { findSleevePurchasableAugs } from "./PersonObjects/Sleeve/SleeveHelpers";
|
||||||
@ -3808,7 +3809,7 @@ function NetscriptFunctions(workerScript) {
|
|||||||
throw makeRuntimeErrorMsg("commitCrime", `Invalid crime: '${crimeRoughName}'`);
|
throw makeRuntimeErrorMsg("commitCrime", `Invalid crime: '${crimeRoughName}'`);
|
||||||
}
|
}
|
||||||
workerScript.log("commitCrime", `Attempting to commit ${crime.name}...`);
|
workerScript.log("commitCrime", `Attempting to commit ${crime.name}...`);
|
||||||
return crime.commit(Router, Player, 1, { workerscript: workerScript });
|
return crime.commit(Router, Player, 1, workerScript);
|
||||||
},
|
},
|
||||||
getCrimeChance: function (crimeRoughName) {
|
getCrimeChance: function (crimeRoughName) {
|
||||||
updateDynamicRam("getCrimeChance", getRamCost("getCrimeChance"));
|
updateDynamicRam("getCrimeChance", getRamCost("getCrimeChance"));
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
import { makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
||||||
import { ScriptUrl } from "./Script/ScriptUrl";
|
import { ScriptUrl } from "./Script/ScriptUrl";
|
||||||
|
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||||
|
import { Script } from "./Script/Script";
|
||||||
|
|
||||||
// Makes a blob that contains the code of a given script.
|
// Makes a blob that contains the code of a given script.
|
||||||
function makeScriptBlob(code) {
|
function makeScriptBlob(code: string): Blob {
|
||||||
return new Blob([code], { type: "text/javascript" });
|
return new Blob([code], { type: "text/javascript" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,10 +16,11 @@ function makeScriptBlob(code) {
|
|||||||
// (i.e. hack, grow, etc.).
|
// (i.e. hack, grow, etc.).
|
||||||
// When the promise returned by this resolves, we'll have finished
|
// When the promise returned by this resolves, we'll have finished
|
||||||
// running the main function of the script.
|
// running the main function of the script.
|
||||||
export async function executeJSScript(scripts = [], workerScript) {
|
export async function executeJSScript(scripts: Script[] = [], workerScript: WorkerScript) {
|
||||||
let loadedModule;
|
let loadedModule;
|
||||||
let urls = null;
|
let uurls: ScriptUrl[] = [];
|
||||||
let script = workerScript.getScript();
|
let script = workerScript.getScript();
|
||||||
|
if (script === null) throw new Error("script is null");
|
||||||
if (shouldCompile(script, scripts)) {
|
if (shouldCompile(script, scripts)) {
|
||||||
// The URL at the top is the one we want to import. It will
|
// The URL at the top is the one we want to import. It will
|
||||||
// recursively import all the other modules in the urlStack.
|
// recursively import all the other modules in the urlStack.
|
||||||
@ -27,31 +30,24 @@ export async function executeJSScript(scripts = [], workerScript) {
|
|||||||
// load fully dynamic content. So we hide the import from webpack
|
// load fully dynamic content. So we hide the import from webpack
|
||||||
// by placing it inside an eval call.
|
// by placing it inside an eval call.
|
||||||
script.markUpdated();
|
script.markUpdated();
|
||||||
urls = _getScriptUrls(script, scripts, []);
|
uurls = _getScriptUrls(script, scripts, []);
|
||||||
script.url = urls[urls.length - 1].url;
|
script.url = uurls[uurls.length - 1].url;
|
||||||
script.module = new Promise((resolve) => resolve(eval("import(urls[urls.length - 1].url)")));
|
script.module = new Promise((resolve) => resolve(eval("import(uurls[uurls.length - 1].url)")));
|
||||||
script.dependencies = urls;
|
script.dependencies = uurls;
|
||||||
}
|
}
|
||||||
loadedModule = await script.module;
|
loadedModule = await script.module;
|
||||||
|
|
||||||
let ns = workerScript.env.vars;
|
let ns = workerScript.env.vars;
|
||||||
|
|
||||||
try {
|
// TODO: putting await in a non-async function yields unhelpful
|
||||||
// TODO: putting await in a non-async function yields unhelpful
|
// "SyntaxError: unexpected reserved word" with no line number information.
|
||||||
// "SyntaxError: unexpected reserved word" with no line number information.
|
if (!loadedModule.main) {
|
||||||
if (!loadedModule.main) {
|
throw makeRuntimeRejectMsg(
|
||||||
throw makeRuntimeRejectMsg(
|
workerScript,
|
||||||
workerScript,
|
`${script.filename} cannot be run because it does not have a main function.`,
|
||||||
`${script.filename} cannot be run because it does not have a main function.`,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
return loadedModule.main(ns);
|
|
||||||
} finally {
|
|
||||||
// Revoke the generated URLs
|
|
||||||
if (urls != null) {
|
|
||||||
for (const b in urls) URL.revokeObjectURL(b.url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return loadedModule.main(ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether we should compile the script parameter.
|
/** Returns whether we should compile the script parameter.
|
||||||
@ -59,7 +55,7 @@ export async function executeJSScript(scripts = [], workerScript) {
|
|||||||
* @param {Script} script
|
* @param {Script} script
|
||||||
* @param {Script[]} scripts
|
* @param {Script[]} scripts
|
||||||
*/
|
*/
|
||||||
function shouldCompile(script, scripts) {
|
function shouldCompile(script: Script, scripts: Script[]): boolean {
|
||||||
if (script.module === "") return true;
|
if (script.module === "") return true;
|
||||||
return script.dependencies.some((dep) => {
|
return script.dependencies.some((dep) => {
|
||||||
const depScript = scripts.find((s) => s.filename == dep.filename);
|
const depScript = scripts.find((s) => s.filename == dep.filename);
|
||||||
@ -93,7 +89,7 @@ function shouldCompile(script, scripts) {
|
|||||||
* the script parameter.
|
* the script parameter.
|
||||||
*/
|
*/
|
||||||
// BUG: apparently seen is never consulted. Oops.
|
// BUG: apparently seen is never consulted. Oops.
|
||||||
function _getScriptUrls(script, scripts, seen) {
|
function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): ScriptUrl[] {
|
||||||
// Inspired by: https://stackoverflow.com/a/43834063/91401
|
// Inspired by: https://stackoverflow.com/a/43834063/91401
|
||||||
/** @type {ScriptUrl[]} */
|
/** @type {ScriptUrl[]} */
|
||||||
const urlStack = [];
|
const urlStack = [];
|
@ -1,6 +1,14 @@
|
|||||||
import { Settings } from "./Settings/Settings";
|
import { Settings } from "./Settings/Settings";
|
||||||
|
|
||||||
interface IPort {}
|
export interface IPort {
|
||||||
|
write: (value: any) => any;
|
||||||
|
tryWrite: (value: any) => boolean;
|
||||||
|
read: () => any;
|
||||||
|
peek: () => any;
|
||||||
|
full: () => boolean;
|
||||||
|
empty: () => boolean;
|
||||||
|
clear: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
export function NetscriptPort(): IPort {
|
export function NetscriptPort(): IPort {
|
||||||
const data: any[] = [];
|
const data: any[] = [];
|
||||||
|
1
src/NetscriptWorker.d.ts
vendored
1
src/NetscriptWorker.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
export declare function startWorkerScript(script: RunningScript, server: BaseServer): boolean;
|
|
@ -9,16 +9,19 @@ import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStart
|
|||||||
import { generateNextPid } from "./Netscript/Pid";
|
import { generateNextPid } from "./Netscript/Pid";
|
||||||
|
|
||||||
import { CONSTANTS } from "./Constants";
|
import { CONSTANTS } from "./Constants";
|
||||||
import { Interpreter } from "./JSInterpreter";
|
import { Interpreter } from "./ThirdParty/JSInterpreter";
|
||||||
import { isScriptErrorMessage, makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
import { isScriptErrorMessage, makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
||||||
import { NetscriptFunctions } from "./NetscriptFunctions";
|
import { NetscriptFunctions } from "./NetscriptFunctions";
|
||||||
import { executeJSScript } from "./NetscriptJSEvaluator";
|
import { executeJSScript } from "./NetscriptJSEvaluator";
|
||||||
import { NetscriptPort } from "./NetscriptPort";
|
import { NetscriptPort, IPort } from "./NetscriptPort";
|
||||||
import { Player } from "./Player";
|
import { Player } from "./Player";
|
||||||
import { RunningScript } from "./Script/RunningScript";
|
import { RunningScript } from "./Script/RunningScript";
|
||||||
import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers";
|
import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers";
|
||||||
import { scriptCalculateOfflineProduction } from "./Script/ScriptHelpers";
|
import { scriptCalculateOfflineProduction } from "./Script/ScriptHelpers";
|
||||||
|
import { Script } from "./Script/Script";
|
||||||
import { AllServers } from "./Server/AllServers";
|
import { AllServers } from "./Server/AllServers";
|
||||||
|
import { Server } from "./Server/Server";
|
||||||
|
import { BaseServer } from "./Server/BaseServer";
|
||||||
import { Settings } from "./Settings/Settings";
|
import { Settings } from "./Settings/Settings";
|
||||||
import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
||||||
|
|
||||||
@ -28,12 +31,13 @@ import { dialogBoxCreate } from "../utils/DialogBox";
|
|||||||
import { arrayToString } from "../utils/helpers/arrayToString";
|
import { arrayToString } from "../utils/helpers/arrayToString";
|
||||||
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
||||||
import { isString } from "../utils/helpers/isString";
|
import { isString } from "../utils/helpers/isString";
|
||||||
|
import { sprintf } from "sprintf-js";
|
||||||
|
|
||||||
import { parse } from "acorn";
|
import { parse } from "acorn";
|
||||||
import { simple as walksimple } from "acorn-walk";
|
import { simple as walksimple } from "acorn-walk";
|
||||||
|
|
||||||
// Netscript Ports are instantiated here
|
// Netscript Ports are instantiated here
|
||||||
export const NetscriptPorts = [];
|
export const NetscriptPorts: IPort[] = [];
|
||||||
for (var i = 0; i < CONSTANTS.NumNetscriptPorts; ++i) {
|
for (var i = 0; i < CONSTANTS.NumNetscriptPorts; ++i) {
|
||||||
NetscriptPorts.push(NetscriptPort());
|
NetscriptPorts.push(NetscriptPort());
|
||||||
}
|
}
|
||||||
@ -51,20 +55,20 @@ export function prestigeWorkerScripts() {
|
|||||||
// JS script promises need a little massaging to have the same guarantees as netscript
|
// JS script promises need a little massaging to have the same guarantees as netscript
|
||||||
// promises. This does said massaging and kicks the script off. It returns a promise
|
// promises. This does said massaging and kicks the script off. It returns a promise
|
||||||
// that resolves or rejects when the corresponding worker script is done.
|
// that resolves or rejects when the corresponding worker script is done.
|
||||||
function startNetscript2Script(workerScript) {
|
function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript> {
|
||||||
workerScript.running = true;
|
workerScript.running = true;
|
||||||
|
|
||||||
// The name of the currently running netscript function, to prevent concurrent
|
// The name of the currently running netscript function, to prevent concurrent
|
||||||
// calls to hack, grow, etc.
|
// calls to hack, grow, etc.
|
||||||
let runningFn = null;
|
let runningFn: string | null = null;
|
||||||
|
|
||||||
// We need to go through the environment and wrap each function in such a way that it
|
// We need to go through the environment and wrap each function in such a way that it
|
||||||
// can be called at most once at a time. This will prevent situations where multiple
|
// can be called at most once at a time. This will prevent situations where multiple
|
||||||
// hack promises are outstanding, for example.
|
// hack promises are outstanding, for example.
|
||||||
function wrap(propName, f) {
|
function wrap(propName: string, f: Function): Function {
|
||||||
// This function unfortunately cannot be an async function, because we don't
|
// This function unfortunately cannot be an async function, because we don't
|
||||||
// know if the original one was, and there's no way to tell.
|
// know if the original one was, and there's no way to tell.
|
||||||
return function (...args) {
|
return function (...args: any[]) {
|
||||||
// Wrap every netscript function with a check for the stop flag.
|
// Wrap every netscript function with a check for the stop flag.
|
||||||
// This prevents cases where we never stop because we are only calling
|
// This prevents cases where we never stop because we are only calling
|
||||||
// netscript functions that don't check this.
|
// netscript functions that don't check this.
|
||||||
@ -115,27 +119,28 @@ function startNetscript2Script(workerScript) {
|
|||||||
|
|
||||||
// Note: the environment that we pass to the JS script only needs to contain the functions visible
|
// Note: the environment that we pass to the JS script only needs to contain the functions visible
|
||||||
// to that script, which env.vars does at this point.
|
// to that script, which env.vars does at this point.
|
||||||
return executeJSScript(workerScript.getServer().scripts, workerScript)
|
return new Promise<WorkerScript>((resolve, reject) => {
|
||||||
.then(function (mainReturnValue) {
|
executeJSScript(workerScript.getServer().scripts, workerScript)
|
||||||
if (mainReturnValue === undefined) return workerScript;
|
.then(() => {
|
||||||
return [mainReturnValue, workerScript];
|
resolve(workerScript);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => reject(e));
|
||||||
if (e instanceof Error) {
|
}).catch((e) => {
|
||||||
workerScript.errorMessage = makeRuntimeRejectMsg(
|
if (e instanceof Error) {
|
||||||
workerScript,
|
workerScript.errorMessage = makeRuntimeRejectMsg(
|
||||||
e.message + ((e.stack && "\nstack:\n" + e.stack.toString()) || ""),
|
workerScript,
|
||||||
);
|
e.message + ((e.stack && "\nstack:\n" + e.stack.toString()) || ""),
|
||||||
throw workerScript;
|
);
|
||||||
} else if (isScriptErrorMessage(e)) {
|
throw workerScript;
|
||||||
workerScript.errorMessage = e;
|
} else if (isScriptErrorMessage(e)) {
|
||||||
throw workerScript;
|
workerScript.errorMessage = e;
|
||||||
}
|
throw workerScript;
|
||||||
throw e; // Don't know what to do with it, let's rethrow.
|
}
|
||||||
});
|
throw e; // Don't know what to do with it, let's rethrow.
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function startNetscript1Script(workerScript) {
|
function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript> {
|
||||||
const code = workerScript.code;
|
const code = workerScript.code;
|
||||||
workerScript.running = true;
|
workerScript.running = true;
|
||||||
|
|
||||||
@ -150,10 +155,10 @@ function startNetscript1Script(workerScript) {
|
|||||||
workerScript.env.stopFlag = true;
|
workerScript.env.stopFlag = true;
|
||||||
workerScript.running = false;
|
workerScript.running = false;
|
||||||
killWorkerScript(workerScript);
|
killWorkerScript(workerScript);
|
||||||
return;
|
return Promise.resolve(workerScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
var interpreterInitialization = function (int, scope) {
|
var interpreterInitialization = function (int: any, scope: any) {
|
||||||
//Add the Netscript environment
|
//Add the Netscript environment
|
||||||
var ns = NetscriptFunctions(workerScript);
|
var ns = NetscriptFunctions(workerScript);
|
||||||
for (let name in ns) {
|
for (let name in ns) {
|
||||||
@ -183,10 +188,10 @@ function startNetscript1Script(workerScript) {
|
|||||||
let cb = arguments[arguments.length - 1];
|
let cb = arguments[arguments.length - 1];
|
||||||
let fnPromise = entry.apply(null, fnArgs);
|
let fnPromise = entry.apply(null, fnArgs);
|
||||||
fnPromise
|
fnPromise
|
||||||
.then(function (res) {
|
.then(function (res: any) {
|
||||||
cb(res);
|
cb(res);
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err: any) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -242,7 +247,7 @@ function startNetscript1Script(workerScript) {
|
|||||||
int.setProperty(scope, "args", int.nativeToPseudo(workerScript.args));
|
int.setProperty(scope, "args", int.nativeToPseudo(workerScript.args));
|
||||||
};
|
};
|
||||||
|
|
||||||
var interpreter;
|
var interpreter: any;
|
||||||
try {
|
try {
|
||||||
interpreter = new Interpreter(codeWithImports, interpreterInitialization, codeLineOffset);
|
interpreter = new Interpreter(codeWithImports, interpreterInitialization, codeLineOffset);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -250,7 +255,7 @@ function startNetscript1Script(workerScript) {
|
|||||||
workerScript.env.stopFlag = true;
|
workerScript.env.stopFlag = true;
|
||||||
workerScript.running = false;
|
workerScript.running = false;
|
||||||
killWorkerScript(workerScript);
|
killWorkerScript(workerScript);
|
||||||
return;
|
return Promise.resolve(workerScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
@ -301,9 +306,9 @@ function startNetscript1Script(workerScript) {
|
|||||||
Should typically be positive
|
Should typically be positive
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
function processNetscript1Imports(code, workerScript) {
|
function processNetscript1Imports(code: string, workerScript: WorkerScript): any {
|
||||||
//allowReserved prevents 'import' from throwing error in ES5
|
//allowReserved prevents 'import' from throwing error in ES5
|
||||||
const ast = parse(code, {
|
const ast: any = parse(code, {
|
||||||
ecmaVersion: 9,
|
ecmaVersion: 9,
|
||||||
allowReserved: true,
|
allowReserved: true,
|
||||||
sourceType: "module",
|
sourceType: "module",
|
||||||
@ -314,7 +319,7 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
throw new Error("Failed to find underlying Server object for script");
|
throw new Error("Failed to find underlying Server object for script");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getScript(scriptName) {
|
function getScript(scriptName: string): Script | null {
|
||||||
for (let i = 0; i < server.scripts.length; ++i) {
|
for (let i = 0; i < server.scripts.length; ++i) {
|
||||||
if (server.scripts[i].filename === scriptName) {
|
if (server.scripts[i].filename === scriptName) {
|
||||||
return server.scripts[i];
|
return server.scripts[i];
|
||||||
@ -328,7 +333,7 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
|
|
||||||
// Walk over the tree and process ImportDeclaration nodes
|
// Walk over the tree and process ImportDeclaration nodes
|
||||||
walksimple(ast, {
|
walksimple(ast, {
|
||||||
ImportDeclaration: (node) => {
|
ImportDeclaration: (node: any) => {
|
||||||
hasImports = true;
|
hasImports = true;
|
||||||
let scriptName = node.source.value;
|
let scriptName = node.source.value;
|
||||||
if (scriptName.startsWith("./")) {
|
if (scriptName.startsWith("./")) {
|
||||||
@ -347,10 +352,10 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
if (node.specifiers.length === 1 && node.specifiers[0].type === "ImportNamespaceSpecifier") {
|
if (node.specifiers.length === 1 && node.specifiers[0].type === "ImportNamespaceSpecifier") {
|
||||||
// import * as namespace from script
|
// import * as namespace from script
|
||||||
let namespace = node.specifiers[0].local.name;
|
let namespace = node.specifiers[0].local.name;
|
||||||
let fnNames = []; //Names only
|
let fnNames: string[] = []; //Names only
|
||||||
let fnDeclarations = []; //FunctionDeclaration Node objects
|
let fnDeclarations: any[] = []; //FunctionDeclaration Node objects
|
||||||
walksimple(scriptAst, {
|
walksimple(scriptAst, {
|
||||||
FunctionDeclaration: (node) => {
|
FunctionDeclaration: (node: any) => {
|
||||||
fnNames.push(node.id.name);
|
fnNames.push(node.id.name);
|
||||||
fnDeclarations.push(node);
|
fnDeclarations.push(node);
|
||||||
},
|
},
|
||||||
@ -360,7 +365,7 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
generatedCode += "var " + namespace + ";\n" + "(function (namespace) {\n";
|
generatedCode += "var " + namespace + ";\n" + "(function (namespace) {\n";
|
||||||
|
|
||||||
//Add the function declarations
|
//Add the function declarations
|
||||||
fnDeclarations.forEach((fn) => {
|
fnDeclarations.forEach((fn: any) => {
|
||||||
generatedCode += generate(fn);
|
generatedCode += generate(fn);
|
||||||
generatedCode += "\n";
|
generatedCode += "\n";
|
||||||
});
|
});
|
||||||
@ -377,15 +382,15 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
//import {...} from script
|
//import {...} from script
|
||||||
|
|
||||||
//Get array of all fns to import
|
//Get array of all fns to import
|
||||||
let fnsToImport = [];
|
let fnsToImport: string[] = [];
|
||||||
node.specifiers.forEach((e) => {
|
node.specifiers.forEach((e: any) => {
|
||||||
fnsToImport.push(e.local.name);
|
fnsToImport.push(e.local.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
//Walk through script and get FunctionDeclaration code for all specified fns
|
//Walk through script and get FunctionDeclaration code for all specified fns
|
||||||
let fnDeclarations = [];
|
let fnDeclarations: any[] = [];
|
||||||
walksimple(scriptAst, {
|
walksimple(scriptAst, {
|
||||||
FunctionDeclaration: (node) => {
|
FunctionDeclaration: (node: any) => {
|
||||||
if (fnsToImport.includes(node.id.name)) {
|
if (fnsToImport.includes(node.id.name)) {
|
||||||
fnDeclarations.push(node);
|
fnDeclarations.push(node);
|
||||||
}
|
}
|
||||||
@ -393,7 +398,7 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Convert FunctionDeclarations into code
|
//Convert FunctionDeclarations into code
|
||||||
fnDeclarations.forEach((fn) => {
|
fnDeclarations.forEach((fn: any) => {
|
||||||
generatedCode += generate(fn);
|
generatedCode += generate(fn);
|
||||||
generatedCode += "\n";
|
generatedCode += "\n";
|
||||||
});
|
});
|
||||||
@ -442,11 +447,11 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
* @param {Server} server - Server on which the script is to be run
|
* @param {Server} server - Server on which the script is to be run
|
||||||
* @returns {number} pid of started script
|
* @returns {number} pid of started script
|
||||||
*/
|
*/
|
||||||
export function startWorkerScript(runningScript, server, parent) {
|
export function startWorkerScript(runningScript: RunningScript, server: BaseServer, parent?: WorkerScript): number {
|
||||||
if (createAndAddWorkerScript(runningScript, server, parent)) {
|
if (createAndAddWorkerScript(runningScript, server, parent)) {
|
||||||
// Push onto runningScripts.
|
// Push onto runningScripts.
|
||||||
// This has to come after createAndAddWorkerScript() because that fn updates RAM usage
|
// This has to come after createAndAddWorkerScript() because that fn updates RAM usage
|
||||||
server.runScript(runningScript, Player.hacknet_node_money_mult);
|
server.runScript(runningScript);
|
||||||
|
|
||||||
// Once the WorkerScript is constructed in createAndAddWorkerScript(), the RunningScript
|
// Once the WorkerScript is constructed in createAndAddWorkerScript(), the RunningScript
|
||||||
// object should have a PID assigned to it, so we return that
|
// object should have a PID assigned to it, so we return that
|
||||||
@ -463,7 +468,11 @@ export function startWorkerScript(runningScript, server, parent) {
|
|||||||
* @param {Server} server - Server on which the script is to be run
|
* @param {Server} server - Server on which the script is to be run
|
||||||
* returns {boolean} indicating whether or not the workerScript was successfully added
|
* returns {boolean} indicating whether or not the workerScript was successfully added
|
||||||
*/
|
*/
|
||||||
export function createAndAddWorkerScript(runningScriptObj, server, parent) {
|
export function createAndAddWorkerScript(
|
||||||
|
runningScriptObj: RunningScript,
|
||||||
|
server: BaseServer,
|
||||||
|
parent?: WorkerScript,
|
||||||
|
): boolean {
|
||||||
// Update server's ram usage
|
// Update server's ram usage
|
||||||
let threads = 1;
|
let threads = 1;
|
||||||
if (runningScriptObj.threads && !isNaN(runningScriptObj.threads)) {
|
if (runningScriptObj.threads && !isNaN(runningScriptObj.threads)) {
|
||||||
@ -503,7 +512,7 @@ export function createAndAddWorkerScript(runningScriptObj, server, parent) {
|
|||||||
WorkerScriptStartStopEventEmitter.emit();
|
WorkerScriptStartStopEventEmitter.emit();
|
||||||
|
|
||||||
// Start the script's execution
|
// Start the script's execution
|
||||||
let p = null; // Script's resulting promise
|
let p: Promise<WorkerScript> | null = null; // Script's resulting promise
|
||||||
if (s.name.endsWith(".js") || s.name.endsWith(".ns")) {
|
if (s.name.endsWith(".js") || s.name.endsWith(".ns")) {
|
||||||
p = startNetscript2Script(s);
|
p = startNetscript2Script(s);
|
||||||
} else {
|
} else {
|
||||||
@ -515,17 +524,19 @@ export function createAndAddWorkerScript(runningScriptObj, server, parent) {
|
|||||||
|
|
||||||
// Once the code finishes (either resolved or rejected, doesnt matter), set its
|
// Once the code finishes (either resolved or rejected, doesnt matter), set its
|
||||||
// running status to false
|
// running status to false
|
||||||
p.then(function (w) {
|
p.then(function (w: WorkerScript) {
|
||||||
// On natural death, the earnings are transfered to the parent if it still exists.
|
// On natural death, the earnings are transfered to the parent if it still exists.
|
||||||
if (parent && parent.running) {
|
if (parent !== undefined) {
|
||||||
parent.scriptRef.onlineExpGained += runningScriptObj.onlineExpGained;
|
if (parent.running) {
|
||||||
parent.scriptRef.onlineMoneyMade += runningScriptObj.onlineMoneyMade;
|
parent.scriptRef.onlineExpGained += runningScriptObj.onlineExpGained;
|
||||||
|
parent.scriptRef.onlineMoneyMade += runningScriptObj.onlineMoneyMade;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the WorkerScript is no longer "running", then this means its execution was
|
// If the WorkerScript is no longer "running", then this means its execution was
|
||||||
// already stopped somewhere else (maybe by something like exit()). This prevents
|
// already stopped somewhere else (maybe by something like exit()). This prevents
|
||||||
// the script from being cleaned up twice
|
// the script from being cleaned up twice
|
||||||
if (!w.running) {
|
if (w === undefined || !w.running) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,7 +552,7 @@ export function createAndAddWorkerScript(runningScriptObj, server, parent) {
|
|||||||
const errorTextArray = w.errorMessage.split("|");
|
const errorTextArray = w.errorMessage.split("|");
|
||||||
if (errorTextArray.length != 4) {
|
if (errorTextArray.length != 4) {
|
||||||
console.error("ERROR: Something wrong with Error text in evaluator...");
|
console.error("ERROR: Something wrong with Error text in evaluator...");
|
||||||
console.error("Error text: " + errorText);
|
console.error("Error text: " + w.errorMessage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const serverIp = errorTextArray[1];
|
const serverIp = errorTextArray[1];
|
||||||
@ -630,14 +641,21 @@ export function loadAllRunningScripts() {
|
|||||||
/**
|
/**
|
||||||
* Run a script from inside another script (run(), exec(), spawn(), etc.)
|
* Run a script from inside another script (run(), exec(), spawn(), etc.)
|
||||||
*/
|
*/
|
||||||
export function runScriptFromScript(caller, server, scriptname, args, workerScript, threads = 1) {
|
export function runScriptFromScript(
|
||||||
|
caller: string,
|
||||||
|
server: BaseServer,
|
||||||
|
scriptname: string,
|
||||||
|
args: any[],
|
||||||
|
workerScript: WorkerScript,
|
||||||
|
threads = 1,
|
||||||
|
): number {
|
||||||
// Sanitize arguments
|
// Sanitize arguments
|
||||||
if (!(workerScript instanceof WorkerScript)) {
|
if (!(workerScript instanceof WorkerScript)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof scriptname !== "string" || !Array.isArray(args)) {
|
if (typeof scriptname !== "string" || !Array.isArray(args)) {
|
||||||
workerScript.log(caller, `Invalid arguments: scriptname='${scriptname} args='${ags}'`);
|
workerScript.log(caller, `Invalid arguments: scriptname='${scriptname} args='${args}'`);
|
||||||
console.error(`runScriptFromScript() failed due to invalid arguments`);
|
console.error(`runScriptFromScript() failed due to invalid arguments`);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -26,6 +26,8 @@ import { IGang } from "../Gang/IGang";
|
|||||||
import { IBladeburner } from "../Bladeburner/IBladeburner";
|
import { IBladeburner } from "../Bladeburner/IBladeburner";
|
||||||
import { ICodingContractReward } from "../CodingContracts";
|
import { ICodingContractReward } from "../CodingContracts";
|
||||||
import { IRouter } from "../ui/Router";
|
import { IRouter } from "../ui/Router";
|
||||||
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||||
|
|
||||||
export interface IPlayer {
|
export interface IPlayer {
|
||||||
// Class members
|
// Class members
|
||||||
@ -33,14 +35,12 @@ export interface IPlayer {
|
|||||||
bitNodeN: number;
|
bitNodeN: number;
|
||||||
city: CityName;
|
city: CityName;
|
||||||
companyName: string;
|
companyName: string;
|
||||||
corporation: ICorporation;
|
corporation: ICorporation | null;
|
||||||
gang: IGang;
|
gang: IGang | null;
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner | null;
|
||||||
currentServer: string;
|
currentServer: string;
|
||||||
factions: string[];
|
factions: string[];
|
||||||
factionInvitations: string[];
|
factionInvitations: string[];
|
||||||
firstProgramAvailable: boolean;
|
|
||||||
firstTimeTraveled: boolean;
|
|
||||||
hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server
|
hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server
|
||||||
has4SData: boolean;
|
has4SData: boolean;
|
||||||
has4SDataTixApi: boolean;
|
has4SDataTixApi: boolean;
|
||||||
@ -122,9 +122,13 @@ export interface IPlayer {
|
|||||||
bladeburner_analysis_mult: number;
|
bladeburner_analysis_mult: number;
|
||||||
bladeburner_success_chance_mult: number;
|
bladeburner_success_chance_mult: number;
|
||||||
|
|
||||||
|
createProgramReqLvl: number;
|
||||||
|
factionWorkType: string;
|
||||||
createProgramName: string;
|
createProgramName: string;
|
||||||
timeWorkedCreateProgram: number;
|
timeWorkedCreateProgram: number;
|
||||||
crimeType: string;
|
crimeType: string;
|
||||||
|
committingCrimeThruSingFn: boolean;
|
||||||
|
singFnCrimeWorkerScript: WorkerScript | null;
|
||||||
timeNeededToCompleteWork: number;
|
timeNeededToCompleteWork: number;
|
||||||
focus: boolean;
|
focus: boolean;
|
||||||
className: string;
|
className: string;
|
||||||
@ -151,20 +155,23 @@ export interface IPlayer {
|
|||||||
workMoneyLossRate: number;
|
workMoneyLossRate: number;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
applyForAgentJob(sing?: boolean): boolean | void;
|
work(numCycles: number): boolean;
|
||||||
applyForBusinessConsultantJob(sing?: boolean): boolean | void;
|
workPartTime(numCycles: number): boolean;
|
||||||
applyForBusinessJob(sing?: boolean): boolean | void;
|
workForFaction(numCycles: number): boolean;
|
||||||
applyForEmployeeJob(sing?: boolean): boolean | void;
|
applyForAgentJob(sing?: boolean): boolean;
|
||||||
applyForItJob(sing?: boolean): boolean | void;
|
applyForBusinessConsultantJob(sing?: boolean): boolean;
|
||||||
applyForJob(entryPosType: CompanyPosition, sing?: boolean): boolean | void;
|
applyForBusinessJob(sing?: boolean): boolean;
|
||||||
applyForNetworkEngineerJob(sing?: boolean): boolean | void;
|
applyForEmployeeJob(sing?: boolean): boolean;
|
||||||
applyForPartTimeEmployeeJob(sing?: boolean): boolean | void;
|
applyForItJob(sing?: boolean): boolean;
|
||||||
applyForPartTimeWaiterJob(sing?: boolean): boolean | void;
|
applyForJob(entryPosType: CompanyPosition, sing?: boolean): boolean;
|
||||||
applyForSecurityEngineerJob(sing?: boolean): boolean | void;
|
applyForNetworkEngineerJob(sing?: boolean): boolean;
|
||||||
applyForSecurityJob(sing?: boolean): boolean | void;
|
applyForPartTimeEmployeeJob(sing?: boolean): boolean;
|
||||||
applyForSoftwareConsultantJob(sing?: boolean): boolean | void;
|
applyForPartTimeWaiterJob(sing?: boolean): boolean;
|
||||||
applyForSoftwareJob(sing?: boolean): boolean | void;
|
applyForSecurityEngineerJob(sing?: boolean): boolean;
|
||||||
applyForWaiterJob(sing?: boolean): boolean | void;
|
applyForSecurityJob(sing?: boolean): boolean;
|
||||||
|
applyForSoftwareConsultantJob(sing?: boolean): boolean;
|
||||||
|
applyForSoftwareJob(sing?: boolean): boolean;
|
||||||
|
applyForWaiterJob(sing?: boolean): boolean;
|
||||||
canAccessBladeburner(): boolean;
|
canAccessBladeburner(): boolean;
|
||||||
canAccessCorporation(): boolean;
|
canAccessCorporation(): boolean;
|
||||||
canAccessGang(): boolean;
|
canAccessGang(): boolean;
|
||||||
@ -178,11 +185,11 @@ export interface IPlayer {
|
|||||||
gainCharismaExp(exp: number): void;
|
gainCharismaExp(exp: number): void;
|
||||||
gainIntelligenceExp(exp: number): void;
|
gainIntelligenceExp(exp: number): void;
|
||||||
gainMoney(money: number): void;
|
gainMoney(money: number): void;
|
||||||
getCurrentServer(): Server;
|
getCurrentServer(): Server | HacknetServer;
|
||||||
getGangFaction(): Faction;
|
getGangFaction(): Faction;
|
||||||
getGangName(): string;
|
getGangName(): string;
|
||||||
getHomeComputer(): Server;
|
getHomeComputer(): Server;
|
||||||
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition;
|
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition | null;
|
||||||
getUpgradeHomeRamCost(): number;
|
getUpgradeHomeRamCost(): number;
|
||||||
gotoLocation(to: LocationName): boolean;
|
gotoLocation(to: LocationName): boolean;
|
||||||
hasAugmentation(aug: Augmentation): boolean;
|
hasAugmentation(aug: Augmentation): boolean;
|
||||||
@ -194,13 +201,14 @@ export interface IPlayer {
|
|||||||
inGang(): boolean;
|
inGang(): boolean;
|
||||||
isQualified(company: Company, position: CompanyPosition): boolean;
|
isQualified(company: Company, position: CompanyPosition): boolean;
|
||||||
loseMoney(money: number): void;
|
loseMoney(money: number): void;
|
||||||
reapplyAllAugmentations(resetMultipliers: boolean): void;
|
reapplyAllAugmentations(resetMultipliers?: boolean): void;
|
||||||
reapplyAllSourceFiles(): void;
|
reapplyAllSourceFiles(): void;
|
||||||
regenerateHp(amt: number): void;
|
regenerateHp(amt: number): void;
|
||||||
recordMoneySource(amt: number, source: string): void;
|
recordMoneySource(amt: number, source: string): void;
|
||||||
setMoney(amt: number): void;
|
setMoney(amt: number): void;
|
||||||
singularityStopWork(): void;
|
singularityStopWork(): void;
|
||||||
startBladeburner(p: any): void;
|
startBladeburner(p: any): void;
|
||||||
|
startFactionWork(router: IRouter, faction: Faction): void;
|
||||||
startClass(router: IRouter, costMult: number, expMult: number, className: string): void;
|
startClass(router: IRouter, costMult: number, expMult: number, className: string): void;
|
||||||
startCorporation(corpName: string, additionalShares?: number): void;
|
startCorporation(corpName: string, additionalShares?: number): void;
|
||||||
startCrime(
|
startCrime(
|
||||||
@ -230,18 +238,40 @@ export interface IPlayer {
|
|||||||
getIntelligenceBonus(weight: number): number;
|
getIntelligenceBonus(weight: number): number;
|
||||||
getCasinoWinnings(): number;
|
getCasinoWinnings(): number;
|
||||||
quitJob(company: string): void;
|
quitJob(company: string): void;
|
||||||
createHacknetServer(): void;
|
createHacknetServer(): HacknetServer;
|
||||||
startCreateProgramWork(router: IRouter, programName: string, time: number, reqLevel: number): void;
|
startCreateProgramWork(router: IRouter, programName: string, time: number, reqLevel: number): void;
|
||||||
queueAugmentation(augmentationName: string): void;
|
queueAugmentation(augmentationName: string): void;
|
||||||
receiveInvite(factionName: string): void;
|
receiveInvite(factionName: string): void;
|
||||||
updateSkillLevels(): void;
|
updateSkillLevels(): void;
|
||||||
gainCodingContractReward(reward: ICodingContractReward, difficulty?: number): string;
|
gainCodingContractReward(reward: ICodingContractReward, difficulty?: number): string;
|
||||||
stopFocusing(): void;
|
stopFocusing(): void;
|
||||||
finishFactionWork(cancelled: boolean, sing?: boolean): void;
|
finishFactionWork(cancelled: boolean, sing?: boolean): string;
|
||||||
finishClass(sing?: boolean): void;
|
finishClass(sing?: boolean): string;
|
||||||
finishWork(cancelled: boolean, sing?: boolean): void;
|
finishWork(cancelled: boolean, sing?: boolean): string;
|
||||||
cancelationPenalty(): number;
|
cancelationPenalty(): number;
|
||||||
finishWorkPartTime(sing?: boolean): void;
|
finishWorkPartTime(sing?: boolean): string;
|
||||||
finishCrime(cancelled: boolean): void;
|
finishCrime(cancelled: boolean): string;
|
||||||
finishCreateProgramWork(cancelled: boolean): void;
|
finishCreateProgramWork(cancelled: boolean): string;
|
||||||
|
resetMultipliers(): void;
|
||||||
|
prestigeAugmentation(): void;
|
||||||
|
prestigeSourceFile(): void;
|
||||||
|
calculateSkill(exp: number, mult?: number): number;
|
||||||
|
resetWorkStatus(generalType?: string, group?: string, workType?: string): void;
|
||||||
|
getWorkHackExpGain(): number;
|
||||||
|
getWorkStrExpGain(): number;
|
||||||
|
getWorkDefExpGain(): number;
|
||||||
|
getWorkDexExpGain(): number;
|
||||||
|
getWorkAgiExpGain(): number;
|
||||||
|
getWorkChaExpGain(): number;
|
||||||
|
getWorkRepGain(): number;
|
||||||
|
getWorkMoneyGain(): number;
|
||||||
|
processWorkEarnings(cycles: number): void;
|
||||||
|
hospitalize(): void;
|
||||||
|
createProgramWork(numCycles: number): boolean;
|
||||||
|
takeClass(numCycles: number): boolean;
|
||||||
|
commitCrime(numCycles: number): boolean;
|
||||||
|
checkForFactionInvitations(): Faction[];
|
||||||
|
setBitNodeNumber(n: number): void;
|
||||||
|
getMult(name: string): number;
|
||||||
|
setMult(name: string, mult: number): void;
|
||||||
}
|
}
|
||||||
|
@ -1,224 +0,0 @@
|
|||||||
import * as augmentationMethods from "./PlayerObjectAugmentationMethods";
|
|
||||||
import * as bladeburnerMethods from "./PlayerObjectBladeburnerMethods";
|
|
||||||
import * as corporationMethods from "./PlayerObjectCorporationMethods";
|
|
||||||
import * as gangMethods from "./PlayerObjectGangMethods";
|
|
||||||
import * as generalMethods from "./PlayerObjectGeneralMethods";
|
|
||||||
import * as serverMethods from "./PlayerObjectServerMethods";
|
|
||||||
|
|
||||||
import { HashManager } from "../../Hacknet/HashManager";
|
|
||||||
import { CityName } from "../../Locations/data/CityNames";
|
|
||||||
|
|
||||||
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
|
||||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../../utils/JSONReviver";
|
|
||||||
|
|
||||||
import Decimal from "decimal.js";
|
|
||||||
|
|
||||||
export function PlayerObject() {
|
|
||||||
//Skills and stats
|
|
||||||
this.hacking_skill = 1;
|
|
||||||
|
|
||||||
//Combat stats
|
|
||||||
this.hp = 10;
|
|
||||||
this.max_hp = 10;
|
|
||||||
this.strength = 1;
|
|
||||||
this.defense = 1;
|
|
||||||
this.dexterity = 1;
|
|
||||||
this.agility = 1;
|
|
||||||
|
|
||||||
//Labor stats
|
|
||||||
this.charisma = 1;
|
|
||||||
|
|
||||||
//Special stats
|
|
||||||
this.intelligence = 0;
|
|
||||||
|
|
||||||
//Hacking multipliers
|
|
||||||
this.hacking_chance_mult = 1;
|
|
||||||
this.hacking_speed_mult = 1;
|
|
||||||
this.hacking_money_mult = 1;
|
|
||||||
this.hacking_grow_mult = 1;
|
|
||||||
|
|
||||||
//Experience and multipliers
|
|
||||||
this.hacking_exp = 0;
|
|
||||||
this.strength_exp = 0;
|
|
||||||
this.defense_exp = 0;
|
|
||||||
this.dexterity_exp = 0;
|
|
||||||
this.agility_exp = 0;
|
|
||||||
this.charisma_exp = 0;
|
|
||||||
this.intelligence_exp = 0;
|
|
||||||
|
|
||||||
this.hacking_mult = 1;
|
|
||||||
this.strength_mult = 1;
|
|
||||||
this.defense_mult = 1;
|
|
||||||
this.dexterity_mult = 1;
|
|
||||||
this.agility_mult = 1;
|
|
||||||
this.charisma_mult = 1;
|
|
||||||
|
|
||||||
this.hacking_exp_mult = 1;
|
|
||||||
this.strength_exp_mult = 1;
|
|
||||||
this.defense_exp_mult = 1;
|
|
||||||
this.dexterity_exp_mult = 1;
|
|
||||||
this.agility_exp_mult = 1;
|
|
||||||
this.charisma_exp_mult = 1;
|
|
||||||
|
|
||||||
this.company_rep_mult = 1;
|
|
||||||
this.faction_rep_mult = 1;
|
|
||||||
|
|
||||||
//Money
|
|
||||||
this.money = new Decimal(1000);
|
|
||||||
|
|
||||||
//IP Address of Starting (home) computer
|
|
||||||
this.homeComputer = "";
|
|
||||||
|
|
||||||
//Location information
|
|
||||||
this.city = CityName.Sector12;
|
|
||||||
this.location = "";
|
|
||||||
|
|
||||||
// Jobs that the player holds
|
|
||||||
// Map of company name (key) -> name of company position (value. Just the name, not the CompanyPosition object)
|
|
||||||
// The CompanyPosition name must match a key value in CompanyPositions
|
|
||||||
this.jobs = {};
|
|
||||||
|
|
||||||
// Company at which player is CURRENTLY working (only valid when the player is actively working)
|
|
||||||
this.companyName = ""; // Name of Company. Must match a key value in Companies map
|
|
||||||
|
|
||||||
// Servers
|
|
||||||
this.currentServer = ""; //IP address of Server currently being accessed through terminal
|
|
||||||
this.purchasedServers = []; //IP Addresses of purchased servers
|
|
||||||
|
|
||||||
// Hacknet Nodes/Servers
|
|
||||||
this.hacknetNodes = []; // Note: For Hacknet Servers, this array holds the IP addresses of the servers
|
|
||||||
this.hashManager = new HashManager();
|
|
||||||
|
|
||||||
//Factions
|
|
||||||
this.factions = []; //Names of all factions player has joined
|
|
||||||
this.factionInvitations = []; //Outstanding faction invitations
|
|
||||||
|
|
||||||
//Augmentations
|
|
||||||
this.queuedAugmentations = [];
|
|
||||||
this.augmentations = [];
|
|
||||||
|
|
||||||
this.sourceFiles = [];
|
|
||||||
|
|
||||||
//Crime statistics
|
|
||||||
this.numPeopleKilled = 0;
|
|
||||||
this.karma = 0;
|
|
||||||
|
|
||||||
this.crime_money_mult = 1;
|
|
||||||
this.crime_success_mult = 1;
|
|
||||||
|
|
||||||
//Flags/variables for working (Company, Faction, Creating Program, Taking Class)
|
|
||||||
this.isWorking = false;
|
|
||||||
this.focus = false;
|
|
||||||
this.workType = "";
|
|
||||||
|
|
||||||
this.currentWorkFactionName = "";
|
|
||||||
this.currentWorkFactionDescription = "";
|
|
||||||
|
|
||||||
this.workHackExpGainRate = 0;
|
|
||||||
this.workStrExpGainRate = 0;
|
|
||||||
this.workDefExpGainRate = 0;
|
|
||||||
this.workDexExpGainRate = 0;
|
|
||||||
this.workAgiExpGainRate = 0;
|
|
||||||
this.workChaExpGainRate = 0;
|
|
||||||
this.workRepGainRate = 0;
|
|
||||||
this.workMoneyGainRate = 0;
|
|
||||||
this.workMoneyLossRate = 0;
|
|
||||||
|
|
||||||
this.workHackExpGained = 0;
|
|
||||||
this.workStrExpGained = 0;
|
|
||||||
this.workDefExpGained = 0;
|
|
||||||
this.workDexExpGained = 0;
|
|
||||||
this.workAgiExpGained = 0;
|
|
||||||
this.workChaExpGained = 0;
|
|
||||||
this.workRepGained = 0;
|
|
||||||
this.workMoneyGained = 0;
|
|
||||||
|
|
||||||
this.createProgramName = "";
|
|
||||||
this.createProgramReqLvl = 0;
|
|
||||||
|
|
||||||
this.className = "";
|
|
||||||
|
|
||||||
this.crimeType = "";
|
|
||||||
|
|
||||||
this.timeWorked = 0; //in ms
|
|
||||||
this.timeWorkedCreateProgram = 0;
|
|
||||||
this.timeNeededToCompleteWork = 0;
|
|
||||||
|
|
||||||
this.work_money_mult = 1;
|
|
||||||
|
|
||||||
//Hacknet Node multipliers
|
|
||||||
this.hacknet_node_money_mult = 1;
|
|
||||||
this.hacknet_node_purchase_cost_mult = 1;
|
|
||||||
this.hacknet_node_ram_cost_mult = 1;
|
|
||||||
this.hacknet_node_core_cost_mult = 1;
|
|
||||||
this.hacknet_node_level_cost_mult = 1;
|
|
||||||
|
|
||||||
//Stock Market
|
|
||||||
this.hasWseAccount = false;
|
|
||||||
this.hasTixApiAccess = false;
|
|
||||||
this.has4SData = false;
|
|
||||||
this.has4SDataTixApi = false;
|
|
||||||
|
|
||||||
//Gang
|
|
||||||
this.gang = null;
|
|
||||||
|
|
||||||
//Corporation
|
|
||||||
this.corporation = null;
|
|
||||||
|
|
||||||
//Bladeburner
|
|
||||||
this.bladeburner = null;
|
|
||||||
this.bladeburner_max_stamina_mult = 1;
|
|
||||||
this.bladeburner_stamina_gain_mult = 1;
|
|
||||||
this.bladeburner_analysis_mult = 1; //Field Analysis Only
|
|
||||||
this.bladeburner_success_chance_mult = 1;
|
|
||||||
|
|
||||||
// Sleeves & Re-sleeving
|
|
||||||
this.sleeves = [];
|
|
||||||
this.resleeves = [];
|
|
||||||
this.sleevesFromCovenant = 0; // # of Duplicate sleeves purchased from the covenant
|
|
||||||
|
|
||||||
//bitnode
|
|
||||||
this.bitNodeN = 1;
|
|
||||||
|
|
||||||
//Flags for determining whether certain "thresholds" have been achieved
|
|
||||||
this.firstFacInvRecvd = false;
|
|
||||||
this.firstAugPurchased = false;
|
|
||||||
this.firstTimeTraveled = false;
|
|
||||||
this.firstProgramAvailable = false;
|
|
||||||
|
|
||||||
//Used to store the last update time.
|
|
||||||
this.lastUpdate = 0;
|
|
||||||
this.totalPlaytime = 0;
|
|
||||||
this.playtimeSinceLastAug = 0;
|
|
||||||
this.playtimeSinceLastBitnode = 0;
|
|
||||||
|
|
||||||
// Keep track of where money comes from
|
|
||||||
this.moneySourceA = new MoneySourceTracker(); // Where money comes from since last-installed Augmentation
|
|
||||||
this.moneySourceB = new MoneySourceTracker(); // Where money comes from for this entire BitNode run
|
|
||||||
|
|
||||||
// Production since last Augmentation installation
|
|
||||||
this.scriptProdSinceLastAug = 0;
|
|
||||||
|
|
||||||
this.exploits = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply player methods to the prototype using Object.assign()
|
|
||||||
Object.assign(
|
|
||||||
PlayerObject.prototype,
|
|
||||||
generalMethods,
|
|
||||||
serverMethods,
|
|
||||||
bladeburnerMethods,
|
|
||||||
corporationMethods,
|
|
||||||
gangMethods,
|
|
||||||
augmentationMethods,
|
|
||||||
);
|
|
||||||
|
|
||||||
PlayerObject.prototype.toJSON = function () {
|
|
||||||
return Generic_toJSON("PlayerObject", this);
|
|
||||||
};
|
|
||||||
|
|
||||||
PlayerObject.fromJSON = function (value) {
|
|
||||||
return Generic_fromJSON(PlayerObject, value.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
Reviver.constructors.PlayerObject = PlayerObject;
|
|
596
src/PersonObjects/Player/PlayerObject.ts
Normal file
596
src/PersonObjects/Player/PlayerObject.ts
Normal file
@ -0,0 +1,596 @@
|
|||||||
|
import * as augmentationMethods from "./PlayerObjectAugmentationMethods";
|
||||||
|
import * as bladeburnerMethods from "./PlayerObjectBladeburnerMethods";
|
||||||
|
import * as corporationMethods from "./PlayerObjectCorporationMethods";
|
||||||
|
import * as gangMethods from "./PlayerObjectGangMethods";
|
||||||
|
import * as generalMethods from "./PlayerObjectGeneralMethods";
|
||||||
|
import * as serverMethods from "./PlayerObjectServerMethods";
|
||||||
|
|
||||||
|
import { IMap } from "../../types";
|
||||||
|
import { Resleeve } from "../Resleeving/Resleeve";
|
||||||
|
import { Sleeve } from "../Sleeve/Sleeve";
|
||||||
|
import { IPlayerOwnedSourceFile } from "../../SourceFile/PlayerOwnedSourceFile";
|
||||||
|
import { Exploit } from "../../Exploits/Exploit";
|
||||||
|
import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||||
|
import { CompanyPosition } from "../../Company/CompanyPosition";
|
||||||
|
import { Server } from "../../Server/Server";
|
||||||
|
import { HacknetServer } from "../../Hacknet/HacknetServer";
|
||||||
|
import { Faction } from "../../Faction/Faction";
|
||||||
|
import { Company } from "../../Company/Company";
|
||||||
|
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||||
|
import { IRouter } from "../../ui/Router";
|
||||||
|
import { ICodingContractReward } from "../../CodingContracts";
|
||||||
|
|
||||||
|
import { IPlayer } from "../IPlayer";
|
||||||
|
import { LocationName } from "../../Locations/data/LocationNames";
|
||||||
|
import { IPlayerOwnedAugmentation } from "../../Augmentation/PlayerOwnedAugmentation";
|
||||||
|
import { ICorporation } from "../../Corporation/ICorporation";
|
||||||
|
import { IGang } from "../../Gang/IGang";
|
||||||
|
import { IBladeburner } from "../../Bladeburner/IBladeburner";
|
||||||
|
import { HacknetNode } from "../../Hacknet/HacknetNode";
|
||||||
|
|
||||||
|
import { HashManager } from "../../Hacknet/HashManager";
|
||||||
|
import { CityName } from "../../Locations/data/CityNames";
|
||||||
|
|
||||||
|
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
||||||
|
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../../utils/JSONReviver";
|
||||||
|
|
||||||
|
import Decimal from "decimal.js";
|
||||||
|
|
||||||
|
export class PlayerObject implements IPlayer {
|
||||||
|
// Class members
|
||||||
|
augmentations: IPlayerOwnedAugmentation[];
|
||||||
|
bitNodeN: number;
|
||||||
|
city: CityName;
|
||||||
|
companyName: string;
|
||||||
|
corporation: ICorporation | null;
|
||||||
|
gang: IGang | null;
|
||||||
|
bladeburner: IBladeburner | null;
|
||||||
|
currentServer: string;
|
||||||
|
factions: string[];
|
||||||
|
factionInvitations: string[];
|
||||||
|
hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server
|
||||||
|
has4SData: boolean;
|
||||||
|
has4SDataTixApi: boolean;
|
||||||
|
hashManager: HashManager;
|
||||||
|
hasTixApiAccess: boolean;
|
||||||
|
hasWseAccount: boolean;
|
||||||
|
homeComputer: string;
|
||||||
|
hp: number;
|
||||||
|
jobs: IMap<string>;
|
||||||
|
init: () => void;
|
||||||
|
isWorking: boolean;
|
||||||
|
karma: number;
|
||||||
|
numPeopleKilled: number;
|
||||||
|
location: LocationName;
|
||||||
|
max_hp: number;
|
||||||
|
money: any;
|
||||||
|
moneySourceA: MoneySourceTracker;
|
||||||
|
moneySourceB: MoneySourceTracker;
|
||||||
|
playtimeSinceLastAug: number;
|
||||||
|
playtimeSinceLastBitnode: number;
|
||||||
|
purchasedServers: any[];
|
||||||
|
queuedAugmentations: IPlayerOwnedAugmentation[];
|
||||||
|
resleeves: Resleeve[];
|
||||||
|
scriptProdSinceLastAug: number;
|
||||||
|
sleeves: Sleeve[];
|
||||||
|
sleevesFromCovenant: number;
|
||||||
|
sourceFiles: IPlayerOwnedSourceFile[];
|
||||||
|
exploits: Exploit[];
|
||||||
|
lastUpdate: number;
|
||||||
|
totalPlaytime: number;
|
||||||
|
|
||||||
|
// Stats
|
||||||
|
hacking_skill: number;
|
||||||
|
strength: number;
|
||||||
|
defense: number;
|
||||||
|
dexterity: number;
|
||||||
|
agility: number;
|
||||||
|
charisma: number;
|
||||||
|
intelligence: number;
|
||||||
|
|
||||||
|
// Experience
|
||||||
|
hacking_exp: number;
|
||||||
|
strength_exp: number;
|
||||||
|
defense_exp: number;
|
||||||
|
dexterity_exp: number;
|
||||||
|
agility_exp: number;
|
||||||
|
charisma_exp: number;
|
||||||
|
intelligence_exp: number;
|
||||||
|
|
||||||
|
// Multipliers
|
||||||
|
hacking_chance_mult: number;
|
||||||
|
hacking_speed_mult: number;
|
||||||
|
hacking_money_mult: number;
|
||||||
|
hacking_grow_mult: number;
|
||||||
|
hacking_mult: number;
|
||||||
|
hacking_exp_mult: number;
|
||||||
|
strength_mult: number;
|
||||||
|
strength_exp_mult: number;
|
||||||
|
defense_mult: number;
|
||||||
|
defense_exp_mult: number;
|
||||||
|
dexterity_mult: number;
|
||||||
|
dexterity_exp_mult: number;
|
||||||
|
agility_mult: number;
|
||||||
|
agility_exp_mult: number;
|
||||||
|
charisma_mult: number;
|
||||||
|
charisma_exp_mult: number;
|
||||||
|
hacknet_node_money_mult: number;
|
||||||
|
hacknet_node_purchase_cost_mult: number;
|
||||||
|
hacknet_node_ram_cost_mult: number;
|
||||||
|
hacknet_node_core_cost_mult: number;
|
||||||
|
hacknet_node_level_cost_mult: number;
|
||||||
|
company_rep_mult: number;
|
||||||
|
faction_rep_mult: number;
|
||||||
|
work_money_mult: number;
|
||||||
|
crime_success_mult: number;
|
||||||
|
crime_money_mult: number;
|
||||||
|
bladeburner_max_stamina_mult: number;
|
||||||
|
bladeburner_stamina_gain_mult: number;
|
||||||
|
bladeburner_analysis_mult: number;
|
||||||
|
bladeburner_success_chance_mult: number;
|
||||||
|
|
||||||
|
createProgramReqLvl: number;
|
||||||
|
factionWorkType: string;
|
||||||
|
createProgramName: string;
|
||||||
|
timeWorkedCreateProgram: number;
|
||||||
|
crimeType: string;
|
||||||
|
committingCrimeThruSingFn: boolean;
|
||||||
|
singFnCrimeWorkerScript: WorkerScript | null;
|
||||||
|
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
|
||||||
|
work: (numCycles: number) => boolean;
|
||||||
|
workPartTime: (numCycles: number) => boolean;
|
||||||
|
workForFaction: (numCycles: number) => boolean;
|
||||||
|
applyForAgentJob: (sing?: boolean) => boolean;
|
||||||
|
applyForBusinessConsultantJob: (sing?: boolean) => boolean;
|
||||||
|
applyForBusinessJob: (sing?: boolean) => boolean;
|
||||||
|
applyForEmployeeJob: (sing?: boolean) => boolean;
|
||||||
|
applyForItJob: (sing?: boolean) => boolean;
|
||||||
|
applyForJob: (entryPosType: CompanyPosition, sing?: boolean) => boolean;
|
||||||
|
applyForNetworkEngineerJob: (sing?: boolean) => boolean;
|
||||||
|
applyForPartTimeEmployeeJob: (sing?: boolean) => boolean;
|
||||||
|
applyForPartTimeWaiterJob: (sing?: boolean) => boolean;
|
||||||
|
applyForSecurityEngineerJob: (sing?: boolean) => boolean;
|
||||||
|
applyForSecurityJob: (sing?: boolean) => boolean;
|
||||||
|
applyForSoftwareConsultantJob: (sing?: boolean) => boolean;
|
||||||
|
applyForSoftwareJob: (sing?: boolean) => boolean;
|
||||||
|
applyForWaiterJob: (sing?: boolean) => boolean;
|
||||||
|
canAccessBladeburner: () => boolean;
|
||||||
|
canAccessCorporation: () => boolean;
|
||||||
|
canAccessGang: () => boolean;
|
||||||
|
canAccessResleeving: () => boolean;
|
||||||
|
canAfford: (cost: number) => boolean;
|
||||||
|
gainHackingExp: (exp: number) => void;
|
||||||
|
gainStrengthExp: (exp: number) => void;
|
||||||
|
gainDefenseExp: (exp: number) => void;
|
||||||
|
gainDexterityExp: (exp: number) => void;
|
||||||
|
gainAgilityExp: (exp: number) => void;
|
||||||
|
gainCharismaExp: (exp: number) => void;
|
||||||
|
gainIntelligenceExp: (exp: number) => void;
|
||||||
|
gainMoney: (money: number) => void;
|
||||||
|
getCurrentServer: () => Server | HacknetServer;
|
||||||
|
getGangFaction: () => Faction;
|
||||||
|
getGangName: () => string;
|
||||||
|
getHomeComputer: () => Server;
|
||||||
|
getNextCompanyPosition: (company: Company, entryPosType: CompanyPosition) => CompanyPosition | null;
|
||||||
|
getUpgradeHomeRamCost: () => number;
|
||||||
|
gotoLocation: (to: LocationName) => boolean;
|
||||||
|
hasAugmentation: (aug: Augmentation) => boolean;
|
||||||
|
hasCorporation: () => boolean;
|
||||||
|
hasGangWith: (facName: string) => boolean;
|
||||||
|
hasTorRouter: () => boolean;
|
||||||
|
hasProgram: (program: string) => boolean;
|
||||||
|
inBladeburner: () => boolean;
|
||||||
|
inGang: () => boolean;
|
||||||
|
isQualified: (company: Company, position: CompanyPosition) => boolean;
|
||||||
|
loseMoney: (money: number) => void;
|
||||||
|
reapplyAllAugmentations: (resetMultipliers?: boolean) => void;
|
||||||
|
reapplyAllSourceFiles: () => void;
|
||||||
|
regenerateHp: (amt: number) => void;
|
||||||
|
recordMoneySource: (amt: number, source: string) => void;
|
||||||
|
setMoney: (amt: number) => void;
|
||||||
|
singularityStopWork: () => void;
|
||||||
|
startBladeburner: (p: any) => void;
|
||||||
|
startFactionWork: (router: IRouter, faction: Faction) => void;
|
||||||
|
startClass: (router: IRouter, costMult: number, expMult: number, className: string) => void;
|
||||||
|
startCorporation: (corpName: string, additionalShares?: number) => void;
|
||||||
|
startCrime: (
|
||||||
|
router: IRouter,
|
||||||
|
crimeType: string,
|
||||||
|
hackExp: number,
|
||||||
|
strExp: number,
|
||||||
|
defExp: number,
|
||||||
|
dexExp: number,
|
||||||
|
agiExp: number,
|
||||||
|
chaExp: number,
|
||||||
|
money: number,
|
||||||
|
time: number,
|
||||||
|
singParams: any,
|
||||||
|
) => void;
|
||||||
|
startFactionFieldWork: (router: IRouter, faction: Faction) => void;
|
||||||
|
startFactionHackWork: (router: IRouter, faction: Faction) => void;
|
||||||
|
startFactionSecurityWork: (router: IRouter, faction: Faction) => void;
|
||||||
|
startFocusing: () => void;
|
||||||
|
startGang: (facName: string, isHacking: boolean) => void;
|
||||||
|
startWork: (router: IRouter, companyName: string) => void;
|
||||||
|
startWorkPartTime: (router: IRouter, companyName: string) => void;
|
||||||
|
takeDamage: (amt: number) => boolean;
|
||||||
|
travel: (to: CityName) => boolean;
|
||||||
|
giveExploit: (exploit: Exploit) => void;
|
||||||
|
queryStatFromString: (str: string) => number;
|
||||||
|
getIntelligenceBonus: (weight: number) => number;
|
||||||
|
getCasinoWinnings: () => number;
|
||||||
|
quitJob: (company: string) => void;
|
||||||
|
createHacknetServer: () => HacknetServer;
|
||||||
|
startCreateProgramWork: (router: IRouter, programName: string, time: number, reqLevel: number) => void;
|
||||||
|
queueAugmentation: (augmentationName: string) => void;
|
||||||
|
receiveInvite: (factionName: string) => void;
|
||||||
|
updateSkillLevels: () => void;
|
||||||
|
gainCodingContractReward: (reward: ICodingContractReward, difficulty?: number) => string;
|
||||||
|
stopFocusing: () => void;
|
||||||
|
finishFactionWork: (cancelled: boolean, sing?: boolean) => string;
|
||||||
|
finishClass: (sing?: boolean) => string;
|
||||||
|
finishWork: (cancelled: boolean, sing?: boolean) => string;
|
||||||
|
cancelationPenalty: () => number;
|
||||||
|
finishWorkPartTime: (sing?: boolean) => string;
|
||||||
|
finishCrime: (cancelled: boolean) => string;
|
||||||
|
finishCreateProgramWork: (cancelled: boolean) => string;
|
||||||
|
resetMultipliers: () => void;
|
||||||
|
prestigeAugmentation: () => void;
|
||||||
|
prestigeSourceFile: () => void;
|
||||||
|
calculateSkill: (exp: number, mult?: number) => number;
|
||||||
|
resetWorkStatus: (generalType?: string, group?: string, workType?: string) => void;
|
||||||
|
getWorkHackExpGain: () => number;
|
||||||
|
getWorkStrExpGain: () => number;
|
||||||
|
getWorkDefExpGain: () => number;
|
||||||
|
getWorkDexExpGain: () => number;
|
||||||
|
getWorkAgiExpGain: () => number;
|
||||||
|
getWorkChaExpGain: () => number;
|
||||||
|
getWorkRepGain: () => number;
|
||||||
|
getWorkMoneyGain: () => number;
|
||||||
|
processWorkEarnings: (cycles: number) => void;
|
||||||
|
hospitalize: () => void;
|
||||||
|
createProgramWork: (numCycles: number) => boolean;
|
||||||
|
takeClass: (numCycles: number) => boolean;
|
||||||
|
commitCrime: (numCycles: number) => boolean;
|
||||||
|
checkForFactionInvitations: () => Faction[];
|
||||||
|
setBitNodeNumber: (n: number) => void;
|
||||||
|
getMult: (name: string) => number;
|
||||||
|
setMult: (name: string, mult: number) => void;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
//Skills and stats
|
||||||
|
this.hacking_skill = 1;
|
||||||
|
|
||||||
|
//Combat stats
|
||||||
|
this.hp = 10;
|
||||||
|
this.max_hp = 10;
|
||||||
|
this.strength = 1;
|
||||||
|
this.defense = 1;
|
||||||
|
this.dexterity = 1;
|
||||||
|
this.agility = 1;
|
||||||
|
|
||||||
|
//Labor stats
|
||||||
|
this.charisma = 1;
|
||||||
|
|
||||||
|
//Special stats
|
||||||
|
this.intelligence = 0;
|
||||||
|
|
||||||
|
//Hacking multipliers
|
||||||
|
this.hacking_chance_mult = 1;
|
||||||
|
this.hacking_speed_mult = 1;
|
||||||
|
this.hacking_money_mult = 1;
|
||||||
|
this.hacking_grow_mult = 1;
|
||||||
|
|
||||||
|
//Experience and multipliers
|
||||||
|
this.hacking_exp = 0;
|
||||||
|
this.strength_exp = 0;
|
||||||
|
this.defense_exp = 0;
|
||||||
|
this.dexterity_exp = 0;
|
||||||
|
this.agility_exp = 0;
|
||||||
|
this.charisma_exp = 0;
|
||||||
|
this.intelligence_exp = 0;
|
||||||
|
|
||||||
|
this.hacking_mult = 1;
|
||||||
|
this.strength_mult = 1;
|
||||||
|
this.defense_mult = 1;
|
||||||
|
this.dexterity_mult = 1;
|
||||||
|
this.agility_mult = 1;
|
||||||
|
this.charisma_mult = 1;
|
||||||
|
|
||||||
|
this.hacking_exp_mult = 1;
|
||||||
|
this.strength_exp_mult = 1;
|
||||||
|
this.defense_exp_mult = 1;
|
||||||
|
this.dexterity_exp_mult = 1;
|
||||||
|
this.agility_exp_mult = 1;
|
||||||
|
this.charisma_exp_mult = 1;
|
||||||
|
|
||||||
|
this.company_rep_mult = 1;
|
||||||
|
this.faction_rep_mult = 1;
|
||||||
|
|
||||||
|
//Money
|
||||||
|
this.money = new Decimal(1000);
|
||||||
|
|
||||||
|
//IP Address of Starting (home) computer
|
||||||
|
this.homeComputer = "";
|
||||||
|
|
||||||
|
//Location information
|
||||||
|
this.city = CityName.Sector12;
|
||||||
|
this.location = LocationName.TravelAgency;
|
||||||
|
|
||||||
|
// Jobs that the player holds
|
||||||
|
// Map of company name (key) -> name of company position (value. Just the name, not the CompanyPosition object)
|
||||||
|
// The CompanyPosition name must match a key value in CompanyPositions
|
||||||
|
this.jobs = {};
|
||||||
|
|
||||||
|
// Company at which player is CURRENTLY working (only valid when the player is actively working)
|
||||||
|
this.companyName = ""; // Name of Company. Must match a key value in Companies ma;
|
||||||
|
|
||||||
|
// Servers
|
||||||
|
this.currentServer = ""; //IP address of Server currently being accessed through termina;
|
||||||
|
this.purchasedServers = []; //IP Addresses of purchased server;
|
||||||
|
|
||||||
|
// Hacknet Nodes/Servers
|
||||||
|
this.hacknetNodes = []; // Note= For Hacknet Servers, this array holds the IP addresses of the server;
|
||||||
|
this.hashManager = new HashManager();
|
||||||
|
|
||||||
|
//Factions
|
||||||
|
this.factions = []; //Names of all factions player has joine;
|
||||||
|
this.factionInvitations = []; //Outstanding faction invitation;
|
||||||
|
|
||||||
|
//Augmentations
|
||||||
|
this.queuedAugmentations = [];
|
||||||
|
this.augmentations = [];
|
||||||
|
|
||||||
|
this.sourceFiles = [];
|
||||||
|
|
||||||
|
//Crime statistics
|
||||||
|
this.numPeopleKilled = 0;
|
||||||
|
this.karma = 0;
|
||||||
|
|
||||||
|
this.crime_money_mult = 1;
|
||||||
|
this.crime_success_mult = 1;
|
||||||
|
|
||||||
|
//Flags/variables for working (Company, Faction, Creating Program, Taking Class)
|
||||||
|
this.isWorking = false;
|
||||||
|
this.focus = false;
|
||||||
|
this.workType = "";
|
||||||
|
|
||||||
|
this.currentWorkFactionName = "";
|
||||||
|
this.currentWorkFactionDescription = "";
|
||||||
|
|
||||||
|
this.workHackExpGainRate = 0;
|
||||||
|
this.workStrExpGainRate = 0;
|
||||||
|
this.workDefExpGainRate = 0;
|
||||||
|
this.workDexExpGainRate = 0;
|
||||||
|
this.workAgiExpGainRate = 0;
|
||||||
|
this.workChaExpGainRate = 0;
|
||||||
|
this.workRepGainRate = 0;
|
||||||
|
this.workMoneyGainRate = 0;
|
||||||
|
this.workMoneyLossRate = 0;
|
||||||
|
|
||||||
|
this.workHackExpGained = 0;
|
||||||
|
this.workStrExpGained = 0;
|
||||||
|
this.workDefExpGained = 0;
|
||||||
|
this.workDexExpGained = 0;
|
||||||
|
this.workAgiExpGained = 0;
|
||||||
|
this.workChaExpGained = 0;
|
||||||
|
this.workRepGained = 0;
|
||||||
|
this.workMoneyGained = 0;
|
||||||
|
|
||||||
|
this.createProgramName = "";
|
||||||
|
this.createProgramReqLvl = 0;
|
||||||
|
|
||||||
|
this.className = "";
|
||||||
|
|
||||||
|
this.crimeType = "";
|
||||||
|
|
||||||
|
(this.timeWorked = 0), //in m;
|
||||||
|
(this.timeWorkedCreateProgram = 0);
|
||||||
|
this.timeNeededToCompleteWork = 0;
|
||||||
|
|
||||||
|
this.work_money_mult = 1;
|
||||||
|
|
||||||
|
//Hacknet Node multipliers
|
||||||
|
this.hacknet_node_money_mult = 1;
|
||||||
|
this.hacknet_node_purchase_cost_mult = 1;
|
||||||
|
this.hacknet_node_ram_cost_mult = 1;
|
||||||
|
this.hacknet_node_core_cost_mult = 1;
|
||||||
|
this.hacknet_node_level_cost_mult = 1;
|
||||||
|
|
||||||
|
//Stock Market
|
||||||
|
this.hasWseAccount = false;
|
||||||
|
this.hasTixApiAccess = false;
|
||||||
|
this.has4SData = false;
|
||||||
|
this.has4SDataTixApi = false;
|
||||||
|
|
||||||
|
//Gang
|
||||||
|
this.gang = null;
|
||||||
|
|
||||||
|
//Corporation
|
||||||
|
this.corporation = null;
|
||||||
|
|
||||||
|
//Bladeburner
|
||||||
|
this.bladeburner = null;
|
||||||
|
this.bladeburner_max_stamina_mult = 1;
|
||||||
|
this.bladeburner_stamina_gain_mult = 1;
|
||||||
|
(this.bladeburner_analysis_mult = 1), //Field Analysis Onl;
|
||||||
|
(this.bladeburner_success_chance_mult = 1);
|
||||||
|
|
||||||
|
// Sleeves & Re-sleeving
|
||||||
|
this.sleeves = [];
|
||||||
|
this.resleeves = [];
|
||||||
|
(this.sleevesFromCovenant = 0), // # of Duplicate sleeves purchased from the covenan;
|
||||||
|
//bitnode
|
||||||
|
(this.bitNodeN = 1);
|
||||||
|
|
||||||
|
//Used to store the last update time.
|
||||||
|
this.lastUpdate = 0;
|
||||||
|
this.totalPlaytime = 0;
|
||||||
|
this.playtimeSinceLastAug = 0;
|
||||||
|
this.playtimeSinceLastBitnode = 0;
|
||||||
|
|
||||||
|
// Keep track of where money comes from
|
||||||
|
(this.moneySourceA = new MoneySourceTracker()), // Where money comes from since last-installed Augmentatio;
|
||||||
|
(this.moneySourceB = new MoneySourceTracker()), // Where money comes from for this entire BitNode ru;
|
||||||
|
// Production since last Augmentation installation
|
||||||
|
(this.scriptProdSinceLastAug = 0);
|
||||||
|
|
||||||
|
this.exploits = [];
|
||||||
|
|
||||||
|
this.init = generalMethods.init;
|
||||||
|
this.prestigeAugmentation = generalMethods.prestigeAugmentation;
|
||||||
|
this.prestigeSourceFile = generalMethods.prestigeSourceFile;
|
||||||
|
this.receiveInvite = generalMethods.receiveInvite;
|
||||||
|
this.calculateSkill = generalMethods.calculateSkill;
|
||||||
|
this.updateSkillLevels = generalMethods.updateSkillLevels;
|
||||||
|
this.resetMultipliers = generalMethods.resetMultipliers;
|
||||||
|
this.hasProgram = generalMethods.hasProgram;
|
||||||
|
this.setMoney = generalMethods.setMoney;
|
||||||
|
this.gainMoney = generalMethods.gainMoney;
|
||||||
|
this.loseMoney = generalMethods.loseMoney;
|
||||||
|
this.canAfford = generalMethods.canAfford;
|
||||||
|
this.recordMoneySource = generalMethods.recordMoneySource;
|
||||||
|
this.gainHackingExp = generalMethods.gainHackingExp;
|
||||||
|
this.gainStrengthExp = generalMethods.gainStrengthExp;
|
||||||
|
this.gainDefenseExp = generalMethods.gainDefenseExp;
|
||||||
|
this.gainDexterityExp = generalMethods.gainDexterityExp;
|
||||||
|
this.gainAgilityExp = generalMethods.gainAgilityExp;
|
||||||
|
this.gainCharismaExp = generalMethods.gainCharismaExp;
|
||||||
|
this.gainIntelligenceExp = generalMethods.gainIntelligenceExp;
|
||||||
|
this.queryStatFromString = generalMethods.queryStatFromString;
|
||||||
|
this.resetWorkStatus = generalMethods.resetWorkStatus;
|
||||||
|
this.processWorkEarnings = generalMethods.processWorkEarnings;
|
||||||
|
this.startWork = generalMethods.startWork;
|
||||||
|
this.cancelationPenalty = generalMethods.cancelationPenalty;
|
||||||
|
this.work = generalMethods.work;
|
||||||
|
this.finishWork = generalMethods.finishWork;
|
||||||
|
this.startWorkPartTime = generalMethods.startWorkPartTime;
|
||||||
|
this.workPartTime = generalMethods.workPartTime;
|
||||||
|
this.finishWorkPartTime = generalMethods.finishWorkPartTime;
|
||||||
|
this.startFocusing = generalMethods.startFocusing;
|
||||||
|
this.stopFocusing = generalMethods.stopFocusing;
|
||||||
|
this.startFactionWork = generalMethods.startFactionWork;
|
||||||
|
this.startFactionHackWork = generalMethods.startFactionHackWork;
|
||||||
|
this.startFactionFieldWork = generalMethods.startFactionFieldWork;
|
||||||
|
this.startFactionSecurityWork = generalMethods.startFactionSecurityWork;
|
||||||
|
this.workForFaction = generalMethods.workForFaction;
|
||||||
|
this.finishFactionWork = generalMethods.finishFactionWork;
|
||||||
|
this.getWorkMoneyGain = generalMethods.getWorkMoneyGain;
|
||||||
|
this.getWorkHackExpGain = generalMethods.getWorkHackExpGain;
|
||||||
|
this.getWorkStrExpGain = generalMethods.getWorkStrExpGain;
|
||||||
|
this.getWorkDefExpGain = generalMethods.getWorkDefExpGain;
|
||||||
|
this.getWorkDexExpGain = generalMethods.getWorkDexExpGain;
|
||||||
|
this.getWorkAgiExpGain = generalMethods.getWorkAgiExpGain;
|
||||||
|
this.getWorkChaExpGain = generalMethods.getWorkChaExpGain;
|
||||||
|
this.getWorkRepGain = generalMethods.getWorkRepGain;
|
||||||
|
this.startCreateProgramWork = generalMethods.startCreateProgramWork;
|
||||||
|
this.createProgramWork = generalMethods.createProgramWork;
|
||||||
|
this.finishCreateProgramWork = generalMethods.finishCreateProgramWork;
|
||||||
|
this.startClass = generalMethods.startClass;
|
||||||
|
this.takeClass = generalMethods.takeClass;
|
||||||
|
this.finishClass = generalMethods.finishClass;
|
||||||
|
this.startCrime = generalMethods.startCrime;
|
||||||
|
this.commitCrime = generalMethods.commitCrime;
|
||||||
|
this.finishCrime = generalMethods.finishCrime;
|
||||||
|
this.singularityStopWork = generalMethods.singularityStopWork;
|
||||||
|
this.takeDamage = generalMethods.takeDamage;
|
||||||
|
this.regenerateHp = generalMethods.regenerateHp;
|
||||||
|
this.hospitalize = generalMethods.hospitalize;
|
||||||
|
this.applyForJob = generalMethods.applyForJob;
|
||||||
|
this.getNextCompanyPosition = generalMethods.getNextCompanyPosition;
|
||||||
|
this.quitJob = generalMethods.quitJob;
|
||||||
|
this.applyForSoftwareJob = generalMethods.applyForSoftwareJob;
|
||||||
|
this.applyForSoftwareConsultantJob = generalMethods.applyForSoftwareConsultantJob;
|
||||||
|
this.applyForItJob = generalMethods.applyForItJob;
|
||||||
|
this.applyForSecurityEngineerJob = generalMethods.applyForSecurityEngineerJob;
|
||||||
|
this.applyForNetworkEngineerJob = generalMethods.applyForNetworkEngineerJob;
|
||||||
|
this.applyForBusinessJob = generalMethods.applyForBusinessJob;
|
||||||
|
this.applyForBusinessConsultantJob = generalMethods.applyForBusinessConsultantJob;
|
||||||
|
this.applyForSecurityJob = generalMethods.applyForSecurityJob;
|
||||||
|
this.applyForAgentJob = generalMethods.applyForAgentJob;
|
||||||
|
this.applyForEmployeeJob = generalMethods.applyForEmployeeJob;
|
||||||
|
this.applyForPartTimeEmployeeJob = generalMethods.applyForPartTimeEmployeeJob;
|
||||||
|
this.applyForWaiterJob = generalMethods.applyForWaiterJob;
|
||||||
|
this.applyForPartTimeWaiterJob = generalMethods.applyForPartTimeWaiterJob;
|
||||||
|
this.isQualified = generalMethods.isQualified;
|
||||||
|
this.reapplyAllAugmentations = generalMethods.reapplyAllAugmentations;
|
||||||
|
this.reapplyAllSourceFiles = generalMethods.reapplyAllSourceFiles;
|
||||||
|
this.checkForFactionInvitations = generalMethods.checkForFactionInvitations;
|
||||||
|
this.setBitNodeNumber = generalMethods.setBitNodeNumber;
|
||||||
|
this.queueAugmentation = generalMethods.queueAugmentation;
|
||||||
|
this.gainCodingContractReward = generalMethods.gainCodingContractReward;
|
||||||
|
this.travel = generalMethods.travel;
|
||||||
|
this.gotoLocation = generalMethods.gotoLocation;
|
||||||
|
this.canAccessResleeving = generalMethods.canAccessResleeving;
|
||||||
|
this.giveExploit = generalMethods.giveExploit;
|
||||||
|
this.getIntelligenceBonus = generalMethods.getIntelligenceBonus;
|
||||||
|
this.getCasinoWinnings = generalMethods.getCasinoWinnings;
|
||||||
|
this.hasAugmentation = augmentationMethods.hasAugmentation;
|
||||||
|
this.canAccessBladeburner = bladeburnerMethods.canAccessBladeburner;
|
||||||
|
this.inBladeburner = bladeburnerMethods.inBladeburner;
|
||||||
|
this.startBladeburner = bladeburnerMethods.startBladeburner;
|
||||||
|
this.canAccessCorporation = corporationMethods.canAccessCorporation;
|
||||||
|
this.hasCorporation = corporationMethods.hasCorporation;
|
||||||
|
this.startCorporation = corporationMethods.startCorporation;
|
||||||
|
this.canAccessGang = gangMethods.canAccessGang;
|
||||||
|
this.getGangFaction = gangMethods.getGangFaction;
|
||||||
|
this.getGangName = gangMethods.getGangName;
|
||||||
|
this.hasGangWith = gangMethods.hasGangWith;
|
||||||
|
this.inGang = gangMethods.inGang;
|
||||||
|
this.startGang = gangMethods.startGang;
|
||||||
|
|
||||||
|
this.hasTorRouter = serverMethods.hasTorRouter;
|
||||||
|
this.getCurrentServer = serverMethods.getCurrentServer;
|
||||||
|
this.getHomeComputer = serverMethods.getHomeComputer;
|
||||||
|
this.getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost;
|
||||||
|
this.createHacknetServer = serverMethods.createHacknetServer;
|
||||||
|
this.factionWorkType = "";
|
||||||
|
this.committingCrimeThruSingFn = false;
|
||||||
|
this.singFnCrimeWorkerScript = null;
|
||||||
|
|
||||||
|
this.getMult = generalMethods.getMult;
|
||||||
|
this.setMult = generalMethods.setMult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the current object to a JSON save state.
|
||||||
|
*/
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("PlayerObject", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiatizes a PlayerObject object from a JSON save state.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
static fromJSON(value: any): PlayerObject {
|
||||||
|
return Generic_fromJSON(PlayerObject, value.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reviver.constructors.PlayerObject = PlayerObject;
|
@ -1,7 +1,8 @@
|
|||||||
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||||
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
export function canAccessBladeburner() {
|
export function canAccessBladeburner(this: IPlayer) {
|
||||||
if (this.bitNodeN === 8) {
|
if (this.bitNodeN === 8) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -9,13 +10,13 @@ export function canAccessBladeburner() {
|
|||||||
return this.bitNodeN === 6 || this.bitNodeN === 7 || SourceFileFlags[6] > 0 || SourceFileFlags[7] > 0;
|
return this.bitNodeN === 6 || this.bitNodeN === 7 || SourceFileFlags[6] > 0 || SourceFileFlags[7] > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inBladeburner() {
|
export function inBladeburner(this: IPlayer): boolean {
|
||||||
if (this.bladeburner == null) {
|
if (this.bladeburner == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.bladeburner instanceof Bladeburner;
|
return this.bladeburner instanceof Bladeburner;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function startBladeburner() {
|
export function startBladeburner(this: IPlayer): void {
|
||||||
this.bladeburner = new Bladeburner(this);
|
this.bladeburner = new Bladeburner(this);
|
||||||
}
|
}
|
@ -1,18 +1,19 @@
|
|||||||
import { Corporation } from "../../Corporation/Corporation";
|
import { Corporation } from "../../Corporation/Corporation";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||||
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
export function canAccessCorporation() {
|
export function canAccessCorporation(this: IPlayer): boolean {
|
||||||
return this.bitNodeN === 3 || SourceFileFlags[3] > 0;
|
return this.bitNodeN === 3 || SourceFileFlags[3] > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasCorporation() {
|
export function hasCorporation(this: IPlayer): boolean {
|
||||||
if (this.corporation == null) {
|
if (this.corporation == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.corporation instanceof Corporation;
|
return this.corporation instanceof Corporation;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function startCorporation(corpName, additionalShares = 0) {
|
export function startCorporation(this: IPlayer, corpName: string, additionalShares = 0): void {
|
||||||
this.corporation = new Corporation({
|
this.corporation = new Corporation({
|
||||||
name: corpName,
|
name: corpName,
|
||||||
});
|
});
|
@ -1,53 +0,0 @@
|
|||||||
import { Factions } from "../../Faction/Factions";
|
|
||||||
import { Gang } from "../../Gang/Gang";
|
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|
||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
|
||||||
|
|
||||||
// Amount of negative karma needed to manage a gang in BitNodes other than 2
|
|
||||||
const GangKarmaRequirement = -54000;
|
|
||||||
|
|
||||||
export function canAccessGang() {
|
|
||||||
if (this.bitNodeN === 2) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (SourceFileFlags[2] <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.karma <= BitNodeMultipliers.GangKarmaRequirement * GangKarmaRequirement;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getGangFaction() {
|
|
||||||
const fac = Factions[this.gang.facName];
|
|
||||||
if (fac == null) {
|
|
||||||
throw new Error(`Gang has invalid faction name: ${this.gang.facName}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fac;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getGangName() {
|
|
||||||
return this.inGang() ? this.gang.facName : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hasGangWith(facName) {
|
|
||||||
return this.inGang() && this.gang.facName === facName;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function inGang() {
|
|
||||||
if (this.gang == null || this.gang == undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.gang instanceof Gang;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function startGang(factionName, hacking) {
|
|
||||||
this.gang = new Gang(factionName, hacking);
|
|
||||||
|
|
||||||
const fac = Factions[factionName];
|
|
||||||
if (fac == null) {
|
|
||||||
throw new Error(`Invalid faction name when creating gang: ${factionName}`);
|
|
||||||
}
|
|
||||||
fac.playerReputation = 0;
|
|
||||||
}
|
|
69
src/PersonObjects/Player/PlayerObjectGangMethods.ts
Normal file
69
src/PersonObjects/Player/PlayerObjectGangMethods.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { Factions } from "../../Faction/Factions";
|
||||||
|
import { Faction } from "../../Faction/Faction";
|
||||||
|
import { Gang } from "../../Gang/Gang";
|
||||||
|
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||||
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||||
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
|
// Amount of negative karma needed to manage a gang in BitNodes other than 2
|
||||||
|
const GangKarmaRequirement = -54000;
|
||||||
|
|
||||||
|
export function canAccessGang(this: IPlayer): boolean {
|
||||||
|
if (this.bitNodeN === 2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (SourceFileFlags[2] <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.karma <= BitNodeMultipliers.GangKarmaRequirement * GangKarmaRequirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGangFaction(this: IPlayer): Faction {
|
||||||
|
const gang = this.gang;
|
||||||
|
if (gang === null) {
|
||||||
|
throw new Error("Cannot get gang faction because player is not in a gang.");
|
||||||
|
}
|
||||||
|
const fac = Factions[gang.facName];
|
||||||
|
if (fac == null) {
|
||||||
|
throw new Error(`Gang has invalid faction name: ${gang.facName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fac;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGangName(this: IPlayer): string {
|
||||||
|
if (!this.inGang()) return "";
|
||||||
|
const gang = this.gang;
|
||||||
|
if (gang === null) {
|
||||||
|
throw new Error("Cannot get gang faction because player is not in a gang.");
|
||||||
|
}
|
||||||
|
return gang.facName;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasGangWith(this: IPlayer, facName: string): boolean {
|
||||||
|
if (!this.inGang()) return false;
|
||||||
|
const gang = this.gang;
|
||||||
|
if (gang === null) {
|
||||||
|
throw new Error("Cannot get gang faction because player is not in a gang.");
|
||||||
|
}
|
||||||
|
return gang.facName === facName;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inGang(this: IPlayer): boolean {
|
||||||
|
if (this.gang == null || this.gang == undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.gang instanceof Gang;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function startGang(this: IPlayer, factionName: string, hacking: boolean): void {
|
||||||
|
this.gang = new Gang(factionName, hacking);
|
||||||
|
|
||||||
|
const fac = Factions[factionName];
|
||||||
|
if (fac == null) {
|
||||||
|
throw new Error(`Invalid faction name when creating gang: ${factionName}`);
|
||||||
|
}
|
||||||
|
fac.playerReputation = 0;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -15,12 +15,16 @@ export function hasTorRouter(this: IPlayer): boolean {
|
|||||||
return SpecialServerIps.hasOwnProperty("Darkweb Server");
|
return SpecialServerIps.hasOwnProperty("Darkweb Server");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentServer(this: IPlayer): Server | HacknetServer | null {
|
export function getCurrentServer(this: IPlayer): Server | HacknetServer {
|
||||||
return AllServers[this.currentServer];
|
const server = AllServers[this.currentServer];
|
||||||
|
if (server === null) throw new Error("somehow connected to a server that does not exist.");
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getHomeComputer(this: IPlayer): Server | HacknetServer | null {
|
export function getHomeComputer(this: IPlayer): Server {
|
||||||
return AllServers[this.homeComputer];
|
const home = AllServers[this.homeComputer];
|
||||||
|
if (home instanceof Server) return home;
|
||||||
|
throw new Error("home computer was not a normal server");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUpgradeHomeRamCost(this: IPlayer): number {
|
export function getUpgradeHomeRamCost(this: IPlayer): number {
|
||||||
|
3
src/Player.d.ts
vendored
3
src/Player.d.ts
vendored
@ -1,3 +0,0 @@
|
|||||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
export declare let Player: IPlayer;
|
|
@ -8,7 +8,7 @@ import Decimal from "decimal.js";
|
|||||||
|
|
||||||
export let Player = new PlayerObject();
|
export let Player = new PlayerObject();
|
||||||
|
|
||||||
export function loadPlayer(saveString) {
|
export function loadPlayer(saveString: string): void {
|
||||||
Player = JSON.parse(saveString, Reviver);
|
Player = JSON.parse(saveString, Reviver);
|
||||||
|
|
||||||
// Parse Decimal.js objects
|
// Parse Decimal.js objects
|
||||||
@ -19,8 +19,8 @@ export function loadPlayer(saveString) {
|
|||||||
Player.corporation.revenue = new Decimal(Player.corporation.revenue);
|
Player.corporation.revenue = new Decimal(Player.corporation.revenue);
|
||||||
Player.corporation.expenses = new Decimal(Player.corporation.expenses);
|
Player.corporation.expenses = new Decimal(Player.corporation.expenses);
|
||||||
|
|
||||||
for (var i = 0; i < Player.corporation.divisions.length; ++i) {
|
for (let i = 0; i < Player.corporation.divisions.length; ++i) {
|
||||||
var ind = Player.corporation.divisions[i];
|
const ind = Player.corporation.divisions[i];
|
||||||
ind.lastCycleRevenue = new Decimal(ind.lastCycleRevenue);
|
ind.lastCycleRevenue = new Decimal(ind.lastCycleRevenue);
|
||||||
ind.lastCycleExpenses = new Decimal(ind.lastCycleExpenses);
|
ind.lastCycleExpenses = new Decimal(ind.lastCycleExpenses);
|
||||||
ind.thisCycleRevenue = new Decimal(ind.thisCycleRevenue);
|
ind.thisCycleRevenue = new Decimal(ind.thisCycleRevenue);
|
2
src/Prestige.d.ts
vendored
2
src/Prestige.d.ts
vendored
@ -1,2 +0,0 @@
|
|||||||
export declare function prestigeAugmentation(): void;
|
|
||||||
export declare function prestigeSourceFile(flume: boolean): void;
|
|
@ -14,6 +14,7 @@ import { updateHashManagerCapacity } from "./Hacknet/HacknetHelpers";
|
|||||||
import { initMessages } from "./Message/MessageHelpers";
|
import { initMessages } from "./Message/MessageHelpers";
|
||||||
import { prestigeWorkerScripts } from "./NetscriptWorker";
|
import { prestigeWorkerScripts } from "./NetscriptWorker";
|
||||||
import { Player } from "./Player";
|
import { Player } from "./Player";
|
||||||
|
import { Router } from "./ui/GameRoot";
|
||||||
import { resetPidCounter } from "./Netscript/Pid";
|
import { resetPidCounter } from "./Netscript/Pid";
|
||||||
import { LiteratureNames } from "./Literature/data/LiteratureNames";
|
import { LiteratureNames } from "./Literature/data/LiteratureNames";
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ import Decimal from "decimal.js";
|
|||||||
const BitNode8StartingMoney = 250e6;
|
const BitNode8StartingMoney = 250e6;
|
||||||
|
|
||||||
// Prestige by purchasing augmentation
|
// Prestige by purchasing augmentation
|
||||||
function prestigeAugmentation() {
|
function prestigeAugmentation(): void {
|
||||||
initBitNodeMultipliers(Player);
|
initBitNodeMultipliers(Player);
|
||||||
|
|
||||||
const maintainMembership = Player.factions.filter(function (faction) {
|
const maintainMembership = Player.factions.filter(function (faction) {
|
||||||
@ -42,7 +43,7 @@ function prestigeAugmentation() {
|
|||||||
// Delete all Worker Scripts objects
|
// Delete all Worker Scripts objects
|
||||||
prestigeWorkerScripts();
|
prestigeWorkerScripts();
|
||||||
|
|
||||||
var homeComp = Player.getHomeComputer();
|
const homeComp = Player.getHomeComputer();
|
||||||
// Delete all servers except home computer
|
// Delete all servers except home computer
|
||||||
prestigeAllServers();
|
prestigeAllServers();
|
||||||
|
|
||||||
@ -70,23 +71,22 @@ function prestigeAugmentation() {
|
|||||||
initForeignServers(Player.getHomeComputer());
|
initForeignServers(Player.getHomeComputer());
|
||||||
|
|
||||||
// Gain favor for Companies
|
// Gain favor for Companies
|
||||||
for (var member in Companies) {
|
for (const member in Companies) {
|
||||||
if (Companies.hasOwnProperty(member)) {
|
if (Companies.hasOwnProperty(member)) {
|
||||||
Companies[member].gainFavor();
|
Companies[member].gainFavor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gain favor for factions
|
// Gain favor for factions
|
||||||
for (var member in Factions) {
|
for (const member in Factions) {
|
||||||
if (Factions.hasOwnProperty(member)) {
|
if (Factions.hasOwnProperty(member)) {
|
||||||
Factions[member].gainFavor();
|
Factions[member].gainFavor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop a Terminal action if there is onerror
|
// Stop a Terminal action if there is onerror
|
||||||
if (Engine._actionInProgress) {
|
if (Terminal.action !== null) {
|
||||||
Engine._actionInProgress = false;
|
Terminal.finishAction(Router, Player, true);
|
||||||
Terminal.finishAction(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-initialize things - This will update any changes
|
// Re-initialize things - This will update any changes
|
||||||
@ -102,8 +102,9 @@ function prestigeAugmentation() {
|
|||||||
initMessages();
|
initMessages();
|
||||||
|
|
||||||
// Gang
|
// Gang
|
||||||
if (Player.inGang()) {
|
const gang = Player.gang;
|
||||||
const faction = Factions[Player.gang.facName];
|
if (Player.inGang() && gang !== null) {
|
||||||
|
const faction = Factions[gang.facName];
|
||||||
if (faction instanceof Faction) {
|
if (faction instanceof Faction) {
|
||||||
joinFaction(faction);
|
joinFaction(faction);
|
||||||
}
|
}
|
||||||
@ -131,8 +132,12 @@ function prestigeAugmentation() {
|
|||||||
|
|
||||||
// Red Pill
|
// Red Pill
|
||||||
if (augmentationExists(AugmentationNames.TheRedPill) && Augmentations[AugmentationNames.TheRedPill].owned) {
|
if (augmentationExists(AugmentationNames.TheRedPill) && Augmentations[AugmentationNames.TheRedPill].owned) {
|
||||||
var WorldDaemon = AllServers[SpecialServerIps[SpecialServerNames.WorldDaemon]];
|
const WorldDaemonIP = SpecialServerIps[SpecialServerNames.WorldDaemon];
|
||||||
var DaedalusServer = AllServers[SpecialServerIps[SpecialServerNames.DaedalusServer]];
|
if (typeof WorldDaemonIP !== "string") throw new Error("WorldDaemonIP should be string");
|
||||||
|
const WorldDaemon = AllServers[WorldDaemonIP];
|
||||||
|
const DaedalusServerIP = SpecialServerIps[SpecialServerNames.DaedalusServer];
|
||||||
|
if (typeof DaedalusServerIP !== "string") throw new Error("DaedalusServerIP should be string");
|
||||||
|
const DaedalusServer = AllServers[DaedalusServerIP];
|
||||||
if (WorldDaemon && DaedalusServer) {
|
if (WorldDaemon && DaedalusServer) {
|
||||||
WorldDaemon.serversOnNetwork.push(DaedalusServer.ip);
|
WorldDaemon.serversOnNetwork.push(DaedalusServer.ip);
|
||||||
DaedalusServer.serversOnNetwork.push(WorldDaemon.ip);
|
DaedalusServer.serversOnNetwork.push(WorldDaemon.ip);
|
||||||
@ -143,7 +148,7 @@ function prestigeAugmentation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prestige by destroying Bit Node and gaining a Source File
|
// Prestige by destroying Bit Node and gaining a Source File
|
||||||
function prestigeSourceFile(flume) {
|
function prestigeSourceFile(flume: boolean): void {
|
||||||
initBitNodeMultipliers(Player);
|
initBitNodeMultipliers(Player);
|
||||||
updateSourceFileFlags(Player);
|
updateSourceFileFlags(Player);
|
||||||
|
|
||||||
@ -189,9 +194,8 @@ function prestigeSourceFile(flume) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stop a Terminal action if there is one
|
// Stop a Terminal action if there is one
|
||||||
if (Engine._actionInProgress) {
|
if (Terminal.action !== null) {
|
||||||
Engine._actionInProgress = false;
|
Terminal.finishAction(Router, Player, true);
|
||||||
Terminal.finishAction(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all Augmentations
|
// Delete all Augmentations
|
||||||
@ -249,7 +253,6 @@ function prestigeSourceFile(flume) {
|
|||||||
deleteStockMarket();
|
deleteStockMarket();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Player.inGang()) clearGangUI();
|
|
||||||
Player.gang = null;
|
Player.gang = null;
|
||||||
Player.corporation = null;
|
Player.corporation = null;
|
||||||
resetIndustryResearchTrees();
|
resetIndustryResearchTrees();
|
@ -53,10 +53,9 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
terminal.print("You already have root access to this computer. There is no reason to run NUKE.exe");
|
terminal.print("You already have root access to this computer. There is no reason to run NUKE.exe");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (server.openPortCount >= server.numOpenPortsRequired) {
|
||||||
if (server.openPortCount >= player.getCurrentServer().numOpenPortsRequired) {
|
|
||||||
server.hasAdminRights = true;
|
server.hasAdminRights = true;
|
||||||
terminal.print("NUKE successful! Gained root access to " + player.getCurrentServer().hostname);
|
terminal.print("NUKE successful! Gained root access to " + server.hostname);
|
||||||
// TODO: Make this take time rather than be instant
|
// TODO: Make this take time rather than be instant
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
3
src/RedPill.d.ts
vendored
3
src/RedPill.d.ts
vendored
@ -1,3 +0,0 @@
|
|||||||
export declare let redPillFlag: boolean;
|
|
||||||
export declare function enterBitNode(router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number);
|
|
||||||
export declare function setRedPillFlag(b: boolean): void;
|
|
@ -8,14 +8,15 @@ import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
|||||||
import { SourceFiles } from "./SourceFile/SourceFiles";
|
import { SourceFiles } from "./SourceFile/SourceFiles";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||||
|
import { IRouter } from "./ui/Router";
|
||||||
|
|
||||||
export let redPillFlag = false;
|
export let redPillFlag = false;
|
||||||
|
|
||||||
export function setRedPillFlag(b) {
|
export function setRedPillFlag(b: boolean): void {
|
||||||
redPillFlag = b;
|
redPillFlag = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
function giveSourceFile(bitNodeNumber) {
|
function giveSourceFile(bitNodeNumber: number): void {
|
||||||
var sourceFileKey = "SourceFile" + bitNodeNumber.toString();
|
var sourceFileKey = "SourceFile" + bitNodeNumber.toString();
|
||||||
var sourceFile = SourceFiles[sourceFileKey];
|
var sourceFile = SourceFiles[sourceFileKey];
|
||||||
if (sourceFile == null) {
|
if (sourceFile == null) {
|
||||||
@ -62,7 +63,7 @@ function giveSourceFile(bitNodeNumber) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function enterBitNode(router, flume, destroyedBitNode, newBitNode) {
|
export function enterBitNode(router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number): void {
|
||||||
if (!flume) {
|
if (!flume) {
|
||||||
giveSourceFile(destroyedBitNode);
|
giveSourceFile(destroyedBitNode);
|
||||||
} else {
|
} else {
|
@ -27,90 +27,125 @@ import Decimal from "decimal.js";
|
|||||||
/* SaveObject.js
|
/* SaveObject.js
|
||||||
* Defines the object used to save/load games
|
* Defines the object used to save/load games
|
||||||
*/
|
*/
|
||||||
let saveObject = new BitburnerSaveObject();
|
|
||||||
|
|
||||||
function BitburnerSaveObject() {
|
class BitburnerSaveObject {
|
||||||
this.PlayerSave = "";
|
PlayerSave = "";
|
||||||
this.AllServersSave = "";
|
AllServersSave = "";
|
||||||
this.CompaniesSave = "";
|
CompaniesSave = "";
|
||||||
this.FactionsSave = "";
|
FactionsSave = "";
|
||||||
this.SpecialServerIpsSave = "";
|
SpecialServerIpsSave = "";
|
||||||
this.AliasesSave = "";
|
AliasesSave = "";
|
||||||
this.GlobalAliasesSave = "";
|
GlobalAliasesSave = "";
|
||||||
this.MessagesSave = "";
|
MessagesSave = "";
|
||||||
this.StockMarketSave = "";
|
StockMarketSave = "";
|
||||||
this.SettingsSave = "";
|
SettingsSave = "";
|
||||||
this.VersionSave = "";
|
VersionSave = "";
|
||||||
this.AllGangsSave = "";
|
AllGangsSave = "";
|
||||||
this.LastExportBonus = "";
|
LastExportBonus = "";
|
||||||
|
|
||||||
|
getSaveString(): string {
|
||||||
|
this.PlayerSave = JSON.stringify(Player);
|
||||||
|
|
||||||
|
// Delete all logs from all running scripts
|
||||||
|
var TempAllServers = JSON.parse(JSON.stringify(AllServers), Reviver);
|
||||||
|
for (var ip in TempAllServers) {
|
||||||
|
var server = TempAllServers[ip];
|
||||||
|
if (server == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < server.runningScripts.length; ++i) {
|
||||||
|
var runningScriptObj = server.runningScripts[i];
|
||||||
|
runningScriptObj.logs.length = 0;
|
||||||
|
runningScriptObj.logs = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.AllServersSave = JSON.stringify(TempAllServers);
|
||||||
|
this.CompaniesSave = JSON.stringify(Companies);
|
||||||
|
this.FactionsSave = JSON.stringify(Factions);
|
||||||
|
this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps);
|
||||||
|
this.AliasesSave = JSON.stringify(Aliases);
|
||||||
|
this.GlobalAliasesSave = JSON.stringify(GlobalAliases);
|
||||||
|
this.MessagesSave = JSON.stringify(Messages);
|
||||||
|
this.StockMarketSave = JSON.stringify(StockMarket);
|
||||||
|
this.SettingsSave = JSON.stringify(Settings);
|
||||||
|
this.VersionSave = JSON.stringify(CONSTANTS.Version);
|
||||||
|
this.LastExportBonus = JSON.stringify(ExportBonus.LastExportBonus);
|
||||||
|
if (Player.inGang()) {
|
||||||
|
this.AllGangsSave = JSON.stringify(AllGangs);
|
||||||
|
}
|
||||||
|
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
|
||||||
|
|
||||||
|
return saveString;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveGame(): void {
|
||||||
|
const saveString = this.getSaveString();
|
||||||
|
|
||||||
|
save(saveString)
|
||||||
|
.then(() => createStatusText("Game saved!"))
|
||||||
|
.catch((err) => console.error(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
exportGame(): void {
|
||||||
|
const saveString = this.getSaveString();
|
||||||
|
|
||||||
|
// Save file name is based on current timestamp and BitNode
|
||||||
|
const epochTime = Math.round(Date.now() / 1000);
|
||||||
|
const bn = Player.bitNodeN;
|
||||||
|
const filename = `bitburnerSave_BN${bn}x${SourceFileFlags[bn]}_${epochTime}.json`;
|
||||||
|
var file = new Blob([saveString], { type: "text/plain" });
|
||||||
|
if (window.navigator.msSaveOrOpenBlob) {
|
||||||
|
// IE10+
|
||||||
|
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||||
|
} else {
|
||||||
|
// Others
|
||||||
|
var a = document.createElement("a"),
|
||||||
|
url = URL.createObjectURL(file);
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
setTimeoutRef(function () {
|
||||||
|
document.body.removeChild(a);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("BitburnerSaveObject", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJSON(value: { data: any }): BitburnerSaveObject {
|
||||||
|
return Generic_fromJSON(BitburnerSaveObject, value.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BitburnerSaveObject.prototype.getSaveString = function () {
|
|
||||||
this.PlayerSave = JSON.stringify(Player);
|
|
||||||
|
|
||||||
// Delete all logs from all running scripts
|
|
||||||
var TempAllServers = JSON.parse(JSON.stringify(AllServers), Reviver);
|
|
||||||
for (var ip in TempAllServers) {
|
|
||||||
var server = TempAllServers[ip];
|
|
||||||
if (server == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (var i = 0; i < server.runningScripts.length; ++i) {
|
|
||||||
var runningScriptObj = server.runningScripts[i];
|
|
||||||
runningScriptObj.logs.length = 0;
|
|
||||||
runningScriptObj.logs = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.AllServersSave = JSON.stringify(TempAllServers);
|
|
||||||
this.CompaniesSave = JSON.stringify(Companies);
|
|
||||||
this.FactionsSave = JSON.stringify(Factions);
|
|
||||||
this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps);
|
|
||||||
this.AliasesSave = JSON.stringify(Aliases);
|
|
||||||
this.GlobalAliasesSave = JSON.stringify(GlobalAliases);
|
|
||||||
this.MessagesSave = JSON.stringify(Messages);
|
|
||||||
this.StockMarketSave = JSON.stringify(StockMarket);
|
|
||||||
this.SettingsSave = JSON.stringify(Settings);
|
|
||||||
this.VersionSave = JSON.stringify(CONSTANTS.Version);
|
|
||||||
this.LastExportBonus = JSON.stringify(ExportBonus.LastExportBonus);
|
|
||||||
if (Player.inGang()) {
|
|
||||||
this.AllGangsSave = JSON.stringify(AllGangs);
|
|
||||||
}
|
|
||||||
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
|
|
||||||
|
|
||||||
return saveString;
|
|
||||||
};
|
|
||||||
|
|
||||||
BitburnerSaveObject.prototype.saveGame = function () {
|
|
||||||
const saveString = this.getSaveString();
|
|
||||||
|
|
||||||
save(saveString)
|
|
||||||
.then(() => createStatusText("Game saved!"))
|
|
||||||
.catch((err) => console.error(err));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Makes necessary changes to the loaded/imported data to ensure
|
// Makes necessary changes to the loaded/imported data to ensure
|
||||||
// the game stills works with new versions
|
// the game stills works with new versions
|
||||||
function evaluateVersionCompatibility(ver) {
|
function evaluateVersionCompatibility(ver: string) {
|
||||||
|
// We have to do this because ts won't let us otherwise
|
||||||
|
const anyPlayer = Player as any;
|
||||||
// This version refactored the Company/job-related code
|
// This version refactored the Company/job-related code
|
||||||
if (ver <= "0.41.2") {
|
if (ver <= "0.41.2") {
|
||||||
// Player's company position is now a string
|
// Player's company position is now a string
|
||||||
if (Player.companyPosition != null && typeof Player.companyPosition !== "string") {
|
if (anyPlayer.companyPosition != null && typeof anyPlayer.companyPosition !== "string") {
|
||||||
Player.companyPosition = Player.companyPosition.data.positionName;
|
anyPlayer.companyPosition = anyPlayer.companyPosition.data.positionName;
|
||||||
if (Player.companyPosition == null) {
|
if (anyPlayer.companyPosition == null) {
|
||||||
Player.companyPosition = "";
|
anyPlayer.companyPosition = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The "companyName" property of all Companies is renamed to "name"
|
// The "companyName" property of all Companies is renamed to "name"
|
||||||
for (var companyName in Companies) {
|
for (const companyName in Companies) {
|
||||||
const company = Companies[companyName];
|
const company: any = Companies[companyName];
|
||||||
if ((company.name == null || company.name === 0 || company.name === "") && company.companyName != null) {
|
if (company.name == 0 && company.companyName != null) {
|
||||||
company.name = company.companyName;
|
company.name = company.companyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (company.companyPositions instanceof Array) {
|
if (company.companyPositions instanceof Array) {
|
||||||
const pos = {};
|
const pos: any = {};
|
||||||
|
|
||||||
for (let i = 0; i < company.companyPositions.length; ++i) {
|
for (let i = 0; i < company.companyPositions.length; ++i) {
|
||||||
pos[company.companyPositions[i]] = true;
|
pos[company.companyPositions[i]] = true;
|
||||||
@ -122,15 +157,15 @@ function evaluateVersionCompatibility(ver) {
|
|||||||
|
|
||||||
// This version allowed players to hold multiple jobs
|
// This version allowed players to hold multiple jobs
|
||||||
if (ver < "0.43.0") {
|
if (ver < "0.43.0") {
|
||||||
if (Player.companyName !== "" && Player.companyPosition != null && Player.companyPosition !== "") {
|
if (anyPlayer.companyName !== "" && anyPlayer.companyPosition != null && anyPlayer.companyPosition !== "") {
|
||||||
Player.jobs[Player.companyName] = Player.companyPosition;
|
anyPlayer.jobs[anyPlayer.companyName] = anyPlayer.companyPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete Player.companyPosition;
|
delete anyPlayer.companyPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadGame(saveString) {
|
function loadGame(saveString: string): boolean {
|
||||||
if (!saveString) return false;
|
if (!saveString) return false;
|
||||||
saveString = decodeURIComponent(escape(atob(saveString)));
|
saveString = decodeURIComponent(escape(atob(saveString)));
|
||||||
|
|
||||||
@ -230,32 +265,6 @@ function loadGame(saveString) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitburnerSaveObject.prototype.exportGame = function () {
|
|
||||||
const saveString = this.getSaveString();
|
|
||||||
|
|
||||||
// Save file name is based on current timestamp and BitNode
|
|
||||||
const epochTime = Math.round(Date.now() / 1000);
|
|
||||||
const bn = Player.bitNodeN;
|
|
||||||
const filename = `bitburnerSave_BN${bn}x${SourceFileFlags[bn]}_${epochTime}.json`;
|
|
||||||
var file = new Blob([saveString], { type: "text/plain" });
|
|
||||||
if (window.navigator.msSaveOrOpenBlob) {
|
|
||||||
// IE10+
|
|
||||||
window.navigator.msSaveOrOpenBlob(file, filename);
|
|
||||||
} else {
|
|
||||||
// Others
|
|
||||||
var a = document.createElement("a"),
|
|
||||||
url = URL.createObjectURL(file);
|
|
||||||
a.href = url;
|
|
||||||
a.download = filename;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
setTimeoutRef(function () {
|
|
||||||
document.body.removeChild(a);
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function createNewUpdateText() {
|
function createNewUpdateText() {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"New update!<br>" +
|
"New update!<br>" +
|
||||||
@ -275,14 +284,8 @@ function createBetaUpdateText() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BitburnerSaveObject.prototype.toJSON = function () {
|
|
||||||
return Generic_toJSON("BitburnerSaveObject", this);
|
|
||||||
};
|
|
||||||
|
|
||||||
BitburnerSaveObject.fromJSON = function (value) {
|
|
||||||
return Generic_fromJSON(BitburnerSaveObject, value.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
Reviver.constructors.BitburnerSaveObject = BitburnerSaveObject;
|
Reviver.constructors.BitburnerSaveObject = BitburnerSaveObject;
|
||||||
|
|
||||||
export { saveObject, loadGame };
|
export { saveObject, loadGame };
|
||||||
|
|
||||||
|
let saveObject = new BitburnerSaveObject();
|
3
src/Script/RamCalculations.d.ts
vendored
3
src/Script/RamCalculations.d.ts
vendored
@ -1,3 +0,0 @@
|
|||||||
import { Script } from "./Script";
|
|
||||||
|
|
||||||
export declare function calculateRamUsage(codeCopy: string, otherScripts: Script[]): number;
|
|
@ -11,6 +11,8 @@ import { parse } from "acorn";
|
|||||||
import { RamCalculationErrorCode } from "./RamCalculationErrorCodes";
|
import { RamCalculationErrorCode } from "./RamCalculationErrorCodes";
|
||||||
|
|
||||||
import { RamCosts, RamCostConstants } from "../Netscript/RamCostGenerator";
|
import { RamCosts, RamCostConstants } from "../Netscript/RamCostGenerator";
|
||||||
|
import { Script } from "../Script/Script";
|
||||||
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
|
||||||
// These special strings are used to reference the presence of a given logical
|
// These special strings are used to reference the presence of a given logical
|
||||||
// construct within a user script.
|
// construct within a user script.
|
||||||
@ -29,7 +31,11 @@ const memCheckGlobalKey = ".__GLOBAL__";
|
|||||||
* @param {WorkerScript} workerScript - Object containing RAM costs of Netscript functions. Also used to
|
* @param {WorkerScript} workerScript - Object containing RAM costs of Netscript functions. Also used to
|
||||||
* keep track of what functions have/havent been accounted for
|
* keep track of what functions have/havent been accounted for
|
||||||
*/
|
*/
|
||||||
async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
|
async function parseOnlyRamCalculate(
|
||||||
|
otherScripts: Script[],
|
||||||
|
code: string,
|
||||||
|
workerScript: WorkerScript,
|
||||||
|
): Promise<number | RamCalculationErrorCode> {
|
||||||
try {
|
try {
|
||||||
/**
|
/**
|
||||||
* Maps dependent identifiers to their dependencies.
|
* Maps dependent identifiers to their dependencies.
|
||||||
@ -41,16 +47,16 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
|
|||||||
* We walk the dependency graph to calculate RAM usage, given that some identifiers
|
* We walk the dependency graph to calculate RAM usage, given that some identifiers
|
||||||
* reference Netscript functions which have a RAM cost.
|
* reference Netscript functions which have a RAM cost.
|
||||||
*/
|
*/
|
||||||
let dependencyMap = {};
|
let dependencyMap: { [key: string]: string[] } = {};
|
||||||
|
|
||||||
// Scripts we've parsed.
|
// Scripts we've parsed.
|
||||||
const completedParses = new Set();
|
const completedParses = new Set();
|
||||||
|
|
||||||
// Scripts we've discovered that need to be parsed.
|
// Scripts we've discovered that need to be parsed.
|
||||||
const parseQueue = [];
|
const parseQueue: string[] = [];
|
||||||
|
|
||||||
// Parses a chunk of code with a given module name, and updates parseQueue and dependencyMap.
|
// Parses a chunk of code with a given module name, and updates parseQueue and dependencyMap.
|
||||||
function parseCode(code, moduleName) {
|
function parseCode(code: string, moduleName: string): void {
|
||||||
const result = parseOnlyCalculateDeps(code, moduleName);
|
const result = parseOnlyCalculateDeps(code, moduleName);
|
||||||
completedParses.add(moduleName);
|
completedParses.add(moduleName);
|
||||||
|
|
||||||
@ -72,6 +78,7 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
|
|||||||
// Process additional modules, which occurs if the "main" script has any imports
|
// Process additional modules, which occurs if the "main" script has any imports
|
||||||
while (parseQueue.length > 0) {
|
while (parseQueue.length > 0) {
|
||||||
const nextModule = parseQueue.shift();
|
const nextModule = parseQueue.shift();
|
||||||
|
if (nextModule === undefined) throw new Error("nextModule should not be undefined");
|
||||||
|
|
||||||
// Additional modules can either be imported from the web (in which case we use
|
// Additional modules can either be imported from the web (in which case we use
|
||||||
// a dynamic import), or from other in-game scripts
|
// a dynamic import), or from other in-game scripts
|
||||||
@ -122,6 +129,7 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
|
|||||||
const resolvedRefs = new Set();
|
const resolvedRefs = new Set();
|
||||||
while (unresolvedRefs.length > 0) {
|
while (unresolvedRefs.length > 0) {
|
||||||
const ref = unresolvedRefs.shift();
|
const ref = unresolvedRefs.shift();
|
||||||
|
if (ref === undefined) throw new Error("ref should not be undefined");
|
||||||
|
|
||||||
// Check if this is one of the special keys, and add the appropriate ram cost if so.
|
// Check if this is one of the special keys, and add the appropriate ram cost if so.
|
||||||
if (ref === "hacknet" && !resolvedRefs.has("hacknet")) {
|
if (ref === "hacknet" && !resolvedRefs.has("hacknet")) {
|
||||||
@ -154,7 +162,7 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
|
|||||||
// Check if this identifier is a function in the workerScript environment.
|
// Check if this identifier is a function in the workerScript environment.
|
||||||
// If it is, then we need to get its RAM cost.
|
// If it is, then we need to get its RAM cost.
|
||||||
try {
|
try {
|
||||||
function applyFuncRam(func) {
|
function applyFuncRam(func: any) {
|
||||||
if (typeof func === "function") {
|
if (typeof func === "function") {
|
||||||
try {
|
try {
|
||||||
let res;
|
let res;
|
||||||
@ -216,27 +224,28 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
|
|||||||
* for RAM usage calculations. It also returns an array of additional modules
|
* for RAM usage calculations. It also returns an array of additional modules
|
||||||
* that need to be parsed (i.e. are 'import'ed scripts).
|
* that need to be parsed (i.e. are 'import'ed scripts).
|
||||||
*/
|
*/
|
||||||
function parseOnlyCalculateDeps(code, currentModule) {
|
function parseOnlyCalculateDeps(code: string, currentModule: string): any {
|
||||||
const ast = parse(code, { sourceType: "module", ecmaVersion: "latest" });
|
const ast = parse(code, { sourceType: "module", ecmaVersion: "latest" });
|
||||||
|
|
||||||
// Everything from the global scope goes in ".". Everything else goes in ".function", where only
|
// Everything from the global scope goes in ".". Everything else goes in ".function", where only
|
||||||
// the outermost layer of functions counts.
|
// the outermost layer of functions counts.
|
||||||
const globalKey = currentModule + memCheckGlobalKey;
|
const globalKey = currentModule + memCheckGlobalKey;
|
||||||
const dependencyMap = {};
|
const dependencyMap: { [key: string]: Set<string> | undefined } = {};
|
||||||
dependencyMap[globalKey] = new Set();
|
dependencyMap[globalKey] = new Set<string>();
|
||||||
|
|
||||||
// If we reference this internal name, we're really referencing that external name.
|
// If we reference this internal name, we're really referencing that external name.
|
||||||
// Filled when we import names from other modules.
|
// Filled when we import names from other modules.
|
||||||
let internalToExternal = {};
|
let internalToExternal: { [key: string]: string | undefined } = {};
|
||||||
|
|
||||||
var additionalModules = [];
|
let additionalModules: string[] = [];
|
||||||
|
|
||||||
// References get added pessimistically. They are added for thisModule.name, name, and for
|
// References get added pessimistically. They are added for thisModule.name, name, and for
|
||||||
// any aliases.
|
// any aliases.
|
||||||
function addRef(key, name) {
|
function addRef(key: string, name: string): void {
|
||||||
const s = dependencyMap[key] || (dependencyMap[key] = new Set());
|
const s = dependencyMap[key] || (dependencyMap[key] = new Set());
|
||||||
if (name in internalToExternal) {
|
const external = internalToExternal[name];
|
||||||
s.add(internalToExternal[name]);
|
if (external !== undefined) {
|
||||||
|
s.add(external);
|
||||||
}
|
}
|
||||||
s.add(currentModule + "." + name);
|
s.add(currentModule + "." + name);
|
||||||
s.add(name); // For builtins like hack.
|
s.add(name); // For builtins like hack.
|
||||||
@ -249,36 +258,36 @@ function parseOnlyCalculateDeps(code, currentModule) {
|
|||||||
// walkDeeper is for doing recursive walks of expressions in composites that we handle.
|
// walkDeeper is for doing recursive walks of expressions in composites that we handle.
|
||||||
function commonVisitors() {
|
function commonVisitors() {
|
||||||
return {
|
return {
|
||||||
Identifier: (node, st) => {
|
Identifier: (node: any, st: any) => {
|
||||||
if (objectPrototypeProperties.includes(node.name)) {
|
if (objectPrototypeProperties.includes(node.name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addRef(st.key, node.name);
|
addRef(st.key, node.name);
|
||||||
},
|
},
|
||||||
WhileStatement: (node, st, walkDeeper) => {
|
WhileStatement: (node: any, st: any, walkDeeper: any) => {
|
||||||
addRef(st.key, specialReferenceWHILE);
|
addRef(st.key, specialReferenceWHILE);
|
||||||
node.test && walkDeeper(node.test, st);
|
node.test && walkDeeper(node.test, st);
|
||||||
node.body && walkDeeper(node.body, st);
|
node.body && walkDeeper(node.body, st);
|
||||||
},
|
},
|
||||||
DoWhileStatement: (node, st, walkDeeper) => {
|
DoWhileStatement: (node: any, st: any, walkDeeper: any) => {
|
||||||
addRef(st.key, specialReferenceWHILE);
|
addRef(st.key, specialReferenceWHILE);
|
||||||
node.test && walkDeeper(node.test, st);
|
node.test && walkDeeper(node.test, st);
|
||||||
node.body && walkDeeper(node.body, st);
|
node.body && walkDeeper(node.body, st);
|
||||||
},
|
},
|
||||||
ForStatement: (node, st, walkDeeper) => {
|
ForStatement: (node: any, st: any, walkDeeper: any) => {
|
||||||
addRef(st.key, specialReferenceFOR);
|
addRef(st.key, specialReferenceFOR);
|
||||||
node.init && walkDeeper(node.init, st);
|
node.init && walkDeeper(node.init, st);
|
||||||
node.test && walkDeeper(node.test, st);
|
node.test && walkDeeper(node.test, st);
|
||||||
node.update && walkDeeper(node.update, st);
|
node.update && walkDeeper(node.update, st);
|
||||||
node.body && walkDeeper(node.body, st);
|
node.body && walkDeeper(node.body, st);
|
||||||
},
|
},
|
||||||
IfStatement: (node, st, walkDeeper) => {
|
IfStatement: (node: any, st: any, walkDeeper: any) => {
|
||||||
addRef(st.key, specialReferenceIF);
|
addRef(st.key, specialReferenceIF);
|
||||||
node.test && walkDeeper(node.test, st);
|
node.test && walkDeeper(node.test, st);
|
||||||
node.consequent && walkDeeper(node.consequent, st);
|
node.consequent && walkDeeper(node.consequent, st);
|
||||||
node.alternate && walkDeeper(node.alternate, st);
|
node.alternate && walkDeeper(node.alternate, st);
|
||||||
},
|
},
|
||||||
MemberExpression: (node, st, walkDeeper) => {
|
MemberExpression: (node: any, st: any, walkDeeper: any) => {
|
||||||
node.object && walkDeeper(node.object, st);
|
node.object && walkDeeper(node.object, st);
|
||||||
node.property && walkDeeper(node.property, st);
|
node.property && walkDeeper(node.property, st);
|
||||||
},
|
},
|
||||||
@ -290,13 +299,15 @@ function parseOnlyCalculateDeps(code, currentModule) {
|
|||||||
{ key: globalKey },
|
{ key: globalKey },
|
||||||
Object.assign(
|
Object.assign(
|
||||||
{
|
{
|
||||||
ImportDeclaration: (node, st) => {
|
ImportDeclaration: (node: any, st: any) => {
|
||||||
const importModuleName = node.source.value;
|
const importModuleName = node.source.value;
|
||||||
additionalModules.push(importModuleName);
|
additionalModules.push(importModuleName);
|
||||||
|
|
||||||
// This module's global scope refers to that module's global scope, no matter how we
|
// This module's global scope refers to that module's global scope, no matter how we
|
||||||
// import it.
|
// import it.
|
||||||
dependencyMap[st.key].add(importModuleName + memCheckGlobalKey);
|
const set = dependencyMap[st.key];
|
||||||
|
if (set === undefined) throw new Error("set should not be undefined");
|
||||||
|
set.add(importModuleName + memCheckGlobalKey);
|
||||||
|
|
||||||
for (let i = 0; i < node.specifiers.length; ++i) {
|
for (let i = 0; i < node.specifiers.length; ++i) {
|
||||||
const spec = node.specifiers[i];
|
const spec = node.specifiers[i];
|
||||||
@ -305,11 +316,13 @@ function parseOnlyCalculateDeps(code, currentModule) {
|
|||||||
internalToExternal[spec.local.name] = importModuleName + "." + spec.imported.name;
|
internalToExternal[spec.local.name] = importModuleName + "." + spec.imported.name;
|
||||||
} else {
|
} else {
|
||||||
// We depend on everything.
|
// We depend on everything.
|
||||||
dependencyMap[st.key].add(importModuleName + ".*");
|
const set = dependencyMap[st.key];
|
||||||
|
if (set === undefined) throw new Error("set should not be undefined");
|
||||||
|
set.add(importModuleName + ".*");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FunctionDeclaration: (node) => {
|
FunctionDeclaration: (node: any) => {
|
||||||
const key = currentModule + "." + node.id.name;
|
const key = currentModule + "." + node.id.name;
|
||||||
walk.recursive(node, { key: key }, commonVisitors());
|
walk.recursive(node, { key: key }, commonVisitors());
|
||||||
},
|
},
|
||||||
@ -327,7 +340,10 @@ function parseOnlyCalculateDeps(code, currentModule) {
|
|||||||
* @param {Script[]} otherScripts - All other scripts on the server.
|
* @param {Script[]} otherScripts - All other scripts on the server.
|
||||||
* Used to account for imported scripts
|
* Used to account for imported scripts
|
||||||
*/
|
*/
|
||||||
export async function calculateRamUsage(codeCopy, otherScripts) {
|
export async function calculateRamUsage(
|
||||||
|
codeCopy: string,
|
||||||
|
otherScripts: Script[],
|
||||||
|
): Promise<RamCalculationErrorCode | number> {
|
||||||
// We don't need a real WorkerScript for this. Just an object that keeps
|
// We don't need a real WorkerScript for this. Just an object that keeps
|
||||||
// track of whatever's needed for RAM calculations
|
// track of whatever's needed for RAM calculations
|
||||||
const workerScript = {
|
const workerScript = {
|
||||||
@ -335,7 +351,7 @@ export async function calculateRamUsage(codeCopy, otherScripts) {
|
|||||||
env: {
|
env: {
|
||||||
vars: RamCosts,
|
vars: RamCosts,
|
||||||
},
|
},
|
||||||
};
|
} as WorkerScript;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await parseOnlyRamCalculate(otherScripts, codeCopy, workerScript);
|
return await parseOnlyRamCalculate(otherScripts, codeCopy, workerScript);
|
@ -3,7 +3,6 @@
|
|||||||
* A Script can have multiple active instances
|
* A Script can have multiple active instances
|
||||||
*/
|
*/
|
||||||
import { Script } from "./Script";
|
import { Script } from "./Script";
|
||||||
import { FconfSettings } from "../Fconf/FconfSettings";
|
|
||||||
import { Settings } from "../Settings/Settings";
|
import { Settings } from "../Settings/Settings";
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
import { Terminal } from "../Terminal";
|
import { Terminal } from "../Terminal";
|
||||||
|
6
src/Script/ScriptHelpers.d.ts
vendored
6
src/Script/ScriptHelpers.d.ts
vendored
@ -1,6 +0,0 @@
|
|||||||
export declare function findRunningScript(
|
|
||||||
filename: string,
|
|
||||||
args: (string | number)[],
|
|
||||||
server: BaseServer,
|
|
||||||
): RunningScript | null;
|
|
||||||
export declare function findRunningScriptByPid(pid: number, server: BaseServer): RunningScript | null;
|
|
@ -1,13 +1,16 @@
|
|||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { AllServers } from "../Server/AllServers";
|
import { AllServers } from "../Server/AllServers";
|
||||||
|
import { BaseServer } from "../Server/BaseServer";
|
||||||
|
import { Server } from "../Server/Server";
|
||||||
|
import { RunningScript } from "../Script/RunningScript";
|
||||||
import { processSingleServerGrowth } from "../Server/ServerHelpers";
|
import { processSingleServerGrowth } from "../Server/ServerHelpers";
|
||||||
|
|
||||||
import { numeralWrapper } from "../ui/numeralFormat";
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
|
|
||||||
import { compareArrays } from "../../utils/helpers/compareArrays";
|
import { compareArrays } from "../../utils/helpers/compareArrays";
|
||||||
|
|
||||||
export function scriptCalculateOfflineProduction(runningScriptObj) {
|
export function scriptCalculateOfflineProduction(runningScript: RunningScript) {
|
||||||
//The Player object stores the last update time from when we were online
|
//The Player object stores the last update time from when we were online
|
||||||
const thisUpdate = new Date().getTime();
|
const thisUpdate = new Date().getTime();
|
||||||
const lastUpdate = Player.lastUpdate;
|
const lastUpdate = Player.lastUpdate;
|
||||||
@ -16,7 +19,7 @@ export function scriptCalculateOfflineProduction(runningScriptObj) {
|
|||||||
//Calculate the "confidence" rating of the script's true production. This is based
|
//Calculate the "confidence" rating of the script's true production. This is based
|
||||||
//entirely off of time. We will arbitrarily say that if a script has been running for
|
//entirely off of time. We will arbitrarily say that if a script has been running for
|
||||||
//4 hours (14400 sec) then we are completely confident in its ability
|
//4 hours (14400 sec) then we are completely confident in its ability
|
||||||
let confidence = runningScriptObj.onlineRunningTime / 14400;
|
let confidence = runningScript.onlineRunningTime / 14400;
|
||||||
if (confidence >= 1) {
|
if (confidence >= 1) {
|
||||||
confidence = 1;
|
confidence = 1;
|
||||||
}
|
}
|
||||||
@ -24,9 +27,9 @@ export function scriptCalculateOfflineProduction(runningScriptObj) {
|
|||||||
//Data map: [MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken]
|
//Data map: [MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken]
|
||||||
|
|
||||||
// Grow
|
// Grow
|
||||||
for (const ip in runningScriptObj.dataMap) {
|
for (const ip in runningScript.dataMap) {
|
||||||
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
|
if (runningScript.dataMap.hasOwnProperty(ip)) {
|
||||||
if (runningScriptObj.dataMap[ip][2] == 0 || runningScriptObj.dataMap[ip][2] == null) {
|
if (runningScript.dataMap[ip][2] == 0 || runningScript.dataMap[ip][2] == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const serv = AllServers[ip];
|
const serv = AllServers[ip];
|
||||||
@ -34,12 +37,13 @@ export function scriptCalculateOfflineProduction(runningScriptObj) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const timesGrown = Math.round(
|
const timesGrown = Math.round(
|
||||||
((0.5 * runningScriptObj.dataMap[ip][2]) / runningScriptObj.onlineRunningTime) * timePassed,
|
((0.5 * runningScript.dataMap[ip][2]) / runningScript.onlineRunningTime) * timePassed,
|
||||||
);
|
);
|
||||||
runningScriptObj.log(`Called on ${serv.hostname} ${timesGrown} times while offline`);
|
runningScript.log(`Called on ${serv.hostname} ${timesGrown} times while offline`);
|
||||||
const host = AllServers[runningScriptObj.server];
|
const host = AllServers[runningScript.server];
|
||||||
|
if (!(serv instanceof Server)) throw new Error("trying to grow a non-normal server");
|
||||||
const growth = processSingleServerGrowth(serv, timesGrown, Player, host.cpuCores);
|
const growth = processSingleServerGrowth(serv, timesGrown, Player, host.cpuCores);
|
||||||
runningScriptObj.log(
|
runningScript.log(
|
||||||
`'${serv.hostname}' grown by ${numeralWrapper.format(growth * 100 - 100, "0.000000%")} while offline`,
|
`'${serv.hostname}' grown by ${numeralWrapper.format(growth * 100 - 100, "0.000000%")} while offline`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -47,28 +51,30 @@ export function scriptCalculateOfflineProduction(runningScriptObj) {
|
|||||||
|
|
||||||
// Offline EXP gain
|
// Offline EXP gain
|
||||||
// A script's offline production will always be at most half of its online production.
|
// A script's offline production will always be at most half of its online production.
|
||||||
const expGain = confidence * (runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime) * timePassed;
|
const expGain = confidence * (runningScript.onlineExpGained / runningScript.onlineRunningTime) * timePassed;
|
||||||
Player.gainHackingExp(expGain);
|
Player.gainHackingExp(expGain);
|
||||||
|
|
||||||
// Update script stats
|
// Update script stats
|
||||||
runningScriptObj.offlineRunningTime += timePassed;
|
runningScript.offlineRunningTime += timePassed;
|
||||||
runningScriptObj.offlineExpGained += expGain;
|
runningScript.offlineExpGained += expGain;
|
||||||
|
|
||||||
// Weaken
|
// Weaken
|
||||||
for (const ip in runningScriptObj.dataMap) {
|
for (const ip in runningScript.dataMap) {
|
||||||
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
|
if (runningScript.dataMap.hasOwnProperty(ip)) {
|
||||||
if (runningScriptObj.dataMap[ip][3] == 0 || runningScriptObj.dataMap[ip][3] == null) {
|
if (runningScript.dataMap[ip][3] == 0 || runningScript.dataMap[ip][3] == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const serv = AllServers[ip];
|
const serv = AllServers[ip];
|
||||||
if (serv == null) {
|
if (serv == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const host = AllServers[runningScriptObj.server];
|
|
||||||
|
if (!(serv instanceof Server)) throw new Error("trying to weaken a non-normal server");
|
||||||
|
const host = AllServers[runningScript.server];
|
||||||
const timesWeakened = Math.round(
|
const timesWeakened = Math.round(
|
||||||
((0.5 * runningScriptObj.dataMap[ip][3]) / runningScriptObj.onlineRunningTime) * timePassed,
|
((0.5 * runningScript.dataMap[ip][3]) / runningScript.onlineRunningTime) * timePassed,
|
||||||
);
|
);
|
||||||
runningScriptObj.log(`Called weaken() on ${serv.hostname} ${timesWeakened} times while offline`);
|
runningScript.log(`Called weaken() on ${serv.hostname} ${timesWeakened} times while offline`);
|
||||||
const coreBonus = 1 + (host.cpuCores - 1) / 16;
|
const coreBonus = 1 + (host.cpuCores - 1) / 16;
|
||||||
serv.weaken(CONSTANTS.ServerWeakenAmount * timesWeakened * coreBonus);
|
serv.weaken(CONSTANTS.ServerWeakenAmount * timesWeakened * coreBonus);
|
||||||
}
|
}
|
||||||
@ -77,7 +83,7 @@ export function scriptCalculateOfflineProduction(runningScriptObj) {
|
|||||||
|
|
||||||
//Returns a RunningScript object matching the filename and arguments on the
|
//Returns a RunningScript object matching the filename and arguments on the
|
||||||
//designated server, and false otherwise
|
//designated server, and false otherwise
|
||||||
export function findRunningScript(filename, args, server) {
|
export function findRunningScript(filename: string, args: (string | number)[], server: BaseServer) {
|
||||||
for (var i = 0; i < server.runningScripts.length; ++i) {
|
for (var i = 0; i < server.runningScripts.length; ++i) {
|
||||||
if (server.runningScripts[i].filename === filename && compareArrays(server.runningScripts[i].args, args)) {
|
if (server.runningScripts[i].filename === filename && compareArrays(server.runningScripts[i].args, args)) {
|
||||||
return server.runningScripts[i];
|
return server.runningScripts[i];
|
||||||
@ -88,7 +94,7 @@ export function findRunningScript(filename, args, server) {
|
|||||||
|
|
||||||
//Returns a RunningScript object matching the pid on the
|
//Returns a RunningScript object matching the pid on the
|
||||||
//designated server, and false otherwise
|
//designated server, and false otherwise
|
||||||
export function findRunningScriptByPid(pid, server) {
|
export function findRunningScriptByPid(pid: number, server: BaseServer) {
|
||||||
for (var i = 0; i < server.runningScripts.length; ++i) {
|
for (var i = 0; i < server.runningScripts.length; ++i) {
|
||||||
if (server.runningScripts[i].pid === pid) {
|
if (server.runningScripts[i].pid === pid) {
|
||||||
return server.runningScripts[i];
|
return server.runningScripts[i];
|
@ -1,4 +1,3 @@
|
|||||||
// Script helper functions
|
|
||||||
export function isScriptFilename(f: string): boolean {
|
export function isScriptFilename(f: string): boolean {
|
||||||
return f.endsWith(".js") || f.endsWith(".script") || f.endsWith(".ns");
|
return f.endsWith(".js") || f.endsWith(".script") || f.endsWith(".ns");
|
||||||
}
|
}
|
@ -11,8 +11,7 @@ import { isValidFilePath } from "../../Terminal/DirectoryHelpers";
|
|||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||||
import { parseFconfSettings } from "../../Fconf/Fconf";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
|
||||||
import { Script } from "../../Script/Script";
|
import { Script } from "../../Script/Script";
|
||||||
import { TextFile } from "../../TextFile";
|
import { TextFile } from "../../TextFile";
|
||||||
import { calculateRamUsage } from "../../Script/RamCalculations";
|
import { calculateRamUsage } from "../../Script/RamCalculations";
|
||||||
@ -144,7 +143,7 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename !== ".fconf" && !isValidFilePath(filename)) {
|
if (!isValidFilePath(filename)) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"Script filename can contain only alphanumerics, hyphens, and underscores, and must end with an extension.",
|
"Script filename can contain only alphanumerics, hyphens, and underscores, and must end with an extension.",
|
||||||
);
|
);
|
||||||
@ -153,14 +152,7 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
const server = props.player.getCurrentServer();
|
const server = props.player.getCurrentServer();
|
||||||
if (server === null) throw new Error("Server should not be null but it is.");
|
if (server === null) throw new Error("Server should not be null but it is.");
|
||||||
if (filename === ".fconf") {
|
if (isScriptFilename(filename)) {
|
||||||
try {
|
|
||||||
parseFconfSettings(code);
|
|
||||||
} catch (e) {
|
|
||||||
dialogBoxCreate(`Invalid .fconf file: ${e}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (isScriptFilename(filename)) {
|
|
||||||
//If the current script already exists on the server, overwrite it
|
//If the current script already exists on the server, overwrite it
|
||||||
for (let i = 0; i < server.scripts.length; i++) {
|
for (let i = 0; i < server.scripts.length; i++) {
|
||||||
if (filename == server.scripts[i].filename) {
|
if (filename == server.scripts[i].filename) {
|
||||||
|
@ -9,7 +9,7 @@ import { isValidFilePath } from "../Terminal/DirectoryHelpers";
|
|||||||
import { TextFile } from "../TextFile";
|
import { TextFile } from "../TextFile";
|
||||||
import { IReturnStatus } from "../types";
|
import { IReturnStatus } from "../types";
|
||||||
|
|
||||||
import { isScriptFilename } from "../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../Script/isScriptFilename";
|
||||||
|
|
||||||
import { createRandomIp } from "../../utils/IPAddress";
|
import { createRandomIp } from "../../utils/IPAddress";
|
||||||
import { compareArrays } from "../../utils/helpers/compareArrays";
|
import { compareArrays } from "../../utils/helpers/compareArrays";
|
||||||
|
@ -295,7 +295,6 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
clickCreateProgram();
|
clickCreateProgram();
|
||||||
} else if (event.keyCode === KEY.F && event.altKey) {
|
} else if (event.keyCode === KEY.F && event.altKey) {
|
||||||
// Overriden by Fconf
|
|
||||||
if (props.page == Page.Terminal && Settings.EnableBashHotkeys) {
|
if (props.page == Page.Terminal && Settings.EnableBashHotkeys) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
1
src/Terminal.d.ts
vendored
1
src/Terminal.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
export declare const Terminal: ITerminal;
|
|
@ -3,13 +3,14 @@ import { IRouter } from "../ui/Router";
|
|||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { HacknetServer } from "../Hacknet/HacknetServer";
|
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||||
import { BaseServer } from "../Server/BaseServer";
|
import { BaseServer } from "../Server/BaseServer";
|
||||||
|
import { Server } from "../Server/Server";
|
||||||
import { Programs } from "../Programs/Programs";
|
import { Programs } from "../Programs/Programs";
|
||||||
import { CodingContractResult } from "../CodingContracts";
|
import { CodingContractResult } from "../CodingContracts";
|
||||||
import { TerminalEvents, TerminalClearEvents } from "./TerminalEvents";
|
import { TerminalEvents, TerminalClearEvents } from "./TerminalEvents";
|
||||||
|
|
||||||
import { TextFile } from "../TextFile";
|
import { TextFile } from "../TextFile";
|
||||||
import { Script } from "../Script/Script";
|
import { Script } from "../Script/Script";
|
||||||
import { isScriptFilename } from "../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../Script/isScriptFilename";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import { AllServers } from "../Server/AllServers";
|
import { AllServers } from "../Server/AllServers";
|
||||||
|
|
||||||
@ -91,7 +92,7 @@ export class Terminal implements ITerminal {
|
|||||||
append(item: Output | Link): void {
|
append(item: Output | Link): void {
|
||||||
this.outputHistory.push(item);
|
this.outputHistory.push(item);
|
||||||
if (this.outputHistory.length > Settings.MaxTerminalCapacity) {
|
if (this.outputHistory.length > Settings.MaxTerminalCapacity) {
|
||||||
this.outputHistory.slice(this.outputHistory.length - Settings.MaxTerminalCapacity);
|
this.outputHistory.splice(0, this.outputHistory.length - Settings.MaxTerminalCapacity);
|
||||||
}
|
}
|
||||||
TerminalEvents.emit();
|
TerminalEvents.emit();
|
||||||
}
|
}
|
||||||
@ -106,12 +107,22 @@ export class Terminal implements ITerminal {
|
|||||||
|
|
||||||
startHack(player: IPlayer): void {
|
startHack(player: IPlayer): void {
|
||||||
// Hacking through Terminal should be faster than hacking through a script
|
// Hacking through Terminal should be faster than hacking through a script
|
||||||
this.startAction(calculateHackingTime(player.getCurrentServer(), player) / 4, "h");
|
const server = player.getCurrentServer();
|
||||||
|
if (server instanceof HacknetServer) {
|
||||||
|
this.error("Cannot hack this kind of server");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.startAction(calculateHackingTime(server, player) / 4, "h");
|
||||||
}
|
}
|
||||||
|
|
||||||
startBackdoor(player: IPlayer): void {
|
startBackdoor(player: IPlayer): void {
|
||||||
// Backdoor should take the same amount of time as hack
|
// Backdoor should take the same amount of time as hack
|
||||||
this.startAction(calculateHackingTime(player.getCurrentServer(), player) / 4, "b");
|
const server = player.getCurrentServer();
|
||||||
|
if (server instanceof HacknetServer) {
|
||||||
|
this.error("Cannot backdoor this kind of server");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.startAction(calculateHackingTime(server, player) / 4, "b");
|
||||||
}
|
}
|
||||||
|
|
||||||
startAnalyze(): void {
|
startAnalyze(): void {
|
||||||
@ -127,6 +138,10 @@ export class Terminal implements ITerminal {
|
|||||||
finishHack(router: IRouter, player: IPlayer, cancelled = false): void {
|
finishHack(router: IRouter, player: IPlayer, cancelled = false): void {
|
||||||
if (cancelled) return;
|
if (cancelled) return;
|
||||||
const server = player.getCurrentServer();
|
const server = player.getCurrentServer();
|
||||||
|
if (server instanceof HacknetServer) {
|
||||||
|
this.error("Cannot hack this kind of server");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate whether hack was successful
|
// Calculate whether hack was successful
|
||||||
const hackChance = calculateHackingChance(server, player);
|
const hackChance = calculateHackingChance(server, player);
|
||||||
@ -179,6 +194,10 @@ export class Terminal implements ITerminal {
|
|||||||
finishBackdoor(router: IRouter, player: IPlayer, cancelled = false): void {
|
finishBackdoor(router: IRouter, player: IPlayer, cancelled = false): void {
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
const server = player.getCurrentServer();
|
const server = player.getCurrentServer();
|
||||||
|
if (server instanceof HacknetServer) {
|
||||||
|
this.error("Cannot hack this kind of server");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
SpecialServerIps[SpecialServerNames.WorldDaemon] &&
|
SpecialServerIps[SpecialServerNames.WorldDaemon] &&
|
||||||
SpecialServerIps[SpecialServerNames.WorldDaemon] == server.ip
|
SpecialServerIps[SpecialServerNames.WorldDaemon] == server.ip
|
||||||
@ -203,24 +222,30 @@ export class Terminal implements ITerminal {
|
|||||||
this.print("Organization name: " + (!isHacknet ? org : "player"));
|
this.print("Organization name: " + (!isHacknet ? org : "player"));
|
||||||
const hasAdminRights = (!isHacknet && currServ.hasAdminRights) || isHacknet;
|
const hasAdminRights = (!isHacknet && currServ.hasAdminRights) || isHacknet;
|
||||||
this.print("Root Access: " + (hasAdminRights ? "YES" : "NO"));
|
this.print("Root Access: " + (hasAdminRights ? "YES" : "NO"));
|
||||||
const hackingSkill = currServ.requiredHackingSkill;
|
if (currServ instanceof Server) {
|
||||||
this.print("Required hacking skill: " + (!isHacknet ? hackingSkill : "N/A"));
|
const hackingSkill = currServ.requiredHackingSkill;
|
||||||
const security = currServ.hackDifficulty;
|
this.print("Required hacking skill: " + (!isHacknet ? hackingSkill : "N/A"));
|
||||||
this.print("Server security level: " + (!isHacknet ? numeralWrapper.formatServerSecurity(security) : "N/A"));
|
const security = currServ.hackDifficulty;
|
||||||
const hackingChance = calculateHackingChance(currServ, player);
|
this.print("Server security level: " + (!isHacknet ? numeralWrapper.formatServerSecurity(security) : "N/A"));
|
||||||
this.print("Chance to hack: " + (!isHacknet ? numeralWrapper.formatPercentage(hackingChance) : "N/A"));
|
const hackingChance = calculateHackingChance(currServ, player);
|
||||||
const hackingTime = calculateHackingTime(currServ, player) * 1000;
|
this.print("Chance to hack: " + (!isHacknet ? numeralWrapper.formatPercentage(hackingChance) : "N/A"));
|
||||||
this.print("Time to hack: " + (!isHacknet ? convertTimeMsToTimeElapsedString(hackingTime, true) : "N/A"));
|
const hackingTime = calculateHackingTime(currServ, player) * 1000;
|
||||||
|
this.print("Time to hack: " + (!isHacknet ? convertTimeMsToTimeElapsedString(hackingTime, true) : "N/A"));
|
||||||
|
}
|
||||||
this.print(
|
this.print(
|
||||||
`Total money available on server: ${!isHacknet ? numeralWrapper.formatMoney(currServ.moneyAvailable) : "N/A"}`,
|
`Total money available on server: ${
|
||||||
|
!(currServ instanceof HacknetServer) ? numeralWrapper.formatMoney(currServ.moneyAvailable) : "N/A"
|
||||||
|
}`,
|
||||||
);
|
);
|
||||||
const numPort = currServ.numOpenPortsRequired;
|
if (currServ instanceof Server) {
|
||||||
this.print("Required number of open ports for NUKE: " + (!isHacknet ? numPort : "N/A"));
|
const numPort = currServ.numOpenPortsRequired;
|
||||||
this.print("SSH port: " + (currServ.sshPortOpen ? "Open" : "Closed"));
|
this.print("Required number of open ports for NUKE: " + (!isHacknet ? numPort : "N/A"));
|
||||||
this.print("FTP port: " + (currServ.ftpPortOpen ? "Open" : "Closed"));
|
this.print("SSH port: " + (currServ.sshPortOpen ? "Open" : "Closed"));
|
||||||
this.print("SMTP port: " + (currServ.smtpPortOpen ? "Open" : "Closed"));
|
this.print("FTP port: " + (currServ.ftpPortOpen ? "Open" : "Closed"));
|
||||||
this.print("HTTP port: " + (currServ.httpPortOpen ? "Open" : "Closed"));
|
this.print("SMTP port: " + (currServ.smtpPortOpen ? "Open" : "Closed"));
|
||||||
this.print("SQL port: " + (currServ.sqlPortOpen ? "Open" : "Closed"));
|
this.print("HTTP port: " + (currServ.httpPortOpen ? "Open" : "Closed"));
|
||||||
|
this.print("SQL port: " + (currServ.sqlPortOpen ? "Open" : "Closed"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { IRouter } from "../../ui/Router";
|
|||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { findRunningScript } from "../../Script/ScriptHelpers";
|
import { findRunningScript } from "../../Script/ScriptHelpers";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
|
|
||||||
export function check(
|
export function check(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
|
@ -2,7 +2,7 @@ import { ITerminal } from "../ITerminal";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
import FileSaver from "file-saver";
|
import FileSaver from "file-saver";
|
||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { ITerminal } from "../ITerminal";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
import { TextFile } from "../../TextFile";
|
import { TextFile } from "../../TextFile";
|
||||||
import { Script } from "../../Script/Script";
|
import { Script } from "../../Script/Script";
|
||||||
|
|
||||||
|
@ -2,8 +2,7 @@ import { ITerminal } from "../ITerminal";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
import { createFconf } from "../../Fconf/Fconf";
|
|
||||||
|
|
||||||
export function nano(
|
export function nano(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
@ -19,11 +18,7 @@ export function nano(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const filename = args[0] + "";
|
const filename = args[0] + "";
|
||||||
if (filename === ".fconf") {
|
if (isScriptFilename(filename)) {
|
||||||
const text = createFconf();
|
|
||||||
router.toScriptEditor(filename, text);
|
|
||||||
return;
|
|
||||||
} else if (isScriptFilename(filename)) {
|
|
||||||
const filepath = terminal.getFilepath(filename);
|
const filepath = terminal.getFilepath(filename);
|
||||||
const script = terminal.getScript(player, filename);
|
const script = terminal.getScript(player, filename);
|
||||||
if (script == null) {
|
if (script == null) {
|
||||||
|
@ -2,7 +2,7 @@ import { ITerminal } from "../ITerminal";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
import { runScript } from "./runScript";
|
import { runScript } from "./runScript";
|
||||||
import { runProgram } from "./runProgram";
|
import { runProgram } from "./runProgram";
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
|||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { Message } from "../../Message/Message";
|
import { Message } from "../../Message/Message";
|
||||||
import { getServer } from "../../Server/ServerHelpers";
|
import { getServer } from "../../Server/ServerHelpers";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
|
|
||||||
export function scp(
|
export function scp(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
|
@ -4,8 +4,8 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
|||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { logBoxCreate } from "../../../utils/LogBox";
|
import { logBoxCreate } from "../../../utils/LogBox";
|
||||||
import { findRunningScriptByPid } from "../../Script/ScriptHelpers";
|
import { findRunningScriptByPid } from "../../Script/ScriptHelpers";
|
||||||
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
import { compareArrays } from "../../../utils/helpers/compareArrays";
|
import { compareArrays } from "../../../utils/helpers/compareArrays";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
|
||||||
|
|
||||||
export function tail(
|
export function tail(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
|
@ -2,7 +2,7 @@ import { ITerminal } from "../ITerminal";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
|
|
||||||
export function wget(
|
export function wget(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
|
@ -12,6 +12,7 @@ import { IRouter } from "../../ui/Router";
|
|||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { TerminalInput } from "./TerminalInput";
|
import { TerminalInput } from "./TerminalInput";
|
||||||
import { TerminalEvents, TerminalClearEvents } from "../TerminalEvents";
|
import { TerminalEvents, TerminalClearEvents } from "../TerminalEvents";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
interface IActionTimerProps {
|
interface IActionTimerProps {
|
||||||
terminal: ITerminal;
|
terminal: ITerminal;
|
||||||
|
1
src/ThirdParty/JSInterpreter.d.ts
vendored
Normal file
1
src/ThirdParty/JSInterpreter.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare let Interpreter: any;
|
1
src/ThirdParty/sprintf-js.d.ts
vendored
Normal file
1
src/ThirdParty/sprintf-js.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare module "sprintf-js";
|
@ -50,7 +50,29 @@ import { startUnclickable } from "./Exploits/unclickable";
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
const Engine = {
|
const Engine: {
|
||||||
|
_lastUpdate: number;
|
||||||
|
updateGame: (numCycles?: number) => void;
|
||||||
|
Counters: {
|
||||||
|
[key: string]: number | undefined;
|
||||||
|
autoSaveCounter: number;
|
||||||
|
updateSkillLevelsCounter: number;
|
||||||
|
updateDisplays: number;
|
||||||
|
updateDisplaysLong: number;
|
||||||
|
updateActiveScriptsDisplay: number;
|
||||||
|
createProgramNotifications: number;
|
||||||
|
augmentationsNotifications: number;
|
||||||
|
checkFactionInvitations: number;
|
||||||
|
passiveFactionGrowth: number;
|
||||||
|
messages: number;
|
||||||
|
mechanicProcess: number;
|
||||||
|
contractGeneration: number;
|
||||||
|
};
|
||||||
|
decrementAllCounters: (numCycles?: number) => void;
|
||||||
|
checkCounters: () => void;
|
||||||
|
load: (saveString: string) => void;
|
||||||
|
start: () => void;
|
||||||
|
} = {
|
||||||
// Time variables (milliseconds unix epoch time)
|
// Time variables (milliseconds unix epoch time)
|
||||||
_lastUpdate: new Date().getTime(),
|
_lastUpdate: new Date().getTime(),
|
||||||
|
|
||||||
@ -106,7 +128,7 @@ const Engine = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gang, if applicable
|
// Gang, if applicable
|
||||||
if (Player.inGang()) {
|
if (Player.inGang() && Player.gang !== null) {
|
||||||
Player.gang.process(numCycles, Player);
|
Player.gang.process(numCycles, Player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,10 +197,10 @@ const Engine = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
decrementAllCounters: function (numCycles = 1) {
|
decrementAllCounters: function (numCycles = 1) {
|
||||||
for (var counter in Engine.Counters) {
|
for (const counterName in Engine.Counters) {
|
||||||
if (Engine.Counters.hasOwnProperty(counter)) {
|
const counter = Engine.Counters[counterName];
|
||||||
Engine.Counters[counter] = Engine.Counters[counter] - numCycles;
|
if (counter === undefined) throw new Error("counter should not be undefined");
|
||||||
}
|
Engine.Counters[counterName] = counter - numCycles;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -328,8 +350,9 @@ const Engine = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gang progress for BitNode 2
|
// Gang progress for BitNode 2
|
||||||
if (Player.inGang()) {
|
const gang = Player.gang;
|
||||||
Player.gang.process(numCyclesOffline, Player);
|
if (Player.inGang() && gang !== null) {
|
||||||
|
gang.process(numCyclesOffline, Player);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Corporation offline progress
|
// Corporation offline progress
|
@ -326,11 +326,11 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
) : page === Page.DevMenu ? (
|
) : page === Page.DevMenu ? (
|
||||||
<DevMenuRoot player={player} engine={engine} router={Router} />
|
<DevMenuRoot player={player} engine={engine} router={Router} />
|
||||||
) : page === Page.Gang ? (
|
) : page === Page.Gang ? (
|
||||||
<GangRoot gang={player.gang} />
|
<GangRoot />
|
||||||
) : page === Page.Corporation ? (
|
) : page === Page.Corporation ? (
|
||||||
<CorporationRoot corp={player.corporation} player={player} />
|
<CorporationRoot />
|
||||||
) : page === Page.Bladeburner ? (
|
) : page === Page.Bladeburner ? (
|
||||||
<BladeburnerRoot bladeburner={player.bladeburner} />
|
<BladeburnerRoot />
|
||||||
) : page === Page.Resleeves ? (
|
) : page === Page.Resleeves ? (
|
||||||
<ResleeveRoot player={player} />
|
<ResleeveRoot player={player} />
|
||||||
) : page === Page.Travel ? (
|
) : page === Page.Travel ? (
|
||||||
|
@ -1,177 +0,0 @@
|
|||||||
// Implement the collapsible main menu headers
|
|
||||||
import { MainMenuLinks } from "./Links";
|
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
interface IMainMenuHeaders {
|
|
||||||
Hacking: HTMLElement | null;
|
|
||||||
Character: HTMLElement | null;
|
|
||||||
World: HTMLElement | null;
|
|
||||||
Help: HTMLElement | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MainMenuHeaders: IMainMenuHeaders = {
|
|
||||||
Hacking: null,
|
|
||||||
Character: null,
|
|
||||||
World: null,
|
|
||||||
Help: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Implements collapsible toggle feature when a header is clicked
|
|
||||||
function toggleHeader(open: boolean, elems: HTMLElement[], links: HTMLElement[]): void {
|
|
||||||
for (let 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 = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let 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 = "";
|
|
||||||
links[i].style.pointerEvents = "none";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function initializeMainMenuHeaders(p: IPlayer, dev = false): boolean {
|
|
||||||
function safeGetElement(id: string): HTMLElement {
|
|
||||||
const elem: HTMLElement | null = document.getElementById(id);
|
|
||||||
if (elem == null) {
|
|
||||||
throw new Error(`Failed to find element with id ${id} in initializeMainMenuHeaders()`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Get references to the DOM elements
|
|
||||||
MainMenuHeaders.Hacking = safeGetElement("hacking-menu-header");
|
|
||||||
MainMenuHeaders.Character = safeGetElement("character-menu-header");
|
|
||||||
MainMenuHeaders.World = safeGetElement("world-menu-header");
|
|
||||||
MainMenuHeaders.Help = safeGetElement("help-menu-header");
|
|
||||||
|
|
||||||
// Set click handlers to turn the headers into collapsibles
|
|
||||||
MainMenuHeaders.Hacking.onclick = function () {
|
|
||||||
const terminal: HTMLElement = safeGetElement("terminal-tab");
|
|
||||||
const createScript: HTMLElement = safeGetElement("create-script-tab");
|
|
||||||
const activeScripts: HTMLElement = safeGetElement("active-scripts-tab");
|
|
||||||
const createProgram: HTMLElement = safeGetElement("create-program-tab");
|
|
||||||
const createProgramNot: HTMLElement = safeGetElement("create-program-notification");
|
|
||||||
|
|
||||||
createProgram.style.display = p.firstProgramAvailable ? "list-item" : "none";
|
|
||||||
|
|
||||||
(this as any).classList.toggle("opened");
|
|
||||||
|
|
||||||
const elems: HTMLElement[] = [terminal, createScript, activeScripts, createProgram];
|
|
||||||
const links: HTMLElement[] = [
|
|
||||||
MainMenuLinks.Terminal,
|
|
||||||
MainMenuLinks.ScriptEditor,
|
|
||||||
MainMenuLinks.ActiveScripts,
|
|
||||||
MainMenuLinks.CreateProgram,
|
|
||||||
];
|
|
||||||
if (terminal.style.maxHeight) {
|
|
||||||
toggleHeader(false, elems, links);
|
|
||||||
createProgramNot.style.display = "none";
|
|
||||||
} else {
|
|
||||||
toggleHeader(true, elems, links);
|
|
||||||
createProgramNot.style.display = "block";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MainMenuHeaders.Character.onclick = function () {
|
|
||||||
const stats: HTMLElement = safeGetElement("stats-tab");
|
|
||||||
const factions: HTMLElement = safeGetElement("factions-tab");
|
|
||||||
const augmentations: HTMLElement = safeGetElement("augmentations-tab");
|
|
||||||
const hacknetnodes: HTMLElement = safeGetElement("hacknet-nodes-tab");
|
|
||||||
const sleeves: HTMLElement = safeGetElement("sleeves-tab");
|
|
||||||
|
|
||||||
sleeves.style.display = p.sleeves.length > 0 ? "list-item" : "none";
|
|
||||||
|
|
||||||
(this as any).classList.toggle("opened");
|
|
||||||
|
|
||||||
const elems: HTMLElement[] = [stats, factions, augmentations, hacknetnodes, sleeves];
|
|
||||||
const links: HTMLElement[] = [
|
|
||||||
MainMenuLinks.Stats,
|
|
||||||
MainMenuLinks.Factions,
|
|
||||||
MainMenuLinks.Augmentations,
|
|
||||||
MainMenuLinks.HacknetNodes,
|
|
||||||
MainMenuLinks.Sleeves,
|
|
||||||
];
|
|
||||||
if (stats.style.maxHeight) {
|
|
||||||
toggleHeader(false, elems, links);
|
|
||||||
} else {
|
|
||||||
toggleHeader(true, elems, links);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MainMenuHeaders.World.onclick = function () {
|
|
||||||
const city: HTMLElement = safeGetElement("city-tab");
|
|
||||||
const travel: HTMLElement = safeGetElement("travel-tab");
|
|
||||||
const job: HTMLElement = safeGetElement("job-tab");
|
|
||||||
const stockmarket: HTMLElement = safeGetElement("stock-market-tab");
|
|
||||||
const bladeburner: HTMLElement = safeGetElement("bladeburner-tab");
|
|
||||||
const corporation: HTMLElement = safeGetElement("corporation-tab");
|
|
||||||
const gang: HTMLElement = safeGetElement("gang-tab");
|
|
||||||
|
|
||||||
// Determine whether certain links should show up
|
|
||||||
job.style.display = p.companyName !== "" ? "list-item" : "none";
|
|
||||||
stockmarket.style.display = p.hasWseAccount ? "list-item" : "none";
|
|
||||||
bladeburner.style.display = p.inBladeburner() ? "list-item" : "none";
|
|
||||||
corporation.style.display = p.hasCorporation() ? "list-item" : "none";
|
|
||||||
gang.style.display = p.inGang() ? "list-item" : "none";
|
|
||||||
|
|
||||||
(this as any).classList.toggle("opened");
|
|
||||||
|
|
||||||
const elems: HTMLElement[] = [city, travel, job, stockmarket, bladeburner, corporation, gang];
|
|
||||||
const links: HTMLElement[] = [
|
|
||||||
MainMenuLinks.City,
|
|
||||||
MainMenuLinks.Travel,
|
|
||||||
MainMenuLinks.Job,
|
|
||||||
MainMenuLinks.StockMarket,
|
|
||||||
MainMenuLinks.Bladeburner,
|
|
||||||
MainMenuLinks.Corporation,
|
|
||||||
MainMenuLinks.Gang,
|
|
||||||
];
|
|
||||||
if (city.style.maxHeight) {
|
|
||||||
toggleHeader(false, elems, links);
|
|
||||||
} else {
|
|
||||||
toggleHeader(true, elems, links);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MainMenuHeaders.Help.onclick = function () {
|
|
||||||
const milestones: HTMLElement = safeGetElement("milestones-tab");
|
|
||||||
const tutorial: HTMLElement = safeGetElement("tutorial-tab");
|
|
||||||
const options: HTMLElement = safeGetElement("options-tab");
|
|
||||||
|
|
||||||
(this as any).classList.toggle("opened");
|
|
||||||
|
|
||||||
const elems: HTMLElement[] = [milestones, tutorial, options];
|
|
||||||
const links: HTMLElement[] = [MainMenuLinks.Milestones, MainMenuLinks.Tutorial, MainMenuLinks.Options];
|
|
||||||
|
|
||||||
if (dev) {
|
|
||||||
elems.push(safeGetElement("dev-tab"));
|
|
||||||
links.push(safeGetElement("dev-menu-link"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tutorial.style.maxHeight) {
|
|
||||||
toggleHeader(false, elems, links);
|
|
||||||
} else {
|
|
||||||
toggleHeader(true, elems, links);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to initialize Main Menu Headers: ${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
// Get references to the Main Menu link DOM elements
|
|
||||||
// Does NOT include collapsible headers for the links
|
|
||||||
import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
|
|
||||||
|
|
||||||
interface IMainMenuLinks {
|
|
||||||
[key: string]: HTMLElement | undefined;
|
|
||||||
Terminal: HTMLElement;
|
|
||||||
ScriptEditor: HTMLElement;
|
|
||||||
ActiveScripts: HTMLElement;
|
|
||||||
CreateProgram: HTMLElement;
|
|
||||||
Stats: HTMLElement;
|
|
||||||
Factions: HTMLElement;
|
|
||||||
Augmentations: HTMLElement;
|
|
||||||
HacknetNodes: HTMLElement;
|
|
||||||
Sleeves: HTMLElement;
|
|
||||||
City: HTMLElement;
|
|
||||||
Travel: HTMLElement;
|
|
||||||
Job: HTMLElement;
|
|
||||||
StockMarket: HTMLElement;
|
|
||||||
Bladeburner: HTMLElement;
|
|
||||||
Corporation: HTMLElement;
|
|
||||||
Gang: HTMLElement;
|
|
||||||
Milestones: HTMLElement;
|
|
||||||
Tutorial: HTMLElement;
|
|
||||||
Options: HTMLElement;
|
|
||||||
DevMenu: HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emptyElement: HTMLElement = ((): HTMLElement => {
|
|
||||||
const elem = document.createElement("div");
|
|
||||||
if (elem === null) throw new Error("unable to create empty div element");
|
|
||||||
return elem;
|
|
||||||
})();
|
|
||||||
|
|
||||||
export const MainMenuLinks: IMainMenuLinks = {
|
|
||||||
Terminal: emptyElement,
|
|
||||||
ScriptEditor: emptyElement,
|
|
||||||
ActiveScripts: emptyElement,
|
|
||||||
CreateProgram: emptyElement,
|
|
||||||
Stats: emptyElement,
|
|
||||||
Factions: emptyElement,
|
|
||||||
Augmentations: emptyElement,
|
|
||||||
HacknetNodes: emptyElement,
|
|
||||||
Sleeves: emptyElement,
|
|
||||||
City: emptyElement,
|
|
||||||
Travel: emptyElement,
|
|
||||||
Job: emptyElement,
|
|
||||||
StockMarket: emptyElement,
|
|
||||||
Bladeburner: emptyElement,
|
|
||||||
Corporation: emptyElement,
|
|
||||||
Gang: emptyElement,
|
|
||||||
Milestones: emptyElement,
|
|
||||||
Tutorial: emptyElement,
|
|
||||||
Options: emptyElement,
|
|
||||||
DevMenu: emptyElement,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function initializeMainMenuLinks(): boolean {
|
|
||||||
return true;
|
|
||||||
try {
|
|
||||||
function safeGetLink(id: string): HTMLElement {
|
|
||||||
const elem: HTMLElement | null = clearEventListeners(id);
|
|
||||||
if (elem == null) {
|
|
||||||
throw new Error(`clearEventListeners() failed for element with id: ${id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
MainMenuLinks.Terminal = safeGetLink("terminal-menu-link");
|
|
||||||
MainMenuLinks.ScriptEditor = safeGetLink("create-script-menu-link");
|
|
||||||
MainMenuLinks.ActiveScripts = safeGetLink("active-scripts-menu-link");
|
|
||||||
MainMenuLinks.CreateProgram = safeGetLink("create-program-menu-link");
|
|
||||||
MainMenuLinks.Stats = safeGetLink("stats-menu-link");
|
|
||||||
MainMenuLinks.Factions = safeGetLink("factions-menu-link");
|
|
||||||
MainMenuLinks.Augmentations = safeGetLink("augmentations-menu-link");
|
|
||||||
MainMenuLinks.HacknetNodes = safeGetLink("hacknet-nodes-menu-link");
|
|
||||||
MainMenuLinks.Sleeves = safeGetLink("sleeves-menu-link");
|
|
||||||
MainMenuLinks.City = safeGetLink("city-menu-link");
|
|
||||||
MainMenuLinks.Travel = safeGetLink("travel-menu-link");
|
|
||||||
MainMenuLinks.Job = safeGetLink("job-menu-link");
|
|
||||||
MainMenuLinks.StockMarket = safeGetLink("stock-market-menu-link");
|
|
||||||
MainMenuLinks.Bladeburner = safeGetLink("bladeburner-menu-link");
|
|
||||||
MainMenuLinks.Corporation = safeGetLink("corporation-menu-link");
|
|
||||||
MainMenuLinks.Gang = safeGetLink("gang-menu-link");
|
|
||||||
MainMenuLinks.Milestones = safeGetLink("milestones-menu-link");
|
|
||||||
MainMenuLinks.Tutorial = safeGetLink("tutorial-menu-link");
|
|
||||||
// const op: HTMLElement | null = document.getElementById("options-menu-link");
|
|
||||||
// if (op === null) throw new Error(`Could not find element with id: "options-menu-link"`);
|
|
||||||
// MainMenuLinks.Options = op; // This click listener is already set, so don't clear it
|
|
||||||
MainMenuLinks.DevMenu = safeGetLink("dev-menu-link");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to initialize Main Menu Links: ${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -195,7 +195,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const contents = result;
|
const contents = result;
|
||||||
save(contents).then(() => location.reload());
|
save(contents).then(() => setTimeout(() => location.reload(), 1000));
|
||||||
};
|
};
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
}
|
}
|
||||||
@ -628,7 +628,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
setDeleteOpen(false);
|
setDeleteOpen(false);
|
||||||
deleteGame()
|
deleteGame()
|
||||||
.then(() => location.reload())
|
.then(() => setTimeout(() => location.reload(), 1000))
|
||||||
.catch((r) => console.error(`Could not delete game: ${r}`));
|
.catch((r) => console.error(`Could not delete game: ${r}`));
|
||||||
}}
|
}}
|
||||||
open={deleteGameOpen}
|
open={deleteGameOpen}
|
||||||
|
@ -5,17 +5,17 @@ interface IError {
|
|||||||
lineNumber?: number;
|
lineNumber?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function exceptionAlert(e: IError): void {
|
export function exceptionAlert(e: IError | string): void {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"Caught an exception: " +
|
"Caught an exception: " +
|
||||||
e +
|
e +
|
||||||
"<br><br>" +
|
"<br><br>" +
|
||||||
"Filename: " +
|
"Filename: " +
|
||||||
(e.fileName || "UNKNOWN FILE NAME") +
|
((e as any).fileName || "UNKNOWN FILE NAME") +
|
||||||
"<br><br>" +
|
"<br><br>" +
|
||||||
"Line Number: " +
|
"Line Number: " +
|
||||||
(e.lineNumber || "UNKNOWN LINE NUMBER") +
|
((e as any).lineNumber || "UNKNOWN LINE NUMBER") +
|
||||||
"<br><br>" +
|
"<br><br>" +
|
||||||
"This is a bug, please report to game developer with this " +
|
"This is a bug, please report to game developer with this " +
|
||||||
"message as well as details about how to reproduce the bug.<br><br>" +
|
"message as well as details about how to reproduce the bug.<br><br>" +
|
||||||
|
Loading…
Reference in New Issue
Block a user