This commit is contained in:
danielyxie 2018-03-12 14:39:04 -05:00
parent 629e2eb425
commit f33d81b1a5
38 changed files with 26916 additions and 7217 deletions

@ -481,10 +481,6 @@ div.faction-clear {
width: 95%; width: 95%;
} }
.installed-augmentation {
/* TODO */
}
/* Tutorial */ /* Tutorial */
#tutorial-container { #tutorial-container {
position: fixed; position: fixed;

@ -253,6 +253,27 @@ a:link, a:visited {
visibility: visible; visibility: visible;
} }
/* help tip. Question mark that opens popup with info/details */
.help-tip {
content:'?';
padding:1px;
margin-left:3px;
color:#fff;
border:1px solid white;
border-radius:5px;
display:inline-block;
}
.help-tip:hover {
background-color: #888;
}
.help-tip:active {
-webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6);
-moz-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6);
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6);
}
/* Flashing button (Red) */ /* Flashing button (Red) */
@-webkit-keyframes glowing { @-webkit-keyframes glowing {
0% { background-color: #B20000; -webkit-box-shadow: 0 0 3px #B20000; } 0% { background-color: #B20000; -webkit-box-shadow: 0 0 3px #B20000; }

31944
dist/bundle.js vendored

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
doc/build/doctrees/shortcuts.doctree vendored Normal file

Binary file not shown.

@ -20,7 +20,7 @@ secrets that you've been searching for.
:caption: Contents: :caption: Contents:
Netscript <netscript> Netscript <netscript>
Keyboard Shortcuts <shortcuts>
Indices and tables Indices and tables

@ -142,6 +142,68 @@ Comments are not evaluated as code, and can be used to document and/or explain c
* comment */ * comment */
print("This code will actually get executed"); print("This code will actually get executed");
Importing Functions
-------------------
In Netscript you can import functions that are declared in other scripts.
The script will incur the RAM usage of all imported functions.
There are two ways of doing this::
import * as namespace from "script filename"; //Import all functions from script
import {fn1, fn2, ...} from "script filename"; //Import specific functions from script
Suppose you have a library script called *testlibrary.script*::
function foo1(args) {
//function definition...
}
function foo2(args) {
//function definition...
}
function foo3(args) {
//function definition...
}
function foo4(args) {
//function definition...
}
Then, if you wanted to use these functions in another script, you can import them like so::
import * as testlib from "testlibrary.script";
values = [1,2,3];
//The imported functions must be specified using the namespace
someVal1 = testlib.foo3(values);
someVal2 = testlib.foo1(values);
if (someVal1 > someVal2) {
//...
} else {
//...
}
If you only wanted to import certain functions, you can do so without needing
to specify a namespace for the import::
import {foo1, foo3} from "testlibrary.script"; //Saves RAM since not all functions are imported!
values = [1,2,3];
//No namespace needed
someVal1 = foo3(values);
someVal2 = foo1(values);
if (someVal1 > someVal2) {
//...
} else {
//...
}
Note that exporting functions is not required.
Javascript Math Module Javascript Math Module
---------------------- ----------------------

@ -0,0 +1,99 @@
Keyboard Shortcuts
==================
This page documents the various keyboard shortcuts that can be used in the game.
Game Navigation
---------------
These are used to switch between the different menus/tabs in the game.
These shortcuts are almost always available. Exceptions include:
* Working at a company or for a faction
* Creating a program
* Taking a university class
* Training at a gym
* Active Mission (aka Hacking Mission)
========== ===========================================================================
Shortcut Action
========== ===========================================================================
Alt + t Switch to Terminal
Alt + c Switch to 'Stats' page
Alt + e Switch to Script Editor. Will open up the last-edited file or a new file
Alt + s Switch to 'Active Scripts' page
Alt + h Switch to 'Hacknet Nodes' page
Alt + w Switch to 'City' page
Alt + j Go to the company where you are employed ('Job' page on navigation menu)
Alt + r Go to Travel Agency in current City ('Travel' page on navigation menu)
Alt + p Switch to 'Create Program' page
Alt + f Switch to 'Factions' page
Alt + a Switch to 'Augmentations' page
Alt + u Switch to 'Tutorial' page
Alt + o Switch to 'Options' page
========== ===========================================================================
Script Editor
-------------
These shortcuts are available only in the Script Editor
============= ===========================================================================
Shortcut Action
============= ===========================================================================
Ctrl + b Save script and return to Terminal
Ctrl + space Function autocompletion
============= ===========================================================================
In the Script Editor you can configure your key binding mode to three preset options:
* `Ace <https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts>`_
* Vim
* Emacs
Terminal Shortcuts
------------------
These shortcuts are available only in the Terminal
============= ===========================================================================
Shortcut Action
============= ===========================================================================
Up/Down arrow Cycle through previous commands
Ctrl + c Cancel a hack/analyze action
Ctrl + l Clear screen
Tab Autocomplete command
============= ===========================================================================
Terminal Bash Shortcuts
-----------------------
These shortcuts were implemented to better emulate a bash shell. They must be enabled
in your Terminal's *.fconf* file. This can be done be entering the Terminal command::
nano .fconf
and then setting the *ENABLE_BASH_HOTKEYS* option to 1.
**Note that these Bash shortcuts override any other shortcuts defined in the game (unless otherwise noted),
as well as your browser's shortcuts**
**Also note that more Bash-like shortcuts will be implemented in the future**
============= ===========================================================================
Shortcut Action
============= ===========================================================================
Ctrl + c Clears current Terminal input (does NOT override default Ctrl + c command)
Ctrl + p Same as Up Arrow
Ctrl + n Same as Down Arrow
Ctrl + a Move cursor to beginning of line (same as 'Home' key)
Ctrl + e Move cursor to end of line (same as 'End' key)
Ctrl + b Move cursor to previous character
Alt + b Move cursor to previous word
Ctrl + f Move cursor to next character
Alt + f Move cursor to next word
Ctrl + h/d Delete previous character ('Backspace')
============= ===========================================================================
Misc Shortcuts
--------------
============= ===========================================================================
Shortcut Action
============= ===========================================================================
Esc Close a script's log window
============= ===========================================================================

@ -443,6 +443,7 @@
<p class="caption"><span class="caption-text">Contents:</span></p> <p class="caption"><span class="caption-text">Contents:</span></p>
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="netscript.html"> Netscript</a></li> <li class="toctree-l1"><a class="reference internal" href="netscript.html"> Netscript</a></li>
<li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li>
</ul> </ul>
<div role="search"> <div role="search">

@ -201,6 +201,7 @@ secrets that you've been searching for.</p>
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a><ul> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a><ul>
<li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#netscript-ports">Netscript Ports</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#netscript-ports">Netscript Ports</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#comments">Comments</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#comments">Comments</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#importing-functions">Importing Functions</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#javascript-math-module">Javascript Math Module</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#javascript-math-module">Javascript Math Module</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#javascript-date-module">Javascript Date Module</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#javascript-date-module">Javascript Date Module</a></li>
<li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#javascript-number-module">Javascript Number Module</a></li> <li class="toctree-l3"><a class="reference internal" href="netscriptmisc.html#javascript-number-module">Javascript Number Module</a></li>
@ -208,6 +209,14 @@ secrets that you've been searching for.</p>
</li> </li>
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a><ul>
<li class="toctree-l2"><a class="reference internal" href="shortcuts.html#game-navigation">Game Navigation</a></li>
<li class="toctree-l2"><a class="reference internal" href="shortcuts.html#script-editor">Script Editor</a></li>
<li class="toctree-l2"><a class="reference internal" href="shortcuts.html#terminal-shortcuts">Terminal Shortcuts</a></li>
<li class="toctree-l2"><a class="reference internal" href="shortcuts.html#terminal-bash-shortcuts">Terminal Bash Shortcuts</a></li>
<li class="toctree-l2"><a class="reference internal" href="shortcuts.html#misc-shortcuts">Misc Shortcuts</a></li>
</ul>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@ -231,6 +240,7 @@ secrets that you've been searching for.</p>
<p class="caption"><span class="caption-text">Contents:</span></p> <p class="caption"><span class="caption-text">Contents:</span></p>
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="netscript.html"> Netscript</a></li> <li class="toctree-l1"><a class="reference internal" href="netscript.html"> Netscript</a></li>
<li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li>
</ul> </ul>
<div role="search"> <div role="search">

@ -202,6 +202,7 @@ to reach out to the developer!</p>
<li class="toctree-l1"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a><ul> <li class="toctree-l1"><a class="reference internal" href="netscriptmisc.html"> Miscellaneous</a><ul>
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#netscript-ports">Netscript Ports</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#netscript-ports">Netscript Ports</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#comments">Comments</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#comments">Comments</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#importing-functions">Importing Functions</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#javascript-math-module">Javascript Math Module</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#javascript-math-module">Javascript Math Module</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#javascript-date-module">Javascript Date Module</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#javascript-date-module">Javascript Date Module</a></li>
<li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#javascript-number-module">Javascript Number Module</a></li> <li class="toctree-l2"><a class="reference internal" href="netscriptmisc.html#javascript-number-module">Javascript Number Module</a></li>
@ -233,6 +234,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="shortcuts.html"> Keyboard Shortcuts</a></li>
</ul> </ul>
<div role="search"> <div role="search">

@ -24,6 +24,7 @@
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<link rel="index" title="Index" href="genindex.html" /> <link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" /> <link rel="search" title="Search" href="search.html" />
<link rel="next" title="Keyboard Shortcuts" href="shortcuts.html" />
<link rel="prev" title="Netscript Singularity Functions" href="netscriptsingularityfunctions.html" /> <link rel="prev" title="Netscript Singularity Functions" href="netscriptsingularityfunctions.html" />
</head> </head>
<body> <body>
@ -34,6 +35,8 @@
<div class="rel" role="navigation" aria-label="related navigation"> <div class="rel" role="navigation" aria-label="related navigation">
<a href="netscriptsingularityfunctions.html" title="Netscript Singularity Functions" <a href="netscriptsingularityfunctions.html" title="Netscript Singularity Functions"
accesskey="P">previous</a> | accesskey="P">previous</a> |
<a href="shortcuts.html" title="Keyboard Shortcuts"
accesskey="N">next</a> |
<a href="genindex.html" title="General Index" <a href="genindex.html" title="General Index"
accesskey="I">index</a> accesskey="I">index</a>
</div> </div>
@ -218,6 +221,66 @@ Comments are not evaluated as code, and can be used to document and/or explain c
</pre></div> </pre></div>
</div> </div>
</div> </div>
<div class="section" id="importing-functions">
<h2>Importing Functions<a class="headerlink" href="#importing-functions" title="Permalink to this headline"></a></h2>
<p>In Netscript you can import functions that are declared in other scripts.
The script will incur the RAM usage of all imported functions.
There are two ways of doing this:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="o">*</span> <span class="k">as</span> <span class="n">namespace</span> <span class="kn">from</span> <span class="s2">&quot;script filename&quot;</span><span class="p">;</span> <span class="o">//</span><span class="n">Import</span> <span class="nb">all</span> <span class="n">functions</span> <span class="kn">from</span> <span class="nn">script</span>
<span class="k">import</span> <span class="p">{</span><span class="n">fn1</span><span class="p">,</span> <span class="n">fn2</span><span class="p">,</span> <span class="o">...</span><span class="p">}</span> <span class="kn">from</span> <span class="s2">&quot;script filename&quot;</span><span class="p">;</span> <span class="o">//</span><span class="n">Import</span> <span class="n">specific</span> <span class="n">functions</span> <span class="kn">from</span> <span class="nn">script</span>
</pre></div>
</div>
<p>Suppose you have a library script called <em>testlibrary.script</em>:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">function</span> <span class="n">foo1</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="p">{</span>
<span class="o">//</span><span class="n">function</span> <span class="n">definition</span><span class="o">...</span>
<span class="p">}</span>
<span class="n">function</span> <span class="n">foo2</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="p">{</span>
<span class="o">//</span><span class="n">function</span> <span class="n">definition</span><span class="o">...</span>
<span class="p">}</span>
<span class="n">function</span> <span class="n">foo3</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="p">{</span>
<span class="o">//</span><span class="n">function</span> <span class="n">definition</span><span class="o">...</span>
<span class="p">}</span>
<span class="n">function</span> <span class="n">foo4</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="p">{</span>
<span class="o">//</span><span class="n">function</span> <span class="n">definition</span><span class="o">...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Then, if you wanted to use these functions in another script, you can import them like so:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="o">*</span> <span class="k">as</span> <span class="n">testlib</span> <span class="kn">from</span> <span class="s2">&quot;testlibrary.script&quot;</span><span class="p">;</span>
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">];</span>
<span class="o">//</span><span class="n">The</span> <span class="n">imported</span> <span class="n">functions</span> <span class="n">must</span> <span class="n">be</span> <span class="n">specified</span> <span class="n">using</span> <span class="n">the</span> <span class="n">namespace</span>
<span class="n">someVal1</span> <span class="o">=</span> <span class="n">testlib</span><span class="o">.</span><span class="n">foo3</span><span class="p">(</span><span class="n">values</span><span class="p">);</span>
<span class="n">someVal2</span> <span class="o">=</span> <span class="n">testlib</span><span class="o">.</span><span class="n">foo1</span><span class="p">(</span><span class="n">values</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">someVal1</span> <span class="o">&gt;</span> <span class="n">someVal2</span><span class="p">)</span> <span class="p">{</span>
<span class="o">//...</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="o">//...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>If you only wanted to import certain functions, you can do so without needing
to specify a namespace for the import:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span>import {foo1, foo3} from &quot;testlibrary.script&quot;; //Saves RAM since not all functions are imported!
values = [1,2,3];
//No namespace needed
someVal1 = foo3(values);
someVal2 = foo1(values);
if (someVal1 &gt; someVal2) {
//...
} else {
//...
}
</pre></div>
</div>
<p>Note that exporting functions is not required.</p>
</div>
<div class="section" id="javascript-math-module"> <div class="section" id="javascript-math-module">
<h2>Javascript Math Module<a class="headerlink" href="#javascript-math-module" title="Permalink to this headline"></a></h2> <h2>Javascript Math Module<a class="headerlink" href="#javascript-math-module" title="Permalink to this headline"></a></h2>
<p>The <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math">Javascript Math Module</a> is <p>The <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math">Javascript Math Module</a> is
@ -274,6 +337,7 @@ However, since the 'new' operator does not work in Netscript, only the Date modu
<li class="toctree-l2 current"><a class="current reference internal" href="#"> Miscellaneous</a><ul> <li class="toctree-l2 current"><a class="current reference internal" href="#"> Miscellaneous</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#netscript-ports">Netscript Ports</a></li> <li class="toctree-l3"><a class="reference internal" href="#netscript-ports">Netscript Ports</a></li>
<li class="toctree-l3"><a class="reference internal" href="#comments">Comments</a></li> <li class="toctree-l3"><a class="reference internal" href="#comments">Comments</a></li>
<li class="toctree-l3"><a class="reference internal" href="#importing-functions">Importing Functions</a></li>
<li class="toctree-l3"><a class="reference internal" href="#javascript-math-module">Javascript Math Module</a></li> <li class="toctree-l3"><a class="reference internal" href="#javascript-math-module">Javascript Math Module</a></li>
<li class="toctree-l3"><a class="reference internal" href="#javascript-date-module">Javascript Date Module</a></li> <li class="toctree-l3"><a class="reference internal" href="#javascript-date-module">Javascript Date Module</a></li>
<li class="toctree-l3"><a class="reference internal" href="#javascript-number-module">Javascript Number Module</a></li> <li class="toctree-l3"><a class="reference internal" href="#javascript-number-module">Javascript Number Module</a></li>
@ -281,6 +345,7 @@ However, since the 'new' operator does not work in Netscript, only the Date modu
</li> </li>
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li>
</ul> </ul>
<div role="search"> <div role="search">
@ -303,6 +368,8 @@ However, since the 'new' operator does not work in Netscript, only the Date modu
<div role="navigation" aria-label="related navigaton"> <div role="navigation" aria-label="related navigaton">
<a href="netscriptsingularityfunctions.html" title="Netscript Singularity Functions" <a href="netscriptsingularityfunctions.html" title="Netscript Singularity Functions"
>previous</a> | >previous</a> |
<a href="shortcuts.html" title="Keyboard Shortcuts"
>next</a> |
<a href="genindex.html" title="General Index" <a href="genindex.html" title="General Index"
>index</a> >index</a>
</div> </div>

Binary file not shown.

@ -86,6 +86,7 @@
<p class="caption"><span class="caption-text">Contents:</span></p> <p class="caption"><span class="caption-text">Contents:</span></p>
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="netscript.html"> Netscript</a></li> <li class="toctree-l1"><a class="reference internal" href="netscript.html"> Netscript</a></li>
<li class="toctree-l1"><a class="reference internal" href="shortcuts.html"> Keyboard Shortcuts</a></li>
</ul> </ul>
<div role="search"> <div role="search">

File diff suppressed because one or more lines are too long

314
doc/build/html/shortcuts.html vendored Normal file

@ -0,0 +1,314 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="English">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Keyboard Shortcuts &#8212; Bitburner 1.0 documentation</title>
<link rel="stylesheet" href="_static/agogo.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="prev" title="Netscript Miscellaneous" href="netscriptmisc.html" />
</head>
<body>
<div class="header-wrapper" role="banner">
<div class="header">
<div class="headertitle"><a
href="index.html">Bitburner 1.0 documentation</a></div>
<div class="rel" role="navigation" aria-label="related navigation">
<a href="netscriptmisc.html" title="Netscript Miscellaneous"
accesskey="P">previous</a> |
<a href="genindex.html" title="General Index"
accesskey="I">index</a>
</div>
</div>
</div>
<div class="content-wrapper">
<div class="content">
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="keyboard-shortcuts">
<h1>Keyboard Shortcuts<a class="headerlink" href="#keyboard-shortcuts" title="Permalink to this headline"></a></h1>
<p>This page documents the various keyboard shortcuts that can be used in the game.</p>
<div class="section" id="game-navigation">
<h2>Game Navigation<a class="headerlink" href="#game-navigation" title="Permalink to this headline"></a></h2>
<p>These are used to switch between the different menus/tabs in the game.
These shortcuts are almost always available. Exceptions include:</p>
<ul class="simple">
<li>Working at a company or for a faction</li>
<li>Creating a program</li>
<li>Taking a university class</li>
<li>Training at a gym</li>
<li>Active Mission (aka Hacking Mission)</li>
</ul>
<table border="1" class="docutils">
<colgroup>
<col width="12%" />
<col width="88%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Shortcut</th>
<th class="head">Action</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>Alt + t</td>
<td>Switch to Terminal</td>
</tr>
<tr class="row-odd"><td>Alt + c</td>
<td>Switch to 'Stats' page</td>
</tr>
<tr class="row-even"><td>Alt + e</td>
<td>Switch to Script Editor. Will open up the last-edited file or a new file</td>
</tr>
<tr class="row-odd"><td>Alt + s</td>
<td>Switch to 'Active Scripts' page</td>
</tr>
<tr class="row-even"><td>Alt + h</td>
<td>Switch to 'Hacknet Nodes' page</td>
</tr>
<tr class="row-odd"><td>Alt + w</td>
<td>Switch to 'City' page</td>
</tr>
<tr class="row-even"><td>Alt + j</td>
<td>Go to the company where you are employed ('Job' page on navigation menu)</td>
</tr>
<tr class="row-odd"><td>Alt + r</td>
<td>Go to Travel Agency in current City ('Travel' page on navigation menu)</td>
</tr>
<tr class="row-even"><td>Alt + p</td>
<td>Switch to 'Create Program' page</td>
</tr>
<tr class="row-odd"><td>Alt + f</td>
<td>Switch to 'Factions' page</td>
</tr>
<tr class="row-even"><td>Alt + a</td>
<td>Switch to 'Augmentations' page</td>
</tr>
<tr class="row-odd"><td>Alt + u</td>
<td>Switch to 'Tutorial' page</td>
</tr>
<tr class="row-even"><td>Alt + o</td>
<td>Switch to 'Options' page</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="script-editor">
<h2>Script Editor<a class="headerlink" href="#script-editor" title="Permalink to this headline"></a></h2>
<p>These shortcuts are available only in the Script Editor</p>
<table border="1" class="docutils">
<colgroup>
<col width="15%" />
<col width="85%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Shortcut</th>
<th class="head">Action</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>Ctrl + b</td>
<td>Save script and return to Terminal</td>
</tr>
<tr class="row-odd"><td>Ctrl + space</td>
<td>Function autocompletion</td>
</tr>
</tbody>
</table>
<p>In the Script Editor you can configure your key binding mode to three preset options:</p>
<ul class="simple">
<li><a class="reference external" href="https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts">Ace</a></li>
<li>Vim</li>
<li>Emacs</li>
</ul>
</div>
<div class="section" id="terminal-shortcuts">
<h2>Terminal Shortcuts<a class="headerlink" href="#terminal-shortcuts" title="Permalink to this headline"></a></h2>
<p>These shortcuts are available only in the Terminal</p>
<table border="1" class="docutils">
<colgroup>
<col width="15%" />
<col width="85%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Shortcut</th>
<th class="head">Action</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>Up/Down arrow</td>
<td>Cycle through previous commands</td>
</tr>
<tr class="row-odd"><td>Ctrl + c</td>
<td>Cancel a hack/analyze action</td>
</tr>
<tr class="row-even"><td>Ctrl + l</td>
<td>Clear screen</td>
</tr>
<tr class="row-odd"><td>Tab</td>
<td>Autocomplete command</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="terminal-bash-shortcuts">
<h2>Terminal Bash Shortcuts<a class="headerlink" href="#terminal-bash-shortcuts" title="Permalink to this headline"></a></h2>
<p>These shortcuts were implemented to better emulate a bash shell. They must be enabled
in your Terminal's <em>.fconf</em> file. This can be done be entering the Terminal command:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">nano</span> <span class="o">.</span><span class="n">fconf</span>
</pre></div>
</div>
<p>and then setting the <em>ENABLE_BASH_HOTKEYS</em> option to 1.</p>
<p><strong>Note that these Bash shortcuts override any other shortcuts defined in the game (unless otherwise noted),
as well as your browser's shortcuts</strong></p>
<p><strong>Also note that more Bash-like shortcuts will be implemented in the future</strong></p>
<table border="1" class="docutils">
<colgroup>
<col width="15%" />
<col width="85%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Shortcut</th>
<th class="head">Action</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>Ctrl + c</td>
<td>Clears current Terminal input (does NOT override default Ctrl + c command)</td>
</tr>
<tr class="row-odd"><td>Ctrl + p</td>
<td>Same as Up Arrow</td>
</tr>
<tr class="row-even"><td>Ctrl + n</td>
<td>Same as Down Arrow</td>
</tr>
<tr class="row-odd"><td>Ctrl + a</td>
<td>Move cursor to beginning of line (same as 'Home' key)</td>
</tr>
<tr class="row-even"><td>Ctrl + e</td>
<td>Move cursor to end of line (same as 'End' key)</td>
</tr>
<tr class="row-odd"><td>Ctrl + b</td>
<td>Move cursor to previous character</td>
</tr>
<tr class="row-even"><td>Alt + b</td>
<td>Move cursor to previous word</td>
</tr>
<tr class="row-odd"><td>Ctrl + f</td>
<td>Move cursor to next character</td>
</tr>
<tr class="row-even"><td>Alt + f</td>
<td>Move cursor to next word</td>
</tr>
<tr class="row-odd"><td>Ctrl + h/d</td>
<td>Delete previous character ('Backspace')</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="misc-shortcuts">
<h2>Misc Shortcuts<a class="headerlink" href="#misc-shortcuts" title="Permalink to this headline"></a></h2>
<table border="1" class="docutils">
<colgroup>
<col width="15%" />
<col width="85%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Shortcut</th>
<th class="head">Action</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>Esc</td>
<td>Close a script's log window</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sidebar">
<h3>Table Of Contents</h3>
<p class="caption"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="netscript.html"> Netscript</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#"> Keyboard Shortcuts</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#game-navigation">Game Navigation</a></li>
<li class="toctree-l2"><a class="reference internal" href="#script-editor">Script Editor</a></li>
<li class="toctree-l2"><a class="reference internal" href="#terminal-shortcuts">Terminal Shortcuts</a></li>
<li class="toctree-l2"><a class="reference internal" href="#terminal-bash-shortcuts">Terminal Bash Shortcuts</a></li>
<li class="toctree-l2"><a class="reference internal" href="#misc-shortcuts">Misc Shortcuts</a></li>
</ul>
</li>
</ul>
<div role="search">
<h3 style="margin-top: 1.5em;">Search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="clearer"></div>
</div>
</div>
<div class="footer-wrapper">
<div class="footer">
<div class="left">
<div role="navigation" aria-label="related navigaton">
<a href="netscriptmisc.html" title="Netscript Miscellaneous"
>previous</a> |
<a href="genindex.html" title="General Index"
>index</a>
</div>
<div role="note" aria-label="source link">
<br/>
<a href="_sources/shortcuts.rst.txt"
rel="nofollow">Show Source</a>
</div>
</div>
<div class="right">
<div class="footer" role="contentinfo">
&#169; Copyright 2017, Bitburner.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.6.4.
</div>
</div>
<div class="clearer"></div>
</div>
</div>
</body>
</html>

@ -20,7 +20,7 @@ secrets that you've been searching for.
:caption: Contents: :caption: Contents:
Netscript <netscript> Netscript <netscript>
Keyboard Shortcuts <shortcuts>
Indices and tables Indices and tables

@ -142,6 +142,68 @@ Comments are not evaluated as code, and can be used to document and/or explain c
* comment */ * comment */
print("This code will actually get executed"); print("This code will actually get executed");
Importing Functions
-------------------
In Netscript you can import functions that are declared in other scripts.
The script will incur the RAM usage of all imported functions.
There are two ways of doing this::
import * as namespace from "script filename"; //Import all functions from script
import {fn1, fn2, ...} from "script filename"; //Import specific functions from script
Suppose you have a library script called *testlibrary.script*::
function foo1(args) {
//function definition...
}
function foo2(args) {
//function definition...
}
function foo3(args) {
//function definition...
}
function foo4(args) {
//function definition...
}
Then, if you wanted to use these functions in another script, you can import them like so::
import * as testlib from "testlibrary.script";
values = [1,2,3];
//The imported functions must be specified using the namespace
someVal1 = testlib.foo3(values);
someVal2 = testlib.foo1(values);
if (someVal1 > someVal2) {
//...
} else {
//...
}
If you only wanted to import certain functions, you can do so without needing
to specify a namespace for the import::
import {foo1, foo3} from "testlibrary.script"; //Saves RAM since not all functions are imported!
values = [1,2,3];
//No namespace needed
someVal1 = foo3(values);
someVal2 = foo1(values);
if (someVal1 > someVal2) {
//...
} else {
//...
}
Note that exporting functions is not required.
Javascript Math Module Javascript Math Module
---------------------- ----------------------

99
doc/source/shortcuts.rst Normal file

@ -0,0 +1,99 @@
Keyboard Shortcuts
==================
This page documents the various keyboard shortcuts that can be used in the game.
Game Navigation
---------------
These are used to switch between the different menus/tabs in the game.
These shortcuts are almost always available. Exceptions include:
* Working at a company or for a faction
* Creating a program
* Taking a university class
* Training at a gym
* Active Mission (aka Hacking Mission)
========== ===========================================================================
Shortcut Action
========== ===========================================================================
Alt + t Switch to Terminal
Alt + c Switch to 'Stats' page
Alt + e Switch to Script Editor. Will open up the last-edited file or a new file
Alt + s Switch to 'Active Scripts' page
Alt + h Switch to 'Hacknet Nodes' page
Alt + w Switch to 'City' page
Alt + j Go to the company where you are employed ('Job' page on navigation menu)
Alt + r Go to Travel Agency in current City ('Travel' page on navigation menu)
Alt + p Switch to 'Create Program' page
Alt + f Switch to 'Factions' page
Alt + a Switch to 'Augmentations' page
Alt + u Switch to 'Tutorial' page
Alt + o Switch to 'Options' page
========== ===========================================================================
Script Editor
-------------
These shortcuts are available only in the Script Editor
============= ===========================================================================
Shortcut Action
============= ===========================================================================
Ctrl + b Save script and return to Terminal
Ctrl + space Function autocompletion
============= ===========================================================================
In the Script Editor you can configure your key binding mode to three preset options:
* `Ace <https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts>`_
* Vim
* Emacs
Terminal Shortcuts
------------------
These shortcuts are available only in the Terminal
============= ===========================================================================
Shortcut Action
============= ===========================================================================
Up/Down arrow Cycle through previous commands
Ctrl + c Cancel a hack/analyze action
Ctrl + l Clear screen
Tab Autocomplete command
============= ===========================================================================
Terminal Bash Shortcuts
-----------------------
These shortcuts were implemented to better emulate a bash shell. They must be enabled
in your Terminal's *.fconf* file. This can be done be entering the Terminal command::
nano .fconf
and then setting the *ENABLE_BASH_HOTKEYS* option to 1.
**Note that these Bash shortcuts override any other shortcuts defined in the game (unless otherwise noted),
as well as your browser's shortcuts**
**Also note that more Bash-like shortcuts will be implemented in the future**
============= ===========================================================================
Shortcut Action
============= ===========================================================================
Ctrl + c Clears current Terminal input (does NOT override default Ctrl + c command)
Ctrl + p Same as Up Arrow
Ctrl + m Same as Down Arrow
Ctrl + a Move cursor to beginning of line (same as 'Home' key)
Ctrl + e Move cursor to end of line (same as 'End' key)
Ctrl + b Move cursor to previous character
Alt + b Move cursor to previous word
Ctrl + f Move cursor to next character
Alt + f Move cursor to next word
Ctrl + h/d Delete previous character ('Backspace')
============= ===========================================================================
Misc Shortcuts
--------------
============= ===========================================================================
Shortcut Action
============= ===========================================================================
Esc Close a script's log window
============= ===========================================================================

@ -578,6 +578,7 @@
<ul id="queued-augmentations-list"></ul> <ul id="queued-augmentations-list"></ul>
<br> <br>
<a id="install-augmentations-button" class="a-link-button"> Install Augmentations </a> <a id="install-augmentations-button" class="a-link-button"> Install Augmentations </a>
<a id="install-augmentations-backup-button" class="a-link-button"> Backup Save (Export) </a>
<br><br> <br><br>
<h1> Installed Augmentations </h1> <h1> Installed Augmentations </h1>
<p style="width:70%;"> List of all augmentations (including Source Files) that have been installed. You have gained the effects of these augmentations </p> <p style="width:70%;"> List of all augmentations (including Source Files) that have been installed. You have gained the effects of these augmentations </p>

@ -39,7 +39,7 @@ routines, to develop your own software, but may not duplicate the Source Code. T
right referenced in the preceding sentence is hereinafter referred to as "Educational Use." By so exercising the Educational right referenced in the preceding sentence is hereinafter referred to as "Educational Use." By so exercising the Educational
Use right you shall not obtain any ownership, copyright, proprietary or other interest in or to the Source Code, or any portion Use right you shall not obtain any ownership, copyright, proprietary or other interest in or to the Source Code, or any portion
of the Source Code. You may dispose of your own software in your sole discretion. When exercising the Educational Use right, of the Source Code. You may dispose of your own software in your sole discretion. When exercising the Educational Use right,
you may not use or exploit the Software, or an portion of the Software, which includes the Source Code, for commercial gain. you may not use or exploit the Software, or any portion of the Software, which includes the Source Code, for commercial gain.
3. Prohibited Uses: Under no circumstances shall you, the end-user, be permitted, allowed or authorized to commercially 3. Prohibited Uses: Under no circumstances shall you, the end-user, be permitted, allowed or authorized to commercially
exploit the Software or any work that in whole or in part contains or is derived from the Software or any part thereof. exploit the Software or any work that in whole or in part contains or is derived from the Software or any part thereof.

65
package-lock.json generated

@ -7211,6 +7211,11 @@
"event-emitter": "0.3.5" "event-emitter": "0.3.5"
} }
}, },
"es6-promise": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
"integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y="
},
"es6-promise-polyfill": { "es6-promise-polyfill": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/es6-promise-polyfill/-/es6-promise-polyfill-1.2.0.tgz", "resolved": "https://registry.npmjs.org/es6-promise-polyfill/-/es6-promise-polyfill-1.2.0.tgz",
@ -7765,6 +7770,11 @@
"loader-utils": "1.1.0" "loader-utils": "1.1.0"
} }
}, },
"file-saver": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.3.tgz",
"integrity": "sha1-zdTETTqiZOrC9o7BZbx5HDSvEjI="
},
"filename-regex": { "filename-regex": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
@ -8537,6 +8547,11 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
},
"imurmurhash": { "imurmurhash": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@ -9290,6 +9305,48 @@
"promise": "6.1.0" "promise": "6.1.0"
} }
}, },
"jszip": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz",
"integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==",
"requires": {
"core-js": "2.3.0",
"es6-promise": "3.0.2",
"lie": "3.1.1",
"pako": "1.0.6",
"readable-stream": "2.0.6"
},
"dependencies": {
"core-js": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
"integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"readable-stream": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "0.10.31",
"util-deprecate": "1.0.2"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -9589,6 +9646,14 @@
"type-check": "0.3.2" "type-check": "0.3.2"
} }
}, },
"lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
"requires": {
"immediate": "3.0.6"
}
},
"listr": { "listr": {
"version": "0.12.0", "version": "0.12.0",
"resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz", "resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz",

@ -42,11 +42,13 @@
"brace": "^0.11.1", "brace": "^0.11.1",
"enhanced-resolve": "^3.4.0", "enhanced-resolve": "^3.4.0",
"escope": "^3.6.0", "escope": "^3.6.0",
"file-saver": "^1.3.3",
"interpret": "^1.0.0", "interpret": "^1.0.0",
"jquery": "^3.3.1", "jquery": "^3.3.1",
"json-loader": "^0.5.4", "json-loader": "^0.5.4",
"json5": "^0.5.1", "json5": "^0.5.1",
"jsplumb": "^2.6.8", "jsplumb": "^2.6.8",
"jszip": "^3.1.5",
"loader-runner": "^2.3.0", "loader-runner": "^2.3.0",
"loader-utils": "^1.1.0", "loader-utils": "^1.1.0",
"memory-fs": "~0.4.1", "memory-fs": "~0.4.1",

@ -323,7 +323,8 @@ Product.prototype.finishProduct = function(employeeProd, industry) {
console.log("designMult: " + designMult); console.log("designMult: " + designMult);
var balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) + var balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) +
(1.5 * opsRatio) + (busRatio); (1.5 * opsRatio) + (busRatio);
var totalMult = progrMult * balanceMult * designMult; var sciMult = 1 + (Math.pow(industry.sciResearch.qty, industry.sciFac) / 1000);
var totalMult = progrMult * balanceMult * designMult * sciMult;
this.qlt = totalMult * ((0.10 * employeeProd[EmployeePositions.Engineer]) + this.qlt = totalMult * ((0.10 * employeeProd[EmployeePositions.Engineer]) +
(0.05 * employeeProd[EmployeePositions.Management]) + (0.05 * employeeProd[EmployeePositions.Management]) +
@ -357,7 +358,7 @@ Product.prototype.finishProduct = function(employeeProd, industry) {
(0.05 * employeeProd[EmployeePositions.Business])); (0.05 * employeeProd[EmployeePositions.Business]));
this.calculateRating(industry); this.calculateRating(industry);
var advMult = 1 + (Math.pow(this.advCost, 0.1) / 100); var advMult = 1 + (Math.pow(this.advCost, 0.1) / 100);
this.mku = 100 / (advMult * Math.pow((this.qlt + 0.001), 0.75) * (busRatio + mgmtRatio)); this.mku = 100 / (advMult * Math.pow((this.qlt + 0.001), 0.6) * (busRatio + mgmtRatio));
this.dmd = industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness))); this.dmd = industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness)));
this.cmp = getRandomInt(0, 70); this.cmp = getRandomInt(0, 70);
@ -483,7 +484,7 @@ var IndustryDescriptions = {
Healthcare: "Create and manage hospitals.<br><br>" + Healthcare: "Create and manage hospitals.<br><br>" +
"Starting cost: " + numeral(IndustryStartingCosts.Healthcare).format("$0.000a") + "<br>" + "Starting cost: " + numeral(IndustryStartingCosts.Healthcare).format("$0.000a") + "<br>" +
"Recommended starting Industry: NO", "Recommended starting Industry: NO",
RealEstate: "Develop and manuage real estate properties.<br><br>" + RealEstate: "Develop and manage real estate properties.<br><br>" +
"Starting cost: " + numeral(IndustryStartingCosts.RealEstate).format("$0.000a") + "<br>" + "Starting cost: " + numeral(IndustryStartingCosts.RealEstate).format("$0.000a") + "<br>" +
"Recommended starting Industry: NO", "Recommended starting Industry: NO",
} }
@ -552,11 +553,11 @@ var ProductRatingWeights = {
var IndustryUpgrades = { var IndustryUpgrades = {
"0": [0, 500e3, 1, 1.05, "0": [0, 500e3, 1, 1.05,
"Coffee", "Provide your employees with coffee, increasing their energy by 5%."], "Coffee", "Provide your employees with coffee, increasing their energy by 5%."],
"1": [1, 1e9, 1.03, 1.03, "1": [1, 1e9, 1.05, 1.03,
"AdVert.Inc", "Hire AdVert.Inc to advertise your company. Each level of " + "AdVert.Inc", "Hire AdVert.Inc to advertise your company. Each level of " +
"this upgrade grants your company a static increase of 4 and 1 to its awareness and " + "this upgrade grants your company a static increase of 4 and 1 to its awareness and " +
"popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " + "popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " +
"by a random percentage between 3% and 6%. These effects are increased by other upgrades " + "by a random percentage between 2% and 4%. These effects are increased by other upgrades " +
"that increase the power of your advertising."] "that increase the power of your advertising."]
} }
@ -786,8 +787,8 @@ Industry.prototype.init = function() {
this.makesProducts = true; this.makesProducts = true;
break; break;
case Industries.Software: case Industries.Software:
this.sciFac = 0.7; this.sciFac = 0.65;
this.advFac = 0.18; this.advFac = 0.16;
this.hwFac = 0.25; this.hwFac = 0.25;
this.reFac = 0.1; this.reFac = 0.1;
this.aiFac = 0.1; this.aiFac = 0.1;
@ -871,20 +872,26 @@ Industry.prototype.getProductDescriptionText = function() {
//Calculates the values that factor into the production and properties of //Calculates the values that factor into the production and properties of
//materials/products (such as quality, etc.) //materials/products (such as quality, etc.)
Industry.prototype.calculateProductionFactors = function(city) { Industry.prototype.calculateProductionFactors = function() {
var warehouse = this.warehouses[city]; var multSum = 0;
if (!(warehouse instanceof Warehouse)) { for (var i = 0; i < Cities.length; ++i) {
this.prodMult = 0; var city = Cities[i];
return; var warehouse = this.warehouses[city];
if (!(warehouse instanceof Warehouse)) {
continue;
}
var materials = warehouse.materials,
office = this.offices[city];
var cityMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) *
Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) *
Math.pow(0.002 * materials.Robots.qty+1, this.robFac) *
Math.pow(0.002 * materials.AICores.qty+1, this.aiFac);
multSum += Math.pow(cityMult, 0.73);
} }
var materials = warehouse.materials,
office = this.offices[city]; multSum < 1 ? this.prodMult = 1 : this.prodMult = multSum;
//Production is multiplied by this
this.prodMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) *
Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) *
Math.pow(0.002 * materials.Robots.qty+1, this.robFac) *
Math.pow(0.002 * materials.AICores.qty+1, this.aiFac);
if (this.prodMult < 1) {this.prodMult = 1;}
} }
Industry.prototype.updateWarehouseSizeUsed = function(warehouse) { Industry.prototype.updateWarehouseSizeUsed = function(warehouse) {
@ -897,6 +904,9 @@ Industry.prototype.updateWarehouseSizeUsed = function(warehouse) {
if (this.products.hasOwnProperty(prodName)) { if (this.products.hasOwnProperty(prodName)) {
var prod = this.products[prodName]; var prod = this.products[prodName];
warehouse.sizeUsed += (prod.data[warehouse.loc][0] * prod.siz); warehouse.sizeUsed += (prod.data[warehouse.loc][0] * prod.siz);
if (prod.data[warehouse.loc][0] > 0 && warehouse.loc === currentCityUi) {
industryWarehouseStorageBreakdownText += (prodName + ": " + formatNumber(prod.data[warehouse.loc][0] * prod.siz, 0) + "<br>");
}
} }
} }
} }
@ -1017,12 +1027,12 @@ Industry.prototype.processProductMarket = function(marketCycles=1) {
//Process production, purchase, and import/export of materials //Process production, purchase, and import/export of materials
Industry.prototype.processMaterials = function(marketCycles=1, company) { Industry.prototype.processMaterials = function(marketCycles=1, company) {
var revenue = 0, expenses = 0; var revenue = 0, expenses = 0, industry = this;
this.calculateProductionFactors();
for (var i = 0; i < Cities.length; ++i) { for (var i = 0; i < Cities.length; ++i) {
var city = Cities[i], office = this.offices[city]; var city = Cities[i], office = this.offices[city];
if (this.warehouses[city] instanceof Warehouse) { if (this.warehouses[city] instanceof Warehouse) {
this.calculateProductionFactors(city);
var warehouse = this.warehouses[city]; var warehouse = this.warehouses[city];
switch(this.state) { switch(this.state) {
@ -1031,9 +1041,17 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
/* Process purchase of materials */ /* Process purchase of materials */
for (var matName in warehouse.materials) { for (var matName in warehouse.materials) {
if (warehouse.materials.hasOwnProperty(matName)) { if (warehouse.materials.hasOwnProperty(matName)) {
(function(matName) { (function(matName, ind) {
var mat = warehouse.materials[matName]; var mat = warehouse.materials[matName];
var buyAmt = (mat.buy * SecsPerMarketCycle * marketCycles), maxAmt var buyAmt, maxAmt;
if (warehouse.smartSupplyEnabled && Object.keys(ind.reqMats).includes(matName)) {
//Smart supply tracker is stored as per second rate
mat.buy = ind.reqMats[matName] * warehouse.smartSupplyStore;
buyAmt = mat.buy * SecsPerMarketCycle * marketCycles;
} else {
buyAmt = (mat.buy * SecsPerMarketCycle * marketCycles);
}
if (matName == "RealEstate") { if (matName == "RealEstate") {
maxAmt = buyAmt; maxAmt = buyAmt;
} else { } else {
@ -1044,13 +1062,15 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
mat.qty += buyAmt; mat.qty += buyAmt;
expenses += (buyAmt * mat.bCost); expenses += (buyAmt * mat.bCost);
} }
})(matName); })(matName, industry);
this.updateWarehouseSizeUsed(warehouse); this.updateWarehouseSizeUsed(warehouse);
} }
} //End process purchase of materials } //End process purchase of materials
break; break;
case "PRODUCTION": case "PRODUCTION":
warehouse.smartSupplyStore = 0; //Reset smart supply amount
/* Process production of materials */ /* Process production of materials */
if (this.prodMats.length > 0) { if (this.prodMats.length > 0) {
var mat = warehouse.materials[this.prodMats[0]]; var mat = warehouse.materials[this.prodMats[0]];
@ -1083,6 +1103,9 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
prod = Math.min(maxAmt, prod); prod = Math.min(maxAmt, prod);
} }
//Keep track of production for smart supply (/s)
warehouse.smartSupplyStore += (prod / (SecsPerMarketCycle * marketCycles));
//Make sure we have enough resource to make our materials //Make sure we have enough resource to make our materials
var producableFrac = 1; var producableFrac = 1;
for (var reqMatName in this.reqMats) { for (var reqMatName in this.reqMats) {
@ -1220,10 +1243,10 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
var expIndustry = company.divisions[foo]; var expIndustry = company.divisions[foo];
var expWarehouse = expIndustry.warehouses[exp.city]; var expWarehouse = expIndustry.warehouses[exp.city];
if (!(expWarehouse instanceof Warehouse)) { if (!(expWarehouse instanceof Warehouse)) {
console.log("ERROR: Invalid export!"); console.log("ERROR: Invalid export! " + expIndustry.name + " " + exp.city);
break; break;
} }
expWarehouse.materials[mat.name].qty += amt; expWarehouse.materials[matName].qty += amt;
mat.qty -= amt; mat.qty -= amt;
break; break;
} }
@ -1275,7 +1298,7 @@ Industry.prototype.processProducts = function(marketCycles=1, corporation) {
office.employeeProd[EmployeePositions.Operations] / total + office.employeeProd[EmployeePositions.Operations] / total +
office.employeeProd[EmployeePositions.Management] / total; office.employeeProd[EmployeePositions.Management] / total;
} }
prod.createProduct(marketCycles, ratio * Math.pow(total, 0.3)); prod.createProduct(marketCycles, ratio * Math.pow(total, 0.29));
if (prod.prog >= 100) { if (prod.prog >= 100) {
prod.finishProduct(office.employeeProd, this); prod.finishProduct(office.employeeProd, this);
} }
@ -1334,6 +1357,8 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
prod = Math.min(maxAmt, prod); prod = Math.min(maxAmt, prod);
} }
warehouse.smartSupplyStore += (prod / (SecsPerMarketCycle * marketCycles));
//Make sure we have enough resources to make our Products //Make sure we have enough resources to make our Products
var producableFrac = 1; var producableFrac = 1;
for (var reqMatName in product.reqMats) { for (var reqMatName in product.reqMats) {
@ -1384,8 +1409,8 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
var businessFactor = this.getBusinessFactor(office); //Business employee productivity var businessFactor = this.getBusinessFactor(office); //Business employee productivity
var advertisingFactor = this.getAdvertisingFactors()[0]; //Awareness + popularity var advertisingFactor = this.getAdvertisingFactors()[0]; //Awareness + popularity
var marketFactor = this.getMarketFactor(product); //Competition + demand var marketFactor = this.getMarketFactor(product); //Competition + demand
var maxSell = Math.pow(product.rat, 0.9) * marketFactor * corporation.getSalesMultiplier() * var maxSell = 0.5 * Math.pow(product.rat, 0.65) * marketFactor * corporation.getSalesMultiplier() *
markup * businessFactor * advertisingFactor; Math.pow(markup, 2) * businessFactor * advertisingFactor;
var sellAmt; var sellAmt;
if (product.sllman[city][0] && product.sllman[city][1] > 0) { if (product.sllman[city][0] && product.sllman[city][1] > 0) {
//Sell amount is manually limited //Sell amount is manually limited
@ -1448,7 +1473,7 @@ Industry.prototype.upgrade = function(upgrade, refs) {
this.awareness += (4 * advMult); this.awareness += (4 * advMult);
this.popularity += (1 * advMult); this.popularity += (1 * advMult);
this.awareness *= (1.01 * advMult); this.awareness *= (1.01 * advMult);
this.popularity *= ((1 + getRandomInt(3, 6) / 100) * advMult); this.popularity *= ((1 + getRandomInt(2, 4) / 100) * advMult);
break; break;
default: default:
console.log("ERROR: Un-implemented function index: " + upgN); console.log("ERROR: Un-implemented function index: " + upgN);
@ -1492,7 +1517,7 @@ Industry.prototype.getAdvertisingFactors = function() {
var awarenessFac = Math.pow(this.awareness + 1, this.advFac); var awarenessFac = Math.pow(this.awareness + 1, this.advFac);
var popularityFac = Math.pow(this.popularity + 1, this.advFac); var popularityFac = Math.pow(this.popularity + 1, this.advFac);
var ratioFac = (this.awareness === 0 ? 0.01 : Math.max((this.popularity + .001) / this.awareness, 0.01)); var ratioFac = (this.awareness === 0 ? 0.01 : Math.max((this.popularity + .001) / this.awareness, 0.01));
var totalFac = awarenessFac * popularityFac * ratioFac; var totalFac = Math.pow(awarenessFac * popularityFac * ratioFac, 0.85);
return [totalFac, awarenessFac, popularityFac, ratioFac]; return [totalFac, awarenessFac, popularityFac, ratioFac];
} }
@ -1960,8 +1985,13 @@ function Warehouse(params={}) {
this.loc = params.loc ? params.loc : ""; this.loc = params.loc ? params.loc : "";
this.size = params.size ? params.size : 0; this.size = params.size ? params.size : 0;
this.level = 0; this.level = 0;
this.sizeUsed = 0; this.sizeUsed = 0;
this.smartSupplyEnabled = false; //Whether or not smart supply is enabled
//Stores the amount of product to be produced. Used for Smart Supply unlock.
//The production tracked by smart supply is always based on the previous cycle,
//so it will always trail the "true" production by 1 cycle
this.smartSupplyStore = 0;
this.materials = { this.materials = {
Water: new Material({name: "Water"}), Water: new Material({name: "Water"}),
@ -1980,11 +2010,15 @@ function Warehouse(params={}) {
Warehouse.prototype.updateMaterialSizeUsed = function() { Warehouse.prototype.updateMaterialSizeUsed = function() {
this.sizeUsed = 0; this.sizeUsed = 0;
if (this.loc === currentCityUi) {industryWarehouseStorageBreakdownText = ""; }
for (var matName in this.materials) { for (var matName in this.materials) {
if (this.materials.hasOwnProperty(matName)) { if (this.materials.hasOwnProperty(matName)) {
var mat = this.materials[matName]; var mat = this.materials[matName];
if (MaterialSizes.hasOwnProperty(matName)) { if (MaterialSizes.hasOwnProperty(matName)) {
this.sizeUsed += (mat.qty * MaterialSizes[matName]); this.sizeUsed += (mat.qty * MaterialSizes[matName]);
if (mat.qty > 0 && this.loc === currentCityUi) {
industryWarehouseStorageBreakdownText += (matName + ": " + formatNumber(mat.qty * MaterialSizes[matName], 0) + "<br>");
}
} }
} }
} }
@ -2009,18 +2043,15 @@ Warehouse.prototype.createUI = function(parentRefs) {
} }
var company = parentRefs.company, industry = parentRefs.industry; var company = parentRefs.company, industry = parentRefs.industry;
removeChildrenFromElement(industryWarehousePanel); removeChildrenFromElement(industryWarehousePanel);
var storageText = "Storage: " + industryWarehouseStorageText = createElement("p", {
(this.sizedUsed >= this.size ? formatNumber(this.sizeUsed, 3) : formatNumber(this.sizeUsed, 3)) + display:"inline-block", class:"tooltip",
"/" + formatNumber(this.size, 3);
industryWarehousePanel.appendChild(createElement("p", {
innerHTML: storageText,
display:"inline-block",
color: this.sizeUsed >= this.size ? "red" : "white", color: this.sizeUsed >= this.size ? "red" : "white",
})); });
industryWarehousePanel.appendChild(industryWarehouseStorageText);
//Upgrade warehouse size button //Upgrade warehouse size button
var upgradeCost = WarehouseUpgradeBaseCost * Math.pow(1.07, Math.round(this.size / 100) - 1); var upgradeCost = WarehouseUpgradeBaseCost * Math.pow(1.07, Math.round(this.size / 100) - 1);
industryWarehousePanel.appendChild(createElement("a", { industryWarehouseUpgradeSizeButton = createElement("a", {
innerText:"Upgrade Warehouse Size - " + numeral(upgradeCost).format('$0.000a'), innerText:"Upgrade Warehouse Size - " + numeral(upgradeCost).format('$0.000a'),
display:"inline-block", display:"inline-block",
class: company.funds.lt(upgradeCost) ? "a-link-button-inactive" : "a-link-button", class: company.funds.lt(upgradeCost) ? "a-link-button-inactive" : "a-link-button",
@ -2036,7 +2067,8 @@ Warehouse.prototype.createUI = function(parentRefs) {
this.createUI(parentRefs); this.createUI(parentRefs);
return; return;
} }
})); });
industryWarehousePanel.appendChild(industryWarehouseUpgradeSizeButton);
//Material requirement text //Material requirement text
var reqText = "This Industry uses [" + Object.keys(industry.reqMats).join(", ") + var reqText = "This Industry uses [" + Object.keys(industry.reqMats).join(", ") +
@ -2050,28 +2082,7 @@ Warehouse.prototype.createUI = function(parentRefs) {
reqText += industry.getProductDescriptionText(); reqText += industry.getProductDescriptionText();
} }
reqText += "<br><br>To get started with production, purchase your required " + reqText += "<br><br>To get started with production, purchase your required " +
"materials or import them from another of your company's divisions.<br><br>" + "materials or import them from another of your company's divisions.<br><br>";
"Current state: ";
switch(industry.state) {
case "START":
reqText += "Preparing...";
break;
case "PURCHASE":
reqText += "Purchasing materials...";
break;
case "PRODUCTION":
reqText += "Producing materials and/or products...";
break;
case "SALE":
reqText += "Selling materials and/or products...";
break;
case "EXPORT":
reqText += "Exporting materials and/or products...";
break;
default:
console.log("ERROR: Invalid state: " + industry.state);
break;
}
//Material ratio text for tooltip //Material ratio text for tooltip
var reqRatioText = "The exact requirements for production are:<br>"; var reqRatioText = "The exact requirements for production are:<br>";
@ -2094,28 +2105,116 @@ Warehouse.prototype.createUI = function(parentRefs) {
innerHTML:reqText, tooltipleft:reqRatioText innerHTML:reqText, tooltipleft:reqRatioText
})); }));
//Current state
industryWarehouseStateText = createElement("p");
industryWarehousePanel.appendChild(industryWarehouseStateText);
//Smart Supply Enable/Disable
if (company.unlockUpgrades[1]) {
if (this.smartSupplyEnabled == null) {this.smartSupplyEnabled = false;}
var smartSupplyCheckboxId = "cmpy-mgmt-smart-supply-checkbox";
industryWarehousePanel.appendChild(createElement("label", {
for:smartSupplyCheckboxId, innerText:"Enable Smart Supply",
color:"white"
}));
industrySmartSupplyCheckbox = createElement("input", {
type:"checkbox", id:smartSupplyCheckboxId, margin:"3px",
changeListener:()=>{
this.smartSupplyEnabled = industrySmartSupplyCheckbox.checked;
}
});
industrySmartSupplyCheckbox.checked = this.smartSupplyEnabled;
industryWarehousePanel.appendChild(industrySmartSupplyCheckbox);
}
//Materials //Materials
industryWarehousePanel.appendChild(createElement("p", { industryWarehousePanel.appendChild(createElement("p", {
innerHTML: "<br>Materials:<br>", innerHTML: "<br>Materials:<br>",
})); }));
industryWarehouseMaterials = createElement("ul");
industryWarehousePanel.appendChild(industryWarehouseMaterials);
//Products
if (industry.makesProducts && Object.keys(industry.products).length > 0) {
industryWarehousePanel.appendChild(createElement("p", {
innerHTML: "<br>Products:<br>",
}));
industryWarehouseProducts = createElement("ul");
industryWarehousePanel.appendChild(industryWarehouseProducts);
}
this.updateUI(parentRefs);
}
Warehouse.prototype.updateUI = function(parentRefs) {
if (parentRefs.company == null || parentRefs.industry == null) {
console.log("ERROR: Warehouse.updateUI called without parentRefs.company or parentRefs.industry");
return;
}
var company = parentRefs.company, industry = parentRefs.industry;
//Storage text
var storageText = "Storage: " +
(this.sizedUsed >= this.size ? formatNumber(this.sizeUsed, 3) : formatNumber(this.sizeUsed, 3)) +
"/" + formatNumber(this.size, 3);
if (industryWarehouseStorageBreakdownText != null &&
industryWarehouseStorageBreakdownText != "") {
storageText += ("<span class='tooltiptext'>" +
industryWarehouseStorageBreakdownText + "</span>");
}
industryWarehouseStorageText.innerHTML = storageText;
//Upgrade warehouse size button
var upgradeCost = WarehouseUpgradeBaseCost * Math.pow(1.07, Math.round(this.size / 100) - 1);
if (company.funds.lt(upgradeCost)) {
industryWarehouseUpgradeSizeButton.className = "a-link-button-inactive";
} else {
industryWarehouseUpgradeSizeButton.className = "a-link-button";
}
//Current state
var stateText = "Current state: ";
switch(industry.state) {
case "START":
stateText += "Preparing...";
break;
case "PURCHASE":
stateText += "Purchasing materials...";
break;
case "PRODUCTION":
stateText += "Producing materials and/or products...";
break;
case "SALE":
stateText += "Selling materials and/or products...";
break;
case "EXPORT":
stateText += "Exporting materials and/or products...";
break;
default:
console.log("ERROR: Invalid state: " + industry.state);
break;
}
industryWarehouseStateText.innerText = stateText;
//Materials
removeChildrenFromElement(industryWarehouseMaterials);
for (var matName in this.materials) { for (var matName in this.materials) {
if (this.materials.hasOwnProperty(matName) && this.materials[matName] instanceof Material) { if (this.materials.hasOwnProperty(matName) && this.materials[matName] instanceof Material) {
if (Object.keys(industry.reqMats).includes(matName) || industry.prodMats.includes(matName) || if (Object.keys(industry.reqMats).includes(matName) || industry.prodMats.includes(matName) ||
matName === "Hardware" || matName === "Robots" || matName === "AICores" || matName === "Hardware" || matName === "Robots" || matName === "AICores" ||
matName === "RealEstate") { matName === "RealEstate") {
this.createMaterialUI(this.materials[matName], matName, parentRefs); industryWarehouseMaterials.appendChild(this.createMaterialUI(this.materials[matName], matName, parentRefs));
} }
} }
} }
//Products //Products
if (!(industry.makesProducts && Object.keys(industry.products).length > 0)) {return;} if (industry.makesProducts && Object.keys(industry.products).length > 0) {
industryWarehousePanel.appendChild(createElement("p", { removeChildrenFromElement(industryWarehouseProducts);
innerHTML: "<br>Products:<br>", for (var productName in industry.products) {
})); if (industry.products.hasOwnProperty(productName) && industry.products[productName] instanceof Product) {
for (var productName in industry.products) { industryWarehouseProducts.appendChild(this.createProductUI(industry.products[productName], parentRefs));
if (industry.products.hasOwnProperty(productName) && industry.products[productName] instanceof Product) { }
this.createProductUI(industry.products[productName], parentRefs);
} }
} }
} }
@ -2185,9 +2284,7 @@ Warehouse.prototype.createMaterialUI = function(mat, matName, parentRefs) {
type:"number", value:mat.buy ? mat.buy : null, placeholder: "Purchase amount", type:"number", value:mat.buy ? mat.buy : null, placeholder: "Purchase amount",
onkeyup:(e)=>{ onkeyup:(e)=>{
e.preventDefault(); e.preventDefault();
if (e.keyCode === 13) { if (e.keyCode === 13) {confirmBtn.click();}
confirmBtn.click();
}
} }
}); });
confirmBtn = createElement("a", { confirmBtn = createElement("a", {
@ -2239,28 +2336,30 @@ Warehouse.prototype.createMaterialUI = function(mat, matName, parentRefs) {
}); });
//Select industry and city to export to //Select industry and city to export to
var industrySelector = createElement("select", {}), var citySelector = createElement("select");
citySelector = createElement("select", {}); var industrySelector = createElement("select", {
changeListener:()=>{
var industryName = industrySelector.options[industrySelector.selectedIndex].value;
for (var foo = 0; foo < company.divisions.length; ++foo) {
if (company.divisions[foo].name == industryName) {
clearSelector(citySelector);
var selectedIndustry = company.divisions[foo];
for (var cityName in company.divisions[foo].warehouses) {
if (company.divisions[foo].warehouses[cityName] instanceof Warehouse) {
citySelector.add(createElement("option", {
value:cityName, text:cityName,
}));
}
}
return;
}
}
}
});
for (var i = 0; i < company.divisions.length; ++i) { for (var i = 0; i < company.divisions.length; ++i) {
industrySelector.add(createElement("option", { industrySelector.add(createElement("option", {
text:company.divisions[i].name, value:company.divisions[i].name, text:company.divisions[i].name, value:company.divisions[i].name,
changeListener:()=>{
var industryName = industrySelector.options[industrySelector.selectedIndex].value;
for (var foo = 0; foo < company.divisions.length; ++foo) {
if (company.divisions[foo].name == industryName) {
clearSelector(citySelector);
var selectedIndustry = company.divisions[foo];
for (var cityName in company.divisions[foo].warehouses) {
if (company.divisions[foo].warehouses[cityName] instanceof Warehouse) {
citySelector.add(createElement("option", {
value:cityName, text:cityName,
}));
}
}
return;
}
}
}
})); //End create element option })); //End create element option
} //End for } //End for
@ -2471,7 +2570,7 @@ Warehouse.prototype.createMaterialUI = function(mat, matName, parentRefs) {
} }
})); }));
industryWarehousePanel.appendChild(div); return div;
} }
Warehouse.prototype.createProductUI = function(product, parentRefs) { Warehouse.prototype.createProductUI = function(product, parentRefs) {
@ -2487,8 +2586,7 @@ Warehouse.prototype.createProductUI = function(product, parentRefs) {
innerHTML: "Designing " + product.name + "...<br>" + innerHTML: "Designing " + product.name + "...<br>" +
formatNumber(product.prog, 2) + "% complete", formatNumber(product.prog, 2) + "% complete",
})); }));
industryWarehousePanel.appendChild(div); return div;
return;
} }
//Completed products //Completed products
@ -2517,7 +2615,10 @@ Warehouse.prototype.createProductUI = function(product, parentRefs) {
"<span class='tooltiptext'>An estimate of how much it costs to produce one unit of this product. " + "<span class='tooltiptext'>An estimate of how much it costs to produce one unit of this product. " +
"If your sell price exceeds this by too much, people won't buy your product. The better your " + "If your sell price exceeds this by too much, people won't buy your product. The better your " +
"product is, the higher you can mark up its price.</span></p><br>" + "product is, the higher you can mark up its price.</span></p><br>" +
"Size: " + formatNumber(product.siz, 3), "<p class='tooltip'>Est. Market Price: " + numeral(product.pCost + product.rat / product.mku).format("$0.000a") +
"<span class='tooltiptext'>An estimate of how much consumers are willing to pay for this product. " +
"Setting the sale price above this may result in less sales. Setting the sale price below this may result " +
"in more sales.</span></p>"
})); }));
var buttonPanel = createElement("div", { var buttonPanel = createElement("div", {
display:"inline-block", display:"inline-block",
@ -2688,7 +2789,7 @@ Warehouse.prototype.createProductUI = function(product, parentRefs) {
createPopup(popupId, [txt, confirmBtn, cancelBtn]); createPopup(popupId, [txt, confirmBtn, cancelBtn]);
} }
})); }));
industryWarehousePanel.appendChild(div); return div;
} }
Warehouse.prototype.toJSON = function() { Warehouse.prototype.toJSON = function() {
@ -2711,7 +2812,7 @@ var CorporationUnlockUpgrades = {
"This allows you to move materials around between different divisions and cities."], "This allows you to move materials around between different divisions and cities."],
//Lets you buy exactly however many required materials you need for production //Lets you buy exactly however many required materials you need for production
"1": [1, 999999e9, "Smart Supply", "NOT YET IMPLEMENTED!!!!!! - Use advanced AI to anticipate your supply needs. " + "1": [1, 50e9, "Smart Supply", "Use advanced AI to anticipate your supply needs. " +
"This allows you to purchase exactly however many materials you need for production."], "This allows you to purchase exactly however many materials you need for production."],
//Displays each material/product's demand //Displays each material/product's demand
@ -2754,10 +2855,10 @@ var CorporationUpgrades = {
"20 seconds."], "20 seconds."],
//Makes advertising more effective //Makes advertising more effective
"3": [3, 4e9, 1.12, 0.01, "3": [3, 4e9, 1.12, 0.005,
"Wilson Analytics", "Purchase data and analysis from Wilson, a marketing research " + "Wilson Analytics", "Purchase data and analysis from Wilson, a marketing research " +
"firm. Each level of this upgrades increases the effectiveness of your " + "firm. Each level of this upgrades increases the effectiveness of your " +
"advertising by 1% (additive)."], "advertising by 0.5% (additive)."],
//Augmentation for employees, increases cre //Augmentation for employees, increases cre
"4": [4, 1e9, 1.06, 0.1, "4": [4, 1e9, 1.06, 0.1,
@ -2825,12 +2926,15 @@ Corporation.prototype.getState = function() {
return this.state.getState(); return this.state.getState();
} }
var numMarketCyclesPersist = 1; Corporation.prototype.storeCycles = function(numCycles=1) {
Corporation.prototype.process = function(numCycles=1) {
var corp = this;
this.storedCycles += numCycles; this.storedCycles += numCycles;
}
Corporation.prototype.process = function() {
var corp = this;
if (this.storedCycles >= CyclesPerIndustryStateCycle) { if (this.storedCycles >= CyclesPerIndustryStateCycle) {
var state = this.getState(); var state = this.getState(), marketCycles=1;
this.storedCycles -= (marketCycles * CyclesPerIndustryStateCycle);
//At the start of a new cycle, calculate profits from previous cycle //At the start of a new cycle, calculate profits from previous cycle
if (state === "START") { if (state === "START") {
@ -2841,7 +2945,7 @@ Corporation.prototype.process = function(numCycles=1) {
this.expenses = this.expenses.plus(ind.lastCycleExpenses); this.expenses = this.expenses.plus(ind.lastCycleExpenses);
}); });
var profit = this.revenue.minus(this.expenses); var profit = this.revenue.minus(this.expenses);
var cycleProfit = profit.times(numMarketCyclesPersist * SecsPerMarketCycle); var cycleProfit = profit.times(marketCycles * SecsPerMarketCycle);
if (isNaN(this.funds)) { if (isNaN(this.funds)) {
dialogBoxCreate("There was an error calculating your Corporations funds and they got reset to 0. " + dialogBoxCreate("There was an error calculating your Corporations funds and they got reset to 0. " +
"This is a bug. Please report to game developer.<br><br>" + "This is a bug. Please report to game developer.<br><br>" +
@ -2852,19 +2956,6 @@ Corporation.prototype.process = function(numCycles=1) {
this.updateSharePrice(); this.updateSharePrice();
} }
//Determine number of market cycles at the START state
if (state === "START") {
if (this.storedCycles >= 2*CyclesPerMarketCycle) {
//Enough cycles stored for 2+ market cycles
//Capped out at 3 to prevent weird behavior
numMarketCyclesPersist = Math.max(3, Math.floor(this.storedCycles / CyclesPerMarketCycle));
} else {
numMarketCyclesPersist = 1;
}
}
var marketCycles = numMarketCyclesPersist;
this.storedCycles -= (marketCycles * CyclesPerIndustryStateCycle);
this.divisions.forEach(function(ind) { this.divisions.forEach(function(ind) {
ind.process(marketCycles, state, corp); ind.process(marketCycles, state, corp);
}); });
@ -2948,12 +3039,17 @@ Corporation.prototype.goPublic = function() {
"your company's stock price in the future.<br><br>" + "your company's stock price in the future.<br><br>" +
"You have a total of " + numeral(this.numShares).format("0.000a") + " of shares that you can issue.", "You have a total of " + numeral(this.numShares).format("0.000a") + " of shares that you can issue.",
}); });
var yesBtn;
var input = createElement("input", { var input = createElement("input", {
type:"number", type:"number",
placeholder: "Shares to issue", placeholder: "Shares to issue",
onkeyup:(e)=>{
e.preventDefault();
if (e.keyCode === 13) {yesBtn.click();}
}
}); });
var br = createElement("br", {}); var br = createElement("br", {});
var yesBtn = createElement("a", { yesBtn = createElement("a", {
class:"a-link-button", class:"a-link-button",
innerText:"Go Public", innerText:"Go Public",
clickListener:()=>{ clickListener:()=>{
@ -3099,11 +3195,20 @@ Corporation.prototype.getScientificResearchMultiplier = function() {
var companyManagementDiv, companyManagementHeaderTabs, companyManagementPanel, var companyManagementDiv, companyManagementHeaderTabs, companyManagementPanel,
currentCityUi, currentCityUi,
corporationUnlockUpgrades, corporationUpgrades, corporationUnlockUpgrades, corporationUpgrades,
//Industry Overview Panel
industryOverviewPanel, industryOverviewText, industryOverviewPanel, industryOverviewText,
//Industry Employee Panel
industryEmployeePanel, industryEmployeeText, industryEmployeeHireButton, industryEmployeeAutohireButton, industryEmployeePanel, industryEmployeeText, industryEmployeeHireButton, industryEmployeeAutohireButton,
industryEmployeeManagementUI, industryEmployeeInfo, industryIndividualEmployeeInfo, industryEmployeeManagementUI, industryEmployeeInfo, industryIndividualEmployeeInfo,
industryOfficeUpgradeSizeButton, industryOfficeUpgradeSizeButton,
industryWarehousePanel,
//Industry Warehouse Panel
industryWarehousePanel, industrySmartSupplyCheckbox, industryWarehouseStorageText,
industryWarehouseStorageBreakdownText,
industryWarehouseUpgradeSizeButton, industryWarehouseStateText,
industryWarehouseMaterials, industryWarehouseProducts,
headerTabs, cityTabs; headerTabs, cityTabs;
Corporation.prototype.createUI = function() { Corporation.prototype.createUI = function() {
companyManagementDiv = createElement("div", { companyManagementDiv = createElement("div", {
@ -3163,28 +3268,33 @@ Corporation.prototype.updateUIHeaderTabs = function() {
var container = createElement("div", { var container = createElement("div", {
class:"popup-box-container", class:"popup-box-container",
id:"cmpy-mgmt-expand-industry-popup", id:"cmpy-mgmt-expand-industry-popup",
}), });
content = createElement("div", {class:"popup-box-content"}), var content = createElement("div", {class:"popup-box-content"});
txt = createElement("p", { var txt = createElement("p", {
innerHTML: "Create a new division to expand into a new industry:", innerHTML: "Create a new division to expand into a new industry:",
}), });
selector = createElement("select", { var selector = createElement("select", {
class:"cmpy-mgmt-industry-select" class:"cmpy-mgmt-industry-select"
}), });
industryDescription = createElement("p", {}), var industryDescription = createElement("p", {});
nameInput = createElement("input", { var yesBtn;
var nameInput = createElement("input", {
type:"text", type:"text",
id:"cmpy-mgmt-expand-industry-name-input", id:"cmpy-mgmt-expand-industry-name-input",
color:"white", color:"white",
backgroundColor:"black", backgroundColor:"black",
display:"block", display:"block",
maxLength: 30, maxLength: 30,
pattern:"[a-zA-Z0-9-_]" pattern:"[a-zA-Z0-9-_]",
}), onkeyup:(e)=>{
nameLabel = createElement("label", { e.preventDefault();
if (e.keyCode === 13) {yesBtn.click();}
}
});
var nameLabel = createElement("label", {
for:"cmpy-mgmt-expand-industry-name-input", for:"cmpy-mgmt-expand-industry-name-input",
innerText:"Division name: " innerText:"Division name: "
}), });
yesBtn = createElement("span", { yesBtn = createElement("span", {
class:"popup-box-button", class:"popup-box-button",
innerText:"Create Division", innerText:"Create Division",
@ -3216,8 +3326,8 @@ Corporation.prototype.updateUIHeaderTabs = function() {
} }
return false; return false;
} }
}), });
noBtn = createElement("span", { var noBtn = createElement("span", {
class:"popup-box-button", class:"popup-box-button",
innerText:"Cancel", innerText:"Cancel",
clickListener: function() { clickListener: function() {
@ -4054,7 +4164,8 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
division.products[product.name] = product; division.products[product.name] = product;
removeElementById(popupId); removeElementById(popupId);
} }
this.updateUIContent(); //this.updateUIContent();
this.displayDivisionContent(division, city);
return false; return false;
} }
}) })
@ -4129,16 +4240,42 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
tooltip:"Upgrade the office's size so that it can hold more employees!", tooltip:"Upgrade the office's size so that it can hold more employees!",
clickListener:()=>{ clickListener:()=>{
var popupId = "cmpy-mgmt-upgrade-office-size-popup"; var popupId = "cmpy-mgmt-upgrade-office-size-popup";
var upgradeCost = OfficeInitialCost * Math.pow(1.07, Math.round(office.size / OfficeInitialSize)); var initialPriceMult = Math.round(office.size / OfficeInitialSize);
var upgradeCost = OfficeInitialCost * Math.pow(1.07, initialPriceMult);
//Calculate cost to upgrade size by 15 employees
var mult = 0;
for (var i = 0; i < 5; ++i) {
mult += (Math.pow(1.07, initialPriceMult + i));
}
var upgradeCost15 = OfficeInitialCost * mult;
//Calculate max upgrade size and cost
var maxMult = (this.funds.dividedBy(OfficeInitialCost)).toNumber();
var maxNum = 1;
mult = Math.pow(1.07, initialPriceMult);
while(maxNum < 50) { //Hard cap of 50x (extra 150 employees)
if (mult >= maxMult) {break;}
var multIncrease = Math.pow(1.07, initialPriceMult + maxNum);
if (mult + multIncrease > maxMult) {
break;
} else {
mult += multIncrease;
}
++maxNum;
}
var upgradeCostMax = OfficeInitialCost * mult;
var text = createElement("p", { var text = createElement("p", {
innerHTML:"Increase the size of your office space to fit " + OfficeInitialSize + innerText:"Increase the size of your office space to fit additional employees!"
" more employees. This will cost " + numeral(upgradeCost).format('$0.000a'),
}); });
var text2 = createElement("p", {innerText: "Upgrade size: "});
var confirmBtn = createElement("a", { var confirmBtn = createElement("a", {
class:"a-link-button", class: this.funds.lt(upgradeCost) ? "a-link-button-inactive" : "a-link-button",
display:"inline-block", display:"inline-block", margin:"4px", innerText:"by 3",
margin:"8px", tooltip:numeral(upgradeCost).format("$0.000a"),
innerText:"Upgrade Office Size",
clickListener:()=>{ clickListener:()=>{
if (this.funds.lt(upgradeCost)) { if (this.funds.lt(upgradeCost)) {
dialogBoxCreate("You don't have enough company funds to purchase this upgrade!"); dialogBoxCreate("You don't have enough company funds to purchase this upgrade!");
@ -4152,17 +4289,48 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
return false; return false;
} }
}); });
var confirmBtn15 = createElement("a", {
class: this.funds.lt(upgradeCost15) ? "a-link-button-inactive" : "a-link-button",
display:"inline-block", margin:"4px", innerText:"by 15",
tooltip:numeral(upgradeCost15).format("$0.000a"),
clickListener:()=>{
if (this.funds.lt(upgradeCost15)) {
dialogBoxCreate("You don't have enough company funds to purchase this upgrade!");
} else {
office.size += (OfficeInitialSize * 5);
this.funds = this.funds.minus(upgradeCost15);
dialogBoxCreate("Office space increased! It can now hold " + office.size + " employees");
this.updateUIContent();
}
removeElementById(popupId);
return false;
}
});
var confirmBtnMax = createElement("a", {
class:this.funds.lt(upgradeCostMax) ? "a-link-button-inactive" : "a-link-button",
display:"inline-block", margin:"4px", innerText:"by MAX (" + maxNum*OfficeInitialSize + ")",
tooltip:numeral(upgradeCostMax).format("$0.000a"),
clickListener:()=>{
if (this.funds.lt(upgradeCostMax)) {
dialogBoxCreate("You don't have enough company funds to purchase this upgrade!");
} else {
office.size += (OfficeInitialSize * maxNum);
this.funds = this.funds.minus(upgradeCostMax);
dialogBoxCreate("Office space increased! It can now hold " + office.size + " employees");
this.updateUIContent();
}
removeElementById(popupId);
return false;
}
});
var cancelBtn = createElement("a", { var cancelBtn = createElement("a", {
class:"a-link-button", class:"a-link-button", innerText:"Cancel", display:"inline-block", margin:"4px",
innerText:"Cancel",
display:"inline-block",
margin:"8px",
clickListener:()=>{ clickListener:()=>{
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} }
}) })
createPopup(popupId, [text, confirmBtn, cancelBtn]); createPopup(popupId, [text, text2, confirmBtn, confirmBtn15, confirmBtnMax, cancelBtn]);
return false; return false;
} }
}); });
@ -4182,6 +4350,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
var totalCostTxt = createElement("p", { var totalCostTxt = createElement("p", {
innerText:"Throwing this party will cost a total of $0" innerText:"Throwing this party will cost a total of $0"
}); });
var confirmBtn;
var input = createElement("input", { var input = createElement("input", {
type:"number", margin:"5px", placeholder:"$ / employee", type:"number", margin:"5px", placeholder:"$ / employee",
inputListener:()=>{ inputListener:()=>{
@ -4191,9 +4360,13 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
var totalCost = input.value * office.employees.length; var totalCost = input.value * office.employees.length;
totalCostTxt.innerText = "Throwing this party will cost a total of " + numeral(totalCost).format('$0.000a'); totalCostTxt.innerText = "Throwing this party will cost a total of " + numeral(totalCost).format('$0.000a');
} }
},
onkeyup:(e)=>{
e.preventDefault();
if (e.keyCode === 13) {confirmBtn.click();}
} }
}); });
var confirmBtn = createElement("a", { confirmBtn = createElement("a", {
class:"a-link-button", class:"a-link-button",
display:"inline-block", display:"inline-block",
innerText:"Throw Party", innerText:"Throw Party",
@ -4383,7 +4556,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
size:WarehouseInitialSize, size:WarehouseInitialSize,
}); });
this.funds = this.funds.minus(WarehouseInitialCost); this.funds = this.funds.minus(WarehouseInitialCost);
this.updateDivisionContent(division); this.displayDivisionContent(division, currentCityUi);
} }
return false; return false;
} }
@ -4411,23 +4584,51 @@ Corporation.prototype.updateDivisionContent = function(division) {
advertisingInfo = advertisingInfo =
"<p class='tooltip'>Advertising Multiplier: x" + formatNumber(totalAdvertisingFac, 3) + "<p class='tooltip'>Advertising Multiplier: x" + formatNumber(totalAdvertisingFac, 3) +
"<span class='tooltiptext' style='font-size:12px'>Total multiplier for this industry's sales due to its awareness and popularity<br>" + "<span class='tooltiptext' style='font-size:12px'>Total multiplier for this industry's sales due to its awareness and popularity<br>" +
"Awareness Bonus: x" + formatNumber(awarenessFac, 3) + "<br>" + "Awareness Bonus: x" + formatNumber(Math.pow(awarenessFac, 0.85), 3) + "<br>" +
"Popularity Bonus: x" + formatNumber(popularityFac, 3) + "<br>" + "Popularity Bonus: x" + formatNumber(Math.pow(popularityFac, 0.85), 3) + "<br>" +
"Ratio Multiplier: x" + formatNumber(ratioFac, 3) + "</span></p><br>" "Ratio Multiplier: x" + formatNumber(Math.pow(ratioFac, 0.85), 3) + "</span></p><br>"
} }
industryOverviewText.innerHTML =
"Industry: " + division.type + "<br><br>" + removeChildrenFromElement(industryOverviewText);
"Awareness: " + formatNumber(division.awareness, 3) + "<br>" + industryOverviewText.appendChild(createElement("p", {
"Popularity: " + formatNumber(division.popularity, 3) + "<br>" + innerHTML:"Industry: " + division.type + " (Corp Funds: " + numeral(this.funds.toNumber()).format("$0.000a") + ")<br><br>" +
advertisingInfo + "<br>" + "Awareness: " + formatNumber(division.awareness, 3) + "<br>" +
"Revenue: " + numeral(division.lastCycleRevenue.toNumber()).format("$0.000a") + " / s<br>" + "Popularity: " + formatNumber(division.popularity, 3) + "<br>" +
"Expenses: " + numeral(division.lastCycleExpenses.toNumber()).format("$0.000a") + " /s<br>" + advertisingInfo + "<br>" +
"Profit: " + profitStr + " / s<br><br>" + "Revenue: " + numeral(division.lastCycleRevenue.toNumber()).format("$0.000a") + " / s<br>" +
"<p class='tooltip'>Production Multiplier: " + formatNumber(division.prodMult, 2) + "Expenses: " + numeral(division.lastCycleExpenses.toNumber()).format("$0.000a") + " /s<br>" +
"<span class='tooltiptext'>Production gain from owning production-boosting materials " + "Profit: " + profitStr + " / s<br><br>"
"such as hardware, Robots, AI Cores, and Real Estate</span></p><br>" + }));
"Scientific Research: " + formatNumber(division.sciResearch.qty, 3); industryOverviewText.appendChild(createElement("p", {
marginTop:"2px",
innerText:"Production Multiplier: " + formatNumber(division.prodMult, 2),
tooltip:"Production gain from owning production-boosting materials " +
"such as hardware, Robots, AI Cores, and Real Estate"
}));
industryOverviewText.appendChild(createElement("div", {
innerText:"?", class:"help-tip",
clickListener:()=>{
dialogBoxCreate("Owning Hardware, Robots, AI Cores, and Real Estate " +
"can boost your Industry's production. The effect these " +
"materials have on your production varies between Industries. " +
"For example, Real Estate may be very effective for some Industries, " +
"but ineffective for others.<br><br>" +
"This division's production multiplier is calculated by summing " +
"the individual production multiplier of each of its office locations. " +
"This production multiplier is applied to each office. Therefore, it is " +
"beneficial to expand into new cities as this can greatly increase the " +
"production multiplier of your entire Division."
)
}
}));
industryOverviewText.appendChild(createElement("br"));
industryOverviewText.appendChild(createElement("p", {
display:"inline-block",
innerText:"Scientific Research: " + formatNumber(division.sciResearch.qty, 3),
tooltip:"Scientific Research increases the quality of the materials and " +
"products that you produce."
}));
//Office and Employee List //Office and Employee List
var office = division.offices[currentCityUi]; var office = division.offices[currentCityUi];
@ -4491,7 +4692,7 @@ Corporation.prototype.updateDivisionContent = function(division) {
//Warehouse //Warehouse
var warehouse = division.warehouses[currentCityUi]; var warehouse = division.warehouses[currentCityUi];
if (warehouse instanceof Warehouse) { if (warehouse instanceof Warehouse) {
warehouse.createUI({industry:division, company:this}); warehouse.updateUI({industry:division, company:this});
} }
} }
@ -4545,7 +4746,13 @@ Corporation.prototype.clearUI = function() {
industryOfficeUpgradeSizeButton = null; industryOfficeUpgradeSizeButton = null;
industryWarehousePanel = null; industryWarehousePanel = null;
industrySmartSupplyCheckbox = null;
industryWarehouseStorageText = null;
industryWarehouseUpgradeSizeButton = null;
industryWarehouseStateText = null;
industryWarehouseMaterials = null;
industryWarehouseProducts = null;
companyManagementHeaderTabs = null; companyManagementHeaderTabs = null;
headerTabs = null; headerTabs = null;

@ -1,5 +1,5 @@
let CONSTANTS = { let CONSTANTS = {
Version: "0.35.0", Version: "0.35.1",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience //Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then //and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -1138,39 +1138,28 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.35.0<br>" + "v0.35.1<br>" +
"-Minor rebalancing of BitNodes due to the fact that Corporations provide a (relatively) new method of " + "* You can now easily download all of your scripts/text files as zip folders. Use the 'help download' Terminal command for details<br>" +
"progressing<br>" + "* Scripts are now downloaded with the .script.js extension at the end of their filename<br>" +
"-Corporation Management Changes:<br>" + "* Corporation Management Changes:<br>" +
"---Once your Corporation gets big/powerful enough, you can now bribe Factions for reputation using company funds an/or stock shares<br>" + "*** Implemented Smart Supply unlock<br>" +
"---You can now only create one Division for every Industry type<br>" + "*** Changed the way a division's Production Multiplier is calculated. It is now the sum of the individual Production Multiplier " +
"---Added several new UI/UX elements<br>" + "for every city. Therefore, it is now beneficial to open offices in different cities<br." +
"---Wilson Analytics multiplier was significantly reduced to 1% per level (additive).<br>" + "*** The breakdown of what is taking up Warehouse space is now listed as a tooltip<br>" +
"---Reduced the effect of Advert Inc upgrade. Advert Inc. upgrade price increases faster<br>" + "*** Several small UI/UX improvements<br>" +
"---Materials can now be marked up at higher prices<br>" + "*** Numerous balance changes. The significant ones are listed below.<br>" +
"-Added Javascript's built-in Number object to Netscript<br>" + "*** Product descriptions will now display their estimated market price<br>" +
"-Added getCharacterInformation(), getCompanyFavor(), and getFactionFavor() Netscript Singularity functions<br>" + "*** The sale price of Products can no longer be marked up as high as before<br>" +
"-Rebalanced Singularity Function RAM Costs. They now cost x8 as much when outside of BN-4 (rather than x10). Also, " + "*** Scientific Research now affects the rating of Products<br>" +
"many of the functions now use significantly less RAM<br>" + "*** In general, the maximum amount of product you are able to sell is reduced<br>" +
"-Refactored Netscript Ports. You can now get a handle for a Netscript port using the " + "*** Sale bonus from advertising (popularity/awareness) now has diminishing returns rather than scaling linearly<br>" +
"getPortHandle() Netscript function. This allows you to access a port's underlying queue (which is just an array) and also " + "* Experience gained during Infiltration now scales linearly based on the clearance level you reach. Compared to before, " +
"makes several new functions available such as tryWrite(), full(), and empty().<br>" + "the experience gained will be much less at lower clearance levels, but much more at higher clearance levels<br>" +
"-Number of Netscript Ports increased from 10 to 20<br>" + "* The editor can now be used to edit both scripts and text files<br>" +
"-Netscript assignments should now return proper values. i.e. i = 5 should return 5.<br>" + "* New Terminal config file that can be edited using the command 'nano .fconf'. Right now there is only one option, but there " +
"-Added throw statements to Netscript. It's not super useful since 'catch' isn't implemented, but it can be used " + "will be more in the future.<br>" +
"to generate custom runtime error messages.<br>" + "* You can now enable Bash-style Terminal hotkeys using the .fconf file referenced above<br>" +
"-Added import declaration to Netscript. With this, you are able to import functions (and only functions) from " + "* Bug Fix: Fixed an issue with the UI elements of Gang Management persisting across different instances of BitNode-2"
"other files. Using export declarations is not necessary<br>" +
"-Most Netscript Runtime errors (the ones that cause your script to crash) should now include the line number where the error occured<br>" +
"-When working for a company, your current company reputation is now displayed<br>" +
"-Whenever you get a Faction Invite it will be immediately appended to your 'invited factions' list. " +
"Therefore the checkFactionInvitations() Singularity Function should now be properly useable since you no longer " +
"need to decline a Faction Invitation before it shows up in the result.<br>" +
"-Bug Fix: When purchasing servers, whitespace should now automatically be removed from the hostname<br>" +
"-Bug Fix: Can no longer have whitespace in the filename of text files created using write()<br>" +
"-Bug Fix: In Netscript, you can no longer assign a Hacknet Node handle (hacknetnodes[i]) to another value <br>" +
"-Bug Fix: If you are in the Factions tab when you accept an invitation from a Faction, the page will now properly 'refresh'<br>" +
"-Bug Fix: Scripts that run recursive functions should now be killed properly<br>"
} }
export {CONSTANTS}; export {CONSTANTS};

117
src/Fconf.js Normal file

@ -0,0 +1,117 @@
import {parse, Node} from "../utils/acorn.js";
var FconfSettings = {
ENABLE_BASH_HOTKEYS: false
}
var FconfComments = {
ENABLE_BASH_HOTKEYS: "Improved Bash emulation mode. Setting this to 1 enables several\n" +
"new Terminal shortcuts and features that more closely resemble\n" +
"a real Bash-style shell. Note that when this mode is enabled,\n" +
"the default browser shortcuts are overriden by the new Bash\n" +
"shortcuts.\n\n" +
"To see a full list of the Terminal shortcuts that this enables, see:\n",
}
//Parse Fconf settings from the config text
//Throws an exception if parsing fails
function parseFconfSettings(config) {
var ast = parse(config, {sourceType:"module"});
var queue = [];
queue.push(ast);
while (queue.length != 0) {
var exp = queue.shift();
switch (exp.type) {
case "BlockStatement":
case "Program":
for (var i = 0; i < exp.body.length; ++i) {
if (exp.body[i] instanceof Node) {
queue.push(exp.body[i]);
}
}
break;
case "AssignmentExpression":
var setting, value;
if (exp.left != null && exp.left.name != null) {
setting = exp.left.name;
} else {
break;
}
if (exp.right != null && exp.right.raw != null) {
value = exp.right.raw;
} else {
break;
}
parseFconfSetting(setting, value);
break;
default:
break;
}
for (var prop in exp) {
if (exp.hasOwnProperty(prop)) {
if (exp[prop] instanceof Node) {
queue.push(exp[prop]);
}
}
}
}
}
function parseFconfSetting(setting, value) {
setting = String(setting);
value = String(value);
if (setting == null || value == null || FconfSettings[setting] == null) {
console.log("WARNING: Invalid .fconf setting: " + setting);
return;
}
//Needed to convert entered value to boolean/strings accordingly
switch(setting) {
case "ENABLE_BASH_HOTKEYS":
var value = value.toLowerCase();
if (value === "1" || value === "true" || value === "y") {
value = true;
} else {
value = false;
}
FconfSettings[setting] = value;
break;
default:
break;
}
return;
}
//Create the .fconf file text from the settings
function createFconf() {
var res = "";
for (var setting in FconfSettings) {
if (FconfSettings.hasOwnProperty(setting)) {
//Setting comments (description)
var comment = FconfComments[setting];
if (comment == null) {continue;}
var comment = comment.split("\n");
for (var i = 0; i < comment.length; ++i) {
res += ("//" + comment[i] + "\n");
}
var value = 0;
if (FconfSettings[setting] === true) {
value = "1";
} else if (FconfSettings[setting] === false) {
value = "0";
} else {
value = String(FconfSettings[setting]);
}
res += (setting + "=" + value + "\n");
}
}
return res;
}
function loadFconf(saveString) {
FconfSettings = JSON.parse(saveString);
}
export {FconfSettings, createFconf, parseFconfSettings, loadFconf}

@ -1,7 +1,6 @@
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {Faction, Factions} from "./Faction.js"; import {Faction, Factions} from "./Faction.js";
import {Locations} from "./Location.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
import {Reviver, Generic_toJSON, import {Reviver, Generic_toJSON,
@ -53,8 +52,6 @@ $(document).mousedown(function(event) {
let GangNames = ["Slum Snakes", "Tetrads", "The Syndicate", "The Dark Army", "Speakers for the Dead", let GangNames = ["Slum Snakes", "Tetrads", "The Syndicate", "The Dark Army", "Speakers for the Dead",
"NiteSec", "The Black Hand"]; "NiteSec", "The Black Hand"];
let GangLocations = [Locations.Aevum, Locations.Chongqing, Locations.Sector12, Locations.NewTokyo,
Locations.Ishima, Locations.Volhaven];
let AllGangs = { let AllGangs = {
"Slum Snakes" : { "Slum Snakes" : {
power: 1, power: 1,
@ -1406,5 +1403,35 @@ function setGangMemberTaskDescription(memberObj, taskName) {
} }
} }
function deleteGangDisplayContent() {
if (gangContainer != null) {removeElementById(gangContainer.id);}
gangContentCreated = false;
gangContainer = null;
managementButton = null;
territoryButton = null;
//Subpages
gangManagementSubpage = null;
gangTerritorySubpage = null;
//Gang Management Elements
gangDesc = null;
gangInfo = null;
gangRecruitMemberButton = null;
gangRecruitRequirementText = null;
gangExpandAllButton = null;
gangCollapseAllButton = null;
gangMemberFilter = null;
gangManageEquipmentButton = null;
gangMemberList = null;
//Gang Equipment Upgrade Elements
gangMemberUpgradeBox = null;
gangMemberUpgradeBoxContent = null;
gangMemberUpgradeBoxFilter = null;
gangMemberUpgradeBoxElements = null;
}
export {Gang, displayGangContent, updateGangContent, loadAllGangs, AllGangs, export {Gang, displayGangContent, updateGangContent, loadAllGangs, AllGangs,
resetGangs}; resetGangs, deleteGangDisplayContent};

@ -9,7 +9,7 @@ let TerminalHelpText =
"clear Clear all text on the terminal <br>" + "clear Clear all text on the terminal <br>" +
"cls See 'clear' command <br>" + "cls See 'clear' command <br>" +
"connect [ip/hostname] Connects to a remote server<br>" + "connect [ip/hostname] Connects to a remote server<br>" +
"download [script/text file] Downloads a script or text file to your computer<br>" + "download [script/text file] Downloads scripts or text files to your computer<br>" +
"free Check the machine's memory (RAM) usage<br>" + "free Check the machine's memory (RAM) usage<br>" +
"hack Hack the current machine<br>" + "hack Hack the current machine<br>" +
"help [command] Display this help text, or the help text for a command<br>" + "help [command] Display this help text, or the help text for a command<br>" +
@ -21,7 +21,7 @@ let TerminalHelpText =
"ls [| grep pattern] Displays all files on the machine<br>" + "ls [| grep pattern] Displays all files on the machine<br>" +
"lscpu Displays the number of CPU cores on the machine<br>" + "lscpu Displays the number of CPU cores on the machine<br>" +
"mem [script] [-t] [n] Displays the amount of RAM required to run the script<br>" + "mem [script] [-t] [n] Displays the amount of RAM required to run the script<br>" +
"nano [script] Script editor - Open up and edit a script<br>" + "nano [file] Text editor - Open up and edit a script or text file<br>" +
"ps Display all scripts that are currently running<br>" + "ps Display all scripts that are currently running<br>" +
"rm [file] Delete a file from the server<br>" + "rm [file] Delete a file from the server<br>" +
"run [name] [-t] [n] [args...] Execute a program or script<br>" + "run [name] [-t] [n] [args...] Execute a program or script<br>" +
@ -87,7 +87,11 @@ let HelpTexts = {
"to this command. Note that only servers that are immediately adjacent to the current server in the network can be connected to. To " + "to this command. Note that only servers that are immediately adjacent to the current server in the network can be connected to. To " +
"see which servers can be connected to, use the 'scan' command.", "see which servers can be connected to, use the 'scan' command.",
download: "download [script/text file]<br>" + download: "download [script/text file]<br>" +
"Downloads a script or text file to your computer (like your real life computer).", "Downloads a script or text file to your computer (like your real life computer).<br>" +
"You can also download all of your scripts/text files as a zip file using the following Terminal commands:<br><br>" +
"Download all scripts and text files: download *<br>" +
"Download all scripts: download *.script<br>" +
"Download all text files: download *.txt<br>",
free: "free<br>" + free: "free<br>" +
"Display's the memory usage on the current machine. Print the amount of RAM that is available on the current server as well as " + "Display's the memory usage on the current machine. Print the amount of RAM that is available on the current server as well as " +
"how much of it is being used.", "how much of it is being used.",
@ -137,8 +141,9 @@ let HelpTexts = {
"mem foo.script -t 50<br>" + "mem foo.script -t 50<br>" +
"The first example above will print the amount of RAM needed to run 'foo.script' with a single thread. The second example " + "The first example above will print the amount of RAM needed to run 'foo.script' with a single thread. The second example " +
"above will print the amount of RAM needed to run 'foo.script' with 50 threads.", "above will print the amount of RAM needed to run 'foo.script' with 50 threads.",
nano: "nano [script name]<br>" + nano: "nano [file name]<br>" +
"Opens up the specified script in the Script Editor. If the script does not already exist, then a new, empty script " + "Opens up the specified file in the Text Editor. Only scripts (.script) or text files (.txt) can be " +
"edited using the Text Editor. If the file does not already exist, then a new, empty one " +
"will be created", "will be created",
ps: "ps<br>" + ps: "ps<br>" +
"Prints all scripts that are running on the current server", "Prints all scripts that are running on the current server",

@ -453,18 +453,20 @@ function updateInfiltrationLevelText(inst) {
totalMoneyValue += inst.secretsStolen[i] * CONSTANTS.InfiltrationMoneyValue * totalMoneyValue += inst.secretsStolen[i] * CONSTANTS.InfiltrationMoneyValue *
BitNodeMultipliers.InfiltrationMoney; BitNodeMultipliers.InfiltrationMoney;
} }
var expMultiplier = 2 * inst.clearanceLevel / inst.maxClearanceLevel;
document.getElementById("infiltration-level-text").innerHTML = document.getElementById("infiltration-level-text").innerHTML =
"Facility name: " + inst.companyName + "<br>" + "Facility name: " + inst.companyName + "<br>" +
"Clearance Level: " + inst.clearanceLevel + "<br>" + "Clearance Level: " + inst.clearanceLevel + "<br>" +
"Security Level: " + formatNumber(inst.securityLevel, 3) + "<br><br>" + "Security Level: " + formatNumber(inst.securityLevel, 3) + "<br><br>" +
"Total reputation value of secrets stolen: " + formatNumber(totalValue, 3) + "<br>" + "Total reputation value of secrets stolen: " + formatNumber(totalValue, 3) + "<br>" +
"Total monetary value of secrets stolen: $" + formatNumber(totalMoneyValue, 2) + "<br><br>" + "Total monetary value of secrets stolen: $" + formatNumber(totalMoneyValue, 2) + "<br><br>" +
"Hack exp gained: " + formatNumber(inst.hackingExpGained, 3) + "<br>" + "Hack exp gained: " + formatNumber(inst.hackingExpGained * expMultiplier, 3) + "<br>" +
"Str exp gained: " + formatNumber(inst.strExpGained, 3) + "<br>" + "Str exp gained: " + formatNumber(inst.strExpGained * expMultiplier, 3) + "<br>" +
"Def exp gained: " + formatNumber(inst.defExpGained, 3) + "<br>" + "Def exp gained: " + formatNumber(inst.defExpGained * expMultiplier, 3) + "<br>" +
"Dex exp gained: " + formatNumber(inst.dexExpGained, 3) + "<br>" + "Dex exp gained: " + formatNumber(inst.dexExpGained * expMultiplier, 3) + "<br>" +
"Agi exp gained: " + formatNumber(inst.agiExpGained, 3) + "<br>" + "Agi exp gained: " + formatNumber(inst.agiExpGained * expMultiplier, 3) + "<br>" +
"Cha exp gained: " + formatNumber(inst.chaExpGained, 3); "Cha exp gained: " + formatNumber(inst.chaExpGained * expMultiplier, 3);
} }
function updateInfiltrationButtons(inst, scenario) { function updateInfiltrationButtons(inst, scenario) {

@ -7,12 +7,14 @@ import {Programs} from "./CreateProgram.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {Factions, Faction, initFactions, import {Factions, Faction, initFactions,
joinFaction} from "./Faction.js"; joinFaction} from "./Faction.js";
import {deleteGangDisplayContent} from "./Gang.js";
import {Locations} from "./Location.js"; import {Locations} from "./Location.js";
import {initMessages, Messages, Message} from "./Message.js"; import {initMessages, Messages, Message} from "./Message.js";
import {initSingularitySFFlags, hasWallStreetSF}from "./NetscriptFunctions.js"; import {initSingularitySFFlags, hasWallStreetSF}from "./NetscriptFunctions.js";
import {WorkerScript, workerScripts, import {WorkerScript, workerScripts,
prestigeWorkerScripts} from "./NetscriptWorker.js"; prestigeWorkerScripts} from "./NetscriptWorker.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {AllServers, AddToAllServers, import {AllServers, AddToAllServers,
initForeignServers, Server, initForeignServers, Server,
prestigeAllServers, prestigeAllServers,
@ -239,13 +241,16 @@ function prestigeSourceFile() {
} }
Player.gang = null; Player.gang = null;
deleteGangDisplayContent();
Player.corporation = null; Player.corporation = null;
//BitNode 3: Corporatocracy //BitNode 3: Corporatocracy
if (Player.bitNodeN === 3) {Player.money = new Decimal(150e9);} if (Player.bitNodeN === 3) {
homeComp.messages.push("corporation-management-handbook.lit"); Player.money = new Decimal(150e9);
dialogBoxCreate("You received a copy of the Corporation Management Handbook on your home computer. " + homeComp.messages.push("corporation-management-handbook.lit");
"Read it if you need help getting started with Corporations!"); dialogBoxCreate("You received a copy of the Corporation Management Handbook on your home computer. " +
"Read it if you need help getting started with Corporations!");
}
//Gain int exp //Gain int exp
Player.gainIntelligenceExp(5); Player.gainIntelligenceExp(5);

@ -6,6 +6,7 @@ import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {loadFactions, Factions, import {loadFactions, Factions,
processPassiveFactionRepGain} from "./Faction.js"; processPassiveFactionRepGain} from "./Faction.js";
import {FconfSettings, loadFconf} from "./Fconf.js";
import {loadAllGangs, AllGangs} from "./Gang.js"; import {loadAllGangs, AllGangs} from "./Gang.js";
import {processAllHacknetNodeEarnings} from "./HacknetNode.js"; import {processAllHacknetNodeEarnings} from "./HacknetNode.js";
import {loadMessages, initMessages, Messages} from "./Message.js"; import {loadMessages, initMessages, Messages} from "./Message.js";
@ -40,6 +41,7 @@ function BitburnerSaveObject() {
this.MessagesSave = ""; this.MessagesSave = "";
this.StockMarketSave = ""; this.StockMarketSave = "";
this.SettingsSave = ""; this.SettingsSave = "";
this.FconfSettingsSave = "";
this.VersionSave = ""; this.VersionSave = "";
this.AllGangsSave = ""; this.AllGangsSave = "";
} }
@ -68,6 +70,7 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
this.MessagesSave = JSON.stringify(Messages); this.MessagesSave = JSON.stringify(Messages);
this.StockMarketSave = JSON.stringify(StockMarket); this.StockMarketSave = JSON.stringify(StockMarket);
this.SettingsSave = JSON.stringify(Settings); this.SettingsSave = JSON.stringify(Settings);
this.FconfSettingsSave = JSON.stringify(FconfSettings);
this.VersionSave = JSON.stringify(CONSTANTS.Version); this.VersionSave = JSON.stringify(CONSTANTS.Version);
if (Player.bitNodeN == 2 && Player.inGang()) { if (Player.bitNodeN == 2 && Player.inGang()) {
this.AllGangsSave = JSON.stringify(AllGangs); this.AllGangsSave = JSON.stringify(AllGangs);
@ -170,6 +173,13 @@ function loadGame(saveString) {
} else { } else {
initSettings(); initSettings();
} }
if (saveObj.hasOwnProperty("FconfSettingsSave")) {
try {
loadFconf(saveObj.FconfSettingsSave);
} catch(e) {
console.log("ERROR: Failed to parse .fconf Settings.");
}
}
if (saveObj.hasOwnProperty("VersionSave")) { if (saveObj.hasOwnProperty("VersionSave")) {
try { try {
var ver = JSON.parse(saveObj.VersionSave, Reviver); var ver = JSON.parse(saveObj.VersionSave, Reviver);
@ -378,6 +388,13 @@ function loadImportedGame(saveObj, saveString) {
} else { } else {
initSettings(); initSettings();
} }
if (saveObj.hasOwnProperty("FconfSettingsSave")) {
try {
loadFconf(saveObj.FconfSettingsSave);
} catch(e) {
console.log("ERROR: Failed to load .fconf settings when importing");
}
}
if (saveObj.hasOwnProperty("VersionSave")) { if (saveObj.hasOwnProperty("VersionSave")) {
try { try {
var ver = JSON.parse(saveObj.VersionSave, Reviver); var ver = JSON.parse(saveObj.VersionSave, Reviver);

@ -15,6 +15,7 @@ require("brace/ext/language_tools");
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 {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,6 +26,7 @@ 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} from "./Terminal.js";
import {TextFile} from "./TextFile.js";
import {parse, Node} from "../utils/acorn.js"; import {parse, Node} from "../utils/acorn.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
@ -206,7 +208,8 @@ function scriptEditorInit() {
//Updates RAM usage in script //Updates RAM usage in script
function updateScriptEditorContent() { function updateScriptEditorContent() {
if (scriptEditorRamCheck == null || !scriptEditorRamCheck.checked) { var filename = document.getElementById("script-editor-filename").value;
if (scriptEditorRamCheck == null || !scriptEditorRamCheck.checked || !filename.endsWith(".script")) {
scriptEditorRamText.innerText = "N/A"; scriptEditorRamText.innerText = "N/A";
return; return;
} }
@ -234,13 +237,13 @@ $(document).keydown(function(e) {
function saveAndCloseScriptEditor() { function saveAndCloseScriptEditor() {
var filename = document.getElementById("script-editor-filename").value; var filename = document.getElementById("script-editor-filename").value;
var editor = ace.edit('javascript-editor');
var code = editor.getValue();
if (iTutorialIsRunning && currITutorialStep == iTutorialSteps.TerminalTypeScript) { if (iTutorialIsRunning && currITutorialStep == iTutorialSteps.TerminalTypeScript) {
if (filename != "foodnstuff") { if (filename != "foodnstuff.script") {
dialogBoxCreate("Leave the script name as 'foodnstuff'!"); dialogBoxCreate("Leave the script name as 'foodnstuff'!");
return; return;
} }
var editor = ace.edit('javascript-editor');
var code = editor.getValue();
code = code.replace(/\s/g, ""); code = code.replace(/\s/g, "");
if (code.indexOf("while(true){hack('foodnstuff');}") == -1) { if (code.indexOf("while(true){hack('foodnstuff');}") == -1) {
dialogBoxCreate("Please copy and paste the code from the tutorial!"); dialogBoxCreate("Please copy and paste the code from the tutorial!");
@ -259,28 +262,50 @@ function saveAndCloseScriptEditor() {
return; return;
} }
filename += ".script"; var s = Player.getCurrentServer();
if (filename === ".fconf") {
//If the current script already exists on the server, overwrite it try {
for (var i = 0; i < Player.getCurrentServer().scripts.length; i++) { parseFconfSettings(code);
if (filename == Player.getCurrentServer().scripts[i].filename) { } catch(e) {
Player.getCurrentServer().scripts[i].saveScript(); dialogBoxCreate("Invalid .fconf file");
Engine.loadTerminalContent();
return; return;
} }
} } else if (filename.endsWith(".script")) {
//If the current script already exists on the server, overwrite it
for (var i = 0; i < s.scripts.length; i++) {
if (filename == s.scripts[i].filename) {
s.scripts[i].saveScript();
Engine.loadTerminalContent();
return;
}
}
//If the current script does NOT exist, create a new one //If the current script does NOT exist, create a new one
var script = new Script(); var script = new Script();
script.saveScript(); script.saveScript();
Player.getCurrentServer().scripts.push(script); s.scripts.push(script);
} else if (filename.endsWith(".txt")) {
for (var i = 0; i < s.textFiles.length; ++i) {
if (s.textFiles[i].fn === filename) {
s.textFiles[i].write(code);
Engine.loadTerminalContent();
return;
}
}
var textFile = new TextFile(filename, code);
s.textFiles.push(textFile);
} else {
dialogBoxCreate("Invalid filename. Must be either a script (.script) or " +
" or text file (.txt)")
return;
}
Engine.loadTerminalContent(); Engine.loadTerminalContent();
} }
//Checks that the string contains only valid characters for a filename, which are alphanumeric, //Checks that the string contains only valid characters for a filename, which are alphanumeric,
// underscores and hyphens // underscores, hyphens, and dots
function checkValidFilename(filename) { function checkValidFilename(filename) {
var regex = /^[a-zA-Z0-9_-]+$/; var regex = /^[.a-zA-Z0-9_-]+$/;
if (filename.match(regex)) { if (filename.match(regex)) {
return true; return true;
@ -303,7 +328,7 @@ Script.prototype.saveScript = function() {
var code = editor.getValue(); var code = editor.getValue();
this.code = code.replace(/^\s+|\s+$/g, ''); this.code = code.replace(/^\s+|\s+$/g, '');
var filename = document.getElementById("script-editor-filename").value + ".script"; var filename = document.getElementById("script-editor-filename").value;
this.filename = filename; this.filename = filename;
//Server //Server
@ -417,7 +442,7 @@ function calculateRamUsage(codeCopy) {
} }
Script.prototype.download = function() { Script.prototype.download = function() {
var filename = this.filename; var filename = this.filename + ".js";
var file = new Blob([this.code], {type: 'text/plain'}); var file = new Blob([this.code], {type: 'text/plain'});
if (window.navigator.msSaveOrOpenBlob) {// IE10+ if (window.navigator.msSaveOrOpenBlob) {// IE10+
window.navigator.msSaveOrOpenBlob(file, filename); window.navigator.msSaveOrOpenBlob(file, filename);
@ -425,7 +450,7 @@ Script.prototype.download = function() {
var a = document.createElement("a"), var a = document.createElement("a"),
url = URL.createObjectURL(file); url = URL.createObjectURL(file);
a.href = url; a.href = url;
a.download = this.filename; a.download = filename;
document.body.appendChild(a); document.body.appendChild(a);
a.click(); a.click();
setTimeout(function() { setTimeout(function() {
@ -675,18 +700,6 @@ function AllServersMap(arr=false, filterOwned=false) {
} }
} }
AllServersMap.prototype.printConsole = function() {
for (var ip in this) {
if (this.hasOwnProperty(ip)) {
var serv = AllServers[ip];
if (serv == null) {
console.log("Warning null server encountered with ip: " + ip);
continue;
}
}
}
}
AllServersMap.prototype.toJSON = function() { AllServersMap.prototype.toJSON = function() {
return Generic_toJSON("AllServersMap", this); return Generic_toJSON("AllServersMap", this);
} }

@ -7,6 +7,8 @@ import {Programs} from "./CreateProgram.js";
import {executeDarkwebTerminalCommand, import {executeDarkwebTerminalCommand,
checkIfConnectedToDarkweb} from "./DarkWeb.js"; checkIfConnectedToDarkweb} from "./DarkWeb.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {FconfSettings, parseFconfSettings,
createFconf} from "./Fconf.js";
import {TerminalHelpText, HelpTexts} from "./HelpText.js"; import {TerminalHelpText, HelpTexts} from "./HelpText.js";
import {iTutorialNextStep, iTutorialSteps, import {iTutorialNextStep, iTutorialSteps,
iTutorialIsRunning, iTutorialIsRunning,
@ -37,6 +39,9 @@ import {yesNoBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetYesButton,
yesNoBoxGetNoButton, yesNoBoxClose} from "../utils/YesNoBox.js"; yesNoBoxGetNoButton, yesNoBoxClose} from "../utils/YesNoBox.js";
import * as JSZip from 'jszip';
import * as FileSaver from 'file-saver';
/* Write text to terminal */ /* Write text to terminal */
//If replace is true then spaces are replaced with "&nbsp;" //If replace is true then spaces are replaced with "&nbsp;"
function post(input) { function post(input) {
@ -65,6 +70,30 @@ function postNetburnerText() {
post("Bitburner v" + CONSTANTS.Version); post("Bitburner v" + CONSTANTS.Version);
} }
//Key Codes
let KEY = {
TAB: 9,
ENTER: 13,
CTRL: 17,
UPARROW: 38,
DOWNARROW: 40,
A: 65,
B: 66,
C: 67,
D: 68,
E: 69,
F: 70,
H: 72,
K: 75,
L: 76,
M: 77,
N: 78,
P: 80,
U: 85,
W: 87,
}
//Defines key commands in terminal //Defines key commands in terminal
$(document).keydown(function(event) { $(document).keydown(function(event) {
//Terminal //Terminal
@ -72,8 +101,7 @@ $(document).keydown(function(event) {
var terminalInput = document.getElementById("terminal-input-text-box"); var terminalInput = document.getElementById("terminal-input-text-box");
if (terminalInput != null && !event.ctrlKey && !event.shiftKey) {terminalInput.focus();} if (terminalInput != null && !event.ctrlKey && !event.shiftKey) {terminalInput.focus();}
//Enter if (event.keyCode === KEY.ENTER) {
if (event.keyCode == 13) {
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) {
@ -84,15 +112,30 @@ $(document).keydown(function(event) {
} }
} }
//Ctrl + c when an "Action" is in progress if (event.keyCode === KEY.C && event.ctrlKey) {
if (event.keyCode == 67 && event.ctrlKey && Engine._actionInProgress) { if (Engine._actionInProgress) {
post("Cancelling..."); //Cancel action
Engine._actionInProgress = false; post("Cancelling...");
Terminal.finishAction(true); Engine._actionInProgress = false;
Terminal.finishAction(true);
} else if (FconfSettings.ENABLE_BASH_HOTKEYS) {
//Dont prevent default so it still copies
Terminal.resetTerminalInput(); //Clear Terminal
}
} }
//Up key to cycle through past commands if (event.keyCode === KEY.L && event.ctrlKey) {
if (event.keyCode == 38) { event.preventDefault();
Terminal.executeCommand("clear"); //Clear screen
}
//Ctrl p same as up arrow
//Ctrl n same as down arrow
if (event.keyCode === KEY.UPARROW ||
(FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.P && event.ctrlKey)) {
if (FconfSettings.ENABLE_BASH_HOTKEYS) {event.preventDefault();}
//Cycle through past commands
if (terminalInput == null) {return;} if (terminalInput == null) {return;}
var i = Terminal.commandHistoryIndex; var i = Terminal.commandHistoryIndex;
var len = Terminal.commandHistory.length; var len = Terminal.commandHistory.length;
@ -110,8 +153,10 @@ $(document).keydown(function(event) {
setTimeout(function(){terminalInput.selectionStart = terminalInput.selectionEnd = 10000; }, 0); setTimeout(function(){terminalInput.selectionStart = terminalInput.selectionEnd = 10000; }, 0);
} }
//Down key if (event.keyCode === KEY.DOWNARROW ||
if (event.keyCode == 40) { (FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.M && event.ctrlKey)) {
if (FconfSettings.ENABLE_BASH_HOTKEYS) {event.preventDefault();}
//Cycle through past commands
if (terminalInput == null) {return;} if (terminalInput == null) {return;}
var i = Terminal.commandHistoryIndex; var i = Terminal.commandHistoryIndex;
var len = Terminal.commandHistory.length; var len = Terminal.commandHistory.length;
@ -132,8 +177,8 @@ $(document).keydown(function(event) {
} }
} }
//Tab (autocomplete) if (event.keyCode === KEY.TAB) {
if (event.keyCode == 9) { //Autocomplete
if (terminalInput == null) {return;} if (terminalInput == null) {return;}
var input = terminalInput.value; var input = terminalInput.value;
if (input == "") {return;} if (input == "") {return;}
@ -163,6 +208,52 @@ $(document).keydown(function(event) {
tabCompletion(command, arg, allPos); tabCompletion(command, arg, allPos);
} }
//Extra Bash Emulation Hotkeys, must be enabled through .fconf
if (FconfSettings.ENABLE_BASH_HOTKEYS) {
if (event.keyCode === KEY.A && event.ctrlKey) {
event.preventDefault();
Terminal.moveTextCursor("home");
}
if (event.keyCode === KEY.E && event.ctrlKey) {
event.preventDefault();
Terminal.moveTextCursor("end");
}
if (event.keyCode === KEY.B && event.ctrlKey) {
event.preventDefault();
Terminal.moveTextCursor("prevchar");
}
if (event.keyCode === KEY.B && event.altKey) {
event.preventDefault();
Terminal.moveTextCursor("prevword");
}
if (event.keyCode === KEY.F && event.ctrlKey) {
event.preventDefault();
Terminal.moveTextCursor("nextchar");
}
if (event.keyCode === KEY.F && event.altKey) {
event.preventDefault();
Terminal.moveTextCursor("nextword");
}
if ((event.keyCode === KEY.H || event.keyCode === KEY.D) && event.ctrlKey) {
Terminal.modifyInput("backspace");
event.preventDefault();
}
//TODO AFTER THIS:
//alt + d deletes word after cursor
//^w deletes word before cursor
//^k clears line after cursor
//^u clears line before cursor
}
} }
}); });
@ -344,8 +435,7 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
return allPos; return allPos;
} }
if (input.startsWith("kill ") || input.startsWith("nano ") || if (input.startsWith("kill ") || input.startsWith("tail ") ||
input.startsWith("tail ") ||
input.startsWith("mem ") || input.startsWith("check ")) { input.startsWith("mem ") || input.startsWith("check ")) {
//All Scripts //All Scripts
for (var i = 0; i < currServ.scripts.length; ++i) { for (var i = 0; i < currServ.scripts.length; ++i) {
@ -354,6 +444,18 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
return allPos; return allPos;
} }
if (input.startsWith("nano ")) {
//Scripts and text files and .fconf
for (var i = 0; i < currServ.scripts.length; ++i) {
allPos.push(currServ.scripts[i].filename);
}
for (var i = 0; i < currServ.textFiles.length; ++i) {
allPos.push(currServ.textFiles[i].fn);
}
allPos.push(".fconf");
return allPos;
}
if (input.startsWith("rm ")) { if (input.startsWith("rm ")) {
for (var i = 0; i < currServ.scripts.length; ++i) { for (var i = 0; i < currServ.scripts.length; ++i) {
allPos.push(currServ.scripts[i].filename); allPos.push(currServ.scripts[i].filename);
@ -420,23 +522,113 @@ let Terminal = {
commandHistory: [], commandHistory: [],
commandHistoryIndex: 0, commandHistoryIndex: 0,
finishAction: function(cancelled = false) {
if (Terminal.hackFlag) {
Terminal.finishHack(cancelled);
} else if (Terminal.analyzeFlag) {
Terminal.finishAnalyze(cancelled);
}
},
resetTerminalInput: function() { resetTerminalInput: function() {
document.getElementById("terminal-input-td").innerHTML = document.getElementById("terminal-input-td").innerHTML =
"<div id='terminal-input-header'>[" + Player.getCurrentServer().hostname + " ~]" + "$ </div>" + "<div id='terminal-input-header'>[" + Player.getCurrentServer().hostname + " ~]" + "$ </div>" +
'<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>'; '<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>';
var hdr = document.getElementById("terminal-input-header"); var hdr = document.getElementById("terminal-input-header");
hdr.style.display = "inline"; hdr.style.display = "inline";
//var lineWidth = document.getElementById("terminal-input-td").offsetWidth; },
//var width = lineWidth - hdr.offsetWidth - 10;
//document.getElementById("terminal-input-text-box").style.width = width + "px"; modifyInput: function(mod) {
try {
var terminalInput = document.getElementById("terminal-input-text-box");
if (terminalInput == null) {return;}
terminalInput.focus();
var inputLength = terminalInput.value.length;
var start = terminalInput.selectionStart;
var end = terminalInput.selectionEnd;
var inputText = terminalInput.value;
switch(mod.toLowerCase()) {
case "backspace":
if (start > 0 && start <= inputLength+1) {
terminalInput.value = inputText.substr(0, start-1) + inputText.substr(start);
}
break;
case "deletewordbefore": //Delete rest of word before the cursor
for (var delStart = start-1; delStart > 0; --delStart) {
if (inputText.charAt(delStart) === " ") {
terminalInput.value = inputText.substr(0, delStart) + inputText.substr(start);
return;
}
}
break;
case "deletewordafter": //Delete rest of word after the cursor
for (var delStart = start+1; delStart <= text.length+1; ++delStart) {
if (inputText.charAt(delStart) === " ") {
terminalInput.value = inputText.substr(0, start) + inputText.substr(delStart);
return;
}
}
break;
case "clearafter": //Deletes everything after cursor
break;
case "clearbefore:": //Deleetes everything before cursor
break;
}
} catch(e) {
console.log("Exception in Terminal.modifyInput: " + e);
}
},
moveTextCursor: function(loc) {
try {
var terminalInput = document.getElementById("terminal-input-text-box");
if (terminalInput == null) {return;}
terminalInput.focus();
var inputLength = terminalInput.value.length;
var start = terminalInput.selectionStart;
var end = terminalInput.selectionEnd;
switch(loc.toLowerCase()) {
case "home":
terminalInput.setSelectionRange(0,0);
break;
case "end":
terminalInput.setSelectionRange(inputLength, inputLength);
break;
case "prevchar":
if (start > 0) {terminalInput.setSelectionRange(start-1, start-1);}
break;
case "prevword":
for (var i = start-2; i >= 0; --i) {
if (terminalInput.value.charAt(i) === " ") {
terminalInput.setSelectionRange(i+1, i+1);
return;
}
}
terminalInput.setSelectionRange(0, 0);
break;
case "nextchar":
terminalInput.setSelectionRange(start+1, start+1);
break;
case "nextword":
for (var i = start+1; i <= inputLength; ++i) {
if (terminalInput.value.charAt(i) === " ") {
terminalInput.setSelectionRange(i, i);
return;
}
}
terminalInput.setSelectionRange(inputLength, inputLength);
break;
default:
console.log("WARNING: Invalid loc argument in Terminal.moveTextCursor()");
break;
}
} catch(e) {
console.log("Exception in Terminal.moveTextCursor: " + e);
}
},
finishAction: function(cancelled = false) {
if (Terminal.hackFlag) {
Terminal.finishHack(cancelled);
} else if (Terminal.analyzeFlag) {
Terminal.finishAnalyze(cancelled);
}
}, },
//Complete the hack/analyze command //Complete the hack/analyze command
@ -484,7 +676,6 @@ let Terminal = {
$("#hack-progress-bar").attr('id', "old-hack-progress-bar"); $("#hack-progress-bar").attr('id', "old-hack-progress-bar");
$("#hack-progress").attr('id', "old-hack-progress"); $("#hack-progress").attr('id', "old-hack-progress");
Terminal.resetTerminalInput(); Terminal.resetTerminalInput();
//document.getElementById("terminal-input-td").innerHTML = '$ <input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>';
$('input[class=terminal-input]').prop('disabled', false); $('input[class=terminal-input]').prop('disabled', false);
Terminal.hackFlag = false; Terminal.hackFlag = false;
@ -540,7 +731,6 @@ let Terminal = {
$("#hack-progress-bar").attr('id', "old-hack-progress-bar"); $("#hack-progress-bar").attr('id', "old-hack-progress-bar");
$("#hack-progress").attr('id', "old-hack-progress"); $("#hack-progress").attr('id', "old-hack-progress");
Terminal.resetTerminalInput(); Terminal.resetTerminalInput();
//document.getElementById("terminal-input-td").innerHTML = '$ <input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>';
$('input[class=terminal-input]').prop('disabled', false); $('input[class=terminal-input]').prop('disabled', false);
}, },
@ -835,13 +1025,45 @@ let Terminal = {
return; return;
} }
var fn = commandArray[1]; var fn = commandArray[1];
if (fn.endsWith(".script")) { if (fn === "*" || fn === "*.script" || fn === "*.txt") {
//Download all scripts as a zip
var zip = new JSZip();
if (fn === "*" || fn === "*.script") {
for (var i = 0; i < s.scripts.length; ++i) {
var file = new Blob([s.scripts[i].code], {type:"text/plain"});
zip.file(s.scripts[i].filename + ".js", file);
}
}
if (fn === "*" || fn === "*.txt") {
for (var i = 0; i < s.textFiles.length; ++i) {
var file = new Blob([s.textFiles[i].text], {type:"text/plain"});
zip.file(s.textFiles[i].fn, file);
}
}
var filename;
switch (fn) {
case "*.script":
filename = "bitburnerScripts.zip"; break;
case "*.txt":
filename = "bitburnerTexts.zip"; break;
default:
filename = "bitburnerFiles.zip"; break;
}
zip.generateAsync({type:"blob"}).then(function(content) {
FileSaver.saveAs(content, filename);
});
return;
} else if (fn.endsWith(".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) {
return s.scripts[i].download(); return s.scripts[i].download();
} }
} }
} else if (fn.endsWith(".txt")) { } else if (fn.endsWith(".txt")) {
//Download a single text file
var txtFile = getTextFile(fn, s); var txtFile = getTextFile(fn, s);
if (txtFile !== null) { if (txtFile !== null) {
return txtFile.download(); return txtFile.download();
@ -984,23 +1206,28 @@ let Terminal = {
} }
var filename = commandArray[1]; var filename = commandArray[1];
if (filename === ".fconf") {
//Can only edit script files var text = createFconf();
if (filename.endsWith(".script") == false) { Engine.loadScriptEditorContent(filename, text);
post("Error: Only .script files are editable with nano (filename must end with .script)"); return; return;
} } else if (filename.endsWith(".script")) {
for (var i = 0; i < s.scripts.length; i++) {
//Script name is the filename without the .script at the end if (filename == s.scripts[i].filename) {
var scriptname = filename.substr(0, filename.indexOf(".script")); Engine.loadScriptEditorContent(filename, s.scripts[i].code);
return;
//Check if the script already exists }
for (var i = 0; i < Player.getCurrentServer().scripts.length; i++) { }
if (filename == Player.getCurrentServer().scripts[i].filename) { } else if (filename.endsWith(".txt")) {
Engine.loadScriptEditorContent(scriptname, Player.getCurrentServer().scripts[i].code); for (var i = 0; i < s.textFiles.length; ++i) {
return; if (filename === s.textFiles[i].fn) {
} Engine.loadScriptEditorContent(filename, s.textFiles[i].text);
} return;
Engine.loadScriptEditorContent(scriptname, ""); }
}
} else {
post("Error: Invalid file. Only scripts (.script), text files (.txt), or .fconf can be edited with nano"); return;
}
Engine.loadScriptEditorContent(filename);
break; break;
case "ps": case "ps":
if (commandArray.length != 1) { if (commandArray.length != 1) {

@ -23,6 +23,7 @@ import {Programs, displayCreateProgramContent,
import {displayFactionContent, joinFaction, import {displayFactionContent, joinFaction,
processPassiveFactionRepGain, Factions, processPassiveFactionRepGain, Factions,
inviteToFaction, initFactions} from "./Faction.js"; inviteToFaction, initFactions} from "./Faction.js";
import {FconfSettings} from "./Fconf.js";
import {Locations, displayLocationContent, import {Locations, displayLocationContent,
initLocationButtons} from "./Location.js"; initLocationButtons} from "./Location.js";
import {displayGangContent, updateGangContent, import {displayGangContent, updateGangContent,
@ -55,8 +56,6 @@ import {StockMarket, StockSymbols,
displayStockMarketContent} from "./StockMarket.js"; displayStockMarketContent} from "./StockMarket.js";
import {Terminal, postNetburnerText, post} from "./Terminal.js"; import {Terminal, postNetburnerText, post} from "./Terminal.js";
/* Shortcuts to navigate through the game /* Shortcuts to navigate through the game
* Alt-t - Terminal * Alt-t - Terminal
* Alt-c - Character * Alt-c - Character
@ -102,6 +101,10 @@ $(document).keydown(function(e) {
e.preventDefault(); e.preventDefault();
Engine.loadCreateProgramContent(); Engine.loadCreateProgramContent();
} else if (e.keyCode == 70 && e.altKey) { } else if (e.keyCode == 70 && e.altKey) {
//Overriden by Fconf
if (Engine.currentPage === Engine.Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) {
return;
}
e.preventDefault(); e.preventDefault();
Engine.loadFactionsContent(); Engine.loadFactionsContent();
} else if (e.keyCode == 65 && e.altKey) { } else if (e.keyCode == 65 && e.altKey) {
@ -715,48 +718,82 @@ let Engine = {
}, },
displayAugmentationsContent: function() { displayAugmentationsContent: function() {
//Purchased/queued augmentations removeChildrenFromElement(Engine.Display.augmentationsContent);
var queuedAugmentationsList = document.getElementById("queued-augmentations-list"); Engine.Display.augmentationsContent.appendChild(createElement("h1", {
innerText:"Purchased Augmentations"
}));
while (queuedAugmentationsList.firstChild) { Engine.Display.augmentationsContent.appendChild(createElement("pre", {
queuedAugmentationsList.removeChild(queuedAugmentationsList.firstChild); width:"70%", whiteSpace:"pre-wrap", display:"block",
} innerText:"Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to install them.\n" +
"WARNING: Installing your Augmentations resets most of your progress, including:\n\n" +
"Stats/Skill levels and Experience\n" +
"Money\n" +
"Scripts on every computer but your home computer\n" +
"Purchased servers\n" +
"Hacknet Nodes\n" +
"Faction/Company reputation\n" +
"Stocks\n\n" +
"Installing Augmentations lets you start over with the perks and benefits granted by all " +
"of the Augmentations you have ever installed. Also, you will keep any scripts and RAM/Core upgrades " +
"on your home computer (but you will lose all programs besides NUKE.exe)."
}));
//Purchased/queued augmentations
var queuedAugmentationsList = createElement("ul", {
id:"queued-augmentations-list"
});
for (var i = 0; i < Player.queuedAugmentations.length; ++i) { for (var i = 0; i < Player.queuedAugmentations.length; ++i) {
var augName = Player.queuedAugmentations[i].name; var augName = Player.queuedAugmentations[i].name;
var aug = Augmentations[augName]; var aug = Augmentations[augName];
var item = document.createElement("li"); var item = createElement("li", {class:"installed-augmentation"});
var hElem = document.createElement("h2"); var displayName = augName;
var pElem = document.createElement("p"); if (augName === AugmentationNames.NeuroFluxGovernor) {
displayName += " - Level " + (Player.queuedAugmentations[i].level);
item.setAttribute("class", "installed-augmentation");
hElem.innerHTML = augName;
if (augName == AugmentationNames.NeuroFluxGovernor) {
hElem.innerHTML += " - Level " + (Player.queuedAugmentations[i].level);
} }
pElem.innerHTML = aug.info; item.appendChild(createElement("h2", {innerHTML:displayName}));
item.appendChild(createElement("p", {innerHTML:aug.info}));
item.appendChild(hElem);
item.appendChild(pElem);
queuedAugmentationsList.appendChild(item); queuedAugmentationsList.appendChild(item);
} }
Engine.Display.augmentationsContent.appendChild(queuedAugmentationsList);
//Install Augmentations button //Install Augmentations button
var installButton = clearEventListeners("install-augmentations-button"); Engine.Display.augmentationsContent.appendChild(createElement("a", {
installButton.addEventListener("click", function() { class:"a-link-button", innerText:"Install Augmentations",
installAugmentations(); tooltip:"'I never asked for this'",
return false; clickListener:()=>{
installAugmentations();
return false;
}
}));
//Backup button
Engine.Display.augmentationsContent.appendChild(createElement("a", {
class:"a-link-button flashing-button", innerText:"Backup Save (Export)",
tooltip:"It's always a good idea to backup/export your save!",
clickListener:()=>{
saveObject.exportGame();
return false;
}
}));
//Installed augmentations list
Engine.Display.augmentationsContent.appendChild(createElement("h1", {
innerText:"Installed Augmentations"
}));
Engine.Display.augmentationsContent.appendChild(createElement("p", {
width:"70%", whiteSpace:"pre-wrap",
innerText:"List of all Augmentations (including Source Files) that have been " +
"installed. You have gained the effects of these Augmentations"
}));
var augmentationsList = createElement("ul", {
id:"augmentations-list"
}); });
//Installed augmentations
var augmentationsList = document.getElementById("augmentations-list");
while (augmentationsList.firstChild) {
augmentationsList.removeChild(augmentationsList.firstChild);
}
//Source Files - Temporary...Will probably put in a separate pane Later //Source Files - Temporary...Will probably put in a separate pane Later
for (var i = 0; i < Player.sourceFiles.length; ++i) { for (var i = 0; i < Player.sourceFiles.length; ++i) {
var srcFileKey = "SourceFile" + Player.sourceFiles[i].n; var srcFileKey = "SourceFile" + Player.sourceFiles[i].n;
@ -765,17 +802,13 @@ let Engine = {
console.log("ERROR: Invalid source file number: " + Player.sourceFiles[i].n); console.log("ERROR: Invalid source file number: " + Player.sourceFiles[i].n);
continue; continue;
} }
var item = document.createElement("li"); var item = createElement("li", {class:"installed-augmentation", });
var hElem = document.createElement("h2"); item.appendChild(createElement("h2", {
var pElem = document.createElement("p"); innerHTML:sourceFileObject.name + "<br>" + "Level " + (Player.sourceFiles[i].lvl) + " / 3",
}));
item.setAttribute("class", "installed-augmentation"); item.appendChild(createElement("p", {
hElem.innerHTML = sourceFileObject.name + "<br>"; innerHTML:sourceFileObject.info,
hElem.innerHTML += "Level " + (Player.sourceFiles[i].lvl) + " / 3"; }));
pElem.innerHTML = sourceFileObject.info;
item.appendChild(hElem);
item.appendChild(pElem);
augmentationsList.appendChild(item); augmentationsList.appendChild(item);
} }
@ -784,22 +817,17 @@ let Engine = {
var augName = Player.augmentations[i].name; var augName = Player.augmentations[i].name;
var aug = Augmentations[augName]; var aug = Augmentations[augName];
var item = document.createElement("li"); var item = createElement("li", {class:"installed-augmentation"});
var hElem = document.createElement("h2"); var displayName = augName;
var pElem = document.createElement("p"); if (augName === AugmentationNames.NeuroFluxGovernor) {
displayName += " - Level " + (Player.augmentations[i].level);
item.setAttribute("class", "installed-augmentation");
hElem.innerHTML = augName;
if (augName == AugmentationNames.NeuroFluxGovernor) {
hElem.innerHTML += " - Level " + (Player.augmentations[i].level);
} }
pElem.innerHTML = aug.info; item.appendChild(createElement("h2", {innerHTML:displayName}));
item.appendChild(createElement("p", {innerHTML:aug.info}));
item.appendChild(hElem);
item.appendChild(pElem);
augmentationsList.appendChild(item); augmentationsList.appendChild(item);
} }
Engine.Display.augmentationsContent.appendChild(augmentationsList);
}, },
displayTutorialContent: function() { displayTutorialContent: function() {
@ -904,7 +932,9 @@ let Engine = {
//Corporation //Corporation
if (Player.corporation instanceof Corporation) { if (Player.corporation instanceof Corporation) {
Player.corporation.process(numCycles); //Stores cycles in a "buffer". Processed separately using Engine Counters
//This is to avoid constant DOM redraws when Corporation is catching up
Player.corporation.storeCycles(numCycles);
} }
//Counters //Counters
@ -937,6 +967,7 @@ let Engine = {
messages: 150, messages: 150,
stockTick: 30, //Update stock prices stockTick: 30, //Update stock prices
sCr: 1500, sCr: 1500,
corpProcess: 5,
}, },
decrementAllCounters: function(numCycles = 1) { decrementAllCounters: function(numCycles = 1) {
@ -1059,6 +1090,13 @@ let Engine = {
} }
Engine.Counters.sCr = 1500; Engine.Counters.sCr = 1500;
} }
if (Engine.Counters.corpProcess <= 0) {
if (Player.corporation instanceof Corporation) {
Player.corporation.process();
}
Engine.Counters.corpProcess = 5;
}
}, },
/* Calculates the hack progress for a manual (non-scripted) hack and updates the progress bar/time accordingly */ /* Calculates the hack progress for a manual (non-scripted) hack and updates the progress bar/time accordingly */

@ -83,6 +83,7 @@ function createElement(type, params={}) {
if (params.border) {el.style.border = params.border;} if (params.border) {el.style.border = params.border;}
if (params.float) {el.style.cssFloat = params.float;} if (params.float) {el.style.cssFloat = params.float;}
if (params.fontSize) {el.style.fontSize = params.fontSize;} if (params.fontSize) {el.style.fontSize = params.fontSize;}
if (params.whiteSpace) {el.style.whiteSpace = params.whiteSpace;}
if (params.width) {el.style.width = params.width;} if (params.width) {el.style.width = params.width;}
if (params.backgroundColor) { if (params.backgroundColor) {
el.style.backgroundColor = params.backgroundColor el.style.backgroundColor = params.backgroundColor

@ -25,13 +25,14 @@ function infiltrationSetText(txt) {
//ram argument is in GB //ram argument is in GB
function infiltrationBoxCreate(inst) { function infiltrationBoxCreate(inst) {
//Gain exp //Gain exp
Player.gainHackingExp(inst.hackingExpGained); var expMultiplier = 2 * inst.clearanceLevel / inst.maxClearanceLevel;
Player.gainStrengthExp(inst.strExpGained); Player.gainHackingExp(inst.hackingExpGained * expMultiplier);
Player.gainDefenseExp(inst.defExpGained); Player.gainStrengthExp(inst.strExpGained * expMultiplier);
Player.gainDexterityExp(inst.dexExpGained); Player.gainDefenseExp(inst.defExpGained * expMultiplier);
Player.gainAgilityExp(inst.agiExpGained); Player.gainDexterityExp(inst.dexExpGained * expMultiplier);
Player.gainCharismaExp(inst.chaExpGained); Player.gainAgilityExp(inst.agiExpGained * expMultiplier);
Player.gainIntelligenceExp(inst.intExpGained); Player.gainCharismaExp(inst.chaExpGained * expMultiplier);
Player.gainIntelligenceExp(inst.intExpGained * expMultiplier);
var totalValue = 0; var totalValue = 0;
for (var i = 0; i < inst.secretsStolen.length; ++i) { for (var i = 0; i < inst.secretsStolen.length; ++i) {