diff --git a/css/augmentations.scss b/css/augmentations.scss
new file mode 100644
index 000000000..eb7fd3722
--- /dev/null
+++ b/css/augmentations.scss
@@ -0,0 +1,27 @@
+/**
+ * Styling for the Augmentations UI. This is the page that displays all of the
+ * player's owned and purchased Augmentations and Source-Files. It also allows
+ * the player to install Augmentations
+ */
+@import "theme";
+
+#augmentations-container {
+ position: fixed;
+ padding-top: 10px;
+}
+
+.augmentations-list {
+ button,
+ div {
+ color: var(--my-font-color);
+ text-decoration: none;
+ }
+
+ button {
+ padding: 2px 5px;
+ }
+
+ div {
+ padding: 6px;
+ }
+}
diff --git a/css/menupages.scss b/css/menupages.scss
index 0c8e55033..b0b45c723 100644
--- a/css/menupages.scss
+++ b/css/menupages.scss
@@ -185,19 +185,6 @@
width: 70%;
}
-#faction-donate-amount-txt,
-#faction-donate-input {
- padding: 6px;
- margin: 6px;
- display: inline-block;
- color: var(--my-font-color);
- background-color: #000;
-}
-
-#faction-donate-amount-txt {
- width: 50%;
-}
-
#faction-container p,
#faction-container pre {
padding: 4px 6px;
@@ -213,45 +200,12 @@
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
-/* Faction Augmentations */
-#faction-augmentations-container {
- position: fixed;
- padding-top: 10px;
-
- p, a, ul, h1 {
- margin: 8px;
- padding: 4px;
- }
-}
-
/* World */
#world-container li {
margin: 0 0 15px 0;
list-style-type: none;
}
-/* Augmentations */
-#augmentations-container {
- position: fixed;
- padding-top: 10px;
-}
-
-.augmentations-list {
- button,
- div {
- color: var(--my-font-color);
- text-decoration: none;
- }
-
- button {
- padding: 2px 5px;
- }
-
- div {
- padding: 6px;
- }
-}
-
/* Tutorial */
#tutorial-container {
position: fixed;
diff --git a/src/Augmentation/AugmentationHelpers.js b/src/Augmentation/AugmentationHelpers.js
index 7110b70c8..9c6809344 100644
--- a/src/Augmentation/AugmentationHelpers.js
+++ b/src/Augmentation/AugmentationHelpers.js
@@ -17,7 +17,6 @@ import { Server } from "../Server/Server";
import { OwnedAugmentationsOrderSetting } from "../Settings/SettingEnums";
import { Settings } from "../Settings/Settings";
-import { SourceFiles } from "../SourceFile";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { createAccordionElement } from "../../utils/uiHelpers/createAccordionElement";
import { Reviver, Generic_toJSON,
@@ -2041,17 +2040,6 @@ function applyAugmentation(aug, reapply=false) {
}
}
- /*
- if (aug.name === AugmentationNames.NeuroFluxGovernor) {
- for (var i = 0; i < Player.augmentations.length; ++i) {
- if (Player.augmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
- //Already have this aug, just upgrade the level
- return;
- }
- }
- }
- */
-
// Push onto Player's Augmentation list
if (!reapply) {
var ownedAug = new PlayerOwnedAugmentation(aug.name);
diff --git a/src/Augmentation/ui/InstalledAugmentations.tsx b/src/Augmentation/ui/InstalledAugmentations.tsx
new file mode 100644
index 000000000..84d8cb2ea
--- /dev/null
+++ b/src/Augmentation/ui/InstalledAugmentations.tsx
@@ -0,0 +1,40 @@
+/**
+ * React Component for displaying a list of the player's installed Augmentations
+ * on the Augmentations UI
+ */
+import * as React from "react";
+
+import { Player } from "../../Player";
+import { Augmentations } from "../../Augmentation/Augmentations";
+import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
+import { Settings } from "../../Settings/Settings";
+import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
+
+import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
+
+export function InstalledAugmentations(): React.ReactElement {
+ const sourceAugs = Player.augmentations.slice();
+
+ if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
+ sourceAugs.sort((aug1, aug2) => {
+ return aug1.name <= aug2.name ? -1 : 1;
+ });
+ }
+
+ const augs = sourceAugs.map((e) => {
+ const aug = Augmentations[e.name];
+
+ let level = null;
+ if (e.name === AugmentationNames.NeuroFluxGovernor) {
+ level = e.level;
+ }
+
+ return (
+
+ )
+ });
+
+ return (
+
{augs}
+ )
+}
diff --git a/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx b/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx
new file mode 100644
index 000000000..39bac22e6
--- /dev/null
+++ b/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx
@@ -0,0 +1,56 @@
+/**
+ * React Component for displaying all of the player's installed Augmentations and
+ * Source-Files.
+ *
+ * It also contains 'configuration' buttons that allow you to change how the
+ * Augs/SF's are displayed
+ */
+import * as React from "react";
+
+import { Settings } from "../../Settings/Settings";
+import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
+
+type IProps = {
+
+}
+
+type IState = {
+ rerenderFlag: boolean;
+}
+
+export class InstalledAugmentationsAndSourceFiles extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+
+ this.state = {
+ rerenderFlag: false,
+ }
+
+ this.sortByAcquirementTime = this.sortByAcquirementTime.bind(this);
+ this.sortInOrder = this.sortInOrder.bind(this);
+ }
+
+ rerender() {
+ this.setState((prevState) => {
+ return {
+ rerenderFlag: !prevState.rerenderFlag,
+ }
+ });
+ }
+
+ sortByAcquirementTime() {
+ Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime;
+ this.rerender();
+ }
+
+ sortInOrder() {
+ Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically
+ this.rerender();
+ }
+
+ render() {
+ return (
+
+ )
+ }
+}
diff --git a/src/Augmentation/ui/ListConfiguration.tsx b/src/Augmentation/ui/ListConfiguration.tsx
new file mode 100644
index 000000000..ef1368b8f
--- /dev/null
+++ b/src/Augmentation/ui/ListConfiguration.tsx
@@ -0,0 +1,5 @@
+/**
+ * React Component for configuring the way installed augmentations and
+ * Source-Files are displayed in the Augmentations UI
+ */
+import * as React from "react";
diff --git a/src/Augmentation/ui/OwnedSourceFiles.tsx b/src/Augmentation/ui/OwnedSourceFiles.tsx
new file mode 100644
index 000000000..24107bcdf
--- /dev/null
+++ b/src/Augmentation/ui/OwnedSourceFiles.tsx
@@ -0,0 +1,40 @@
+/**
+ * React Component for displaying a list of the player's Source-Files
+ * on the Augmentations UI
+ */
+import * as React from "react";
+
+import { Player } from "../../Player";
+import { Augmentations } from "../../Augmentation/Augmentations";
+import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
+import { Settings } from "../../Settings/Settings";
+import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
+
+import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
+
+export function OwnedSourceFiles(): React.ReactElement {
+ const sourceAugs = Player.augmentations.slice();
+
+ if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
+ sourceAugs.sort((aug1, aug2) => {
+ return aug1.name <= aug2.name ? -1 : 1;
+ });
+ }
+
+ const augs = sourceAugs.map((e) => {
+ const aug = Augmentations[e.name];
+
+ let level = null;
+ if (e.name === AugmentationNames.NeuroFluxGovernor) {
+ level = e.level;
+ }
+
+ return (
+
+ )
+ });
+
+ return (
+
{augs}
+ )
+}
diff --git a/src/Augmentation/ui/PurchasedAugmentations.tsx b/src/Augmentation/ui/PurchasedAugmentations.tsx
new file mode 100644
index 000000000..bd966dfe5
--- /dev/null
+++ b/src/Augmentation/ui/PurchasedAugmentations.tsx
@@ -0,0 +1,30 @@
+/**
+ * React component for displaying all of the player's purchased (but not installed)
+ * Augmentations on the Augmentations UI.
+ */
+import * as React from "react";
+
+import { Augmentations } from "../../Augmentation/Augmentations";
+import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
+import { Player } from "../../Player";
+
+import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
+
+export function PurchasedAugmentations(): React.ReactElement {
+ const augs: React.ReactElement[] = [];
+ for (const ownedAug of Player.queuedAugmentations) {
+ const aug = Augmentations[ownedAug.name];
+ let level = null;
+ if (ownedAug.name === AugmentationNames.NeuroFluxGovernor) {
+ level = ownedAug.level;
+ }
+
+ augs.push(
+
+ )
+ }
+
+ return (
+
{augs}
+ )
+}
diff --git a/src/Augmentation/ui/Root.tsx b/src/Augmentation/ui/Root.tsx
new file mode 100644
index 000000000..565267f31
--- /dev/null
+++ b/src/Augmentation/ui/Root.tsx
@@ -0,0 +1,72 @@
+/**
+ * Root React component for the Augmentations UI page that display all of your
+ * owned and purchased Augmentations and Source-Files.
+ */
+import * as React from "react";
+
+import { Augmentations } from "../../Augmentation/Augmentations";
+import { Player } from "../../Player";
+
+import { StdButton } from "../../ui/React/StdButton";
+
+type IProps = {
+ exportGameFn: () => void;
+ installAugmentationsFn: () => void;
+}
+
+type IState = {
+
+}
+
+export class AugmentationsRoot extends React.Component {
+ constructor(props: IProps) {
+ super(props);
+ }
+
+ render() {
+ return (
+
+
Purchased Augmentations
+
+ Below is a list of all Augmentations you have purchased but not
+ yet installed. Click the button below to install them.
+
+
+ WARNING: Installing your Augmentations resets most of your progress,
+ including:
+
+
- Stats/Skill levels and Experience
+
- Money
+
- Scripts on every computer but your home computer
+
- Purchased servers
+
- Hacknet Nodes
+
- Faction/Company reputation
+
- Stocks
+
+ 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)
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/src/PersonObjects/IPlayer.ts b/src/PersonObjects/IPlayer.ts
index be95132c8..09146f514 100644
--- a/src/PersonObjects/IPlayer.ts
+++ b/src/PersonObjects/IPlayer.ts
@@ -101,6 +101,10 @@ export interface IPlayer {
work_money_mult: number;
crime_success_mult: number;
crime_money_mult: number;
+ bladeburner_max_stamina_mult: number;
+ bladeburner_stamina_gain_mult: number;
+ bladeburner_analysis_mult: number;
+ bladeburner_success_chance_mult: number;
// Methods
applyForAgentJob(sing?: boolean): boolean | void;
diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.js b/src/PersonObjects/Player/PlayerObjectGeneralMethods.js
index c263175d5..385c836cf 100644
--- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.js
+++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.js
@@ -36,7 +36,8 @@ import {
import { safetlyCreateUniqueServer } from "../../Server/ServerHelpers";
import { Settings } from "../../Settings/Settings";
import { SpecialServerIps, SpecialServerNames } from "../../Server/SpecialServerIps";
-import { SourceFiles, applySourceFile } from "../../SourceFile";
+import { applySourceFile } from "../../SourceFile/applySourceFile";
+import { SourceFiles } from "../../SourceFile/SourceFiles";
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
import Decimal from "decimal.js";
diff --git a/src/RedPill.js b/src/RedPill.js
index 23a56ccfe..c4cebac46 100644
--- a/src/RedPill.js
+++ b/src/RedPill.js
@@ -5,7 +5,7 @@ import { BitNodes } from "./BitNode/BitNode";
import { Engine } from "./engine";
import { Player } from "./Player";
import { prestigeSourceFile } from "./Prestige";
-import { SourceFiles, SourceFile } from "./SourceFile";
+import { SourceFiles } from "./SourceFile/SourceFiles";
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
import { Terminal } from "./Terminal";
import { setTimeoutRef } from "./utils/SetTimeoutRef";
@@ -20,9 +20,6 @@ import {
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
-
-
-
// Returns promise
function writeRedPillLine(line) {
return new Promise(function(resolve, reject) {
diff --git a/src/SourceFile.js b/src/SourceFile.js
deleted file mode 100644
index 7c9219562..000000000
--- a/src/SourceFile.js
+++ /dev/null
@@ -1,256 +0,0 @@
-import { Player } from "./Player";
-import { BitNodes } from "./BitNode/BitNode";
-
-// Each SourceFile corresponds to a BitNode with the same number
-function SourceFile(number, info="") {
- var bitnodeKey = "BitNode" + number;
- var bitnode = BitNodes[bitnodeKey];
- if (bitnode == null) {
- throw new Error("Invalid Bit Node for this Source File");
- }
-
- this.n = number;
- this.name = "Source-File " + number + ": " + bitnode.name;
- this.lvl = 1;
- this.info = info;
- this.owned = false;
-}
-
-let SourceFiles = {};
-function initSourceFiles() {
- SourceFiles = {};
- SourceFiles["SourceFile1"] = new SourceFile(1, "This Source-File lets the player start with 32GB of RAM on his/her " +
- "home computer. It also increases all of the player's multipliers by:
" +
- "Level 1: 16% " +
- "Level 2: 24% " +
- "Level 3: 28%");
- SourceFiles["SourceFile2"] = new SourceFile(2, "This Source-File allows you to form gangs in other BitNodes " +
- "once your karma decreases to a certain value. It also increases the player's " +
- "crime success rate, crime money, and charisma multipliers by:
" +
- "Level 1: 24% " +
- "Level 2: 36% " +
- "Level 3: 42%");
- SourceFiles["SourceFile3"] = new SourceFile(3,"This Source-File lets you create corporations on other BitNodes (although " +
- "some BitNodes will disable this mechanic). This Source-File also increases your charisma and company salary multipliers by: " +
- "Level 1: 8% " +
- "Level 2: 12% " +
- "Level 3: 14%");
- SourceFiles["SourceFile4"] = new SourceFile(4, "This Source-File lets you access and use the Singularity Functions in every BitNode. Every " +
- "level of this Source-File opens up more of the Singularity Functions you can use.");
- SourceFiles["SourceFile5"] = new SourceFile(5, "This Source-File grants a special new stat called Intelligence. Intelligence " +
- "is unique because it is permanent and persistent (it never gets reset back to 1). However, " +
- "gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't " +
- "know when you gain experience and how much). Higher Intelligence levels will boost your production " +
- "for many actions in the game. In addition, this Source-File will unlock the getBitNodeMultipliers() " +
- "Netscript function, and will raise all of your hacking-related multipliers by:
" +
- "Level 1: 8% " +
- "Level 2: 12% " +
- "Level 3: 14%");
- SourceFiles["SourceFile6"] = new SourceFile(6, "This Source-File allows you to access the NSA's Bladeburner Division in other " +
- "BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your combat stats by:
" +
- "Level 1: 8% " +
- "Level 2: 12% " +
- "Level 3: 14%");
- SourceFiles["SourceFile7"] = new SourceFile(7, "This Source-File allows you to access the Bladeburner Netscript API in other " +
- "BitNodes. In addition, this Source-File will increase all of your Bladeburner multipliers by:
" +
- "Level 1: 8% " +
- "Level 2: 12% " +
- "Level 3: 14%");
- SourceFiles["SourceFile8"] = new SourceFile(8, "This Source-File grants the following benefits:
" +
- "Level 1: Permanent access to WSE and TIX API " +
- "Level 2: Ability to short stocks in other BitNodes " +
- "Level 3: Ability to use limit/stop orders in other BitNodes
" +
- "This Source-File also increases your hacking growth multipliers by: " +
- " Level 1: 12% Level 2: 18% Level 3: 21%");
- SourceFiles["SourceFile9"] = new SourceFile(9, "This Source-File grants the following benefits:
" +
- "Level 1: Permanently unlocks the Hacknet Server in other BitNodes " +
- "Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode " +
- "Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode
" +
- "(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT " +
- "when installing Augmentations)");
- SourceFiles["SourceFile10"] = new SourceFile(10, "This Source-File unlocks Sleeve technology in other BitNodes. Each level of this " +
- "Source-File also grants you a Duplicate Sleeve");
- SourceFiles["SourceFile11"] = new SourceFile(11, "This Source-File makes it so that company favor increases BOTH the player's salary and reputation gain rate " +
- "at that company by 1% per favor (rather than just the reputation gain). This Source-File also " +
- " increases the player's company salary and reputation gain multipliers by:
" +
- "Level 1: 32% " +
- "Level 2: 48% " +
- "Level 3: 56% ");
- SourceFiles["SourceFile12"] = new SourceFile(12, "This Source-File increases all your multipliers by 1% per level. 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)");
-}
-
-// Takes in a PlayerOwnedSourceFile as the "srcFile" argument
-function applySourceFile(srcFile) {
- var srcFileKey = "SourceFile" + srcFile.n;
- var sourceFileObject = SourceFiles[srcFileKey];
- if (sourceFileObject == null) {
- console.log("ERROR: Invalid source file number: " + srcFile.n);
- return;
- }
-
- switch(srcFile.n) {
- case 1: // The Source Genesis
- var mult = 0;
- for (var i = 0; i < srcFile.lvl; ++i) {
- mult += (16 / (Math.pow(2, i)));
- }
- var incMult = 1 + (mult / 100);
- var decMult = 1 - (mult / 100);
- Player.hacking_chance_mult *= incMult;
- Player.hacking_speed_mult *= incMult;
- Player.hacking_money_mult *= incMult;
- Player.hacking_grow_mult *= incMult;
- Player.hacking_mult *= incMult;
- Player.strength_mult *= incMult;
- Player.defense_mult *= incMult;
- Player.dexterity_mult *= incMult;
- Player.agility_mult *= incMult;
- Player.charisma_mult *= incMult;
- Player.hacking_exp_mult *= incMult;
- Player.strength_exp_mult *= incMult;
- Player.defense_exp_mult *= incMult;
- Player.dexterity_exp_mult *= incMult;
- Player.agility_exp_mult *= incMult;
- Player.charisma_exp_mult *= incMult;
- Player.company_rep_mult *= incMult;
- Player.faction_rep_mult *= incMult;
- Player.crime_money_mult *= incMult;
- Player.crime_success_mult *= incMult;
- Player.hacknet_node_money_mult *= incMult;
- Player.hacknet_node_purchase_cost_mult *= decMult;
- Player.hacknet_node_ram_cost_mult *= decMult;
- Player.hacknet_node_core_cost_mult *= decMult;
- Player.hacknet_node_level_cost_mult *= decMult;
- Player.work_money_mult *= incMult;
- break;
- case 2: // Rise of the Underworld
- var mult = 0;
- for (var i = 0; i < srcFile.lvl; ++i) {
- mult += (24 / (Math.pow(2, i)));
- }
- var incMult = 1 + (mult / 100);
- Player.crime_money_mult *= incMult;
- Player.crime_success_mult *= incMult;
- Player.charisma_mult *= incMult;
- break;
- case 3: // Corporatocracy
- var mult = 0;
- for (var i = 0; i < srcFile.lvl; ++i) {
- mult += (8 / (Math.pow(2, i)));
- }
- var incMult = 1 + (mult / 100);
- Player.charisma_mult *= incMult;
- Player.work_money_mult *= incMult;
- break;
- case 4: // The Singularity
- // No effects, just gives access to Singularity functions
- break;
- case 5: // Artificial Intelligence
- var mult = 0;
- for (var i = 0; i < srcFile.lvl; ++i) {
- mult += (8 / (Math.pow(2, i)));
- }
- var incMult = 1 + (mult / 100);
- Player.hacking_chance_mult *= incMult;
- Player.hacking_speed_mult *= incMult;
- Player.hacking_money_mult *= incMult;
- Player.hacking_grow_mult *= incMult;
- Player.hacking_mult *= incMult;
- Player.hacking_exp_mult *= incMult;
- break;
- case 6: // Bladeburner
- var mult = 0;
- for (var i = 0; i < srcFile.lvl; ++i) {
- mult += (8 / (Math.pow(2, i)));
- }
- var incMult = 1 + (mult / 100);
- Player.strength_exp_mult *= incMult;
- Player.defense_exp_mult *= incMult;
- Player.dexterity_exp_mult *= incMult;
- Player.agility_exp_mult *= incMult;
- Player.strength_mult *= incMult;
- Player.defense_mult *= incMult;
- Player.dexterity_mult *= incMult;
- Player.agility_mult *= incMult;
- break;
- case 7: // Bladeburner 2079
- var mult = 0;
- for (var i = 0; i < srcFile.lvl; ++i) {
- mult += (8 / (Math.pow(2, i)));
- }
- var incMult = 1 + (mult / 100);
- Player.bladeburner_max_stamina_mult *= incMult;
- Player.bladeburner_stamina_gain_mult *= incMult;
- Player.bladeburner_analysis_mult *= incMult;
- Player.bladeburner_success_chance_mult *= incMult;
- break;
- case 8: // Ghost of Wall Street
- var mult = 0;
- for (var i = 0; i < srcFile.lvl; ++i) {
- mult += (12 / (Math.pow(2, i)));
- }
- var incMult = 1 + (mult / 100);
- Player.hacking_grow_mult *= incMult;
- break;
- case 9: // Hacktocracy
- // This has non-multiplier effects
- break;
- case 10: // Digital Carbon
- // No effects, just grants sleeves
- break;
- case 11: // The Big Crash
- var mult = 0;
- for (var i = 0; i < srcFile.lvl; ++i) {
- mult += (32 / (Math.pow(2, i)));
- }
- var incMult = 1 + (mult / 100);
- Player.work_money_mult *= incMult;
- Player.company_rep_mult *= incMult;
- break;
- case 12: // The Recursion
- var inc = Math.pow(1.01, srcFile.lvl);
- var dec = Math.pow(0.99, srcFile.lvl);
-
- Player.hacking_chance_mult *= inc;
- Player.hacking_speed_mult *= inc;
- Player.hacking_money_mult *= inc;
- Player.hacking_grow_mult *= inc;
- Player.hacking_mult *= inc;
-
- Player.strength_mult *= inc;
- Player.defense_mult *= inc;
- Player.dexterity_mult *= inc;
- Player.agility_mult *= inc;
- Player.charisma_mult *= inc;
-
- Player.hacking_exp_mult *= inc;
- Player.strength_exp_mult *= inc;
- Player.defense_exp_mult *= inc;
- Player.dexterity_exp_mult *= inc;
- Player.agility_exp_mult *= inc;
- Player.charisma_exp_mult *= inc;
-
- Player.company_rep_mult *= inc;
- Player.faction_rep_mult *= inc;
-
- Player.crime_money_mult *= inc;
- Player.crime_success_mult *= inc;
-
- Player.hacknet_node_money_mult *= inc;
- Player.hacknet_node_purchase_cost_mult *= dec;
- Player.hacknet_node_ram_cost_mult *= dec;
- Player.hacknet_node_core_cost_mult *= dec;
- Player.hacknet_node_level_cost_mult *= dec;
-
- Player.work_money_mult *= inc;
- break;
- default:
- console.log("ERROR: Invalid source file number: " + srcFile.n);
- break;
- }
-
- sourceFileObject.owned = true;
-}
-
-export {SourceFiles, applySourceFile, initSourceFiles};
diff --git a/src/SourceFile/SourceFile.ts b/src/SourceFile/SourceFile.ts
new file mode 100644
index 000000000..96290507a
--- /dev/null
+++ b/src/SourceFile/SourceFile.ts
@@ -0,0 +1,21 @@
+import { BitNodes } from "../BitNode/BitNode";
+
+export class SourceFile {
+ info: string;
+ lvl: number = 1;
+ n: number;
+ name: string;
+ owned: boolean = false;
+
+ constructor(number: number, info: string="") {
+ const bitnodeKey = "BitNode" + number;
+ const bitnode = BitNodes[bitnodeKey];
+ if (bitnode == null) {
+ throw new Error("Invalid Bit Node for this Source File");
+ }
+
+ this.n = number;
+ this.name = `Source-File ${number}: ${bitnode.name}`
+ this.info = info;
+ }
+}
diff --git a/src/SourceFile/SourceFiles.ts b/src/SourceFile/SourceFiles.ts
new file mode 100644
index 000000000..bc35dcba8
--- /dev/null
+++ b/src/SourceFile/SourceFiles.ts
@@ -0,0 +1,64 @@
+import { SourceFile } from "./SourceFile";
+import { IMap } from "../types";
+
+export const SourceFiles: IMap = {};
+
+SourceFiles["SourceFile1"] = new SourceFile(1, "This Source-File lets the player start with 32GB of RAM on his/her " +
+ "home computer. It also increases all of the player's multipliers by:
" +
+ "Level 1: 16% " +
+ "Level 2: 24% " +
+ "Level 3: 28%");
+SourceFiles["SourceFile2"] = new SourceFile(2, "This Source-File allows you to form gangs in other BitNodes " +
+ "once your karma decreases to a certain value. It also increases the player's " +
+ "crime success rate, crime money, and charisma multipliers by:
" +
+ "Level 1: 24% " +
+ "Level 2: 36% " +
+ "Level 3: 42%");
+SourceFiles["SourceFile3"] = new SourceFile(3,"This Source-File lets you create corporations on other BitNodes (although " +
+ "some BitNodes will disable this mechanic). This Source-File also increases your charisma and company salary multipliers by: " +
+ "Level 1: 8% " +
+ "Level 2: 12% " +
+ "Level 3: 14%");
+SourceFiles["SourceFile4"] = new SourceFile(4, "This Source-File lets you access and use the Singularity Functions in every BitNode. Every " +
+ "level of this Source-File opens up more of the Singularity Functions you can use.");
+SourceFiles["SourceFile5"] = new SourceFile(5, "This Source-File grants a special new stat called Intelligence. Intelligence " +
+ "is unique because it is permanent and persistent (it never gets reset back to 1). However, " +
+ "gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't " +
+ "know when you gain experience and how much). Higher Intelligence levels will boost your production " +
+ "for many actions in the game. In addition, this Source-File will unlock the getBitNodeMultipliers() " +
+ "Netscript function, and will raise all of your hacking-related multipliers by:
" +
+ "Level 1: 8% " +
+ "Level 2: 12% " +
+ "Level 3: 14%");
+SourceFiles["SourceFile6"] = new SourceFile(6, "This Source-File allows you to access the NSA's Bladeburner Division in other " +
+ "BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your combat stats by:
" +
+ "Level 1: 8% " +
+ "Level 2: 12% " +
+ "Level 3: 14%");
+SourceFiles["SourceFile7"] = new SourceFile(7, "This Source-File allows you to access the Bladeburner Netscript API in other " +
+ "BitNodes. In addition, this Source-File will increase all of your Bladeburner multipliers by:
" +
+ "Level 1: 8% " +
+ "Level 2: 12% " +
+ "Level 3: 14%");
+SourceFiles["SourceFile8"] = new SourceFile(8, "This Source-File grants the following benefits:
" +
+ "Level 1: Permanent access to WSE and TIX API " +
+ "Level 2: Ability to short stocks in other BitNodes " +
+ "Level 3: Ability to use limit/stop orders in other BitNodes
" +
+ "This Source-File also increases your hacking growth multipliers by: " +
+ " Level 1: 12% Level 2: 18% Level 3: 21%");
+SourceFiles["SourceFile9"] = new SourceFile(9, "This Source-File grants the following benefits:
" +
+ "Level 1: Permanently unlocks the Hacknet Server in other BitNodes " +
+ "Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode " +
+ "Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode
" +
+ "(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT " +
+ "when installing Augmentations)");
+SourceFiles["SourceFile10"] = new SourceFile(10, "This Source-File unlocks Sleeve technology in other BitNodes. Each level of this " +
+ "Source-File also grants you a Duplicate Sleeve");
+SourceFiles["SourceFile11"] = new SourceFile(11, "This Source-File makes it so that company favor increases BOTH the player's salary and reputation gain rate " +
+ "at that company by 1% per favor (rather than just the reputation gain). This Source-File also " +
+ " increases the player's company salary and reputation gain multipliers by:
" +
+ "Level 1: 32% " +
+ "Level 2: 48% " +
+ "Level 3: 56% ");
+SourceFiles["SourceFile12"] = new SourceFile(12, "This Source-File increases all your multipliers by 1% per level. 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)");
diff --git a/src/SourceFile/applySourceFile.ts b/src/SourceFile/applySourceFile.ts
new file mode 100644
index 000000000..e38b014ec
--- /dev/null
+++ b/src/SourceFile/applySourceFile.ts
@@ -0,0 +1,176 @@
+import { PlayerOwnedSourceFile } from "./PlayerOwnedSourceFile";
+import { SourceFiles } from "./SourceFiles";
+
+import { Player } from "../Player";
+
+export function applySourceFile(srcFile: PlayerOwnedSourceFile) {
+ const srcFileKey = "SourceFile" + srcFile.n;
+ const sourceFileObject = SourceFiles[srcFileKey];
+ if (sourceFileObject == null) {
+ console.error(`Invalid source file number: ${srcFile.n}`);
+ return;
+ }
+
+ switch (srcFile.n) {
+ case 1: // The Source Genesis
+ var mult = 0;
+ for (var i = 0; i < srcFile.lvl; ++i) {
+ mult += (16 / (Math.pow(2, i)));
+ }
+ var incMult = 1 + (mult / 100);
+ var decMult = 1 - (mult / 100);
+ Player.hacking_chance_mult *= incMult;
+ Player.hacking_speed_mult *= incMult;
+ Player.hacking_money_mult *= incMult;
+ Player.hacking_grow_mult *= incMult;
+ Player.hacking_mult *= incMult;
+ Player.strength_mult *= incMult;
+ Player.defense_mult *= incMult;
+ Player.dexterity_mult *= incMult;
+ Player.agility_mult *= incMult;
+ Player.charisma_mult *= incMult;
+ Player.hacking_exp_mult *= incMult;
+ Player.strength_exp_mult *= incMult;
+ Player.defense_exp_mult *= incMult;
+ Player.dexterity_exp_mult *= incMult;
+ Player.agility_exp_mult *= incMult;
+ Player.charisma_exp_mult *= incMult;
+ Player.company_rep_mult *= incMult;
+ Player.faction_rep_mult *= incMult;
+ Player.crime_money_mult *= incMult;
+ Player.crime_success_mult *= incMult;
+ Player.hacknet_node_money_mult *= incMult;
+ Player.hacknet_node_purchase_cost_mult *= decMult;
+ Player.hacknet_node_ram_cost_mult *= decMult;
+ Player.hacknet_node_core_cost_mult *= decMult;
+ Player.hacknet_node_level_cost_mult *= decMult;
+ Player.work_money_mult *= incMult;
+ break;
+ case 2: // Rise of the Underworld
+ var mult = 0;
+ for (var i = 0; i < srcFile.lvl; ++i) {
+ mult += (24 / (Math.pow(2, i)));
+ }
+ var incMult = 1 + (mult / 100);
+ Player.crime_money_mult *= incMult;
+ Player.crime_success_mult *= incMult;
+ Player.charisma_mult *= incMult;
+ break;
+ case 3: // Corporatocracy
+ var mult = 0;
+ for (var i = 0; i < srcFile.lvl; ++i) {
+ mult += (8 / (Math.pow(2, i)));
+ }
+ var incMult = 1 + (mult / 100);
+ Player.charisma_mult *= incMult;
+ Player.work_money_mult *= incMult;
+ break;
+ case 4: // The Singularity
+ // No effects, just gives access to Singularity functions
+ break;
+ case 5: // Artificial Intelligence
+ var mult = 0;
+ for (var i = 0; i < srcFile.lvl; ++i) {
+ mult += (8 / (Math.pow(2, i)));
+ }
+ var incMult = 1 + (mult / 100);
+ Player.hacking_chance_mult *= incMult;
+ Player.hacking_speed_mult *= incMult;
+ Player.hacking_money_mult *= incMult;
+ Player.hacking_grow_mult *= incMult;
+ Player.hacking_mult *= incMult;
+ Player.hacking_exp_mult *= incMult;
+ break;
+ case 6: // Bladeburner
+ var mult = 0;
+ for (var i = 0; i < srcFile.lvl; ++i) {
+ mult += (8 / (Math.pow(2, i)));
+ }
+ var incMult = 1 + (mult / 100);
+ Player.strength_exp_mult *= incMult;
+ Player.defense_exp_mult *= incMult;
+ Player.dexterity_exp_mult *= incMult;
+ Player.agility_exp_mult *= incMult;
+ Player.strength_mult *= incMult;
+ Player.defense_mult *= incMult;
+ Player.dexterity_mult *= incMult;
+ Player.agility_mult *= incMult;
+ break;
+ case 7: // Bladeburner 2079
+ var mult = 0;
+ for (var i = 0; i < srcFile.lvl; ++i) {
+ mult += (8 / (Math.pow(2, i)));
+ }
+ var incMult = 1 + (mult / 100);
+ Player.bladeburner_max_stamina_mult *= incMult;
+ Player.bladeburner_stamina_gain_mult *= incMult;
+ Player.bladeburner_analysis_mult *= incMult;
+ Player.bladeburner_success_chance_mult *= incMult;
+ break;
+ case 8: // Ghost of Wall Street
+ var mult = 0;
+ for (var i = 0; i < srcFile.lvl; ++i) {
+ mult += (12 / (Math.pow(2, i)));
+ }
+ var incMult = 1 + (mult / 100);
+ Player.hacking_grow_mult *= incMult;
+ break;
+ case 9: // Hacktocracy
+ // This has non-multiplier effects
+ break;
+ case 10: // Digital Carbon
+ // No effects, just grants sleeves
+ break;
+ case 11: // The Big Crash
+ var mult = 0;
+ for (var i = 0; i < srcFile.lvl; ++i) {
+ mult += (32 / (Math.pow(2, i)));
+ }
+ var incMult = 1 + (mult / 100);
+ Player.work_money_mult *= incMult;
+ Player.company_rep_mult *= incMult;
+ break;
+ case 12: // The Recursion
+ var inc = Math.pow(1.01, srcFile.lvl);
+ var dec = Math.pow(0.99, srcFile.lvl);
+
+ Player.hacking_chance_mult *= inc;
+ Player.hacking_speed_mult *= inc;
+ Player.hacking_money_mult *= inc;
+ Player.hacking_grow_mult *= inc;
+ Player.hacking_mult *= inc;
+
+ Player.strength_mult *= inc;
+ Player.defense_mult *= inc;
+ Player.dexterity_mult *= inc;
+ Player.agility_mult *= inc;
+ Player.charisma_mult *= inc;
+
+ Player.hacking_exp_mult *= inc;
+ Player.strength_exp_mult *= inc;
+ Player.defense_exp_mult *= inc;
+ Player.dexterity_exp_mult *= inc;
+ Player.agility_exp_mult *= inc;
+ Player.charisma_exp_mult *= inc;
+
+ Player.company_rep_mult *= inc;
+ Player.faction_rep_mult *= inc;
+
+ Player.crime_money_mult *= inc;
+ Player.crime_success_mult *= inc;
+
+ Player.hacknet_node_money_mult *= inc;
+ Player.hacknet_node_purchase_cost_mult *= dec;
+ Player.hacknet_node_ram_cost_mult *= dec;
+ Player.hacknet_node_core_cost_mult *= dec;
+ Player.hacknet_node_level_cost_mult *= dec;
+
+ Player.work_money_mult *= inc;
+ break;
+ default:
+ console.log("ERROR: Invalid source file number: " + srcFile.n);
+ break;
+ }
+
+ sourceFileObject.owned = true;
+}
diff --git a/src/engine.jsx b/src/engine.jsx
index e86bbcdfb..488c21eb6 100644
--- a/src/engine.jsx
+++ b/src/engine.jsx
@@ -13,7 +13,6 @@ import {
PlayerOwnedAugmentation
} from "./Augmentation/AugmentationHelpers";
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
-
import {
BitNodes,
initBitNodes,
@@ -54,14 +53,14 @@ import {
updateOnlineScriptTimes,
} from "./NetscriptWorker";
import { Player } from "./Player";
-import { prestigeAugmentation, prestigeSourceFile } from "./Prestige";
+import { prestigeAugmentation } from "./Prestige";
import { Programs } from "./Programs/Programs";
import {
displayCreateProgramContent,
getNumAvailableCreateProgram,
initCreateProgramButtons
} from "./Programs/ProgramHelpers";
-import { redPillFlag, hackWorldDaemon } from "./RedPill";
+import { redPillFlag } from "./RedPill";
import { saveObject, loadGame } from "./SaveObject";
import {
getCurrentEditor,
@@ -69,10 +68,7 @@ import {
updateScriptEditorContent
} from "./Script/ScriptHelpers";
import { AllServers, initForeignServers } from "./Server/AllServers";
-
-import { Server } from "./Server/Server";
import { Settings } from "./Settings/Settings";
-import { initSourceFiles, SourceFiles } from "./SourceFile";
import { updateSourceFileFlags } from "./SourceFile/SourceFileFlags";
import {
SpecialServerIps,
@@ -87,7 +83,6 @@ import {
displayStockMarketContent
} from "./StockMarket/StockMarket";
import { Terminal, postNetburnerText } from "./Terminal";
-
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
import {
clearSleevesPage,
@@ -1045,7 +1040,6 @@ const Engine = {
if (loadGame(saveString)) {
initBitNodes();
initBitNodeMultipliers(Player);
- initSourceFiles();
Engine.setDisplayElements(); // Sets variables for important DOM elements
Engine.init(); // Initialize buttons, work, etc.
initAugmentations(); // Also calls Player.reapplyAllAugmentations()
@@ -1168,7 +1162,6 @@ const Engine = {
console.log("Initializing new game");
initBitNodes();
initBitNodeMultipliers(Player);
- initSourceFiles();
initSpecialServerIps();
Engine.setDisplayElements(); // Sets variables for important DOM elements
Engine.start(); // Run main game loop and Scripts loop
diff --git a/src/engineStyle.js b/src/engineStyle.js
index df9dd7250..c297b37cc 100644
--- a/src/engineStyle.js
+++ b/src/engineStyle.js
@@ -11,6 +11,7 @@ import "../css/scripteditor.scss";
import "../css/codemirror-overrides.scss";
import "../css/hacknetnodes.scss";
import "../css/menupages.scss";
+import "../css/augmentations.scss";
import "../css/redpill.scss";
import "../css/stockmarket.scss";
import "../css/workinprogress.scss";
diff --git a/src/ui/React/AugmentationAccordion.tsx b/src/ui/React/AugmentationAccordion.tsx
new file mode 100644
index 000000000..430a9800c
--- /dev/null
+++ b/src/ui/React/AugmentationAccordion.tsx
@@ -0,0 +1,33 @@
+/**
+ * React Component for displaying a single Augmentation as an accordion.
+ *
+ * The header of the accordion contains the Augmentation's name (and level, if
+ * applicable), and the accordion's panel contains the Augmentation's level.
+ */
+import * as React from "react";
+
+import { Accordion } from "./Accordion";
+
+import { Augmentation } from "../../Augmentation/Augmentation";
+import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
+
+type IProps = {
+ aug: Augmentation,
+ level?: number | string | null,
+}
+
+export function AugmentationAccordion(props: IProps): React.ReactElement {
+ let displayName = props.aug.name;
+ if (props.level != null) {
+ if (props.aug.name === AugmentationNames.NeuroFluxGovernor) {
+ displayName += (` - Level ${props.level}`)
+ }
+ }
+
+ return (
+ {displayName}}
+ panelContent={