Merge pull request #949 from danielyxie/dev

v0.51.8
This commit is contained in:
hydroflame 2021-05-07 22:29:39 -04:00 committed by GitHub
commit b35d8475e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 273 additions and 351 deletions

File diff suppressed because one or more lines are too long

@ -1,2 +1,2 @@
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([840,0]),o()}({779:function(n,t,o){},781:function(n,t,o){},783:function(n,t,o){},785:function(n,t,o){},787:function(n,t,o){},789:function(n,t,o){},791:function(n,t,o){},793:function(n,t,o){},795:function(n,t,o){},797:function(n,t,o){},799:function(n,t,o){},801:function(n,t,o){},803:function(n,t,o){},805:function(n,t,o){},807:function(n,t,o){},809:function(n,t,o){},811:function(n,t,o){},813:function(n,t,o){},815:function(n,t,o){},817:function(n,t,o){},819:function(n,t,o){},821:function(n,t,o){},823:function(n,t,o){},825:function(n,t,o){},827:function(n,t,o){},829:function(n,t,o){},831:function(n,t,o){},833:function(n,t,o){},835:function(n,t,o){},837:function(n,t,o){},840:function(n,t,o){"use strict";o.r(t);o(839),o(837),o(835),o(833),o(831),o(829),o(827),o(825),o(823),o(821),o(819),o(817),o(815),o(813),o(811),o(809),o(807),o(805),o(803),o(801),o(799),o(797),o(795),o(793),o(791),o(789),o(787),o(785),o(783),o(781),o(779)}});
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([841,0]),o()}({780:function(n,t,o){},782:function(n,t,o){},784:function(n,t,o){},786:function(n,t,o){},788:function(n,t,o){},790:function(n,t,o){},792:function(n,t,o){},794:function(n,t,o){},796:function(n,t,o){},798:function(n,t,o){},800:function(n,t,o){},802:function(n,t,o){},804:function(n,t,o){},806:function(n,t,o){},808:function(n,t,o){},810:function(n,t,o){},812:function(n,t,o){},814:function(n,t,o){},816:function(n,t,o){},818:function(n,t,o){},820:function(n,t,o){},822:function(n,t,o){},824:function(n,t,o){},826:function(n,t,o){},828:function(n,t,o){},830:function(n,t,o){},832:function(n,t,o){},834:function(n,t,o){},836:function(n,t,o){},838:function(n,t,o){},841:function(n,t,o){"use strict";o.r(t);o(840),o(838),o(836),o(834),o(832),o(830),o(828),o(826),o(824),o(822),o(820),o(818),o(816),o(814),o(812),o(810),o(808),o(806),o(804),o(802),o(800),o(798),o(796),o(794),o(792),o(790),o(788),o(786),o(784),o(782),o(780)}});
//# sourceMappingURL=engineStyle.bundle.js.map

28
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -47,7 +47,7 @@ List of all Source-Files
+------------------------------------+-------------------------------------------------------------------------------------+
| BitNode-9: Coming Soon | |
+------------------------------------+-------------------------------------------------------------------------------------+
| BitNode-10: Digital Carbon | * Each level of this grants a Duplicate Sleeve |
| BitNode-10: Digital Carbon | * Each level of this grants a Duplicate Sleeve. |
| | * Allows the player to access the :ref:`netscript_sleeveapi` in other BitNodes |
+------------------------------------+-------------------------------------------------------------------------------------+
| BitNode-11: The Big Crash | * Company favor increases both the player's salary and reputation gain at that |

@ -3,6 +3,63 @@
Changelog
=========
v0.51.8 - 2021-05-07 It was there all along (hydroflame)
--------------------------------------------------------
**Servers**
* Update n00dles metadata
**Netscript**
* 'hashGainRate' use the correct 'usedRam' and 'maxRam'
* Fix 'setActionAutolevel' logging.
* Fix 'setActionLevel' not working at all.
* Add 'installBackdoor' singularity function.
**Hacknet**
* Fix Hacknet Servers total production always displaying 0
**Documentation**
* Updated guide to no longer recommend BN12.
* Fix documentation for maxNumNodes (@ModdedGamers)
* Fix typo in 'sourcefiles.rst'
* Fix typo in 'recommendedbitnodeorder.rst'
* Fix 'getServer' documentation missing 'server' argument.
* Fix missing ram cost in 'getData.rst'
* Fix basic formulas examples.
* Fix typo in BN11 description.
* Fix formatting issue in Bladeburner (@Pimgd)
**Misc.**
* Fix negative money being displayed in full.
* Fix Hacking Missions not working.
* Fix Corporation tree not rendering.
* Fix script being needlessly recompiled. This should save real ram (not game ram)
* w0r1d_d43m0n can be backdoored
* Coding Contracts title is click-to-copy (@Rodeth)
* Covenant memory upgrade works better.
* Fix Neuroflux not being correctly calculated when entering BN with SF12.
* Delete Active Script now delete all active scripts, not just home.
* Now you can 'cd' in directories that only contain '.txt' files.
* Fix 'analyze' always saying players had root access
* Passive faction rep no longer builds for special factions.
* Donation option no longer appears for special factions.
* Rephrased some milestones.
* donation textbox now accepts money in the format '1b' and the like (@Dawe)
* Fix being able to join hated factions simultaneously. (@Dawe)
* 'ls' now displays files in multiple column. (Helps players with many files)
* Bladeburner multiplers now appear under Character>Stats and
Character>Augmentation when they are relevant.
* Fix missing functions syntax highlight in codemirror.
* Fix infiltration number formatting.
* script income transfers to parent on death. This helps keep track of
income for scripts that spawn short lived scripts.
v0.51.7 - 2021-04-28 n00dles
----------------------------

