Finished refactoring augmentations page UI to use react

This commit is contained in:
danielyxie 2019-05-15 00:15:07 -07:00 committed by danielyxie
parent 9442b348e6
commit 2597b33f81
14 changed files with 561 additions and 508 deletions

@ -10,6 +10,13 @@
padding-top: 10px; padding-top: 10px;
} }
#augmentations-content {
> p {
font-size: $defaultFontSize * 0.875;
width: 70%;
}
}
.augmentations-list { .augmentations-list {
button, button,
div { div {
@ -18,10 +25,7 @@
} }
button { button {
padding: 2px 5px; padding: 4px;
} }
div {
padding: 6px;
}
} }

@ -1,32 +1,39 @@
import { Augmentation } from "./Augmentation"; import { Augmentation } from "./Augmentation";
import { Augmentations } from "./Augmentations"; import { Augmentations } from "./Augmentations";
import { PlayerOwnedAugmentation } from "./PlayerOwnedAugmentation"; import { PlayerOwnedAugmentation } from "./PlayerOwnedAugmentation";
import { AugmentationNames } from "./data/AugmentationNames"; import { AugmentationNames } from "./data/AugmentationNames";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { AugmentationsRoot } from "./ui/Root";
import { CONSTANTS } from "../Constants";
import { Factions,
factionExists } from "../Faction/Factions";
import { addWorkerScript } from "../NetscriptWorker";
import { Player } from "../Player";
import { prestigeAugmentation } from "../Prestige";
import { saveObject } from "../SaveObject";
import { RunningScript } from "../Script/RunningScript";
import { Script } from "../Script/Script";
import { Server } from "../Server/Server";
import { OwnedAugmentationsOrderSetting } from "../Settings/SettingEnums";
import { Settings } from "../Settings/Settings";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { createAccordionElement } from "../../utils/uiHelpers/createAccordionElement"; import { CONSTANTS } from "../Constants";
import { Reviver, Generic_toJSON, import { Factions, factionExists } from "../Faction/Factions";
Generic_fromJSON } from "../../utils/JSONReviver"; import { addWorkerScript } from "../NetscriptWorker";
import { formatNumber } from "../../utils/StringHelperFunctions"; import { Player } from "../Player";
import { clearObject } from "../../utils/helpers/clearObject"; import { prestigeAugmentation } from "../Prestige";
import { createElement } from "../../utils/uiHelpers/createElement"; import { saveObject } from "../SaveObject";
import { isString } from "../../utils/helpers/isString"; import { RunningScript } from "../Script/RunningScript";
import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement"; import { Script } from "../Script/Script";
import { Server } from "../Server/Server";
import { OwnedAugmentationsOrderSetting } from "../Settings/SettingEnums";
import { Settings } from "../Settings/Settings";
import { Page, routing } from "../ui/navigationTracking";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { createAccordionElement } from "../../utils/uiHelpers/createAccordionElement";
import {
Reviver,
Generic_toJSON,
Generic_fromJSON
} from "../../utils/JSONReviver";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { clearObject } from "../../utils/helpers/clearObject";
import { createElement } from "../../utils/uiHelpers/createElement";
import { isString } from "../../utils/helpers/isString";
import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement";
import React from "react";
import ReactDOM from "react-dom";
function AddToAugmentations(aug) { function AddToAugmentations(aug) {
var name = aug.name; var name = aug.name;
@ -2092,211 +2099,17 @@ function augmentationExists(name) {
return Augmentations.hasOwnProperty(name); return Augmentations.hasOwnProperty(name);
} }
function displayAugmentationsContent(contentEl) { export function displayAugmentationsContent(contentEl) {
removeChildrenFromElement(contentEl); if (!routing.isOn(Page.Augmentations)) { return; }
contentEl.appendChild(createElement("h1", { if (!(contentEl instanceof HTMLElement)) { return; }
innerText:"Purchased Augmentations",
}));
contentEl.appendChild(createElement("pre", { ReactDOM.render(
width:"70%", whiteSpace:"pre-wrap", display:"block", <AugmentationsRoot
innerText:"Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to install them.\n" + exportGameFn={saveObject.exportGame.bind(saveObject)}
"WARNING: Installing your Augmentations resets most of your progress, including:\n\n" + installAugmentationsFn={installAugmentations}
"Stats/Skill levels and Experience\n" + />,
"Money\n" + contentEl
"Scripts on every computer but your home computer\n" + );
"Purchased servers\n" +
"Hacknet Nodes\n" +
"Faction/Company reputation\n" +
"Stocks\n" +
"Installing Augmentations lets you start over with the perks and benefits granted by all " +
"of the Augmentations you have ever installed. Also, you will keep any scripts and RAM/Core upgrades " +
"on your home computer (but you will lose all programs besides NUKE.exe)."
}));
//Install Augmentations button
contentEl.appendChild(createElement("a", {
class:"a-link-button", innerText:"Install Augmentations",
tooltip:"'I never asked for this'",
clickListener:()=>{
installAugmentations();
return false;
}
}));
//Backup button
contentEl.appendChild(createElement("a", {
class:"a-link-button flashing-button", innerText:"Backup Save (Export)",
tooltip:"It's always a good idea to backup/export your save!",
clickListener:()=>{
saveObject.exportGame();
return false;
}
}));
//Purchased/queued augmentations list
var queuedAugmentationsList = createElement("ul", {class:"augmentations-list"});
for (var i = 0; i < Player.queuedAugmentations.length; ++i) {
var augName = Player.queuedAugmentations[i].name;
var aug = Augmentations[augName];
var displayName = augName;
if (augName === AugmentationNames.NeuroFluxGovernor) {
displayName += " - Level " + (Player.queuedAugmentations[i].level);
}
var accordion = createAccordionElement({hdrText:displayName, panelText:aug.info});
queuedAugmentationsList.appendChild(accordion[0]);
}
contentEl.appendChild(queuedAugmentationsList);
//Installed augmentations list
contentEl.appendChild(createElement("h1", {
innerText:"Installed Augmentations", marginTop:"8px",
}));
contentEl.appendChild(createElement("p", {
width:"70%", whiteSpace:"pre-wrap",
innerText:"List of all Augmentations (including Source Files) that have been " +
"installed. You have gained the effects of these Augmentations."
}));
var augmentationsList = createElement("ul", {class:"augmentations-list"});
//Expand/Collapse All buttons
contentEl.appendChild(createElement("a", {
class:"a-link-button", fontSize:"14px", innerText:"Expand All", display:"inline-block",
clickListener:()=>{
var allHeaders = augmentationsList.getElementsByClassName("accordion-header");
for (var i = 0; i < allHeaders.length; ++i) {
if (!allHeaders[i].classList.contains("active")) {allHeaders[i].click();}
}
}
}));
contentEl.appendChild(createElement("a", {
class:"a-link-button", fontSize:"14px", innerText:"Collapse All", display:"inline-block",
clickListener:()=>{
var allHeaders = augmentationsList.getElementsByClassName("accordion-header");
for (var i = 0; i < allHeaders.length; ++i) {
if (allHeaders[i].classList.contains("active")) {allHeaders[i].click();}
}
}
}));
//Sort Buttons
const sortInOrderButton = createElement("a", {
class:"a-link-button", fontSize:"14px", innerText:"Sort in Order",
tooltip:"Sorts the Augmentations alphabetically and Source Files in numerical order (1, 2, 3,...)",
clickListener:()=>{
removeChildrenFromElement(augmentationsList);
//Create a copy of Player's Source Files and augs array and sort them
var sourceFiles = Player.sourceFiles.slice();
var augs = Player.augmentations.slice();
sourceFiles.sort((sf1, sf2)=>{
return sf1.n - sf2.n;
});
augs.sort((aug1, aug2)=>{
return aug1.name <= aug2.name ? -1 : 1;
});
displaySourceFiles(augmentationsList, sourceFiles);
displayAugmentations(augmentationsList, augs);
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically;
}
});
contentEl.appendChild(sortInOrderButton);
const sortByAcquirementTimeButton = createElement("a", {
class:"a-link-button", fontSize:"14px", innerText:"Sort by Acquirement Time",
tooltip:"Sorts the Augmentations and Source Files based on when you acquired them (same as default)",
clickListener:()=>{
removeChildrenFromElement(augmentationsList);
displaySourceFiles(augmentationsList, Player.sourceFiles);
displayAugmentations(augmentationsList, Player.augmentations);
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime;
}
});
contentEl.appendChild(sortByAcquirementTimeButton);
if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
sortInOrderButton.click();
} else {
sortByAcquirementTimeButton.click();
}
contentEl.appendChild(augmentationsList);
// Display multiplier information at the bottom
contentEl.appendChild(createElement("p", {
display: "block",
innerHTML:
`<br><br><strong><u>Total Multipliers:</u></strong><br>` +
'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%<br>' +
'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%<br>' +
'Hacking Money multiplier: ' + formatNumber(Player.hacking_money_mult * 100, 2) + '%<br>' +
'Hacking Growth multiplier: ' + formatNumber(Player.hacking_grow_mult * 100, 2) + '%<br><br>' +
'Hacking Level multiplier: ' + formatNumber(Player.hacking_mult * 100, 2) + '%<br>' +
'Hacking Experience multiplier: ' + formatNumber(Player.hacking_exp_mult * 100, 2) + '%<br><br>' +
'Strength Level multiplier: ' + formatNumber(Player.strength_mult * 100, 2) + '%<br>' +
'Strength Experience multiplier: ' + formatNumber(Player.strength_exp_mult * 100, 2) + '%<br><br>' +
'Defense Level multiplier: ' + formatNumber(Player.defense_mult * 100, 2) + '%<br>' +
'Defense Experience multiplier: ' + formatNumber(Player.defense_exp_mult * 100, 2) + '%<br><br>' +
'Dexterity Level multiplier: ' + formatNumber(Player.dexterity_mult * 100, 2) + '%<br>' +
'Dexterity Experience multiplier: ' + formatNumber(Player.dexterity_exp_mult * 100, 2) + '%<br><br>' +
'Agility Level multiplier: ' + formatNumber(Player.agility_mult * 100, 2) + '%<br>' +
'Agility Experience multiplier: ' + formatNumber(Player.agility_exp_mult * 100, 2) + '%<br><br>' +
'Charisma Level multiplier: ' + formatNumber(Player.charisma_mult * 100, 2) + '%<br>' +
'Charisma Experience multiplier: ' + formatNumber(Player.charisma_exp_mult * 100, 2) + '%<br><br>' +
'Hacknet Node production multiplier: ' + formatNumber(Player.hacknet_node_money_mult * 100, 2) + '%<br>' +
'Hacknet Node purchase cost multiplier: ' + formatNumber(Player.hacknet_node_purchase_cost_mult * 100, 2) + '%<br>' +
'Hacknet Node RAM upgrade cost multiplier: ' + formatNumber(Player.hacknet_node_ram_cost_mult * 100, 2) + '%<br>' +
'Hacknet Node Core purchase cost multiplier: ' + formatNumber(Player.hacknet_node_core_cost_mult * 100, 2) + '%<br>' +
'Hacknet Node level upgrade cost multiplier: ' + formatNumber(Player.hacknet_node_level_cost_mult * 100, 2) + '%<br><br>' +
'Company reputation gain multiplier: ' + formatNumber(Player.company_rep_mult * 100, 2) + '%<br>' +
'Faction reputation gain multiplier: ' + formatNumber(Player.faction_rep_mult * 100, 2) + '%<br>' +
'Salary multiplier: ' + formatNumber(Player.work_money_mult * 100, 2) + '%<br>' +
'Crime success multiplier: ' + formatNumber(Player.crime_success_mult * 100, 2) + '%<br>' +
'Crime money multiplier: ' + formatNumber(Player.crime_money_mult * 100, 2) + '%<br><br><br>',
}))
}
//Creates the accordion elements to display Augmentations
// @listElement - List DOM element to append accordion elements to
// @augs - Array of Augmentation objects
function displayAugmentations(listElement, augs) {
for (var i = 0; i < augs.length; ++i) {
var augName = augs[i].name;
var aug = Augmentations[augName];
var displayName = augName;
if (augName === AugmentationNames.NeuroFluxGovernor) {
displayName += " - Level " + (augs[i].level);
}
var accordion = createAccordionElement({hdrText:displayName, panelText:aug.info});
listElement.appendChild(accordion[0]);
}
}
//Creates the accordion elements to display Source Files
// @listElement - List DOM element to append accordion elements to
// @sourceFiles - Array of Source File objects
function displaySourceFiles(listElement, sourceFiles) {
for (var i = 0; i < sourceFiles.length; ++i) {
var srcFileKey = "SourceFile" + sourceFiles[i].n;
var sourceFileObject = SourceFiles[srcFileKey];
if (sourceFileObject == null) {
console.log("ERROR: Invalid source file number: " + sourceFiles[i].n);
continue;
}
const maxLevel = sourceFiles[i].n == 12 ? "∞" : "3";
var accordion = createAccordionElement({
hdrText:sourceFileObject.name + "<br>" + "Level " + (sourceFiles[i].lvl) + " / "+maxLevel,
panelText:sourceFileObject.info
});
listElement.appendChild(accordion[0]);
}
} }
export function isRepeatableAug(aug) { export function isRepeatableAug(aug) {
@ -2307,6 +2120,9 @@ export function isRepeatableAug(aug) {
return false; return false;
} }
export {installAugmentations, export {
initAugmentations, applyAugmentation, augmentationExists, installAugmentations,
displayAugmentationsContent}; initAugmentations,
applyAugmentation,
augmentationExists,
};

@ -30,11 +30,13 @@ export function InstalledAugmentations(): React.ReactElement {
} }
return ( return (
<AugmentationAccordion aug={aug} key={e.name} level={level} /> <li key={e.name}>
<AugmentationAccordion aug={aug} level={level} />
</li>
) )
}); });
return ( return (
<ul>{augs}</ul> <>{augs}</>
) )
} }

