mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
commit
802f28082d
@ -59,10 +59,16 @@
|
||||
}
|
||||
|
||||
#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-cell { color: $my-stat-money-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-cell { color: $my-stat-cha-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 {
|
||||
@include borderRadius(12px);
|
||||
|
@ -17,7 +17,8 @@ body {
|
||||
p,
|
||||
pre,
|
||||
h2,
|
||||
.text {
|
||||
.text,
|
||||
td {
|
||||
color: var(--my-font-color);
|
||||
}
|
||||
|
||||
@ -79,6 +80,28 @@ a:visited {
|
||||
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 {
|
||||
background-color: #fa3e3e;
|
||||
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
|
41
dist/engineStyle.css
vendored
41
dist/engineStyle.css
vendored
@ -26,7 +26,8 @@ body {
|
||||
p,
|
||||
pre,
|
||||
h2,
|
||||
.text {
|
||||
.text,
|
||||
td {
|
||||
color: var(--my-font-color); }
|
||||
|
||||
h1 {
|
||||
@ -78,6 +79,26 @@ a:visited {
|
||||
top: 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 {
|
||||
background-color: #fa3e3e;
|
||||
color: #fff;
|
||||
@ -684,18 +705,36 @@ button {
|
||||
#character-hp-wrapper {
|
||||
color: #dd3434; }
|
||||
|
||||
.character-hp-cell {
|
||||
color: #dd3434; }
|
||||
|
||||
#character-money-wrapper {
|
||||
color: #ffd700; }
|
||||
|
||||
.character-money-cell {
|
||||
color: #ffd700; }
|
||||
|
||||
#character-hack-wrapper {
|
||||
color: #adff2f; }
|
||||
|
||||
.character-hack-cell {
|
||||
color: #adff2f; }
|
||||
|
||||
#character-cha-wrapper {
|
||||
color: #a671d1; }
|
||||
|
||||
.character-cha-cell {
|
||||
color: #a671d1; }
|
||||
|
||||
#character-int-wrapper {
|
||||
color: #6495ed; }
|
||||
|
||||
.character-int-cell {
|
||||
color: #6495ed; }
|
||||
|
||||
.character-combat-cell {
|
||||
color: #faffdf; }
|
||||
|
||||
.character-overview-btn {
|
||||
-webkit-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
|
||||
=========
|
||||
|
||||
|
||||
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
|
||||
-------------------
|
||||
|
||||
|
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
|
||||
workRepGain: Reputation 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 id="factions-tab" class="mainmenu-accordion-panel">
|
||||
<button id="factions-menu-link"> Factions </button>
|
||||
<span id="factions-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
<li id="augmentations-tab" class="mainmenu-accordion-panel">
|
||||
<button id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> Augmentations </button>
|
||||
<span id="augmentations-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
<li id="hacknet-nodes-tab" class="mainmenu-accordion-panel">
|
||||
<button id="hacknet-nodes-menu-link"> Hacknet Nodes </button>
|
||||
|
@ -5,92 +5,104 @@ import * as React from "react";
|
||||
|
||||
import { Player } from "../../Player";
|
||||
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 {
|
||||
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 (
|
||||
<>
|
||||
<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>
|
||||
{'Hacking Chance multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_chance_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Hacking Speed multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_speed_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Hacking Money multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_money_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Hacking Growth multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_grow_mult)}
|
||||
</pre><br />
|
||||
<pre>
|
||||
{'Hacking Level multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Hacking Experience multiplier: ' + numeralWrapper.formatPercentage(Player.hacking_exp_mult)}
|
||||
</pre>
|
||||
<br />
|
||||
<pre>
|
||||
{'Strength Level multiplier: ' + numeralWrapper.formatPercentage(Player.strength_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Strength Experience multiplier: ' + numeralWrapper.formatPercentage(Player.strength_exp_mult)}
|
||||
</pre>
|
||||
<br />
|
||||
<pre>
|
||||
{'Defense Level multiplier: ' + numeralWrapper.formatPercentage(Player.defense_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Defense Experience multiplier: ' + numeralWrapper.formatPercentage(Player.defense_exp_mult)}
|
||||
</pre><br />
|
||||
<pre>
|
||||
{'Dexterity Level multiplier: ' + numeralWrapper.formatPercentage(Player.dexterity_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Dexterity Experience multiplier: ' + numeralWrapper.formatPercentage(Player.dexterity_exp_mult)}
|
||||
</pre><br />
|
||||
<pre>
|
||||
{'Agility Level multiplier: ' + numeralWrapper.formatPercentage(Player.agility_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Agility Experience multiplier: ' + numeralWrapper.formatPercentage(Player.agility_exp_mult)}
|
||||
</pre><br />
|
||||
<pre>
|
||||
{'Charisma Level multiplier: ' + numeralWrapper.formatPercentage(Player.charisma_mult)}
|
||||
</pre>
|
||||
<pre>
|
||||
{'Charisma Experience multiplier: ' + numeralWrapper.formatPercentage(Player.charisma_exp_mult)}
|
||||
</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>
|
||||
{MultiplierTable([
|
||||
['Hacking Level ', Player.hacking_mult, Player.hacking_mult*mults.hacking_mult],
|
||||
['Hacking Experience ', Player.hacking_exp_mult, Player.hacking_exp_mult*mults.hacking_exp_mult]
|
||||
])}<br />
|
||||
|
||||
|
||||
{MultiplierTable([
|
||||
['Strength Level ', Player.strength_mult, Player.strength_mult*mults.strength_mult],
|
||||
['Strength Experience ', Player.strength_exp_mult, Player.strength_exp_mult*mults.strength_exp_mult]
|
||||
])}<br />
|
||||
|
||||
{MultiplierTable([
|
||||
['Defense Level ', Player.defense_mult, Player.defense_mult*mults.defense_mult],
|
||||
['Defense Experience ', Player.defense_exp_mult, Player.defense_exp_mult*mults.defense_exp_mult]
|
||||
])}<br />
|
||||
|
||||
{MultiplierTable([
|
||||
['Dexterity Level ', Player.dexterity_mult, Player.dexterity_mult*mults.dexterity_mult],
|
||||
['Dexterity Experience ', Player.dexterity_exp_mult, Player.dexterity_exp_mult*mults.dexterity_exp_mult]
|
||||
])}<br />
|
||||
|
||||
{MultiplierTable([
|
||||
['Agility Level ', Player.agility_mult, Player.agility_mult*mults.agility_mult],
|
||||
['Agility Experience ', Player.agility_exp_mult, Player.agility_exp_mult*mults.agility_exp_mult]
|
||||
])}<br />
|
||||
|
||||
{MultiplierTable([
|
||||
['Charisma Level ', Player.charisma_mult, Player.charisma_mult*mults.charisma_mult],
|
||||
['Charisma Experience ', Player.charisma_exp_mult, Player.charisma_exp_mult*mults.charisma_exp_mult]
|
||||
])}<br />
|
||||
|
||||
{MultiplierTable([
|
||||
['Hacknet Node production ', Player.hacknet_node_money_mult, Player.hacknet_node_money_mult*mults.hacknet_node_money_mult],
|
||||
['Hacknet Node purchase cost ', Player.hacknet_node_purchase_cost_mult, Player.hacknet_node_purchase_cost_mult*mults.hacknet_node_purchase_cost_mult],
|
||||
['Hacknet Node RAM upgrade cost ', Player.hacknet_node_ram_cost_mult, Player.hacknet_node_ram_cost_mult*mults.hacknet_node_ram_cost_mult],
|
||||
['Hacknet Node Core purchase cost ', Player.hacknet_node_core_cost_mult, Player.hacknet_node_core_cost_mult*mults.hacknet_node_core_cost_mult],
|
||||
['Hacknet Node level upgrade cost ', Player.hacknet_node_level_cost_mult, Player.hacknet_node_level_cost_mult*mults.hacknet_node_level_cost_mult]
|
||||
])}<br />
|
||||
|
||||
{MultiplierTable([
|
||||
['Company reputation gain ', Player.company_rep_mult, Player.company_rep_mult*mults.company_rep_mult],
|
||||
['Faction reputation gain ', Player.faction_rep_mult, Player.faction_rep_mult*mults.faction_rep_mult],
|
||||
['Salary ', Player.work_money_mult, Player.work_money_mult*mults.work_money_mult]
|
||||
])}<br />
|
||||
|
||||
{MultiplierTable([
|
||||
['Crime success ', Player.crime_success_mult, Player.crime_success_mult*mults.crime_success_mult],
|
||||
['Crime money ', Player.crime_money_mult, Player.crime_money_mult*mults.crime_money_mult],
|
||||
])}<br />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
|
||||
"Level 3: 56%");
|
||||
BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
|
||||
"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 " +
|
||||
"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)");
|
||||
@ -460,11 +460,12 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.PurchasedServerLimit = dec;
|
||||
BitNodeMultipliers.PurchasedServerMaxRam = dec;
|
||||
|
||||
BitNodeMultipliers.ManualHackMoney = dec;
|
||||
BitNodeMultipliers.ScriptHackMoney = dec;
|
||||
BitNodeMultipliers.CompanyWorkMoney = dec;
|
||||
BitNodeMultipliers.CrimeMoney = dec;
|
||||
BitNodeMultipliers.HacknetNodeMoney = dec;
|
||||
BitNodeMultipliers.ManualHackMoney = dec;
|
||||
BitNodeMultipliers.ScriptHackMoney = dec;
|
||||
BitNodeMultipliers.CompanyWorkMoney = dec;
|
||||
BitNodeMultipliers.CrimeMoney = dec;
|
||||
BitNodeMultipliers.HacknetNodeMoney = dec;
|
||||
BitNodeMultipliers.CodingContractMoney = dec;
|
||||
|
||||
BitNodeMultipliers.CompanyWorkExpGain = dec;
|
||||
BitNodeMultipliers.ClassGymExpGain = dec;
|
||||
|
@ -31,6 +31,7 @@ import { KEY } from "../utils/helpers/keyCodes";
|
||||
|
||||
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks";
|
||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
import { removeElement } from "../utils/uiHelpers/removeElement";
|
||||
@ -991,12 +992,16 @@ Bladeburner.prototype.process = function() {
|
||||
}
|
||||
|
||||
Bladeburner.prototype.calculateMaxStamina = function() {
|
||||
var effAgility = Player.agility * this.skillMultipliers.effAgi;
|
||||
var maxStamina = (Math.pow(effAgility, 0.8) + this.staminaBonus);
|
||||
maxStamina *= this.skillMultipliers.stamina;
|
||||
maxStamina *= Player.bladeburner_max_stamina_mult;
|
||||
const effAgility = Player.agility * this.skillMultipliers.effAgi;
|
||||
let maxStamina = (Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
||||
this.skillMultipliers.stamina *
|
||||
Player.bladeburner_max_stamina_mult;
|
||||
if (this.maxStamina !== maxStamina) {
|
||||
const oldMax = this.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()");}
|
||||
this.maxStamina = maxStamina;
|
||||
}
|
||||
|
||||
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.overviewChaos.childNodes[0].nodeValue = "City Chaos: " + formatNumber(this.getCurrentCity().chaos);
|
||||
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.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) + "%";
|
||||
|
@ -74,7 +74,6 @@ for (const md of codingContractTypesMetadata) {
|
||||
// tslint:disable-next-line
|
||||
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
|
||||
|
@ -6,7 +6,7 @@
|
||||
import { IMap } from "./types";
|
||||
|
||||
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
|
||||
* 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:
|
||||
`
|
||||
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.
|
||||
* missing ram cost in many function now added to documentation
|
||||
* typos
|
||||
* 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.
|
||||
`
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import { CorporationUpgrades } from "../data/CorporationUpgrades";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
|
||||
|
||||
export class Overview extends BaseReactComponent {
|
||||
// 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")}` +
|
||||
"</span></p><br><br>";
|
||||
|
||||
const storedTime = this.corp().storedCycles * CONSTANTS.MilliPerCycle / 1000;
|
||||
if (storedTime > 15) {
|
||||
txt += `Bonus Time: ${storedTime} seconds<br><br>`;
|
||||
const storedTime = this.corp().storedCycles * CONSTANTS.MilliPerCycle;
|
||||
if (storedTime > 15000) {
|
||||
txt += `Bonus time: ${convertTimeMsToTimeElapsedString(storedTime)}<br><br>`;
|
||||
}
|
||||
|
||||
let prodMult = this.corp().getProductionMultiplier(),
|
||||
|
@ -88,7 +88,7 @@ export class DonateOption extends React.Component<IProps, IState> {
|
||||
return (
|
||||
<div className={"faction-work-div"}>
|
||||
<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
|
||||
onClick={this.donate}
|
||||
text={"Donate Money"}
|
||||
|
@ -33,6 +33,7 @@ import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import { removeElement } from "../utils/uiHelpers/removeElement";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
|
||||
|
||||
// Constants
|
||||
@ -1570,7 +1571,9 @@ Gang.prototype.updateGangContent = function() {
|
||||
// Update territory information
|
||||
UIElems.gangTerritoryInfoText.innerHTML = "";
|
||||
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)) {
|
||||
const gangTerritoryInfo = AllGangs[gangname];
|
||||
let territory = gangTerritoryInfo.territory * 100;
|
||||
@ -1670,7 +1673,7 @@ Gang.prototype.updateGangContent = function() {
|
||||
|
||||
const CyclesPerSecond = 1000 / Engine._idleSpeed;
|
||||
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",
|
||||
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",
|
||||
@ -1942,6 +1945,8 @@ Gang.prototype.setGangMemberTaskDescription = function(memberObj, taskName) {
|
||||
Gang.prototype.clearUI = function() {
|
||||
if (UIElems.gangContainer instanceof Element) { removeElement(UIElems.gangContainer); }
|
||||
|
||||
if (UIElems.gangMemberUpgradeBox instanceof Element) { removeElement(UIElems.gangMemberUpgradeBox); }
|
||||
|
||||
for (const prop in UIElems) {
|
||||
UIElems[prop] = null;
|
||||
}
|
||||
|
@ -15,9 +15,15 @@ export class City {
|
||||
*/
|
||||
name: CityName;
|
||||
|
||||
constructor(name: CityName, locations: LocationName[]=[]) {
|
||||
/**
|
||||
* Metro map ascii art
|
||||
*/
|
||||
asciiArt: string;
|
||||
|
||||
constructor(name: CityName, locations: LocationName[]=[], asciiArt: string='') {
|
||||
this.name = name;
|
||||
this.locations = locations;
|
||||
this.asciiArt = asciiArt;
|
||||
}
|
||||
|
||||
addLocation(loc: LocationName): void {
|
||||
|
@ -40,6 +40,181 @@ Cities[CityName.NewTokyo] = new City(CityName.NewTokyo);
|
||||
Cities[CityName.Sector12] = new City(CityName.Sector12);
|
||||
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.
|
||||
for (const metadata of LocationsMetadata) {
|
||||
const loc = constructLocation(metadata);
|
||||
|
@ -127,6 +127,7 @@ export function createStartCorporationPopup(p: IPlayer) {
|
||||
});
|
||||
|
||||
const nameInput = createElement("input", {
|
||||
class: 'text-input',
|
||||
placeholder: "Corporation Name",
|
||||
}) as HTMLInputElement;
|
||||
|
||||
|
@ -17,18 +17,59 @@ type IProps = {
|
||||
|
||||
export class LocationCity extends React.Component<IProps, any> {
|
||||
render() {
|
||||
const locationButtons = this.props.city.locations.map((locName) => {
|
||||
return (
|
||||
<li key={locName}>
|
||||
<StdButton onClick={this.props.enterLocation.bind(this, locName)} text={locName} />
|
||||
</li>
|
||||
)
|
||||
});
|
||||
const thiscity = this;
|
||||
const topprop = this.props
|
||||
|
||||
function LocationLetter(location: string) {
|
||||
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 (
|
||||
<ul>
|
||||
{locationButtons}
|
||||
</ul>
|
||||
<>
|
||||
{elems}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -32,21 +32,16 @@ export class TravelAgencyLocation extends React.Component<IProps, any> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const travelBtns: React.ReactNode[] = [];
|
||||
for (const key in CityName) {
|
||||
const city = CityName[key];
|
||||
const thisTravelAgencyLocation = this;
|
||||
|
||||
// Skip current city
|
||||
if (city === this.props.p.city) { continue; }
|
||||
|
||||
travelBtns.push(
|
||||
<StdButton
|
||||
key={city}
|
||||
onClick={createTravelPopup.bind(null, city, this.props.travel)}
|
||||
style={this.btnStyle}
|
||||
text={`Travel to ${city}`}
|
||||
/>
|
||||
)
|
||||
function LocationLetter(props: any) {
|
||||
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)}>
|
||||
<span className='tooltiptext'>{props.city}</span>
|
||||
{props.city[0]}
|
||||
</span>
|
||||
}
|
||||
return <span>{props.city[0]}</span>
|
||||
}
|
||||
|
||||
return (
|
||||
@ -55,7 +50,28 @@ export class TravelAgencyLocation extends React.Component<IProps, any> {
|
||||
From here, you can travel to any other city! A ticket
|
||||
costs {numeralWrapper.formatMoney(CONSTANTS.TravelCost)}
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
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,
|
||||
getAugmentationPrereq: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getAugmentationCost: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
getAugmentationStats: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
purchaseAugmentation: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
softReset: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
installAugmentations: () => RamCostConstants.ScriptSingularityFn3RamCost,
|
||||
|
||||
// Gang API
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
augmentationExists,
|
||||
installAugmentations
|
||||
} from "./Augmentation/AugmentationHelpers";
|
||||
import { prestigeAugmentation } from "./Prestige";
|
||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
|
||||
import { findCrime } from "./Crime/CrimeHelpers";
|
||||
@ -51,7 +52,7 @@ import {
|
||||
purchaseHashUpgrade,
|
||||
updateHashManagerCapacity,
|
||||
} from "./Hacknet/HacknetHelpers";
|
||||
import { HacknetServer } from "./Hacknet/HacknetServer";
|
||||
import { HacknetServer, MaxNumberHacknetServers } from "./Hacknet/HacknetServer";
|
||||
import { CityName } from "./Locations/data/CityNames";
|
||||
import { LocationName } from "./Locations/data/LocationNames";
|
||||
|
||||
@ -391,6 +392,9 @@ function NetscriptFunctions(workerScript) {
|
||||
numNodes : function() {
|
||||
return Player.hacknetNodes.length;
|
||||
},
|
||||
maxNumNodes : function() {
|
||||
return MaxNumberHacknetServers;
|
||||
},
|
||||
purchaseNode : function() {
|
||||
return purchaseHacknet();
|
||||
},
|
||||
@ -2742,6 +2746,12 @@ function NetscriptFunctions(workerScript) {
|
||||
workChaExpGain: Player.workChaExpGained,
|
||||
workRepGain: Player.workRepGained,
|
||||
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() {
|
||||
@ -3415,6 +3425,24 @@ function NetscriptFunctions(workerScript) {
|
||||
var aug = Augmentations[name];
|
||||
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) {
|
||||
updateDynamicRam("purchaseAugmentation", getRamCost("purchaseAugmentation"));
|
||||
if (Player.bitNodeN !== 4) {
|
||||
@ -3483,6 +3511,24 @@ function NetscriptFunctions(workerScript) {
|
||||
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) {
|
||||
updateDynamicRam("installAugmentations", getRamCost("installAugmentations"));
|
||||
if (Player.bitNodeN !== 4) {
|
||||
|
@ -6,6 +6,7 @@ import { killWorkerScript } from "./Netscript/killWorkerScript";
|
||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||
import { workerScripts } from "./Netscript/WorkerScripts";
|
||||
import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter";
|
||||
import { generateNextPid } from "./Netscript/Pid";
|
||||
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { Engine } from "./engine";
|
||||
@ -412,42 +413,6 @@ function processNetscript1Imports(code, workerScript) {
|
||||
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
|
||||
* 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
|
||||
if (!w.running) { return; }
|
||||
|
||||
console.log("Stopping script " + w.name + " because it finished running naturally");
|
||||
killWorkerScript(s);
|
||||
w.log("Script finished running");
|
||||
}).catch(function(w) {
|
||||
@ -547,8 +511,8 @@ export function createAndAddWorkerScript(runningScriptObj, server) {
|
||||
if (isScriptErrorMessage(w.errorMessage)) {
|
||||
var errorTextArray = w.errorMessage.split("|");
|
||||
if (errorTextArray.length != 4) {
|
||||
console.log("ERROR: Something wrong with Error text in evaluator...");
|
||||
console.log("Error text: " + errorText);
|
||||
console.error("ERROR: Something wrong with Error text in evaluator...");
|
||||
console.error("Error text: " + errorText);
|
||||
return;
|
||||
}
|
||||
var serverIp = errorTextArray[1];
|
||||
@ -567,11 +531,11 @@ export function createAndAddWorkerScript(runningScriptObj, server) {
|
||||
w.env.stopFlag = true;
|
||||
} else if (isScriptErrorMessage(w)) {
|
||||
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;
|
||||
} else {
|
||||
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);
|
||||
|
@ -4,7 +4,7 @@ import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||
export function canAccessBladeburner() {
|
||||
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() {
|
||||
|
@ -411,7 +411,7 @@ export function recordMoneySource(amt, source) {
|
||||
|
||||
export function gainHackingExp(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;
|
||||
if(this.hacking_exp < 0) {
|
||||
@ -421,7 +421,7 @@ export function gainHackingExp(exp) {
|
||||
|
||||
export function gainStrengthExp(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;
|
||||
if(this.strength_exp < 0) {
|
||||
@ -431,7 +431,7 @@ export function gainStrengthExp(exp) {
|
||||
|
||||
export function gainDefenseExp(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;
|
||||
if(this.defense_exp < 0) {
|
||||
@ -441,7 +441,7 @@ export function gainDefenseExp(exp) {
|
||||
|
||||
export function gainDexterityExp(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;
|
||||
if(this.dexterity_exp < 0) {
|
||||
@ -451,7 +451,7 @@ export function gainDexterityExp(exp) {
|
||||
|
||||
export function gainAgilityExp(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;
|
||||
if(this.agility_exp < 0) {
|
||||
@ -461,7 +461,7 @@ export function gainAgilityExp(exp) {
|
||||
|
||||
export function gainCharismaExp(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;
|
||||
if(this.charisma_exp < 0) {
|
||||
@ -471,7 +471,7 @@ export function gainCharismaExp(exp) {
|
||||
|
||||
export function gainIntelligenceExp(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) {
|
||||
this.intelligence_exp += exp;
|
||||
@ -1827,7 +1827,6 @@ export function isQualified(company, position) {
|
||||
|
||||
/********** Reapplying Augmentations and Source File ***********/
|
||||
export function reapplyAllAugmentations(resetMultipliers=true) {
|
||||
console.log("Re-applying augmentations");
|
||||
if (resetMultipliers) {
|
||||
this.resetMultipliers();
|
||||
}
|
||||
@ -1856,7 +1855,6 @@ export function reapplyAllAugmentations(resetMultipliers=true) {
|
||||
}
|
||||
|
||||
export function reapplyAllSourceFiles() {
|
||||
console.log("Re-applying source files");
|
||||
//Will always be called after reapplyAllAugmentations() so multipliers do not have to be reset
|
||||
//this.resetMultipliers();
|
||||
|
||||
|
@ -20,6 +20,7 @@ import { Message } from "./Message/Message";
|
||||
import { initMessages, Messages } from "./Message/MessageHelpers";
|
||||
import { prestigeWorkerScripts } from "./NetscriptWorker";
|
||||
import { Player } from "./Player";
|
||||
import { resetPidCounter } from "./Netscript/Pid";
|
||||
|
||||
import {
|
||||
AllServers,
|
||||
@ -172,6 +173,8 @@ function prestigeAugmentation() {
|
||||
DaedalusServer.serversOnNetwork.push(WorldDaemon.ip);
|
||||
}
|
||||
}
|
||||
|
||||
resetPidCounter();
|
||||
}
|
||||
|
||||
|
||||
@ -346,6 +349,8 @@ function prestigeSourceFile() {
|
||||
|
||||
// Gain int exp
|
||||
Player.gainIntelligenceExp(5);
|
||||
|
||||
resetPidCounter();
|
||||
}
|
||||
|
||||
export {prestigeAugmentation, prestigeSourceFile};
|
||||
|
@ -112,7 +112,7 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
|
||||
var request = objectStore.put(saveString, "save");
|
||||
|
||||
request.onerror = function(e) {
|
||||
console.log("Error saving game to IndexedDB: " + e);
|
||||
console.error("Error saving game to IndexedDB: " + e);
|
||||
}
|
||||
|
||||
request.onsuccess = function(e) {
|
||||
@ -124,7 +124,7 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
|
||||
} catch(e) {
|
||||
if (e.code == 22) {
|
||||
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 " +
|
||||
"supports it. If you would like to save to localStorage as well, then " +
|
||||
"consider killing several of your scripts to " +
|
||||
@ -247,7 +247,7 @@ function loadGame(saveString) {
|
||||
try {
|
||||
Settings.load(saveObj.SettingsSave);
|
||||
} 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();
|
||||
}
|
||||
} else {
|
||||
@ -257,7 +257,7 @@ function loadGame(saveString) {
|
||||
try {
|
||||
loadFconf(saveObj.FconfSettingsSave);
|
||||
} catch(e) {
|
||||
console.log("ERROR: Failed to parse .fconf Settings.");
|
||||
console.error("ERROR: Failed to parse .fconf Settings.");
|
||||
}
|
||||
}
|
||||
if (saveObj.hasOwnProperty("VersionSave")) {
|
||||
@ -281,7 +281,7 @@ function loadGame(saveString) {
|
||||
try {
|
||||
loadAllGangs(saveObj.AllGangsSave);
|
||||
} 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 {
|
||||
loadFconf(saveObj.FconfSettingsSave);
|
||||
} 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")) {
|
||||
@ -460,7 +460,7 @@ function loadImportedGame(saveObj, saveString) {
|
||||
try {
|
||||
loadAllGangs(saveObj.AllGangsSave);
|
||||
} 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|" +
|
||||
"getOwnedSourceFiles|getAugmentationsFromFaction|" +
|
||||
"getAugmentationPrereq|getAugmentationCost|purchaseAugmentation|" +
|
||||
"installAugmentations|" +
|
||||
"softReset|installAugmentations|getAugmentationStats|" +
|
||||
|
||||
// TIX API
|
||||
"getStockPrice|getStockPosition|getStockSymbols|getStockMaxShares|" +
|
||||
@ -103,7 +103,7 @@ let NetscriptFunctions =
|
||||
// Hacknet Node API
|
||||
"hacknet|numNodes|purchaseNode|getPurchaseNodeCost|getNodeStats|" +
|
||||
"upgradeLevel|upgradeRam|upgradeCore|upgradeCache|getLevelUpgradeCost|" +
|
||||
"getRamUpgradeCost|getCoreUpgradeCost|getCacheUpgradeCost|" +
|
||||
"getRamUpgradeCost|getCoreUpgradeCost|getCacheUpgradeCost|maxNumNodes|" +
|
||||
|
||||
// Gang API
|
||||
"gang|" +
|
||||
|
@ -1760,7 +1760,14 @@ let Terminal = {
|
||||
const filepath = Terminal.getFilepath(filename);
|
||||
const script = Terminal.getScript(filename);
|
||||
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 {
|
||||
Engine.loadScriptEditorContent(filepath, script.code);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ import {
|
||||
} from "./PersonObjects/Resleeving/ResleevingUI";
|
||||
|
||||
import { createStatusText } from "./ui/createStatusText";
|
||||
import { displayCharacterInfo } from "./ui/displayCharacterInfo";
|
||||
import { CharacterInfo } from "./ui/CharacterInfo";
|
||||
import { Page, routing } from "./ui/navigationTracking";
|
||||
import { numeralWrapper } from "./ui/numeralFormat";
|
||||
import { setSettingsLabels } from "./ui/setSettingsLabels";
|
||||
@ -567,7 +567,7 @@ const Engine = {
|
||||
|
||||
/// Display character info
|
||||
updateCharacterInfo: function() {
|
||||
displayCharacterInfo(Engine.Display.characterInfo, Player);
|
||||
ReactDOM.render(CharacterInfo(Player), Engine.Display.characterInfo)
|
||||
},
|
||||
|
||||
// TODO Refactor this into Faction implementation
|
||||
@ -592,7 +592,7 @@ const Engine = {
|
||||
factionsList.appendChild(createElement("a", {
|
||||
class:"a-link-button", innerText:factionName, padding:"4px", margin:"4px",
|
||||
display:"inline-block",
|
||||
clickListener:()=>{
|
||||
clickListener: () => {
|
||||
Engine.loadFactionContent();
|
||||
displayFactionContent(factionName);
|
||||
return false;
|
||||
@ -774,6 +774,7 @@ const Engine = {
|
||||
updateDisplaysLong: 15,
|
||||
updateActiveScriptsDisplay: 5,
|
||||
createProgramNotifications: 10,
|
||||
augmentationsNotifications: 10,
|
||||
checkFactionInvitations: 100,
|
||||
passiveFactionGrowth: 600,
|
||||
messages: 150,
|
||||
@ -868,6 +869,19 @@ const Engine = {
|
||||
Engine.Counters.createProgramNotifications = 10;
|
||||
}
|
||||
|
||||
if (Engine.Counters.augmentationsNotifications <= 0) {
|
||||
var num = Player.queuedAugmentations.length;
|
||||
var elem = document.getElementById("augmentations-notification");
|
||||
if (num > 0) {
|
||||
elem.innerHTML = num;
|
||||
elem.setAttribute("class", "notification-on");
|
||||
} else {
|
||||
elem.innerHTML = "";
|
||||
elem.setAttribute("class", "notification-off");
|
||||
}
|
||||
Engine.Counters.augmentationsNotifications = 10;
|
||||
}
|
||||
|
||||
if (Engine.Counters.checkFactionInvitations <= 0) {
|
||||
var invitedFactions = Player.checkForFactionInvitations();
|
||||
if (invitedFactions.length > 0) {
|
||||
@ -881,6 +895,17 @@ const Engine = {
|
||||
var randFaction = invitedFactions[Math.floor(Math.random() * invitedFactions.length)];
|
||||
inviteToFaction(randFaction);
|
||||
}
|
||||
|
||||
const num = Player.factionInvitations.length;
|
||||
const elem = document.getElementById("factions-notification");
|
||||
if (num > 0) {
|
||||
elem.innerHTML = num;
|
||||
elem.setAttribute("class", "notification-on");
|
||||
} else {
|
||||
elem.innerHTML = "";
|
||||
elem.setAttribute("class", "notification-off");
|
||||
}
|
||||
|
||||
Engine.Counters.checkFactionInvitations = 100;
|
||||
}
|
||||
|
||||
@ -1536,19 +1561,18 @@ window.onload = function() {
|
||||
indexedDbRequest = window.indexedDB.open("bitburnerSave", 1);
|
||||
|
||||
indexedDbRequest.onerror = function(e) {
|
||||
console.log("Error opening indexedDB: ");
|
||||
console.log(e);
|
||||
console.error("Error opening indexedDB: ");
|
||||
console.error(e);
|
||||
return Engine.load(null); // Try to load from localstorage
|
||||
};
|
||||
|
||||
indexedDbRequest.onsuccess = function(e) {
|
||||
console.log("Opening bitburnerSave database successful!");
|
||||
indexedDb = e.target.result;
|
||||
var transaction = indexedDb.transaction(["savestring"]);
|
||||
var objectStore = transaction.objectStore("savestring");
|
||||
var request = objectStore.get("save");
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -60,9 +60,11 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
|
||||
</li>
|
||||
<li id="factions-tab" class="mainmenu-accordion-panel">
|
||||
<button id="factions-menu-link"> Factions </button>
|
||||
<span id="factions-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
<li id="augmentations-tab" class="mainmenu-accordion-panel">
|
||||
<button id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> Augmentations </button>
|
||||
<span id="augmentations-notification" class="notification-off"> </span>
|
||||
</li>
|
||||
<li id="hacknet-nodes-tab" class="mainmenu-accordion-panel">
|
||||
<button id="hacknet-nodes-menu-link"> Hacknet Nodes </button>
|
||||
|
@ -24,14 +24,14 @@ export function ScriptProduction(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<p id="active-scripts-total-prod">
|
||||
Total online production of Active scripts:
|
||||
Total online production of Active scripts:
|
||||
<span className="money-gold">
|
||||
<span id="active-scripts-total-production-active">
|
||||
{numeralWrapper.formatMoney(onlineProduction)}
|
||||
</span> / sec
|
||||
</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">
|
||||
{numeralWrapper.formatMoney(props.p.scriptProdSinceLastAug)}
|
||||
</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() {
|
||||
const intelligence = (
|
||||
<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>
|
||||
);
|
||||
|
||||
@ -19,28 +19,28 @@ export class CharacterOverviewComponent extends Component {
|
||||
<table>
|
||||
<tbody>
|
||||
<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 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 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 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 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 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 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 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>
|
||||
{
|
||||
Player.intelligence >= 1 &&
|
||||
@ -51,4 +51,4 @@ export class CharacterOverviewComponent extends Component {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ type IProps = {
|
||||
}
|
||||
|
||||
export function SourceFileAccordion(props: IProps): React.ReactElement {
|
||||
const maxLevel = props.sf.n === 3 ? "∞" : "3";
|
||||
const maxLevel = props.sf.n === 12 ? "∞" : "3";
|
||||
|
||||
return (
|
||||
<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;
|
||||
|
||||
function dialogBoxCreate(txt, preformatted=false) {
|
||||
console.log(`dialogBoxCreate() called`)
|
||||
var container = document.createElement("div");
|
||||
container.setAttribute("class", "dialog-box-container");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user