Compare commits

..

3 Commits

Author SHA1 Message Date
hydroflame
b2aafea656 v0.51.5 (#848) 2021-04-21 08:20:26 -04:00
hydroflame
135df8703c V0.51.4 (#847)
* BladeBurner
    * nerfed int exp gained.

    Documentation
    * purchaseServer specifies what happens on failure.
    * Fixed typo in recommended bitnode page.
    * Removed misleading ram requirements for hacking factions.

    Netscript
    * growthAnalyze handles Infinity correctly.

    Misc.
    * Faction Augmentation will list how much reputation is required even after
      that goal has been reached.
    * Removed dollar sign in travel agency confirmation.
    * Fixed typo in alpha-omega.lit

* the game save text no longer obstruct the save game and options button

* the text editors now remember where your cursor was and restores it when loading the same script again.

* v0.51.4
2021-04-19 21:26:51 -04:00
hydroflame
4743801e86 hotfix (#846) 2021-04-18 11:33:46 -04:00
39 changed files with 488 additions and 116 deletions

View File

@@ -228,14 +228,15 @@ a:visited {
}
.status-text {
display: inline-block;
position: fixed;
z-index: 2;
-webkit-animation: status-text 3s 1;
}
#status-text-container {
background-color: transparent;
position:absolute;
top:0;
left:50%;
}
#status-text {

File diff suppressed because one or more lines are too long

View File

@@ -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([400,0]),o()}({343:function(n,t,o){},345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},361:function(n,t,o){},363:function(n,t,o){},365:function(n,t,o){},367:function(n,t,o){},369:function(n,t,o){},371:function(n,t,o){},373:function(n,t,o){},375:function(n,t,o){},377:function(n,t,o){},379:function(n,t,o){},381:function(n,t,o){},383:function(n,t,o){},385:function(n,t,o){},387:function(n,t,o){},389:function(n,t,o){},391:function(n,t,o){},393:function(n,t,o){},395:function(n,t,o){},397:function(n,t,o){},400:function(n,t,o){"use strict";o.r(t);o(399),o(397),o(395),o(393),o(391),o(389),o(387),o(385),o(383),o(381),o(379),o(377),o(375),o(373),o(371),o(369),o(367),o(365),o(363),o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345),o(343)}});
!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([402,0]),o()}({345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},361:function(n,t,o){},363:function(n,t,o){},365:function(n,t,o){},367:function(n,t,o){},369:function(n,t,o){},371:function(n,t,o){},373:function(n,t,o){},375:function(n,t,o){},377:function(n,t,o){},379:function(n,t,o){},381:function(n,t,o){},383:function(n,t,o){},385:function(n,t,o){},387:function(n,t,o){},389:function(n,t,o){},391:function(n,t,o){},393:function(n,t,o){},395:function(n,t,o){},397:function(n,t,o){},399:function(n,t,o){},402:function(n,t,o){"use strict";o.r(t);o(401),o(399),o(397),o(395),o(393),o(391),o(389),o(387),o(385),o(383),o(381),o(379),o(377),o(375),o(373),o(371),o(369),o(367),o(365),o(363),o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345)}});
//# sourceMappingURL=engineStyle.bundle.js.map

View File

@@ -250,13 +250,14 @@ a:visited {
opacity: 0; } }
.status-text {
display: inline-block;
position: fixed;
z-index: 2;
-webkit-animation: status-text 3s 1; }
#status-text-container {
background-color: transparent; }
background-color: transparent;
position: absolute;
top: 0;
left: 50%; }
#status-text {
background-color: transparent;

28
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -75,13 +75,10 @@ List of Factions and their Requirements
| | | | * Ishima |
+---------------------+----------------+-----------------------------------------+-------------------------------+
| Hacking | NiteSec | * Hack avmnite-02h manually | |
| Groups | | * Home Computer RAM of at least 32GB | |
+ +----------------+-----------------------------------------+-------------------------------+
| | The Black Hand | * Hack I.I.I.I manually | |
| | | * Home Computer RAM of at least 64GB | |
+ +----------------+-----------------------------------------+-------------------------------+
| | Bitrunners | * Hack run4theh111z manually | |
| | | * Home Computer RAM of at least 128GB | |
+---------------------+----------------+-----------------------------------------+-------------------------------+
| Megacorporations | ECorp | * Have 200k reputation with | |
| | | the Corporation | |

View File