@ -7,18 +7,22 @@
*/ */
import * as React from "react"; import * as React from "react";
import { InstalledAugmentations } from "./InstalledAugmentations";
import { ListConfiguration } from "./ListConfiguration";
import { OwnedSourceFiles } from "./OwnedSourceFiles";
import { Settings } from "../../Settings/Settings"; import { Settings } from "../../Settings/Settings";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
type IProps = { type IProps = {}
}
type IState = { type IState = {
rerenderFlag: boolean; rerenderFlag: boolean;
} }
export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps, IState> { export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps, IState> {
listRef: React.RefObject<HTMLUListElement>;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
@ -26,8 +30,44 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
rerenderFlag: false, rerenderFlag: false,
} }
this.collapseAllHeaders = this.collapseAllHeaders.bind(this);
this.expandAllHeaders = this.expandAllHeaders.bind(this);
this.sortByAcquirementTime = this.sortByAcquirementTime.bind(this); this.sortByAcquirementTime = this.sortByAcquirementTime.bind(this);
this.sortInOrder = this.sortInOrder.bind(this); this.sortInOrder = this.sortInOrder.bind(this);
this.listRef = React.createRef();
}
collapseAllHeaders() {
const ul = this.listRef.current;
if (ul == null) { return; }
const tickers = ul.getElementsByClassName("accordion-header");
for (let i = 0; i < tickers.length; ++i) {
const ticker = tickers[i];
if (!(ticker instanceof HTMLButtonElement)) {
continue;
}
if (ticker.classList.contains("active")) {
ticker.click();
}
}
}
expandAllHeaders() {
const ul = this.listRef.current;
if (ul == null) { return; }
const tickers = ul.getElementsByClassName("accordion-header");
for (let i = 0; i < tickers.length; ++i) {
const ticker = tickers[i];
if (!(ticker instanceof HTMLButtonElement)) {
continue;
}
if (!ticker.classList.contains("active")) {
ticker.click();
}
}
} }
rerender() { rerender() {
@ -50,7 +90,18 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
render() { render() {
return ( return (
<>
<ListConfiguration
collapseAllButtonsFn={this.collapseAllHeaders}
expandAllButtonsFn={this.expandAllHeaders}
sortByAcquirementTimeFn={this.sortByAcquirementTime}
sortInOrderFn={this.sortInOrder}
/>
<ul className="augmentations-list" ref={this.listRef}>
<OwnedSourceFiles />
<InstalledAugmentations />
</ul>
</>
) )
} }
} }

