mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-29 09:27:33 +01:00
commit
28e42b448d
38
dist/vendor.bundle.js
vendored
38
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -53,4 +53,5 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="root"/>
|
<div id="root"/>
|
||||||
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="main.bundle.js"></script></body>
|
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="main.bundle.js"></script></body>
|
||||||
|
<!-- http://plaza.dsolver.ca/m/hydroflame4418 -->
|
||||||
</html>
|
</html>
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
62
package-lock.json
generated
62
package-lock.json
generated
@ -21,6 +21,7 @@
|
|||||||
"@types/numeral": "0.0.25",
|
"@types/numeral": "0.0.25",
|
||||||
"@types/react": "^17.0.21",
|
"@types/react": "^17.0.21",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
|
"@types/react-resizable": "^1.7.3",
|
||||||
"acorn": "^8.4.1",
|
"acorn": "^8.4.1",
|
||||||
"acorn-walk": "^8.1.1",
|
"acorn-walk": "^8.1.1",
|
||||||
"ajv": "^5.1.5",
|
"ajv": "^5.1.5",
|
||||||
@ -53,7 +54,9 @@
|
|||||||
"numeral": "2.0.6",
|
"numeral": "2.0.6",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-draggable": "^4.4.4",
|
||||||
"react-modal": "^3.12.1",
|
"react-modal": "^3.12.1",
|
||||||
|
"react-resizable": "^3.0.4",
|
||||||
"sprintf-js": "^1.1.1",
|
"sprintf-js": "^1.1.1",
|
||||||
"tapable": "^1.0.0",
|
"tapable": "^1.0.0",
|
||||||
"treant-js": "^1.0.1",
|
"treant-js": "^1.0.1",
|
||||||
@ -4673,6 +4676,14 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-resizable": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-DAx+hdnHFMJHgl8geiKo3jLt1GCT838SwQixjCtbRRfqCBawAKriVLCZ1nvp7B/2Pxd94MWod8NyJEnAAmNHNA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-transition-group": {
|
"node_modules/@types/react-transition-group": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||||
@ -22097,6 +22108,19 @@
|
|||||||
"react": "17.0.2"
|
"react": "17.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-draggable": {
|
||||||
|
"version": "4.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.4.tgz",
|
||||||
|
"integrity": "sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==",
|
||||||
|
"dependencies": {
|
||||||
|
"clsx": "^1.1.1",
|
||||||
|
"prop-types": "^15.6.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16.3.0",
|
||||||
|
"react-dom": ">= 16.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "16.8.3",
|
"version": "16.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
|
||||||
@ -22130,6 +22154,18 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-resizable": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==",
|
||||||
|
"dependencies": {
|
||||||
|
"prop-types": "15.x",
|
||||||
|
"react-draggable": "^4.0.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-transition-group": {
|
"node_modules/react-transition-group": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||||
@ -31573,6 +31609,14 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-resizable": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-DAx+hdnHFMJHgl8geiKo3jLt1GCT838SwQixjCtbRRfqCBawAKriVLCZ1nvp7B/2Pxd94MWod8NyJEnAAmNHNA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/react-transition-group": {
|
"@types/react-transition-group": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||||
@ -45494,6 +45538,15 @@
|
|||||||
"scheduler": "^0.20.2"
|
"scheduler": "^0.20.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-draggable": {
|
||||||
|
"version": "4.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.4.tgz",
|
||||||
|
"integrity": "sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==",
|
||||||
|
"requires": {
|
||||||
|
"clsx": "^1.1.1",
|
||||||
|
"prop-types": "^15.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.8.3",
|
"version": "16.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
|
||||||
@ -45521,6 +45574,15 @@
|
|||||||
"integrity": "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==",
|
"integrity": "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"react-resizable": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==",
|
||||||
|
"requires": {
|
||||||
|
"prop-types": "15.x",
|
||||||
|
"react-draggable": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-transition-group": {
|
"react-transition-group": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
"@types/numeral": "0.0.25",
|
"@types/numeral": "0.0.25",
|
||||||
"@types/react": "^17.0.21",
|
"@types/react": "^17.0.21",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
|
"@types/react-resizable": "^1.7.3",
|
||||||
"acorn": "^8.4.1",
|
"acorn": "^8.4.1",
|
||||||
"acorn-walk": "^8.1.1",
|
"acorn-walk": "^8.1.1",
|
||||||
"ajv": "^5.1.5",
|
"ajv": "^5.1.5",
|
||||||
@ -54,7 +55,9 @@
|
|||||||
"numeral": "2.0.6",
|
"numeral": "2.0.6",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-draggable": "^4.4.4",
|
||||||
"react-modal": "^3.12.1",
|
"react-modal": "^3.12.1",
|
||||||
|
"react-resizable": "^3.0.4",
|
||||||
"sprintf-js": "^1.1.1",
|
"sprintf-js": "^1.1.1",
|
||||||
"tapable": "^1.0.0",
|
"tapable": "^1.0.0",
|
||||||
"treant-js": "^1.0.1",
|
"treant-js": "^1.0.1",
|
||||||
|
@ -57,7 +57,6 @@ import { calculateServerGrowth } from "./Server/formulas/grow";
|
|||||||
import { AllGangs } from "./Gang/AllGangs";
|
import { AllGangs } from "./Gang/AllGangs";
|
||||||
import { Factions, factionExists } from "./Faction/Factions";
|
import { Factions, factionExists } from "./Faction/Factions";
|
||||||
import { joinFaction, purchaseAugmentation } from "./Faction/FactionHelpers";
|
import { joinFaction, purchaseAugmentation } from "./Faction/FactionHelpers";
|
||||||
import { FactionWorkType } from "./Faction/FactionWorkTypeEnum";
|
|
||||||
import { netscriptCanGrow, netscriptCanHack, netscriptCanWeaken } from "./Hacking/netscriptCanHack";
|
import { netscriptCanGrow, netscriptCanHack, netscriptCanWeaken } from "./Hacking/netscriptCanHack";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -133,9 +132,6 @@ import { workerScripts } from "./Netscript/WorkerScripts";
|
|||||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||||
import { makeRuntimeRejectMsg, netscriptDelay, resolveNetscriptRequestedThreads } from "./NetscriptEvaluator";
|
import { makeRuntimeRejectMsg, netscriptDelay, resolveNetscriptRequestedThreads } from "./NetscriptEvaluator";
|
||||||
import { Interpreter } from "./ThirdParty/JSInterpreter";
|
import { Interpreter } from "./ThirdParty/JSInterpreter";
|
||||||
import { SleeveTaskType } from "./PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
|
||||||
import { findSleevePurchasableAugs } from "./PersonObjects/Sleeve/SleeveHelpers";
|
|
||||||
import { Exploit } from "./Exploits/Exploit";
|
|
||||||
import { Router } from "./ui/GameRoot";
|
import { Router } from "./ui/GameRoot";
|
||||||
|
|
||||||
import { numeralWrapper } from "./ui/numeralFormat";
|
import { numeralWrapper } from "./ui/numeralFormat";
|
||||||
@ -161,6 +157,9 @@ import { CodingContract } from "./CodingContracts";
|
|||||||
import { Stock } from "./StockMarket/Stock";
|
import { Stock } from "./StockMarket/Stock";
|
||||||
import { BaseServer } from "./Server/BaseServer";
|
import { BaseServer } from "./Server/BaseServer";
|
||||||
import { INetscriptGang, NetscriptGang } from "./NetscriptFunctions/Gang";
|
import { INetscriptGang, NetscriptGang } from "./NetscriptFunctions/Gang";
|
||||||
|
import { INetscriptSleeve, NetscriptSleeve } from "./NetscriptFunctions/Sleeve";
|
||||||
|
import { INetscriptExtra, NetscriptExtra } from "./NetscriptFunctions/Extra";
|
||||||
|
import { INetscriptHacknet, NetscriptHacknet } from "./NetscriptFunctions/Hacknet";
|
||||||
|
|
||||||
const defaultInterpreter = new Interpreter("", () => undefined);
|
const defaultInterpreter = new Interpreter("", () => undefined);
|
||||||
|
|
||||||
@ -197,9 +196,11 @@ function toNative(pseudoObj: any): any {
|
|||||||
return nativeObj;
|
return nativeObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NS {
|
interface NS extends INetscriptExtra {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
hacknet: INetscriptHacknet;
|
||||||
gang: INetscriptGang;
|
gang: INetscriptGang;
|
||||||
|
sleeve: INetscriptSleeve;
|
||||||
}
|
}
|
||||||
|
|
||||||
function NetscriptFunctions(workerScript: WorkerScript): NS {
|
function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||||
@ -366,35 +367,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utility function to get Hacknet Node object
|
|
||||||
const getHacknetNode = function (i: any, callingFn = ""): HacknetNode | HacknetServer {
|
|
||||||
if (isNaN(i)) {
|
|
||||||
throw makeRuntimeErrorMsg(callingFn, "Invalid index specified for Hacknet Node: " + i);
|
|
||||||
}
|
|
||||||
if (i < 0 || i >= Player.hacknetNodes.length) {
|
|
||||||
throw makeRuntimeErrorMsg(callingFn, "Index specified for Hacknet Node is out-of-bounds: " + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasHacknetServers(Player)) {
|
|
||||||
const hi = Player.hacknetNodes[i];
|
|
||||||
if (typeof hi !== "string") throw new Error("hacknet node was not a string");
|
|
||||||
const hserver = AllServers[hi];
|
|
||||||
if (!(hserver instanceof HacknetServer)) throw new Error("hacknet server was not actually hacknet server");
|
|
||||||
if (hserver == null) {
|
|
||||||
throw makeRuntimeErrorMsg(
|
|
||||||
callingFn,
|
|
||||||
`Could not get Hacknet Server for index ${i}. This is probably a bug, please report to game dev`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hserver;
|
|
||||||
} else {
|
|
||||||
const node = Player.hacknetNodes[i];
|
|
||||||
if (!(node instanceof HacknetNode)) throw new Error("hacknet node was not node.");
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeRuntimeErrorMsg = function (caller: string, msg: string): string {
|
const makeRuntimeErrorMsg = function (caller: string, msg: string): string {
|
||||||
const errstack = new Error().stack;
|
const errstack = new Error().stack;
|
||||||
if (errstack === undefined) throw new Error("how did we not throw an error?");
|
if (errstack === undefined) throw new Error("how did we not throw an error?");
|
||||||
@ -510,23 +482,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkSleeveAPIAccess = function (func: any): void {
|
|
||||||
if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) {
|
|
||||||
throw makeRuntimeErrorMsg(
|
|
||||||
`sleeve.${func}`,
|
|
||||||
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkSleeveNumber = function (func: any, sleeveNumber: any): void {
|
|
||||||
if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) {
|
|
||||||
const msg = `Invalid sleeve number: ${sleeveNumber}`;
|
|
||||||
workerScript.log(func, msg);
|
|
||||||
throw makeRuntimeErrorMsg(`sleeve.${func}`, msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getCodingContract = function (func: any, ip: any, fn: any): CodingContract {
|
const getCodingContract = function (func: any, ip: any, fn: any): CodingContract {
|
||||||
const server = safeGetServer(ip, func);
|
const server = safeGetServer(ip, func);
|
||||||
const contract = server.getContract(fn);
|
const contract = server.getContract(fn);
|
||||||
@ -758,146 +713,28 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
const helper = {
|
const helper = {
|
||||||
updateDynamicRam: updateDynamicRam,
|
updateDynamicRam: updateDynamicRam,
|
||||||
makeRuntimeErrorMsg: makeRuntimeErrorMsg,
|
makeRuntimeErrorMsg: makeRuntimeErrorMsg,
|
||||||
|
string: (funcName: string, argName: string, v: any): string => {
|
||||||
|
if (typeof v === "string") return v;
|
||||||
|
if (typeof v === "number") return v + ""; // cast to string;
|
||||||
|
throw makeRuntimeErrorMsg(funcName, `${argName} should be a string`);
|
||||||
|
},
|
||||||
|
number: (funcName: string, argName: string, v: any): number => {
|
||||||
|
if (typeof v === "number") return v;
|
||||||
|
if (!isNaN(v) && !isNaN(parseFloat(v))) return parseFloat(v);
|
||||||
|
throw makeRuntimeErrorMsg(funcName, `${argName} should be a number`);
|
||||||
|
},
|
||||||
|
boolean: (v: any): boolean => {
|
||||||
|
return !!v; // Just convert it to boolean.
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const gang = NetscriptGang(Player, workerScript, helper);
|
const gang = NetscriptGang(Player, workerScript, helper);
|
||||||
|
const sleeve = NetscriptSleeve(Player, workerScript, helper);
|
||||||
|
const extra = NetscriptExtra(Player, workerScript, helper);
|
||||||
|
const hacknet = NetscriptHacknet(Player, workerScript, helper);
|
||||||
|
|
||||||
const functions = {
|
const functions = {
|
||||||
hacknet: {
|
hacknet: hacknet,
|
||||||
numNodes: function (): any {
|
|
||||||
return Player.hacknetNodes.length;
|
|
||||||
},
|
|
||||||
maxNumNodes: function (): any {
|
|
||||||
if (hasHacknetServers(Player)) {
|
|
||||||
return HacknetServerConstants.MaxServers;
|
|
||||||
}
|
|
||||||
return Infinity;
|
|
||||||
},
|
|
||||||
purchaseNode: function (): any {
|
|
||||||
return purchaseHacknet(Player);
|
|
||||||
},
|
|
||||||
getPurchaseNodeCost: function (): any {
|
|
||||||
if (hasHacknetServers(Player)) {
|
|
||||||
return getCostOfNextHacknetServer(Player);
|
|
||||||
} else {
|
|
||||||
return getCostOfNextHacknetNode(Player);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getNodeStats: function (i: any): any {
|
|
||||||
const node = getHacknetNode(i, "getNodeStats");
|
|
||||||
const hasUpgraded = hasHacknetServers(Player);
|
|
||||||
const res: any = {
|
|
||||||
name: node instanceof HacknetServer ? node.hostname : node.name,
|
|
||||||
level: node.level,
|
|
||||||
ram: node instanceof HacknetServer ? node.maxRam : node.ram,
|
|
||||||
cores: node.cores,
|
|
||||||
production: node instanceof HacknetServer ? node.hashRate : node.moneyGainRatePerSecond,
|
|
||||||
timeOnline: node.onlineTimeSeconds,
|
|
||||||
totalProduction: node instanceof HacknetServer ? node.totalHashesGenerated : node.totalMoneyGenerated,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (hasUpgraded && node instanceof HacknetServer) {
|
|
||||||
res.cache = node.cache;
|
|
||||||
res.hashCapacity = node.hashCapacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
upgradeLevel: function (i: any, n: any): any {
|
|
||||||
const node = getHacknetNode(i, "upgradeLevel");
|
|
||||||
return purchaseLevelUpgrade(Player, node, n);
|
|
||||||
},
|
|
||||||
upgradeRam: function (i: any, n: any): any {
|
|
||||||
const node = getHacknetNode(i, "upgradeRam");
|
|
||||||
return purchaseRamUpgrade(Player, node, n);
|
|
||||||
},
|
|
||||||
upgradeCore: function (i: any, n: any): any {
|
|
||||||
const node = getHacknetNode(i, "upgradeCore");
|
|
||||||
return purchaseCoreUpgrade(Player, node, n);
|
|
||||||
},
|
|
||||||
upgradeCache: function (i: any, n: any): any {
|
|
||||||
if (!hasHacknetServers(Player)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const node = getHacknetNode(i, "upgradeCache");
|
|
||||||
if (!(node instanceof HacknetServer)) {
|
|
||||||
workerScript.log("upgradeCache", "Can only be called on hacknet servers");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const res = purchaseCacheUpgrade(Player, node, n);
|
|
||||||
if (res) {
|
|
||||||
updateHashManagerCapacity(Player);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
getLevelUpgradeCost: function (i: any, n: any): any {
|
|
||||||
const node = getHacknetNode(i, "upgradeLevel");
|
|
||||||
return node.calculateLevelUpgradeCost(n, Player.hacknet_node_level_cost_mult);
|
|
||||||
},
|
|
||||||
getRamUpgradeCost: function (i: any, n: any): any {
|
|
||||||
const node = getHacknetNode(i, "upgradeRam");
|
|
||||||
return node.calculateRamUpgradeCost(n, Player.hacknet_node_ram_cost_mult);
|
|
||||||
},
|
|
||||||
getCoreUpgradeCost: function (i: any, n: any): any {
|
|
||||||
const node = getHacknetNode(i, "upgradeCore");
|
|
||||||
return node.calculateCoreUpgradeCost(n, Player.hacknet_node_core_cost_mult);
|
|
||||||
},
|
|
||||||
getCacheUpgradeCost: function (i: any, n: any): any {
|
|
||||||
if (!hasHacknetServers(Player)) {
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
const node = getHacknetNode(i, "upgradeCache");
|
|
||||||
if (!(node instanceof HacknetServer)) {
|
|
||||||
workerScript.log("getCacheUpgradeCost", "Can only be called on hacknet servers");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return node.calculateCacheUpgradeCost(n);
|
|
||||||
},
|
|
||||||
numHashes: function (): any {
|
|
||||||
if (!hasHacknetServers(Player)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return Player.hashManager.hashes;
|
|
||||||
},
|
|
||||||
hashCapacity: function (): any {
|
|
||||||
if (!hasHacknetServers(Player)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return Player.hashManager.capacity;
|
|
||||||
},
|
|
||||||
hashCost: function (upgName: any): any {
|
|
||||||
if (!hasHacknetServers(Player)) {
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Player.hashManager.getUpgradeCost(upgName);
|
|
||||||
},
|
|
||||||
spendHashes: function (upgName: any, upgTarget: any): any {
|
|
||||||
if (!hasHacknetServers(Player)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return purchaseHashUpgrade(Player, upgName, upgTarget);
|
|
||||||
},
|
|
||||||
getHashUpgradeLevel: function (upgName: any): any {
|
|
||||||
const level = Player.hashManager.upgrades[upgName];
|
|
||||||
if (level === undefined) {
|
|
||||||
throw makeRuntimeErrorMsg("hacknet.hashUpgradeLevel", `Invalid Hash Upgrade: ${upgName}`);
|
|
||||||
}
|
|
||||||
return level;
|
|
||||||
},
|
|
||||||
getStudyMult: function (): any {
|
|
||||||
if (!hasHacknetServers(Player)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Player.hashManager.getStudyMult();
|
|
||||||
},
|
|
||||||
getTrainingMult: function (): any {
|
|
||||||
if (!hasHacknetServers(Player)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Player.hashManager.getTrainingMult();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sprintf: sprintf,
|
sprintf: sprintf,
|
||||||
vsprintf: vsprintf,
|
vsprintf: vsprintf,
|
||||||
scan: function (ip: any = workerScript.serverIp, hostnames: any = true): any {
|
scan: function (ip: any = workerScript.serverIp, hostnames: any = true): any {
|
||||||
@ -4653,227 +4490,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
},
|
},
|
||||||
}, // End coding contracts
|
}, // End coding contracts
|
||||||
|
|
||||||
// Duplicate Sleeve API
|
sleeve: sleeve,
|
||||||
sleeve: {
|
|
||||||
getNumSleeves: function (): any {
|
|
||||||
updateDynamicRam("getNumSleeves", getRamCost("sleeve", "getNumSleeves"));
|
|
||||||
checkSleeveAPIAccess("getNumSleeves");
|
|
||||||
return Player.sleeves.length;
|
|
||||||
},
|
|
||||||
setToShockRecovery: function (sleeveNumber: any = 0): any {
|
|
||||||
updateDynamicRam("setToShockRecovery", getRamCost("sleeve", "setToShockRecovery"));
|
|
||||||
checkSleeveAPIAccess("setToShockRecovery");
|
|
||||||
checkSleeveNumber("setToShockRecovery", sleeveNumber);
|
|
||||||
return Player.sleeves[sleeveNumber].shockRecovery(Player);
|
|
||||||
},
|
|
||||||
setToSynchronize: function (sleeveNumber: any = 0): any {
|
|
||||||
updateDynamicRam("setToSynchronize", getRamCost("sleeve", "setToSynchronize"));
|
|
||||||
checkSleeveAPIAccess("setToSynchronize");
|
|
||||||
checkSleeveNumber("setToSynchronize", sleeveNumber);
|
|
||||||
return Player.sleeves[sleeveNumber].synchronize(Player);
|
|
||||||
},
|
|
||||||
setToCommitCrime: function (sleeveNumber: any = 0, crimeName: any = ""): any {
|
|
||||||
updateDynamicRam("setToCommitCrime", getRamCost("sleeve", "setToCommitCrime"));
|
|
||||||
checkSleeveAPIAccess("setToCommitCrime");
|
|
||||||
checkSleeveNumber("setToCommitCrime", sleeveNumber);
|
|
||||||
return Player.sleeves[sleeveNumber].commitCrime(Player, crimeName);
|
|
||||||
},
|
|
||||||
setToUniversityCourse: function (sleeveNumber: any = 0, universityName: any = "", className: any = ""): any {
|
|
||||||
updateDynamicRam("setToUniversityCourse", getRamCost("sleeve", "setToUniversityCourse"));
|
|
||||||
checkSleeveAPIAccess("setToUniversityCourse");
|
|
||||||
checkSleeveNumber("setToUniversityCourse", sleeveNumber);
|
|
||||||
return Player.sleeves[sleeveNumber].takeUniversityCourse(Player, universityName, className);
|
|
||||||
},
|
|
||||||
travel: function (sleeveNumber: any = 0, cityName: any = ""): any {
|
|
||||||
updateDynamicRam("travel", getRamCost("sleeve", "travel"));
|
|
||||||
checkSleeveAPIAccess("travel");
|
|
||||||
checkSleeveNumber("travel", sleeveNumber);
|
|
||||||
return Player.sleeves[sleeveNumber].travel(Player, cityName);
|
|
||||||
},
|
|
||||||
setToCompanyWork: function (sleeveNumber: any = 0, companyName: any = ""): any {
|
|
||||||
updateDynamicRam("setToCompanyWork", getRamCost("sleeve", "setToCompanyWork"));
|
|
||||||
checkSleeveAPIAccess("setToCompanyWork");
|
|
||||||
checkSleeveNumber("setToCompanyWork", sleeveNumber);
|
|
||||||
|
|
||||||
// Cannot work at the same company that another sleeve is working at
|
|
||||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
|
||||||
if (i === sleeveNumber) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const other = Player.sleeves[i];
|
|
||||||
if (other.currentTask === SleeveTaskType.Company && other.currentTaskLocation === companyName) {
|
|
||||||
throw makeRuntimeErrorMsg(
|
|
||||||
"sleeve.setToFactionWork",
|
|
||||||
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Player.sleeves[sleeveNumber].workForCompany(Player, companyName);
|
|
||||||
},
|
|
||||||
setToFactionWork: function (sleeveNumber: any = 0, factionName: any = "", workType: any = ""): any {
|
|
||||||
updateDynamicRam("setToFactionWork", getRamCost("sleeve", "setToFactionWork"));
|
|
||||||
checkSleeveAPIAccess("setToFactionWork");
|
|
||||||
checkSleeveNumber("setToFactionWork", sleeveNumber);
|
|
||||||
|
|
||||||
// Cannot work at the same faction that another sleeve is working at
|
|
||||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
|
||||||
if (i === sleeveNumber) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const other = Player.sleeves[i];
|
|
||||||
if (other.currentTask === SleeveTaskType.Faction && other.currentTaskLocation === factionName) {
|
|
||||||
throw makeRuntimeErrorMsg(
|
|
||||||
"sleeve.setToFactionWork",
|
|
||||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Player.sleeves[sleeveNumber].workForFaction(Player, factionName, workType);
|
|
||||||
},
|
|
||||||
setToGymWorkout: function (sleeveNumber: any = 0, gymName: any = "", stat: any = ""): any {
|
|
||||||
updateDynamicRam("setToGymWorkout", getRamCost("sleeve", "setToGymWorkout"));
|
|
||||||
checkSleeveAPIAccess("setToGymWorkout");
|
|
||||||
checkSleeveNumber("setToGymWorkout", sleeveNumber);
|
|
||||||
|
|
||||||
return Player.sleeves[sleeveNumber].workoutAtGym(Player, gymName, stat);
|
|
||||||
},
|
|
||||||
getSleeveStats: function (sleeveNumber: any = 0): any {
|
|
||||||
updateDynamicRam("getSleeveStats", getRamCost("sleeve", "getSleeveStats"));
|
|
||||||
checkSleeveAPIAccess("getSleeveStats");
|
|
||||||
checkSleeveNumber("getSleeveStats", sleeveNumber);
|
|
||||||
|
|
||||||
const sl = Player.sleeves[sleeveNumber];
|
|
||||||
return {
|
|
||||||
shock: 100 - sl.shock,
|
|
||||||
sync: sl.sync,
|
|
||||||
hacking_skill: sl.hacking_skill,
|
|
||||||
strength: sl.strength,
|
|
||||||
defense: sl.defense,
|
|
||||||
dexterity: sl.dexterity,
|
|
||||||
agility: sl.agility,
|
|
||||||
charisma: sl.charisma,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getTask: function (sleeveNumber: any = 0): any {
|
|
||||||
updateDynamicRam("getTask", getRamCost("sleeve", "getTask"));
|
|
||||||
checkSleeveAPIAccess("getTask");
|
|
||||||
checkSleeveNumber("getTask", sleeveNumber);
|
|
||||||
|
|
||||||
const sl = Player.sleeves[sleeveNumber];
|
|
||||||
return {
|
|
||||||
task: SleeveTaskType[sl.currentTask],
|
|
||||||
crime: sl.crimeType,
|
|
||||||
location: sl.currentTaskLocation,
|
|
||||||
gymStatType: sl.gymStatType,
|
|
||||||
factionWorkType: FactionWorkType[sl.factionWorkType],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getInformation: function (sleeveNumber: any = 0): any {
|
|
||||||
updateDynamicRam("getInformation", getRamCost("sleeve", "getInformation"));
|
|
||||||
checkSleeveAPIAccess("getInformation");
|
|
||||||
checkSleeveNumber("getInformation", sleeveNumber);
|
|
||||||
|
|
||||||
const sl = Player.sleeves[sleeveNumber];
|
|
||||||
return {
|
|
||||||
city: sl.city,
|
|
||||||
hp: sl.hp,
|
|
||||||
jobs: Object.keys(Player.jobs), // technically sleeves have the same jobs as the player.
|
|
||||||
jobTitle: Object.values(Player.jobs),
|
|
||||||
maxHp: sl.max_hp,
|
|
||||||
tor: SpecialServerIps.hasOwnProperty("Darkweb Server"), // There's no reason not to give that infomation here as well. Worst case scenario it isn't used.
|
|
||||||
|
|
||||||
mult: {
|
|
||||||
agility: sl.agility_mult,
|
|
||||||
agilityExp: sl.agility_exp_mult,
|
|
||||||
companyRep: sl.company_rep_mult,
|
|
||||||
crimeMoney: sl.crime_money_mult,
|
|
||||||
crimeSuccess: sl.crime_success_mult,
|
|
||||||
defense: sl.defense_mult,
|
|
||||||
defenseExp: sl.defense_exp_mult,
|
|
||||||
dexterity: sl.dexterity_mult,
|
|
||||||
dexterityExp: sl.dexterity_exp_mult,
|
|
||||||
factionRep: sl.faction_rep_mult,
|
|
||||||
hacking: sl.hacking_mult,
|
|
||||||
hackingExp: sl.hacking_exp_mult,
|
|
||||||
strength: sl.strength_mult,
|
|
||||||
strengthExp: sl.strength_exp_mult,
|
|
||||||
workMoney: sl.work_money_mult,
|
|
||||||
},
|
|
||||||
|
|
||||||
timeWorked: sl.currentTaskTime,
|
|
||||||
earningsForSleeves: {
|
|
||||||
workHackExpGain: sl.earningsForSleeves.hack,
|
|
||||||
workStrExpGain: sl.earningsForSleeves.str,
|
|
||||||
workDefExpGain: sl.earningsForSleeves.def,
|
|
||||||
workDexExpGain: sl.earningsForSleeves.dex,
|
|
||||||
workAgiExpGain: sl.earningsForSleeves.agi,
|
|
||||||
workChaExpGain: sl.earningsForSleeves.cha,
|
|
||||||
workMoneyGain: sl.earningsForSleeves.money,
|
|
||||||
},
|
|
||||||
earningsForPlayer: {
|
|
||||||
workHackExpGain: sl.earningsForPlayer.hack,
|
|
||||||
workStrExpGain: sl.earningsForPlayer.str,
|
|
||||||
workDefExpGain: sl.earningsForPlayer.def,
|
|
||||||
workDexExpGain: sl.earningsForPlayer.dex,
|
|
||||||
workAgiExpGain: sl.earningsForPlayer.agi,
|
|
||||||
workChaExpGain: sl.earningsForPlayer.cha,
|
|
||||||
workMoneyGain: sl.earningsForPlayer.money,
|
|
||||||
},
|
|
||||||
earningsForTask: {
|
|
||||||
workHackExpGain: sl.earningsForTask.hack,
|
|
||||||
workStrExpGain: sl.earningsForTask.str,
|
|
||||||
workDefExpGain: sl.earningsForTask.def,
|
|
||||||
workDexExpGain: sl.earningsForTask.dex,
|
|
||||||
workAgiExpGain: sl.earningsForTask.agi,
|
|
||||||
workChaExpGain: sl.earningsForTask.cha,
|
|
||||||
workMoneyGain: sl.earningsForTask.money,
|
|
||||||
},
|
|
||||||
workRepGain: sl.getRepGain(Player),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getSleeveAugmentations: function (sleeveNumber: any = 0): any {
|
|
||||||
updateDynamicRam("getSleeveAugmentations", getRamCost("sleeve", "getSleeveAugmentations"));
|
|
||||||
checkSleeveAPIAccess("getSleeveAugmentations");
|
|
||||||
checkSleeveNumber("getSleeveAugmentations", sleeveNumber);
|
|
||||||
|
|
||||||
const augs = [];
|
|
||||||
for (let i = 0; i < Player.sleeves[sleeveNumber].augmentations.length; i++) {
|
|
||||||
augs.push(Player.sleeves[sleeveNumber].augmentations[i].name);
|
|
||||||
}
|
|
||||||
return augs;
|
|
||||||
},
|
|
||||||
getSleevePurchasableAugs: function (sleeveNumber: any = 0): any {
|
|
||||||
updateDynamicRam("getSleevePurchasableAugs", getRamCost("sleeve", "getSleevePurchasableAugs"));
|
|
||||||
checkSleeveAPIAccess("getSleevePurchasableAugs");
|
|
||||||
checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber);
|
|
||||||
|
|
||||||
const purchasableAugs = findSleevePurchasableAugs(Player.sleeves[sleeveNumber], Player);
|
|
||||||
const augs = [];
|
|
||||||
for (let i = 0; i < purchasableAugs.length; i++) {
|
|
||||||
const aug = purchasableAugs[i];
|
|
||||||
augs.push({
|
|
||||||
name: aug.name,
|
|
||||||
cost: aug.startingCost,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return augs;
|
|
||||||
},
|
|
||||||
purchaseSleeveAug: function (sleeveNumber: any = 0, augName: any = ""): any {
|
|
||||||
updateDynamicRam("purchaseSleeveAug", getRamCost("sleeve", "purchaseSleeveAug"));
|
|
||||||
checkSleeveAPIAccess("purchaseSleeveAug");
|
|
||||||
checkSleeveNumber("purchaseSleeveAug", sleeveNumber);
|
|
||||||
|
|
||||||
const aug = Augmentations[augName];
|
|
||||||
if (!aug) {
|
|
||||||
throw makeRuntimeErrorMsg("sleeve.purchaseSleeveAug", `Invalid aug: ${augName}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Player.sleeves[sleeveNumber].tryBuyAugmentation(Player, aug);
|
|
||||||
},
|
|
||||||
}, // End sleeve
|
|
||||||
formulas: {
|
formulas: {
|
||||||
basic: {
|
basic: {
|
||||||
calculateSkill: function (exp: any, mult: any = 1): any {
|
calculateSkill: function (exp: any, mult: any = 1): any {
|
||||||
@ -4981,28 +4598,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, // end formulas
|
}, // end formulas
|
||||||
heart: {
|
|
||||||
// Easter egg function
|
|
||||||
break: function (): number {
|
|
||||||
return Player.karma;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
exploit: function (): any {
|
|
||||||
Player.giveExploit(Exploit.UndocumentedFunctionCall);
|
|
||||||
},
|
|
||||||
bypass: function (doc: any): any {
|
|
||||||
// reset both fields first
|
|
||||||
doc.completely_unused_field = undefined;
|
|
||||||
const real_document: any = document;
|
|
||||||
real_document.completely_unused_field = undefined;
|
|
||||||
// set one to true and check that it affected the other.
|
|
||||||
real_document.completely_unused_field = true;
|
|
||||||
if (doc.completely_unused_field && workerScript.ramUsage === 1.6) {
|
|
||||||
Player.giveExploit(Exploit.Bypass);
|
|
||||||
}
|
|
||||||
doc.completely_unused_field = undefined;
|
|
||||||
real_document.completely_unused_field = undefined;
|
|
||||||
},
|
|
||||||
flags: function (data: any): any {
|
flags: function (data: any): any {
|
||||||
data = toNative(data);
|
data = toNative(data);
|
||||||
// We always want the help flag.
|
// We always want the help flag.
|
||||||
@ -5035,6 +4630,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
...extra,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getFunctionNames(obj: NS): string[] {
|
function getFunctionNames(obj: NS): string[] {
|
||||||
|
39
src/NetscriptFunctions/Extra.ts
Normal file
39
src/NetscriptFunctions/Extra.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { INetscriptHelper } from "./INetscriptHelper";
|
||||||
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { Exploit } from "../Exploits/Exploit";
|
||||||
|
|
||||||
|
export interface INetscriptExtra {
|
||||||
|
heart: {
|
||||||
|
break(): number;
|
||||||
|
};
|
||||||
|
exploit(): void;
|
||||||
|
bypass(doc: Document): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NetscriptExtra(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): INetscriptExtra {
|
||||||
|
return {
|
||||||
|
heart: {
|
||||||
|
// Easter egg function
|
||||||
|
break: function (): number {
|
||||||
|
return player.karma;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
exploit: function (): void {
|
||||||
|
player.giveExploit(Exploit.UndocumentedFunctionCall);
|
||||||
|
},
|
||||||
|
bypass: function (doc: any): void {
|
||||||
|
// reset both fields first
|
||||||
|
doc.completely_unused_field = undefined;
|
||||||
|
const real_document: any = document;
|
||||||
|
real_document.completely_unused_field = undefined;
|
||||||
|
// set one to true and check that it affected the other.
|
||||||
|
real_document.completely_unused_field = true;
|
||||||
|
if (doc.completely_unused_field && workerScript.ramUsage === 1.6) {
|
||||||
|
player.giveExploit(Exploit.Bypass);
|
||||||
|
}
|
||||||
|
doc.completely_unused_field = undefined;
|
||||||
|
real_document.completely_unused_field = undefined;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
@ -10,7 +10,7 @@ import { GangMember } from "../Gang/GangMember";
|
|||||||
import { GangMemberTask } from "../Gang/GangMemberTask";
|
import { GangMemberTask } from "../Gang/GangMemberTask";
|
||||||
|
|
||||||
export interface INetscriptGang {
|
export interface INetscriptGang {
|
||||||
createGang(faction: any): boolean;
|
createGang(faction: string): boolean;
|
||||||
inGang(): boolean;
|
inGang(): boolean;
|
||||||
getMemberNames(): string[];
|
getMemberNames(): string[];
|
||||||
getGangInformation(): any;
|
getGangInformation(): any;
|
||||||
@ -59,7 +59,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createGang: function (faction: string): any {
|
createGang: function (faction: string): boolean {
|
||||||
helper.updateDynamicRam("createGang", getRamCost("gang", "createGang"));
|
helper.updateDynamicRam("createGang", getRamCost("gang", "createGang"));
|
||||||
// this list is copied from Faction/ui/Root.tsx
|
// this list is copied from Faction/ui/Root.tsx
|
||||||
const GangNames = [
|
const GangNames = [
|
||||||
|
213
src/NetscriptFunctions/Hacknet.ts
Normal file
213
src/NetscriptFunctions/Hacknet.ts
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
import { INetscriptHelper } from "./INetscriptHelper";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
||||||
|
import {
|
||||||
|
getCostOfNextHacknetNode,
|
||||||
|
getCostOfNextHacknetServer,
|
||||||
|
hasHacknetServers,
|
||||||
|
purchaseHacknet,
|
||||||
|
purchaseLevelUpgrade,
|
||||||
|
purchaseRamUpgrade,
|
||||||
|
purchaseCoreUpgrade,
|
||||||
|
purchaseCacheUpgrade,
|
||||||
|
purchaseHashUpgrade,
|
||||||
|
updateHashManagerCapacity,
|
||||||
|
} from "../Hacknet/HacknetHelpers";
|
||||||
|
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||||
|
import { HacknetNode } from "../Hacknet/HacknetNode";
|
||||||
|
import { AllServers } from "../Server/AllServers";
|
||||||
|
|
||||||
|
export interface INetscriptHacknet {
|
||||||
|
numNodes(): number;
|
||||||
|
maxNumNodes(): number;
|
||||||
|
purchaseNode(): any;
|
||||||
|
getPurchaseNodeCost(): number;
|
||||||
|
getNodeStats(i: number): any;
|
||||||
|
upgradeLevel(i: number, n: number): boolean;
|
||||||
|
upgradeRam(i: number, n: number): boolean;
|
||||||
|
upgradeCore(i: number, n: number): boolean;
|
||||||
|
upgradeCache(i: number, n: number): boolean;
|
||||||
|
getLevelUpgradeCost(i: number, n: number): number;
|
||||||
|
getRamUpgradeCost(i: number, n: number): number;
|
||||||
|
getCoreUpgradeCost(i: number, n: number): number;
|
||||||
|
getCacheUpgradeCost(i: number, n: number): number;
|
||||||
|
numHashes(): number;
|
||||||
|
hashCapacity(): number;
|
||||||
|
hashCost(upgName: string): number;
|
||||||
|
spendHashes(upgName: string, upgTarget: string): any;
|
||||||
|
getHashUpgradeLevel(upgName: string): number;
|
||||||
|
getStudyMult(): number;
|
||||||
|
getTrainingMult(): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NetscriptHacknet(
|
||||||
|
player: IPlayer,
|
||||||
|
workerScript: WorkerScript,
|
||||||
|
helper: INetscriptHelper,
|
||||||
|
): INetscriptHacknet {
|
||||||
|
// Utility function to get Hacknet Node object
|
||||||
|
const getHacknetNode = function (i: any, callingFn = ""): HacknetNode | HacknetServer {
|
||||||
|
if (isNaN(i)) {
|
||||||
|
throw helper.makeRuntimeErrorMsg(callingFn, "Invalid index specified for Hacknet Node: " + i);
|
||||||
|
}
|
||||||
|
if (i < 0 || i >= player.hacknetNodes.length) {
|
||||||
|
throw helper.makeRuntimeErrorMsg(callingFn, "Index specified for Hacknet Node is out-of-bounds: " + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasHacknetServers(player)) {
|
||||||
|
const hi = player.hacknetNodes[i];
|
||||||
|
if (typeof hi !== "string") throw new Error("hacknet node was not a string");
|
||||||
|
const hserver = AllServers[hi];
|
||||||
|
if (!(hserver instanceof HacknetServer)) throw new Error("hacknet server was not actually hacknet server");
|
||||||
|
if (hserver == null) {
|
||||||
|
throw helper.makeRuntimeErrorMsg(
|
||||||
|
callingFn,
|
||||||
|
`Could not get Hacknet Server for index ${i}. This is probably a bug, please report to game dev`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hserver;
|
||||||
|
} else {
|
||||||
|
const node = player.hacknetNodes[i];
|
||||||
|
if (!(node instanceof HacknetNode)) throw new Error("hacknet node was not node.");
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
numNodes: function (): any {
|
||||||
|
return player.hacknetNodes.length;
|
||||||
|
},
|
||||||
|
maxNumNodes: function (): any {
|
||||||
|
if (hasHacknetServers(player)) {
|
||||||
|
return HacknetServerConstants.MaxServers;
|
||||||
|
}
|
||||||
|
return Infinity;
|
||||||
|
},
|
||||||
|
purchaseNode: function (): any {
|
||||||
|
return purchaseHacknet(player);
|
||||||
|
},
|
||||||
|
getPurchaseNodeCost: function (): any {
|
||||||
|
if (hasHacknetServers(player)) {
|
||||||
|
return getCostOfNextHacknetServer(player);
|
||||||
|
} else {
|
||||||
|
return getCostOfNextHacknetNode(player);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getNodeStats: function (i: any): any {
|
||||||
|
const node = getHacknetNode(i, "getNodeStats");
|
||||||
|
const hasUpgraded = hasHacknetServers(player);
|
||||||
|
const res: any = {
|
||||||
|
name: node instanceof HacknetServer ? node.hostname : node.name,
|
||||||
|
level: node.level,
|
||||||
|
ram: node instanceof HacknetServer ? node.maxRam : node.ram,
|
||||||
|
cores: node.cores,
|
||||||
|
production: node instanceof HacknetServer ? node.hashRate : node.moneyGainRatePerSecond,
|
||||||
|
timeOnline: node.onlineTimeSeconds,
|
||||||
|
totalProduction: node instanceof HacknetServer ? node.totalHashesGenerated : node.totalMoneyGenerated,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (hasUpgraded && node instanceof HacknetServer) {
|
||||||
|
res.cache = node.cache;
|
||||||
|
res.hashCapacity = node.hashCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
upgradeLevel: function (i: any, n: any): any {
|
||||||
|
const node = getHacknetNode(i, "upgradeLevel");
|
||||||
|
return purchaseLevelUpgrade(player, node, n);
|
||||||
|
},
|
||||||
|
upgradeRam: function (i: any, n: any): any {
|
||||||
|
const node = getHacknetNode(i, "upgradeRam");
|
||||||
|
return purchaseRamUpgrade(player, node, n);
|
||||||
|
},
|
||||||
|
upgradeCore: function (i: any, n: any): any {
|
||||||
|
const node = getHacknetNode(i, "upgradeCore");
|
||||||
|
return purchaseCoreUpgrade(player, node, n);
|
||||||
|
},
|
||||||
|
upgradeCache: function (i: any, n: any): any {
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const node = getHacknetNode(i, "upgradeCache");
|
||||||
|
if (!(node instanceof HacknetServer)) {
|
||||||
|
workerScript.log("upgradeCache", "Can only be called on hacknet servers");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const res = purchaseCacheUpgrade(player, node, n);
|
||||||
|
if (res) {
|
||||||
|
updateHashManagerCapacity(player);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
getLevelUpgradeCost: function (i: any, n: any): any {
|
||||||
|
const node = getHacknetNode(i, "upgradeLevel");
|
||||||
|
return node.calculateLevelUpgradeCost(n, player.hacknet_node_level_cost_mult);
|
||||||
|
},
|
||||||
|
getRamUpgradeCost: function (i: any, n: any): any {
|
||||||
|
const node = getHacknetNode(i, "upgradeRam");
|
||||||
|
return node.calculateRamUpgradeCost(n, player.hacknet_node_ram_cost_mult);
|
||||||
|
},
|
||||||
|
getCoreUpgradeCost: function (i: any, n: any): any {
|
||||||
|
const node = getHacknetNode(i, "upgradeCore");
|
||||||
|
return node.calculateCoreUpgradeCost(n, player.hacknet_node_core_cost_mult);
|
||||||
|
},
|
||||||
|
getCacheUpgradeCost: function (i: any, n: any): any {
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
const node = getHacknetNode(i, "upgradeCache");
|
||||||
|
if (!(node instanceof HacknetServer)) {
|
||||||
|
workerScript.log("getCacheUpgradeCost", "Can only be called on hacknet servers");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return node.calculateCacheUpgradeCost(n);
|
||||||
|
},
|
||||||
|
numHashes: function (): any {
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return player.hashManager.hashes;
|
||||||
|
},
|
||||||
|
hashCapacity: function (): any {
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return player.hashManager.capacity;
|
||||||
|
},
|
||||||
|
hashCost: function (upgName: any): any {
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return player.hashManager.getUpgradeCost(upgName);
|
||||||
|
},
|
||||||
|
spendHashes: function (upgName: any, upgTarget: any): any {
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return purchaseHashUpgrade(player, upgName, upgTarget);
|
||||||
|
},
|
||||||
|
getHashUpgradeLevel: function (upgName: any): any {
|
||||||
|
const level = player.hashManager.upgrades[upgName];
|
||||||
|
if (level === undefined) {
|
||||||
|
throw helper.makeRuntimeErrorMsg("hacknet.hashUpgradeLevel", `Invalid Hash Upgrade: ${upgName}`);
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
},
|
||||||
|
getStudyMult: function (): any {
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return player.hashManager.getStudyMult();
|
||||||
|
},
|
||||||
|
getTrainingMult: function (): any {
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return player.hashManager.getTrainingMult();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
export interface INetscriptHelper {
|
export interface INetscriptHelper {
|
||||||
updateDynamicRam(functionName: string, ram: number): void;
|
updateDynamicRam(functionName: string, ram: number): void;
|
||||||
makeRuntimeErrorMsg(functionName: string, message: string): void;
|
makeRuntimeErrorMsg(functionName: string, message: string): void;
|
||||||
|
string(funcName: string, argName: string, v: any): string;
|
||||||
|
number(funcName: string, argName: string, v: any): number;
|
||||||
|
boolean(v: any): boolean;
|
||||||
}
|
}
|
||||||
|
333
src/NetscriptFunctions/Sleeve.ts
Normal file
333
src/NetscriptFunctions/Sleeve.ts
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
import { INetscriptHelper } from "./INetscriptHelper";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||||
|
import { FactionWorkType } from "../Faction/FactionWorkTypeEnum";
|
||||||
|
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
||||||
|
import { SleeveTaskType } from "../PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
||||||
|
import { SpecialServerIps } from "../Server/SpecialServerIps";
|
||||||
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
||||||
|
import { Augmentations } from "../Augmentation/Augmentations";
|
||||||
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
|
|
||||||
|
export interface INetscriptSleeve {
|
||||||
|
getNumSleeves(): number;
|
||||||
|
setToShockRecovery(sleeveNumber?: number): boolean;
|
||||||
|
setToSynchronize(sleeveNumber?: number): boolean;
|
||||||
|
setToCommitCrime(sleeveNumber?: number, crimeName?: string): boolean;
|
||||||
|
setToUniversityCourse(sleeveNumber?: number, universityName?: string, className?: string): boolean;
|
||||||
|
travel(sleeveNumber?: number, cityName?: string): boolean;
|
||||||
|
setToCompanyWork(sleeveNumber?: number, companyName?: string): boolean;
|
||||||
|
setToFactionWork(sleeveNumber?: number, factionName?: string, workType?: string): boolean;
|
||||||
|
setToGymWorkout(sleeveNumber?: number, gymName?: string, stat?: string): boolean;
|
||||||
|
getSleeveStats(sleeveNumber?: number): {
|
||||||
|
shock: number;
|
||||||
|
sync: number;
|
||||||
|
hacking_skill: number;
|
||||||
|
strength: number;
|
||||||
|
defense: number;
|
||||||
|
dexterity: number;
|
||||||
|
agility: number;
|
||||||
|
charisma: number;
|
||||||
|
};
|
||||||
|
getTask(sleeveNumber?: number): {
|
||||||
|
task: string;
|
||||||
|
crime: string;
|
||||||
|
location: string;
|
||||||
|
gymStatType: string;
|
||||||
|
factionWorkType: string;
|
||||||
|
};
|
||||||
|
getInformation(sleeveNumber?: number): any;
|
||||||
|
getSleeveAugmentations(sleeveNumber?: number): string[];
|
||||||
|
getSleevePurchasableAugs(sleeveNumber?: number): {
|
||||||
|
name: string;
|
||||||
|
cost: number;
|
||||||
|
}[];
|
||||||
|
purchaseSleeveAug(sleeveNumber?: number, augName?: string): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NetscriptSleeve(
|
||||||
|
player: IPlayer,
|
||||||
|
workerScript: WorkerScript,
|
||||||
|
helper: INetscriptHelper,
|
||||||
|
): INetscriptSleeve {
|
||||||
|
const checkSleeveAPIAccess = function (func: any): void {
|
||||||
|
if (player.bitNodeN !== 10 && !SourceFileFlags[10]) {
|
||||||
|
throw helper.makeRuntimeErrorMsg(
|
||||||
|
`sleeve.${func}`,
|
||||||
|
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkSleeveNumber = function (func: any, sleeveNumber: any): void {
|
||||||
|
if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) {
|
||||||
|
const msg = `Invalid sleeve number: ${sleeveNumber}`;
|
||||||
|
workerScript.log(func, msg);
|
||||||
|
throw helper.makeRuntimeErrorMsg(`sleeve.${func}`, msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
getNumSleeves: function (): number {
|
||||||
|
helper.updateDynamicRam("getNumSleeves", getRamCost("sleeve", "getNumSleeves"));
|
||||||
|
checkSleeveAPIAccess("getNumSleeves");
|
||||||
|
return player.sleeves.length;
|
||||||
|
},
|
||||||
|
setToShockRecovery: function (asleeveNumber: any = 0): boolean {
|
||||||
|
const sleeveNumber = helper.number("setToShockRecovery", "sleeveNumber", asleeveNumber);
|
||||||
|
helper.updateDynamicRam("setToShockRecovery", getRamCost("sleeve", "setToShockRecovery"));
|
||||||
|
checkSleeveAPIAccess("setToShockRecovery");
|
||||||
|
checkSleeveNumber("setToShockRecovery", sleeveNumber);
|
||||||
|
return player.sleeves[sleeveNumber].shockRecovery(player);
|
||||||
|
},
|
||||||
|
setToSynchronize: function (asleeveNumber: any = 0): boolean {
|
||||||
|
const sleeveNumber = helper.number("setToSynchronize", "sleeveNumber", asleeveNumber);
|
||||||
|
helper.updateDynamicRam("setToSynchronize", getRamCost("sleeve", "setToSynchronize"));
|
||||||
|
checkSleeveAPIAccess("setToSynchronize");
|
||||||
|
checkSleeveNumber("setToSynchronize", sleeveNumber);
|
||||||
|
return player.sleeves[sleeveNumber].synchronize(player);
|
||||||
|
},
|
||||||
|
setToCommitCrime: function (asleeveNumber: any = 0, acrimeName: any = ""): boolean {
|
||||||
|
const sleeveNumber = helper.number("setToCommitCrime", "sleeveNumber", asleeveNumber);
|
||||||
|
const crimeName = helper.string("setToUniversityCourse", "crimeName", acrimeName);
|
||||||
|
helper.updateDynamicRam("setToCommitCrime", getRamCost("sleeve", "setToCommitCrime"));
|
||||||
|
checkSleeveAPIAccess("setToCommitCrime");
|
||||||
|
checkSleeveNumber("setToCommitCrime", sleeveNumber);
|
||||||
|
return player.sleeves[sleeveNumber].commitCrime(player, crimeName);
|
||||||
|
},
|
||||||
|
setToUniversityCourse: function (asleeveNumber: any = 0, auniversityName: any = "", aclassName: any = ""): boolean {
|
||||||
|
const sleeveNumber = helper.number("setToUniversityCourse", "sleeveNumber", asleeveNumber);
|
||||||
|
const universityName = helper.string("setToUniversityCourse", "universityName", auniversityName);
|
||||||
|
const className = helper.string("setToUniversityCourse", "className", aclassName);
|
||||||
|
helper.updateDynamicRam("setToUniversityCourse", getRamCost("sleeve", "setToUniversityCourse"));
|
||||||
|
checkSleeveAPIAccess("setToUniversityCourse");
|
||||||
|
checkSleeveNumber("setToUniversityCourse", sleeveNumber);
|
||||||
|
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
|
||||||
|
},
|
||||||
|
travel: function (asleeveNumber: any = 0, acityName: any = ""): boolean {
|
||||||
|
const sleeveNumber = helper.number("travel", "sleeveNumber", asleeveNumber);
|
||||||
|
const cityName = helper.string("setToUniversityCourse", "cityName", acityName);
|
||||||
|
helper.updateDynamicRam("travel", getRamCost("sleeve", "travel"));
|
||||||
|
checkSleeveAPIAccess("travel");
|
||||||
|
checkSleeveNumber("travel", sleeveNumber);
|
||||||
|
return player.sleeves[sleeveNumber].travel(player, cityName as CityName);
|
||||||
|
},
|
||||||
|
setToCompanyWork: function (asleeveNumber: any = 0, acompanyName: any = ""): boolean {
|
||||||
|
const sleeveNumber = helper.number("setToCompanyWork", "sleeveNumber", asleeveNumber);
|
||||||
|
const companyName = helper.string("setToUniversityCourse", "companyName", acompanyName);
|
||||||
|
helper.updateDynamicRam("setToCompanyWork", getRamCost("sleeve", "setToCompanyWork"));
|
||||||
|
checkSleeveAPIAccess("setToCompanyWork");
|
||||||
|
checkSleeveNumber("setToCompanyWork", sleeveNumber);
|
||||||
|
|
||||||
|
// Cannot work at the same company that another sleeve is working at
|
||||||
|
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||||
|
if (i === sleeveNumber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const other = player.sleeves[i];
|
||||||
|
if (other.currentTask === SleeveTaskType.Company && other.currentTaskLocation === companyName) {
|
||||||
|
throw helper.makeRuntimeErrorMsg(
|
||||||
|
"sleeve.setToFactionWork",
|
||||||
|
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return player.sleeves[sleeveNumber].workForCompany(player, companyName);
|
||||||
|
},
|
||||||
|
setToFactionWork: function (asleeveNumber: any = 0, afactionName: any = "", aworkType: any = ""): boolean {
|
||||||
|
const sleeveNumber = helper.number("setToFactionWork", "sleeveNumber", asleeveNumber);
|
||||||
|
const factionName = helper.string("setToUniversityCourse", "factionName", afactionName);
|
||||||
|
const workType = helper.string("setToUniversityCourse", "workType", aworkType);
|
||||||
|
helper.updateDynamicRam("setToFactionWork", getRamCost("sleeve", "setToFactionWork"));
|
||||||
|
checkSleeveAPIAccess("setToFactionWork");
|
||||||
|
checkSleeveNumber("setToFactionWork", sleeveNumber);
|
||||||
|
|
||||||
|
// Cannot work at the same faction that another sleeve is working at
|
||||||
|
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||||
|
if (i === sleeveNumber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const other = player.sleeves[i];
|
||||||
|
if (other.currentTask === SleeveTaskType.Faction && other.currentTaskLocation === factionName) {
|
||||||
|
throw helper.makeRuntimeErrorMsg(
|
||||||
|
"sleeve.setToFactionWork",
|
||||||
|
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType);
|
||||||
|
},
|
||||||
|
setToGymWorkout: function (asleeveNumber: any = 0, agymName: any = "", astat: any = ""): boolean {
|
||||||
|
const sleeveNumber = helper.number("setToGymWorkout", "sleeveNumber", asleeveNumber);
|
||||||
|
const gymName = helper.string("setToUniversityCourse", "gymName", agymName);
|
||||||
|
const stat = helper.string("setToUniversityCourse", "stat", astat);
|
||||||
|
helper.updateDynamicRam("setToGymWorkout", getRamCost("sleeve", "setToGymWorkout"));
|
||||||
|
checkSleeveAPIAccess("setToGymWorkout");
|
||||||
|
checkSleeveNumber("setToGymWorkout", sleeveNumber);
|
||||||
|
|
||||||
|
return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat);
|
||||||
|
},
|
||||||
|
getSleeveStats: function (asleeveNumber: any = 0): {
|
||||||
|
shock: number;
|
||||||
|
sync: number;
|
||||||
|
hacking_skill: number;
|
||||||
|
strength: number;
|
||||||
|
defense: number;
|
||||||
|
dexterity: number;
|
||||||
|
agility: number;
|
||||||
|
charisma: number;
|
||||||
|
} {
|
||||||
|
const sleeveNumber = helper.number("getSleeveStats", "sleeveNumber", asleeveNumber);
|
||||||
|
helper.updateDynamicRam("getSleeveStats", getRamCost("sleeve", "getSleeveStats"));
|
||||||
|
checkSleeveAPIAccess("getSleeveStats");
|
||||||
|
checkSleeveNumber("getSleeveStats", sleeveNumber);
|
||||||
|
|
||||||
|
const sl = player.sleeves[sleeveNumber];
|
||||||
|
return {
|
||||||
|
shock: 100 - sl.shock,
|
||||||
|
sync: sl.sync,
|
||||||
|
hacking_skill: sl.hacking_skill,
|
||||||
|
strength: sl.strength,
|
||||||
|
defense: sl.defense,
|
||||||
|
dexterity: sl.dexterity,
|
||||||
|
agility: sl.agility,
|
||||||
|
charisma: sl.charisma,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getTask: function (asleeveNumber: any = 0): {
|
||||||
|
task: string;
|
||||||
|
crime: string;
|
||||||
|
location: string;
|
||||||
|
gymStatType: string;
|
||||||
|
factionWorkType: string;
|
||||||
|
} {
|
||||||
|
const sleeveNumber = helper.number("getTask", "sleeveNumber", asleeveNumber);
|
||||||
|
helper.updateDynamicRam("getTask", getRamCost("sleeve", "getTask"));
|
||||||
|
checkSleeveAPIAccess("getTask");
|
||||||
|
checkSleeveNumber("getTask", sleeveNumber);
|
||||||
|
|
||||||
|
const sl = player.sleeves[sleeveNumber];
|
||||||
|
return {
|
||||||
|
task: SleeveTaskType[sl.currentTask],
|
||||||
|
crime: sl.crimeType,
|
||||||
|
location: sl.currentTaskLocation,
|
||||||
|
gymStatType: sl.gymStatType,
|
||||||
|
factionWorkType: FactionWorkType[sl.factionWorkType],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getInformation: function (asleeveNumber: any = 0): any {
|
||||||
|
const sleeveNumber = helper.number("getInformation", "sleeveNumber", asleeveNumber);
|
||||||
|
helper.updateDynamicRam("getInformation", getRamCost("sleeve", "getInformation"));
|
||||||
|
checkSleeveAPIAccess("getInformation");
|
||||||
|
checkSleeveNumber("getInformation", sleeveNumber);
|
||||||
|
|
||||||
|
const sl = player.sleeves[sleeveNumber];
|
||||||
|
return {
|
||||||
|
city: sl.city,
|
||||||
|
hp: sl.hp,
|
||||||
|
jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player.
|
||||||
|
jobTitle: Object.values(player.jobs),
|
||||||
|
maxHp: sl.max_hp,
|
||||||
|
tor: SpecialServerIps.hasOwnProperty("Darkweb Server"), // There's no reason not to give that infomation here as well. Worst case scenario it isn't used.
|
||||||
|
|
||||||
|
mult: {
|
||||||
|
agility: sl.agility_mult,
|
||||||
|
agilityExp: sl.agility_exp_mult,
|
||||||
|
companyRep: sl.company_rep_mult,
|
||||||
|
crimeMoney: sl.crime_money_mult,
|
||||||
|
crimeSuccess: sl.crime_success_mult,
|
||||||
|
defense: sl.defense_mult,
|
||||||
|
defenseExp: sl.defense_exp_mult,
|
||||||
|
dexterity: sl.dexterity_mult,
|
||||||
|
dexterityExp: sl.dexterity_exp_mult,
|
||||||
|
factionRep: sl.faction_rep_mult,
|
||||||
|
hacking: sl.hacking_mult,
|
||||||
|
hackingExp: sl.hacking_exp_mult,
|
||||||
|
strength: sl.strength_mult,
|
||||||
|
strengthExp: sl.strength_exp_mult,
|
||||||
|
workMoney: sl.work_money_mult,
|
||||||
|
},
|
||||||
|
|
||||||
|
timeWorked: sl.currentTaskTime,
|
||||||
|
earningsForSleeves: {
|
||||||
|
workHackExpGain: sl.earningsForSleeves.hack,
|
||||||
|
workStrExpGain: sl.earningsForSleeves.str,
|
||||||
|
workDefExpGain: sl.earningsForSleeves.def,
|
||||||
|
workDexExpGain: sl.earningsForSleeves.dex,
|
||||||
|
workAgiExpGain: sl.earningsForSleeves.agi,
|
||||||
|
workChaExpGain: sl.earningsForSleeves.cha,
|
||||||
|
workMoneyGain: sl.earningsForSleeves.money,
|
||||||
|
},
|
||||||
|
earningsForPlayer: {
|
||||||
|
workHackExpGain: sl.earningsForPlayer.hack,
|
||||||
|
workStrExpGain: sl.earningsForPlayer.str,
|
||||||
|
workDefExpGain: sl.earningsForPlayer.def,
|
||||||
|
workDexExpGain: sl.earningsForPlayer.dex,
|
||||||
|
workAgiExpGain: sl.earningsForPlayer.agi,
|
||||||
|
workChaExpGain: sl.earningsForPlayer.cha,
|
||||||
|
workMoneyGain: sl.earningsForPlayer.money,
|
||||||
|
},
|
||||||
|
earningsForTask: {
|
||||||
|
workHackExpGain: sl.earningsForTask.hack,
|
||||||
|
workStrExpGain: sl.earningsForTask.str,
|
||||||
|
workDefExpGain: sl.earningsForTask.def,
|
||||||
|
workDexExpGain: sl.earningsForTask.dex,
|
||||||
|
workAgiExpGain: sl.earningsForTask.agi,
|
||||||
|
workChaExpGain: sl.earningsForTask.cha,
|
||||||
|
workMoneyGain: sl.earningsForTask.money,
|
||||||
|
},
|
||||||
|
workRepGain: sl.getRepGain(player),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getSleeveAugmentations: function (asleeveNumber: any = 0): string[] {
|
||||||
|
const sleeveNumber = helper.number("getSleeveAugmentations", "sleeveNumber", asleeveNumber);
|
||||||
|
helper.updateDynamicRam("getSleeveAugmentations", getRamCost("sleeve", "getSleeveAugmentations"));
|
||||||
|
checkSleeveAPIAccess("getSleeveAugmentations");
|
||||||
|
checkSleeveNumber("getSleeveAugmentations", sleeveNumber);
|
||||||
|
|
||||||
|
const augs = [];
|
||||||
|
for (let i = 0; i < player.sleeves[sleeveNumber].augmentations.length; i++) {
|
||||||
|
augs.push(player.sleeves[sleeveNumber].augmentations[i].name);
|
||||||
|
}
|
||||||
|
return augs;
|
||||||
|
},
|
||||||
|
getSleevePurchasableAugs: function (asleeveNumber: any = 0): {
|
||||||
|
name: string;
|
||||||
|
cost: number;
|
||||||
|
}[] {
|
||||||
|
const sleeveNumber = helper.number("getSleevePurchasableAugs", "sleeveNumber", asleeveNumber);
|
||||||
|
helper.updateDynamicRam("getSleevePurchasableAugs", getRamCost("sleeve", "getSleevePurchasableAugs"));
|
||||||
|
checkSleeveAPIAccess("getSleevePurchasableAugs");
|
||||||
|
checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber);
|
||||||
|
|
||||||
|
const purchasableAugs = findSleevePurchasableAugs(player.sleeves[sleeveNumber], player);
|
||||||
|
const augs = [];
|
||||||
|
for (let i = 0; i < purchasableAugs.length; i++) {
|
||||||
|
const aug = purchasableAugs[i];
|
||||||
|
augs.push({
|
||||||
|
name: aug.name,
|
||||||
|
cost: aug.startingCost,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return augs;
|
||||||
|
},
|
||||||
|
purchaseSleeveAug: function (asleeveNumber: any = 0, aaugName: any = ""): boolean {
|
||||||
|
const sleeveNumber = helper.number("purchaseSleeveAug", "sleeveNumber", asleeveNumber);
|
||||||
|
const augName = helper.string("setToUniversityCourse", "augName", aaugName);
|
||||||
|
helper.updateDynamicRam("purchaseSleeveAug", getRamCost("sleeve", "purchaseSleeveAug"));
|
||||||
|
checkSleeveAPIAccess("purchaseSleeveAug");
|
||||||
|
checkSleeveNumber("purchaseSleeveAug", sleeveNumber);
|
||||||
|
|
||||||
|
const aug = Augmentations[augName];
|
||||||
|
if (!aug) {
|
||||||
|
throw helper.makeRuntimeErrorMsg("sleeve.purchaseSleeveAug", `Invalid aug: ${augName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
@ -53,4 +53,5 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="root" />
|
<div id="root" />
|
||||||
</body>
|
</body>
|
||||||
|
<!-- http://plaza.dsolver.ca/m/hydroflame4418 -->
|
||||||
</html>
|
</html>
|
||||||
|
@ -6,6 +6,9 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
|
import Draggable from "react-draggable";
|
||||||
|
import { ResizableBox } from "react-resizable";
|
||||||
|
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
||||||
|
|
||||||
export const LogBoxEvents = new EventEmitter<[RunningScript]>();
|
export const LogBoxEvents = new EventEmitter<[RunningScript]>();
|
||||||
|
|
||||||
@ -64,20 +67,6 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
function closeHandler(event: KeyboardEvent): void {
|
|
||||||
if (event.keyCode === 27) {
|
|
||||||
props.onClose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("keydown", closeHandler);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("keydown", closeHandler);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function kill(): void {
|
function kill(): void {
|
||||||
killWorkerScript(props.script, props.script.server, true);
|
killWorkerScript(props.script, props.script.server, true);
|
||||||
props.onClose();
|
props.onClose();
|
||||||
@ -113,51 +102,57 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Draggable handle="#drag">
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexFlow: "column",
|
|
||||||
backgroundColor: "gray",
|
|
||||||
width: "50%",
|
|
||||||
position: "fixed",
|
|
||||||
left: "50%",
|
|
||||||
top: "40%",
|
|
||||||
margin: "-10% 0 0 -25%",
|
|
||||||
height: "auto",
|
|
||||||
maxHeight: "50%",
|
|
||||||
zIndex: 10,
|
|
||||||
border: "2px solid $hacker-green",
|
|
||||||
}}
|
|
||||||
ref={container}
|
|
||||||
>
|
|
||||||
<Paper
|
<Paper
|
||||||
style={{
|
style={{
|
||||||
cursor: "grab",
|
display: "flex",
|
||||||
|
flexFlow: "column",
|
||||||
|
position: "fixed",
|
||||||
|
left: "40%",
|
||||||
|
top: "30%",
|
||||||
|
zIndex: 1400,
|
||||||
}}
|
}}
|
||||||
|
ref={container}
|
||||||
>
|
>
|
||||||
<Box display="flex" alignItems="center" onMouseDown={drag}>
|
<Paper
|
||||||
<Typography color="primary" variant="h6" noWrap component="div">
|
style={{
|
||||||
{props.script.filename} {props.script.args.map((x: any): string => `${x}`).join(" ")}
|
cursor: "grab",
|
||||||
</Typography>
|
}}
|
||||||
|
>
|
||||||
|
<Box id="drag" display="flex" alignItems="center">
|
||||||
|
<Typography color="primary" variant="h6" noWrap component="div">
|
||||||
|
{props.script.filename} {props.script.args.map((x: any): string => `${x}`).join(" ")}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
<Box display="flex" marginLeft="auto">
|
<Box display="flex" marginLeft="auto">
|
||||||
<Button onClick={kill}>Kill Script</Button>
|
<Button onClick={kill}>Kill Script</Button>
|
||||||
<Button onClick={props.onClose}>Close</Button>
|
<Button onClick={props.onClose}>Close</Button>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Paper>
|
||||||
|
<Paper sx={{ overflow: "scroll", overflowWrap: "break-word", whiteSpace: "pre-line" }}>
|
||||||
|
<ResizableBox
|
||||||
|
height={500}
|
||||||
|
width={500}
|
||||||
|
handle={
|
||||||
|
<span style={{ position: "absolute", right: 0, bottom: 0 }}>
|
||||||
|
<ArrowForwardIosIcon color="primary" style={{ transform: "rotate(45deg)" }} />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
{props.script.logs.map(
|
||||||
|
(line: string, i: number): JSX.Element => (
|
||||||
|
<Typography key={i}>
|
||||||
|
{line}
|
||||||
|
<br />
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</ResizableBox>
|
||||||
|
</Paper>
|
||||||
</Paper>
|
</Paper>
|
||||||
<Paper>
|
</Draggable>
|
||||||
<Box maxHeight="25vh" overflow="scroll" sx={{ overflowWrap: "break-word", whiteSpace: "pre-line" }}>
|
|
||||||
{props.script.logs.map(
|
|
||||||
(line: string, i: number): JSX.Element => (
|
|
||||||
<Typography key={i}>
|
|
||||||
{line}
|
|
||||||
<br />
|
|
||||||
</Typography>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
|
||||||
</Paper>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user