@ -66,7 +66,7 @@ documentation_title = '{0} Documentation'.format(project)
# The short X.Y version.
version = '0.51'
# The full version, including alpha/beta/rc tags.
release = '0.51.7'
release = '0.51.8'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

@ -323,7 +323,7 @@ Source-File
:Max Level: 3
This Source-File unlocks Sleeve technology in other BitNodes.
Each level of this Source-File also grants you a Duplicate Sleeve
Each level of this Source-File also grants you a Duplicate Sleeve.
Difficulty
Hard

@ -1,9 +1,10 @@
getServer() Netscript Function
==========================================
.. js:function:: getServer()
.. js:function:: getServer([hostname])
:RAM cost: 4 GB
:param string hostname: Hostname of the server, defaults to host server.
If you are not in BitNode-5, then you must have Source-File 5-1 in order to run this function.

@ -3,6 +3,7 @@ getData() Netscript Function
.. js:function:: getData(filename[, hostname=current hostname])
:RAM cost: 5 GB
:param string filename: Filename of the contract
:param string hostname: Hostname of the server containing the contract.
Optional. Defaults to current server if not provided

@ -20,4 +20,4 @@ growPercent() Netscript Function
.. code-block:: javascript
tprint(growPercent(getServer(), 50, getPlayer()))
tprint(formulas.basic.growPercent(getServer(), 50, getPlayer()))

@ -21,4 +21,4 @@ growTime() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(growTime(server, getPlayer()));
tprint(formulas.basic.growTime(server, getPlayer()));

@ -21,4 +21,4 @@ hackChance() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(hackChance(server, getPlayer()));
tprint(formulas.basic.hackChance(server, getPlayer()));

@ -21,4 +21,4 @@ hackExp() Netscript Function
server = getServer();
server.hackDifficulty = 99.9;
tprint(hackExp(server, getPlayer()));
tprint(formulas.basic.hackExp(server, getPlayer()));

@ -22,4 +22,4 @@ hackPercent() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(hackPercent(server, getPlayer()));
tprint(formulas.basic.hackPercent(server, getPlayer()));

@ -21,4 +21,4 @@ hackTime() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(hackTime(server, getPlayer()));
tprint(formulas.basic.hackTime(server, getPlayer()));

@ -21,4 +21,4 @@ weakenTime() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(weakenTime(server, getPlayer()));
tprint(formulas.basic.weakenTime(server, getPlayer()));

@ -124,5 +124,5 @@
"watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development"
},
"version": "0.51.7"
"version": "0.51.8"
}

@ -44,6 +44,18 @@ export function PlayerMultipliers(): React.ReactElement {
</table>
}
function BladeburnerMults(): React.ReactElement {
if(!Player.canAccessBladeburner()) return (<></>);
return (<>
{MultiplierTable([
['Bladeburner Success Chance', Player.bladeburner_max_stamina_mult, Player.bladeburner_max_stamina_mult*mults.bladeburner_max_stamina_mult],
['Bladeburner Max Stamina', Player.bladeburner_max_stamina_mult, Player.bladeburner_max_stamina_mult*mults.bladeburner_max_stamina_mult],
['Bladeburner Stamina Gain', Player.bladeburner_max_stamina_mult, Player.bladeburner_max_stamina_mult*mults.bladeburner_max_stamina_mult],
['Bladeburner Field Analysis', Player.bladeburner_max_stamina_mult, Player.bladeburner_max_stamina_mult*mults.bladeburner_max_stamina_mult],
])}<br />
</>);
}
return (
<>
<p><strong><u>Multipliers:</u></strong></p><br />
@ -103,6 +115,8 @@ export function PlayerMultipliers(): React.ReactElement {
['Crime success ', Player.crime_success_mult, Player.crime_success_mult*mults.crime_success_mult],
['Crime money ', Player.crime_money_mult, Player.crime_money_mult*mults.crime_money_mult],
])}<br />
<BladeburnerMults />
</>
)
}

