Merge pull request #238 from danielyxie/dev

v0.36.1
This commit is contained in:
danielyxie 2018-05-11 16:37:37 -05:00 committed by GitHub
commit 11562fdb3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 170372 additions and 22032 deletions

File diff suppressed because one or more lines are too long

143884
dist/tests.bundle.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -422,7 +422,7 @@ getHackingMultipliers
.. js:function:: getHackingMultipliers() .. js:function:: getHackingMultipliers()
Returns an object containing the Player's hacking related multipliers. These multipliers are Returns an object containing the Player's hacking related multipliers. These multipliers are
returned in integer forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure:: returned in fractional forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure::
{ {
chance: Player's hacking chance multiplier, chance: Player's hacking chance multiplier,
@ -437,6 +437,30 @@ getHackingMultipliers
print(mults.chance); print(mults.chance);
print(mults.growth); print(mults.growth);
getHacknetMultipliers
^^^^^^^^^^^^^^^^^^^^^
.. js:function:: getHacknetMultipliers()
Returns an object containing the Player's hacknet related multipliers. These multipliers are
returned in fractional forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure::
{
production: Player's hacknet production multiplier,
purchaseCost: Player's hacknet purchase cost multiplier,
ramCost: Player's hacknet ram cost multiplier,
coreCost: Player's hacknet core cost multiplier,
levelCost: Player's hacknet level cost multiplier
}
Example of how this can be used::
mults = getHacknetMultipliers();
print(mults.production);
print(mults.purchaseCost);
getServerMoneyAvailable getServerMoneyAvailable
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
@ -779,13 +803,20 @@ scriptKill
Kills all scripts with the specified filename on the target server specified by *hostname/ip*, regardless of arguments. Returns Kills all scripts with the specified filename on the target server specified by *hostname/ip*, regardless of arguments. Returns
true if one or more scripts were successfully killed, and false if none were. true if one or more scripts were successfully killed, and false if none were.
getScriptName
^^^^^^^^^^^^^
.. js:function:: getScriptName()
Returns the current script name
getScriptRam getScriptRam
^^^^^^^^^^^^ ^^^^^^^^^^^^
.. js:function:: getScriptRam(scriptname, hostname/ip) .. js:function:: getScriptRam(scriptname[, hostname/ip])
:param string scriptname: Filename of script. This is case-sensitive. :param string scriptname: Filename of script. This is case-sensitive.
:param string hostname/ip: Hostname or IP of target server :param string hostname/ip: Hostname or IP of target server the script is located on. This is optional, If it is not specified then the function will se the current server as the target server.
Returns the amount of RAM required to run the specified script on the target server Returns the amount of RAM required to run the specified script on the target server

@ -17,6 +17,22 @@ hacknetnodes
accessed using *hacknetnodes[0]*. The fourth Hacknet Node you purchase will have the name accessed using *hacknetnodes[0]*. The fourth Hacknet Node you purchase will have the name
"hacknet-node-3" and can be accessed using *hacknetnodes[3]*. "hacknet-node-3" and can be accessed using *hacknetnodes[3]*.
Purchasing Hacknet Nodes
^^^^^^^^^^^^^^^^^^^^^^^^
The following is a list of supported functions for purchasing Hacknet Nodes.
.. js:function:: getNextHacknetNodeCost()
Returns the cost of purchasing a new Hacknet Node
.. js:function:: purchaseHacknetNode()
Purchases a new Hacknet Node. Returns a number with the index of the Hacknet Node. This index is equivalent to the number at the
end of the Hacknet Node's name (e.g The Hacknet Node named 'hacknet-node-4' will have an index of 4). If the player cannot afford
to purchase a new Hacknet Node then the function will return false.
Hacknet Node Member Variables Hacknet Node Member Variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -25,6 +41,11 @@ a value to these.
Note that these must be called on an element inside the *hacknetnodes* array, not the array itself. Note that these must be called on an element inside the *hacknetnodes* array, not the array itself.
.. js:attribute:: hacknetnodes[i].name
Returns the name of the corresponding Hacknet Node
.. js:attribute:: hacknetnodes[i].level .. js:attribute:: hacknetnodes[i].level
Returns the level of the corresponding Hacknet Node Returns the level of the corresponding Hacknet Node
@ -90,6 +111,29 @@ array itself.
Returns the cost of upgrading the number of cores of the specified Hacknet Node. Upgrading a Node's Returns the cost of upgrading the number of cores of the specified Hacknet Node. Upgrading a Node's
number of cores adds one additional core. number of cores adds one additional core.
Utils
^^^^^
.. js:function:: getHacknetMultipliers()
Returns an object containing the Player's hacknet related multipliers. These multipliers are
returned in integer forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure::
{
production: Player's hacknet production multiplier,
purchaseCost: Player's hacknet purchase cost multiplier,
ramCost: Player's hacknet ram cost multiplier,
coreCost: Player's hacknet core cost multiplier,
levelCost: Player's hacknet level cost multiplier
}
Example of how this can be used::
mults = getHacknetMultipliers();
print(mults.production);
print(mults.purchaseCost);
Example(s) Example(s)
^^^^^^^^^^ ^^^^^^^^^^

@ -147,7 +147,7 @@ Terminal commands::
$ download * $ download *
$ download *.script $ download *.script
$download *.txt $ download *.txt
free free
^^^^ ^^^^

@ -174,12 +174,14 @@
<li><a href="netscriptfunctions.html#getHackingLevel">getHackingLevel() (built-in function)</a> <li><a href="netscriptfunctions.html#getHackingLevel">getHackingLevel() (built-in function)</a>
</li> </li>
<li><a href="netscriptfunctions.html#getHackingMultipliers">getHackingMultipliers() (built-in function)</a> <li><a href="netscriptfunctions.html#getHackingMultipliers">getHackingMultipliers() (built-in function)</a>
</li>
<li><a href="netscriptfunctions.html#getHacknetMultipliers">getHacknetMultipliers() (built-in function)</a>, <a href="netscripthacknetnodeapi.html#getHacknetMultipliers">[1]</a>
</li> </li>
<li><a href="netscriptfunctions.html#getHackTime">getHackTime() (built-in function)</a> <li><a href="netscriptfunctions.html#getHackTime">getHackTime() (built-in function)</a>
</li> </li>
<li><a href="netscriptfunctions.html#getHostname">getHostname() (built-in function)</a> <li><a href="netscriptfunctions.html#getHostname">getHostname() (built-in function)</a>
</li> </li>
<li><a href="netscriptfunctions.html#getNextHacknetNodeCost">getNextHacknetNodeCost() (built-in function)</a> <li><a href="netscriptfunctions.html#getNextHacknetNodeCost">getNextHacknetNodeCost() (built-in function)</a>, <a href="netscripthacknetnodeapi.html#getNextHacknetNodeCost">[1]</a>
</li> </li>
<li><a href="netscriptsingularityfunctions.html#getOwnedAugmentations">getOwnedAugmentations() (built-in function)</a> <li><a href="netscriptsingularityfunctions.html#getOwnedAugmentations">getOwnedAugmentations() (built-in function)</a>
</li> </li>
@ -191,6 +193,8 @@
</li> </li>
</ul></td> </ul></td>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="netscriptfunctions.html#getScriptName">getScriptName() (built-in function)</a>
</li>
<li><a href="netscriptfunctions.html#getScriptRam">getScriptRam() (built-in function)</a> <li><a href="netscriptfunctions.html#getScriptRam">getScriptRam() (built-in function)</a>
</li> </li>
<li><a href="netscriptfunctions.html#getServerBaseSecurityLevel">getServerBaseSecurityLevel() (built-in function)</a> <li><a href="netscriptfunctions.html#getServerBaseSecurityLevel">getServerBaseSecurityLevel() (built-in function)</a>
@ -240,6 +244,8 @@
<li><a href="netscripthacknetnodeapi.html#hacknetnodes[i].level">hacknetnodes[i].level (hacknetnodes[i] attribute)</a> <li><a href="netscripthacknetnodeapi.html#hacknetnodes[i].level">hacknetnodes[i].level (hacknetnodes[i] attribute)</a>
</li> </li>
<li><a href="netscripthacknetnodeapi.html#hacknetnodes[i].moneyGainRatePerSecond">hacknetnodes[i].moneyGainRatePerSecond (hacknetnodes[i] attribute)</a> <li><a href="netscripthacknetnodeapi.html#hacknetnodes[i].moneyGainRatePerSecond">hacknetnodes[i].moneyGainRatePerSecond (hacknetnodes[i] attribute)</a>
</li>
<li><a href="netscripthacknetnodeapi.html#hacknetnodes[i].name">hacknetnodes[i].name (hacknetnodes[i] attribute)</a>
</li> </li>
</ul></td> </ul></td>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
@ -325,7 +331,7 @@
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="netscriptsingularityfunctions.html#purchaseAugmentation">purchaseAugmentation() (built-in function)</a> <li><a href="netscriptsingularityfunctions.html#purchaseAugmentation">purchaseAugmentation() (built-in function)</a>
</li> </li>
<li><a href="netscriptfunctions.html#purchaseHacknetNode">purchaseHacknetNode() (built-in function)</a> <li><a href="netscriptfunctions.html#purchaseHacknetNode">purchaseHacknetNode() (built-in function)</a>, <a href="netscripthacknetnodeapi.html#purchaseHacknetNode">[1]</a>
</li> </li>
<li><a href="netscriptsingularityfunctions.html#purchaseProgram">purchaseProgram() (built-in function)</a> <li><a href="netscriptsingularityfunctions.html#purchaseProgram">purchaseProgram() (built-in function)</a>
</li> </li>

@ -106,6 +106,7 @@ secrets that you've been searching for.</p>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethostname">getHostname</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethostname">getHostname</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethackinglevel">getHackingLevel</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethackinglevel">getHackingLevel</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethackingmultipliers">getHackingMultipliers</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethackingmultipliers">getHackingMultipliers</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethacknetmultipliers">getHacknetMultipliers</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getservermoneyavailable">getServerMoneyAvailable</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getservermoneyavailable">getServerMoneyAvailable</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getservermaxmoney">getServerMaxMoney</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getservermaxmoney">getServerMaxMoney</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getservergrowth">getServerGrowth</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getservergrowth">getServerGrowth</a></li>
@ -130,6 +131,7 @@ secrets that you've been searching for.</p>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#rm">rm</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#rm">rm</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#scriptrunning">scriptRunning</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#scriptrunning">scriptRunning</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#scriptkill">scriptKill</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#scriptkill">scriptKill</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getscriptname">getScriptName</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getscriptram">getScriptRam</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getscriptram">getScriptRam</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethacktime">getHackTime</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#gethacktime">getHackTime</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getgrowtime">getGrowTime</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptfunctions.html#getgrowtime">getGrowTime</a></li>
@ -151,8 +153,10 @@ secrets that you've been searching for.</p>
</li> </li>
<li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html"> Hacknet Node API</a><ul> <li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html"> Hacknet Node API</a><ul>
<li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknetnodes">hacknetnodes</a></li> <li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknetnodes">hacknetnodes</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#purchasing-hacknet-nodes">Purchasing Hacknet Nodes</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknet-node-member-variables">Hacknet Node Member Variables</a></li> <li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknet-node-member-variables">Hacknet Node Member Variables</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknet-node-methods">Hacknet Node Methods</a></li> <li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknet-node-methods">Hacknet Node Methods</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#utils">Utils</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#example-s">Example(s)</a></li> <li class="toctree-l3"><a class="reference internal" href="netscripthacknetnodeapi.html#example-s">Example(s)</a></li>
</ul> </ul>
</li> </li>

@ -107,6 +107,7 @@ to reach out to the developer!</p>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethostname">getHostname</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethostname">getHostname</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethackinglevel">getHackingLevel</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethackinglevel">getHackingLevel</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethackingmultipliers">getHackingMultipliers</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethackingmultipliers">getHackingMultipliers</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethacknetmultipliers">getHacknetMultipliers</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getservermoneyavailable">getServerMoneyAvailable</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getservermoneyavailable">getServerMoneyAvailable</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getservermaxmoney">getServerMaxMoney</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getservermaxmoney">getServerMaxMoney</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getservergrowth">getServerGrowth</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getservergrowth">getServerGrowth</a></li>
@ -131,6 +132,7 @@ to reach out to the developer!</p>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#rm">rm</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#rm">rm</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#scriptrunning">scriptRunning</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#scriptrunning">scriptRunning</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#scriptkill">scriptKill</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#scriptkill">scriptKill</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getscriptname">getScriptName</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getscriptram">getScriptRam</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getscriptram">getScriptRam</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethacktime">getHackTime</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#gethacktime">getHackTime</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getgrowtime">getGrowTime</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptfunctions.html#getgrowtime">getGrowTime</a></li>
@ -152,8 +154,10 @@ to reach out to the developer!</p>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="netscripthacknetnodeapi.html"> Hacknet Node API</a><ul> <li class="toctree-l1"><a class="reference internal" href="netscripthacknetnodeapi.html"> Hacknet Node API</a><ul>
<li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknetnodes">hacknetnodes</a></li> <li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknetnodes">hacknetnodes</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#purchasing-hacknet-nodes">Purchasing Hacknet Nodes</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknet-node-member-variables">Hacknet Node Member Variables</a></li> <li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknet-node-member-variables">Hacknet Node Member Variables</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknet-node-methods">Hacknet Node Methods</a></li> <li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#hacknet-node-methods">Hacknet Node Methods</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#utils">Utils</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#example-s">Example(s)</a></li> <li class="toctree-l2"><a class="reference internal" href="netscripthacknetnodeapi.html#example-s">Example(s)</a></li>
</ul> </ul>
</li> </li>
@ -234,6 +238,7 @@ to reach out to the developer!</p>
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a></li>
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="terminal.html"> Terminal</a></li>
<li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li> <li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li>
</ul> </ul>

@ -722,7 +722,7 @@ is sorted in alphabetic order</p>
<dt id="getHackingMultipliers"> <dt id="getHackingMultipliers">
<code class="descname">getHackingMultipliers</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#getHackingMultipliers" title="Permalink to this definition"></a></dt> <code class="descname">getHackingMultipliers</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#getHackingMultipliers" title="Permalink to this definition"></a></dt>
<dd><p>Returns an object containing the Player's hacking related multipliers. These multipliers are <dd><p>Returns an object containing the Player's hacking related multipliers. These multipliers are
returned in integer forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure:</p> returned in fractional forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="p">{</span> <div class="highlight-default"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="n">chance</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacking chance multiplier,</span> <span class="n">chance</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacking chance multiplier,</span>
<span class="n">speed</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacking speed multiplier,</span> <span class="n">speed</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacking speed multiplier,</span>
@ -739,6 +739,31 @@ returned in integer forms, not percentages (e.g. 1.5 instead of 150%). The objec
</div> </div>
</dd></dl> </dd></dl>
</div>
<div class="section" id="gethacknetmultipliers">
<h2>getHacknetMultipliers<a class="headerlink" href="#gethacknetmultipliers" title="Permalink to this headline"></a></h2>
<dl class="function">
<dt id="getHacknetMultipliers">
<code class="descname">getHacknetMultipliers</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#getHacknetMultipliers" title="Permalink to this definition"></a></dt>
<dd><p>Returns an object containing the Player's hacknet related multipliers. These multipliers are
returned in fractional forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="n">production</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet production multiplier,</span>
<span class="n">purchaseCost</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet purchase cost multiplier,</span>
<span class="n">ramCost</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet ram cost multiplier,</span>
<span class="n">coreCost</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet core cost multiplier,</span>
<span class="n">levelCost</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet level cost multiplier</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Example of how this can be used:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">mults</span> <span class="o">=</span> <span class="n">getHacknetMultipliers</span><span class="p">();</span>
<span class="nb">print</span><span class="p">(</span><span class="n">mults</span><span class="o">.</span><span class="n">production</span><span class="p">);</span>
<span class="nb">print</span><span class="p">(</span><span class="n">mults</span><span class="o">.</span><span class="n">purchaseCost</span><span class="p">);</span>
</pre></div>
</div>
</dd></dl>
</div> </div>
<div class="section" id="getservermoneyavailable"> <div class="section" id="getservermoneyavailable">
<h2>getServerMoneyAvailable<a class="headerlink" href="#getservermoneyavailable" title="Permalink to this headline"></a></h2> <h2>getServerMoneyAvailable<a class="headerlink" href="#getservermoneyavailable" title="Permalink to this headline"></a></h2>
@ -1310,19 +1335,28 @@ by its arguments.</p>
true if one or more scripts were successfully killed, and false if none were.</p> true if one or more scripts were successfully killed, and false if none were.</p>
</dd></dl> </dd></dl>
</div>
<div class="section" id="getscriptname">
<h2>getScriptName<a class="headerlink" href="#getscriptname" title="Permalink to this headline"></a></h2>
<dl class="function">
<dt id="getScriptName">
<code class="descname">getScriptName</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#getScriptName" title="Permalink to this definition"></a></dt>
<dd><p>Returns the current script name</p>
</dd></dl>
</div> </div>
<div class="section" id="getscriptram"> <div class="section" id="getscriptram">
<h2>getScriptRam<a class="headerlink" href="#getscriptram" title="Permalink to this headline"></a></h2> <h2>getScriptRam<a class="headerlink" href="#getscriptram" title="Permalink to this headline"></a></h2>
<dl class="function"> <dl class="function">
<dt id="getScriptRam"> <dt id="getScriptRam">
<code class="descname">getScriptRam</code><span class="sig-paren">(</span><em>scriptname</em>, <em>hostname/ip</em><span class="sig-paren">)</span><a class="headerlink" href="#getScriptRam" title="Permalink to this definition"></a></dt> <code class="descname">getScriptRam</code><span class="sig-paren">(</span><em>scriptname</em><span class="optional">[</span>, <em>hostname/ip</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#getScriptRam" title="Permalink to this definition"></a></dt>
<dd><table class="docutils field-list" frame="void" rules="none"> <dd><table class="docutils field-list" frame="void" rules="none">
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
<tbody valign="top"> <tbody valign="top">
<tr class="field-odd field"><th class="field-name">Arguments:</th><td class="field-body"><ul class="first last simple"> <tr class="field-odd field"><th class="field-name">Arguments:</th><td class="field-body"><ul class="first last simple">
<li><strong>scriptname</strong> (<em>string</em>) -- Filename of script. This is case-sensitive.</li> <li><strong>scriptname</strong> (<em>string</em>) -- Filename of script. This is case-sensitive.</li>
<li><strong>hostname/ip</strong> (<em>string</em>) -- Hostname or IP of target server</li> <li><strong>hostname/ip</strong> (<em>string</em>) -- Hostname or IP of target server the script is located on. This is optional, If it is not specified then the function will se the current server as the target server.</li>
</ul> </ul>
</td> </td>
</tr> </tr>
@ -1617,6 +1651,7 @@ you create in functions such as <a class="reference external" href="https://deve
<li class="toctree-l3"><a class="reference internal" href="#gethostname">getHostname</a></li> <li class="toctree-l3"><a class="reference internal" href="#gethostname">getHostname</a></li>
<li class="toctree-l3"><a class="reference internal" href="#gethackinglevel">getHackingLevel</a></li> <li class="toctree-l3"><a class="reference internal" href="#gethackinglevel">getHackingLevel</a></li>
<li class="toctree-l3"><a class="reference internal" href="#gethackingmultipliers">getHackingMultipliers</a></li> <li class="toctree-l3"><a class="reference internal" href="#gethackingmultipliers">getHackingMultipliers</a></li>
<li class="toctree-l3"><a class="reference internal" href="#gethacknetmultipliers">getHacknetMultipliers</a></li>
<li class="toctree-l3"><a class="reference internal" href="#getservermoneyavailable">getServerMoneyAvailable</a></li> <li class="toctree-l3"><a class="reference internal" href="#getservermoneyavailable">getServerMoneyAvailable</a></li>
<li class="toctree-l3"><a class="reference internal" href="#getservermaxmoney">getServerMaxMoney</a></li> <li class="toctree-l3"><a class="reference internal" href="#getservermaxmoney">getServerMaxMoney</a></li>
<li class="toctree-l3"><a class="reference internal" href="#getservergrowth">getServerGrowth</a></li> <li class="toctree-l3"><a class="reference internal" href="#getservergrowth">getServerGrowth</a></li>
@ -1641,6 +1676,7 @@ you create in functions such as <a class="reference external" href="https://deve
<li class="toctree-l3"><a class="reference internal" href="#rm">rm</a></li> <li class="toctree-l3"><a class="reference internal" href="#rm">rm</a></li>
<li class="toctree-l3"><a class="reference internal" href="#scriptrunning">scriptRunning</a></li> <li class="toctree-l3"><a class="reference internal" href="#scriptrunning">scriptRunning</a></li>
<li class="toctree-l3"><a class="reference internal" href="#scriptkill">scriptKill</a></li> <li class="toctree-l3"><a class="reference internal" href="#scriptkill">scriptKill</a></li>
<li class="toctree-l3"><a class="reference internal" href="#getscriptname">getScriptName</a></li>
<li class="toctree-l3"><a class="reference internal" href="#getscriptram">getScriptRam</a></li> <li class="toctree-l3"><a class="reference internal" href="#getscriptram">getScriptRam</a></li>
<li class="toctree-l3"><a class="reference internal" href="#gethacktime">getHackTime</a></li> <li class="toctree-l3"><a class="reference internal" href="#gethacktime">getHackTime</a></li>
<li class="toctree-l3"><a class="reference internal" href="#getgrowtime">getGrowTime</a></li> <li class="toctree-l3"><a class="reference internal" href="#getgrowtime">getGrowTime</a></li>
@ -1663,6 +1699,7 @@ you create in functions such as <a class="reference external" href="https://deve
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a></li>
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="terminal.html"> Terminal</a></li>
<li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li> <li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li>
</ul> </ul>

@ -66,12 +66,36 @@ correspond to the number at the end of the name of the Hacknet Node. For example
the first Hacknet Node you purchase will have the name &quot;hacknet-node-0&quot; and can be the first Hacknet Node you purchase will have the name &quot;hacknet-node-0&quot; and can be
accessed using <em>hacknetnodes[0]</em>. The fourth Hacknet Node you purchase will have the name accessed using <em>hacknetnodes[0]</em>. The fourth Hacknet Node you purchase will have the name
&quot;hacknet-node-3&quot; and can be accessed using <em>hacknetnodes[3]</em>.</div></blockquote> &quot;hacknet-node-3&quot; and can be accessed using <em>hacknetnodes[3]</em>.</div></blockquote>
</div>
<div class="section" id="purchasing-hacknet-nodes">
<h2>Purchasing Hacknet Nodes<a class="headerlink" href="#purchasing-hacknet-nodes" title="Permalink to this headline"></a></h2>
<p>The following is a list of supported functions for purchasing Hacknet Nodes.</p>
<dl class="function">
<dt id="getNextHacknetNodeCost">
<code class="descname">getNextHacknetNodeCost</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#getNextHacknetNodeCost" title="Permalink to this definition"></a></dt>
<dd><p>Returns the cost of purchasing a new Hacknet Node</p>
</dd></dl>
<dl class="function">
<dt id="purchaseHacknetNode">
<code class="descname">purchaseHacknetNode</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#purchaseHacknetNode" title="Permalink to this definition"></a></dt>
<dd><p>Purchases a new Hacknet Node. Returns a number with the index of the Hacknet Node. This index is equivalent to the number at the
end of the Hacknet Node's name (e.g The Hacknet Node named 'hacknet-node-4' will have an index of 4). If the player cannot afford
to purchase a new Hacknet Node then the function will return false.</p>
</dd></dl>
</div> </div>
<div class="section" id="hacknet-node-member-variables"> <div class="section" id="hacknet-node-member-variables">
<h2>Hacknet Node Member Variables<a class="headerlink" href="#hacknet-node-member-variables" title="Permalink to this headline"></a></h2> <h2>Hacknet Node Member Variables<a class="headerlink" href="#hacknet-node-member-variables" title="Permalink to this headline"></a></h2>
<p>The following is a list of member variables for a Hacknet Node object. These variables are read-only, which means you cannot assign <p>The following is a list of member variables for a Hacknet Node object. These variables are read-only, which means you cannot assign
a value to these.</p> a value to these.</p>
<p>Note that these must be called on an element inside the <em>hacknetnodes</em> array, not the array itself.</p> <p>Note that these must be called on an element inside the <em>hacknetnodes</em> array, not the array itself.</p>
<dl class="attribute">
<dt id="hacknetnodes[i].name">
<code class="descclassname">hacknetnodes[i].</code><code class="descname">name</code><a class="headerlink" href="#hacknetnodes[i].name" title="Permalink to this definition"></a></dt>
<dd><p>Returns the name of the corresponding Hacknet Node</p>
</dd></dl>
<dl class="attribute"> <dl class="attribute">
<dt id="hacknetnodes[i].level"> <dt id="hacknetnodes[i].level">
<code class="descclassname">hacknetnodes[i].</code><code class="descname">level</code><a class="headerlink" href="#hacknetnodes[i].level" title="Permalink to this definition"></a></dt> <code class="descclassname">hacknetnodes[i].</code><code class="descname">level</code><a class="headerlink" href="#hacknetnodes[i].level" title="Permalink to this definition"></a></dt>
@ -177,6 +201,31 @@ additional core is successfully purchased, and false otherwise.</p>
number of cores adds one additional core.</p> number of cores adds one additional core.</p>
</dd></dl> </dd></dl>
</div>
<div class="section" id="utils">
<h2>Utils<a class="headerlink" href="#utils" title="Permalink to this headline"></a></h2>
<dl class="function">
<dt id="getHacknetMultipliers">
<code class="descname">getHacknetMultipliers</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#getHacknetMultipliers" title="Permalink to this definition"></a></dt>
<dd><p>Returns an object containing the Player's hacknet related multipliers. These multipliers are
returned in integer forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="n">production</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet production multiplier,</span>
<span class="n">purchaseCost</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet purchase cost multiplier,</span>
<span class="n">ramCost</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet ram cost multiplier,</span>
<span class="n">coreCost</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet core cost multiplier,</span>
<span class="n">levelCost</span><span class="p">:</span> <span class="n">Player</span><span class="s1">&#39;s hacknet level cost multiplier</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Example of how this can be used:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">mults</span> <span class="o">=</span> <span class="n">getHacknetMultipliers</span><span class="p">();</span>
<span class="nb">print</span><span class="p">(</span><span class="n">mults</span><span class="o">.</span><span class="n">production</span><span class="p">);</span>
<span class="nb">print</span><span class="p">(</span><span class="n">mults</span><span class="o">.</span><span class="n">purchaseCost</span><span class="p">);</span>
</pre></div>
</div>
</dd></dl>
</div> </div>
<div class="section" id="example-s"> <div class="section" id="example-s">
<h2>Example(s)<a class="headerlink" href="#example-s" title="Permalink to this headline"></a></h2> <h2>Example(s)<a class="headerlink" href="#example-s" title="Permalink to this headline"></a></h2>
@ -234,8 +283,10 @@ Nodes to a level of at least 75, RAM to at least 8GB, and number of cores to at
<li class="toctree-l2"><a class="reference internal" href="netscriptadvancedfunctions.html"> Advanced Functions</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptadvancedfunctions.html"> Advanced Functions</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#"> Hacknet Node API</a><ul> <li class="toctree-l2 current"><a class="current reference internal" href="#"> Hacknet Node API</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#hacknetnodes">hacknetnodes</a></li> <li class="toctree-l3"><a class="reference internal" href="#hacknetnodes">hacknetnodes</a></li>
<li class="toctree-l3"><a class="reference internal" href="#purchasing-hacknet-nodes">Purchasing Hacknet Nodes</a></li>
<li class="toctree-l3"><a class="reference internal" href="#hacknet-node-member-variables">Hacknet Node Member Variables</a></li> <li class="toctree-l3"><a class="reference internal" href="#hacknet-node-member-variables">Hacknet Node Member Variables</a></li>
<li class="toctree-l3"><a class="reference internal" href="#hacknet-node-methods">Hacknet Node Methods</a></li> <li class="toctree-l3"><a class="reference internal" href="#hacknet-node-methods">Hacknet Node Methods</a></li>
<li class="toctree-l3"><a class="reference internal" href="#utils">Utils</a></li>
<li class="toctree-l3"><a class="reference internal" href="#example-s">Example(s)</a></li> <li class="toctree-l3"><a class="reference internal" href="#example-s">Example(s)</a></li>
</ul> </ul>
</li> </li>
@ -244,6 +295,7 @@ Nodes to a level of at least 75, RAM to at least 8GB, and number of cores to at
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a></li>
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="terminal.html"> Terminal</a></li>
<li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li> <li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li>
</ul> </ul>

Binary file not shown.

File diff suppressed because one or more lines are too long

@ -185,7 +185,7 @@ $ download importantInfo.txt
Terminal commands:</p> Terminal commands:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span>$ download * <div class="highlight-default"><div class="highlight"><pre><span></span>$ download *
$ download *.script $ download *.script
$download *.txt $ download *.txt
</pre></div> </pre></div>
</div> </div>
</div> </div>

@ -422,7 +422,7 @@ getHackingMultipliers
.. js:function:: getHackingMultipliers() .. js:function:: getHackingMultipliers()
Returns an object containing the Player's hacking related multipliers. These multipliers are Returns an object containing the Player's hacking related multipliers. These multipliers are
returned in integer forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure:: returned in fractional forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure::
{ {
chance: Player's hacking chance multiplier, chance: Player's hacking chance multiplier,
@ -437,6 +437,30 @@ getHackingMultipliers
print(mults.chance); print(mults.chance);
print(mults.growth); print(mults.growth);
getHacknetMultipliers
^^^^^^^^^^^^^^^^^^^^^
.. js:function:: getHacknetMultipliers()
Returns an object containing the Player's hacknet related multipliers. These multipliers are
returned in fractional forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure::
{
production: Player's hacknet production multiplier,
purchaseCost: Player's hacknet purchase cost multiplier,
ramCost: Player's hacknet ram cost multiplier,
coreCost: Player's hacknet core cost multiplier,
levelCost: Player's hacknet level cost multiplier
}
Example of how this can be used::
mults = getHacknetMultipliers();
print(mults.production);
print(mults.purchaseCost);
getServerMoneyAvailable getServerMoneyAvailable
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
@ -779,13 +803,20 @@ scriptKill
Kills all scripts with the specified filename on the target server specified by *hostname/ip*, regardless of arguments. Returns Kills all scripts with the specified filename on the target server specified by *hostname/ip*, regardless of arguments. Returns
true if one or more scripts were successfully killed, and false if none were. true if one or more scripts were successfully killed, and false if none were.
getScriptName
^^^^^^^^^^^^^
.. js:function:: getScriptName()
Returns the current script name
getScriptRam getScriptRam
^^^^^^^^^^^^ ^^^^^^^^^^^^
.. js:function:: getScriptRam(scriptname, hostname/ip) .. js:function:: getScriptRam(scriptname[, hostname/ip])
:param string scriptname: Filename of script. This is case-sensitive. :param string scriptname: Filename of script. This is case-sensitive.
:param string hostname/ip: Hostname or IP of target server :param string hostname/ip: Hostname or IP of target server the script is located on. This is optional, If it is not specified then the function will se the current server as the target server.
Returns the amount of RAM required to run the specified script on the target server Returns the amount of RAM required to run the specified script on the target server

@ -17,6 +17,22 @@ hacknetnodes
accessed using *hacknetnodes[0]*. The fourth Hacknet Node you purchase will have the name accessed using *hacknetnodes[0]*. The fourth Hacknet Node you purchase will have the name
"hacknet-node-3" and can be accessed using *hacknetnodes[3]*. "hacknet-node-3" and can be accessed using *hacknetnodes[3]*.
Purchasing Hacknet Nodes
^^^^^^^^^^^^^^^^^^^^^^^^
The following is a list of supported functions for purchasing Hacknet Nodes.
.. js:function:: getNextHacknetNodeCost()
Returns the cost of purchasing a new Hacknet Node
.. js:function:: purchaseHacknetNode()
Purchases a new Hacknet Node. Returns a number with the index of the Hacknet Node. This index is equivalent to the number at the
end of the Hacknet Node's name (e.g The Hacknet Node named 'hacknet-node-4' will have an index of 4). If the player cannot afford
to purchase a new Hacknet Node then the function will return false.
Hacknet Node Member Variables Hacknet Node Member Variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -25,6 +41,11 @@ a value to these.
Note that these must be called on an element inside the *hacknetnodes* array, not the array itself. Note that these must be called on an element inside the *hacknetnodes* array, not the array itself.
.. js:attribute:: hacknetnodes[i].name
Returns the name of the corresponding Hacknet Node
.. js:attribute:: hacknetnodes[i].level .. js:attribute:: hacknetnodes[i].level
Returns the level of the corresponding Hacknet Node Returns the level of the corresponding Hacknet Node
@ -90,6 +111,29 @@ array itself.
Returns the cost of upgrading the number of cores of the specified Hacknet Node. Upgrading a Node's Returns the cost of upgrading the number of cores of the specified Hacknet Node. Upgrading a Node's
number of cores adds one additional core. number of cores adds one additional core.
Utils
^^^^^
.. js:function:: getHacknetMultipliers()
Returns an object containing the Player's hacknet related multipliers. These multipliers are
returned in integer forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure::
{
production: Player's hacknet production multiplier,
purchaseCost: Player's hacknet purchase cost multiplier,
ramCost: Player's hacknet ram cost multiplier,
coreCost: Player's hacknet core cost multiplier,
levelCost: Player's hacknet level cost multiplier
}
Example of how this can be used::
mults = getHacknetMultipliers();
print(mults.production);
print(mults.purchaseCost);
Example(s) Example(s)
^^^^^^^^^^ ^^^^^^^^^^

@ -819,6 +819,18 @@
<input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites"> <input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites">
</fieldset> </fieldset>
<!-- Disable Terminal and Navigation Shortcuts -->
<fieldset>
<label for="settingsDisableHotkeys" class="tooltip">Disable Hotkeys:
<span class="tooltiptext">
If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled.
This includes Terminal commands, hotkeys to navigate between different parts of the game,
and the "Save and Close (Ctrl + b)" hotkey in the Text Editor.
</span>
</label>
<input type="checkbox" name="settingsDisableHotkeys" id="settingsDisableHotkeys">
</fieldset>
<!-- Donate button --> <!-- Donate button -->
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick"> <input type="hidden" name="cmd" value="_s-xclick">
@ -861,5 +873,5 @@
<div class="loaderlabel">Loading Bitburner...</div> <div class="loaderlabel">Loading Bitburner...</div>
</div> </div>
</body> </body>
<script src="dist/bundle.js"></script> <script src="dist/engine.bundle.js"></script>
</html> </html>

2167
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -32,6 +32,7 @@
"supports-color": "^4.2.1", "supports-color": "^4.2.1",
"tapable": "^0.2.7", "tapable": "^0.2.7",
"uglifyjs-webpack-plugin": "^0.4.6", "uglifyjs-webpack-plugin": "^0.4.6",
"uuid": "^3.2.1",
"w3c-blob": "0.0.1", "w3c-blob": "0.0.1",
"watchpack": "^1.4.0", "watchpack": "^1.4.0",
"webpack-sources": "^1.0.1", "webpack-sources": "^1.0.1",
@ -42,6 +43,8 @@
"beautify-lint": "^1.0.3", "beautify-lint": "^1.0.3",
"benchmark": "^2.1.1", "benchmark": "^2.1.1",
"bundle-loader": "~0.5.0", "bundle-loader": "~0.5.0",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"codacy-coverage": "^2.0.1", "codacy-coverage": "^2.0.1",
"codecov.io": "^0.1.2", "codecov.io": "^0.1.2",
"coffee-loader": "~0.7.1", "coffee-loader": "~0.7.1",
@ -79,6 +82,7 @@
"webpack": "^4.1.1", "webpack": "^4.1.1",
"webpack-cli": "^2.0.12", "webpack-cli": "^2.0.12",
"webpack-dev-middleware": "^1.9.0", "webpack-dev-middleware": "^1.9.0",
"webpack-dev-server": "^3.1.4",
"worker-loader": "^0.8.0" "worker-loader": "^0.8.0"
}, },
"engines": { "engines": {
@ -92,25 +96,7 @@
"url": "git+https://github.com/danielyxie/bitburner.git" "url": "git+https://github.com/danielyxie/bitburner.git"
}, },
"scripts": { "scripts": {
"appveyor:benchmark": "npm run benchmark", "start:dev": "webpack-dev-server"
"appveyor:test": "node node_modules\\mocha\\bin\\mocha --max-old-space-size=4096 --harmony test/*.test.js",
"beautify-lint": "beautify-lint \"lib/**/*.js\" \"hot/**/*.js\" \"bin/**/*.js\" \"benchmark/*.js\" \"test/*.js\"",
"benchmark": "mocha --max-old-space-size=4096 --harmony test/*.benchmark.js -R spec",
"build:examples": "cd examples && node buildAll.js",
"circleci:lint": "npm run lint-files && npm run nsp",
"circleci:test": "node node_modules/mocha/bin/mocha --max-old-space-size=4096 --harmony test/*.test.js",
"cover": "node --max-old-space-size=4096 --harmony ./node_modules/istanbul/lib/cli.js cover -x '**/*.runtime.js' node_modules/mocha/bin/_mocha -- test/*.test.js",
"cover:min": "node --max-old-space-size=4096 --harmony ./node_modules/.bin/istanbul cover -x '**/*.runtime.js' --report lcovonly node_modules/mocha/bin/_mocha -- test/*.test.js",
"fix": "npm run lint -- --fix",
"lint": "eslint lib bin hot buildin \"test/**/webpack.config.js\" \"test/binCases/**/test.js\" \"examples/**/webpack.config.js\"",
"lint-files": "npm run lint && npm run beautify-lint",
"nsp": "nsp check --output summary",
"pretest": "npm run lint-files",
"publish-patch": "npm run lint && npm run beautify-lint && mocha && npm version patch && git push && git push --tags && npm publish",
"test": "mocha test/*.test.js --max-old-space-size=4096 --harmony --check-leaks",
"travis:benchmark": "npm run benchmark",
"travis:lint": "npm run lint-files && npm run nsp",
"travis:test": "npm run cover:min"
}, },
"version": "0.35.1" "version": "0.35.1"
} }

@ -1,185 +1,205 @@
import {workerScripts, import {workerScripts,
addWorkerScript, addWorkerScript,
killWorkerScript} from "./NetscriptWorker.js"; killWorkerScript} from "./NetscriptWorker.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {getServer} from "./Server.js"; import {getServer} from "./Server.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
import {printArray} from "../utils/HelperFunctions.js"; import {printArray, createElement,
import {logBoxCreate} from "../utils/LogBox.js"; createAccordionElement, removeElement,
import numeral from "../utils/numeral.min.js"; removeChildrenFromElement, exceptionAlert} from "../utils/HelperFunctions.js";
import {formatNumber} from "../utils/StringHelperFunctions.js"; import {logBoxCreate} from "../utils/LogBox.js";
import numeral from "../utils/numeral.min.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
/* {
/* Active Scripts UI*/ * serverName: {
function setActiveScriptsClickHandlers() { * header: Server Header Element
//Server panel click handlers * panel: Server Panel List (ul) element
var serverPanels = document.getElementsByClassName("active-scripts-server-header"); * scripts: {
if (serverPanels == null) { * script id: Ref to Script information
console.log("ERROR: Could not find Active Scripts server panels"); * }
return; * }
} * ...
for (i = 0; i < serverPanels.length; ++i) { */
serverPanels[i].onclick = function() { let ActiveScriptsUI = {};
this.classList.toggle("active"); let ActiveScriptsTasks = []; //Sequentially schedule the creation/deletion of UI elements
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
//Script Panel click handlers
var scriptPanels = document.getElementsByClassName("active-scripts-script-header");
if (scriptPanels == null) {
console.log("ERROR: Could not find Active Scripts panels for individual scripts");
return;
}
for (var i = 0; i < scriptPanels.length; ++i) {
scriptPanels[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
}
//Returns the ul element containins all script items for a specific server
function getActiveScriptsServerList(server) {
if (server == null) {return null;}
var panelname = "active-scripts-server-panel-" + server.hostname;
var item = document.getElementById(panelname + "-script-list");
if (item == null) {
console.log("ERROR: Cannot find list for: " + server.hostname);
}
return item;
}
function createActiveScriptsServerPanel(server) { function createActiveScriptsServerPanel(server) {
var panelname = "active-scripts-server-panel-" + server.hostname; ActiveScriptsTasks.push(function(server) {
var activeScriptsList = document.getElementById("active-scripts-list"); let hostname = server.hostname;
//Div of entire Panel var activeScriptsList = document.getElementById("active-scripts-list");
var panelDiv = document.createElement("div");
panelDiv.setAttribute("id", panelname);
//Panel Header let res = createAccordionElement({hdrText:hostname});
var panelHdr = document.createElement("button"); let li = res[0];
panelHdr.setAttribute("class", "active-scripts-server-header") var hdr = res[1];
panelHdr.setAttribute("id", panelname + "-hdr"); let panel = res[2];
panelHdr.innerHTML = server.hostname;
//Panel content if (ActiveScriptsUI[hostname] != null) {
var panelContentDiv = document.createElement("div"); console.log("WARNING: Tried to create already-existing Active Scripts Server panel. This is most likely fine. It probably means many scripts just got started up on a new server. Aborting");
panelContentDiv.setAttribute("class", "active-scripts-server-panel"); return;
panelContentDiv.setAttribute("id", panelname + "-content"); }
//List of scripts var panelScriptList = createElement("ul");
var panelScriptList = document.createElement("ul"); panel.appendChild(panelScriptList);
panelScriptList.setAttribute("id", panelname + "-script-list"); activeScriptsList.appendChild(li);
panelContentDiv.appendChild(panelScriptList); ActiveScriptsUI[hostname] = {
panelDiv.appendChild(panelHdr); header: hdr,
panelDiv.appendChild(panelContentDiv); panel: panel,
activeScriptsList.appendChild(panelDiv); panelList: panelScriptList,
scripts: {}, //Holds references to li elements for each active script
scriptHdrs: {}, //Holds references to header elements for each active script
scriptStats: {} //Holds references to the p elements containing text for each active script
};
setActiveScriptsClickHandlers() //Reset click handlers return li;
}.bind(null, server));
return panelDiv;
} }
//Deletes the info for a particular server (Dropdown header + Panel with all info) //Deletes the info for a particular server (Dropdown header + Panel with all info)
//in the Active Scripts page if it exists //in the Active Scripts page if it exists
function deleteActiveScriptsServerPanel(server) { function deleteActiveScriptsServerPanel(server) {
var panelname = "active-scripts-server-panel-" + server.hostname; ActiveScriptsTasks.push(function(server) {
var panel = document.getElementById(panelname); let hostname = server.hostname;
if (panel == null) { if (ActiveScriptsUI[hostname] == null) {
console.log("No such panel exists: " + panelname); console.log("WARNING: Tried to delete non-existent Active Scripts Server panel. Aborting");
return; return;
} }
//Remove the panel if it has no elements //Make sure it's empty
var scriptList = document.getElementById(panelname + "-script-list"); if (Object.keys(ActiveScriptsUI[hostname].scripts).length > 0) {
if (scriptList.childNodes.length == 0) { console.log("WARNING: Tried to delete Active Scripts Server panel that still has scripts. Aborting");
panel.parentNode.removeChild(panel); return;
} }
removeElement(ActiveScriptsUI[hostname].panel);
removeElement(ActiveScriptsUI[hostname].header);
delete ActiveScriptsUI[hostname];
}.bind(null, server));
} }
function addActiveScriptsItem(workerscript) { function addActiveScriptsItem(workerscript) {
//Get server panel
var server = getServer(workerscript.serverIp); var server = getServer(workerscript.serverIp);
if (server == null) { if (server == null) {
console.log("ERROR: Invalid server IP for workerscript."); console.log("ERROR: Invalid server IP for workerscript in addActiveScriptsItem()");
return; return;
} }
var panelname = "active-scripts-server-panel-" + server.hostname; let hostname = server.hostname;
if (ActiveScriptsUI[hostname] == null) {
var panel = document.getElementById(panelname); createActiveScriptsServerPanel(server);
if (panel == null) {
panel = createActiveScriptsServerPanel(server);
} }
//Create the element itself. Each element is an accordion collapsible ActiveScriptsTasks.push(function(workerscript, hostname) {
var itemNameArray = ["active", "scripts", server.hostname, workerscript.name]; //Create the unique identifier (key) for this script
for (var i = 0; i < workerscript.args.length; ++i) { var itemNameArray = ["active", "scripts", hostname, workerscript.name];
itemNameArray.push(String(workerscript.args[i])); for (var i = 0; i < workerscript.args.length; ++i) {
} itemNameArray.push(String(workerscript.args[i]));
var itemName = itemNameArray.join("-"); }
var item = document.createElement("li"); var itemName = itemNameArray.join("-");
item.setAttribute("id", itemName);
var btn = document.createElement("button"); let res = createAccordionElement({hdrText:workerscript.name});
btn.setAttribute("class", "active-scripts-script-header"); let li = res[0];
btn.innerHTML = workerscript.name; let hdr = res[1];
let panel = res[2];
var itemContentDiv = document.createElement("div"); hdr.classList.remove("accordion-header");
itemContentDiv.setAttribute("class", "active-scripts-script-panel"); hdr.classList.add("active-scripts-script-header");
itemContentDiv.setAttribute("id", itemName + "-content"); panel.classList.remove("accordion-panel");
panel.classList.add("active-scripts-script-panel");
item.appendChild(btn); //Handle the constant elements on the panel that don't change after creation
item.appendChild(itemContentDiv); //Threads, args, kill/log button
panel.appendChild(createElement("p", {
innerHTML: "Threads: " + workerscript.scriptRef.threads + "<br>" +
"Args: " + printArray(workerscript.args)
}));
var panelText = createElement("p", {
innerText:"Loading...", fontSize:"14px",
});
panel.appendChild(panelText);
panel.appendChild(createElement("br"));
panel.appendChild(createElement("span", {
innerText:"Log", class:"active-scripts-button", margin:"4px", padding:"4px",
clickListener:()=>{
logBoxCreate(workerscript.scriptRef);
return false;
}
}));
panel.appendChild(createElement("span", {
innerText:"Kill Script", class:"active-scripts-button", margin:"4px", padding:"4px",
clickListener:()=>{
killWorkerScript(workerscript.scriptRef, workerscript.scriptRef.scriptRef.server);
dialogBoxCreate("Killing script, may take a few minutes to complete...");
return false;
}
}));
createActiveScriptsText(workerscript, itemContentDiv); //Append element to list
ActiveScriptsUI[hostname]["panelList"].appendChild(li);
//Append element to list ActiveScriptsUI[hostname].scripts[itemName] = li;
var list = getActiveScriptsServerList(server); ActiveScriptsUI[hostname].scriptHdrs[itemName] = hdr;
list.appendChild(item); ActiveScriptsUI[hostname].scriptStats[itemName] = panelText;
}.bind(null, workerscript, hostname));
setActiveScriptsClickHandlers() //Reset click handlers
} }
function deleteActiveScriptsItem(workerscript) { function deleteActiveScriptsItem(workerscript) {
var server = getServer(workerscript.serverIp); ActiveScriptsTasks.push(function(workerscript) {
if (server == null) { var server = getServer(workerscript.serverIp);
console.log("ERROR: Invalid server IP for workerscript."); if (server == null) {
return; console.log("ERROR: Invalid server IP for workerscript.");
} return;
var itemNameArray = ["active", "scripts", server.hostname, workerscript.name]; }
for (var i = 0; i < workerscript.args.length; ++i) { let hostname = server.hostname;
itemNameArray.push(String(workerscript.args[i])); if (ActiveScriptsUI[hostname] == null) {
} console.log("ERROR: Trying to delete Active Script UI Element with a hostname that cant be found in ActiveScriptsUI: " + hostname);
var itemName = itemNameArray.join("-"); return;
var li = document.getElementById(itemName); }
if (li == null) {
console.log("could not find Active scripts li element for: " + workerscript.name); var itemNameArray = ["active", "scripts", server.hostname, workerscript.name];
return; for (var i = 0; i < workerscript.args.length; ++i) {
} itemNameArray.push(String(workerscript.args[i]));
li.parentNode.removeChild(li); }
deleteActiveScriptsServerPanel(server); var itemName = itemNameArray.join("-");
let li = ActiveScriptsUI[hostname].scripts[itemName];
if (li == null) {
console.log("ERROR: Cannot find Active Script UI element for workerscript: ");
console.log(workerscript);
return;
}
removeElement(li);
delete ActiveScriptsUI[hostname].scripts[itemName];
delete ActiveScriptsUI[hostname].scriptHdrs[itemName];
delete ActiveScriptsUI[hostname].scriptStats[itemName];
if (Object.keys(ActiveScriptsUI[hostname].scripts).length === 0) {
deleteActiveScriptsServerPanel(server);
}
}.bind(null, workerscript));
} }
//Update the ActiveScriptsItems array //Update the ActiveScriptsItems array
function updateActiveScriptsItems() { function updateActiveScriptsItems() {
//Run tasks that need to be done sequentially (adding items, creating/deleting server panels)
//We'll limit this to 50 at a time in case someone decides to start a bunch of scripts all at once...
let numTasks = Math.min(50, ActiveScriptsTasks.length);
for (let i = 0; i < numTasks; ++i) {
let task = ActiveScriptsTasks.shift();
try {
task();
} catch(e) {
exceptionAlert(e);
console.log(task);
}
}
var total = 0; var total = 0;
for (var i = 0; i < workerScripts.length; ++i) { for (var i = 0; i < workerScripts.length; ++i) {
total += updateActiveScriptsItemContent(workerScripts[i]); try {
total += updateActiveScriptsItemContent(workerScripts[i]);
} catch(e) {
exceptionAlert(e);
}
} }
document.getElementById("active-scripts-total-prod").innerHTML = document.getElementById("active-scripts-total-prod").innerHTML =
"Total online production of Active Scripts: " + numeral(total).format('$0.000a') + " / sec<br>" + "Total online production of Active Scripts: " + numeral(total).format('$0.000a') + " / sec<br>" +
@ -196,69 +216,50 @@ function updateActiveScriptsItemContent(workerscript) {
console.log("ERROR: Invalid server IP for workerscript."); console.log("ERROR: Invalid server IP for workerscript.");
return; return;
} }
let hostname = server.hostname;
if (ActiveScriptsUI[hostname] == null) {
return; //Hasn't been created yet. We'll skip it
}
var itemNameArray = ["active", "scripts", server.hostname, workerscript.name]; var itemNameArray = ["active", "scripts", server.hostname, workerscript.name];
for (var i = 0; i < workerscript.args.length; ++i) { for (var i = 0; i < workerscript.args.length; ++i) {
itemNameArray.push(String(workerscript.args[i])); itemNameArray.push(String(workerscript.args[i]));
} }
var itemName = itemNameArray.join("-"); var itemName = itemNameArray.join("-");
var itemContent = document.getElementById(itemName + "-content")
//Add the updated text back. Returns the total online production rate if (ActiveScriptsUI[hostname].scriptStats[itemName] == null) {
return updateActiveScriptsText(workerscript, itemContent); return; //Hasn't been fully added yet. We'll skip it
}
var item = ActiveScriptsUI[hostname].scriptStats[itemName];
//Update the text if necessary. This fn returns the online $/s production
return updateActiveScriptsText(workerscript, item, itemName);
} }
function createActiveScriptsText(workerscript, item) { function updateActiveScriptsText(workerscript, item, itemName) {
var itemTextHeader = document.createElement("p"); var server = getServer(workerscript.serverIp);
var itemTextStats = document.createElement("p"); if (server == null) {
var itemId = item.id; console.log("ERROR: Invalid server IP for workerscript.");
itemTextStats.setAttribute("id", itemId + "-stats"); return;
}
//Server ip/hostname let hostname = server.hostname;
var threads = "Threads: " + workerscript.scriptRef.threads; if (ActiveScriptsUI[hostname] == null || ActiveScriptsUI[hostname].scriptHdrs[itemName] == null) {
var args = "Args: " + printArray(workerscript.args); console.log("ERROR: Trying to update Active Script UI Element with a hostname that cant be found in ActiveScriptsUI: " + hostname);
return;
itemTextHeader.innerHTML = threads + "<br>" + args + "<br>";
item.appendChild(itemTextHeader);
item.appendChild(itemTextStats);
var onlineMps = updateActiveScriptsText(workerscript, item, itemTextStats);
var logButton = document.createElement("span");
logButton.innerHTML = "Log";
var killButton = document.createElement("span");
killButton.innerHTML = "Kill script";
logButton.setAttribute("class", "active-scripts-button");
killButton.setAttribute("class", "active-scripts-button");
logButton.addEventListener("click", function() {
logBoxCreate(workerscript.scriptRef);
return false;
});
killButton.addEventListener("click", function() {
killWorkerScript(workerscript.scriptRef, workerscript.scriptRef.scriptRef.server);
dialogBoxCreate("Killing script, may take a few minutes to complete...");
return false;
});
item.appendChild(logButton);
item.appendChild(killButton);
//Return total online production rate
return onlineMps;
}
function updateActiveScriptsText(workerscript, item, statsEl=null) {
var itemId = item.id
var itemTextStats = document.getElementById(itemId + "-stats");
if (itemTextStats == null || itemTextStats === undefined) {
itemTextStats = statsEl;
} }
//Updates statistics only var onlineMps = workerscript.scriptRef.onlineMoneyMade / workerscript.scriptRef.onlineRunningTime;
//Only update if the item is visible
if (ActiveScriptsUI[hostname].header.classList.contains("active") === false) {return onlineMps;}
if (ActiveScriptsUI[hostname].scriptHdrs[itemName].classList.contains("active") === false) {return onlineMps;}
removeChildrenFromElement(item);
//Online //Online
var onlineTotalMoneyMade = "Total online production: $" + formatNumber(workerscript.scriptRef.onlineMoneyMade, 2); var onlineTotalMoneyMade = "Total online production: $" + formatNumber(workerscript.scriptRef.onlineMoneyMade, 2);
var onlineTotalExpEarned = (Array(26).join(" ") + formatNumber(workerscript.scriptRef.onlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;"); var onlineTotalExpEarned = (Array(26).join(" ") + formatNumber(workerscript.scriptRef.onlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;");
var onlineMps = workerscript.scriptRef.onlineMoneyMade / workerscript.scriptRef.onlineRunningTime;
var onlineMpsText = "Online production rate: $" + formatNumber(onlineMps, 2) + "/second"; var onlineMpsText = "Online production rate: $" + formatNumber(onlineMps, 2) + "/second";
var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime; var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime;
var onlineEpsText = (Array(25).join(" ") + formatNumber(onlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;"); var onlineEpsText = (Array(25).join(" ") + formatNumber(onlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
@ -272,10 +273,10 @@ function updateActiveScriptsText(workerscript, item, statsEl=null) {
var offlineEps = workerscript.scriptRef.offlineExpGained / workerscript.scriptRef.offlineRunningTime; var offlineEps = workerscript.scriptRef.offlineExpGained / workerscript.scriptRef.offlineRunningTime;
var offlineEpsText = (Array(26).join(" ") + formatNumber(offlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;"); var offlineEpsText = (Array(26).join(" ") + formatNumber(offlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
itemTextStats.innerHTML = onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" + item.innerHTML = onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" +
onlineMpsText + "<br>" + onlineEpsText + "<br>" + offlineTotalMoneyMade + "<br>" + offlineTotalExpEarned + "<br>" + onlineMpsText + "<br>" + onlineEpsText + "<br>" + offlineTotalMoneyMade + "<br>" + offlineTotalExpEarned + "<br>" +
offlineMpsText + "<br>" + offlineEpsText + "<br>"; offlineMpsText + "<br>" + offlineEpsText + "<br>";
return onlineMps; return onlineMps;
} }
export {setActiveScriptsClickHandlers, addActiveScriptsItem, deleteActiveScriptsItem, updateActiveScriptsItems}; export {addActiveScriptsItem, deleteActiveScriptsItem, updateActiveScriptsItems};

@ -105,10 +105,10 @@ function initBitNodes() {
"for progression. Furthermore:<br><br>" + "for progression. Furthermore:<br><br>" +
"Hacking and Hacknet Nodes will be significantly less profitable<br>" + "Hacking and Hacknet Nodes will be significantly less profitable<br>" +
"Your hacking level is reduced by 50%<br>" + "Your hacking level is reduced by 50%<br>" +
"Hacking experience gain from scripts is reduced by 80%<br>" + "Hacking experience gain from scripts is reduced by 75%<br>" +
"Corporations have 80% lower valuations and are therefore less profitable<br>" + "Corporations have 80% lower valuations and are therefore less profitable<br>" +
"Working for companies is 50% less profitable<br>" + "Working for companies is 50% less profitable<br>" +
"Crimes and Infiltration are 75% less profitable<br><br>" + "Crimes and Infiltration are 50% less profitable<br><br>" +
"Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade " + "Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade " +
"its level up to a maximum of 3. This Source-File allows you to access the NSA's Bladeburner Division in other " + "its level up to a maximum of 3. This Source-File allows you to access the NSA's Bladeburner Division in other " +
"BitNodes. In addition, this Source-File will raise the experience gain rate of all your combat stats by:<br><br>" + "BitNodes. In addition, this Source-File will raise the experience gain rate of all your combat stats by:<br><br>" +
@ -274,12 +274,12 @@ function initBitNodeMultipliers() {
BitNodeMultipliers.ServerStartingSecurity = 1.5; BitNodeMultipliers.ServerStartingSecurity = 1.5;
BitNodeMultipliers.ScriptHackMoney = 0.5; BitNodeMultipliers.ScriptHackMoney = 0.5;
BitNodeMultipliers.CompanyWorkMoney = 0.5; BitNodeMultipliers.CompanyWorkMoney = 0.5;
BitNodeMultipliers.CrimeMoney = 0.25; BitNodeMultipliers.CrimeMoney = 0.5;
BitNodeMultipliers.InfiltrationMoney = 0.25; BitNodeMultipliers.InfiltrationMoney = 0.5;
BitNodeMultipliers.CorporationValuation = 0.2; BitNodeMultipliers.CorporationValuation = 0.2;
BitNodeMultipliers.HacknetNodeMoney = 0.2; BitNodeMultipliers.HacknetNodeMoney = 0.2;
BitNodeMultipliers.FactionPassiveRepGain = 0; BitNodeMultipliers.FactionPassiveRepGain = 0;
BitNodeMultipliers.HackExpGain = 0.2; BitNodeMultipliers.HackExpGain = 0.25;
break; break;
case 8: //Ghost of Wall Street case 8: //Ghost of Wall Street
BitNodeMultipliers.ScriptHackMoney = 0; BitNodeMultipliers.ScriptHackMoney = 0;

@ -24,7 +24,7 @@ var CityNames = ["Aevum", "Chongqing", "Sector-12", "New Tokyo", "Ishima", "Volh
var CyclesPerSecond = 5; //Game cycle is 200 ms var CyclesPerSecond = 5; //Game cycle is 200 ms
var StaminaGainPerSecond = 0.0085; var StaminaGainPerSecond = 0.0085;
var BaseStaminaLoss = 0.29; //Base stamina loss per action. Increased based on difficulty var BaseStaminaLoss = 0.285; //Base stamina loss per action. Increased based on difficulty
var MaxStaminaToGainFactor = 70000; //Max Stamina is divided by this to get bonus stamina gain var MaxStaminaToGainFactor = 70000; //Max Stamina is divided by this to get bonus stamina gain
var DifficultyToTimeFactor = 10; //Action Difficulty divided by this to get base action time var DifficultyToTimeFactor = 10; //Action Difficulty divided by this to get base action time
@ -691,9 +691,9 @@ Bladeburner.prototype.create = function() {
"and information-gathering ONLY. Do NOT engage. Stealth is of the utmost importance.<br><br>" + "and information-gathering ONLY. Do NOT engage. Stealth is of the utmost importance.<br><br>" +
"Successfully completing Tracking contracts will slightly improve your Synthoid population estimate for " + "Successfully completing Tracking contracts will slightly improve your Synthoid population estimate for " +
"whatever city you are currently in.", "whatever city you are currently in.",
baseDifficulty:150,difficultyFac:1.02,rewardFac:1.041, baseDifficulty:125,difficultyFac:1.02,rewardFac:1.041,
rankGain:0.3, hpLoss:0.5, rankGain:0.3, hpLoss:0.5,
count:getRandomInt(400, 800), countGrowth:getRandomInt(1, 5), count:getRandomInt(300, 800), countGrowth:getRandomInt(1, 5),
weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05}, weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1},
isStealth:true isStealth:true
@ -705,7 +705,7 @@ Bladeburner.prototype.create = function() {
"current city, and will also increase its chaos level.", "current city, and will also increase its chaos level.",
baseDifficulty:250, difficultyFac:1.04,rewardFac:1.085, baseDifficulty:250, difficultyFac:1.04,rewardFac:1.085,
rankGain:0.9, hpLoss:1, rankGain:0.9, hpLoss:1,
count:getRandomInt(250, 500), countGrowth:getRandomInt(1, 3), count:getRandomInt(200, 750), countGrowth:getRandomInt(1, 3),
weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1}, weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
isKill:true isKill:true
@ -717,7 +717,7 @@ Bladeburner.prototype.create = function() {
"city, and will also increase its chaos level.", "city, and will also increase its chaos level.",
baseDifficulty:200, difficultyFac:1.03, rewardFac:1.065, baseDifficulty:200, difficultyFac:1.03, rewardFac:1.065,
rankGain:0.6, hpLoss:1, rankGain:0.6, hpLoss:1,
count:getRandomInt(300, 600), countGrowth:getRandomInt(1,4), count:getRandomInt(300, 900), countGrowth:getRandomInt(1,4),
weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1}, weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
isKill:true isKill:true
@ -732,7 +732,7 @@ Bladeburner.prototype.create = function() {
"You will NOT lose HP from failed Investigation ops.", "You will NOT lose HP from failed Investigation ops.",
baseDifficulty:400, difficultyFac:1.03,rewardFac:1.07,reqdRank:25, baseDifficulty:400, difficultyFac:1.03,rewardFac:1.07,reqdRank:25,
rankGain:2, rankLoss:0.2, rankGain:2, rankLoss:0.2,
count:getRandomInt(100, 300), countGrowth:1, count:getRandomInt(50, 400), countGrowth:1,
weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1}, weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1},
decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
isStealth:true isStealth:true
@ -745,7 +745,7 @@ Bladeburner.prototype.create = function() {
"data.", "data.",
baseDifficulty:500, difficultyFac:1.04, rewardFac:1.09, reqdRank:100, baseDifficulty:500, difficultyFac:1.04, rewardFac:1.09, reqdRank:100,
rankGain:4, rankLoss:0.4, hpLoss:2, rankGain:4, rankLoss:0.4, hpLoss:2,
count:getRandomInt(100, 250), countGrowth:1, count:getRandomInt(50, 300), countGrowth:1,
weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1}, weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1},
decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
isStealth:true isStealth:true
@ -756,7 +756,7 @@ Bladeburner.prototype.create = function() {
"notorious Synthoid criminals.", "notorious Synthoid criminals.",
baseDifficulty:650, difficultyFac:1.04, rewardFac:1.095, reqdRank:500, baseDifficulty:650, difficultyFac:1.04, rewardFac:1.095, reqdRank:500,
rankGain:5, rankLoss:0.5, hpLoss:2.5, rankGain:5, rankLoss:0.5, hpLoss:2.5,
count:getRandomInt(100,250), countGrowth:0.75, count:getRandomInt(25,400), countGrowth:0.75,
weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1}, weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1},
decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9}, decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9},
isStealth:true isStealth:true
@ -768,7 +768,7 @@ Bladeburner.prototype.create = function() {
"in order for this Operation to be successful", "in order for this Operation to be successful",
baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000, baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000,
rankGain:50,rankLoss:2.5,hpLoss:50, rankGain:50,rankLoss:2.5,hpLoss:50,
count:getRandomInt(50, 100), countGrowth:0.2, count:getRandomInt(25, 150), countGrowth:0.2,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
isKill:true isKill:true
@ -780,7 +780,7 @@ Bladeburner.prototype.create = function() {
"drawing any attention. Stealth and discretion are key.", "drawing any attention. Stealth and discretion are key.",
baseDifficulty:1000, difficultyFac:1.05, rewardFac:1.11, reqdRank:20e3, baseDifficulty:1000, difficultyFac:1.05, rewardFac:1.11, reqdRank:20e3,
rankGain:20, rankLoss:2, hpLoss:10, rankGain:20, rankLoss:2, hpLoss:10,
count:getRandomInt(50, 200), countGrowth:0.1, count:getRandomInt(25, 250), countGrowth:0.1,
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
isStealth:true, isKill:true isStealth:true, isKill:true
@ -792,7 +792,7 @@ Bladeburner.prototype.create = function() {
"in the Synthoid communities.", "in the Synthoid communities.",
baseDifficulty:1500, difficultyFac:1.06, rewardFac:1.14, reqdRank:50e3, baseDifficulty:1500, difficultyFac:1.06, rewardFac:1.14, reqdRank:50e3,
rankGain:40, rankLoss:4, hpLoss:5, rankGain:40, rankLoss:4, hpLoss:5,
count:getRandomInt(50, 150), countGrowth:0.1, count:getRandomInt(25, 200), countGrowth:0.1,
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8},
isStealth:true, isKill:true isStealth:true, isKill:true
@ -3149,9 +3149,9 @@ function initBladeburner() {
Skills[SkillNames.BladesIntuition] = new Skill({ Skills[SkillNames.BladesIntuition] = new Skill({
name:SkillNames.BladesIntuition, name:SkillNames.BladesIntuition,
desc:"Each level of this skill increases your success chance " + desc:"Each level of this skill increases your success chance " +
"for all contracts and operations by 2%", "for all contracts and operations by 3%",
baseCost:5, costInc:2, baseCost:5, costInc:2,
successChanceAll:2 successChanceAll:3
}); });
Skills[SkillNames.Reaper] = new Skill({ Skills[SkillNames.Reaper] = new Skill({
name:SkillNames.Reaper, name:SkillNames.Reaper,
@ -3163,9 +3163,9 @@ function initBladeburner() {
Skills[SkillNames.Cloak] = new Skill({ Skills[SkillNames.Cloak] = new Skill({
name:SkillNames.Cloak, name:SkillNames.Cloak,
desc:"Each level of this skill increases your " + desc:"Each level of this skill increases your " +
"success chance in stealth-related contracts and operations by 5%", "success chance in stealth-related contracts and operations by 5.5%",
baseCost:3, costInc:1, baseCost:3, costInc:1,
successChanceStealth:5 successChanceStealth:5.5
}); });
//TODO Marksman //TODO Marksman
@ -3188,32 +3188,32 @@ function initBladeburner() {
Skills[SkillNames.ShortCircuit] = new Skill({ Skills[SkillNames.ShortCircuit] = new Skill({
name:SkillNames.ShortCircuit, name:SkillNames.ShortCircuit,
desc:"Each level of this skill increases your success chance " + desc:"Each level of this skill increases your success chance " +
"in contracts and operations that involve retirement by 5%", "in contracts and operations that involve retirement by 5.5%",
baseCost:3, costInc:2, baseCost:3, costInc:2,
successChanceKill:5 successChanceKill:5.5
}); });
Skills[SkillNames.DigitalObserver] = new Skill({ Skills[SkillNames.DigitalObserver] = new Skill({
name:SkillNames.DigitalObserver, name:SkillNames.DigitalObserver,
desc:"Each level of this skill increases your success chance in " + desc:"Each level of this skill increases your success chance in " +
"all operations by 3%", "all operations by 4%",
baseCost:5, costInc:2, baseCost:5, costInc:2,
successChanceOperation:3 successChanceOperation:4
}); });
Skills[SkillNames.Datamancer] = new Skill({ Skills[SkillNames.Datamancer] = new Skill({
name:SkillNames.Datamancer, name:SkillNames.Datamancer,
desc:"Each level of this skill increases your effectiveness in " + desc:"Each level of this skill increases your effectiveness in " +
"synthoid population analysis and investigation by 4%. " + "synthoid population analysis and investigation by 5%. " +
"This affects all actions that can potentially increase " + "This affects all actions that can potentially increase " +
"the accuracy of your synthoid population/community estimates.", "the accuracy of your synthoid population/community estimates.",
baseCost:3,costInc:1, baseCost:3,costInc:1,
successChanceEstimate:4 successChanceEstimate:5
}); });
Skills[SkillNames.Tracer] = new Skill({ Skills[SkillNames.Tracer] = new Skill({
name:SkillNames.Tracer, name:SkillNames.Tracer,
desc:"Each level of this skill increases your success chance in " + desc:"Each level of this skill increases your success chance in " +
"all contracts by 3%", "all contracts by 4%",
baseCost:3, costInc:2, baseCost:3, costInc:2,
successChanceContract:3 successChanceContract:4
}); });
Skills[SkillNames.CybersEdge] = new Skill({ Skills[SkillNames.CybersEdge] = new Skill({
name:SkillNames.CybersEdge, name:SkillNames.CybersEdge,

@ -40,6 +40,7 @@ let CONSTANTS = {
/* Netscript Constants */ /* Netscript Constants */
//RAM Costs for different commands //RAM Costs for different commands
ScriptBaseRamCost: 1.4,
ScriptWhileRamCost: 0.2, ScriptWhileRamCost: 0.2,
ScriptForRamCost: 0.2, ScriptForRamCost: 0.2,
ScriptIfRamCost: 0.15, ScriptIfRamCost: 0.15,
@ -690,6 +691,7 @@ let CONSTANTS = {
"hostname/ip, regardless of arguments. Returns true if one or more scripts were successfully killed, and false if there were none. <br><br>" + "hostname/ip, regardless of arguments. Returns true if one or more scripts were successfully killed, and false if there were none. <br><br>" +
"The first argument must be a string with the name of the script. The script name is case sensitive. The second argument is " + "The first argument must be a string with the name of the script. The script name is case sensitive. The second argument is " +
"a string with the hostname or IP of the target server. Both arguments are required.<br><br>" + "a string with the hostname or IP of the target server. Both arguments are required.<br><br>" +
"<i><u>getScriptName()</u></i><br>Returns the filename of the current script (including the extension)<br><br>" +
"<i><u>getScriptRam(scriptname, hostname/ip)</u></i><br>Returns the amount of RAM required to run the specified script on the " + "<i><u>getScriptRam(scriptname, hostname/ip)</u></i><br>Returns the amount of RAM required to run the specified script on the " +
"target server. The first argument must be a string with the name of the script. The script name is case sensitive. " + "target server. The first argument must be a string with the name of the script. The script name is case sensitive. " +
"The second argument is a string with the hostname or IP of the server where that script is. Both arguments are required.<br><br>" + "The second argument is a string with the hostname or IP of the server where that script is. Both arguments are required.<br><br>" +
@ -1138,6 +1140,24 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.36.1<br>" +
"* Bladeburner Changes: <br>" +
"** Bug Fix: You can no longer get Bladeburner faction reputation through Infiltration<br>" +
"** Initial difficulty of Tracking contracts reduced<br>" +
"** Datamancer skill effect increased from 4% per level to 5%<br>" +
"** Slightly decreased the base stamina cost of contracts/operations<br>" +
"** Slightly increased the effects of the Tracer, Digital Observer, Short Circuit, Cloak, and Blade's Intuition skills<br>" +
"* Crime, Infiltration, and Hacking are now slightly more profitable in BN-6<br>" +
"* Added getScriptName() and getHacknetMultipliers() Netscript functions (added by Github user hydroflame)<br>" +
"* getScriptRam() Netscript function now has default value for the second argument, which is hostname/ip (implemented by Github user hydroflame)<br>" +
"* There is now a soft-cap on stock price, which means it's no longer possible for the price of a stock to reach insanely-high values<br>" +
"* The ctrl+b hotkey in the text editor is now also triggered by command+b or winkey+b<br>" +
"* Many servers now have additional RAM<br>" +
"* Added an option to disable hotkeys/keyboard shortcuts<br>" +
"* Refactored 'Active Scripts' UI page to optimize its performance<br>" +
"* Added a new .fconf setting: ENABLE_TIMESTAMP<br>" +
"* Bug Fix: Fixed a typo in the Fulcrum Technologies company name (Technolgies -> Technologies)<br>" +
"* Bug Fix: hacknetnodes keyword should no longer incur RAM cost if its in a comment<br>" +
"v0.36.0<br>" + "v0.36.0<br>" +
"* Added BN-6: Bladeburners<br>" + "* Added BN-6: Bladeburners<br>" +
"* Rebalanced many combat Augmentations so that they are slightly less powerful<br>" + "* Rebalanced many combat Augmentations so that they are slightly less powerful<br>" +

@ -1,7 +1,8 @@
import {parse, Node} from "../utils/acorn.js"; import {parse, Node} from "../utils/acorn.js";
var FconfSettings = { var FconfSettings = {
ENABLE_BASH_HOTKEYS: false ENABLE_BASH_HOTKEYS: false,
ENABLE_TIMESTAMPS: false,
} }
var FconfComments = { var FconfComments = {
@ -12,6 +13,8 @@ var FconfComments = {
"shortcuts.\n\n" + "shortcuts.\n\n" +
"To see a full list of the Terminal shortcuts that this enables, see:\n" + "To see a full list of the Terminal shortcuts that this enables, see:\n" +
"http://bitburner.readthedocs.io/en/latest/shortcuts.html", "http://bitburner.readthedocs.io/en/latest/shortcuts.html",
ENABLE_TIMESTAMPS: "Terminal commands and log entries will be timestamped. The timestamp\n" +
"will have the format: M/D h:m",
} }
//Parse Fconf settings from the config text //Parse Fconf settings from the config text
@ -70,6 +73,7 @@ function parseFconfSetting(setting, value) {
//Needed to convert entered value to boolean/strings accordingly //Needed to convert entered value to boolean/strings accordingly
switch(setting) { switch(setting) {
case "ENABLE_BASH_HOTKEYS": case "ENABLE_BASH_HOTKEYS":
case "ENABLE_TIMESTAMPS":
var value = value.toLowerCase(); var value = value.toLowerCase();
if (value === "1" || value === "true" || value === "y") { if (value === "1" || value === "true" || value === "y") {
value = true; value = true;
@ -105,14 +109,19 @@ function createFconf() {
} else { } else {
value = String(FconfSettings[setting]); value = String(FconfSettings[setting]);
} }
res += (setting + "=" + value + "\n"); res += (setting + "=" + value + "\n\n");
} }
} }
return res; return res;
} }
function loadFconf(saveString) { function loadFconf(saveString) {
FconfSettings = JSON.parse(saveString); let tempFconfSettings = JSON.parse(saveString);
for (var setting in tempFconfSettings) {
if (tempFconfSettings.hasOwnProperty(setting)) {
FconfSettings[setting] = tempFconfSettings[setting];
}
}
} }
export {FconfSettings, createFconf, parseFconfSettings, loadFconf} export {FconfSettings, createFconf, parseFconfSettings, loadFconf}

@ -1170,12 +1170,24 @@ function updateGangContent() {
for (var gangname in AllGangs) { for (var gangname in AllGangs) {
if (AllGangs.hasOwnProperty(gangname)) { if (AllGangs.hasOwnProperty(gangname)) {
var gangTerritoryInfo = AllGangs[gangname]; var gangTerritoryInfo = AllGangs[gangname];
let territory = gangTerritoryInfo.territory*100;
//Fix some rounding issues graphically
let displayNumber;
if (territory <= 0) {
displayNumber = formatNumber(0, 2);
} else if (territory >= 100) {
displayNumber = formatNumber(100, 2);
} else {
displayNumber = formatNumber(territory, 2);
}
if (gangname == Player.gang.facName) { if (gangname == Player.gang.facName) {
gangTerritoryInfoText.innerHTML += ("<b>" + gangname + "</b><br>(Power: " + formatNumber(gangTerritoryInfo.power, 6) + "): " + gangTerritoryInfoText.innerHTML += ("<b>" + gangname + "</b><br>(Power: " + formatNumber(gangTerritoryInfo.power, 6) + "): " +
formatNumber(100*gangTerritoryInfo.territory, 2) + "%<br><br>"); displayNumber + "%<br><br>");
} else { } else {
gangTerritoryInfoText.innerHTML += (gangname + "<br>(Power: " + formatNumber(gangTerritoryInfo.power, 6) + "): " + gangTerritoryInfoText.innerHTML += (gangname + "<br>(Power: " + formatNumber(gangTerritoryInfo.power, 6) + "): " +
formatNumber(100*gangTerritoryInfo.territory, 2) + "%<br><br>"); displayNumber + "%<br><br>");
} }
} }
} }
@ -1227,10 +1239,19 @@ function updateGangContent() {
})); }));
gangInfo.appendChild(createElement("br", {})); gangInfo.appendChild(createElement("br", {}));
var territoryMult = AllGangs[Player.gang.facName].territory; //Fix some rounding issues graphically
var territoryMult = AllGangs[Player.gang.facName].territory * 100;
let displayNumber;
if (territoryMult <= 0) {
displayNumber = formatNumber(0, 2);
} else if (territoryMult >= 100) {
displayNumber = formatNumber(100, 2);
} else {
displayNumber = formatNumber(territoryMult, 2);
}
gangInfo.appendChild(createElement("p", { //Territory multiplier gangInfo.appendChild(createElement("p", { //Territory multiplier
display:"inline-block", display:"inline-block",
innerText:"Territory: " + formatNumber(territoryMult * 100, 3) + "%", innerText:"Territory: " + formatNumber(displayNumber, 3) + "%",
tooltip:"The percentage of total territory your Gang controls" tooltip:"The percentage of total territory your Gang controls"
})); }));
gangInfo.appendChild(createElement("br", {})); gangInfo.appendChild(createElement("br", {}));

@ -52,7 +52,7 @@ var Locations = {
AevumECorp: "ECorp", AevumECorp: "ECorp",
AevumBachmanAndAssociates: "Bachman & Associates", AevumBachmanAndAssociates: "Bachman & Associates",
AevumClarkeIncorporated: "Clarke Incorporated", AevumClarkeIncorporated: "Clarke Incorporated",
AevumFulcrumTechnologies: "Fulcrum Technolgies", AevumFulcrumTechnologies: "Fulcrum Technologies",
AevumAeroCorp: "AeroCorp", AevumAeroCorp: "AeroCorp",
AevumGalacticCybersystems: "Galactic Cybersystems", AevumGalacticCybersystems: "Galactic Cybersystems",
AevumWatchdogSecurity: "Watchdog Security", AevumWatchdogSecurity: "Watchdog Security",
@ -2013,7 +2013,10 @@ function purchaseTorRouter() {
} }
Player.loseMoney(CONSTANTS.TorRouterCost); Player.loseMoney(CONSTANTS.TorRouterCost);
var darkweb = new Server(createRandomIp(), "darkweb", "", false, false, false, 1); var darkweb = new Server({
ip:createRandomIp(), hostname:"darkweb", organizationName:"",
isConnectedTo:false, adminRights:false, purchasedByPlayer:false, maxRam:1
});
AddToAllServers(darkweb); AddToAllServers(darkweb);
SpecialServerIps.addIp("Darkweb Server", darkweb.ip); SpecialServerIps.addIp("Darkweb Server", darkweb.ip);

@ -32,7 +32,8 @@ import {Locations} from "./Location.js";
import {Message, Messages} from "./Message.js"; import {Message, Messages} from "./Message.js";
import {inMission} from "./Missions.js"; import {inMission} from "./Missions.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {Script, findRunningScript, RunningScript} from "./Script.js"; import {Script, findRunningScript, RunningScript,
isScriptFilename} from "./Script.js";
import {Server, getServer, AddToAllServers, import {Server, getServer, AddToAllServers,
AllServers, processSingleServerGrowth, AllServers, processSingleServerGrowth,
GetServerByHostname} from "./Server.js"; GetServerByHostname} from "./Server.js";
@ -73,6 +74,55 @@ var hasCorporationSF=false, //Source-File 3
hasBn11SF=false; //Source-File 11 hasBn11SF=false; //Source-File 11
var possibleLogs = {
ALL: true,
scan: true,
hack: true,
sleep: true,
disableLog: true,
enableLog: true,
grow: true,
weaken: true,
nuke: true,
brutessh: true,
ftpcrack: true,
relaysmtp: true,
httpworm: true,
sqlinject: true,
spawn: true,
kill: true,
killall: true,
scp: true,
getHackingLevel: true,
getServerMoneyAvailable: true,
getServerSecurityLevel: true,
getServerBaseSecurityLevel: true,
getServerMinSecurityLevel: true,
getServerRequiredHackingLevel: true,
getServerMaxMoney: true,
getServerGrowth: true,
getServerNumPortsRequired: true,
getServerRam: true,
buyStock: true,
sellStock: true,
purchaseServer: true,
deleteServer: true,
universityCourse: true,
gymWorkout: true,
travelToCity: true,
purchaseTor: true,
purchaseProgram: true,
stopAction: true,
upgradeHomeRam: true,
workForCompany: true,
applyToCompany: true,
joinFaction: true,
workForFaction: true,
createProgram: true,
commitCrime: true,
shortStock: true,
sellShort: true,
}
var singularitySFLvl=1, wallStreetSFLvl=1; var singularitySFLvl=1, wallStreetSFLvl=1;
@ -353,13 +403,23 @@ function NetscriptFunctions(workerScript) {
}, },
disableLog : function(fn) { disableLog : function(fn) {
if (workerScript.checkingRam) {return 0;} if (workerScript.checkingRam) {return 0;}
if(possibleLogs[fn]===undefined) {
throw makeRuntimeRejectMsg(workerScript, "Invalid argument to disableLog: "+fn);
}
workerScript.disableLogs[fn] = true; workerScript.disableLogs[fn] = true;
workerScript.scriptRef.log("Disabled logging for " + fn); if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.disableLog == null) {
workerScript.scriptRef.log("Disabled logging for " + fn);
}
}, },
enableLog : function(fn) { enableLog : function(fn) {
if (workerScript.checkingRam) {return 0;} if (workerScript.checkingRam) {return 0;}
if(possibleLogs[fn]===undefined) {
throw makeRuntimeRejectMsg(workerScript, "Invalid argument to enableLog: "+fn);
}
delete workerScript.disableLogs[fn]; delete workerScript.disableLogs[fn];
workerScript.scriptRef.log("Enabled logging for " + fn); if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.enableLog == null) {
workerScript.scriptRef.log("Enabled logging for " + fn);
}
}, },
nuke : function(ip){ nuke : function(ip){
if (workerScript.checkingRam) { if (workerScript.checkingRam) {
@ -741,7 +801,7 @@ function NetscriptFunctions(workerScript) {
}); });
return res; return res;
} }
if (!scriptname.endsWith(".lit") && !scriptname.endsWith(".script") && if (!scriptname.endsWith(".lit") && !isScriptFilename(scriptname) &&
!scriptname.endsWith("txt")) { !scriptname.endsWith("txt")) {
throw makeRuntimeRejectMsg(workerScript, "Error: scp() does not work with this file type. It only works for .script, .lit, and .txt files"); throw makeRuntimeRejectMsg(workerScript, "Error: scp() does not work with this file type. It only works for .script, .lit, and .txt files");
} }
@ -1035,6 +1095,23 @@ function NetscriptFunctions(workerScript) {
growth: Player.hacking_grow_mult, growth: Player.hacking_grow_mult,
}; };
}, },
getHacknetMultipliers : function() {
if (workerScript.checkingRam) {
if (workerScript.loadedFns.getHacknetMultipliers) {
return 0;
} else {
workerScript.loadedFns.getHacknetMultipliers = true;
return CONSTANTS.ScriptGetMultipliersRamCost;
}
}
return {
production: Player.hacknet_node_money_mult,
purchaseCost: Player.hacknet_node_purchase_cost_mult,
ramCost: Player.hacknet_node_ram_cost_mult,
coreCost: Player.hacknet_node_core_cost_mult,
levelCost: Player.hacknet_node_level_cost_mult,
};
},
getBitNodeMultipliers: function() { getBitNodeMultipliers: function() {
if (workerScript.checkingRam) { if (workerScript.checkingRam) {
if (workerScript.loadedFns.getBitNodeMultipliers) { if (workerScript.loadedFns.getBitNodeMultipliers) {
@ -1632,7 +1709,15 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("Error: Not enough money to purchase server. Need $" + formatNumber(cost, 2)); workerScript.scriptRef.log("Error: Not enough money to purchase server. Need $" + formatNumber(cost, 2));
return ""; return "";
} }
var newServ = new Server(createRandomIp(), hostnameStr, "", false, true, true, ram); var newServ = new Server({
ip: createRandomIp(),
hostname: hostnameStr,
organizationName: "",
isConnectedTo: false,
adminRights: true,
purchasedByPlayer: true,
maxRam: ram,
});
AddToAllServers(newServ); AddToAllServers(newServ);
Player.purchasedServers.push(newServ.ip); Player.purchasedServers.push(newServ.ip);
@ -1917,7 +2002,7 @@ function NetscriptFunctions(workerScript) {
return true; return true;
} }
} }
} else if (fn.endsWith(".script")) { } else if (isScriptFilename(fn)) {
for (var i = 0; i < s.scripts.length; ++i) { for (var i = 0; i < s.scripts.length; ++i) {
if (s.scripts[i].filename === fn) { if (s.scripts[i].filename === fn) {
//Check that the script isnt currently running //Check that the script isnt currently running
@ -1993,7 +2078,11 @@ function NetscriptFunctions(workerScript) {
} }
return suc; return suc;
}, },
getScriptRam : function (scriptname, ip) { getScriptName : function() {
if (workerScript.checkingRam) {return 0;}
return workerScript.name;
},
getScriptRam : function (scriptname, ip=workerScript.serverIp) {
if (workerScript.checkingRam) { if (workerScript.checkingRam) {
if (workerScript.loadedFns.getScriptRam) { if (workerScript.loadedFns.getScriptRam) {
return 0; return 0;
@ -2431,7 +2520,10 @@ function NetscriptFunctions(workerScript) {
} }
Player.loseMoney(CONSTANTS.TorRouterCost); Player.loseMoney(CONSTANTS.TorRouterCost);
var darkweb = new Server(createRandomIp(), "darkweb", "", false, false, false, 1); var darkweb = new Server({
ip:createRandomIp(), hostname:"darkweb", organizationName:"",
isConnectedTo:false, adminRights:false, purchasedByPlayer:false, maxRam:1
});
AddToAllServers(darkweb); AddToAllServers(darkweb);
SpecialServerIps.addIp("Darkweb Server", darkweb.ip); SpecialServerIps.addIp("Darkweb Server", darkweb.ip);
@ -3298,41 +3390,42 @@ function NetscriptFunctions(workerScript) {
} }
crime = crime.toLowerCase(); crime = crime.toLowerCase();
let enableCommitCrimeLog = workerScript.disableLogs.ALL == null && workerScript.disableLogs.commitCrime == null
if (crime.includes("shoplift")) { if (crime.includes("shoplift")) {
workerScript.scriptRef.log("Attempting to shoplift..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to shoplift...");}
return commitShopliftCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitShopliftCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("rob") && crime.includes("store")) { } else if (crime.includes("rob") && crime.includes("store")) {
workerScript.scriptRef.log("Attempting to rob a store..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to rob a store...");}
return commitRobStoreCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitRobStoreCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("mug")) { } else if (crime.includes("mug")) {
workerScript.scriptRef.log("Attempting to mug someone..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to mug someone...");}
return commitMugCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitMugCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("larceny")) { } else if (crime.includes("larceny")) {
workerScript.scriptRef.log("Attempting to commit larceny..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to commit larceny...");}
return commitLarcenyCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitLarcenyCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("drugs")) { } else if (crime.includes("drugs")) {
workerScript.scriptRef.log("Attempting to deal drugs..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to deal drugs...");}
return commitDealDrugsCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitDealDrugsCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("bond") && crime.includes("forge")) { } else if (crime.includes("bond") && crime.includes("forge")) {
workerScript.scriptRef.log("Attempting to forge corporate bonds..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to forge corporate bonds...");}
return commitBondForgeryCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitBondForgeryCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("traffick") && crime.includes("arms")) { } else if (crime.includes("traffick") && crime.includes("arms")) {
workerScript.scriptRef.log("Attempting to traffick illegal arms..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to traffick illegal arms...");}
return commitTraffickArmsCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitTraffickArmsCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("homicide")) { } else if (crime.includes("homicide")) {
workerScript.scriptRef.log("Attempting to commit homicide..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to commit homicide...");}
return commitHomicideCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitHomicideCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("grand") && crime.includes("auto")) { } else if (crime.includes("grand") && crime.includes("auto")) {
workerScript.scriptRef.log("Attempting to commit grand theft auto..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to commit grand theft auto...");}
return commitGrandTheftAutoCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitGrandTheftAutoCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("kidnap")) { } else if (crime.includes("kidnap")) {
workerScript.scriptRef.log("Attempting to kidnap and ransom a high-profile target..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to kidnap and ransom a high-profile target...");}
return commitKidnapCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitKidnapCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("assassinate")) { } else if (crime.includes("assassinate")) {
workerScript.scriptRef.log("Attempting to assassinate a high-profile target..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to assassinate a high-profile target...");}
return commitAssassinationCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}) return commitAssassinationCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript})
} else if (crime.includes("heist")) { } else if (crime.includes("heist")) {
workerScript.scriptRef.log("Attempting to pull off a heist..."); if(enableCommitCrimeLog) {workerScript.scriptRef.log("Attempting to pull off a heist...");}
return commitHeistCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript}); return commitHeistCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else { } else {
throw makeRuntimeRejectMsg(workerScript, "Invalid crime passed into commitCrime(): " + crime); throw makeRuntimeRejectMsg(workerScript, "Invalid crime passed into commitCrime(): " + crime);

102
src/NetscriptJSEvaluator.js Normal file

@ -0,0 +1,102 @@
import {registerEnv, unregisterEnv, makeEnvHeader} from "./NetscriptJSPreamble.js";
import {makeRuntimeRejectMsg} from "./NetscriptEvaluator.js";
// Makes a blob that contains the code of a given script.
export function makeScriptBlob(code) {
return new Blob([code], {type: "text/javascript"});
}
// Begin executing a user JS script, and return a promise that resolves
// or rejects when the script finishes.
// - script is a script to execute (see Script.js). We depend only on .filename and .code.
// scripts is an array of other scripts on the server.
// env is the global environment that should be visible to all the scripts
// (i.e. hack, grow, etc.).
// When the promise returned by this resolves, we'll have finished
// running the main function of the script.
export async function executeJSScript(script, scripts = [], env = {}) {
const envUuid = registerEnv(env);
const envHeader = makeEnvHeader(envUuid);
const urlStack = _getScriptUrls(script, scripts, envHeader, []);
// The URL at the top is the one we want to import. It will
// recursively import all the other modules in the urlStack.
//
// Webpack likes to turn the import into a require, which sort of
// but not really behaves like import. Particularly, it cannot
// load fully dynamic content. So we hide the import from webpack
// by placing it inside an eval call.
try {
// TODO: putting await in a non-async function yields unhelpful
// "SyntaxError: unexpected reserved word" with no line number information.
const loadedModule = await eval('import(urlStack[urlStack.length - 1])');
if (!loadedModule.main) {
throw makeRuntimeRejectMsg(script.filename +
" did not have a main function, cannot run it.");
}
return await loadedModule.main();
} finally {
// Revoke the generated URLs and unregister the environment.
for (const url in urlStack) URL.revokeObjectURL(url);
unregisterEnv(envUuid);
};
}
// Gets a stack of blob urls, the top/right-most element being
// the blob url for the named script on the named server.
//
// - script -- the script for whom we are getting a URL.
// - scripts -- all the scripts available on this server
// - envHeader -- the preamble that goes at the start of every NSJS script.
// - seen -- The modules above this one -- to prevent mutual dependency.
//
// TODO We don't make any effort to cache a given module when it is imported at
// different parts of the tree. That hasn't presented any problem with during
// testing, but it might be an idea for the future. Would require a topo-sort
// then url-izing from leaf-most to root-most.
function _getScriptUrls(script, scripts, envHeader, seen) {
// Inspired by: https://stackoverflow.com/a/43834063/91401
const urlStack = [];
seen.push(script);
try {
// Replace every import statement with an import to a blob url containing
// the corresponding script. E.g.
//
// import {foo} from "bar.js";
//
// becomes
//
// import {foo} from "blob://<uuid>"
//
// Where the blob URL contains the script content.
const transformedCode = script.code.replace(/((?:from|import)\s+(?:'|"))([^'"]+)('|";)/g,
(unmodified, prefix, filename, suffix) => {
const isAllowedImport = scripts.some(s => s.filename == filename);
if (!isAllowedImport) return unmodified;
// Find the corresponding script.
const [importedScript] = scripts.filter(s => s.filename == filename);
// Try to get a URL for the requested script and its dependencies.
const urls = _getScriptUrls(importedScript, scripts, envHeader, seen);
// The top url in the stack is the replacement import file for this script.
urlStack.push(...urls);
return [prefix, urls[urls.length - 1], suffix].join('');
});
// Inject the NSJS preamble at the top of the code.
const transformedCodeWithHeader = [envHeader, transformedCode].join("\n");
// If we successfully transformed the code, create a blob url for it and
// push that URL onto the top of the stack.
urlStack.push(URL.createObjectURL(makeScriptBlob(transformedCodeWithHeader)));
return urlStack;
} catch (err) {
// If there is an error, we need to clean up the URLs.
for (const url in urlStack) URL.revokeObjectURL(url);
throw err;
} finally {
seen.pop();
}
}

@ -0,0 +1,42 @@
// A utility function that adds a preamble to each Netscript JS
// script. This preamble will set all the global functions and
// variables appropriately for the module.
//
// One caveat is that we don't allow the variables in the preable
// to change. Unlike in normal Javascript, this would not change
// properties of self. It would instead just change the variable
// within the given module -- not good! Users should not really
// need to do this anyway.
import uuidv4 from "uuid/v4";
import {sprintf} from "sprintf-js";
window.__NSJS__environments = {};
// Returns the UUID for the env.
export function registerEnv(env) {
const uuid = uuidv4();
window.__NSJS__environments[uuid] = env;
return uuid;
}
export function unregisterEnv(uuid) {
delete window.__NSJS__environments[uuid];
}
export function makeEnvHeader(uuid) {
if (!(uuid in window.__NSJS__environments)) throw new Error("uuid is not in the environment" + uuid);
const env = window.__NSJS__environments[uuid];
var envLines = [];
for (const prop in env) {
envLines.push("const ", prop, " = ", "__NSJS_ENV[\"", prop, "\"];\n");
}
return sprintf(`
'use strict';
const __NSJS_ENV = window.__NSJS__environments['%s'];
// The global variable assignments (hack, weaken, etc.).
%s
`, uuid, envLines.join(""));
}

@ -5,7 +5,9 @@ import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {Environment} from "./NetscriptEnvironment.js"; import {Environment} from "./NetscriptEnvironment.js";
import {evaluate, isScriptErrorMessage, import {evaluate, isScriptErrorMessage,
makeRuntimeRejectMsg,
killNetscriptDelay} from "./NetscriptEvaluator.js"; killNetscriptDelay} from "./NetscriptEvaluator.js";
import {executeJSScript} from "./NetscriptJSEvaluator.js";
import {NetscriptPort} from "./NetscriptPort.js"; import {NetscriptPort} from "./NetscriptPort.js";
import {AllServers} from "./Server.js"; import {AllServers} from "./Server.js";
import {Settings} from "./Settings.js"; import {Settings} from "./Settings.js";
@ -54,6 +56,77 @@ function prestigeWorkerScripts() {
workerScripts.length = 0; workerScripts.length = 0;
} }
// JS script promises need a little massaging to have the same guarantees as netscript
// promises. This does said massaging and kicks the script off. It returns a promise
// that resolves or rejects when the corresponding worker script is done.
function startJsScript(workerScript) {
workerScript.running = true;
// The name of the currently running netscript function, to prevent concurrent
// calls to hack, grow, etc.
let runningFn = null;
// We need to go through the environment and wrap each function in such a way that it
// can be called at most once at a time. This will prevent situations where multiple
// hack promises are outstanding, for example.
function wrap(propName, f) {
// This function unfortunately cannot be an async function, because we don't
// know if the original one was, and there's no way to tell.
return function (...args) {
// Wrap every netscript function with a check for the stop flag.
// This prevents cases where we never stop because we are only calling
// netscript functions that don't check this.
// This is not a problem for legacy Netscript because it also checks the
// stop flag in the evaluator.
if (workerScript.env.stopFlag) {throw workerScript;}
if (propName === "sleep") return f(...args); // OK for multiple simultaneous calls to sleep.
const msg = "Concurrent calls to Netscript functions not allowed! " +
"Did you forget to await hack(), grow(), or some other " +
"promise-returning function? (Currently running: %s tried to run: %s)"
if (runningFn) {
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, sprintf(msg, runningFn, propName), null)
throw workerScript;
}
runningFn = propName;
let result = f(...args);
if (result && result.finally !== undefined) {
return result.finally(function () {
runningFn = null;
});
} else {
runningFn = null;
return result;
}
}
};
for (let prop in workerScript.env.vars) {
if (typeof workerScript.env.vars[prop] !== "function") continue;
workerScript.env.vars[prop] = wrap(prop, workerScript.env.vars[prop]);
}
// Note: the environment that we pass to the JS script only needs to contain the functions visible
// to that script, which env.vars does at this point.
return executeJSScript(workerScript.scriptRef.scriptRef,
workerScript.getServer().scripts,
workerScript.env.vars).then(function (mainReturnValue) {
if (mainReturnValue === undefined) return workerScript;
return [mainReturnValue, workerScript];
}).catch(e => {
if (e instanceof Error) {
workerScript.errorMessage = makeRuntimeRejectMsg(
workerScript, e.message + (e.stack && ("\nstack:\n" + e.stack.toString()) || ""));
throw workerScript;
} else if (isScriptErrorMessage(e)) {
workerScript.errorMessage = e;
throw workerScript;
}
throw e; // Don't know what to do with it, let's rethrow.
});
}
//Loop through workerScripts and run every script that is not currently running //Loop through workerScripts and run every script that is not currently running
function runScriptsLoop() { function runScriptsLoop() {
//Delete any scripts that finished or have been killed. Loop backwards bc removing //Delete any scripts that finished or have been killed. Loop backwards bc removing
@ -87,18 +160,23 @@ function runScriptsLoop() {
for (var i = 0; i < workerScripts.length; i++) { for (var i = 0; i < workerScripts.length; i++) {
//If it isn't running, start the script //If it isn't running, start the script
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) { if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
try { let p = null; // p is the script's result promise.
var ast = parse(workerScripts[i].code, {sourceType:"module"}); if (workerScripts[i].name.endsWith(".js")) {
//console.log(ast); p = startJsScript(workerScripts[i]);
} catch (e) { } else {
console.log("Error parsing script: " + workerScripts[i].name); try {
dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e); var ast = parse(workerScripts[i].code, {sourceType:"module"});
workerScripts[i].env.stopFlag = true; //console.log(ast);
continue; } catch (e) {
} console.log("Error parsing script: " + workerScripts[i].name);
dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e);
workerScripts[i].env.stopFlag = true;
continue;
}
workerScripts[i].running = true;
p = evaluate(ast, workerScripts[i]);
}
workerScripts[i].running = true;
var p = evaluate(ast, workerScripts[i]);
//Once the code finishes (either resolved or rejected, doesnt matter), set its //Once the code finishes (either resolved or rejected, doesnt matter), set its
//running status to false //running status to false
p.then(function(w) { p.then(function(w) {

@ -210,7 +210,10 @@ function PlayerObject() {
PlayerObject.prototype.init = function() { PlayerObject.prototype.init = function() {
/* Initialize Player's home computer */ /* Initialize Player's home computer */
var t_homeComp = new Server(createRandomIp(), "home", "Home PC", true, true, true, 8); var t_homeComp = new Server({
ip:createRandomIp(), hostname:"home", organizationName:"Home PC",
isConnectedTo:true, adminRights:true, purchasedByPlayer:true, maxRam:8
});
this.homeComputer = t_homeComp.ip; this.homeComputer = t_homeComp.ip;
this.currentServer = t_homeComp.ip; this.currentServer = t_homeComp.ip;
AddToAllServers(t_homeComp); AddToAllServers(t_homeComp);
@ -1280,7 +1283,7 @@ PlayerObject.prototype.finishCreateProgramWork = function(cancelled, sing=false)
this.getHomeComputer().programs.push(programName); this.getHomeComputer().programs.push(programName);
} else { } else {
var perc = Math.floor(this.timeWorkedCreateProgram / this.timeNeededToCompleteWork * 100).toString(); var perc = (Math.floor(this.timeWorkedCreateProgram / this.timeNeededToCompleteWork * 10000)/100).toString();
var incompleteName = programName + "-" + perc + "%-INC"; var incompleteName = programName + "-" + perc + "%-INC";
this.getHomeComputer().programs.push(incompleteName); this.getHomeComputer().programs.push(incompleteName);
} }
@ -1413,8 +1416,8 @@ PlayerObject.prototype.takeClass = function(numCycles) {
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * cyclesPerSec, 2) + " / sec) <br><br>" + "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * cyclesPerSec, 2) + " / sec) <br><br>" +
"You have gained: <br>" + "You have gained: <br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br>" + formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" + formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" + formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br>" + formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br>" + formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br>" +
@ -1582,14 +1585,16 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
this.workAgiExpGained *= 2; this.workAgiExpGained *= 2;
this.workChaExpGained *= 2; this.workChaExpGained *= 2;
if (this.committingCrimeThruSingFn) { if (this.committingCrimeThruSingFn) {
this.singFnCrimeWorkerScript.scriptRef.log("Crime successful! Gained " + if(this.singFnCrimeWorkerScript.disableLogs.ALL == null && this.singFnCrimeWorkerScript.disableLogs.commitCrime == null) {
numeral(this.workMoneyGained).format("$0.000a") + ", " + this.singFnCrimeWorkerScript.scriptRef.log("Crime successful! Gained " +
formatNumber(this.workHackExpGained, 3) + " hack exp, " + numeral(this.workMoneyGained).format("$0.000a") + ", " +
formatNumber(this.workStrExpGained, 3) + " str exp, " + formatNumber(this.workHackExpGained, 3) + " hack exp, " +
formatNumber(this.workDefExpGained, 3) + " def exp, " + formatNumber(this.workStrExpGained, 3) + " str exp, " +
formatNumber(this.workDexExpGained, 3) + " dex exp, " + formatNumber(this.workDefExpGained, 3) + " def exp, " +
formatNumber(this.workAgiExpGained, 3) + " agi exp, " + formatNumber(this.workDexExpGained, 3) + " dex exp, " +
formatNumber(this.workChaExpGained, 3) + " cha exp."); formatNumber(this.workAgiExpGained, 3) + " agi exp, " +
formatNumber(this.workChaExpGained, 3) + " cha exp.");
}
} else { } else {
dialogBoxCreate("Crime successful! <br><br>" + dialogBoxCreate("Crime successful! <br><br>" +
"You gained:<br>"+ "You gained:<br>"+
@ -1611,13 +1616,15 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
this.workAgiExpGained /= 2; this.workAgiExpGained /= 2;
this.workChaExpGained /= 2; this.workChaExpGained /= 2;
if (this.committingCrimeThruSingFn) { if (this.committingCrimeThruSingFn) {
this.singFnCrimeWorkerScript.scriptRef.log("Crime failed! Gained " + if(this.singFnCrimeWorkerScript.disableLogs.ALL == null && this.singFnCrimeWorkerScript.disableLogs.commitCrime == null) {
formatNumber(this.workHackExpGained, 3) + " hack exp, " + this.singFnCrimeWorkerScript.scriptRef.log("Crime failed! Gained " +
formatNumber(this.workStrExpGained, 3) + " str exp, " + formatNumber(this.workHackExpGained, 3) + " hack exp, " +
formatNumber(this.workDefExpGained, 3) + " def exp, " + formatNumber(this.workStrExpGained, 3) + " str exp, " +
formatNumber(this.workDexExpGained, 3) + " dex exp, " + formatNumber(this.workDefExpGained, 3) + " def exp, " +
formatNumber(this.workAgiExpGained, 3) + " agi exp, " + formatNumber(this.workDexExpGained, 3) + " dex exp, " +
formatNumber(this.workChaExpGained, 3) + " chaexp."); formatNumber(this.workAgiExpGained, 3) + " agi exp, " +
formatNumber(this.workChaExpGained, 3) + " cha exp.");
}
} else { } else {
dialogBoxCreate("Crime failed! <br><br>" + dialogBoxCreate("Crime failed! <br><br>" +
"You gained:<br>"+ "You gained:<br>"+

@ -13,9 +13,12 @@ require("brace/keybinding/vim");
require("brace/keybinding/emacs"); require("brace/keybinding/emacs");
require("brace/ext/language_tools"); require("brace/ext/language_tools");
// Importing this doesn't work for some reason.
const walk = require("acorn/dist/walk");
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {parseFconfSettings} from "./Fconf.js"; import {FconfSettings, parseFconfSettings} from "./Fconf.js";
import {iTutorialSteps, iTutorialNextStep, import {iTutorialSteps, iTutorialNextStep,
iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js"; iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js";
import {evaluateImport} from "./NetscriptEvaluator.js"; import {evaluateImport} from "./NetscriptEvaluator.js";
@ -25,7 +28,7 @@ import {addWorkerScript, killWorkerScript,
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {AllServers, processSingleServerGrowth} from "./Server.js"; import {AllServers, processSingleServerGrowth} from "./Server.js";
import {Settings} from "./Settings.js"; import {Settings} from "./Settings.js";
import {post} from "./Terminal.js"; import {post, Terminal} from "./Terminal.js";
import {TextFile} from "./TextFile.js"; import {TextFile} from "./TextFile.js";
import {parse, Node} from "../utils/acorn.js"; import {parse, Node} from "../utils/acorn.js";
@ -42,6 +45,10 @@ var keybindings = {
emacs: "ace/keyboard/emacs", emacs: "ace/keyboard/emacs",
}; };
function isScriptFilename(f) {
return f.endsWith(".js") || f.endsWith(".script");
}
var scriptEditorRamCheck = null, scriptEditorRamText = null; var scriptEditorRamCheck = null, scriptEditorRamText = null;
function scriptEditorInit() { function scriptEditorInit() {
//Create buttons at the bottom of script editor //Create buttons at the bottom of script editor
@ -209,7 +216,7 @@ function scriptEditorInit() {
//Updates RAM usage in script //Updates RAM usage in script
function updateScriptEditorContent() { function updateScriptEditorContent() {
var filename = document.getElementById("script-editor-filename").value; var filename = document.getElementById("script-editor-filename").value;
if (scriptEditorRamCheck == null || !scriptEditorRamCheck.checked || !filename.endsWith(".script")) { if (scriptEditorRamCheck == null || !scriptEditorRamCheck.checked || !isScriptFilename(filename)) {
scriptEditorRamText.innerText = "N/A"; scriptEditorRamText.innerText = "N/A";
return; return;
} }
@ -226,9 +233,10 @@ function updateScriptEditorContent() {
//Define key commands in script editor (ctrl o to save + close, etc.) //Define key commands in script editor (ctrl o to save + close, etc.)
$(document).keydown(function(e) { $(document).keydown(function(e) {
if (Settings.DisableHotkeys === true) {return;}
if (Engine.currentPage == Engine.Page.ScriptEditor) { if (Engine.currentPage == Engine.Page.ScriptEditor) {
//Ctrl + b //Ctrl + b
if (e.keyCode == 66 && e.ctrlKey) { if (e.keyCode == 66 && (e.ctrlKey || e.metaKey)) {
e.preventDefault(); e.preventDefault();
saveAndCloseScriptEditor(); saveAndCloseScriptEditor();
} }
@ -270,7 +278,7 @@ function saveAndCloseScriptEditor() {
dialogBoxCreate("Invalid .fconf file"); dialogBoxCreate("Invalid .fconf file");
return; return;
} }
} else if (filename.endsWith(".script")) { } else if (isScriptFilename(filename)) {
//If the current script already exists on the server, overwrite it //If the current script already exists on the server, overwrite it
for (var i = 0; i < s.scripts.length; i++) { for (var i = 0; i < s.scripts.length; i++) {
if (filename == s.scripts[i].filename) { if (filename == s.scripts[i].filename) {
@ -348,6 +356,219 @@ Script.prototype.updateRamUsage = function() {
} }
} }
// These special strings are used to reference the presence of a given logical
// construct within a user script.
const specialReferenceIF = "__SPECIAL_referenceIf";
const specialReferenceFOR = "__SPECIAL_referenceFor";
const specialReferenceWHILE = "__SPECIAL_referenceWhile";
// The global scope of a script is registered under this key during parsing.
const memCheckGlobalKey = ".__GLOBAL__";
// Calcluates the amount of RAM a script uses. Uses parsing and AST walking only,
// rather than NetscriptEvaluator. This is useful because NetscriptJS code does
// not work under NetscriptEvaluator.
function parseOnlyRamCalculate(server, code, workerScript) {
try {
// Maps dependent identifiers to their dependencies.
//
// The initial identifier is __SPECIAL_INITIAL_MODULE__.__GLOBAL__.
// It depends on all the functions declared in the module, all the global scopes
// of its imports, and any identifiers referenced in this global scope. Each
// function depends on all the identifiers referenced internally.
// We walk the dependency graph to calculate RAM usage, given that some identifiers
// reference Netscript functions which have a RAM cost.
let dependencyMap = {};
// Scripts we've parsed.
const completedParses = new Set();
// Scripts we've discovered that need to be parsed.
const parseQueue = [];
// Parses a chunk of code with a given module name, and updates parseQueue and dependencyMap.
function parseCode(code, moduleName) {
const result = parseOnlyCalculateDeps(code, moduleName);
completedParses.add(moduleName);
// Add any additional modules to the parse queue;
for (let i = 0; i < result.additionalModules.length; ++i) {
if (!completedParses.has(result.additionalModules[i])) {
parseQueue.push(result.additionalModules[i]);
}
}
// Splice all the references in.
dependencyMap = {...dependencyMap, ...result.dependencyMap};
}
const initialModule = "__SPECIAL_INITIAL_MODULE__";
parseCode(code, initialModule);
while (parseQueue.length > 0) {
// Get the code from the server.
const nextModule = parseQueue.shift();
const script = server.getScript(nextModule);
if (!script) return -1; // No such script on the server.
// Not sure why we always take copies, but let's do that here too.
parseCode(script.code.repeat(1), nextModule);
}
// Finally, walk the reference map and generate a ram cost. The initial set of keys to scan
// are those that start with __SPECIAL_INITIAL_MODULE__.
let ram = CONSTANTS.ScriptBaseRamCost;
const unresolvedRefs = Object.keys(dependencyMap).filter(s => s.startsWith(initialModule));
const resolvedRefs = new Set();
while (unresolvedRefs.length > 0) {
const ref = unresolvedRefs.shift();
resolvedRefs.add(ref);
if (ref.endsWith(".*")) {
// A prefix reference. We need to find all matching identifiers.
const prefix = ref.slice(0, ref.length - 2);
for (let ident of Object.keys(dependencyMap).filter(k => k.startsWith(prefix))) {
for (let dep of dependencyMap[ident] || []) {
if (!resolvedRefs.has(dep)) unresolvedRefs.push(dep);
}
}
} else {
// An exact reference. Add all dependencies of this ref.
for (let dep of dependencyMap[ref] || []) {
if (!resolvedRefs.has(dep)) unresolvedRefs.push(dep);
}
}
// Check if this is one of the special keys, and add the appropriate ram cost if so.
if (ref == specialReferenceIF) ram += CONSTANTS.ScriptIfRamCost;
if (ref == specialReferenceFOR) ram += CONSTANTS.ScriptForRamCost;
if (ref == specialReferenceWHILE) ram += CONSTANTS.ScriptWhileRamCost;
if (ref == "hacknetnodes") ram += CONSTANTS.ScriptHacknetNodesRamCost;
// Check if this ident is a function in the workerscript env. If it is, then we need to
// get its RAM cost. We do this by calling it, which works because the running script
// is in checkingRam mode.
//
// TODO it would be simpler to just reference a dictionary.
try {
var func = workerScript.env.get(ref);
if (typeof func === "function") {
try {
var res = func.apply(null, []);
if (typeof res === "number") {
ram += res;
}
} catch(e) {
console.log("ERROR applying function: " + e);
}
}
} catch (error) { continue; }
}
return ram;
} catch (error) {
console.info("parse or eval error: ", error);
// This is not unexpected. The user may be editing a script, and it may be in
// a transitory invalid state.
return -1;
}
}
// Parses one script and calculates its ram usage, for the global scope and each function.
// Returns a cost map and a dependencyMap for the module. Returns a reference map to be joined
// onto the main reference map, and a list of modules that need to be parsed.
function parseOnlyCalculateDeps(code, currentModule) {
const ast = parse(code, {sourceType:"module", ecmaVersion: 8});
// Everything from the global scope goes in ".". Everything else goes in ".function", where only
// the outermost layer of functions counts.
const globalKey = currentModule + memCheckGlobalKey;
const dependencyMap = {};
dependencyMap[globalKey] = new Set();
// If we reference this internal name, we're really referencing that external name.
// Filled when we import names from other modules.
let internalToExternal = {};
var additionalModules = [];
// References get added pessimistically. They are added for thisModule.name, name, and for
// any aliases.
function addRef(key, name) {
const s = dependencyMap[key] || (dependencyMap[key] = new Set());
if (name in internalToExternal) {
s.add(internalToExternal[name]);
}
s.add(currentModule + "." + name);
s.add(name); // For builtins like hack.
}
// If we discover a dependency identifier, state.key is the dependent identifier.
// walkDeeper is for doing recursive walks of expressions in composites that we handle.
function commonVisitors() {
return {
Identifier: (node, st, walkDeeper) => {
addRef(st.key, node.name);
},
WhileStatement: (node, st, walkDeeper) => {
addRef(st.key, specialReferenceWHILE);
node.test && walkDeeper(node.test, st);
node.body && walkDeeper(node.body, st);
},
DoWhileStatement: (node, st, walkDeeper) => {
addRef(st.key, specialReferenceWHILE);
node.test && walkDeeper(node.test, st);
node.body && walkDeeper(node.body, st);
},
ForStatement: (node, st, walkDeeper) => {
addRef(st.key, specialReferenceFOR);
node.init && walkDeeper(node.init, st);
node.test && walkDeeper(node.test, st);
node.update && walkDeeper(node.update, st);
node.body && walkDeeper(node.body, st);
},
IfStatement: (node, st, walkDeeper) => {
addRef(st.key, specialReferenceIF);
node.test && walkDeeper(node.test, st);
node.consequent && walkDeeper(node.consequent, st);
node.alternate && walkDeeper(node.alternate, st);
},
}
}
walk.recursive(ast, {key: globalKey}, {
ImportDeclaration: (node, st, walkDeeper) => {
const importModuleName = node.source.value;
additionalModules.push(importModuleName);
// This module's global scope refers to that module's global scope, no matter how we
// import it.
dependencyMap[st.key].add(importModuleName + memCheckGlobalKey);
for (let i = 0; i < node.specifiers.length; ++i) {
const spec = node.specifiers[i];
if (spec.imported !== undefined && spec.local !== undefined) {
// We depend on specific things.
internalToExternal[spec.local.name] = importModuleName + "." + spec.imported.name;
} else {
// We depend on everything.
dependencyMap[st.key].add(importModuleName + ".*");
}
}
},
FunctionDeclaration: (node, st, walkDeeper) => {
// Don't use walkDeeper, because we are changing the visitor set.
const key = currentModule + "." + node.id.name;
walk.recursive(node, {key: key}, commonVisitors());
},
...commonVisitors()
});
return {dependencyMap: dependencyMap, additionalModules: additionalModules};
}
function calculateRamUsage(codeCopy) { function calculateRamUsage(codeCopy) {
//Create a temporary/mock WorkerScript and an AST from the code //Create a temporary/mock WorkerScript and an AST from the code
var currServ = Player.getCurrentServer(); var currServ = Player.getCurrentServer();
@ -359,6 +580,14 @@ function calculateRamUsage(codeCopy) {
workerScript.checkingRam = true; //Netscript functions will return RAM usage workerScript.checkingRam = true; //Netscript functions will return RAM usage
workerScript.serverIp = currServ.ip; workerScript.serverIp = currServ.ip;
try {
return parseOnlyRamCalculate(currServ, codeCopy, workerScript);
} catch (e) {
console.log("Failed to parse ram using new method. Falling back.", e);
}
// Try the old way.
try { try {
var ast = parse(codeCopy, {sourceType:"module"}); var ast = parse(codeCopy, {sourceType:"module"});
} catch(e) { } catch(e) {
@ -366,7 +595,7 @@ function calculateRamUsage(codeCopy) {
} }
//Search through AST, scanning for any 'Identifier' nodes for functions, or While/For/If nodes //Search through AST, scanning for any 'Identifier' nodes for functions, or While/For/If nodes
var queue = [], ramUsage = 1.4; var queue = [], ramUsage = CONSTANTS.ScriptBaseRamCost;
var whileUsed = false, forUsed = false, ifUsed = false; var whileUsed = false, forUsed = false, ifUsed = false;
queue.push(ast); queue.push(ast);
while (queue.length != 0) { while (queue.length != 0) {
@ -630,7 +859,11 @@ RunningScript.prototype.log = function(txt) {
//to improve performance //to improve performance
this.logs.shift(); this.logs.shift();
} }
this.logs.push(txt); let logEntry = txt;
if (FconfSettings.ENABLE_TIMESTAMPS) {
logEntry = "[" + Terminal.getTimestamp() + "] " + logEntry;
}
this.logs.push(logEntry);
this.logUpd = true; this.logUpd = true;
} }
@ -712,4 +945,4 @@ AllServersMap.fromJSON = function(value) {
Reviver.constructors.AllServersMap = AllServersMap; Reviver.constructors.AllServersMap = AllServersMap;
export {updateScriptEditorContent, loadAllRunningScripts, findRunningScript, export {updateScriptEditorContent, loadAllRunningScripts, findRunningScript,
RunningScript, Script, AllServersMap, scriptEditorInit}; RunningScript, Script, AllServersMap, scriptEditorInit, isScriptFilename};

@ -9,11 +9,12 @@ import {createRandomIp, isValidIPAddress, ipExists} from "../utils/IPAddress.js"
import {Reviver, Generic_toJSON, import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js"; Generic_fromJSON} from "../utils/JSONReviver.js";
function Server(ip=createRandomIp(), hostname="", organizationName="", function Server(params={ip:createRandomIp(), hostname:""}) {
isConnectedTo=false, adminRights=false, purchasedByPlayer=false, maxRam=0) { /* Properties */
/* Properties */ //Connection information
//Connection information this.ip = params.ip ? params.ip : createRandomIp();
this.ip = ip;
var hostname = params.hostname;
var i = 0; var i = 0;
var suffix = ""; var suffix = "";
while (GetServerByHostname(hostname+suffix) != null) { while (GetServerByHostname(hostname+suffix) != null) {
@ -21,76 +22,74 @@ function Server(ip=createRandomIp(), hostname="", organizationName="",
suffix = "-" + i; suffix = "-" + i;
++i; ++i;
} }
this.hostname = hostname + suffix; this.hostname = hostname + suffix;
this.organizationName = organizationName; this.organizationName = params.organizationName != null ? params.organizationName : "";
this.isConnectedTo = isConnectedTo; //Whether the player is connected to this server this.isConnectedTo = params.isConnectedTo != null ? params.isConnectedTo : false;
//Access information //Access information
this.hasAdminRights = adminRights; //Whether player has admin rights this.hasAdminRights = params.adminRights != null ? params.adminRights : false;
this.purchasedByPlayer = purchasedByPlayer; this.purchasedByPlayer = params.purchasedByPlayer != null ? params.purchasedByPlayer : false;
this.manuallyHacked = false; //Flag that tracks whether or not the server has been hacked at least once this.manuallyHacked = false; //Flag that tracks whether or not the server has been hacked at least once
//RAM, CPU speed and Scripts //RAM, CPU speed and Scripts
this.maxRam = maxRam; //GB this.maxRam = params.maxRam != null ? params.maxRam : 0; //GB
this.ramUsed = 0; this.ramUsed = 0;
this.cpuCores = 1; //Max of 8, affects hacking times and Hacking Mission starting Cores this.cpuCores = 1; //Max of 8, affects hacking times and Hacking Mission starting Cores
this.scripts = []; this.scripts = [];
this.runningScripts = []; //Stores RunningScript objects this.runningScripts = []; //Stores RunningScript objects
this.programs = []; this.programs = [];
this.messages = []; this.messages = [];
this.textFiles = []; this.textFiles = [];
this.dir = 0; //new Directory(this, null, ""); this.dir = 0; //new Directory(this, null, ""); TODO
/* Hacking information (only valid for "foreign" aka non-purchased servers) */ /* Hacking information (only valid for "foreign" aka non-purchased servers) */
//Skill required to attempt a hack. Whether a hack is successful will be determined this.requiredHackingSkill = params.requiredHackingSkill != null ? params.requiredHackingSkill : 1;
//by a separate formula this.moneyAvailable = params.moneyAvailable != null ? params.moneyAvailable * BitNodeMultipliers.ServerStartingMoney : 0;
this.requiredHackingSkill = 1; this.moneyMax = 25 * this.moneyAvailable * BitNodeMultipliers.ServerMaxMoney;
//Total money available on this server //Hack Difficulty is synonymous with server security. Base Difficulty = Starting difficulty
this.moneyAvailable = 0; this.hackDifficulty = params.hackDifficulty != null ? params.hackDifficulty * BitNodeMultipliers.ServerStartingSecurity : 1;
this.moneyMax = 0; this.baseDifficulty = this.hackDifficulty;
this.minDifficulty = Math.max(1, Math.round(this.hackDifficulty / 3));
this.serverGrowth = params.serverGrowth != null ? params.serverGrowth : 1; //Integer from 0 to 100. Affects money increase from grow()
//Parameters used in formulas that dictate how moneyAvailable and requiredHackingSkill change. //The IP's of all servers reachable from this one (what shows up if you run scan/netstat)
this.hackDifficulty = 1; //Affects hack success rate and how the requiredHackingSkill increases over time (1-100)
this.baseDifficulty = 1; //Starting difficulty
this.minDifficulty = 1;
this.serverGrowth = 0; //Affects how the moneyAvailable increases (0-100)
//The IP's of all servers reachable from this one (what shows up if you run scan/netstat)
// NOTE: Only contains IP and not the Server objects themselves // NOTE: Only contains IP and not the Server objects themselves
this.serversOnNetwork = []; this.serversOnNetwork = [];
//Port information, required for porthacking servers to get admin rights //Port information, required for porthacking servers to get admin rights
this.numOpenPortsRequired = 5; this.numOpenPortsRequired = params.numOpenPortsRequired != null ? params.numOpenPortsRequired : 5;
this.sshPortOpen = false; //Port 22 this.sshPortOpen = false; //Port 22
this.ftpPortOpen = false; //Port 21 this.ftpPortOpen = false; //Port 21
this.smtpPortOpen = false; //Port 25 this.smtpPortOpen = false; //Port 25
this.httpPortOpen = false; //Port 80 this.httpPortOpen = false; //Port 80
this.sqlPortOpen = false; //Port 1433 this.sqlPortOpen = false; //Port 1433
this.openPortCount = 0; this.openPortCount = 0;
}; };
/*
//Set the hacking properties of a server //Set the hacking properties of a server
Server.prototype.setHackingParameters = function(requiredHackingSkill, moneyAvailable, hackDifficulty, serverGrowth) { Server.prototype.setHackingParameters = function(requiredHackingSkill, moneyAvailable, hackDifficulty, serverGrowth) {
this.requiredHackingSkill = requiredHackingSkill; this.requiredHackingSkill = requiredHackingSkill;
if (isNaN(moneyAvailable)) { if (isNaN(moneyAvailable)) {
this.moneyAvailable = 1e6; this.moneyAvailable = 1e6;
} else { } else {
this.moneyAvailable = moneyAvailable * BitNodeMultipliers.ServerStartingMoney; this.moneyAvailable = moneyAvailable * BitNodeMultipliers.ServerStartingMoney;
} }
this.moneyMax = 25 * this.moneyAvailable * BitNodeMultipliers.ServerMaxMoney; this.moneyMax =
this.hackDifficulty = hackDifficulty * BitNodeMultipliers.ServerStartingSecurity; this.hackDifficulty = hackDifficulty * BitNodeMultipliers.ServerStartingSecurity;
this.baseDifficulty = hackDifficulty * BitNodeMultipliers.ServerStartingSecurity; this.baseDifficulty = hackDifficulty * BitNodeMultipliers.ServerStartingSecurity;
this.minDifficulty = Math.max(1, Math.round(this.hackDifficulty / 3)); this.minDifficulty = Math.max(1, Math.round(this.hackDifficulty / 3));
this.serverGrowth = serverGrowth; this.serverGrowth = serverGrowth;
} }
//Set the port properties of a server //Set the port properties of a server
//Right now its only the number of open ports needed to PortHack the server. //Right now its only the number of open ports needed to PortHack the server.
Server.prototype.setPortProperties = function(numOpenPortsReq) { Server.prototype.setPortProperties = function(numOpenPortsReq) {
this.numOpenPortsRequired = numOpenPortsReq; this.numOpenPortsRequired = numOpenPortsReq;
} }
*/
Server.prototype.setMaxRam = function(ram) { Server.prototype.setMaxRam = function(ram) {
this.maxRam = ram; this.maxRam = ram;
@ -109,12 +108,12 @@ Server.prototype.getServerOnNetwork = function(i) {
//Given the name of the script, returns the corresponding //Given the name of the script, returns the corresponding
//script object on the server (if it exists) //script object on the server (if it exists)
Server.prototype.getScript = function(scriptName) { Server.prototype.getScript = function(scriptName) {
for (var i = 0; i < this.scripts.length; i++) { for (var i = 0; i < this.scripts.length; i++) {
if (this.scripts[i].filename == scriptName) { if (this.scripts[i].filename == scriptName) {
return this.scripts[i]; return this.scripts[i];
} }
} }
return null; return null;
} }
//Strengthens a server's security level (difficulty) by the specified amount //Strengthens a server's security level (difficulty) by the specified amount
@ -133,413 +132,553 @@ Server.prototype.weaken = function(amt) {
//Functions for loading and saving a Server //Functions for loading and saving a Server
Server.prototype.toJSON = function() { Server.prototype.toJSON = function() {
return Generic_toJSON("Server", this); return Generic_toJSON("Server", this);
} }
Server.fromJSON = function(value) { Server.fromJSON = function(value) {
return Generic_fromJSON(Server, value.data); return Generic_fromJSON(Server, value.data);
} }
Reviver.constructors.Server = Server; Reviver.constructors.Server = Server;
function initForeignServers() { function initForeignServers() {
//MegaCorporations //MegaCorporations
var ECorpServer = new Server(createRandomIp(), "ecorp", "ECorp", false, false, false, 0); var ECorpServer = new Server({
ECorpServer.setHackingParameters(getRandomInt(1150, 1300), getRandomInt(30000000000, 70000000000), 99, 99); ip:createRandomIp(), hostname:"ecorp", organizationName:"ECorp",
ECorpServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1150, 1300), moneyAvailable:getRandomInt(30e9, 70e9),
hackDifficulty:99,serverGrowth:99, numOpenPortsRequired: 5,
});
AddToAllServers(ECorpServer); AddToAllServers(ECorpServer);
var MegaCorpServer = new Server(createRandomIp(), "megacorp", "MegaCorp", false, false, false, 0); var MegaCorpServer = new Server({
MegaCorpServer.setHackingParameters(getRandomInt(1150, 1300), getRandomInt(40000000000, 60000000000), 99, 99); ip:createRandomIp(), hostname:"megacorp", organizationName:"MegaCorp",
MegaCorpServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1150, 1300), moneyAvailable:getRandomInt(40e9, 60e9),
hackDifficulty:99, serverGrowth:99, numOpenPortsRequired:5
});
AddToAllServers(MegaCorpServer); AddToAllServers(MegaCorpServer);
var BachmanAndAssociatesServer = new Server(createRandomIp(), "b-and-a", "Bachman & Associates", false, false, false, 0); var BachmanAndAssociatesServer = new Server({
BachmanAndAssociatesServer.setHackingParameters(getRandomInt(1000, 1050), getRandomInt(20000000000, 25000000000), getRandomInt(75, 85), getRandomInt(65, 75)); ip:createRandomIp(), hostname:"b-and-a", organizationName:"Bachman & Associates",
BachmanAndAssociatesServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1000, 1050), moneyAvailable:getRandomInt(20e9, 25e9),
hackDifficulty:getRandomInt(75, 85), serverGrowth:getRandomInt(65, 75), numOpenPortsRequired:5
});
AddToAllServers(BachmanAndAssociatesServer); AddToAllServers(BachmanAndAssociatesServer);
var BladeIndustriesServer = new Server(createRandomIp(), "blade", "Blade Industries", false, false, false, 2); var BladeIndustriesServer = new Server({
BladeIndustriesServer.setHackingParameters(getRandomInt(1000, 1100), getRandomInt(12000000000, 20000000000), getRandomInt(90, 95), getRandomInt(60, 75)); ip:createRandomIp(), hostname:"blade", organizationName:"Blade Industries", maxRam:128,
BladeIndustriesServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1000, 1100), moneyAvailable:getRandomInt(12e9, 20e9),
hackDifficulty:getRandomInt(90, 95), serverGrowth:getRandomInt(60, 75), numOpenPortsRequired:5
});
BladeIndustriesServer.messages.push("beyond-man.lit"); BladeIndustriesServer.messages.push("beyond-man.lit");
AddToAllServers(BladeIndustriesServer); AddToAllServers(BladeIndustriesServer);
var NWOServer = new Server(createRandomIp(), "nwo", "New World Order", false, false, false, 2); var NWOServer = new Server({
NWOServer.setHackingParameters(getRandomInt(1000, 1200), getRandomInt(25000000000, 35000000000), 99, getRandomInt(75, 85)); ip:createRandomIp(), hostname:"nwo", organizationName:"New World Order",
NWOServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1000, 1200), moneyAvailable:getRandomInt(25e9, 35e9),
hackDifficulty:99, serverGrowth:getRandomInt(75, 85), numOpenPortsRequired:5
});
NWOServer.messages.push("the-hidden-world.lit"); NWOServer.messages.push("the-hidden-world.lit");
AddToAllServers(NWOServer); AddToAllServers(NWOServer);
var ClarkeIncorporatedServer = new Server(createRandomIp(), "clarkeinc", "Clarke Incorporated", false, false, false, 2); var ClarkeIncorporatedServer = new Server({
ClarkeIncorporatedServer.setHackingParameters(getRandomInt(1000, 1200), getRandomInt(15000000000, 25000000000), getRandomInt(50, 60), getRandomInt(50, 70)); ip:createRandomIp(), hostname:"clarkeinc", organizationName:"Clarke Incorporated",
ClarkeIncorporatedServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1000, 1200), moneyAvailable:getRandomInt(15e9, 25e9),
hackDifficulty:getRandomInt(50, 60), serverGrowth:getRandomInt(50, 70), numOpenPortsRequired:5
});
ClarkeIncorporatedServer.messages.push("beyond-man.lit"); ClarkeIncorporatedServer.messages.push("beyond-man.lit");
ClarkeIncorporatedServer.messages.push("cost-of-immortality.lit"); ClarkeIncorporatedServer.messages.push("cost-of-immortality.lit");
AddToAllServers(ClarkeIncorporatedServer); AddToAllServers(ClarkeIncorporatedServer);
var OmniTekIncorporatedServer = new Server(createRandomIp(), "omnitek", "OmniTek Incorporated", false, false, false, 2); var OmniTekIncorporatedServer = new Server({
OmniTekIncorporatedServer.setHackingParameters(getRandomInt(900, 1100), getRandomInt(15000000000, 20000000000), getRandomInt(90, 99), getRandomInt(95, 99)); ip:createRandomIp(), hostname:"omnitek", organizationName:"OmniTek Incorporated", maxRam:256,
OmniTekIncorporatedServer.setPortProperties(5); requiredHackingSkill:getRandomInt(900, 1100), moneyAvailable:getRandomInt(15e9, 20e9),
hackDifficulty:getRandomInt(90, 99), serverGrowth:getRandomInt(95, 99), numOpenPortsRequired:5
});
OmniTekIncorporatedServer.messages.push("coded-intelligence.lit"); OmniTekIncorporatedServer.messages.push("coded-intelligence.lit");
OmniTekIncorporatedServer.messages.push("history-of-synthoids.lit");
AddToAllServers(OmniTekIncorporatedServer); AddToAllServers(OmniTekIncorporatedServer);
var FourSigmaServer = new Server(createRandomIp(), "4sigma", "FourSigma", false, false, false, 0); var FourSigmaServer = new Server({
FourSigmaServer.setHackingParameters(getRandomInt(950, 1200), getRandomInt(15000000000, 25000000000), getRandomInt(60, 70), getRandomInt(75, 99)); ip:createRandomIp(), hostname:"4sigma", organizationName:"FourSigma",
FourSigmaServer.setPortProperties(5); requiredHackingSkill:getRandomInt(950, 1200), moneyAvailable:getRandomInt(15e9, 25e9),
hackDifficulty:getRandomInt(60, 70), serverGrowth:getRandomInt(75, 99), numOpenPortsRequired:5
});
AddToAllServers(FourSigmaServer); AddToAllServers(FourSigmaServer);
var KuaiGongInternationalServer = new Server(createRandomIp(), "kuai-gong", "KuaiGong International", false, false, false, 0); var KuaiGongInternationalServer = new Server({
KuaiGongInternationalServer.setHackingParameters(getRandomInt(1000, 1250), getRandomInt(20000000000, 30000000000), getRandomInt(95, 99), getRandomInt(90, 99)); ip:createRandomIp(), hostname:"kuai-gong", organizationName:"KuaiGong International",
KuaiGongInternationalServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1000, 1250), moneyAvailable:getRandomInt(20e9, 30e9),
hackDifficulty:getRandomInt(95, 99), serverGrowth:getRandomInt(90, 99), numOpenPortsRequired:5,
});
AddToAllServers(KuaiGongInternationalServer); AddToAllServers(KuaiGongInternationalServer);
//Technology and communications companies (large targets) //Technology and communications companies (large targets)
var FulcrumTechnologiesServer = new Server(createRandomIp(), "fulcrumtech", "Fulcrum Technologies", false, false, false, 64); var FulcrumTechnologiesServer = new Server({
FulcrumTechnologiesServer.setHackingParameters(getRandomInt(1000, 1200), getRandomInt(1400000000, 1800000000), getRandomInt(85, 95), getRandomInt(80, 99)); ip:createRandomIp(), hostname:"fulcrumtech", organizationName:"Fulcrum Technologies", maxRam:512,
FulcrumTechnologiesServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1000, 1200), moneyAvailable:getRandomInt(1.4e9, 1.8e9),
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(80, 99), numOpenPortsRequired:5
});
FulcrumTechnologiesServer.messages.push("simulated-reality.lit"); FulcrumTechnologiesServer.messages.push("simulated-reality.lit");
AddToAllServers(FulcrumTechnologiesServer); AddToAllServers(FulcrumTechnologiesServer);
var FulcrumSecretTechnologiesServer = new Server(createRandomIp(), "fulcrumassets", "Fulcrum Technologies Assets", false, false, false, 0); var FulcrumSecretTechnologiesServer = new Server({
FulcrumSecretTechnologiesServer.setHackingParameters(getRandomInt(1200, 1500), 1000000, 99, 1); ip:createRandomIp(), hostname:"fulcrumassets", organizationName:"Fulcrum Technologies Assets",
FulcrumSecretTechnologiesServer.setPortProperties(5); requiredHackingSkill:getRandomInt(1200, 1500), moneyAvailable:1e6,
hackDifficulty:99, serverGrowth:1, numOpenPortsRequired:5
});
AddToAllServers(FulcrumSecretTechnologiesServer); AddToAllServers(FulcrumSecretTechnologiesServer);
SpecialServerIps.addIp(SpecialServerNames.FulcrumSecretTechnologies, FulcrumSecretTechnologiesServer.ip); SpecialServerIps.addIp(SpecialServerNames.FulcrumSecretTechnologies, FulcrumSecretTechnologiesServer.ip);
var StormTechnologiesServer = new Server(createRandomIp(), "stormtech", "Storm Technologies", false, false, false, 0); var StormTechnologiesServer = new Server({
StormTechnologiesServer.setHackingParameters(getRandomInt(900, 1050), getRandomInt(1000000000, 1200000000), getRandomInt(80, 90), getRandomInt(70, 90)); ip:createRandomIp(), hostname:"stormtech", organizationName:"Storm Technologies",
StormTechnologiesServer.setPortProperties(5); requiredHackingSkill:getRandomInt(900, 1050), moneyAvailable:getRandomInt(1e9, 1.2e9),
hackDifficulty:getRandomInt(80, 90), serverGrowth:getRandomInt(70, 90), numOpenPortsRequired:5
});
AddToAllServers(StormTechnologiesServer); AddToAllServers(StormTechnologiesServer);
var DefCommServer = new Server(createRandomIp(), "defcomm", "DefComm", false, false, false, 0); var DefCommServer = new Server({
DefCommServer.setHackingParameters(getRandomInt(900, 1000), getRandomInt(800000000, 950000000), getRandomInt(85, 95), getRandomInt(50, 70)); ip:createRandomIp(), hostname:"defcomm", organizationName:"DefComm",
DefCommServer.setPortProperties(5); requiredHackingSkill:getRandomInt(900, 1000), moneyAvailable:getRandomInt(800e6, 950e6),
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(50, 70), numOpenPortsRequired:5
});
AddToAllServers(DefCommServer); AddToAllServers(DefCommServer);
var InfoCommServer = new Server(createRandomIp(), "infocomm", "InfoComm", false, false, false, 0); var InfoCommServer = new Server({
InfoCommServer.setHackingParameters(getRandomInt(875, 950), getRandomInt(600000000, 900000000), getRandomInt(70, 90), getRandomInt(35, 75)); ip:createRandomIp(), hostname:"infocomm", organizationName:"InfoComm",
InfoCommServer.setPortProperties(5); requiredHackingSkill:getRandomInt(875, 950), moneyAvailable:getRandomInt(600e6, 900e6),
hackDifficulty:getRandomInt(70, 90), serverGrowth:getRandomInt(35, 75), numOpenPortsRequired:5
});
AddToAllServers(InfoCommServer); AddToAllServers(InfoCommServer);
var HeliosLabsServer = new Server(createRandomIp(), "helios", "Helios Labs", false, false, false, 2); var HeliosLabsServer = new Server({
HeliosLabsServer.setHackingParameters(getRandomInt(800, 900), getRandomInt(550000000, 750000000), getRandomInt(85, 95), getRandomInt(70, 80)); ip:createRandomIp(), hostname:"helios", organizationName:"Helios Labs", maxRam:128,
HeliosLabsServer.setPortProperties(5); requiredHackingSkill:getRandomInt(800, 900), moneyAvailable:getRandomInt(550e6, 750e6),
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:5
});
HeliosLabsServer.messages.push("beyond-man.lit"); HeliosLabsServer.messages.push("beyond-man.lit");
AddToAllServers(HeliosLabsServer); AddToAllServers(HeliosLabsServer);
var VitaLifeServer = new Server(createRandomIp(), "vitalife", "VitaLife", false, false, false, 32); var VitaLifeServer = new Server({
VitaLifeServer.setHackingParameters(getRandomInt(775, 900), getRandomInt(700000000, 800000000), getRandomInt(80, 90), getRandomInt(60, 80)); ip:createRandomIp(), hostname:"vitalife", organizationName:"VitaLife", maxRam:64,
VitaLifeServer.setPortProperties(5); requiredHackingSkill:getRandomInt(775, 900), moneyAvailable:getRandomInt(700e6, 800e6),
hackDifficulty:getRandomInt(80, 90), serverGrowth:getRandomInt(60, 80), numOpenPortsRequired:5
});
VitaLifeServer.messages.push("A-Green-Tomorrow.lit"); VitaLifeServer.messages.push("A-Green-Tomorrow.lit");
AddToAllServers(VitaLifeServer); AddToAllServers(VitaLifeServer);
var IcarusMicrosystemsServer = new Server(createRandomIp(), "icarus", "Icarus Microsystems", false, false, false, 0); var IcarusMicrosystemsServer = new Server({
IcarusMicrosystemsServer.setHackingParameters(getRandomInt(850, 925), getRandomInt(900000000, 1000000000), getRandomInt(85, 95), getRandomInt(85, 95)); ip:createRandomIp(), hostname:"icarus", organizationName:"Icarus Microsystems",
IcarusMicrosystemsServer.setPortProperties(5); requiredHackingSkill:getRandomInt(850, 925), moneyAvailable:getRandomInt(900e6, 1000e6),
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(85, 95), numOpenPortsRequired:5
});
AddToAllServers(IcarusMicrosystemsServer); AddToAllServers(IcarusMicrosystemsServer);
var UniversalEnergyServer = new Server(createRandomIp(), "univ-energy", "Universal Energy", false, false, false, 32); var UniversalEnergyServer = new Server({
UniversalEnergyServer.setHackingParameters(getRandomInt(800, 900), getRandomInt(1100000000, 1200000000), getRandomInt(80, 90), getRandomInt(80, 90)); ip:createRandomIp(), hostname:"univ-energy", organizationName:"Universal Energy", maxRam:64,
UniversalEnergyServer.setPortProperties(4); requiredHackingSkill:getRandomInt(800, 900), moneyAvailable:getRandomInt(1.1e9, 1.2e9),
hackDifficulty:getRandomInt(80, 90), serverGrowth:getRandomInt(80, 90), numOpenPortsRequired:4
});
AddToAllServers(UniversalEnergyServer); AddToAllServers(UniversalEnergyServer);
var TitanLabsServer = new Server(createRandomIp(), "titan-labs", "Titan Laboratories", false, false, false, 32); var TitanLabsServer = new Server({
TitanLabsServer.setHackingParameters(getRandomInt(800, 875), getRandomInt(750000000, 900000000), getRandomInt(70, 80), getRandomInt(60, 80)); ip:createRandomIp(), hostname:"titan-labs", organizationName:"Titan Laboratories", maxRam:64,
TitanLabsServer.setPortProperties(5); requiredHackingSkill:getRandomInt(800, 875), moneyAvailable:getRandomInt(750e6, 900e6),
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(60, 80), numOpenPortsRequired:5
});
TitanLabsServer.messages.push("coded-intelligence.lit"); TitanLabsServer.messages.push("coded-intelligence.lit");
AddToAllServers(TitanLabsServer); AddToAllServers(TitanLabsServer);
var MicrodyneTechnologiesServer = new Server(createRandomIp(), "microdyne", "Microdyne Technologies", false, false, false, 16); var MicrodyneTechnologiesServer = new Server({
MicrodyneTechnologiesServer.setHackingParameters(getRandomInt(800, 875), getRandomInt(500000000, 700000000), getRandomInt(65, 75), getRandomInt(70, 90)); ip:createRandomIp(), hostname:"microdyne", organizationName:"Microdyne Technologies", maxRam:32,
MicrodyneTechnologiesServer.setPortProperties(5); requiredHackingSkill:getRandomInt(800, 875), moneyAvailable:getRandomInt(500e6, 700e6),
hackDifficulty:getRandomInt(65, 75), serverGrowth:getRandomInt(70, 90), numOpenPortsRequired:5
});
MicrodyneTechnologiesServer.messages.push("synthetic-muscles.lit"); MicrodyneTechnologiesServer.messages.push("synthetic-muscles.lit");
AddToAllServers(MicrodyneTechnologiesServer); AddToAllServers(MicrodyneTechnologiesServer);
var TaiYangDigitalServer = new Server(createRandomIp(), "taiyang-digital", "Taiyang Digital", false, false, false, 2); var TaiYangDigitalServer = new Server({
TaiYangDigitalServer.setHackingParameters(getRandomInt(850, 950), getRandomInt(800000000, 900000000), getRandomInt(70, 80), getRandomInt(70, 80)); ip:createRandomIp(), hostname:"taiyang-digital", organizationName:"Taiyang Digital",
TaiYangDigitalServer.setPortProperties(5); requiredHackingSkill:getRandomInt(850, 950), moneyAvailable:getRandomInt(800e6, 900e6),
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:5
});
TaiYangDigitalServer.messages.push("A-Green-Tomorrow.lit"); TaiYangDigitalServer.messages.push("A-Green-Tomorrow.lit");
TaiYangDigitalServer.messages.push("brighter-than-the-sun.lit"); TaiYangDigitalServer.messages.push("brighter-than-the-sun.lit");
AddToAllServers(TaiYangDigitalServer); AddToAllServers(TaiYangDigitalServer);
var GalacticCyberSystemsServer = new Server(createRandomIp(), "galactic-cyber", "Galactic Cybersystems", false, false, false, 0); var GalacticCyberSystemsServer = new Server({
GalacticCyberSystemsServer.setHackingParameters(getRandomInt(825, 875), getRandomInt(750000000, 850000000), getRandomInt(55, 65), getRandomInt(70, 90)); ip:createRandomIp(), hostname:"galactic-cyber", organizationName:"Galactic Cybersystems",
GalacticCyberSystemsServer.setPortProperties(5); requiredHackingSkill:getRandomInt(825, 875), moneyAvailable:getRandomInt(750e6, 850e6),
hackDifficulty:getRandomInt(55, 65), serverGrowth:getRandomInt(70, 90), numOpenPortsRequired:5
});
AddToAllServers(GalacticCyberSystemsServer); AddToAllServers(GalacticCyberSystemsServer);
//Defense Companies ("Large" Companies) //Defense Companies ("Large" Companies)
var AeroCorpServer = new Server(createRandomIp(), "aerocorp", "AeroCorp", false, false, false, 2); var AeroCorpServer = new Server({
AeroCorpServer.setHackingParameters(getRandomInt(850, 925), getRandomInt(1000000000, 1200000000), getRandomInt(80, 90), getRandomInt(55, 65)); ip:createRandomIp(), hostname:"aerocorp", organizationName:"AeroCorp",
AeroCorpServer.setPortProperties(5); requiredHackingSkill:getRandomInt(850, 925), moneyAvailable:getRandomInt(1e9, 1.2e9),
hackDifficulty:getRandomInt(80, 90), serverGrowth:getRandomInt(55, 65), numOpenPortsRequired:5
});
AeroCorpServer.messages.push("man-and-machine.lit"); AeroCorpServer.messages.push("man-and-machine.lit");
AddToAllServers(AeroCorpServer); AddToAllServers(AeroCorpServer);
var OmniaCybersystemsServer = new Server(createRandomIp(), "omnia", "Omnia Cybersystems", false, false, false, 0); var OmniaCybersystemsServer = new Server({
OmniaCybersystemsServer.setHackingParameters(getRandomInt(850, 950), getRandomInt(900000000, 1000000000), getRandomInt(85, 95), getRandomInt(60, 70)); ip:createRandomIp(), hostname:"omnia", organizationName:"Omnia Cybersystems", maxRam:64,
OmniaCybersystemsServer.setPortProperties(5); requiredHackingSkill:getRandomInt(850, 950), moneyAvailable:getRandomInt(900e6, 1e9),
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(60, 70), numOpenPortsRequired:5
});
OmniaCybersystemsServer.messages.push("history-of-synthoids.lit");
AddToAllServers(OmniaCybersystemsServer); AddToAllServers(OmniaCybersystemsServer);
var ZBDefenseServer = new Server(createRandomIp(), "zb-def", "ZB Defense Industries", false, false, false, 2); var ZBDefenseServer = new Server({
ZBDefenseServer.setHackingParameters(getRandomInt(775, 825), getRandomInt(900000000, 1100000000), getRandomInt(55, 65), getRandomInt(65, 75)); ip:createRandomIp(), hostname:"zb-def", organizationName:"ZB Defense Industries",
ZBDefenseServer.setPortProperties(4); requiredHackingSkill:getRandomInt(775, 825), moneyAvailable:getRandomInt(900e6, 1.1e9),
hackDifficulty:getRandomInt(55, 65), serverGrowth:getRandomInt(65, 75), numOpenPortsRequired:4
});
ZBDefenseServer.messages.push("synthetic-muscles.lit"); ZBDefenseServer.messages.push("synthetic-muscles.lit");
AddToAllServers(ZBDefenseServer); AddToAllServers(ZBDefenseServer);
var AppliedEnergeticsServer = new Server(createRandomIp(), "applied-energetics", "Applied Energetics", false, false, false, 0); var AppliedEnergeticsServer = new Server({
AppliedEnergeticsServer.setHackingParameters(getRandomInt(775, 850), getRandomInt(700000000, 1000000000), getRandomInt(60, 80), getRandomInt(70, 75)); ip:createRandomIp(), hostname:"applied-energetics", organizationName:"Applied Energetics",
AppliedEnergeticsServer.setPortProperties(4); requiredHackingSkill:getRandomInt(775, 850), moneyAvailable:getRandomInt(700e6, 1e9),
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(70, 75), numOpenPortsRequired:4
});
AddToAllServers(AppliedEnergeticsServer); AddToAllServers(AppliedEnergeticsServer);
var SolarisSpaceSystemsServer = new Server(createRandomIp(), "solaris", "Solaris Space Systems", false, false, false, 2); var SolarisSpaceSystemsServer = new Server({
SolarisSpaceSystemsServer.setHackingParameters(getRandomInt(750, 850), getRandomInt(700000000, 900000000), getRandomInt(70, 80), getRandomInt(70, 80)); ip:createRandomIp(), hostname:"solaris", organizationName:"Solaris Space Systems", maxRam:64,
SolarisSpaceSystemsServer.setPortProperties(5); requiredHackingSkill:getRandomInt(750, 850), moneyAvailable:getRandomInt(700e6, 900e6),
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:5
});
SolarisSpaceSystemsServer.messages.push("A-Green-Tomorrow.lit"); SolarisSpaceSystemsServer.messages.push("A-Green-Tomorrow.lit");
SolarisSpaceSystemsServer.messages.push("the-failed-frontier.lit"); SolarisSpaceSystemsServer.messages.push("the-failed-frontier.lit");
AddToAllServers(SolarisSpaceSystemsServer); AddToAllServers(SolarisSpaceSystemsServer);
var DeltaOneServer = new Server(createRandomIp(), "deltaone", "Delta One", false, false, false, 0); var DeltaOneServer = new Server({
DeltaOneServer.setHackingParameters(getRandomInt(800, 900), getRandomInt(1300000000, 1700000000), getRandomInt(75, 85), getRandomInt(50, 70)); ip:createRandomIp(), hostname:"deltaone", organizationName:"Delta One",
DeltaOneServer.setPortProperties(5); requiredHackingSkill:getRandomInt(800, 900), moneyAvailable:getRandomInt(1.3e9, 1.7e9),
hackDifficulty:getRandomInt(75, 85), serverGrowth:getRandomInt(50, 70), numOpenPortsRequired:5
});
AddToAllServers(DeltaOneServer); AddToAllServers(DeltaOneServer);
//Health, medicine, pharmaceutical companies ("Large" targets) //Health, medicine, pharmaceutical companies ("Large" targets)
var GlobalPharmaceuticalsServer = new Server(createRandomIp(), "global-pharm", "Global Pharmaceuticals", false, false, false, 16); var GlobalPharmaceuticalsServer = new Server({
GlobalPharmaceuticalsServer.setHackingParameters(getRandomInt(750, 850), getRandomInt(1500000000, 1750000000), getRandomInt(75, 85), getRandomInt(80, 90)); ip:createRandomIp(), hostname:"global-pharm", organizationName:"Global Pharmaceuticals", maxRam:32,
GlobalPharmaceuticalsServer.setPortProperties(4); requiredHackingSkill:getRandomInt(750, 850), moneyAvailable:getRandomInt(1.5e9, 1.75e9),
hackDifficulty:getRandomInt(75, 85), serverGrowth:getRandomInt(80, 90), numOpenPortsRequired:4
});
GlobalPharmaceuticalsServer.messages.push("A-Green-Tomorrow.lit"); GlobalPharmaceuticalsServer.messages.push("A-Green-Tomorrow.lit");
AddToAllServers(GlobalPharmaceuticalsServer); AddToAllServers(GlobalPharmaceuticalsServer);
var NovaMedicalServer = new Server(createRandomIp(), "nova-med", "Nova Medical", false, false, false, 0); var NovaMedicalServer = new Server({
NovaMedicalServer.setHackingParameters(getRandomInt(775, 850), getRandomInt(1100000000, 1250000000), getRandomInt(60, 80), getRandomInt(65, 85)); ip:createRandomIp(), hostname:"nova-med", organizationName:"Nova Medical",
NovaMedicalServer.setPortProperties(4); requiredHackingSkill:getRandomInt(775, 850), moneyAvailable:getRandomInt(1.1e9, 1.25e9),
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(65, 85), numOpenPortsRequired:4
});
AddToAllServers(NovaMedicalServer); AddToAllServers(NovaMedicalServer);
var ZeusMedicalServer = new Server(createRandomIp(), "zeus-med", "Zeus Medical", false, false, false, 0); var ZeusMedicalServer = new Server({
ZeusMedicalServer.setHackingParameters(getRandomInt(800, 850), getRandomInt(1300000000, 1500000000), getRandomInt(70, 90), getRandomInt(70, 80)); ip:createRandomIp(), hostname:"zeus-med", organizationName:"Zeus Medical",
ZeusMedicalServer.setPortProperties(5); requiredHackingSkill:getRandomInt(800, 850), moneyAvailable:getRandomInt(1.3e9, 1.5e9),
hackDifficulty:getRandomInt(70, 90), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:5
});
AddToAllServers(ZeusMedicalServer); AddToAllServers(ZeusMedicalServer);
var UnitaLifeGroupServer = new Server(createRandomIp(), "unitalife", "UnitaLife Group", false, false, false, 32); var UnitaLifeGroupServer = new Server({
UnitaLifeGroupServer.setHackingParameters(getRandomInt(775, 825), getRandomInt(1000000000, 1100000000), getRandomInt(70, 80), getRandomInt(70, 80)); ip:createRandomIp(), hostname:"unitalife", organizationName:"UnitaLife Group", maxRam:32,
UnitaLifeGroupServer.setPortProperties(4); requiredHackingSkill:getRandomInt(775, 825), moneyAvailable:getRandomInt(1e9, 1.1e9),
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:4
});
AddToAllServers(UnitaLifeGroupServer); AddToAllServers(UnitaLifeGroupServer);
//"Medium level" targets //"Medium level" targets
var LexoCorpServer = new Server(createRandomIp(), "lexo-corp", "Lexo Corporation", false, false, false, 16); var LexoCorpServer = new Server({
LexoCorpServer.setHackingParameters(getRandomInt(650, 750), getRandomInt(700000000, 800000000), getRandomInt(60, 80), getRandomInt(55, 65)); ip:createRandomIp(), hostname:"lexo-corp", organizationName:"Lexo Corporation", maxRam:32,
LexoCorpServer.setPortProperties(4); requiredHackingSkill:getRandomInt(650, 750), moneyAvailable:getRandomInt(700e6, 800e6),
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(55, 65), numOpenPortsRequired:4
});
AddToAllServers(LexoCorpServer); AddToAllServers(LexoCorpServer);
var RhoConstructionServer = new Server(createRandomIp(), "rho-construction", "Rho Construction", false, false, false, 0); var RhoConstructionServer = new Server({
RhoConstructionServer.setHackingParameters(getRandomInt(475, 525), getRandomInt(500000000, 700000000), getRandomInt(40, 60), getRandomInt(40, 60)); ip:createRandomIp(), hostname:"rho-construction", organizationName:"Rho Construction",
RhoConstructionServer.setPortProperties(3); requiredHackingSkill:getRandomInt(475, 525), moneyAvailable:getRandomInt(500e6, 700e6),
hackDifficulty:getRandomInt(40, 60), serverGrowth:getRandomInt(40, 60), numOpenPortsRequired:3
});
AddToAllServers(RhoConstructionServer); AddToAllServers(RhoConstructionServer);
var AlphaEnterprisesServer = new Server(createRandomIp(), "alpha-ent", "Alpha Enterprises", false, false, false, 2); var AlphaEnterprisesServer = new Server({
AlphaEnterprisesServer.setHackingParameters(getRandomInt(500, 600), getRandomInt(600000000, 750000000), getRandomInt(50, 70), getRandomInt(50, 60)); ip:createRandomIp(), hostname:"alpha-ent", organizationName:"Alpha Enterprises", maxRam:32,
AlphaEnterprisesServer.setPortProperties(4); requiredHackingSkill:getRandomInt(500, 600), moneyAvailable:getRandomInt(600e6, 750e6),
hackDifficulty:getRandomInt(50, 70), serverGrowth:getRandomInt(50, 60),numOpenPortsRequired:4
});
AlphaEnterprisesServer.messages.push("sector-12-crime.lit"); AlphaEnterprisesServer.messages.push("sector-12-crime.lit");
AddToAllServers(AlphaEnterprisesServer); AddToAllServers(AlphaEnterprisesServer);
var AevumPoliceServer = new Server(createRandomIp(), "aevum-police", "Aevum Police Network", false, false, false, 0); var AevumPoliceServer = new Server({
AevumPoliceServer.setHackingParameters(getRandomInt(400, 450), getRandomInt(200000000, 400000000), getRandomInt(70, 80), getRandomInt(30, 50)); ip:createRandomIp(), hostname:"aevum-police", organizationName:"Aevum Police Network", maxRam:32,
AevumPoliceServer.setPortProperties(4); requiredHackingSkill:getRandomInt(400, 450), moneyAvailable:getRandomInt(200e6, 400e6),
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(30, 50), numOpenPortsRequired:4
});
AddToAllServers(AevumPoliceServer); AddToAllServers(AevumPoliceServer);
var RothmanUniversityServer = new Server(createRandomIp(), "rothman-uni", "Rothman University Network", false, false, false, 4); var RothmanUniversityServer = new Server({
RothmanUniversityServer.setHackingParameters(getRandomInt(370, 430), getRandomInt(175000000, 250000000), getRandomInt(45, 55), getRandomInt(35, 45)); ip:createRandomIp(), hostname:"rothman-uni", organizationName:"Rothman University Network", maxRam:64,
RothmanUniversityServer.setPortProperties(3); requiredHackingSkill:getRandomInt(370, 430), moneyAvailable:getRandomInt(175e6, 250e6),
hackDifficulty:getRandomInt(45, 55), serverGrowth:getRandomInt(35, 45), numOpenPortsRequired:3
});
RothmanUniversityServer.messages.push("secret-societies.lit"); RothmanUniversityServer.messages.push("secret-societies.lit");
RothmanUniversityServer.messages.push("the-failed-frontier.lit"); RothmanUniversityServer.messages.push("the-failed-frontier.lit");
RothmanUniversityServer.messages.push("tensions-in-tech-race.lit"); RothmanUniversityServer.messages.push("tensions-in-tech-race.lit");
AddToAllServers(RothmanUniversityServer); AddToAllServers(RothmanUniversityServer);
var ZBInstituteOfTechnologyServer = new Server(createRandomIp(), "zb-institute", "ZB Institute of Technology Network", false, false, false, 4); var ZBInstituteOfTechnologyServer = new Server({
ZBInstituteOfTechnologyServer.setHackingParameters(getRandomInt(725, 775), getRandomInt(800000000, 1100000000), getRandomInt(65, 85), getRandomInt(75, 85)); ip:createRandomIp(), hostname:"zb-institute", organizationName:"ZB Institute of Technology Network", maxRam:64,
ZBInstituteOfTechnologyServer.setPortProperties(5); requiredHackingSkill:getRandomInt(725, 775), moneyAvailable:getRandomInt(800e6, 1.1e9),
hackDifficulty:getRandomInt(65, 85), serverGrowth:getRandomInt(75, 85), numOpenPortsRequired:5
});
AddToAllServers(ZBInstituteOfTechnologyServer); AddToAllServers(ZBInstituteOfTechnologyServer);
var SummitUniversityServer = new Server(createRandomIp(), "summit-uni", "Summit University Network", false, false, false, 4); var SummitUniversityServer = new Server({
SummitUniversityServer.setHackingParameters(getRandomInt(425, 475), getRandomInt(200000000, 350000000), getRandomInt(45, 65), getRandomInt(40, 60)); ip:createRandomIp(), hostname:"summit-uni", organizationName:"Summit University Network", maxRam:32,
SummitUniversityServer.setPortProperties(3); requiredHackingSkill:getRandomInt(425, 475), moneyAvailable:getRandomInt(200e6, 350e6),
hackDifficulty:getRandomInt(45, 65), serverGrowth:getRandomInt(40, 60), numOpenPortsRequired:3
});
SummitUniversityServer.messages.push("secret-societies.lit"); SummitUniversityServer.messages.push("secret-societies.lit");
SummitUniversityServer.messages.push("the-failed-frontier.lit"); SummitUniversityServer.messages.push("the-failed-frontier.lit");
SummitUniversityServer.messages.push("synthetic-muscles.lit"); SummitUniversityServer.messages.push("synthetic-muscles.lit");
AddToAllServers(SummitUniversityServer); AddToAllServers(SummitUniversityServer);
var SysCoreSecuritiesServer = new Server(createRandomIp(), "syscore", "SysCore Securities", false, false, false, 0); var SysCoreSecuritiesServer = new Server({
SysCoreSecuritiesServer.setHackingParameters(getRandomInt(550, 650), getRandomInt(400000000, 600000000), getRandomInt(60, 80), getRandomInt(60, 70)); ip:createRandomIp(), hostname:"syscore", organizationName:"SysCore Securities",
SysCoreSecuritiesServer.setPortProperties(4); requiredHackingSkill:getRandomInt(550, 650), moneyAvailable:getRandomInt(400e6, 600e6),
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(60, 70), numOpenPortsRequired:4
});
AddToAllServers(SysCoreSecuritiesServer); AddToAllServers(SysCoreSecuritiesServer);
var CatalystVenturesServer = new Server(createRandomIp(), "catalyst", "Catalyst Ventures", false, false, false, 2); var CatalystVenturesServer = new Server({
CatalystVenturesServer.setHackingParameters(getRandomInt(400, 450), getRandomInt(300000000, 550000000), getRandomInt(60, 70), getRandomInt(25, 55)); ip:createRandomIp(), hostname:"catalyst", organizationName:"Catalyst Ventures",
CatalystVenturesServer.setPortProperties(3); requiredHackingSkill:getRandomInt(400, 450), moneyAvailable:getRandomInt(300e6, 550e6),
hackDifficulty:getRandomInt(60, 70), serverGrowth:getRandomInt(25, 55), numOpenPortsRequired:3,
});
CatalystVenturesServer.messages.push("tensions-in-tech-race.lit"); CatalystVenturesServer.messages.push("tensions-in-tech-race.lit");
AddToAllServers(CatalystVenturesServer); AddToAllServers(CatalystVenturesServer);
var TheHubServer = new Server(createRandomIp(), "the-hub", "The Hub", false, false, false, 0); var TheHubServer = new Server({
TheHubServer.setHackingParameters(getRandomInt(275, 325), getRandomInt(150000000, 200000000), getRandomInt(35, 45), getRandomInt(45, 55)); ip:createRandomIp(), hostname:"the-hub", organizationName:"The Hub",
TheHubServer.setPortProperties(2); requiredHackingSkill:getRandomInt(275, 325), moneyAvailable:getRandomInt(150e6, 200e6),
hackDifficulty:getRandomInt(35, 45), serverGrowth:getRandomInt(45, 55), numOpenPortsRequired:2
});
AddToAllServers(TheHubServer); AddToAllServers(TheHubServer);
var CompuTekServer = new Server(createRandomIp(), "comptek", "CompuTek", false, false, false, 8); var CompuTekServer = new Server({
CompuTekServer.setHackingParameters(getRandomInt(300, 400), getRandomInt(220000000, 250000000), getRandomInt(55, 65), getRandomInt(45, 65)); ip:createRandomIp(), hostname:"comptek", organizationName:"CompuTek",
CompuTekServer.setPortProperties(3); requiredHackingSkill:getRandomInt(300, 400), moneyAvailable:getRandomInt(220e6, 250e6),
hackDifficulty:getRandomInt(55, 65), serverGrowth:getRandomInt(45, 65), numOpenPortsRequired:3
});
CompuTekServer.messages.push("man-and-machine.lit"); CompuTekServer.messages.push("man-and-machine.lit");
AddToAllServers(CompuTekServer); AddToAllServers(CompuTekServer);
var NetLinkTechnologiesServer = new Server(createRandomIp(), "netlink", "NetLink Technologies", false, false, false, 2); var NetLinkTechnologiesServer = new Server({
NetLinkTechnologiesServer.setHackingParameters(getRandomInt(375, 425), 275000000, getRandomInt(60, 80), getRandomInt(45, 75)); ip:createRandomIp(), hostname:"netlink", organizationName:"NetLink Technologies", maxRam:64,
NetLinkTechnologiesServer.setPortProperties(3); requiredHackingSkill:getRandomInt(375, 425), moneyAvailable:275e6,
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(45, 75), numOpenPortsRequired:3
});
NetLinkTechnologiesServer.messages.push("simulated-reality.lit"); NetLinkTechnologiesServer.messages.push("simulated-reality.lit");
AddToAllServers(NetLinkTechnologiesServer); AddToAllServers(NetLinkTechnologiesServer);
var JohnsonOrthopedicsServer = new Server(createRandomIp(), "johnson-ortho", "Johnson Orthopedics", false, false, false, 4); var JohnsonOrthopedicsServer = new Server({
JohnsonOrthopedicsServer.setHackingParameters(getRandomInt(250, 300), getRandomInt(70000000, 85000000), getRandomInt(35, 65), getRandomInt(35, 65)); ip:createRandomIp(), hostname:"johnson-ortho", organizationName:"Johnson Orthopedics",
JohnsonOrthopedicsServer.setPortProperties(2); requiredHackingSkill:getRandomInt(250, 300), moneyAvailable:getRandomInt(70e6, 85e6),
hackDifficulty:getRandomInt(35, 65), serverGrowth:getRandomInt(35, 65), numOpenPortsRequired:2
});
AddToAllServers(JohnsonOrthopedicsServer); AddToAllServers(JohnsonOrthopedicsServer);
//"Low level" targets //"Low level" targets
var FoodNStuffServer = new Server(createRandomIp(), "foodnstuff", "Food N Stuff Supermarket", false, false, false, 16); var FoodNStuffServer = new Server({
FoodNStuffServer.setHackingParameters(1, 2000000, 10, 5); ip:createRandomIp(), hostname:"foodnstuff", organizationName:"Food N Stuff Supermarket", maxRam:16,
FoodNStuffServer.setPortProperties(0); requiredHackingSkill:1, moneyAvailable:2e6,
hackDifficulty:10, serverGrowth:5, numOpenPortsRequired:0
});
FoodNStuffServer.messages.push("sector-12-crime.lit"); FoodNStuffServer.messages.push("sector-12-crime.lit");
AddToAllServers(FoodNStuffServer); AddToAllServers(FoodNStuffServer);
var SigmaCosmeticsServer = new Server(createRandomIp(), "sigma-cosmetics", "Sigma Cosmetics", false, false, false, 16); var SigmaCosmeticsServer = new Server({
SigmaCosmeticsServer.setHackingParameters(5, 2300000, 10, 10); ip:createRandomIp(), hostname:"sigma-cosmetics", organizationName:"Sigma Cosmetics", maxRam:16,
SigmaCosmeticsServer.setPortProperties(0); requiredHackingSkill:5, moneyAvailable:2.3e6,
hackDifficulty:10, serverGrowth:10, numOpenPortsRequired:0
});
AddToAllServers(SigmaCosmeticsServer); AddToAllServers(SigmaCosmeticsServer);
var JoesGunsServer = new Server(createRandomIp(), "joesguns", "Joe's Guns", false, false, false, 16); var JoesGunsServer = new Server({
JoesGunsServer.setHackingParameters(10, 2500000, 15, 20); ip:createRandomIp(), hostname:"joesguns", organizationName:"Joe's Guns", maxRam:16,
JoesGunsServer.setPortProperties(0); requiredHackingSkill:10, moneyAvailable:2.5e6,
hackDifficulty:15, serverGrowth:20, numOpenPortsRequired:0
});
AddToAllServers(JoesGunsServer); AddToAllServers(JoesGunsServer);
var Zer0NightclubServer = new Server(createRandomIp(), "zer0", "ZER0 Nightclub", false, false, false, 32); var Zer0NightclubServer = new Server({
Zer0NightclubServer.setHackingParameters(75, 7500000, 25, 40); ip:createRandomIp(), hostname:"zer0", organizationName:"ZER0 Nightclub", maxRam:32,
Zer0NightclubServer.setPortProperties(1); requiredHackingSkill:75, moneyAvailable:7.5e6,
hackDifficulty:25, serverGrowth:40, numOpenPortsRequired:1
});
AddToAllServers(Zer0NightclubServer); AddToAllServers(Zer0NightclubServer);
var NectarNightclubServer = new Server(createRandomIp(), "nectar-net", "Nectar Nightclub Network", false, false, false, 8); var NectarNightclubServer = new Server({
NectarNightclubServer.setHackingParameters(20, 2750000, 20, 25); ip:createRandomIp(), hostname:"nectar-net", organizationName:"Nectar Nightclub Network", maxRam:16,
NectarNightclubServer.setPortProperties(0); requiredHackingSkill:20, moneyAvailable:2.75e6,
hackDifficulty:20, serverGrowth:25, numOpenPortsRequired:0
});
AddToAllServers(NectarNightclubServer); AddToAllServers(NectarNightclubServer);
var NeoNightclubServer = new Server(createRandomIp(), "neo-net", "Neo Nightclub Network", false, false, false, 32); var NeoNightclubServer = new Server({
NeoNightclubServer.setHackingParameters(50, 5000000, 25, 25); ip:createRandomIp(), hostname:"neo-net", organizationName:"Neo Nightclub Network", maxRam:32,
NeoNightclubServer.setPortProperties(1); requiredHackingSkill:50, moneyAvailable:5e6,
hackDifficulty:25, serverGrowth:25, numOpenPortsRequired:1
});
NeoNightclubServer.messages.push("the-hidden-world.lit"); NeoNightclubServer.messages.push("the-hidden-world.lit");
AddToAllServers(NeoNightclubServer); AddToAllServers(NeoNightclubServer);
var SilverHelixServer = new Server(createRandomIp(), "silver-helix", "Silver Helix", false, false, false, 64); var SilverHelixServer = new Server({
SilverHelixServer.setHackingParameters(150, 45000000, 30, 30); ip:createRandomIp(), hostname:"silver-helix", organizationName:"Silver Helix", maxRam:64,
SilverHelixServer.setPortProperties(2); requiredHackingSkill:150, moneyAvailable:45e6,
hackDifficulty:30, serverGrowth:30, numOpenPortsRequired:2
});
SilverHelixServer.messages.push("new-triads.lit"); SilverHelixServer.messages.push("new-triads.lit");
AddToAllServers(SilverHelixServer); AddToAllServers(SilverHelixServer);
var HongFangTeaHouseServer = new Server(createRandomIp(), "hong-fang-tea", "HongFang Teahouse", false, false, false, 16); var HongFangTeaHouseServer = new Server({
HongFangTeaHouseServer.setHackingParameters(30, 3000000, 15, 20); ip:createRandomIp(), hostname:"hong-fang-tea", organizationName:"HongFang Teahouse", maxRam:16,
HongFangTeaHouseServer.setPortProperties(0); requiredHackingSkill:30, moneyAvailable:3e6,
hackDifficulty:15, serverGrowth:20, numOpenPortsRequired:0
});
HongFangTeaHouseServer.messages.push("brighter-than-the-sun.lit"); HongFangTeaHouseServer.messages.push("brighter-than-the-sun.lit");
AddToAllServers(HongFangTeaHouseServer); AddToAllServers(HongFangTeaHouseServer);
var HaraKiriSushiBarServer = new Server(createRandomIp(), "harakiri-sushi", "HaraKiri Sushi Bar Network", false, false, false, 16); var HaraKiriSushiBarServer = new Server({
HaraKiriSushiBarServer.setHackingParameters(40, 4000000, 15, 40); ip:createRandomIp(), hostname:"harakiri-sushi", organizationName:"HaraKiri Sushi Bar Network",maxRam:16,
HaraKiriSushiBarServer.setPortProperties(0); requiredHackingSkill:40, moneyAvailable:4e6,
hackDifficulty:15, serverGrowth:40, numOpenPortsRequired:0
});
AddToAllServers(HaraKiriSushiBarServer); AddToAllServers(HaraKiriSushiBarServer);
var PhantasyServer = new Server(createRandomIp(), "phantasy", "Phantasy Club", false, false, false, 32); var PhantasyServer = new Server({
PhantasyServer.setHackingParameters(100, 24000000, 20, 35); ip:createRandomIp(), hostname:"phantasy", organizationName:"Phantasy Club", maxRam:32,
PhantasyServer.setPortProperties(2); requiredHackingSkill:100, moneyAvailable:24e6,
hackDifficulty:20, serverGrowth:35, numOpenPortsRequired:2
});
AddToAllServers(PhantasyServer); AddToAllServers(PhantasyServer);
var MaxHardwareServer = new Server(createRandomIp(), "max-hardware", "Max Hardware Store", false, false, false, 32); var MaxHardwareServer = new Server({
MaxHardwareServer.setHackingParameters(80, 10000000, 15, 30); ip:createRandomIp(), hostname:"max-hardware", organizationName:"Max Hardware Store", maxRam:32,
MaxHardwareServer.setPortProperties(1); requiredHackingSkill:80, moneyAvailable:10e6,
hackDifficulty:15, serverGrowth:30, numOpenPortsRequired:1,
});
AddToAllServers(MaxHardwareServer); AddToAllServers(MaxHardwareServer);
var OmegaSoftwareServer = new Server(createRandomIp(), "omega-net", "Omega Software", false, false, false, 32); var OmegaSoftwareServer = new Server({
OmegaSoftwareServer.setHackingParameters(getRandomInt(180, 220), getRandomInt(60000000, 70000000), getRandomInt(25, 35), getRandomInt(30, 40)); ip:createRandomIp(), hostname:"omega-net", organizationName:"Omega Software", maxRam:32,
OmegaSoftwareServer.setPortProperties(2); requiredHackingSkill:getRandomInt(180, 220), moneyAvailable:getRandomInt(60e6, 70e6),
hackDifficulty:getRandomInt(25, 35), serverGrowth:getRandomInt(30, 40), numOpenPortsRequired:2
});
OmegaSoftwareServer.messages.push("the-new-god.lit"); OmegaSoftwareServer.messages.push("the-new-god.lit");
AddToAllServers(OmegaSoftwareServer); AddToAllServers(OmegaSoftwareServer);
//Gyms //Gyms
var CrushFitnessGymServer = new Server(createRandomIp(), "crush-fitness", "Crush Fitness", false, false, false, 0); var CrushFitnessGymServer = new Server({
CrushFitnessGymServer.setHackingParameters(getRandomInt(225, 275), getRandomInt(40000000, 60000000), getRandomInt(35, 45), getRandomInt(27, 33)); ip:createRandomIp(), hostname:"crush-fitness", organizationName:"Crush Fitness",
CrushFitnessGymServer.setPortProperties(2); requiredHackingSkill:getRandomInt(225, 275), moneyAvailable:getRandomInt(40e6, 60e6),
hackDifficulty:getRandomInt(35, 45), serverGrowth:getRandomInt(27, 33), numOpenPortsRequired:2
});
AddToAllServers(CrushFitnessGymServer); AddToAllServers(CrushFitnessGymServer);
var IronGymServer = new Server(createRandomIp(), "iron-gym", "Iron Gym Network", false, false, false, 32); var IronGymServer = new Server({
IronGymServer.setHackingParameters(100, 20000000, 30, 20); ip:createRandomIp(), hostname:"iron-gym", organizationName:"Iron Gym Network", maxRam:32,
IronGymServer.setPortProperties(1); requiredHackingSkill:100, moneyAvailable:20e6,
hackDifficulty:30, serverGrowth:20, numOpenPortsRequired:1
});
AddToAllServers(IronGymServer); AddToAllServers(IronGymServer);
var MilleniumFitnessGymServer = new Server(createRandomIp(), "millenium-fitness", "Millenium Fitness Network", false, false, false, 0); var MilleniumFitnessGymServer = new Server({
MilleniumFitnessGymServer.setHackingParameters(getRandomInt(475, 525), 250000000, getRandomInt(45, 55), getRandomInt(25, 45)); ip:createRandomIp(), hostname:"millenium-fitness", organizationName:"Millenium Fitness Network",
MilleniumFitnessGymServer.setPortProperties(3); requiredHackingSkill:getRandomInt(475, 525), moneyAvailable:250e6,
hackDifficulty:getRandomInt(45, 55), serverGrowth:getRandomInt(25, 45), numOpenPortsRequired:3,
});
AddToAllServers(MilleniumFitnessGymServer); AddToAllServers(MilleniumFitnessGymServer);
var PowerhouseGymServer = new Server(createRandomIp(), "powerhouse-fitness", "Powerhouse Fitness", false, false, false, 0); var PowerhouseGymServer = new Server({
PowerhouseGymServer.setHackingParameters(getRandomInt(950, 1100), 900000000, getRandomInt(55, 65), getRandomInt(50, 60)); ip:createRandomIp(), hostname:"powerhouse-fitness", organizationName:"Powerhouse Fitness",
PowerhouseGymServer.setPortProperties(5); requiredHackingSkill:getRandomInt(950, 1100), moneyAvailable:900e6,
hackDifficulty:getRandomInt(55, 65), serverGrowth:getRandomInt(50, 60), numOpenPortsRequired:5,
});
AddToAllServers(PowerhouseGymServer); AddToAllServers(PowerhouseGymServer);
var SnapFitnessGymServer = new Server(createRandomIp(), "snap-fitness", "Snap Fitness", false, false, false, 0); var SnapFitnessGymServer = new Server({
SnapFitnessGymServer.setHackingParameters(getRandomInt(675, 800), 450000000, getRandomInt(40, 60), getRandomInt(40, 60)); ip:createRandomIp(), hostname:"snap-fitness", organizationName:"Snap Fitness",
SnapFitnessGymServer.setPortProperties(4); requiredHackingSkill:getRandomInt(675, 800), moneyAvailable:450e6,
hackDifficulty:getRandomInt(40, 60), serverGrowth:getRandomInt(40, 60), numOpenPortsRequired:4
});
AddToAllServers(SnapFitnessGymServer); AddToAllServers(SnapFitnessGymServer);
//Faction servers, cannot hack money from these //Faction servers, cannot hack money from these
var BitRunnersServer = new Server(createRandomIp(), "run4theh111z", "The Runners", false, false, false, 2); var BitRunnersServer = new Server({
BitRunnersServer.setHackingParameters(getRandomInt(505, 550), 0, 0, 0); ip:createRandomIp(), hostname:"run4theh111z", organizationName:"The Runners", maxRam:128,
BitRunnersServer.setPortProperties(4); requiredHackingSkill:getRandomInt(505, 550), moneyAvailable:0,
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:4
});
BitRunnersServer.messages.push("simulated-reality.lit"); BitRunnersServer.messages.push("simulated-reality.lit");
BitRunnersServer.messages.push("the-new-god.lit"); BitRunnersServer.messages.push("the-new-god.lit");
AddToAllServers(BitRunnersServer); AddToAllServers(BitRunnersServer);
SpecialServerIps.addIp(SpecialServerNames.BitRunnersServer, BitRunnersServer.ip); SpecialServerIps.addIp(SpecialServerNames.BitRunnersServer, BitRunnersServer.ip);
var TheBlackHandServer = new Server(createRandomIp(), "I.I.I.I", "I.I.I.I", false, false, false, 2); var TheBlackHandServer = new Server({
TheBlackHandServer.setHackingParameters(getRandomInt(340, 365), 0, 0, 0); ip:createRandomIp(), hostname:"I.I.I.I", organizationName:"I.I.I.I", maxRam:64,
TheBlackHandServer.setPortProperties(3); requiredHackingSkill:getRandomInt(340, 365), moneyAvailable:0,
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:3,
});
TheBlackHandServer.messages.push("democracy-is-dead.lit"); TheBlackHandServer.messages.push("democracy-is-dead.lit");
AddToAllServers(TheBlackHandServer); AddToAllServers(TheBlackHandServer);
SpecialServerIps.addIp(SpecialServerNames.TheBlackHandServer, TheBlackHandServer.ip); SpecialServerIps.addIp(SpecialServerNames.TheBlackHandServer, TheBlackHandServer.ip);
var NiteSecServer = new Server(createRandomIp(), "avmnite-02h", "NiteSec", false, false, false, 2); var NiteSecServer = new Server({
NiteSecServer.setHackingParameters(getRandomInt(202, 220), 0, 0, 0); ip:createRandomIp(), hostname:"avmnite-02h", organizationName:"NiteSec", maxRam:32,
NiteSecServer.setPortProperties(2); requiredHackingSkill:getRandomInt(202, 220), moneyAvailable:0,
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:2
});
NiteSecServer.messages.push("democracy-is-dead.lit"); NiteSecServer.messages.push("democracy-is-dead.lit");
AddToAllServers(NiteSecServer); AddToAllServers(NiteSecServer);
SpecialServerIps.addIp(SpecialServerNames.NiteSecServer, NiteSecServer.ip); SpecialServerIps.addIp(SpecialServerNames.NiteSecServer, NiteSecServer.ip);
var DarkArmyServer = new Server(createRandomIp(), ".", ".", false, false, false, 0); var DarkArmyServer = new Server({
DarkArmyServer.setHackingParameters(getRandomInt(505, 550), 0, 0, 0); ip:createRandomIp(), hostname:".", organizationName:".", maxRam:16,
DarkArmyServer.setPortProperties(4); requiredHackingSkill:getRandomInt(505, 550), moneyAvailable:0,
AddToAllServers(DarkArmyServer); hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:4
});
AddToAllServers(DarkArmyServer);
SpecialServerIps.addIp(SpecialServerNames.TheDarkArmyServer, DarkArmyServer.ip); SpecialServerIps.addIp(SpecialServerNames.TheDarkArmyServer, DarkArmyServer.ip);
var CyberSecServer = new Server(createRandomIp(), "CSEC", "CyberSec", false, false, false, 2); var CyberSecServer = new Server({
CyberSecServer.setHackingParameters(getRandomInt(51, 60), 0, 0, 0); ip:createRandomIp(), hostname:"CSEC", organizationName:"CyberSec", maxRam:8,
CyberSecServer.setPortProperties(1); requiredHackingSkill:getRandomInt(51, 60), moneyAvailable:0,
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:1
});
CyberSecServer.messages.push("democracy-is-dead.lit"); CyberSecServer.messages.push("democracy-is-dead.lit");
AddToAllServers(CyberSecServer); AddToAllServers(CyberSecServer);
SpecialServerIps.addIp(SpecialServerNames.CyberSecServer, CyberSecServer.ip); SpecialServerIps.addIp(SpecialServerNames.CyberSecServer, CyberSecServer.ip);
var DaedalusServer = new Server(createRandomIp(), "The-Cave", "Helios", false, false, false, 2); var DaedalusServer = new Server({
DaedalusServer.setHackingParameters(925, 0, 0, 0); ip:createRandomIp(), hostname:"The-Cave", organizationName:"Helios",
DaedalusServer.setPortProperties(5); requiredHackingSkill:925, moneyAvailable:0,
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:5
});
DaedalusServer.messages.push("alpha-omega.lit"); DaedalusServer.messages.push("alpha-omega.lit");
AddToAllServers(DaedalusServer); AddToAllServers(DaedalusServer);
SpecialServerIps.addIp(SpecialServerNames.DaedalusServer, DaedalusServer.ip); SpecialServerIps.addIp(SpecialServerNames.DaedalusServer, DaedalusServer.ip);
//Super special Servers //Super special Servers
var WorldDaemon = new Server(createRandomIp(), SpecialServerNames.WorldDaemon, SpecialServerNames.WorldDaemon, false, false, false, 0); var WorldDaemon = new Server({
WorldDaemon.setHackingParameters(3000, 0, 0, 0); ip:createRandomIp(), hostname:SpecialServerNames.WorldDaemon, organizationName:SpecialServerNames.WorldDaemon,
WorldDaemon.setPortProperties(5); requiredHackingSkill:3000, moneyAvailable:0,
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:5
});
AddToAllServers(WorldDaemon); AddToAllServers(WorldDaemon);
SpecialServerIps.addIp(SpecialServerNames.WorldDaemon, WorldDaemon.ip); SpecialServerIps.addIp(SpecialServerNames.WorldDaemon, WorldDaemon.ip);
@ -655,7 +794,7 @@ function initForeignServers() {
//Applied server growth for a single server. Returns the percentage growth //Applied server growth for a single server. Returns the percentage growth
function processSingleServerGrowth(server, numCycles) { function processSingleServerGrowth(server, numCycles) {
//Server growth processed once every 450 game cycles //Server growth processed once every 450 game cycles
var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0); var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0);
//Get adjusted growth rate, which accounts for server security //Get adjusted growth rate, which accounts for server security
var growthRate = CONSTANTS.ServerBaseGrowthRate; var growthRate = CONSTANTS.ServerBaseGrowthRate;
@ -720,11 +859,11 @@ function loadAllServers(saveString) {
} }
function SizeOfAllServers() { function SizeOfAllServers() {
var size = 0, key; var size = 0, key;
for (key in AllServers) { for (key in AllServers) {
if (AllServers.hasOwnProperty(key)) size++; if (AllServers.hasOwnProperty(key)) size++;
} }
return size; return size;
} }
//Add a server onto the map of all servers in the game //Add a server onto the map of all servers in the game
@ -741,16 +880,16 @@ function AddToAllServers(server) {
} }
//Returns server object with corresponding hostname //Returns server object with corresponding hostname
// Relatively slow, would rather not use this a lot // Relatively slow, would rather not use this a lot
function GetServerByHostname(hostname) { function GetServerByHostname(hostname) {
for (var ip in AllServers) { for (var ip in AllServers) {
if (AllServers.hasOwnProperty(ip)) { if (AllServers.hasOwnProperty(ip)) {
if (AllServers[ip].hostname == hostname) { if (AllServers[ip].hostname == hostname) {
return AllServers[ip]; return AllServers[ip];
} }
} }
} }
return null; return null;
} }
//Get server by IP or hostname. Returns null if invalid //Get server by IP or hostname. Returns null if invalid

@ -32,7 +32,10 @@ function purchaseServer(ram, cost) {
} }
//Create server //Create server
var newServ = new Server(createRandomIp(), hostname, "", false, true, true, ram); var newServ = new Server({
ip:createRandomIp(), hostname:hostname, organizationName:"",
isConnectedTo:false, adminRights:true, purchasedByPlayer:true, maxRam:ram
});
AddToAllServers(newServ); AddToAllServers(newServ);
//Add to Player's purchasedServers array //Add to Player's purchasedServers array

@ -2,17 +2,18 @@ import {Engine} from "./engine.js";
/* Settings.js */ /* Settings.js */
let Settings = { let Settings = {
CodeInstructionRunTime: 50, CodeInstructionRunTime: 50,
MaxLogCapacity: 50, MaxLogCapacity: 50,
MaxPortCapacity: 50, MaxPortCapacity: 50,
SuppressMessages: false, SuppressMessages: false,
SuppressFactionInvites: false, SuppressFactionInvites: false,
AutosaveInterval: 60, AutosaveInterval: 60,
ThemeHighlightColor: "#ffffff", DisableHotkeys: false,
ThemeFontColor: "#66ff33", ThemeHighlightColor: "#ffffff",
ThemeBackgroundColor: "#000000", ThemeFontColor: "#66ff33",
EditorTheme: "Monokai", ThemeBackgroundColor: "#000000",
EditorKeybinding: "ace", EditorTheme: "Monokai",
EditorKeybinding: "ace",
} }
function loadSettings(saveString) { function loadSettings(saveString) {
@ -26,6 +27,7 @@ function initSettings() {
Settings.SuppressMessages = false; Settings.SuppressMessages = false;
Settings.SuppressFactionInvites = false; Settings.SuppressFactionInvites = false;
Settings.AutosaveInterval = 60; Settings.AutosaveInterval = 60;
Settings.DisableHotkeys = false;
} }
function setSettingsLabels() { function setSettingsLabels() {
@ -35,6 +37,7 @@ function setSettingsLabels() {
var suppressMsgs = document.getElementById("settingsSuppressMessages"); var suppressMsgs = document.getElementById("settingsSuppressMessages");
var suppressFactionInv = document.getElementById("settingsSuppressFactionInvites") var suppressFactionInv = document.getElementById("settingsSuppressFactionInvites")
var autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel"); var autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel");
var disableHotkeys = document.getElementById("settingsDisableHotkeys");
//Initialize values on labels //Initialize values on labels
nsExecTime.innerHTML = Settings.CodeInstructionRunTime + "ms"; nsExecTime.innerHTML = Settings.CodeInstructionRunTime + "ms";
@ -43,6 +46,7 @@ function setSettingsLabels() {
suppressMsgs.checked = Settings.SuppressMessages; suppressMsgs.checked = Settings.SuppressMessages;
suppressFactionInv.checked = Settings.SuppressFactionInvites; suppressFactionInv.checked = Settings.SuppressFactionInvites;
autosaveInterval.innerHTML = Settings.AutosaveInterval; autosaveInterval.innerHTML = Settings.AutosaveInterval;
disableHotkeys.checked = Settings.DisableHotkeys;
//Set handlers for when input changes //Set handlers for when input changes
var nsExecTimeInput = document.getElementById("settingsNSExecTimeRangeVal"); var nsExecTimeInput = document.getElementById("settingsNSExecTimeRangeVal");
@ -79,14 +83,18 @@ function setSettingsLabels() {
} }
}; };
document.getElementById("settingsSuppressMessages").onclick = function() { suppressMsgs.onclick = function() {
Settings.SuppressMessages = this.checked; Settings.SuppressMessages = this.checked;
}; };
document.getElementById("settingsSuppressFactionInvites").onclick = function() { suppressFactionInv.onclick = function() {
Settings.SuppressFactionInvites = this.checked; Settings.SuppressFactionInvites = this.checked;
}; };
disableHotkeys.onclick = function() {
Settings.DisableHotkeys = this.checked;
}
//Theme //Theme
if (Settings.ThemeHighlightColor == null || Settings.ThemeFontColor == null || Settings.ThemeBackgroundColor == null) { if (Settings.ThemeHighlightColor == null || Settings.ThemeFontColor == null || Settings.ThemeBackgroundColor == null) {
console.log("ERROR: Cannot find Theme Settings"); console.log("ERROR: Cannot find Theme Settings");

@ -19,7 +19,8 @@ import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
yesNoTxtInpBoxGetInput, yesNoBoxClose, yesNoTxtInpBoxGetInput, yesNoBoxClose,
yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox.js"; yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox.js";
/* StockMarket.js */ let StockPriceCap = 1e9; //Put a limit on how high a price can go
function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) { function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) {
this.symbol = symbol; this.symbol = symbol;
this.name = name; this.name = name;
@ -580,6 +581,10 @@ function updateStockPrices() {
chc = (chc - stock.otlkMag)/100; chc = (chc - stock.otlkMag)/100;
if (isNaN(chc)) {chc = 0.5;} if (isNaN(chc)) {chc = 0.5;}
} }
if (stock.price >= StockPriceCap) {
chc = -1; //Limit on stock price
stock.b = false;
}
var c = Math.random(); var c = Math.random();
if (c < chc) { if (c < chc) {

@ -22,7 +22,8 @@ import {killWorkerScript, addWorkerScript} from "./NetscriptWorker.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {hackWorldDaemon} from "./RedPill.js"; import {hackWorldDaemon} from "./RedPill.js";
import {findRunningScript, RunningScript, import {findRunningScript, RunningScript,
AllServersMap, Script} from "./Script.js"; AllServersMap, Script,
isScriptFilename} from "./Script.js";
import {AllServers, GetServerByHostname, import {AllServers, GetServerByHostname,
getServer, Server} from "./Server.js"; getServer, Server} from "./Server.js";
import {Settings} from "./Settings.js"; import {Settings} from "./Settings.js";
@ -85,11 +86,15 @@ var KEY = {
E: 69, E: 69,
F: 70, F: 70,
H: 72, H: 72,
J: 74,
K: 75, K: 75,
L: 76, L: 76,
M: 77, M: 77,
N: 78, N: 78,
O: 79,
P: 80, P: 80,
R: 82,
S: 83,
U: 85, U: 85,
W: 87, W: 87,
} }
@ -105,7 +110,12 @@ $(document).keydown(function(event) {
event.preventDefault(); //Prevent newline from being entered in Script Editor event.preventDefault(); //Prevent newline from being entered in Script Editor
var command = $('input[class=terminal-input]').val(); var command = $('input[class=terminal-input]').val();
if (command.length > 0) { if (command.length > 0) {
post("[" + Player.getCurrentServer().hostname + " ~]> " + command); post(
"[" +
(FconfSettings.ENABLE_TIMESTAMPS ? Terminal.getTimestamp() + " " : "") +
Player.getCurrentServer().hostname +
" ~]> " + command
);
Terminal.resetTerminalInput(); //Clear input first Terminal.resetTerminalInput(); //Clear input first
Terminal.executeCommand(command); Terminal.executeCommand(command);
@ -258,9 +268,9 @@ $(document).keydown(function(event) {
}); });
//Keep terminal in focus //Keep terminal in focus
let terminalCtrlPressed = false; let terminalCtrlPressed = false, shiftKeyPressed = false;
$(document).ready(function() { $(document).ready(function() {
if (Engine.currentPage == Engine.Page.Terminal) { if (Engine.currentPage === Engine.Page.Terminal) {
$('.terminal-input').focus(); $('.terminal-input').focus();
} }
}); });
@ -268,15 +278,16 @@ $(document).keydown(function(e) {
if (Engine.currentPage == Engine.Page.Terminal) { if (Engine.currentPage == Engine.Page.Terminal) {
if (e.which == 17) { if (e.which == 17) {
terminalCtrlPressed = true; terminalCtrlPressed = true;
} else if (terminalCtrlPressed == true) { } else if (e.shiftKey) {
shiftKeyPressed = true;
} else if (terminalCtrlPressed || shiftKeyPressed) {
//Don't focus //Don't focus
} else { } else {
var inputTextBox = document.getElementById("terminal-input-text-box"); var inputTextBox = document.getElementById("terminal-input-text-box");
if (inputTextBox != null) { if (inputTextBox != null) {inputTextBox.focus();}
inputTextBox.focus();
}
terminalCtrlPressed = false; terminalCtrlPressed = false;
shiftKeyPressed = false;
} }
} }
}) })
@ -285,6 +296,9 @@ $(document).keyup(function(e) {
if (e.which == 17) { if (e.which == 17) {
terminalCtrlPressed = false; terminalCtrlPressed = false;
} }
if (e.shiftKey) {
shiftKeyPressed = false;
}
} }
}) })
@ -623,6 +637,11 @@ let Terminal = {
} }
}, },
getTimestamp: function() {
let d = new Date();
return (d.getMonth() + "/" + d.getDay() + " " + d.getHours() + ":" + d.getMinutes());
},
finishAction: function(cancelled = false) { finishAction: function(cancelled = false) {
if (Terminal.hackFlag) { if (Terminal.hackFlag) {
Terminal.finishHack(cancelled); Terminal.finishHack(cancelled);
@ -980,7 +999,7 @@ let Terminal = {
} }
//Can only tail script files //Can only tail script files
if (scriptName.endsWith(".script") == false) { if (isScriptFilename(scriptName) == false) {
post("Error: tail can only be called on .script files (filename must end with .script)"); return; post("Error: tail can only be called on .script files (filename must end with .script)"); return;
} }
@ -1055,7 +1074,7 @@ let Terminal = {
FileSaver.saveAs(content, filename); FileSaver.saveAs(content, filename);
}); });
return; return;
} else if (fn.endsWith(".script")) { } else if (isScriptFilename(fn)) {
//Download a single script //Download a single script
for (var i = 0; i < s.scripts.length; ++i) { for (var i = 0; i < s.scripts.length; ++i) {
if (s.scripts[i].filename === fn) { if (s.scripts[i].filename === fn) {
@ -1210,7 +1229,7 @@ let Terminal = {
var text = createFconf(); var text = createFconf();
Engine.loadScriptEditorContent(filename, text); Engine.loadScriptEditorContent(filename, text);
return; return;
} else if (filename.endsWith(".script")) { } else if (isScriptFilename(filename)) {
for (var i = 0; i < s.scripts.length; i++) { for (var i = 0; i < s.scripts.length; i++) {
if (filename == s.scripts[i].filename) { if (filename == s.scripts[i].filename) {
Engine.loadScriptEditorContent(filename, s.scripts[i].code); Engine.loadScriptEditorContent(filename, s.scripts[i].code);
@ -1257,7 +1276,7 @@ let Terminal = {
return; return;
} }
} }
} else if (delTarget.endsWith(".script")) { } else if (isScriptFilename(delTarget)) {
for (var i = 0; i < s.scripts.length; ++i) { for (var i = 0; i < s.scripts.length; ++i) {
if (s.scripts[i].filename == delTarget) { if (s.scripts[i].filename == delTarget) {
//Check that the script isnt currently running //Check that the script isnt currently running
@ -1303,12 +1322,11 @@ let Terminal = {
} }
//Check if its a script or just a program/executable //Check if its a script or just a program/executable
if (executableName.indexOf(".script") == -1) { //if (isScriptFilename(executableName)) {
//Not a script if (executableName.includes(".script") || executableName.includes(".js") || executableName.includes(".ns")) {
Terminal.runProgram(executableName);
} else {
//Script
Terminal.runScript(executableName); Terminal.runScript(executableName);
} else {
Terminal.runProgram(executableName);
} }
} }
break; break;
@ -1361,7 +1379,7 @@ let Terminal = {
return; return;
} }
var scriptname = args[0]; var scriptname = args[0];
if (!scriptname.endsWith(".lit") && !scriptname.endsWith(".script") && if (!scriptname.endsWith(".lit") && !isScriptFilename(scriptName) &&
!scriptname.endsWith(".txt")){ !scriptname.endsWith(".txt")){
post("Error: scp only works for .script, .txt, and .lit files"); post("Error: scp only works for .script, .txt, and .lit files");
return; return;
@ -1480,7 +1498,7 @@ let Terminal = {
} }
//Can only tail script files //Can only tail script files
if (scriptName.endsWith(".script") == false) { if (isScriptFilename(scriptName) == false) {
post("Error: tail can only be called on .script files (filename must end with .script)"); return; post("Error: tail can only be called on .script files (filename must end with .script)"); return;
} }

@ -9,8 +9,7 @@ import {formatNumber,
import {loxBoxCreate, logBoxUpdateText, import {loxBoxCreate, logBoxUpdateText,
logBoxOpened} from "../utils/LogBox.js"; logBoxOpened} from "../utils/LogBox.js";
import {setActiveScriptsClickHandlers, import {updateActiveScriptsItems} from "./ActiveScriptsUI.js";
updateActiveScriptsItems} from "./ActiveScriptsUI.js";
import {Augmentations, installAugmentations, import {Augmentations, installAugmentations,
initAugmentations, AugmentationNames, initAugmentations, AugmentationNames,
displayAugmentationsContent} from "./Augmentations.js"; displayAugmentationsContent} from "./Augmentations.js";
@ -58,7 +57,7 @@ import {StockMarket, StockSymbols,
initSymbolToStockMap, stockMarketCycle, initSymbolToStockMap, stockMarketCycle,
updateStockPrices, updateStockPrices,
displayStockMarketContent} from "./StockMarket.js"; displayStockMarketContent} from "./StockMarket.js";
import {Terminal, postNetburnerText, post} from "./Terminal.js"; import {Terminal, postNetburnerText, post, KEY} from "./Terminal.js";
/* Shortcuts to navigate through the game /* Shortcuts to navigate through the game
* Alt-t - Terminal * Alt-t - Terminal
@ -76,51 +75,52 @@ import {Terminal, postNetburnerText, post} from "./Terminal.js";
* Alt-o - Options * Alt-o - Options
*/ */
$(document).keydown(function(e) { $(document).keydown(function(e) {
if (Settings.DisableHotkeys === true) {return;}
if (!Player.isWorking && !redPillFlag && !inMission && !cinematicTextFlag) { if (!Player.isWorking && !redPillFlag && !inMission && !cinematicTextFlag) {
if (e.keyCode == 84 && e.altKey) { if (e.keyCode == 84 && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadTerminalContent(); Engine.loadTerminalContent();
} else if (e.keyCode == 67 && e.altKey) { } else if (e.keyCode === KEY.C && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadCharacterContent(); Engine.loadCharacterContent();
} else if (e.keyCode == 69 && e.altKey) { } else if (e.keyCode === KEY.E && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadScriptEditorContent(); Engine.loadScriptEditorContent();
} else if (e.keyCode == 83 && e.altKey) { } else if (e.keyCode === KEY.S && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadActiveScriptsContent(); Engine.loadActiveScriptsContent();
} else if (e.keyCode == 72 && e.altKey) { } else if (e.keyCode === KEY.H && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadHacknetNodesContent(); Engine.loadHacknetNodesContent();
} else if (e.keyCode == 87 && e.altKey) { } else if (e.keyCode === KEY.W && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadWorldContent(); Engine.loadWorldContent();
} else if (e.keyCode == 74 && e.altKey) { } else if (e.keyCode === KEY.J && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadJobContent(); Engine.loadJobContent();
} else if (e.keyCode == 82 && e.altKey) { } else if (e.keyCode === KEY.R && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadTravelContent(); Engine.loadTravelContent();
} else if (e.keyCode == 80 && e.altKey) { } else if (e.keyCode === KEY.P && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadCreateProgramContent(); Engine.loadCreateProgramContent();
} else if (e.keyCode == 70 && e.altKey) { } else if (e.keyCode === KEY.F && e.altKey) {
//Overriden by Fconf //Overriden by Fconf
if (Engine.currentPage === Engine.Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) { if (Engine.currentPage === Engine.Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) {
return; return;
} }
e.preventDefault(); e.preventDefault();
Engine.loadFactionsContent(); Engine.loadFactionsContent();
} else if (e.keyCode == 65 && e.altKey) { } else if (e.keyCode === KEY.A && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadAugmentationsContent(); Engine.loadAugmentationsContent();
} else if (e.keyCode == 85 && e.altKey) { } else if (e.keyCode === KEY.U && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadTutorialContent(); Engine.loadTutorialContent();
} }
} }
if (e.keyCode == 79 && e.altKey) { if (e.keyCode === KEY.O && e.altKey) {
e.preventDefault(); e.preventDefault();
gameOptionsBoxOpen(); gameOptionsBoxOpen();
} }
@ -260,7 +260,6 @@ let Engine = {
loadActiveScriptsContent: function() { loadActiveScriptsContent: function() {
Engine.hideAllContent(); Engine.hideAllContent();
Engine.Display.activeScriptsContent.style.display = "block"; Engine.Display.activeScriptsContent.style.display = "block";
setActiveScriptsClickHandlers();
updateActiveScriptsItems(); updateActiveScriptsItems();
Engine.currentPage = Engine.Page.ActiveScripts; Engine.currentPage = Engine.Page.ActiveScripts;
document.getElementById("active-scripts-menu-link").classList.add("active"); document.getElementById("active-scripts-menu-link").classList.add("active");
@ -963,7 +962,7 @@ let Engine = {
} else if (Engine.currentPage === Engine.Page.Corporation) { } else if (Engine.currentPage === Engine.Page.Corporation) {
Player.corporation.updateUIContent(); Player.corporation.updateUIContent();
} }
Engine.Counters.updateDisplaysMed = 9; Engine.Counters.updateDisplaysMed = 6;
} }
if (Engine.Counters.updateDisplaysLong <= 0) { if (Engine.Counters.updateDisplaysLong <= 0) {

49
tests/NetscriptJSTest.js Normal file

@ -0,0 +1,49 @@
import {executeJSScript} from "../src/NetscriptJSEvaluator.js";
const chai = require("chai");
const chaiAsPromised = require("chai-as-promised");
chai.should();
chai.use(chaiAsPromised);
console.info('asdf');
describe('NSJS ScriptStore', function() {
it('should run an imported function', async function() {
const s = { filename: "", code: "export function main() { return 2; }" };
chai.expect(await executeJSScript(s)).to.equal(2);
});
it('should handle recursive imports', async function() {
const s1 = { filename: "s1.js", code: "export function iAmRecursiveImport(x) { return x + 2; }" };
const s2 = { filename: "", code: `
import {iAmRecursiveImport} from \"s1.js\";
export function main() { return iAmRecursiveImport(3);
}`};
chai.expect(await executeJSScript(s2, [s1, s2])).to.equal(5);
});
it (`should correctly reference the passed global env`, async function() {
var [x, y] = [0, 0];
var env = {
updateX: function(value) { x = value; },
updateY: function(value) { y = value; },
};
const s1 = {filename: "s1.js", code: "export function importedFn(x) { updateX(x); }"};
const s2 = {filename: "s2.js", code: `
import {importedFn} from "s1.js";
export function main() { updateY(7); importedFn(3); }
`}
await executeJSScript(s2, [s1, s2], env);
chai.expect(y).to.equal(7);
chai.expect(x).to.equal(3);
});
it (`should throw on circular dep`, async function() {
const s1 = {filename: "s1.js", code: "import \"s2.js\""};
const s2 = {filename: "s2.js", code: `
import * as s1 from "s1.js";
export function main() {}
`}
executeJSScript(s2, [s1, s2]).should.eventually.throw();
});
});

20
tests/index.html Normal file

@ -0,0 +1,20 @@
<html>
<!-- From https://medium.com/dailyjs/running-mocha-tests-as-native-es6-modules-in-a-browser-882373f2ecb0 -->
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link href="https://unpkg.com/mocha@4.0.1/mocha.css" rel="stylesheet" />
</head>
<body>
<div id="mocha"></div>
<script src="https://unpkg.com/mocha@4.0.1/mocha.js"></script>
<script>mocha.setup('bdd')</script>
<script type="module" src="../dist/tests.bundle.js"></script>
<script type="module">
mocha.checkLeaks();
mocha.run();
</script>
</body>
</html>

3
tests/index.js Normal file

@ -0,0 +1,3 @@
//require("babel-core/register");
//require("babel-polyfill");
module.exports = require("./NetscriptJSTest.js");

@ -61,6 +61,7 @@ function infiltrationBoxCreate(inst) {
var selector = document.getElementById("infiltration-faction-select"); var selector = document.getElementById("infiltration-faction-select");
selector.innerHTML = ""; selector.innerHTML = "";
for (var i = 0; i < Player.factions.length; ++i) { for (var i = 0; i < Player.factions.length; ++i) {
if (Player.factions[i] === "Bladeburners") {continue;}
selector.innerHTML += "<option value='" + Player.factions[i] + selector.innerHTML += "<option value='" + Player.factions[i] +
"'>" + Player.factions[i] + "</option>"; "'>" + Player.factions[i] + "</option>";
} }

@ -15,11 +15,14 @@ module.exports = {
}), }),
], ],
target: "web", target: "web",
entry: "./src/engine.js", entry: {
engine: "./src/engine.js",
tests: "./tests/index.js",
},
devtool: "nosources-source-map", devtool: "nosources-source-map",
output: { output: {
path: path.resolve(__dirname, "dist"), path: path.resolve(__dirname, "dist"),
filename: "bundle.js", filename: "[name].bundle.js",
devtoolModuleFilenameTemplate: "[id]" devtoolModuleFilenameTemplate: "[id]"
}, },
module: { module: {
@ -44,5 +47,8 @@ module.exports = {
namedChunks: false, namedChunks: false,
minimize: false, minimize: false,
portableRecords: true portableRecords: true
},
devServer: {
publicPath: "/dist",
} }
}; };