mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-27 01:53:48 +01:00
merge base
This commit is contained in:
commit
9c23fc89d1
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
|
||||||
|
16
dist/bitburner.d.ts
vendored
16
dist/bitburner.d.ts
vendored
@ -1773,6 +1773,18 @@ export declare interface Grafting {
|
|||||||
*/
|
*/
|
||||||
getAugmentationGraftTime(augName: string): number;
|
getAugmentationGraftTime(augName: string): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of Augmentations that can be grafted.
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 5 GB
|
||||||
|
*
|
||||||
|
* Note that this function returns a list of currently graftable Augmentations,
|
||||||
|
* based off of the Augmentations that you already own.
|
||||||
|
*
|
||||||
|
* @returns An array of graftable Augmentations.
|
||||||
|
*/
|
||||||
|
getGraftableAugmentations(): string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins grafting the named aug. You must be in New Tokyo to use this.
|
* Begins grafting the named aug. You must be in New Tokyo to use this.
|
||||||
* @remarks
|
* @remarks
|
||||||
@ -2911,9 +2923,11 @@ export declare interface NS {
|
|||||||
* Returns the security increase that would occur if a grow with this many threads happened.
|
* Returns the security increase that would occur if a grow with this many threads happened.
|
||||||
*
|
*
|
||||||
* @param threads - Amount of threads that will be used.
|
* @param threads - Amount of threads that will be used.
|
||||||
|
* @param hostname - Optional. Hostname of the target server. The number of threads is limited to the number needed to hack the servers maximum amount of money.
|
||||||
|
* @param cores - Optional. The number of cores of the server that would run grow.
|
||||||
* @returns The security increase.
|
* @returns The security increase.
|
||||||
*/
|
*/
|
||||||
growthAnalyzeSecurity(threads: number): number;
|
growthAnalyzeSecurity(threads: number, hostname?: string, cores?: number): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Suspends the script for n milliseconds.
|
* Suspends the script for n milliseconds.
|
||||||
|
4
dist/main.bundle.js
vendored
4
dist/main.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/main.bundle.js.map
vendored
2
dist/main.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
40
dist/vendor.bundle.js
vendored
40
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/vendor.bundle.js.map
vendored
2
dist/vendor.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
@ -66,7 +66,7 @@ documentation_title = '{0} Documentation'.format(project)
|
|||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '1.6'
|
version = '1.6'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '1.6.3'
|
release = '1.6.4'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
@ -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);
|
|
||||||
}
|
|
4
electron/package-lock.json
generated
4
electron/package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"version": "1.6.3",
|
"version": "1.6.4",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"version": "1.6.3",
|
"version": "1.6.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron-config": "^2.0.0",
|
"electron-config": "^2.0.0",
|
||||||
"electron-log": "^4.4.4",
|
"electron-log": "^4.4.4",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"version": "1.6.3",
|
"version": "1.6.4",
|
||||||
"description": "A cyberpunk-themed programming incremental game",
|
"description": "A cyberpunk-themed programming incremental game",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"author": "Daniel Xie & Olivier Gagnon",
|
"author": "Daniel Xie & Olivier Gagnon",
|
||||||
|
25
markdown/bitburner.grafting.getgraftableaugmentations.md
Normal file
25
markdown/bitburner.grafting.getgraftableaugmentations.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||||
|
|
||||||
|
[Home](./index.md) > [bitburner](./bitburner.md) > [Grafting](./bitburner.grafting.md) > [getGraftableAugmentations](./bitburner.grafting.getgraftableaugmentations.md)
|
||||||
|
|
||||||
|
## Grafting.getGraftableAugmentations() method
|
||||||
|
|
||||||
|
Retrieves a list of Augmentations that can be grafted.
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
getGraftableAugmentations(): string[];
|
||||||
|
```
|
||||||
|
<b>Returns:</b>
|
||||||
|
|
||||||
|
string\[\]
|
||||||
|
|
||||||
|
An array of graftable Augmentations.
|
||||||
|
|
||||||
|
## Remarks
|
||||||
|
|
||||||
|
RAM cost: 5 GB
|
||||||
|
|
||||||
|
Note that this function returns a list of currently graftable Augmentations, based off of the Augmentations that you already own.
|
||||||
|
|
@ -22,5 +22,6 @@ This API requires Source-File 10 to use.
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| [getAugmentationGraftPrice(augName)](./bitburner.grafting.getaugmentationgraftprice.md) | Retrieve the grafting cost of an aug. |
|
| [getAugmentationGraftPrice(augName)](./bitburner.grafting.getaugmentationgraftprice.md) | Retrieve the grafting cost of an aug. |
|
||||||
| [getAugmentationGraftTime(augName)](./bitburner.grafting.getaugmentationgrafttime.md) | Retrieves the time required to graft an aug. |
|
| [getAugmentationGraftTime(augName)](./bitburner.grafting.getaugmentationgrafttime.md) | Retrieves the time required to graft an aug. |
|
||||||
|
| [getGraftableAugmentations()](./bitburner.grafting.getgraftableaugmentations.md) | Retrieves a list of Augmentations that can be grafted. |
|
||||||
| [graftAugmentation(augName, focus)](./bitburner.grafting.graftaugmentation.md) | Begins grafting the named aug. You must be in New Tokyo to use this. |
|
| [graftAugmentation(augName, focus)](./bitburner.grafting.graftaugmentation.md) | Begins grafting the named aug. You must be in New Tokyo to use this. |
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ Calculate the security increase for a number of thread.
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
growthAnalyzeSecurity(threads: number): number;
|
growthAnalyzeSecurity(threads: number, hostname?: string, cores?: number): number;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
@ -17,6 +17,8 @@ growthAnalyzeSecurity(threads: number): number;
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| threads | number | Amount of threads that will be used. |
|
| threads | number | Amount of threads that will be used. |
|
||||||
|
| hostname | string | Optional. Hostname of the target server. The number of threads is limited to the number needed to hack the servers maximum amount of money. |
|
||||||
|
| cores | number | Optional. The number of cores of the server that would run grow. |
|
||||||
|
|
||||||
<b>Returns:</b>
|
<b>Returns:</b>
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ export async function main(ns) {
|
|||||||
| [getWeakenTime(host)](./bitburner.ns.getweakentime.md) | Get the execution time of a weaken() call. |
|
| [getWeakenTime(host)](./bitburner.ns.getweakentime.md) | Get the execution time of a weaken() call. |
|
||||||
| [grow(host, opts)](./bitburner.ns.grow.md) | Spoof money in a servers bank account, increasing the amount available. |
|
| [grow(host, opts)](./bitburner.ns.grow.md) | Spoof money in a servers bank account, increasing the amount available. |
|
||||||
| [growthAnalyze(host, growthAmount, cores)](./bitburner.ns.growthanalyze.md) | Calculate the number of grow thread needed to grow a server by a certain multiplier. |
|
| [growthAnalyze(host, growthAmount, cores)](./bitburner.ns.growthanalyze.md) | Calculate the number of grow thread needed to grow a server by a certain multiplier. |
|
||||||
| [growthAnalyzeSecurity(threads)](./bitburner.ns.growthanalyzesecurity.md) | Calculate the security increase for a number of thread. |
|
| [growthAnalyzeSecurity(threads, hostname, cores)](./bitburner.ns.growthanalyzesecurity.md) | Calculate the security increase for a number of thread. |
|
||||||
| [hack(host, opts)](./bitburner.ns.hack.md) | Steal a servers money. |
|
| [hack(host, opts)](./bitburner.ns.hack.md) | Steal a servers money. |
|
||||||
| [hackAnalyze(host)](./bitburner.ns.hackanalyze.md) | Get the part of money stolen with a single thread. |
|
| [hackAnalyze(host)](./bitburner.ns.hackanalyze.md) | Get the part of money stolen with a single thread. |
|
||||||
| [hackAnalyzeChance(host)](./bitburner.ns.hackanalyzechance.md) | Get the chance of successfully hacking a server. |
|
| [hackAnalyzeChance(host)](./bitburner.ns.hackanalyzechance.md) | Get the chance of successfully hacking a server. |
|
||||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"version": "1.6.3",
|
"version": "1.6.4",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"version": "1.6.3",
|
"version": "1.6.4",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "SEE LICENSE IN license.txt",
|
"license": "SEE LICENSE IN license.txt",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"license": "SEE LICENSE IN license.txt",
|
"license": "SEE LICENSE IN license.txt",
|
||||||
"version": "1.6.3",
|
"version": "1.6.4",
|
||||||
"main": "electron-main.js",
|
"main": "electron-main.js",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Daniel Xie & Olivier Gagnon"
|
"name": "Daniel Xie & Olivier Gagnon"
|
||||||
|
@ -431,9 +431,6 @@ export class Augmentation {
|
|||||||
// Name of Augmentation
|
// Name of Augmentation
|
||||||
name = "";
|
name = "";
|
||||||
|
|
||||||
// Whether the player owns this Augmentation
|
|
||||||
owned = false;
|
|
||||||
|
|
||||||
// Array of names of all prerequisites
|
// Array of names of all prerequisites
|
||||||
prereqs: string[] = [];
|
prereqs: string[] = [];
|
||||||
|
|
||||||
|
@ -7,7 +7,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";
|
||||||
@ -75,7 +74,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);
|
||||||
@ -134,8 +133,6 @@ function resetAugmentation(aug: Augmentation): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void {
|
function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void {
|
||||||
Augmentations[aug.name].owned = true;
|
|
||||||
|
|
||||||
const augObj = Augmentations[aug.name];
|
const augObj = Augmentations[aug.name];
|
||||||
|
|
||||||
// Apply multipliers
|
// Apply multipliers
|
||||||
|
@ -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 (
|
||||||
<>
|
<>
|
||||||
@ -176,7 +178,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}
|
||||||
@ -215,6 +217,8 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const n = nextSourceFileLvl;
|
||||||
return (
|
return (
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
<>
|
<>
|
||||||
@ -228,19 +232,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";
|
||||||
@ -1920,7 +1919,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the Player starts doing some other actions, set action to idle and alert
|
// If the Player starts doing some other actions, set action to idle and alert
|
||||||
if (Augmentations[AugmentationNames.BladesSimulacrum].owned === false && player.isWorking) {
|
if (player.hasAugmentation(AugmentationNames.BladesSimulacrum) === false && player.isWorking) {
|
||||||
if (this.action.type !== ActionTypes["Idle"]) {
|
if (this.action.type !== ActionTypes["Idle"]) {
|
||||||
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
||||||
if (this.automateEnabled) {
|
if (this.automateEnabled) {
|
||||||
|
@ -116,8 +116,8 @@ export const CONSTANTS: {
|
|||||||
TotalNumBitNodes: number;
|
TotalNumBitNodes: number;
|
||||||
LatestUpdate: string;
|
LatestUpdate: string;
|
||||||
} = {
|
} = {
|
||||||
VersionString: "1.6.3",
|
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,11 @@ 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";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
player: IPlayer;
|
player: IPlayer;
|
||||||
@ -18,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 () {
|
||||||
@ -45,6 +52,27 @@ 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 {
|
||||||
|
checkForMessagesToSend();
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (error) throw new ReferenceError("Manually thrown error");
|
if (error) throw new ReferenceError("Manually thrown error");
|
||||||
}, [error]);
|
}, [error]);
|
||||||
@ -82,12 +110,29 @@ 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>
|
||||||
<Button onClick={quickHackW0r1dD43m0n}>Quick w0rld_d34m0n</Button>
|
<Button onClick={quickHackW0r1dD43m0n}>Quick w0rld_d34m0n</Button>
|
||||||
<Button onClick={hackW0r1dD43m0n}>Hack w0rld_d34m0n</Button>
|
<Button onClick={hackW0r1dD43m0n}>Hack w0rld_d34m0n</Button>
|
||||||
<Button onClick={() => setError(true)}>Throw Error</Button>
|
<Button onClick={() => setError(true)}>Throw Error</Button>
|
||||||
|
<Button onClick={checkMessages}>Check Messages</Button>
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
);
|
);
|
||||||
|
@ -62,7 +62,8 @@ export function hasAugmentationPrereqs(aug: Augmentation): boolean {
|
|||||||
console.error(`Invalid prereq Augmentation ${aug.prereqs[i]}`);
|
console.error(`Invalid prereq Augmentation ${aug.prereqs[i]}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (prereqAug.owned === false) {
|
|
||||||
|
if (Player.hasAugmentation(prereqAug, true) === false) {
|
||||||
hasPrereqs = false;
|
hasPrereqs = false;
|
||||||
|
|
||||||
// Check if the aug is purchased
|
// Check if the aug is purchased
|
||||||
|
@ -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,11 +491,25 @@ 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,
|
||||||
special: true,
|
offerSecurityWork: false,
|
||||||
keepOnInstall: true,
|
special: true,
|
||||||
|
keepOnInstall: true,
|
||||||
|
assignment: (): React.ReactElement => {
|
||||||
|
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()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
[FactionNames.Infiltrators]: new FactionInfo({
|
[FactionNames.Infiltrators]: new FactionInfo({
|
||||||
|
@ -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();
|
||||||
const offersWork =
|
const offersWork =
|
||||||
props.factionInfo.offerFieldWork || props.factionInfo.offerSecurityWork || props.factionInfo.offerHackingWork;
|
props.factionInfo.offerFieldWork || props.factionInfo.offerSecurityWork || props.factionInfo.offerHackingWork;
|
||||||
@ -97,18 +110,7 @@ export function Info(props: IProps): React.ReactElement {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Typography>-------------------------</Typography>
|
<Typography>-------------------------</Typography>
|
||||||
<Typography>
|
<Assignment />
|
||||||
{offersWork ? (
|
|
||||||
<>
|
|
||||||
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();
|
||||||
|
@ -1,31 +1,14 @@
|
|||||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
import { MessageFilenames } from "./MessageHelpers";
|
||||||
|
|
||||||
export class Message {
|
export class Message {
|
||||||
// Name of Message file
|
// Name of Message file
|
||||||
filename = "";
|
filename: MessageFilenames;
|
||||||
|
|
||||||
// The text contains in the Message
|
// The text contains in the Message
|
||||||
msg = "";
|
msg: string;
|
||||||
|
|
||||||
// Flag indicating whether this Message has been received by the player
|
constructor(filename: MessageFilenames, msg: string) {
|
||||||
recvd = false;
|
|
||||||
|
|
||||||
constructor(filename = "", msg = "") {
|
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
this.msg = msg;
|
this.msg = msg;
|
||||||
this.recvd = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize the current object to a JSON save state
|
|
||||||
toJSON(): any {
|
|
||||||
return Generic_toJSON("Message", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initializes a Message Object from a JSON save state
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
||||||
static fromJSON(value: any): Message {
|
|
||||||
return Generic_fromJSON(Message, value.data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reviver.constructors.Message = Message;
|
|
||||||
|
@ -5,23 +5,23 @@ import { Programs } from "../Programs/Programs";
|
|||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { Page } from "../ui/Router";
|
import { Page } from "../ui/Router";
|
||||||
import { GetServer } from "../Server/AllServers";
|
import { GetServer } from "../Server/AllServers";
|
||||||
|
import { SpecialServers } from "../Server/data/SpecialServers";
|
||||||
import { Settings } from "../Settings/Settings";
|
import { Settings } from "../Settings/Settings";
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { Reviver } from "../utils/JSONReviver";
|
|
||||||
import { FactionNames } from "../Faction/data/FactionNames";
|
import { FactionNames } from "../Faction/data/FactionNames";
|
||||||
|
import { Server } from "../Server/Server";
|
||||||
|
|
||||||
//Sends message to player, including a pop up
|
//Sends message to player, including a pop up
|
||||||
function sendMessage(msg: Message, forced = false): void {
|
function sendMessage(msg: Message, forced = false): void {
|
||||||
msg.recvd = true;
|
|
||||||
if (forced || !Settings.SuppressMessages) {
|
if (forced || !Settings.SuppressMessages) {
|
||||||
showMessage(msg.filename);
|
showMessage(msg.filename);
|
||||||
}
|
}
|
||||||
addMessageToServer(msg, "home");
|
addMessageToServer(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMessage(name: string): void {
|
function showMessage(name: MessageFilenames): void {
|
||||||
const msg = Messages[name];
|
const msg = Messages[name];
|
||||||
if (!msg) throw new Error("trying to display unexistent message");
|
if (!(msg instanceof Message)) throw new Error("trying to display unexistent message");
|
||||||
const txt =
|
const txt =
|
||||||
"Message received from unknown sender: <br><br>" +
|
"Message received from unknown sender: <br><br>" +
|
||||||
"<i>" +
|
"<i>" +
|
||||||
@ -34,21 +34,27 @@ function showMessage(name: string): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Adds a message to a server
|
//Adds a message to a server
|
||||||
function addMessageToServer(msg: Message, serverHostname: string): void {
|
function addMessageToServer(msg: Message): void {
|
||||||
const server = GetServer(serverHostname);
|
//Short-circuit if the message has already been saved
|
||||||
if (server == null) {
|
if (recvd(msg)) {
|
||||||
console.warn(`Could not find server ${serverHostname}`);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < server.messages.length; ++i) {
|
const server = GetServer("home");
|
||||||
const other = server.messages[i];
|
if (server == null) {
|
||||||
if (msg.filename === other) {
|
throw new Error("The home server doesn't exist. You done goofed.");
|
||||||
return; //Already exists
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
server.messages.push(msg.filename);
|
server.messages.push(msg.filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Returns whether the given message has already been received
|
||||||
|
function recvd(msg: Message): boolean {
|
||||||
|
const server = GetServer("home");
|
||||||
|
if (server == null) {
|
||||||
|
throw new Error("The home server doesn't exist. You done goofed.");
|
||||||
|
}
|
||||||
|
return server.messages.includes(msg.filename);
|
||||||
|
}
|
||||||
|
|
||||||
//Checks if any of the 'timed' messages should be sent
|
//Checks if any of the 'timed' messages should be sent
|
||||||
function checkForMessagesToSend(): void {
|
function checkForMessagesToSend(): void {
|
||||||
if (Router.page() === Page.BitVerse) return;
|
if (Router.page() === Page.BitVerse) return;
|
||||||
@ -60,46 +66,48 @@ function checkForMessagesToSend(): void {
|
|||||||
const cybersecTest = Messages[MessageFilenames.CyberSecTest];
|
const cybersecTest = Messages[MessageFilenames.CyberSecTest];
|
||||||
const nitesecTest = Messages[MessageFilenames.NiteSecTest];
|
const nitesecTest = Messages[MessageFilenames.NiteSecTest];
|
||||||
const bitrunnersTest = Messages[MessageFilenames.BitRunnersTest];
|
const bitrunnersTest = Messages[MessageFilenames.BitRunnersTest];
|
||||||
|
const truthGazer = Messages[MessageFilenames.TruthGazer];
|
||||||
const redpill = Messages[MessageFilenames.RedPill];
|
const redpill = Messages[MessageFilenames.RedPill];
|
||||||
|
|
||||||
if (Player.hasAugmentation(AugmentationNames.TheRedPill)) {
|
if (Player.hasAugmentation(AugmentationNames.TheRedPill)) {
|
||||||
//Force the message if the player has never destroyed a BitNode
|
//Get the world daemon required hacking level
|
||||||
sendMessage(redpill, Player.sourceFiles.length === 0);
|
const worldDaemon = GetServer(SpecialServers.WorldDaemon);
|
||||||
} else if (!jumper0.recvd && Player.hacking >= 25) {
|
if (!(worldDaemon instanceof Server)) {
|
||||||
|
throw new Error("The world daemon is not a server???? Please un-break reality");
|
||||||
|
}
|
||||||
|
//If the daemon can be hacked, send the player icarus.msg
|
||||||
|
if (Player.hacking >= worldDaemon.requiredHackingSkill) {
|
||||||
|
sendMessage(redpill, Player.sourceFiles.length === 0);
|
||||||
|
}
|
||||||
|
//If the daemon cannot be hacked, send the player truthgazer.msg a single time.
|
||||||
|
else if (!recvd(truthGazer)) {
|
||||||
|
sendMessage(truthGazer);
|
||||||
|
}
|
||||||
|
} else if (!recvd(jumper0) && Player.hacking >= 25) {
|
||||||
sendMessage(jumper0);
|
sendMessage(jumper0);
|
||||||
const flightName = Programs.Flight.name;
|
const flightName = Programs.Flight.name;
|
||||||
const homeComp = Player.getHomeComputer();
|
const homeComp = Player.getHomeComputer();
|
||||||
if (!homeComp.programs.includes(flightName)) {
|
if (!homeComp.programs.includes(flightName)) {
|
||||||
homeComp.programs.push(flightName);
|
homeComp.programs.push(flightName);
|
||||||
}
|
}
|
||||||
} else if (!jumper1.recvd && Player.hacking >= 40) {
|
} else if (!recvd(jumper1) && Player.hacking >= 40) {
|
||||||
sendMessage(jumper1);
|
sendMessage(jumper1);
|
||||||
} else if (!cybersecTest.recvd && Player.hacking >= 50) {
|
} else if (!recvd(cybersecTest) && Player.hacking >= 50) {
|
||||||
sendMessage(cybersecTest);
|
sendMessage(cybersecTest);
|
||||||
} else if (!jumper2.recvd && Player.hacking >= 175) {
|
} else if (!recvd(jumper2) && Player.hacking >= 175) {
|
||||||
sendMessage(jumper2);
|
sendMessage(jumper2);
|
||||||
} else if (!nitesecTest.recvd && Player.hacking >= 200) {
|
} else if (!recvd(nitesecTest) && Player.hacking >= 200) {
|
||||||
sendMessage(nitesecTest);
|
sendMessage(nitesecTest);
|
||||||
} else if (!jumper3.recvd && Player.hacking >= 350) {
|
} else if (!recvd(jumper3) && Player.hacking >= 350) {
|
||||||
sendMessage(jumper3);
|
sendMessage(jumper3);
|
||||||
} else if (!jumper4.recvd && Player.hacking >= 490) {
|
} else if (!recvd(jumper4) && Player.hacking >= 490) {
|
||||||
sendMessage(jumper4);
|
sendMessage(jumper4);
|
||||||
} else if (!bitrunnersTest.recvd && Player.hacking >= 500) {
|
} else if (!recvd(bitrunnersTest) && Player.hacking >= 500) {
|
||||||
sendMessage(bitrunnersTest);
|
sendMessage(bitrunnersTest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddToAllMessages(msg: Message): void {
|
export enum MessageFilenames {
|
||||||
Messages[msg.filename] = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Messages: { [key: string]: Message } = {};
|
|
||||||
|
|
||||||
function loadMessages(saveString: string): void {
|
|
||||||
Messages = JSON.parse(saveString, Reviver);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MessageFilenames {
|
|
||||||
Jumper0 = "j0.msg",
|
Jumper0 = "j0.msg",
|
||||||
Jumper1 = "j1.msg",
|
Jumper1 = "j1.msg",
|
||||||
Jumper2 = "j2.msg",
|
Jumper2 = "j2.msg",
|
||||||
@ -108,105 +116,103 @@ enum MessageFilenames {
|
|||||||
CyberSecTest = "csec-test.msg",
|
CyberSecTest = "csec-test.msg",
|
||||||
NiteSecTest = "nitesec-test.msg",
|
NiteSecTest = "nitesec-test.msg",
|
||||||
BitRunnersTest = "19dfj3l1nd.msg",
|
BitRunnersTest = "19dfj3l1nd.msg",
|
||||||
|
TruthGazer = "truthgazer.msg",
|
||||||
RedPill = "icarus.msg",
|
RedPill = "icarus.msg",
|
||||||
}
|
}
|
||||||
|
|
||||||
function initMessages(): void {
|
//Reset
|
||||||
//Reset
|
const Messages: Record<MessageFilenames, Message> = {
|
||||||
Messages = {};
|
|
||||||
|
|
||||||
//jump3R Messages
|
//jump3R Messages
|
||||||
AddToAllMessages(
|
[MessageFilenames.Jumper0]: new Message(
|
||||||
new Message(
|
MessageFilenames.Jumper0,
|
||||||
MessageFilenames.Jumper0,
|
"I know you can sense it. I know you're searching for it. " +
|
||||||
"I know you can sense it. I know you're searching for it. " +
|
"It's why you spend night after " +
|
||||||
"It's why you spend night after " +
|
"night at your computer. <br><br>It's real, I've seen it. And I can " +
|
||||||
"night at your computer. <br><br>It's real, I've seen it. And I can " +
|
"help you find it. But not right now. You're not ready yet.<br><br>" +
|
||||||
"help you find it. But not right now. You're not ready yet.<br><br>" +
|
"Use this program to track your progress<br><br>" +
|
||||||
"Use this program to track your progress<br><br>" +
|
"The fl1ght.exe program was added to your home computer<br><br>" +
|
||||||
"The fl1ght.exe program was added to your home computer<br><br>" +
|
"-jump3R",
|
||||||
"-jump3R",
|
),
|
||||||
),
|
|
||||||
);
|
[MessageFilenames.Jumper1]: new Message(
|
||||||
AddToAllMessages(
|
MessageFilenames.Jumper1,
|
||||||
new Message(
|
`Soon you will be contacted by a hacking group known as ${FactionNames.NiteSec}. ` +
|
||||||
MessageFilenames.Jumper1,
|
"They can help you with your search. <br><br>" +
|
||||||
`Soon you will be contacted by a hacking group known as ${FactionNames.NiteSec}. ` +
|
"You should join them, garner their favor, and " +
|
||||||
"They can help you with your search. <br><br>" +
|
"exploit them for their Augmentations. But do not trust them. " +
|
||||||
"You should join them, garner their favor, and " +
|
"They are not what they seem. No one is.<br><br>" +
|
||||||
"exploit them for their Augmentations. But do not trust them. " +
|
"-jump3R",
|
||||||
"They are not what they seem. No one is.<br><br>" +
|
),
|
||||||
"-jump3R",
|
|
||||||
),
|
[MessageFilenames.Jumper2]: new Message(
|
||||||
);
|
MessageFilenames.Jumper2,
|
||||||
AddToAllMessages(
|
"Do not try to save the world. There is no world to save. If " +
|
||||||
new Message(
|
"you want to find the truth, worry only about yourself. Ethics and " +
|
||||||
MessageFilenames.Jumper2,
|
`morals will get you killed. <br><br>Watch out for a hacking group known as ${FactionNames.NiteSec}.` +
|
||||||
"Do not try to save the world. There is no world to save. If " +
|
"<br><br>-jump3R",
|
||||||
"you want to find the truth, worry only about yourself. Ethics and " +
|
),
|
||||||
`morals will get you killed. <br><br>Watch out for a hacking group known as ${FactionNames.NiteSec}.` +
|
|
||||||
"<br><br>-jump3R",
|
[MessageFilenames.Jumper3]: new Message(
|
||||||
),
|
MessageFilenames.Jumper3,
|
||||||
);
|
"You must learn to walk before you can run. And you must " +
|
||||||
AddToAllMessages(
|
`run before you can fly. Look for ${FactionNames.TheBlackHand}. <br><br>` +
|
||||||
new Message(
|
"I.I.I.I <br><br>-jump3R",
|
||||||
MessageFilenames.Jumper3,
|
),
|
||||||
"You must learn to walk before you can run. And you must " +
|
|
||||||
`run before you can fly. Look for ${FactionNames.TheBlackHand}. <br><br>` +
|
[MessageFilenames.Jumper4]: new Message(
|
||||||
"I.I.I.I <br><br>-jump3R",
|
MessageFilenames.Jumper4,
|
||||||
),
|
"To find what you are searching for, you must understand the bits. " +
|
||||||
);
|
"The bits are all around us. The runners will help you.<br><br>" +
|
||||||
AddToAllMessages(
|
"-jump3R",
|
||||||
new Message(
|
),
|
||||||
MessageFilenames.Jumper4,
|
|
||||||
"To find what you are searching for, you must understand the bits. " +
|
|
||||||
"The bits are all around us. The runners will help you.<br><br>" +
|
|
||||||
"-jump3R",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
//Messages from hacking factions
|
//Messages from hacking factions
|
||||||
AddToAllMessages(
|
[MessageFilenames.CyberSecTest]: new Message(
|
||||||
new Message(
|
MessageFilenames.CyberSecTest,
|
||||||
MessageFilenames.CyberSecTest,
|
"We've been watching you. Your skills are very impressive. But you're wasting " +
|
||||||
"We've been watching you. Your skills are very impressive. But you're wasting " +
|
"your talents. If you join us, you can put your skills to good use and change " +
|
||||||
"your talents. If you join us, you can put your skills to good use and change " +
|
"the world for the better. If you join us, we can unlock your full potential. <br><br>" +
|
||||||
"the world for the better. If you join us, we can unlock your full potential. <br><br>" +
|
"But first, you must pass our test. Find and install the backdoor on our server. <br><br>" +
|
||||||
"But first, you must pass our test. Find and install the backdoor on our server. <br><br>" +
|
`-${FactionNames.CyberSec}`,
|
||||||
`-${FactionNames.CyberSec}`,
|
),
|
||||||
),
|
|
||||||
);
|
|
||||||
AddToAllMessages(
|
|
||||||
new Message(
|
|
||||||
MessageFilenames.NiteSecTest,
|
|
||||||
"People say that the corrupted governments and corporations rule the world. " +
|
|
||||||
"Yes, maybe they do. But do you know who everyone really fears? People " +
|
|
||||||
"like us. Because they can't hide from us. Because they can't fight shadows " +
|
|
||||||
"and ideas with bullets. <br><br>" +
|
|
||||||
"Join us, and people will fear you, too. <br><br>" +
|
|
||||||
"Find and install the backdoor on our server. Then, we will contact you again." +
|
|
||||||
`<br><br>-${FactionNames.NiteSec}`,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
AddToAllMessages(
|
|
||||||
new Message(
|
|
||||||
MessageFilenames.BitRunnersTest,
|
|
||||||
"We know what you are doing. We know what drives you. We know " +
|
|
||||||
"what you are looking for. <br><br> " +
|
|
||||||
"We can help you find the answers.<br><br>" +
|
|
||||||
"run4theh111z",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
AddToAllMessages(
|
[MessageFilenames.NiteSecTest]: new Message(
|
||||||
new Message(
|
MessageFilenames.NiteSecTest,
|
||||||
MessageFilenames.RedPill,
|
"People say that the corrupted governments and corporations rule the world. " +
|
||||||
"@)(#V%*N)@(#*)*C)@#%*)*V)@#(*%V@)(#VN%*)@#(*%<br>" +
|
"Yes, maybe they do. But do you know who everyone really fears? People " +
|
||||||
")@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)<br>" +
|
"like us. Because they can't hide from us. Because they can't fight shadows " +
|
||||||
"@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB<br>" +
|
"and ideas with bullets. <br><br>" +
|
||||||
"DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)",
|
"Join us, and people will fear you, too. <br><br>" +
|
||||||
),
|
"Find and install the backdoor on our server. Then, we will contact you again." +
|
||||||
);
|
`<br><br>-${FactionNames.NiteSec}`,
|
||||||
}
|
),
|
||||||
|
|
||||||
export { Messages, checkForMessagesToSend, showMessage, loadMessages, initMessages };
|
[MessageFilenames.BitRunnersTest]: new Message(
|
||||||
|
MessageFilenames.BitRunnersTest,
|
||||||
|
"We know what you are doing. We know what drives you. We know " +
|
||||||
|
"what you are looking for. <br><br> " +
|
||||||
|
"We can help you find the answers.<br><br>" +
|
||||||
|
"run4theh111z",
|
||||||
|
),
|
||||||
|
|
||||||
|
//Messages to guide players to the daemon
|
||||||
|
[MessageFilenames.TruthGazer]: new Message(
|
||||||
|
MessageFilenames.TruthGazer,
|
||||||
|
//"THE TRUTH CAN NO LONGER ESCAPE YOUR GAZE"
|
||||||
|
"@&*($#@&__TH3__#@A&#@*)__TRU1H__(*)&*)($#@&()E&R)W&<br>" +
|
||||||
|
"%@*$^$()@&$)$*@__CAN__()(@^#)@&@)#__N0__(#@&#)@&@&(<br>" +
|
||||||
|
"*(__LON6ER__^#)@)(()*#@)@__ESCAP3__)#(@(#@*@()@(#*$<br>" +
|
||||||
|
"()@)#$*%)$#()$#__Y0UR__(*)$#()%(&(%)*!)($__GAZ3__#(",
|
||||||
|
),
|
||||||
|
|
||||||
|
[MessageFilenames.RedPill]: new Message(
|
||||||
|
MessageFilenames.RedPill,
|
||||||
|
//"FIND THE-CAVE"
|
||||||
|
"@)(#V%*N)@(#*)*C)@#%*)*V)@#(*%V@)(#VN%*)@#(*%<br>" +
|
||||||
|
")@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)<br>" +
|
||||||
|
"@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB<br>" +
|
||||||
|
"DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)",
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Messages, checkForMessagesToSend, showMessage };
|
||||||
|
@ -182,6 +182,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
|
||||||
@ -311,6 +313,7 @@ const ui: IMap<any> = {
|
|||||||
const grafting: IMap<any> = {
|
const grafting: IMap<any> = {
|
||||||
getAugmentationGraftPrice: 3.75,
|
getAugmentationGraftPrice: 3.75,
|
||||||
getAugmentationGraftTime: 3.75,
|
getAugmentationGraftTime: 3.75,
|
||||||
|
getGraftableAugmentations: 5,
|
||||||
graftAugmentation: 7.5,
|
graftAugmentation: 7.5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,12 +34,12 @@ import { RunningScript } from "./Script/RunningScript";
|
|||||||
import {
|
import {
|
||||||
getServerOnNetwork,
|
getServerOnNetwork,
|
||||||
numCycleForGrowth,
|
numCycleForGrowth,
|
||||||
|
numCycleForGrowthCorrected,
|
||||||
processSingleServerGrowth,
|
processSingleServerGrowth,
|
||||||
safetlyCreateUniqueServer,
|
safetlyCreateUniqueServer,
|
||||||
} 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";
|
||||||
@ -638,7 +638,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
|
|
||||||
if (percentHacked > 0) {
|
if (percentHacked > 0) {
|
||||||
// thread count is limited to the maximum number of threads needed
|
// thread count is limited to the maximum number of threads needed
|
||||||
threads = Math.ceil(1 / percentHacked);
|
threads = Math.min(threads, Math.ceil(1 / percentHacked));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,9 +757,26 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
|
|
||||||
return numCycleForGrowth(server, Number(growth), Player, cores);
|
return numCycleForGrowth(server, Number(growth), Player, cores);
|
||||||
},
|
},
|
||||||
growthAnalyzeSecurity: function (_threads: unknown): number {
|
growthAnalyzeSecurity: function (_threads: unknown, _hostname?: unknown, _cores?: unknown): number {
|
||||||
updateDynamicRam("growthAnalyzeSecurity", getRamCost(Player, "growthAnalyzeSecurity"));
|
updateDynamicRam("growthAnalyzeSecurity", getRamCost(Player, "growthAnalyzeSecurity"));
|
||||||
const threads = helper.number("growthAnalyzeSecurity", "threads", _threads);
|
let threads = helper.number("growthAnalyzeSecurity", "threads", _threads);
|
||||||
|
if (_hostname) {
|
||||||
|
const cores = helper.number("growthAnalyzeSecurity", "cores", _cores) || 1;
|
||||||
|
const hostname = helper.string("growthAnalyzeSecurity", "hostname", _hostname);
|
||||||
|
const server = safeGetServer(hostname, "growthAnalyzeSecurity");
|
||||||
|
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
workerScript.log("growthAnalyzeSecurity", () => "Cannot be executed on this server.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxThreadsNeeded = Math.ceil(
|
||||||
|
numCycleForGrowthCorrected(server, server.moneyMax, server.moneyAvailable, Player, cores),
|
||||||
|
);
|
||||||
|
|
||||||
|
threads = Math.min(threads, maxThreadsNeeded);
|
||||||
|
}
|
||||||
|
|
||||||
return 2 * CONSTANTS.ServerFortifyAmount * threads;
|
return 2 * CONSTANTS.ServerFortifyAmount * threads;
|
||||||
},
|
},
|
||||||
weaken: async function (_hostname: unknown, { threads: requestedThreads }: BasicHGWOptions = {}): Promise<number> {
|
weaken: async function (_hostname: unknown, { threads: requestedThreads }: BasicHGWOptions = {}): Promise<number> {
|
||||||
@ -1535,7 +1552,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);
|
||||||
},
|
},
|
||||||
|
@ -4,7 +4,7 @@ import { CityName } from "../Locations/data/CityNames";
|
|||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation";
|
import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation";
|
||||||
import { getAvailableAugs } from "../PersonObjects/Grafting/ui/GraftingRoot";
|
import { getGraftingAvailableAugs } from "../PersonObjects/Grafting/GraftingHelpers";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { Grafting as IGrafting } from "../ScriptEditor/NetscriptDefinitions";
|
import { Grafting as IGrafting } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
import { Router } from "../ui/GameRoot";
|
import { Router } from "../ui/GameRoot";
|
||||||
@ -28,7 +28,7 @@ export function NetscriptGrafting(player: IPlayer, workerScript: WorkerScript, h
|
|||||||
updateRam("getAugmentationGraftPrice");
|
updateRam("getAugmentationGraftPrice");
|
||||||
const augName = helper.string("getAugmentationGraftPrice", "augName", _augName);
|
const augName = helper.string("getAugmentationGraftPrice", "augName", _augName);
|
||||||
checkGraftingAPIAccess("getAugmentationGraftPrice");
|
checkGraftingAPIAccess("getAugmentationGraftPrice");
|
||||||
if (!Augmentations.hasOwnProperty(augName)) {
|
if (!getGraftingAvailableAugs(player).includes(augName) || !Augmentations.hasOwnProperty(augName)) {
|
||||||
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftPrice", `Invalid aug: ${augName}`);
|
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftPrice", `Invalid aug: ${augName}`);
|
||||||
}
|
}
|
||||||
const craftableAug = new GraftableAugmentation(Augmentations[augName]);
|
const craftableAug = new GraftableAugmentation(Augmentations[augName]);
|
||||||
@ -39,13 +39,20 @@ export function NetscriptGrafting(player: IPlayer, workerScript: WorkerScript, h
|
|||||||
updateRam("getAugmentationGraftTime");
|
updateRam("getAugmentationGraftTime");
|
||||||
const augName = helper.string("getAugmentationGraftTime", "augName", _augName);
|
const augName = helper.string("getAugmentationGraftTime", "augName", _augName);
|
||||||
checkGraftingAPIAccess("getAugmentationGraftTime");
|
checkGraftingAPIAccess("getAugmentationGraftTime");
|
||||||
if (!Augmentations.hasOwnProperty(augName)) {
|
if (!getGraftingAvailableAugs(player).includes(augName) || !Augmentations.hasOwnProperty(augName)) {
|
||||||
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftTime", `Invalid aug: ${augName}`);
|
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftTime", `Invalid aug: ${augName}`);
|
||||||
}
|
}
|
||||||
const craftableAug = new GraftableAugmentation(Augmentations[augName]);
|
const craftableAug = new GraftableAugmentation(Augmentations[augName]);
|
||||||
return craftableAug.time;
|
return craftableAug.time;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getGraftableAugmentations: (): string[] => {
|
||||||
|
updateRam("getGraftableAugmentations");
|
||||||
|
checkGraftingAPIAccess("getGraftableAugmentations");
|
||||||
|
const graftableAugs = getGraftingAvailableAugs(player);
|
||||||
|
return graftableAugs;
|
||||||
|
},
|
||||||
|
|
||||||
graftAugmentation: (_augName: string, _focus: unknown = true): boolean => {
|
graftAugmentation: (_augName: string, _focus: unknown = true): boolean => {
|
||||||
updateRam("graftAugmentation");
|
updateRam("graftAugmentation");
|
||||||
const augName = helper.string("graftAugmentation", "augName", _augName);
|
const augName = helper.string("graftAugmentation", "augName", _augName);
|
||||||
@ -57,7 +64,7 @@ export function NetscriptGrafting(player: IPlayer, workerScript: WorkerScript, h
|
|||||||
"You must be in New Tokyo to begin grafting an Augmentation.",
|
"You must be in New Tokyo to begin grafting an Augmentation.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!getAvailableAugs(player).includes(augName)) {
|
if (!getGraftingAvailableAugs(player).includes(augName) || !Augmentations.hasOwnProperty(augName)) {
|
||||||
workerScript.log("grafting.graftAugmentation", () => `Invalid aug: ${augName}`);
|
workerScript.log("grafting.graftAugmentation", () => `Invalid aug: ${augName}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -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}'`);
|
||||||
}
|
}
|
||||||
@ -580,6 +582,7 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid hostname: '${hostname}'`);
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid hostname: '${hostname}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Home case
|
||||||
if (hostname === "home") {
|
if (hostname === "home") {
|
||||||
player.getCurrentServer().isConnectedTo = false;
|
player.getCurrentServer().isConnectedTo = false;
|
||||||
player.currentServer = player.getHomeComputer().hostname;
|
player.currentServer = player.getHomeComputer().hostname;
|
||||||
@ -588,6 +591,7 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Adjacent server case
|
||||||
const server = player.getCurrentServer();
|
const server = player.getCurrentServer();
|
||||||
for (let i = 0; i < server.serversOnNetwork.length; i++) {
|
for (let i = 0; i < server.serversOnNetwork.length; i++) {
|
||||||
const other = getServerOnNetwork(server, i);
|
const other = getServerOnNetwork(server, i);
|
||||||
@ -601,6 +605,17 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Backdoor case
|
||||||
|
const other = GetServer(hostname);
|
||||||
|
if (other !== null && other instanceof Server && other.backdoorInstalled) {
|
||||||
|
player.getCurrentServer().isConnectedTo = false;
|
||||||
|
player.currentServer = target.hostname;
|
||||||
|
player.getCurrentServer().isConnectedTo = true;
|
||||||
|
Terminal.setcwd("/");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Failure case
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
manualHack: (_ctx: NetscriptContext) =>
|
manualHack: (_ctx: NetscriptContext) =>
|
||||||
@ -649,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");
|
||||||
}
|
}
|
||||||
@ -849,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) {
|
||||||
@ -905,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;
|
||||||
@ -977,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();
|
||||||
},
|
},
|
||||||
@ -1004,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)) {
|
||||||
@ -1028,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
|
||||||
@ -1117,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`);
|
||||||
@ -1187,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) {
|
||||||
@ -1236,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();
|
||||||
@ -1257,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) {
|
||||||
@ -1269,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) {
|
||||||
@ -1292,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()) {
|
||||||
@ -1322,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",
|
||||||
|
15
src/PersonObjects/Grafting/GraftingHelpers.ts
Normal file
15
src/PersonObjects/Grafting/GraftingHelpers.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||||
|
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||||
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
|
export const getGraftingAvailableAugs = (player: IPlayer): string[] => {
|
||||||
|
const augs: string[] = [];
|
||||||
|
|
||||||
|
for (const [augName, aug] of Object.entries(Augmentations)) {
|
||||||
|
if (augName === AugmentationNames.NeuroFluxGovernor || augName === AugmentationNames.TheRedPill || aug.isSpecial)
|
||||||
|
continue;
|
||||||
|
augs.push(augName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation));
|
||||||
|
};
|
@ -15,22 +15,11 @@ import { ConfirmationModal } from "../../../ui/React/ConfirmationModal";
|
|||||||
import { Money } from "../../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
import { convertTimeMsToTimeElapsedString, formatNumber } from "../../../utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString, formatNumber } from "../../../utils/StringHelperFunctions";
|
||||||
import { IPlayer } from "../../IPlayer";
|
import { IPlayer } from "../../IPlayer";
|
||||||
|
import { getGraftingAvailableAugs } from "../GraftingHelpers";
|
||||||
import { GraftableAugmentation } from "../GraftableAugmentation";
|
import { GraftableAugmentation } from "../GraftableAugmentation";
|
||||||
|
|
||||||
const GraftableAugmentations: IMap<GraftableAugmentation> = {};
|
const GraftableAugmentations: IMap<GraftableAugmentation> = {};
|
||||||
|
|
||||||
export const getAvailableAugs = (player: IPlayer): string[] => {
|
|
||||||
const augs: string[] = [];
|
|
||||||
|
|
||||||
for (const [augName, aug] of Object.entries(Augmentations)) {
|
|
||||||
if (augName === AugmentationNames.NeuroFluxGovernor || augName === AugmentationNames.TheRedPill || aug.isSpecial)
|
|
||||||
continue;
|
|
||||||
augs.push(augName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation));
|
|
||||||
};
|
|
||||||
|
|
||||||
const canGraft = (player: IPlayer, aug: GraftableAugmentation): boolean => {
|
const canGraft = (player: IPlayer, aug: GraftableAugmentation): boolean => {
|
||||||
if (player.money < aug.cost) {
|
if (player.money < aug.cost) {
|
||||||
return false;
|
return false;
|
||||||
@ -71,7 +60,7 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
GraftableAugmentations[name] = graftableAug;
|
GraftableAugmentations[name] = graftableAug;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [selectedAug, setSelectedAug] = useState(getAvailableAugs(player)[0]);
|
const [selectedAug, setSelectedAug] = useState(getGraftingAvailableAugs(player)[0]);
|
||||||
const [graftOpen, setGraftOpen] = useState(false);
|
const [graftOpen, setGraftOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -92,10 +81,10 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
|
|
||||||
<Box sx={{ my: 3 }}>
|
<Box sx={{ my: 3 }}>
|
||||||
<Typography variant="h5">Graft Augmentations</Typography>
|
<Typography variant="h5">Graft Augmentations</Typography>
|
||||||
{getAvailableAugs(player).length > 0 ? (
|
{getGraftingAvailableAugs(player).length > 0 ? (
|
||||||
<Paper sx={{ my: 1, width: "fit-content", display: "grid", gridTemplateColumns: "1fr 3fr" }}>
|
<Paper sx={{ my: 1, width: "fit-content", display: "grid", gridTemplateColumns: "1fr 3fr" }}>
|
||||||
<List sx={{ height: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
|
<List sx={{ height: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
|
||||||
{getAvailableAugs(player).map((k, i) => (
|
{getGraftingAvailableAugs(player).map((k, i) => (
|
||||||
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
|
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
|
||||||
<Typography>{k}</Typography>
|
<Typography>{k}</Typography>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
|
@ -7,7 +7,7 @@ import { Augmentation } from "../../Augmentation/Augmentation";
|
|||||||
|
|
||||||
import { calculateEntropy } from "../Grafting/EntropyAccumulation";
|
import { calculateEntropy } from "../Grafting/EntropyAccumulation";
|
||||||
|
|
||||||
export function hasAugmentation(this: IPlayer, aug: string | Augmentation, installed = false): boolean {
|
export function hasAugmentation(this: IPlayer, aug: string | Augmentation, includeQueued = false): boolean {
|
||||||
const augName: string = aug instanceof Augmentation ? aug.name : aug;
|
const augName: string = aug instanceof Augmentation ? aug.name : aug;
|
||||||
|
|
||||||
for (const owned of this.augmentations) {
|
for (const owned of this.augmentations) {
|
||||||
@ -16,7 +16,7 @@ export function hasAugmentation(this: IPlayer, aug: string | Augmentation, insta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!installed) {
|
if (!includeQueued) {
|
||||||
for (const owned of this.queuedAugmentations) {
|
for (const owned of this.queuedAugmentations) {
|
||||||
if (owned.name === augName) {
|
if (owned.name === augName) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -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));
|
||||||
@ -475,7 +474,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));
|
||||||
}
|
}
|
||||||
@ -1045,7 +1044,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1323,20 +1322,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();
|
||||||
@ -2092,12 +2092,7 @@ export function reapplyAllAugmentations(this: IPlayer, resetMultipliers = true):
|
|||||||
|
|
||||||
const playerAug = this.augmentations[i];
|
const playerAug = this.augmentations[i];
|
||||||
const augName = playerAug.name;
|
const augName = playerAug.name;
|
||||||
const aug = Augmentations[augName];
|
|
||||||
if (aug == null) {
|
|
||||||
console.warn(`Invalid augmentation name in Player.reapplyAllAugmentations(). Aug ${augName} will be skipped`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
aug.owned = true;
|
|
||||||
if (augName == AugmentationNames.NeuroFluxGovernor) {
|
if (augName == AugmentationNames.NeuroFluxGovernor) {
|
||||||
for (let j = 0; j < playerAug.level; ++j) {
|
for (let j = 0; j < playerAug.level; ++j) {
|
||||||
applyAugmentation(this.augmentations[i], true);
|
applyAugmentation(this.augmentations[i], true);
|
||||||
@ -2718,7 +2713,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 {
|
||||||
@ -2756,7 +2751,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 {
|
||||||
|
@ -12,7 +12,6 @@ import { Faction } from "./Faction/Faction";
|
|||||||
import { Factions, initFactions } from "./Faction/Factions";
|
import { Factions, initFactions } from "./Faction/Factions";
|
||||||
import { joinFaction } from "./Faction/FactionHelpers";
|
import { joinFaction } from "./Faction/FactionHelpers";
|
||||||
import { updateHashManagerCapacity } from "./Hacknet/HacknetHelpers";
|
import { updateHashManagerCapacity } from "./Hacknet/HacknetHelpers";
|
||||||
import { initMessages } from "./Message/MessageHelpers";
|
|
||||||
import { prestigeWorkerScripts } from "./NetscriptWorker";
|
import { prestigeWorkerScripts } from "./NetscriptWorker";
|
||||||
import { Player } from "./Player";
|
import { Player } from "./Player";
|
||||||
import { Router } from "./ui/GameRoot";
|
import { Router } from "./ui/GameRoot";
|
||||||
@ -21,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";
|
||||||
@ -56,15 +54,15 @@ export function prestigeAugmentation(): void {
|
|||||||
AddToAllServers(homeComp);
|
AddToAllServers(homeComp);
|
||||||
prestigeHomeComputer(Player, homeComp);
|
prestigeHomeComputer(Player, homeComp);
|
||||||
|
|
||||||
if (augmentationExists(AugmentationNames.Neurolink) && Augmentations[AugmentationNames.Neurolink].owned) {
|
if (augmentationExists(AugmentationNames.Neurolink) && Player.hasAugmentation(AugmentationNames.Neurolink)) {
|
||||||
homeComp.programs.push(Programs.FTPCrackProgram.name);
|
homeComp.programs.push(Programs.FTPCrackProgram.name);
|
||||||
homeComp.programs.push(Programs.RelaySMTPProgram.name);
|
homeComp.programs.push(Programs.RelaySMTPProgram.name);
|
||||||
}
|
}
|
||||||
if (augmentationExists(AugmentationNames.CashRoot) && Augmentations[AugmentationNames.CashRoot].owned) {
|
if (augmentationExists(AugmentationNames.CashRoot) && Player.hasAugmentation(AugmentationNames.CashRoot)) {
|
||||||
Player.setMoney(1e6);
|
Player.setMoney(1e6);
|
||||||
homeComp.programs.push(Programs.BruteSSHProgram.name);
|
homeComp.programs.push(Programs.BruteSSHProgram.name);
|
||||||
}
|
}
|
||||||
if (augmentationExists(AugmentationNames.PCMatrix) && Augmentations[AugmentationNames.PCMatrix].owned) {
|
if (augmentationExists(AugmentationNames.PCMatrix) && Player.hasAugmentation(AugmentationNames.PCMatrix)) {
|
||||||
homeComp.programs.push(Programs.DeepscanV1.name);
|
homeComp.programs.push(Programs.DeepscanV1.name);
|
||||||
homeComp.programs.push(Programs.AutoLink.name);
|
homeComp.programs.push(Programs.AutoLink.name);
|
||||||
}
|
}
|
||||||
@ -105,9 +103,6 @@ export function prestigeAugmentation(): void {
|
|||||||
Player.reapplyAllSourceFiles();
|
Player.reapplyAllSourceFiles();
|
||||||
initCompanies();
|
initCompanies();
|
||||||
|
|
||||||
// Messages
|
|
||||||
initMessages();
|
|
||||||
|
|
||||||
// Apply entropy from grafting
|
// Apply entropy from grafting
|
||||||
Player.applyEntropy(Player.entropy);
|
Player.applyEntropy(Player.entropy);
|
||||||
|
|
||||||
@ -143,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;
|
||||||
}
|
}
|
||||||
@ -155,7 +150,7 @@ export function prestigeAugmentation(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Red Pill
|
// Red Pill
|
||||||
if (augmentationExists(AugmentationNames.TheRedPill) && Augmentations[AugmentationNames.TheRedPill].owned) {
|
if (augmentationExists(AugmentationNames.TheRedPill) && Player.hasAugmentation(AugmentationNames.TheRedPill)) {
|
||||||
const WorldDaemon = GetServer(SpecialServers.WorldDaemon);
|
const WorldDaemon = GetServer(SpecialServers.WorldDaemon);
|
||||||
const DaedalusServer = GetServer(SpecialServers.DaedalusServer);
|
const DaedalusServer = GetServer(SpecialServers.DaedalusServer);
|
||||||
if (WorldDaemon && DaedalusServer) {
|
if (WorldDaemon && DaedalusServer) {
|
||||||
@ -164,7 +159,7 @@ export function prestigeAugmentation(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (augmentationExists(AugmentationNames.StaneksGift1) && Augmentations[AugmentationNames.StaneksGift1].owned) {
|
if (augmentationExists(AugmentationNames.StaneksGift1) && Player.hasAugmentation(AugmentationNames.StaneksGift1)) {
|
||||||
joinFaction(Factions[FactionNames.ChurchOfTheMachineGod]);
|
joinFaction(Factions[FactionNames.ChurchOfTheMachineGod]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,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
|
||||||
@ -202,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);
|
||||||
@ -238,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),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,9 +245,6 @@ export function prestigeSourceFile(flume: boolean): void {
|
|||||||
Player.reapplyAllSourceFiles();
|
Player.reapplyAllSourceFiles();
|
||||||
initCompanies();
|
initCompanies();
|
||||||
|
|
||||||
// Messages
|
|
||||||
initMessages();
|
|
||||||
|
|
||||||
if (Player.sourceFileLvl(5) > 0 || Player.bitNodeN === 5) {
|
if (Player.sourceFileLvl(5) > 0 || Player.bitNodeN === 5) {
|
||||||
homeComp.programs.push(Programs.Formulas.name);
|
homeComp.programs.push(Programs.Formulas.name);
|
||||||
}
|
}
|
||||||
@ -271,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;
|
||||||
}
|
}
|
||||||
@ -299,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;
|
||||||
@ -316,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;
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,9 @@ import { Companies, loadCompanies } from "./Company/Companies";
|
|||||||
import { CONSTANTS } from "./Constants";
|
import { CONSTANTS } from "./Constants";
|
||||||
import { Factions, loadFactions } from "./Faction/Factions";
|
import { Factions, loadFactions } from "./Faction/Factions";
|
||||||
import { loadAllGangs, AllGangs } from "./Gang/AllGangs";
|
import { loadAllGangs, AllGangs } from "./Gang/AllGangs";
|
||||||
import { loadMessages, initMessages, Messages } from "./Message/MessageHelpers";
|
|
||||||
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";
|
||||||
|
|
||||||
@ -67,7 +65,6 @@ class BitburnerSaveObject {
|
|||||||
FactionsSave = "";
|
FactionsSave = "";
|
||||||
AliasesSave = "";
|
AliasesSave = "";
|
||||||
GlobalAliasesSave = "";
|
GlobalAliasesSave = "";
|
||||||
MessagesSave = "";
|
|
||||||
StockMarketSave = "";
|
StockMarketSave = "";
|
||||||
SettingsSave = "";
|
SettingsSave = "";
|
||||||
VersionSave = "";
|
VersionSave = "";
|
||||||
@ -83,7 +80,6 @@ class BitburnerSaveObject {
|
|||||||
this.FactionsSave = JSON.stringify(Factions);
|
this.FactionsSave = JSON.stringify(Factions);
|
||||||
this.AliasesSave = JSON.stringify(Aliases);
|
this.AliasesSave = JSON.stringify(Aliases);
|
||||||
this.GlobalAliasesSave = JSON.stringify(GlobalAliases);
|
this.GlobalAliasesSave = JSON.stringify(GlobalAliases);
|
||||||
this.MessagesSave = JSON.stringify(Messages);
|
|
||||||
this.StockMarketSave = JSON.stringify(StockMarket);
|
this.StockMarketSave = JSON.stringify(StockMarket);
|
||||||
this.SettingsSave = JSON.stringify(Settings);
|
this.SettingsSave = JSON.stringify(Settings);
|
||||||
this.VersionSave = JSON.stringify(CONSTANTS.VersionNumber);
|
this.VersionSave = JSON.stringify(CONSTANTS.VersionNumber);
|
||||||
@ -129,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;
|
||||||
}
|
}
|
||||||
@ -398,6 +394,9 @@ function evaluateVersionCompatibility(ver: string | number): void {
|
|||||||
delete anyPlayer.resleeves;
|
delete anyPlayer.resleeves;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ver < 14) {
|
||||||
|
delete (Settings as any).EditorTheme;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,17 +440,6 @@ function loadGame(saveString: string): boolean {
|
|||||||
console.warn(`Save file did not contain a GlobalAliases property`);
|
console.warn(`Save file did not contain a GlobalAliases property`);
|
||||||
loadGlobalAliases("");
|
loadGlobalAliases("");
|
||||||
}
|
}
|
||||||
if (saveObj.hasOwnProperty("MessagesSave")) {
|
|
||||||
try {
|
|
||||||
loadMessages(saveObj.MessagesSave);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(`Could not load Messages from save`);
|
|
||||||
initMessages();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.warn(`Save file did not contain a Messages property`);
|
|
||||||
initMessages();
|
|
||||||
}
|
|
||||||
if (saveObj.hasOwnProperty("StockMarketSave")) {
|
if (saveObj.hasOwnProperty("StockMarketSave")) {
|
||||||
try {
|
try {
|
||||||
loadStockMarket(saveObj.StockMarketSave);
|
loadStockMarket(saveObj.StockMarketSave);
|
||||||
|
79
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
79
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;
|
||||||
*/
|
*/
|
||||||
@ -3784,6 +3808,18 @@ export interface Grafting {
|
|||||||
*/
|
*/
|
||||||
getAugmentationGraftTime(augName: string): number;
|
getAugmentationGraftTime(augName: string): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of Augmentations that can be grafted.
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 5 GB
|
||||||
|
*
|
||||||
|
* Note that this function returns a list of currently graftable Augmentations,
|
||||||
|
* based off of the Augmentations that you already own.
|
||||||
|
*
|
||||||
|
* @returns An array of graftable Augmentations.
|
||||||
|
*/
|
||||||
|
getGraftableAugmentations(): string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins grafting the named aug. You must be in New Tokyo to use this.
|
* Begins grafting the named aug. You must be in New Tokyo to use this.
|
||||||
* @remarks
|
* @remarks
|
||||||
@ -4693,9 +4729,11 @@ export interface NS {
|
|||||||
* Returns the security increase that would occur if a grow with this many threads happened.
|
* Returns the security increase that would occur if a grow with this many threads happened.
|
||||||
*
|
*
|
||||||
* @param threads - Amount of threads that will be used.
|
* @param threads - Amount of threads that will be used.
|
||||||
|
* @param hostname - Optional. Hostname of the target server. The number of threads is limited to the number needed to hack the servers maximum amount of money.
|
||||||
|
* @param cores - Optional. The number of cores of the server that would run grow.
|
||||||
* @returns The security increase.
|
* @returns The security increase.
|
||||||
*/
|
*/
|
||||||
growthAnalyzeSecurity(threads: number): number;
|
growthAnalyzeSecurity(threads: number, hostname?: string, cores?: number): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Suspends the script for n milliseconds.
|
* Suspends the script for n milliseconds.
|
||||||
@ -5129,8 +5167,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
|
||||||
@ -6781,8 +6818,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
|
||||||
@ -6798,6 +6836,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
|
||||||
@ -6805,9 +6859,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
|
||||||
@ -7051,8 +7108,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">
|
||||||
|
@ -51,3 +51,14 @@ export function getSubdirectories(serv: BaseServer, dir: string): string[] {
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true, if the server's directory itself or one of its subdirectory contains files.
|
||||||
|
*/
|
||||||
|
export function containsFiles(server: BaseServer, dir: string): boolean {
|
||||||
|
const dirWithTrailingSlash = dir + (dir.slice(-1) === "/" ? "" : "/");
|
||||||
|
|
||||||
|
return [...server.scripts.map((s) => s.filename), ...server.textFiles.map((t) => t.fn)].some((filename) =>
|
||||||
|
filename.startsWith(dirWithTrailingSlash),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -2,9 +2,10 @@ import { ITerminal } from "../ITerminal";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { showMessage } from "../../Message/MessageHelpers";
|
import { MessageFilenames, showMessage } from "../../Message/MessageHelpers";
|
||||||
import { showLiterature } from "../../Literature/LiteratureHelpers";
|
import { showLiterature } from "../../Literature/LiteratureHelpers";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||||
|
import { checkEnum } from "../../utils/helpers/checkEnum";
|
||||||
|
|
||||||
export function cat(
|
export function cat(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
@ -43,6 +44,7 @@ export function cat(
|
|||||||
} else if (filename.endsWith(".msg")) {
|
} else if (filename.endsWith(".msg")) {
|
||||||
const file = server.messages[i];
|
const file = server.messages[i];
|
||||||
if (file !== filename) continue;
|
if (file !== filename) continue;
|
||||||
|
if (!checkEnum(MessageFilenames, file)) return;
|
||||||
showMessage(file);
|
showMessage(file);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
|||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
import { evaluateDirectoryPath, removeTrailingSlash } from "../DirectoryHelpers";
|
import { evaluateDirectoryPath, removeTrailingSlash } from "../DirectoryHelpers";
|
||||||
|
import { containsFiles } from "../DirectoryServerHelpers";
|
||||||
|
|
||||||
export function cd(
|
export function cd(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
@ -31,10 +32,7 @@ export function cd(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const server = player.getCurrentServer();
|
const server = player.getCurrentServer();
|
||||||
if (
|
if (!containsFiles(server, evaledDir)) {
|
||||||
!server.scripts.some((script) => script.filename.startsWith(evaledDir + "")) &&
|
|
||||||
!server.textFiles.some((file) => file.fn.startsWith(evaledDir + ""))
|
|
||||||
) {
|
|
||||||
terminal.error("Invalid path. Failed to change directories");
|
terminal.error("Invalid path. Failed to change directories");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
<>
|
<>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user