mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-26 16:07:33 +01:00
Merge branch 'dev' into dev
This commit is contained in:
commit
224463e6dd
31
.github/workflows/deploy.yml
vendored
31
.github/workflows/deploy.yml
vendored
@ -1,31 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Test
|
||||
run: npm run test
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: .
|
25
.github/workflows/test.yml
vendored
25
.github/workflows/test.yml
vendored
@ -1,25 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
test:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Test
|
||||
run: npm run test
|
@ -78,6 +78,10 @@
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
.menu-header {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#hacking-menu-header-li,
|
||||
#character-menu-header-li,
|
||||
#world-menu-header-li,
|
||||
@ -129,7 +133,5 @@
|
||||
|
||||
/* Slide down transition */
|
||||
.mainmenu-accordion-panel {
|
||||
max-height: 0;
|
||||
opacity: 1;
|
||||
transition: max-height 0.2s ease-out;
|
||||
}
|
||||
|
@ -12,6 +12,11 @@
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#generic-react-container {
|
||||
position: fixed;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* Character Info */
|
||||
#character-container {
|
||||
padding-top: 10px;
|
||||
|
@ -113,6 +113,10 @@ a:visited {
|
||||
color: #fff;
|
||||
border-radius: 2px;
|
||||
padding: 1px 3px;
|
||||
font-size: $defaultFontSize * 0.625;
|
||||
top: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.notification-off {
|
||||
@ -120,6 +124,21 @@ a:visited {
|
||||
color: #333;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
display: "none";
|
||||
}
|
||||
|
||||
.notification {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.notification .badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 2px;
|
||||
background: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* help tip. Question mark that opens popup with info/details */
|
||||
|
4
dist/engine.bundle.js
vendored
4
dist/engine.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/engineStyle.bundle.js
vendored
2
dist/engineStyle.bundle.js
vendored
@ -1,2 +1,2 @@
|
||||
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],a=0,s=[];a<f.length;a++)i=f[a],Object.prototype.hasOwnProperty.call(u,i)&&u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(p&&p(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={2:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var p=c;r.push([905,0]),o()}({905:function(n,t,o){"use strict";o.r(t);o(906),o(908),o(910),o(912),o(914),o(916),o(918),o(920),o(922),o(924),o(926),o(928),o(930),o(932),o(934),o(936),o(938),o(940),o(942),o(944),o(946),o(948),o(950),o(952),o(954),o(956),o(958),o(960),o(962),o(964),o(966),o(968),o(970)},908:function(n,t,o){},910:function(n,t,o){},912:function(n,t,o){},914:function(n,t,o){},916:function(n,t,o){},918:function(n,t,o){},920:function(n,t,o){},922:function(n,t,o){},924:function(n,t,o){},926:function(n,t,o){},928:function(n,t,o){},930:function(n,t,o){},932:function(n,t,o){},934:function(n,t,o){},936:function(n,t,o){},938:function(n,t,o){},940:function(n,t,o){},942:function(n,t,o){},944:function(n,t,o){},946:function(n,t,o){},948:function(n,t,o){},950:function(n,t,o){},952:function(n,t,o){},954:function(n,t,o){},956:function(n,t,o){},958:function(n,t,o){},960:function(n,t,o){},962:function(n,t,o){},964:function(n,t,o){},966:function(n,t,o){},968:function(n,t,o){},970:function(n,t,o){}});
|
||||
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],a=0,s=[];a<f.length;a++)i=f[a],Object.prototype.hasOwnProperty.call(u,i)&&u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(p&&p(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={2:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var p=c;r.push([907,0]),o()}({907:function(n,t,o){"use strict";o.r(t);o(908),o(910),o(912),o(914),o(916),o(918),o(920),o(922),o(924),o(926),o(928),o(930),o(932),o(934),o(936),o(938),o(940),o(942),o(944),o(946),o(948),o(950),o(952),o(954),o(956),o(958),o(960),o(962),o(964),o(966),o(968),o(970),o(972)},910:function(n,t,o){},912:function(n,t,o){},914:function(n,t,o){},916:function(n,t,o){},918:function(n,t,o){},920:function(n,t,o){},922:function(n,t,o){},924:function(n,t,o){},926:function(n,t,o){},928:function(n,t,o){},930:function(n,t,o){},932:function(n,t,o){},934:function(n,t,o){},936:function(n,t,o){},938:function(n,t,o){},940:function(n,t,o){},942:function(n,t,o){},944:function(n,t,o){},946:function(n,t,o){},948:function(n,t,o){},950:function(n,t,o){},952:function(n,t,o){},954:function(n,t,o){},956:function(n,t,o){},958:function(n,t,o){},960:function(n,t,o){},962:function(n,t,o){},964:function(n,t,o){},966:function(n,t,o){},968:function(n,t,o){},970:function(n,t,o){},972:function(n,t,o){}});
|
||||
//# sourceMappingURL=engineStyle.bundle.js.map
|
72
dist/engineStyle.css
vendored
72
dist/engineStyle.css
vendored
@ -105,13 +105,30 @@ a:visited {
|
||||
background-color: #fa3e3e;
|
||||
color: #fff;
|
||||
border-radius: 2px;
|
||||
padding: 1px 3px; }
|
||||
padding: 1px 3px;
|
||||
font-size: 10px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
position: absolute; }
|
||||
|
||||
.notification-off {
|
||||
background-color: #333;
|
||||
color: #333;
|
||||
border-radius: 0;
|
||||
padding: 0; }
|
||||
padding: 0;
|
||||
display: "none"; }
|
||||
|
||||
.notification {
|
||||
position: relative;
|
||||
display: inline-block; }
|
||||
|
||||
.notification .badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 2px;
|
||||
background: red;
|
||||
color: white; }
|
||||
|
||||
/* help tip. Question mark that opens popup with info/details */
|
||||
.help-tip {
|
||||
@ -638,13 +655,30 @@ a:visited {
|
||||
background-color: #fa3e3e;
|
||||
color: #fff;
|
||||
border-radius: 2px;
|
||||
padding: 1px 3px; }
|
||||
padding: 1px 3px;
|
||||
font-size: 10px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
position: absolute; }
|
||||
|
||||
.notification-off {
|
||||
background-color: #333;
|
||||
color: #333;
|
||||
border-radius: 0;
|
||||
padding: 0; }
|
||||
padding: 0;
|
||||
display: "none"; }
|
||||
|
||||
.notification {
|
||||
position: relative;
|
||||
display: inline-block; }
|
||||
|
||||
.notification .badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 2px;
|
||||
background: red;
|
||||
color: white; }
|
||||
|
||||
/* help tip. Question mark that opens popup with info/details */
|
||||
.help-tip {
|
||||
@ -1121,6 +1155,9 @@ button {
|
||||
.mainmenu > li button.active:hover {
|
||||
background-color: #aaa; }
|
||||
|
||||
.menu-header {
|
||||
position: relative; }
|
||||
|
||||
#hacking-menu-header-li,
|
||||
#character-menu-header-li,
|
||||
#world-menu-header-li,
|
||||
@ -1166,8 +1203,6 @@ button {
|
||||
|
||||
/* Slide down transition */
|
||||
.mainmenu-accordion-panel {
|
||||
max-height: 0;
|
||||
opacity: 1;
|
||||
transition: max-height 0.2s ease-out; }
|
||||
|
||||
/* COLORS */
|
||||
@ -1652,6 +1687,10 @@ button {
|
||||
width: 99%;
|
||||
overflow-y: scroll; }
|
||||
|
||||
#generic-react-container {
|
||||
position: fixed;
|
||||
padding: 10px; }
|
||||
|
||||
/* Character Info */
|
||||
#character-container {
|
||||
padding-top: 10px;
|
||||
@ -2052,13 +2091,30 @@ a:visited {
|
||||
background-color: #fa3e3e;
|
||||
color: #fff;
|
||||
border-radius: 2px;
|
||||
padding: 1px 3px; }
|
||||
padding: 1px 3px;
|
||||
font-size: 10px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
position: absolute; }
|
||||
|
||||
.notification-off {
|
||||
background-color: #333;
|
||||
color: #333;
|
||||
border-radius: 0;
|
||||
padding: 0; }
|
||||
padding: 0;
|
||||
display: "none"; }
|
||||
|
||||
.notification {
|
||||
position: relative;
|
||||
display: inline-block; }
|
||||
|
||||
.notification .badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 2px;
|
||||
background: red;
|
||||
color: white; }
|
||||
|
||||
/* help tip. Question mark that opens popup with info/details */
|
||||
.help-tip {
|
||||
|
26
dist/vendor.bundle.js
vendored
26
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
253
index.html
253
index.html
@ -41,159 +41,7 @@
|
||||
<div id="entire-game-container" style="visibility: hidden">
|
||||
<div id="mainmenu-container">
|
||||
<!-- Main menu -->
|
||||
<ul id="mainmenu" class="mainmenu noscrollbar">
|
||||
<!-- Hacking dropdown -->
|
||||
<li id="hacking-menu-header-li">
|
||||
<button id="hacking-menu-header" class="mainmenu-accordion-header noselect">Hacking</button>
|
||||
</li>
|
||||
<li id="terminal-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="terminal-menu-link">Terminal</button>
|
||||
</li>
|
||||
<li id="create-script-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="create-script-menu-link">Create Script</button>
|
||||
</li>
|
||||
<li id="active-scripts-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="active-scripts-menu-link">Active Scripts</button>
|
||||
</li>
|
||||
<li id="create-program-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="create-program-menu-link">Create Program</button>
|
||||
<span id="create-program-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
|
||||
<!-- Character dropdown -->
|
||||
<li id="character-menu-header-li">
|
||||
<button id="character-menu-header" class="mainmenu-accordion-header noselect">Character</button>
|
||||
</li>
|
||||
<li id="stats-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="stats-menu-link">Stats</button>
|
||||
</li>
|
||||
<li id="factions-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="factions-menu-link">Factions</button>
|
||||
<span id="factions-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
<li id="augmentations-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap">
|
||||
Augmentations
|
||||
</button>
|
||||
<span id="augmentations-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
<li id="hacknet-nodes-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="hacknet-nodes-menu-link">Hacknet</button>
|
||||
</li>
|
||||
<li id="sleeves-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="sleeves-menu-link">Sleeves</button>
|
||||
</li>
|
||||
|
||||
<!-- World dropdown -->
|
||||
<li id="world-menu-header-li">
|
||||
<button id="world-menu-header" class="mainmenu-accordion-header noselect">World</button>
|
||||
</li>
|
||||
<li id="city-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="city-menu-link">City</button>
|
||||
</li>
|
||||
<li id="travel-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="travel-menu-link">Travel</button>
|
||||
</li>
|
||||
<li id="job-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="job-menu-link">Job</button>
|
||||
</li>
|
||||
<li id="stock-market-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="stock-market-menu-link">Stock Market</button>
|
||||
</li>
|
||||
<li id="bladeburner-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="bladeburner-menu-link">Bladeburner</button>
|
||||
</li>
|
||||
<li id="corporation-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="corporation-menu-link">Corp</button>
|
||||
</li>
|
||||
<li id="gang-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="gang-menu-link">Gang</button>
|
||||
</li>
|
||||
|
||||
<li id="help-menu-header-li">
|
||||
<button id="help-menu-header" class="mainmenu-accordion-header noselect">Help</button>
|
||||
</li>
|
||||
<li id="milestones-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="milestones-menu-link">Milestones</button>
|
||||
</li>
|
||||
<li id="tutorial-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="tutorial-menu-link">Tutorial</button>
|
||||
</li>
|
||||
<li id="options-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="options-menu-link">Options</button>
|
||||
</li>
|
||||
<li id="dev-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="dev-menu-link">Dev</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="script-editor-container" class="generic-menupage-container">
|
||||
<div id="script-editor-wrapper">
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag">
|
||||
<strong style="background-color: #555">Script name: </strong>
|
||||
</p>
|
||||
<input id="script-editor-filename" type="text" maxlength="100" tabindex="1"/>
|
||||
</div>
|
||||
|
||||
<div id="monaco-editor"></div>
|
||||
|
||||
<div id="script-editor-buttons-wrapper"></div>
|
||||
<!-- Buttons below script editor -->
|
||||
</div>
|
||||
<!-- End wrapper -->
|
||||
|
||||
<div id="script-editor-options-panel">
|
||||
<h1 style="color: white">Script Editor Options</h1>
|
||||
<fieldset>
|
||||
<label for="script-editor-option-editor">Editor</label>
|
||||
<select id="script-editor-option-editor" class="dropdown">
|
||||
<option value="Ace">Ace</option>
|
||||
<option value="CodeMirror">CodeMirror</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-theme">Theme</label>
|
||||
<select id="script-editor-option-theme" class="dropdown"></select>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-keybinding">Key Binding</label>
|
||||
<select id="script-editor-option-keybinding" class="dropdown"></select>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-highlightactiveline">Highlight Active Line</label>
|
||||
<input type="checkbox" class="optionCheckbox" name="script-editor-option-highlightactiveline" id="script-editor-option-highlightactiveline" checked/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-showinvisibles">Show Invisibles</label>
|
||||
<input type="checkbox" class="optionCheckbox" name="script-editor-option-showinvisibles" id="script-editor-option-showinvisibles"/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-usesofttab">Use Soft Tab</label>
|
||||
<input type="checkbox" class="optionCheckbox" name="script-editor-option-usesofttab" id="script-editor-option-usesofttab" checked/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="script-editor-option-flex1-fieldset"></fieldset>
|
||||
<fieldset id="script-editor-option-flex2-fieldset"></fieldset>
|
||||
<fieldset id="script-editor-option-flex3-fieldset"></fieldset>
|
||||
<fieldset id="script-editor-option-flex4-fieldset"></fieldset>
|
||||
</div>
|
||||
<!-- End script editor options panel -->
|
||||
|
||||
<!-- TODO(hydroflame): remove this once Monaco is implemented -->
|
||||
<div id="ace-editor" style="display: none"></div>
|
||||
<form id="codemirror-form-wrapper" style="display: none">
|
||||
<textarea id="codemirror-editor"></textarea>
|
||||
</form>
|
||||
<div id="codemirror-vim-command-display-wrapper" style="display: none">
|
||||
Key Buffer: <span id="codemirror-vim-command-display"></span>
|
||||
</div>
|
||||
<div id="sidebar"></div>
|
||||
</div>
|
||||
|
||||
<!-- Terminal page -->
|
||||
@ -208,92 +56,8 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Character Info page -->
|
||||
<div id="character-container" class="generic-menupage-container">
|
||||
<div id="character-content"></div>
|
||||
</div>
|
||||
|
||||
<!-- Active scripts info page -->
|
||||
<div id="active-scripts-container" class="generic-menupage-container">
|
||||
<p id="active-scripts-text">
|
||||
This page displays a list of all of your scripts that are currently running across every machine. It also
|
||||
provides information about each script's production. The scripts are categorized by the hostname of the
|
||||
servers on which they are running.
|
||||
</p>
|
||||
<p id="active-scripts-total-prod">
|
||||
Total online production of Active scripts:
|
||||
<span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br/>
|
||||
Total online production since last Aug installation:
|
||||
<span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span>
|
||||
(<span class="money-gold"><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span>)
|
||||
</p>
|
||||
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none"></ul>
|
||||
</div>
|
||||
|
||||
<!-- Hacknet Nodes -->
|
||||
<div id="hacknet-nodes-container" class="generic-menupage-container">
|
||||
<!-- React Component -->
|
||||
</div>
|
||||
|
||||
<!-- Create a program(executable) -->
|
||||
<div id="create-program-container" class="generic-menupage-container">
|
||||
<p id="create-program-page-text">
|
||||
This page displays any programs that you are able to create. Writing the code for a program takes time, which
|
||||
can vary based on how complex the program is. If you are working on creating a program you can cancel at any
|
||||
time. Your progress will be saved and you can continue later.
|
||||
</p>
|
||||
|
||||
<ul id="create-program-list"></ul>
|
||||
</div>
|
||||
|
||||
<!-- Factions -->
|
||||
<div id="factions-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Single Faction info (when you select a faction from the Factions menu) -->
|
||||
<div id="faction-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Augmentations -->
|
||||
<div id="augmentations-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Milestones content -->
|
||||
<div id="milestones-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Tutorial content -->
|
||||
<div id="tutorial-container" class="generic-menupage-container">
|
||||
<h1>Tutorial (AKA Links to Documentation)</h1>
|
||||
<a id="tutorial-getting-started-link" class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html">
|
||||
Getting Started</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html">
|
||||
Servers & Networking</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html">
|
||||
Hacking</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html">
|
||||
Scripts</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/netscript.html">
|
||||
Netscript Programming Language</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html">
|
||||
Traveling</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html">
|
||||
Companies</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html">
|
||||
Infiltration</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html">
|
||||
Factions</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html">
|
||||
Augmentations</a><br/><br/>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
|
||||
Keyboard Shortcuts</a>
|
||||
</div>
|
||||
|
||||
<!-- Location (visiting a location in World) -->
|
||||
<div id="location-container" class="generic-menupage-container"></div>
|
||||
<div id="generic-react-container" class="generic-menupage-container"></div>
|
||||
<div id="infiltration-container" class="generic-fullscreen-container"></div>
|
||||
<div id="stock-market-container" class="generic-menupage-container"></div>
|
||||
<div id="bladeburner-container" class="generic-menupage-container"></div>
|
||||
<div id="resleeve-container" class="generic-menupage-container"></div>
|
||||
<div id="gang-container" class="generic-menupage-container"></div>
|
||||
<div id="corporation-container" class="generic-menupage-container"></div>
|
||||
<div id="sleeves-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Generic Yes/No Pop Up box -->
|
||||
<div id="yes-no-box-container" class="popup-box-container">
|
||||
@ -329,19 +93,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- End of Infiltration pop up box -->
|
||||
<div id="infiltration-box-container" class="popup-box-container">
|
||||
<div id="infiltration-box-content" class="popup-box-content">
|
||||
<p id="infiltration-box-text"></p>
|
||||
|
||||
<button id="infiltration-box-sell" class="a-link-button">Sell on Black Market</button>
|
||||
<br/><br/>
|
||||
<select id="infiltration-faction-select" class="dropdown"></select>
|
||||
<br/>
|
||||
<button id="infiltration-box-faction" class="a-link-button">Give to Faction for Reputation</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mission container -->
|
||||
<div id="mission-container" class="generic-fullscreen-container"></div>
|
||||
|
||||
|
13
package-lock.json
generated
13
package-lock.json
generated
@ -61,6 +61,7 @@
|
||||
"@testing-library/cypress": "^8.0.1",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/lodash": "^4.14.168",
|
||||
"@types/node": "^16.9.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||
"@typescript-eslint/parser": "^4.22.0",
|
||||
"babel-jest": "^27.0.6",
|
||||
@ -3565,9 +3566,9 @@
|
||||
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.2.tgz",
|
||||
"integrity": "sha512-TbG4TOx9hng8FKxaVrCisdaxKxqEwJ3zwHoCWXZ0Jw6mnvTInpaB99/2Cy4+XxpXtjNv9/TgfGSvZFyfV/t8Fw==",
|
||||
"version": "16.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
|
||||
"integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/normalize-package-data": {
|
||||
@ -28624,9 +28625,9 @@
|
||||
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.2.tgz",
|
||||
"integrity": "sha512-TbG4TOx9hng8FKxaVrCisdaxKxqEwJ3zwHoCWXZ0Jw6mnvTInpaB99/2Cy4+XxpXtjNv9/TgfGSvZFyfV/t8Fw==",
|
||||
"version": "16.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
|
||||
"integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/normalize-package-data": {
|
||||
|
@ -59,6 +59,7 @@
|
||||
"@testing-library/cypress": "^8.0.1",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/lodash": "^4.14.168",
|
||||
"@types/node": "^16.9.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||
"@typescript-eslint/parser": "^4.22.0",
|
||||
"babel-jest": "^27.0.6",
|
||||
|
@ -2455,22 +2455,6 @@ function augmentationExists(name) {
|
||||
return Augmentations.hasOwnProperty(name);
|
||||
}
|
||||
|
||||
export function displayAugmentationsContent(contentEl) {
|
||||
if (!routing.isOn(Page.Augmentations)) {
|
||||
return;
|
||||
}
|
||||
if (!(contentEl instanceof HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
function backup() {
|
||||
saveObject.exportGame();
|
||||
onExport(Player);
|
||||
}
|
||||
|
||||
ReactDOM.render(<AugmentationsRoot exportGameFn={backup} installAugmentationsFn={installAugmentations} />, contentEl);
|
||||
}
|
||||
|
||||
export function isRepeatableAug(aug) {
|
||||
const augName = aug instanceof Augmentation ? aug.name : aug;
|
||||
|
||||
|
@ -44,47 +44,49 @@ export class AugmentationsRoot extends React.Component<IProps, IState> {
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="augmentations-content">
|
||||
<h1>Purchased Augmentations</h1>
|
||||
<p>
|
||||
Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to
|
||||
install them.
|
||||
</p>
|
||||
<p>WARNING: Installing your Augmentations resets most of your progress, including:</p>
|
||||
<br />
|
||||
<p>- Stats/Skill levels and Experience</p>
|
||||
<p>- Money</p>
|
||||
<p>- Scripts on every computer but your home computer</p>
|
||||
<p>- Purchased servers</p>
|
||||
<p>- Hacknet Nodes</p>
|
||||
<p>- Faction/Company reputation</p>
|
||||
<p>- Stocks</p>
|
||||
<br />
|
||||
<p>
|
||||
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)
|
||||
</p>
|
||||
<StdButton
|
||||
onClick={this.props.installAugmentationsFn}
|
||||
text="Install Augmentations"
|
||||
tooltip="'I never asked for this'"
|
||||
/>
|
||||
<StdButton
|
||||
addClasses="flashing-button"
|
||||
onClick={this.export}
|
||||
text={`Backup Save ${exportBonusStr()}`}
|
||||
tooltip="It's always a good idea to backup/export your save!"
|
||||
/>
|
||||
<PurchasedAugmentations />
|
||||
<h1>Installed Augmentations</h1>
|
||||
<p>
|
||||
{`List of all Augmentations ${Player.sourceFiles.length > 0 ? "and Source Files " : ""} ` +
|
||||
`that have been installed. You have gained the effects of these.`}
|
||||
</p>
|
||||
<InstalledAugmentationsAndSourceFiles />
|
||||
<br /> <br />
|
||||
<PlayerMultipliers />
|
||||
<div id="augmentations-container">
|
||||
<div id="augmentations-content">
|
||||
<h1>Purchased Augmentations</h1>
|
||||
<p>
|
||||
Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to
|
||||
install them.
|
||||
</p>
|
||||
<p>WARNING: Installing your Augmentations resets most of your progress, including:</p>
|
||||
<br />
|
||||
<p>- Stats/Skill levels and Experience</p>
|
||||
<p>- Money</p>
|
||||
<p>- Scripts on every computer but your home computer</p>
|
||||
<p>- Purchased servers</p>
|
||||
<p>- Hacknet Nodes</p>
|
||||
<p>- Faction/Company reputation</p>
|
||||
<p>- Stocks</p>
|
||||
<br />
|
||||
<p>
|
||||
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)
|
||||
</p>
|
||||
<StdButton
|
||||
onClick={this.props.installAugmentationsFn}
|
||||
text="Install Augmentations"
|
||||
tooltip="'I never asked for this'"
|
||||
/>
|
||||
<StdButton
|
||||
addClasses="flashing-button"
|
||||
onClick={this.export}
|
||||
text={`Backup Save ${exportBonusStr()}`}
|
||||
tooltip="It's always a good idea to backup/export your save!"
|
||||
/>
|
||||
<PurchasedAugmentations />
|
||||
<h1>Installed Augmentations</h1>
|
||||
<p>
|
||||
{`List of all Augmentations ${Player.sourceFiles.length > 0 ? "and Source Files " : ""} ` +
|
||||
`that have been installed. You have gained the effects of these.`}
|
||||
</p>
|
||||
<InstalledAugmentationsAndSourceFiles />
|
||||
<br /> <br />
|
||||
<PlayerMultipliers />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ interface IProps {
|
||||
|
||||
export function Root(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<div id="bladeburner-container">
|
||||
<div style={{ height: "60%", display: "block", position: "relative" }}>
|
||||
<div
|
||||
style={{
|
||||
@ -41,6 +41,6 @@ export function Root(props: IProps): React.ReactElement {
|
||||
>
|
||||
<AllPages bladeburner={props.bladeburner} player={props.player} />
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -69,13 +69,13 @@ export class Node {
|
||||
}
|
||||
|
||||
// Determine what css class this Node should have in the diagram
|
||||
let htmlClass = "";
|
||||
let htmlClass = "tooltip";
|
||||
if (this.researched) {
|
||||
htmlClass = "researched";
|
||||
htmlClass += " researched";
|
||||
} else if (this.parent && this.parent.researched === false) {
|
||||
htmlClass = "locked";
|
||||
htmlClass += " locked";
|
||||
} else {
|
||||
htmlClass = "unlocked";
|
||||
htmlClass += " unlocked";
|
||||
}
|
||||
|
||||
const research: Research | null = ResearchMap[this.text];
|
||||
@ -84,7 +84,7 @@ export class Node {
|
||||
children: childrenArray,
|
||||
HTMLclass: htmlClass,
|
||||
innerHTML:
|
||||
`<div id="${sanitizedName}-corp-research-click-listener" class="tooltip">` +
|
||||
`<div id="${sanitizedName}-corp-research-click-listener">` +
|
||||
`${this.text}<br>${numeralWrapper.format(this.cost, "0,0")} Scientific Research` +
|
||||
`<span class="tooltiptext">` +
|
||||
`${research.desc}` +
|
||||
|
@ -20,7 +20,8 @@ function ExpandButton(props: IExpandButtonProps): React.ReactElement {
|
||||
const allIndustries = Object.keys(Industries).sort();
|
||||
const possibleIndustries = allIndustries
|
||||
.filter(
|
||||
(industryType: string) => props.corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
|
||||
(industryType: string) =>
|
||||
props.corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
|
||||
)
|
||||
.sort();
|
||||
if (possibleIndustries.length === 0) return <></>;
|
||||
@ -50,12 +51,12 @@ export function CorporationRoot(props: IProps): React.ReactElement {
|
||||
const [divisionName, setDivisionName] = useState("Overview");
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 150);
|
||||
const id = setInterval(rerender, 1000);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="corporation-container">
|
||||
<div>
|
||||
<HeaderTab
|
||||
current={divisionName === "Overview"}
|
||||
@ -74,6 +75,6 @@ export function CorporationRoot(props: IProps): React.ReactElement {
|
||||
<ExpandButton corp={props.corp} setDivisionName={setDivisionName} />
|
||||
</div>
|
||||
<MainPanel rerender={rerender} corp={props.corp} divisionName={divisionName} player={props.player} />
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -59,6 +59,14 @@ export function ExportPopup(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
const currentDivision = props.corp.divisions.find((division: IIndustry) => division.name === industry);
|
||||
if (currentDivision === undefined)
|
||||
throw new Error(`Export popup somehow ended up with undefined division '${currentDivision}'`);
|
||||
const possibleCities = Object.keys(currentDivision.warehouses).filter(
|
||||
(city) => currentDivision.warehouses[city] !== 0,
|
||||
);
|
||||
if (possibleCities.length > 0 && !possibleCities.includes(city)) {
|
||||
setCity(possibleCities[0]);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -74,15 +82,14 @@ export function ExportPopup(props: IProps): React.ReactElement {
|
||||
))}
|
||||
</select>
|
||||
<select className="dropdown" onChange={onCityChange} defaultValue={city}>
|
||||
{currentDivision &&
|
||||
Object.keys(currentDivision.warehouses).map((cityName: string) => {
|
||||
if (currentDivision.warehouses[cityName] === 0) return;
|
||||
return (
|
||||
<option key={cityName} value={cityName}>
|
||||
{cityName}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
{possibleCities.map((cityName: string) => {
|
||||
if (currentDivision.warehouses[cityName] === 0) return;
|
||||
return (
|
||||
<option key={cityName} value={cityName}>
|
||||
{cityName}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
<input className="text-input" placeholder="Export amount / s" onChange={onAmtChange} />
|
||||
<button className="std-button" style={{ display: "inline-block" }} onClick={exportMaterial}>
|
||||
|
@ -52,6 +52,7 @@ export function Overview(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function openBribeFactionPopup(): void {
|
||||
console.log("hello click");
|
||||
const popupId = "corp-bribe-popup";
|
||||
createPopup(popupId, BribeFactionPopup, {
|
||||
player: props.player,
|
||||
|
@ -29,8 +29,8 @@ function BulkPurchaseText(props: IBulkPurchaseTextProps): React.ReactElement {
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
Purchasing {numeralWrapper.format(parsedAmt, "0,0.00")} of
|
||||
{props.mat.name} will cost {numeralWrapper.formatMoney(cost)}
|
||||
Purchasing {numeralWrapper.format(parsedAmt, "0,0.00")} of {props.mat.name} will cost{" "}
|
||||
{numeralWrapper.formatMoney(cost)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
1647
src/DevMenu.jsx
1647
src/DevMenu.jsx
File diff suppressed because it is too large
Load Diff
1607
src/DevMenu.tsx
Normal file
1607
src/DevMenu.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@ -86,7 +86,7 @@ export function displayFactionContent(factionName, initiallyOnAugmentationsPage
|
||||
p={Player}
|
||||
startHackingMissionFn={startHackingMission}
|
||||
/>,
|
||||
Engine.Display.factionContent,
|
||||
Engine.Display.content,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ export function FactionList(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="factions-container">
|
||||
<h1>Factions</h1>
|
||||
<p>Lists all factions you have joined</p>
|
||||
<br />
|
||||
@ -60,6 +60,6 @@ export function FactionList(props: IProps): React.ReactElement {
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ export class FactionRoot extends React.Component<IProps, IState> {
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div id="faction-container">
|
||||
<h1>{faction.name}</h1>
|
||||
<Info faction={faction} factionInfo={factionInfo} />
|
||||
{canAccessGang && <Option buttonText={"Manage Gang"} infoText={gangInfo} onClick={this.manageGang} />}
|
||||
@ -266,7 +266,7 @@ export class FactionRoot extends React.Component<IProps, IState> {
|
||||
|
||||
renderAugmentationsPage(): React.ReactNode {
|
||||
return (
|
||||
<div>
|
||||
<div id="faction-container">
|
||||
<AugmentationsPage faction={this.props.faction} p={this.props.p} routeToMainPage={this.routeToMain} />
|
||||
</div>
|
||||
);
|
||||
|
@ -30,7 +30,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="gang-container">
|
||||
<a className="a-link-button" style={{ display: "inline-block" }} onClick={back}>
|
||||
Back
|
||||
</a>
|
||||
@ -53,6 +53,6 @@ export function Root(props: IProps): React.ReactElement {
|
||||
) : (
|
||||
<TerritorySubpage gang={props.gang} />
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div id="hacknet-nodes-container">
|
||||
<h1>Hacknet {hasHacknetServers(props.player) ? "Servers" : "Nodes"}</h1>
|
||||
<GeneralInfo hasHacknetServers={hasHacknetServers(props.player)} />
|
||||
|
||||
|
@ -3,15 +3,30 @@
|
||||
* to TypeScript at the moment
|
||||
*/
|
||||
export interface IEngine {
|
||||
indexedDb: any;
|
||||
_lastUpdate: number;
|
||||
hideAllContent: () => void;
|
||||
loadBladeburnerContent: () => void;
|
||||
loadFactionContent: () => void;
|
||||
loadTerminalContent: () => void;
|
||||
loadScriptEditorContent: () => void;
|
||||
loadActiveScriptsContent: () => void;
|
||||
loadCreateProgramContent: () => void;
|
||||
loadCharacterContent: () => void;
|
||||
loadFactionsContent: () => void;
|
||||
loadGangContent: () => void;
|
||||
loadInfiltrationContent: (name: string, difficulty: number, maxLevel: number) => void;
|
||||
loadAugmentationsContent: () => void;
|
||||
loadHacknetNodesContent: () => void;
|
||||
loadSleevesContent: () => void;
|
||||
loadLocationContent: () => void;
|
||||
loadTravelContent: () => void;
|
||||
loadJobContent: () => void;
|
||||
loadStockMarketContent: () => void;
|
||||
loadBladeburnerContent: () => void;
|
||||
loadCorporationContent: () => void;
|
||||
loadGangContent: () => void;
|
||||
loadMilestonesContent: () => void;
|
||||
loadTutorialContent: () => void;
|
||||
loadDevMenuContent: () => void;
|
||||
loadFactionContent: () => void;
|
||||
loadInfiltrationContent: (name: string, difficulty: number, maxLevel: number) => void;
|
||||
loadMissionContent: () => void;
|
||||
loadResleevingContent: () => void;
|
||||
loadStockMarketContent: () => void;
|
||||
loadTerminalContent: () => void;
|
||||
}
|
||||
|
@ -104,18 +104,18 @@ function iTutorialEvaluateStep() {
|
||||
}
|
||||
|
||||
// Disable and clear main menu
|
||||
const terminalMainMenu = clearEventListeners("terminal-menu-link");
|
||||
const statsMainMenu = clearEventListeners("stats-menu-link");
|
||||
const activeScriptsMainMenu = clearEventListeners("active-scripts-menu-link");
|
||||
const hacknetMainMenu = clearEventListeners("hacknet-nodes-menu-link");
|
||||
const cityMainMenu = clearEventListeners("city-menu-link");
|
||||
const tutorialMainMenu = clearEventListeners("tutorial-menu-link");
|
||||
terminalMainMenu.removeAttribute("class");
|
||||
statsMainMenu.removeAttribute("class");
|
||||
activeScriptsMainMenu.removeAttribute("class");
|
||||
hacknetMainMenu.removeAttribute("class");
|
||||
cityMainMenu.removeAttribute("class");
|
||||
tutorialMainMenu.removeAttribute("class");
|
||||
// const terminalMainMenu = clearEventListeners("terminal-menu-link");
|
||||
// const statsMainMenu = clearEventListeners("stats-menu-link");
|
||||
// const activeScriptsMainMenu = clearEventListeners("active-scripts-menu-link");
|
||||
// const hacknetMainMenu = clearEventListeners("hacknet-nodes-menu-link");
|
||||
// const cityMainMenu = clearEventListeners("city-menu-link");
|
||||
// const tutorialMainMenu = clearEventListeners("tutorial-menu-link");
|
||||
// terminalMainMenu.removeAttribute("class");
|
||||
// statsMainMenu.removeAttribute("class");
|
||||
// activeScriptsMainMenu.removeAttribute("class");
|
||||
// hacknetMainMenu.removeAttribute("class");
|
||||
// cityMainMenu.removeAttribute("class");
|
||||
// tutorialMainMenu.removeAttribute("class");
|
||||
|
||||
// Interactive Tutorial Next button
|
||||
const nextBtn = document.getElementById("interactive-tutorial-next");
|
||||
@ -138,14 +138,6 @@ function iTutorialEvaluateStep() {
|
||||
"the main navigation menu (left-hand side of the screen)",
|
||||
);
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
// Flash 'Stats' menu and set its tutorial click handler
|
||||
statsMainMenu.setAttribute("class", "flashing-button");
|
||||
statsMainMenu.addEventListener("click", function () {
|
||||
Engine.loadCharacterContent();
|
||||
iTutorialNextStep(); //Opening the character page will go to the next step
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.CharacterPage:
|
||||
Engine.loadCharacterContent();
|
||||
@ -162,14 +154,6 @@ function iTutorialEvaluateStep() {
|
||||
"main navigation menu.",
|
||||
);
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
// Flash 'Terminal' menu and set its tutorial click handler
|
||||
terminalMainMenu.setAttribute("class", "flashing-button");
|
||||
terminalMainMenu.addEventListener("click", function () {
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.TerminalIntro:
|
||||
Engine.loadTerminalContent();
|
||||
@ -345,14 +329,6 @@ function iTutorialEvaluateStep() {
|
||||
"<code class='interactive-tutorial-tab flashing-button'>Active Scripts</code> link in the main navigation menu.",
|
||||
);
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
// Flash 'Active Scripts' menu and set its tutorial click handler
|
||||
activeScriptsMainMenu.setAttribute("class", "flashing-button");
|
||||
activeScriptsMainMenu.addEventListener("click", function () {
|
||||
Engine.loadActiveScriptsContent();
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsPage:
|
||||
Engine.loadActiveScriptsContent();
|
||||
@ -362,14 +338,6 @@ function iTutorialEvaluateStep() {
|
||||
"your scripts are doing. Let's go back to the <code class='interactive-tutorial-tab flashing-button'>Terminal</code>",
|
||||
);
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
// Flash 'Terminal' button and set its tutorial click handler
|
||||
terminalMainMenu.setAttribute("class", "flashing-button");
|
||||
terminalMainMenu.addEventListener("click", function () {
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsToTerminal:
|
||||
Engine.loadTerminalContent();
|
||||
@ -402,14 +370,6 @@ function iTutorialEvaluateStep() {
|
||||
"the <code class='interactive-tutorial-tab flashing-button'>Hacknet</code> page through the main navigation menu now.",
|
||||
);
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
// Flash 'Hacknet' menu and set its tutorial click handler
|
||||
hacknetMainMenu.setAttribute("class", "flashing-button");
|
||||
hacknetMainMenu.addEventListener("click", function () {
|
||||
Engine.loadHacknetNodesContent();
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesIntroduction:
|
||||
Engine.loadHacknetNodesContent();
|
||||
@ -428,14 +388,6 @@ function iTutorialEvaluateStep() {
|
||||
"Let's go to the <code class='interactive-tutorial-tab flashing-button'>City</code> page through the main navigation menu.",
|
||||
);
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
// Flash 'City' menu and set its tutorial click handler
|
||||
cityMainMenu.setAttribute("class", "flashing-button");
|
||||
cityMainMenu.addEventListener("click", function () {
|
||||
Engine.loadLocationContent();
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.WorldDescription:
|
||||
Engine.loadLocationContent();
|
||||
@ -447,14 +399,6 @@ function iTutorialEvaluateStep() {
|
||||
"Lastly, click on the <code class='interactive-tutorial-tab flashing-button'>Tutorial</code> link in the main navigation menu.",
|
||||
);
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
// Flash 'Tutorial' menu and set its tutorial click handler
|
||||
tutorialMainMenu.setAttribute("class", "flashing-button");
|
||||
tutorialMainMenu.addEventListener("click", function () {
|
||||
Engine.loadTutorialContent();
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.TutorialPageInfo:
|
||||
Engine.loadTutorialContent();
|
||||
@ -481,29 +425,6 @@ function iTutorialEvaluateStep() {
|
||||
|
||||
// Go to the next step and evaluate it
|
||||
function iTutorialNextStep() {
|
||||
// Special behavior for certain steps
|
||||
if (ITutorial.currStep === iTutorialSteps.GoToCharacterPage) {
|
||||
document.getElementById("stats-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.CharacterGoToTerminalPage) {
|
||||
document.getElementById("terminal-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.TerminalGoToActiveScriptsPage) {
|
||||
document.getElementById("active-scripts-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.ActiveScriptsPage) {
|
||||
document.getElementById("terminal-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.GoToHacknetNodesPage) {
|
||||
document.getElementById("hacknet-nodes-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.HacknetNodesGoToWorldPage) {
|
||||
document.getElementById("city-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.WorldDescription) {
|
||||
document.getElementById("tutorial-menu-link").removeAttribute("class");
|
||||
}
|
||||
|
||||
ITutorial.stepIsDone[ITutorial.currStep] = true;
|
||||
if (ITutorial.currStep < iTutorialSteps.End) {
|
||||
ITutorial.currStep += 1;
|
||||
@ -527,17 +448,6 @@ function iTutorialEnd() {
|
||||
Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5;
|
||||
}
|
||||
|
||||
// Initialize references to main menu links
|
||||
// We have to call initializeMainMenuLinks() again because the Interactive Tutorial
|
||||
// re-creates Main menu links with clearEventListeners()
|
||||
if (!initializeMainMenuLinks()) {
|
||||
const errorMsg =
|
||||
"Failed to initialize Main Menu Links. Please try refreshing the page. " +
|
||||
"If that doesn't work, report the issue to the developer";
|
||||
exceptionAlert(new Error(errorMsg));
|
||||
console.error(errorMsg);
|
||||
return;
|
||||
}
|
||||
Engine.init();
|
||||
|
||||
ITutorial.currStep = iTutorialSteps.End;
|
||||
|
@ -144,7 +144,7 @@ export class LocationRoot extends React.Component<IProps, IState> {
|
||||
|
||||
render(): React.ReactNode {
|
||||
if (this.state.inCity) {
|
||||
return this.renderCity();
|
||||
return <div id="location-container">{this.renderCity()}</div>;
|
||||
} else {
|
||||
return this.renderLocation();
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This subcomponent renders all of the buttons for purchasing things from tech vendors
|
||||
*/
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { Location } from "../Location";
|
||||
import { RamButton } from "./RamButton";
|
||||
@ -44,6 +44,10 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 1000);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
const btnStyle = { display: "block" };
|
||||
|
||||
const purchaseServerButtons: React.ReactNode[] = [];
|
||||
|
@ -1,26 +0,0 @@
|
||||
import { Page, routing } from ".././ui/navigationTracking";
|
||||
import { Root } from "./ui/Root";
|
||||
import { Player } from "../Player";
|
||||
import * as React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
|
||||
let milestonesContainer: HTMLElement | null = null;
|
||||
|
||||
(function () {
|
||||
function setContainer(): void {
|
||||
milestonesContainer = document.getElementById("milestones-container");
|
||||
document.removeEventListener("DOMContentLoaded", setContainer);
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", setContainer);
|
||||
})();
|
||||
|
||||
export function displayMilestonesContent(): void {
|
||||
if (!routing.isOn(Page.Milestones)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (milestonesContainer instanceof HTMLElement) {
|
||||
ReactDOM.render(<Root player={Player} />, milestonesContainer);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ function highestMilestone(p: IPlayer, milestones: Milestone[]): number {
|
||||
return n;
|
||||
}
|
||||
|
||||
export function Root(props: IProps): JSX.Element {
|
||||
export function MilestonesRoot(props: IProps): JSX.Element {
|
||||
const n = highestMilestone(props.player, Milestones);
|
||||
const milestones = Milestones.map((milestone: Milestone, i: number) => {
|
||||
if (i <= n + 1) {
|
||||
@ -30,7 +30,7 @@ export function Root(props: IProps): JSX.Element {
|
||||
}
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<div id="milestones-container">
|
||||
<h1>Milestones</h1>
|
||||
<p>
|
||||
Milestones don't reward you for completing them. They are here to guide you if you're lost. They will reset when
|
||||
@ -40,6 +40,6 @@ export function Root(props: IProps): JSX.Element {
|
||||
|
||||
<h2>Completing fl1ght.exe</h2>
|
||||
<li>{milestones}</li>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -21,15 +21,18 @@ import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile";
|
||||
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
|
||||
import { Exploit } from "../Exploits/Exploit";
|
||||
import { ICorporation } from "../Corporation/ICorporation";
|
||||
import { IGang } from "../Gang/IGang";
|
||||
import { IBladeburner } from "../Bladeburner/IBladeburner";
|
||||
|
||||
export interface IPlayer {
|
||||
// Class members
|
||||
augmentations: IPlayerOwnedAugmentation[];
|
||||
bladeburner: any;
|
||||
bitNodeN: number;
|
||||
city: CityName;
|
||||
companyName: string;
|
||||
corporation: ICorporation;
|
||||
gang: IGang;
|
||||
bladeburner: IBladeburner;
|
||||
currentServer: string;
|
||||
factions: string[];
|
||||
factionInvitations: string[];
|
||||
@ -63,6 +66,7 @@ export interface IPlayer {
|
||||
sleevesFromCovenant: number;
|
||||
sourceFiles: IPlayerOwnedSourceFile[];
|
||||
exploits: Exploit[];
|
||||
lastUpdate: number;
|
||||
totalPlaytime: number;
|
||||
|
||||
// Stats
|
||||
@ -81,6 +85,7 @@ export interface IPlayer {
|
||||
dexterity_exp: number;
|
||||
agility_exp: number;
|
||||
charisma_exp: number;
|
||||
intelligence_exp: number;
|
||||
|
||||
// Multipliers
|
||||
hacking_chance_mult: number;
|
||||
@ -192,4 +197,8 @@ export interface IPlayer {
|
||||
getCasinoWinnings(): number;
|
||||
quitJob(company: string): void;
|
||||
createHacknetServer(): void;
|
||||
startCreateProgramWork(programName: string, time: number, reqLevel: number): void;
|
||||
queueAugmentation(augmentationName: string): void;
|
||||
receiveInvite(factionName: string): void;
|
||||
updateSkillLevels(): void;
|
||||
}
|
||||
|
@ -60,9 +60,11 @@ const SortFunctions: {
|
||||
Dexterity: (a: Resleeve, b: Resleeve): number => a.dexterity - b.dexterity,
|
||||
Agility: (a: Resleeve, b: Resleeve): number => a.agility - b.agility,
|
||||
Charisma: (a: Resleeve, b: Resleeve): number => a.charisma - b.charisma,
|
||||
AverageCombatStats: (a: Resleeve, b: Resleeve): number => getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
||||
AverageCombatStats: (a: Resleeve, b: Resleeve): number =>
|
||||
getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
||||
getAverage(b.strength, b.defense, b.dexterity, b.agility),
|
||||
AverageAllStats: (a: Resleeve, b: Resleeve): number => getAverage(a.hacking_skill, a.strength, a.defense, a.dexterity, a.agility, a.charisma) -
|
||||
AverageAllStats: (a: Resleeve, b: Resleeve): number =>
|
||||
getAverage(a.hacking_skill, a.strength, a.defense, a.dexterity, a.agility, a.charisma) -
|
||||
getAverage(b.hacking_skill, b.strength, b.defense, b.dexterity, b.agility, b.charisma),
|
||||
TotalNumAugmentations: (a: Resleeve, b: Resleeve): number => a.augmentations.length - b.augmentations.length,
|
||||
};
|
||||
@ -87,7 +89,7 @@ export function ResleeveRoot(props: IProps): React.ReactElement {
|
||||
props.player.resleeves.sort(sortFunction);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="resleeve-container">
|
||||
<p style={{ display: "block", width: "75%" }}>
|
||||
Re-sleeving is the process of digitizing and transferring your consciousness into a new human body, or 'sleeve'.
|
||||
Here at VitaLife, you can purchase new specially-engineered bodies for the re-sleeve process. Many of these
|
||||
@ -114,6 +116,6 @@ export function ResleeveRoot(props: IProps): React.ReactElement {
|
||||
{props.player.resleeves.map((resleeve, i) => (
|
||||
<ResleeveElem key={i} player={props.player} resleeve={resleeve} />
|
||||
))}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -875,12 +875,14 @@ export class Sleeve extends Person {
|
||||
if (!factionInfo.offerHackingWork) {
|
||||
return false;
|
||||
}
|
||||
console.log("Hacking");
|
||||
this.factionWorkType = FactionWorkType.Hacking;
|
||||
this.gainRatesForTask.hack = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
} else if (sanitizedWorkType.includes("field")) {
|
||||
if (!factionInfo.offerFieldWork) {
|
||||
return false;
|
||||
}
|
||||
console.log("Field");
|
||||
this.factionWorkType = FactionWorkType.Field;
|
||||
this.gainRatesForTask.hack = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.str = 0.1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
@ -892,6 +894,7 @@ export class Sleeve extends Person {
|
||||
if (!factionInfo.offerSecurityWork) {
|
||||
return false;
|
||||
}
|
||||
console.log("Security");
|
||||
this.factionWorkType = FactionWorkType.Security;
|
||||
this.gainRatesForTask.hack = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.str = 0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
@ -905,6 +908,7 @@ export class Sleeve extends Person {
|
||||
this.currentTaskLocation = factionName;
|
||||
this.currentTask = SleeveTaskType.Faction;
|
||||
this.currentTaskMaxTime = CONSTANTS.MillisecondsPer20Hours;
|
||||
console.log(this.currentTaskLocation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import { StatsElement } from "../ui/StatsElement";
|
||||
import { MoreStatsContent } from "../ui/MoreStatsContent";
|
||||
import { MoreEarningsContent } from "../ui/MoreEarningsContent";
|
||||
import { TaskSelector } from "../ui/TaskSelector";
|
||||
import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
@ -63,6 +64,7 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function setTask(): void {
|
||||
console.log(abc);
|
||||
props.sleeve.resetTaskStatus(); // sets to idle
|
||||
switch (abc[0]) {
|
||||
case "------":
|
||||
@ -100,15 +102,28 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
desc = <>This sleeve is currently idle</>;
|
||||
break;
|
||||
case SleeveTaskType.Company:
|
||||
desc = <>This sleeve is currently working your job at ${props.sleeve.currentTaskLocation}.</>;
|
||||
desc = <>This sleeve is currently working your job at {props.sleeve.currentTaskLocation}.</>;
|
||||
break;
|
||||
case SleeveTaskType.Faction:
|
||||
case SleeveTaskType.Faction: {
|
||||
let doing = "nothing";
|
||||
switch (props.sleeve.factionWorkType) {
|
||||
case FactionWorkType.Field:
|
||||
doing = "Field work";
|
||||
break;
|
||||
case FactionWorkType.Hacking:
|
||||
doing = "Hacking contracts";
|
||||
break;
|
||||
case FactionWorkType.Security:
|
||||
doing = "Security work";
|
||||
break;
|
||||
}
|
||||
desc = (
|
||||
<>
|
||||
This sleeve is currently doing ${props.sleeve.factionWorkType} for ${props.sleeve.currentTaskLocation}.
|
||||
This sleeve is currently doing {doing} for {props.sleeve.currentTaskLocation}.
|
||||
</>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case SleeveTaskType.Crime:
|
||||
desc = (
|
||||
<>
|
||||
|
@ -20,7 +20,7 @@ export function SleeveRoot(props: IProps): React.ReactElement {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ width: "70%" }}>
|
||||
<div id="sleeves-container" style={{ width: "70%" }}>
|
||||
<h1>Sleeves</h1>
|
||||
<p>
|
||||
Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciousness has been copied. In
|
||||
|
@ -53,7 +53,10 @@ function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
|
||||
function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
// Array of all factions that other sleeves are working for
|
||||
const forbiddenFactions = [];
|
||||
const forbiddenFactions = ["Bladeburners"];
|
||||
if (player.gang) {
|
||||
forbiddenFactions.push(player.gang.facName);
|
||||
}
|
||||
for (const otherSleeve of player.sleeves) {
|
||||
if (sleeve === otherSleeve) {
|
||||
continue;
|
||||
@ -180,8 +183,10 @@ const canDo: {
|
||||
"Work for Company": (player: IPlayer, sleeve: Sleeve) => possibleJobs(player, sleeve).length > 0,
|
||||
"Work for Faction": (player: IPlayer, sleeve: Sleeve) => possibleFactions(player, sleeve).length > 0,
|
||||
"Commit Crime": () => true,
|
||||
"Take University Course": (player: IPlayer, sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
||||
"Workout at Gym": (player: IPlayer, sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
||||
"Take University Course": (player: IPlayer, sleeve: Sleeve) =>
|
||||
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
||||
"Workout at Gym": (player: IPlayer, sleeve: Sleeve) =>
|
||||
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
||||
"Shock Recovery": (player: IPlayer, sleeve: Sleeve) => sleeve.shock < 100,
|
||||
Synchronize: (player: IPlayer, sleeve: Sleeve) => sleeve.sync < 100,
|
||||
};
|
||||
@ -226,7 +231,8 @@ export function TaskSelector(props: IProps): React.ReactElement {
|
||||
const [s1, setS1] = useState(abc[1]);
|
||||
const [s2, setS2] = useState(abc[2]);
|
||||
|
||||
const validActions = Object.keys(canDo).filter((k) => (canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve),
|
||||
const validActions = Object.keys(canDo).filter((k) =>
|
||||
(canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve),
|
||||
);
|
||||
|
||||
const detailsF = tasks[s0];
|
||||
@ -234,6 +240,15 @@ export function TaskSelector(props: IProps): React.ReactElement {
|
||||
const details = detailsF(props.player, props.sleeve);
|
||||
const details2 = details.second(s1);
|
||||
|
||||
if (details.first.length > 0 && !details.first.includes(s1)) {
|
||||
setS1(details.first[0]);
|
||||
props.setABC([s0, details.first[0], s2]);
|
||||
}
|
||||
if (details2.length > 0 && !details2.includes(s2)) {
|
||||
setS2(details2[0]);
|
||||
props.setABC([s0, s1, details2[0]]);
|
||||
}
|
||||
|
||||
function onS0Change(event: React.ChangeEvent<HTMLSelectElement>): void {
|
||||
const n = event.target.value;
|
||||
const detailsF = tasks[n];
|
||||
|
@ -23,7 +23,7 @@ import { prestigeHomeComputer } from "./Server/ServerHelpers";
|
||||
import { SourceFileFlags, updateSourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||
import { SpecialServerIps, prestigeSpecialServerIps, SpecialServerNames } from "./Server/SpecialServerIps";
|
||||
import { deleteStockMarket, initStockMarket, initSymbolToStockMap } from "./StockMarket/StockMarket";
|
||||
import { Terminal, postNetburnerText } from "./Terminal";
|
||||
import { Terminal, postVersion } from "./Terminal";
|
||||
|
||||
import { Page, routing } from "./ui/navigationTracking";
|
||||
|
||||
@ -52,7 +52,7 @@ function prestigeAugmentation() {
|
||||
Terminal.resetTerminalInput();
|
||||
Engine.loadTerminalContent();
|
||||
$("#terminal tr:not(:last)").remove();
|
||||
postNetburnerText();
|
||||
postVersion();
|
||||
|
||||
// Delete all Worker Scripts objects
|
||||
prestigeWorkerScripts();
|
||||
@ -233,7 +233,7 @@ function prestigeSourceFile(flume) {
|
||||
|
||||
// Clear terminal
|
||||
$("#terminal tr:not(:last)").remove();
|
||||
postNetburnerText();
|
||||
postVersion();
|
||||
|
||||
// Messages
|
||||
initMessages();
|
||||
|
@ -1,74 +0,0 @@
|
||||
import { Programs } from "./Programs";
|
||||
|
||||
import { Player } from "../Player";
|
||||
import { createElement } from "../../utils/uiHelpers/createElement";
|
||||
|
||||
// this has the same key as 'Programs', not program names
|
||||
const aLinks = {};
|
||||
|
||||
function displayCreateProgramContent() {
|
||||
for (const key in aLinks) {
|
||||
const p = Programs[key];
|
||||
aLinks[key].style.display = "none";
|
||||
if (!Player.hasProgram(p.name) && p.create.req(Player)) {
|
||||
aLinks[key].style.display = "inline-block";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Returns the number of programs that are currently available to be created
|
||||
function getNumAvailableCreateProgram() {
|
||||
var count = 0;
|
||||
for (const key in Programs) {
|
||||
// Non-creatable program
|
||||
if (Programs[key].create == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Already has program
|
||||
if (Player.hasProgram(Programs[key].name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Does not meet requirements
|
||||
if (!Programs[key].create.req(Player)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if (Player.firstProgramAvailable === false && count > 0) {
|
||||
Player.firstProgramAvailable = true;
|
||||
document.getElementById("hacking-menu-header").click();
|
||||
document.getElementById("hacking-menu-header").click();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function initCreateProgramButtons() {
|
||||
const createProgramList = document.getElementById("create-program-list");
|
||||
for (const key in Programs) {
|
||||
if (Programs[key].create === null) {
|
||||
continue;
|
||||
}
|
||||
const elem = createElement("a", {
|
||||
class: "a-link-button",
|
||||
id: Programs[key].htmlID(),
|
||||
innerText: Programs[key].name,
|
||||
tooltip: Programs[key].create.tooltip,
|
||||
});
|
||||
aLinks[key] = elem;
|
||||
createProgramList.appendChild(elem);
|
||||
}
|
||||
|
||||
for (const key in aLinks) {
|
||||
const p = Programs[key];
|
||||
aLinks[key].addEventListener("click", function () {
|
||||
Player.startCreateProgramWork(p.name, p.create.time, p.create.level);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { displayCreateProgramContent, getNumAvailableCreateProgram, initCreateProgramButtons };
|
25
src/Programs/ProgramHelpers.ts
Normal file
25
src/Programs/ProgramHelpers.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Programs } from "./Programs";
|
||||
import { Program } from "./Program";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { createElement } from "../../utils/uiHelpers/createElement";
|
||||
|
||||
//Returns the programs this player can create.
|
||||
export function getAvailableCreatePrograms(player: IPlayer): Program[] {
|
||||
const programs: Program[] = [];
|
||||
for (const key in Programs) {
|
||||
// Non-creatable program
|
||||
const create = Programs[key].create;
|
||||
if (create == null) continue;
|
||||
|
||||
// Already has program
|
||||
if (player.hasProgram(Programs[key].name)) continue;
|
||||
|
||||
// Does not meet requirements
|
||||
if (!create.req(player)) continue;
|
||||
|
||||
programs.push(Programs[key]);
|
||||
}
|
||||
|
||||
return programs;
|
||||
}
|
48
src/Programs/ui/ProgramsRoot.tsx
Normal file
48
src/Programs/ui/ProgramsRoot.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Programs } from "../Programs";
|
||||
import { getAvailableCreatePrograms } from "../ProgramHelpers";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function ProgramsRoot(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 1000);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="create-program-container">
|
||||
<p id="create-program-page-text">
|
||||
This page displays any programs that you are able to create. Writing the code for a program takes time, which
|
||||
can vary based on how complex the program is. If you are working on creating a program you can cancel at any
|
||||
time. Your progress will be saved and you can continue later.
|
||||
</p>
|
||||
|
||||
<ul id="create-program-list">
|
||||
{getAvailableCreatePrograms(props.player).map((program) => {
|
||||
const create = program.create;
|
||||
if (create === null) return <></>;
|
||||
|
||||
return (
|
||||
<a
|
||||
key={program.name}
|
||||
className="a-link-button tooltip"
|
||||
onClick={() => props.player.startCreateProgramWork(program.name, create.time, create.level)}
|
||||
>
|
||||
{program.name}
|
||||
<span className="tooltiptext">{create.tooltip}</span>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
1
src/SaveObject.d.ts
vendored
Normal file
1
src/SaveObject.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare const saveObject: any;
|
269
src/Sidebar/ui/SidebarRoot.tsx
Normal file
269
src/Sidebar/ui/SidebarRoot.tsx
Normal file
@ -0,0 +1,269 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../../InteractiveTutorial";
|
||||
import { getAvailableCreatePrograms } from "../../Programs/ProgramHelpers";
|
||||
import { ICorporation } from "../../Corporation/ICorporation";
|
||||
import { IGang } from "../../Gang/IGang";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
|
||||
export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
const [divisionName, setDivisionName] = useState("Overview");
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 20);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
const [hackingOpen, setHackingOpen] = useState(true);
|
||||
const [characterOpen, setCharacterOpen] = useState(true);
|
||||
const [worldOpen, setWorldOpen] = useState(true);
|
||||
const [helpOpen, setHelpOpen] = useState(true);
|
||||
|
||||
const flashTerminal =
|
||||
ITutorial.currStep === iTutorialSteps.CharacterGoToTerminalPage ||
|
||||
ITutorial.currStep === iTutorialSteps.ActiveScriptsPage;
|
||||
|
||||
const flashStats = ITutorial.currStep === iTutorialSteps.GoToCharacterPage;
|
||||
|
||||
const flashActiveScripts = ITutorial.currStep === iTutorialSteps.TerminalGoToActiveScriptsPage;
|
||||
|
||||
const flashHacknet = ITutorial.currStep === iTutorialSteps.GoToHacknetNodesPage;
|
||||
|
||||
const flashCity = ITutorial.currStep === iTutorialSteps.HacknetNodesGoToWorldPage;
|
||||
|
||||
const flashTutorial = ITutorial.currStep === iTutorialSteps.WorldDescription;
|
||||
|
||||
function clickTerminal() {
|
||||
props.engine.loadTerminalContent();
|
||||
if (flashTerminal) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickStats() {
|
||||
props.engine.loadTerminalContent();
|
||||
if (flashStats) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickActiveScripts() {
|
||||
props.engine.loadActiveScriptsContent();
|
||||
if (flashActiveScripts) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickHacknet() {
|
||||
props.engine.loadHacknetNodesContent();
|
||||
if (flashHacknet) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickCity() {
|
||||
props.engine.loadLocationContent();
|
||||
if (flashCity) iTutorialNextStep();
|
||||
}
|
||||
|
||||
function clickTutorial() {
|
||||
props.engine.loadTutorialContent();
|
||||
if (flashTutorial) iTutorialNextStep();
|
||||
}
|
||||
|
||||
const programCount = getAvailableCreatePrograms(props.player).length;
|
||||
const canCreateProgram =
|
||||
programCount > 0 ||
|
||||
props.player.augmentations.length > 0 ||
|
||||
props.player.queuedAugmentations.length > 0 ||
|
||||
props.player.sourceFiles.length > 0;
|
||||
|
||||
const canOpenFactions =
|
||||
props.player.factionInvitations.length > 0 ||
|
||||
props.player.factions.length > 0 ||
|
||||
props.player.augmentations.length > 0 ||
|
||||
props.player.queuedAugmentations.length > 0 ||
|
||||
props.player.sourceFiles.length > 0;
|
||||
|
||||
const canOpenAugmentations =
|
||||
props.player.augmentations.length > 0 ||
|
||||
props.player.queuedAugmentations.length > 0 ||
|
||||
props.player.sourceFiles.length > 0;
|
||||
|
||||
const canOpenSleeves = props.player.sleeves.length > 0;
|
||||
|
||||
const canCorporation = props.player.corporation != null;
|
||||
const canGang = props.player.gang != null;
|
||||
|
||||
return (
|
||||
<ul id="mainmenu" className="mainmenu noscrollbar noselect">
|
||||
{/* Hacking dropdown */}
|
||||
<li className="menu-header">
|
||||
<button
|
||||
id="hacking-menu-header"
|
||||
className={
|
||||
"noselect mainmenu-accordion-header" +
|
||||
(hackingOpen ? " opened" : "") +
|
||||
(flashTerminal ? " flashing-button" : "")
|
||||
}
|
||||
onClick={() => setHackingOpen((old) => !old)}
|
||||
>
|
||||
Hacking
|
||||
</button>
|
||||
</li>
|
||||
{hackingOpen && (
|
||||
<>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashTerminal ? "flashing-button" : ""} onClick={clickTerminal}>
|
||||
Terminal
|
||||
</button>
|
||||
</li>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadScriptEditorContent()}>Create Script</button>
|
||||
</li>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashActiveScripts ? "flashing-button" : ""} onClick={clickActiveScripts}>
|
||||
Active Scripts
|
||||
</button>
|
||||
</li>
|
||||
{canCreateProgram && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className="notification" onClick={() => props.engine.loadCreateProgramContent()}>
|
||||
Create Program
|
||||
{programCount > 0 && <span className="badge">{programCount}</span>}
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Character dropdown */}
|
||||
<li className="menu-header">
|
||||
<button
|
||||
id="character-menu-header"
|
||||
className={"noselect mainmenu-accordion-header" + (characterOpen ? " opened" : "")}
|
||||
onClick={() => setCharacterOpen((old) => !old)}
|
||||
>
|
||||
Character
|
||||
</button>
|
||||
</li>
|
||||
{characterOpen && (
|
||||
<>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashStats ? "flashing-button" : ""} onClick={clickStats}>
|
||||
Stats
|
||||
</button>
|
||||
</li>
|
||||
{canOpenFactions && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className="notification" onClick={() => props.engine.loadFactionsContent()}>
|
||||
Factions
|
||||
{props.player.factionInvitations.length > 0 && (
|
||||
<span className="badge">{props.player.factionInvitations.length}</span>
|
||||
)}
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
{canOpenAugmentations && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className="notification" onClick={() => props.engine.loadAugmentationsContent()}>
|
||||
Augmentations
|
||||
{props.player.queuedAugmentations.length > 0 && (
|
||||
<span className="badge">{props.player.queuedAugmentations.length}</span>
|
||||
)}
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashHacknet ? "flashing-button" : ""} onClick={clickHacknet}>
|
||||
Hacknet
|
||||
</button>
|
||||
</li>
|
||||
{canOpenSleeves && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadSleevesContent()}>Sleeves</button>
|
||||
</li>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{/* World dropdown */}
|
||||
<li className="menu-header">
|
||||
<button
|
||||
id="world-menu-header"
|
||||
className={"noselect mainmenu-accordion-header" + (worldOpen ? " opened" : "")}
|
||||
onClick={() => setWorldOpen((old) => !old)}
|
||||
>
|
||||
World
|
||||
</button>
|
||||
</li>
|
||||
|
||||
{worldOpen && (
|
||||
<>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashCity ? "flashing-button" : ""} onClick={clickCity}>
|
||||
City
|
||||
</button>
|
||||
</li>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadTravelContent()}>Travel</button>
|
||||
</li>
|
||||
{props.player.companyName !== "" && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadJobContent()}>Job</button>
|
||||
</li>
|
||||
)}
|
||||
{props.player.hasWseAccount && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadStockMarketContent()}>Stock Market</button>
|
||||
</li>
|
||||
)}
|
||||
{props.player.bladeburner && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadBladeburnerContent()}>Bladeburner</button>
|
||||
</li>
|
||||
)}
|
||||
{canCorporation && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadCorporationContent()}>Corp</button>
|
||||
</li>
|
||||
)}
|
||||
{canGang && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadGangContent()}>Gang</button>
|
||||
</li>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<li className="menu-header">
|
||||
<button
|
||||
id="help-menu-header"
|
||||
className={"noselect mainmenu-accordion-header" + (helpOpen ? " opened" : "")}
|
||||
onClick={() => setHelpOpen((old) => !old)}
|
||||
>
|
||||
Help
|
||||
</button>
|
||||
</li>
|
||||
{helpOpen && (
|
||||
<>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadMilestonesContent()}>Milestones</button>
|
||||
</li>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashTutorial ? "flashing-button" : ""} onClick={clickTutorial}>
|
||||
Tutorial
|
||||
</button>
|
||||
</li>
|
||||
{/*<li className="mainmenu-accordion-panel">
|
||||
<button>Options</button>
|
||||
</li>*/}
|
||||
{process.env.NODE_ENV === "development" && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadDevMenuContent()}>Dev</button>
|
||||
</li>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
}
|
@ -307,7 +307,7 @@ export function processStockPrices(numCycles = 1): void {
|
||||
|
||||
let stockMarketContainer: HTMLElement | null = null;
|
||||
function setStockMarketContainer(): void {
|
||||
stockMarketContainer = document.getElementById("stock-market-container");
|
||||
stockMarketContainer = document.getElementById("generic-react-container");
|
||||
document.removeEventListener("DOMContentLoaded", setStockMarketContainer);
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ export class StockMarketRoot extends React.Component<IProps, IState> {
|
||||
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<div>
|
||||
<div id="stock-market-container">
|
||||
<InfoAndPurchases initStockMarket={this.props.initStockMarket} p={this.props.p} rerender={this.rerender} />
|
||||
{this.props.p.hasWseAccount && (
|
||||
<StockTickers
|
||||
|
@ -64,7 +64,7 @@ import * as FileSaver from "file-saver";
|
||||
import * as libarg from "arg";
|
||||
import React from "react";
|
||||
|
||||
function postNetburnerText() {
|
||||
function postVersion() {
|
||||
post("Bitburner v" + CONSTANTS.Version);
|
||||
}
|
||||
|
||||
@ -2616,4 +2616,4 @@ let Terminal = {
|
||||
},
|
||||
};
|
||||
|
||||
export { postNetburnerText, Terminal };
|
||||
export { postVersion, Terminal };
|
||||
|
99
src/Tutorial/ui/TutorialRoot.tsx
Normal file
99
src/Tutorial/ui/TutorialRoot.tsx
Normal file
@ -0,0 +1,99 @@
|
||||
import React from "react";
|
||||
|
||||
export function TutorialRoot(): React.ReactElement {
|
||||
return (
|
||||
<div id="tutorial-container">
|
||||
<h1>Tutorial (AKA Links to Documentation)</h1>
|
||||
<a
|
||||
id="tutorial-getting-started-link"
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html"
|
||||
>
|
||||
Getting Started
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html"
|
||||
>
|
||||
Servers & Networking
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html"
|
||||
>
|
||||
Hacking
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html"
|
||||
>
|
||||
Scripts
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a className="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/netscript.html">
|
||||
Netscript Programming Language
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html"
|
||||
>
|
||||
Traveling
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html"
|
||||
>
|
||||
Companies
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html"
|
||||
>
|
||||
Infiltration
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html"
|
||||
>
|
||||
Factions
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a
|
||||
className="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html"
|
||||
>
|
||||
Augmentations
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a className="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
|
||||
Keyboard Shortcuts
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
676
src/engine.jsx
676
src/engine.jsx
@ -5,7 +5,13 @@
|
||||
*/
|
||||
import { convertTimeMsToTimeElapsedString, replaceAt } from "../utils/StringHelperFunctions";
|
||||
import { Augmentations } from "./Augmentation/Augmentations";
|
||||
import { initAugmentations, displayAugmentationsContent } from "./Augmentation/AugmentationHelpers";
|
||||
import {
|
||||
initAugmentations,
|
||||
displayAugmentationsContent,
|
||||
installAugmentations,
|
||||
} from "./Augmentation/AugmentationHelpers";
|
||||
import { onExport } from "./ExportBonus";
|
||||
import { AugmentationsRoot } from "./Augmentation/ui/Root";
|
||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
||||
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||
@ -15,12 +21,13 @@ import { generateRandomContract } from "./CodingContractGenerator";
|
||||
import { initCompanies } from "./Company/Companies";
|
||||
import { Corporation } from "./Corporation/Corporation";
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { createDevMenu, closeDevMenu } from "./DevMenu";
|
||||
import { DevMenuRoot } from "./DevMenu";
|
||||
import { Factions, initFactions } from "./Faction/Factions";
|
||||
import { processPassiveFactionRepGain, inviteToFaction } from "./Faction/FactionHelpers";
|
||||
import { FactionList } from "./Faction/ui/FactionList";
|
||||
import { Root as BladeburnerRoot } from "./Bladeburner/ui/Root";
|
||||
import { Root as GangRoot } from "./Gang/ui/Root";
|
||||
import { SidebarRoot } from "./Sidebar/ui/SidebarRoot";
|
||||
import { CorporationRoot } from "./Corporation/ui/CorporationRoot";
|
||||
import { ResleeveRoot } from "./PersonObjects/Resleeving/ui/ResleeveRoot";
|
||||
import { SleeveRoot } from "./PersonObjects/Sleeve/ui/SleeveRoot";
|
||||
@ -42,11 +49,7 @@ import { workerScripts } from "./Netscript/WorkerScripts";
|
||||
import { loadAllRunningScripts, updateOnlineScriptTimes } from "./NetscriptWorker";
|
||||
import { Player } from "./Player";
|
||||
import { prestigeAugmentation } from "./Prestige";
|
||||
import {
|
||||
displayCreateProgramContent,
|
||||
getNumAvailableCreateProgram,
|
||||
initCreateProgramButtons,
|
||||
} from "./Programs/ProgramHelpers";
|
||||
import { ProgramsRoot } from "./Programs/ui/ProgramsRoot";
|
||||
import { redPillFlag } from "./RedPill";
|
||||
import { saveObject, loadGame } from "./SaveObject";
|
||||
import { Root as ScriptEditorRoot } from "./ScriptEditor/ui/Root";
|
||||
@ -55,8 +58,9 @@ import { Settings } from "./Settings/Settings";
|
||||
import { updateSourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||
import { initSpecialServerIps } from "./Server/SpecialServerIps";
|
||||
import { initSymbolToStockMap, processStockPrices, displayStockMarketContent } from "./StockMarket/StockMarket";
|
||||
import { displayMilestonesContent } from "./Milestones/MilestoneHelpers";
|
||||
import { Terminal, postNetburnerText } from "./Terminal";
|
||||
import { MilestonesRoot } from "./Milestones/ui/MilestonesRoot";
|
||||
import { Terminal, postVersion } from "./Terminal";
|
||||
import { TutorialRoot } from "./Tutorial/ui/TutorialRoot";
|
||||
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
||||
|
||||
import { createStatusText } from "./ui/createStatusText";
|
||||
@ -173,33 +177,15 @@ const Engine = {
|
||||
// Display objects
|
||||
// TODO-Refactor this into its own component
|
||||
Display: {
|
||||
// Generic page that most react loads into.
|
||||
content: null,
|
||||
// Main menu content
|
||||
terminalContent: null,
|
||||
characterContent: null,
|
||||
scriptEditorContent: null,
|
||||
activeScriptsContent: null,
|
||||
hacknetNodesContent: null,
|
||||
createProgramContent: null,
|
||||
factionsContent: null,
|
||||
factionContent: null,
|
||||
augmentationsContent: null,
|
||||
milestonesContent: null,
|
||||
tutorialContent: null,
|
||||
infiltrationContent: null,
|
||||
stockMarketContent: null,
|
||||
gangContent: null,
|
||||
bladeburnerContent: null,
|
||||
resleeveContent: null,
|
||||
sleeveContent: null,
|
||||
corporationContent: null,
|
||||
locationContent: null,
|
||||
workInProgressContent: null,
|
||||
redPillContent: null,
|
||||
cinematicTextContent: null,
|
||||
missionContent: null,
|
||||
|
||||
// Character info
|
||||
characterInfo: null,
|
||||
},
|
||||
|
||||
indexedDb: undefined,
|
||||
@ -217,104 +203,115 @@ const Engine = {
|
||||
|
||||
loadCharacterContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.characterContent.style.display = "block";
|
||||
Engine.updateCharacterInfo();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.CharacterInfo);
|
||||
ReactDOM.render(<CharacterInfo player={Player} />, Engine.Display.content);
|
||||
MainMenuLinks.Stats.classList.add("active");
|
||||
},
|
||||
|
||||
loadScriptEditorContent: function (filename = "", code = "") {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.scriptEditorContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.ScriptEditor);
|
||||
|
||||
MainMenuLinks.ScriptEditor.classList.add("active");
|
||||
ReactDOM.render(
|
||||
<ScriptEditorRoot filename={filename} code={code} player={Player} engine={this} />,
|
||||
Engine.Display.scriptEditorContent,
|
||||
Engine.Display.content,
|
||||
);
|
||||
|
||||
MainMenuLinks.ScriptEditor.classList.add("active");
|
||||
},
|
||||
|
||||
loadActiveScriptsContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.activeScriptsContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.ActiveScripts);
|
||||
ReactDOM.render(
|
||||
<ActiveScriptsRoot p={Player} workerScripts={workerScripts} />,
|
||||
Engine.Display.activeScriptsContent,
|
||||
);
|
||||
MainMenuLinks.ActiveScripts.classList.add("active");
|
||||
ReactDOM.render(<ActiveScriptsRoot p={Player} workerScripts={workerScripts} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadHacknetNodesContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.hacknetNodesContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.HacknetNodes);
|
||||
ReactDOM.render(<HacknetRoot player={Player} />, Engine.Display.hacknetNodesContent);
|
||||
MainMenuLinks.HacknetNodes.classList.add("active");
|
||||
ReactDOM.render(<HacknetRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadCreateProgramContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.createProgramContent.style.display = "block";
|
||||
displayCreateProgramContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.CreateProgram);
|
||||
MainMenuLinks.CreateProgram.classList.add("active");
|
||||
ReactDOM.render(<ProgramsRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadFactionsContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.factionsContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Factions);
|
||||
ReactDOM.render(<FactionList player={Player} engine={this} />, Engine.Display.factionsContent);
|
||||
MainMenuLinks.Factions.classList.add("active");
|
||||
ReactDOM.render(<FactionList player={Player} engine={this} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadFactionContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.factionContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Faction);
|
||||
},
|
||||
|
||||
loadAugmentationsContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.augmentationsContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Augmentations);
|
||||
displayAugmentationsContent(Engine.Display.augmentationsContent);
|
||||
MainMenuLinks.Augmentations.classList.add("active");
|
||||
|
||||
function backup() {
|
||||
saveObject.exportGame();
|
||||
onExport(Player);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<AugmentationsRoot exportGameFn={backup} installAugmentationsFn={installAugmentations} />,
|
||||
Engine.Display.content,
|
||||
);
|
||||
},
|
||||
|
||||
loadMilestonesContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.milestonesContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Milestones);
|
||||
displayMilestonesContent();
|
||||
MainMenuLinks.Milestones.classList.add("active");
|
||||
ReactDOM.render(<MilestonesRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadTutorialContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.tutorialContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Tutorial);
|
||||
MainMenuLinks.Tutorial.classList.add("active");
|
||||
ReactDOM.render(<TutorialRoot />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadDevMenuContent: function () {
|
||||
Engine.hideAllContent();
|
||||
createDevMenu();
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
throw new Error("Cannot create Dev Menu because you are not in a dev build");
|
||||
}
|
||||
Engine.Display.content.style.display = "block";
|
||||
ReactDOM.render(<DevMenuRoot player={Player} engine={this} />, Engine.Display.content);
|
||||
routing.navigateTo(Page.DevMenu);
|
||||
MainMenuLinks.DevMenu.classList.add("active");
|
||||
},
|
||||
|
||||
loadLocationContent: function (initiallyInCity = true) {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.locationContent.style.display = "block";
|
||||
MainMenuLinks.City.classList.add("active");
|
||||
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Location);
|
||||
const rootComponent = <LocationRoot initiallyInCity={initiallyInCity} engine={Engine} p={Player} />;
|
||||
ReactDOM.render(rootComponent, Engine.Display.locationContent);
|
||||
MainMenuLinks.City.classList.add("active");
|
||||
ReactDOM.render(
|
||||
<LocationRoot initiallyInCity={initiallyInCity} engine={Engine} p={Player} />,
|
||||
Engine.Display.content,
|
||||
);
|
||||
},
|
||||
|
||||
loadTravelContent: function () {
|
||||
@ -322,12 +319,10 @@ const Engine = {
|
||||
// and make sure that the 'City' main menu link doesnt become 'active'
|
||||
Engine.hideAllContent();
|
||||
Player.gotoLocation(LocationName.TravelAgency);
|
||||
Engine.Display.locationContent.style.display = "block";
|
||||
MainMenuLinks.Travel.classList.add("active");
|
||||
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Location);
|
||||
const rootComponent = <LocationRoot initiallyInCity={false} engine={Engine} p={Player} />;
|
||||
ReactDOM.render(rootComponent, Engine.Display.locationContent);
|
||||
MainMenuLinks.Travel.classList.add("active");
|
||||
ReactDOM.render(<LocationRoot initiallyInCity={false} engine={Engine} p={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadJobContent: function () {
|
||||
@ -341,30 +336,31 @@ const Engine = {
|
||||
}
|
||||
Engine.hideAllContent();
|
||||
Player.gotoLocation(Player.companyName);
|
||||
Engine.Display.locationContent.style.display = "block";
|
||||
MainMenuLinks.Job.classList.add("active");
|
||||
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Location);
|
||||
const rootComponent = <LocationRoot initiallyInCity={false} engine={Engine} p={Player} />;
|
||||
ReactDOM.render(rootComponent, Engine.Display.locationContent);
|
||||
MainMenuLinks.Job.classList.add("active");
|
||||
ReactDOM.render(<LocationRoot initiallyInCity={false} engine={Engine} p={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadWorkInProgressContent: function () {
|
||||
Engine.hideAllContent();
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
const mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.workInProgressContent.style.display = "block";
|
||||
routing.navigateTo(Page.WorkInProgress);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadRedPillContent: function () {
|
||||
Engine.hideAllContent();
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
const mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.redPillContent.style.display = "block";
|
||||
routing.navigateTo(Page.RedPill);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadCinematicTextContent: function () {
|
||||
Engine.hideAllContent();
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
@ -373,6 +369,7 @@ const Engine = {
|
||||
routing.navigateTo(Page.CinematicText);
|
||||
},
|
||||
|
||||
// TODO reactify
|
||||
loadInfiltrationContent: function (name, difficulty, maxLevel) {
|
||||
Engine.hideAllContent();
|
||||
const mainMenu = document.getElementById("mainmenu-container");
|
||||
@ -384,21 +381,19 @@ const Engine = {
|
||||
|
||||
loadStockMarketContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.stockMarketContent.style.display = "block";
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.StockMarket);
|
||||
MainMenuLinks.StockMarket.classList.add("active");
|
||||
displayStockMarketContent();
|
||||
},
|
||||
|
||||
loadGangContent: function () {
|
||||
if (!Player.inGang()) return;
|
||||
Engine.hideAllContent();
|
||||
if (Player.inGang()) {
|
||||
Engine.Display.gangContent.style.display = "block";
|
||||
routing.navigateTo(Page.Gang);
|
||||
ReactDOM.render(<GangRoot engine={this} gang={Player.gang} player={Player} />, Engine.Display.gangContent);
|
||||
} else {
|
||||
Engine.loadTerminalContent();
|
||||
routing.navigateTo(Page.Terminal);
|
||||
}
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Gang);
|
||||
MainMenuLinks.Gang.classList.add("active");
|
||||
ReactDOM.render(<GangRoot engine={this} gang={Player.gang} player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadMissionContent: function () {
|
||||
@ -412,120 +407,53 @@ const Engine = {
|
||||
loadCorporationContent: function () {
|
||||
if (!(Player.corporation instanceof Corporation)) return;
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Corporation);
|
||||
Engine.Display.corporationContent.style.display = "block";
|
||||
ReactDOM.render(<CorporationRoot corp={Player.corporation} player={Player} />, Engine.Display.corporationContent);
|
||||
MainMenuLinks.Corporation.classList.add("active");
|
||||
ReactDOM.render(<CorporationRoot corp={Player.corporation} player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadBladeburnerContent: function () {
|
||||
if (!(Player.bladeburner instanceof Bladeburner)) return;
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Bladeburner);
|
||||
Engine.Display.bladeburnerContent.style.display = "block";
|
||||
MainMenuLinks.Bladeburner.classList.add("active");
|
||||
ReactDOM.render(
|
||||
<BladeburnerRoot bladeburner={Player.bladeburner} player={Player} engine={this} />,
|
||||
Engine.Display.bladeburnerContent,
|
||||
Engine.Display.content,
|
||||
);
|
||||
MainMenuLinks.Bladeburner.classList.add("active");
|
||||
},
|
||||
|
||||
loadSleevesContent: function () {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.content.style.display = "block";
|
||||
routing.navigateTo(Page.Sleeves);
|
||||
Engine.Display.sleevesContent.style.display = "block";
|
||||
ReactDOM.render(<SleeveRoot player={Player} />, Engine.Display.sleevesContent);
|
||||
ReactDOM.render(<SleeveRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
loadResleevingContent: function () {
|
||||
Engine.hideAllContent();
|
||||
routing.navigateTo(Page.Resleeves);
|
||||
Engine.Display.resleeveContent.style.display = "block";
|
||||
ReactDOM.render(<ResleeveRoot player={Player} />, Engine.Display.resleeveContent);
|
||||
Engine.Display.content.style.display = "block";
|
||||
MainMenuLinks.City.classList.add("active");
|
||||
ReactDOM.render(<ResleeveRoot player={Player} />, Engine.Display.content);
|
||||
},
|
||||
|
||||
// Helper function that hides all content
|
||||
hideAllContent: function () {
|
||||
Engine.Display.terminalContent.style.display = "none";
|
||||
Engine.Display.characterContent.style.display = "none";
|
||||
Engine.Display.scriptEditorContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.scriptEditorContent);
|
||||
|
||||
Engine.Display.activeScriptsContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.activeScriptsContent);
|
||||
Engine.Display.content.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.content);
|
||||
|
||||
Engine.Display.infiltrationContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.infiltrationContent);
|
||||
|
||||
Engine.Display.hacknetNodesContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.hacknetNodesContent);
|
||||
|
||||
Engine.Display.createProgramContent.style.display = "none";
|
||||
|
||||
Engine.Display.factionsContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.factionsContent);
|
||||
|
||||
Engine.Display.factionContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.factionContent);
|
||||
|
||||
Engine.Display.augmentationsContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.augmentationsContent);
|
||||
|
||||
Engine.Display.milestonesContent.style.display = "none";
|
||||
Engine.Display.tutorialContent.style.display = "none";
|
||||
|
||||
Engine.Display.locationContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.locationContent);
|
||||
|
||||
Engine.Display.gangContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.gangContent);
|
||||
|
||||
Engine.Display.bladeburnerContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.bladeburnerContent);
|
||||
|
||||
Engine.Display.resleeveContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.resleeveContent);
|
||||
|
||||
Engine.Display.sleevesContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.sleevesContent);
|
||||
|
||||
Engine.Display.corporationContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.corporationContent);
|
||||
|
||||
Engine.Display.workInProgressContent.style.display = "none";
|
||||
Engine.Display.redPillContent.style.display = "none";
|
||||
Engine.Display.cinematicTextContent.style.display = "none";
|
||||
Engine.Display.stockMarketContent.style.display = "none";
|
||||
Engine.Display.missionContent.style.display = "none";
|
||||
|
||||
// Make nav menu tabs inactive
|
||||
Engine.inactivateMainMenuLinks();
|
||||
|
||||
// Close dev menu
|
||||
closeDevMenu();
|
||||
},
|
||||
|
||||
// Remove 'active' css class from all main menu links
|
||||
inactivateMainMenuLinks: function () {
|
||||
MainMenuLinks.Terminal.classList.remove("active");
|
||||
MainMenuLinks.ScriptEditor.classList.remove("active");
|
||||
MainMenuLinks.ActiveScripts.classList.remove("active");
|
||||
MainMenuLinks.CreateProgram.classList.remove("active");
|
||||
MainMenuLinks.Stats.classList.remove("active");
|
||||
MainMenuLinks.Factions.classList.remove("active");
|
||||
MainMenuLinks.Augmentations.classList.remove("active");
|
||||
MainMenuLinks.HacknetNodes.classList.remove("active");
|
||||
MainMenuLinks.Sleeves.classList.remove("active");
|
||||
MainMenuLinks.City.classList.remove("active");
|
||||
MainMenuLinks.Travel.classList.remove("active");
|
||||
MainMenuLinks.Job.classList.remove("active");
|
||||
MainMenuLinks.StockMarket.classList.remove("active");
|
||||
MainMenuLinks.Gang.classList.remove("active");
|
||||
MainMenuLinks.Bladeburner.classList.remove("active");
|
||||
MainMenuLinks.Corporation.classList.remove("active");
|
||||
MainMenuLinks.Gang.classList.remove("active");
|
||||
MainMenuLinks.Milestones.classList.remove("active");
|
||||
MainMenuLinks.Tutorial.classList.remove("active");
|
||||
MainMenuLinks.Options.classList.remove("active");
|
||||
MainMenuLinks.DevMenu.classList.remove("active");
|
||||
},
|
||||
|
||||
displayCharacterOverviewInfo: function () {
|
||||
@ -540,11 +468,6 @@ const Engine = {
|
||||
}
|
||||
},
|
||||
|
||||
/// Display character info
|
||||
updateCharacterInfo: function () {
|
||||
ReactDOM.render(CharacterInfo(Player), Engine.Display.characterInfo);
|
||||
},
|
||||
|
||||
// Main Game Loop
|
||||
idleTimer: function () {
|
||||
// Get time difference
|
||||
@ -676,7 +599,6 @@ const Engine = {
|
||||
autoSaveCounter: 300,
|
||||
updateSkillLevelsCounter: 10,
|
||||
updateDisplays: 3,
|
||||
updateDisplaysMed: 9,
|
||||
updateDisplaysLong: 15,
|
||||
updateActiveScriptsDisplay: 5,
|
||||
createProgramNotifications: 10,
|
||||
@ -718,86 +640,11 @@ const Engine = {
|
||||
Engine.Counters.updateSkillLevelsCounter = 10;
|
||||
}
|
||||
|
||||
if (Engine.Counters.updateActiveScriptsDisplay <= 0) {
|
||||
if (routing.isOn(Page.ActiveScripts)) {
|
||||
ReactDOM.render(
|
||||
<ActiveScriptsRoot p={Player} workerScripts={workerScripts} />,
|
||||
Engine.Display.activeScriptsContent,
|
||||
);
|
||||
}
|
||||
|
||||
Engine.Counters.updateActiveScriptsDisplay = 5;
|
||||
}
|
||||
|
||||
if (Engine.Counters.updateDisplays <= 0) {
|
||||
Engine.displayCharacterOverviewInfo();
|
||||
if (routing.isOn(Page.CreateProgram)) {
|
||||
displayCreateProgramContent();
|
||||
}
|
||||
|
||||
Engine.Counters.updateDisplays = 3;
|
||||
}
|
||||
|
||||
if (Engine.Counters.updateDisplaysMed <= 0) {
|
||||
if (routing.isOn(Page.CharacterInfo)) {
|
||||
Engine.updateCharacterInfo();
|
||||
}
|
||||
Engine.Counters.updateDisplaysMed = 9;
|
||||
}
|
||||
|
||||
if (Engine.Counters.createProgramNotifications <= 0) {
|
||||
var num = getNumAvailableCreateProgram();
|
||||
var elem = document.getElementById("create-program-notification");
|
||||
if (num > 0) {
|
||||
elem.innerHTML = num;
|
||||
elem.setAttribute("class", "notification-on");
|
||||
} else {
|
||||
elem.innerHTML = "";
|
||||
elem.setAttribute("class", "notification-off");
|
||||
}
|
||||
Engine.Counters.createProgramNotifications = 10;
|
||||
}
|
||||
|
||||
if (Engine.Counters.augmentationsNotifications <= 0) {
|
||||
var num = Player.queuedAugmentations.length;
|
||||
var elem = document.getElementById("augmentations-notification");
|
||||
if (num > 0) {
|
||||
elem.innerHTML = num;
|
||||
elem.setAttribute("class", "notification-on");
|
||||
} else {
|
||||
elem.innerHTML = "";
|
||||
elem.setAttribute("class", "notification-off");
|
||||
}
|
||||
Engine.Counters.augmentationsNotifications = 10;
|
||||
}
|
||||
|
||||
if (Engine.Counters.checkFactionInvitations <= 0) {
|
||||
var invitedFactions = Player.checkForFactionInvitations();
|
||||
if (invitedFactions.length > 0) {
|
||||
if (Player.firstFacInvRecvd === false) {
|
||||
Player.firstFacInvRecvd = true;
|
||||
document.getElementById("factions-tab").style.display = "list-item";
|
||||
document.getElementById("character-menu-header").click();
|
||||
document.getElementById("character-menu-header").click();
|
||||
}
|
||||
|
||||
var randFaction = invitedFactions[Math.floor(Math.random() * invitedFactions.length)];
|
||||
inviteToFaction(randFaction);
|
||||
}
|
||||
|
||||
const num = Player.factionInvitations.length;
|
||||
const elem = document.getElementById("factions-notification");
|
||||
if (num > 0) {
|
||||
elem.innerHTML = num;
|
||||
elem.setAttribute("class", "notification-on");
|
||||
} else {
|
||||
elem.innerHTML = "";
|
||||
elem.setAttribute("class", "notification-off");
|
||||
}
|
||||
|
||||
Engine.Counters.checkFactionInvitations = 100;
|
||||
}
|
||||
|
||||
if (Engine.Counters.passiveFactionGrowth <= 0) {
|
||||
var adjustedCycles = Math.floor(5 - Engine.Counters.passiveFactionGrowth);
|
||||
processPassiveFactionRepGain(adjustedCycles);
|
||||
@ -872,29 +719,6 @@ const Engine = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Collapses a main menu header. Used when initializing the game.
|
||||
* @param elems {HTMLElement[]} Elements under header
|
||||
*/
|
||||
closeMainMenuHeader: function (elems) {
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
elems[i].style.maxHeight = null;
|
||||
elems[i].style.opacity = 0;
|
||||
elems[i].style.pointerEvents = "none";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Expands a main menu header. Used when initializing the game.
|
||||
* @param elems {HTMLElement[]} Elements under header
|
||||
*/
|
||||
openMainMenuHeader: function (elems) {
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
elems[i].style.maxHeight = elems[i].scrollHeight + "px";
|
||||
elems[i].style.display = "block";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Used in game when clicking on a main menu header (NOT used for initialization)
|
||||
* @param open {boolean} Whether header is being opened or closed
|
||||
@ -926,27 +750,6 @@ const Engine = {
|
||||
},
|
||||
|
||||
load: function (saveString) {
|
||||
// Initialize main menu accordion panels to all start as "open"
|
||||
const terminal = document.getElementById("terminal-tab");
|
||||
const createScript = document.getElementById("create-script-tab");
|
||||
const activeScripts = document.getElementById("active-scripts-tab");
|
||||
const createProgram = document.getElementById("create-program-tab");
|
||||
const stats = document.getElementById("stats-tab");
|
||||
const factions = document.getElementById("factions-tab");
|
||||
const augmentations = document.getElementById("augmentations-tab");
|
||||
const hacknetnodes = document.getElementById("hacknet-nodes-tab");
|
||||
const city = document.getElementById("city-tab");
|
||||
const travel = document.getElementById("travel-tab");
|
||||
const job = document.getElementById("job-tab");
|
||||
const stockmarket = document.getElementById("stock-market-tab");
|
||||
const bladeburner = document.getElementById("bladeburner-tab");
|
||||
const corp = document.getElementById("corporation-tab");
|
||||
const gang = document.getElementById("gang-tab");
|
||||
const milestones = document.getElementById("milestones-tab");
|
||||
const tutorial = document.getElementById("tutorial-tab");
|
||||
const options = document.getElementById("options-tab");
|
||||
const dev = document.getElementById("dev-tab");
|
||||
|
||||
// Load game from save or create new game
|
||||
if (loadGame(saveString)) {
|
||||
initBitNodeMultipliers(Player);
|
||||
@ -1084,66 +887,6 @@ const Engine = {
|
||||
{Reputation(offlineReputation)} divided amongst your factions.
|
||||
</>,
|
||||
);
|
||||
// Close main menu accordions for loaded game
|
||||
var visibleMenuTabs = [
|
||||
terminal,
|
||||
createScript,
|
||||
activeScripts,
|
||||
stats,
|
||||
hacknetnodes,
|
||||
city,
|
||||
milestones,
|
||||
tutorial,
|
||||
options,
|
||||
dev,
|
||||
];
|
||||
if (Player.firstFacInvRecvd) {
|
||||
visibleMenuTabs.push(factions);
|
||||
} else {
|
||||
factions.style.display = "none";
|
||||
}
|
||||
if (Player.firstAugPurchased) {
|
||||
visibleMenuTabs.push(augmentations);
|
||||
} else {
|
||||
augmentations.style.display = "none";
|
||||
}
|
||||
if (Player.companyName !== "") {
|
||||
visibleMenuTabs.push(job);
|
||||
} else {
|
||||
job.style.display = "none";
|
||||
}
|
||||
if (Player.firstTimeTraveled) {
|
||||
visibleMenuTabs.push(travel);
|
||||
} else {
|
||||
travel.style.display = "none";
|
||||
}
|
||||
if (Player.firstProgramAvailable) {
|
||||
visibleMenuTabs.push(createProgram);
|
||||
} else {
|
||||
createProgram.style.display = "none";
|
||||
}
|
||||
if (Player.hasWseAccount) {
|
||||
visibleMenuTabs.push(stockmarket);
|
||||
} else {
|
||||
stockmarket.style.display = "none";
|
||||
}
|
||||
if (Player.bladeburner instanceof Bladeburner) {
|
||||
visibleMenuTabs.push(bladeburner);
|
||||
} else {
|
||||
bladeburner.style.display = "none";
|
||||
}
|
||||
if (Player.corporation instanceof Corporation) {
|
||||
visibleMenuTabs.push(corp);
|
||||
} else {
|
||||
corp.style.display = "none";
|
||||
}
|
||||
if (Player.inGang()) {
|
||||
visibleMenuTabs.push(gang);
|
||||
} else {
|
||||
gang.style.display = "none";
|
||||
}
|
||||
|
||||
Engine.closeMainMenuHeader(visibleMenuTabs);
|
||||
} else {
|
||||
// No save found, start new game
|
||||
initBitNodeMultipliers(Player);
|
||||
@ -1158,115 +901,27 @@ const Engine = {
|
||||
initMessages();
|
||||
updateSourceFileFlags(Player);
|
||||
|
||||
// Open main menu accordions for new game
|
||||
const hackingHdr = document.getElementById("hacking-menu-header");
|
||||
hackingHdr.classList.toggle("opened");
|
||||
const characterHdr = document.getElementById("character-menu-header");
|
||||
characterHdr.classList.toggle("opened");
|
||||
const worldHdr = document.getElementById("world-menu-header");
|
||||
worldHdr.classList.toggle("opened");
|
||||
const helpHdr = document.getElementById("help-menu-header");
|
||||
helpHdr.classList.toggle("opened");
|
||||
|
||||
// Hide tabs that wont be revealed until later
|
||||
factions.style.display = "none";
|
||||
augmentations.style.display = "none";
|
||||
job.style.display = "none";
|
||||
stockmarket.style.display = "none";
|
||||
travel.style.display = "none";
|
||||
createProgram.style.display = "none";
|
||||
bladeburner.style.display = "none";
|
||||
corp.style.display = "none";
|
||||
gang.style.display = "none";
|
||||
dev.style.display = "none";
|
||||
|
||||
Engine.openMainMenuHeader([
|
||||
terminal,
|
||||
createScript,
|
||||
activeScripts,
|
||||
stats,
|
||||
hacknetnodes,
|
||||
city,
|
||||
milestones,
|
||||
tutorial,
|
||||
options,
|
||||
]);
|
||||
|
||||
// Start interactive tutorial
|
||||
iTutorialStart();
|
||||
removeLoadingScreen();
|
||||
}
|
||||
|
||||
ReactDOM.render(<SidebarRoot engine={this} player={Player} />, document.getElementById("sidebar"));
|
||||
// Initialize labels on game settings
|
||||
setSettingsLabels();
|
||||
Terminal.resetTerminalInput();
|
||||
},
|
||||
|
||||
setDisplayElements: function () {
|
||||
Engine.Display.content = document.getElementById("generic-react-container");
|
||||
Engine.Display.content.style.display = "none";
|
||||
// Content elements
|
||||
Engine.Display.terminalContent = document.getElementById("terminal-container");
|
||||
routing.navigateTo(Page.Terminal);
|
||||
|
||||
Engine.Display.characterContent = document.getElementById("character-container");
|
||||
Engine.Display.characterContent.style.display = "none";
|
||||
|
||||
Engine.Display.scriptEditorContent = document.getElementById("script-editor-container");
|
||||
Engine.Display.scriptEditorContent.style.display = "none";
|
||||
|
||||
Engine.Display.activeScriptsContent = document.getElementById("active-scripts-container");
|
||||
Engine.Display.activeScriptsContent.style.display = "none";
|
||||
|
||||
Engine.Display.hacknetNodesContent = document.getElementById("hacknet-nodes-container");
|
||||
Engine.Display.hacknetNodesContent.style.display = "none";
|
||||
|
||||
Engine.Display.createProgramContent = document.getElementById("create-program-container");
|
||||
Engine.Display.createProgramContent.style.display = "none";
|
||||
|
||||
Engine.Display.factionsContent = document.getElementById("factions-container");
|
||||
Engine.Display.factionsContent.style.display = "none";
|
||||
|
||||
Engine.Display.factionContent = document.getElementById("faction-container");
|
||||
Engine.Display.factionContent.style.display = "none";
|
||||
|
||||
Engine.Display.augmentationsContent = document.getElementById("augmentations-container");
|
||||
Engine.Display.augmentationsContent.style.display = "none";
|
||||
|
||||
Engine.Display.milestonesContent = document.getElementById("milestones-container");
|
||||
Engine.Display.milestonesContent.style.display = "none";
|
||||
|
||||
Engine.Display.tutorialContent = document.getElementById("tutorial-container");
|
||||
Engine.Display.tutorialContent.style.display = "none";
|
||||
|
||||
Engine.Display.infiltrationContent = document.getElementById("infiltration-container");
|
||||
Engine.Display.infiltrationContent.style.display = "none";
|
||||
|
||||
Engine.Display.stockMarketContent = document.getElementById("stock-market-container");
|
||||
Engine.Display.stockMarketContent.style.display = "none";
|
||||
|
||||
Engine.Display.gangContent = document.getElementById("gang-container");
|
||||
Engine.Display.gangContent.style.display = "none";
|
||||
|
||||
Engine.Display.bladeburnerContent = document.getElementById("bladeburner-container");
|
||||
Engine.Display.bladeburnerContent.style.display = "none";
|
||||
|
||||
Engine.Display.resleeveContent = document.getElementById("resleeve-container");
|
||||
Engine.Display.resleeveContent.style.display = "none";
|
||||
|
||||
Engine.Display.sleevesContent = document.getElementById("sleeves-container");
|
||||
Engine.Display.sleevesContent.style.display = "none";
|
||||
|
||||
Engine.Display.corporationContent = document.getElementById("corporation-container");
|
||||
Engine.Display.corporationContent.style.display = "none";
|
||||
|
||||
Engine.Display.missionContent = document.getElementById("mission-container");
|
||||
Engine.Display.missionContent.style.display = "none";
|
||||
|
||||
// Character info
|
||||
Engine.Display.characterInfo = document.getElementById("character-content");
|
||||
|
||||
// Location page (page that shows up when you visit a specific location in World)
|
||||
Engine.Display.locationContent = document.getElementById("location-container");
|
||||
Engine.Display.locationContent.style.display = "none";
|
||||
|
||||
// Work In Progress
|
||||
Engine.Display.workInProgressContent = document.getElementById("work-in-progress-container");
|
||||
Engine.Display.workInProgressContent.style.display = "none";
|
||||
@ -1275,19 +930,12 @@ const Engine = {
|
||||
Engine.Display.redPillContent = document.getElementById("red-pill-container");
|
||||
Engine.Display.redPillContent.style.display = "none";
|
||||
|
||||
Engine.Display.infiltrationContent = document.getElementById("infiltration-container");
|
||||
Engine.Display.infiltrationContent.style.display = "none";
|
||||
|
||||
// Cinematic Text
|
||||
Engine.Display.cinematicTextContent = document.getElementById("cinematic-text-container");
|
||||
Engine.Display.cinematicTextContent.style.display = "none";
|
||||
|
||||
// Initialize references to main menu links
|
||||
if (!initializeMainMenuLinks()) {
|
||||
const errorMsg =
|
||||
"Failed to initialize Main Menu Links. Please try refreshing the page. " +
|
||||
"If that doesn't work, report the issue to the developer";
|
||||
exceptionAlert(new Error(errorMsg));
|
||||
console.error(errorMsg);
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
// Initialization
|
||||
@ -1297,120 +945,6 @@ const Engine = {
|
||||
saveObject.importGame();
|
||||
};
|
||||
|
||||
// Initialize Main Menu Headers (this must be done after initializing the links)
|
||||
if (!initializeMainMenuHeaders(Player, process.env.NODE_ENV === "development")) {
|
||||
const errorMsg =
|
||||
"Failed to initialize Main Menu Headers. Please try refreshing the page. " +
|
||||
"If that doesn't work, report the issue to the developer";
|
||||
exceptionAlert(new Error(errorMsg));
|
||||
console.error(errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
MainMenuLinks.Terminal.addEventListener("click", function () {
|
||||
Engine.loadTerminalContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.ScriptEditor.addEventListener("click", function () {
|
||||
Engine.loadScriptEditorContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.ActiveScripts.addEventListener("click", function () {
|
||||
Engine.loadActiveScriptsContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.CreateProgram.addEventListener("click", function () {
|
||||
Engine.loadCreateProgramContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Stats.addEventListener("click", function () {
|
||||
Engine.loadCharacterContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Factions.addEventListener("click", function () {
|
||||
Engine.loadFactionsContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Augmentations.addEventListener("click", function () {
|
||||
Engine.loadAugmentationsContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.HacknetNodes.addEventListener("click", function () {
|
||||
Engine.loadHacknetNodesContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Sleeves.addEventListener("click", function () {
|
||||
Engine.loadSleevesContent();
|
||||
MainMenuLinks.Sleeves.classList.add("active");
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.City.addEventListener("click", function () {
|
||||
Engine.loadLocationContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Travel.addEventListener("click", function () {
|
||||
Engine.loadTravelContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Job.addEventListener("click", function () {
|
||||
Engine.loadJobContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.StockMarket.addEventListener("click", function () {
|
||||
Engine.loadStockMarketContent();
|
||||
MainMenuLinks.StockMarket.classList.add("active");
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Bladeburner.addEventListener("click", function () {
|
||||
Engine.loadBladeburnerContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Corporation.addEventListener("click", function () {
|
||||
Engine.loadCorporationContent();
|
||||
MainMenuLinks.Corporation.classList.add("active");
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Gang.addEventListener("click", function () {
|
||||
Engine.loadGangContent();
|
||||
MainMenuLinks.Gang.classList.add("active");
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Milestones.addEventListener("click", function () {
|
||||
Engine.loadMilestonesContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.Tutorial.addEventListener("click", function () {
|
||||
Engine.loadTutorialContent();
|
||||
return false;
|
||||
});
|
||||
|
||||
MainMenuLinks.DevMenu.addEventListener("click", function () {
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
Engine.loadDevMenuContent();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Active scripts list
|
||||
Engine.ActiveScriptsList = document.getElementById("active-scripts-list");
|
||||
|
||||
// Save, Delete, Import/Export buttons
|
||||
Engine.Clickables.saveMainMenuButton = document.getElementById("save-game-link");
|
||||
Engine.Clickables.saveMainMenuButton.addEventListener("click", function () {
|
||||
@ -1440,11 +974,8 @@ const Engine = {
|
||||
return false;
|
||||
});
|
||||
|
||||
// Create Program buttons
|
||||
initCreateProgramButtons();
|
||||
|
||||
// Message at the top of terminal
|
||||
postNetburnerText();
|
||||
postVersion();
|
||||
|
||||
// Player was working cancel button
|
||||
if (Player.isWorking) {
|
||||
@ -1481,16 +1012,6 @@ const Engine = {
|
||||
// Character overview screen
|
||||
document.getElementById("character-overview-container").style.display = "block";
|
||||
|
||||
// Remove classes from links (they might be set from tutorial)
|
||||
document.getElementById("terminal-menu-link").removeAttribute("class");
|
||||
document.getElementById("stats-menu-link").removeAttribute("class");
|
||||
document.getElementById("create-script-menu-link").removeAttribute("class");
|
||||
document.getElementById("active-scripts-menu-link").removeAttribute("class");
|
||||
document.getElementById("hacknet-nodes-menu-link").removeAttribute("class");
|
||||
document.getElementById("city-menu-link").removeAttribute("class");
|
||||
document.getElementById("milestones-menu-link").removeAttribute("class");
|
||||
document.getElementById("tutorial-menu-link").removeAttribute("class");
|
||||
|
||||
// Copy Save Data to Clipboard
|
||||
document.getElementById("copy-save-to-clipboard-link").addEventListener("click", function () {
|
||||
const saveString = saveObject.getSaveString();
|
||||
@ -1539,7 +1060,6 @@ const Engine = {
|
||||
}
|
||||
dialogBoxCreate("Forcefully deleted all running scripts. Please save and refresh page.");
|
||||
gameOptionsBoxClose();
|
||||
return false;
|
||||
});
|
||||
|
||||
// DEBUG Soft Reset
|
||||
@ -1547,13 +1067,11 @@ const Engine = {
|
||||
dialogBoxCreate("Soft Reset!");
|
||||
prestigeAugmentation();
|
||||
gameOptionsBoxClose();
|
||||
return false;
|
||||
});
|
||||
|
||||
// DEBUG File diagnostic
|
||||
document.getElementById("debug-files").addEventListener("click", function () {
|
||||
createPopup("debug-files-diagnostic-popup", FileDiagnosticPopup, {});
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
|
320
src/index.html
320
src/index.html
@ -41,176 +41,7 @@
|
||||
<div id="entire-game-container" style="visibility: hidden">
|
||||
<div id="mainmenu-container">
|
||||
<!-- Main menu -->
|
||||
<ul id="mainmenu" class="mainmenu noscrollbar">
|
||||
<!-- Hacking dropdown -->
|
||||
<li id="hacking-menu-header-li">
|
||||
<button id="hacking-menu-header" class="mainmenu-accordion-header noselect">Hacking</button>
|
||||
</li>
|
||||
<li id="terminal-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="terminal-menu-link">Terminal</button>
|
||||
</li>
|
||||
<li id="create-script-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="create-script-menu-link">Create Script</button>
|
||||
</li>
|
||||
<li id="active-scripts-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="active-scripts-menu-link">Active Scripts</button>
|
||||
</li>
|
||||
<li id="create-program-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="create-program-menu-link">Create Program</button>
|
||||
<span id="create-program-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
|
||||
<!-- Character dropdown -->
|
||||
<li id="character-menu-header-li">
|
||||
<button id="character-menu-header" class="mainmenu-accordion-header noselect">Character</button>
|
||||
</li>
|
||||
<li id="stats-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="stats-menu-link">Stats</button>
|
||||
</li>
|
||||
<li id="factions-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="factions-menu-link">Factions</button>
|
||||
<span id="factions-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
<li id="augmentations-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap">
|
||||
Augmentations
|
||||
</button>
|
||||
<span id="augmentations-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
<li id="hacknet-nodes-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="hacknet-nodes-menu-link">Hacknet</button>
|
||||
</li>
|
||||
<li id="sleeves-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="sleeves-menu-link">Sleeves</button>
|
||||
</li>
|
||||
|
||||
<!-- World dropdown -->
|
||||
<li id="world-menu-header-li">
|
||||
<button id="world-menu-header" class="mainmenu-accordion-header noselect">World</button>
|
||||
</li>
|
||||
<li id="city-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="city-menu-link">City</button>
|
||||
</li>
|
||||
<li id="travel-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="travel-menu-link">Travel</button>
|
||||
</li>
|
||||
<li id="job-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="job-menu-link">Job</button>
|
||||
</li>
|
||||
<li id="stock-market-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="stock-market-menu-link">Stock Market</button>
|
||||
</li>
|
||||
<li id="bladeburner-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="bladeburner-menu-link">Bladeburner</button>
|
||||
</li>
|
||||
<li id="corporation-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="corporation-menu-link">Corp</button>
|
||||
</li>
|
||||
<li id="gang-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="gang-menu-link">Gang</button>
|
||||
</li>
|
||||
|
||||
<li id="help-menu-header-li">
|
||||
<button id="help-menu-header" class="mainmenu-accordion-header noselect">Help</button>
|
||||
</li>
|
||||
<li id="milestones-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="milestones-menu-link">Milestones</button>
|
||||
</li>
|
||||
<li id="tutorial-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="tutorial-menu-link">Tutorial</button>
|
||||
</li>
|
||||
<li id="options-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="options-menu-link">Options</button>
|
||||
</li>
|
||||
<li id="dev-tab" class="mainmenu-accordion-panel noselect">
|
||||
<button id="dev-menu-link">Dev</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="script-editor-container" class="generic-menupage-container">
|
||||
<div id="script-editor-wrapper">
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag">
|
||||
<strong style="background-color: #555">Script name: </strong>
|
||||
</p>
|
||||
<input id="script-editor-filename" type="text" maxlength="100" tabindex="1" />
|
||||
</div>
|
||||
|
||||
<div id="monaco-editor"></div>
|
||||
|
||||
<div id="script-editor-buttons-wrapper"></div>
|
||||
<!-- Buttons below script editor -->
|
||||
</div>
|
||||
<!-- End wrapper -->
|
||||
|
||||
<div id="script-editor-options-panel">
|
||||
<h1 style="color: white">Script Editor Options</h1>
|
||||
<fieldset>
|
||||
<label for="script-editor-option-editor">Editor</label>
|
||||
<select id="script-editor-option-editor" class="dropdown">
|
||||
<option value="Ace">Ace</option>
|
||||
<option value="CodeMirror">CodeMirror</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-theme">Theme</label>
|
||||
<select id="script-editor-option-theme" class="dropdown"></select>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-keybinding">Key Binding</label>
|
||||
<select id="script-editor-option-keybinding" class="dropdown"></select>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-highlightactiveline">Highlight Active Line</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="optionCheckbox"
|
||||
name="script-editor-option-highlightactiveline"
|
||||
id="script-editor-option-highlightactiveline"
|
||||
checked
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-showinvisibles">Show Invisibles</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="optionCheckbox"
|
||||
name="script-editor-option-showinvisibles"
|
||||
id="script-editor-option-showinvisibles"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-usesofttab">Use Soft Tab</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="optionCheckbox"
|
||||
name="script-editor-option-usesofttab"
|
||||
id="script-editor-option-usesofttab"
|
||||
checked
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="script-editor-option-flex1-fieldset"></fieldset>
|
||||
<fieldset id="script-editor-option-flex2-fieldset"></fieldset>
|
||||
<fieldset id="script-editor-option-flex3-fieldset"></fieldset>
|
||||
<fieldset id="script-editor-option-flex4-fieldset"></fieldset>
|
||||
</div>
|
||||
<!-- End script editor options panel -->
|
||||
|
||||
<!-- TODO(hydroflame): remove this once Monaco is implemented -->
|
||||
<div id="ace-editor" style="display: none"></div>
|
||||
<form id="codemirror-form-wrapper" style="display: none">
|
||||
<textarea id="codemirror-editor"></textarea>
|
||||
</form>
|
||||
<div id="codemirror-vim-command-display-wrapper" style="display: none">
|
||||
Key Buffer: <span id="codemirror-vim-command-display"></span>
|
||||
</div>
|
||||
<div id="sidebar"></div>
|
||||
</div>
|
||||
|
||||
<!-- Terminal page -->
|
||||
@ -232,142 +63,8 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Character Info page -->
|
||||
<div id="character-container" class="generic-menupage-container">
|
||||
<div id="character-content"></div>
|
||||
</div>
|
||||
|
||||
<!-- Active scripts info page -->
|
||||
<div id="active-scripts-container" class="generic-menupage-container">
|
||||
<p id="active-scripts-text">
|
||||
This page displays a list of all of your scripts that are currently running across every machine. It also
|
||||
provides information about each script's production. The scripts are categorized by the hostname of the
|
||||
servers on which they are running.
|
||||
</p>
|
||||
<p id="active-scripts-total-prod">
|
||||
Total online production of Active scripts:
|
||||
<span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br />
|
||||
Total online production since last Aug installation:
|
||||
<span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span>
|
||||
(<span class="money-gold"
|
||||
><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span
|
||||
>)
|
||||
</p>
|
||||
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none"></ul>
|
||||
</div>
|
||||
|
||||
<!-- Hacknet Nodes -->
|
||||
<div id="hacknet-nodes-container" class="generic-menupage-container">
|
||||
<!-- React Component -->
|
||||
</div>
|
||||
|
||||
<!-- Create a program(executable) -->
|
||||
<div id="create-program-container" class="generic-menupage-container">
|
||||
<p id="create-program-page-text">
|
||||
This page displays any programs that you are able to create. Writing the code for a program takes time, which
|
||||
can vary based on how complex the program is. If you are working on creating a program you can cancel at any
|
||||
time. Your progress will be saved and you can continue later.
|
||||
</p>
|
||||
|
||||
<ul id="create-program-list"></ul>
|
||||
</div>
|
||||
|
||||
<!-- Factions -->
|
||||
<div id="factions-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Single Faction info (when you select a faction from the Factions menu) -->
|
||||
<div id="faction-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Augmentations -->
|
||||
<div id="augmentations-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Milestones content -->
|
||||
<div id="milestones-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Tutorial content -->
|
||||
<div id="tutorial-container" class="generic-menupage-container">
|
||||
<h1>Tutorial (AKA Links to Documentation)</h1>
|
||||
<a
|
||||
id="tutorial-getting-started-link"
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html"
|
||||
>
|
||||
Getting Started</a
|
||||
><br /><br />
|
||||
<a
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html"
|
||||
>
|
||||
Servers & Networking</a
|
||||
><br /><br />
|
||||
<a
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html"
|
||||
>
|
||||
Hacking</a
|
||||
><br /><br />
|
||||
<a
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html"
|
||||
>
|
||||
Scripts</a
|
||||
><br /><br />
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/netscript.html">
|
||||
Netscript Programming Language</a
|
||||
><br /><br />
|
||||
<a
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html"
|
||||
>
|
||||
Traveling</a
|
||||
><br /><br />
|
||||
<a
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html"
|
||||
>
|
||||
Companies</a
|
||||
><br /><br />
|
||||
<a
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html"
|
||||
>
|
||||
Infiltration</a
|
||||
><br /><br />
|
||||
<a
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html"
|
||||
>
|
||||
Factions</a
|
||||
><br /><br />
|
||||
<a
|
||||
class="a-link-button"
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html"
|
||||
>
|
||||
Augmentations</a
|
||||
><br /><br />
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
|
||||
Keyboard Shortcuts</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Location (visiting a location in World) -->
|
||||
<div id="location-container" class="generic-menupage-container"></div>
|
||||
<div id="generic-react-container" class="generic-menupage-container"></div>
|
||||
<div id="infiltration-container" class="generic-fullscreen-container"></div>
|
||||
<div id="stock-market-container" class="generic-menupage-container"></div>
|
||||
<div id="bladeburner-container" class="generic-menupage-container"></div>
|
||||
<div id="resleeve-container" class="generic-menupage-container"></div>
|
||||
<div id="gang-container" class="generic-menupage-container"></div>
|
||||
<div id="corporation-container" class="generic-menupage-container"></div>
|
||||
<div id="sleeves-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Generic Yes/No Pop Up box -->
|
||||
<div id="yes-no-box-container" class="popup-box-container">
|
||||
@ -403,19 +100,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- End of Infiltration pop up box -->
|
||||
<div id="infiltration-box-container" class="popup-box-container">
|
||||
<div id="infiltration-box-content" class="popup-box-content">
|
||||
<p id="infiltration-box-text"></p>
|
||||
|
||||
<button id="infiltration-box-sell" class="a-link-button">Sell on Black Market</button>
|
||||
<br /><br />
|
||||
<select id="infiltration-faction-select" class="dropdown"></select>
|
||||
<br />
|
||||
<button id="infiltration-box-faction" class="a-link-button">Give to Faction for Reputation</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mission container -->
|
||||
<div id="mission-container" class="generic-fullscreen-container"></div>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Root React Component for the "Active Scripts" UI page. This page displays
|
||||
* and provides information about all of the player's scripts that are currently running
|
||||
*/
|
||||
import * as React from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { ScriptProduction } from "./ScriptProduction";
|
||||
import { ServerAccordions } from "./ServerAccordions";
|
||||
@ -15,23 +15,28 @@ type IProps = {
|
||||
workerScripts: Map<number, WorkerScript>;
|
||||
};
|
||||
|
||||
export class ActiveScriptsRoot extends React.Component<IProps> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
export function ActiveScriptsRoot(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
const [divisionName, setDivisionName] = useState("Overview");
|
||||
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
This page displays a list of all of your scripts that are currently running across every machine. It also
|
||||
provides information about each script's production. The scripts are categorized by the hostname of the
|
||||
servers on which they are running.
|
||||
</p>
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 20);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
<ScriptProduction {...this.props} />
|
||||
<ServerAccordions {...this.props} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div id="active-scripts-container">
|
||||
<p>
|
||||
This page displays a list of all of your scripts that are currently running across every machine. It also
|
||||
provides information about each script's production. The scripts are categorized by the hostname of the servers
|
||||
on which they are running.
|
||||
</p>
|
||||
|
||||
<ScriptProduction {...props} />
|
||||
<ServerAccordions {...props} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import * as React from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { BitNodes } from "../BitNode/BitNode";
|
||||
@ -13,12 +13,27 @@ import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
||||
import { StatsTable } from "./React/StatsTable";
|
||||
import { Money } from "./React/Money";
|
||||
|
||||
export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function CharacterInfo(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
const [divisionName, setDivisionName] = useState("Overview");
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 20);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
function LastEmployer(): React.ReactElement {
|
||||
if (p.companyName) {
|
||||
if (props.player.companyName) {
|
||||
return (
|
||||
<>
|
||||
<span>Employer at which you last worked: {p.companyName}</span>
|
||||
<span>Employer at which you last worked: {props.player.companyName}</span>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
@ -26,10 +41,10 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
return <></>;
|
||||
}
|
||||
function LastJob(): React.ReactElement {
|
||||
if (p.companyName !== "") {
|
||||
if (props.player.companyName !== "") {
|
||||
return (
|
||||
<>
|
||||
<span>Job you last worked: {p.jobs[p.companyName]}</span>
|
||||
<span>Job you last worked: {props.player.jobs[props.player.companyName]}</span>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
@ -37,13 +52,13 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
return <></>;
|
||||
}
|
||||
function Employers(): React.ReactElement {
|
||||
if (p.jobs && Object.keys(p.jobs).length !== 0)
|
||||
if (props.player.jobs && Object.keys(props.player.jobs).length !== 0)
|
||||
return (
|
||||
<>
|
||||
<span>All Employers:</span>
|
||||
<br />
|
||||
<ul>
|
||||
{Object.keys(p.jobs).map((j) => (
|
||||
{Object.keys(props.player.jobs).map((j) => (
|
||||
<li key={j}> * {j}</li>
|
||||
))}
|
||||
</ul>
|
||||
@ -56,17 +71,17 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
|
||||
function Hacknet(): React.ReactElement {
|
||||
// Can't import HacknetHelpers for some reason.
|
||||
if (!(p.bitNodeN === 9 || SourceFileFlags[9] > 0)) {
|
||||
if (!(props.player.bitNodeN === 9 || SourceFileFlags[9] > 0)) {
|
||||
return (
|
||||
<>
|
||||
<span>{`Hacknet Nodes owned: ${p.hacknetNodes.length}`}</span>
|
||||
<span>{`Hacknet Nodes owned: ${props.player.hacknetNodes.length}`}</span>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<span>{`Hacknet Servers owned: ${p.hacknetNodes.length} / ${HacknetServerConstants.MaxServers}`}</span>
|
||||
<span>{`Hacknet Servers owned: ${props.player.hacknetNodes.length} / ${HacknetServerConstants.MaxServers}`}</span>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
@ -126,10 +141,10 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
<>
|
||||
<u>Money earned since you last installed Augmentations:</u>
|
||||
<br />
|
||||
{convertMoneySourceTrackerToString(p.moneySourceA)}
|
||||
{convertMoneySourceTrackerToString(props.player.moneySourceA)}
|
||||
</>
|
||||
);
|
||||
if (p.sourceFiles.length !== 0) {
|
||||
if (props.player.sourceFiles.length !== 0) {
|
||||
content = (
|
||||
<>
|
||||
{content}
|
||||
@ -137,7 +152,7 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
<br />
|
||||
<u>Money earned in this BitNode:</u>
|
||||
<br />
|
||||
{convertMoneySourceTrackerToString(p.moneySourceB)}
|
||||
{convertMoneySourceTrackerToString(props.player.moneySourceB)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -146,11 +161,11 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
}
|
||||
|
||||
function Intelligence(): React.ReactElement {
|
||||
if (p.intelligence > 0 && (p.bitNodeN === 5 || SourceFileFlags[5] > 0)) {
|
||||
if (props.player.intelligence > 0 && (props.player.bitNodeN === 5 || SourceFileFlags[5] > 0)) {
|
||||
return (
|
||||
<tr key="5">
|
||||
<td>Intelligence:</td>
|
||||
<td style={{ textAlign: "right" }}>{numeralWrapper.formatSkill(p.intelligence)}</td>
|
||||
<td style={{ textAlign: "right" }}>{numeralWrapper.formatSkill(props.player.intelligence)}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
@ -189,15 +204,15 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
}
|
||||
|
||||
function BladeburnerMults(): React.ReactElement {
|
||||
if (!p.canAccessBladeburner()) return <></>;
|
||||
if (!props.player.canAccessBladeburner()) return <></>;
|
||||
return (
|
||||
<>
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Bladeburner Success Chance", p.bladeburner_max_stamina_mult],
|
||||
["Bladeburner Max Stamina", p.bladeburner_stamina_gain_mult],
|
||||
["Bladeburner Stamina Gain", p.bladeburner_analysis_mult],
|
||||
["Bladeburner Field Analysis", p.bladeburner_success_chance_mult],
|
||||
["Bladeburner Success Chance", props.player.bladeburner_max_stamina_mult],
|
||||
["Bladeburner Max Stamina", props.player.bladeburner_stamina_gain_mult],
|
||||
["Bladeburner Stamina Gain", props.player.bladeburner_analysis_mult],
|
||||
["Bladeburner Field Analysis", props.player.bladeburner_success_chance_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
@ -206,12 +221,12 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
}
|
||||
|
||||
function CurrentBitNode(): React.ReactElement {
|
||||
if (p.sourceFiles.length > 0) {
|
||||
const index = "BitNode" + p.bitNodeN;
|
||||
if (props.player.sourceFiles.length > 0) {
|
||||
const index = "BitNode" + props.player.bitNodeN;
|
||||
return (
|
||||
<>
|
||||
<span>
|
||||
Current BitNode: {p.bitNodeN} ({BitNodes[index].name})
|
||||
Current BitNode: {props.player.bitNodeN} ({BitNodes[index].name})
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
@ -230,198 +245,254 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const timeRows = [["Time played since last Augmentation:", convertTimeMsToTimeElapsedString(p.playtimeSinceLastAug)]];
|
||||
if (p.sourceFiles.length > 0) {
|
||||
const timeRows = [
|
||||
["Time played since last Augmentation:", convertTimeMsToTimeElapsedString(props.player.playtimeSinceLastAug)],
|
||||
];
|
||||
if (props.player.sourceFiles.length > 0) {
|
||||
timeRows.push([
|
||||
"Time played since last Bitnode destroyed:",
|
||||
convertTimeMsToTimeElapsedString(p.playtimeSinceLastBitnode),
|
||||
convertTimeMsToTimeElapsedString(props.player.playtimeSinceLastBitnode),
|
||||
]);
|
||||
}
|
||||
timeRows.push(["Total Time played:", convertTimeMsToTimeElapsedString(p.totalPlaytime)]);
|
||||
timeRows.push(["Total Time played:", convertTimeMsToTimeElapsedString(props.player.totalPlaytime)]);
|
||||
|
||||
return (
|
||||
<pre>
|
||||
<b>General</b>
|
||||
<br />
|
||||
<br />
|
||||
<span>Current City: {p.city}</span>
|
||||
<br />
|
||||
<LastEmployer />
|
||||
<LastJob />
|
||||
<Employers />
|
||||
<span>
|
||||
Money: <Money money={p.money.toNumber()} />
|
||||
</span>
|
||||
<button className="popup-box-button" style={{ display: "inline-block", float: "none" }} onClick={openMoneyModal}>
|
||||
Money Statistics & Breakdown
|
||||
</button>
|
||||
<br />
|
||||
<br />
|
||||
<b>Stats</b>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr key="0">
|
||||
<td key="0">Hacking:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(p.hacking_skill)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(p.hacking_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="1">
|
||||
<td key="0">Strength:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(p.strength)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(p.strength_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="2">
|
||||
<td key="0">Defense:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(p.defense)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(p.defense_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="3">
|
||||
<td key="0">Dexterity:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(p.dexterity)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(p.dexterity_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="4">
|
||||
<td key="0">Agility:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(p.agility)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(p.agility_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="5">
|
||||
<td key="0">Charisma:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(p.charisma)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(p.charisma_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<Intelligence />
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Hacking Chance", p.hacking_chance_mult],
|
||||
["Hacking Speed", p.hacking_speed_mult],
|
||||
["Hacking Money", p.hacking_money_mult, p.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney],
|
||||
["Hacking Growth", p.hacking_grow_mult, p.hacking_grow_mult * BitNodeMultipliers.ServerGrowthRate],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Hacking Level", p.hacking_mult, p.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier],
|
||||
["Hacking Experience", p.hacking_exp_mult, p.hacking_exp_mult * BitNodeMultipliers.HackExpGain],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<div id="character-container">
|
||||
<pre>
|
||||
<b>General</b>
|
||||
<br />
|
||||
<br />
|
||||
<span>Current City: {props.player.city}</span>
|
||||
<br />
|
||||
<LastEmployer />
|
||||
<LastJob />
|
||||
<Employers />
|
||||
<span>
|
||||
Money: <Money money={props.player.money.toNumber()} />
|
||||
</span>
|
||||
<button
|
||||
className="popup-box-button"
|
||||
style={{ display: "inline-block", float: "none" }}
|
||||
onClick={openMoneyModal}
|
||||
>
|
||||
Money Statistics & Breakdown
|
||||
</button>
|
||||
<br />
|
||||
<br />
|
||||
<b>Stats</b>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr key="0">
|
||||
<td key="0">Hacking:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(props.player.hacking_skill)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(props.player.hacking_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="1">
|
||||
<td key="0">Strength:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(props.player.strength)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(props.player.strength_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="2">
|
||||
<td key="0">Defense:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(props.player.defense)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(props.player.defense_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="3">
|
||||
<td key="0">Dexterity:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(props.player.dexterity)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(props.player.dexterity_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="4">
|
||||
<td key="0">Agility:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(props.player.agility)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(props.player.agility_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<tr key="5">
|
||||
<td key="0">Charisma:</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatSkill(props.player.charisma)}
|
||||
</td>
|
||||
<td key="2" style={{ textAlign: "right" }}>
|
||||
({numeralWrapper.formatExp(props.player.charisma_exp)} exp)
|
||||
</td>
|
||||
</tr>
|
||||
<Intelligence />
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Hacking Chance", props.player.hacking_chance_mult],
|
||||
["Hacking Speed", props.player.hacking_speed_mult],
|
||||
[
|
||||
"Hacking Money",
|
||||
props.player.hacking_money_mult,
|
||||
props.player.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney,
|
||||
],
|
||||
[
|
||||
"Hacking Growth",
|
||||
props.player.hacking_grow_mult,
|
||||
props.player.hacking_grow_mult * BitNodeMultipliers.ServerGrowthRate,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Hacking Level",
|
||||
props.player.hacking_mult,
|
||||
props.player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier,
|
||||
],
|
||||
[
|
||||
"Hacking Experience",
|
||||
props.player.hacking_exp_mult,
|
||||
props.player.hacking_exp_mult * BitNodeMultipliers.HackExpGain,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Strength Level", p.strength_mult, p.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier],
|
||||
["Strength Experience", p.strength_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Strength Level",
|
||||
props.player.strength_mult,
|
||||
props.player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier,
|
||||
],
|
||||
["Strength Experience", props.player.strength_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Defense Level", p.defense_mult, p.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier],
|
||||
["Defense Experience", p.defense_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Defense Level",
|
||||
props.player.defense_mult,
|
||||
props.player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier,
|
||||
],
|
||||
["Defense Experience", props.player.defense_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Dexterity Level", p.dexterity_mult, p.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier],
|
||||
["Dexterity Experience", p.dexterity_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Dexterity Level",
|
||||
props.player.dexterity_mult,
|
||||
props.player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier,
|
||||
],
|
||||
["Dexterity Experience", props.player.dexterity_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Agility Level", p.agility_mult, p.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier],
|
||||
["Agility Experience", p.agility_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Agility Level",
|
||||
props.player.agility_mult,
|
||||
props.player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier,
|
||||
],
|
||||
["Agility Experience", props.player.agility_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Charisma Level", p.charisma_mult, p.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier],
|
||||
["Charisma Experience", p.charisma_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Charisma Level",
|
||||
props.player.charisma_mult,
|
||||
props.player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier,
|
||||
],
|
||||
["Charisma Experience", props.player.charisma_exp_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Hacknet Node production",
|
||||
p.hacknet_node_money_mult,
|
||||
p.hacknet_node_money_mult * BitNodeMultipliers.HacknetNodeMoney,
|
||||
],
|
||||
["Hacknet Node purchase cost", p.hacknet_node_purchase_cost_mult],
|
||||
["Hacknet Node RAM upgrade cost", p.hacknet_node_ram_cost_mult],
|
||||
["Hacknet Node Core purchase cost", p.hacknet_node_core_cost_mult],
|
||||
["Hacknet Node level upgrade cost", p.hacknet_node_level_cost_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Hacknet Node production",
|
||||
props.player.hacknet_node_money_mult,
|
||||
props.player.hacknet_node_money_mult * BitNodeMultipliers.HacknetNodeMoney,
|
||||
],
|
||||
["Hacknet Node purchase cost", props.player.hacknet_node_purchase_cost_mult],
|
||||
["Hacknet Node RAM upgrade cost", props.player.hacknet_node_ram_cost_mult],
|
||||
["Hacknet Node Core purchase cost", props.player.hacknet_node_core_cost_mult],
|
||||
["Hacknet Node level upgrade cost", props.player.hacknet_node_level_cost_mult],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Company reputation gain", p.company_rep_mult],
|
||||
["Faction reputation gain", p.faction_rep_mult, p.faction_rep_mult * BitNodeMultipliers.FactionWorkRepGain],
|
||||
["Salary", p.work_money_mult, p.work_money_mult * BitNodeMultipliers.CompanyWorkMoney],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Company reputation gain", props.player.company_rep_mult],
|
||||
[
|
||||
"Faction reputation gain",
|
||||
props.player.faction_rep_mult,
|
||||
props.player.faction_rep_mult * BitNodeMultipliers.FactionWorkRepGain,
|
||||
],
|
||||
[
|
||||
"Salary",
|
||||
props.player.work_money_mult,
|
||||
props.player.work_money_mult * BitNodeMultipliers.CompanyWorkMoney,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Crime success", p.crime_success_mult],
|
||||
["Crime money", p.crime_money_mult, p.crime_money_mult * BitNodeMultipliers.CrimeMoney],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Crime success", props.player.crime_success_mult],
|
||||
[
|
||||
"Crime money",
|
||||
props.player.crime_money_mult,
|
||||
props.player.crime_money_mult * BitNodeMultipliers.CrimeMoney,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<BladeburnerMults />
|
||||
<br />
|
||||
<BladeburnerMults />
|
||||
<br />
|
||||
|
||||
<b>Misc.</b>
|
||||
<br />
|
||||
<br />
|
||||
<span>{`Servers owned: ${p.purchasedServers.length} / ${getPurchaseServerLimit()}`}</span>
|
||||
<br />
|
||||
<Hacknet />
|
||||
<span>{`Augmentations installed: ${p.augmentations.length}`}</span>
|
||||
<br />
|
||||
<br />
|
||||
{StatsTable(timeRows)}
|
||||
<br />
|
||||
<CurrentBitNode />
|
||||
</pre>
|
||||
<b>Misc.</b>
|
||||
<br />
|
||||
<br />
|
||||
<span>{`Servers owned: ${props.player.purchasedServers.length} / ${getPurchaseServerLimit()}`}</span>
|
||||
<br />
|
||||
<Hacknet />
|
||||
<span>{`Augmentations installed: ${props.player.augmentations.length}`}</span>
|
||||
<br />
|
||||
<br />
|
||||
{StatsTable(timeRows)}
|
||||
<br />
|
||||
<CurrentBitNode />
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
|
||||
|
||||
interface IMainMenuLinks {
|
||||
[key: string]: HTMLElement | undefined;
|
||||
Terminal: HTMLElement;
|
||||
ScriptEditor: HTMLElement;
|
||||
ActiveScripts: HTMLElement;
|
||||
@ -55,6 +56,7 @@ export const MainMenuLinks: IMainMenuLinks = {
|
||||
};
|
||||
|
||||
export function initializeMainMenuLinks(): boolean {
|
||||
return true;
|
||||
try {
|
||||
function safeGetLink(id: string): HTMLElement {
|
||||
const elem: HTMLElement | null = clearEventListeners(id);
|
||||
@ -83,9 +85,9 @@ export function initializeMainMenuLinks(): boolean {
|
||||
MainMenuLinks.Gang = safeGetLink("gang-menu-link");
|
||||
MainMenuLinks.Milestones = safeGetLink("milestones-menu-link");
|
||||
MainMenuLinks.Tutorial = safeGetLink("tutorial-menu-link");
|
||||
const op: HTMLElement | null = document.getElementById("options-menu-link");
|
||||
if (op === null) throw new Error(`Could not find element with id: "options-menu-link"`);
|
||||
MainMenuLinks.Options = op; // This click listener is already set, so don't clear it
|
||||
// const op: HTMLElement | null = document.getElementById("options-menu-link");
|
||||
// if (op === null) throw new Error(`Could not find element with id: "options-menu-link"`);
|
||||
// MainMenuLinks.Options = op; // This click listener is already set, so don't clear it
|
||||
MainMenuLinks.DevMenu = safeGetLink("dev-menu-link");
|
||||
|
||||
return true;
|
||||
|
@ -9,7 +9,7 @@
|
||||
"target": "es6",
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"types": ["cypress", "@testing-library/cypress"]
|
||||
"types": ["cypress", "@testing-library/cypress", "node"]
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ $(document).click(function (event) {
|
||||
|
||||
var gameOptionsOpened = false;
|
||||
function gameOptionsBoxInit() {
|
||||
return;
|
||||
//Menu link button
|
||||
document.getElementById("options-menu-link").addEventListener("click", function () {
|
||||
gameOptionsBoxOpen();
|
||||
|
Loading…
Reference in New Issue
Block a user