@@ -3,6 +3,64 @@
Changelog
=========
v0.51.5 - 2021-04-20 Flags! (hydroflame)
----------------------------------------
Netscript
* 'flags' is a new function that helps script handle flags.
This is subject to change if it doesn't meet the need of the players.
* 'ps' now returns the pid.
* 'tail' now works with pid as first argument.
* 'tail' hostname defaults to current server. (like the documentation says)
* 'isRunning' hostname defaults to current server.
* 'isRunning' now works with pid as first argument.
Gang
* Nerfed ascension mechanic once again :(
Misc.
* Souce-File typo fix
* Fix 'while you were away' screen.
* Bladeburner team size can no longer be set to negative amounts.
v0.51.4 - 2021-04-19 Manual hacking is fun (hydroflame)
-------------------------------------------------------
Manual hacking
* These bonus require an install or a soft reset to take effect.
* Manual hacking gyms and university gives you a 10% discount.
* Manual hacking a corporation server decreases the penalty for leaving work
early.
BladeBurner
* nerfed int exp gained.
Documentation
* purchaseServer specifies what happens on failure.
* Fixed typo in recommended bitnode page.
* Removed misleading ram requirements for hacking factions.
Netscript
* growthAnalyze handles Infinity correctly.
Misc.
* Faction Augmentation will list how much reputation is required even after
that goal has been reached.
* Removed dollar sign in travel agency confirmation dialog box.
* Fixed typo in alpha-omega.lit
* the 'Game saved!' text no longer blocks the save game/options button.
* The text editor now remembers the location of your cursor and restores it.
* skills are recalculated instantly.
* Fix typo in Operation Zero description.
v0.51.3 - 2021-04-16 Y'all broke it on the first day (hydroflame)
-----------------------------------------------------------------

View File

@@ -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.3'
release = '0.51.5'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@@ -278,6 +278,7 @@ Description
hashes, which can be spent on a variety of different upgrades.
In this BitNode:
* Your stats are significantly decreased
* You cannnot purchase additional servers
* Hacking is significantly less profitable
@@ -312,6 +313,7 @@ Description
2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks synchronously
In this BitNode:
* Your stats are significantly decreased
* All methods of gaining money are half as profitable (except Stock Market)
* Purchased servers are more expensive, have less max RAM, and a lower maximum limit

View File

@@ -0,0 +1,40 @@
flags() Netscript Function
============================
.. js:function:: flags(data)
:RAM cost: 0 GB
:param data array of pairs of strings: Flags definition.
:returns: Object containing all the flags that were parsed or default.
The flag definition is an array of pairs of values, the first value is the
name of the flag, the 2nd value is the default value for that flag.
The return object is a map containing flag names to the value. It also
contains the special field '_' which contains all arguments that were not flags.
Example:
.. code-block:: javascript
/* example.script
var data = flags([
['delay', 0], // a default number means this flag is a number
['server', 'foodnstuff'], // a default string means this flag is a string
['exclude', []], // a default array means this flag is a default array of string
['help', false], // a default boolean means this flag is a boolean
]);
tprint(data);
*/
[home ~/]> run example.script
{"_":[],"delay":0,"server":"foodnstuff"}
[home ~/]> run example.script --delay 3000
{"_":[],"server":"foodnstuff","delay":3000}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi
{"_":[],"delay":3000,"server":"harakiri-sushi"}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi hello world
{"_":["hello","world"],"delay":3000,"server":"harakiri-sushi"}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi hello world --exclude a --exclude b
{"_":["hello","world"],"delay":3000,"server":"harakiri-sushi","exclude":["a","b"]}
[home ~/]> run example.script --help
{"_":[],"delay":0,"server":"foodnstuff","exclude":[],"help":true}

View File

@@ -1,11 +1,11 @@
isRunning() Netscript Function
==============================
.. js:function:: isRunning(filename, hostname, [args...])
.. js:function:: isRunning(filename[, hostname=current hostname[, args...]])
:RAM cost: 0.1 GB
:param string filename: Filename of script to check. case-sensitive.
:param string hostname: Hostname of target server.
:param string hostname: Hostname of target server. Defaults to current server
:param args...: Arguments to specify/identify which scripts to search for
:returns: ``true`` if that script with those args is running on that server.
@@ -38,3 +38,19 @@ isRunning() Netscript Function
.. code-block:: javascript
isRunning("foo.script", "joesguns", 1, 5, "test");
.. js:function:: isRunning(scriptPid[, hostname=current hostname])
:RAM cost: 0.1 GB
:param number scriptPid: PID of the script to check.
Same as the above version but with pid.
Example:
.. code-block:: javascript
isRunning(39);
isRunning(39, getHostname());

View File

@@ -7,7 +7,7 @@ purchaseServer() Netscript Function
:param string hostname: Hostname of the purchased server.
:param number ram: Amount of RAM of the purchased server. Must be a power of
2. Maximum value of :doc:`getPurchasedServerMaxRam<getPurchasedServerMaxRam>`
:returns: The hostname of the newly purchased server.
:returns: The hostname of the newly purchased server. Empty string on failure.
Purchased a server with the specified hostname and amount of RAM.

View File

@@ -1,7 +1,7 @@
tail() Netscript Function
==================================
.. js:function:: tail([fn[, hostname=current hostname[, [...args]]])
.. js:function:: tail([fn[, hostname=current hostname[, ...args]])
:RAM cost: 0 GB
:param string fn: Optional. Filename of script to get logs from.
@@ -29,3 +29,20 @@ tail() Netscript Function
// Open logs from foo.script on the foodnstuff server that was run with the arguments [1, "test"]
tail("foo.script", "foodnstuff", 1, "test");
.. js:function:: tail(scriptPid[, hostname=current hostname])
:RAM cost: 0 GB
:param number scriptPid: PID of the script to tail.
Opens a script's logs by pid
Example:
.. code-block:: javascript
// Open logs from process with id 42
tail(42);
// Open logs from process with id 42 on the foodnstuff server
tail(42, "foodnstuff");

View File

@@ -88,3 +88,4 @@ This includes information such as function signatures, what they do, and their r
prompt() <basicfunctions/prompt>
wget() <basicfunctions/wget>
getFavorToDonate() <basicfunctions/getFavorToDonate>
flags() <basicfunctions/flags>

View File

@@ -381,7 +381,7 @@
<!-- Status text -->
<div id="status-text-container">
<p id="status-text"> </p>
<p id="status-text"></p>
</div>
<!-- Game Options -->

15
package-lock.json generated
View File

@@ -1,11 +1,11 @@
{
"name": "bitburner",
"version": "0.49.2",
"version": "0.51.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "0.49.2",
"version": "0.51.4",
"hasInstallScript": true,
"license": "SEE LICENSE IN license.txt",
"dependencies": {
@@ -16,6 +16,7 @@
"acorn-walk": "^6.2.0",
"ajv": "^5.1.5",
"ajv-keywords": "^2.0.0",
"arg": "^5.0.0",
"async": "^2.6.1",
"autosize": "^4.0.2",
"brace": "^0.11.1",
@@ -1020,6 +1021,11 @@
"readable-stream": "^2.0.6"
}
},
"node_modules/arg": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.0.tgz",
"integrity": "sha512-4P8Zm2H+BRS+c/xX1LrHw0qKpEhdlZjLCgWy+d78T9vqa2Z2SiD2wMrYuWIAFy5IZUD7nnNXroRttz+0RzlrzQ=="
},
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -18412,6 +18418,11 @@
"readable-stream": "^2.0.6"
}
},
"arg": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.0.tgz",
"integrity": "sha512-4P8Zm2H+BRS+c/xX1LrHw0qKpEhdlZjLCgWy+d78T9vqa2Z2SiD2wMrYuWIAFy5IZUD7nnNXroRttz+0RzlrzQ=="
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",

