mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 01:23:49 +01:00
Merge pull request #1225 from danielyxie/dev
Fix scrolling and pages display
This commit is contained in:
commit
3b314f5d1d
@ -11,5 +11,5 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
@ -4,10 +4,7 @@
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#active-scripts-container {
|
||||
position: fixed;
|
||||
padding-top: 10px;
|
||||
|
||||
.active-scripts-container {
|
||||
> p {
|
||||
width: 70%;
|
||||
margin: 6px;
|
||||
|
@ -5,12 +5,7 @@
|
||||
*/
|
||||
@import "theme";
|
||||
|
||||
#augmentations-container {
|
||||
position: fixed;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#augmentations-content {
|
||||
.augmentations-content {
|
||||
> p {
|
||||
font-size: $defaultFontSize * 0.875;
|
||||
width: 70%;
|
||||
|
@ -1,8 +1,6 @@
|
||||
@import "theme";
|
||||
|
||||
#bladeburner-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
.bladeburner-container {
|
||||
a,
|
||||
div,
|
||||
p,
|
||||
|
@ -6,7 +6,9 @@
|
||||
*/
|
||||
|
||||
#character-overview-wrapper {
|
||||
position: relative;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#character-overview-container {
|
||||
|
@ -1,49 +0,0 @@
|
||||
@import "theme";
|
||||
|
||||
/**
|
||||
* Customized styling for the Code Mirror editor
|
||||
*/
|
||||
|
||||
#codemirror-form-wrapper {
|
||||
height: 80%;
|
||||
margin: 10px 0 0 6px;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
z-index: 1;
|
||||
font-family: $fontFamily;
|
||||
font-size: $defaultFontSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight matches
|
||||
*/
|
||||
.cm-matchhighlight {
|
||||
background-color: #8f908a;
|
||||
}
|
||||
|
||||
.CodeMirror-selection-highlight-scrollbar {
|
||||
background-color: #8f908a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Invisibles
|
||||
*/
|
||||
.cm-whitespace::before {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
color: #404f7d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vim command display
|
||||
*/
|
||||
#codemirror-vim-command-display-wrapper {
|
||||
background-color: white;
|
||||
font-size: 13px;
|
||||
height: 30px;
|
||||
margin-left: 6px;
|
||||
}
|
@ -8,10 +8,10 @@
|
||||
* companies
|
||||
*/
|
||||
|
||||
#cmpy-mgmt-container p,
|
||||
#cmpy-mgmt-container a,
|
||||
#cmpy-mgmt-container div,
|
||||
#cmpy-mgmt-container br {
|
||||
.cmpy-mgmt-container p,
|
||||
.cmpy-mgmt-container a,
|
||||
.cmpy-mgmt-container div,
|
||||
.cmpy-mgmt-container br {
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
}
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
#corporation-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
}
|
@ -5,10 +5,7 @@
|
||||
* Styling for the Gang mechanic UI (BitNode-2)
|
||||
*/
|
||||
|
||||
#gang-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
|
||||
.gang-container {
|
||||
p,
|
||||
pre {
|
||||
font-size: $defaultFontSize * 0.9375;
|
||||
|
@ -5,11 +5,6 @@
|
||||
* Styling for the Hacknet Nodes UI Page
|
||||
*/
|
||||
|
||||
#hacknet-nodes-container {
|
||||
position: fixed;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.hacknet-general-info {
|
||||
margin: 10px;
|
||||
width: 70vw;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -5,23 +5,19 @@
|
||||
terminal which has its own page) */
|
||||
|
||||
.generic-menupage-container {
|
||||
height: 100%;
|
||||
padding-left: 10px;
|
||||
padding-left: 2px;
|
||||
margin-left: 10%;
|
||||
width: 99%;
|
||||
-ms-overflow-style: none; /* for Internet Explorer, Edge */
|
||||
scrollbar-width: none; /* for Firefox */
|
||||
}
|
||||
|
||||
#generic-react-container {
|
||||
padding: 10px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
/* Character Info */
|
||||
#character-container {
|
||||
padding-top: 10px;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
/* World */
|
||||
#world-container {
|
||||
position: fixed;
|
||||
padding-top: 10px;
|
||||
#generic-react-container::-webkit-scrollbar {
|
||||
display: none; /* for Chrome, Safari, and Opera */
|
||||
}
|
||||
|
||||
#world-city-name,
|
||||
|
@ -1,5 +1,3 @@
|
||||
#milestones-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
.milestones-container {
|
||||
width: 60%;
|
||||
}
|
||||
|
@ -27,6 +27,10 @@
|
||||
color: var(--my-font-color);
|
||||
}
|
||||
|
||||
.popup-box-input-div {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.popup-box-button,
|
||||
.popup-box-button-inactive {
|
||||
color: #aaa;
|
||||
@ -189,11 +193,6 @@
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
/* Generic Yes No Box */
|
||||
#yes-no-text-input-box-input {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Game Options */
|
||||
#game-options-container {
|
||||
transition: opacity 400ms ease-in;
|
||||
|
@ -3,11 +3,6 @@
|
||||
*/
|
||||
@import "theme";
|
||||
|
||||
#resleeve-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.resleeve-elem {
|
||||
border: 1px solid white;
|
||||
margin: 4px;
|
||||
|
@ -5,29 +5,14 @@
|
||||
* Styling for Script Editor (both Ace and CodeMirror)
|
||||
*/
|
||||
|
||||
#script-editor-container {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* This temp element is used for auto adjusting filename field */
|
||||
.tmp-element {
|
||||
visibility: hidden;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#script-editor-container {
|
||||
position: fixed;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#script-editor-buttons-wrapper {
|
||||
width: 100%;
|
||||
padding-right: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#script-editor-wrapper {
|
||||
height: 100%;
|
||||
.script-editor-wrapper {
|
||||
height: 110vh;
|
||||
width: 70%;
|
||||
background: transparent;
|
||||
}
|
||||
|
@ -3,11 +3,6 @@
|
||||
*/
|
||||
@import "theme";
|
||||
|
||||
#sleeves-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.sleeve-elem {
|
||||
border: 1px solid white;
|
||||
margin: 4px;
|
||||
|
@ -1,9 +1,6 @@
|
||||
@import "theme";
|
||||
|
||||
#stock-market-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
|
||||
.stock-market-container {
|
||||
p {
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
}
|
||||
|
@ -12,6 +12,12 @@
|
||||
|
||||
body {
|
||||
background-color: var(--my-background-color);
|
||||
-ms-overflow-style: none; /* for Internet Explorer, Edge */
|
||||
scrollbar-width: none; /* for Firefox */
|
||||
}
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
display: none; /* for Chrome, Safari, and Opera */
|
||||
}
|
||||
|
||||
p,
|
||||
@ -113,6 +119,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 +130,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(r,i)&&r[i]&&s.push(r[i][0]),r[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 u.push.apply(u,l||[]),o()}function o(){for(var n,t=0;t<u.length;t++){for(var o=u[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==r[c]&&(e=!1)}e&&(u.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},r={2:0},u=[];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;u.push([910,0]),o()}({910:function(n,t,o){"use strict";o.r(t);o(911),o(913),o(915),o(917),o(919),o(921),o(923),o(925),o(927),o(929),o(931),o(933),o(935),o(937),o(939),o(941),o(943),o(945),o(947),o(949),o(951),o(953),o(955),o(957),o(959),o(961),o(963),o(965),o(967),o(969),o(971)},913:function(n,t,o){},915:function(n,t,o){},917:function(n,t,o){},919:function(n,t,o){},921:function(n,t,o){},923:function(n,t,o){},925:function(n,t,o){},927:function(n,t,o){},929:function(n,t,o){},931:function(n,t,o){},933:function(n,t,o){},935:function(n,t,o){},937:function(n,t,o){},939:function(n,t,o){},941:function(n,t,o){},943:function(n,t,o){},945:function(n,t,o){},947:function(n,t,o){},949:function(n,t,o){},951:function(n,t,o){},953:function(n,t,o){},955:function(n,t,o){},957:function(n,t,o){},959:function(n,t,o){},961:function(n,t,o){},963:function(n,t,o){},965:function(n,t,o){},967:function(n,t,o){},969:function(n,t,o){},971:function(n,t,o){}});
|
||||
//# sourceMappingURL=engineStyle.bundle.js.map
|
292
dist/engineStyle.css
vendored
292
dist/engineStyle.css
vendored
@ -12,7 +12,7 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top; }
|
||||
vertical-align: middle; }
|
||||
|
||||
:root {
|
||||
--my-font-color: #6f3;
|
||||
@ -21,7 +21,15 @@
|
||||
--my-prompt-color: #f92672; }
|
||||
|
||||
body {
|
||||
background-color: var(--my-background-color); }
|
||||
background-color: var(--my-background-color);
|
||||
-ms-overflow-style: none;
|
||||
/* for Internet Explorer, Edge */
|
||||
scrollbar-width: none;
|
||||
/* for Firefox */ }
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
/* for Chrome, Safari, and Opera */ }
|
||||
|
||||
p,
|
||||
pre,
|
||||
@ -105,13 +113,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 {
|
||||
@ -545,7 +570,7 @@ input[type="checkbox"] {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top; }
|
||||
vertical-align: middle; }
|
||||
|
||||
:root {
|
||||
--my-font-color: #6f3;
|
||||
@ -554,7 +579,15 @@ input[type="checkbox"] {
|
||||
--my-prompt-color: #f92672; }
|
||||
|
||||
body {
|
||||
background-color: var(--my-background-color); }
|
||||
background-color: var(--my-background-color);
|
||||
-ms-overflow-style: none;
|
||||
/* for Internet Explorer, Edge */
|
||||
scrollbar-width: none;
|
||||
/* for Firefox */ }
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
/* for Chrome, Safari, and Opera */ }
|
||||
|
||||
p,
|
||||
pre,
|
||||
@ -638,13 +671,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 +1171,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 +1219,6 @@ button {
|
||||
|
||||
/* Slide down transition */
|
||||
.mainmenu-accordion-panel {
|
||||
max-height: 0;
|
||||
opacity: 1;
|
||||
transition: max-height 0.2s ease-out; }
|
||||
|
||||
/* COLORS */
|
||||
@ -1176,7 +1227,9 @@ button {
|
||||
* Styling for the Character Overview Panel (top-right panel)
|
||||
*/
|
||||
#character-overview-wrapper {
|
||||
position: relative; }
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0; }
|
||||
|
||||
#character-overview-container {
|
||||
display: none;
|
||||
@ -1351,25 +1404,13 @@ button {
|
||||
/**
|
||||
* Styling for Script Editor (both Ace and CodeMirror)
|
||||
*/
|
||||
#script-editor-container {
|
||||
background-color: transparent; }
|
||||
|
||||
/* This temp element is used for auto adjusting filename field */
|
||||
.tmp-element {
|
||||
visibility: hidden;
|
||||
white-space: pre; }
|
||||
|
||||
#script-editor-container {
|
||||
position: fixed;
|
||||
padding-top: 10px; }
|
||||
|
||||
#script-editor-buttons-wrapper {
|
||||
width: 100%;
|
||||
padding-right: 0;
|
||||
margin-right: 0; }
|
||||
|
||||
#script-editor-wrapper {
|
||||
height: 100%;
|
||||
.script-editor-wrapper {
|
||||
height: 110vh;
|
||||
width: 70%;
|
||||
background: transparent; }
|
||||
|
||||
@ -1437,63 +1478,18 @@ button {
|
||||
align-items: center;
|
||||
justify-content: start; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/**
|
||||
* Customized styling for the Code Mirror editor
|
||||
*/
|
||||
#codemirror-form-wrapper {
|
||||
height: 80%;
|
||||
margin: 10px 0 0 6px; }
|
||||
|
||||
.CodeMirror {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
z-index: 1;
|
||||
font-family: "Lucida Console", "Lucida Sans Unicode", "Fira Mono", "Consolas", "Courier New", Courier, monospace, "Times New Roman";
|
||||
font-size: 16px; }
|
||||
|
||||
/**
|
||||
* Highlight matches
|
||||
*/
|
||||
.cm-matchhighlight {
|
||||
background-color: #8f908a; }
|
||||
|
||||
.CodeMirror-selection-highlight-scrollbar {
|
||||
background-color: #8f908a; }
|
||||
|
||||
/**
|
||||
* Show Invisibles
|
||||
*/
|
||||
.cm-whitespace::before {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
color: #404f7d; }
|
||||
|
||||
/**
|
||||
* Vim command display
|
||||
*/
|
||||
#codemirror-vim-command-display-wrapper {
|
||||
background-color: white;
|
||||
font-size: 13px;
|
||||
height: 30px;
|
||||
margin-left: 6px; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
.active-scripts-list {
|
||||
list-style-type: none; }
|
||||
|
||||
#active-scripts-container {
|
||||
position: fixed;
|
||||
padding-top: 10px; }
|
||||
#active-scripts-container > p {
|
||||
width: 70%;
|
||||
margin: 6px;
|
||||
padding: 4px; }
|
||||
#active-scripts-container .accordion-header > pre {
|
||||
color: white; }
|
||||
.active-scripts-container > p {
|
||||
width: 70%;
|
||||
margin: 6px;
|
||||
padding: 4px; }
|
||||
|
||||
.active-scripts-container .accordion-header > pre {
|
||||
color: white; }
|
||||
|
||||
.active-scripts-server-header {
|
||||
background-color: #444;
|
||||
@ -1588,10 +1584,6 @@ button {
|
||||
/**
|
||||
* Styling for the Hacknet Nodes UI Page
|
||||
*/
|
||||
#hacknet-nodes-container {
|
||||
position: fixed;
|
||||
padding: 10px; }
|
||||
|
||||
.hacknet-general-info {
|
||||
margin: 10px;
|
||||
width: 70vw; }
|
||||
@ -1646,21 +1638,20 @@ button {
|
||||
/* CSS for different main menu pages, such as character info, script editor, etc (but excluding
|
||||
terminal which has its own page) */
|
||||
.generic-menupage-container {
|
||||
height: 100%;
|
||||
padding-left: 10px;
|
||||
padding-left: 2px;
|
||||
margin-left: 10%;
|
||||
width: 99%;
|
||||
-ms-overflow-style: none;
|
||||
/* for Internet Explorer, Edge */
|
||||
scrollbar-width: none;
|
||||
/* for Firefox */ }
|
||||
|
||||
#generic-react-container {
|
||||
padding: 10px;
|
||||
overflow-y: scroll; }
|
||||
|
||||
/* Character Info */
|
||||
#character-container {
|
||||
padding-top: 10px;
|
||||
position: fixed; }
|
||||
|
||||
/* World */
|
||||
#world-container {
|
||||
position: fixed;
|
||||
padding-top: 10px; }
|
||||
#generic-react-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
/* for Chrome, Safari, and Opera */ }
|
||||
|
||||
#world-city-name,
|
||||
#world-city-desc {
|
||||
@ -1781,11 +1772,7 @@ button {
|
||||
*/
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
#augmentations-container {
|
||||
position: fixed;
|
||||
padding-top: 10px; }
|
||||
|
||||
#augmentations-content > p {
|
||||
.augmentations-content > p {
|
||||
font-size: 14px;
|
||||
width: 70%; }
|
||||
|
||||
@ -1825,13 +1812,11 @@ button {
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
#stock-market-container {
|
||||
position: fixed;
|
||||
padding: 6px; }
|
||||
#stock-market-container p {
|
||||
font-size: 13px; }
|
||||
#stock-market-container a {
|
||||
font-size: 14px; }
|
||||
.stock-market-container p {
|
||||
font-size: 13px; }
|
||||
|
||||
.stock-market-container a {
|
||||
font-size: 14px; }
|
||||
|
||||
.stock-market-info-and-purchases > h2 {
|
||||
display: block;
|
||||
@ -1959,7 +1944,7 @@ button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top; }
|
||||
vertical-align: middle; }
|
||||
|
||||
:root {
|
||||
--my-font-color: #6f3;
|
||||
@ -1968,7 +1953,15 @@ button {
|
||||
--my-prompt-color: #f92672; }
|
||||
|
||||
body {
|
||||
background-color: var(--my-background-color); }
|
||||
background-color: var(--my-background-color);
|
||||
-ms-overflow-style: none;
|
||||
/* for Internet Explorer, Edge */
|
||||
scrollbar-width: none;
|
||||
/* for Firefox */ }
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
/* for Chrome, Safari, and Opera */ }
|
||||
|
||||
p,
|
||||
pre,
|
||||
@ -2052,13 +2045,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 {
|
||||
@ -2393,6 +2403,9 @@ input[type="checkbox"] {
|
||||
/* Sit on top of the container */
|
||||
color: var(--my-font-color); }
|
||||
|
||||
.popup-box-input-div {
|
||||
margin: 2px; }
|
||||
|
||||
.popup-box-button,
|
||||
.popup-box-button-inactive {
|
||||
color: #aaa;
|
||||
@ -2535,10 +2548,6 @@ input[type="checkbox"] {
|
||||
#infiltration-faction-select {
|
||||
background-color: #000; }
|
||||
|
||||
/* Generic Yes No Box */
|
||||
#yes-no-text-input-box-input {
|
||||
color: #fff; }
|
||||
|
||||
/* Game Options */
|
||||
#game-options-container {
|
||||
transition: opacity 400ms ease-in; }
|
||||
@ -2695,7 +2704,7 @@ input[type="checkbox"] {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top; }
|
||||
vertical-align: middle; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
@ -2997,10 +3006,10 @@ input[type="checkbox"] {
|
||||
* for the mechanic before it got changed to avoid confusion with normal
|
||||
* companies
|
||||
*/
|
||||
#cmpy-mgmt-container p,
|
||||
#cmpy-mgmt-container a,
|
||||
#cmpy-mgmt-container div,
|
||||
#cmpy-mgmt-container br {
|
||||
.cmpy-mgmt-container p,
|
||||
.cmpy-mgmt-container a,
|
||||
.cmpy-mgmt-container div,
|
||||
.cmpy-mgmt-container br {
|
||||
font-size: 13px; }
|
||||
|
||||
/* Header tabs */
|
||||
@ -3130,15 +3139,12 @@ input[type="checkbox"] {
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
#bladeburner-container {
|
||||
position: fixed;
|
||||
padding: 6px; }
|
||||
#bladeburner-container a,
|
||||
#bladeburner-container div,
|
||||
#bladeburner-container p,
|
||||
#bladeburner-container pre,
|
||||
#bladeburner-container td {
|
||||
font-size: 13px; }
|
||||
.bladeburner-container a,
|
||||
.bladeburner-container div,
|
||||
.bladeburner-container p,
|
||||
.bladeburner-container pre,
|
||||
.bladeburner-container td {
|
||||
font-size: 13px; }
|
||||
|
||||
.bladeburner-action {
|
||||
border: 1px solid #fff;
|
||||
@ -3245,15 +3251,13 @@ input[type="checkbox"] {
|
||||
/**
|
||||
* Styling for the Gang mechanic UI (BitNode-2)
|
||||
*/
|
||||
#gang-container {
|
||||
position: fixed;
|
||||
padding: 6px; }
|
||||
#gang-container p,
|
||||
#gang-container pre {
|
||||
font-size: 15px; }
|
||||
#gang-container select {
|
||||
background-color: black;
|
||||
color: white; }
|
||||
.gang-container p,
|
||||
.gang-container pre {
|
||||
font-size: 15px; }
|
||||
|
||||
.gang-container select {
|
||||
background-color: black;
|
||||
color: white; }
|
||||
|
||||
#gang-management-subpage > p {
|
||||
padding: 4px; }
|
||||
@ -3283,10 +3287,6 @@ input[type="checkbox"] {
|
||||
*/
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
#sleeves-container {
|
||||
position: fixed;
|
||||
padding: 6px; }
|
||||
|
||||
.sleeve-elem {
|
||||
border: 1px solid white;
|
||||
margin: 4px;
|
||||
@ -3308,10 +3308,6 @@ input[type="checkbox"] {
|
||||
*/
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
#resleeve-container {
|
||||
position: fixed;
|
||||
padding: 6px; }
|
||||
|
||||
.resleeve-elem {
|
||||
border: 1px solid white;
|
||||
margin: 4px;
|
||||
@ -6243,9 +6239,7 @@ html {
|
||||
.casino-card.black {
|
||||
color: black; }
|
||||
|
||||
#milestones-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
.milestones-container {
|
||||
width: 60%; }
|
||||
|
||||
/* COLORS */
|
||||
@ -6294,9 +6288,5 @@ html {
|
||||
50% {
|
||||
color: #adff2f; } }
|
||||
|
||||
#corporation-container {
|
||||
position: fixed;
|
||||
padding: 6px; }
|
||||
|
||||
|
||||
/*# sourceMappingURL=engineStyle.css.map*/
|
30
dist/vendor.bundle.js
vendored
30
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,10 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Character Info page -->
|
||||
<div id="character-container" class="generic-menupage-container">
|
||||
<div id="character-content"></div>
|
||||
<div class="generic-menupage-container">
|
||||
<div id="generic-react-container"></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="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 +95,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,48 +44,50 @@ 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>
|
||||
<>
|
||||
<div className="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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ interface IProps {
|
||||
|
||||
export function Root(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<div className="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>
|
||||
);
|
||||
}
|
||||
|
@ -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 className="cmpy-mgmt-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>
|
||||
);
|
||||
}
|
||||
|
79
src/Corporation/ui/CreateCorporationPopup.tsx
Normal file
79
src/Corporation/ui/CreateCorporationPopup.tsx
Normal file
@ -0,0 +1,79 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
popupId: string;
|
||||
}
|
||||
|
||||
export function CreateCorporationPopup(props: IProps): React.ReactElement {
|
||||
if (!props.player.canAccessCorporation() || props.player.hasCorporation()) {
|
||||
removePopup(props.popupId);
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const [name, setName] = useState("");
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setName(event.target.value);
|
||||
}
|
||||
|
||||
function selfFund(): void {
|
||||
if (!props.player.canAfford(150e9)) {
|
||||
dialogBoxCreate("You don't have enough money to create a corporation! You need $150b.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == "") {
|
||||
dialogBoxCreate("Invalid company name!");
|
||||
return;
|
||||
}
|
||||
|
||||
props.player.startCorporation(name);
|
||||
props.player.loseMoney(150e9);
|
||||
|
||||
dialogBoxCreate(
|
||||
"Congratulations! You just self-funded your own corporation. You can visit " +
|
||||
"and manage your company in the City.",
|
||||
);
|
||||
removePopup(props.popupId);
|
||||
}
|
||||
|
||||
function seed(): void {
|
||||
if (name == "") {
|
||||
dialogBoxCreate("Invalid company name!");
|
||||
return;
|
||||
}
|
||||
|
||||
props.player.startCorporation(name, 500e6);
|
||||
|
||||
dialogBoxCreate(
|
||||
"Congratulations! You just started your own corporation with government seed money. " +
|
||||
"You can visit and manage your company in the City.",
|
||||
);
|
||||
removePopup(props.popupId);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Would you like to start a corporation? This will require $150b for registration and initial funding. This $150b
|
||||
can either be self-funded, or you can obtain the seed money from the government in exchange for 500 million
|
||||
shares
|
||||
<br />
|
||||
<br />
|
||||
If you would like to start one, please enter a name for your corporation below:
|
||||
</p>
|
||||
<input autoFocus={true} className="text-input" placeholder="Corporation Name" onChange={onChange} value={name} />
|
||||
<button className="std-button" onClick={seed} disabled={name == ""}>
|
||||
Use seed money
|
||||
</button>
|
||||
<button className="std-button" onClick={selfFund} disabled={name == "" || !props.player.canAfford(150e9)}>
|
||||
Self-Fund (<Money money={150e9} player={props.player} />)
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
@ -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}>
|
||||
|
@ -273,7 +273,7 @@ export function Overview(props: IProps): React.ReactElement {
|
||||
function Upgrades(): React.ReactElement {
|
||||
// Don't show upgrades
|
||||
if (props.corp.divisions.length <= 0) {
|
||||
return <></>;
|
||||
return <h1>Unlock upgrades after creating your first division</h1>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
58
src/Faction/ui/CreateGangPopup.tsx
Normal file
58
src/Faction/ui/CreateGangPopup.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* React Component for the popup used to create a new gang.
|
||||
*/
|
||||
import React from "react";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { IEngine } from "../../IEngine";
|
||||
|
||||
interface ICreateGangPopupProps {
|
||||
popupId: string;
|
||||
facName: string;
|
||||
p: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
|
||||
export function CreateGangPopup(props: ICreateGangPopupProps): React.ReactElement {
|
||||
|
||||
const combatGangText = "This is a COMBAT gang. Members in this gang will have different tasks than HACKING gangs. " +
|
||||
"Compared to hacking gangs, progression with combat gangs can be more difficult as territory management " +
|
||||
"is more important. However, well-managed combat gangs can progress faster than hacking ones.";
|
||||
|
||||
const hackingGangText = "This is a HACKING gang. Members in this gang will have different tasks than COMBAT gangs. " +
|
||||
"Compared to combat gangs, progression with hacking gangs is more straightforward as territory warfare " +
|
||||
"is not as important.";
|
||||
|
||||
function isHacking(): boolean {
|
||||
return ["NiteSec", "The Black Hand"].includes(props.facName);
|
||||
}
|
||||
|
||||
function createGang(): void {
|
||||
props.p.startGang(props.facName, isHacking());
|
||||
removePopup(props.popupId);
|
||||
props.engine.loadGangContent();
|
||||
}
|
||||
|
||||
function onKeyUp(event: React.KeyboardEvent): void {
|
||||
if (event.keyCode === 13) createGang();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Would you like to create a new Gang with {props.facName}?
|
||||
<br/>
|
||||
<br/>
|
||||
Note that this will prevent you from creating a Gang with any other Faction until this BitNode is destroyed. It also resets your reputation with this faction.
|
||||
<br/>
|
||||
<br/>
|
||||
{ (isHacking()) ? hackingGangText : combatGangText }
|
||||
<br/>
|
||||
<br/>
|
||||
Other than hacking vs combat, there are NO differences between the Factions you can create a Gang with, and each of these Factions have all Augmentations available.
|
||||
<div className="popup-box-input-div" >
|
||||
<StdButton onClick={createGang} onKeyUp={onKeyUp} text="Create Gang" style={{float: "right"}} autoFocus={true}/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
@ -19,7 +19,8 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { createSleevePurchasesFromCovenantPopup } from "../../PersonObjects/Sleeve/SleeveCovenantPurchases";
|
||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||
|
||||
import { yesNoBoxClose, yesNoBoxCreate, yesNoBoxGetNoButton, yesNoBoxGetYesButton } from "../../../utils/YesNoBox";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { CreateGangPopup } from "./CreateGangPopup";
|
||||
|
||||
type IProps = {
|
||||
engine: IEngine;
|
||||
@ -97,59 +98,13 @@ export class FactionRoot extends React.Component<IProps, IState> {
|
||||
return this.props.engine.loadGangContent();
|
||||
}
|
||||
|
||||
// Otherwise, we have to create the gang
|
||||
const facName = this.props.faction.name;
|
||||
let isHacking = false;
|
||||
if (facName === "NiteSec" || facName === "The Black Hand") {
|
||||
isHacking = true;
|
||||
}
|
||||
|
||||
// A Yes/No popup box will allow the player to confirm gang creation
|
||||
const yesBtn = yesNoBoxGetYesButton();
|
||||
const noBtn = yesNoBoxGetNoButton();
|
||||
if (yesBtn == null || noBtn == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
yesBtn.innerHTML = "Create Gang";
|
||||
yesBtn.addEventListener("click", () => {
|
||||
this.props.p.startGang(facName, isHacking);
|
||||
const worldMenuHeader = document.getElementById("world-menu-header");
|
||||
if (worldMenuHeader instanceof HTMLElement) {
|
||||
worldMenuHeader.click();
|
||||
worldMenuHeader.click();
|
||||
}
|
||||
|
||||
this.props.engine.loadGangContent();
|
||||
yesNoBoxClose();
|
||||
const popupId = "create-gang-popup";
|
||||
createPopup(popupId, CreateGangPopup, {
|
||||
popupId: popupId,
|
||||
facName: this.props.faction.name,
|
||||
p: this.props.p,
|
||||
engine: this.props.engine
|
||||
});
|
||||
|
||||
noBtn.innerHTML = "Cancel";
|
||||
noBtn.addEventListener("click", () => {
|
||||
yesNoBoxClose();
|
||||
});
|
||||
|
||||
// Pop-up text
|
||||
let gangTypeText = "";
|
||||
if (isHacking) {
|
||||
gangTypeText =
|
||||
"This is a HACKING gang. Members in this gang will have different tasks than COMBAT gangs. " +
|
||||
"Compared to combat gangs, progression with hacking gangs is more straightforward as territory warfare " +
|
||||
"is not as important.<br><br>";
|
||||
} else {
|
||||
gangTypeText =
|
||||
"This is a COMBAT gang. Members in this gang will have different tasks than HACKING gangs. " +
|
||||
"Compared to hacking gangs, progression with combat gangs can be more difficult as territory management " +
|
||||
"is more important. However, well-managed combat gangs can progress faster than hacking ones.<br><br>";
|
||||
}
|
||||
yesNoBoxCreate(
|
||||
`Would you like to create a new Gang with ${facName}?<br><br>` +
|
||||
"Note that this will prevent you from creating a Gang with any other Faction until " +
|
||||
"this BitNode is destroyed. It also resets your reputation with this faction.<br><br>" +
|
||||
gangTypeText +
|
||||
"Other than hacking vs combat, there are NO differences between the Factions you can " +
|
||||
"create a Gang with, and each of these Factions have all Augmentations available.",
|
||||
);
|
||||
}
|
||||
|
||||
rerender(): void {
|
||||
@ -223,7 +178,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,9 +221,9 @@ export class FactionRoot extends React.Component<IProps, IState> {
|
||||
|
||||
renderAugmentationsPage(): React.ReactNode {
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<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 className="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>
|
||||
<>
|
||||
<h1>Hacknet {hasHacknetServers(props.player) ? "Servers" : "Nodes"}</h1>
|
||||
<GeneralInfo hasHacknetServers={hasHacknetServers(props.player)} />
|
||||
|
||||
@ -140,6 +140,6 @@ export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
)}
|
||||
|
||||
<ul id={"hacknet-nodes-list"}>{nodes}</ul>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -9,24 +9,13 @@ import { CityName } from "./data/CityNames";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { AddToAllServers, createUniqueRandomIp } from "../Server/AllServers";
|
||||
import { safetlyCreateUniqueServer } from "../Server/ServerHelpers";
|
||||
import { getPurchaseServerCost, purchaseServer } from "../Server/ServerPurchases";
|
||||
import { SpecialServerIps } from "../Server/SpecialServerIps";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { Money } from "../ui/React/Money";
|
||||
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import {
|
||||
yesNoBoxGetYesButton,
|
||||
yesNoBoxGetNoButton,
|
||||
yesNoBoxClose,
|
||||
yesNoBoxCreate,
|
||||
yesNoTxtInpBoxGetYesButton,
|
||||
yesNoTxtInpBoxGetNoButton,
|
||||
yesNoTxtInpBoxClose,
|
||||
yesNoTxtInpBoxCreate,
|
||||
} from "../../utils/YesNoBox";
|
||||
import { yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose, yesNoBoxCreate } from "../../utils/YesNoBox";
|
||||
|
||||
import { createElement } from "../../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../../utils/uiHelpers/createPopup";
|
||||
@ -34,232 +23,6 @@ import { createPopupCloseButton } from "../../utils/uiHelpers/createPopupCloseBu
|
||||
import { removeElementById } from "../../utils/uiHelpers/removeElementById";
|
||||
import * as React from "react";
|
||||
|
||||
/**
|
||||
* Create a pop-up box that lets the player confirm traveling to a different city.
|
||||
* If settings are configured to suppress this popup, just instantly travel.
|
||||
* The actual "Travel" implementation is implemented in the UI, and is passed in
|
||||
* as an argument.
|
||||
* @param {CityName} destination - City that the player is traveling to
|
||||
* @param {Function} travelFn - Function that changes the player's state for traveling
|
||||
*/
|
||||
type TravelFunction = (to: CityName) => void;
|
||||
export function createTravelPopup(destination: CityName, travelFn: TravelFunction): void {
|
||||
const cost: number = CONSTANTS.TravelCost;
|
||||
|
||||
if (Settings.SuppressTravelConfirmation) {
|
||||
travelFn(destination);
|
||||
return;
|
||||
}
|
||||
|
||||
const yesBtn = yesNoBoxGetYesButton();
|
||||
const noBtn = yesNoBoxGetNoButton();
|
||||
if (yesBtn == null || noBtn == null) {
|
||||
console.warn(`Could not find YesNo pop-up box buttons`);
|
||||
return;
|
||||
}
|
||||
|
||||
yesBtn.innerHTML = "Yes";
|
||||
yesBtn.addEventListener("click", () => {
|
||||
yesNoBoxClose();
|
||||
travelFn(destination);
|
||||
return false;
|
||||
});
|
||||
|
||||
noBtn.innerHTML = "No";
|
||||
noBtn.addEventListener("click", () => {
|
||||
yesNoBoxClose();
|
||||
return false;
|
||||
});
|
||||
|
||||
yesNoBoxCreate(
|
||||
<span>
|
||||
Would you like to travel to {destination}? The trip will cost <Money money={cost} />.
|
||||
</span>,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pop-up box that lets the player purchase a server.
|
||||
* @param {number} ram - Amount of RAM (GB) on server
|
||||
* @param {IPlayer} p - Player object
|
||||
*/
|
||||
export function createPurchaseServerPopup(ram: number, p: IPlayer): void {
|
||||
const cost = getPurchaseServerCost(ram);
|
||||
if (cost === Infinity) {
|
||||
dialogBoxCreate("Something went wrong when trying to purchase this server. Please contact developer.");
|
||||
return;
|
||||
}
|
||||
|
||||
const yesBtn = yesNoTxtInpBoxGetYesButton();
|
||||
const noBtn = yesNoTxtInpBoxGetNoButton();
|
||||
if (yesBtn == null || noBtn == null) {
|
||||
return;
|
||||
}
|
||||
yesBtn.innerHTML = "Purchase Server";
|
||||
noBtn.innerHTML = "Cancel";
|
||||
yesBtn.addEventListener("click", function () {
|
||||
purchaseServer(ram, p);
|
||||
yesNoTxtInpBoxClose();
|
||||
});
|
||||
noBtn.addEventListener("click", function () {
|
||||
yesNoTxtInpBoxClose();
|
||||
});
|
||||
|
||||
yesNoTxtInpBoxCreate(
|
||||
<>
|
||||
Would you like to purchase a new server with {numeralWrapper.formatRAM(ram)} of RAM for{" "}
|
||||
<Money money={cost} player={p} />?
|
||||
<br />
|
||||
<br />
|
||||
Please enter the server hostname below:
|
||||
<br />
|
||||
</>,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a popup that lets the player start a Corporation
|
||||
* @param {IPlayer} p - Player object
|
||||
*/
|
||||
export function createStartCorporationPopup(p: IPlayer): void {
|
||||
if (!p.canAccessCorporation() || p.hasCorporation()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const popupId = "create-corporation-popup";
|
||||
const txt = createElement("p", {
|
||||
innerHTML:
|
||||
"Would you like to start a corporation? This will require $150b for registration " +
|
||||
"and initial funding. This $150b can either be self-funded, or you can obtain " +
|
||||
"the seed money from the government in exchange for 500 million shares<br><br>" +
|
||||
"If you would like to start one, please enter a name for your corporation below:",
|
||||
});
|
||||
|
||||
const nameInput = createElement("input", {
|
||||
class: "text-input",
|
||||
placeholder: "Corporation Name",
|
||||
}) as HTMLInputElement;
|
||||
|
||||
const selfFundedButton = createElement("button", {
|
||||
class: "popup-box-button",
|
||||
innerText: "Self-Fund",
|
||||
clickListener: () => {
|
||||
if (!p.canAfford(150e9)) {
|
||||
dialogBoxCreate("You don't have enough money to create a corporation! You need $150b.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const companyName = nameInput.value;
|
||||
if (companyName == null || companyName == "") {
|
||||
dialogBoxCreate("Invalid company name!");
|
||||
return false;
|
||||
}
|
||||
|
||||
p.startCorporation(companyName);
|
||||
p.loseMoney(150e9);
|
||||
|
||||
const worldHeader = document.getElementById("world-menu-header");
|
||||
if (worldHeader instanceof HTMLElement) {
|
||||
worldHeader.click();
|
||||
worldHeader.click();
|
||||
}
|
||||
dialogBoxCreate(
|
||||
"Congratulations! You just self-funded your own corporation. You can visit " +
|
||||
"and manage your company in the City.",
|
||||
);
|
||||
removeElementById(popupId);
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
const seedMoneyButton = createElement("button", {
|
||||
class: "popup-box-button",
|
||||
innerText: "Use Seed Money",
|
||||
clickListener: () => {
|
||||
const companyName = nameInput.value;
|
||||
if (companyName == null || companyName == "") {
|
||||
dialogBoxCreate("Invalid company name!");
|
||||
return false;
|
||||
}
|
||||
|
||||
p.startCorporation(companyName, 500e6);
|
||||
|
||||
const worldHeader = document.getElementById("world-menu-header");
|
||||
if (worldHeader instanceof HTMLElement) {
|
||||
worldHeader.click();
|
||||
worldHeader.click();
|
||||
}
|
||||
dialogBoxCreate(
|
||||
"Congratulations! You just started your own corporation with government seed money. " +
|
||||
"You can visit and manage your company in the City.",
|
||||
);
|
||||
removeElementById(popupId);
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
const cancelBtn = createPopupCloseButton(popupId, {
|
||||
class: "popup-box-button",
|
||||
});
|
||||
|
||||
createPopup(popupId, [txt, nameInput, cancelBtn, selfFundedButton, seedMoneyButton]);
|
||||
nameInput.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a popup that lets the player upgrade the cores on his/her home computer
|
||||
* @param {IPlayer} p - Player object
|
||||
*/
|
||||
export function createUpgradeHomeCoresPopup(p: IPlayer): void {
|
||||
const currentCores = p.getHomeComputer().cpuCores;
|
||||
if (currentCores >= 8) {
|
||||
dialogBoxCreate(<>You have the maximum amount of CPU cores on your home computer.</>);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cost of purchasing another cost is found by indexing this array with number of current cores
|
||||
const allCosts = [0, 10e9, 250e9, 5e12, 100e12, 1e15, 20e15, 200e15];
|
||||
const cost: number = allCosts[currentCores];
|
||||
|
||||
const yesBtn = yesNoBoxGetYesButton();
|
||||
const noBtn = yesNoBoxGetNoButton();
|
||||
if (yesBtn == null || noBtn == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
yesBtn.innerHTML = "Purchase";
|
||||
yesBtn.addEventListener("click", () => {
|
||||
if (!p.canAfford(cost)) {
|
||||
dialogBoxCreate("You do not have enough money to purchase an additional CPU Core for your home computer!");
|
||||
} else {
|
||||
p.loseMoney(cost);
|
||||
p.getHomeComputer().cpuCores++;
|
||||
dialogBoxCreate(
|
||||
"You purchased an additional CPU Core for your home computer! It now has " +
|
||||
p.getHomeComputer().cpuCores +
|
||||
" cores.",
|
||||
);
|
||||
}
|
||||
yesNoBoxClose();
|
||||
});
|
||||
|
||||
noBtn.innerHTML = "Cancel";
|
||||
noBtn.addEventListener("click", () => {
|
||||
yesNoBoxClose();
|
||||
});
|
||||
|
||||
yesNoBoxCreate(
|
||||
<>
|
||||
Would you like to purchase an additional CPU Core for your home computer? Each CPU Core lets you start with an
|
||||
additional Core Node in Hacking Missions.
|
||||
<br />
|
||||
<br />
|
||||
Purchasing an additional core (for a total of {p.getHomeComputer().cpuCores + 1}) will cost{" "}
|
||||
<Money money={cost} player={p} />
|
||||
</>,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to purchase a TOR router
|
||||
* @param {IPlayer} p - Player object
|
||||
|
58
src/Locations/ui/PurchaseServerPopup.tsx
Normal file
58
src/Locations/ui/PurchaseServerPopup.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* React Component for the popup used to purchase a new server.
|
||||
*/
|
||||
import React, { useState } from "react";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
import { purchaseServer } from "../../Server/ServerPurchases";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
|
||||
interface IPurchaseServerPopupProps {
|
||||
ram: number;
|
||||
cost: number;
|
||||
p: IPlayer;
|
||||
popupId: string;
|
||||
rerender: () => void;
|
||||
}
|
||||
|
||||
export function PurchaseServerPopup(props: IPurchaseServerPopupProps): React.ReactElement {
|
||||
const [hostname, setHostname] = useState("");
|
||||
|
||||
function tryToPurchaseServer(): void {
|
||||
purchaseServer(hostname, props.ram, props.cost, props.p);
|
||||
|
||||
removePopup(props.popupId);
|
||||
}
|
||||
|
||||
function onKeyUp(event: React.KeyboardEvent<HTMLInputElement>): void {
|
||||
if (event.keyCode === 13) tryToPurchaseServer();
|
||||
}
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setHostname(event.target.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Would you like to purchase a new server with {numeralWrapper.formatRAM(props.ram)} of RAM for{" "}
|
||||
<Money money={props.cost} player={props.p} />?
|
||||
<br />
|
||||
<br />
|
||||
Please enter the server hostname below:
|
||||
<br />
|
||||
<div className="popup-box-input-div">
|
||||
<input
|
||||
autoFocus
|
||||
onKeyUp={onKeyUp}
|
||||
onChange={onChange}
|
||||
className="text-input noselect"
|
||||
type="text"
|
||||
placeholder="Unique Hostname"
|
||||
/>
|
||||
<StdButton onClick={tryToPurchaseServer} text="Purchase Server" disabled={!props.p.canAfford(props.cost)} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
@ -13,7 +13,8 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { Location } from "../Location";
|
||||
import { createStartCorporationPopup } from "../LocationsHelpers";
|
||||
import { CreateCorporationPopup } from "../../Corporation/ui/CreateCorporationPopup";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { LocationName } from "../data/LocationNames";
|
||||
|
||||
import { IEngine } from "../../IEngine";
|
||||
@ -59,7 +60,11 @@ export class SpecialLocation extends React.Component<IProps, IState> {
|
||||
* Click handler for "Create Corporation" button at Sector-12 City Hall
|
||||
*/
|
||||
createCorporationPopup(): void {
|
||||
createStartCorporationPopup(this.props.p);
|
||||
const popupId = `create-start-corporation-popup`;
|
||||
createPopup(popupId, CreateCorporationPopup, {
|
||||
player: this.props.p,
|
||||
popupId: popupId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,10 +3,9 @@
|
||||
*
|
||||
* 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 { createPurchaseServerPopup } from "../LocationsHelpers";
|
||||
import { RamButton } from "./RamButton";
|
||||
import { TorButton } from "./TorButton";
|
||||
import { CoresButton } from "./CoresButton";
|
||||
@ -14,8 +13,12 @@ import { CoresButton } from "./CoresButton";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { getPurchaseServerCost } from "../../Server/ServerPurchases";
|
||||
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { PurchaseServerPopup } from "./PurchaseServerPopup";
|
||||
|
||||
|
||||
type IProps = {
|
||||
loc: Location;
|
||||
@ -23,10 +26,28 @@ type IProps = {
|
||||
};
|
||||
|
||||
export function TechVendorLocation(props: IProps): React.ReactElement {
|
||||
|
||||
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
|
||||
function openPurchaseServer(ram: number, cost: number, p: IPlayer): void {
|
||||
const popupId = "purchase-server-popup";
|
||||
createPopup(popupId, PurchaseServerPopup, {
|
||||
ram: ram,
|
||||
cost: cost,
|
||||
p: p,
|
||||
popupId: popupId,
|
||||
rerender: rerender
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 1000);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
const btnStyle = { display: "block" };
|
||||
|
||||
const purchaseServerButtons: React.ReactNode[] = [];
|
||||
@ -35,7 +56,7 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
|
||||
purchaseServerButtons.push(
|
||||
<StdButton
|
||||
key={i}
|
||||
onClick={() => createPurchaseServerPopup(i, props.p)}
|
||||
onClick={() => openPurchaseServer(i, cost, props.p)}
|
||||
style={btnStyle}
|
||||
text={
|
||||
<>
|
||||
|
@ -6,13 +6,14 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { CityName } from "../data/CityNames";
|
||||
import { createTravelPopup } from "../LocationsHelpers";
|
||||
import { TravelConfirmationPopup } from "./TravelConfirmationPopup";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { WorldMap } from "../../ui/React/WorldMap";
|
||||
|
||||
@ -21,67 +22,63 @@ type IProps = {
|
||||
travel: (to: CityName) => void;
|
||||
};
|
||||
|
||||
export class TravelAgencyLocation extends React.Component<IProps, any> {
|
||||
/**
|
||||
* Stores button styling that sets them all to block display
|
||||
*/
|
||||
btnStyle: any;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.btnStyle = { display: "block" };
|
||||
function createTravelPopup(p: IPlayer, city: string, travel: () => void): void {
|
||||
if (Settings.SuppressTravelConfirmation) {
|
||||
travel();
|
||||
return;
|
||||
}
|
||||
const popupId = `travel-confirmation`;
|
||||
createPopup(popupId, TravelConfirmationPopup, {
|
||||
player: p,
|
||||
city: city,
|
||||
travel: travel,
|
||||
popupId: popupId,
|
||||
});
|
||||
}
|
||||
|
||||
asciiWorldMap(): React.ReactNode {
|
||||
// map needs all this whitespace!
|
||||
// prettier-ignore
|
||||
return (
|
||||
<div className="noselect">
|
||||
<p>
|
||||
From here, you can travel to any other city! A ticket costs{" "}
|
||||
<Money money={CONSTANTS.TravelCost} player={this.props.p} />.
|
||||
</p>
|
||||
<WorldMap currentCity={this.props.p.city} onTravel={(city: CityName) => createTravelPopup(city, this.props.travel)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function ASCIIWorldMap(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<div className="noselect">
|
||||
<p>
|
||||
From here, you can travel to any other city! A ticket costs{" "}
|
||||
<Money money={CONSTANTS.TravelCost} player={props.p} />.
|
||||
</p>
|
||||
<WorldMap
|
||||
currentCity={props.p.city}
|
||||
onTravel={(city: CityName) => createTravelPopup(props.p, city, () => props.travel(city))}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
listWorldMap(): React.ReactNode {
|
||||
const travelBtns: React.ReactNode[] = [];
|
||||
for (const key in CityName) {
|
||||
const city: CityName = (CityName as any)[key];
|
||||
function ListWorldMap(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
From here, you can travel to any other city! A ticket costs{" "}
|
||||
<Money money={CONSTANTS.TravelCost} player={props.p} />.
|
||||
</p>
|
||||
{Object.values(CityName)
|
||||
.filter((city: string) => city != props.p.city)
|
||||
.map((city: string) => (
|
||||
<StdButton
|
||||
key={city}
|
||||
onClick={() =>
|
||||
createTravelPopup(props.p, city, () => props.travel(CityName[city as keyof typeof CityName]))
|
||||
}
|
||||
style={{ display: "block" }}
|
||||
text={`Travel to ${city}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Skip current city
|
||||
if (city === this.props.p.city) {
|
||||
continue;
|
||||
}
|
||||
|
||||
travelBtns.push(
|
||||
<StdButton
|
||||
key={city}
|
||||
onClick={createTravelPopup.bind(null, city, this.props.travel)}
|
||||
style={this.btnStyle}
|
||||
text={`Travel to ${city}`}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
From here, you can travel to any other city! A ticket costs <Money money={CONSTANTS.TravelCost} />.
|
||||
</p>
|
||||
{travelBtns}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
if (Settings.DisableASCIIArt) {
|
||||
return this.listWorldMap();
|
||||
} else {
|
||||
return this.asciiWorldMap();
|
||||
}
|
||||
export function TravelAgencyLocation(props: IProps): React.ReactElement {
|
||||
console.log(Settings.DisableASCIIArt);
|
||||
if (Settings.DisableASCIIArt) {
|
||||
return <ListWorldMap p={props.p} travel={props.travel} />;
|
||||
} else {
|
||||
return <ASCIIWorldMap p={props.p} travel={props.travel} />;
|
||||
}
|
||||
}
|
||||
|
33
src/Locations/ui/TravelConfirmationPopup.tsx
Normal file
33
src/Locations/ui/TravelConfirmationPopup.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
city: string;
|
||||
travel: () => void;
|
||||
popupId: string;
|
||||
}
|
||||
|
||||
export function TravelConfirmationPopup(props: IProps): React.ReactElement {
|
||||
const cost = CONSTANTS.TravelCost;
|
||||
function travel(): void {
|
||||
props.travel();
|
||||
removePopup(props.popupId);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>
|
||||
Would you like to travel to {props.city}? The trip will cost <Money money={cost} player={props.player} />.
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<button className="std-button" onClick={travel}>
|
||||
Travel
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
@ -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 className="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;
|
||||
}
|
||||
|
@ -160,13 +160,13 @@ export function PlayerObject() {
|
||||
this.has4SDataTixApi = false;
|
||||
|
||||
//Gang
|
||||
this.gang = 0;
|
||||
this.gang = null;
|
||||
|
||||
//Corporation
|
||||
this.corporation = 0;
|
||||
this.corporation = null;
|
||||
|
||||
//Bladeburner
|
||||
this.bladeburner = 0;
|
||||
this.bladeburner = null;
|
||||
this.bladeburner_max_stamina_mult = 1;
|
||||
this.bladeburner_stamina_gain_mult = 1;
|
||||
this.bladeburner_analysis_mult = 1; //Field Analysis Only
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -64,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 "------":
|
||||
@ -108,10 +109,13 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
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 = (
|
||||
<>
|
||||
|
@ -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 (
|
||||
<>
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
}
|
1
src/SaveObject.d.ts
vendored
Normal file
1
src/SaveObject.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare const saveObject: any;
|
@ -308,7 +308,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="script-editor-wrapper">
|
||||
<div className="script-editor-wrapper">
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag" className="noselect">
|
||||
{" "}
|
||||
|
@ -10,7 +10,6 @@ import { CONSTANTS } from "../Constants";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import { yesNoTxtInpBoxGetInput } from "../../utils/YesNoBox";
|
||||
import { isPowerOfTwo } from "../../utils/helpers/isPowerOfTwo";
|
||||
|
||||
// Returns the cost of purchasing a server with the given RAM
|
||||
@ -44,9 +43,7 @@ export function getPurchaseServerMaxRam(): number {
|
||||
}
|
||||
|
||||
// Manually purchase a server (NOT through Netscript)
|
||||
export function purchaseServer(ram: number, p: IPlayer): void {
|
||||
const cost = getPurchaseServerCost(ram);
|
||||
|
||||
export function purchaseServer(hostname: string, ram: number, cost: number, p: IPlayer): void {
|
||||
//Check if player has enough money
|
||||
if (!p.canAfford(cost)) {
|
||||
dialogBoxCreate("You don't have enough money to purchase this server!", false);
|
||||
@ -65,7 +62,6 @@ export function purchaseServer(ram: number, p: IPlayer): void {
|
||||
return;
|
||||
}
|
||||
|
||||
const hostname = yesNoTxtInpBoxGetInput();
|
||||
if (hostname == "") {
|
||||
dialogBoxCreate("You must enter a hostname for your new server!");
|
||||
return;
|
||||
|
274
src/Sidebar/ui/SidebarRoot.tsx
Normal file
274
src/Sidebar/ui/SidebarRoot.tsx
Normal file
@ -0,0 +1,274 @@
|
||||
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.loadCharacterContent();
|
||||
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;
|
||||
|
||||
// TODO(hydroflame): these should not as any but right now the def is that it
|
||||
// can only be defined;
|
||||
const canCorporation = !!(props.player.corporation as any);
|
||||
const canGang = !!(props.player.gang as any);
|
||||
const canJob = props.player.companyName !== "";
|
||||
const canStockMarket = props.player.hasWseAccount;
|
||||
const canBladeburner = !!(props.player.bladeburner as any);
|
||||
|
||||
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>
|
||||
{canJob && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadJobContent()}>Job</button>
|
||||
</li>
|
||||
)}
|
||||
{canStockMarket && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadStockMarketContent()}>Stock Market</button>
|
||||
</li>
|
||||
)}
|
||||
{canBladeburner && (
|
||||
<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 className="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 (
|
||||
<>
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
}
|
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;
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -8,7 +8,6 @@ import "../css/mainmenu.scss";
|
||||
import "../css/characteroverview.scss";
|
||||
import "../css/terminal.scss";
|
||||
import "../css/scripteditor.scss";
|
||||
import "../css/codemirror-overrides.scss";
|
||||
import "../css/activescripts.scss";
|
||||
import "../css/hacknetnodes.scss";
|
||||
import "../css/menupages.scss";
|
||||
@ -32,4 +31,3 @@ import "../css/dev-menu.css";
|
||||
import "../css/casino.scss";
|
||||
import "../css/milestones.scss";
|
||||
import "../css/infiltration.scss";
|
||||
import "../css/corporation.scss";
|
||||
|
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,10 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Character Info page -->
|
||||
<div id="character-container" class="generic-menupage-container">
|
||||
<div id="character-content"></div>
|
||||
<div class="generic-menupage-container">
|
||||
<div id="generic-react-container"></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="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 +102,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 className="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 />
|
||||
<>
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -6,9 +6,11 @@ import * as React from "react";
|
||||
|
||||
interface IStdButtonProps {
|
||||
addClasses?: string;
|
||||
autoFocus?: boolean;
|
||||
disabled?: boolean;
|
||||
id?: string;
|
||||
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
|
||||
onKeyUp?: (e: React.KeyboardEvent<HTMLElement>) => any;
|
||||
style?: any;
|
||||
text: string | JSX.Element;
|
||||
tooltip?: string | JSX.Element;
|
||||
@ -43,7 +45,7 @@ export function StdButton(props: IStdButtonProps): React.ReactElement {
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={className} id={props.id} onClick={props.onClick} style={props.style}>
|
||||
<button className={className} id={props.id} onClick={props.onClick} onKeyUp={props.onKeyUp} style={props.style} autoFocus={props.autoFocus}>
|
||||
{props.text}
|
||||
{hasTooltip && tooltip}
|
||||
</button>
|
||||
|
@ -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