@ -221,7 +221,7 @@ BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
"The growth rate of servers is significantly reduced<br>" +
"Weakening a server is twice as effective<br>" +
"Company wages are decreased by 50%<br>" +
"Corporation valuations are 99% lower and are therefore significantly less profitable<br>" +
"Corporation valuations are 90% lower and are therefore significantly less profitable<br>" +
"Hacknet Node production is significantly decreased<br>" +
"Crime and Infiltration are more lucrative<br>" +
"Augmentations are twice as expensive<br><br>" +

@ -736,7 +736,7 @@ Bladeburner.prototype.completeAction = function() {
}
}
var logLossText = "";
if (loss > 0) {logLossText += "Lost " + formatNumber(loss, 3) + " rank.";}
if (loss > 0) {logLossText += "Lost " + formatNumber(loss, 3) + " rank. ";}
if (damage > 0) {logLossText += "Took " + formatNumber(damage, 0) + " damage.";}
if (isOperation && this.logging.ops) {
this.log(action.name + " failed! " + logLossText);

@ -6,7 +6,7 @@
import { IMap } from "./types";
export const CONSTANTS: IMap<any> = {
Version: "0.51.7",
Version: "0.51.8",
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -228,61 +228,60 @@ export const CONSTANTS: IMap<any> = {
LatestUpdate:
`
v0.51.7 - 2021-04-28 n00dles
v0.51.8 - 2021-05-07 It was there all along (hydroflame)
-------
Tutorial servers
Servers
* All the tutorial servers have been reverted to their original value
* The new server n00dles has been added as tutorial server.
Terminal
* 'tail' now accepts Pid.
* 'analyze' now handles Hacknet Servers correctly.
* 'ServerProfiler.exe' now handles Hacknet Servers correctly.
SF12
* Now makes you start with Neuroflux Governor equal to the level of the SF.
* Update n00dles metadata
Netscript
* Deprecated 'getServerRam'.
* 'getServerMaxRam' added to replace 'getServerRam'
* 'getServerUsedRam' added to replace 'getServerRam'
* 'getBitnodeMultipliers' is available inside BN5
* Time logged by hack/grow/weaken now displays in human time.
* thread count logged by hack/grow/weaken now displays with commas every
thousands place.
* 'hashGainRate' use the correct 'usedRam' and 'maxRam'
* Fix 'setActionAutolevel' logging.
* Fix 'setActionLevel' not working at all.
* Add 'installBackdoor' singularity function.
Donation
Hacknet
* Always visible but locked until favor requirements are reached.
* Fix Hacknet Servers total production always displaying 0
Augmentations
Documentation
* City factions has been rebalanced to give a reason to visit them all.
Sleeves
* Fix sleeves not being able to work at Volhavens gym.
Lint
* This shouldn't change anything but was like 10h of work.
* Updated guide to no longer recommend BN12.
* Fix documentation for maxNumNodes (@ModdedGamers)
* Fix typo in 'sourcefiles.rst'
* Fix typo in 'recommendedbitnodeorder.rst'
* Fix 'getServer' documentation missing 'server' argument.
* Fix missing ram cost in 'getData.rst'
* Fix basic formulas examples.
* Fix typo in BN11 description.
* Fix formatting issue in Bladeburner (@Pimgd)
Misc.
* Plethora of typo fixed (@Pimgd)
* ps documentation fix (@Dawe)
* The dev menu now has a quick bitflume option.
* Fix SF -1 not being as powerful as intended.
* Fix cashroot starter kit not displaying correctly.
* Fix DOM element 'character-overview-text' being nested twice.
* Hacknet documentation example fix.
* Money amount under 1000 dont display 3 decimal anymore.
* Fix nextSourceFile flag miscalculation on the bitverse (for Bn12)
* Faction invite text says "Decide later"/"Join!" instead of "No"/"Yes"
* Fix negative money being displayed in full.
* Fix Hacking Missions not working.
* Fix Corporation tree not rendering.
* Fix script being needlessly recompiled. This should save real ram (not game ram)
* w0r1d_d43m0n can be backdoored
* Coding Contracts title is click-to-copy (@Rodeth)
* Covenant memory upgrade works better.
* Fix Neuroflux not being correctly calculated when entering BN with SF12.
* Delete Active Script now delete all active scripts, not just home.
* Now you can 'cd' in directories that only contain '.txt' files.
* Fix 'analyze' always saying players had root access
* Passive faction rep no longer builds for special factions.
* Donation option no longer appears for special factions.
* Rephrased some milestones.
* donation textbox now accepts money in the format '1b' and the like (@Dawe)
* Fix being able to join hated factions simultaneously. (@Dawe)
* 'ls' now displays files in multiple column. (Helps players with many files)
* Bladeburner multiplers now appear under Character>Stats and
Character>Augmentation when they are relevant.
* Fix missing functions syntax highlight in codemirror.
* Fix infiltration number formatting.
* script income transfers to parent on death. This helps keep track of
income for scripts that spawn short lived scripts.
`,
}

@ -60,7 +60,7 @@ export class Overview extends BaseReactComponent {
let txt = "Total Funds: " + numeralWrapper.format(this.corp().funds.toNumber(), '$0.000a') + "<br>" +
"Total Revenue: " + numeralWrapper.format(this.corp().revenue.toNumber(), "$0.000a") + " / s<br>" +
"Total Expenses: " + numeralWrapper.format(this.corp().expenses.toNumber(), "$0.000a") + "/ s<br>" +
"Total Expenses: " + numeralWrapper.format(this.corp().expenses.toNumber(), "$0.000a") + " / s<br>" +
"Total Profits: " + profitStr + " / s<br>" +
dividendStr +
"Publicly Traded: " + (this.corp().public ? "Yes" : "No") + "<br>" +

@ -56,6 +56,12 @@ export function joinFaction(faction) {
Factions[enemy].isBanned = true;
}
}
for (var i = 0; i < Player.factionInvitations.length; ++i) {
if (Player.factionInvitations[i] == faction.name || Factions[Player.factionInvitations[i]].isBanned) {
Player.factionInvitations.splice(i, 1);
i--;
}
}
}
export function startHackingMission(faction) {

@ -12,6 +12,8 @@ import { Reputation } from "../../ui/React/Reputation";
import { StdButton } from "../../ui/React/StdButton";
import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = {
@ -73,7 +75,7 @@ export class DonateOption extends React.Component<IProps, IState> {
}
handleChange(e: React.ChangeEvent<HTMLInputElement>): void {
const amt = parseFloat(e.target.value);
const amt = numeralWrapper.parseMoney(e.target.value);
if (isNaN(amt)) {
this.setState({

@ -421,7 +421,9 @@ function processAllHacknetServerEarnings(numCycles) {
// Also, update the hash rate before processing
const hserver = AllServers[Player.hacknetNodes[i]];
hserver.updateHashRate(Player.hacknet_node_money_mult);
hashes += hserver.process(numCycles);
const h = hserver.process(numCycles);
hserver.totalHashesGenerated += h;
hashes += h;
}
Player.hashManager.storeHashes(hashes);

@ -3981,7 +3981,7 @@ function NetscriptFunctions(workerScript) {
setActionAutolevel: function(type="", name="", autoLevel=true) {
updateDynamicRam("setActionAutolevel", getRamCost("bladeburner", "setActionAutolevel"));
checkBladeburnerAccess("setActionAutolevel");
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
const action = getBladeburnerActionObject("setActionAutolevel", type, name);
action.autoLevel = autoLevel;
},
setActionLevel: function(type="", name="", level=1) {
@ -3991,7 +3991,7 @@ function NetscriptFunctions(workerScript) {
if(level < 1 || level > action.maxLevel) {
throw makeRuntimeErrorMsg("bladeburner.setActionLevel", `Level must be between 1 and ${action.maxLevel}, is ${level}`)
}
actionObj.level = level;
action.level = level;
},
getRank: function() {
updateDynamicRam("getRank", getRamCost("bladeburner", "getRank"));

@ -417,8 +417,8 @@ function processNetscript1Imports(code, workerScript) {
* @param {Server} server - Server on which the script is to be run
* @returns {number} pid of started script
*/
export function startWorkerScript(runningScript, server) {
if (createAndAddWorkerScript(runningScript, server)) {
export function startWorkerScript(runningScript, server, parent) {
if (createAndAddWorkerScript(runningScript, server, parent)) {
// Push onto runningScripts.
// This has to come after createAndAddWorkerScript() because that fn updates RAM usage
server.runScript(runningScript, Player.hacknet_node_money_mult);
@ -438,7 +438,7 @@ export function startWorkerScript(runningScript, server) {
* @param {Server} server - Server on which the script is to be run
* returns {boolean} indicating whether or not the workerScript was successfully added
*/
export function createAndAddWorkerScript(runningScriptObj, server) {
export function createAndAddWorkerScript(runningScriptObj, server, parent) {
// Update server's ram usage
let threads = 1;
if (runningScriptObj.threads && !isNaN(runningScriptObj.threads)) {
@ -489,6 +489,12 @@ export function createAndAddWorkerScript(runningScriptObj, server) {
// Once the code finishes (either resolved or rejected, doesnt matter), set its
// running status to false
p.then(function(w) {
// On natural death, the earnings are transfered to the parent if it still exists.
if(parent && parent.running) {
parent.scriptRef.onlineExpGained += runningScriptObj.onlineExpGained;
parent.scriptRef.onlineMoneyMade += runningScriptObj.onlineMoneyMade;
}
// If the WorkerScript is no longer "running", then this means its execution was
// already stopped somewhere else (maybe by something like exit()). This prevents
// the script from being cleaned up twice
@ -643,7 +649,7 @@ export function runScriptFromScript(caller, server, scriptname, args, workerScri
let runningScriptObj = new RunningScript(script, args);
runningScriptObj.threads = threads;
return startWorkerScript(runningScriptObj, server);
return startWorkerScript(runningScriptObj, server, workerScript);
}
}
}

@ -1,5 +1,5 @@
import { Program } from "./Program";
import { programsMetadata } from "./data/programsMetadata";
import { programsMetadata } from "./data/ProgramsMetadata";
import { IMap } from "../types";
export const Programs: IMap<Program> = {};

@ -178,7 +178,7 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
netscriptFns.push(name);
//Get functions from namespaces
const namespaces = ["bladeburner", "hacknet", "codingcontract", "gang", "sleeve"];
const namespaces = ["bladeburner", "hacknet", "codingcontract", "gang", "sleeve", "heart", "formulas"];
if (namespaces.includes(name)) {
let namespace = fnsObj[name];
if (typeof namespace !== "object") {continue;}

@ -1,5 +1,7 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
import CodeMirror from "codemirror/lib/codemirror.js";
import { NetscriptFunctions } from "../NetscriptFunctions";
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -26,7 +28,7 @@ CodeMirror.defineMode("netscript", function(config, parserConfig) {
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
return {
const ret = {
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
"return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
"debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
@ -40,234 +42,16 @@ CodeMirror.defineMode("netscript", function(config, parserConfig) {
// Netscript Basic Functions
"hack": atom,
"hackAnalyzeThreads": atom,
"hackAnalyzePercent": atom,
"hackChance": atom,
"sleep": atom,
"grow": atom,
"weaken": atom,
"growthAnalyze": atom,
"print": atom,
"tprint": atom,
"scan": atom,
"nuke": atom,
"brutessh": atom,
"ftpcrack": atom,
"clearLog": atom,
"disableLog": atom,
"enableLog": atom,
"isLogEnabled": atom,
"getScriptLogs": atom,
"tail": atom,
"relaysmtp": atom,
"httpworm": atom,
"sqlinject": atom,
"run": atom,
"exec": atom,
"spawn": atom,
"kill": atom,
"killall": atom,
"exit": atom,
"scp": atom,
"ls": atom,
"ps": atom,
"hasRootAccess": atom,
"getIp": atom,
"getHackingMultipliers": atom,
"getBitNodeMultipliers": atom,
"getStats": atom,
"isBusy": atom,
"getHacknetMultipliers": atom,
"getHostname": atom,
"getHackingLevel": atom,
"getServerMoneyAvailable": atom,
"getServerMaxMoney": atom,
"getServerGrowth": atom,
"getServerSecurityLevel": atom,
"getServerBaseSecurityLevel": atom,
"getServerMinSecurityLevel": atom,
"getServerRequiredHackingLevel": atom,
"getServerNumPortsRequired": atom,
"getServerRam": atom,
"serverExists": atom,
"fileExists": atom,
"isRunning": atom,
"deleteServer": atom,
"getPurchasedServers": atom,
"getPurchasedServerLimit": atom,
"getPurchasedServerMaxRam": atom,
"getPurchasedServerCost": atom,
"purchaseServer": atom,
"round": atom,
"write": atom,
"tryWrite": atom,
"read": atom,
"peek": atom,
"clear": atom,
"rm": atom,
"getPortHandle": atom,
"scriptRunning": atom,
"scriptKill": atom,
"getScriptName": atom,
"getScriptRam": atom,
"getHackTime": atom,
"getGrowTime": atom,
"getWeakenTime": atom,
"getScriptIncome": atom,
"getScriptExpGain": atom,
"getTimeSinceLastAug": atom,
"prompt": atom,
// Netscript Singularity Functions
"universityCourse": atom,
"getCharacterInformation": atom,
"gymWorkout": atom,
"travelToCity": atom,
"purchaseTor": atom,
"purchaseProgram": atom,
"upgradeHomeRam": atom,
"getUpgradeHomeRamCost": atom,
"workForCompany": atom,
"applyToCompany": atom,
"getCompanyRep": atom,
"getCompanyFavor": atom,
"stopAction": atom,
"getFactionFavor": atom,
"getFavorToDonate": atom,
"getFactionFavorGain": atom,
"getCompanyFavorGain": atom,
"checkFactionInvitations": atom,
"joinFaction": atom,
"workForFaction": atom,
"getFactionRep": atom,
"donateToFaction": atom,
"createProgram": atom,
"commitCrime": atom,
"getCrimeChance": atom,
"getOwnedAugmentations": atom,
"getOwnedSourceFiles": atom,
"getAugmentationsFromFaction": atom,
"getAugmentationPrereq": atom,
"getAugmentationCost": atom,
"purchaseAugmentation": atom,
"installAugmentations": atom,
// Netscript TIX API
"getStockPrice": atom,
"getStockAskPrice": atom,
"getStockBidPrice": atom,
"getStockPosition": atom,
"getStockSymbols": atom,
"getStockMaxShares": atom,
"getStockPurchaseCost": atom,
"getStockSaleGain": atom,
"buyStock": atom,
"sellStock": atom,
"shortStock": atom,
"sellShort": atom,
"placeOrder": atom,
"cancelOrder": atom,
"getOrders": atom,
"getStockVolatility": atom,
"getStockForecast": atom,
"purchase4SMarketData": atom,
"purchase4SMarketDataTixApi": atom,
// Netscript Hacknet Node API
"hacknet": atom,
"numNodes": atom,
"purchaseNode": atom,
"getPurchaseNodeCost": atom,
"getNodeStats": atom,
"upgradeLevel": atom,
"upgradeRam": atom,
"upgradeCore": atom,
"upgradeCache": atom,
"getLevelUpgradeCost": atom,
"getRamUpgradeCost": atom,
"getCoreUpgradeCost": atom,
"getCacheUpgradeCost": atom,
// Netscript Gang API
"gang": atom,
"getMemberNames": atom,
"getGangInformation": atom,
"getMemberInformation": atom,
"canRecruitMember": atom,
"recruitMember": atom,
"getTaskNames": atom,
"setMemberTask": atom,
"getEquipmentNames": atom,
"getEquipmentCost": atom,
"getEquipmentType": atom,
"purchaseEquipment": atom,
"ascendMember": atom,
"setTerritoryWarfare": atom,
"getChanceToWinClash": atom,
"getBonusTime": atom,
// Netscript Bladeburner API
"bladeburner": atom,
"getContractNames": atom,
"getOperationNames": atom,
"getBlackOpNames": atom,
"getGeneralActionNames": atom,
"getSkillNames": atom,
"startAction": atom,
"stopBladeburnerAction": atom,
"getCurrentAction": atom,
"getActionTime": atom,
"getActionEstimatedSuccessChance": atom,
"getActionCountRemaining": atom,
"getActionMaxLevel": atom,
"getActionCurrentLevel": atom,
"getActionAutolevel": atom,
"getActionRepGain": atom,
"setActionAutolevel": atom,
"setActionLevel": atom,
"getRank": atom,
"getBlackOpRank": atom,
"getSkillPoints": atom,
"getSkillLevel": atom,
"getSkillUpgradeCost": atom,
"upgradeSkill": atom,
"getTeamSize": atom,
"getCity": atom,
"setTeamSize": atom,
"getCityEstimatedPopulation": atom,
"getCityEstimatedCommunities": atom,
"getCityChaos": atom,
"switchCity": atom,
"getStamina": atom,
"joinBladeburnerFaction": atom,
// Repeat of above "getBonusTime": atom,
// Netscript Coding Contract API
"codingcontract": atom,
"attempt": atom,
"getContractType": atom,
"getData": atom,
"getDescription": atom,
"getNumTriesRemaining": atom,
// Sleeve API
"sleeve": atom,
"getNumSleeves": atom,
"setToShockRecovery": atom,
"setToSynchronize": atom,
"setToCommitCrime": atom,
"setToUniversityCourse": atom,
"travel": atom,
"setToCompanyWork": atom,
"setToFactionWork": atom,
"setToGymWorkout": atom,
"getSleeveStats": atom,
"getTask": atom,
"getInformation": atom,
"getSleeveAugmentations": atom,
"getSleevePurchasableAugs": atom,
"purchaseSleeveAug": atom,
};
function push(obj) {
for(const key of Object.keys(obj)) {
if(typeof obj[key] === 'function') ret[key] = atom;
if(typeof obj[key] === 'object') push(obj[key]);
}
}
push(NetscriptFunctions(null));
return ret;
}());
var isOperatorChar = /[+\-*&%=<>!?|~^@]/;

@ -1702,10 +1702,14 @@ let Terminal = {
}
// Display all programs and scripts
let allFiles = [];
let folders = [];
const allPrograms = [];
const allScripts = [];
const allTextFiles = [];
const allContracts = [];
const allMessages = [];
const folders = [];
function handleFn(fn) {
function handleFn(fn, dest) {
let parsedFn = fn;
if (prefix) {
if (!fn.startsWith(prefix)) {
@ -1734,29 +1738,53 @@ let Terminal = {
return;
}
allFiles.push(parsedFn);
dest.push(parsedFn);
}
// Get all of the programs and scripts on the machine into one temporary array
const s = Player.getCurrentServer();
for (const program of s.programs) handleFn(program);
for (const script of s.scripts) handleFn(script.filename);
for (const txt of s.textFiles) handleFn(txt.fn);
for (const contract of s.contracts) handleFn(contract.fn);
for (const msgOrLit of s.messages) (msgOrLit instanceof Message) ? handleFn(msgOrLit.filename) : handleFn(msgOrLit);
for (const program of s.programs) handleFn(program, allPrograms);
for (const script of s.scripts) handleFn(script.filename, allScripts);
for (const txt of s.textFiles) handleFn(txt.fn, allTextFiles);
for (const contract of s.contracts) handleFn(contract.fn, allContracts);
for (const msgOrLit of s.messages) (msgOrLit instanceof Message) ? handleFn(msgOrLit.filename, allMessages) : handleFn(msgOrLit, allMessages);
// Sort the files/folders alphabetically then print each
allFiles.sort();
allPrograms.sort();
allScripts.sort();
allTextFiles.sort();
allContracts.sort();
allMessages.sort();
folders.sort();
const config = { color: "#0000FF" };
for (const dir of folders) {
postContent(dir, config);
function postSegments(segments, config) {
const maxLength = Math.max(...segments.map(s => s.length))+1;
const filesPerRow = Math.floor(80 / maxLength);
for(let i = 0; i < segments.length; i++) {
let row = '';
for(let col = 0; col < filesPerRow; col++) {
if(!(i < segments.length)) break;
row += segments[i];
row += " ".repeat((maxLength * (col+1)) - row.length);
i++
}
postContent(row, config);
}
}
for (const file of allFiles) {
postContent(file);
}
const config = { color: "#0000FF" };
postSegments(folders, config);
postElement(<br />);
postSegments(allMessages);
postElement(<br />);
postSegments(allTextFiles);
postElement(<br />);
postSegments(allPrograms);
postElement(<br />);
postSegments(allContracts);
postElement(<br />);
postSegments(allScripts);
},
executeMemCommand: function(commandArray) {

@ -643,12 +643,6 @@ const Engine = {
clickListener: (e) => {
if (!e.isTrusted) { return false; }
joinFaction(Factions[factionName]);
for (var i = 0; i < Player.factionInvitations.length; ++i) {
if (Player.factionInvitations[i] == factionName || Factions[Player.factionInvitations[i]].isBanned) {
Player.factionInvitations.splice(i, 1);
i--;
}
}
Engine.displayFactionsInfo();
return false;
},

@ -108,6 +108,18 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
</>
}
function BladeburnerMults(): React.ReactElement {
if(!p.canAccessBladeburner()) return (<></>);
return (<>
<MultiplierTable rows={[
['Bladeburner Success Chance', p.bladeburner_max_stamina_mult],
['Bladeburner Max Stamina', p.bladeburner_stamina_gain_mult],
['Bladeburner Stamina Gain', p.bladeburner_analysis_mult],
['Bladeburner Field Analysis', p.bladeburner_success_chance_mult],
]} /><br />
</>);
}
function CurrentBitNode(): React.ReactElement {
if(p.sourceFiles.length > 0) {
@ -233,7 +245,9 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
<MultiplierTable rows={[
['Crime success', p.crime_success_mult],
['Crime money', p.crime_money_mult, p.crime_money_mult*BitNodeMultipliers.CrimeMoney],
]} /><br /><br />
]} /><br />
<BladeburnerMults /><br />
<b>Misc.</b><br /><br />
<span>{`Servers owned: ${p.purchasedServers.length} / ${getPurchaseServerLimit()}`}</span><br />

@ -138,6 +138,22 @@ class NumeralFormatter {
formatThreads(n: number): string {
return this.format(n, "0,0");
}
parseMoney(s: string): number {
// numeral library does not handle formats like 1e10 well (returns 110),
// so if both return a valid number, return the biggest one
const numeralValue = numeral(s).value();
const parsed = parseFloat(s);
if (isNaN(parsed) && numeralValue === null) {
return NaN;
} else if (isNaN(parsed)) {
return numeralValue;
} else if (numeralValue === null) {
return parsed;
} else {
return Math.max(numeralValue, parsed);
}
}
}
export const numeralWrapper = new NumeralFormatter();

@ -36,8 +36,6 @@ function factionInvitationBoxCreate(faction) {
var i = Player.factionInvitations.findIndex((facName)=>{return facName === faction.name});
if (i === -1) {
console.error("Could not find faction in Player.factionInvitations");
} else {
Player.factionInvitations.splice(i, 1);
}
joinFaction(faction);
factionInvitationBoxClose();

@ -1,6 +1,6 @@
import { dialogBoxCreate } from "./DialogBox";
import { clearEventListeners } from "./uiHelpers/clearEventListeners";
import { formatNumber } from "./StringHelperFunctions";
import { numeralWrapper } from "../src/ui/numeralFormat";
import { BitNodeMultipliers } from "../src/BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../src/Constants";
@ -38,12 +38,12 @@ function infiltrationBoxCreate(inst) {
Player.gainIntelligenceExp(inst.calcGainedIntelligenceExp());
const expGainText = ["You gained:",
`${formatNumber(inst.calcGainedHackingExp(), 3)} hacking exp`,
`${formatNumber(inst.calcGainedStrengthExp(), 3)} str exp`,
`${formatNumber(inst.calcGainedDefenseExp(), 3)} def exp`,
`${formatNumber(inst.calcGainedDexterityExp(), 3)} dex exp`,
`${formatNumber(inst.calcGainedAgilityExp(), 3)} agi exp`,
`${formatNumber(inst.calcGainedCharismaExp(), 3)} cha exp`].join("\n");
`${numeralWrapper.formatExp(inst.calcGainedHackingExp(), 3)} hacking exp`,
`${numeralWrapper.formatExp(inst.calcGainedStrengthExp(), 3)} str exp`,
`${numeralWrapper.formatExp(inst.calcGainedDefenseExp(), 3)} def exp`,
`${numeralWrapper.formatExp(inst.calcGainedDexterityExp(), 3)} dex exp`,
`${numeralWrapper.formatExp(inst.calcGainedAgilityExp(), 3)} agi exp`,
`${numeralWrapper.formatExp(inst.calcGainedCharismaExp(), 3)} cha exp`].join("\n");
var totalValue = 0;
for (var i = 0; i < inst.secretsStolen.length; ++i) {
@ -58,9 +58,9 @@ function infiltrationBoxCreate(inst) {
CONSTANTS.InfiltrationRepValue * BitNodeMultipliers.InfiltrationRep;
var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue * BitNodeMultipliers.InfiltrationMoney;
infiltrationSetText("You can sell the classified documents and secrets " +
"you stole from " + inst.companyName + " for <span class='money-gold'>$" +
formatNumber(moneyValue, 2) + "</span> on the black market or you can give it " +
"to a faction to gain <span class='light-yellow'>" + formatNumber(facValue, 3) + " reputation</span> with " +
"you stole from " + inst.companyName + " for <span class='money-gold'>" +
numeralWrapper.formatMoney(moneyValue) + "</span> on the black market or you can give it " +
"to a faction to gain <span class='light-yellow'>" + numeralWrapper.formatReputation(facValue) + " reputation</span> with " +
"that faction.");
var selector = document.getElementById("infiltration-faction-select");
selector.innerHTML = "";
@ -88,7 +88,7 @@ function infiltrationBoxCreate(inst) {
Player.gainMoney(moneyValue);
Player.recordMoneySource(moneyValue, "infiltration");
dialogBoxCreate("You sold the classified information you stole from " + inst.companyName +
" for <span class='money-gold'>$" + formatNumber(moneyValue, 2) + "</span> on the black market!<br><br>" +
" for <span class='money-gold'>" + numeralWrapper.formatMoney(moneyValue) + "</span> on the black market!<br><br>" +
expGainText);
infiltrationBoxClose();
return false;
@ -108,7 +108,7 @@ function infiltrationBoxCreate(inst) {
}
faction.playerReputation += facValue;
dialogBoxCreate("You gave the classified information you stole from " + inst.companyName +
" to " + facName + " and gained <span class='light-yellow'>" + formatNumber(facValue, 3) + " reputation</span> with the faction. <br><br>" +
" to " + facName + " and gained <span class='light-yellow'>" + numeralWrapper.formatReputation(facValue) + " reputation</span> with the faction. <br><br>" +
expGainText);
infiltrationBoxClose();
return false;