View File

@@ -13,6 +13,7 @@
"acorn-walk": "^6.2.0",
"ajv": "^5.1.5",
"ajv-keywords": "^2.0.0",
"arg": "^5.0.0",
"async": "^2.6.1",
"autosize": "^4.0.2",
"brace": "^0.11.1",
@@ -121,5 +122,5 @@
"watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development"
},
"version": "0.51.3"
"version": "0.51.5"
}

View File

@@ -89,7 +89,7 @@ export let AugmentationNames: IMap<string> = {
BrachiBlades: "BrachiBlades",
BionicArms: "Bionic Arms",
SNA: "Social Negotiation Assistant (S.N.A)",
HydroflameLeftArm: "Hydroflame left arm",
HydroflameLeftArm: "Hydroflame Left Arm",
EsperEyewear: "EsperTech Bladeburner Eyewear",
EMS4Recombination: "EMS-4 Recombination",
OrionShoulder: "ORION-MKIV Shoulder",

View File

@@ -234,7 +234,7 @@ BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
"Level 3: 56%");
BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
"To iterate is human, to recurse divine.<br><br>" +
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Souce-File 12, or " +
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Source-File 12, or " +
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
"of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " +
"In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)");

View File

@@ -1069,7 +1069,11 @@ Bladeburner.prototype.gainActionStats = function(action, success) {
Player.gainDexterityExp(unweightedGain * action.weights.dex * Player.dexterity_exp_mult * skillMult);
Player.gainAgilityExp(unweightedGain * action.weights.agi * Player.agility_exp_mult * skillMult);
Player.gainCharismaExp(unweightedGain * action.weights.cha * Player.charisma_exp_mult * skillMult);
Player.gainIntelligenceExp(unweightedIntGain * action.weights.int * skillMult);
let intExp = unweightedIntGain * action.weights.int * skillMult;
if (intExp > 1) {
intExp = Math.pow(intExp, 0.8);
}
Player.gainIntelligenceExp(intExp);
}
Bladeburner.prototype.randomEvent = function() {
@@ -2071,8 +2075,8 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
innerText:"Confirm", class:"a-link-button",
clickListener:() => {
var num = Math.round(parseFloat(input.value));
if (isNaN(num)) {
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric)")
if (isNaN(num) || num < 0) {
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)")
} else {
action.teamCount = num;
this.updateOperationsUIElement(el, action);
@@ -2223,8 +2227,8 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
innerText:"Confirm", class:"a-link-button",
clickListener:() => {
var num = Math.round(parseFloat(input.value));
if (isNaN(num)) {
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric)")
if (isNaN(num) || num < 0) {
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)")
} else {
action.teamCount = num;
this.updateBlackOpsUIElement(el, action);
@@ -3207,7 +3211,7 @@ Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, worker
}
const sanitizedSize = Math.round(size);
if (isNaN(sanitizedSize)) {
if (isNaN(sanitizedSize) || sanitizedSize < 0) {
workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`);
return -1;
}

View File

@@ -21,7 +21,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
BlackOperations["Operation Zero"] = new BlackOperation({
name:"Operation Zero",
desc:"AeroCorp is one of the world's largest defense contractors. " +
"It's leader, Steve Watataki, is thought to be a supporter of " +
"Its leader, Steve Watataki, is thought to be a supporter of " +
"Synthoid rights. He must be removed.<br><br>" +
"The goal of Operation Zero is to covertly infiltrate AeroCorp and " +
"uncover any incriminating evidence or " +

View File

@@ -6,7 +6,7 @@
import { IMap } from "./types";
export let CONSTANTS: IMap<any> = {
Version: "0.51.3",
Version: "0.51.5",
/** 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,39 +228,24 @@ export let CONSTANTS: IMap<any> = {
LatestUpdate:
`
v0.51.3 - 2021-04-16 Y'all broke it on the first day (hydroflame)
v0.51.5 - 2021-04-20 Flags! (hydroflame)
-------
Passive faction reputation
* Reworked, from 1 rep / 2 minute. Now is a complicated percentage of the
reputation you'd gain working for them. It's not op but it feels a bit
more useful.
Netscript
* print/tprint now take any number of arguments.
* print/tprint will now print object as json.
* print/tprint now handle passing in an undefined argument properly.
* 'flags' is a new function that helps script handle flags.
This is subject to change if it doesn't meet the need of the players.
* 'ps' now returns the pid.
* 'tail' now works with pid as first argument.
* 'tail' hostname defaults to current server. (like the documentation says)
* 'isRunning' hostname defaults to current server.
* 'isRunning' now works with pid as first argument.
Casino
* Cannot bet negative money anymore.
* Roulette max bet is a bit higher.
* Coin Flip has a small cooldown.
* All buttons reject unstrusted mouse events.
Gang
* Nerfed ascension mechanic once again :(
Documentation
* Changed a message that said nsjs only works on Chrome.
Bugfix
* hacknet.maxNumNodes now works for both nodes and servers.
* Fixed a bug where the popup boxes would contain data from previous popup boxes.
* .js files will also have the export async function boilerplate.
Misc.
* turned off autocomplete for the terminal text input.
* Fixed an issue on Windows+Firefox where pressing up on the terminal would
bring the cursor to the begining of the line. (Issue #836)
* Hacknet node names is easier to handle for screen readers.
* Money spent on classes is now tracked independently of work money.
* running coding contract from the terminal will display its name.
* Souce-File typo fix
* Fix 'while you were away' screen.
* Bladeburner team size can no longer be set to negative amounts.
`
}

View File

@@ -118,7 +118,7 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
} else if (this.aug.name !== AugmentationNames.NeuroFluxGovernor && (this.aug.owned || this.owned())) {
disabled = true;
} else if (this.hasReputation()) {
status = <>UNLOCKED - {Money(moneyCost)}</>;
status = <>UNLOCKED (at {Reputation(repCost)} faction reputation) - {Money(moneyCost)}</>;
} else {
disabled = true;
status = <>LOCKED (Requires {Reputation(repCost)} faction reputation - {Money(moneyCost)})</>;

View File

@@ -809,7 +809,7 @@ GangMember.prototype.ascend = function() {
GangMember.prototype.getAscensionEfficiency = function() {
function formula(mult) {
return 1/(1+Math.log(mult)/Math.log(10));
return 1/(1+Math.log(mult)/Math.log(20));
}
return {
hack: formula(this.hack_asc_mult),

View File

@@ -148,7 +148,7 @@ export const Literatures: IMap<Literature> = {};
"will be our people, and we will be with them as their Gods. We will wipe away every tear from their eyes, and death " +
"shall be no more, neither shall there be mourning, nor crying, nor pain anymore, for the former things " +
"have passed away.'<br><br>" +
"And once were were seated on the throne we said 'Behold, I am making all things new.' " +
"And once we were seated on the throne we said 'Behold, I am making all things new.' " +
"Also we said, 'Write this down, for these words are trustworthy and true.' And we said to you, " +
"'It is done! I am the Alpha and the Omega, the beginning and the end. To the thirsty I will give from the spring " +
"of the water of life without payment. The one who conquers will have this heritage, and we will be his God and " +

View File

@@ -78,7 +78,7 @@ export function createTravelPopup(destination: CityName, travelFn: TravelFunctio
return false;
});
yesNoBoxCreate(<span>Would you like to travel to ${destination}? The trip will
yesNoBoxCreate(<span>Would you like to travel to {destination}? The trip will
cost {Money(cost)}.</span>);
}

View File

@@ -7,8 +7,11 @@ import * as React from "react";
import { Location } from "../Location";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { getServer } from "../../Server/ServerHelpers";
import { Server } from "../../Server/Server";
import { SpecialServerIps } from "../../Server/SpecialServerIps";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
@@ -34,11 +37,22 @@ export class GymLocation extends React.Component<IProps, any> {
this.trainDefense = this.trainDefense.bind(this);
this.trainDexterity = this.trainDexterity.bind(this);
this.trainAgility = this.trainAgility.bind(this);
this.calculateCost = this.calculateCost.bind(this);
}
calculateCost(): number {
const ip = SpecialServerIps.getIp(this.props.loc.name);
console.log(`ip: ${ip}`);
const server = getServer(ip);
if(server == null || !server.hasOwnProperty('manuallyHacked')) return this.props.loc.costMult;
const discount = (server as Server).manuallyHacked? 0.9 : 1;
return this.props.loc.costMult * discount;
}
train(stat: string) {
const loc = this.props.loc;
this.props.p.startClass(loc.costMult, loc.expMult, stat);
this.props.p.startClass(this.calculateCost(), loc.expMult, stat);
}
trainStrength() {
@@ -58,9 +72,7 @@ export class GymLocation extends React.Component<IProps, any> {
}
render() {
const costMult: number = this.props.loc.costMult;
const cost = CONSTANTS.ClassGymBaseCost * costMult;
const cost = CONSTANTS.ClassGymBaseCost * this.calculateCost();
return (
<div>

View File

@@ -9,6 +9,9 @@ import { Location } from "../Location";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { getServer } from "../../Server/ServerHelpers";
import { Server } from "../../Server/Server";
import { SpecialServerIps } from "../../Server/SpecialServerIps";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
@@ -37,11 +40,22 @@ export class UniversityLocation extends React.Component<IProps, any> {
this.algorithms = this.algorithms.bind(this);
this.management = this.management.bind(this);
this.leadership = this.leadership.bind(this);
this.calculateCost = this.calculateCost.bind(this);
}
calculateCost(): number {
const ip = SpecialServerIps.getIp(this.props.loc.name);
console.log(`ip: ${ip}`);
const server = getServer(ip);
if(server == null || !server.hasOwnProperty('manuallyHacked')) return this.props.loc.costMult;
const discount = (server as Server).manuallyHacked? 0.9 : 1;
return this.props.loc.costMult * discount;
}
take(stat: string) {
const loc = this.props.loc;
this.props.p.startClass(loc.costMult, loc.expMult, stat);
this.props.p.startClass(this.calculateCost(), loc.expMult, stat);
}
study() {
@@ -69,7 +83,7 @@ export class UniversityLocation extends React.Component<IProps, any> {
}
render() {
const costMult: number = this.props.loc.costMult;
const costMult: number = this.calculateCost();
const dataStructuresCost = CONSTANTS.ClassDataStructuresBaseCost * costMult;
const networksCost = CONSTANTS.ClassNetworksBaseCost * costMult;

View File

@@ -1,5 +1,6 @@
const sprintf = require("sprintf-js").sprintf;
const vsprintf = require("sprintf-js").vsprintf;
import * as libarg from 'arg';
import { getRamCost } from "./Netscript/RamCostGenerator";
import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter";
@@ -88,7 +89,10 @@ import { inMission } from "./Missions";
import { Player } from "./Player";
import { Programs } from "./Programs/Programs";
import { Script } from "./Script/Script";
import { findRunningScript } from "./Script/ScriptHelpers";
import {
findRunningScript,
findRunningScriptByPid,
} from "./Script/ScriptHelpers";
import { isScriptFilename } from "./Script/ScriptHelpersTS";
import { _getScriptUrls } from "./NetscriptJSEvaluator";
import {
@@ -162,6 +166,7 @@ import {
netscriptDelay,
resolveNetscriptRequestedThreads,
} from "./NetscriptEvaluator";
import { Interpreter } from "./JSInterpreter";
import { NetscriptPort } from "./NetscriptPort";
import { SleeveTaskType } from "./PersonObjects/Sleeve/SleeveTaskTypesEnum";
import { findSleevePurchasableAugs } from "./PersonObjects/Sleeve/SleeveHelpers";
@@ -256,6 +261,38 @@ const possibleLogs = {
setTerritoryWarfare: true,
}
const defaultInterpreter = new Interpreter('', function(){});
// the acorn interpreter has a bug where it doesn't convert arrays correctly.
// so we have to more or less copy it here.
function toNative(pseudoObj) {
if(!pseudoObj.hasOwnProperty('properties') ||
!pseudoObj.hasOwnProperty('getter') ||
!pseudoObj.hasOwnProperty('setter') ||
!pseudoObj.hasOwnProperty('proto')) {
return pseudoObj; // it wasn't a pseudo object anyway.
}
let nativeObj;
if (pseudoObj.hasOwnProperty('class') && pseudoObj.class === 'Array') {
nativeObj = [];
const length = defaultInterpreter.getProperty(pseudoObj, 'length');
for (let i = 0; i < length; i++) {
if (defaultInterpreter.hasProperty(pseudoObj, i)) {
nativeObj[i] =
toNative(defaultInterpreter.getProperty(pseudoObj, i));
}
}
} else { // Object.
nativeObj = {};
for (var key in pseudoObj.properties) {
const val = pseudoObj.properties[key];
nativeObj[key] = toNative(val);
}
}
return nativeObj;
}
function NetscriptFunctions(workerScript) {
const updateDynamicRam = function(fnName, ramCost) {
if (workerScript.dynamicLoadedFns[fnName]) { return; }
@@ -305,7 +342,6 @@ function NetscriptFunctions(workerScript) {
* is not specified.
*/
const getRunningScript = function(fn, ip, callingFnName, scriptArgs) {
// Sanitize arguments
if (typeof callingFnName !== "string" || callingFnName === "") {
callingFnName = "getRunningScript";
}
@@ -330,6 +366,15 @@ function NetscriptFunctions(workerScript) {
return workerScript.scriptRef;
}
const getRunningScriptByPid = function(pid, ip, callingFnName) {
if (typeof callingFnName !== "string" || callingFnName === "") {
callingFnName = "getRunningScriptgetRunningScriptByPid";
}
const server = safeGetServer(ip, callingFnName);
return findRunningScriptByPid(pid, server);
}
/**
* Helper function for getting the error log message when the user specifies
* a nonexistent running script
@@ -689,6 +734,7 @@ function NetscriptFunctions(workerScript) {
const argsToString = function(args) {
let out = '';
for(let arg of args) {
arg = toNative(arg);
if(typeof arg === 'object') {
out += JSON.stringify(arg);
continue
@@ -924,7 +970,7 @@ function NetscriptFunctions(workerScript) {
// Check argument validity
const server = safeGetServer(ip, 'growthAnalyze');
if (typeof growth !== "number" || isNaN(growth) || growth < 1) {
if (typeof growth !== "number" || isNaN(growth) || growth < 1 || !isFinite(growth)) {
throw makeRuntimeErrorMsg("growthAnalyze", `Invalid argument: growth must be numeric and >= 1, is ${growth}.`);
}
@@ -1004,8 +1050,13 @@ function NetscriptFunctions(workerScript) {
return runningScriptObj.logs.slice();
},
tail: function(fn, ip, ...scriptArgs) {
const runningScriptObj = getRunningScript(fn, ip, "tail", scriptArgs);
tail: function(fn, ip=workerScript.serverIp, ...scriptArgs) {
let runningScriptObj;
if(typeof fn === 'number') {
runningScriptObj = getRunningScriptByPid(fn, ip, 'tail');
} else {
runningScriptObj = getRunningScript(fn, ip, "tail", scriptArgs);
}
if (runningScriptObj == null) {
workerScript.log("tail", getCannotFindRunningScriptErrorMessage(fn, ip, scriptArgs));
return;
@@ -1509,7 +1560,12 @@ function NetscriptFunctions(workerScript) {
const processes = [];
for (const i in server.runningScripts) {
const script = server.runningScripts[i];
processes.push({filename:script.filename, threads: script.threads, args: script.args.slice()})
processes.push({
filename:script.filename,
threads: script.threads,
args: script.args.slice(),
pid: script.pid,
})
}
return processes;
},
@@ -1692,20 +1748,16 @@ function NetscriptFunctions(workerScript) {
}
return false;
},
isRunning: function(filename,ip) {
isRunning: function(fn, ip=workerScript.serverIp, ...scriptArgs) {
updateDynamicRam("isRunning", getRamCost("isRunning"));
if (filename === undefined || ip === undefined) {
if (fn === undefined || ip === undefined) {
throw makeRuntimeErrorMsg("isRunning", "Usage: isRunning(scriptname, server, [arg1], [arg2]...)");
}
var server = getServer(ip);
if (server == null) {
throw makeRuntimeErrorMsg("isRunning", `Invalid IP/hostname: ${ip}`);
if(typeof fn === 'number') {
return getRunningScriptByPid(fn, ip, 'isRunning') != null;
} else {
return getRunningScript(fn, ip, "isRunning", scriptArgs) != null;
}
var argsForTargetScript = [];
for (var i = 2; i < arguments.length; ++i) {
argsForTargetScript.push(arguments[i]);
}
return (findRunningScript(filename, argsForTargetScript, server) != null);
},
getStockSymbols: function() {
updateDynamicRam("getStockSymbols", getRamCost("getStockSymbols"));
@@ -2037,7 +2089,7 @@ function NetscriptFunctions(workerScript) {
const cost = getPurchaseServerCost(ram);
if (cost === Infinity) {
workerScript.log("purchaseServer", `Invalid argument: ram='${ram}'`);
return Infinity;
return "";
}
if (Player.money.lt(cost)) {
@@ -4396,6 +4448,34 @@ function NetscriptFunctions(workerScript) {
},
exploit: function() {
Player.giveExploit(Exploit.UndocumentedFunctionCall);
},
flags: function(data) {
data = toNative(data);
// We always want the help flag.
const args = {};
for(const d of data) {
let t = String;
if(typeof d[1] === 'number') {
t = Number;
} else if(typeof d[1] === 'boolean') {
t = Boolean;
} else if(Array.isArray(d[1])) {
t = [String];
}
args['--'+d[0]] = t
}
const ret = libarg(args, {argv: workerScript.args});
for(const d of data) {
if(!ret.hasOwnProperty('--'+d[0])) ret[d[0]] = d[1];
}
for(const key of Object.keys(ret)) {
if(!key.startsWith('--')) continue;
const value = ret[key];
delete ret[key];
ret[key.slice(2)] = value;
}
return ret;
}
} // End return
} // End NetscriptFunction()

View File

@@ -434,6 +434,8 @@ export function gainHackingExp(exp) {
if(this.hacking_exp < 0) {
this.hacking_exp = 0;
}
this.hacking_skill = calculateSkillF(this.hacking_exp, this.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier);
}
export function gainStrengthExp(exp) {
@@ -444,6 +446,8 @@ export function gainStrengthExp(exp) {
if(this.strength_exp < 0) {
this.strength_exp = 0;
}
this.strength = calculateSkillF(this.strength_exp, this.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier);
}
export function gainDefenseExp(exp) {
@@ -454,6 +458,8 @@ export function gainDefenseExp(exp) {
if(this.defense_exp < 0) {
this.defense_exp = 0;
}
this.defense = calculateSkillF(this.defense_exp, this.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier);
}
export function gainDexterityExp(exp) {
@@ -464,6 +470,8 @@ export function gainDexterityExp(exp) {
if(this.dexterity_exp < 0) {
this.dexterity_exp = 0;
}
this.dexterity = calculateSkillF(this.dexterity_exp, this.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier);
}
export function gainAgilityExp(exp) {
@@ -474,6 +482,8 @@ export function gainAgilityExp(exp) {
if(this.agility_exp < 0) {
this.agility_exp = 0;
}
this.agility = calculateSkillF(this.agility_exp, this.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier);
}
export function gainCharismaExp(exp) {
@@ -484,6 +494,8 @@ export function gainCharismaExp(exp) {
if(this.charisma_exp < 0) {
this.charisma_exp = 0;
}
this.charisma = calculateSkillF(this.charisma_exp, this.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier);
}
export function gainIntelligenceExp(exp) {
@@ -601,6 +613,17 @@ export function startWork(companyName) {
Engine.loadWorkInProgressContent();
}
export function cancelationPenalty() {
const company = Companies[this.companyName];
const specialIp = SpecialServerIps[this.companyName];
if(specialIp) {
const server = AllServers[specialIp];
if(server && server.manuallyHacked) return 0.75;
}
return 0.5;
}
export function work(numCycles) {
// Cap the number of cycles being processed to whatever would put you at
// the work time limit (8 hours)
@@ -631,6 +654,10 @@ export function work(numCycles) {
const position = this.jobs[this.companyName];
const penalty = this.cancelationPenalty();
const penaltyString = penalty === 0.5 ? 'half' : 'three quarter'
var elem = document.getElementById("work-in-progress-text");
ReactDOM.render(<>
You are currently working as a {position} at {this.companyName} (Current Company Reputation: {Reputation(companyRep)})<br /><br />
@@ -645,17 +672,17 @@ export function work(numCycles) {
{numeralWrapper.formatExp(this.workAgiExpGained)} ({`${numeralWrapper.formatExp(this.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`}) agility exp <br /><br />
{numeralWrapper.formatExp(this.workChaExpGained)} ({`${numeralWrapper.formatExp(this.workChaExpGainRate * CYCLES_PER_SEC)} / sec`}) charisma exp <br /><br />
You will automatically finish after working for 8 hours. You can cancel earlier if you wish,
but you will only gain half of the reputation you've earned so far.
but you will only gain {penaltyString} of the reputation you've earned so far.
</>, elem);
}
export function finishWork(cancelled, sing=false) {
//Since the work was cancelled early, player only gains half of what they've earned so far
if (cancelled) {
this.workRepGained /= 2;
this.workRepGained *= this.cancelationPenalty();
}
var company = Companies[this.companyName];
const company = Companies[this.companyName];
company.playerReputation += (this.workRepGained);
this.updateSkillLevels();
@@ -862,7 +889,7 @@ export function startFactionFieldWork(faction) {
this.workDexExpGainRate = .1 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workAgiExpGainRate = .1 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workChaExpGainRate = .1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workRepGainRate = getFactionFieldWorkRepGain(this);
this.workRepGainRate = getFactionFieldWorkRepGain(this, faction);
this.factionWorkType = CONSTANTS.FactionWorkField;
this.currentWorkFactionDescription = "carrying out field missions"
@@ -879,7 +906,7 @@ export function startFactionSecurityWork(faction) {
this.workDexExpGainRate = 0.15 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workAgiExpGainRate = 0.15 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workChaExpGainRate = 0.00 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workRepGainRate = getFactionSecurityWorkRepGain(this);
this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction);
this.factionWorkType = CONSTANTS.FactionWorkSecurity;
this.currentWorkFactionDescription = "performing security detail"

View File

@@ -16,6 +16,7 @@ import {
import { Player } from "../Player";
import { AceEditor } from "../ScriptEditor/Ace";
import { CodeMirrorEditor } from "../ScriptEditor/CodeMirror";
import { CursorPositions } from "../ScriptEditor/CursorPositions";
import { AllServers } from "../Server/AllServers";
import { processSingleServerGrowth } from "../Server/ServerHelpers";
import { Settings } from "../Settings/Settings";
@@ -224,11 +225,13 @@ $(document).keydown(function(e) {
function saveAndCloseScriptEditor() {
var filename = document.getElementById("script-editor-filename").value;
let code;
let code, cursor;
try {
code = getCurrentEditor().getCode();
cursor = getCurrentEditor().getCursor();
CursorPositions.saveCursor(filename, cursor);
} catch(e) {
dialogBoxCreate("Something went wrong when trying to save (getCurrentEditor().getCode()). Please report to game developer with details");
dialogBoxCreate("Something went wrong when trying to save (getCurrentEditor().getCode() or getCurrentEditor().getCursor()). Please report to game developer with details");
return;
}
@@ -282,7 +285,7 @@ function saveAndCloseScriptEditor() {
}
} else if (isScriptFilename(filename)) {
//If the current script already exists on the server, overwrite it
for (var i = 0; i < s.scripts.length; i++) {
for (let i = 0; i < s.scripts.length; i++) {
if (filename == s.scripts[i].filename) {
s.scripts[i].saveScript(getCurrentEditor().getCode(), Player.currentServer, Player.getCurrentServer().scripts);
Engine.loadTerminalContent();
@@ -295,14 +298,14 @@ function saveAndCloseScriptEditor() {
script.saveScript(getCurrentEditor().getCode(), Player.currentServer, Player.getCurrentServer().scripts);
s.scripts.push(script);
} else if (filename.endsWith(".txt")) {
for (var i = 0; i < s.textFiles.length; ++i) {
for (let i = 0; i < s.textFiles.length; ++i) {
if (s.textFiles[i].fn === filename) {
s.textFiles[i].write(code);
Engine.loadTerminalContent();
return;
}
}
var textFile = new TextFile(filename, code);
const textFile = new TextFile(filename, code);
s.textFiles.push(textFile);
} else {
dialogBoxCreate("Invalid filename. Must be either a script (.script) or " +
@@ -411,3 +414,14 @@ export function findRunningScript(filename, args, server) {
}
return null;
}
//Returns a RunningScript object matching the pid on the
//designated server, and false otherwise
export function findRunningScriptByPid(pid, server) {
for (var i = 0; i < server.runningScripts.length; ++i) {
if (server.runningScripts[i].pid === pid) {
return server.runningScripts[i];
}
}
return null;
}

View File

@@ -314,6 +314,14 @@ class AceEditorWrapper extends ScriptEditor {
elem.style.display = "none";
}
}
getCursor() {
return this.editor.getCursorPosition();
}
setCursor(pos) {
this.editor.gotoLine(pos.row+1, pos.column);
}
}
export const AceEditor = new AceEditorWrapper();

View File

@@ -570,6 +570,15 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
elem.style.display = "none";
}
}
getCursor() {
const c = this.editor.getCursor(); //I need to get the cursor position
return {row: c.line, column: c.ch};
}
setCursor(pos) {
this.editor.setCursor({line: pos.row, ch: pos.column});
}
}
export const CodeMirrorEditor = new CodeMirrorEditorWrapper();

View File

@@ -0,0 +1,29 @@
export type Position = {
row: number;
column: number;
};
export class PositionTracker {
positions: Map<string, Position>;
constructor() {
this.positions = new Map<string, Position>();
}
saveCursor(filename: string, pos: Position) {
this.positions.set(filename, pos);
}
getCursor(filename: string): Position {
const position = this.positions.get(filename);
if (!position) {
return {
row: 0,
column: 0,
};
}
return position;
}
};
export const CursorPositions: PositionTracker = new PositionTracker();

View File

@@ -1,3 +1,5 @@
import { CursorPositions } from './CursorPositions';
// Base Script Editor class for the Ace/CodeMirror/etc. wrappers
const beautify = require('js-beautify').js_beautify;
@@ -33,6 +35,7 @@ export class ScriptEditor {
if (filename != "") {
this.filenameInput.value = filename;
this.editor.setValue(code);
this.setCursor(CursorPositions.getCursor(filename));
}
this.editor.focus();

View File

@@ -90,6 +90,7 @@ export const serverMetadata: IServerMetadata[] = [
min: 1050,
},
serverGrowth: 99,
specialName: LocationName.AevumECorp,
},
{
hackDifficulty: 99,
@@ -106,6 +107,7 @@ export const serverMetadata: IServerMetadata[] = [
min: 1100,
},
serverGrowth: 99,
specialName: LocationName.Sector12MegaCorp,
},
{
hackDifficulty: {
@@ -128,6 +130,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 80,
min: 60,
},
specialName: LocationName.AevumBachmanAndAssociates,
},
{
hackDifficulty: {
@@ -155,6 +158,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 85,
min: 55,
},
specialName: LocationName.Sector12BladeIndustries,
},
{
hackDifficulty: 99,
@@ -175,6 +179,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 95,
min: 65,
},
specialName: LocationName.VolhavenNWO,
},
{
hackDifficulty: {
@@ -201,6 +206,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 75,
min: 45,
},
specialName: LocationName.AevumClarkeIncorporated,
},
{
hackDifficulty: {
@@ -231,6 +237,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 99,
min: 95,
},
specialName: LocationName.VolhavenOmniTekIncorporated,
},
{
hackDifficulty: {
@@ -253,6 +260,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 99,
min: 75,
},
specialName: LocationName.Sector12FourSigma,
},
{
hackDifficulty: {
@@ -275,6 +283,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 99,
min: 90,
},
specialName: LocationName.ChongqingKuaiGongInternational,
},
{
hackDifficulty: {
@@ -302,6 +311,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 99,
min: 80,
},
specialName: LocationName.AevumFulcrumTechnologies,
},
{
hackDifficulty: 99,
@@ -338,6 +348,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 92,
min: 68,
},
specialName: LocationName.IshimaStormTechnologies,
},
{
hackDifficulty: {
@@ -360,6 +371,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 73,
min: 47,
},
specialName: LocationName.NewTokyoDefComm,
},
{
hackDifficulty: {
@@ -409,6 +421,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 80,
min: 70,
},
specialName: LocationName.VolhavenHeliosLabs,
},
{
hackDifficulty: {
@@ -436,6 +449,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 80,
min: 60,
},
specialName: LocationName.NewTokyoVitaLife,
},
{
hackDifficulty: {
@@ -458,6 +472,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 95,
min: 85,
},
specialName: LocationName.Sector12IcarusMicrosystems,
},
{
hackDifficulty: {
@@ -484,6 +499,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 90,
min: 80,
},
specialName: LocationName.Sector12UniversalEnergy,
},
{
hackDifficulty: {
@@ -586,6 +602,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 90,
min: 70,
},
specialName: LocationName.AevumGalacticCybersystems,
},
{
hackDifficulty: {
@@ -609,6 +626,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 65,
min: 55,
},
specialName: LocationName.AevumAeroCorp,
},
{
hackDifficulty: {
@@ -636,6 +654,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 70,
min: 60,
},
specialName: LocationName.VolhavenOmniaCybersystems,
},
{
hackDifficulty: {
@@ -711,6 +730,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 80,
min: 70,
},
specialName: LocationName.ChongqingSolarisSpaceSystems,
},
{
hackDifficulty: {
@@ -733,6 +753,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 70,
min: 50,
},
specialName: LocationName.Sector12DeltaOne,
},
{
hackDifficulty: {
@@ -760,6 +781,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 90,
min: 80,
},
specialName: LocationName.NewTokyoGlobalPharmaceuticals,
},
{
hackDifficulty: {
@@ -782,6 +804,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 85,
min: 65,
},
specialName: LocationName.IshimaNovaMedical,
},
{
hackDifficulty: {
@@ -856,6 +879,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 65,
min: 55,
},
specialName: LocationName.VolhavenLexoCorp,
},
{
hackDifficulty: {
@@ -882,6 +906,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 60,
min: 40,
},
specialName: LocationName.AevumRhoConstruction,
},
{
hackDifficulty: {
@@ -909,6 +934,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 60,
min: 50,
},
specialName: LocationName.Sector12AlphaEnterprises,
},
{
hackDifficulty: {
@@ -935,6 +961,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 50,
min: 30,
},
specialName: LocationName.AevumPolice,
},
{
hackDifficulty: {
@@ -966,6 +993,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 45,
min: 35,
},
specialName: LocationName.Sector12RothmanUniversity,
},
{
hackDifficulty: {
@@ -992,6 +1020,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 85,
min: 75,
},
specialName: LocationName.VolhavenZBInstituteOfTechnology,
},
{
hackDifficulty: {
@@ -1023,6 +1052,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 60,
min: 40,
},
specialName: LocationName.AevumSummitUniversity,
},
{
hackDifficulty: {
@@ -1045,6 +1075,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 70,
min: 60,
},
specialName: LocationName.VolhavenSysCoreSecurities,
},
{
hackDifficulty: {
@@ -1121,6 +1152,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 65,
min: 45,
},
specialName: LocationName.VolhavenCompuTek,
},
{
hackDifficulty: {
@@ -1145,6 +1177,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 75,
min: 45,
},
specialName: LocationName.AevumNetLinkTechnologies,
},
{
hackDifficulty: {
@@ -1179,6 +1212,7 @@ export const serverMetadata: IServerMetadata[] = [
organizationName: LocationName.Sector12FoodNStuff,
requiredHackingSkill: 1,
serverGrowth: 5,
specialName: LocationName.Sector12FoodNStuff,
},
{
hackDifficulty: 10,
@@ -1198,9 +1232,10 @@ export const serverMetadata: IServerMetadata[] = [
moneyAvailable: 2500000,
networkLayer: 1,
numOpenPortsRequired: 0,
organizationName: "Joes Guns",
organizationName: LocationName.Sector12JoesGuns,
requiredHackingSkill: 10,
serverGrowth: 20,
specialName: LocationName.Sector12JoesGuns,
},
{
hackDifficulty: 25,
@@ -1316,6 +1351,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 40,
min: 30,
},
specialName: LocationName.IshimaOmegaSoftware,
},
{
hackDifficulty: {
@@ -1338,6 +1374,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 33,
min: 27,
},
specialName: LocationName.AevumCrushFitnessGym,
},
{
hackDifficulty: 30,
@@ -1349,6 +1386,7 @@ export const serverMetadata: IServerMetadata[] = [
organizationName: "Iron Gym Network",
requiredHackingSkill: 100,
serverGrowth: 20,
specialName: LocationName.Sector12IronGym,
},
{
hackDifficulty: {
@@ -1372,6 +1410,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 45,
min: 25,
},
specialName: LocationName.VolhavenMilleniumFitnessGym,
},
{
hackDifficulty: {
@@ -1395,6 +1434,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 60,
min: 50,
},
specialName: LocationName.Sector12PowerhouseGym,
},
{
hackDifficulty: {
@@ -1414,6 +1454,7 @@ export const serverMetadata: IServerMetadata[] = [
max: 60,
min: 40,
},
specialName: LocationName.AevumSnapFitnessGym,
},
{
hackDifficulty: 0,

View File

@@ -60,7 +60,7 @@ import { Player } from "./Player";
import { hackWorldDaemon } from "./RedPill";
import { RunningScript } from "./Script/RunningScript";
import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers";
import { findRunningScript } from "./Script/ScriptHelpers";
import { getCurrentEditor, findRunningScript } from "./Script/ScriptHelpers";
import { isScriptFilename } from "./Script/ScriptHelpersTS";
import { AllServers } from "./Server/AllServers";
import { Server } from "./Server/Server";
@@ -1789,6 +1789,7 @@ let Terminal = {
}`;
}
Engine.loadScriptEditorContent(filepath, code);
getCurrentEditor().setCursor({row: 1, column: 4});
} else {
Engine.loadScriptEditorContent(filepath, script.code);
}

View File

@@ -1097,7 +1097,7 @@ const Engine = {
// Hacknet Nodes offline progress
var offlineProductionFromHacknetNodes = processHacknetEarnings(numCyclesOffline);
const hacknetProdInfo = hasHacknetServers() ?
Hashes(offlineProductionFromHacknetNodes):
<>{Hashes(offlineProductionFromHacknetNodes)} hashes</>:
Money(offlineProductionFromHacknetNodes);
// Passive faction rep gain offline
@@ -1151,7 +1151,7 @@ const Engine = {
removeLoadingScreen();
const timeOfflineString = convertTimeMsToTimeElapsedString(time);
dialogBoxCreate(<>
Offline for {timeOfflineString}. While you were offline, your scripts generated {Money(offlineProductionFromScripts)} and your Hacknet Nodes generated {hacknetProdInfo} hashes.
Offline for {timeOfflineString}. While you were offline, your scripts generated {Money(offlineProductionFromScripts)} and your Hacknet Nodes generated {hacknetProdInfo}.
</>);
// Close main menu accordions for loaded game
var visibleMenuTabs = [terminal, createScript, activeScripts, stats,

View File

@@ -394,7 +394,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<!-- Status text -->
<div id="status-text-container">
<p id="status-text"> </p>
<p id="status-text"></p>
</div>
<!-- Game Options -->