@ -3,3 +3,37 @@
* Source-Files are displayed in the Augmentations UI * Source-Files are displayed in the Augmentations UI
*/ */
import * as React from "react"; import * as React from "react";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
collapseAllButtonsFn: () => void;
expandAllButtonsFn: () => void;
sortByAcquirementTimeFn: () => void;
sortInOrderFn: () => void;
}
export function ListConfiguration(props: IProps): React.ReactElement {
return (
<>
<StdButton
onClick={props.expandAllButtonsFn}
text="Expand All"
/>
<StdButton
onClick={props.collapseAllButtonsFn}
text="Collapse All"
/>
<StdButton
onClick={props.sortInOrderFn}
text="Sort in Order"
tooltip="Sorts the Augmentations alphabetically and Source-Files in numeral order"
/>
<StdButton
onClick={props.sortByAcquirementTimeFn}
text="Sort by Acquirement Time"
tooltip="Sorts the Augmentations and Source-Files based on when you acquired them (same as default)"
/>
</>
)
}

@ -5,36 +5,37 @@
import * as React from "react"; import * as React from "react";
import { Player } from "../../Player"; import { Player } from "../../Player";
import { Augmentations } from "../../Augmentation/Augmentations";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Settings } from "../../Settings/Settings"; import { Settings } from "../../Settings/Settings";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { SourceFiles } from "../../SourceFile/SourceFiles";
import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion"; import { SourceFileAccordion } from "../../ui/React/SourceFileAccordion";
export function OwnedSourceFiles(): React.ReactElement { export function OwnedSourceFiles(): React.ReactElement {
const sourceAugs = Player.augmentations.slice(); const sourceSfs = Player.sourceFiles.slice();
if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) { if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
sourceAugs.sort((aug1, aug2) => { sourceSfs.sort((sf1, sf2) => {
return aug1.name <= aug2.name ? -1 : 1; return sf1.n - sf2.n;
}); });
} }
const augs = sourceAugs.map((e) => { const sfs = sourceSfs.map((e) => {
const aug = Augmentations[e.name]; const srcFileKey = "SourceFile" + e.n;
const sfObj = SourceFiles[srcFileKey];
let level = null; if (sfObj == null) {
if (e.name === AugmentationNames.NeuroFluxGovernor) { console.error(`Invalid source file number: ${e.n}`);
level = e.level; return null;
} }
return ( return (
<AugmentationAccordion aug={aug} key={e.name} level={level} /> <li key={e.n}>
<SourceFileAccordion level={e.lvl} sf={sfObj} />
</li>
) )
}); });
return ( return (
<ul>{augs}</ul> <>{sfs}</>
) );
} }

@ -0,0 +1,96 @@
/**
* React component for displaying the player's multipliers on the Augmentation UI page
*/
import * as React from "react";
import { Player } from "../../Player";
import { numeralWrapper } from "../../ui/numeralFormat";
export function PlayerMultipliers(): React.ReactElement {
return (
<>
<p><strong><u>Total Multipliers:</u></strong></p>
<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>
</>
)
}

@ -20,7 +20,9 @@ export function PurchasedAugmentations(): React.ReactElement {
} }
augs.push( augs.push(
<AugmentationAccordion aug={aug} key={ownedAug.name} level={level} /> <li key={`${ownedAug.name}${ownedAug.level}`}>
<AugmentationAccordion aug={aug} level={level} />
</li>
) )
} }

