mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-02 04:23:48 +01:00
commit
802f28082d
@ -59,10 +59,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#character-hp-wrapper { color: $my-stat-hp-color; }
|
#character-hp-wrapper { color: $my-stat-hp-color; }
|
||||||
|
.character-hp-cell { color: $my-stat-hp-color; }
|
||||||
#character-money-wrapper { color: $my-stat-money-color; }
|
#character-money-wrapper { color: $my-stat-money-color; }
|
||||||
|
.character-money-cell { color: $my-stat-money-color; }
|
||||||
#character-hack-wrapper { color: $my-stat-hack-color; }
|
#character-hack-wrapper { color: $my-stat-hack-color; }
|
||||||
|
.character-hack-cell { color: $my-stat-hack-color; }
|
||||||
#character-cha-wrapper { color: $my-stat-cha-color; }
|
#character-cha-wrapper { color: $my-stat-cha-color; }
|
||||||
|
.character-cha-cell { color: $my-stat-cha-color; }
|
||||||
#character-int-wrapper { color: $my-stat-int-color; }
|
#character-int-wrapper { color: $my-stat-int-color; }
|
||||||
|
.character-int-cell { color: $my-stat-int-color; }
|
||||||
|
.character-combat-cell { color: $my-stat-physical; }
|
||||||
|
|
||||||
.character-overview-btn {
|
.character-overview-btn {
|
||||||
@include borderRadius(12px);
|
@include borderRadius(12px);
|
||||||
|
@ -17,7 +17,8 @@ body {
|
|||||||
p,
|
p,
|
||||||
pre,
|
pre,
|
||||||
h2,
|
h2,
|
||||||
.text {
|
.text,
|
||||||
|
td {
|
||||||
color: var(--my-font-color);
|
color: var(--my-font-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +80,28 @@ a:visited {
|
|||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#factions-tab {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#factions-notification {
|
||||||
|
font-size: $defaultFontSize * 0.625;
|
||||||
|
position: absolute; /* Position the badge within the relatively positioned button */
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#augmentations-tab {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#augmentations-notification {
|
||||||
|
font-size: $defaultFontSize * 0.625;
|
||||||
|
position: absolute; /* Position the badge within the relatively positioned button */
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.notification-on {
|
.notification-on {
|
||||||
background-color: #fa3e3e;
|
background-color: #fa3e3e;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
4
dist/engine.bundle.js
vendored
4
dist/engine.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/engineStyle.bundle.js
vendored
2
dist/engineStyle.bundle.js
vendored
@ -1,2 +1,2 @@
|
|||||||
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([362,0]),o()}({305:function(n,t,o){},307:function(n,t,o){},309:function(n,t,o){},311:function(n,t,o){},313:function(n,t,o){},315:function(n,t,o){},317:function(n,t,o){},319:function(n,t,o){},321:function(n,t,o){},323:function(n,t,o){},325:function(n,t,o){},327:function(n,t,o){},329:function(n,t,o){},331:function(n,t,o){},333:function(n,t,o){},335:function(n,t,o){},337:function(n,t,o){},339:function(n,t,o){},341:function(n,t,o){},343:function(n,t,o){},345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},362:function(n,t,o){"use strict";o.r(t);o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345),o(343),o(341),o(339),o(337),o(335),o(333),o(331),o(329),o(327),o(325),o(323),o(321),o(319),o(317),o(315),o(313),o(311),o(309),o(307),o(305)}});
|
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([363,0]),o()}({306:function(n,t,o){},308:function(n,t,o){},310:function(n,t,o){},312:function(n,t,o){},314:function(n,t,o){},316:function(n,t,o){},318:function(n,t,o){},320:function(n,t,o){},322:function(n,t,o){},324:function(n,t,o){},326:function(n,t,o){},328:function(n,t,o){},330:function(n,t,o){},332:function(n,t,o){},334:function(n,t,o){},336:function(n,t,o){},338:function(n,t,o){},340:function(n,t,o){},342:function(n,t,o){},344:function(n,t,o){},346:function(n,t,o){},348:function(n,t,o){},350:function(n,t,o){},352:function(n,t,o){},354:function(n,t,o){},356:function(n,t,o){},358:function(n,t,o){},360:function(n,t,o){},363:function(n,t,o){"use strict";o.r(t);o(362),o(360),o(358),o(356),o(354),o(352),o(350),o(348),o(346),o(344),o(342),o(340),o(338),o(336),o(334),o(332),o(330),o(328),o(326),o(324),o(322),o(320),o(318),o(316),o(314),o(312),o(310),o(308),o(306)}});
|
||||||
//# sourceMappingURL=engineStyle.bundle.js.map
|
//# sourceMappingURL=engineStyle.bundle.js.map
|
41
dist/engineStyle.css
vendored
41
dist/engineStyle.css
vendored
@ -26,7 +26,8 @@ body {
|
|||||||
p,
|
p,
|
||||||
pre,
|
pre,
|
||||||
h2,
|
h2,
|
||||||
.text {
|
.text,
|
||||||
|
td {
|
||||||
color: var(--my-font-color); }
|
color: var(--my-font-color); }
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@ -78,6 +79,26 @@ a:visited {
|
|||||||
top: 0;
|
top: 0;
|
||||||
right: 0; }
|
right: 0; }
|
||||||
|
|
||||||
|
#factions-tab {
|
||||||
|
position: relative; }
|
||||||
|
|
||||||
|
#factions-notification {
|
||||||
|
font-size: 10px;
|
||||||
|
position: absolute;
|
||||||
|
/* Position the badge within the relatively positioned button */
|
||||||
|
top: 0;
|
||||||
|
right: 0; }
|
||||||
|
|
||||||
|
#augmentations-tab {
|
||||||
|
position: relative; }
|
||||||
|
|
||||||
|
#augmentations-notification {
|
||||||
|
font-size: 10px;
|
||||||
|
position: absolute;
|
||||||
|
/* Position the badge within the relatively positioned button */
|
||||||
|
top: 0;
|
||||||
|
right: 0; }
|
||||||
|
|
||||||
.notification-on {
|
.notification-on {
|
||||||
background-color: #fa3e3e;
|
background-color: #fa3e3e;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@ -684,18 +705,36 @@ button {
|
|||||||
#character-hp-wrapper {
|
#character-hp-wrapper {
|
||||||
color: #dd3434; }
|
color: #dd3434; }
|
||||||
|
|
||||||
|
.character-hp-cell {
|
||||||
|
color: #dd3434; }
|
||||||
|
|
||||||
#character-money-wrapper {
|
#character-money-wrapper {
|
||||||
color: #ffd700; }
|
color: #ffd700; }
|
||||||
|
|
||||||
|
.character-money-cell {
|
||||||
|
color: #ffd700; }
|
||||||
|
|
||||||
#character-hack-wrapper {
|
#character-hack-wrapper {
|
||||||
color: #adff2f; }
|
color: #adff2f; }
|
||||||
|
|
||||||
|
.character-hack-cell {
|
||||||
|
color: #adff2f; }
|
||||||
|
|
||||||
#character-cha-wrapper {
|
#character-cha-wrapper {
|
||||||
color: #a671d1; }
|
color: #a671d1; }
|
||||||
|
|
||||||
|
.character-cha-cell {
|
||||||
|
color: #a671d1; }
|
||||||
|
|
||||||
#character-int-wrapper {
|
#character-int-wrapper {
|
||||||
color: #6495ed; }
|
color: #6495ed; }
|
||||||
|
|
||||||
|
.character-int-cell {
|
||||||
|
color: #6495ed; }
|
||||||
|
|
||||||
|
.character-combat-cell {
|
||||||
|
color: #faffdf; }
|
||||||
|
|
||||||
.character-overview-btn {
|
.character-overview-btn {
|
||||||
-webkit-border-radius: 12px;
|
-webkit-border-radius: 12px;
|
||||||
-moz-border-radius: 12px;
|
-moz-border-radius: 12px;
|
||||||
|
24
dist/vendor.bundle.js
vendored
24
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -3,6 +3,49 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
||||||
|
v0.48.0 - ASCII - 2020-03-07
|
||||||
|
-------
|
||||||
|
|
||||||
|
**ASCII**
|
||||||
|
* Travel Agency now displays a world map
|
||||||
|
* Cities are now top view of metro station maps
|
||||||
|
|
||||||
|
**Netscript**
|
||||||
|
* 'softReset' is a new netscript function that performs a soft reset
|
||||||
|
regardless of if the player has bought augmentations or not.
|
||||||
|
* 'getAugmentationStats' is a new netscript function that returns the stats of
|
||||||
|
an augmentation.
|
||||||
|
* getCharacterInformation now additionally returns exp
|
||||||
|
* pid resets back to 1 when installing or destroying a BitNode.
|
||||||
|
* New '.ns' scripts start with a main function.
|
||||||
|
* 'hacknet.maxNumNodes' returns the maximum number of hacknet nodes.
|
||||||
|
|
||||||
|
**Bladeburner**
|
||||||
|
* Current stamina will scale as max stamina increases, this prevents players
|
||||||
|
from having very high penalty when they gain huge amount of exp at the
|
||||||
|
start of a reset.
|
||||||
|
|
||||||
|
**Misc.**
|
||||||
|
* Fixed an issue where SF3 was listed as infinitly repeatable and SF12 as
|
||||||
|
having a limit of 3.
|
||||||
|
* Fixed an issue where the gang equipment screen would freeze the game if a
|
||||||
|
script installed augmentations while it is open.
|
||||||
|
* All BonusTime now displays in the 'H M S' format.
|
||||||
|
* Donation textbox style updated to match the rest of the game.
|
||||||
|
* Corporation name style updated to match the rest of the game.
|
||||||
|
* minor formatting under Hacking>Active Scripts
|
||||||
|
* typo in BN12 description
|
||||||
|
* BN12 now reduces contract money
|
||||||
|
* Character>Stats percentages are aligned, server and hacknet limit are
|
||||||
|
displayed, if the player has SF5 the reduces stats are shown.
|
||||||
|
* Character>Augmentations now displays by how much the player stats will
|
||||||
|
increase.
|
||||||
|
* Character>Augmentations has a badge indicating how many augs the player
|
||||||
|
has bought but not installed
|
||||||
|
* Character>Factions has a badge indicating how many factions have pending
|
||||||
|
invites.
|
||||||
|
|
||||||
v0.47.2 - 7/15/2019
|
v0.47.2 - 7/15/2019
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
8
doc/source/netscript/hacknetnodeapi/maxNumNodes.rst
Normal file
8
doc/source/netscript/hacknetnodeapi/maxNumNodes.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
maxNumNodes() Netscript Function
|
||||||
|
=============================
|
||||||
|
|
||||||
|
.. js:function:: maxNumNodes()
|
||||||
|
|
||||||
|
:RAM cost: 0 GB
|
||||||
|
|
||||||
|
Returns the maximum number of Hacknet Nodes you can own.
|
@ -0,0 +1,16 @@
|
|||||||
|
getAugmentationStats() Netscript Function
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
.. js:function:: getAugmentationStats(name)
|
||||||
|
|
||||||
|
:RAM cost: 5 GB
|
||||||
|
|
||||||
|
:param string name: Name of Augmentation. CASE-SENSITIVE
|
||||||
|
|
||||||
|
If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.
|
||||||
|
|
||||||
|
ns.getAugmentationStats("Synfibril Muscle")
|
||||||
|
{
|
||||||
|
strength_mult: 1.3,
|
||||||
|
defense_mult: 1.3,
|
||||||
|
}
|
@ -49,4 +49,10 @@ getCharacterInformation() Netscript Function
|
|||||||
workChaExpGain: Cha experience earned so far from work
|
workChaExpGain: Cha experience earned so far from work
|
||||||
workRepGain: Reputation earned so far from work, if applicable
|
workRepGain: Reputation earned so far from work, if applicable
|
||||||
workMoneyGain: Money earned so far from work, if applicable
|
workMoneyGain: Money earned so far from work, if applicable
|
||||||
|
hackingExp: Total hacking experience
|
||||||
|
strengthExp: Total strength experience
|
||||||
|
defenseExp: Total defense experience
|
||||||
|
dexterityExp: Total dexterity experience
|
||||||
|
agilityExp: Total agility experience
|
||||||
|
charismaExp: Total charisma experience
|
||||||
}
|
}
|
||||||
|
8
doc/source/netscript/singularityfunctions/softReset.rst
Normal file
8
doc/source/netscript/singularityfunctions/softReset.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
softReset() Netscript Function
|
||||||
|
===================================
|
||||||
|
|
||||||
|
.. js:function:: softReset()
|
||||||
|
|
||||||
|
If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.
|
||||||
|
|
||||||
|
This function will perform a reset even if you don't have any augmentation installed.
|
@ -58,9 +58,11 @@
|
|||||||
</li>
|
</li>
|
||||||
<li id="factions-tab" class="mainmenu-accordion-panel">
|
<li id="factions-tab" class="mainmenu-accordion-panel">
|
||||||
<button id="factions-menu-link"> Factions </button>
|
<button id="factions-menu-link"> Factions </button>
|
||||||
|
<span id="factions-notification" class="notification-off"> </span>
|
||||||
</li>
|
</li>
|
||||||
<li id="augmentations-tab" class="mainmenu-accordion-panel">
|
<li id="augmentations-tab" class="mainmenu-accordion-panel">
|
||||||
<button id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> Augmentations </button>
|
<button id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> Augmentations </button>
|
||||||
|
<span id="augmentations-notification" class="notification-off"> </span>
|
||||||
</li>
|
</li>
|
||||||
<li id="hacknet-nodes-tab" class="mainmenu-accordion-panel">
|
<li id="hacknet-nodes-tab" class="mainmenu-accordion-panel">
|
||||||
<button id="hacknet-nodes-menu-link"> Hacknet Nodes </button>
|
<button id="hacknet-nodes-menu-link"> Hacknet Nodes </button>
|
||||||
|
@ -5,92 +5,104 @@ import * as React from "react";
|
|||||||
|
|
||||||
import { Player } from "../../Player";
|
import { Player } from "../../Player";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
import { Augmentations} from "../Augmentations";
|
||||||
|
|
||||||
|
function calculateAugmentedStats() {
|
||||||
|
const augP: any = {};
|
||||||
|
for(const aug of Player.queuedAugmentations) {
|
||||||
|
const augObj = Augmentations[aug.name];
|
||||||
|
for (const mult in augObj.mults) {
|
||||||
|
const v = augP[mult] ? augP[mult] : 1;
|
||||||
|
augP[mult] = v * augObj.mults[mult];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return augP;
|
||||||
|
}
|
||||||
|
|
||||||
export function PlayerMultipliers(): React.ReactElement {
|
export function PlayerMultipliers(): React.ReactElement {
|
||||||
|
const mults = calculateAugmentedStats();
|
||||||
|
function MultiplierTable(rows: any[]): React.ReactElement {
|
||||||
|
function improvements(r: number) {
|
||||||
|
let elems: any[] = [];
|
||||||
|
if(r) {
|
||||||
|
elems = [
|
||||||
|
<td key='2'> => </td>,
|
||||||
|
<td key='3'>{numeralWrapper.formatPercentage(r)}</td>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return elems;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <table>
|
||||||
|
<tbody>
|
||||||
|
{rows.map((r: any) => <tr key={r[0]}>
|
||||||
|
<td key='0'><span>{r[0]} multiplier: </span></td>
|
||||||
|
<td key='1' style={{textAlign: 'right'}}>{numeralWrapper.formatPercentage(r[1])}</td>
|
||||||
|
{improvements(r[2])}
|
||||||
|
</tr>)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p><strong><u>Total Multipliers:</u></strong></p>
|
<p><strong><u>Multipliers:</u></strong></p><br />
|
||||||
|
{MultiplierTable([
|
||||||
|
['Hacking Chance ', Player.hacking_chance_mult, Player.hacking_chance_mult*mults.hacking_chance_mult],
|
||||||
|
['Hacking Speed ', Player.hacking_speed_mult, Player.hacking_speed_mult*mults.hacking_speed_mult],
|
||||||
|
['Hacking Money ', Player.hacking_money_mult, Player.hacking_money_mult*mults.hacking_money_mult],
|
||||||
|
['Hacking Growth ', Player.hacking_grow_mult, Player.hacking_grow_mult*mults.hacking_grow_mult]
|
||||||
|
])}<br />
|
||||||
|
|
||||||
<pre>
|
{MultiplierTable([
|
||||||
{'Hacking Chance multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_chance_mult)}
|
['Hacking Level ', Player.hacking_mult, Player.hacking_mult*mults.hacking_mult],
|
||||||
</pre>
|
['Hacking Experience ', Player.hacking_exp_mult, Player.hacking_exp_mult*mults.hacking_exp_mult]
|
||||||
<pre>
|
])}<br />
|
||||||
{'Hacking Speed multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_speed_mult)}
|
|
||||||
</pre>
|
|
||||||
<pre>
|
{MultiplierTable([
|
||||||
{'Hacking Money multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_money_mult)}
|
['Strength Level ', Player.strength_mult, Player.strength_mult*mults.strength_mult],
|
||||||
</pre>
|
['Strength Experience ', Player.strength_exp_mult, Player.strength_exp_mult*mults.strength_exp_mult]
|
||||||
<pre>
|
])}<br />
|
||||||
{'Hacking Growth multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_grow_mult)}
|
|
||||||
</pre><br />
|
{MultiplierTable([
|
||||||
<pre>
|
['Defense Level ', Player.defense_mult, Player.defense_mult*mults.defense_mult],
|
||||||
{'Hacking Level multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_mult)}
|
['Defense Experience ', Player.defense_exp_mult, Player.defense_exp_mult*mults.defense_exp_mult]
|
||||||
</pre>
|
])}<br />
|
||||||
<pre>
|
|
||||||
{'Hacking Experience multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_exp_mult)}
|
{MultiplierTable([
|
||||||
</pre>
|
['Dexterity Level ', Player.dexterity_mult, Player.dexterity_mult*mults.dexterity_mult],
|
||||||
<br />
|
['Dexterity Experience ', Player.dexterity_exp_mult, Player.dexterity_exp_mult*mults.dexterity_exp_mult]
|
||||||
<pre>
|
])}<br />
|
||||||
{'Strength Level multiplier: ' + numeralWrapper.formatPercentage(Player.strength_mult)}
|
|
||||||
</pre>
|
{MultiplierTable([
|
||||||
<pre>
|
['Agility Level ', Player.agility_mult, Player.agility_mult*mults.agility_mult],
|
||||||
{'Strength Experience multiplier: ' + numeralWrapper.formatPercentage(Player.strength_exp_mult)}
|
['Agility Experience ', Player.agility_exp_mult, Player.agility_exp_mult*mults.agility_exp_mult]
|
||||||
</pre>
|
])}<br />
|
||||||
<br />
|
|
||||||
<pre>
|
{MultiplierTable([
|
||||||
{'Defense Level multiplier: ' + numeralWrapper.formatPercentage(Player.defense_mult)}
|
['Charisma Level ', Player.charisma_mult, Player.charisma_mult*mults.charisma_mult],
|
||||||
</pre>
|
['Charisma Experience ', Player.charisma_exp_mult, Player.charisma_exp_mult*mults.charisma_exp_mult]
|
||||||
<pre>
|
])}<br />
|
||||||
{'Defense Experience multiplier: ' + numeralWrapper.formatPercentage(Player.defense_exp_mult)}
|
|
||||||
</pre><br />
|
{MultiplierTable([
|
||||||
<pre>
|
['Hacknet Node production ', Player.hacknet_node_money_mult, Player.hacknet_node_money_mult*mults.hacknet_node_money_mult],
|
||||||
{'Dexterity Level multiplier: ' + numeralWrapper.formatPercentage(Player.dexterity_mult)}
|
['Hacknet Node purchase cost ', Player.hacknet_node_purchase_cost_mult, Player.hacknet_node_purchase_cost_mult*mults.hacknet_node_purchase_cost_mult],
|
||||||
</pre>
|
['Hacknet Node RAM upgrade cost ', Player.hacknet_node_ram_cost_mult, Player.hacknet_node_ram_cost_mult*mults.hacknet_node_ram_cost_mult],
|
||||||
<pre>
|
['Hacknet Node Core purchase cost ', Player.hacknet_node_core_cost_mult, Player.hacknet_node_core_cost_mult*mults.hacknet_node_core_cost_mult],
|
||||||
{'Dexterity Experience multiplier: ' + numeralWrapper.formatPercentage(Player.dexterity_exp_mult)}
|
['Hacknet Node level upgrade cost ', Player.hacknet_node_level_cost_mult, Player.hacknet_node_level_cost_mult*mults.hacknet_node_level_cost_mult]
|
||||||
</pre><br />
|
])}<br />
|
||||||
<pre>
|
|
||||||
{'Agility Level multiplier: ' + numeralWrapper.formatPercentage(Player.agility_mult)}
|
{MultiplierTable([
|
||||||
</pre>
|
['Company reputation gain ', Player.company_rep_mult, Player.company_rep_mult*mults.company_rep_mult],
|
||||||
<pre>
|
['Faction reputation gain ', Player.faction_rep_mult, Player.faction_rep_mult*mults.faction_rep_mult],
|
||||||
{'Agility Experience multiplier: ' + numeralWrapper.formatPercentage(Player.agility_exp_mult)}
|
['Salary ', Player.work_money_mult, Player.work_money_mult*mults.work_money_mult]
|
||||||
</pre><br />
|
])}<br />
|
||||||
<pre>
|
|
||||||
{'Charisma Level multiplier: ' + numeralWrapper.formatPercentage(Player.charisma_mult)}
|
{MultiplierTable([
|
||||||
</pre>
|
['Crime success ', Player.crime_success_mult, Player.crime_success_mult*mults.crime_success_mult],
|
||||||
<pre>
|
['Crime money ', Player.crime_money_mult, Player.crime_money_mult*mults.crime_money_mult],
|
||||||
{'Charisma Experience multiplier: ' + numeralWrapper.formatPercentage(Player.charisma_exp_mult)}
|
])}<br />
|
||||||
</pre><br />
|
|
||||||
<pre>
|
|
||||||
{'Hacknet Node production multiplier: ' + numeralWrapper.formatPercentage(Player.hacknet_node_money_mult)}
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
{'Hacknet Node purchase cost multiplier: ' + numeralWrapper.formatPercentage(Player.hacknet_node_purchase_cost_mult)}
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
{'Hacknet Node RAM upgrade cost multiplier: ' + numeralWrapper.formatPercentage(Player.hacknet_node_ram_cost_mult)}
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
{'Hacknet Node Core purchase cost multiplier: ' + numeralWrapper.formatPercentage(Player.hacknet_node_core_cost_mult)}
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
{'Hacknet Node level upgrade cost multiplier: ' + numeralWrapper.formatPercentage(Player.hacknet_node_level_cost_mult)}
|
|
||||||
</pre><br />
|
|
||||||
<pre>
|
|
||||||
{'Company reputation gain multiplier: ' + numeralWrapper.formatPercentage(Player.company_rep_mult)}
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
{'Faction reputation gain multiplier: ' + numeralWrapper.formatPercentage(Player.faction_rep_mult)}
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
{'Salary multiplier: ' + numeralWrapper.formatPercentage(Player.work_money_mult)}
|
|
||||||
</pre><br />
|
|
||||||
<pre>
|
|
||||||
{'Crime success multiplier: ' + numeralWrapper.formatPercentage(Player.crime_success_mult)}
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
{'Crime money multiplier: ' + numeralWrapper.formatPercentage(Player.crime_money_mult)}
|
|
||||||
</pre>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
|
|||||||
"Level 3: 56%");
|
"Level 3: 56%");
|
||||||
BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
|
BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
|
||||||
"To iterate is human, to recurse divine.<br><br>" +
|
"To iterate is human, to recurse divine.<br><br>" +
|
||||||
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give your Souce-File 12, or " +
|
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Souce-File 12, or " +
|
||||||
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
|
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
|
||||||
"of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " +
|
"of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " +
|
||||||
"In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)");
|
"In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)");
|
||||||
@ -465,6 +465,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
|||||||
BitNodeMultipliers.CompanyWorkMoney = dec;
|
BitNodeMultipliers.CompanyWorkMoney = dec;
|
||||||
BitNodeMultipliers.CrimeMoney = dec;
|
BitNodeMultipliers.CrimeMoney = dec;
|
||||||
BitNodeMultipliers.HacknetNodeMoney = dec;
|
BitNodeMultipliers.HacknetNodeMoney = dec;
|
||||||
|
BitNodeMultipliers.CodingContractMoney = dec;
|
||||||
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain = dec;
|
BitNodeMultipliers.CompanyWorkExpGain = dec;
|
||||||
BitNodeMultipliers.ClassGymExpGain = dec;
|
BitNodeMultipliers.ClassGymExpGain = dec;
|
||||||
|
@ -31,6 +31,7 @@ import { KEY } from "../utils/helpers/keyCodes";
|
|||||||
|
|
||||||
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
||||||
import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks";
|
import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks";
|
||||||
|
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||||
import { createElement } from "../utils/uiHelpers/createElement";
|
import { createElement } from "../utils/uiHelpers/createElement";
|
||||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||||
import { removeElement } from "../utils/uiHelpers/removeElement";
|
import { removeElement } from "../utils/uiHelpers/removeElement";
|
||||||
@ -991,12 +992,16 @@ Bladeburner.prototype.process = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bladeburner.prototype.calculateMaxStamina = function() {
|
Bladeburner.prototype.calculateMaxStamina = function() {
|
||||||
var effAgility = Player.agility * this.skillMultipliers.effAgi;
|
const effAgility = Player.agility * this.skillMultipliers.effAgi;
|
||||||
var maxStamina = (Math.pow(effAgility, 0.8) + this.staminaBonus);
|
let maxStamina = (Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
||||||
maxStamina *= this.skillMultipliers.stamina;
|
this.skillMultipliers.stamina *
|
||||||
maxStamina *= Player.bladeburner_max_stamina_mult;
|
Player.bladeburner_max_stamina_mult;
|
||||||
if (isNaN(maxStamina)) {throw new Error("Max Stamina calculated to be NaN in Bladeburner.calculateMaxStamina()");}
|
if (this.maxStamina !== maxStamina) {
|
||||||
|
const oldMax = this.maxStamina;
|
||||||
this.maxStamina = maxStamina;
|
this.maxStamina = maxStamina;
|
||||||
|
this.stamina = this.maxStamina * this.stamina / oldMax;
|
||||||
|
}
|
||||||
|
if (isNaN(maxStamina)) {throw new Error("Max Stamina calculated to be NaN in Bladeburner.calculateMaxStamina()");}
|
||||||
}
|
}
|
||||||
|
|
||||||
Bladeburner.prototype.calculateStaminaGainPerSecond = function() {
|
Bladeburner.prototype.calculateStaminaGainPerSecond = function() {
|
||||||
@ -2349,7 +2354,7 @@ Bladeburner.prototype.updateOverviewContent = function() {
|
|||||||
DomElems.overviewEstComms.childNodes[0].nodeValue = "Est. Synthoid Communities: " + formatNumber(this.getCurrentCity().comms, 0);
|
DomElems.overviewEstComms.childNodes[0].nodeValue = "Est. Synthoid Communities: " + formatNumber(this.getCurrentCity().comms, 0);
|
||||||
DomElems.overviewChaos.childNodes[0].nodeValue = "City Chaos: " + formatNumber(this.getCurrentCity().chaos);
|
DomElems.overviewChaos.childNodes[0].nodeValue = "City Chaos: " + formatNumber(this.getCurrentCity().chaos);
|
||||||
DomElems.overviewSkillPoints.innerText = "Skill Points: " + formatNumber(this.skillPoints, 0);
|
DomElems.overviewSkillPoints.innerText = "Skill Points: " + formatNumber(this.skillPoints, 0);
|
||||||
DomElems.overviewBonusTime.childNodes[0].nodeValue = "Bonus time: " + this.storedCycles/CyclesPerSecond;
|
DomElems.overviewBonusTime.childNodes[0].nodeValue = "Bonus time: " + convertTimeMsToTimeElapsedString(this.storedCycles/CyclesPerSecond*1000);
|
||||||
DomElems.overviewAugSuccessMult.innerText = "Aug. Success Chance Mult: " + formatNumber(Player.bladeburner_success_chance_mult*100, 1) + "%";
|
DomElems.overviewAugSuccessMult.innerText = "Aug. Success Chance Mult: " + formatNumber(Player.bladeburner_success_chance_mult*100, 1) + "%";
|
||||||
DomElems.overviewAugMaxStaminaMult.innerText = "Aug. Max Stamina Mult: " + formatNumber(Player.bladeburner_max_stamina_mult*100, 1) + "%";
|
DomElems.overviewAugMaxStaminaMult.innerText = "Aug. Max Stamina Mult: " + formatNumber(Player.bladeburner_max_stamina_mult*100, 1) + "%";
|
||||||
DomElems.overviewAugStaminaGainMult.innerText = "Aug. Stamina Gain Mult: " + formatNumber(Player.bladeburner_stamina_gain_mult*100, 1) + "%";
|
DomElems.overviewAugStaminaGainMult.innerText = "Aug. Stamina Gain Mult: " + formatNumber(Player.bladeburner_stamina_gain_mult*100, 1) + "%";
|
||||||
|
@ -74,7 +74,6 @@ for (const md of codingContractTypesMetadata) {
|
|||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
CodingContractTypes[md.name] = new CodingContractType(md.name, md.desc, md.gen, md.solver, md.difficulty, md.numTries);
|
CodingContractTypes[md.name] = new CodingContractType(md.name, md.desc, md.gen, md.solver, md.difficulty, md.numTries);
|
||||||
}
|
}
|
||||||
console.info(`${Object.keys(CodingContractTypes).length} Coding Contract Types loaded`);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum representing the different types of rewards a Coding Contract can give
|
* Enum representing the different types of rewards a Coding Contract can give
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import { IMap } from "./types";
|
import { IMap } from "./types";
|
||||||
|
|
||||||
export let CONSTANTS: IMap<any> = {
|
export let CONSTANTS: IMap<any> = {
|
||||||
Version: "0.47.3",
|
Version: "0.48.0",
|
||||||
|
|
||||||
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
|
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
|
||||||
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
|
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
|
||||||
@ -228,11 +228,46 @@ export let CONSTANTS: IMap<any> = {
|
|||||||
|
|
||||||
LatestUpdate:
|
LatestUpdate:
|
||||||
`
|
`
|
||||||
v0.47.3
|
v0.48.0 - ASCII
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
ASCII
|
||||||
|
* Travel Agency now displays a world map
|
||||||
|
* Cities are now top view of metro station maps
|
||||||
|
|
||||||
|
Netscript
|
||||||
|
* 'softReset' is a new netscript function that performs a soft reset
|
||||||
|
regardless of if the player has bought augmentations or not.
|
||||||
|
* 'getAugmentationStats' is a new netscript function that returns the stats of
|
||||||
|
an augmentation.
|
||||||
|
* getCharacterInformation now additionally returns exp
|
||||||
|
* pid resets back to 1 when installing or destroying a BitNode.
|
||||||
|
* New '.ns' scripts start with a main function.
|
||||||
|
* 'hacknet.maxNumNodes' returns the maximum number of hacknet nodes.
|
||||||
|
|
||||||
|
Bladeburner
|
||||||
|
* Current stamina will scale as max stamina increases, this prevents players
|
||||||
|
from having very high penalty when they gain huge amount of exp at the
|
||||||
|
start of a reset.
|
||||||
|
|
||||||
Misc.
|
Misc.
|
||||||
* missing ram cost in many function now added to documentation
|
* Fixed an issue where SF3 was listed as infinitly repeatable and SF12 as
|
||||||
* typos
|
having a limit of 3.
|
||||||
|
* Fixed an issue where the gang equipment screen would freeze the game if a
|
||||||
|
script installed augmentations while it is open.
|
||||||
|
* All BonusTime now displays in the 'H M S' format.
|
||||||
|
* Donation textbox style updated to match the rest of the game.
|
||||||
|
* Corporation name style updated to match the rest of the game.
|
||||||
|
* minor formatting under Hacking>Active Scripts
|
||||||
|
* typo in BN12 description
|
||||||
|
* BN12 now reduces contract money
|
||||||
|
* Character>Stats percentages are aligned, server and hacknet limit are
|
||||||
|
displayed, if the player has SF5 the reduces stats are shown.
|
||||||
|
* Character>Augmentations now displays by how much the player stats will
|
||||||
|
increase.
|
||||||
|
* Character>Augmentations has a badge indicating how many augs the player
|
||||||
|
has bought but not installed
|
||||||
|
* Character>Factions has a badge indicating how many factions have pending
|
||||||
|
invites.
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import { CorporationUpgrades } from "../data/CorporationUpgrades";
|
|||||||
|
|
||||||
import { CONSTANTS } from "../../Constants";
|
import { CONSTANTS } from "../../Constants";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
|
||||||
|
|
||||||
export class Overview extends BaseReactComponent {
|
export class Overview extends BaseReactComponent {
|
||||||
// Generic Function for Creating a button
|
// Generic Function for Creating a button
|
||||||
@ -71,9 +72,9 @@ export class Overview extends BaseReactComponent {
|
|||||||
`Private Shares: ${numeralWrapper.format(this.corp().totalShares - this.corp().issuedShares - this.corp().numShares, "0.000a")}` +
|
`Private Shares: ${numeralWrapper.format(this.corp().totalShares - this.corp().issuedShares - this.corp().numShares, "0.000a")}` +
|
||||||
"</span></p><br><br>";
|
"</span></p><br><br>";
|
||||||
|
|
||||||
const storedTime = this.corp().storedCycles * CONSTANTS.MilliPerCycle / 1000;
|
const storedTime = this.corp().storedCycles * CONSTANTS.MilliPerCycle;
|
||||||
if (storedTime > 15) {
|
if (storedTime > 15000) {
|
||||||
txt += `Bonus Time: ${storedTime} seconds<br><br>`;
|
txt += `Bonus time: ${convertTimeMsToTimeElapsedString(storedTime)}<br><br>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let prodMult = this.corp().getProductionMultiplier(),
|
let prodMult = this.corp().getProductionMultiplier(),
|
||||||
|
@ -88,7 +88,7 @@ export class DonateOption extends React.Component<IProps, IState> {
|
|||||||
return (
|
return (
|
||||||
<div className={"faction-work-div"}>
|
<div className={"faction-work-div"}>
|
||||||
<div className={"faction-work-div-wrapper"}>
|
<div className={"faction-work-div-wrapper"}>
|
||||||
<input onChange={this.handleChange} placeholder={"Donation amount"} style={inputStyleMarkup} />
|
<input className='text-input' onChange={this.handleChange} placeholder={"Donation amount"} style={inputStyleMarkup} />
|
||||||
<StdButton
|
<StdButton
|
||||||
onClick={this.donate}
|
onClick={this.donate}
|
||||||
text={"Donate Money"}
|
text={"Donate Money"}
|
||||||
|
@ -33,6 +33,7 @@ import { createPopup } from "../utils/uiHelpers/createPopup";
|
|||||||
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
||||||
import { removeElement } from "../utils/uiHelpers/removeElement";
|
import { removeElement } from "../utils/uiHelpers/removeElement";
|
||||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||||
|
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||||
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
@ -1570,7 +1571,9 @@ Gang.prototype.updateGangContent = function() {
|
|||||||
// Update territory information
|
// Update territory information
|
||||||
UIElems.gangTerritoryInfoText.innerHTML = "";
|
UIElems.gangTerritoryInfoText.innerHTML = "";
|
||||||
const playerPower = AllGangs[this.facName].power;
|
const playerPower = AllGangs[this.facName].power;
|
||||||
for (const gangname in AllGangs) {
|
let gangNames = Object.keys(AllGangs).filter(g => g != this.facName);
|
||||||
|
gangNames.unshift(this.facName);
|
||||||
|
for (const gangname of gangNames) {
|
||||||
if (AllGangs.hasOwnProperty(gangname)) {
|
if (AllGangs.hasOwnProperty(gangname)) {
|
||||||
const gangTerritoryInfo = AllGangs[gangname];
|
const gangTerritoryInfo = AllGangs[gangname];
|
||||||
let territory = gangTerritoryInfo.territory * 100;
|
let territory = gangTerritoryInfo.territory * 100;
|
||||||
@ -1670,7 +1673,7 @@ Gang.prototype.updateGangContent = function() {
|
|||||||
|
|
||||||
const CyclesPerSecond = 1000 / Engine._idleSpeed;
|
const CyclesPerSecond = 1000 / Engine._idleSpeed;
|
||||||
UIElems.gangInfo.appendChild(createElement("p", { // Stored Cycles
|
UIElems.gangInfo.appendChild(createElement("p", { // Stored Cycles
|
||||||
innerText: `Bonus time(s): ${this.storedCycles / CyclesPerSecond}`,
|
innerText: `Bonus time: ${convertTimeMsToTimeElapsedString(this.storedCycles / CyclesPerSecond*1000)}`,
|
||||||
display: "inline-block",
|
display: "inline-block",
|
||||||
tooltip: "You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by the browser). " +
|
tooltip: "You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by the browser). " +
|
||||||
"Bonus time makes the Gang mechanic progress faster, up to 5x the normal speed",
|
"Bonus time makes the Gang mechanic progress faster, up to 5x the normal speed",
|
||||||
@ -1942,6 +1945,8 @@ Gang.prototype.setGangMemberTaskDescription = function(memberObj, taskName) {
|
|||||||
Gang.prototype.clearUI = function() {
|
Gang.prototype.clearUI = function() {
|
||||||
if (UIElems.gangContainer instanceof Element) { removeElement(UIElems.gangContainer); }
|
if (UIElems.gangContainer instanceof Element) { removeElement(UIElems.gangContainer); }
|
||||||
|
|
||||||
|
if (UIElems.gangMemberUpgradeBox instanceof Element) { removeElement(UIElems.gangMemberUpgradeBox); }
|
||||||
|
|
||||||
for (const prop in UIElems) {
|
for (const prop in UIElems) {
|
||||||
UIElems[prop] = null;
|
UIElems[prop] = null;
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,15 @@ export class City {
|
|||||||
*/
|
*/
|
||||||
name: CityName;
|
name: CityName;
|
||||||
|
|
||||||
constructor(name: CityName, locations: LocationName[]=[]) {
|
/**
|
||||||
|
* Metro map ascii art
|
||||||
|
*/
|
||||||
|
asciiArt: string;
|
||||||
|
|
||||||
|
constructor(name: CityName, locations: LocationName[]=[], asciiArt: string='') {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.locations = locations;
|
this.locations = locations;
|
||||||
|
this.asciiArt = asciiArt;
|
||||||
}
|
}
|
||||||
|
|
||||||
addLocation(loc: LocationName): void {
|
addLocation(loc: LocationName): void {
|
||||||
|
@ -40,6 +40,181 @@ Cities[CityName.NewTokyo] = new City(CityName.NewTokyo);
|
|||||||
Cities[CityName.Sector12] = new City(CityName.Sector12);
|
Cities[CityName.Sector12] = new City(CityName.Sector12);
|
||||||
Cities[CityName.Volhaven] = new City(CityName.Volhaven);
|
Cities[CityName.Volhaven] = new City(CityName.Volhaven);
|
||||||
|
|
||||||
|
Cities[CityName.Aevum].asciiArt = `
|
||||||
|
[aevum police headquarters] 26
|
||||||
|
o
|
||||||
|
I \\ [bachman & associates]
|
||||||
|
\\ 56 B
|
||||||
|
x \\ [summit university]
|
||||||
|
\\ \\ 28
|
||||||
|
\\ [snap fitness gym] x o--L------------
|
||||||
|
K \\ /
|
||||||
|
\\ \\ P
|
||||||
|
x 58 \\ / [travel agency]
|
||||||
|
\\ 94 95 o
|
||||||
|
90 x 59 o------o |
|
||||||
|
\\ / \\ | 98 102 103
|
||||||
|
o--------N------x----o 93 96 o-----+------------o o----o
|
||||||
|
\\ | \\ /
|
||||||
|
[hospital] \\ 61 [ecorp] x 31 99 o-F-o 101
|
||||||
|
o |
|
||||||
|
| o---E-- | [fulcrum tech.]
|
||||||
|
x 62 / A [aerocorp]
|
||||||
|
[crush fitness gym] | / |
|
||||||
|
| / |
|
||||||
|
o--------D------+--o o
|
||||||
|
| |\\ [rho construction]
|
||||||
|
H [netlink tech.] | J
|
||||||
|
| | \\
|
||||||
|
| 34 x \\
|
||||||
|
[clarke inc.] C | \\ [world stock exchange]
|
||||||
|
| | \\
|
||||||
|
| | o-M-------Q--------o
|
||||||
|
[galactic cybersystems] G 35 x
|
||||||
|
| [watchdog security]
|
||||||
|
|
|
||||||
|
67 o
|
||||||
|
|
||||||
|
[the slums] O `
|
||||||
|
Cities[CityName.Chongqing].asciiArt = `
|
||||||
|
|
|
||||||
|
75 o
|
||||||
|
\\
|
||||||
|
o 76
|
||||||
|
7 | |
|
||||||
|
| + 77
|
||||||
|
[world stock exchange] F |
|
||||||
|
\\ o 78 [kuaigong international]
|
||||||
|
\\ /
|
||||||
|
38 o----x--x------x------A---------
|
||||||
|
/ 39 | 41
|
||||||
|
37 o + 79 o--x--x-C-0
|
||||||
|
/ | /
|
||||||
|
/ x-----+-----x-----0 [hospital]
|
||||||
|
[solaris space system] B |
|
||||||
|
| + 80
|
||||||
|
| |
|
||||||
|
34 o E [travel agency]
|
||||||
|
|
|
||||||
|
|
|
||||||
|
x 82
|
||||||
|
[the slums] D `
|
||||||
|
Cities[CityName.Ishima].asciiArt = `
|
||||||
|
o 59
|
||||||
|
o o |
|
||||||
|
[storm tech.] | | G [world stock exchange]
|
||||||
|
| | 28 |
|
||||||
|
23 o--C------o--------+----x----o |
|
||||||
|
/ / 25 | 27 \\ x 57
|
||||||
|
/ / | \\ |
|
||||||
|
/ / | \\ |
|
||||||
|
o 22 o | \\| 29/56
|
||||||
|
| | o
|
||||||
|
| [hospital] D / \\ 3 2 1
|
||||||
|
o | / \\ o-------x------o
|
||||||
|
/ o / \\ /
|
||||||
|
48 o / 55 x \\ /
|
||||||
|
\\ / / x
|
||||||
|
\\ / [nova medical] / 4/30 \\
|
||||||
|
49 x A \\
|
||||||
|
/ \\ / \\
|
||||||
|
/ \\ [travel agency] F o 31
|
||||||
|
/ \\ 51 /
|
||||||
|
/ o----B------x-----o
|
||||||
|
o 50 52
|
||||||
|
[omega soft.]
|
||||||
|
[the slums] E `
|
||||||
|
Cities[CityName.NewTokyo].asciiArt = `
|
||||||
|
|
||||||
|
|
||||||
|
o
|
||||||
|
\\
|
||||||
|
\\ [defcomm]
|
||||||
|
\\
|
||||||
|
o--x---A--x--o [travel agency]
|
||||||
|
7 8 10 G
|
||||||
|
[vitalife] o 12 [global pharmaceuticals]
|
||||||
|
|
|
||||||
|
o--D-x----x-------x-C-+--------x--x-B-x---x-o
|
||||||
|
21 22 23 \\ 24 25 26 27
|
||||||
|
\\
|
||||||
|
[noodle bar] x 14
|
||||||
|
\\
|
||||||
|
\\
|
||||||
|
[hospital] o 15 [world stock exchange]
|
||||||
|
|
|
||||||
|
o--x--E--x-----x-----x---+---x----x--H--x-o
|
||||||
|
|
|
||||||
|
|
|
||||||
|
o 17
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
F [the slums]
|
||||||
|
`
|
||||||
|
Cities[CityName.Sector12].asciiArt = `
|
||||||
|
78 o 97
|
||||||
|
o [icarus microsystems] /
|
||||||
|
N [powerhouse gym] o I
|
||||||
|
1 | | /
|
||||||
|
o-----+---x----o 4 A [alpha ent.] o-------o /
|
||||||
|
| 3 \\ | \\ /
|
||||||
|
| \\ | [iron gym] x 95
|
||||||
|
(79) x \\ | / \\
|
||||||
|
| o-E----+----x----J--o 10 / o----T--o
|
||||||
|
| | 8 \\ 94 x
|
||||||
|
80 x [city hall] | x 11 / [world stock exchange]
|
||||||
|
| | \\ /
|
||||||
|
| C [cia] \\ /
|
||||||
|
Q [hospital] | F P [universal energy]
|
||||||
|
| o [deltaone] \\ /
|
||||||
|
| 35 o---------x 13/92/36
|
||||||
|
L [megacorp] 33 / / \\
|
||||||
|
| o------------o 34 / \\
|
||||||
|
(29) | / [carmichael sec.] D \\
|
||||||
|
o-----+-----x------o / O [rothman university]
|
||||||
|
| 31 32 [nsa] M
|
||||||
|
| /
|
||||||
|
B [blade industries] H
|
||||||
|
| / [four sigma]
|
||||||
|
| [joe's guns] /
|
||||||
|
| /
|
||||||
|
85 o--G--------K--------S-------o 88 [the slums] R
|
||||||
|
|
||||||
|
[foodnstuff] [travel agency] `
|
||||||
|
Cities[CityName.Volhaven].asciiArt = `
|
||||||
|
[omnia cybersystems]
|
||||||
|
17 66 68
|
||||||
|
o o------G-------o
|
||||||
|
\\ / \\
|
||||||
|
\\ o 65 o 69
|
||||||
|
[syscore sec.] H | |
|
||||||
|
\\ | | [millenium fitness gym]
|
||||||
|
\\ | 21 22 23 24 | 26
|
||||||
|
o----+--x--x----x---x---+-----x-------D-----o
|
||||||
|
19 | | 28
|
||||||
|
| F [omnitek inc.]
|
||||||
|
[hospital] J 63 o
|
||||||
|
| / 72
|
||||||
|
3 | 5 6 / 9
|
||||||
|
o--------+----x-----x----+----------M-------o
|
||||||
|
/ | |
|
||||||
|
/ 61 x [helios labs] B [world stock exchange]
|
||||||
|
[travel agency] L | |
|
||||||
|
/ | o
|
||||||
|
/ E [nwo] / 75
|
||||||
|
/ [computek] | /
|
||||||
|
/ A-------o------I-----o
|
||||||
|
1 o | |
|
||||||
|
| [zb] o 77
|
||||||
|
[lexocorp] C
|
||||||
|
|
|
||||||
|
o
|
||||||
|
57
|
||||||
|
|
||||||
|
|
||||||
|
[the slums] K `
|
||||||
|
|
||||||
// Then construct all locations, and add them to the cities as we go.
|
// Then construct all locations, and add them to the cities as we go.
|
||||||
for (const metadata of LocationsMetadata) {
|
for (const metadata of LocationsMetadata) {
|
||||||
const loc = constructLocation(metadata);
|
const loc = constructLocation(metadata);
|
||||||
|
@ -127,6 +127,7 @@ export function createStartCorporationPopup(p: IPlayer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const nameInput = createElement("input", {
|
const nameInput = createElement("input", {
|
||||||
|
class: 'text-input',
|
||||||
placeholder: "Corporation Name",
|
placeholder: "Corporation Name",
|
||||||
}) as HTMLInputElement;
|
}) as HTMLInputElement;
|
||||||
|
|
||||||
|
@ -17,18 +17,59 @@ type IProps = {
|
|||||||
|
|
||||||
export class LocationCity extends React.Component<IProps, any> {
|
export class LocationCity extends React.Component<IProps, any> {
|
||||||
render() {
|
render() {
|
||||||
const locationButtons = this.props.city.locations.map((locName) => {
|
const thiscity = this;
|
||||||
return (
|
const topprop = this.props
|
||||||
<li key={locName}>
|
|
||||||
<StdButton onClick={this.props.enterLocation.bind(this, locName)} text={locName} />
|
function LocationLetter(location: string) {
|
||||||
</li>
|
if (location)
|
||||||
)
|
return <span key={location} className='tooltip' style={{color: 'blue', whiteSpace: 'nowrap', margin: '0px', padding: '0px', cursor: 'pointer'}} onClick={topprop.enterLocation.bind(thiscity, location)}>
|
||||||
});
|
X
|
||||||
|
</span>
|
||||||
|
return <span>*</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
const locationLettersRegex = /[A-Z]/g;
|
||||||
|
const letterMap: any = {'A': 0,'B': 1,'C': 2,'D': 3,'E': 4,'F': 5,'G': 6,
|
||||||
|
'H': 7,'I': 8,'J': 9,'K': 10,'L': 11,'M': 12,'N': 13,'O': 14,
|
||||||
|
'P': 15,'Q': 16,'R': 17,'S': 18,'T': 19,'U': 20,'V': 21,'W': 22,
|
||||||
|
'X': 23,'Y': 24,'Z': 25}
|
||||||
|
|
||||||
|
let locI = 0;
|
||||||
|
function lineElems(s: string) {
|
||||||
|
let elems: any[] = [];
|
||||||
|
let matches: any[] = [];
|
||||||
|
let match: any;
|
||||||
|
while ((match = locationLettersRegex.exec(s)) !== null) {
|
||||||
|
matches.push(match);
|
||||||
|
}
|
||||||
|
if (matches.length === 0) {
|
||||||
|
elems.push(s);
|
||||||
|
return elems;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parts: any[] = [];
|
||||||
|
for(let i = 0; i < matches.length; i++) {
|
||||||
|
const startI = i === 0 ? 0 : matches[i-1].index+1;
|
||||||
|
const endI = matches[i].index;
|
||||||
|
elems.push(s.slice(startI, endI))
|
||||||
|
const locationI = letterMap[s[matches[i].index]];
|
||||||
|
elems.push(LocationLetter(thiscity.props.city.locations[locationI]))
|
||||||
|
locI++;
|
||||||
|
}
|
||||||
|
elems.push(s.slice(matches[matches.length-1].index+1))
|
||||||
|
return elems;
|
||||||
|
}
|
||||||
|
|
||||||
|
let elems: any[] = [];
|
||||||
|
const lines = this.props.city.asciiArt.split('\n');
|
||||||
|
for(const i in lines) {
|
||||||
|
elems.push(<pre key={i}>{lineElems(lines[i])}</pre>)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul>
|
<>
|
||||||
{locationButtons}
|
{elems}
|
||||||
</ul>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,21 +32,16 @@ export class TravelAgencyLocation extends React.Component<IProps, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const travelBtns: React.ReactNode[] = [];
|
const thisTravelAgencyLocation = this;
|
||||||
for (const key in CityName) {
|
|
||||||
const city = CityName[key];
|
|
||||||
|
|
||||||
// Skip current city
|
function LocationLetter(props: any) {
|
||||||
if (city === this.props.p.city) { continue; }
|
if(props.city !== thisTravelAgencyLocation.props.p.city) {
|
||||||
|
return <span className='tooltip' style={{color: 'blue', whiteSpace: 'nowrap', margin: '0px', padding: '0px'}} onClick={createTravelPopup.bind(null, props.city, thisTravelAgencyLocation.props.travel)}>
|
||||||
travelBtns.push(
|
<span className='tooltiptext'>{props.city}</span>
|
||||||
<StdButton
|
{props.city[0]}
|
||||||
key={city}
|
</span>
|
||||||
onClick={createTravelPopup.bind(null, city, this.props.travel)}
|
}
|
||||||
style={this.btnStyle}
|
return <span>{props.city[0]}</span>
|
||||||
text={`Travel to ${city}`}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -55,7 +50,28 @@ export class TravelAgencyLocation extends React.Component<IProps, any> {
|
|||||||
From here, you can travel to any other city! A ticket
|
From here, you can travel to any other city! A ticket
|
||||||
costs {numeralWrapper.formatMoney(CONSTANTS.TravelCost)}
|
costs {numeralWrapper.formatMoney(CONSTANTS.TravelCost)}
|
||||||
</p>
|
</p>
|
||||||
{travelBtns}
|
<pre> ,_ . ._. _. .</pre>
|
||||||
|
<pre> , _-\','|~\~ ~/ ;-'_ _-' ,;_;_, ~~-</pre>
|
||||||
|
<pre> /~~-\_/-'~'--' \~~| ', ,' / / ~|-_\_/~/~ ~~--~~~~'--_</pre>
|
||||||
|
<pre> / ,/'-/~ '\ ,' _ , '<LocationLetter city='Volhaven' />,'|~ ._/-, /~</pre>
|
||||||
|
<pre> ~/-'~\_, '-,| '|. ' ~ ,\ /'~ / /_ /~</pre>
|
||||||
|
<pre>.-~ '| '',\~|\ _\~ ,_ , <LocationLetter city='Chongqing' /> /,</pre>
|
||||||
|
<pre> '\ <LocationLetter city='Sector-12' /> /'~ |_/~\\,-,~ \ " ,_,/ |</pre>
|
||||||
|
<pre> | / ._-~'\_ _~| \ ) <LocationLetter city='New Tokyo' /></pre>
|
||||||
|
<pre> \ __-\ '/ ~ |\ \_ / ~</pre>
|
||||||
|
<pre> ., '\ |, ~-_ - | \\_' ~| /\ \~ ,</pre>
|
||||||
|
<pre> ~-_' _; '\ '-, \,' /\/ |</pre>
|
||||||
|
<pre> '\_,~'\_ \_ _, /' ' |, /|'</pre>
|
||||||
|
<pre> / \_ ~ | / \ ~'; -,_.</pre>
|
||||||
|
<pre> | ~\ | | , '-_, ,; ~ ~\</pre>
|
||||||
|
<pre> \, <LocationLetter city='Aevum' /> / \ / /| ,-, , -,</pre>
|
||||||
|
<pre> | ,/ | |' |/ ,- ~ \ '.</pre>
|
||||||
|
<pre> ,| ,/ \ ,/ \ <LocationLetter city='Ishima' /> |</pre>
|
||||||
|
<pre> / | ~ -~~-, / _</pre>
|
||||||
|
<pre> | ,-' ~ /</pre>
|
||||||
|
<pre> / ,' ~</pre>
|
||||||
|
<pre> ',| ~</pre>
|
||||||
|
<pre> ~'</pre>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
42
src/Netscript/Pid.ts
Normal file
42
src/Netscript/Pid.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { workerScripts } from "./WorkerScripts";
|
||||||
|
|
||||||
|
let pidCounter = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and return the next availble PID for a script
|
||||||
|
*/
|
||||||
|
export function generateNextPid(): number {
|
||||||
|
let tempCounter = pidCounter;
|
||||||
|
|
||||||
|
// Cap the number of search iterations at some arbitrary value to avoid
|
||||||
|
// infinite loops. We'll assume that players wont have 1mil+ running scripts
|
||||||
|
let found = false;
|
||||||
|
for (let i = 0; i < 1e6;) {
|
||||||
|
if (!workerScripts.has(tempCounter + i)) {
|
||||||
|
found = true;
|
||||||
|
tempCounter = tempCounter + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i === Number.MAX_SAFE_INTEGER - 1) {
|
||||||
|
i = 1;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
pidCounter = tempCounter + 1;
|
||||||
|
if (pidCounter >= Number.MAX_SAFE_INTEGER) {
|
||||||
|
pidCounter = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempCounter;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetPidCounter(): void {
|
||||||
|
pidCounter = 1;
|
||||||
|
}
|
@ -202,7 +202,9 @@ export const RamCosts: IMap<any> = {
|
|||||||
getAugmentationsFromFaction: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
getAugmentationsFromFaction: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||||
getAugmentationPrereq: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
getAugmentationPrereq: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||||
getAugmentationCost: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
getAugmentationCost: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||||
|
getAugmentationStats: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||||
purchaseAugmentation: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
purchaseAugmentation: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||||
|
softReset: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||||
installAugmentations: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
installAugmentations: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||||
|
|
||||||
// Gang API
|
// Gang API
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
augmentationExists,
|
augmentationExists,
|
||||||
installAugmentations
|
installAugmentations
|
||||||
} from "./Augmentation/AugmentationHelpers";
|
} from "./Augmentation/AugmentationHelpers";
|
||||||
|
import { prestigeAugmentation } from "./Prestige";
|
||||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||||
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
|
||||||
import { findCrime } from "./Crime/CrimeHelpers";
|
import { findCrime } from "./Crime/CrimeHelpers";
|
||||||
@ -51,7 +52,7 @@ import {
|
|||||||
purchaseHashUpgrade,
|
purchaseHashUpgrade,
|
||||||
updateHashManagerCapacity,
|
updateHashManagerCapacity,
|
||||||
} from "./Hacknet/HacknetHelpers";
|
} from "./Hacknet/HacknetHelpers";
|
||||||
import { HacknetServer } from "./Hacknet/HacknetServer";
|
import { HacknetServer, MaxNumberHacknetServers } from "./Hacknet/HacknetServer";
|
||||||
import { CityName } from "./Locations/data/CityNames";
|
import { CityName } from "./Locations/data/CityNames";
|
||||||
import { LocationName } from "./Locations/data/LocationNames";
|
import { LocationName } from "./Locations/data/LocationNames";
|
||||||
|
|
||||||
@ -391,6 +392,9 @@ function NetscriptFunctions(workerScript) {
|
|||||||
numNodes : function() {
|
numNodes : function() {
|
||||||
return Player.hacknetNodes.length;
|
return Player.hacknetNodes.length;
|
||||||
},
|
},
|
||||||
|
maxNumNodes : function() {
|
||||||
|
return MaxNumberHacknetServers;
|
||||||
|
},
|
||||||
purchaseNode : function() {
|
purchaseNode : function() {
|
||||||
return purchaseHacknet();
|
return purchaseHacknet();
|
||||||
},
|
},
|
||||||
@ -2742,6 +2746,12 @@ function NetscriptFunctions(workerScript) {
|
|||||||
workChaExpGain: Player.workChaExpGained,
|
workChaExpGain: Player.workChaExpGained,
|
||||||
workRepGain: Player.workRepGained,
|
workRepGain: Player.workRepGained,
|
||||||
workMoneyGain: Player.workMoneyGained,
|
workMoneyGain: Player.workMoneyGained,
|
||||||
|
hackingExp: Player.hacking_exp,
|
||||||
|
strengthExp: Player.strength_exp,
|
||||||
|
defenseExp: Player.defense_exp,
|
||||||
|
dexterityExp: Player.dexterity_exp,
|
||||||
|
agilityExp: Player.agility_exp,
|
||||||
|
charismaExp: Player.charisma_exp,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
isBusy: function() {
|
isBusy: function() {
|
||||||
@ -3415,6 +3425,24 @@ function NetscriptFunctions(workerScript) {
|
|||||||
var aug = Augmentations[name];
|
var aug = Augmentations[name];
|
||||||
return [aug.baseRepRequirement, aug.baseCost];
|
return [aug.baseRepRequirement, aug.baseCost];
|
||||||
},
|
},
|
||||||
|
getAugmentationStats: function(name) {
|
||||||
|
updateDynamicRam("getAugmentationStats", getRamCost("getAugmentationStats"));
|
||||||
|
if (Player.bitNodeN !== 4) {
|
||||||
|
if (SourceFileFlags[4] <= 2) {
|
||||||
|
throw makeRuntimeRejectMsg(workerScript, "Cannot run getAugmentationStats(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!augmentationExists(name)) {
|
||||||
|
workerScript.scriptRef.log("ERROR: getAugmentationStats() failed. Invalid Augmentation name passed in (note: this is case-sensitive): " + name);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var aug = Augmentations[name];
|
||||||
|
return Object.assign({}, aug.mults);
|
||||||
|
},
|
||||||
purchaseAugmentation: function(faction, name) {
|
purchaseAugmentation: function(faction, name) {
|
||||||
updateDynamicRam("purchaseAugmentation", getRamCost("purchaseAugmentation"));
|
updateDynamicRam("purchaseAugmentation", getRamCost("purchaseAugmentation"));
|
||||||
if (Player.bitNodeN !== 4) {
|
if (Player.bitNodeN !== 4) {
|
||||||
@ -3483,6 +3511,24 @@ function NetscriptFunctions(workerScript) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
softReset: function() {
|
||||||
|
updateDynamicRam("softReset", getRamCost("softReset"));
|
||||||
|
if (Player.bitNodeN !== 4) {
|
||||||
|
if (SourceFileFlags[4] <= 2) {
|
||||||
|
throw makeRuntimeRejectMsg(workerScript, "Cannot run softReset(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
workerScript.log("Soft resetting. This will cause this script to be killed");
|
||||||
|
setTimeoutRef(() => {
|
||||||
|
prestigeAugmentation();
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
// Prevent workerScript from "finishing execution naturally"
|
||||||
|
workerScript.running = false;
|
||||||
|
killWorkerScript(workerScript);
|
||||||
|
},
|
||||||
installAugmentations: function(cbScript) {
|
installAugmentations: function(cbScript) {
|
||||||
updateDynamicRam("installAugmentations", getRamCost("installAugmentations"));
|
updateDynamicRam("installAugmentations", getRamCost("installAugmentations"));
|
||||||
if (Player.bitNodeN !== 4) {
|
if (Player.bitNodeN !== 4) {
|
||||||
|
@ -6,6 +6,7 @@ import { killWorkerScript } from "./Netscript/killWorkerScript";
|
|||||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||||
import { workerScripts } from "./Netscript/WorkerScripts";
|
import { workerScripts } from "./Netscript/WorkerScripts";
|
||||||
import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter";
|
import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter";
|
||||||
|
import { generateNextPid } from "./Netscript/Pid";
|
||||||
|
|
||||||
import { CONSTANTS } from "./Constants";
|
import { CONSTANTS } from "./Constants";
|
||||||
import { Engine } from "./engine";
|
import { Engine } from "./engine";
|
||||||
@ -412,42 +413,6 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Find and return the next availble PID for a script
|
|
||||||
*/
|
|
||||||
let pidCounter = 1;
|
|
||||||
function generateNextPid() {
|
|
||||||
let tempCounter = pidCounter;
|
|
||||||
|
|
||||||
// Cap the number of search iterations at some arbitrary value to avoid
|
|
||||||
// infinite loops. We'll assume that players wont have 1mil+ running scripts
|
|
||||||
let found = false;
|
|
||||||
for (let i = 0; i < 1e6;) {
|
|
||||||
if (!workerScripts.has(tempCounter + i)) {
|
|
||||||
found = true;
|
|
||||||
tempCounter = tempCounter + i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i === Number.MAX_SAFE_INTEGER - 1) {
|
|
||||||
i = 1;
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
pidCounter = tempCounter + 1;
|
|
||||||
if (pidCounter >= Number.MAX_SAFE_INTEGER) {
|
|
||||||
pidCounter = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tempCounter;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to start a RunningScript (by creating and starting its
|
* Used to start a RunningScript (by creating and starting its
|
||||||
* corresponding WorkerScript), and add the RunningScript to the server on which
|
* corresponding WorkerScript), and add the RunningScript to the server on which
|
||||||
@ -535,7 +500,6 @@ export function createAndAddWorkerScript(runningScriptObj, server) {
|
|||||||
// the script from being cleaned up twice
|
// the script from being cleaned up twice
|
||||||
if (!w.running) { return; }
|
if (!w.running) { return; }
|
||||||
|
|
||||||
console.log("Stopping script " + w.name + " because it finished running naturally");
|
|
||||||
killWorkerScript(s);
|
killWorkerScript(s);
|
||||||
w.log("Script finished running");
|
w.log("Script finished running");
|
||||||
}).catch(function(w) {
|
}).catch(function(w) {
|
||||||
@ -547,8 +511,8 @@ export function createAndAddWorkerScript(runningScriptObj, server) {
|
|||||||
if (isScriptErrorMessage(w.errorMessage)) {
|
if (isScriptErrorMessage(w.errorMessage)) {
|
||||||
var errorTextArray = w.errorMessage.split("|");
|
var errorTextArray = w.errorMessage.split("|");
|
||||||
if (errorTextArray.length != 4) {
|
if (errorTextArray.length != 4) {
|
||||||
console.log("ERROR: Something wrong with Error text in evaluator...");
|
console.error("ERROR: Something wrong with Error text in evaluator...");
|
||||||
console.log("Error text: " + errorText);
|
console.error("Error text: " + errorText);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var serverIp = errorTextArray[1];
|
var serverIp = errorTextArray[1];
|
||||||
@ -567,11 +531,11 @@ export function createAndAddWorkerScript(runningScriptObj, server) {
|
|||||||
w.env.stopFlag = true;
|
w.env.stopFlag = true;
|
||||||
} else if (isScriptErrorMessage(w)) {
|
} else if (isScriptErrorMessage(w)) {
|
||||||
dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer");
|
dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer");
|
||||||
console.log("ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN: " + w.toString());
|
console.error("ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN: " + w.toString());
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
dialogBoxCreate("An unknown script died for an unknown reason. This is a bug please contact game dev");
|
dialogBoxCreate("An unknown script died for an unknown reason. This is a bug please contact game dev");
|
||||||
console.log(w);
|
console.error(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
killWorkerScript(s);
|
killWorkerScript(s);
|
||||||
|
@ -4,7 +4,7 @@ import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|||||||
export function canAccessBladeburner() {
|
export function canAccessBladeburner() {
|
||||||
if (this.bitNodeN === 8) { return false; }
|
if (this.bitNodeN === 8) { return false; }
|
||||||
|
|
||||||
return (this.bitNodeN === 6) || (this.bitNodeN === 7) || (SourceFileFlags[6] > 0);
|
return (this.bitNodeN === 6) || (this.bitNodeN === 7) || (SourceFileFlags[6] > 0) || (SourceFileFlags[7] > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inBladeburner() {
|
export function inBladeburner() {
|
||||||
|
@ -411,7 +411,7 @@ export function recordMoneySource(amt, source) {
|
|||||||
|
|
||||||
export function gainHackingExp(exp) {
|
export function gainHackingExp(exp) {
|
||||||
if (isNaN(exp)) {
|
if (isNaN(exp)) {
|
||||||
console.log("ERR: NaN passed into Player.gainHackingExp()"); return;
|
console.error("ERR: NaN passed into Player.gainHackingExp()"); return;
|
||||||
}
|
}
|
||||||
this.hacking_exp += exp;
|
this.hacking_exp += exp;
|
||||||
if(this.hacking_exp < 0) {
|
if(this.hacking_exp < 0) {
|
||||||
@ -421,7 +421,7 @@ export function gainHackingExp(exp) {
|
|||||||
|
|
||||||
export function gainStrengthExp(exp) {
|
export function gainStrengthExp(exp) {
|
||||||
if (isNaN(exp)) {
|
if (isNaN(exp)) {
|
||||||
console.log("ERR: NaN passed into Player.gainStrengthExp()"); return;
|
console.error("ERR: NaN passed into Player.gainStrengthExp()"); return;
|
||||||
}
|
}
|
||||||
this.strength_exp += exp;
|
this.strength_exp += exp;
|
||||||
if(this.strength_exp < 0) {
|
if(this.strength_exp < 0) {
|
||||||
@ -431,7 +431,7 @@ export function gainStrengthExp(exp) {
|
|||||||
|
|
||||||
export function gainDefenseExp(exp) {
|
export function gainDefenseExp(exp) {
|
||||||
if (isNaN(exp)) {
|
if (isNaN(exp)) {
|
||||||
console.log("ERR: NaN passed into player.gainDefenseExp()"); return;
|
console.error("ERR: NaN passed into player.gainDefenseExp()"); return;
|
||||||
}
|
}
|
||||||
this.defense_exp += exp;
|
this.defense_exp += exp;
|
||||||
if(this.defense_exp < 0) {
|
if(this.defense_exp < 0) {
|
||||||
@ -441,7 +441,7 @@ export function gainDefenseExp(exp) {
|
|||||||
|
|
||||||
export function gainDexterityExp(exp) {
|
export function gainDexterityExp(exp) {
|
||||||
if (isNaN(exp)) {
|
if (isNaN(exp)) {
|
||||||
console.log("ERR: NaN passed into Player.gainDexterityExp()"); return;
|
console.error("ERR: NaN passed into Player.gainDexterityExp()"); return;
|
||||||
}
|
}
|
||||||
this.dexterity_exp += exp;
|
this.dexterity_exp += exp;
|
||||||
if(this.dexterity_exp < 0) {
|
if(this.dexterity_exp < 0) {
|
||||||
@ -451,7 +451,7 @@ export function gainDexterityExp(exp) {
|
|||||||
|
|
||||||
export function gainAgilityExp(exp) {
|
export function gainAgilityExp(exp) {
|
||||||
if (isNaN(exp)) {
|
if (isNaN(exp)) {
|
||||||
console.log("ERR: NaN passed into Player.gainAgilityExp()"); return;
|
console.error("ERR: NaN passed into Player.gainAgilityExp()"); return;
|
||||||
}
|
}
|
||||||
this.agility_exp += exp;
|
this.agility_exp += exp;
|
||||||
if(this.agility_exp < 0) {
|
if(this.agility_exp < 0) {
|
||||||
@ -461,7 +461,7 @@ export function gainAgilityExp(exp) {
|
|||||||
|
|
||||||
export function gainCharismaExp(exp) {
|
export function gainCharismaExp(exp) {
|
||||||
if (isNaN(exp)) {
|
if (isNaN(exp)) {
|
||||||
console.log("ERR: NaN passed into Player.gainCharismaExp()"); return;
|
console.error("ERR: NaN passed into Player.gainCharismaExp()"); return;
|
||||||
}
|
}
|
||||||
this.charisma_exp += exp;
|
this.charisma_exp += exp;
|
||||||
if(this.charisma_exp < 0) {
|
if(this.charisma_exp < 0) {
|
||||||
@ -471,7 +471,7 @@ export function gainCharismaExp(exp) {
|
|||||||
|
|
||||||
export function gainIntelligenceExp(exp) {
|
export function gainIntelligenceExp(exp) {
|
||||||
if (isNaN(exp)) {
|
if (isNaN(exp)) {
|
||||||
console.log("ERROR: NaN passed into Player.gainIntelligenceExp()"); return;
|
console.error("ERROR: NaN passed into Player.gainIntelligenceExp()"); return;
|
||||||
}
|
}
|
||||||
if (SourceFileFlags[5] > 0 || this.intelligence > 0) {
|
if (SourceFileFlags[5] > 0 || this.intelligence > 0) {
|
||||||
this.intelligence_exp += exp;
|
this.intelligence_exp += exp;
|
||||||
@ -1827,7 +1827,6 @@ export function isQualified(company, position) {
|
|||||||
|
|
||||||
/********** Reapplying Augmentations and Source File ***********/
|
/********** Reapplying Augmentations and Source File ***********/
|
||||||
export function reapplyAllAugmentations(resetMultipliers=true) {
|
export function reapplyAllAugmentations(resetMultipliers=true) {
|
||||||
console.log("Re-applying augmentations");
|
|
||||||
if (resetMultipliers) {
|
if (resetMultipliers) {
|
||||||
this.resetMultipliers();
|
this.resetMultipliers();
|
||||||
}
|
}
|
||||||
@ -1856,7 +1855,6 @@ export function reapplyAllAugmentations(resetMultipliers=true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function reapplyAllSourceFiles() {
|
export function reapplyAllSourceFiles() {
|
||||||
console.log("Re-applying source files");
|
|
||||||
//Will always be called after reapplyAllAugmentations() so multipliers do not have to be reset
|
//Will always be called after reapplyAllAugmentations() so multipliers do not have to be reset
|
||||||
//this.resetMultipliers();
|
//this.resetMultipliers();
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import { Message } from "./Message/Message";
|
|||||||
import { initMessages, Messages } from "./Message/MessageHelpers";
|
import { initMessages, Messages } from "./Message/MessageHelpers";
|
||||||
import { prestigeWorkerScripts } from "./NetscriptWorker";
|
import { prestigeWorkerScripts } from "./NetscriptWorker";
|
||||||
import { Player } from "./Player";
|
import { Player } from "./Player";
|
||||||
|
import { resetPidCounter } from "./Netscript/Pid";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AllServers,
|
AllServers,
|
||||||
@ -172,6 +173,8 @@ function prestigeAugmentation() {
|
|||||||
DaedalusServer.serversOnNetwork.push(WorldDaemon.ip);
|
DaedalusServer.serversOnNetwork.push(WorldDaemon.ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetPidCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -346,6 +349,8 @@ function prestigeSourceFile() {
|
|||||||
|
|
||||||
// Gain int exp
|
// Gain int exp
|
||||||
Player.gainIntelligenceExp(5);
|
Player.gainIntelligenceExp(5);
|
||||||
|
|
||||||
|
resetPidCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
export {prestigeAugmentation, prestigeSourceFile};
|
export {prestigeAugmentation, prestigeSourceFile};
|
||||||
|
@ -112,7 +112,7 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
|
|||||||
var request = objectStore.put(saveString, "save");
|
var request = objectStore.put(saveString, "save");
|
||||||
|
|
||||||
request.onerror = function(e) {
|
request.onerror = function(e) {
|
||||||
console.log("Error saving game to IndexedDB: " + e);
|
console.error("Error saving game to IndexedDB: " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
request.onsuccess = function(e) {
|
request.onsuccess = function(e) {
|
||||||
@ -124,7 +124,7 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
|
|||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (e.code == 22) {
|
if (e.code == 22) {
|
||||||
createStatusText("Save failed for localStorage! Check console(F12)");
|
createStatusText("Save failed for localStorage! Check console(F12)");
|
||||||
console.log("Failed to save game to localStorage because the size of the save file " +
|
console.error("Failed to save game to localStorage because the size of the save file " +
|
||||||
"is too large. However, the game will still be saved to IndexedDb if your browser " +
|
"is too large. However, the game will still be saved to IndexedDb if your browser " +
|
||||||
"supports it. If you would like to save to localStorage as well, then " +
|
"supports it. If you would like to save to localStorage as well, then " +
|
||||||
"consider killing several of your scripts to " +
|
"consider killing several of your scripts to " +
|
||||||
@ -247,7 +247,7 @@ function loadGame(saveString) {
|
|||||||
try {
|
try {
|
||||||
Settings.load(saveObj.SettingsSave);
|
Settings.load(saveObj.SettingsSave);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log("ERROR: Failed to parse Settings. Re-initing default values");
|
console.error("ERROR: Failed to parse Settings. Re-initing default values");
|
||||||
Settings.init();
|
Settings.init();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -257,7 +257,7 @@ function loadGame(saveString) {
|
|||||||
try {
|
try {
|
||||||
loadFconf(saveObj.FconfSettingsSave);
|
loadFconf(saveObj.FconfSettingsSave);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log("ERROR: Failed to parse .fconf Settings.");
|
console.error("ERROR: Failed to parse .fconf Settings.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (saveObj.hasOwnProperty("VersionSave")) {
|
if (saveObj.hasOwnProperty("VersionSave")) {
|
||||||
@ -281,7 +281,7 @@ function loadGame(saveString) {
|
|||||||
try {
|
try {
|
||||||
loadAllGangs(saveObj.AllGangsSave);
|
loadAllGangs(saveObj.AllGangsSave);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log("ERROR: Failed to parse AllGangsSave: " + e);
|
console.error("ERROR: Failed to parse AllGangsSave: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ function loadImportedGame(saveObj, saveString) {
|
|||||||
try {
|
try {
|
||||||
loadFconf(saveObj.FconfSettingsSave);
|
loadFconf(saveObj.FconfSettingsSave);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log("ERROR: Failed to load .fconf settings when importing");
|
console.error("ERROR: Failed to load .fconf settings when importing");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (saveObj.hasOwnProperty("VersionSave")) {
|
if (saveObj.hasOwnProperty("VersionSave")) {
|
||||||
@ -460,7 +460,7 @@ function loadImportedGame(saveObj, saveString) {
|
|||||||
try {
|
try {
|
||||||
loadAllGangs(saveObj.AllGangsSave);
|
loadAllGangs(saveObj.AllGangsSave);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log("ERROR: Failed to parse AllGangsSave: " + e);
|
console.error("ERROR: Failed to parse AllGangsSave: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ let NetscriptFunctions =
|
|||||||
"createProgram|commitCrime|getCrimeChance|getOwnedAugmentations|" +
|
"createProgram|commitCrime|getCrimeChance|getOwnedAugmentations|" +
|
||||||
"getOwnedSourceFiles|getAugmentationsFromFaction|" +
|
"getOwnedSourceFiles|getAugmentationsFromFaction|" +
|
||||||
"getAugmentationPrereq|getAugmentationCost|purchaseAugmentation|" +
|
"getAugmentationPrereq|getAugmentationCost|purchaseAugmentation|" +
|
||||||
"installAugmentations|" +
|
"softReset|installAugmentations|getAugmentationStats|" +
|
||||||
|
|
||||||
// TIX API
|
// TIX API
|
||||||
"getStockPrice|getStockPosition|getStockSymbols|getStockMaxShares|" +
|
"getStockPrice|getStockPosition|getStockSymbols|getStockMaxShares|" +
|
||||||
@ -103,7 +103,7 @@ let NetscriptFunctions =
|
|||||||
// Hacknet Node API
|
// Hacknet Node API
|
||||||
"hacknet|numNodes|purchaseNode|getPurchaseNodeCost|getNodeStats|" +
|
"hacknet|numNodes|purchaseNode|getPurchaseNodeCost|getNodeStats|" +
|
||||||
"upgradeLevel|upgradeRam|upgradeCore|upgradeCache|getLevelUpgradeCost|" +
|
"upgradeLevel|upgradeRam|upgradeCore|upgradeCache|getLevelUpgradeCost|" +
|
||||||
"getRamUpgradeCost|getCoreUpgradeCost|getCacheUpgradeCost|" +
|
"getRamUpgradeCost|getCoreUpgradeCost|getCacheUpgradeCost|maxNumNodes|" +
|
||||||
|
|
||||||
// Gang API
|
// Gang API
|
||||||
"gang|" +
|
"gang|" +
|
||||||
|
@ -1760,7 +1760,14 @@ let Terminal = {
|
|||||||
const filepath = Terminal.getFilepath(filename);
|
const filepath = Terminal.getFilepath(filename);
|
||||||
const script = Terminal.getScript(filename);
|
const script = Terminal.getScript(filename);
|
||||||
if (script == null) {
|
if (script == null) {
|
||||||
Engine.loadScriptEditorContent(filepath);
|
let code = ""
|
||||||
|
if(filename.endsWith(".ns")) {
|
||||||
|
code = `export async function main(ns) {
|
||||||
|
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
console.log('default code');
|
||||||
|
Engine.loadScriptEditorContent(filepath, code);
|
||||||
} else {
|
} else {
|
||||||
Engine.loadScriptEditorContent(filepath, script.code);
|
Engine.loadScriptEditorContent(filepath, script.code);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ import {
|
|||||||
} from "./PersonObjects/Resleeving/ResleevingUI";
|
} from "./PersonObjects/Resleeving/ResleevingUI";
|
||||||
|
|
||||||
import { createStatusText } from "./ui/createStatusText";
|
import { createStatusText } from "./ui/createStatusText";
|
||||||
import { displayCharacterInfo } from "./ui/displayCharacterInfo";
|
import { CharacterInfo } from "./ui/CharacterInfo";
|
||||||
import { Page, routing } from "./ui/navigationTracking";
|
import { Page, routing } from "./ui/navigationTracking";
|
||||||
import { numeralWrapper } from "./ui/numeralFormat";
|
import { numeralWrapper } from "./ui/numeralFormat";
|
||||||
import { setSettingsLabels } from "./ui/setSettingsLabels";
|
import { setSettingsLabels } from "./ui/setSettingsLabels";
|
||||||
@ -567,7 +567,7 @@ const Engine = {
|
|||||||
|
|
||||||
/// Display character info
|
/// Display character info
|
||||||
updateCharacterInfo: function() {
|
updateCharacterInfo: function() {
|
||||||
displayCharacterInfo(Engine.Display.characterInfo, Player);
|
ReactDOM.render(CharacterInfo(Player), Engine.Display.characterInfo)
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO Refactor this into Faction implementation
|
// TODO Refactor this into Faction implementation
|
||||||
@ -592,7 +592,7 @@ const Engine = {
|
|||||||
factionsList.appendChild(createElement("a", {
|
factionsList.appendChild(createElement("a", {
|
||||||
class:"a-link-button", innerText:factionName, padding:"4px", margin:"4px",
|
class:"a-link-button", innerText:factionName, padding:"4px", margin:"4px",
|
||||||
display:"inline-block",
|
display:"inline-block",
|
||||||
clickListener:()=>{
|
clickListener: () => {
|
||||||
Engine.loadFactionContent();
|
Engine.loadFactionContent();
|
||||||
displayFactionContent(factionName);
|
displayFactionContent(factionName);
|
||||||
return false;
|
return false;
|
||||||
@ -774,6 +774,7 @@ const Engine = {
|
|||||||
updateDisplaysLong: 15,
|
updateDisplaysLong: 15,
|
||||||
updateActiveScriptsDisplay: 5,
|
updateActiveScriptsDisplay: 5,
|
||||||
createProgramNotifications: 10,
|
createProgramNotifications: 10,
|
||||||
|
augmentationsNotifications: 10,
|
||||||
checkFactionInvitations: 100,
|
checkFactionInvitations: 100,
|
||||||
passiveFactionGrowth: 600,
|
passiveFactionGrowth: 600,
|
||||||
messages: 150,
|
messages: 150,
|
||||||
@ -868,6 +869,19 @@ const Engine = {
|
|||||||
Engine.Counters.createProgramNotifications = 10;
|
Engine.Counters.createProgramNotifications = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Engine.Counters.augmentationsNotifications <= 0) {
|
||||||
|
var num = Player.queuedAugmentations.length;
|
||||||
|
var elem = document.getElementById("augmentations-notification");
|
||||||
|
if (num > 0) {
|
||||||
|
elem.innerHTML = num;
|
||||||
|
elem.setAttribute("class", "notification-on");
|
||||||
|
} else {
|
||||||
|
elem.innerHTML = "";
|
||||||
|
elem.setAttribute("class", "notification-off");
|
||||||
|
}
|
||||||
|
Engine.Counters.augmentationsNotifications = 10;
|
||||||
|
}
|
||||||
|
|
||||||
if (Engine.Counters.checkFactionInvitations <= 0) {
|
if (Engine.Counters.checkFactionInvitations <= 0) {
|
||||||
var invitedFactions = Player.checkForFactionInvitations();
|
var invitedFactions = Player.checkForFactionInvitations();
|
||||||
if (invitedFactions.length > 0) {
|
if (invitedFactions.length > 0) {
|
||||||
@ -881,6 +895,17 @@ const Engine = {
|
|||||||
var randFaction = invitedFactions[Math.floor(Math.random() * invitedFactions.length)];
|
var randFaction = invitedFactions[Math.floor(Math.random() * invitedFactions.length)];
|
||||||
inviteToFaction(randFaction);
|
inviteToFaction(randFaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const num = Player.factionInvitations.length;
|
||||||
|
const elem = document.getElementById("factions-notification");
|
||||||
|
if (num > 0) {
|
||||||
|
elem.innerHTML = num;
|
||||||
|
elem.setAttribute("class", "notification-on");
|
||||||
|
} else {
|
||||||
|
elem.innerHTML = "";
|
||||||
|
elem.setAttribute("class", "notification-off");
|
||||||
|
}
|
||||||
|
|
||||||
Engine.Counters.checkFactionInvitations = 100;
|
Engine.Counters.checkFactionInvitations = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1536,19 +1561,18 @@ window.onload = function() {
|
|||||||
indexedDbRequest = window.indexedDB.open("bitburnerSave", 1);
|
indexedDbRequest = window.indexedDB.open("bitburnerSave", 1);
|
||||||
|
|
||||||
indexedDbRequest.onerror = function(e) {
|
indexedDbRequest.onerror = function(e) {
|
||||||
console.log("Error opening indexedDB: ");
|
console.error("Error opening indexedDB: ");
|
||||||
console.log(e);
|
console.error(e);
|
||||||
return Engine.load(null); // Try to load from localstorage
|
return Engine.load(null); // Try to load from localstorage
|
||||||
};
|
};
|
||||||
|
|
||||||
indexedDbRequest.onsuccess = function(e) {
|
indexedDbRequest.onsuccess = function(e) {
|
||||||
console.log("Opening bitburnerSave database successful!");
|
|
||||||
indexedDb = e.target.result;
|
indexedDb = e.target.result;
|
||||||
var transaction = indexedDb.transaction(["savestring"]);
|
var transaction = indexedDb.transaction(["savestring"]);
|
||||||
var objectStore = transaction.objectStore("savestring");
|
var objectStore = transaction.objectStore("savestring");
|
||||||
var request = objectStore.get("save");
|
var request = objectStore.get("save");
|
||||||
request.onerror = function(e) {
|
request.onerror = function(e) {
|
||||||
console.log("Error in Database request to get savestring: " + e);
|
console.error("Error in Database request to get savestring: " + e);
|
||||||
return Engine.load(null); // Try to load from localstorage
|
return Engine.load(null); // Try to load from localstorage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +60,11 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
|
|||||||
</li>
|
</li>
|
||||||
<li id="factions-tab" class="mainmenu-accordion-panel">
|
<li id="factions-tab" class="mainmenu-accordion-panel">
|
||||||
<button id="factions-menu-link"> Factions </button>
|
<button id="factions-menu-link"> Factions </button>
|
||||||
|
<span id="factions-notification" class="notification-off"> </span>
|
||||||
</li>
|
</li>
|
||||||
<li id="augmentations-tab" class="mainmenu-accordion-panel">
|
<li id="augmentations-tab" class="mainmenu-accordion-panel">
|
||||||
<button id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> Augmentations </button>
|
<button id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> Augmentations </button>
|
||||||
|
<span id="augmentations-notification" class="notification-off"> </span>
|
||||||
</li>
|
</li>
|
||||||
<li id="hacknet-nodes-tab" class="mainmenu-accordion-panel">
|
<li id="hacknet-nodes-tab" class="mainmenu-accordion-panel">
|
||||||
<button id="hacknet-nodes-menu-link"> Hacknet Nodes </button>
|
<button id="hacknet-nodes-menu-link"> Hacknet Nodes </button>
|
||||||
|
@ -24,14 +24,14 @@ export function ScriptProduction(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<p id="active-scripts-total-prod">
|
<p id="active-scripts-total-prod">
|
||||||
Total online production of Active scripts:
|
Total online production of Active scripts:
|
||||||
<span className="money-gold">
|
<span className="money-gold">
|
||||||
<span id="active-scripts-total-production-active">
|
<span id="active-scripts-total-production-active">
|
||||||
{numeralWrapper.formatMoney(onlineProduction)}
|
{numeralWrapper.formatMoney(onlineProduction)}
|
||||||
</span> / sec
|
</span> / sec
|
||||||
</span><br />
|
</span><br />
|
||||||
|
|
||||||
Total online production since last Aug installation:
|
Total online production since last Aug installation:
|
||||||
<span id="active-scripts-total-prod-aug-total" className="money-gold">
|
<span id="active-scripts-total-prod-aug-total" className="money-gold">
|
||||||
{numeralWrapper.formatMoney(props.p.scriptProdSinceLastAug)}
|
{numeralWrapper.formatMoney(props.p.scriptProdSinceLastAug)}
|
||||||
</span>
|
</span>
|
||||||
|
238
src/ui/CharacterInfo.tsx
Normal file
238
src/ui/CharacterInfo.tsx
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
|
import { BitNodes } from "../BitNode/BitNode";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
|
||||||
|
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||||
|
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||||
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
|
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
||||||
|
import { getPurchaseServerLimit } from "../Server/ServerPurchases";
|
||||||
|
import { MaxNumberHacknetServers } from "../Hacknet/HacknetServer";
|
||||||
|
|
||||||
|
|
||||||
|
export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||||
|
function LastEmployer(): React.ReactElement {
|
||||||
|
if (p.companyName) {
|
||||||
|
return <><span>Employer at which you last worked: {p.companyName}</span><br /></>;
|
||||||
|
}
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
function LastJob(): React.ReactElement {
|
||||||
|
if (p.companyName !== "") {
|
||||||
|
return <><span>Job you last worked: {p.jobs[p.companyName]}</span><br /></>;
|
||||||
|
}
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
function Employers(): React.ReactElement {
|
||||||
|
if (p.jobs && Object.keys(p.jobs).length !== 0)
|
||||||
|
return <>
|
||||||
|
<span>All Employers:</span><br />
|
||||||
|
<ul>
|
||||||
|
{Object.keys(p.jobs).map(j => <li key='j'> * {j}</li>)}
|
||||||
|
</ul><br /><br />
|
||||||
|
</>
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertMoneySourceTrackerToString(src: MoneySourceTracker): string {
|
||||||
|
let parts: string[] = [`Total: ${numeralWrapper.formatMoney(src.total)}`];
|
||||||
|
if (src.bladeburner) { parts.push(`Bladeburner: ${numeralWrapper.formatMoney(src.bladeburner)}`) };
|
||||||
|
if (src.codingcontract) { parts.push(`Coding Contracts: ${numeralWrapper.formatMoney(src.codingcontract)}`) };
|
||||||
|
if (src.work) { parts.push(`Company Work: ${numeralWrapper.formatMoney(src.work)}`) };
|
||||||
|
if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}`) };
|
||||||
|
if (src.crime) { parts.push(`Crimes: ${numeralWrapper.formatMoney(src.crime)}`) };
|
||||||
|
if (src.gang) { parts.push(`Gang: ${numeralWrapper.formatMoney(src.gang)}`) };
|
||||||
|
if (src.hacking) { parts.push(`Hacking: ${numeralWrapper.formatMoney(src.hacking)}`) };
|
||||||
|
if (src.hacknetnode) { parts.push(`Hacknet Nodes: ${numeralWrapper.formatMoney(src.hacknetnode)}`) };
|
||||||
|
if (src.hospitalization) { parts.push(`Hospitalization: ${numeralWrapper.formatMoney(src.hospitalization)}`) };
|
||||||
|
if (src.infiltration) { parts.push(`Infiltration: ${numeralWrapper.formatMoney(src.infiltration)}`) };
|
||||||
|
if (src.stock) { parts.push(`Stock Market: ${numeralWrapper.formatMoney(src.stock)}`) };
|
||||||
|
|
||||||
|
return parts.join("<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
function openMoneyModal() {
|
||||||
|
let txt: string = "<u>Money earned since you last installed Augmentations:</u><br>" +
|
||||||
|
convertMoneySourceTrackerToString(p.moneySourceA);
|
||||||
|
if (p.sourceFiles.length !== 0) {
|
||||||
|
txt += "<br><br><u>Money earned in this BitNode:</u><br>" +
|
||||||
|
convertMoneySourceTrackerToString(p.moneySourceB);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogBoxCreate(txt, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Intelligence(): React.ReactElement {
|
||||||
|
if (p.intelligence > 0) {
|
||||||
|
return <tr key='5'>
|
||||||
|
<td>Intelligence:</td>
|
||||||
|
<td style={{textAlign: 'right'}}>{(p.intelligence).toLocaleString()}</td>
|
||||||
|
</tr>;
|
||||||
|
}
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MultiplierTable(props: any): React.ReactElement {
|
||||||
|
function bn5Stat(r: any) {
|
||||||
|
if(SourceFileFlags[5] > 0 && r.length > 2 && r[1] != r[2]) {
|
||||||
|
return <td key='2' style={{textAlign: 'right'}}> ({numeralWrapper.formatPercentage(r[2])})</td>
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return <>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
{props.rows.map((r: any) => <tr key={r[0]}>
|
||||||
|
<td key='0'>{r[0]} multiplier: </td>
|
||||||
|
<td key='1' style={{textAlign: 'right'}}>{numeralWrapper.formatPercentage(r[1])}</td>
|
||||||
|
{bn5Stat(r)}
|
||||||
|
</tr>)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
function BitNodeTimeText(): React.ReactElement {
|
||||||
|
if(p.sourceFiles.length > 0) {
|
||||||
|
return <>
|
||||||
|
<span>Time played since last Bitnode destroyed: {convertTimeMsToTimeElapsedString(p.playtimeSinceLastBitnode)}</span>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
|
||||||
|
function CurrentBitNode(): React.ReactElement {
|
||||||
|
if(p.sourceFiles.length > 0) {
|
||||||
|
|
||||||
|
const index = "BitNode" + p.bitNodeN;
|
||||||
|
return <>
|
||||||
|
<span>Current BitNode: {p.bitNodeN} ({BitNodes[index].name})</span><br /><br />
|
||||||
|
<div style={{width:"60%", fontSize: "13px", marginLeft:"4%"}}>
|
||||||
|
{BitNodes[index].info.split("<br>").map((t, i) => <div key={i}>
|
||||||
|
<span style={{whiteSpace: 'pre-wrap', overflowWrap: 'break-word'}}>{t}</span><br />
|
||||||
|
</div>)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<pre>
|
||||||
|
<b>General</b>
|
||||||
|
<br /><br />
|
||||||
|
<span>Current City: {p.city}</span><br />
|
||||||
|
<LastEmployer />
|
||||||
|
<LastJob />
|
||||||
|
<Employers />
|
||||||
|
<span>Money: {numeralWrapper.formatMoney(p.money.toNumber())}</span>
|
||||||
|
<button className="popup-box-button" style={{display: 'inline-block', float: 'none'}} onClick={openMoneyModal}>Money Statistics & Breakdown</button><br /><br />
|
||||||
|
<b>Stats</b>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr key='0'>
|
||||||
|
<td key='0'>Hacking:</td>
|
||||||
|
<td key='1' style={{textAlign: 'right'}}>{p.hacking_skill.toLocaleString()}</td>
|
||||||
|
<td key='2' style={{textAlign: 'right'}}>({numeralWrapper.format(p.hacking_exp, '0.000a')} exp)</td>
|
||||||
|
</tr>
|
||||||
|
<tr key='1'>
|
||||||
|
<td key='0'>Strength:</td>
|
||||||
|
<td key='1' style={{textAlign: 'right'}}>{p.strength.toLocaleString()}</td>
|
||||||
|
<td key='2' style={{textAlign: 'right'}}>({numeralWrapper.format(p.strength_exp, '0.000a')} exp)</td>
|
||||||
|
</tr>
|
||||||
|
<tr key='2'>
|
||||||
|
<td key='0'>Defense:</td>
|
||||||
|
<td key='1' style={{textAlign: 'right'}}>{p.defense.toLocaleString()}</td>
|
||||||
|
<td key='2' style={{textAlign: 'right'}}>({numeralWrapper.format(p.defense_exp, '0.000a')} exp)</td>
|
||||||
|
</tr>
|
||||||
|
<tr key='3'>
|
||||||
|
<td key='0'>Dexterity:</td>
|
||||||
|
<td key='1' style={{textAlign: 'right'}}>{p.dexterity.toLocaleString()}</td>
|
||||||
|
<td key='2' style={{textAlign: 'right'}}>({numeralWrapper.format(p.dexterity_exp, '0.000a')} exp)</td>
|
||||||
|
</tr>
|
||||||
|
<tr key='4'>
|
||||||
|
<td key='0'>Agility:</td>
|
||||||
|
<td key='1' style={{textAlign: 'right'}}>{p.agility.toLocaleString()}</td>
|
||||||
|
<td key='2' style={{textAlign: 'right'}}>({numeralWrapper.format(p.agility_exp, '0.000a')} exp)</td>
|
||||||
|
</tr>
|
||||||
|
<tr key='5'>
|
||||||
|
<td key='0'>Charisma:</td>
|
||||||
|
<td key='1' style={{textAlign: 'right'}}>{p.charisma.toLocaleString()}</td>
|
||||||
|
<td key='2' style={{textAlign: 'right'}}>({numeralWrapper.format(p.charisma_exp, '0.000a')} exp)</td>
|
||||||
|
</tr>
|
||||||
|
<Intelligence />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<br />
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Hacking Chance', p.hacking_chance_mult],
|
||||||
|
['Hacking Speed', p.hacking_speed_mult],
|
||||||
|
['Hacking Money', p.hacking_money_mult, p.hacking_speed_mult*BitNodeMultipliers.ScriptHackMoney],
|
||||||
|
['Hacking Growth', p.hacking_grow_mult, p.hacking_money_mult*BitNodeMultipliers.ServerGrowthRate]
|
||||||
|
]} /><br />
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Hacking Level', p.hacking_mult, p.hacking_mult*BitNodeMultipliers.HackingLevelMultiplier],
|
||||||
|
['Hacking Experience', p.hacking_exp_mult, p.hacking_exp_mult*BitNodeMultipliers.HackExpGain],
|
||||||
|
]} /><br />
|
||||||
|
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Strength Level', p.strength_mult, p.strength_mult*BitNodeMultipliers.StrengthLevelMultiplier],
|
||||||
|
['Strength Experience', p.strength_exp_mult]
|
||||||
|
]} /><br />
|
||||||
|
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Defense Level', p.defense_mult, p.defense_mult*BitNodeMultipliers.DefenseLevelMultiplier],
|
||||||
|
['Defense Experience', p.defense_exp_mult]
|
||||||
|
]} /><br />
|
||||||
|
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Dexterity Level', p.dexterity_mult, p.dexterity_mult*BitNodeMultipliers.DexterityLevelMultiplier],
|
||||||
|
['Dexterity Experience', p.dexterity_exp_mult]
|
||||||
|
]} /><br />
|
||||||
|
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Agility Level', p.agility_mult, p.agility_mult*BitNodeMultipliers.AgilityLevelMultiplier],
|
||||||
|
['Agility Experience', p.agility_exp_mult]
|
||||||
|
]} /><br />
|
||||||
|
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Charisma Level', p.charisma_mult, p.charisma_mult*BitNodeMultipliers.CharismaLevelMultiplier],
|
||||||
|
['Charisma Experience', p.charisma_exp_mult]
|
||||||
|
]} /><br />
|
||||||
|
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Hacknet Node production', p.hacknet_node_money_mult, p.hacknet_node_money_mult*BitNodeMultipliers.HacknetNodeMoney],
|
||||||
|
['Hacknet Node purchase cost', p.hacknet_node_purchase_cost_mult],
|
||||||
|
['Hacknet Node RAM upgrade cost', p.hacknet_node_ram_cost_mult],
|
||||||
|
['Hacknet Node Core purchase cost', p.hacknet_node_core_cost_mult],
|
||||||
|
['Hacknet Node level upgrade cost', p.hacknet_node_level_cost_mult]
|
||||||
|
]} /><br />
|
||||||
|
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Company reputation gain', p.company_rep_mult],
|
||||||
|
['Faction reputation gain', p.faction_rep_mult, p.faction_rep_mult*BitNodeMultipliers.FactionWorkRepGain],
|
||||||
|
['Salary', p.work_money_mult, p.work_money_mult*BitNodeMultipliers.CompanyWorkMoney]
|
||||||
|
]} /><br />
|
||||||
|
|
||||||
|
<MultiplierTable rows={[
|
||||||
|
['Crime success', p.crime_success_mult],
|
||||||
|
['Crime money', p.crime_money_mult, p.crime_money_mult*BitNodeMultipliers.CrimeMoney]
|
||||||
|
]} /><br /><br />
|
||||||
|
|
||||||
|
<b>Misc.</b><br /><br />
|
||||||
|
<span>Servers owned: {p.purchasedServers.length} / {getPurchaseServerLimit()}</span><br />
|
||||||
|
<span>Hacknet Nodes owned: {p.hacknetNodes.length} / {MaxNumberHacknetServers}</span><br />
|
||||||
|
<span>Augmentations installed: {p.augmentations.length}</span><br />
|
||||||
|
<span>Time played since last Augmentation: {convertTimeMsToTimeElapsedString(p.playtimeSinceLastAug)}</span><br />
|
||||||
|
<BitNodeTimeText />
|
||||||
|
<span>Time played: {convertTimeMsToTimeElapsedString(p.totalPlaytime)}</span><br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<CurrentBitNode />
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
}
|
@ -10,7 +10,7 @@ export class CharacterOverviewComponent extends Component {
|
|||||||
render() {
|
render() {
|
||||||
const intelligence = (
|
const intelligence = (
|
||||||
<tr id="character-int-wrapper">
|
<tr id="character-int-wrapper">
|
||||||
<td>Int: </td><td id="character-int-text" className="character-stat-cell">{(Player.intelligence).toLocaleString()}</td>
|
<td className="character-int-cell">Int: </td><td id="character-int-text" className="character-int-cell character-stat-cell">{(Player.intelligence).toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -19,28 +19,28 @@ export class CharacterOverviewComponent extends Component {
|
|||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr id="character-hp-wrapper">
|
<tr id="character-hp-wrapper">
|
||||||
<td>Hp:</td><td id="character-hp-text" className="character-stat-cell">{Player.hp + " / " + Player.max_hp}</td>
|
<td className="character-hp-cell">Hp:</td><td id="character-hp-text" className="character-hp-cell character-stat-cell">{Player.hp + " / " + Player.max_hp}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="character-money-wrapper">
|
<tr id="character-money-wrapper">
|
||||||
<td>Money: </td><td id="character-money-text" className="character-stat-cell">{numeralWrapper.format(Player.money.toNumber(), '$0.000a')}</td>
|
<td className="character-money-cell">Money: </td><td id="character-money-text" className="character-money-cell character-stat-cell">{numeralWrapper.format(Player.money.toNumber(), '$0.000a')}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="character-hack-wrapper">
|
<tr id="character-hack-wrapper">
|
||||||
<td>Hack: </td><td id="character-hack-text" className="character-stat-cell">{(Player.hacking_skill).toLocaleString()}</td>
|
<td className="character-hack-cell">Hack: </td><td id="character-hack-text" className="character-hack-cell character-stat-cell">{(Player.hacking_skill).toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="character-str-wrapper">
|
<tr id="character-str-wrapper">
|
||||||
<td>Str: </td><td id="character-str-text" className="character-stat-cell">{(Player.strength).toLocaleString()}</td>
|
<td className="character-combat-cell">Str: </td><td id="character-str-text" className="character-combat-cell character-stat-cell">{(Player.strength).toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="character-def-wrapper">
|
<tr id="character-def-wrapper">
|
||||||
<td>Def: </td><td id="character-def-text" className="character-stat-cell">{(Player.defense).toLocaleString()}</td>
|
<td className="character-combat-cell">Def: </td><td id="character-def-text" className="character-combat-cell character-stat-cell">{(Player.defense).toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="character-dex-wrapper">
|
<tr id="character-dex-wrapper">
|
||||||
<td>Dex: </td><td id="character-dex-text" className="character-stat-cell">{(Player.dexterity).toLocaleString()}</td>
|
<td className="character-combat-cell">Dex: </td><td id="character-dex-text" className="character-combat-cell character-stat-cell">{(Player.dexterity).toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="character-agi-wrapper">
|
<tr id="character-agi-wrapper">
|
||||||
<td>Agi: </td><td id="character-agi-text" className="character-stat-cell">{(Player.agility).toLocaleString()}</td>
|
<td className="character-combat-cell">Agi: </td><td id="character-agi-text" className="character-combat-cell character-stat-cell">{(Player.agility).toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="character-cha-wrapper">
|
<tr id="character-cha-wrapper">
|
||||||
<td>Cha: </td><td id="character-cha-text" className="character-stat-cell">{(Player.charisma).toLocaleString()}</td>
|
<td className="character-cha-cell">Cha: </td><td id="character-cha-text" className="character-cha-cell character-stat-cell">{(Player.charisma).toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{
|
{
|
||||||
Player.intelligence >= 1 &&
|
Player.intelligence >= 1 &&
|
||||||
|
@ -16,7 +16,7 @@ type IProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function SourceFileAccordion(props: IProps): React.ReactElement {
|
export function SourceFileAccordion(props: IProps): React.ReactElement {
|
||||||
const maxLevel = props.sf.n === 3 ? "∞" : "3";
|
const maxLevel = props.sf.n === 12 ? "∞" : "3";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<Accordion
|
||||||
|
@ -1,157 +0,0 @@
|
|||||||
// Displays character info on a given element. This is used to create & update
|
|
||||||
// the 'Stats' page from the main menu
|
|
||||||
import { BitNodes } from "../BitNode/BitNode";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
import { numeralWrapper } from "../ui/numeralFormat";
|
|
||||||
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
|
||||||
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
|
||||||
|
|
||||||
import { createElement } from "../../utils/uiHelpers/createElement";
|
|
||||||
import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement";
|
|
||||||
|
|
||||||
export function displayCharacterInfo(elem: HTMLElement, p: IPlayer) {
|
|
||||||
removeChildrenFromElement(elem);
|
|
||||||
|
|
||||||
let companyPosition = "";
|
|
||||||
if (p.companyName !== "") {
|
|
||||||
companyPosition = p.jobs[p.companyName];
|
|
||||||
}
|
|
||||||
|
|
||||||
var intText = "";
|
|
||||||
if (p.intelligence > 0) {
|
|
||||||
intText = 'Intelligence: ' + (p.intelligence).toLocaleString() + '<br>';
|
|
||||||
}
|
|
||||||
|
|
||||||
let bitNodeTimeText = "";
|
|
||||||
if(p.sourceFiles.length > 0) {
|
|
||||||
bitNodeTimeText = 'Time played since last Bitnode destroyed: ' + convertTimeMsToTimeElapsedString(p.playtimeSinceLastBitnode) + '<br>';
|
|
||||||
}
|
|
||||||
|
|
||||||
const unlockedBitnodes: boolean = p.sourceFiles.length !== 0;
|
|
||||||
|
|
||||||
// General info
|
|
||||||
elem.appendChild(createElement("pre", {
|
|
||||||
display: "block",
|
|
||||||
innerHTML:
|
|
||||||
'<b>General</b><br><br>' +
|
|
||||||
'Current City: ' + p.city + '<br><br>' +
|
|
||||||
`Employer at which you last worked: ${p.companyName}<br>` +
|
|
||||||
`Job you last worked: ${companyPosition}<br>` +
|
|
||||||
`All Employers: ${Object.keys(p.jobs).join(", ")}<br><br>`
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Money, and a button to show money breakdown
|
|
||||||
elem.appendChild(createElement("pre", {
|
|
||||||
display: "inline-block",
|
|
||||||
innerHTML: 'Money: ' + numeralWrapper.formatMoney(p.money.toNumber()) + '<br><br><br>',
|
|
||||||
margin: "6px",
|
|
||||||
}));
|
|
||||||
|
|
||||||
function convertMoneySourceTrackerToString(src: MoneySourceTracker): string {
|
|
||||||
let parts: string[] = [`Total: ${numeralWrapper.formatMoney(src.total)}`];
|
|
||||||
if (src.bladeburner) { parts.push(`Bladeburner: ${numeralWrapper.formatMoney(src.bladeburner)}`) };
|
|
||||||
if (src.codingcontract) { parts.push(`Coding Contracts: ${numeralWrapper.formatMoney(src.codingcontract)}`) };
|
|
||||||
if (src.work) { parts.push(`Company Work: ${numeralWrapper.formatMoney(src.work)}`) };
|
|
||||||
if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}`) };
|
|
||||||
if (src.crime) { parts.push(`Crimes: ${numeralWrapper.formatMoney(src.crime)}`) };
|
|
||||||
if (src.gang) { parts.push(`Gang: ${numeralWrapper.formatMoney(src.gang)}`) };
|
|
||||||
if (src.hacking) { parts.push(`Hacking: ${numeralWrapper.formatMoney(src.hacking)}`) };
|
|
||||||
if (src.hacknetnode) { parts.push(`Hacknet Nodes: ${numeralWrapper.formatMoney(src.hacknetnode)}`) };
|
|
||||||
if (src.hospitalization) { parts.push(`Hospitalization: ${numeralWrapper.formatMoney(src.hospitalization)}`) };
|
|
||||||
if (src.infiltration) { parts.push(`Infiltration: ${numeralWrapper.formatMoney(src.infiltration)}`) };
|
|
||||||
if (src.stock) { parts.push(`Stock Market: ${numeralWrapper.formatMoney(src.stock)}`) };
|
|
||||||
|
|
||||||
return parts.join("<br>");
|
|
||||||
}
|
|
||||||
|
|
||||||
elem.appendChild(createElement("button", {
|
|
||||||
class: "popup-box-button",
|
|
||||||
display: "inline-block",
|
|
||||||
float: "none",
|
|
||||||
innerText: "Money Statistics & Breakdown",
|
|
||||||
clickListener: () => {
|
|
||||||
let txt: string = "<u>Money earned since you last installed Augmentations:</u><br>" +
|
|
||||||
convertMoneySourceTrackerToString(p.moneySourceA);
|
|
||||||
if (unlockedBitnodes) {
|
|
||||||
txt += "<br><br><u>Money earned in this BitNode:</u><br>" +
|
|
||||||
convertMoneySourceTrackerToString(p.moneySourceB);
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogBoxCreate(txt, false);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Stats and multiplier
|
|
||||||
elem.appendChild(createElement("pre", {
|
|
||||||
display: "block",
|
|
||||||
innerHTML:
|
|
||||||
'<b>Stats</b><br><br>' +
|
|
||||||
'Hacking Level: ' + (p.hacking_skill).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(p.hacking_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Strength: ' + (p.strength).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(p.strength_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Defense: ' + (p.defense).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(p.defense_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Dexterity: ' + (p.dexterity).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(p.dexterity_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Agility: ' + (p.agility).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(p.agility_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Charisma: ' + (p.charisma).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(p.charisma_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
intText + '<br><br>' +
|
|
||||||
'<b>Multipliers</b><br><br>' +
|
|
||||||
'Hacking Chance multiplier: ' + numeralWrapper.formatPercentage(p.hacking_chance_mult) + '<br>' +
|
|
||||||
'Hacking Speed multiplier: ' + numeralWrapper.formatPercentage(p.hacking_speed_mult) + '<br>' +
|
|
||||||
'Hacking Money multiplier: ' + numeralWrapper.formatPercentage(p.hacking_money_mult) + '<br>' +
|
|
||||||
'Hacking Growth multiplier: ' + numeralWrapper.formatPercentage(p.hacking_grow_mult) + '<br><br>' +
|
|
||||||
'Hacking Level multiplier: ' + numeralWrapper.formatPercentage(p.hacking_mult) + '<br>' +
|
|
||||||
'Hacking Experience multiplier: ' + numeralWrapper.formatPercentage(p.hacking_exp_mult) + '<br><br>' +
|
|
||||||
'Strength Level multiplier: ' + numeralWrapper.formatPercentage(p.strength_mult) + '<br>' +
|
|
||||||
'Strength Experience multiplier: ' + numeralWrapper.formatPercentage(p.strength_exp_mult) + '<br><br>' +
|
|
||||||
'Defense Level multiplier: ' + numeralWrapper.formatPercentage(p.defense_mult) + '<br>' +
|
|
||||||
'Defense Experience multiplier: ' + numeralWrapper.formatPercentage(p.defense_exp_mult) + '<br><br>' +
|
|
||||||
'Dexterity Level multiplier: ' + numeralWrapper.formatPercentage(p.dexterity_mult) + '<br>' +
|
|
||||||
'Dexterity Experience multiplier: ' + numeralWrapper.formatPercentage(p.dexterity_exp_mult) + '<br><br>' +
|
|
||||||
'Agility Level multiplier: ' + numeralWrapper.formatPercentage(p.agility_mult) + '<br>' +
|
|
||||||
'Agility Experience multiplier: ' + numeralWrapper.formatPercentage(p.agility_exp_mult) + '<br><br>' +
|
|
||||||
'Charisma Level multiplier: ' + numeralWrapper.formatPercentage(p.charisma_mult) + '<br>' +
|
|
||||||
'Charisma Experience multiplier: ' + numeralWrapper.formatPercentage(p.charisma_exp_mult) + '<br><br>' +
|
|
||||||
'Hacknet Node production multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_money_mult) + '<br>' +
|
|
||||||
'Hacknet Node purchase cost multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_purchase_cost_mult) + '<br>' +
|
|
||||||
'Hacknet Node RAM upgrade cost multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_ram_cost_mult) + '<br>' +
|
|
||||||
'Hacknet Node Core purchase cost multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_core_cost_mult) + '<br>' +
|
|
||||||
'Hacknet Node level upgrade cost multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_level_cost_mult) + '<br><br>' +
|
|
||||||
'Company reputation gain multiplier: ' + numeralWrapper.formatPercentage(p.company_rep_mult) + '<br>' +
|
|
||||||
'Faction reputation gain multiplier: ' + numeralWrapper.formatPercentage(p.faction_rep_mult) + '<br>' +
|
|
||||||
'Salary multiplier: ' + numeralWrapper.formatPercentage(p.work_money_mult) + '<br>' +
|
|
||||||
'Crime success multiplier: ' + numeralWrapper.formatPercentage(p.crime_success_mult) + '<br>' +
|
|
||||||
'Crime money multiplier: ' + numeralWrapper.formatPercentage(p.crime_money_mult) + '<br><br><br>' +
|
|
||||||
'<b>Misc</b><br><br>' +
|
|
||||||
'Servers owned: ' + p.purchasedServers.length + '<br>' +
|
|
||||||
'Hacknet Nodes owned: ' + p.hacknetNodes.length + '<br>' +
|
|
||||||
'Augmentations installed: ' + p.augmentations.length + '<br>' +
|
|
||||||
'Time played since last Augmentation: ' + convertTimeMsToTimeElapsedString(p.playtimeSinceLastAug) + '<br>' +
|
|
||||||
bitNodeTimeText +
|
|
||||||
'Time played: ' + convertTimeMsToTimeElapsedString(p.totalPlaytime),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// BitNode information, if player has gotten that far
|
|
||||||
if (unlockedBitnodes) {
|
|
||||||
var index = "BitNode" + p.bitNodeN;
|
|
||||||
|
|
||||||
elem.appendChild(createElement("p", {
|
|
||||||
width:"60%",
|
|
||||||
innerHTML:
|
|
||||||
"<br>Current BitNode: " + p.bitNodeN + " (" + BitNodes[index].name + ")<br><br>",
|
|
||||||
}));
|
|
||||||
|
|
||||||
elem.appendChild(createElement("p", {
|
|
||||||
width:"60%", fontSize: "13px", marginLeft:"4%",
|
|
||||||
innerHTML:BitNodes[index].info,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -42,7 +42,6 @@ document.addEventListener("keydown", function (event) {
|
|||||||
let dialogBoxOpened = false;
|
let dialogBoxOpened = false;
|
||||||
|
|
||||||
function dialogBoxCreate(txt, preformatted=false) {
|
function dialogBoxCreate(txt, preformatted=false) {
|
||||||
console.log(`dialogBoxCreate() called`)
|
|
||||||
var container = document.createElement("div");
|
var container = document.createElement("div");
|
||||||
container.setAttribute("class", "dialog-box-container");
|
container.setAttribute("class", "dialog-box-container");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user