mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-22 15:43:49 +01:00
Merge pull request #3449 from danielyxie/dev
basic doc no longer hacker themed
This commit is contained in:
commit
a9eaea0568
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
.history
|
||||||
.vscode
|
.vscode
|
||||||
Changelog.txt
|
Changelog.txt
|
||||||
Netburner.txt
|
Netburner.txt
|
||||||
|
@ -1,453 +0,0 @@
|
|||||||
:root {
|
|
||||||
--dark-text-color: #0c0;
|
|
||||||
--dark-link-color: #090;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-nav-content-wrap {
|
|
||||||
background-color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-nav-content {
|
|
||||||
background-color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .highlighted {
|
|
||||||
background: #333;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight {
|
|
||||||
background-color: #17181c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight .nn {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight .nb {
|
|
||||||
color: #8bb8df;
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight .kn,
|
|
||||||
.highlight .kc,
|
|
||||||
.highlight .k {
|
|
||||||
color: #41c2ea;
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight .s1,
|
|
||||||
.highlight .s2 {
|
|
||||||
color: #b3e87f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight .nt {
|
|
||||||
color: #ccb350;
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight .c1 {
|
|
||||||
color: #686868;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content div[class^="highlight"] {
|
|
||||||
border-color: #1a1a1a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon,
|
|
||||||
.icon-home {
|
|
||||||
color: var(--dark-link-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-nav-content a,
|
|
||||||
.wy-nav-content a:visited {
|
|
||||||
color: var(--dark-link-color) !important;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-neutral {
|
|
||||||
background-color: #17181c !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-neutral:hover {
|
|
||||||
background-color: #101114 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-neutral:visited {
|
|
||||||
color: #c1c1c1 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
color: #bdbdbd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-nav-side {
|
|
||||||
background-color: #000;
|
|
||||||
border: 1px solid #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical > a {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical li.current {
|
|
||||||
background-color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical li.current > a,
|
|
||||||
.wy-menu-vertical li.on a {
|
|
||||||
background-color: #000;
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical li.toctree-l1.current > a,
|
|
||||||
.wy-menu-vertical li.current a {
|
|
||||||
border-color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical header,
|
|
||||||
.wy-menu-vertical p.caption {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
html.writer-html4 .rst-content dl:not(.docutils) > dt,
|
|
||||||
html.writer-html5
|
|
||||||
.rst-content
|
|
||||||
dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)
|
|
||||||
> dt {
|
|
||||||
background-color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical li.current a {
|
|
||||||
color: #090;
|
|
||||||
}
|
|
||||||
.wy-menu-vertical a {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical li.current a:hover {
|
|
||||||
background-color: #222;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical a:hover,
|
|
||||||
.wy-menu-vertical li.current > a:hover,
|
|
||||||
.wy-menu-vertical li.on a:hover {
|
|
||||||
background-color: #000;
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical li.toctree-l2.current > a,
|
|
||||||
.wy-menu-vertical li.toctree-l2.current li.toctree-l3 > a {
|
|
||||||
background-color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-side-nav-search {
|
|
||||||
background-color: #000;
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-side-nav-search .wy-dropdown > a,
|
|
||||||
.wy-side-nav-search > a {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-side-nav-search input[type="text"] {
|
|
||||||
border-left: 0px;
|
|
||||||
border-right: 0px;
|
|
||||||
border-top: 0px;
|
|
||||||
border-radius: 0px;
|
|
||||||
box-shadow: none;
|
|
||||||
border-bottom-color: #0c0;
|
|
||||||
background-color: #333;
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-switcher {
|
|
||||||
background-color: #0b0c0d;
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer-html4 .rst-content dl:not(.docutils) > dt,
|
|
||||||
writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) > dt {
|
|
||||||
background-color: #0b0b0b;
|
|
||||||
color: #007dce;
|
|
||||||
border-color: #282828;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content code,
|
|
||||||
.rst-content tt {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list) > dt,
|
|
||||||
writer-html5
|
|
||||||
.rst-content
|
|
||||||
dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)
|
|
||||||
dl:not(.field-list)
|
|
||||||
> dt {
|
|
||||||
background-color: #0f0f0f;
|
|
||||||
color: #959595;
|
|
||||||
border-color: #2b2b2b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content code,
|
|
||||||
.rst-content tt,
|
|
||||||
code {
|
|
||||||
background-color: #2d2d2d;
|
|
||||||
border-color: #1c1c1c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content code.xref,
|
|
||||||
.rst-content tt.xref,
|
|
||||||
a .rst-content code,
|
|
||||||
a .rst-content tt {
|
|
||||||
color: #cecece;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .hint,
|
|
||||||
.rst-content .important,
|
|
||||||
.rst-content .tip,
|
|
||||||
.rst-content .wy-alert-success.admonition,
|
|
||||||
.rst-content .wy-alert-success.admonition-todo,
|
|
||||||
.rst-content .wy-alert-success.attention,
|
|
||||||
.rst-content .wy-alert-success.caution,
|
|
||||||
.rst-content .wy-alert-success.danger,
|
|
||||||
.rst-content .wy-alert-success.error,
|
|
||||||
.rst-content .wy-alert-success.note,
|
|
||||||
.rst-content .wy-alert-success.seealso,
|
|
||||||
.rst-content .wy-alert-success.warning,
|
|
||||||
.wy-alert.wy-alert-success {
|
|
||||||
background-color: #00392e;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .hint .admonition-title,
|
|
||||||
.rst-content .hint .wy-alert-title,
|
|
||||||
.rst-content .important .admonition-title,
|
|
||||||
.rst-content .important .wy-alert-title,
|
|
||||||
.rst-content .tip .admonition-title,
|
|
||||||
.rst-content .tip .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.admonition-todo .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.admonition-todo .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.admonition .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.admonition .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.attention .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.attention .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.caution .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.caution .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.danger .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.danger .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.error .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.error .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.note .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.note .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.seealso .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.seealso .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-success.warning .admonition-title,
|
|
||||||
.rst-content .wy-alert-success.warning .wy-alert-title,
|
|
||||||
.rst-content .wy-alert.wy-alert-success .admonition-title,
|
|
||||||
.wy-alert.wy-alert-success .rst-content .admonition-title,
|
|
||||||
.wy-alert.wy-alert-success .wy-alert-title {
|
|
||||||
background-color: #006a56;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .note,
|
|
||||||
.rst-content .seealso,
|
|
||||||
.rst-content .wy-alert-info.admonition,
|
|
||||||
.rst-content .wy-alert-info.admonition-todo,
|
|
||||||
.rst-content .wy-alert-info.attention,
|
|
||||||
.rst-content .wy-alert-info.caution,
|
|
||||||
.rst-content .wy-alert-info.danger,
|
|
||||||
.rst-content .wy-alert-info.error,
|
|
||||||
.rst-content .wy-alert-info.hint,
|
|
||||||
.rst-content .wy-alert-info.important,
|
|
||||||
.rst-content .wy-alert-info.tip,
|
|
||||||
.rst-content .wy-alert-info.warning,
|
|
||||||
.wy-alert.wy-alert-info {
|
|
||||||
background-color: #002c4d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .note .admonition-title,
|
|
||||||
.rst-content .note .wy-alert-title,
|
|
||||||
.rst-content .seealso .admonition-title,
|
|
||||||
.rst-content .seealso .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.admonition-todo .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.admonition-todo .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.admonition .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.admonition .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.attention .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.attention .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.caution .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.caution .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.danger .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.danger .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.error .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.error .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.hint .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.hint .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.important .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.important .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.tip .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.tip .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-info.warning .admonition-title,
|
|
||||||
.rst-content .wy-alert-info.warning .wy-alert-title,
|
|
||||||
.rst-content .wy-alert.wy-alert-info .admonition-title,
|
|
||||||
.wy-alert.wy-alert-info .rst-content .admonition-title,
|
|
||||||
.wy-alert.wy-alert-info .wy-alert-title {
|
|
||||||
background-color: #004a7b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content dl:not(.docutils) dt {
|
|
||||||
background-color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .admonition-todo,
|
|
||||||
.rst-content .attention,
|
|
||||||
.rst-content .caution,
|
|
||||||
.rst-content .warning,
|
|
||||||
.rst-content .wy-alert-warning.admonition,
|
|
||||||
.rst-content .wy-alert-warning.danger,
|
|
||||||
.rst-content .wy-alert-warning.error,
|
|
||||||
.rst-content .wy-alert-warning.hint,
|
|
||||||
.rst-content .wy-alert-warning.important,
|
|
||||||
.rst-content .wy-alert-warning.note,
|
|
||||||
.rst-content .wy-alert-warning.seealso,
|
|
||||||
.rst-content .wy-alert-warning.tip,
|
|
||||||
.wy-alert.wy-alert-warning {
|
|
||||||
background-color: #533500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .admonition-todo .admonition-title,
|
|
||||||
.rst-content .admonition-todo .wy-alert-title,
|
|
||||||
.rst-content .attention .admonition-title,
|
|
||||||
.rst-content .attention .wy-alert-title,
|
|
||||||
.rst-content .caution .admonition-title,
|
|
||||||
.rst-content .caution .wy-alert-title,
|
|
||||||
.rst-content .warning .admonition-title,
|
|
||||||
.rst-content .warning .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-warning.admonition .admonition-title,
|
|
||||||
.rst-content .wy-alert-warning.admonition .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-warning.danger .admonition-title,
|
|
||||||
.rst-content .wy-alert-warning.danger .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-warning.error .admonition-title,
|
|
||||||
.rst-content .wy-alert-warning.error .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-warning.hint .admonition-title,
|
|
||||||
.rst-content .wy-alert-warning.hint .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-warning.important .admonition-title,
|
|
||||||
.rst-content .wy-alert-warning.important .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-warning.note .admonition-title,
|
|
||||||
.rst-content .wy-alert-warning.note .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-warning.seealso .admonition-title,
|
|
||||||
.rst-content .wy-alert-warning.seealso .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-warning.tip .admonition-title,
|
|
||||||
.rst-content .wy-alert-warning.tip .wy-alert-title,
|
|
||||||
.rst-content .wy-alert.wy-alert-warning .admonition-title,
|
|
||||||
.wy-alert.wy-alert-warning .rst-content .admonition-title,
|
|
||||||
.wy-alert.wy-alert-warning .wy-alert-title {
|
|
||||||
background-color: #803b00;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .danger,
|
|
||||||
.rst-content .error,
|
|
||||||
.rst-content .wy-alert-danger.admonition,
|
|
||||||
.rst-content .wy-alert-danger.admonition-todo,
|
|
||||||
.rst-content .wy-alert-danger.attention,
|
|
||||||
.rst-content .wy-alert-danger.caution,
|
|
||||||
.rst-content .wy-alert-danger.hint,
|
|
||||||
.rst-content .wy-alert-danger.important,
|
|
||||||
.rst-content .wy-alert-danger.note,
|
|
||||||
.rst-content .wy-alert-danger.seealso,
|
|
||||||
.rst-content .wy-alert-danger.tip,
|
|
||||||
.rst-content .wy-alert-danger.warning,
|
|
||||||
.wy-alert.wy-alert-danger {
|
|
||||||
background-color: #82231a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content .danger .admonition-title,
|
|
||||||
.rst-content .danger .wy-alert-title,
|
|
||||||
.rst-content .error .admonition-title,
|
|
||||||
.rst-content .error .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.admonition-todo .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.admonition .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.admonition .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.attention .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.attention .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.caution .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.caution .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.hint .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.hint .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.important .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.important .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.note .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.note .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.seealso .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.seealso .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.tip .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.tip .wy-alert-title,
|
|
||||||
.rst-content .wy-alert-danger.warning .admonition-title,
|
|
||||||
.rst-content .wy-alert-danger.warning .wy-alert-title,
|
|
||||||
.rst-content .wy-alert.wy-alert-danger .admonition-title,
|
|
||||||
.wy-alert.wy-alert-danger .rst-content .admonition-title,
|
|
||||||
.wy-alert.wy-alert-danger .wy-alert-title {
|
|
||||||
background-color: #b9372b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-nav-top {
|
|
||||||
background-color: #0b152d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content table.docutils thead,
|
|
||||||
.rst-content table.field-list thead,
|
|
||||||
.wy-table thead {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,
|
|
||||||
.wy-table-backed,
|
|
||||||
.wy-table-odd td,
|
|
||||||
.wy-table-striped tr:nth-child(2n-1) td {
|
|
||||||
background-color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content table.docutils:not(.field-list) tr:nth-child(2n) td,
|
|
||||||
.wy-table-backed,
|
|
||||||
.wy-table-odd td,
|
|
||||||
.wy-table-striped tr:nth-child(2n) td {
|
|
||||||
background-color: #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content table.docutils td,
|
|
||||||
.wy-table-bordered-all td,
|
|
||||||
writer-html5 .rst-content table.docutils th,
|
|
||||||
.rst-content table.docutils,
|
|
||||||
.wy-table-bordered-all {
|
|
||||||
border-color: #262626;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rst-content table.docutils caption,
|
|
||||||
.rst-content table.field-list caption,
|
|
||||||
.wy-table caption {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-menu-vertical li.toctree-l3.current > a,
|
|
||||||
.wy-menu-vertical li.toctree-l3.current li.toctree-l4 > a {
|
|
||||||
background-color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wy-side-nav-search > div.version {
|
|
||||||
color: var(--dark-text-color);
|
|
||||||
}
|
|
@ -8,7 +8,6 @@ import { CONSTANTS } from "../Constants";
|
|||||||
import { Factions, factionExists } from "../Faction/Factions";
|
import { Factions, factionExists } from "../Faction/Factions";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { prestigeAugmentation } from "../Prestige";
|
import { prestigeAugmentation } from "../Prestige";
|
||||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { clearObject } from "../utils/helpers/clearObject";
|
import { clearObject } from "../utils/helpers/clearObject";
|
||||||
@ -73,7 +72,7 @@ function initAugmentations(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getBaseAugmentationPriceMultiplier(): number {
|
function getBaseAugmentationPriceMultiplier(): number {
|
||||||
return CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][SourceFileFlags[11]];
|
return CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][Player.sourceFileLvl(11)];
|
||||||
}
|
}
|
||||||
export function getGenericAugmentationPriceMultiplier(): number {
|
export function getGenericAugmentationPriceMultiplier(): number {
|
||||||
return Math.pow(getBaseAugmentationPriceMultiplier(), Player.queuedAugmentations.length);
|
return Math.pow(getBaseAugmentationPriceMultiplier(), Player.queuedAugmentations.length);
|
||||||
|
@ -7,7 +7,6 @@ import * as React from "react";
|
|||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||||
import { Player } from "../../Player";
|
import { Player } from "../../Player";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { Augmentations } from "../Augmentations";
|
import { Augmentations } from "../Augmentations";
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ interface IBitNodeModifiedStatsProps {
|
|||||||
|
|
||||||
function BitNodeModifiedStats(props: IBitNodeModifiedStatsProps): React.ReactElement {
|
function BitNodeModifiedStats(props: IBitNodeModifiedStatsProps): React.ReactElement {
|
||||||
// If player doesn't have SF5 or if the property isn't affected by BitNode mults
|
// If player doesn't have SF5 or if the property isn't affected by BitNode mults
|
||||||
if (props.mult === 1 || SourceFileFlags[5] === 0)
|
if (props.mult === 1 || Player.sourceFileLvl(5) === 0)
|
||||||
return <Typography color={props.color}>{numeralWrapper.formatPercentage(props.base)}</Typography>;
|
return <Typography color={props.color}>{numeralWrapper.formatPercentage(props.base)}</Typography>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|
||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { BitNodes } from "../BitNode";
|
import { BitNodes } from "../BitNode";
|
||||||
import { enterBitNode } from "../../RedPill";
|
import { enterBitNode } from "../../RedPill";
|
||||||
@ -128,12 +127,6 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
const destroyed = player.bitNodeN;
|
const destroyed = player.bitNodeN;
|
||||||
const [destroySequence, setDestroySequence] = useState(!props.quick);
|
const [destroySequence, setDestroySequence] = useState(!props.quick);
|
||||||
|
|
||||||
// Update NextSourceFileFlags
|
|
||||||
const nextSourceFileFlags = SourceFileFlags.slice();
|
|
||||||
if (!props.flume) {
|
|
||||||
if (nextSourceFileFlags[destroyed] < 3) ++nextSourceFileFlags[destroyed];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (destroySequence) {
|
if (destroySequence) {
|
||||||
return (
|
return (
|
||||||
<CinematicText
|
<CinematicText
|
||||||
@ -164,6 +157,15 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nextSourceFileLvl = (n: number): number => {
|
||||||
|
const lvl = player.sourceFileLvl(n);
|
||||||
|
if (n !== destroyed) {
|
||||||
|
return lvl;
|
||||||
|
}
|
||||||
|
const max = n === 12 ? Infinity : 3;
|
||||||
|
return Math.min(max, lvl + 1);
|
||||||
|
};
|
||||||
|
|
||||||
if (Settings.DisableASCIIArt) {
|
if (Settings.DisableASCIIArt) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -177,7 +179,7 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
<BitNodePortal
|
<BitNodePortal
|
||||||
key={node.number}
|
key={node.number}
|
||||||
n={node.number}
|
n={node.number}
|
||||||
level={nextSourceFileFlags[node.number]}
|
level={nextSourceFileLvl(node.number)}
|
||||||
enter={enter}
|
enter={enter}
|
||||||
flume={props.flume}
|
flume={props.flume}
|
||||||
destroyedBitNode={destroyed}
|
destroyedBitNode={destroyed}
|
||||||
@ -216,6 +218,8 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const n = nextSourceFileLvl;
|
||||||
return (
|
return (
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
<>
|
<>
|
||||||
@ -229,19 +233,19 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>O | | | \| | O / _/ | / O | |/ | | | O</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>O | | | \| | O / _/ | / O | |/ | | | O</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | | |O / | | O / | O O | | \ O| | | |</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | | |O / | | O / | O O | | \ O| | | |</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | |/ \/ / __| | |/ \ | \ | |__ \ \/ \| | |</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | |/ \/ / __| | |/ \ | \ | |__ \ \/ \| | |</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| O | |_/ |\| \ <BitNodePortal n={13} level={nextSourceFileFlags[13]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \__| \_| | O |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| O | |_/ |\| \ <BitNodePortal n={13} level={n(13)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \__| \_| | O |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | |_/ | | \| / | \_| | | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | |_/ | | \| / | \_| | | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| / \| | / / \ |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| / \| | / / \ |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | <BitNodePortal n={10} level={nextSourceFileFlags[10]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | / | <BitNodePortal n={11} level={nextSourceFileFlags[11]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | <BitNodePortal n={10} level={n(10)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | / | <BitNodePortal n={11} level={n(11)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> <BitNodePortal n={9} level={nextSourceFileFlags[9]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | | | | | | <BitNodePortal n={12} level={nextSourceFileFlags[12]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> <BitNodePortal n={9} level={n(9)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | | | | | | <BitNodePortal n={12} level={n(12)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | / / \ \ | | | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | / / \ \ | | | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| | / <BitNodePortal n={7} level={nextSourceFileFlags[7]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> / \ <BitNodePortal n={8} level={nextSourceFileFlags[8]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \ | |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| | / <BitNodePortal n={7} level={n(7)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> / \ <BitNodePortal n={8} level={n(8)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \ | |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ | / / | | \ \ | / </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ | / / | | \ \ | / </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ \JUMP <BitNodePortal n={5} level={nextSourceFileFlags[5]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} />3R | | | | | | R3<BitNodePortal n={6} level={nextSourceFileFlags[6]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> PMUJ/ / </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ \JUMP <BitNodePortal n={5} level={n(5)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} />3R | | | | | | R3<BitNodePortal n={6} level={n(6)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> PMUJ/ / </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \|| | | | | | | | | ||/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \|| | | | | | | | | ||/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| \_ | | | | | | _/ |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| \_ | | | | | | _/ |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ \| / \ / \ |/ / </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ \| / \ / \ |/ / </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> <BitNodePortal n={1} level={nextSourceFileFlags[1]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> |/ <BitNodePortal n={2} level={nextSourceFileFlags[2]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | <BitNodePortal n={3} level={nextSourceFileFlags[3]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \| <BitNodePortal n={4} level={nextSourceFileFlags[4]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> <BitNodePortal n={1} level={n(1)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> |/ <BitNodePortal n={2} level={n(2)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | <BitNodePortal n={3} level={n(3)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \| <BitNodePortal n={4} level={n(4)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | | | | | | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | | | | | | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \JUMP3R|JUMP|3R| |R3|PMUJ|R3PMUJ/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \JUMP3R|JUMP|3R| |R3|PMUJ|R3PMUJ/ </Typography>
|
||||||
<br />
|
<br />
|
||||||
|
@ -28,7 +28,6 @@ import { Factions, factionExists } from "../Faction/Factions";
|
|||||||
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { Settings } from "../Settings/Settings";
|
import { Settings } from "../Settings/Settings";
|
||||||
import { Augmentations } from "../Augmentation/Augmentations";
|
|
||||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||||
import { getTimestamp } from "../utils/helpers/getTimestamp";
|
import { getTimestamp } from "../utils/helpers/getTimestamp";
|
||||||
import { joinFaction } from "../Faction/FactionHelpers";
|
import { joinFaction } from "../Faction/FactionHelpers";
|
||||||
|
@ -117,7 +117,7 @@ export const CONSTANTS: {
|
|||||||
LatestUpdate: string;
|
LatestUpdate: string;
|
||||||
} = {
|
} = {
|
||||||
VersionString: "1.6.4",
|
VersionString: "1.6.4",
|
||||||
VersionNumber: 13,
|
VersionNumber: 14,
|
||||||
|
|
||||||
// Speed (in ms) at which the main loop is updated
|
// Speed (in ms) at which the main loop is updated
|
||||||
_idleSpeed: 200,
|
_idleSpeed: 200,
|
||||||
|
@ -51,29 +51,31 @@ export function NewIndustry(corporation: ICorporation, industry: string, name: s
|
|||||||
export function NewCity(corporation: ICorporation, division: IIndustry, city: string): void {
|
export function NewCity(corporation: ICorporation, division: IIndustry, city: string): void {
|
||||||
if (corporation.funds < CorporationConstants.OfficeInitialCost) {
|
if (corporation.funds < CorporationConstants.OfficeInitialCost) {
|
||||||
throw new Error("You don't have enough company funds to open a new office!");
|
throw new Error("You don't have enough company funds to open a new office!");
|
||||||
} else {
|
|
||||||
corporation.funds = corporation.funds - CorporationConstants.OfficeInitialCost;
|
|
||||||
division.offices[city] = new OfficeSpace({
|
|
||||||
loc: city,
|
|
||||||
size: CorporationConstants.OfficeInitialSize,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
if (division.offices[city]) {
|
||||||
|
throw new Error(`You have already expanded into ${city} for ${division.name}`);
|
||||||
|
}
|
||||||
|
corporation.funds = corporation.funds - CorporationConstants.OfficeInitialCost;
|
||||||
|
division.offices[city] = new OfficeSpace({
|
||||||
|
loc: city,
|
||||||
|
size: CorporationConstants.OfficeInitialSize,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UnlockUpgrade(corporation: ICorporation, upgrade: CorporationUnlockUpgrade): void {
|
export function UnlockUpgrade(corporation: ICorporation, upgrade: CorporationUnlockUpgrade): void {
|
||||||
if (corporation.funds < upgrade[1]) {
|
if (corporation.funds < upgrade.price) {
|
||||||
throw new Error("Insufficient funds");
|
throw new Error("Insufficient funds");
|
||||||
}
|
}
|
||||||
if (corporation.unlockUpgrades[upgrade[0]] === 1) {
|
if (corporation.unlockUpgrades[upgrade.index] === 1) {
|
||||||
throw new Error(`You have already unlocked the ${upgrade[2]} upgrade!`);
|
throw new Error(`You have already unlocked the ${upgrade.name} upgrade!`);
|
||||||
}
|
}
|
||||||
corporation.unlock(upgrade);
|
corporation.unlock(upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgrade): void {
|
export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgrade): void {
|
||||||
const baseCost = upgrade[1];
|
const baseCost = upgrade.basePrice;
|
||||||
const priceMult = upgrade[2];
|
const priceMult = upgrade.priceMult;
|
||||||
const level = corporation.upgrades[upgrade[0]];
|
const level = corporation.upgrades[upgrade.index];
|
||||||
const cost = baseCost * Math.pow(priceMult, level);
|
const cost = baseCost * Math.pow(priceMult, level);
|
||||||
if (corporation.funds < cost) {
|
if (corporation.funds < cost) {
|
||||||
throw new Error("Insufficient funds");
|
throw new Error("Insufficient funds");
|
||||||
@ -345,10 +347,17 @@ export function PurchaseWarehouse(corp: ICorporation, division: IIndustry, city:
|
|||||||
corp.funds = corp.funds - CorporationConstants.WarehouseInitialCost;
|
corp.funds = corp.funds - CorporationConstants.WarehouseInitialCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, warehouse: Warehouse): void {
|
export function UpgradeWarehouseCost(warehouse: Warehouse, amt: number): number {
|
||||||
const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1);
|
return Array.from(Array(amt).keys()).reduce(
|
||||||
|
(acc, index) => acc + CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1 + index),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, warehouse: Warehouse, amt = 1): void {
|
||||||
|
const sizeUpgradeCost = UpgradeWarehouseCost(warehouse, amt);
|
||||||
if (corp.funds < sizeUpgradeCost) return;
|
if (corp.funds < sizeUpgradeCost) return;
|
||||||
++warehouse.level;
|
warehouse.level += amt;
|
||||||
warehouse.updateSize(corp, division);
|
warehouse.updateSize(corp, division);
|
||||||
corp.funds = corp.funds - sizeUpgradeCost;
|
corp.funds = corp.funds - sizeUpgradeCost;
|
||||||
}
|
}
|
||||||
@ -416,7 +425,7 @@ export function MakeProduct(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const product = new Product({
|
const product = new Product({
|
||||||
name: productName.replace(/[<>]/g, ""), //Sanitize for HTMl elements
|
name: productName.replace(/[<>]/g, "").trim(), //Sanitize for HTMl elements
|
||||||
createCity: city,
|
createCity: city,
|
||||||
designCost: designInvest,
|
designCost: designInvest,
|
||||||
advCost: marketingInvest,
|
advCost: marketingInvest,
|
||||||
@ -488,12 +497,23 @@ export function CancelExportMaterial(divisionName: string, cityName: string, mat
|
|||||||
export function LimitProductProduction(product: Product, cityName: string, qty: number): void {
|
export function LimitProductProduction(product: Product, cityName: string, qty: number): void {
|
||||||
if (qty < 0 || isNaN(qty)) {
|
if (qty < 0 || isNaN(qty)) {
|
||||||
product.prdman[cityName][0] = false;
|
product.prdman[cityName][0] = false;
|
||||||
|
product.prdman[cityName][1] = 0;
|
||||||
} else {
|
} else {
|
||||||
product.prdman[cityName][0] = true;
|
product.prdman[cityName][0] = true;
|
||||||
product.prdman[cityName][1] = qty;
|
product.prdman[cityName][1] = qty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function LimitMaterialProduction(material: Material, qty: number): void {
|
||||||
|
if (qty < 0 || isNaN(qty)) {
|
||||||
|
material.prdman[0] = false;
|
||||||
|
material.prdman[1] = 0;
|
||||||
|
} else {
|
||||||
|
material.prdman[0] = true;
|
||||||
|
material.prdman[1] = qty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function SetMaterialMarketTA1(material: Material, on: boolean): void {
|
export function SetMaterialMarketTA1(material: Material, on: boolean): void {
|
||||||
material.marketTa1 = on;
|
material.marketTa1 = on;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,8 @@ export class Corporation {
|
|||||||
upgrades: number[];
|
upgrades: number[];
|
||||||
upgradeMultipliers: number[];
|
upgradeMultipliers: number[];
|
||||||
|
|
||||||
|
avgProfit = 0;
|
||||||
|
|
||||||
state = new CorporationState();
|
state = new CorporationState();
|
||||||
|
|
||||||
constructor(params: IParams = {}) {
|
constructor(params: IParams = {}) {
|
||||||
@ -106,6 +108,8 @@ export class Corporation {
|
|||||||
this.expenses = this.expenses + ind.lastCycleExpenses;
|
this.expenses = this.expenses + ind.lastCycleExpenses;
|
||||||
});
|
});
|
||||||
const profit = this.revenue - this.expenses;
|
const profit = this.revenue - this.expenses;
|
||||||
|
this.avgProfit =
|
||||||
|
(this.avgProfit * (CorporationConstants.AvgProfitLength - 1) + profit) / CorporationConstants.AvgProfitLength;
|
||||||
const cycleProfit = profit * (marketCycles * CorporationConstants.SecsPerMarketCycle);
|
const cycleProfit = profit * (marketCycles * CorporationConstants.SecsPerMarketCycle);
|
||||||
if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) {
|
if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
@ -160,7 +164,7 @@ export class Corporation {
|
|||||||
|
|
||||||
determineValuation(): number {
|
determineValuation(): number {
|
||||||
let val,
|
let val,
|
||||||
profit = this.revenue - this.expenses;
|
profit = this.avgProfit;
|
||||||
if (this.public) {
|
if (this.public) {
|
||||||
// Account for dividends
|
// Account for dividends
|
||||||
if (this.dividendPercentage > 0) {
|
if (this.dividendPercentage > 0) {
|
||||||
@ -260,8 +264,8 @@ export class Corporation {
|
|||||||
|
|
||||||
//One time upgrades that unlock new features
|
//One time upgrades that unlock new features
|
||||||
unlock(upgrade: CorporationUnlockUpgrade): void {
|
unlock(upgrade: CorporationUnlockUpgrade): void {
|
||||||
const upgN = upgrade[0],
|
const upgN = upgrade.index,
|
||||||
price = upgrade[1];
|
price = upgrade.price;
|
||||||
while (this.unlockUpgrades.length <= upgN) {
|
while (this.unlockUpgrades.length <= upgN) {
|
||||||
this.unlockUpgrades.push(0);
|
this.unlockUpgrades.push(0);
|
||||||
}
|
}
|
||||||
@ -282,10 +286,10 @@ export class Corporation {
|
|||||||
|
|
||||||
//Levelable upgrades
|
//Levelable upgrades
|
||||||
upgrade(upgrade: CorporationUpgrade): void {
|
upgrade(upgrade: CorporationUpgrade): void {
|
||||||
const upgN = upgrade[0],
|
const upgN = upgrade.index,
|
||||||
basePrice = upgrade[1],
|
basePrice = upgrade.basePrice,
|
||||||
priceMult = upgrade[2],
|
priceMult = upgrade.priceMult,
|
||||||
upgradeAmt = upgrade[3]; //Amount by which the upgrade multiplier gets increased (additive)
|
upgradeAmt = upgrade.benefit; //Amount by which the upgrade multiplier gets increased (additive)
|
||||||
while (this.upgrades.length <= upgN) {
|
while (this.upgrades.length <= upgN) {
|
||||||
this.upgrades.push(0);
|
this.upgrades.push(0);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ export const CorporationConstants: {
|
|||||||
AllMaterials: string[];
|
AllMaterials: string[];
|
||||||
FundingRoundShares: number[];
|
FundingRoundShares: number[];
|
||||||
FundingRoundMultiplier: number[];
|
FundingRoundMultiplier: number[];
|
||||||
|
AvgProfitLength: number;
|
||||||
} = {
|
} = {
|
||||||
INITIALSHARES: 1e9, //Total number of shares you have at your company
|
INITIALSHARES: 1e9, //Total number of shares you have at your company
|
||||||
SHARESPERPRICEUPDATE: 1e6, //When selling large number of shares, price is dynamically updated for every batch of this amount
|
SHARESPERPRICEUPDATE: 1e6, //When selling large number of shares, price is dynamically updated for every batch of this amount
|
||||||
@ -83,4 +84,6 @@ export const CorporationConstants: {
|
|||||||
],
|
],
|
||||||
FundingRoundShares: [0.1, 0.35, 0.25, 0.2],
|
FundingRoundShares: [0.1, 0.35, 0.25, 0.2],
|
||||||
FundingRoundMultiplier: [4, 3, 3, 2.5],
|
FundingRoundMultiplier: [4, 3, 3, 2.5],
|
||||||
|
|
||||||
|
AvgProfitLength: 1,
|
||||||
};
|
};
|
||||||
|
@ -1,70 +1,100 @@
|
|||||||
import { IMap } from "../../types";
|
export interface CorporationUnlockUpgrade {
|
||||||
|
index: number;
|
||||||
|
price: number;
|
||||||
|
name: string;
|
||||||
|
desc: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type CorporationUnlockUpgrade = [number, number, string, string];
|
export enum CorporationUnlockUpgradeIndex {
|
||||||
|
Export = 0,
|
||||||
|
SmartSupply = 1,
|
||||||
|
MarketResearchDemand = 2,
|
||||||
|
MarketDataCompetition = 3,
|
||||||
|
VeChain = 4,
|
||||||
|
ShadyAccounting = 5,
|
||||||
|
GovernmentPartnership = 6,
|
||||||
|
WarehouseAPI = 7,
|
||||||
|
OfficeAPI = 8,
|
||||||
|
}
|
||||||
|
|
||||||
// Corporation Unlock Upgrades
|
// Corporation Unlock Upgrades
|
||||||
// Upgrades for entire corporation, unlocks features, either you have it or you dont
|
// Upgrades for entire corporation, unlocks features, either you have it or you dont
|
||||||
// The data structure is an array with the following format:
|
export const CorporationUnlockUpgrades: Record<CorporationUnlockUpgradeIndex, CorporationUnlockUpgrade> = {
|
||||||
// [index in Corporation feature upgrades array, price, name, description]
|
|
||||||
export const CorporationUnlockUpgrades: IMap<CorporationUnlockUpgrade> = {
|
|
||||||
//Lets you export goods
|
//Lets you export goods
|
||||||
"0": [
|
[CorporationUnlockUpgradeIndex.Export]: {
|
||||||
0,
|
index: 0,
|
||||||
20e9,
|
price: 20e9,
|
||||||
"Export",
|
name: "Export",
|
||||||
"Develop infrastructure to export your materials to your other facilities. " +
|
desc:
|
||||||
|
"Develop infrastructure to export your materials to your other facilities. " +
|
||||||
"This allows you to move materials around between different divisions and cities.",
|
"This allows you to move materials around between different divisions and cities.",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Lets you buy exactly however many required materials you need for production
|
//Lets you buy exactly however many required materials you need for production
|
||||||
"1": [
|
[CorporationUnlockUpgradeIndex.SmartSupply]: {
|
||||||
1,
|
index: 1,
|
||||||
25e9,
|
price: 25e9,
|
||||||
"Smart Supply",
|
name: "Smart Supply",
|
||||||
"Use advanced AI to anticipate your supply needs. " +
|
desc:
|
||||||
|
"Use advanced AI to anticipate your supply needs. " +
|
||||||
"This allows you to purchase exactly however many materials you need for production.",
|
"This allows you to purchase exactly however many materials you need for production.",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Displays each material/product's demand
|
//Displays each material/product's demand
|
||||||
"2": [
|
[CorporationUnlockUpgradeIndex.MarketResearchDemand]: {
|
||||||
2,
|
index: 2,
|
||||||
5e9,
|
price: 5e9,
|
||||||
"Market Research - Demand",
|
name: "Market Research - Demand",
|
||||||
"Mine and analyze market data to determine the demand of all resources. " +
|
desc:
|
||||||
|
"Mine and analyze market data to determine the demand of all resources. " +
|
||||||
"The demand attribute, which affects sales, will be displayed for every material and product.",
|
"The demand attribute, which affects sales, will be displayed for every material and product.",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Display's each material/product's competition
|
//Display's each material/product's competition
|
||||||
"3": [
|
[CorporationUnlockUpgradeIndex.MarketDataCompetition]: {
|
||||||
3,
|
index: 3,
|
||||||
5e9,
|
price: 5e9,
|
||||||
"Market Data - Competition",
|
name: "Market Data - Competition",
|
||||||
"Mine and analyze market data to determine how much competition there is on the market " +
|
desc:
|
||||||
|
"Mine and analyze market data to determine how much competition there is on the market " +
|
||||||
"for all resources. The competition attribute, which affects sales, will be displayed for " +
|
"for all resources. The competition attribute, which affects sales, will be displayed for " +
|
||||||
"every material and product.",
|
"every material and product.",
|
||||||
],
|
},
|
||||||
"4": [
|
[CorporationUnlockUpgradeIndex.VeChain]: {
|
||||||
4,
|
index: 4,
|
||||||
10e9,
|
price: 10e9,
|
||||||
"VeChain",
|
name: "VeChain",
|
||||||
"Use AI and blockchain technology to identify where you can improve your supply chain systems. " +
|
desc:
|
||||||
|
"Use AI and blockchain technology to identify where you can improve your supply chain systems. " +
|
||||||
"This upgrade will allow you to view a wide array of useful statistics about your " +
|
"This upgrade will allow you to view a wide array of useful statistics about your " +
|
||||||
"Corporation.",
|
"Corporation.",
|
||||||
],
|
},
|
||||||
"5": [
|
[CorporationUnlockUpgradeIndex.ShadyAccounting]: {
|
||||||
5,
|
index: 5,
|
||||||
500e12,
|
price: 500e12,
|
||||||
"Shady Accounting",
|
name: "Shady Accounting",
|
||||||
"Utilize unscrupulous accounting practices and pay off government officials to save money " +
|
desc:
|
||||||
|
"Utilize unscrupulous accounting practices and pay off government officials to save money " +
|
||||||
"on taxes. This reduces the dividend tax rate by 5%.",
|
"on taxes. This reduces the dividend tax rate by 5%.",
|
||||||
],
|
},
|
||||||
"6": [
|
[CorporationUnlockUpgradeIndex.GovernmentPartnership]: {
|
||||||
6,
|
index: 6,
|
||||||
2e15,
|
price: 2e15,
|
||||||
"Government Partnership",
|
name: "Government Partnership",
|
||||||
"Help national governments further their agendas in exchange for lowered taxes. " +
|
desc:
|
||||||
|
"Help national governments further their agendas in exchange for lowered taxes. " +
|
||||||
"This reduces the dividend tax rate by 10%",
|
"This reduces the dividend tax rate by 10%",
|
||||||
],
|
},
|
||||||
"7": [7, 50e9, "Warehouse API", "Enables the warehouse API."],
|
[CorporationUnlockUpgradeIndex.WarehouseAPI]: {
|
||||||
"8": [8, 50e9, "Office API", "Enables the office API."],
|
index: 7,
|
||||||
|
price: 50e9,
|
||||||
|
name: "Warehouse API",
|
||||||
|
desc: "Enables the warehouse API.",
|
||||||
|
},
|
||||||
|
[CorporationUnlockUpgradeIndex.OfficeAPI]: {
|
||||||
|
index: 8,
|
||||||
|
price: 50e9,
|
||||||
|
name: "Office API",
|
||||||
|
desc: "Enables the office API.",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,127 +1,153 @@
|
|||||||
import { IMap } from "../../types";
|
export interface CorporationUpgrade {
|
||||||
|
index: number;
|
||||||
|
basePrice: number;
|
||||||
|
priceMult: number;
|
||||||
|
benefit: number;
|
||||||
|
name: string;
|
||||||
|
desc: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type CorporationUpgrade = [number, number, number, number, string, string];
|
export enum CorporationUpgradeIndex {
|
||||||
|
SmartFactories = 0,
|
||||||
|
SmartStorage = 1,
|
||||||
|
DreamSense = 2,
|
||||||
|
WilsonAnalytics = 3,
|
||||||
|
NuoptimalNootropicInjectorImplants = 4,
|
||||||
|
SpeechProcessorImplants = 5,
|
||||||
|
NeuralAccelerators = 6,
|
||||||
|
FocusWires = 7,
|
||||||
|
ABCSalesBots = 8,
|
||||||
|
ProjectInsight = 9,
|
||||||
|
}
|
||||||
|
|
||||||
// Corporation Upgrades
|
// Corporation Upgrades
|
||||||
// Upgrades for entire corporation, levelable upgrades
|
// Upgrades for entire corporation, levelable upgrades
|
||||||
// The data structure is an array with the following format
|
export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpgrade> = {
|
||||||
// [index in Corporation upgrades array, base price, price mult, benefit mult (additive), name, desc]
|
|
||||||
export const CorporationUpgrades: IMap<CorporationUpgrade> = {
|
|
||||||
//Smart factories, increases production
|
//Smart factories, increases production
|
||||||
"0": [
|
[CorporationUpgradeIndex.SmartFactories]: {
|
||||||
0,
|
index: CorporationUpgradeIndex.SmartFactories,
|
||||||
2e9,
|
basePrice: 2e9,
|
||||||
1.06,
|
priceMult: 1.06,
|
||||||
0.03,
|
benefit: 0.03,
|
||||||
"Smart Factories",
|
name: "Smart Factories",
|
||||||
"Advanced AI automatically optimizes the operation and productivity " +
|
desc:
|
||||||
|
"Advanced AI automatically optimizes the operation and productivity " +
|
||||||
"of factories. Each level of this upgrade increases your global production by 3% (additive).",
|
"of factories. Each level of this upgrade increases your global production by 3% (additive).",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Smart warehouses, increases storage size
|
//Smart warehouses, increases storage size
|
||||||
"1": [
|
[CorporationUpgradeIndex.SmartStorage]: {
|
||||||
1,
|
index: CorporationUpgradeIndex.SmartStorage,
|
||||||
2e9,
|
basePrice: 2e9,
|
||||||
1.06,
|
priceMult: 1.06,
|
||||||
0.1,
|
benefit: 0.1,
|
||||||
"Smart Storage",
|
name: "Smart Storage",
|
||||||
"Advanced AI automatically optimizes your warehouse storage methods. " +
|
desc:
|
||||||
|
"Advanced AI automatically optimizes your warehouse storage methods. " +
|
||||||
"Each level of this upgrade increases your global warehouse storage size by 10% (additive).",
|
"Each level of this upgrade increases your global warehouse storage size by 10% (additive).",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Advertise through dreams, passive popularity/ awareness gain
|
//Advertise through dreams, passive popularity/ awareness gain
|
||||||
"2": [
|
[CorporationUpgradeIndex.DreamSense]: {
|
||||||
2,
|
index: CorporationUpgradeIndex.DreamSense,
|
||||||
4e9,
|
basePrice: 4e9,
|
||||||
1.1,
|
priceMult: 1.1,
|
||||||
0.001,
|
benefit: 0.001,
|
||||||
"DreamSense",
|
name: "DreamSense",
|
||||||
"Use DreamSense LCC Technologies to advertise your corporation " +
|
desc:
|
||||||
|
"Use DreamSense LCC Technologies to advertise your corporation " +
|
||||||
"to consumers through their dreams. Each level of this upgrade provides a passive " +
|
"to consumers through their dreams. Each level of this upgrade provides a passive " +
|
||||||
"increase in awareness of all of your companies (divisions) by 0.004 / market cycle," +
|
"increase in awareness of all of your companies (divisions) by 0.004 / market cycle," +
|
||||||
"and in popularity by 0.001 / market cycle. A market cycle is approximately " +
|
"and in popularity by 0.001 / market cycle. A market cycle is approximately " +
|
||||||
"15 seconds.",
|
"15 seconds.",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Makes advertising more effective
|
//Makes advertising more effective
|
||||||
"3": [
|
[CorporationUpgradeIndex.WilsonAnalytics]: {
|
||||||
3,
|
index: CorporationUpgradeIndex.WilsonAnalytics,
|
||||||
4e9,
|
basePrice: 4e9,
|
||||||
1.5,
|
priceMult: 1.5,
|
||||||
0.005,
|
benefit: 0.005,
|
||||||
"Wilson Analytics",
|
name: "Wilson Analytics",
|
||||||
"Purchase data and analysis from Wilson, a marketing research " +
|
desc:
|
||||||
|
"Purchase data and analysis from Wilson, a marketing research " +
|
||||||
"firm. Each level of this upgrades increases the effectiveness of your " +
|
"firm. Each level of this upgrades increases the effectiveness of your " +
|
||||||
"advertising by 0.5% (additive).",
|
"advertising by 0.5% (additive).",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Augmentation for employees, increases cre
|
//Augmentation for employees, increases cre
|
||||||
"4": [
|
[CorporationUpgradeIndex.NuoptimalNootropicInjectorImplants]: {
|
||||||
4,
|
index: CorporationUpgradeIndex.NuoptimalNootropicInjectorImplants,
|
||||||
1e9,
|
basePrice: 1e9,
|
||||||
1.06,
|
priceMult: 1.06,
|
||||||
0.1,
|
benefit: 0.1,
|
||||||
"Nuoptimal Nootropic Injector Implants",
|
name: "Nuoptimal Nootropic Injector Implants",
|
||||||
"Purchase the Nuoptimal Nootropic " +
|
desc:
|
||||||
|
"Purchase the Nuoptimal Nootropic " +
|
||||||
"Injector augmentation for your employees. Each level of this upgrade " +
|
"Injector augmentation for your employees. Each level of this upgrade " +
|
||||||
"globally increases the creativity of your employees by 10% (additive).",
|
"globally increases the creativity of your employees by 10% (additive).",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Augmentation for employees, increases cha
|
//Augmentation for employees, increases cha
|
||||||
"5": [
|
[CorporationUpgradeIndex.SpeechProcessorImplants]: {
|
||||||
5,
|
index: CorporationUpgradeIndex.SpeechProcessorImplants,
|
||||||
1e9,
|
basePrice: 1e9,
|
||||||
1.06,
|
priceMult: 1.06,
|
||||||
0.1,
|
benefit: 0.1,
|
||||||
"Speech Processor Implants",
|
name: "Speech Processor Implants",
|
||||||
"Purchase the Speech Processor augmentation for your employees. " +
|
desc:
|
||||||
|
"Purchase the Speech Processor augmentation for your employees. " +
|
||||||
"Each level of this upgrade globally increases the charisma of your employees by 10% (additive).",
|
"Each level of this upgrade globally increases the charisma of your employees by 10% (additive).",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Augmentation for employees, increases int
|
//Augmentation for employees, increases int
|
||||||
"6": [
|
[CorporationUpgradeIndex.NeuralAccelerators]: {
|
||||||
6,
|
index: CorporationUpgradeIndex.NeuralAccelerators,
|
||||||
1e9,
|
basePrice: 1e9,
|
||||||
1.06,
|
priceMult: 1.06,
|
||||||
0.1,
|
benefit: 0.1,
|
||||||
"Neural Accelerators",
|
name: "Neural Accelerators",
|
||||||
"Purchase the Neural Accelerator augmentation for your employees. " +
|
desc:
|
||||||
|
"Purchase the Neural Accelerator augmentation for your employees. " +
|
||||||
"Each level of this upgrade globally increases the intelligence of your employees " +
|
"Each level of this upgrade globally increases the intelligence of your employees " +
|
||||||
"by 10% (additive).",
|
"by 10% (additive).",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Augmentation for employees, increases eff
|
//Augmentation for employees, increases eff
|
||||||
"7": [
|
[CorporationUpgradeIndex.FocusWires]: {
|
||||||
7,
|
index: CorporationUpgradeIndex.FocusWires,
|
||||||
1e9,
|
basePrice: 1e9,
|
||||||
1.06,
|
priceMult: 1.06,
|
||||||
0.1,
|
benefit: 0.1,
|
||||||
"FocusWires",
|
name: "FocusWires",
|
||||||
"Purchase the FocusWire augmentation for your employees. Each level " +
|
desc:
|
||||||
|
"Purchase the FocusWire augmentation for your employees. Each level " +
|
||||||
"of this upgrade globally increases the efficiency of your employees by 10% (additive).",
|
"of this upgrade globally increases the efficiency of your employees by 10% (additive).",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Improves sales of materials/products
|
//Improves sales of materials/products
|
||||||
"8": [
|
[CorporationUpgradeIndex.ABCSalesBots]: {
|
||||||
8,
|
index: CorporationUpgradeIndex.ABCSalesBots,
|
||||||
1e9,
|
basePrice: 1e9,
|
||||||
1.07,
|
priceMult: 1.07,
|
||||||
0.01,
|
benefit: 0.01,
|
||||||
"ABC SalesBots",
|
name: "ABC SalesBots",
|
||||||
"Always Be Closing. Purchase these robotic salesmen to increase the amount of " +
|
desc:
|
||||||
|
"Always Be Closing. Purchase these robotic salesmen to increase the amount of " +
|
||||||
"materials and products you sell. Each level of this upgrade globally increases your sales " +
|
"materials and products you sell. Each level of this upgrade globally increases your sales " +
|
||||||
"by 1% (additive).",
|
"by 1% (additive).",
|
||||||
],
|
},
|
||||||
|
|
||||||
//Improves scientific research rate
|
//Improves scientific research rate
|
||||||
"9": [
|
[CorporationUpgradeIndex.ProjectInsight]: {
|
||||||
9,
|
index: CorporationUpgradeIndex.ProjectInsight,
|
||||||
5e9,
|
basePrice: 5e9,
|
||||||
1.07,
|
priceMult: 1.07,
|
||||||
0.05,
|
benefit: 0.05,
|
||||||
"Project Insight",
|
name: "Project Insight",
|
||||||
"Purchase 'Project Insight', a R&D service provided by the secretive " +
|
desc:
|
||||||
|
"Purchase 'Project Insight', a R&D service provided by the secretive " +
|
||||||
"Fulcrum Technologies. Each level of this upgrade globally increases the amount of " +
|
"Fulcrum Technologies. Each level of this upgrade globally increases the amount of " +
|
||||||
"Scientific Research you produce by 5% (additive).",
|
"Scientific Research you produce by 5% (additive).",
|
||||||
],
|
},
|
||||||
};
|
};
|
||||||
|
@ -8,8 +8,8 @@ import { EmployeePositions } from "../EmployeePositions";
|
|||||||
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
import { UpgradeOfficeSizeModal } from "./UpgradeOfficeSizeModal";
|
import { UpgradeOfficeSizeModal } from "./modals/UpgradeOfficeSizeModal";
|
||||||
import { ThrowPartyModal } from "./ThrowPartyModal";
|
import { ThrowPartyModal } from "./modals/ThrowPartyModal";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { useCorporation, useDivision } from "./Context";
|
import { useCorporation, useDivision } from "./Context";
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ import { Industries } from "../IndustryData";
|
|||||||
import { IndustryUpgrades } from "../IndustryUpgrades";
|
import { IndustryUpgrades } from "../IndustryUpgrades";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
||||||
import { MakeProductModal } from "./MakeProductModal";
|
import { MakeProductModal } from "./modals/MakeProductModal";
|
||||||
import { ResearchModal } from "./ResearchModal";
|
import { ResearchModal } from "./modals/ResearchModal";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||||
import { StatsTable } from "../../ui/React/StatsTable";
|
import { StatsTable } from "../../ui/React/StatsTable";
|
||||||
|
@ -6,7 +6,7 @@ import { CorporationConstants } from "../data/Constants";
|
|||||||
import { Material } from "../Material";
|
import { Material } from "../Material";
|
||||||
import { Product } from "../Product";
|
import { Product } from "../Product";
|
||||||
import { Warehouse } from "../Warehouse";
|
import { Warehouse } from "../Warehouse";
|
||||||
import { SmartSupplyModal } from "./SmartSupplyModal";
|
import { SmartSupplyModal } from "./modals/SmartSupplyModal";
|
||||||
import { ProductElem } from "./ProductElem";
|
import { ProductElem } from "./ProductElem";
|
||||||
import { MaterialElem } from "./MaterialElem";
|
import { MaterialElem } from "./MaterialElem";
|
||||||
import { MaterialSizes } from "../MaterialSizes";
|
import { MaterialSizes } from "../MaterialSizes";
|
||||||
|
@ -20,13 +20,13 @@ interface IProps {
|
|||||||
export function LevelableUpgrade(props: IProps): React.ReactElement {
|
export function LevelableUpgrade(props: IProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const data = props.upgrade;
|
const data = props.upgrade;
|
||||||
const level = corp.upgrades[data[0]];
|
const level = corp.upgrades[data.index];
|
||||||
|
|
||||||
const baseCost = data[1];
|
const baseCost = data.basePrice;
|
||||||
const priceMult = data[2];
|
const priceMult = data.priceMult;
|
||||||
const cost = baseCost * Math.pow(priceMult, level);
|
const cost = baseCost * Math.pow(priceMult, level);
|
||||||
|
|
||||||
const tooltip = data[5];
|
const tooltip = data.desc;
|
||||||
function onClick(): void {
|
function onClick(): void {
|
||||||
if (corp.funds < cost) return;
|
if (corp.funds < cost) return;
|
||||||
try {
|
try {
|
||||||
@ -45,7 +45,7 @@ export function LevelableUpgrade(props: IProps): React.ReactElement {
|
|||||||
</Button>
|
</Button>
|
||||||
<Tooltip title={tooltip}>
|
<Tooltip title={tooltip}>
|
||||||
<Typography>
|
<Typography>
|
||||||
{data[4]} - lvl {level}
|
{data.name} - lvl {level}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -5,10 +5,10 @@ import React, { useState } from "react";
|
|||||||
import { OfficeSpace } from "../OfficeSpace";
|
import { OfficeSpace } from "../OfficeSpace";
|
||||||
import { Material } from "../Material";
|
import { Material } from "../Material";
|
||||||
import { Warehouse } from "../Warehouse";
|
import { Warehouse } from "../Warehouse";
|
||||||
import { ExportModal } from "./ExportModal";
|
import { ExportModal } from "./modals/ExportModal";
|
||||||
import { MaterialMarketTaModal } from "./MaterialMarketTaModal";
|
import { MaterialMarketTaModal } from "./modals/MaterialMarketTaModal";
|
||||||
import { SellMaterialModal } from "./SellMaterialModal";
|
import { SellMaterialModal } from "./modals/SellMaterialModal";
|
||||||
import { PurchaseMaterialModal } from "./PurchaseMaterialModal";
|
import { PurchaseMaterialModal } from "./modals/PurchaseMaterialModal";
|
||||||
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ import Tooltip from "@mui/material/Tooltip";
|
|||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
import { LimitMaterialProductionModal } from "./modals/LimitMaterialProductionModal";
|
||||||
|
|
||||||
interface IMaterialProps {
|
interface IMaterialProps {
|
||||||
warehouse: Warehouse;
|
warehouse: Warehouse;
|
||||||
@ -37,6 +38,8 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
|||||||
const [exportOpen, setExportOpen] = useState(false);
|
const [exportOpen, setExportOpen] = useState(false);
|
||||||
const [sellMaterialOpen, setSellMaterialOpen] = useState(false);
|
const [sellMaterialOpen, setSellMaterialOpen] = useState(false);
|
||||||
const [materialMarketTaOpen, setMaterialMarketTaOpen] = useState(false);
|
const [materialMarketTaOpen, setMaterialMarketTaOpen] = useState(false);
|
||||||
|
const [limitProductionOpen, setLimitProductionOpen] = useState(false);
|
||||||
|
|
||||||
const warehouse = props.warehouse;
|
const warehouse = props.warehouse;
|
||||||
const city = props.city;
|
const city = props.city;
|
||||||
const mat = props.mat;
|
const mat = props.mat;
|
||||||
@ -110,6 +113,12 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
|||||||
sellButtonText = <>Sell (0.000/0.000)</>;
|
sellButtonText = <>Sell (0.000/0.000)</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Limit Production button
|
||||||
|
let limitMaterialButtonText = "Limit Material";
|
||||||
|
if (mat.prdman[0]) {
|
||||||
|
limitMaterialButtonText += " (" + numeralWrapper.format(mat.prdman[1], nf) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper>
|
<Paper>
|
||||||
<Box sx={{ display: "grid", gridTemplateColumns: "2fr 1fr", m: "5px" }}>
|
<Box sx={{ display: "grid", gridTemplateColumns: "2fr 1fr", m: "5px" }}>
|
||||||
@ -194,6 +203,14 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<Button color={tutorial ? "error" : "primary"} onClick={() => setLimitProductionOpen(true)}>
|
||||||
|
{limitMaterialButtonText}
|
||||||
|
</Button>
|
||||||
|
<LimitMaterialProductionModal
|
||||||
|
material={mat}
|
||||||
|
open={limitProductionOpen}
|
||||||
|
onClose={() => setLimitProductionOpen(false)}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
@ -2,18 +2,18 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { LevelableUpgrade } from "./LevelableUpgrade";
|
import { LevelableUpgrade } from "./LevelableUpgrade";
|
||||||
import { UnlockUpgrade } from "./UnlockUpgrade";
|
import { UnlockUpgrade } from "./UnlockUpgrade";
|
||||||
import { BribeFactionModal } from "./BribeFactionModal";
|
import { BribeFactionModal } from "./modals/BribeFactionModal";
|
||||||
import { SellSharesModal } from "./SellSharesModal";
|
import { SellSharesModal } from "./modals/SellSharesModal";
|
||||||
import { BuybackSharesModal } from "./BuybackSharesModal";
|
import { BuybackSharesModal } from "./modals/BuybackSharesModal";
|
||||||
import { IssueDividendsModal } from "./IssueDividendsModal";
|
import { IssueDividendsModal } from "./modals/IssueDividendsModal";
|
||||||
import { IssueNewSharesModal } from "./IssueNewSharesModal";
|
import { IssueNewSharesModal } from "./modals/IssueNewSharesModal";
|
||||||
import { FindInvestorsModal } from "./FindInvestorsModal";
|
import { FindInvestorsModal } from "./modals/FindInvestorsModal";
|
||||||
import { GoPublicModal } from "./GoPublicModal";
|
import { GoPublicModal } from "./modals/GoPublicModal";
|
||||||
import { Factions } from "../../Faction/Factions";
|
import { Factions } from "../../Faction/Factions";
|
||||||
|
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../data/Constants";
|
||||||
import { CorporationUnlockUpgrade, CorporationUnlockUpgrades } from "../data/CorporationUnlockUpgrades";
|
import { CorporationUnlockUpgrade, CorporationUnlockUpgrades } from "../data/CorporationUnlockUpgrades";
|
||||||
import { CorporationUpgrade, CorporationUpgrades } from "../data/CorporationUpgrades";
|
import { CorporationUpgrade, CorporationUpgradeIndex, CorporationUpgrades } from "../data/CorporationUpgrades";
|
||||||
|
|
||||||
import { CONSTANTS } from "../../Constants";
|
import { CONSTANTS } from "../../Constants";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
@ -164,9 +164,9 @@ function Upgrades({ rerender }: IUpgradeProps): React.ReactElement {
|
|||||||
<Typography variant="h4">Unlocks</Typography>
|
<Typography variant="h4">Unlocks</Typography>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
{Object.values(CorporationUnlockUpgrades)
|
{Object.values(CorporationUnlockUpgrades)
|
||||||
.filter((upgrade: CorporationUnlockUpgrade) => !corp.unlockUpgrades[upgrade[0]])
|
.filter((upgrade: CorporationUnlockUpgrade) => !corp.unlockUpgrades[upgrade.index])
|
||||||
.map((upgrade: CorporationUnlockUpgrade) => (
|
.map((upgrade: CorporationUnlockUpgrade) => (
|
||||||
<UnlockUpgrade rerender={rerender} upgradeData={upgrade} key={upgrade[0]} />
|
<UnlockUpgrade rerender={rerender} upgradeData={upgrade} key={upgrade.index} />
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Paper>
|
</Paper>
|
||||||
@ -174,9 +174,9 @@ function Upgrades({ rerender }: IUpgradeProps): React.ReactElement {
|
|||||||
<Typography variant="h4">Upgrades</Typography>
|
<Typography variant="h4">Upgrades</Typography>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
{corp.upgrades
|
{corp.upgrades
|
||||||
.map((level: number, i: number) => CorporationUpgrades[i])
|
.map((level: number, i: number) => CorporationUpgrades[i as CorporationUpgradeIndex])
|
||||||
.map((upgrade: CorporationUpgrade) => (
|
.map((upgrade: CorporationUpgrade) => (
|
||||||
<LevelableUpgrade rerender={rerender} upgrade={upgrade} key={upgrade[0]} />
|
<LevelableUpgrade rerender={rerender} upgrade={upgrade} key={upgrade.index} />
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
@ -2,10 +2,11 @@ import React, { useState } from "react";
|
|||||||
|
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../data/Constants";
|
||||||
import { Product } from "../Product";
|
import { Product } from "../Product";
|
||||||
import { DiscontinueProductModal } from "./DiscontinueProductModal";
|
import { DiscontinueProductModal } from "./modals/DiscontinueProductModal";
|
||||||
import { LimitProductProductionModal } from "./LimitProductProductionModal";
|
import { LimitProductProductionModal } from "./modals/LimitProductProductionModal";
|
||||||
import { SellProductModal } from "./SellProductModal";
|
import { SellProductModal } from "./modals/SellProductModal";
|
||||||
import { ProductMarketTaModal } from "./ProductMarketTaModal";
|
import { ProductMarketTaModal } from "./modals/ProductMarketTaModal";
|
||||||
|
import { CancelProductModal } from "./modals/CancelProductModal";
|
||||||
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ export function ProductElem(props: IProductProps): React.ReactElement {
|
|||||||
const [sellOpen, setSellOpen] = useState(false);
|
const [sellOpen, setSellOpen] = useState(false);
|
||||||
const [limitOpen, setLimitOpen] = useState(false);
|
const [limitOpen, setLimitOpen] = useState(false);
|
||||||
const [discontinueOpen, setDiscontinueOpen] = useState(false);
|
const [discontinueOpen, setDiscontinueOpen] = useState(false);
|
||||||
|
const [cancelOpen, setCancelOpen] = useState(false);
|
||||||
const [marketTaOpen, setMarketTaOpen] = useState(false);
|
const [marketTaOpen, setMarketTaOpen] = useState(false);
|
||||||
const city = props.city;
|
const city = props.city;
|
||||||
const product = props.product;
|
const product = props.product;
|
||||||
@ -111,6 +113,13 @@ export function ProductElem(props: IProductProps): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<br />
|
<br />
|
||||||
<Typography>{numeralWrapper.format(product.prog, "0.00")}% complete</Typography>
|
<Typography>{numeralWrapper.format(product.prog, "0.00")}% complete</Typography>
|
||||||
|
<Button onClick={() => setCancelOpen(true)}>Cancel</Button>
|
||||||
|
<CancelProductModal
|
||||||
|
product={product}
|
||||||
|
rerender={props.rerender}
|
||||||
|
open={cancelOpen}
|
||||||
|
onClose={() => setCancelOpen(false)}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@ -171,6 +180,13 @@ export function ProductElem(props: IProductProps): React.ReactElement {
|
|||||||
<Typography>Est. Market Price: {numeralWrapper.formatMoney(product.pCost)}</Typography>
|
<Typography>Est. Market Price: {numeralWrapper.formatMoney(product.pCost)}</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Button onClick={() => setDiscontinueOpen(true)}>Discontinue</Button>
|
||||||
|
<DiscontinueProductModal
|
||||||
|
product={product}
|
||||||
|
rerender={props.rerender}
|
||||||
|
open={discontinueOpen}
|
||||||
|
onClose={() => setDiscontinueOpen(false)}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -186,14 +202,6 @@ export function ProductElem(props: IProductProps): React.ReactElement {
|
|||||||
open={limitOpen}
|
open={limitOpen}
|
||||||
onClose={() => setLimitOpen(false)}
|
onClose={() => setLimitOpen(false)}
|
||||||
/>
|
/>
|
||||||
<Button onClick={() => setDiscontinueOpen(true)}>Discontinue</Button>
|
|
||||||
|
|
||||||
<DiscontinueProductModal
|
|
||||||
product={product}
|
|
||||||
rerender={props.rerender}
|
|
||||||
open={discontinueOpen}
|
|
||||||
onClose={() => setDiscontinueOpen(false)}
|
|
||||||
/>
|
|
||||||
{division.hasResearch("Market-TA.I") && (
|
{division.hasResearch("Market-TA.I") && (
|
||||||
<>
|
<>
|
||||||
<Button onClick={() => setMarketTaOpen(true)}>Market-TA</Button>
|
<Button onClick={() => setMarketTaOpen(true)}>Market-TA</Button>
|
||||||
|
@ -20,9 +20,9 @@ interface IProps {
|
|||||||
export function UnlockUpgrade(props: IProps): React.ReactElement {
|
export function UnlockUpgrade(props: IProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const data = props.upgradeData;
|
const data = props.upgradeData;
|
||||||
const tooltip = data[3];
|
const tooltip = data.desc;
|
||||||
function onClick(): void {
|
function onClick(): void {
|
||||||
if (corp.funds < data[1]) return;
|
if (corp.funds < data.price) return;
|
||||||
try {
|
try {
|
||||||
UU(corp, props.upgradeData);
|
UU(corp, props.upgradeData);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -34,11 +34,11 @@ export function UnlockUpgrade(props: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<Box display="flex" alignItems="center" flexDirection="row-reverse">
|
<Box display="flex" alignItems="center" flexDirection="row-reverse">
|
||||||
<Button disabled={corp.funds < data[1]} sx={{ mx: 1 }} onClick={onClick}>
|
<Button disabled={corp.funds < data.price} sx={{ mx: 1 }} onClick={onClick}>
|
||||||
<MoneyCost money={data[1]} corp={corp} />
|
<MoneyCost money={data.price} corp={corp} />
|
||||||
</Button>
|
</Button>
|
||||||
<Tooltip title={tooltip}>
|
<Tooltip title={tooltip}>
|
||||||
<Typography>{data[2]}</Typography>
|
<Typography>{data.name}</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Factions } from "../../Faction/Factions";
|
import { Factions } from "../../../Faction/Factions";
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../../ui/Context";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
@ -1,14 +1,14 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../../ui/Context";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import { BuyBackShares } from "../Actions";
|
import { BuyBackShares } from "../../Actions";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
34
src/Corporation/ui/modals/CancelProductModal.tsx
Normal file
34
src/Corporation/ui/modals/CancelProductModal.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { Product } from "../../Product";
|
||||||
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
|
import { useDivision } from "../Context";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
product: Product;
|
||||||
|
rerender: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a popup that lets the player cancel a product
|
||||||
|
export function CancelProductModal(props: IProps): React.ReactElement {
|
||||||
|
const division = useDivision();
|
||||||
|
function cancel(): void {
|
||||||
|
division.discontinueProduct(props.product);
|
||||||
|
props.onClose();
|
||||||
|
props.rerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal open={props.open} onClose={props.onClose}>
|
||||||
|
<Typography>
|
||||||
|
Are you sure you want to do this? Canceling a product removes it completely and permanently. You will receive no
|
||||||
|
money back by doing so
|
||||||
|
</Typography>
|
||||||
|
<Button onClick={cancel}>Cancel</Button>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
6
src/Corporation/ui/CreateCorporationModal.tsx → src/Corporation/ui/modals/CreateCorporationModal.tsx
6
src/Corporation/ui/CreateCorporationModal.tsx → src/Corporation/ui/modals/CreateCorporationModal.tsx
@ -1,8 +1,8 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../../ui/Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { Product } from "../Product";
|
import { Product } from "../../Product";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useDivision } from "./Context";
|
import { useDivision } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
|
|
@ -1,12 +1,12 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Material } from "../Material";
|
import { Material } from "../../Material";
|
||||||
import { Export } from "../Export";
|
import { Export } from "../../Export";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { IIndustry } from "../../IIndustry";
|
||||||
import { ExportMaterial } from "../Actions";
|
import { ExportMaterial } from "../../Actions";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import { isRelevantMaterial } from "./Helpers";
|
import { isRelevantMaterial } from "../Helpers";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
@ -1,13 +1,13 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
@ -1,13 +1,13 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { IssueDividends } from "../Actions";
|
import { IssueDividends } from "../../Actions";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
@ -1,14 +1,14 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../../../utils/helpers/getRandomInt";
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
interface IEffectTextProps {
|
interface IEffectTextProps {
|
||||||
shares: number | null;
|
shares: number | null;
|
53
src/Corporation/ui/modals/LimitMaterialProductionModal.tsx
Normal file
53
src/Corporation/ui/modals/LimitMaterialProductionModal.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { LimitMaterialProduction } from "../../Actions";
|
||||||
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
import { Material } from "../../Material";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
material: Material;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a popup that lets the player limit the production of a product
|
||||||
|
export function LimitMaterialProductionModal(props: IProps): React.ReactElement {
|
||||||
|
const [limit, setLimit] = useState<number | null>(null);
|
||||||
|
|
||||||
|
// reset modal internal state on modal close
|
||||||
|
useEffect(() => {
|
||||||
|
if (!props.open) {
|
||||||
|
setLimit(null);
|
||||||
|
}
|
||||||
|
}, [props.open]);
|
||||||
|
|
||||||
|
function limitMaterialProduction(): void {
|
||||||
|
let qty = limit;
|
||||||
|
if (qty === null) qty = -1;
|
||||||
|
LimitMaterialProduction(props.material, qty);
|
||||||
|
props.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
|
||||||
|
if (event.key === KEY.ENTER) limitMaterialProduction();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
|
if (event.target.value === "") setLimit(null);
|
||||||
|
else setLimit(parseFloat(event.target.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal open={props.open} onClose={props.onClose}>
|
||||||
|
<Typography>
|
||||||
|
Enter a limit to the amount of this material you would like to produce per second. Leave the box empty to set no
|
||||||
|
limit.
|
||||||
|
</Typography>
|
||||||
|
<TextField autoFocus={true} placeholder="Limit" type="number" onChange={onChange} onKeyDown={onKeyDown} />
|
||||||
|
<Button onClick={limitMaterialProduction}>Limit production</Button>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Product } from "../Product";
|
import { Product } from "../../Product";
|
||||||
import { LimitProductProduction } from "../Actions";
|
import { LimitProductProduction } from "../../Actions";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -18,6 +18,13 @@ interface IProps {
|
|||||||
export function LimitProductProductionModal(props: IProps): React.ReactElement {
|
export function LimitProductProductionModal(props: IProps): React.ReactElement {
|
||||||
const [limit, setLimit] = useState<number | null>(null);
|
const [limit, setLimit] = useState<number | null>(null);
|
||||||
|
|
||||||
|
// reset modal internal state on modal close
|
||||||
|
useEffect(() => {
|
||||||
|
if (!props.open) {
|
||||||
|
setLimit(null);
|
||||||
|
}
|
||||||
|
}, [props.open]);
|
||||||
|
|
||||||
function limitProductProduction(): void {
|
function limitProductProduction(): void {
|
||||||
let qty = limit;
|
let qty = limit;
|
||||||
if (qty === null) qty = -1;
|
if (qty === null) qty = -1;
|
@ -1,15 +1,15 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { Industries } from "../IndustryData";
|
import { Industries } from "../../IndustryData";
|
||||||
import { MakeProduct } from "../Actions";
|
import { MakeProduct } from "../../Actions";
|
||||||
import { useCorporation, useDivision } from "./Context";
|
import { useCorporation, useDivision } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
8
src/Corporation/ui/MaterialMarketTaModal.tsx → src/Corporation/ui/modals/MaterialMarketTaModal.tsx
8
src/Corporation/ui/MaterialMarketTaModal.tsx → src/Corporation/ui/modals/MaterialMarketTaModal.tsx
@ -1,8 +1,8 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { Material } from "../Material";
|
import { Material } from "../../Material";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useDivision } from "./Context";
|
import { useDivision } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { Product } from "../Product";
|
import { Product } from "../../Product";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useDivision } from "./Context";
|
import { useDivision } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
88
src/Corporation/ui/PurchaseMaterialModal.tsx → src/Corporation/ui/modals/PurchaseMaterialModal.tsx
88
src/Corporation/ui/PurchaseMaterialModal.tsx → src/Corporation/ui/modals/PurchaseMaterialModal.tsx
@ -1,16 +1,16 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { MaterialSizes } from "../MaterialSizes";
|
import { MaterialSizes } from "../../MaterialSizes";
|
||||||
import { Warehouse } from "../Warehouse";
|
import { Warehouse } from "../../Warehouse";
|
||||||
import { Material } from "../Material";
|
import { Material } from "../../Material";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { BulkPurchase, BuyMaterial } from "../Actions";
|
import { BulkPurchase, BuyMaterial } from "../../Actions";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useCorporation, useDivision } from "./Context";
|
import { useCorporation, useDivision } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
interface IBulkPurchaseTextProps {
|
interface IBulkPurchaseTextProps {
|
||||||
warehouse: Warehouse;
|
warehouse: Warehouse;
|
||||||
@ -18,37 +18,6 @@ interface IBulkPurchaseTextProps {
|
|||||||
amount: string;
|
amount: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BulkPurchaseText(props: IBulkPurchaseTextProps): React.ReactElement {
|
|
||||||
const parsedAmt = parseFloat(props.amount);
|
|
||||||
const cost = parsedAmt * props.mat.bCost;
|
|
||||||
|
|
||||||
const matSize = MaterialSizes[props.mat.name];
|
|
||||||
const maxAmount = (props.warehouse.size - props.warehouse.sizeUsed) / matSize;
|
|
||||||
|
|
||||||
if (parsedAmt * matSize > maxAmount) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography color={"error"}>Not enough warehouse space to purchase this amount</Typography>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else if (isNaN(cost) || parsedAmt < 0) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography color={"error"}>Invalid put for Bulk Purchase amount</Typography>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography>
|
|
||||||
Purchasing {numeralWrapper.format(parsedAmt, "0,0.00")} of {props.mat.name} will cost{" "}
|
|
||||||
{numeralWrapper.formatMoney(cost)}
|
|
||||||
</Typography>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IBPProps {
|
interface IBPProps {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
mat: Material;
|
mat: Material;
|
||||||
@ -58,6 +27,41 @@ interface IBPProps {
|
|||||||
function BulkPurchaseSection(props: IBPProps): React.ReactElement {
|
function BulkPurchaseSection(props: IBPProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [buyAmt, setBuyAmt] = useState("");
|
const [buyAmt, setBuyAmt] = useState("");
|
||||||
|
const [disabled, setDisabled] = useState(false);
|
||||||
|
|
||||||
|
function BulkPurchaseText(props: IBulkPurchaseTextProps): React.ReactElement {
|
||||||
|
const parsedAmt = parseFloat(props.amount);
|
||||||
|
const cost = parsedAmt * props.mat.bCost;
|
||||||
|
|
||||||
|
const matSize = MaterialSizes[props.mat.name];
|
||||||
|
const maxAmount = (props.warehouse.size - props.warehouse.sizeUsed) / matSize;
|
||||||
|
|
||||||
|
if (parsedAmt > maxAmount) {
|
||||||
|
setDisabled(true);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography color={"error"}>Not enough warehouse space to purchase this amount</Typography>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else if (isNaN(cost) || parsedAmt < 0) {
|
||||||
|
setDisabled(true);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography color={"error"}>Invalid input for Bulk Purchase amount</Typography>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setDisabled(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography>
|
||||||
|
Purchasing {numeralWrapper.format(parsedAmt, "0,0.00")} of {props.mat.name} will cost{" "}
|
||||||
|
{numeralWrapper.formatMoney(cost)}
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function bulkPurchase(): void {
|
function bulkPurchase(): void {
|
||||||
try {
|
try {
|
||||||
@ -90,7 +94,9 @@ function BulkPurchaseSection(props: IBPProps): React.ReactElement {
|
|||||||
placeholder="Bulk Purchase amount"
|
placeholder="Bulk Purchase amount"
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
/>
|
/>
|
||||||
<Button onClick={bulkPurchase}>Confirm Bulk Purchase</Button>
|
<Button disabled={disabled} onClick={bulkPurchase}>
|
||||||
|
Confirm Bulk Purchase
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -1,13 +1,13 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { IndustryResearchTrees } from "../IndustryData";
|
import { IndustryResearchTrees } from "../../IndustryData";
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { IIndustry } from "../../IIndustry";
|
||||||
import { Research } from "../Actions";
|
import { Research } from "../../Actions";
|
||||||
import { Node } from "../ResearchTree";
|
import { Node } from "../../ResearchTree";
|
||||||
import { ResearchMap } from "../ResearchMap";
|
import { ResearchMap } from "../../ResearchMap";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../../Settings/Settings";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
@ -1,12 +1,12 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Material } from "../Material";
|
import { Material } from "../../Material";
|
||||||
import { SellMaterial } from "../Actions";
|
import { SellMaterial } from "../../Actions";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
function initialPrice(mat: Material): string {
|
function initialPrice(mat: Material): string {
|
||||||
let val = mat.sCost ? mat.sCost + "" : "";
|
let val = mat.sCost ? mat.sCost + "" : "";
|
@ -1,15 +1,15 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Product } from "../Product";
|
import { Product } from "../../Product";
|
||||||
import { SellProduct } from "../Actions";
|
import { SellProduct } from "../../Actions";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||||
import Switch from "@mui/material/Switch";
|
import Switch from "@mui/material/Switch";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
function initialPrice(product: Product): string {
|
function initialPrice(product: Product): string {
|
||||||
let val = product.sCost ? product.sCost + "" : "";
|
let val = product.sCost ? product.sCost + "" : "";
|
@ -1,16 +1,16 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../../ui/Context";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import { ICorporation } from "../ICorporation";
|
import { ICorporation } from "../../ICorporation";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
import { SellShares } from "../Actions";
|
import { SellShares } from "../../Actions";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@ -33,19 +33,22 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
function ProfitIndicator(props: { shares: number | null; corp: ICorporation }): React.ReactElement {
|
function ProfitIndicator(props: { shares: number | null; corp: ICorporation }): React.ReactElement {
|
||||||
if (props.shares === null) return <></>;
|
if (props.shares === null) return <></>;
|
||||||
|
let text = "";
|
||||||
if (isNaN(props.shares) || props.shares <= 0) {
|
if (isNaN(props.shares) || props.shares <= 0) {
|
||||||
return <>ERROR: Invalid value entered for number of shares to sell</>;
|
text = `ERROR: Invalid value entered for number of shares to sell`;
|
||||||
} else if (props.shares > corp.numShares) {
|
} else if (props.shares > corp.numShares) {
|
||||||
return <>You don't have this many shares to sell!</>;
|
text = `You don't have this many shares to sell!`;
|
||||||
} else {
|
} else {
|
||||||
const stockSaleResults = corp.calculateShareSale(props.shares);
|
const stockSaleResults = corp.calculateShareSale(props.shares);
|
||||||
const profit = stockSaleResults[0];
|
const profit = stockSaleResults[0];
|
||||||
return (
|
text = `Sell ${props.shares} shares for a total of ${numeralWrapper.formatMoney(profit)}`;
|
||||||
<>
|
|
||||||
Sell {props.shares} shares for a total of {numeralWrapper.formatMoney(profit)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Typography>
|
||||||
|
<small>{text}</small>
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sell(): void {
|
function sell(): void {
|
||||||
@ -84,7 +87,6 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
|||||||
<br />
|
<br />
|
||||||
The current price of your company's stock is {numeralWrapper.formatMoney(corp.sharePrice)}
|
The current price of your company's stock is {numeralWrapper.formatMoney(corp.sharePrice)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<ProfitIndicator shares={shares} corp={corp} />
|
|
||||||
<br />
|
<br />
|
||||||
<TextField
|
<TextField
|
||||||
variant="standard"
|
variant="standard"
|
||||||
@ -97,6 +99,7 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
|||||||
<Button disabled={disabled} onClick={sell} sx={{ mx: 1 }}>
|
<Button disabled={disabled} onClick={sell} sx={{ mx: 1 }}>
|
||||||
Sell shares
|
Sell shares
|
||||||
</Button>
|
</Button>
|
||||||
|
<ProfitIndicator shares={shares} corp={corp} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { Warehouse } from "../Warehouse";
|
import { Warehouse } from "../../Warehouse";
|
||||||
import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../Actions";
|
import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../../Actions";
|
||||||
import { Material } from "../Material";
|
import { Material } from "../../Material";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useDivision } from "./Context";
|
import { useDivision } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||||
import Switch from "@mui/material/Switch";
|
import Switch from "@mui/material/Switch";
|
@ -1,16 +1,16 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { OfficeSpace } from "../OfficeSpace";
|
import { OfficeSpace } from "../../OfficeSpace";
|
||||||
import { ThrowParty } from "../Actions";
|
import { ThrowParty } from "../../Actions";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
14
src/Corporation/ui/UpgradeOfficeSizeModal.tsx → src/Corporation/ui/modals/UpgradeOfficeSizeModal.tsx
14
src/Corporation/ui/UpgradeOfficeSizeModal.tsx → src/Corporation/ui/modals/UpgradeOfficeSizeModal.tsx
@ -1,11 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { OfficeSpace } from "../OfficeSpace";
|
import { OfficeSpace } from "../../OfficeSpace";
|
||||||
import { ICorporation } from "../ICorporation";
|
import { ICorporation } from "../../ICorporation";
|
||||||
import { UpgradeOfficeSize } from "../Actions";
|
import { UpgradeOfficeSize } from "../../Actions";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
@ -17,7 +17,7 @@ export function DummyGrid(props: IProps): React.ReactElement {
|
|||||||
const ghostGrid = zeros([props.width, props.height]);
|
const ghostGrid = zeros([props.width, props.height]);
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Table>
|
<Table sx={{ width: props.width, height: props.height }}>
|
||||||
<Grid
|
<Grid
|
||||||
width={props.width}
|
width={props.width}
|
||||||
height={props.height}
|
height={props.height}
|
||||||
|
@ -66,6 +66,7 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
|||||||
user, Stat Fragments increase the efficacy of adjacent Stat Fragments by 10%, and do not need to be
|
user, Stat Fragments increase the efficacy of adjacent Stat Fragments by 10%, and do not need to be
|
||||||
charged.
|
charged.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<br />
|
||||||
|
|
||||||
<DummyGrid
|
<DummyGrid
|
||||||
width={4}
|
width={4}
|
||||||
@ -86,11 +87,12 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Typography sx={{ fontStyle: "italic" }}>
|
<Typography sx={{ fontStyle: "italic" }}>
|
||||||
This boost provides a bonus to the touching fragment
|
This Booster Fragment provides a bonus to the adjacent Stat Fragment.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<br />
|
||||||
|
|
||||||
<DummyGrid
|
<DummyGrid
|
||||||
width={4}
|
width={3}
|
||||||
height={4}
|
height={4}
|
||||||
fragments={[
|
fragments={[
|
||||||
new ActiveFragment({
|
new ActiveFragment({
|
||||||
@ -108,8 +110,10 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Typography sx={{ fontStyle: "italic" }}>
|
<Typography sx={{ fontStyle: "italic" }}>
|
||||||
Even though the booster touches many tiles, the bonus is only applied once.
|
Even though the Booster Fragment touches the Stat Fragment in multiple places, the bonus is only
|
||||||
|
applied once.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<br />
|
||||||
|
|
||||||
<DummyGrid
|
<DummyGrid
|
||||||
width={4}
|
width={4}
|
||||||
@ -122,16 +126,17 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
|||||||
fragment: Fragments.find((f) => f.id === 5) ?? Fragments[0],
|
fragment: Fragments.find((f) => f.id === 5) ?? Fragments[0],
|
||||||
}),
|
}),
|
||||||
new ActiveFragment({
|
new ActiveFragment({
|
||||||
x: 2,
|
x: 1,
|
||||||
y: 0,
|
y: 1,
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
fragment: Fragments.find((f) => f.id === 105) ?? Fragments[0],
|
fragment: Fragments.find((f) => f.id === 105) ?? Fragments[0],
|
||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Typography sx={{ fontStyle: "italic" }}>
|
<Typography sx={{ fontStyle: "italic" }}>
|
||||||
Even though the booster touches many tiles, the bonus is only applied once.
|
This Booster Fragment does nothing, as it is not touching a Stat Fragment.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<br />
|
||||||
|
|
||||||
<DummyGrid
|
<DummyGrid
|
||||||
width={4}
|
width={4}
|
||||||
@ -158,10 +163,10 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Typography sx={{ fontStyle: "italic" }}>
|
<Typography sx={{ fontStyle: "italic" }}>
|
||||||
This booster provides bonus to all fragment it touches.
|
This Booster Fragment provides a bonus to both Stat Fragments it's touching.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<Typography>
|
<Typography>
|
||||||
Stat Fragments are charged using the stanek.chargeFragment(rootX, rootY) NetScript API function. The
|
Stat Fragments are charged using the stanek.chargeFragment(rootX, rootY) NetScript API function. The
|
||||||
charging process ordinarily takes 1000ms to complete, but only takes 200ms during bonus time. When the
|
charging process ordinarily takes 1000ms to complete, but only takes 200ms during bonus time. When the
|
||||||
|
@ -10,6 +10,10 @@ import Button from "@mui/material/Button";
|
|||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
|
import { MenuItem, SelectChangeEvent, TextField, Select } from "@mui/material";
|
||||||
|
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
||||||
|
import { GangConstants } from "../../Gang/data/Constants";
|
||||||
|
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||||
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
|
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@ -19,6 +23,8 @@ interface IProps {
|
|||||||
|
|
||||||
export function General(props: IProps): React.ReactElement {
|
export function General(props: IProps): React.ReactElement {
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
|
const [corporationName, setCorporationName] = useState("");
|
||||||
|
const [gangFaction, setGangFaction] = useState("");
|
||||||
|
|
||||||
function addMoney(n: number) {
|
function addMoney(n: number) {
|
||||||
return function () {
|
return function () {
|
||||||
@ -46,6 +52,23 @@ export function General(props: IProps): React.ReactElement {
|
|||||||
props.router.toBitVerse(false, false);
|
props.router.toBitVerse(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createCorporation(): void {
|
||||||
|
props.player.startCorporation(corporationName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function joinBladeburner(): void {
|
||||||
|
props.player.bladeburner = new Bladeburner(props.player);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startGang(): void {
|
||||||
|
const isHacking = gangFaction === FactionNames.NiteSec || gangFaction === FactionNames.TheBlackHand;
|
||||||
|
props.player.startGang(gangFaction, isHacking);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setGangFactionDropdown(event: SelectChangeEvent<string>): void {
|
||||||
|
setGangFaction(event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
function checkMessages(): void {
|
function checkMessages(): void {
|
||||||
checkForMessagesToSend();
|
checkForMessagesToSend();
|
||||||
}
|
}
|
||||||
@ -87,6 +110,22 @@ export function General(props: IProps): React.ReactElement {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button onClick={upgradeRam}>+ RAM</Button>
|
<Button onClick={upgradeRam}>+ RAM</Button>
|
||||||
<br />
|
<br />
|
||||||
|
<Typography>Corporation Name:</Typography>
|
||||||
|
<TextField value={corporationName} onChange={(x) => setCorporationName(x.target.value)} />
|
||||||
|
<Button onClick={createCorporation}>Create Corporation</Button>
|
||||||
|
<br />
|
||||||
|
<Typography>Gang Faction:</Typography>
|
||||||
|
<Select value={gangFaction} onChange={setGangFactionDropdown}>
|
||||||
|
{GangConstants.Names.map((factionName) => (
|
||||||
|
<MenuItem key={factionName} value={factionName}>
|
||||||
|
{factionName}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
<Button onClick={startGang}>Start Gang</Button>
|
||||||
|
<br />
|
||||||
|
<Button onClick={joinBladeburner}>Join BladeBurner</Button>
|
||||||
|
<br />
|
||||||
|
|
||||||
<Button onClick={quickB1tFlum3}>Quick b1t_flum3.exe</Button>
|
<Button onClick={quickB1tFlum3}>Quick b1t_flum3.exe</Button>
|
||||||
<Button onClick={b1tflum3}>Run b1t_flum3.exe</Button>
|
<Button onClick={b1tflum3}>Run b1t_flum3.exe</Button>
|
||||||
|
@ -15,7 +15,6 @@ import {
|
|||||||
getFactionSecurityWorkRepGain,
|
getFactionSecurityWorkRepGain,
|
||||||
getFactionFieldWorkRepGain,
|
getFactionFieldWorkRepGain,
|
||||||
} from "../PersonObjects/formulas/reputation";
|
} from "../PersonObjects/formulas/reputation";
|
||||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { InvitationEvent } from "./ui/InvitationModal";
|
import { InvitationEvent } from "./ui/InvitationModal";
|
||||||
@ -120,13 +119,14 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
|||||||
aug.baseCost = 750e3 * mult * BitNodeMultipliers.AugmentationMoneyCost;
|
aug.baseCost = 750e3 * mult * BitNodeMultipliers.AugmentationMoneyCost;
|
||||||
|
|
||||||
for (let i = 0; i < Player.queuedAugmentations.length - 1; ++i) {
|
for (let i = 0; i < Player.queuedAugmentations.length - 1; ++i) {
|
||||||
aug.baseCost *= CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][SourceFileFlags[11]];
|
aug.baseCost *= CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][Player.sourceFileLvl(11)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const name of Object.keys(Augmentations)) {
|
for (const name of Object.keys(Augmentations)) {
|
||||||
if (Augmentations.hasOwnProperty(name)) {
|
if (Augmentations.hasOwnProperty(name)) {
|
||||||
Augmentations[name].baseCost *= CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][SourceFileFlags[11]];
|
Augmentations[name].baseCost *=
|
||||||
|
CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][Player.sourceFileLvl(11)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
import { FactionNames } from "./data/FactionNames";
|
import { FactionNames } from "./data/FactionNames";
|
||||||
|
import { use } from "../ui/Context";
|
||||||
|
import { Option } from "./ui/Option";
|
||||||
|
|
||||||
interface FactionInfoParams {
|
interface FactionInfoParams {
|
||||||
infoText?: JSX.Element;
|
infoText?: JSX.Element;
|
||||||
@ -10,6 +12,7 @@ interface FactionInfoParams {
|
|||||||
offerSecurityWork?: boolean;
|
offerSecurityWork?: boolean;
|
||||||
special?: boolean;
|
special?: boolean;
|
||||||
keepOnInstall?: boolean;
|
keepOnInstall?: boolean;
|
||||||
|
assignment?: () => React.ReactElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,6 +54,11 @@ export class FactionInfo {
|
|||||||
*/
|
*/
|
||||||
special: boolean;
|
special: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data to display on the faction screen.
|
||||||
|
*/
|
||||||
|
assignment?: () => React.ReactElement;
|
||||||
|
|
||||||
constructor(params: FactionInfoParams) {
|
constructor(params: FactionInfoParams) {
|
||||||
this.infoText = params.infoText ?? <></>;
|
this.infoText = params.infoText ?? <></>;
|
||||||
this.enemies = params.enemies ?? [];
|
this.enemies = params.enemies ?? [];
|
||||||
@ -60,6 +68,7 @@ export class FactionInfo {
|
|||||||
|
|
||||||
this.keep = params.keepOnInstall ?? false;
|
this.keep = params.keepOnInstall ?? false;
|
||||||
this.special = params.special ?? false;
|
this.special = params.special ?? false;
|
||||||
|
this.assignment = params.assignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
offersWork(): boolean {
|
offersWork(): boolean {
|
||||||
@ -438,11 +447,21 @@ export const FactionInfos: IMap<FactionInfo> = {
|
|||||||
),
|
),
|
||||||
|
|
||||||
special: true,
|
special: true,
|
||||||
|
assignment: (): React.ReactElement => {
|
||||||
|
const router = use.Router();
|
||||||
|
return (
|
||||||
|
<Option
|
||||||
|
buttonText={"Open Bladeburner headquarters"}
|
||||||
|
infoText={"You can gain reputation with bladeburner by completing contracts and operations."}
|
||||||
|
onClick={() => router.toBladeburner()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// prettier-ignore
|
|
||||||
[FactionNames.ChurchOfTheMachineGod]: new FactionInfo({
|
[FactionNames.ChurchOfTheMachineGod]: new FactionInfo({
|
||||||
infoText:(<>
|
// prettier-ignore
|
||||||
|
infoText:(<>
|
||||||
{" `` "}<br />
|
{" `` "}<br />
|
||||||
{" -odmmNmds: "}<br />
|
{" -odmmNmds: "}<br />
|
||||||
{" `hNmo:..-omNh. "}<br />
|
{" `hNmo:..-omNh. "}<br />
|
||||||
@ -472,13 +491,24 @@ export const FactionInfos: IMap<FactionInfo> = {
|
|||||||
{" -smNNNNmdo- "}<br />
|
{" -smNNNNmdo- "}<br />
|
||||||
{" `..` "}<br /><br />
|
{" `..` "}<br /><br />
|
||||||
Many cultures predict an end to humanity in the near future, a final
|
Many cultures predict an end to humanity in the near future, a final
|
||||||
Armageddon that will end the world; but we disagree.
|
Armageddon that will end the world; but we disagree.</>),
|
||||||
<br /><br />Note that for this faction, reputation can
|
offerHackingWork: false,
|
||||||
only be gained by charging Stanek's gift.</>),
|
offerFieldWork: false,
|
||||||
offerHackingWork: false,
|
offerSecurityWork: false,
|
||||||
offerFieldWork: false,
|
special: true,
|
||||||
offerSecurityWork: false,
|
keepOnInstall: true,
|
||||||
special: true,
|
assignment: (): React.ReactElement => {
|
||||||
keepOnInstall: true,
|
const router = use.Router();
|
||||||
|
return (
|
||||||
|
<Option
|
||||||
|
buttonText={"Open Staneks Gift"}
|
||||||
|
infoText={
|
||||||
|
"Stanek's Gift is a powerful augmentation that powers up the stat you chose to boost." +
|
||||||
|
"Gaining reputation with the Church of the Machine God can only be done by charging the gift."
|
||||||
|
}
|
||||||
|
onClick={() => router.toStaneksGift()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -31,6 +31,17 @@ const useStyles = makeStyles(() =>
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function DefaultAssignment(): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<Typography>
|
||||||
|
Perform work/carry out assignments for your faction to help further its cause! By doing so you will earn
|
||||||
|
reputation for your faction. You will also gain reputation passively over time, although at a very slow rate.
|
||||||
|
Earning reputation will allow you to purchase Augmentations through this faction, which are powerful upgrades that
|
||||||
|
enhance your abilities.
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function Info(props: IProps): React.ReactElement {
|
export function Info(props: IProps): React.ReactElement {
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
@ -44,6 +55,8 @@ export function Info(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const Assignment = props.factionInfo.assignment ?? DefaultAssignment;
|
||||||
|
|
||||||
const favorGain = props.faction.getFavorGain();
|
const favorGain = props.faction.getFavorGain();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -94,12 +107,7 @@ export function Info(props: IProps): React.ReactElement {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Typography>-------------------------</Typography>
|
<Typography>-------------------------</Typography>
|
||||||
<Typography>
|
<Assignment />
|
||||||
Perform work/carry out assignments for your faction to help further its cause! By doing so you will earn
|
|
||||||
reputation for your faction. You will also gain reputation passively over time, although at a very slow rate.
|
|
||||||
Earning reputation will allow you to purchase Augmentations through this faction, which are powerful upgrades
|
|
||||||
that enhance your abilities.
|
|
||||||
</Typography>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -252,6 +252,7 @@ export class Gang implements IGang {
|
|||||||
const total = Object.values(AllGangs)
|
const total = Object.values(AllGangs)
|
||||||
.map((g) => g.territory)
|
.map((g) => g.territory)
|
||||||
.reduce((p, c) => p + c, 0);
|
.reduce((p, c) => p + c, 0);
|
||||||
|
console.log(total);
|
||||||
Object.values(AllGangs).forEach((g) => (g.territory /= total));
|
Object.values(AllGangs).forEach((g) => (g.territory /= total));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,11 @@ import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../InteractiveTuto
|
|||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { GetServer } from "../Server/AllServers";
|
import { GetServer } from "../Server/AllServers";
|
||||||
import { Server } from "../Server/Server";
|
import { Server } from "../Server/Server";
|
||||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
|
||||||
|
|
||||||
// Returns a boolean indicating whether the player has Hacknet Servers
|
// Returns a boolean indicating whether the player has Hacknet Servers
|
||||||
// (the upgraded form of Hacknet Nodes)
|
// (the upgraded form of Hacknet Nodes)
|
||||||
export function hasHacknetServers(player: IPlayer): boolean {
|
export function hasHacknetServers(player: IPlayer): boolean {
|
||||||
return player.bitNodeN === 9 || SourceFileFlags[9] > 0;
|
return player.bitNodeN === 9 || player.sourceFileLvl(9) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purchaseHacknet(player: IPlayer): number {
|
export function purchaseHacknet(player: IPlayer): number {
|
||||||
|
@ -15,7 +15,7 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
|
|
||||||
import { Location } from "../Location";
|
import { Location } from "../Location";
|
||||||
import { CreateCorporationModal } from "../../Corporation/ui/CreateCorporationModal";
|
import { CreateCorporationModal } from "../../Corporation/ui/modals/CreateCorporationModal";
|
||||||
import { LocationName } from "../data/LocationNames";
|
import { LocationName } from "../data/LocationNames";
|
||||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||||
import { Factions } from "../../Faction/Factions";
|
import { Factions } from "../../Faction/Factions";
|
||||||
@ -34,6 +34,7 @@ import { HacknetServer } from "../../Hacknet/HacknetServer";
|
|||||||
import { GetServer } from "../../Server/AllServers";
|
import { GetServer } from "../../Server/AllServers";
|
||||||
import { ArcadeRoot } from "../../Arcade/ui/ArcadeRoot";
|
import { ArcadeRoot } from "../../Arcade/ui/ArcadeRoot";
|
||||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||||
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
loc: Location;
|
loc: Location;
|
||||||
@ -316,7 +317,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
|
|||||||
return renderGrafting();
|
return renderGrafting();
|
||||||
}
|
}
|
||||||
case LocationName.Sector12CityHall: {
|
case LocationName.Sector12CityHall: {
|
||||||
return <CreateCorporation />;
|
return (BitNodeMultipliers.CorporationSoftCap < 0.15 && <></>) || <CreateCorporation />;
|
||||||
}
|
}
|
||||||
case LocationName.Sector12NSA: {
|
case LocationName.Sector12NSA: {
|
||||||
return renderBladeburner();
|
return renderBladeburner();
|
||||||
|
@ -177,6 +177,8 @@ const singularity: IMap<any> = {
|
|||||||
installAugmentations: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
installAugmentations: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
isFocused: SF4Cost(0.1),
|
isFocused: SF4Cost(0.1),
|
||||||
setFocus: SF4Cost(0.1),
|
setFocus: SF4Cost(0.1),
|
||||||
|
b1tflum3: SF4Cost(16),
|
||||||
|
destroyW0r1dD43m0n: SF4Cost(32),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Gang API
|
// Gang API
|
||||||
|
@ -40,7 +40,6 @@ import {
|
|||||||
} from "./Server/ServerHelpers";
|
} from "./Server/ServerHelpers";
|
||||||
import { getPurchaseServerCost, getPurchaseServerLimit, getPurchaseServerMaxRam } from "./Server/ServerPurchases";
|
import { getPurchaseServerCost, getPurchaseServerLimit, getPurchaseServerMaxRam } from "./Server/ServerPurchases";
|
||||||
import { Server } from "./Server/Server";
|
import { Server } from "./Server/Server";
|
||||||
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
|
||||||
import { influenceStockThroughServerHack, influenceStockThroughServerGrow } from "./StockMarket/PlayerInfluencing";
|
import { influenceStockThroughServerHack, influenceStockThroughServerGrow } from "./StockMarket/PlayerInfluencing";
|
||||||
|
|
||||||
import { isValidFilePath, removeLeadingSlash } from "./Terminal/DirectoryHelpers";
|
import { isValidFilePath, removeLeadingSlash } from "./Terminal/DirectoryHelpers";
|
||||||
@ -1548,7 +1547,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
},
|
},
|
||||||
getBitNodeMultipliers: function (): IBNMults {
|
getBitNodeMultipliers: function (): IBNMults {
|
||||||
updateDynamicRam("getBitNodeMultipliers", getRamCost(Player, "getBitNodeMultipliers"));
|
updateDynamicRam("getBitNodeMultipliers", getRamCost(Player, "getBitNodeMultipliers"));
|
||||||
if (SourceFileFlags[5] <= 0 && Player.bitNodeN !== 5) {
|
if (Player.sourceFileLvl(5) <= 0 && Player.bitNodeN !== 5) {
|
||||||
throw makeRuntimeErrorMsg("getBitNodeMultipliers", "Requires Source-File 5 to run.");
|
throw makeRuntimeErrorMsg("getBitNodeMultipliers", "Requires Source-File 5 to run.");
|
||||||
}
|
}
|
||||||
const copy = Object.assign({}, BitNodeMultipliers);
|
const copy = Object.assign({}, BitNodeMultipliers);
|
||||||
|
@ -53,6 +53,9 @@ import {
|
|||||||
SellShares,
|
SellShares,
|
||||||
BuyBackShares,
|
BuyBackShares,
|
||||||
SetSmartSupplyUseLeftovers,
|
SetSmartSupplyUseLeftovers,
|
||||||
|
LimitMaterialProduction,
|
||||||
|
LimitProductProduction,
|
||||||
|
UpgradeWarehouseCost,
|
||||||
} from "../Corporation/Actions";
|
} from "../Corporation/Actions";
|
||||||
import { CorporationUnlockUpgrades } from "../Corporation/data/CorporationUnlockUpgrades";
|
import { CorporationUnlockUpgrades } from "../Corporation/data/CorporationUnlockUpgrades";
|
||||||
import { CorporationUpgrades } from "../Corporation/data/CorporationUpgrades";
|
import { CorporationUpgrades } from "../Corporation/data/CorporationUpgrades";
|
||||||
@ -64,6 +67,7 @@ import { CorporationConstants } from "../Corporation/data/Constants";
|
|||||||
import { IndustryUpgrades } from "../Corporation/IndustryUpgrades";
|
import { IndustryUpgrades } from "../Corporation/IndustryUpgrades";
|
||||||
import { ResearchMap } from "../Corporation/ResearchMap";
|
import { ResearchMap } from "../Corporation/ResearchMap";
|
||||||
import { Factions } from "../Faction/Factions";
|
import { Factions } from "../Faction/Factions";
|
||||||
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
|
|
||||||
export function NetscriptCorporation(
|
export function NetscriptCorporation(
|
||||||
player: IPlayer,
|
player: IPlayer,
|
||||||
@ -74,6 +78,8 @@ export function NetscriptCorporation(
|
|||||||
if (!player.canAccessCorporation() || player.hasCorporation()) return false;
|
if (!player.canAccessCorporation() || player.hasCorporation()) return false;
|
||||||
if (!corporationName) return false;
|
if (!corporationName) return false;
|
||||||
if (player.bitNodeN !== 3 && !selfFund) throw new Error("cannot use seed funds outside of BitNode 3");
|
if (player.bitNodeN !== 3 && !selfFund) throw new Error("cannot use seed funds outside of BitNode 3");
|
||||||
|
if (BitNodeMultipliers.CorporationSoftCap < 0.15)
|
||||||
|
throw new Error(`You cannot create a corporation in Bitnode ${player.bitNodeN}`);
|
||||||
|
|
||||||
if (selfFund) {
|
if (selfFund) {
|
||||||
if (!player.canAfford(150e9)) return false;
|
if (!player.canAfford(150e9)) return false;
|
||||||
@ -88,35 +94,35 @@ export function NetscriptCorporation(
|
|||||||
|
|
||||||
function hasUnlockUpgrade(upgradeName: string): boolean {
|
function hasUnlockUpgrade(upgradeName: string): boolean {
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
|
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||||
const upgN = upgrade[0];
|
const upgN = upgrade.index;
|
||||||
return corporation.unlockUpgrades[upgN] === 1;
|
return corporation.unlockUpgrades[upgN] === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUnlockUpgradeCost(upgradeName: string): number {
|
function getUnlockUpgradeCost(upgradeName: string): number {
|
||||||
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
|
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||||
return upgrade[1];
|
return upgrade.price;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUpgradeLevel(_upgradeName: string): number {
|
function getUpgradeLevel(_upgradeName: string): number {
|
||||||
const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
|
const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
|
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||||
const upgN = upgrade[0];
|
const upgN = upgrade.index;
|
||||||
return corporation.upgrades[upgN];
|
return corporation.upgrades[upgN];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUpgradeLevelCost(_upgradeName: string): number {
|
function getUpgradeLevelCost(_upgradeName: string): number {
|
||||||
const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
|
const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
|
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||||
const upgN = upgrade[0];
|
const upgN = upgrade.index;
|
||||||
const baseCost = upgrade[1];
|
const baseCost = upgrade.basePrice;
|
||||||
const priceMult = upgrade[2];
|
const priceMult = upgrade.priceMult;
|
||||||
const level = corporation.upgrades[upgN];
|
const level = corporation.upgrades[upgN];
|
||||||
return baseCost * Math.pow(priceMult, level);
|
return baseCost * Math.pow(priceMult, level);
|
||||||
}
|
}
|
||||||
@ -311,12 +317,16 @@ export function NetscriptCorporation(
|
|||||||
checkAccess("getPurchaseWarehouseCost", 7);
|
checkAccess("getPurchaseWarehouseCost", 7);
|
||||||
return CorporationConstants.WarehouseInitialCost;
|
return CorporationConstants.WarehouseInitialCost;
|
||||||
},
|
},
|
||||||
getUpgradeWarehouseCost: function (_divisionName: unknown, _cityName: unknown): number {
|
getUpgradeWarehouseCost: function (_divisionName: unknown, _cityName: unknown, _amt: unknown = 1): number {
|
||||||
checkAccess("upgradeWarehouse", 7);
|
checkAccess("upgradeWarehouse", 7);
|
||||||
const divisionName = helper.string("getUpgradeWarehouseCost", "divisionName", _divisionName);
|
const divisionName = helper.string("getUpgradeWarehouseCost", "divisionName", _divisionName);
|
||||||
const cityName = helper.city("getUpgradeWarehouseCost", "cityName", _cityName);
|
const cityName = helper.city("getUpgradeWarehouseCost", "cityName", _cityName);
|
||||||
|
const amt = helper.number("getUpgradeWarehouseCost", "amount", _amt);
|
||||||
|
if (amt < 1) {
|
||||||
|
throw helper.makeRuntimeErrorMsg(`corporation.getUpgradeWarehouseCost`, "You must provide a positive number");
|
||||||
|
}
|
||||||
const warehouse = getWarehouse(divisionName, cityName);
|
const warehouse = getWarehouse(divisionName, cityName);
|
||||||
return CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1);
|
return UpgradeWarehouseCost(warehouse, amt);
|
||||||
},
|
},
|
||||||
hasWarehouse: function (_divisionName: unknown, _cityName: unknown): boolean {
|
hasWarehouse: function (_divisionName: unknown, _cityName: unknown): boolean {
|
||||||
checkAccess("hasWarehouse", 7);
|
checkAccess("hasWarehouse", 7);
|
||||||
@ -348,6 +358,7 @@ export function NetscriptCorporation(
|
|||||||
const material = getMaterial(divisionName, cityName, materialName);
|
const material = getMaterial(divisionName, cityName, materialName);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
return {
|
return {
|
||||||
|
cost: material.bCost,
|
||||||
name: material.name,
|
name: material.name,
|
||||||
qty: material.qty,
|
qty: material.qty,
|
||||||
qlt: material.qlt,
|
qlt: material.qlt,
|
||||||
@ -389,12 +400,16 @@ export function NetscriptCorporation(
|
|||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
PurchaseWarehouse(corporation, getDivision(divisionName), cityName);
|
PurchaseWarehouse(corporation, getDivision(divisionName), cityName);
|
||||||
},
|
},
|
||||||
upgradeWarehouse: function (_divisionName: unknown, _cityName: unknown): void {
|
upgradeWarehouse: function (_divisionName: unknown, _cityName: unknown, _amt: unknown = 1): void {
|
||||||
checkAccess("upgradeWarehouse", 7);
|
checkAccess("upgradeWarehouse", 7);
|
||||||
const divisionName = helper.string("upgradeWarehouse", "divisionName", _divisionName);
|
const divisionName = helper.string("upgradeWarehouse", "divisionName", _divisionName);
|
||||||
const cityName = helper.city("upgradeWarehouse", "cityName", _cityName);
|
const cityName = helper.city("upgradeWarehouse", "cityName", _cityName);
|
||||||
|
const amt = helper.number("upgradeWarehouse", "amount", _amt);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
UpgradeWarehouse(corporation, getDivision(divisionName), getWarehouse(divisionName, cityName));
|
if (amt < 1) {
|
||||||
|
throw helper.makeRuntimeErrorMsg(`corporation.upgradeWarehouse`, "You must provide a positive number");
|
||||||
|
}
|
||||||
|
UpgradeWarehouse(corporation, getDivision(divisionName), getWarehouse(divisionName, cityName), amt);
|
||||||
},
|
},
|
||||||
sellMaterial: function (
|
sellMaterial: function (
|
||||||
_divisionName: unknown,
|
_divisionName: unknown,
|
||||||
@ -508,6 +523,19 @@ export function NetscriptCorporation(
|
|||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
MakeProduct(corporation, getDivision(divisionName), cityName, productName, designInvest, marketingInvest);
|
MakeProduct(corporation, getDivision(divisionName), cityName, productName, designInvest, marketingInvest);
|
||||||
},
|
},
|
||||||
|
limitProductProduction: function (
|
||||||
|
_divisionName: unknown,
|
||||||
|
_productName: unknown,
|
||||||
|
_cityName: unknown,
|
||||||
|
_qty: unknown,
|
||||||
|
) {
|
||||||
|
checkAccess("limitProductProduction", 7);
|
||||||
|
const divisionName = helper.string("limitProductProduction", "divisionName", _divisionName);
|
||||||
|
const cityName = helper.city("limitMaterialProduction", "cityName", _cityName);
|
||||||
|
const productName = helper.string("limitProductProduction", "productName", _productName);
|
||||||
|
const qty = helper.number("limitMaterialProduction", "qty", _qty);
|
||||||
|
LimitProductProduction(getProduct(divisionName, productName), cityName, qty);
|
||||||
|
},
|
||||||
exportMaterial: function (
|
exportMaterial: function (
|
||||||
_sourceDivision: unknown,
|
_sourceDivision: unknown,
|
||||||
_sourceCity: unknown,
|
_sourceCity: unknown,
|
||||||
@ -548,6 +576,19 @@ export function NetscriptCorporation(
|
|||||||
const amt = helper.string("cancelExportMaterial", "amt", _amt);
|
const amt = helper.string("cancelExportMaterial", "amt", _amt);
|
||||||
CancelExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "");
|
CancelExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "");
|
||||||
},
|
},
|
||||||
|
limitMaterialProduction: function (
|
||||||
|
_divisionName: unknown,
|
||||||
|
_cityName: unknown,
|
||||||
|
_materialName: unknown,
|
||||||
|
_qty: unknown,
|
||||||
|
) {
|
||||||
|
checkAccess("limitMaterialProduction", 7);
|
||||||
|
const divisionName = helper.string("limitMaterialProduction", "divisionName", _divisionName);
|
||||||
|
const cityName = helper.city("limitMaterialProduction", "cityName", _cityName);
|
||||||
|
const materialName = helper.string("limitMaterialProduction", "materialName", _materialName);
|
||||||
|
const qty = helper.number("limitMaterialProduction", "qty", _qty);
|
||||||
|
LimitMaterialProduction(getMaterial(divisionName, cityName, materialName), qty);
|
||||||
|
},
|
||||||
setMaterialMarketTA1: function (
|
setMaterialMarketTA1: function (
|
||||||
_divisionName: unknown,
|
_divisionName: unknown,
|
||||||
_cityName: unknown,
|
_cityName: unknown,
|
||||||
@ -820,7 +861,7 @@ export function NetscriptCorporation(
|
|||||||
checkAccess("unlockUpgrade");
|
checkAccess("unlockUpgrade");
|
||||||
const upgradeName = helper.string("unlockUpgrade", "upgradeName", _upgradeName);
|
const upgradeName = helper.string("unlockUpgrade", "upgradeName", _upgradeName);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
|
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||||
UnlockUpgrade(corporation, upgrade);
|
UnlockUpgrade(corporation, upgrade);
|
||||||
},
|
},
|
||||||
@ -828,7 +869,7 @@ export function NetscriptCorporation(
|
|||||||
checkAccess("levelUpgrade");
|
checkAccess("levelUpgrade");
|
||||||
const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
|
const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
|
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||||
LevelUpgrade(corporation, upgrade);
|
LevelUpgrade(corporation, upgrade);
|
||||||
},
|
},
|
||||||
|
@ -3,11 +3,13 @@ import { IPlayer } from "../PersonObjects/IPlayer";
|
|||||||
import { Exploit } from "../Exploits/Exploit";
|
import { Exploit } from "../Exploits/Exploit";
|
||||||
import * as bcrypt from "bcryptjs";
|
import * as bcrypt from "bcryptjs";
|
||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
import { INetscriptHelper } from "./INetscriptHelper";
|
||||||
|
import { Apr1Events as devMenu } from "../ui/Apr1";
|
||||||
|
|
||||||
export interface INetscriptExtra {
|
export interface INetscriptExtra {
|
||||||
heart: {
|
heart: {
|
||||||
break(): number;
|
break(): number;
|
||||||
};
|
};
|
||||||
|
openDevMenu(): void;
|
||||||
exploit(): void;
|
exploit(): void;
|
||||||
bypass(doc: Document): void;
|
bypass(doc: Document): void;
|
||||||
alterReality(): void;
|
alterReality(): void;
|
||||||
@ -22,6 +24,9 @@ export function NetscriptExtra(player: IPlayer, workerScript: WorkerScript, help
|
|||||||
return player.karma;
|
return player.karma;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
openDevMenu: function (): void {
|
||||||
|
devMenu.emit();
|
||||||
|
},
|
||||||
exploit: function (): void {
|
exploit: function (): void {
|
||||||
player.giveExploit(Exploit.UndocumentedFunctionCall);
|
player.giveExploit(Exploit.UndocumentedFunctionCall);
|
||||||
},
|
},
|
||||||
|
@ -47,6 +47,8 @@ import { Server } from "../Server/Server";
|
|||||||
import { netscriptCanHack } from "../Hacking/netscriptCanHack";
|
import { netscriptCanHack } from "../Hacking/netscriptCanHack";
|
||||||
import { FactionInfos } from "../Faction/FactionInfo";
|
import { FactionInfos } from "../Faction/FactionInfo";
|
||||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||||
|
import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames";
|
||||||
|
import { enterBitNode } from "../RedPill";
|
||||||
|
|
||||||
export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> {
|
export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> {
|
||||||
const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation {
|
const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation {
|
||||||
@ -94,8 +96,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
return {
|
return {
|
||||||
getOwnedAugmentations: (_ctx: NetscriptContext) =>
|
getOwnedAugmentations: (_ctx: NetscriptContext) =>
|
||||||
function (_purchased: unknown = false): string[] {
|
function (_purchased: unknown = false): string[] {
|
||||||
const purchased = _ctx.helper.boolean(_purchased);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const purchased = _ctx.helper.boolean(_purchased);
|
||||||
const res = [];
|
const res = [];
|
||||||
for (let i = 0; i < player.augmentations.length; ++i) {
|
for (let i = 0; i < player.augmentations.length; ++i) {
|
||||||
res.push(player.augmentations[i].name);
|
res.push(player.augmentations[i].name);
|
||||||
@ -109,52 +111,52 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
getAugmentationsFromFaction: (_ctx: NetscriptContext) =>
|
getAugmentationsFromFaction: (_ctx: NetscriptContext) =>
|
||||||
function (_facName: unknown): string[] {
|
function (_facName: unknown): string[] {
|
||||||
const facName = _ctx.helper.string("facName", _facName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const facName = _ctx.helper.string("facName", _facName);
|
||||||
const faction = getFaction(_ctx, facName);
|
const faction = getFaction(_ctx, facName);
|
||||||
|
|
||||||
return getFactionAugmentationsFiltered(player, faction);
|
return getFactionAugmentationsFiltered(player, faction);
|
||||||
},
|
},
|
||||||
getAugmentationCost: (_ctx: NetscriptContext) =>
|
getAugmentationCost: (_ctx: NetscriptContext) =>
|
||||||
function (_augName: unknown): [number, number] {
|
function (_augName: unknown): [number, number] {
|
||||||
const augName = _ctx.helper.string("augName", _augName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const augName = _ctx.helper.string("augName", _augName);
|
||||||
const aug = getAugmentation(_ctx, augName);
|
const aug = getAugmentation(_ctx, augName);
|
||||||
return [aug.baseRepRequirement, aug.baseCost];
|
return [aug.baseRepRequirement, aug.baseCost];
|
||||||
},
|
},
|
||||||
getAugmentationPrereq: (_ctx: NetscriptContext) =>
|
getAugmentationPrereq: (_ctx: NetscriptContext) =>
|
||||||
function (_augName: unknown): string[] {
|
function (_augName: unknown): string[] {
|
||||||
const augName = _ctx.helper.string("augName", _augName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const augName = _ctx.helper.string("augName", _augName);
|
||||||
const aug = getAugmentation(_ctx, augName);
|
const aug = getAugmentation(_ctx, augName);
|
||||||
return aug.prereqs.slice();
|
return aug.prereqs.slice();
|
||||||
},
|
},
|
||||||
getAugmentationPrice: (_ctx: NetscriptContext) =>
|
getAugmentationPrice: (_ctx: NetscriptContext) =>
|
||||||
function (_augName: unknown): number {
|
function (_augName: unknown): number {
|
||||||
const augName = _ctx.helper.string("augName", _augName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const augName = _ctx.helper.string("augName", _augName);
|
||||||
const aug = getAugmentation(_ctx, augName);
|
const aug = getAugmentation(_ctx, augName);
|
||||||
return aug.baseCost;
|
return aug.baseCost;
|
||||||
},
|
},
|
||||||
getAugmentationRepReq: (_ctx: NetscriptContext) =>
|
getAugmentationRepReq: (_ctx: NetscriptContext) =>
|
||||||
function (_augName: unknown): number {
|
function (_augName: unknown): number {
|
||||||
const augName = _ctx.helper.string("augName", _augName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const augName = _ctx.helper.string("augName", _augName);
|
||||||
const aug = getAugmentation(_ctx, augName);
|
const aug = getAugmentation(_ctx, augName);
|
||||||
return aug.baseRepRequirement;
|
return aug.baseRepRequirement;
|
||||||
},
|
},
|
||||||
getAugmentationStats: (_ctx: NetscriptContext) =>
|
getAugmentationStats: (_ctx: NetscriptContext) =>
|
||||||
function (_augName: unknown): AugmentationStats {
|
function (_augName: unknown): AugmentationStats {
|
||||||
const augName = _ctx.helper.string("augName", _augName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const augName = _ctx.helper.string("augName", _augName);
|
||||||
const aug = getAugmentation(_ctx, augName);
|
const aug = getAugmentation(_ctx, augName);
|
||||||
return Object.assign({}, aug.mults);
|
return Object.assign({}, aug.mults);
|
||||||
},
|
},
|
||||||
purchaseAugmentation: (_ctx: NetscriptContext) =>
|
purchaseAugmentation: (_ctx: NetscriptContext) =>
|
||||||
function (_facName: unknown, _augName: unknown): boolean {
|
function (_facName: unknown, _augName: unknown): boolean {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
const facName = _ctx.helper.string("facName", _facName);
|
const facName = _ctx.helper.string("facName", _facName);
|
||||||
const augName = _ctx.helper.string("augName", _augName);
|
const augName = _ctx.helper.string("augName", _augName);
|
||||||
_ctx.helper.checkSingularityAccess();
|
|
||||||
const fac = getFaction(_ctx, facName);
|
const fac = getFaction(_ctx, facName);
|
||||||
const aug = getAugmentation(_ctx, augName);
|
const aug = getAugmentation(_ctx, augName);
|
||||||
|
|
||||||
@ -200,8 +202,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
softReset: (_ctx: NetscriptContext) =>
|
softReset: (_ctx: NetscriptContext) =>
|
||||||
function (_cbScript: unknown = ""): void {
|
function (_cbScript: unknown = ""): void {
|
||||||
const cbScript = _ctx.helper.string("cbScript", _cbScript);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const cbScript = _ctx.helper.string("cbScript", _cbScript);
|
||||||
|
|
||||||
workerScript.log("softReset", () => "Soft resetting. This will cause this script to be killed");
|
workerScript.log("softReset", () => "Soft resetting. This will cause this script to be killed");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -215,8 +217,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
installAugmentations: (_ctx: NetscriptContext) =>
|
installAugmentations: (_ctx: NetscriptContext) =>
|
||||||
function (_cbScript: unknown = ""): boolean {
|
function (_cbScript: unknown = ""): boolean {
|
||||||
const cbScript = _ctx.helper.string("cbScript", _cbScript);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const cbScript = _ctx.helper.string("cbScript", _cbScript);
|
||||||
|
|
||||||
if (player.queuedAugmentations.length === 0) {
|
if (player.queuedAugmentations.length === 0) {
|
||||||
workerScript.log("installAugmentations", () => "You do not have any Augmentations to be installed.");
|
workerScript.log("installAugmentations", () => "You do not have any Augmentations to be installed.");
|
||||||
@ -239,8 +241,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
|
|
||||||
goToLocation: (_ctx: NetscriptContext) =>
|
goToLocation: (_ctx: NetscriptContext) =>
|
||||||
function (_locationName: unknown): boolean {
|
function (_locationName: unknown): boolean {
|
||||||
const locationName = _ctx.helper.string("locationName", _locationName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const locationName = _ctx.helper.string("locationName", _locationName);
|
||||||
const location = Object.values(Locations).find((l) => l.name === locationName);
|
const location = Object.values(Locations).find((l) => l.name === locationName);
|
||||||
if (!location) {
|
if (!location) {
|
||||||
workerScript.log("goToLocation", () => `No location named ${locationName}`);
|
workerScript.log("goToLocation", () => `No location named ${locationName}`);
|
||||||
@ -256,10 +258,10 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
universityCourse: (_ctx: NetscriptContext) =>
|
universityCourse: (_ctx: NetscriptContext) =>
|
||||||
function (_universityName: unknown, _className: unknown, _focus: unknown = true): boolean {
|
function (_universityName: unknown, _className: unknown, _focus: unknown = true): boolean {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
const universityName = _ctx.helper.string("universityName", _universityName);
|
const universityName = _ctx.helper.string("universityName", _universityName);
|
||||||
const className = _ctx.helper.string("className", _className);
|
const className = _ctx.helper.string("className", _className);
|
||||||
const focus = _ctx.helper.boolean(_focus);
|
const focus = _ctx.helper.boolean(_focus);
|
||||||
_ctx.helper.checkSingularityAccess();
|
|
||||||
const wasFocusing = player.focus;
|
const wasFocusing = player.focus;
|
||||||
if (player.isWorking) {
|
if (player.isWorking) {
|
||||||
const txt = player.singularityStopWork();
|
const txt = player.singularityStopWork();
|
||||||
@ -347,10 +349,10 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
|
|
||||||
gymWorkout: (_ctx: NetscriptContext) =>
|
gymWorkout: (_ctx: NetscriptContext) =>
|
||||||
function (_gymName: unknown, _stat: unknown, _focus: unknown = true): boolean {
|
function (_gymName: unknown, _stat: unknown, _focus: unknown = true): boolean {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
const gymName = _ctx.helper.string("gymName", _gymName);
|
const gymName = _ctx.helper.string("gymName", _gymName);
|
||||||
const stat = _ctx.helper.string("stat", _stat);
|
const stat = _ctx.helper.string("stat", _stat);
|
||||||
const focus = _ctx.helper.boolean(_focus);
|
const focus = _ctx.helper.boolean(_focus);
|
||||||
_ctx.helper.checkSingularityAccess();
|
|
||||||
const wasFocusing = player.focus;
|
const wasFocusing = player.focus;
|
||||||
if (player.isWorking) {
|
if (player.isWorking) {
|
||||||
const txt = player.singularityStopWork();
|
const txt = player.singularityStopWork();
|
||||||
@ -462,8 +464,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
|
|
||||||
travelToCity: (_ctx: NetscriptContext) =>
|
travelToCity: (_ctx: NetscriptContext) =>
|
||||||
function (_cityName: unknown): boolean {
|
function (_cityName: unknown): boolean {
|
||||||
const cityName = _ctx.helper.city("cityName", _cityName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const cityName = _ctx.helper.city("cityName", _cityName);
|
||||||
|
|
||||||
switch (cityName) {
|
switch (cityName) {
|
||||||
case CityName.Aevum:
|
case CityName.Aevum:
|
||||||
@ -520,8 +522,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
purchaseProgram: (_ctx: NetscriptContext) =>
|
purchaseProgram: (_ctx: NetscriptContext) =>
|
||||||
function (_programName: unknown): boolean {
|
function (_programName: unknown): boolean {
|
||||||
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
||||||
|
|
||||||
if (!player.hasTorRouter()) {
|
if (!player.hasTorRouter()) {
|
||||||
workerScript.log("purchaseProgram", () => "You do not have the TOR router.");
|
workerScript.log("purchaseProgram", () => "You do not have the TOR router.");
|
||||||
@ -569,8 +571,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
connect: (_ctx: NetscriptContext) =>
|
connect: (_ctx: NetscriptContext) =>
|
||||||
function (_hostname: unknown): boolean {
|
function (_hostname: unknown): boolean {
|
||||||
const hostname = _ctx.helper.string("hostname", _hostname);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const hostname = _ctx.helper.string("hostname", _hostname);
|
||||||
if (!hostname) {
|
if (!hostname) {
|
||||||
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid hostname: '${hostname}'`);
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid hostname: '${hostname}'`);
|
||||||
}
|
}
|
||||||
@ -662,8 +664,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
setFocus: (_ctx: NetscriptContext) =>
|
setFocus: (_ctx: NetscriptContext) =>
|
||||||
function (_focus: unknown): boolean {
|
function (_focus: unknown): boolean {
|
||||||
const focus = _ctx.helper.boolean(_focus);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const focus = _ctx.helper.boolean(_focus);
|
||||||
if (!player.isWorking) {
|
if (!player.isWorking) {
|
||||||
throw _ctx.helper.makeRuntimeErrorMsg("Not currently working");
|
throw _ctx.helper.makeRuntimeErrorMsg("Not currently working");
|
||||||
}
|
}
|
||||||
@ -862,9 +864,9 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
workForCompany: (_ctx: NetscriptContext) =>
|
workForCompany: (_ctx: NetscriptContext) =>
|
||||||
function (_companyName: unknown, _focus: unknown = true): boolean {
|
function (_companyName: unknown, _focus: unknown = true): boolean {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
let companyName = _ctx.helper.string("companyName", _companyName);
|
let companyName = _ctx.helper.string("companyName", _companyName);
|
||||||
const focus = _ctx.helper.boolean(_focus);
|
const focus = _ctx.helper.boolean(_focus);
|
||||||
_ctx.helper.checkSingularityAccess();
|
|
||||||
|
|
||||||
// Sanitize input
|
// Sanitize input
|
||||||
if (companyName == null) {
|
if (companyName == null) {
|
||||||
@ -918,9 +920,9 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
applyToCompany: (_ctx: NetscriptContext) =>
|
applyToCompany: (_ctx: NetscriptContext) =>
|
||||||
function (_companyName: unknown, _field: unknown): boolean {
|
function (_companyName: unknown, _field: unknown): boolean {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
const companyName = _ctx.helper.string("companyName", _companyName);
|
const companyName = _ctx.helper.string("companyName", _companyName);
|
||||||
const field = _ctx.helper.string("field", _field);
|
const field = _ctx.helper.string("field", _field);
|
||||||
_ctx.helper.checkSingularityAccess();
|
|
||||||
getCompany(_ctx, companyName);
|
getCompany(_ctx, companyName);
|
||||||
|
|
||||||
player.location = companyName as LocationName;
|
player.location = companyName as LocationName;
|
||||||
@ -990,22 +992,22 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
getCompanyRep: (_ctx: NetscriptContext) =>
|
getCompanyRep: (_ctx: NetscriptContext) =>
|
||||||
function (_companyName: unknown): number {
|
function (_companyName: unknown): number {
|
||||||
const companyName = _ctx.helper.string("companyName", _companyName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const companyName = _ctx.helper.string("companyName", _companyName);
|
||||||
const company = getCompany(_ctx, companyName);
|
const company = getCompany(_ctx, companyName);
|
||||||
return company.playerReputation;
|
return company.playerReputation;
|
||||||
},
|
},
|
||||||
getCompanyFavor: (_ctx: NetscriptContext) =>
|
getCompanyFavor: (_ctx: NetscriptContext) =>
|
||||||
function (_companyName: unknown): number {
|
function (_companyName: unknown): number {
|
||||||
const companyName = _ctx.helper.string("companyName", _companyName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const companyName = _ctx.helper.string("companyName", _companyName);
|
||||||
const company = getCompany(_ctx, companyName);
|
const company = getCompany(_ctx, companyName);
|
||||||
return company.favor;
|
return company.favor;
|
||||||
},
|
},
|
||||||
getCompanyFavorGain: (_ctx: NetscriptContext) =>
|
getCompanyFavorGain: (_ctx: NetscriptContext) =>
|
||||||
function (_companyName: unknown): number {
|
function (_companyName: unknown): number {
|
||||||
const companyName = _ctx.helper.string("companyName", _companyName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const companyName = _ctx.helper.string("companyName", _companyName);
|
||||||
const company = getCompany(_ctx, companyName);
|
const company = getCompany(_ctx, companyName);
|
||||||
return company.getFavorGain();
|
return company.getFavorGain();
|
||||||
},
|
},
|
||||||
@ -1017,8 +1019,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
joinFaction: (_ctx: NetscriptContext) =>
|
joinFaction: (_ctx: NetscriptContext) =>
|
||||||
function (_facName: unknown): boolean {
|
function (_facName: unknown): boolean {
|
||||||
const facName = _ctx.helper.string("facName", _facName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const facName = _ctx.helper.string("facName", _facName);
|
||||||
getFaction(_ctx, facName);
|
getFaction(_ctx, facName);
|
||||||
|
|
||||||
if (!player.factionInvitations.includes(facName)) {
|
if (!player.factionInvitations.includes(facName)) {
|
||||||
@ -1041,10 +1043,10 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
workForFaction: (_ctx: NetscriptContext) =>
|
workForFaction: (_ctx: NetscriptContext) =>
|
||||||
function (_facName: unknown, _type: unknown, _focus: unknown = true): boolean {
|
function (_facName: unknown, _type: unknown, _focus: unknown = true): boolean {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
const facName = _ctx.helper.string("facName", _facName);
|
const facName = _ctx.helper.string("facName", _facName);
|
||||||
const type = _ctx.helper.string("type", _type);
|
const type = _ctx.helper.string("type", _type);
|
||||||
const focus = _ctx.helper.boolean(_focus);
|
const focus = _ctx.helper.boolean(_focus);
|
||||||
_ctx.helper.checkSingularityAccess();
|
|
||||||
getFaction(_ctx, facName);
|
getFaction(_ctx, facName);
|
||||||
|
|
||||||
// if the player is in a gang and the target faction is any of the gang faction, fail
|
// if the player is in a gang and the target faction is any of the gang faction, fail
|
||||||
@ -1130,30 +1132,30 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
getFactionRep: (_ctx: NetscriptContext) =>
|
getFactionRep: (_ctx: NetscriptContext) =>
|
||||||
function (_facName: unknown): number {
|
function (_facName: unknown): number {
|
||||||
const facName = _ctx.helper.string("facName", _facName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const facName = _ctx.helper.string("facName", _facName);
|
||||||
const faction = getFaction(_ctx, facName);
|
const faction = getFaction(_ctx, facName);
|
||||||
return faction.playerReputation;
|
return faction.playerReputation;
|
||||||
},
|
},
|
||||||
getFactionFavor: (_ctx: NetscriptContext) =>
|
getFactionFavor: (_ctx: NetscriptContext) =>
|
||||||
function (_facName: unknown): number {
|
function (_facName: unknown): number {
|
||||||
const facName = _ctx.helper.string("facName", _facName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const facName = _ctx.helper.string("facName", _facName);
|
||||||
const faction = getFaction(_ctx, facName);
|
const faction = getFaction(_ctx, facName);
|
||||||
return faction.favor;
|
return faction.favor;
|
||||||
},
|
},
|
||||||
getFactionFavorGain: (_ctx: NetscriptContext) =>
|
getFactionFavorGain: (_ctx: NetscriptContext) =>
|
||||||
function (_facName: unknown): number {
|
function (_facName: unknown): number {
|
||||||
const facName = _ctx.helper.string("facName", _facName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const facName = _ctx.helper.string("facName", _facName);
|
||||||
const faction = getFaction(_ctx, facName);
|
const faction = getFaction(_ctx, facName);
|
||||||
return faction.getFavorGain();
|
return faction.getFavorGain();
|
||||||
},
|
},
|
||||||
donateToFaction: (_ctx: NetscriptContext) =>
|
donateToFaction: (_ctx: NetscriptContext) =>
|
||||||
function (_facName: unknown, _amt: unknown): boolean {
|
function (_facName: unknown, _amt: unknown): boolean {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
const facName = _ctx.helper.string("facName", _facName);
|
const facName = _ctx.helper.string("facName", _facName);
|
||||||
const amt = _ctx.helper.number("amt", _amt);
|
const amt = _ctx.helper.number("amt", _amt);
|
||||||
_ctx.helper.checkSingularityAccess();
|
|
||||||
const faction = getFaction(_ctx, facName);
|
const faction = getFaction(_ctx, facName);
|
||||||
if (!player.factions.includes(faction.name)) {
|
if (!player.factions.includes(faction.name)) {
|
||||||
workerScript.log("donateToFaction", () => `You can't donate to '${facName}' because you aren't a member`);
|
workerScript.log("donateToFaction", () => `You can't donate to '${facName}' because you aren't a member`);
|
||||||
@ -1200,9 +1202,9 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
createProgram: (_ctx: NetscriptContext) =>
|
createProgram: (_ctx: NetscriptContext) =>
|
||||||
function (_programName: unknown, _focus: unknown = true): boolean {
|
function (_programName: unknown, _focus: unknown = true): boolean {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
||||||
const focus = _ctx.helper.boolean(_focus);
|
const focus = _ctx.helper.boolean(_focus);
|
||||||
_ctx.helper.checkSingularityAccess();
|
|
||||||
|
|
||||||
const wasFocusing = player.focus;
|
const wasFocusing = player.focus;
|
||||||
if (player.isWorking) {
|
if (player.isWorking) {
|
||||||
@ -1249,8 +1251,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
commitCrime: (_ctx: NetscriptContext) =>
|
commitCrime: (_ctx: NetscriptContext) =>
|
||||||
function (_crimeRoughName: unknown): number {
|
function (_crimeRoughName: unknown): number {
|
||||||
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
||||||
|
|
||||||
if (player.isWorking) {
|
if (player.isWorking) {
|
||||||
const txt = player.singularityStopWork();
|
const txt = player.singularityStopWork();
|
||||||
@ -1270,8 +1272,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
getCrimeChance: (_ctx: NetscriptContext) =>
|
getCrimeChance: (_ctx: NetscriptContext) =>
|
||||||
function (_crimeRoughName: unknown): number {
|
function (_crimeRoughName: unknown): number {
|
||||||
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
||||||
|
|
||||||
const crime = findCrime(crimeRoughName.toLowerCase());
|
const crime = findCrime(crimeRoughName.toLowerCase());
|
||||||
if (crime == null) {
|
if (crime == null) {
|
||||||
@ -1282,8 +1284,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
getCrimeStats: (_ctx: NetscriptContext) =>
|
getCrimeStats: (_ctx: NetscriptContext) =>
|
||||||
function (_crimeRoughName: unknown): CrimeStats {
|
function (_crimeRoughName: unknown): CrimeStats {
|
||||||
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
||||||
|
|
||||||
const crime = findCrime(crimeRoughName.toLowerCase());
|
const crime = findCrime(crimeRoughName.toLowerCase());
|
||||||
if (crime == null) {
|
if (crime == null) {
|
||||||
@ -1305,8 +1307,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
getDarkwebProgramCost: (_ctx: NetscriptContext) =>
|
getDarkwebProgramCost: (_ctx: NetscriptContext) =>
|
||||||
function (_programName: unknown): number {
|
function (_programName: unknown): number {
|
||||||
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
|
||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
||||||
|
|
||||||
// If we don't have Tor, log it and return -1
|
// If we don't have Tor, log it and return -1
|
||||||
if (!player.hasTorRouter()) {
|
if (!player.hasTorRouter()) {
|
||||||
@ -1335,5 +1337,51 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
}
|
}
|
||||||
return item.price;
|
return item.price;
|
||||||
},
|
},
|
||||||
|
b1tflum3:
|
||||||
|
(_ctx: NetscriptContext) =>
|
||||||
|
(_nextBN: unknown, _callbackScript: unknown = ""): void => {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const nextBN = _ctx.helper.number("nextBN", _nextBN);
|
||||||
|
const callbackScript = _ctx.helper.string("callbackScript", _callbackScript);
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
enterBitNode(Router, true, player.bitNodeN, nextBN);
|
||||||
|
if (callbackScript)
|
||||||
|
setTimeout(() => {
|
||||||
|
runAfterReset(callbackScript);
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
destroyW0r1dD43m0n:
|
||||||
|
(_ctx: NetscriptContext) =>
|
||||||
|
(_nextBN: unknown, _callbackScript: unknown = ""): void => {
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
const nextBN = _ctx.helper.number("nextBN", _nextBN);
|
||||||
|
const callbackScript = _ctx.helper.string("callbackScript", _callbackScript);
|
||||||
|
_ctx.helper.checkSingularityAccess();
|
||||||
|
|
||||||
|
const hackingRequirements = (): boolean => {
|
||||||
|
const wd = GetServer(SpecialServers.WorldDaemon);
|
||||||
|
if (!(wd instanceof Server))
|
||||||
|
throw new Error("WorldDaemon was not a normal server. This is a bug contact dev.");
|
||||||
|
if (player.hacking < wd.requiredHackingSkill) return false;
|
||||||
|
if (!wd.hasAdminRights) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
const bladeburnerRequirements = (): boolean => {
|
||||||
|
if (!player.inBladeburner()) return false;
|
||||||
|
if (!player.bladeburner) return false;
|
||||||
|
return player.bladeburner.blackops[BlackOperationNames.OperationDaedalus];
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!hackingRequirements() && !bladeburnerRequirements()) {
|
||||||
|
_ctx.log(() => "Requirements not met to destroy the world daemon");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
enterBitNode(Router, false, player.bitNodeN, nextBN);
|
||||||
|
if (callbackScript)
|
||||||
|
setTimeout(() => {
|
||||||
|
runAfterReset(callbackScript);
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import { INetscriptHelper } from "./INetscriptHelper";
|
|||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||||
import { FactionWorkType } from "../Faction/FactionWorkTypeEnum";
|
import { FactionWorkType } from "../Faction/FactionWorkTypeEnum";
|
||||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
|
||||||
import { SleeveTaskType } from "../PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
import { SleeveTaskType } from "../PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
||||||
@ -20,7 +19,7 @@ import {
|
|||||||
|
|
||||||
export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): ISleeve {
|
export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): ISleeve {
|
||||||
const checkSleeveAPIAccess = function (func: string): void {
|
const checkSleeveAPIAccess = function (func: string): void {
|
||||||
if (player.bitNodeN !== 10 && !SourceFileFlags[10]) {
|
if (player.bitNodeN !== 10 && !player.sourceFileLvl(10)) {
|
||||||
throw helper.makeRuntimeErrorMsg(
|
throw helper.makeRuntimeErrorMsg(
|
||||||
`sleeve.${func}`,
|
`sleeve.${func}`,
|
||||||
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|
||||||
import { IPlayer } from "../IPlayer";
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
export function canAccessBladeburner(this: IPlayer): boolean {
|
export function canAccessBladeburner(this: IPlayer): boolean {
|
||||||
@ -7,7 +6,7 @@ export function canAccessBladeburner(this: IPlayer): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.bitNodeN === 6 || this.bitNodeN === 7 || SourceFileFlags[6] > 0 || SourceFileFlags[7] > 0;
|
return this.bitNodeN === 6 || this.bitNodeN === 7 || this.sourceFileLvl(6) > 0 || this.sourceFileLvl(7) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inBladeburner(this: IPlayer): boolean {
|
export function inBladeburner(this: IPlayer): boolean {
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { Corporation } from "../../Corporation/Corporation";
|
import { Corporation } from "../../Corporation/Corporation";
|
||||||
import { CorporationUnlockUpgrades } from "../../Corporation/data/CorporationUnlockUpgrades";
|
import {
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
CorporationUnlockUpgradeIndex,
|
||||||
|
CorporationUnlockUpgrades,
|
||||||
|
} from "../../Corporation/data/CorporationUnlockUpgrades";
|
||||||
import { IPlayer } from "../IPlayer";
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
export function canAccessCorporation(this: IPlayer): boolean {
|
export function canAccessCorporation(this: IPlayer): boolean {
|
||||||
return this.bitNodeN === 3 || SourceFileFlags[3] > 0;
|
return this.bitNodeN === 3 || this.sourceFileLvl(3) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasCorporation(this: IPlayer): boolean {
|
export function hasCorporation(this: IPlayer): boolean {
|
||||||
@ -19,9 +21,9 @@ export function startCorporation(this: IPlayer, corpName: string, additionalShar
|
|||||||
name: corpName,
|
name: corpName,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (SourceFileFlags[3] === 3) {
|
if (this.sourceFileLvl(3) === 3) {
|
||||||
const warehouseApi = CorporationUnlockUpgrades["7"][0];
|
const warehouseApi = CorporationUnlockUpgrades[CorporationUnlockUpgradeIndex.WarehouseAPI].index;
|
||||||
const OfficeApi = CorporationUnlockUpgrades["8"][0];
|
const OfficeApi = CorporationUnlockUpgrades[CorporationUnlockUpgradeIndex.OfficeAPI].index;
|
||||||
|
|
||||||
this.corporation.unlockUpgrades[warehouseApi] = 1;
|
this.corporation.unlockUpgrades[warehouseApi] = 1;
|
||||||
this.corporation.unlockUpgrades[OfficeApi] = 1;
|
this.corporation.unlockUpgrades[OfficeApi] = 1;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Factions } from "../../Faction/Factions";
|
import { Factions } from "../../Faction/Factions";
|
||||||
import { Faction } from "../../Faction/Faction";
|
import { Faction } from "../../Faction/Faction";
|
||||||
import { Gang } from "../../Gang/Gang";
|
import { Gang } from "../../Gang/Gang";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|
||||||
import { IPlayer } from "../IPlayer";
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
// Amount of negative karma needed to manage a gang in BitNodes other than 2
|
// Amount of negative karma needed to manage a gang in BitNodes other than 2
|
||||||
@ -11,7 +10,7 @@ export function canAccessGang(this: IPlayer): boolean {
|
|||||||
if (this.bitNodeN === 2) {
|
if (this.bitNodeN === 2) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (SourceFileFlags[2] <= 0) {
|
if (this.sourceFileLvl(2) <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ import { SpecialServers } from "../../Server/data/SpecialServers";
|
|||||||
import { applySourceFile } from "../../SourceFile/applySourceFile";
|
import { applySourceFile } from "../../SourceFile/applySourceFile";
|
||||||
import { applyExploit } from "../../Exploits/applyExploits";
|
import { applyExploit } from "../../Exploits/applyExploits";
|
||||||
import { SourceFiles } from "../../SourceFile/SourceFiles";
|
import { SourceFiles } from "../../SourceFile/SourceFiles";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|
||||||
import { influenceStockThroughCompanyWork } from "../../StockMarket/PlayerInfluencing";
|
import { influenceStockThroughCompanyWork } from "../../StockMarket/PlayerInfluencing";
|
||||||
import { getHospitalizationCost } from "../../Hospital/Hospital";
|
import { getHospitalizationCost } from "../../Hospital/Hospital";
|
||||||
import { WorkerScript } from "../../Netscript/WorkerScript";
|
import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||||
@ -121,7 +120,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
|
|||||||
|
|
||||||
this.queuedAugmentations = [];
|
this.queuedAugmentations = [];
|
||||||
|
|
||||||
const numSleeves = Math.min(3, SourceFileFlags[10] + (this.bitNodeN === 10 ? 1 : 0)) + this.sleevesFromCovenant;
|
const numSleeves = Math.min(3, this.sourceFileLvl(10) + (this.bitNodeN === 10 ? 1 : 0)) + this.sleevesFromCovenant;
|
||||||
if (this.sleeves.length > numSleeves) this.sleeves.length = numSleeves;
|
if (this.sleeves.length > numSleeves) this.sleeves.length = numSleeves;
|
||||||
for (let i = this.sleeves.length; i < numSleeves; i++) {
|
for (let i = this.sleeves.length; i < numSleeves; i++) {
|
||||||
this.sleeves.push(new Sleeve(this));
|
this.sleeves.push(new Sleeve(this));
|
||||||
@ -467,7 +466,7 @@ export function gainIntelligenceExp(this: IPlayer, exp: number): void {
|
|||||||
console.error("ERROR: NaN passed into Player.gainIntelligenceExp()");
|
console.error("ERROR: NaN passed into Player.gainIntelligenceExp()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (SourceFileFlags[5] > 0 || this.intelligence > 0) {
|
if (this.sourceFileLvl(5) > 0 || this.intelligence > 0) {
|
||||||
this.intelligence_exp += exp;
|
this.intelligence_exp += exp;
|
||||||
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp));
|
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp));
|
||||||
}
|
}
|
||||||
@ -1037,7 +1036,7 @@ export function getWorkMoneyGain(this: IPlayer): number {
|
|||||||
// If player has SF-11, calculate salary multiplier from favor
|
// If player has SF-11, calculate salary multiplier from favor
|
||||||
let bn11Mult = 1;
|
let bn11Mult = 1;
|
||||||
const company = Companies[this.companyName];
|
const company = Companies[this.companyName];
|
||||||
if (SourceFileFlags[11] > 0) {
|
if (this.sourceFileLvl(11) > 0) {
|
||||||
bn11Mult = 1 + company.favor / 100;
|
bn11Mult = 1 + company.favor / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1315,20 +1314,21 @@ export function createProgramWork(this: IPlayer, numCycles: number): boolean {
|
|||||||
|
|
||||||
export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): string {
|
export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): string {
|
||||||
const programName = this.createProgramName;
|
const programName = this.createProgramName;
|
||||||
if (cancelled === false) {
|
if (!cancelled) {
|
||||||
|
//Complete case
|
||||||
|
this.gainIntelligenceExp((CONSTANTS.IntelligenceProgramBaseExpGain * this.timeWorked) / 1000);
|
||||||
dialogBoxCreate(`You've finished creating ${programName}!<br>The new program can be found on your home computer.`);
|
dialogBoxCreate(`You've finished creating ${programName}!<br>The new program can be found on your home computer.`);
|
||||||
|
|
||||||
this.getHomeComputer().programs.push(programName);
|
if (!this.getHomeComputer().programs.includes(programName)) {
|
||||||
} else {
|
this.getHomeComputer().programs.push(programName);
|
||||||
|
}
|
||||||
|
} else if (!this.getHomeComputer().programs.includes(programName)) {
|
||||||
|
//Incomplete case
|
||||||
const perc = (Math.floor((this.timeWorkedCreateProgram / this.timeNeededToCompleteWork) * 10000) / 100).toString();
|
const perc = (Math.floor((this.timeWorkedCreateProgram / this.timeNeededToCompleteWork) * 10000) / 100).toString();
|
||||||
const incompleteName = programName + "-" + perc + "%-INC";
|
const incompleteName = programName + "-" + perc + "%-INC";
|
||||||
this.getHomeComputer().programs.push(incompleteName);
|
this.getHomeComputer().programs.push(incompleteName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cancelled) {
|
|
||||||
this.gainIntelligenceExp((CONSTANTS.IntelligenceProgramBaseExpGain * this.timeWorked) / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isWorking = false;
|
this.isWorking = false;
|
||||||
|
|
||||||
this.resetWorkStatus();
|
this.resetWorkStatus();
|
||||||
@ -2699,7 +2699,7 @@ export function gotoLocation(this: IPlayer, to: LocationName): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function canAccessGrafting(this: IPlayer): boolean {
|
export function canAccessGrafting(this: IPlayer): boolean {
|
||||||
return this.bitNodeN === 10 || SourceFileFlags[10] > 0;
|
return this.bitNodeN === 10 || this.sourceFileLvl(10) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function giveExploit(this: IPlayer, exploit: Exploit): void {
|
export function giveExploit(this: IPlayer, exploit: Exploit): void {
|
||||||
@ -2737,7 +2737,7 @@ export function setMult(this: IPlayer, name: string, mult: number): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function canAccessCotMG(this: IPlayer): boolean {
|
export function canAccessCotMG(this: IPlayer): boolean {
|
||||||
return this.bitNodeN === 13 || SourceFileFlags[13] > 0;
|
return this.bitNodeN === 13 || this.sourceFileLvl(13) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sourceFileLvl(this: IPlayer, n: number): number {
|
export function sourceFileLvl(this: IPlayer, n: number): number {
|
||||||
|
@ -20,7 +20,6 @@ import { LiteratureNames } from "./Literature/data/LiteratureNames";
|
|||||||
|
|
||||||
import { GetServer, AddToAllServers, initForeignServers, prestigeAllServers } from "./Server/AllServers";
|
import { GetServer, AddToAllServers, initForeignServers, prestigeAllServers } from "./Server/AllServers";
|
||||||
import { prestigeHomeComputer } from "./Server/ServerHelpers";
|
import { prestigeHomeComputer } from "./Server/ServerHelpers";
|
||||||
import { SourceFileFlags, updateSourceFileFlags } from "./SourceFile/SourceFileFlags";
|
|
||||||
import { SpecialServers } from "./Server/data/SpecialServers";
|
import { SpecialServers } from "./Server/data/SpecialServers";
|
||||||
import { deleteStockMarket, initStockMarket, initSymbolToStockMap } from "./StockMarket/StockMarket";
|
import { deleteStockMarket, initStockMarket, initSymbolToStockMap } from "./StockMarket/StockMarket";
|
||||||
import { Terminal } from "./Terminal";
|
import { Terminal } from "./Terminal";
|
||||||
@ -139,7 +138,7 @@ export function prestigeAugmentation(): void {
|
|||||||
if (Player.bitNodeN === 8) {
|
if (Player.bitNodeN === 8) {
|
||||||
Player.money = BitNode8StartingMoney;
|
Player.money = BitNode8StartingMoney;
|
||||||
}
|
}
|
||||||
if (Player.bitNodeN === 8 || SourceFileFlags[8] > 0) {
|
if (Player.bitNodeN === 8 || Player.sourceFileLvl(8) > 0) {
|
||||||
Player.hasWseAccount = true;
|
Player.hasWseAccount = true;
|
||||||
Player.hasTixApiAccess = true;
|
Player.hasTixApiAccess = true;
|
||||||
}
|
}
|
||||||
@ -174,7 +173,6 @@ export function prestigeAugmentation(): void {
|
|||||||
// Prestige by destroying Bit Node and gaining a Source File
|
// Prestige by destroying Bit Node and gaining a Source File
|
||||||
export function prestigeSourceFile(flume: boolean): void {
|
export function prestigeSourceFile(flume: boolean): void {
|
||||||
initBitNodeMultipliers(Player);
|
initBitNodeMultipliers(Player);
|
||||||
updateSourceFileFlags(Player);
|
|
||||||
|
|
||||||
Player.prestigeSourceFile();
|
Player.prestigeSourceFile();
|
||||||
prestigeWorkerScripts(); // Delete all Worker Scripts objects
|
prestigeWorkerScripts(); // Delete all Worker Scripts objects
|
||||||
@ -198,9 +196,9 @@ export function prestigeSourceFile(flume: boolean): void {
|
|||||||
// Re-create foreign servers
|
// Re-create foreign servers
|
||||||
initForeignServers(Player.getHomeComputer());
|
initForeignServers(Player.getHomeComputer());
|
||||||
|
|
||||||
if (SourceFileFlags[9] >= 2) {
|
if (Player.sourceFileLvl(9) >= 2) {
|
||||||
homeComp.setMaxRam(128);
|
homeComp.setMaxRam(128);
|
||||||
} else if (SourceFileFlags[1] > 0) {
|
} else if (Player.sourceFileLvl(1) > 0) {
|
||||||
homeComp.setMaxRam(32);
|
homeComp.setMaxRam(32);
|
||||||
} else {
|
} else {
|
||||||
homeComp.setMaxRam(8);
|
homeComp.setMaxRam(8);
|
||||||
@ -234,10 +232,10 @@ export function prestigeSourceFile(flume: boolean): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Give levels of NeuroFluxGoverner for Source-File 12. Must be done here before Augmentations are recalculated
|
// Give levels of NeuroFluxGoverner for Source-File 12. Must be done here before Augmentations are recalculated
|
||||||
if (SourceFileFlags[12] > 0) {
|
if (Player.sourceFileLvl(12) > 0) {
|
||||||
Player.augmentations.push({
|
Player.augmentations.push({
|
||||||
name: AugmentationNames.NeuroFluxGovernor,
|
name: AugmentationNames.NeuroFluxGovernor,
|
||||||
level: SourceFileFlags[12],
|
level: Player.sourceFileLvl(12),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +262,7 @@ export function prestigeSourceFile(flume: boolean): void {
|
|||||||
if (Player.bitNodeN === 8) {
|
if (Player.bitNodeN === 8) {
|
||||||
Player.money = BitNode8StartingMoney;
|
Player.money = BitNode8StartingMoney;
|
||||||
}
|
}
|
||||||
if (Player.bitNodeN === 8 || SourceFileFlags[8] > 0) {
|
if (Player.bitNodeN === 8 || Player.sourceFileLvl(8) > 0) {
|
||||||
Player.hasWseAccount = true;
|
Player.hasWseAccount = true;
|
||||||
Player.hasTixApiAccess = true;
|
Player.hasTixApiAccess = true;
|
||||||
}
|
}
|
||||||
@ -292,7 +290,7 @@ export function prestigeSourceFile(flume: boolean): void {
|
|||||||
Player.bladeburner = null;
|
Player.bladeburner = null;
|
||||||
|
|
||||||
// Source-File 9 (level 3) effect
|
// Source-File 9 (level 3) effect
|
||||||
if (SourceFileFlags[9] >= 3) {
|
if (Player.sourceFileLvl(9) >= 3) {
|
||||||
const hserver = Player.createHacknetServer();
|
const hserver = Player.createHacknetServer();
|
||||||
|
|
||||||
hserver.level = 100;
|
hserver.level = 100;
|
||||||
@ -309,7 +307,7 @@ export function prestigeSourceFile(flume: boolean): void {
|
|||||||
staneksGift.prestigeSourceFile();
|
staneksGift.prestigeSourceFile();
|
||||||
|
|
||||||
// Gain int exp
|
// Gain int exp
|
||||||
if (SourceFileFlags[5] !== 0 && !flume) Player.gainIntelligenceExp(300);
|
if (Player.sourceFileLvl(5) !== 0 && !flume) Player.gainIntelligenceExp(300);
|
||||||
|
|
||||||
resetPidCounter();
|
resetPidCounter();
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,4 @@ export class Program {
|
|||||||
this.create = create;
|
this.create = create;
|
||||||
this.run = run;
|
this.run = run;
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlID(): string {
|
|
||||||
const name = this.name.endsWith(".exe") ? this.name.slice(0, -".exe".length) : this.name;
|
|
||||||
return "create-program-" + name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import React from "react";
|
|||||||
import { Player } from "./Player";
|
import { Player } from "./Player";
|
||||||
import { prestigeSourceFile } from "./Prestige";
|
import { prestigeSourceFile } from "./Prestige";
|
||||||
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
|
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
|
||||||
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
|
||||||
import { SourceFiles } from "./SourceFile/SourceFiles";
|
import { SourceFiles } from "./SourceFile/SourceFiles";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
||||||
@ -69,7 +68,7 @@ function giveSourceFile(bitNodeNumber: number): void {
|
|||||||
export function enterBitNode(router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number): void {
|
export function enterBitNode(router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number): void {
|
||||||
if (!flume) {
|
if (!flume) {
|
||||||
giveSourceFile(destroyedBitNode);
|
giveSourceFile(destroyedBitNode);
|
||||||
} else if (SourceFileFlags[5] === 0 && newBitNode !== 5) {
|
} else if (Player.sourceFileLvl(5) === 0 && newBitNode !== 5) {
|
||||||
Player.intelligence = 0;
|
Player.intelligence = 0;
|
||||||
Player.intelligence_exp = 0;
|
Player.intelligence_exp = 0;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import { loadAllGangs, AllGangs } from "./Gang/AllGangs";
|
|||||||
import { Player, loadPlayer } from "./Player";
|
import { Player, loadPlayer } from "./Player";
|
||||||
import { saveAllServers, loadAllServers, GetAllServers } from "./Server/AllServers";
|
import { saveAllServers, loadAllServers, GetAllServers } from "./Server/AllServers";
|
||||||
import { Settings } from "./Settings/Settings";
|
import { Settings } from "./Settings/Settings";
|
||||||
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
|
||||||
import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket";
|
import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket";
|
||||||
import { staneksGift, loadStaneksGift } from "./CotMG/Helper";
|
import { staneksGift, loadStaneksGift } from "./CotMG/Helper";
|
||||||
|
|
||||||
@ -126,7 +125,7 @@ class BitburnerSaveObject {
|
|||||||
// Save file name is based on current timestamp and BitNode
|
// Save file name is based on current timestamp and BitNode
|
||||||
const epochTime = Math.round(Date.now() / 1000);
|
const epochTime = Math.round(Date.now() / 1000);
|
||||||
const bn = Player.bitNodeN;
|
const bn = Player.bitNodeN;
|
||||||
let filename = `bitburnerSave_${epochTime}_BN${bn}x${SourceFileFlags[bn]}.json`;
|
let filename = `bitburnerSave_${epochTime}_BN${bn}x${Player.sourceFileLvl(bn) + 1}.json`;
|
||||||
if (isRecovery) filename = "RECOVERY" + filename;
|
if (isRecovery) filename = "RECOVERY" + filename;
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
@ -395,6 +394,9 @@ function evaluateVersionCompatibility(ver: string | number): void {
|
|||||||
delete anyPlayer.resleeves;
|
delete anyPlayer.resleeves;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ver < 14) {
|
||||||
|
delete (Settings as any).EditorTheme;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
63
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
63
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -2386,6 +2386,30 @@ export interface Singularity {
|
|||||||
* purchased. Throws an error if the specified program/exploit does not exist
|
* purchased. Throws an error if the specified program/exploit does not exist
|
||||||
*/
|
*/
|
||||||
getDarkwebProgramCost(programName: string): number;
|
getDarkwebProgramCost(programName: string): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* b1t_flum3 into a different BN.
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 16 GB * 16/4/1
|
||||||
|
*
|
||||||
|
* @param nextBN - BN number to jump to
|
||||||
|
* @param callbackScript - Name of the script to launch in the next BN.
|
||||||
|
*/
|
||||||
|
b1tflum3(nextBN: number, callbackScript?: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the w0r1d_d43m0n and move on to the next BN.
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 32 GB * 16/4/1
|
||||||
|
*
|
||||||
|
* You must have the special augment installed and the required hacking level
|
||||||
|
* OR
|
||||||
|
* Completed the final black op.
|
||||||
|
*
|
||||||
|
* @param nextBN - BN number to jump to
|
||||||
|
* @param callbackScript - Name of the script to launch in the next BN.
|
||||||
|
*/
|
||||||
|
destroyW0r1dD43m0n(nextBN: number, callbackScript?: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3234,7 +3258,7 @@ export interface CodingContract {
|
|||||||
* Attempts to solve the Coding Contract with the provided solution.
|
* Attempts to solve the Coding Contract with the provided solution.
|
||||||
*
|
*
|
||||||
* @param answer - Solution for the contract.
|
* @param answer - Solution for the contract.
|
||||||
* @param fn - Filename of the contract.
|
* @param filename - Filename of the contract.
|
||||||
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
|
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
|
||||||
* @param opts - Optional parameters for configuring function behavior.
|
* @param opts - Optional parameters for configuring function behavior.
|
||||||
* @returns True if the solution was correct, false otherwise. If the returnReward option is configured, then the function will instead return a string. If the contract is successfully solved, the string will contain a description of the contract’s reward. Otherwise, it will be an empty string.
|
* @returns True if the solution was correct, false otherwise. If the returnReward option is configured, then the function will instead return a string. If the contract is successfully solved, the string will contain a description of the contract’s reward. Otherwise, it will be an empty string.
|
||||||
@ -3249,7 +3273,7 @@ export interface CodingContract {
|
|||||||
* Returns a name describing the type of problem posed by the Coding Contract.
|
* Returns a name describing the type of problem posed by the Coding Contract.
|
||||||
* (e.g. Find Largest Prime Factor, Total Ways to Sum, etc.)
|
* (e.g. Find Largest Prime Factor, Total Ways to Sum, etc.)
|
||||||
*
|
*
|
||||||
* @param fn - Filename of the contract.
|
* @param filename - Filename of the contract.
|
||||||
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
|
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
|
||||||
* @returns Name describing the type of problem posed by the Coding Contract.
|
* @returns Name describing the type of problem posed by the Coding Contract.
|
||||||
*/
|
*/
|
||||||
@ -3262,7 +3286,7 @@ export interface CodingContract {
|
|||||||
*
|
*
|
||||||
* Get the full text description for the problem posed by the Coding Contract.
|
* Get the full text description for the problem posed by the Coding Contract.
|
||||||
*
|
*
|
||||||
* @param fn - Filename of the contract.
|
* @param filename - Filename of the contract.
|
||||||
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
|
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
|
||||||
* @returns Contract’s text description.
|
* @returns Contract’s text description.
|
||||||
*/
|
*/
|
||||||
@ -3290,7 +3314,7 @@ export interface CodingContract {
|
|||||||
*
|
*
|
||||||
* Get the number of tries remaining on the contract before it self-destructs.
|
* Get the number of tries remaining on the contract before it self-destructs.
|
||||||
*
|
*
|
||||||
* @param fn - Filename of the contract.
|
* @param filename - Filename of the contract.
|
||||||
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
|
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
|
||||||
* @returns How many attempts are remaining for the contract;
|
* @returns How many attempts are remaining for the contract;
|
||||||
*/
|
*/
|
||||||
@ -5085,8 +5109,7 @@ export interface NS {
|
|||||||
* PID stands for Process ID. The PID is a unique identifier for each script.
|
* PID stands for Process ID. The PID is a unique identifier for each script.
|
||||||
* The PID will always be a positive integer.
|
* The PID will always be a positive integer.
|
||||||
*
|
*
|
||||||
* Running this function with a numThreads argument of 0 will return 0 without running the script.
|
* Running this function with 0 or a negative numThreads argument will cause a runtime error.
|
||||||
* However, running this function with a negative numThreads argument will cause a runtime error.
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
@ -6737,8 +6760,9 @@ export interface WarehouseAPI {
|
|||||||
* Upgrade warehouse
|
* Upgrade warehouse
|
||||||
* @param divisionName - Name of the division
|
* @param divisionName - Name of the division
|
||||||
* @param cityName - Name of the city
|
* @param cityName - Name of the city
|
||||||
|
* @param amt - amount of upgrades defaults to 1
|
||||||
*/
|
*/
|
||||||
upgradeWarehouse(divisionName: string, cityName: string): void;
|
upgradeWarehouse(divisionName: string, cityName: string, amt?: number): void;
|
||||||
/**
|
/**
|
||||||
* Create a new product
|
* Create a new product
|
||||||
* @param divisionName - Name of the division
|
* @param divisionName - Name of the division
|
||||||
@ -6754,6 +6778,22 @@ export interface WarehouseAPI {
|
|||||||
designInvest: number,
|
designInvest: number,
|
||||||
marketingInvest: number,
|
marketingInvest: number,
|
||||||
): void;
|
): void;
|
||||||
|
/**
|
||||||
|
* Limit Material Production.
|
||||||
|
* @param divisionName - Name of the division
|
||||||
|
* @param cityName - Name of the city
|
||||||
|
* @param materialName - Name of the material
|
||||||
|
* @param qty - Amount to limit to
|
||||||
|
*/
|
||||||
|
limitMaterialProduction(divisionName: string, cityName: string, materialName: string, qty: number): void;
|
||||||
|
/**
|
||||||
|
* Limit Product Production.
|
||||||
|
* @param divisionName - Name of the division
|
||||||
|
* @param cityName - Name of the city
|
||||||
|
* @param productName - Name of the product
|
||||||
|
* @param qty - Amount to limit to
|
||||||
|
*/
|
||||||
|
limitProductProduction(divisionName: string, cityName: string, productName: string, qty: number): void;
|
||||||
/**
|
/**
|
||||||
* Gets the cost to purchase a warehouse
|
* Gets the cost to purchase a warehouse
|
||||||
* @returns cost
|
* @returns cost
|
||||||
@ -6761,9 +6801,12 @@ export interface WarehouseAPI {
|
|||||||
getPurchaseWarehouseCost(): number;
|
getPurchaseWarehouseCost(): number;
|
||||||
/**
|
/**
|
||||||
* Gets the cost to upgrade a warehouse to the next level
|
* Gets the cost to upgrade a warehouse to the next level
|
||||||
|
* @param divisionName - Name of the division
|
||||||
|
* @param cityName - Name of the city
|
||||||
|
* @param amt - amount of upgrades defaults to 1
|
||||||
* @returns cost to upgrade
|
* @returns cost to upgrade
|
||||||
*/
|
*/
|
||||||
getUpgradeWarehouseCost(adivisionName: any, acityName: any): number;
|
getUpgradeWarehouseCost(adivisionName: any, acityName: any, amt?: number): number;
|
||||||
/**
|
/**
|
||||||
* Check if you have a warehouse in city
|
* Check if you have a warehouse in city
|
||||||
* @returns true if warehouse is present, false if not
|
* @returns true if warehouse is present, false if not
|
||||||
@ -7007,8 +7050,10 @@ interface Material {
|
|||||||
cmp: number | undefined;
|
cmp: number | undefined;
|
||||||
/** Amount of material produced */
|
/** Amount of material produced */
|
||||||
prod: number;
|
prod: number;
|
||||||
/** Amount of material sold */
|
/** Amount of material sold */
|
||||||
sell: number;
|
sell: number;
|
||||||
|
/** cost to buy material */
|
||||||
|
cost: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,6 +9,10 @@ import Select from "@mui/material/Select";
|
|||||||
import Switch from "@mui/material/Switch";
|
import Switch from "@mui/material/Switch";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
|
import EditIcon from "@mui/icons-material/Edit";
|
||||||
|
import SaveIcon from "@mui/icons-material/Save";
|
||||||
|
|
||||||
|
import { ThemeEditorModal } from "./ThemeEditorModal";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
options: Options;
|
options: Options;
|
||||||
@ -23,6 +27,7 @@ export function OptionsModal(props: IProps): React.ReactElement {
|
|||||||
const [fontSize, setFontSize] = useState(props.options.fontSize);
|
const [fontSize, setFontSize] = useState(props.options.fontSize);
|
||||||
const [wordWrap, setWordWrap] = useState(props.options.wordWrap);
|
const [wordWrap, setWordWrap] = useState(props.options.wordWrap);
|
||||||
const [vim, setVim] = useState(props.options.vim);
|
const [vim, setVim] = useState(props.options.vim);
|
||||||
|
const [themeEditorOpen, setThemeEditorOpen] = useState(false);
|
||||||
|
|
||||||
function save(): void {
|
function save(): void {
|
||||||
props.save({
|
props.save({
|
||||||
@ -43,6 +48,7 @@ export function OptionsModal(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={props.open} onClose={props.onClose}>
|
<Modal open={props.open} onClose={props.onClose}>
|
||||||
|
<ThemeEditorModal open={themeEditorOpen} onClose={() => setThemeEditorOpen(false)} />
|
||||||
<Box display="flex" flexDirection="row" alignItems="center">
|
<Box display="flex" flexDirection="row" alignItems="center">
|
||||||
<Typography>Theme: </Typography>
|
<Typography>Theme: </Typography>
|
||||||
<Select onChange={(event) => setTheme(event.target.value)} value={theme}>
|
<Select onChange={(event) => setTheme(event.target.value)} value={theme}>
|
||||||
@ -53,7 +59,11 @@ export function OptionsModal(props: IProps): React.ReactElement {
|
|||||||
<MenuItem value="light">light</MenuItem>
|
<MenuItem value="light">light</MenuItem>
|
||||||
<MenuItem value="dracula">dracula</MenuItem>
|
<MenuItem value="dracula">dracula</MenuItem>
|
||||||
<MenuItem value="one-dark">one-dark</MenuItem>
|
<MenuItem value="one-dark">one-dark</MenuItem>
|
||||||
|
<MenuItem value="customTheme">Custom theme</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
|
<Button onClick={() => setThemeEditorOpen(true)} sx={{ mx: 1 }} startIcon={<EditIcon />}>
|
||||||
|
Edit custom theme
|
||||||
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box display="flex" flexDirection="row" alignItems="center">
|
<Box display="flex" flexDirection="row" alignItems="center">
|
||||||
@ -80,7 +90,9 @@ export function OptionsModal(props: IProps): React.ReactElement {
|
|||||||
<TextField type="number" label="Font size" value={fontSize} onChange={onFontChange} />
|
<TextField type="number" label="Font size" value={fontSize} onChange={onFontChange} />
|
||||||
</Box>
|
</Box>
|
||||||
<br />
|
<br />
|
||||||
<Button onClick={save}>Save</Button>
|
<Button onClick={save} startIcon={<SaveIcon />}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import { Settings } from "../../Settings/Settings";
|
|||||||
import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial";
|
import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial";
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import { saveObject } from "../../SaveObject";
|
import { saveObject } from "../../SaveObject";
|
||||||
import { loadThemes } from "./themes";
|
import { loadThemes, makeTheme, sanitizeTheme } from "./themes";
|
||||||
import { GetServer } from "../../Server/AllServers";
|
import { GetServer } from "../../Server/AllServers";
|
||||||
|
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -362,6 +362,8 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, "netscript.d.ts");
|
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, "netscript.d.ts");
|
||||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, "netscript.d.ts");
|
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, "netscript.d.ts");
|
||||||
loadThemes(monaco);
|
loadThemes(monaco);
|
||||||
|
sanitizeTheme(Settings.EditorTheme);
|
||||||
|
monaco.editor.defineTheme("customTheme", makeTheme(Settings.EditorTheme));
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the editor is mounted
|
// When the editor is mounted
|
||||||
@ -993,7 +995,11 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
</Box>
|
</Box>
|
||||||
<OptionsModal
|
<OptionsModal
|
||||||
open={optionsOpen}
|
open={optionsOpen}
|
||||||
onClose={() => setOptionsOpen(false)}
|
onClose={() => {
|
||||||
|
sanitizeTheme(Settings.EditorTheme);
|
||||||
|
monacoRef.current?.editor.defineTheme("customTheme", makeTheme(Settings.EditorTheme));
|
||||||
|
setOptionsOpen(false);
|
||||||
|
}}
|
||||||
options={{
|
options={{
|
||||||
theme: Settings.MonacoTheme,
|
theme: Settings.MonacoTheme,
|
||||||
insertSpaces: Settings.MonacoInsertSpaces,
|
insertSpaces: Settings.MonacoInsertSpaces,
|
||||||
@ -1002,6 +1008,8 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
vim: Settings.MonacoVim,
|
vim: Settings.MonacoVim,
|
||||||
}}
|
}}
|
||||||
save={(options: Options) => {
|
save={(options: Options) => {
|
||||||
|
sanitizeTheme(Settings.EditorTheme);
|
||||||
|
monacoRef.current?.editor.defineTheme("customTheme", makeTheme(Settings.EditorTheme));
|
||||||
setOptions(options);
|
setOptions(options);
|
||||||
Settings.MonacoTheme = options.theme;
|
Settings.MonacoTheme = options.theme;
|
||||||
Settings.MonacoInsertSpaces = options.insertSpaces;
|
Settings.MonacoInsertSpaces = options.insertSpaces;
|
||||||
|
276
src/ScriptEditor/ui/ThemeEditorModal.tsx
Normal file
276
src/ScriptEditor/ui/ThemeEditorModal.tsx
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
import { History, Reply, Save } from "@mui/icons-material";
|
||||||
|
import { Box, Button, Paper, TextField, Tooltip, Typography } from "@mui/material";
|
||||||
|
import IconButton from "@mui/material/IconButton";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { Color, ColorPicker } from "material-ui-color";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Settings } from "../../Settings/Settings";
|
||||||
|
import { Modal } from "../../ui/React/Modal";
|
||||||
|
import { OptionSwitch } from "../../ui/React/OptionSwitch";
|
||||||
|
import { defaultMonacoTheme, IScriptEditorTheme } from "./themes";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
onClose: () => void;
|
||||||
|
open: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IColorEditorProps {
|
||||||
|
label: string;
|
||||||
|
themePath: string;
|
||||||
|
color: string | undefined;
|
||||||
|
onColorChange: (name: string, value: string) => void;
|
||||||
|
defaultColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slightly tweaked version of the same function found in game options
|
||||||
|
function ColorEditor({ label, themePath, onColorChange, color, defaultColor }: IColorEditorProps): React.ReactElement {
|
||||||
|
if (color === undefined) {
|
||||||
|
console.error(`color ${themePath} was undefined, reverting to default`);
|
||||||
|
color = defaultColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Tooltip title={label}>
|
||||||
|
<span>
|
||||||
|
<TextField
|
||||||
|
label={themePath}
|
||||||
|
value={"#" + color}
|
||||||
|
sx={{ display: "block", my: 1 }}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: (
|
||||||
|
<>
|
||||||
|
<ColorPicker
|
||||||
|
hideTextfield
|
||||||
|
deferred
|
||||||
|
value={"#" + color}
|
||||||
|
onChange={(newColor: Color) => onColorChange(themePath, newColor.hex)}
|
||||||
|
disableAlpha
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
endAdornment: (
|
||||||
|
<>
|
||||||
|
<IconButton onClick={() => onColorChange(themePath, defaultColor)}>
|
||||||
|
<Reply color="primary" />
|
||||||
|
</IconButton>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ThemeEditorModal(props: IProps): React.ReactElement {
|
||||||
|
const setRerender = useState(false)[1];
|
||||||
|
function rerender(): void {
|
||||||
|
setRerender((o) => !o);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to deep copy the object since it has nested attributes
|
||||||
|
const [themeCopy, setThemeCopy] = useState<IScriptEditorTheme>(JSON.parse(JSON.stringify(Settings.EditorTheme)));
|
||||||
|
|
||||||
|
function onColorChange(name: string, value: string): void {
|
||||||
|
setThemeCopy(_.set(themeCopy, name, value));
|
||||||
|
rerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onThemeChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
|
try {
|
||||||
|
const importedTheme = JSON.parse(event.target.value);
|
||||||
|
if (typeof importedTheme !== "object") return;
|
||||||
|
setThemeCopy(importedTheme);
|
||||||
|
} catch (err) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={props.open}
|
||||||
|
onClose={() => {
|
||||||
|
setThemeCopy(Settings.EditorTheme);
|
||||||
|
props.onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h4">Customize Editor theme</Typography>
|
||||||
|
<Typography>Hover over input boxes for more information</Typography>
|
||||||
|
<Paper sx={{ p: 1, my: 1 }}>
|
||||||
|
<OptionSwitch
|
||||||
|
checked={themeCopy.base === "vs"}
|
||||||
|
onChange={(val) => {
|
||||||
|
setThemeCopy(_.set(themeCopy, "base", val ? "vs" : "vs-dark"));
|
||||||
|
rerender();
|
||||||
|
}}
|
||||||
|
text="Use light theme as base"
|
||||||
|
tooltip={
|
||||||
|
<>
|
||||||
|
If enabled, the <code>vs</code> light theme will be used as the theme base, otherwise,{" "}
|
||||||
|
<code>vs-dark</code> will be used.
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "fit-content", gap: 1 }}>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h6">UI</Typography>
|
||||||
|
<ColorEditor
|
||||||
|
label="Background color"
|
||||||
|
themePath="common.bg"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.common.bg}
|
||||||
|
defaultColor={defaultMonacoTheme.common.bg}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Current line and minimap background color"
|
||||||
|
themePath="ui.line"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.ui.line}
|
||||||
|
defaultColor={defaultMonacoTheme.ui.line}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Base text color"
|
||||||
|
themePath="common.fg"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.common.fg}
|
||||||
|
defaultColor={defaultMonacoTheme.common.fg}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Popup background color"
|
||||||
|
themePath="ui.panel.bg"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.ui.panel.bg}
|
||||||
|
defaultColor={defaultMonacoTheme.ui.panel.bg}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Background color for selected item in popup"
|
||||||
|
themePath="ui.panel.selected"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.ui.panel.selected}
|
||||||
|
defaultColor={defaultMonacoTheme.ui.panel.selected}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Popup border color"
|
||||||
|
themePath="ui.panel.border"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.ui.panel.border}
|
||||||
|
defaultColor={defaultMonacoTheme.ui.panel.border}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Background color of highlighted text"
|
||||||
|
themePath="ui.selection.bg"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.ui.selection.bg}
|
||||||
|
defaultColor={defaultMonacoTheme.ui.selection.bg}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h6">Syntax</Typography>
|
||||||
|
<ColorEditor
|
||||||
|
label="Numbers, function names, and other key vars"
|
||||||
|
themePath="common.accent"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.common.accent}
|
||||||
|
defaultColor={defaultMonacoTheme.common.accent}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Keywords"
|
||||||
|
themePath="syntax.keyword"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.keyword}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.keyword}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Strings"
|
||||||
|
themePath="syntax.string"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.string}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.string}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Regexp literals as well as escapes within strings"
|
||||||
|
themePath="syntax.regexp"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.regexp}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.regexp}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Constants"
|
||||||
|
themePath="syntax.constant"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.constant}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.constant}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Entities"
|
||||||
|
themePath="syntax.entity"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.entity}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.entity}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="'this', 'ns', types, and tags"
|
||||||
|
themePath="syntax.tag"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.tag}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.tag}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Netscript functions and constructors"
|
||||||
|
themePath="syntax.markup"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.markup}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.markup}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Errors"
|
||||||
|
themePath="syntax.error"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.error}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.error}
|
||||||
|
/>
|
||||||
|
<ColorEditor
|
||||||
|
label="Comments"
|
||||||
|
themePath="syntax.comment"
|
||||||
|
onColorChange={onColorChange}
|
||||||
|
color={themeCopy.syntax.comment}
|
||||||
|
defaultColor={defaultMonacoTheme.syntax.comment}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
<Paper sx={{ p: 1 }}>
|
||||||
|
<TextField
|
||||||
|
multiline
|
||||||
|
fullWidth
|
||||||
|
maxRows={10}
|
||||||
|
label={"import / export theme"}
|
||||||
|
value={JSON.stringify(themeCopy, undefined, 2)}
|
||||||
|
onChange={onThemeChange}
|
||||||
|
/>
|
||||||
|
<Box sx={{ mt: 1 }}>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
Settings.EditorTheme = { ...themeCopy };
|
||||||
|
props.onClose();
|
||||||
|
}}
|
||||||
|
startIcon={<Save />}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setThemeCopy(defaultMonacoTheme);
|
||||||
|
rerender();
|
||||||
|
}}
|
||||||
|
startIcon={<History />}
|
||||||
|
>
|
||||||
|
Reset to default
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
@ -1,3 +1,216 @@
|
|||||||
|
export interface IScriptEditorTheme {
|
||||||
|
[key: string]: any;
|
||||||
|
base: string;
|
||||||
|
inherit: boolean;
|
||||||
|
common: {
|
||||||
|
[key: string]: string;
|
||||||
|
accent: string;
|
||||||
|
bg: string;
|
||||||
|
fg: string;
|
||||||
|
};
|
||||||
|
syntax: {
|
||||||
|
[key: string]: string;
|
||||||
|
tag: string;
|
||||||
|
entity: string;
|
||||||
|
string: string;
|
||||||
|
regexp: string;
|
||||||
|
markup: string;
|
||||||
|
keyword: string;
|
||||||
|
comment: string;
|
||||||
|
constant: string;
|
||||||
|
error: string;
|
||||||
|
};
|
||||||
|
ui: {
|
||||||
|
[key: string]: any;
|
||||||
|
line: string;
|
||||||
|
panel: {
|
||||||
|
[key: string]: string;
|
||||||
|
bg: string;
|
||||||
|
selected: string;
|
||||||
|
border: string;
|
||||||
|
};
|
||||||
|
selection: {
|
||||||
|
[key: string]: string;
|
||||||
|
bg: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultMonacoTheme: IScriptEditorTheme = {
|
||||||
|
base: "vs-dark",
|
||||||
|
inherit: true,
|
||||||
|
common: {
|
||||||
|
accent: "B5CEA8",
|
||||||
|
bg: "1E1E1E",
|
||||||
|
fg: "D4D4D4",
|
||||||
|
},
|
||||||
|
syntax: {
|
||||||
|
tag: "569CD6",
|
||||||
|
entity: "569CD6",
|
||||||
|
string: "CE9178",
|
||||||
|
regexp: "646695",
|
||||||
|
markup: "569CD6",
|
||||||
|
keyword: "569CD6",
|
||||||
|
comment: "6A9955",
|
||||||
|
constant: "569CD6",
|
||||||
|
error: "F44747",
|
||||||
|
},
|
||||||
|
ui: {
|
||||||
|
line: "1E1E1E",
|
||||||
|
panel: {
|
||||||
|
bg: "252526",
|
||||||
|
selected: "252526",
|
||||||
|
border: "1E1E1E",
|
||||||
|
},
|
||||||
|
selection: {
|
||||||
|
bg: "ADD6FF26",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Regex used for token color validation
|
||||||
|
// https://github.com/microsoft/vscode/blob/973684056e67153952f495fce93bf50d0ec0b892/src/vs/editor/common/languages/supports/tokenization.ts#L153
|
||||||
|
const colorRegExp = /^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/;
|
||||||
|
|
||||||
|
// Recursively sanitize the theme data to prevent errors
|
||||||
|
// Invalid data will be replaced with FF0000 (bright red)
|
||||||
|
export const sanitizeTheme = (theme: IScriptEditorTheme): void => {
|
||||||
|
for (const [k, v] of Object.entries(theme)) {
|
||||||
|
switch (k) {
|
||||||
|
case "base":
|
||||||
|
if (!["vs-dark", "vs"].includes(theme.base)) theme.base = "vs-dark";
|
||||||
|
continue;
|
||||||
|
case "inherit":
|
||||||
|
if (typeof theme.inherit !== "boolean") theme.inherit = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const repairBlock = (block: { [key: string]: any }): void => {
|
||||||
|
for (const [k, v] of Object.entries(block)) {
|
||||||
|
if (typeof v === "object") {
|
||||||
|
repairBlock(v as { [key: string]: string });
|
||||||
|
} else if (!v.match(colorRegExp)) block[k] = "FF0000";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
repairBlock(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function makeTheme(theme: IScriptEditorTheme): any {
|
||||||
|
const themeRules = [
|
||||||
|
{
|
||||||
|
token: "",
|
||||||
|
background: theme.ui.line,
|
||||||
|
foreground: theme.common.fg,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "identifier",
|
||||||
|
foreground: theme.common.accent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "keyword",
|
||||||
|
foreground: theme.syntax.keyword,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "string",
|
||||||
|
foreground: theme.syntax.string,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "string.escape",
|
||||||
|
foreground: theme.syntax.regexp,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "comment",
|
||||||
|
foreground: theme.syntax.comment,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "constant",
|
||||||
|
foreground: theme.syntax.constant,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "entity",
|
||||||
|
foreground: theme.syntax.entity,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "type",
|
||||||
|
foreground: theme.syntax.tag,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "tag",
|
||||||
|
foreground: theme.syntax.tag,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "regexp",
|
||||||
|
foreground: theme.syntax.regexp,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "attribute",
|
||||||
|
foreground: theme.syntax.tag,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "constructor",
|
||||||
|
foreground: theme.syntax.markup,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "invalid",
|
||||||
|
foreground: theme.syntax.error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "number",
|
||||||
|
foreground: theme.common.accent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "delimiter",
|
||||||
|
foreground: theme.common.fg,
|
||||||
|
},
|
||||||
|
// Custom tokens
|
||||||
|
{
|
||||||
|
token: "ns",
|
||||||
|
foreground: theme.syntax.tag,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "netscriptfunction",
|
||||||
|
foreground: theme.syntax.markup,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "otherkeywords",
|
||||||
|
foreground: theme.syntax.keyword,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "otherkeyvars",
|
||||||
|
foreground: theme.common.accent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "this",
|
||||||
|
foreground: theme.syntax.tag,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const themeColors = Object.fromEntries(
|
||||||
|
[
|
||||||
|
["editor.background", theme.common.bg],
|
||||||
|
["editor.foreground", theme.common.fg],
|
||||||
|
["editor.lineHighlightBackground", theme.ui.line],
|
||||||
|
["editor.selectionBackground", theme.ui.selection.bg],
|
||||||
|
|
||||||
|
["editorSuggestWidget.background", theme.ui.panel.bg],
|
||||||
|
["editorSuggestWidget.border", theme.ui.panel.border],
|
||||||
|
["editorSuggestWidget.selectedBackground", theme.ui.panel.selected],
|
||||||
|
|
||||||
|
["editorHoverWidget.background", theme.ui.panel.bg],
|
||||||
|
["editorHoverWidget.border", theme.ui.panel.border],
|
||||||
|
|
||||||
|
["editorWidget.background", theme.ui.panel.bg],
|
||||||
|
["editorWidget.border", theme.ui.panel.border],
|
||||||
|
|
||||||
|
["input.background", theme.ui.panel.bg],
|
||||||
|
["input.border", theme.ui.panel.border],
|
||||||
|
].map(([k, v]) => [k, "#" + v]),
|
||||||
|
);
|
||||||
|
|
||||||
|
return { base: theme.base, inherit: theme.inherit, rules: themeRules, colors: themeColors };
|
||||||
|
}
|
||||||
|
|
||||||
export async function loadThemes(monaco: { editor: any }): Promise<void> {
|
export async function loadThemes(monaco: { editor: any }): Promise<void> {
|
||||||
monaco.editor.defineTheme("monokai", {
|
monaco.editor.defineTheme("monokai", {
|
||||||
base: "vs-dark",
|
base: "vs-dark",
|
||||||
@ -261,6 +474,7 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
|
|||||||
foreground: "FFB86C",
|
foreground: "FFB86C",
|
||||||
fontStyle: "italic",
|
fontStyle: "italic",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
token: "netscriptfunction",
|
token: "netscriptfunction",
|
||||||
foreground: "FF79C6",
|
foreground: "FF79C6",
|
||||||
|
@ -5,6 +5,7 @@ import { defaultStyles } from "../Themes/Styles";
|
|||||||
import { WordWrapOptions } from "../ScriptEditor/ui/Options";
|
import { WordWrapOptions } from "../ScriptEditor/ui/Options";
|
||||||
import { OverviewSettings } from "../ui/React/Overview";
|
import { OverviewSettings } from "../ui/React/Overview";
|
||||||
import { IStyleSettings } from "../ScriptEditor/NetscriptDefinitions";
|
import { IStyleSettings } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
|
import { defaultMonacoTheme, IScriptEditorTheme } from "../ScriptEditor/ui/themes";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the default settings the player could customize.
|
* Represents the default settings the player could customize.
|
||||||
@ -157,6 +158,11 @@ interface IDefaultSettings {
|
|||||||
* If the game's sidebar is opened
|
* If the game's sidebar is opened
|
||||||
*/
|
*/
|
||||||
IsSidebarOpened: boolean;
|
IsSidebarOpened: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script editor theme data
|
||||||
|
*/
|
||||||
|
EditorTheme: IScriptEditorTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,6 +222,8 @@ export const defaultSettings: IDefaultSettings = {
|
|||||||
theme: defaultTheme,
|
theme: defaultTheme,
|
||||||
styles: defaultStyles,
|
styles: defaultStyles,
|
||||||
overview: { x: 0, y: 0, opened: true },
|
overview: { x: 0, y: 0, opened: true },
|
||||||
|
|
||||||
|
EditorTheme: defaultMonacoTheme,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,6 +270,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
|||||||
theme: { ...defaultTheme },
|
theme: { ...defaultTheme },
|
||||||
styles: { ...defaultStyles },
|
styles: { ...defaultStyles },
|
||||||
overview: defaultSettings.overview,
|
overview: defaultSettings.overview,
|
||||||
|
EditorTheme: { ...defaultMonacoTheme },
|
||||||
init() {
|
init() {
|
||||||
Object.assign(Settings, defaultSettings);
|
Object.assign(Settings, defaultSettings);
|
||||||
},
|
},
|
||||||
@ -273,6 +282,8 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
|||||||
delete save.styles;
|
delete save.styles;
|
||||||
Object.assign(Settings.overview, save.overview);
|
Object.assign(Settings.overview, save.overview);
|
||||||
delete save.overview;
|
delete save.overview;
|
||||||
|
Object.assign(Settings.EditorTheme, save.EditorTheme);
|
||||||
|
delete save.EditorTheme;
|
||||||
Object.assign(Settings, save);
|
Object.assign(Settings, save);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
// Contains an array containing information about the player's source files
|
|
||||||
// Array[n] returns what level the player has of Source-File N.
|
|
||||||
|
|
||||||
import { CONSTANTS } from "../Constants";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
export const SourceFileFlags: number[] = Array(CONSTANTS.TotalNumBitNodes + 1); // Skip index 0
|
|
||||||
|
|
||||||
export function updateSourceFileFlags(p: IPlayer): void {
|
|
||||||
for (let i = 0; i < SourceFileFlags.length; ++i) {
|
|
||||||
SourceFileFlags[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < p.sourceFiles.length; ++i) {
|
|
||||||
const sf = p.sourceFiles[i];
|
|
||||||
SourceFileFlags[sf.n] = sf.lvl;
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ import { OrderTypes } from "../data/OrderTypes";
|
|||||||
import { PositionTypes } from "../data/PositionTypes";
|
import { PositionTypes } from "../data/PositionTypes";
|
||||||
|
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
|
|
||||||
@ -288,12 +287,12 @@ export function StockTicker(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
// Whether the player has access to orders besides market orders (limit/stop)
|
// Whether the player has access to orders besides market orders (limit/stop)
|
||||||
function hasOrderAccess(): boolean {
|
function hasOrderAccess(): boolean {
|
||||||
return props.p.bitNodeN === 8 || SourceFileFlags[8] >= 3;
|
return props.p.bitNodeN === 8 || props.p.sourceFileLvl(8) >= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether the player has access to shorting stocks
|
// Whether the player has access to shorting stocks
|
||||||
function hasShortAccess(): boolean {
|
function hasShortAccess(): boolean {
|
||||||
return props.p.bitNodeN === 8 || SourceFileFlags[8] >= 2;
|
return props.p.bitNodeN === 8 || props.p.sourceFileLvl(8) >= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -9,7 +9,6 @@ import { Stock } from "../Stock";
|
|||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
@ -67,7 +66,7 @@ function ShortPosition(props: IProps): React.ReactElement {
|
|||||||
percentageGains = 0;
|
percentageGains = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.p.bitNodeN === 8 || SourceFileFlags[8] >= 2) {
|
if (props.p.bitNodeN === 8 || props.p.sourceFileLvl(8) >= 2) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box display="flex">
|
<Box display="flex">
|
||||||
|
@ -366,9 +366,9 @@ export function ThemeEditorModal(props: IProps): React.ReactElement {
|
|||||||
sx={{ mb: 1 }}
|
sx={{ mb: 1 }}
|
||||||
multiline
|
multiline
|
||||||
fullWidth
|
fullWidth
|
||||||
maxRows={3}
|
maxRows={10}
|
||||||
label={"import / export theme"}
|
label={"import / export theme"}
|
||||||
value={JSON.stringify(customTheme)}
|
value={JSON.stringify(customTheme, undefined, 2)}
|
||||||
onChange={onThemeChange}
|
onChange={onThemeChange}
|
||||||
/>
|
/>
|
||||||
<>
|
<>
|
||||||
|
@ -1121,14 +1121,17 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
|||||||
|
|
||||||
dfs(0, 0, left, right, data, "", res);
|
dfs(0, 0, left, right, data, "", res);
|
||||||
|
|
||||||
const sanitizedPlayerAns = removeBracketsFromArrayString(ans).replace(/\s/g, "");
|
const sanitizedPlayerAns: string = removeBracketsFromArrayString(ans);
|
||||||
|
const sanitizedPlayerAnsArr: string[] = sanitizedPlayerAns.split(",");
|
||||||
|
for (let i = 0; i < sanitizedPlayerAnsArr.length; ++i) {
|
||||||
|
sanitizedPlayerAnsArr[i] = removeQuotesFromString(sanitizedPlayerAnsArr[i]).replace(/\s/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
const playerAnsArray: string[] = sanitizedPlayerAns.split(",");
|
if (sanitizedPlayerAnsArr.length !== res.length) {
|
||||||
if (playerAnsArray.length !== res.length) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (const resultInAnswer of res) {
|
for (const resultInAnswer of res) {
|
||||||
if (!playerAnsArray.includes(resultInAnswer)) {
|
if (!sanitizedPlayerAnsArr.includes(resultInAnswer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
* Game engine. Handles the main game loop.
|
* Game engine. Handles the main game loop.
|
||||||
*/
|
*/
|
||||||
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
||||||
import { Augmentations } from "./Augmentation/Augmentations";
|
|
||||||
import { initAugmentations } from "./Augmentation/AugmentationHelpers";
|
import { initAugmentations } from "./Augmentation/AugmentationHelpers";
|
||||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||||
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
||||||
@ -32,7 +31,6 @@ import { saveObject, loadGame } from "./SaveObject";
|
|||||||
import { initForeignServers } from "./Server/AllServers";
|
import { initForeignServers } from "./Server/AllServers";
|
||||||
import { Settings } from "./Settings/Settings";
|
import { Settings } from "./Settings/Settings";
|
||||||
import { ThemeEvents } from "./Themes/ui/Theme";
|
import { ThemeEvents } from "./Themes/ui/Theme";
|
||||||
import { updateSourceFileFlags } from "./SourceFile/SourceFileFlags";
|
|
||||||
import { initSymbolToStockMap, processStockPrices } from "./StockMarket/StockMarket";
|
import { initSymbolToStockMap, processStockPrices } from "./StockMarket/StockMarket";
|
||||||
import { Terminal } from "./Terminal";
|
import { Terminal } from "./Terminal";
|
||||||
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
||||||
@ -256,7 +254,6 @@ const Engine: {
|
|||||||
ThemeEvents.emit();
|
ThemeEvents.emit();
|
||||||
|
|
||||||
initBitNodeMultipliers(Player);
|
initBitNodeMultipliers(Player);
|
||||||
updateSourceFileFlags(Player);
|
|
||||||
initAugmentations(); // Also calls Player.reapplyAllAugmentations()
|
initAugmentations(); // Also calls Player.reapplyAllAugmentations()
|
||||||
Player.reapplyAllSourceFiles();
|
Player.reapplyAllSourceFiles();
|
||||||
if (Player.hasWseAccount) {
|
if (Player.hasWseAccount) {
|
||||||
@ -439,7 +436,6 @@ const Engine: {
|
|||||||
initCompanies();
|
initCompanies();
|
||||||
initFactions();
|
initFactions();
|
||||||
initAugmentations();
|
initAugmentations();
|
||||||
updateSourceFileFlags(Player);
|
|
||||||
|
|
||||||
// Start interactive tutorial
|
// Start interactive tutorial
|
||||||
iTutorialStart();
|
iTutorialStart();
|
||||||
|
@ -6,7 +6,6 @@ import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
|||||||
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
||||||
import { getPurchaseServerLimit } from "../Server/ServerPurchases";
|
import { getPurchaseServerLimit } from "../Server/ServerPurchases";
|
||||||
import { Settings } from "../Settings/Settings";
|
import { Settings } from "../Settings/Settings";
|
||||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
|
||||||
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
|
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
|
||||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||||
import { use } from "./Context";
|
import { use } from "./Context";
|
||||||
@ -44,6 +43,7 @@ interface MultTableProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function MultiplierTable(props: MultTableProps): React.ReactElement {
|
function MultiplierTable(props: MultTableProps): React.ReactElement {
|
||||||
|
const player = use.Player();
|
||||||
return (
|
return (
|
||||||
<Table sx={{ display: "table", width: "100%", mb: (props.noMargin ?? false) === true ? 0 : 2 }}>
|
<Table sx={{ display: "table", width: "100%", mb: (props.noMargin ?? false) === true ? 0 : 2 }}>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
@ -52,7 +52,7 @@ function MultiplierTable(props: MultTableProps): React.ReactElement {
|
|||||||
value = data[1] as number,
|
value = data[1] as number,
|
||||||
modded = data[2] as number | null;
|
modded = data[2] as number | null;
|
||||||
|
|
||||||
if (modded && modded !== value && SourceFileFlags[5] > 0) {
|
if (modded && modded !== value && player.sourceFileLvl(5) > 0) {
|
||||||
return (
|
return (
|
||||||
<StatsRow key={mult} name={mult} color={props.color} data={{}}>
|
<StatsRow key={mult} name={mult} color={props.color} data={{}}>
|
||||||
<>
|
<>
|
||||||
@ -88,7 +88,7 @@ function CurrentBitNode(): React.ReactElement {
|
|||||||
<Box>
|
<Box>
|
||||||
<Paper sx={{ p: 1 }}>
|
<Paper sx={{ p: 1 }}>
|
||||||
<Typography variant="h5">
|
<Typography variant="h5">
|
||||||
BitNode {player.bitNodeN}: {BitNodes[index].name} (Level {lvl})
|
BitNode {player.bitNodeN}: {BitNodes[index].name} (Level {lvl + 1})
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography sx={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>{BitNodes[index].info}</Typography>
|
<Typography sx={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>{BitNodes[index].info}</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
@ -270,11 +270,13 @@ export function CharacterStats(): React.ReactElement {
|
|||||||
data={{ content: `${player.purchasedServers.length} / ${getPurchaseServerLimit()}` }}
|
data={{ content: `${player.purchasedServers.length} / ${getPurchaseServerLimit()}` }}
|
||||||
/>
|
/>
|
||||||
<StatsRow
|
<StatsRow
|
||||||
name={`Hacknet ${player.bitNodeN === 9 || SourceFileFlags[9] > 0 ? "Servers" : "Nodes"} owned`}
|
name={`Hacknet ${player.bitNodeN === 9 || player.sourceFileLvl(9) > 0 ? "Servers" : "Nodes"} owned`}
|
||||||
color={Settings.theme.primary}
|
color={Settings.theme.primary}
|
||||||
data={{
|
data={{
|
||||||
content: `${player.hacknetNodes.length}${
|
content: `${player.hacknetNodes.length}${
|
||||||
player.bitNodeN === 9 || SourceFileFlags[9] > 0 ? ` / ${HacknetServerConstants.MaxServers}` : ""
|
player.bitNodeN === 9 || player.sourceFileLvl(9) > 0
|
||||||
|
? ` / ${HacknetServerConstants.MaxServers}`
|
||||||
|
: ""
|
||||||
}`,
|
}`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -320,7 +322,7 @@ export function CharacterStats(): React.ReactElement {
|
|||||||
color={Settings.theme.cha}
|
color={Settings.theme.cha}
|
||||||
data={{ level: player.charisma, exp: player.charisma_exp }}
|
data={{ level: player.charisma, exp: player.charisma_exp }}
|
||||||
/>
|
/>
|
||||||
{player.intelligence > 0 && (player.bitNodeN === 5 || SourceFileFlags[5] > 0) && (
|
{player.intelligence > 0 && (player.bitNodeN === 5 || player.sourceFileLvl(5) > 0) && (
|
||||||
<StatsRow
|
<StatsRow
|
||||||
name="Intelligence"
|
name="Intelligence"
|
||||||
color={Settings.theme.int}
|
color={Settings.theme.int}
|
||||||
@ -335,7 +337,7 @@ export function CharacterStats(): React.ReactElement {
|
|||||||
<Paper sx={{ p: 1 }}>
|
<Paper sx={{ p: 1 }}>
|
||||||
<Typography variant="h5" color="primary" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
<Typography variant="h5" color="primary" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
||||||
Multipliers
|
Multipliers
|
||||||
{SourceFileFlags[5] > 0 && (
|
{player.sourceFileLvl(5) > 0 && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
<Typography>
|
<Typography>
|
||||||
|
@ -167,6 +167,7 @@ module.exports = (env, argv) => {
|
|||||||
options: {
|
options: {
|
||||||
name: "[contenthash].[ext]",
|
name: "[contenthash].[ext]",
|
||||||
outputPath: "images",
|
outputPath: "images",
|
||||||
|
publicPath: `${outputDirectory}/images`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
Loading…
Reference in New Issue
Block a user