@ -4,9 +4,11 @@
*/ */
import * as React from "react"; import * as React from "react";
import { Augmentations } from "../../Augmentation/Augmentations"; import { InstalledAugmentationsAndSourceFiles } from "./InstalledAugmentationsAndSourceFiles";
import { Player } from "../../Player"; import { PlayerMultipliers } from "./PlayerMultipliers";
import { PurchasedAugmentations } from "./PurchasedAugmentations";
import { Player } from "../../Player";
import { StdButton } from "../../ui/React/StdButton"; import { StdButton } from "../../ui/React/StdButton";
type IProps = { type IProps = {
@ -25,7 +27,7 @@ export class AugmentationsRoot extends React.Component<IProps, IState> {
render() { render() {
return ( return (
<div> <div id="augmentations-content">
<h1>Purchased Augmentations</h1> <h1>Purchased Augmentations</h1>
<p> <p>
Below is a list of all Augmentations you have purchased but not Below is a list of all Augmentations you have purchased but not
@ -34,14 +36,14 @@ export class AugmentationsRoot extends React.Component<IProps, IState> {
<p> <p>
WARNING: Installing your Augmentations resets most of your progress, WARNING: Installing your Augmentations resets most of your progress,
including: including:
</p> </p><br />
<p>- Stats/Skill levels and Experience</p> <p>- Stats/Skill levels and Experience</p>
<p>- Money</p> <p>- Money</p>
<p>- Scripts on every computer but your home computer</p> <p>- Scripts on every computer but your home computer</p>
<p>- Purchased servers</p> <p>- Purchased servers</p>
<p>- Hacknet Nodes</p> <p>- Hacknet Nodes</p>
<p>- Faction/Company reputation</p> <p>- Faction/Company reputation</p>
<p>- Stocks</p> <p>- Stocks</p><br />
<p> <p>
Installing Augmentations lets you start over with the perks and Installing Augmentations lets you start over with the perks and
benefits granted by all of the Augmentations you have ever benefits granted by all of the Augmentations you have ever
@ -62,10 +64,19 @@ export class AugmentationsRoot extends React.Component<IProps, IState> {
text="Backup Save (Export)" text="Backup Save (Export)"
tooltip="It's always a good idea to backup/export your save!" tooltip="It's always a good idea to backup/export your save!"
/> />
<PurchasedAugmentations />
<ul className="augmentations-list"> <h1>Installed Augmentations</h1>
<p>
{
`List of all Augmentations ${Player.sourceFiles.length > 0 ? "and Source Files " : ""} ` +
`that have been installed. You have gained the effects of these.`
}
</p>
<InstalledAugmentationsAndSourceFiles />
</ul> <br /> <br />
<PlayerMultipliers />
</div> </div>
) )
} }

@ -25,235 +25,232 @@ class BitNode {
} }
export let BitNodes: IMap<BitNode> = {}; export const BitNodes: IMap<BitNode> = {};
export function initBitNodes() { BitNodes["BitNode1"] = new BitNode(1, "Source Genesis", "The original BitNode",
BitNodes = {}; "The first BitNode created by the Enders to imprison the minds of humans. It became " +
BitNodes["BitNode1"] = new BitNode(1, "Source Genesis", "The original BitNode", "the prototype and testing-grounds for all of the BitNodes that followed.<br><br>" +
"The first BitNode created by the Enders to imprison the minds of humans. It became " + "This is the first BitNode that you play through. It has no special " +
"the prototype and testing-grounds for all of the BitNodes that followed.<br><br>" + "modifications or mechanics.<br><br>" +
"This is the first BitNode that you play through. It has no special " + "Destroying this BitNode will give you Source-File 1, or if you already have " +
"modifications or mechanics.<br><br>" + "this Source-File it will upgrade its level up to a maximum of 3. This Source-File " +
"Destroying this BitNode will give you Source-File 1, or if you already have " + "lets the player start with 32GB of RAM on his/her home computer when entering a " +
"this Source-File it will upgrade its level up to a maximum of 3. This Source-File " + "new BitNode, and also increases all of the player's multipliers by:<br><br>" +
"lets the player start with 32GB of RAM on his/her home computer when entering a " + "Level 1: 16%<br>" +
"new BitNode, and also increases all of the player's multipliers by:<br><br>" + "Level 2: 24%<br>" +
"Level 1: 16%<br>" + "Level 3: 28%");
"Level 2: 24%<br>" + BitNodes["BitNode2"] = new BitNode(2, "Rise of the Underworld", "From the shadows, they rose", //Gangs
"Level 3: 28%"); "From the shadows, they rose.<br><br>Organized crime groups quickly filled the void of power " +
BitNodes["BitNode2"] = new BitNode(2, "Rise of the Underworld", "From the shadows, they rose", //Gangs "left behind from the collapse of Western government in the 2050s. As society and civlization broke down, " +
"From the shadows, they rose.<br><br>Organized crime groups quickly filled the void of power " + "people quickly succumbed to the innate human impulse of evil and savagery. The organized crime " +
"left behind from the collapse of Western government in the 2050s. As society and civlization broke down, " + "factions quickly rose to the top of the modern world.<br><br>" +
"people quickly succumbed to the innate human impulse of evil and savagery. The organized crime " + "In this BitNode:<br><br>" +
"factions quickly rose to the top of the modern world.<br><br>" + "Your hacking level is reduced by 20%<br>" +
"In this BitNode:<br><br>" + "The growth rate and maximum amount of money available on servers are significantly decreased<br>" +
"Your hacking level is reduced by 20%<br>" + "The amount of money gained from crimes and Infiltration is tripled<br>" +
"The growth rate and maximum amount of money available on servers are significantly decreased<br>" + "Certain Factions (Slum Snakes, Tetrads, The Syndicate, The Dark Army, Speakers for the Dead, " +
"The amount of money gained from crimes and Infiltration is tripled<br>" + "NiteSec, The Black Hand) give the player the ability to form and manage their own gangs. These gangs " +
"Certain Factions (Slum Snakes, Tetrads, The Syndicate, The Dark Army, Speakers for the Dead, " + "will earn the player money and reputation with the corresponding Faction<br>" +
"NiteSec, The Black Hand) give the player the ability to form and manage their own gangs. These gangs " + "Every Augmentation in the game will be available through the Factions listed above<br>" +
"will earn the player money and reputation with the corresponding Faction<br>" + "For every Faction NOT listed above, reputation gains are halved<br>" +
"Every Augmentation in the game will be available through the Factions listed above<br>" + "You will no longer gain passive reputation with Factions<br><br>" +
"For every Faction NOT listed above, reputation gains are halved<br>" + "Destroying this BitNode will give you Source-File 2, or if you already have this Source-File it will " +
"You will no longer gain passive reputation with Factions<br><br>" + "upgrade its level up to a maximum of 3. This Source-File allows you to form gangs in other BitNodes " +
"Destroying this BitNode will give you Source-File 2, or if you already have this Source-File it will " + "once your karma decreases to a certain value. " +
"upgrade its level up to a maximum of 3. This Source-File allows you to form gangs in other BitNodes " + "It also increases the player's crime success rate, crime money, and charisma multipliers by:<br><br>" +
"once your karma decreases to a certain value. " + "Level 1: 24%<br>" +
"It also increases the player's crime success rate, crime money, and charisma multipliers by:<br><br>" + "Level 2: 36%<br>" +
"Level 1: 24%<br>" + "Level 3: 42%");
"Level 2: 36%<br>" + BitNodes["BitNode3"] = new BitNode(3, "Corporatocracy", "The Price of Civilization",
"Level 3: 42%"); "Our greatest illusion is that a healthy society can revolve around a " +
BitNodes["BitNode3"] = new BitNode(3, "Corporatocracy", "The Price of Civilization", "single-minded pursuit of wealth.<br><br>" +
"Our greatest illusion is that a healthy society can revolve around a " + "Sometime in the early 21st century economic and political globalization turned " +
"single-minded pursuit of wealth.<br><br>" + "the world into a corporatocracy, and it never looked back. Now, the privileged " +
"Sometime in the early 21st century economic and political globalization turned " + "elite will happily bankrupt their own countrymen, decimate their own community, " +
"the world into a corporatocracy, and it never looked back. Now, the privileged " + "and evict their neighbors from houses in their desperate bid to increase their wealth.<br><br>" +
"elite will happily bankrupt their own countrymen, decimate their own community, " + "In this BitNode you can create and manage your own corporation. Running a successful corporation " +
"and evict their neighbors from houses in their desperate bid to increase their wealth.<br><br>" + "has the potential of generating massive profits. All other forms of income are reduced by 75%. Furthermore: <br><br>" +
"In this BitNode you can create and manage your own corporation. Running a successful corporation " + "The price and reputation cost of all Augmentations is tripled<br>" +
"has the potential of generating massive profits. All other forms of income are reduced by 75%. Furthermore: <br><br>" + "The starting and maximum amount of money on servers is reduced by 75%<br>" +
"The price and reputation cost of all Augmentations is tripled<br>" + "Server growth rate is reduced by 80%<br>" +
"The starting and maximum amount of money on servers is reduced by 75%<br>" + "You now only need 75 favour with a faction in order to donate to it, rather than 150<br><br>" +
"Server growth rate is reduced by 80%<br>" + "Destroying this BitNode will give you Source-File 3, or if you already have this Source-File it will " +
"You now only need 75 favour with a faction in order to donate to it, rather than 150<br><br>" + "upgrade its level up to a maximum of 3. This Source-File lets you create corporations on other BitNodes (although " +
"Destroying this BitNode will give you Source-File 3, or if you already have this Source-File it will " + "some BitNodes will disable this mechanic). This Source-File also increases your charisma and company salary multipliers by:<br>" +
"upgrade its level up to a maximum of 3. This Source-File lets you create corporations on other BitNodes (although " + "Level 1: 8%<br>" +
"some BitNodes will disable this mechanic). This Source-File also increases your charisma and company salary multipliers by:<br>" + "Level 2: 12%<br>" +
"Level 1: 8%<br>" + "Level 3: 14%");
"Level 2: 12%<br>" + BitNodes["BitNode4"] = new BitNode(4, "The Singularity", "The Man and the Machine",
"Level 3: 14%"); "The Singularity has arrived. The human race is gone, replaced " +
BitNodes["BitNode4"] = new BitNode(4, "The Singularity", "The Man and the Machine", "by artificially superintelligent beings that are more machine than man. <br><br>" +
"The Singularity has arrived. The human race is gone, replaced " + "In this BitNode, progressing is significantly harder. Experience gain rates " +
"by artificially superintelligent beings that are more machine than man. <br><br>" + "for all stats are reduced. Most methods of earning money will now give significantly less.<br><br>" +
"In this BitNode, progressing is significantly harder. Experience gain rates " + "In this BitNode you will gain access to a new set of Netscript Functions known as Singularity Functions. " +
"for all stats are reduced. Most methods of earning money will now give significantly less.<br><br>" + "These functions allow you to control most aspects of the game through scripts, including working for factions/companies, " +
"In this BitNode you will gain access to a new set of Netscript Functions known as Singularity Functions. " + "purchasing/installing Augmentations, and creating programs.<br><br>" +
"These functions allow you to control most aspects of the game through scripts, including working for factions/companies, " + "Destroying this BitNode will give you Source-File 4, or if you already have this Source-File it will " +
"purchasing/installing Augmentations, and creating programs.<br><br>" + "upgrade its level up to a maximum of 3. This Source-File lets you access and use the Singularity " +
"Destroying this BitNode will give you Source-File 4, or if you already have this Source-File it will " + "Functions in other BitNodes. Each level of this Source-File will open up more Singularity Functions " +
"upgrade its level up to a maximum of 3. This Source-File lets you access and use the Singularity " + "that you can use.");
"Functions in other BitNodes. Each level of this Source-File will open up more Singularity Functions " + BitNodes["BitNode5"] = new BitNode(5, "Artificial Intelligence", "Posthuman",
"that you can use."); "They said it couldn't be done. They said the human brain, " +
BitNodes["BitNode5"] = new BitNode(5, "Artificial Intelligence", "Posthuman", "along with its consciousness and intelligence, couldn't be replicated. They said the complexity " +
"They said it couldn't be done. They said the human brain, " + "of the brain results from unpredictable, nonlinear interactions that couldn't be modeled " +
"along with its consciousness and intelligence, couldn't be replicated. They said the complexity " + "by 1's and 0's. They were wrong.<br><br>" +
"of the brain results from unpredictable, nonlinear interactions that couldn't be modeled " + "In this BitNode:<br><br>" +
"by 1's and 0's. They were wrong.<br><br>" + "The base security level of servers is doubled<br>" +
"In this BitNode:<br><br>" + "The starting money on servers is halved, but the maximum money remains the same<br>" +
"The base security level of servers is doubled<br>" + "Most methods of earning money now give significantly less<br>" +
"The starting money on servers is halved, but the maximum money remains the same<br>" + "Infiltration gives 50% more reputation and money<br>" +
"Most methods of earning money now give significantly less<br>" + "Corporations have 50% lower valuations and are therefore less profitable<br>" +
"Infiltration gives 50% more reputation and money<br>" + "Augmentations are more expensive<br>" +
"Corporations have 50% lower valuations and are therefore less profitable<br>" + "Hacking experience gain rates are reduced<br><br>" +
"Augmentations are more expensive<br>" + "Destroying this BitNode will give you Source-File 5, or if you already have this Source-File it will " +
"Hacking experience gain rates are reduced<br><br>" + "upgrade its level up to a maximum of 3. This Source-File grants you a special new stat called Intelligence. " +
"Destroying this BitNode will give you Source-File 5, or if you already have this Source-File it will " + "Intelligence is unique because it is permanent and persistent (it never gets reset back to 1). However " +
"upgrade its level up to a maximum of 3. This Source-File grants you a special new stat called Intelligence. " + "gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't know " +
"Intelligence is unique because it is permanent and persistent (it never gets reset back to 1). However " + "when you gain experience and how much). Higher Intelligence levels will boost your production for many actions " +
"gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't know " + "in the game. <br><br>" +
"when you gain experience and how much). Higher Intelligence levels will boost your production for many actions " + "In addition, this Source-File will unlock the getBitNodeMultipliers() Netscript function, " +
"in the game. <br><br>" + "and will also raise all of your hacking-related multipliers by:<br><br>" +
"In addition, this Source-File will unlock the getBitNodeMultipliers() Netscript function, " + "Level 1: 8%<br>" +
"and will also raise all of your hacking-related multipliers by:<br><br>" + "Level 2: 12%<br>" +
"Level 1: 8%<br>" + "Level 3: 14%");
"Level 2: 12%<br>" + BitNodes["BitNode6"] = new BitNode(6, "Bladeburners", "Like Tears in Rain",
"Level 3: 14%"); "In the middle of the 21st century, OmniTek Incorporated began designing and manufacturing advanced synthetic " +
BitNodes["BitNode6"] = new BitNode(6, "Bladeburners", "Like Tears in Rain", "androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth generation " +
"In the middle of the 21st century, OmniTek Incorporated began designing and manufacturing advanced synthetic " + "of their Synthoid design, called MK-VI, by developing a hyperintelligent AI. Many argue that this was " +
"androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth generation " + "the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, and more intelligent " +
"of their Synthoid design, called MK-VI, by developing a hyperintelligent AI. Many argue that this was " + "than the humans that had created them.<br><br>" +
"the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, and more intelligent " + "In this BitNode you will be able to access the Bladeburner Division at the NSA, which provides a new mechanic " +
"than the humans that had created them.<br><br>" + "for progression. Furthermore:<br><br>" +
"In this BitNode you will be able to access the Bladeburner Division at the NSA, which provides a new mechanic " + "Hacking and Hacknet Nodes will be less profitable<br>" +
"for progression. Furthermore:<br><br>" + "Your hacking level is reduced by 65%<br>" +
"Hacking and Hacknet Nodes will be less profitable<br>" + "Hacking experience gain from scripts is reduced by 75%<br>" +
"Your hacking level is reduced by 65%<br>" + "Corporations have 80% lower valuations and are therefore less profitable<br>" +
"Hacking experience gain from scripts is reduced by 75%<br>" + "Working for companies is 50% less profitable<br>" +
"Corporations have 80% lower valuations and are therefore less profitable<br>" + "Crimes and Infiltration are 25% less profitable<br><br>" +
"Working for companies is 50% less profitable<br>" + "Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade " +
"Crimes and Infiltration are 25% less profitable<br><br>" + "its level up to a maximum of 3. This Source-File allows you to access the NSA's Bladeburner Division in other " +
"Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade " + "BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your combat stats by:<br><br>" +
"its level up to a maximum of 3. This Source-File allows you to access the NSA's Bladeburner Division in other " + "Level 1: 8%<br>" +
"BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your combat stats by:<br><br>" + "Level 2: 12%<br>" +
"Level 1: 8%<br>" + "Level 3: 14%");
"Level 2: 12%<br>" + BitNodes["BitNode7"] = new BitNode(7, "Bladeburners 2079", "More human than humans",
"Level 3: 14%"); "In the middle of the 21st century, you were doing cutting-edge work at OmniTek Incorporated as part of the AI design team " +
BitNodes["BitNode7"] = new BitNode(7, "Bladeburners 2079", "More human than humans", "for advanced synthetic androids, or Synthoids for short. You helped achieve a major technological " +
"In the middle of the 21st century, you were doing cutting-edge work at OmniTek Incorporated as part of the AI design team " + "breakthrough in the sixth generation of the company's Synthoid design, called MK-VI, by developing a hyperintelligent AI. " +
"for advanced synthetic androids, or Synthoids for short. You helped achieve a major technological " + "Many argue that this was the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, " +
"breakthrough in the sixth generation of the company's Synthoid design, called MK-VI, by developing a hyperintelligent AI. " + "and more intelligent than the humans that had created them.<br><br>" +
"Many argue that this was the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, " + "In this BitNode you will be able to access the Bladeburner API, which allows you to access Bladeburner " +
"and more intelligent than the humans that had created them.<br><br>" + "functionality through Netscript. Furthermore: <br><br>" +
"In this BitNode you will be able to access the Bladeburner API, which allows you to access Bladeburner " + "The rank you gain from Bladeburner contracts/operations is reduced by 40%<br>" +
"functionality through Netscript. Furthermore: <br><br>" + "Bladeburner skills cost twice as many skill points<br>" +
"The rank you gain from Bladeburner contracts/operations is reduced by 40%<br>" + "Augmentations are 3x more expensive<br>" +
"Bladeburner skills cost twice as many skill points<br>" + "Hacking and Hacknet Nodes will be significantly less profitable<br>" +
"Augmentations are 3x more expensive<br>" + "Your hacking level is reduced by 65%<br>" +
"Hacking and Hacknet Nodes will be significantly less profitable<br>" + "Hacking experience gain from scripts is reduced by 75%<br>" +
"Your hacking level is reduced by 65%<br>" + "Corporations have 80% lower valuations and are therefore less profitable<br>" +
"Hacking experience gain from scripts is reduced by 75%<br>" + "Working for companies is 50% less profitable<br>" +
"Corporations have 80% lower valuations and are therefore less profitable<br>" + "Crimes and Infiltration are 25% less profitable<br><br>" +
"Working for companies is 50% less profitable<br>" + "Destroying this BitNode will give you Source-File 7, or if you already have this Source-File it will upgrade " +
"Crimes and Infiltration are 25% less profitable<br><br>" + "its level up to a maximum of 3. This Source-File allows you to access the Bladeburner Netscript API in other " +
"Destroying this BitNode will give you Source-File 7, or if you already have this Source-File it will upgrade " + "BitNodes. In addition, this Source-File will increase all of your Bladeburner multipliers by:<br><br>" +
"its level up to a maximum of 3. This Source-File allows you to access the Bladeburner Netscript API in other " + "Level 1: 8%<br>" +
"BitNodes. In addition, this Source-File will increase all of your Bladeburner multipliers by:<br><br>" + "Level 2: 12%<br>" +
"Level 1: 8%<br>" + "Level 3: 14%");
"Level 2: 12%<br>" + BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "Money never sleeps",
"Level 3: 14%"); "You are trying to make a name for yourself as an up-and-coming hedge fund manager on Wall Street.<br><br>" +
BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "Money never sleeps", "In this BitNode:<br><br>" +
"You are trying to make a name for yourself as an up-and-coming hedge fund manager on Wall Street.<br><br>" + "You start with $250 million<br>" +
"In this BitNode:<br><br>" + "The only way to earn money is by trading on the stock market<br>" +
"You start with $250 million<br>" + "You start with a WSE membership and access to the TIX API<br>" +
"The only way to earn money is by trading on the stock market<br>" + "You are able to short stocks and place different types of orders (limit/stop)<br>" +
"You start with a WSE membership and access to the TIX API<br>" + "You can immediately donate to factions to gain reputation<br><br>" +
"You are able to short stocks and place different types of orders (limit/stop)<br>" + "Destroying this BitNode will give you Source-File 8, or if you already have this Source-File it will " +
"You can immediately donate to factions to gain reputation<br><br>" + "upgrade its level up to a maximum of 3. This Source-File grants the following benefits:<br><br>" +
"Destroying this BitNode will give you Source-File 8, or if you already have this Source-File it will " + "Level 1: Permanent access to WSE and TIX API<br>" +
"upgrade its level up to a maximum of 3. This Source-File grants the following benefits:<br><br>" + "Level 2: Ability to short stocks in other BitNodes<br>" +
"Level 1: Permanent access to WSE and TIX API<br>" + "Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" +
"Level 2: Ability to short stocks in other BitNodes<br>" + "This Source-File also increases your hacking growth multipliers by: " +
"Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" + "<br>Level 1: 12%<br>Level 2: 18%<br>Level 3: 21%");
"This Source-File also increases your hacking growth multipliers by: " + BitNodes["BitNode9"] = new BitNode(9, "Hacktocracy", "Hacknet Unleashed",
"<br>Level 1: 12%<br>Level 2: 18%<br>Level 3: 21%"); "When Fulcrum Technologies released their open-source Linux distro Chapeau, it quickly " +
BitNodes["BitNode9"] = new BitNode(9, "Hacktocracy", "Hacknet Unleashed", "became the OS of choice for the underground hacking community. Chapeau became especially notorious for " +
"When Fulcrum Technologies released their open-source Linux distro Chapeau, it quickly " + "powering the Hacknet, a global, decentralized network used for nefarious purposes. Fulcrum quickly " +
"became the OS of choice for the underground hacking community. Chapeau became especially notorious for " + "abandoned the project and dissociated themselves from it.<br><br>" +
"powering the Hacknet, a global, decentralized network used for nefarious purposes. Fulcrum quickly " + "This BitNode unlocks the Hacknet Server, an upgraded version of the Hacknet Node. Hacknet Servers generate " +
"abandoned the project and dissociated themselves from it.<br><br>" + "hashes, which can be spent on a variety of different upgrades.<br><br>" +
"This BitNode unlocks the Hacknet Server, an upgraded version of the Hacknet Node. Hacknet Servers generate " + "In this BitNode:<br><br>" +
"hashes, which can be spent on a variety of different upgrades.<br><br>" + "Your stats are significantly decreased<br>" +
"In this BitNode:<br><br>" + "You cannnot purchase additional servers<br>" +
"Your stats are significantly decreased<br>" + "Hacking is significantly less profitable<br><br>" +
"You cannnot purchase additional servers<br>" + "Destroying this BitNode will give you Source-File 9, or if you already have this Source-File it will " +
"Hacking is significantly less profitable<br><br>" + "upgrade its level up to a maximum of 3. This Source-File grants the following benefits:<br><br>" +
"Destroying this BitNode will give you Source-File 9, or if you already have this Source-File it will " + "Level 1: Permanently unlocks the Hacknet Server in other BitNodes<br>" +
"upgrade its level up to a maximum of 3. This Source-File grants the following benefits:<br><br>" + "Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode<br>" +
"Level 1: Permanently unlocks the Hacknet Server in other BitNodes<br>" + "Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode<br><br>" +
"Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode<br>" + "(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT " +
"Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode<br><br>" + "when installing Augmentations)");
"(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT " + BitNodes["BitNode10"] = new BitNode(10, "Digital Carbon", "Your body is not who you are",
"when installing Augmentations)"); "In 2084, VitaLife unveiled to the world the Persona Core, a technology that allowed people " +
BitNodes["BitNode10"] = new BitNode(10, "Digital Carbon", "Your body is not who you are", "to digitize their consciousness. Their consciousness could then be transferred into Synthoids " +
"In 2084, VitaLife unveiled to the world the Persona Core, a technology that allowed people " + "or other bodies by trasmitting the digitized data. Human bodies became nothing more than 'sleeves' for the " +
"to digitize their consciousness. Their consciousness could then be transferred into Synthoids " + "human consciousness. Mankind had finally achieved immortality - at least for those that could afford it.<br><br>" +
"or other bodies by trasmitting the digitized data. Human bodies became nothing more than 'sleeves' for the " + "This BitNode unlocks Sleeve technology. Sleeve technology allows you to:<br><br>" +
"human consciousness. Mankind had finally achieved immortality - at least for those that could afford it.<br><br>" + "1. Re-sleeve: Purchase and transfer your consciousness into a new body<br>" +
"This BitNode unlocks Sleeve technology. Sleeve technology allows you to:<br><br>" + "2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks synchronously<br><br>" +
"1. Re-sleeve: Purchase and transfer your consciousness into a new body<br>" + "In this BitNode:<br><br>" +
"2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks synchronously<br><br>" + "Your stats are significantly decreased<br>" +
"In this BitNode:<br><br>" + "All methods of gaining money are half as profitable (except Stock Market)<br>" +
"Your stats are significantly decreased<br>" + "Purchased servers are more expensive, have less max RAM, and a lower maximum limit<br>" +
"All methods of gaining money are half as profitable (except Stock Market)<br>" + "Augmentations are 5x as expensive and require twice as much reputation<br><br>" +
"Purchased servers are more expensive, have less max RAM, and a lower maximum limit<br>" + "Destroying this BitNode will give you Source-File 10, or if you already have this Source-File it will " +
"Augmentations are 5x as expensive and require twice as much reputation<br><br>" + "upgrade its level up to a maximum of 3. This Source-File unlocks Sleeve technology in other BitNodes. " +
"Destroying this BitNode will give you Source-File 10, or if you already have this Source-File it will " + "Each level of this Source-File also grants you a Duplicate Sleeve");
"upgrade its level up to a maximum of 3. This Source-File unlocks Sleeve technology in other BitNodes. " + BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
"Each level of this Source-File also grants you a Duplicate Sleeve"); "The 2050s was defined by the massive amounts of violent civil unrest and anarchic rebellion that rose all around the world. It was this period " +
BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.", "of disorder that eventually lead to the governmental reformation of many global superpowers, most notably " +
"The 2050s was defined by the massive amounts of violent civil unrest and anarchic rebellion that rose all around the world. It was this period " + "the USA and China. But just as the world was slowly beginning to recover from these dark times, financial catastrophe hit.<br><br>" +
"of disorder that eventually lead to the governmental reformation of many global superpowers, most notably " + "In many countries, the high cost of trying to deal with the civil disorder bankrupted the governments. In all of this chaos and confusion, hackers " +
"the USA and China. But just as the world was slowly beginning to recover from these dark times, financial catastrophe hit.<br><br>" + "were able to steal billions of dollars from the world's largest electronic banks, prompting an international banking crisis as " +
"In many countries, the high cost of trying to deal with the civil disorder bankrupted the governments. In all of this chaos and confusion, hackers " + "governments were unable to bail out insolvent banks. Now, the world is slowly crumbling in the middle of the biggest economic crisis of all time.<br><br>" +
"were able to steal billions of dollars from the world's largest electronic banks, prompting an international banking crisis as " + "In this BitNode:<br><br>" +
"governments were unable to bail out insolvent banks. Now, the world is slowly crumbling in the middle of the biggest economic crisis of all time.<br><br>" + "Your hacking stat and experience gain are halved<br>" +
"In this BitNode:<br><br>" + "The starting and maximum amount of money available on servers is significantly decreased<br>" +
"Your hacking stat and experience gain are halved<br>" + "The growth rate of servers is significantly reduced<br>" +
"The starting and maximum amount of money available on servers is significantly decreased<br>" + "Weakening a server is twice as effective<br>" +
"The growth rate of servers is significantly reduced<br>" + "Company wages are decreased by 50%<br>" +
"Weakening a server is twice as effective<br>" + "Corporation valuations are 99% lower and are therefore significantly less profitable<br>" +
"Company wages are decreased by 50%<br>" + "Hacknet Node production is significantly decreased<br>" +
"Corporation valuations are 99% lower and are therefore significantly less profitable<br>" + "Crime and Infiltration are more lucrative<br>" +
"Hacknet Node production is significantly decreased<br>" + "Augmentations are twice as expensive<br><br>" +
"Crime and Infiltration are more lucrative<br>" + "Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will " +
"Augmentations are twice as expensive<br><br>" + "upgrade its level up to a maximum of 3. This Source-File makes it so that company favor increases BOTH " +
"Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will " + "the player's salary and reputation gain rate at that company by 1% per favor (rather than just the reputation gain). " +
"upgrade its level up to a maximum of 3. This Source-File makes it so that company favor increases BOTH " + "This Source-File also increases the player's company salary and reputation gain multipliers by:<br><br>" +
"the player's salary and reputation gain rate at that company by 1% per favor (rather than just the reputation gain). " + "Level 1: 32%<br>" +
"This Source-File also increases the player's company salary and reputation gain multipliers by:<br><br>" + "Level 2: 48%<br>" +
"Level 1: 32%<br>" + "Level 3: 56%");
"Level 2: 48%<br>" + BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
"Level 3: 56%"); "To iterate is human, to recurse divine.<br><br>" +
BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.", "Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give your Souce-File 12, or " +
"To iterate is human, to recurse divine.<br><br>" + "if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give your Souce-File 12, or " + "of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " +
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " + "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)");
"of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " + // Books: Frontera, Shiner
"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)"); BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
//Books: Frontera, Shiner BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON");
BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes BitNodes["BitNode15"] = new BitNode(15, "", "COMING SOON");
BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON"); BitNodes["BitNode16"] = new BitNode(16, "", "COMING SOON");
BitNodes["BitNode15"] = new BitNode(15, "", "COMING SOON"); BitNodes["BitNode17"] = new BitNode(17, "", "COMING SOON");
BitNodes["BitNode16"] = new BitNode(16, "", "COMING SOON"); BitNodes["BitNode18"] = new BitNode(18, "", "COMING SOON");
BitNodes["BitNode17"] = new BitNode(17, "", "COMING SOON"); BitNodes["BitNode19"] = new BitNode(19, "", "COMING SOON");
BitNodes["BitNode18"] = new BitNode(18, "", "COMING SOON"); BitNodes["BitNode20"] = new BitNode(20, "", "COMING SOON");
BitNodes["BitNode19"] = new BitNode(19, "", "COMING SOON"); BitNodes["BitNode21"] = new BitNode(21, "", "COMING SOON");
BitNodes["BitNode20"] = new BitNode(20, "", "COMING SOON"); BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON");
BitNodes["BitNode21"] = new BitNode(21, "", "COMING SOON"); BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON");
BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON"); BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON");
BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
}
export function initBitNodeMultipliers(p: IPlayer) { export function initBitNodeMultipliers(p: IPlayer) {
if (p.bitNodeN == null) { if (p.bitNodeN == null) {

@ -15,7 +15,6 @@ import {
import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
import { import {
BitNodes, BitNodes,
initBitNodes,
initBitNodeMultipliers initBitNodeMultipliers
} from "./BitNode/BitNode"; } from "./BitNode/BitNode";
import { Bladeburner } from "./Bladeburner"; import { Bladeburner } from "./Bladeburner";
@ -310,8 +309,8 @@ const Engine = {
loadAugmentationsContent: function() { loadAugmentationsContent: function() {
Engine.hideAllContent(); Engine.hideAllContent();
Engine.Display.augmentationsContent.style.display = "block"; Engine.Display.augmentationsContent.style.display = "block";
displayAugmentationsContent(Engine.Display.augmentationsContent);
routing.navigateTo(Page.Augmentations); routing.navigateTo(Page.Augmentations);
displayAugmentationsContent(Engine.Display.augmentationsContent);
MainMenuLinks.Augmentations.classList.add("active"); MainMenuLinks.Augmentations.classList.add("active");
}, },
@ -488,13 +487,20 @@ const Engine = {
Engine.Display.activeScriptsContent.style.display = "none"; Engine.Display.activeScriptsContent.style.display = "none";
clearHacknetNodesUI(); clearHacknetNodesUI();
Engine.Display.createProgramContent.style.display = "none"; Engine.Display.createProgramContent.style.display = "none";
Engine.Display.factionsContent.style.display = "none"; Engine.Display.factionsContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.factionContent);
Engine.Display.factionContent.style.display = "none"; Engine.Display.factionContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.factionContent);
Engine.Display.augmentationsContent.style.display = "none"; Engine.Display.augmentationsContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.augmentationsContent);
Engine.Display.tutorialContent.style.display = "none"; Engine.Display.tutorialContent.style.display = "none";
Engine.Display.locationContent.style.display = "none"; Engine.Display.locationContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.locationContent); ReactDOM.unmountComponentAtNode(Engine.Display.locationContent);
Engine.Display.workInProgressContent.style.display = "none"; Engine.Display.workInProgressContent.style.display = "none";
Engine.Display.redPillContent.style.display = "none"; Engine.Display.redPillContent.style.display = "none";
Engine.Display.cinematicTextContent.style.display = "none"; Engine.Display.cinematicTextContent.style.display = "none";
@ -1038,7 +1044,6 @@ const Engine = {
// Load game from save or create new game // Load game from save or create new game
if (loadGame(saveString)) { if (loadGame(saveString)) {
initBitNodes();
initBitNodeMultipliers(Player); initBitNodeMultipliers(Player);
Engine.setDisplayElements(); // Sets variables for important DOM elements Engine.setDisplayElements(); // Sets variables for important DOM elements
Engine.init(); // Initialize buttons, work, etc. Engine.init(); // Initialize buttons, work, etc.
@ -1160,7 +1165,6 @@ const Engine = {
} else { } else {
// No save found, start new game // No save found, start new game
console.log("Initializing new game"); console.log("Initializing new game");
initBitNodes();
initBitNodeMultipliers(Player); initBitNodeMultipliers(Player);
initSpecialServerIps(); initSpecialServerIps();
Engine.setDisplayElements(); // Sets variables for important DOM elements Engine.setDisplayElements(); // Sets variables for important DOM elements

@ -45,12 +45,12 @@ export class Accordion extends React.Component<IProps, IState> {
render() { render() {
return ( return (
<div> <>
<button className={"accordion-header"} onClick={this.handleHeaderClick}> <button className={"accordion-header"} onClick={this.handleHeaderClick}>
{this.props.headerContent} {this.props.headerContent}
</button> </button>
<AccordionPanel opened={this.state.panelOpened} panelContent={this.props.panelContent} /> <AccordionPanel opened={this.state.panelOpened} panelContent={this.props.panelContent} />
</div> </>
) )
} }
} }

@ -2,7 +2,7 @@
* React Component for displaying a single Augmentation as an accordion. * React Component for displaying a single Augmentation as an accordion.
* *
* The header of the accordion contains the Augmentation's name (and level, if * The header of the accordion contains the Augmentation's name (and level, if
* applicable), and the accordion's panel contains the Augmentation's level. * applicable), and the accordion's panel contains the Augmentation's description.
*/ */
import * as React from "react"; import * as React from "react";
@ -26,8 +26,8 @@ export function AugmentationAccordion(props: IProps): React.ReactElement {
return ( return (
<Accordion <Accordion
headerContent={<p>{displayName}</p>} headerContent={<>{displayName}</>}
panelContent={<p>{props.aug.info}</p>} panelContent={<p dangerouslySetInnerHTML={{__html: props.aug.info}}></p>}
/> />
) )
} }

@ -0,0 +1,35 @@
/**
* React Component for displaying a single Source-File as an accordion.
*
* The header of the accordion contains the Source-Files's name and level,
* and the accordion's panel contains the Source-File's description.
*/
import * as React from "react";
import { Accordion } from "./Accordion";
import { SourceFile } from "../../SourceFile/SourceFile";
type IProps = {
level: number,
sf: SourceFile,
}
export function SourceFileAccordion(props: IProps): React.ReactElement {
const maxLevel = props.sf.n === 3 ? "∞" : "3";
return (
<Accordion
headerContent={
<>
{props.sf.name}
<br />
{`Level ${props.level} / ${maxLevel}`}
</>
}
panelContent={
<p dangerouslySetInnerHTML={{__html: props.sf.info}}></p>
}
/>
)
}