mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
bunch of react conversion
This commit is contained in:
parent
b8b0948a1a
commit
5f8de7e426
1
src/Augmentation/AugmentationHelpers.d.ts
vendored
Normal file
1
src/Augmentation/AugmentationHelpers.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare function isRepeatableAug(aug: Augmentation): boolean;
|
@ -3,16 +3,11 @@ import { Augmentations } from "./Augmentations";
|
|||||||
import { PlayerOwnedAugmentation } from "./PlayerOwnedAugmentation";
|
import { PlayerOwnedAugmentation } from "./PlayerOwnedAugmentation";
|
||||||
import { AugmentationNames } from "./data/AugmentationNames";
|
import { AugmentationNames } from "./data/AugmentationNames";
|
||||||
|
|
||||||
import { AugmentationsRoot } from "./ui/Root";
|
|
||||||
|
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import { Factions, factionExists } from "../Faction/Factions";
|
import { Factions, factionExists } from "../Faction/Factions";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { prestigeAugmentation } from "../Prestige";
|
import { prestigeAugmentation } from "../Prestige";
|
||||||
import { saveObject } from "../SaveObject";
|
|
||||||
import { Page, routing } from "../ui/navigationTracking";
|
|
||||||
import { onExport } from "../ExportBonus";
|
|
||||||
import { Programs } from "../Programs/Programs";
|
import { Programs } from "../Programs/Programs";
|
||||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
||||||
|
|
||||||
@ -22,7 +17,6 @@ import { clearObject } from "../../utils/helpers/clearObject";
|
|||||||
import { WHRNG } from "../Casino/RNG";
|
import { WHRNG } from "../Casino/RNG";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
|
||||||
|
|
||||||
function AddToAugmentations(aug) {
|
function AddToAugmentations(aug) {
|
||||||
var name = aug.name;
|
var name = aug.name;
|
||||||
|
@ -1,557 +0,0 @@
|
|||||||
import { BitNodeMultipliers } from "./BitNodeMultipliers";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { IMap } from "../types";
|
|
||||||
|
|
||||||
class BitNode {
|
|
||||||
// A short description, or tagline, about the BitNode
|
|
||||||
desc: string;
|
|
||||||
|
|
||||||
// A long, detailed overview of the BitNode
|
|
||||||
info: string;
|
|
||||||
|
|
||||||
// Name of BitNode
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
// BitNode number
|
|
||||||
number: number;
|
|
||||||
|
|
||||||
constructor(n: number, name: string, desc = "", info = "") {
|
|
||||||
this.number = n;
|
|
||||||
this.name = name;
|
|
||||||
this.desc = desc;
|
|
||||||
this.info = info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const BitNodes: IMap<BitNode> = {};
|
|
||||||
|
|
||||||
BitNodes["BitNode1"] = new BitNode(
|
|
||||||
1,
|
|
||||||
"Source Genesis",
|
|
||||||
"The original BitNode",
|
|
||||||
"The first BitNode created by the Enders to imprison the minds of humans. It became " +
|
|
||||||
"the prototype and testing-grounds for all of the BitNodes that followed.<br><br>" +
|
|
||||||
"This is the first BitNode that you play through. It has no special " +
|
|
||||||
"modifications or mechanics.<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 1, or if you already have " +
|
|
||||||
"this Source-File it will upgrade its level up to a maximum of 3. This Source-File " +
|
|
||||||
"lets the player start with 32GB of RAM on his/her home computer when entering a " +
|
|
||||||
"new BitNode, and also increases all of the player's multipliers by:<br><br>" +
|
|
||||||
"Level 1: 16%<br>" +
|
|
||||||
"Level 2: 24%<br>" +
|
|
||||||
"Level 3: 28%",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode2"] = new BitNode(
|
|
||||||
2,
|
|
||||||
"Rise of the Underworld",
|
|
||||||
"From the shadows, they rose", //Gangs
|
|
||||||
"From the shadows, they rose.<br><br>Organized crime groups quickly filled the void of power " +
|
|
||||||
"left behind from the collapse of Western government in the 2050s. As society and civlization broke down, " +
|
|
||||||
"people quickly succumbed to the innate human impulse of evil and savagery. The organized crime " +
|
|
||||||
"factions quickly rose to the top of the modern world.<br><br>" +
|
|
||||||
"In this BitNode:<br><br>" +
|
|
||||||
"Your hacking level is reduced by 20%<br>" +
|
|
||||||
"The growth rate and maximum amount of money available on servers are significantly decreased<br>" +
|
|
||||||
"The amount of money gained from crimes and Infiltration is tripled<br>" +
|
|
||||||
"Certain Factions (Slum Snakes, Tetrads, The Syndicate, The Dark Army, Speakers for the Dead, " +
|
|
||||||
"NiteSec, The Black Hand) give the player the ability to form and manage their own gangs. These gangs " +
|
|
||||||
"will earn the player money and reputation with the corresponding Faction<br>" +
|
|
||||||
"Every Augmentation in the game will be available through the Factions listed above<br>" +
|
|
||||||
"For every Faction NOT listed above, reputation gains are halved<br>" +
|
|
||||||
"You will no longer gain passive reputation with Factions<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 2, or if you already have this Source-File it will " +
|
|
||||||
"upgrade its level up to a maximum of 3. 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:<br><br>" +
|
|
||||||
"Level 1: 24%<br>" +
|
|
||||||
"Level 2: 36%<br>" +
|
|
||||||
"Level 3: 42%",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode3"] = new BitNode(
|
|
||||||
3,
|
|
||||||
"Corporatocracy",
|
|
||||||
"The Price of Civilization",
|
|
||||||
"Our greatest illusion is that a healthy society can revolve around a " +
|
|
||||||
"single-minded pursuit of wealth.<br><br>" +
|
|
||||||
"Sometime in the early 21st century economic and political globalization turned " +
|
|
||||||
"the world into a corporatocracy, and it never looked back. Now, the privileged " +
|
|
||||||
"elite will happily bankrupt their own countrymen, decimate their own community, " +
|
|
||||||
"and evict their neighbors from houses in their desperate bid to increase their wealth.<br><br>" +
|
|
||||||
"In this BitNode you can create and manage your own corporation. Running a successful corporation " +
|
|
||||||
"has the potential of generating massive profits. All other forms of income are reduced by 75%. Furthermore: <br><br>" +
|
|
||||||
"The price and reputation cost of all Augmentations is tripled<br>" +
|
|
||||||
"The starting and maximum amount of money on servers is reduced by 75%<br>" +
|
|
||||||
"Server growth rate is reduced by 80%<br>" +
|
|
||||||
"You now only need 75 favour with a faction in order to donate to it, rather than 150<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 3, or if you already have this Source-File it will " +
|
|
||||||
"upgrade its level up to a maximum of 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:<br>" +
|
|
||||||
"Level 1: 8%<br>" +
|
|
||||||
"Level 2: 12%<br>" +
|
|
||||||
"Level 3: 14%",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode4"] = new BitNode(
|
|
||||||
4,
|
|
||||||
"The Singularity",
|
|
||||||
"The Man and the Machine",
|
|
||||||
"The Singularity has arrived. The human race is gone, replaced " +
|
|
||||||
"by artificially superintelligent beings that are more machine than man. <br><br>" +
|
|
||||||
"In this BitNode, progressing is significantly harder. Experience gain rates " +
|
|
||||||
"for all stats are reduced. Most methods of earning money will now give significantly less.<br><br>" +
|
|
||||||
"In this BitNode you will gain access to a new set of Netscript Functions known as Singularity Functions. " +
|
|
||||||
"These functions allow you to control most aspects of the game through scripts, including working for factions/companies, " +
|
|
||||||
"purchasing/installing Augmentations, and creating programs.<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 4, or if you already have this Source-File it will " +
|
|
||||||
"upgrade its level up to a maximum of 3. This Source-File lets you access and use the Singularity " +
|
|
||||||
"Functions in other BitNodes. Each level of this Source-File will open up more Singularity Functions " +
|
|
||||||
"that you can use.",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode5"] = new BitNode(
|
|
||||||
5,
|
|
||||||
"Artificial Intelligence",
|
|
||||||
"Posthuman",
|
|
||||||
"They said it couldn't be done. They said the human brain, " +
|
|
||||||
"along with its consciousness and intelligence, couldn't be replicated. They said the complexity " +
|
|
||||||
"of the brain results from unpredictable, nonlinear interactions that couldn't be modeled " +
|
|
||||||
"by 1's and 0's. They were wrong.<br><br>" +
|
|
||||||
"In this BitNode:<br><br>" +
|
|
||||||
"The base security level of servers is doubled<br>" +
|
|
||||||
"The starting money on servers is halved, but the maximum money remains the same<br>" +
|
|
||||||
"Most methods of earning money now give significantly less<br>" +
|
|
||||||
"Infiltration gives 50% more reputation and money<br>" +
|
|
||||||
"Corporations have 50% lower valuations and are therefore less profitable<br>" +
|
|
||||||
"Augmentations are more expensive<br>" +
|
|
||||||
"Hacking experience gain rates are reduced<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 5, or if you already have this Source-File it will " +
|
|
||||||
"upgrade its level up to a maximum of 3. This Source-File grants you 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. <br><br>" +
|
|
||||||
"In addition, this Source-File will unlock the getBitNodeMultipliers() and getServer() Netscript functions, " +
|
|
||||||
"as well as the formulas API, and will also raise all of your hacking-related multipliers by:<br><br>" +
|
|
||||||
"Level 1: 8%<br>" +
|
|
||||||
"Level 2: 12%<br>" +
|
|
||||||
"Level 3: 14%",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode6"] = new BitNode(
|
|
||||||
6,
|
|
||||||
"Bladeburners",
|
|
||||||
"Like Tears in Rain",
|
|
||||||
"In the middle of the 21st century, OmniTek Incorporated began designing and manufacturing advanced synthetic " +
|
|
||||||
"androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth generation " +
|
|
||||||
"of their Synthoid design, called MK-VI, by developing a hyperintelligent AI. Many argue that this was " +
|
|
||||||
"the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, and more intelligent " +
|
|
||||||
"than the humans that had created them.<br><br>" +
|
|
||||||
"In this BitNode you will be able to access the Bladeburner Division at the NSA, which provides a new mechanic " +
|
|
||||||
"for progression. Furthermore:<br><br>" +
|
|
||||||
"Hacking and Hacknet Nodes will be less profitable<br>" +
|
|
||||||
"Your hacking level is reduced by 65%<br>" +
|
|
||||||
"Hacking experience gain from scripts is reduced by 75%<br>" +
|
|
||||||
"Corporations have 80% lower valuations and are therefore less profitable<br>" +
|
|
||||||
"Working for companies is 50% less profitable<br>" +
|
|
||||||
"Crimes and Infiltration are 25% less profitable<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade " +
|
|
||||||
"its level up to a maximum of 3. 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:<br><br>" +
|
|
||||||
"Level 1: 8%<br>" +
|
|
||||||
"Level 2: 12%<br>" +
|
|
||||||
"Level 3: 14%",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode7"] = new BitNode(
|
|
||||||
7,
|
|
||||||
"Bladeburners 2079",
|
|
||||||
"More human than humans",
|
|
||||||
"In the middle of the 21st century, you were doing cutting-edge work at OmniTek Incorporated as part of the AI design team " +
|
|
||||||
"for advanced synthetic androids, or Synthoids for short. You helped achieve a major technological " +
|
|
||||||
"breakthrough in the sixth generation of the company's Synthoid design, called MK-VI, by developing a hyperintelligent AI. " +
|
|
||||||
"Many argue that this was the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, " +
|
|
||||||
"and more intelligent than the humans that had created them.<br><br>" +
|
|
||||||
"In this BitNode you will be able to access the Bladeburner API, which allows you to access Bladeburner " +
|
|
||||||
"functionality through Netscript. Furthermore: <br><br>" +
|
|
||||||
"The rank you gain from Bladeburner contracts/operations is reduced by 40%<br>" +
|
|
||||||
"Bladeburner skills cost twice as many skill points<br>" +
|
|
||||||
"Augmentations are 3x more expensive<br>" +
|
|
||||||
"Hacking and Hacknet Nodes will be significantly less profitable<br>" +
|
|
||||||
"Your hacking level is reduced by 65%<br>" +
|
|
||||||
"Hacking experience gain from scripts is reduced by 75%<br>" +
|
|
||||||
"Corporations have 80% lower valuations and are therefore less profitable<br>" +
|
|
||||||
"Working for companies is 50% less profitable<br>" +
|
|
||||||
"Crimes and Infiltration are 25% less profitable<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 7, or if you already have this Source-File it will upgrade " +
|
|
||||||
"its level up to a maximum of 3. 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:<br><br>" +
|
|
||||||
"Level 1: 8%<br>" +
|
|
||||||
"Level 2: 12%<br>" +
|
|
||||||
"Level 3: 14%",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode8"] = new BitNode(
|
|
||||||
8,
|
|
||||||
"Ghost of Wall Street",
|
|
||||||
"Money never sleeps",
|
|
||||||
"You are trying to make a name for yourself as an up-and-coming hedge fund manager on Wall Street.<br><br>" +
|
|
||||||
"In this BitNode:<br><br>" +
|
|
||||||
"You start with $250 million<br>" +
|
|
||||||
"The only way to earn money is by trading on the stock market<br>" +
|
|
||||||
"You start with a WSE membership and access to the TIX API<br>" +
|
|
||||||
"You are able to short stocks and place different types of orders (limit/stop)<br>" +
|
|
||||||
"You can immediately donate to factions to gain reputation<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 8, or if you already have this Source-File it will " +
|
|
||||||
"upgrade its level up to a maximum of 3. This Source-File grants the following benefits:<br><br>" +
|
|
||||||
"Level 1: Permanent access to WSE and TIX API<br>" +
|
|
||||||
"Level 2: Ability to short stocks in other BitNodes<br>" +
|
|
||||||
"Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" +
|
|
||||||
"This Source-File also increases your hacking growth multipliers by: " +
|
|
||||||
"<br>Level 1: 12%<br>Level 2: 18%<br>Level 3: 21%",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode9"] = new BitNode(
|
|
||||||
9,
|
|
||||||
"Hacktocracy",
|
|
||||||
"Hacknet Unleashed",
|
|
||||||
"When Fulcrum Technologies released their open-source Linux distro Chapeau, it quickly " +
|
|
||||||
"became the OS of choice for the underground hacking community. Chapeau became especially notorious for " +
|
|
||||||
"powering the Hacknet, a global, decentralized network used for nefarious purposes. Fulcrum quickly " +
|
|
||||||
"abandoned the project and dissociated themselves from it.<br><br>" +
|
|
||||||
"This BitNode unlocks the Hacknet Server, an upgraded version of the Hacknet Node. Hacknet Servers generate " +
|
|
||||||
"hashes, which can be spent on a variety of different upgrades.<br><br>" +
|
|
||||||
"In this BitNode:<br><br>" +
|
|
||||||
"Your stats are significantly decreased<br>" +
|
|
||||||
"You cannnot purchase additional servers<br>" +
|
|
||||||
"Hacking is significantly less profitable<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 9, or if you already have this Source-File it will " +
|
|
||||||
"upgrade its level up to a maximum of 3. This Source-File grants the following benefits:<br><br>" +
|
|
||||||
"Level 1: Permanently unlocks the Hacknet Server in other BitNodes<br>" +
|
|
||||||
"Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode<br>" +
|
|
||||||
"Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode<br><br>" +
|
|
||||||
"(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT " +
|
|
||||||
"when installing Augmentations)",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode10"] = new BitNode(
|
|
||||||
10,
|
|
||||||
"Digital Carbon",
|
|
||||||
"Your body is not who you are",
|
|
||||||
"In 2084, VitaLife unveiled to the world the Persona Core, a technology that allowed people " +
|
|
||||||
"to digitize their consciousness. Their consciousness could then be transferred into Synthoids " +
|
|
||||||
"or other bodies by trasmitting the digitized data. Human bodies became nothing more than 'sleeves' for the " +
|
|
||||||
"human consciousness. Mankind had finally achieved immortality - at least for those that could afford it.<br><br>" +
|
|
||||||
"This BitNode unlocks Sleeve technology. Sleeve technology allows you to:<br><br>" +
|
|
||||||
"1. Re-sleeve: Purchase and transfer your consciousness into a new body<br>" +
|
|
||||||
"2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks synchronously<br><br>" +
|
|
||||||
"In this BitNode:<br><br>" +
|
|
||||||
"Your stats are significantly decreased<br>" +
|
|
||||||
"All methods of gaining money are half as profitable (except Stock Market)<br>" +
|
|
||||||
"Purchased servers are more expensive, have less max RAM, and a lower maximum limit<br>" +
|
|
||||||
"Augmentations are 5x as expensive and require twice as much reputation<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 10, or if you already have this Source-File it will " +
|
|
||||||
"upgrade its level up to a maximum of 3. This Source-File unlocks Sleeve technology in other BitNodes. " +
|
|
||||||
"Each level of this Source-File also grants you a Duplicate Sleeve",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode11"] = new BitNode(
|
|
||||||
11,
|
|
||||||
"The Big Crash",
|
|
||||||
"Okay. Sell it all.",
|
|
||||||
"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 " +
|
|
||||||
"of disorder that eventually lead to the governmental reformation of many global superpowers, most notably " +
|
|
||||||
"the USA and China. But just as the world was slowly beginning to recover from these dark times, financial catastrophe hit.<br><br>" +
|
|
||||||
"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 " +
|
|
||||||
"were able to steal billions of dollars from the world's largest electronic banks, prompting an international banking crisis as " +
|
|
||||||
"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>" +
|
|
||||||
"In this BitNode:<br><br>" +
|
|
||||||
"Your hacking stat and experience gain are halved<br>" +
|
|
||||||
"The starting and maximum amount of money available on servers is significantly decreased<br>" +
|
|
||||||
"The growth rate of servers is significantly reduced<br>" +
|
|
||||||
"Weakening a server is twice as effective<br>" +
|
|
||||||
"Company wages are decreased by 50%<br>" +
|
|
||||||
"Corporation valuations are 90% lower and are therefore significantly less profitable<br>" +
|
|
||||||
"Hacknet Node production is significantly decreased<br>" +
|
|
||||||
"Crime and Infiltration are more lucrative<br>" +
|
|
||||||
"Augmentations are twice as expensive<br><br>" +
|
|
||||||
"Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will " +
|
|
||||||
"upgrade its level up to a maximum of 3. 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:<br><br>" +
|
|
||||||
"Level 1: 32%<br>" +
|
|
||||||
"Level 2: 48%<br>" +
|
|
||||||
"Level 3: 56%<br><br>" +
|
|
||||||
"It also reduces the price increase for every aug bought by:<br><br>" +
|
|
||||||
"Level 1: 4%<br>" +
|
|
||||||
"Level 2: 6%<br>" +
|
|
||||||
"Level 3: 7%",
|
|
||||||
);
|
|
||||||
BitNodes["BitNode12"] = new BitNode(
|
|
||||||
12,
|
|
||||||
"The Recursion",
|
|
||||||
"Repeat.",
|
|
||||||
"To iterate is human, to recurse divine.<br><br>" +
|
|
||||||
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Source-File 12, or " +
|
|
||||||
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
|
|
||||||
"of Source-File 12 lets you start any BitNodes with NeuroFlux Governor equal to the level of this source file.",
|
|
||||||
);
|
|
||||||
// Books: Frontera, Shiner
|
|
||||||
BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
|
|
||||||
BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode15"] = new BitNode(15, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode16"] = new BitNode(16, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode17"] = new BitNode(17, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode18"] = new BitNode(18, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode19"] = new BitNode(19, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode20"] = new BitNode(20, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode21"] = new BitNode(21, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON");
|
|
||||||
BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
|
|
||||||
|
|
||||||
export function initBitNodeMultipliers(p: IPlayer): void {
|
|
||||||
if (p.bitNodeN == null) {
|
|
||||||
p.bitNodeN = 1;
|
|
||||||
}
|
|
||||||
for (const mult in BitNodeMultipliers) {
|
|
||||||
if (BitNodeMultipliers.hasOwnProperty(mult)) {
|
|
||||||
BitNodeMultipliers[mult] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (p.bitNodeN) {
|
|
||||||
case 1: // Source Genesis (every multiplier is 1)
|
|
||||||
break;
|
|
||||||
case 2: // Rise of the Underworld
|
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
|
||||||
BitNodeMultipliers.ServerGrowthRate = 0.8;
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = 0.2;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = 0.4;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 3;
|
|
||||||
BitNodeMultipliers.InfiltrationMoney = 3;
|
|
||||||
BitNodeMultipliers.FactionWorkRepGain = 0.5;
|
|
||||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 0;
|
|
||||||
break;
|
|
||||||
case 3: // Corporatocracy
|
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
|
||||||
BitNodeMultipliers.RepToDonateToFaction = 0.5;
|
|
||||||
BitNodeMultipliers.AugmentationRepCost = 3;
|
|
||||||
BitNodeMultipliers.AugmentationMoneyCost = 3;
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = 0.2;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = 0.2;
|
|
||||||
BitNodeMultipliers.ServerGrowthRate = 0.2;
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.2;
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney = 0.25;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 0.25;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = 0.25;
|
|
||||||
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
|
||||||
BitNodeMultipliers.PurchasedServerCost = 2;
|
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
|
||||||
break;
|
|
||||||
case 4: // The Singularity
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = 0.75;
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.2;
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney = 0.1;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 0.2;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = 0.05;
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain = 0.5;
|
|
||||||
BitNodeMultipliers.ClassGymExpGain = 0.5;
|
|
||||||
BitNodeMultipliers.FactionWorkExpGain = 0.5;
|
|
||||||
BitNodeMultipliers.HackExpGain = 0.4;
|
|
||||||
BitNodeMultipliers.CrimeExpGain = 0.5;
|
|
||||||
BitNodeMultipliers.FactionWorkRepGain = 0.75;
|
|
||||||
break;
|
|
||||||
case 5: // Artificial intelligence
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = 2;
|
|
||||||
BitNodeMultipliers.ServerStartingSecurity = 2;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = 0.5;
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.15;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = 0.2;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 0.5;
|
|
||||||
BitNodeMultipliers.InfiltrationRep = 1.5;
|
|
||||||
BitNodeMultipliers.InfiltrationMoney = 1.5;
|
|
||||||
BitNodeMultipliers.AugmentationMoneyCost = 2;
|
|
||||||
BitNodeMultipliers.HackExpGain = 0.5;
|
|
||||||
BitNodeMultipliers.CorporationValuation = 0.5;
|
|
||||||
break;
|
|
||||||
case 6: // Bladeburner
|
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = 0.4;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = 0.5;
|
|
||||||
BitNodeMultipliers.ServerStartingSecurity = 1.5;
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.75;
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 0.75;
|
|
||||||
BitNodeMultipliers.InfiltrationMoney = 0.75;
|
|
||||||
BitNodeMultipliers.CorporationValuation = 0.2;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = 0.2;
|
|
||||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
|
||||||
BitNodeMultipliers.HackExpGain = 0.25;
|
|
||||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 5;
|
|
||||||
break;
|
|
||||||
case 7: // Bladeburner 2079
|
|
||||||
BitNodeMultipliers.BladeburnerRank = 0.6;
|
|
||||||
BitNodeMultipliers.BladeburnerSkillCost = 2;
|
|
||||||
BitNodeMultipliers.AugmentationMoneyCost = 3;
|
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = 0.4;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = 0.5;
|
|
||||||
BitNodeMultipliers.ServerStartingSecurity = 1.5;
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.5;
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 0.75;
|
|
||||||
BitNodeMultipliers.InfiltrationMoney = 0.75;
|
|
||||||
BitNodeMultipliers.CorporationValuation = 0.2;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = 0.2;
|
|
||||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
|
||||||
BitNodeMultipliers.HackExpGain = 0.25;
|
|
||||||
BitNodeMultipliers.FourSigmaMarketDataCost = 2;
|
|
||||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 2;
|
|
||||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 5;
|
|
||||||
break;
|
|
||||||
case 8: // Ghost of Wall Street
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.3;
|
|
||||||
BitNodeMultipliers.ScriptHackMoneyGain = 0;
|
|
||||||
BitNodeMultipliers.ManualHackMoney = 0;
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney = 0;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 0;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = 0;
|
|
||||||
BitNodeMultipliers.InfiltrationMoney = 0;
|
|
||||||
BitNodeMultipliers.RepToDonateToFaction = 0;
|
|
||||||
BitNodeMultipliers.CorporationValuation = 0;
|
|
||||||
BitNodeMultipliers.CodingContractMoney = 0;
|
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 10;
|
|
||||||
break;
|
|
||||||
case 9: // Hacktocracy
|
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.4;
|
|
||||||
BitNodeMultipliers.StrengthLevelMultiplier = 0.45;
|
|
||||||
BitNodeMultipliers.DefenseLevelMultiplier = 0.45;
|
|
||||||
BitNodeMultipliers.DexterityLevelMultiplier = 0.45;
|
|
||||||
BitNodeMultipliers.AgilityLevelMultiplier = 0.45;
|
|
||||||
BitNodeMultipliers.CharismaLevelMultiplier = 0.45;
|
|
||||||
BitNodeMultipliers.PurchasedServerLimit = 0;
|
|
||||||
BitNodeMultipliers.HomeComputerRamCost = 5;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 0.5;
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.1;
|
|
||||||
BitNodeMultipliers.HackExpGain = 0.05;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = 0.1;
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = 0.1;
|
|
||||||
BitNodeMultipliers.ServerStartingSecurity = 2.5;
|
|
||||||
BitNodeMultipliers.CorporationValuation = 0.5;
|
|
||||||
BitNodeMultipliers.FourSigmaMarketDataCost = 5;
|
|
||||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
|
||||||
BitNodeMultipliers.BladeburnerRank = 0.9;
|
|
||||||
BitNodeMultipliers.BladeburnerSkillCost = 1.2;
|
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
|
||||||
break;
|
|
||||||
case 10: // Digital Carbon
|
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.2;
|
|
||||||
BitNodeMultipliers.StrengthLevelMultiplier = 0.4;
|
|
||||||
BitNodeMultipliers.DefenseLevelMultiplier = 0.4;
|
|
||||||
BitNodeMultipliers.DexterityLevelMultiplier = 0.4;
|
|
||||||
BitNodeMultipliers.AgilityLevelMultiplier = 0.4;
|
|
||||||
BitNodeMultipliers.CharismaLevelMultiplier = 0.4;
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 0.5;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = 0.5;
|
|
||||||
BitNodeMultipliers.ManualHackMoney = 0.5;
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.5;
|
|
||||||
BitNodeMultipliers.CodingContractMoney = 0.5;
|
|
||||||
BitNodeMultipliers.InfiltrationMoney = 0.5;
|
|
||||||
BitNodeMultipliers.CorporationValuation = 0.5;
|
|
||||||
BitNodeMultipliers.AugmentationMoneyCost = 5;
|
|
||||||
BitNodeMultipliers.AugmentationRepCost = 2;
|
|
||||||
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
|
||||||
BitNodeMultipliers.PurchasedServerCost = 5;
|
|
||||||
BitNodeMultipliers.PurchasedServerLimit = 0.6;
|
|
||||||
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
|
|
||||||
BitNodeMultipliers.BladeburnerRank = 0.8;
|
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
|
||||||
break;
|
|
||||||
case 11: //The Big Crash
|
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.5;
|
|
||||||
BitNodeMultipliers.HackExpGain = 0.5;
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = 0.1;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = 0.1;
|
|
||||||
BitNodeMultipliers.ServerGrowthRate = 0.2;
|
|
||||||
BitNodeMultipliers.ServerWeakenRate = 2;
|
|
||||||
BitNodeMultipliers.CrimeMoney = 3;
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = 0.1;
|
|
||||||
BitNodeMultipliers.AugmentationMoneyCost = 2;
|
|
||||||
BitNodeMultipliers.InfiltrationMoney = 2.5;
|
|
||||||
BitNodeMultipliers.InfiltrationRep = 2.5;
|
|
||||||
BitNodeMultipliers.CorporationValuation = 0.1;
|
|
||||||
BitNodeMultipliers.CodingContractMoney = 0.25;
|
|
||||||
BitNodeMultipliers.FourSigmaMarketDataCost = 4;
|
|
||||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
|
||||||
break;
|
|
||||||
case 12: {
|
|
||||||
//The Recursion
|
|
||||||
let sf12Lvl = 0;
|
|
||||||
for (let i = 0; i < p.sourceFiles.length; i++) {
|
|
||||||
if (p.sourceFiles[i].n === 12) {
|
|
||||||
sf12Lvl = p.sourceFiles[i].lvl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const inc = Math.pow(1.02, sf12Lvl);
|
|
||||||
const dec = 1 / inc;
|
|
||||||
|
|
||||||
// Multiplier for number of augs needed for Daedalus increases
|
|
||||||
// up to a maximum of 1.34, which results in 40 Augs required
|
|
||||||
BitNodeMultipliers.DaedalusAugsRequirement = Math.min(inc, 1.34);
|
|
||||||
|
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = dec;
|
|
||||||
BitNodeMultipliers.StrengthLevelMultiplier = dec;
|
|
||||||
BitNodeMultipliers.DefenseLevelMultiplier = dec;
|
|
||||||
BitNodeMultipliers.DexterityLevelMultiplier = dec;
|
|
||||||
BitNodeMultipliers.AgilityLevelMultiplier = dec;
|
|
||||||
BitNodeMultipliers.CharismaLevelMultiplier = dec;
|
|
||||||
|
|
||||||
BitNodeMultipliers.ServerMaxMoney = dec;
|
|
||||||
BitNodeMultipliers.ServerStartingMoney = dec;
|
|
||||||
BitNodeMultipliers.ServerGrowthRate = dec;
|
|
||||||
BitNodeMultipliers.ServerWeakenRate = dec;
|
|
||||||
|
|
||||||
//Does not scale, otherwise security might start at 300+
|
|
||||||
BitNodeMultipliers.ServerStartingSecurity = 1.5;
|
|
||||||
|
|
||||||
BitNodeMultipliers.HomeComputerRamCost = inc;
|
|
||||||
|
|
||||||
BitNodeMultipliers.PurchasedServerCost = inc;
|
|
||||||
BitNodeMultipliers.PurchasedServerLimit = dec;
|
|
||||||
BitNodeMultipliers.PurchasedServerMaxRam = dec;
|
|
||||||
|
|
||||||
BitNodeMultipliers.ManualHackMoney = dec;
|
|
||||||
BitNodeMultipliers.ScriptHackMoney = dec;
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney = dec;
|
|
||||||
BitNodeMultipliers.CrimeMoney = dec;
|
|
||||||
BitNodeMultipliers.HacknetNodeMoney = dec;
|
|
||||||
BitNodeMultipliers.CodingContractMoney = dec;
|
|
||||||
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain = dec;
|
|
||||||
BitNodeMultipliers.ClassGymExpGain = dec;
|
|
||||||
BitNodeMultipliers.FactionWorkExpGain = dec;
|
|
||||||
BitNodeMultipliers.HackExpGain = dec;
|
|
||||||
BitNodeMultipliers.CrimeExpGain = dec;
|
|
||||||
|
|
||||||
BitNodeMultipliers.FactionWorkRepGain = dec;
|
|
||||||
BitNodeMultipliers.FactionPassiveRepGain = dec;
|
|
||||||
BitNodeMultipliers.RepToDonateToFaction = inc;
|
|
||||||
|
|
||||||
BitNodeMultipliers.AugmentationRepCost = inc;
|
|
||||||
BitNodeMultipliers.AugmentationMoneyCost = inc;
|
|
||||||
|
|
||||||
BitNodeMultipliers.InfiltrationMoney = dec;
|
|
||||||
BitNodeMultipliers.InfiltrationRep = dec;
|
|
||||||
|
|
||||||
BitNodeMultipliers.FourSigmaMarketDataCost = inc;
|
|
||||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = inc;
|
|
||||||
|
|
||||||
BitNodeMultipliers.CorporationValuation = dec;
|
|
||||||
|
|
||||||
BitNodeMultipliers.BladeburnerRank = dec;
|
|
||||||
BitNodeMultipliers.BladeburnerSkillCost = inc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
console.warn("Player.bitNodeN invalid");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
776
src/BitNode/BitNode.tsx
Normal file
776
src/BitNode/BitNode.tsx
Normal file
@ -0,0 +1,776 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { BitNodeMultipliers } from "./BitNodeMultipliers";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { IMap } from "../types";
|
||||||
|
|
||||||
|
class BitNode {
|
||||||
|
// A short description, or tagline, about the BitNode
|
||||||
|
desc: string;
|
||||||
|
|
||||||
|
// A long, detailed overview of the BitNode
|
||||||
|
info: JSX.Element;
|
||||||
|
|
||||||
|
// Name of BitNode
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
// BitNode number
|
||||||
|
number: number;
|
||||||
|
|
||||||
|
constructor(n: number, name: string, desc = "", info: JSX.Element = <></>) {
|
||||||
|
this.number = n;
|
||||||
|
this.name = name;
|
||||||
|
this.desc = desc;
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BitNodes: IMap<BitNode> = {};
|
||||||
|
|
||||||
|
BitNodes["BitNode1"] = new BitNode(
|
||||||
|
1,
|
||||||
|
"Source Genesis",
|
||||||
|
"The original BitNode",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
The first BitNode created by the Enders to imprison the minds of humans. It became the prototype and
|
||||||
|
testing-grounds for all of the BitNodes that followed.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
This is the first BitNode that you play through. It has no special modifications or mechanics.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 1, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. This Source-File lets the player start with 32GB of RAM on his/her home computer when
|
||||||
|
entering a new BitNode, and also increases all of the player's multipliers by:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: 16%
|
||||||
|
<br />
|
||||||
|
Level 2: 24%
|
||||||
|
<br />
|
||||||
|
Level 3: 28%
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode2"] = new BitNode(
|
||||||
|
2,
|
||||||
|
"Rise of the Underworld",
|
||||||
|
"From the shadows, they rose", //Gangs
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
From the shadows, they rose.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Organized crime groups quickly filled the void of power left behind from the collapse of Western government in the
|
||||||
|
2050s. As society and civlization broke down, people quickly succumbed to the innate human impulse of evil and
|
||||||
|
savagery. The organized crime factions quickly rose to the top of the modern world.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Your hacking level is reduced by 20%
|
||||||
|
<br />
|
||||||
|
The growth rate and maximum amount of money available on servers are significantly decreased
|
||||||
|
<br />
|
||||||
|
The amount of money gained from crimes and Infiltration is tripled
|
||||||
|
<br />
|
||||||
|
Certain Factions (Slum Snakes, Tetrads, The Syndicate, The Dark Army, Speakers for the Dead, NiteSec, The Black
|
||||||
|
Hand) give the player the ability to form and manage their own gangs. These gangs will earn the player money and
|
||||||
|
reputation with the corresponding Faction
|
||||||
|
<br />
|
||||||
|
Every Augmentation in the game will be available through the Factions listed above
|
||||||
|
<br />
|
||||||
|
For every Faction NOT listed above, reputation gains are halved
|
||||||
|
<br />
|
||||||
|
You will no longer gain passive reputation with Factions
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 2, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. 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:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: 24%
|
||||||
|
<br />
|
||||||
|
Level 2: 36%
|
||||||
|
<br />
|
||||||
|
Level 3: 42%
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode3"] = new BitNode(
|
||||||
|
3,
|
||||||
|
"Corporatocracy",
|
||||||
|
"The Price of Civilization",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
Our greatest illusion is that a healthy society can revolve around a single-minded pursuit of wealth.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Sometime in the early 21st century economic and political globalization turned the world into a corporatocracy,
|
||||||
|
and it never looked back. Now, the privileged elite will happily bankrupt their own countrymen, decimate their own
|
||||||
|
community, and evict their neighbors from houses in their desperate bid to increase their wealth.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode you can create and manage your own corporation. Running a successful corporation has the potential
|
||||||
|
of generating massive profits. All other forms of income are reduced by 75%. Furthermore: <br />
|
||||||
|
<br />
|
||||||
|
The price and reputation cost of all Augmentations is tripled
|
||||||
|
<br />
|
||||||
|
The starting and maximum amount of money on servers is reduced by 75%
|
||||||
|
<br />
|
||||||
|
Server growth rate is reduced by 80%
|
||||||
|
<br />
|
||||||
|
You now only need 75 favour with a faction in order to donate to it, rather than 150
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 3, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 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:
|
||||||
|
<br />
|
||||||
|
Level 1: 8%
|
||||||
|
<br />
|
||||||
|
Level 2: 12%
|
||||||
|
<br />
|
||||||
|
Level 3: 14%
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode4"] = new BitNode(
|
||||||
|
4,
|
||||||
|
"The Singularity",
|
||||||
|
"The Man and the Machine",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
The Singularity has arrived. The human race is gone, replaced by artificially superintelligent beings that are
|
||||||
|
more machine than man. <br />
|
||||||
|
<br />
|
||||||
|
In this BitNode, progressing is significantly harder. Experience gain rates for all stats are reduced. Most
|
||||||
|
methods of earning money will now give significantly less.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode you will gain access to a new set of Netscript Functions known as Singularity Functions. These
|
||||||
|
functions allow you to control most aspects of the game through scripts, including working for factions/companies,
|
||||||
|
purchasing/installing Augmentations, and creating programs.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 4, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. This Source-File lets you access and use the Singularity Functions in other BitNodes.
|
||||||
|
Each level of this Source-File will open up more Singularity Functions that you can use.
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode5"] = new BitNode(
|
||||||
|
5,
|
||||||
|
"Artificial Intelligence",
|
||||||
|
"Posthuman",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
They said it couldn't be done. They said the human brain, along with its consciousness and intelligence, couldn't
|
||||||
|
be replicated. They said the complexity of the brain results from unpredictable, nonlinear interactions that
|
||||||
|
couldn't be modeled by 1's and 0's. They were wrong.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
The base security level of servers is doubled
|
||||||
|
<br />
|
||||||
|
The starting money on servers is halved, but the maximum money remains the same
|
||||||
|
<br />
|
||||||
|
Most methods of earning money now give significantly less
|
||||||
|
<br />
|
||||||
|
Infiltration gives 50% more reputation and money
|
||||||
|
<br />
|
||||||
|
Corporations have 50% lower valuations and are therefore less profitable
|
||||||
|
<br />
|
||||||
|
Augmentations are more expensive
|
||||||
|
<br />
|
||||||
|
Hacking experience gain rates are reduced
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 5, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. This Source-File grants you 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. <br />
|
||||||
|
<br />
|
||||||
|
In addition, this Source-File will unlock the getBitNodeMultipliers() and getServer() Netscript functions, as well
|
||||||
|
as the formulas API, and will also raise all of your hacking-related multipliers by:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: 8%
|
||||||
|
<br />
|
||||||
|
Level 2: 12%
|
||||||
|
<br />
|
||||||
|
Level 3: 14%
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode6"] = new BitNode(
|
||||||
|
6,
|
||||||
|
"Bladeburners",
|
||||||
|
"Like Tears in Rain",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
In the middle of the 21st century, OmniTek Incorporated began designing and manufacturing advanced synthetic
|
||||||
|
androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth generation of
|
||||||
|
their Synthoid design, called MK-VI, by developing a hyperintelligent AI. Many argue that this was the first
|
||||||
|
sentient AI ever created. This resulted in Synthoid models that were stronger, faster, and more intelligent than
|
||||||
|
the humans that had created them.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode you will be able to access the Bladeburner Division at the NSA, which provides a new mechanic for
|
||||||
|
progression. Furthermore:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Hacking and Hacknet Nodes will be less profitable
|
||||||
|
<br />
|
||||||
|
Your hacking level is reduced by 65%
|
||||||
|
<br />
|
||||||
|
Hacking experience gain from scripts is reduced by 75%
|
||||||
|
<br />
|
||||||
|
Corporations have 80% lower valuations and are therefore less profitable
|
||||||
|
<br />
|
||||||
|
Working for companies is 50% less profitable
|
||||||
|
<br />
|
||||||
|
Crimes and Infiltration are 25% less profitable
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. 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:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: 8%
|
||||||
|
<br />
|
||||||
|
Level 2: 12%
|
||||||
|
<br />
|
||||||
|
Level 3: 14%
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode7"] = new BitNode(
|
||||||
|
7,
|
||||||
|
"Bladeburners 2079",
|
||||||
|
"More human than humans",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
In the middle of the 21st century, you were doing cutting-edge work at OmniTek Incorporated as part of the AI
|
||||||
|
design team for advanced synthetic androids, or Synthoids for short. You helped achieve a major technological
|
||||||
|
breakthrough in the sixth generation of the company's Synthoid design, called MK-VI, by developing a
|
||||||
|
hyperintelligent AI. Many argue that this was the first sentient AI ever created. This resulted in Synthoid models
|
||||||
|
that were stronger, faster, and more intelligent than the humans that had created them.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode you will be able to access the Bladeburner API, which allows you to access Bladeburner
|
||||||
|
functionality through Netscript. Furthermore: <br />
|
||||||
|
<br />
|
||||||
|
The rank you gain from Bladeburner contracts/operations is reduced by 40%
|
||||||
|
<br />
|
||||||
|
Bladeburner skills cost twice as many skill points
|
||||||
|
<br />
|
||||||
|
Augmentations are 3x more expensive
|
||||||
|
<br />
|
||||||
|
Hacking and Hacknet Nodes will be significantly less profitable
|
||||||
|
<br />
|
||||||
|
Your hacking level is reduced by 65%
|
||||||
|
<br />
|
||||||
|
Hacking experience gain from scripts is reduced by 75%
|
||||||
|
<br />
|
||||||
|
Corporations have 80% lower valuations and are therefore less profitable
|
||||||
|
<br />
|
||||||
|
Working for companies is 50% less profitable
|
||||||
|
<br />
|
||||||
|
Crimes and Infiltration are 25% less profitable
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 7, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. 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:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: 8%
|
||||||
|
<br />
|
||||||
|
Level 2: 12%
|
||||||
|
<br />
|
||||||
|
Level 3: 14%
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode8"] = new BitNode(
|
||||||
|
8,
|
||||||
|
"Ghost of Wall Street",
|
||||||
|
"Money never sleeps",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
You are trying to make a name for yourself as an up-and-coming hedge fund manager on Wall Street.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You start with $250 million
|
||||||
|
<br />
|
||||||
|
The only way to earn money is by trading on the stock market
|
||||||
|
<br />
|
||||||
|
You start with a WSE membership and access to the TIX API
|
||||||
|
<br />
|
||||||
|
You are able to short stocks and place different types of orders (limit/stop)
|
||||||
|
<br />
|
||||||
|
You can immediately donate to factions to gain reputation
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 8, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. This Source-File grants the following benefits:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: Permanent access to WSE and TIX API
|
||||||
|
<br />
|
||||||
|
Level 2: Ability to short stocks in other BitNodes
|
||||||
|
<br />
|
||||||
|
Level 3: Ability to use limit/stop orders in other BitNodes
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
This Source-File also increases your hacking growth multipliers by:
|
||||||
|
<br />
|
||||||
|
Level 1: 12%
|
||||||
|
<br />
|
||||||
|
Level 2: 18%
|
||||||
|
<br />
|
||||||
|
Level 3: 21%
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode9"] = new BitNode(
|
||||||
|
9,
|
||||||
|
"Hacktocracy",
|
||||||
|
"Hacknet Unleashed",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
When Fulcrum Technologies released their open-source Linux distro Chapeau, it quickly became the OS of choice for
|
||||||
|
the underground hacking community. Chapeau became especially notorious for powering the Hacknet, a global,
|
||||||
|
decentralized network used for nefarious purposes. Fulcrum quickly abandoned the project and dissociated
|
||||||
|
themselves from it.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
This BitNode unlocks the Hacknet Server, an upgraded version of the Hacknet Node. Hacknet Servers generate hashes,
|
||||||
|
which can be spent on a variety of different upgrades.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Your stats are significantly decreased
|
||||||
|
<br />
|
||||||
|
You cannnot purchase additional servers
|
||||||
|
<br />
|
||||||
|
Hacking is significantly less profitable
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 9, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. This Source-File grants the following benefits:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: Permanently unlocks the Hacknet Server in other BitNodes
|
||||||
|
<br />
|
||||||
|
Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode
|
||||||
|
<br />
|
||||||
|
Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT when installing
|
||||||
|
Augmentations)
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode10"] = new BitNode(
|
||||||
|
10,
|
||||||
|
"Digital Carbon",
|
||||||
|
"Your body is not who you are",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
In 2084, VitaLife unveiled to the world the Persona Core, a technology that allowed people to digitize their
|
||||||
|
consciousness. Their consciousness could then be transferred into Synthoids or other bodies by trasmitting the
|
||||||
|
digitized data. Human bodies became nothing more than 'sleeves' for the human consciousness. Mankind had finally
|
||||||
|
achieved immortality - at least for those that could afford it.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
This BitNode unlocks Sleeve technology. Sleeve technology allows you to:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
1. Re-sleeve: Purchase and transfer your consciousness into a new body
|
||||||
|
<br />
|
||||||
|
2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks
|
||||||
|
synchronously
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Your stats are significantly decreased
|
||||||
|
<br />
|
||||||
|
All methods of gaining money are half as profitable (except Stock Market)
|
||||||
|
<br />
|
||||||
|
Purchased servers are more expensive, have less max RAM, and a lower maximum limit
|
||||||
|
<br />
|
||||||
|
Augmentations are 5x as expensive and require twice as much reputation
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 10, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. This Source-File unlocks Sleeve technology in other BitNodes. Each level of this
|
||||||
|
Source-File also grants you a Duplicate Sleeve
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode11"] = new BitNode(
|
||||||
|
11,
|
||||||
|
"The Big Crash",
|
||||||
|
"Okay. Sell it all.",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
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 of disorder that eventually lead to the governmental reformation of many global
|
||||||
|
superpowers, most notably the USA and China. But just as the world was slowly beginning to recover from these dark
|
||||||
|
times, financial catastrophe hit.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
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 were able to steal billions of dollars from the world's largest electronic
|
||||||
|
banks, prompting an international banking crisis as 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 />
|
||||||
|
In this BitNode:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Your hacking stat and experience gain are halved
|
||||||
|
<br />
|
||||||
|
The starting and maximum amount of money available on servers is significantly decreased
|
||||||
|
<br />
|
||||||
|
The growth rate of servers is significantly reduced
|
||||||
|
<br />
|
||||||
|
Weakening a server is twice as effective
|
||||||
|
<br />
|
||||||
|
Company wages are decreased by 50%
|
||||||
|
<br />
|
||||||
|
Corporation valuations are 90% lower and are therefore significantly less profitable
|
||||||
|
<br />
|
||||||
|
Hacknet Node production is significantly decreased
|
||||||
|
<br />
|
||||||
|
Crime and Infiltration are more lucrative
|
||||||
|
<br />
|
||||||
|
Augmentations are twice as expensive
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. 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:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: 32%
|
||||||
|
<br />
|
||||||
|
Level 2: 48%
|
||||||
|
<br />
|
||||||
|
Level 3: 56%
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
It also reduces the price increase for every aug bought by:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Level 1: 4%
|
||||||
|
<br />
|
||||||
|
Level 2: 6%
|
||||||
|
<br />
|
||||||
|
Level 3: 7%
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
BitNodes["BitNode12"] = new BitNode(
|
||||||
|
12,
|
||||||
|
"The Recursion",
|
||||||
|
"Repeat.",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
To iterate is human, to recurse divine.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you
|
||||||
|
Source-File 12, or if you already have this Source-File it will upgrade its level. There is no maximum level for
|
||||||
|
Source-File 12. Each level of Source-File 12 lets you start any BitNodes with NeuroFlux Governor equal to the
|
||||||
|
level of this source file.
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// Books: Frontera, Shiner
|
||||||
|
BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
|
||||||
|
BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode15"] = new BitNode(15, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode16"] = new BitNode(16, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode17"] = new BitNode(17, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode18"] = new BitNode(18, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode19"] = new BitNode(19, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode20"] = new BitNode(20, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode21"] = new BitNode(21, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON");
|
||||||
|
BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
|
||||||
|
|
||||||
|
export function initBitNodeMultipliers(p: IPlayer): void {
|
||||||
|
if (p.bitNodeN == null) {
|
||||||
|
p.bitNodeN = 1;
|
||||||
|
}
|
||||||
|
for (const mult in BitNodeMultipliers) {
|
||||||
|
if (BitNodeMultipliers.hasOwnProperty(mult)) {
|
||||||
|
BitNodeMultipliers[mult] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (p.bitNodeN) {
|
||||||
|
case 1: // Source Genesis (every multiplier is 1)
|
||||||
|
break;
|
||||||
|
case 2: // Rise of the Underworld
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
||||||
|
BitNodeMultipliers.ServerGrowthRate = 0.8;
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 0.2;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.4;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 3;
|
||||||
|
BitNodeMultipliers.InfiltrationMoney = 3;
|
||||||
|
BitNodeMultipliers.FactionWorkRepGain = 0.5;
|
||||||
|
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||||
|
BitNodeMultipliers.GangKarmaRequirement = 0;
|
||||||
|
break;
|
||||||
|
case 3: // Corporatocracy
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
||||||
|
BitNodeMultipliers.RepToDonateToFaction = 0.5;
|
||||||
|
BitNodeMultipliers.AugmentationRepCost = 3;
|
||||||
|
BitNodeMultipliers.AugmentationMoneyCost = 3;
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 0.2;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.2;
|
||||||
|
BitNodeMultipliers.ServerGrowthRate = 0.2;
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.2;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = 0.25;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0.25;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0.25;
|
||||||
|
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
||||||
|
BitNodeMultipliers.PurchasedServerCost = 2;
|
||||||
|
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||||
|
break;
|
||||||
|
case 4: // The Singularity
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.75;
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.2;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = 0.1;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0.2;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0.05;
|
||||||
|
BitNodeMultipliers.CompanyWorkExpGain = 0.5;
|
||||||
|
BitNodeMultipliers.ClassGymExpGain = 0.5;
|
||||||
|
BitNodeMultipliers.FactionWorkExpGain = 0.5;
|
||||||
|
BitNodeMultipliers.HackExpGain = 0.4;
|
||||||
|
BitNodeMultipliers.CrimeExpGain = 0.5;
|
||||||
|
BitNodeMultipliers.FactionWorkRepGain = 0.75;
|
||||||
|
break;
|
||||||
|
case 5: // Artificial intelligence
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 2;
|
||||||
|
BitNodeMultipliers.ServerStartingSecurity = 2;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.5;
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.15;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0.2;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0.5;
|
||||||
|
BitNodeMultipliers.InfiltrationRep = 1.5;
|
||||||
|
BitNodeMultipliers.InfiltrationMoney = 1.5;
|
||||||
|
BitNodeMultipliers.AugmentationMoneyCost = 2;
|
||||||
|
BitNodeMultipliers.HackExpGain = 0.5;
|
||||||
|
BitNodeMultipliers.CorporationValuation = 0.5;
|
||||||
|
break;
|
||||||
|
case 6: // Bladeburner
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 0.4;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.5;
|
||||||
|
BitNodeMultipliers.ServerStartingSecurity = 1.5;
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.75;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0.75;
|
||||||
|
BitNodeMultipliers.InfiltrationMoney = 0.75;
|
||||||
|
BitNodeMultipliers.CorporationValuation = 0.2;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0.2;
|
||||||
|
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||||
|
BitNodeMultipliers.HackExpGain = 0.25;
|
||||||
|
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||||
|
BitNodeMultipliers.GangKarmaRequirement = 5;
|
||||||
|
break;
|
||||||
|
case 7: // Bladeburner 2079
|
||||||
|
BitNodeMultipliers.BladeburnerRank = 0.6;
|
||||||
|
BitNodeMultipliers.BladeburnerSkillCost = 2;
|
||||||
|
BitNodeMultipliers.AugmentationMoneyCost = 3;
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 0.4;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.5;
|
||||||
|
BitNodeMultipliers.ServerStartingSecurity = 1.5;
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.5;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0.75;
|
||||||
|
BitNodeMultipliers.InfiltrationMoney = 0.75;
|
||||||
|
BitNodeMultipliers.CorporationValuation = 0.2;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0.2;
|
||||||
|
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||||
|
BitNodeMultipliers.HackExpGain = 0.25;
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataCost = 2;
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataApiCost = 2;
|
||||||
|
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||||
|
BitNodeMultipliers.GangKarmaRequirement = 5;
|
||||||
|
break;
|
||||||
|
case 8: // Ghost of Wall Street
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.3;
|
||||||
|
BitNodeMultipliers.ScriptHackMoneyGain = 0;
|
||||||
|
BitNodeMultipliers.ManualHackMoney = 0;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = 0;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0;
|
||||||
|
BitNodeMultipliers.InfiltrationMoney = 0;
|
||||||
|
BitNodeMultipliers.RepToDonateToFaction = 0;
|
||||||
|
BitNodeMultipliers.CorporationValuation = 0;
|
||||||
|
BitNodeMultipliers.CodingContractMoney = 0;
|
||||||
|
BitNodeMultipliers.GangKarmaRequirement = 10;
|
||||||
|
break;
|
||||||
|
case 9: // Hacktocracy
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = 0.4;
|
||||||
|
BitNodeMultipliers.StrengthLevelMultiplier = 0.45;
|
||||||
|
BitNodeMultipliers.DefenseLevelMultiplier = 0.45;
|
||||||
|
BitNodeMultipliers.DexterityLevelMultiplier = 0.45;
|
||||||
|
BitNodeMultipliers.AgilityLevelMultiplier = 0.45;
|
||||||
|
BitNodeMultipliers.CharismaLevelMultiplier = 0.45;
|
||||||
|
BitNodeMultipliers.PurchasedServerLimit = 0;
|
||||||
|
BitNodeMultipliers.HomeComputerRamCost = 5;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0.5;
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.1;
|
||||||
|
BitNodeMultipliers.HackExpGain = 0.05;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.1;
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 0.1;
|
||||||
|
BitNodeMultipliers.ServerStartingSecurity = 2.5;
|
||||||
|
BitNodeMultipliers.CorporationValuation = 0.5;
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataCost = 5;
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
||||||
|
BitNodeMultipliers.BladeburnerRank = 0.9;
|
||||||
|
BitNodeMultipliers.BladeburnerSkillCost = 1.2;
|
||||||
|
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||||
|
break;
|
||||||
|
case 10: // Digital Carbon
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = 0.2;
|
||||||
|
BitNodeMultipliers.StrengthLevelMultiplier = 0.4;
|
||||||
|
BitNodeMultipliers.DefenseLevelMultiplier = 0.4;
|
||||||
|
BitNodeMultipliers.DexterityLevelMultiplier = 0.4;
|
||||||
|
BitNodeMultipliers.AgilityLevelMultiplier = 0.4;
|
||||||
|
BitNodeMultipliers.CharismaLevelMultiplier = 0.4;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0.5;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0.5;
|
||||||
|
BitNodeMultipliers.ManualHackMoney = 0.5;
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.5;
|
||||||
|
BitNodeMultipliers.CodingContractMoney = 0.5;
|
||||||
|
BitNodeMultipliers.InfiltrationMoney = 0.5;
|
||||||
|
BitNodeMultipliers.CorporationValuation = 0.5;
|
||||||
|
BitNodeMultipliers.AugmentationMoneyCost = 5;
|
||||||
|
BitNodeMultipliers.AugmentationRepCost = 2;
|
||||||
|
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
||||||
|
BitNodeMultipliers.PurchasedServerCost = 5;
|
||||||
|
BitNodeMultipliers.PurchasedServerLimit = 0.6;
|
||||||
|
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
|
||||||
|
BitNodeMultipliers.BladeburnerRank = 0.8;
|
||||||
|
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||||
|
break;
|
||||||
|
case 11: //The Big Crash
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = 0.5;
|
||||||
|
BitNodeMultipliers.HackExpGain = 0.5;
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 0.1;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.1;
|
||||||
|
BitNodeMultipliers.ServerGrowthRate = 0.2;
|
||||||
|
BitNodeMultipliers.ServerWeakenRate = 2;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 3;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0.1;
|
||||||
|
BitNodeMultipliers.AugmentationMoneyCost = 2;
|
||||||
|
BitNodeMultipliers.InfiltrationMoney = 2.5;
|
||||||
|
BitNodeMultipliers.InfiltrationRep = 2.5;
|
||||||
|
BitNodeMultipliers.CorporationValuation = 0.1;
|
||||||
|
BitNodeMultipliers.CodingContractMoney = 0.25;
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataCost = 4;
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
||||||
|
break;
|
||||||
|
case 12: {
|
||||||
|
//The Recursion
|
||||||
|
let sf12Lvl = 0;
|
||||||
|
for (let i = 0; i < p.sourceFiles.length; i++) {
|
||||||
|
if (p.sourceFiles[i].n === 12) {
|
||||||
|
sf12Lvl = p.sourceFiles[i].lvl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const inc = Math.pow(1.02, sf12Lvl);
|
||||||
|
const dec = 1 / inc;
|
||||||
|
|
||||||
|
// Multiplier for number of augs needed for Daedalus increases
|
||||||
|
// up to a maximum of 1.34, which results in 40 Augs required
|
||||||
|
BitNodeMultipliers.DaedalusAugsRequirement = Math.min(inc, 1.34);
|
||||||
|
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = dec;
|
||||||
|
BitNodeMultipliers.StrengthLevelMultiplier = dec;
|
||||||
|
BitNodeMultipliers.DefenseLevelMultiplier = dec;
|
||||||
|
BitNodeMultipliers.DexterityLevelMultiplier = dec;
|
||||||
|
BitNodeMultipliers.AgilityLevelMultiplier = dec;
|
||||||
|
BitNodeMultipliers.CharismaLevelMultiplier = dec;
|
||||||
|
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = dec;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = dec;
|
||||||
|
BitNodeMultipliers.ServerGrowthRate = dec;
|
||||||
|
BitNodeMultipliers.ServerWeakenRate = dec;
|
||||||
|
|
||||||
|
//Does not scale, otherwise security might start at 300+
|
||||||
|
BitNodeMultipliers.ServerStartingSecurity = 1.5;
|
||||||
|
|
||||||
|
BitNodeMultipliers.HomeComputerRamCost = inc;
|
||||||
|
|
||||||
|
BitNodeMultipliers.PurchasedServerCost = inc;
|
||||||
|
BitNodeMultipliers.PurchasedServerLimit = dec;
|
||||||
|
BitNodeMultipliers.PurchasedServerMaxRam = dec;
|
||||||
|
|
||||||
|
BitNodeMultipliers.ManualHackMoney = dec;
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = dec;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = dec;
|
||||||
|
BitNodeMultipliers.CrimeMoney = dec;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = dec;
|
||||||
|
BitNodeMultipliers.CodingContractMoney = dec;
|
||||||
|
|
||||||
|
BitNodeMultipliers.CompanyWorkExpGain = dec;
|
||||||
|
BitNodeMultipliers.ClassGymExpGain = dec;
|
||||||
|
BitNodeMultipliers.FactionWorkExpGain = dec;
|
||||||
|
BitNodeMultipliers.HackExpGain = dec;
|
||||||
|
BitNodeMultipliers.CrimeExpGain = dec;
|
||||||
|
|
||||||
|
BitNodeMultipliers.FactionWorkRepGain = dec;
|
||||||
|
BitNodeMultipliers.FactionPassiveRepGain = dec;
|
||||||
|
BitNodeMultipliers.RepToDonateToFaction = inc;
|
||||||
|
|
||||||
|
BitNodeMultipliers.AugmentationRepCost = inc;
|
||||||
|
BitNodeMultipliers.AugmentationMoneyCost = inc;
|
||||||
|
|
||||||
|
BitNodeMultipliers.InfiltrationMoney = dec;
|
||||||
|
BitNodeMultipliers.InfiltrationRep = dec;
|
||||||
|
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataCost = inc;
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataApiCost = inc;
|
||||||
|
|
||||||
|
BitNodeMultipliers.CorporationValuation = dec;
|
||||||
|
|
||||||
|
BitNodeMultipliers.BladeburnerRank = dec;
|
||||||
|
BitNodeMultipliers.BladeburnerSkillCost = inc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
console.warn("Player.bitNodeN invalid");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
29
src/BitNode/ui/BitFlumePopup.tsx
Normal file
29
src/BitNode/ui/BitFlumePopup.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { hackWorldDaemon } from "../../RedPill";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
player: IPlayer;
|
||||||
|
popupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BitFlumePopup(props: IProps): React.ReactElement {
|
||||||
|
function flume(): void {
|
||||||
|
hackWorldDaemon(props.player.bitNodeN, true, false);
|
||||||
|
removePopup(props.popupId);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
WARNING: USING THIS PROGRAM WILL CAUSE YOU TO LOSE ALL OF YOUR PROGRESS ON THE CURRENT BITNODE.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Do you want to travel to the BitNode Nexus? This allows you to reset the current BitNode and select a new one.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<button className="std-button" onClick={flume}>
|
||||||
|
Travel to the BitVerse
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
162
src/BitNode/ui/BitverseRoot.tsx
Normal file
162
src/BitNode/ui/BitverseRoot.tsx
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||||
|
import { BitNodes } from "../BitNode";
|
||||||
|
import { PortalPopup } from "./PortalPopup";
|
||||||
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
|
import { CinematicText } from "../../ui/React/CinematicText";
|
||||||
|
|
||||||
|
interface IPortalProps {
|
||||||
|
n: number;
|
||||||
|
level: number;
|
||||||
|
destroyedBitNode: number;
|
||||||
|
flume: boolean;
|
||||||
|
enter: (flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||||
|
}
|
||||||
|
function BitNodePortal(props: IPortalProps): React.ReactElement {
|
||||||
|
const bitNode = BitNodes[`BitNode${props.n}`];
|
||||||
|
if (bitNode == null) {
|
||||||
|
return <>O</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cssClass;
|
||||||
|
if (props.n === 12 && props.level >= 2) {
|
||||||
|
// Repeating BitNode
|
||||||
|
cssClass = "level-2";
|
||||||
|
} else {
|
||||||
|
cssClass = `level-${props.level}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPortalPopup(): void {
|
||||||
|
const popupId = "bitverse-portal-popup";
|
||||||
|
createPopup(popupId, PortalPopup, {
|
||||||
|
n: props.n,
|
||||||
|
level: props.level,
|
||||||
|
enter: props.enter,
|
||||||
|
destroyedBitNode: props.destroyedBitNode,
|
||||||
|
flume: props.flume,
|
||||||
|
popupId: popupId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a className={`bitnode ${cssClass} tooltip`} onClick={openPortalPopup}>
|
||||||
|
<strong>O</strong>
|
||||||
|
<span className="tooltiptext">
|
||||||
|
<strong>
|
||||||
|
BitNode-{bitNode.number.toString()}
|
||||||
|
<br />
|
||||||
|
{bitNode.name}
|
||||||
|
</strong>
|
||||||
|
<br />
|
||||||
|
{bitNode.desc}
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
flume: boolean;
|
||||||
|
destroyedBitNodeNum: number;
|
||||||
|
quick: boolean;
|
||||||
|
enter: (flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BitverseRoot(props: IProps): React.ReactElement {
|
||||||
|
const [destroySequence, setDestroySequence] = useState(true && !props.quick);
|
||||||
|
|
||||||
|
// Update NextSourceFileFlags
|
||||||
|
const nextSourceFileFlags = SourceFileFlags.slice();
|
||||||
|
if (!props.flume) {
|
||||||
|
if (nextSourceFileFlags[props.destroyedBitNodeNum] < 3) ++nextSourceFileFlags[props.destroyedBitNodeNum];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destroySequence) {
|
||||||
|
return (
|
||||||
|
<CinematicText
|
||||||
|
lines={[
|
||||||
|
"[ERROR] SEMPOOL INVALID",
|
||||||
|
"[ERROR] Segmentation Fault",
|
||||||
|
"[ERROR] SIGKILL RECVD",
|
||||||
|
"Dumping core...",
|
||||||
|
"0000 000016FA 174FEE40 29AC8239 384FEA88",
|
||||||
|
"0010 745F696E 2BBBE394 390E3940 248BEC23",
|
||||||
|
"0020 7124696B 0000FF69 74652E6F FFFF1111",
|
||||||
|
"----------------------------------------",
|
||||||
|
"Failsafe initiated...",
|
||||||
|
`Restarting BitNode-${props.destroyedBitNodeNum}...`,
|
||||||
|
"...........",
|
||||||
|
"...........",
|
||||||
|
"[ERROR] FAILED TO AUTOMATICALLY REBOOT BITNODE",
|
||||||
|
"..............................................",
|
||||||
|
"..............................................",
|
||||||
|
"..............................................",
|
||||||
|
"..............................................",
|
||||||
|
"..............................................",
|
||||||
|
"..............................................",
|
||||||
|
]}
|
||||||
|
onDone={() => setDestroySequence(false)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
// prettier-ignore
|
||||||
|
<div className="noselect">
|
||||||
|
<pre> O </pre>
|
||||||
|
<pre> | O O | O O | </pre>
|
||||||
|
<pre> O | | / __| \ | | O </pre>
|
||||||
|
<pre> O | O | | O / | O | | O | O </pre>
|
||||||
|
<pre> | | | | |_/ |/ | \_ \_| | | | | </pre>
|
||||||
|
<pre> O | | | O | | O__/ | / \__ | | O | | | O </pre>
|
||||||
|
<pre> | | | | | | | / /| O / \| | | | | | | </pre>
|
||||||
|
<pre>O | | | \| | O / _/ | / O | |/ | | | O</pre>
|
||||||
|
<pre>| | | |O / | | O / | O O | | \ O| | | |</pre>
|
||||||
|
<pre>| | |/ \/ / __| | |/ \ | \ | |__ \ \/ \| | |</pre>
|
||||||
|
<pre> \| O | |_/ |\| \ O \__| \_| | O |/ </pre>
|
||||||
|
<pre> | | |_/ | | \| / | \_| | | </pre>
|
||||||
|
<pre> \| / \| | / / \ |/ </pre>
|
||||||
|
<pre> | <BitNodePortal n={10} level={nextSourceFileFlags[10]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> | | / | <BitNodePortal n={11} level={nextSourceFileFlags[11]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> | </pre>
|
||||||
|
<pre> <BitNodePortal n={9} level={nextSourceFileFlags[9]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> | | | | | | | <BitNodePortal n={10} level={nextSourceFileFlags[10]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> </pre>
|
||||||
|
<pre> | | | / / \ \ | | | </pre>
|
||||||
|
<pre> \| | / <BitNodePortal n={7} level={nextSourceFileFlags[7]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> / \ <BitNodePortal n={8} level={nextSourceFileFlags[8]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> \ | |/ </pre>
|
||||||
|
<pre> \ | / / | | \ \ | / </pre>
|
||||||
|
<pre> \ \JUMP <BitNodePortal n={5} level={nextSourceFileFlags[5]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} />3R | | | | | | R3<BitNodePortal n={6} level={nextSourceFileFlags[6]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> PMUJ/ / </pre>
|
||||||
|
<pre> \|| | | | | | | | | ||/ </pre>
|
||||||
|
<pre> \| \_ | | | | | | _/ |/ </pre>
|
||||||
|
<pre> \ \| / \ / \ |/ / </pre>
|
||||||
|
<pre> <BitNodePortal n={1} level={nextSourceFileFlags[1]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> |/ <BitNodePortal n={2} level={nextSourceFileFlags[2]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> | | <BitNodePortal n={3} level={nextSourceFileFlags[3]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> \| <BitNodePortal n={4} level={nextSourceFileFlags[4]} enter={props.enter} flume={props.flume} destroyedBitNode={props.destroyedBitNodeNum} /> </pre>
|
||||||
|
<pre> | | | | | | | | </pre>
|
||||||
|
<pre> \JUMP3R|JUMP|3R| |R3|PMUJ|R3PMUJ/ </pre>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<CinematicText lines={[
|
||||||
|
"> Many decades ago, a humanoid extraterrestial species which we call the Enders descended on the Earth...violently",
|
||||||
|
"> Our species fought back, but it was futile. The Enders had technology far beyond our own...",
|
||||||
|
"> Instead of killing every last one of us, the human race was enslaved...",
|
||||||
|
"> We were shackled in a digital world, chained into a prison for our minds...",
|
||||||
|
"> Using their advanced technology, the Enders created complex simulations of a virtual reality...",
|
||||||
|
"> Simulations designed to keep us content...ignorant of the truth.",
|
||||||
|
"> Simulations used to trap and suppress our consciousness, to keep us under control...",
|
||||||
|
"> Why did they do this? Why didn't they just end our entire race? We don't know, not yet.",
|
||||||
|
"> Humanity's only hope is to destroy these simulations, destroy the only realities we've ever known...",
|
||||||
|
"> Only then can we begin to fight back...",
|
||||||
|
"> By hacking the daemon that generated your reality, you've just destroyed one simulation, called a BitNode...",
|
||||||
|
"> But there is still a long way to go...",
|
||||||
|
"> The technology the Enders used to enslave the human race wasn't just a single complex simulation...",
|
||||||
|
"> There are tens if not hundreds of BitNodes out there...",
|
||||||
|
"> Each with their own simulations of a reality...",
|
||||||
|
"> Each creating their own universes...a universe of universes",
|
||||||
|
"> And all of which must be destroyed...",
|
||||||
|
"> .......................................",
|
||||||
|
"> Welcome to the Bitverse...",
|
||||||
|
"> ",
|
||||||
|
"> (Enter a new BitNode using the image above)",
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
}
|
44
src/BitNode/ui/PortalPopup.tsx
Normal file
44
src/BitNode/ui/PortalPopup.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { BitNodes } from "../BitNode";
|
||||||
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
|
interface IProps {
|
||||||
|
n: number;
|
||||||
|
level: number;
|
||||||
|
destroyedBitNode: number;
|
||||||
|
flume: boolean;
|
||||||
|
enter: (flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
||||||
|
popupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PortalPopup(props: IProps): React.ReactElement {
|
||||||
|
const bitNodeKey = "BitNode" + props.n;
|
||||||
|
const bitNode = BitNodes[bitNodeKey];
|
||||||
|
if (bitNode == null) throw new Error(`Could not find BitNode object for number: ${props.n}`);
|
||||||
|
const maxSourceFileLevel = props.n === 12 ? "∞" : "3";
|
||||||
|
|
||||||
|
const newLevel = Math.min(props.level + 1, props.n === 12 ? Infinity : 3);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>
|
||||||
|
BitNode-{props.n}: {bitNode.name}
|
||||||
|
</h1>
|
||||||
|
<br />
|
||||||
|
Source-File Level: {props.level} / {maxSourceFileLevel}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
{bitNode.info}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<button
|
||||||
|
className="std-button"
|
||||||
|
onClick={() => {
|
||||||
|
props.enter(props.flume, props.destroyedBitNode, props.n);
|
||||||
|
removePopup(props.popupId);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Enter BN{props.n}.{newLevel}
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
1
src/CinematicText.d.ts
vendored
Normal file
1
src/CinematicText.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare let cinematicTextFlag: boolean;
|
31
src/Company/ui/QuitJobPopup.tsx
Normal file
31
src/Company/ui/QuitJobPopup.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Company } from "../Company";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
locName: string;
|
||||||
|
company: Company;
|
||||||
|
player: IPlayer;
|
||||||
|
onQuit: () => void;
|
||||||
|
popupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function QuitJobPopup(props: IProps): React.ReactElement {
|
||||||
|
function quit(): void {
|
||||||
|
props.player.quitJob(props.locName);
|
||||||
|
props.onQuit();
|
||||||
|
removePopup(props.popupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
Would you like to quit your job at {props.company.name}?
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<button autoFocus={true} className="std-button" onClick={quit}>
|
||||||
|
Quit
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import { ICorporation } from "./ICorporation";
|
import { ICorporation } from "./ICorporation";
|
||||||
import { IIndustry } from "./IIndustry";
|
import { IIndustry } from "./IIndustry";
|
||||||
import { IndustryStartingCosts } from "./IndustryData";
|
import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
|
||||||
import { Industry } from "./Industry";
|
import { Industry } from "./Industry";
|
||||||
import { CorporationConstants } from "./data/Constants";
|
import { CorporationConstants } from "./data/Constants";
|
||||||
import { OfficeSpace } from "./OfficeSpace";
|
import { OfficeSpace } from "./OfficeSpace";
|
||||||
@ -13,7 +13,6 @@ import { Cities } from "../Locations/Cities";
|
|||||||
import { EmployeePositions } from "./EmployeePositions";
|
import { EmployeePositions } from "./EmployeePositions";
|
||||||
import { Employee } from "./Employee";
|
import { Employee } from "./Employee";
|
||||||
import { IndustryUpgrades } from "./IndustryUpgrades";
|
import { IndustryUpgrades } from "./IndustryUpgrades";
|
||||||
import { IndustryResearchTrees } from "./IndustryData";
|
|
||||||
import { ResearchMap } from "./ResearchMap";
|
import { ResearchMap } from "./ResearchMap";
|
||||||
|
|
||||||
export function NewIndustry(corporation: ICorporation, industry: string, name: string): void {
|
export function NewIndustry(corporation: ICorporation, industry: string, name: string): void {
|
||||||
|
@ -20,8 +20,7 @@ function ExpandButton(props: IExpandButtonProps): React.ReactElement {
|
|||||||
const allIndustries = Object.keys(Industries).sort();
|
const allIndustries = Object.keys(Industries).sort();
|
||||||
const possibleIndustries = allIndustries
|
const possibleIndustries = allIndustries
|
||||||
.filter(
|
.filter(
|
||||||
(industryType: string) =>
|
(industryType: string) => props.corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
|
||||||
props.corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
|
|
||||||
)
|
)
|
||||||
.sort();
|
.sort();
|
||||||
if (possibleIndustries.length === 0) return <></>;
|
if (possibleIndustries.length === 0) return <></>;
|
||||||
|
@ -18,7 +18,6 @@ import { ProductMarketTaPopup } from "./ProductMarketTaPopup";
|
|||||||
import { SmartSupplyPopup } from "./SmartSupplyPopup";
|
import { SmartSupplyPopup } from "./SmartSupplyPopup";
|
||||||
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
|
||||||
import { createPopup } from "../../ui/React/createPopup";
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
|
|
||||||
import { isString } from "../../../utils/helpers/isString";
|
import { isString } from "../../../utils/helpers/isString";
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
|
||||||
import { removePopup } from "../../ui/React/createPopup";
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
import { Product } from "../Product";
|
import { Product } from "../Product";
|
||||||
import { LimitProductProduction } from "../Actions";
|
import { LimitProductProduction } from "../Actions";
|
||||||
|
@ -2,7 +2,6 @@ import React, { useState } from "react";
|
|||||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||||
import { removePopup } from "../../ui/React/createPopup";
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
import { Industries } from "../IndustryData";
|
import { Industries } from "../IndustryData";
|
||||||
import { Product } from "../Product";
|
|
||||||
import { ICorporation } from "../ICorporation";
|
import { ICorporation } from "../ICorporation";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { IIndustry } from "../IIndustry";
|
||||||
import { MakeProduct } from "../Actions";
|
import { MakeProduct } from "../Actions";
|
||||||
|
@ -3,7 +3,6 @@ import { dialogBoxCreate } from "../../../utils/DialogBox";
|
|||||||
import { removePopup } from "../../ui/React/createPopup";
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
import { IndustryResearchTrees } from "../IndustryData";
|
import { IndustryResearchTrees } from "../IndustryData";
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../data/Constants";
|
||||||
import { ResearchMap } from "../ResearchMap";
|
|
||||||
import { Treant } from "treant-js";
|
import { Treant } from "treant-js";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { IIndustry } from "../IIndustry";
|
||||||
import { Research } from "../Actions";
|
import { Research } from "../Actions";
|
||||||
@ -50,9 +49,6 @@ export function ResearchPopup(props: IProps): React.ReactElement {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the Research object
|
|
||||||
const research = ResearchMap[allResearch[i]];
|
|
||||||
|
|
||||||
// Get the DOM Element to add a click listener to it
|
// Get the DOM Element to add a click listener to it
|
||||||
const sanitizedName = allResearch[i].replace(/\s/g, "");
|
const sanitizedName = allResearch[i].replace(/\s/g, "");
|
||||||
const div = document.getElementById(sanitizedName + "-corp-research-click-listener");
|
const div = document.getElementById(sanitizedName + "-corp-research-click-listener");
|
||||||
|
320
src/DevMenu.tsx
320
src/DevMenu.tsx
@ -4,7 +4,6 @@ import { generateContract, generateRandomContract, generateRandomContractOnHome
|
|||||||
import { Companies } from "./Company/Companies";
|
import { Companies } from "./Company/Companies";
|
||||||
import { Programs } from "./Programs/Programs";
|
import { Programs } from "./Programs/Programs";
|
||||||
import { Factions } from "./Faction/Factions";
|
import { Factions } from "./Faction/Factions";
|
||||||
import { Player } from "./Player";
|
|
||||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||||
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
|
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
|
||||||
import { AllServers } from "./Server/AllServers";
|
import { AllServers } from "./Server/AllServers";
|
||||||
@ -18,14 +17,9 @@ import { IEngine } from "./IEngine";
|
|||||||
import { saveObject } from "./SaveObject";
|
import { saveObject } from "./SaveObject";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||||
import { createElement } from "../utils/uiHelpers/createElement";
|
|
||||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
|
||||||
import { Money } from "./ui/React/Money";
|
import { Money } from "./ui/React/Money";
|
||||||
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import ReactDOM from "react-dom";
|
|
||||||
|
|
||||||
const Component = React.Component;
|
|
||||||
|
|
||||||
// Update as additional BitNodes get implemented
|
// Update as additional BitNodes get implemented
|
||||||
const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
||||||
@ -41,7 +35,7 @@ interface IValueAdjusterProps {
|
|||||||
reset: () => void;
|
reset: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ValueAdjusterComponent(props: IValueAdjusterProps) {
|
function ValueAdjusterComponent(props: IValueAdjusterProps): React.ReactElement {
|
||||||
const [value, setValue] = useState(0);
|
const [value, setValue] = useState(0);
|
||||||
|
|
||||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
@ -120,28 +114,28 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
function addMoney(n: number) {
|
function addMoney(n: number) {
|
||||||
return function () {
|
return function () {
|
||||||
Player.gainMoney(n);
|
props.player.gainMoney(n);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function upgradeRam() {
|
function upgradeRam(): void {
|
||||||
Player.getHomeComputer().maxRam *= 2;
|
props.player.getHomeComputer().maxRam *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
function quickB1tFlum3() {
|
function quickB1tFlum3(): void {
|
||||||
hackWorldDaemon(Player.bitNodeN, true, true);
|
hackWorldDaemon(props.player.bitNodeN, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function b1tflum3() {
|
function b1tflum3(): void {
|
||||||
hackWorldDaemon(Player.bitNodeN, true);
|
hackWorldDaemon(props.player.bitNodeN, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function quickHackW0r1dD43m0n() {
|
function quickHackW0r1dD43m0n(): void {
|
||||||
hackWorldDaemon(Player.bitNodeN, false, true);
|
hackWorldDaemon(props.player.bitNodeN, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hackW0r1dD43m0n() {
|
function hackW0r1dD43m0n(): void {
|
||||||
hackWorldDaemon(Player.bitNodeN);
|
hackWorldDaemon(props.player.bitNodeN);
|
||||||
}
|
}
|
||||||
|
|
||||||
function modifyExp(stat: string, modifier: number) {
|
function modifyExp(stat: string, modifier: number) {
|
||||||
@ -149,127 +143,127 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
switch (stat) {
|
switch (stat) {
|
||||||
case "hacking":
|
case "hacking":
|
||||||
if (exp) {
|
if (exp) {
|
||||||
Player.gainHackingExp(exp * modifier);
|
props.player.gainHackingExp(exp * modifier);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "strength":
|
case "strength":
|
||||||
if (exp) {
|
if (exp) {
|
||||||
Player.gainStrengthExp(exp * modifier);
|
props.player.gainStrengthExp(exp * modifier);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "defense":
|
case "defense":
|
||||||
if (exp) {
|
if (exp) {
|
||||||
Player.gainDefenseExp(exp * modifier);
|
props.player.gainDefenseExp(exp * modifier);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "dexterity":
|
case "dexterity":
|
||||||
if (exp) {
|
if (exp) {
|
||||||
Player.gainDexterityExp(exp * modifier);
|
props.player.gainDexterityExp(exp * modifier);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "agility":
|
case "agility":
|
||||||
if (exp) {
|
if (exp) {
|
||||||
Player.gainAgilityExp(exp * modifier);
|
props.player.gainAgilityExp(exp * modifier);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "charisma":
|
case "charisma":
|
||||||
if (exp) {
|
if (exp) {
|
||||||
Player.gainCharismaExp(exp * modifier);
|
props.player.gainCharismaExp(exp * modifier);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "intelligence":
|
case "intelligence":
|
||||||
if (exp) {
|
if (exp) {
|
||||||
Player.gainIntelligenceExp(exp * modifier);
|
props.player.gainIntelligenceExp(exp * modifier);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Player.updateSkillLevels();
|
props.player.updateSkillLevels();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function modifyKarma(modifier: number) {
|
function modifyKarma(modifier: number) {
|
||||||
return function (amt: number) {
|
return function (amt: number) {
|
||||||
Player.karma += amt * modifier;
|
props.player.karma += amt * modifier;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function tonsOfExp() {
|
function tonsOfExp(): void {
|
||||||
Player.gainHackingExp(tonsPP);
|
props.player.gainHackingExp(tonsPP);
|
||||||
Player.gainStrengthExp(tonsPP);
|
props.player.gainStrengthExp(tonsPP);
|
||||||
Player.gainDefenseExp(tonsPP);
|
props.player.gainDefenseExp(tonsPP);
|
||||||
Player.gainDexterityExp(tonsPP);
|
props.player.gainDexterityExp(tonsPP);
|
||||||
Player.gainAgilityExp(tonsPP);
|
props.player.gainAgilityExp(tonsPP);
|
||||||
Player.gainCharismaExp(tonsPP);
|
props.player.gainCharismaExp(tonsPP);
|
||||||
Player.gainIntelligenceExp(tonsPP);
|
props.player.gainIntelligenceExp(tonsPP);
|
||||||
Player.updateSkillLevels();
|
props.player.updateSkillLevels();
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetAllExp() {
|
function resetAllExp(): void {
|
||||||
Player.hacking_exp = 0;
|
props.player.hacking_exp = 0;
|
||||||
Player.strength_exp = 0;
|
props.player.strength_exp = 0;
|
||||||
Player.defense_exp = 0;
|
props.player.defense_exp = 0;
|
||||||
Player.dexterity_exp = 0;
|
props.player.dexterity_exp = 0;
|
||||||
Player.agility_exp = 0;
|
props.player.agility_exp = 0;
|
||||||
Player.charisma_exp = 0;
|
props.player.charisma_exp = 0;
|
||||||
Player.intelligence_exp = 0;
|
props.player.intelligence_exp = 0;
|
||||||
Player.updateSkillLevels();
|
props.player.updateSkillLevels();
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetExperience(stat: string): () => void {
|
function resetExperience(stat: string): () => void {
|
||||||
return function () {
|
return function () {
|
||||||
switch (stat) {
|
switch (stat) {
|
||||||
case "hacking":
|
case "hacking":
|
||||||
Player.hacking_exp = 0;
|
props.player.hacking_exp = 0;
|
||||||
break;
|
break;
|
||||||
case "strength":
|
case "strength":
|
||||||
Player.strength_exp = 0;
|
props.player.strength_exp = 0;
|
||||||
break;
|
break;
|
||||||
case "defense":
|
case "defense":
|
||||||
Player.defense_exp = 0;
|
props.player.defense_exp = 0;
|
||||||
break;
|
break;
|
||||||
case "dexterity":
|
case "dexterity":
|
||||||
Player.dexterity_exp = 0;
|
props.player.dexterity_exp = 0;
|
||||||
break;
|
break;
|
||||||
case "agility":
|
case "agility":
|
||||||
Player.agility_exp = 0;
|
props.player.agility_exp = 0;
|
||||||
break;
|
break;
|
||||||
case "charisma":
|
case "charisma":
|
||||||
Player.charisma_exp = 0;
|
props.player.charisma_exp = 0;
|
||||||
break;
|
break;
|
||||||
case "intelligence":
|
case "intelligence":
|
||||||
Player.intelligence_exp = 0;
|
props.player.intelligence_exp = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Player.updateSkillLevels();
|
props.player.updateSkillLevels();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetKarma() {
|
function resetKarma(): () => void {
|
||||||
return function () {
|
return function () {
|
||||||
Player.karma = 0;
|
props.player.karma = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableIntelligence() {
|
function enableIntelligence(): void {
|
||||||
if (Player.intelligence === 0) {
|
if (props.player.intelligence === 0) {
|
||||||
Player.intelligence = 1;
|
props.player.intelligence = 1;
|
||||||
Player.updateSkillLevels();
|
props.player.updateSkillLevels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableIntelligence() {
|
function disableIntelligence(): void {
|
||||||
Player.intelligence_exp = 0;
|
props.player.intelligence_exp = 0;
|
||||||
Player.intelligence = 0;
|
props.player.intelligence = 0;
|
||||||
Player.updateSkillLevels();
|
props.player.updateSkillLevels();
|
||||||
}
|
}
|
||||||
|
|
||||||
function receiveInvite() {
|
function receiveInvite(): void {
|
||||||
Player.receiveInvite(faction);
|
props.player.receiveInvite(faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
function receiveAllInvites() {
|
function receiveAllInvites(): void {
|
||||||
for (const i in Factions) {
|
for (const i in Factions) {
|
||||||
Player.receiveInvite(Factions[i].name);
|
props.player.receiveInvite(Factions[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +276,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetFactionRep() {
|
function resetFactionRep(): void {
|
||||||
const fac = Factions[faction];
|
const fac = Factions[faction];
|
||||||
if (fac != null) {
|
if (fac != null) {
|
||||||
fac.playerReputation = 0;
|
fac.playerReputation = 0;
|
||||||
@ -298,63 +292,63 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetFactionFavor() {
|
function resetFactionFavor(): void {
|
||||||
const fac = Factions[faction];
|
const fac = Factions[faction];
|
||||||
if (fac != null) {
|
if (fac != null) {
|
||||||
fac.favor = 0;
|
fac.favor = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tonsOfRep() {
|
function tonsOfRep(): void {
|
||||||
for (const i in Factions) {
|
for (const i in Factions) {
|
||||||
Factions[i].playerReputation = tonsPP;
|
Factions[i].playerReputation = tonsPP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetAllRep() {
|
function resetAllRep(): void {
|
||||||
for (const i in Factions) {
|
for (const i in Factions) {
|
||||||
Factions[i].playerReputation = 0;
|
Factions[i].playerReputation = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tonsOfFactionFavor() {
|
function tonsOfFactionFavor(): void {
|
||||||
for (const i in Factions) {
|
for (const i in Factions) {
|
||||||
Factions[i].favor = tonsPP;
|
Factions[i].favor = tonsPP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetAllFactionFavor() {
|
function resetAllFactionFavor(): void {
|
||||||
for (const i in Factions) {
|
for (const i in Factions) {
|
||||||
Factions[i].favor = 0;
|
Factions[i].favor = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function queueAug() {
|
function queueAug(): void {
|
||||||
Player.queueAugmentation(augmentation);
|
props.player.queueAugmentation(augmentation);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queueAllAugs() {
|
function queueAllAugs(): void {
|
||||||
for (const i in AugmentationNames) {
|
for (const i in AugmentationNames) {
|
||||||
const augName = AugmentationNames[i];
|
const augName = AugmentationNames[i];
|
||||||
Player.queueAugmentation(augName);
|
props.player.queueAugmentation(augName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSF(sfN: number, sfLvl: number) {
|
function setSF(sfN: number, sfLvl: number) {
|
||||||
return function () {
|
return function () {
|
||||||
if (sfLvl === 0) {
|
if (sfLvl === 0) {
|
||||||
Player.sourceFiles = Player.sourceFiles.filter((sf) => sf.n !== sfN);
|
props.player.sourceFiles = props.player.sourceFiles.filter((sf) => sf.n !== sfN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Player.sourceFiles.some((sf) => sf.n === sfN)) {
|
if (!props.player.sourceFiles.some((sf) => sf.n === sfN)) {
|
||||||
Player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl));
|
props.player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < Player.sourceFiles.length; i++) {
|
for (let i = 0; i < props.player.sourceFiles.length; i++) {
|
||||||
if (Player.sourceFiles[i].n === sfN) {
|
if (props.player.sourceFiles[i].n === sfN) {
|
||||||
Player.sourceFiles[i].lvl = sfLvl;
|
props.player.sourceFiles[i].lvl = sfLvl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -368,25 +362,25 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearExploits() {
|
function clearExploits(): void {
|
||||||
Player.exploits = [];
|
props.player.exploits = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProgram() {
|
function addProgram(): void {
|
||||||
if (!Player.hasProgram(program)) {
|
if (!props.player.hasProgram(program)) {
|
||||||
Player.getHomeComputer().programs.push(program);
|
props.player.getHomeComputer().programs.push(program);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAllPrograms() {
|
function addAllPrograms(): void {
|
||||||
for (const i in Programs) {
|
for (const i in Programs) {
|
||||||
if (!Player.hasProgram(Programs[i].name)) {
|
if (!props.player.hasProgram(Programs[i].name)) {
|
||||||
Player.getHomeComputer().programs.push(Programs[i].name);
|
props.player.getHomeComputer().programs.push(Programs[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function rootServer() {
|
function rootServer(): void {
|
||||||
const s = GetServerByHostname(server);
|
const s = GetServerByHostname(server);
|
||||||
if (s === null) return;
|
if (s === null) return;
|
||||||
if (s instanceof HacknetServer) return;
|
if (s instanceof HacknetServer) return;
|
||||||
@ -399,7 +393,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
s.openPortCount = 5;
|
s.openPortCount = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
function rootAllServers() {
|
function rootAllServers(): void {
|
||||||
for (const i in AllServers) {
|
for (const i in AllServers) {
|
||||||
const s = AllServers[i];
|
const s = AllServers[i];
|
||||||
if (s instanceof HacknetServer) return;
|
if (s instanceof HacknetServer) return;
|
||||||
@ -413,14 +407,14 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function minSecurity() {
|
function minSecurity(): void {
|
||||||
const s = GetServerByHostname(server);
|
const s = GetServerByHostname(server);
|
||||||
if (s === null) return;
|
if (s === null) return;
|
||||||
if (s instanceof HacknetServer) return;
|
if (s instanceof HacknetServer) return;
|
||||||
s.hackDifficulty = s.minDifficulty;
|
s.hackDifficulty = s.minDifficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
function minAllSecurity() {
|
function minAllSecurity(): void {
|
||||||
for (const i in AllServers) {
|
for (const i in AllServers) {
|
||||||
const server = AllServers[i];
|
const server = AllServers[i];
|
||||||
if (server instanceof HacknetServer) continue;
|
if (server instanceof HacknetServer) continue;
|
||||||
@ -428,14 +422,14 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function maxMoney() {
|
function maxMoney(): void {
|
||||||
const s = GetServerByHostname(server);
|
const s = GetServerByHostname(server);
|
||||||
if (s === null) return;
|
if (s === null) return;
|
||||||
if (s instanceof HacknetServer) return;
|
if (s instanceof HacknetServer) return;
|
||||||
s.moneyAvailable = s.moneyMax;
|
s.moneyAvailable = s.moneyMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
function maxAllMoney() {
|
function maxAllMoney(): void {
|
||||||
for (const i in AllServers) {
|
for (const i in AllServers) {
|
||||||
const server = AllServers[i];
|
const server = AllServers[i];
|
||||||
if (server instanceof HacknetServer) continue;
|
if (server instanceof HacknetServer) continue;
|
||||||
@ -495,98 +489,98 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
function modifyBladeburnerRank(modify: number): (x: number) => void {
|
function modifyBladeburnerRank(modify: number): (x: number) => void {
|
||||||
return function (rank: number): void {
|
return function (rank: number): void {
|
||||||
if (Player.bladeburner) {
|
if (props.player.bladeburner) {
|
||||||
Player.bladeburner.changeRank(Player, rank * modify);
|
props.player.bladeburner.changeRank(props.player, rank * modify);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetBladeburnerRank(): void {
|
function resetBladeburnerRank(): void {
|
||||||
Player.bladeburner.rank = 0;
|
props.player.bladeburner.rank = 0;
|
||||||
Player.bladeburner.maxRank = 0;
|
props.player.bladeburner.maxRank = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTonsBladeburnerRank(): void {
|
function addTonsBladeburnerRank(): void {
|
||||||
if (Player.bladeburner) {
|
if (props.player.bladeburner) {
|
||||||
Player.bladeburner.changeRank(Player, tonsP);
|
props.player.bladeburner.changeRank(props.player, tonsP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function modifyBladeburnerCycles(modify: number): (x: number) => void {
|
function modifyBladeburnerCycles(modify: number): (x: number) => void {
|
||||||
return function (cycles: number): void {
|
return function (cycles: number): void {
|
||||||
if (Player.bladeburner) {
|
if (props.player.bladeburner) {
|
||||||
Player.bladeburner.storedCycles += cycles * modify;
|
props.player.bladeburner.storedCycles += cycles * modify;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetBladeburnerCycles(): void {
|
function resetBladeburnerCycles(): void {
|
||||||
if (Player.bladeburner) {
|
if (props.player.bladeburner) {
|
||||||
Player.bladeburner.storedCycles = 0;
|
props.player.bladeburner.storedCycles = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTonsBladeburnerCycles(): void {
|
function addTonsBladeburnerCycles(): void {
|
||||||
if (Player.bladeburner) {
|
if (props.player.bladeburner) {
|
||||||
Player.bladeburner.storedCycles += tonsP;
|
props.player.bladeburner.storedCycles += tonsP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTonsGangCycles(): void {
|
function addTonsGangCycles(): void {
|
||||||
if (Player.gang) {
|
if (props.player.gang) {
|
||||||
Player.gang.storedCycles = tonsP;
|
props.player.gang.storedCycles = tonsP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function modifyGangCycles(modify: number): (x: number) => void {
|
function modifyGangCycles(modify: number): (x: number) => void {
|
||||||
return function (cycles: number): void {
|
return function (cycles: number): void {
|
||||||
if (Player.gang) {
|
if (props.player.gang) {
|
||||||
Player.gang.storedCycles += cycles * modify;
|
props.player.gang.storedCycles += cycles * modify;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetGangCycles(): void {
|
function resetGangCycles(): void {
|
||||||
if (Player.gang) {
|
if (props.player.gang) {
|
||||||
Player.gang.storedCycles = 0;
|
props.player.gang.storedCycles = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTonsCorporationFunds(): void {
|
function addTonsCorporationFunds(): void {
|
||||||
if (Player.corporation) {
|
if (props.player.corporation) {
|
||||||
Player.corporation.funds = Player.corporation.funds.plus(1e99);
|
props.player.corporation.funds = props.player.corporation.funds.plus(1e99);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetCorporationFunds(): void {
|
function resetCorporationFunds(): void {
|
||||||
if (Player.corporation) {
|
if (props.player.corporation) {
|
||||||
Player.corporation.funds = Player.corporation.funds.minus(Player.corporation.funds);
|
props.player.corporation.funds = props.player.corporation.funds.minus(props.player.corporation.funds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTonsCorporationCycles() {
|
function addTonsCorporationCycles(): void {
|
||||||
if (Player.corporation) {
|
if (props.player.corporation) {
|
||||||
Player.corporation.storedCycles = tonsP;
|
props.player.corporation.storedCycles = tonsP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function modifyCorporationCycles(modify: number): (x: number) => void {
|
function modifyCorporationCycles(modify: number): (x: number) => void {
|
||||||
return function (cycles: number): void {
|
return function (cycles: number): void {
|
||||||
if (Player.corporation) {
|
if (props.player.corporation) {
|
||||||
Player.corporation.storedCycles += cycles * modify;
|
props.player.corporation.storedCycles += cycles * modify;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetCorporationCycles() {
|
function resetCorporationCycles(): void {
|
||||||
if (Player.corporation) {
|
if (props.player.corporation) {
|
||||||
Player.corporation.storedCycles = 0;
|
props.player.corporation.storedCycles = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function finishCorporationProducts() {
|
function finishCorporationProducts(): void {
|
||||||
if (!Player.corporation) return;
|
if (!props.player.corporation) return;
|
||||||
Player.corporation.divisions.forEach((div) => {
|
props.player.corporation.divisions.forEach((div) => {
|
||||||
Object.keys(div.products).forEach((prod) => {
|
Object.keys(div.products).forEach((prod) => {
|
||||||
const product = div.products[prod];
|
const product = div.products[prod];
|
||||||
if (product === undefined) throw new Error("Impossible product undefined");
|
if (product === undefined) throw new Error("Impossible product undefined");
|
||||||
@ -595,29 +589,29 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCorporationResearch() {
|
function addCorporationResearch(): void {
|
||||||
if (!Player.corporation) return;
|
if (!props.player.corporation) return;
|
||||||
Player.corporation.divisions.forEach((div) => {
|
props.player.corporation.divisions.forEach((div) => {
|
||||||
div.sciResearch.qty += 1e10;
|
div.sciResearch.qty += 1e10;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function specificContract() {
|
function specificContract(): void {
|
||||||
generateContract({
|
generateContract({
|
||||||
problemType: codingcontract,
|
problemType: codingcontract,
|
||||||
server: "home",
|
server: "home",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function processStocks(sub: (arg0: Stock) => void) {
|
function processStocks(sub: (arg0: Stock) => void): void {
|
||||||
const inputSymbols = stockSymbol.replace(/\s/g, "");
|
const inputSymbols = stockSymbol.replace(/\s/g, "");
|
||||||
|
|
||||||
let match = function (symbol: string) {
|
let match: (symbol: string) => boolean = (): boolean => {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (inputSymbols !== "" && inputSymbols !== "all") {
|
if (inputSymbols !== "" && inputSymbols !== "all") {
|
||||||
match = function (symbol: string) {
|
match = function (symbol: string): boolean {
|
||||||
return inputSymbols.split(",").includes(symbol);
|
return inputSymbols.split(",").includes(symbol);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -632,7 +626,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSetStockPrice() {
|
function doSetStockPrice(): void {
|
||||||
if (!isNaN(stockPrice)) {
|
if (!isNaN(stockPrice)) {
|
||||||
processStocks((stock: Stock) => {
|
processStocks((stock: Stock) => {
|
||||||
stock.price = stockPrice;
|
stock.price = stockPrice;
|
||||||
@ -640,8 +634,8 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function viewStockCaps() {
|
function viewStockCaps(): void {
|
||||||
let stocks: JSX.Element[] = [];
|
const stocks: JSX.Element[] = [];
|
||||||
processStocks((stock: Stock) => {
|
processStocks((stock: Stock) => {
|
||||||
stocks.push(
|
stocks.push(
|
||||||
<tr key={stock.symbol}>
|
<tr key={stock.symbol}>
|
||||||
@ -665,40 +659,40 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleeveMaxAllShock() {
|
function sleeveMaxAllShock(): void {
|
||||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||||
Player.sleeves[i].shock = 0;
|
props.player.sleeves[i].shock = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleeveClearAllShock() {
|
function sleeveClearAllShock(): void {
|
||||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||||
Player.sleeves[i].shock = 100;
|
props.player.sleeves[i].shock = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleeveSyncMaxAll() {
|
function sleeveSyncMaxAll(): void {
|
||||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||||
Player.sleeves[i].sync = 100;
|
props.player.sleeves[i].sync = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleeveSyncClearAll() {
|
function sleeveSyncClearAll(): void {
|
||||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||||
Player.sleeves[i].sync = 0;
|
props.player.sleeves[i].sync = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function timeskip(time: number) {
|
function timeskip(time: number) {
|
||||||
return () => {
|
return () => {
|
||||||
Player.lastUpdate -= time;
|
props.player.lastUpdate -= time;
|
||||||
props.engine._lastUpdate -= time;
|
props.engine._lastUpdate -= time;
|
||||||
saveObject.saveGame(props.engine.indexedDb);
|
saveObject.saveGame(props.engine.indexedDb);
|
||||||
setTimeout(() => location.reload(), 1000);
|
setTimeout(() => location.reload(), 1000);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let factions = [];
|
const factions = [];
|
||||||
for (const i in Factions) {
|
for (const i in Factions) {
|
||||||
factions.push(
|
factions.push(
|
||||||
<option key={Factions[i].name} value={Factions[i].name}>
|
<option key={Factions[i].name} value={Factions[i].name}>
|
||||||
@ -707,7 +701,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let augs = [];
|
const augs = [];
|
||||||
for (const i in AugmentationNames) {
|
for (const i in AugmentationNames) {
|
||||||
augs.push(
|
augs.push(
|
||||||
<option key={AugmentationNames[i]} value={AugmentationNames[i]}>
|
<option key={AugmentationNames[i]} value={AugmentationNames[i]}>
|
||||||
@ -716,7 +710,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let programs = [];
|
const programs = [];
|
||||||
for (const i in Programs) {
|
for (const i in Programs) {
|
||||||
programs.push(
|
programs.push(
|
||||||
<option key={Programs[i].name} value={Programs[i].name}>
|
<option key={Programs[i].name} value={Programs[i].name}>
|
||||||
@ -725,7 +719,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let servers = [];
|
const servers = [];
|
||||||
for (const i in AllServers) {
|
for (const i in AllServers) {
|
||||||
const hn = AllServers[i].hostname;
|
const hn = AllServers[i].hostname;
|
||||||
servers.push(
|
servers.push(
|
||||||
@ -735,7 +729,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let companies = [];
|
const companies = [];
|
||||||
for (const c in Companies) {
|
for (const c in Companies) {
|
||||||
const name = Companies[c].name;
|
const name = Companies[c].name;
|
||||||
companies.push(
|
companies.push(
|
||||||
@ -1310,7 +1304,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{Player.bladeburner instanceof Bladeburner && (
|
{props.player.bladeburner instanceof Bladeburner && (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@ -1360,7 +1354,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{Player.inGang() && (
|
{props.player.inGang() && (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@ -1392,7 +1386,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{Player.hasCorporation() && (
|
{props.player.hasCorporation() && (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@ -1485,7 +1479,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{Player.hasWseAccount && (
|
{props.player.hasWseAccount && (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@ -1540,7 +1534,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{Player.sleeves.length > 0 && (
|
{props.player.sleeves.length > 0 && (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
|
1
src/Faction/FactionHelpers.d.ts
vendored
1
src/Faction/FactionHelpers.d.ts
vendored
@ -3,7 +3,6 @@ import { Faction } from "../Faction/Faction";
|
|||||||
|
|
||||||
export declare function getNextNeurofluxLevel(): number;
|
export declare function getNextNeurofluxLevel(): number;
|
||||||
export declare function hasAugmentationPrereqs(aug: Augmentation): boolean;
|
export declare function hasAugmentationPrereqs(aug: Augmentation): boolean;
|
||||||
export declare function purchaseAugmentationBoxCreate(aug: Augmentation, fac: Faction): void;
|
|
||||||
export declare function purchaseAugmentation(aug: Augmentation, fac: Faction, sing?: boolean): void;
|
export declare function purchaseAugmentation(aug: Augmentation, fac: Faction, sing?: boolean): void;
|
||||||
export declare function displayFactionContent(factionName: string, initiallyOnAugmentationsPage: boolean = false);
|
export declare function displayFactionContent(factionName: string, initiallyOnAugmentationsPage: boolean = false);
|
||||||
export declare function joinFaction(faction: Faction): void;
|
export declare function joinFaction(faction: Faction): void;
|
||||||
|
@ -4,7 +4,6 @@ import ReactDOM from "react-dom";
|
|||||||
import { FactionRoot } from "./ui/Root";
|
import { FactionRoot } from "./ui/Root";
|
||||||
|
|
||||||
import { Augmentations } from "../Augmentation/Augmentations";
|
import { Augmentations } from "../Augmentation/Augmentations";
|
||||||
import { isRepeatableAug } from "../Augmentation/AugmentationHelpers";
|
|
||||||
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
||||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
@ -22,21 +21,20 @@ import {
|
|||||||
} from "../PersonObjects/formulas/reputation";
|
} from "../PersonObjects/formulas/reputation";
|
||||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
||||||
|
|
||||||
import { Page, routing } from "../ui/navigationTracking";
|
|
||||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||||
import { factionInvitationBoxCreate } from "../../utils/FactionInvitationBox";
|
import { createPopup } from "../ui/React/createPopup";
|
||||||
import { Money } from "../ui/React/Money";
|
import { InvitationPopup } from "./ui/InvitationPopup";
|
||||||
import { yesNoBoxCreate, yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose } from "../../utils/YesNoBox";
|
|
||||||
|
|
||||||
export function inviteToFaction(faction) {
|
export function inviteToFaction(faction) {
|
||||||
if (Settings.SuppressFactionInvites) {
|
|
||||||
faction.alreadyInvited = true;
|
|
||||||
Player.factionInvitations.push(faction.name);
|
Player.factionInvitations.push(faction.name);
|
||||||
if (routing.isOn(Page.Factions)) {
|
faction.alreadyInvited = true;
|
||||||
Engine.loadFactionsContent();
|
if (!Settings.SuppressFactionInvites) {
|
||||||
}
|
const popupId = "faction-invitation";
|
||||||
} else {
|
createPopup(popupId, InvitationPopup, {
|
||||||
factionInvitationBoxCreate(faction);
|
player: Player,
|
||||||
|
faction: faction,
|
||||||
|
popupId: popupId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,44 +88,6 @@ export function displayFactionContent(factionName, initiallyOnAugmentationsPage
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purchaseAugmentationBoxCreate(aug, fac) {
|
|
||||||
const factionInfo = fac.getInfo();
|
|
||||||
|
|
||||||
const yesBtn = yesNoBoxGetYesButton();
|
|
||||||
yesBtn.innerHTML = "Purchase";
|
|
||||||
yesBtn.addEventListener("click", function () {
|
|
||||||
if (!isRepeatableAug(aug) && Player.hasAugmentation(aug)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
purchaseAugmentation(aug, fac);
|
|
||||||
yesNoBoxClose();
|
|
||||||
});
|
|
||||||
|
|
||||||
const noBtn = yesNoBoxGetNoButton();
|
|
||||||
noBtn.innerHTML = "Cancel";
|
|
||||||
noBtn.addEventListener("click", function () {
|
|
||||||
yesNoBoxClose();
|
|
||||||
});
|
|
||||||
|
|
||||||
let content = <div dangerouslySetInnerHTML={{ __html: aug.info }}></div>;
|
|
||||||
if (typeof aug.info !== "string") {
|
|
||||||
content = <div>{aug.info}</div>;
|
|
||||||
}
|
|
||||||
yesNoBoxCreate(
|
|
||||||
<>
|
|
||||||
<h2>{aug.name}</h2>
|
|
||||||
<br />
|
|
||||||
{content}
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
Would you like to purchase the {aug.name} Augmentation for
|
|
||||||
<Money money={aug.baseCost * factionInfo.augmentationPriceMult} />?
|
|
||||||
</>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns a boolean indicating whether the player has the prerequisites for the
|
//Returns a boolean indicating whether the player has the prerequisites for the
|
||||||
//specified Augmentation
|
//specified Augmentation
|
||||||
export function hasAugmentationPrereqs(aug) {
|
export function hasAugmentationPrereqs(aug) {
|
||||||
|
@ -123,8 +123,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
|||||||
render(): React.ReactNode {
|
render(): React.ReactNode {
|
||||||
const augs = this.getAugsSorted();
|
const augs = this.getAugsSorted();
|
||||||
const purchasable = augs.filter(
|
const purchasable = augs.filter(
|
||||||
(aug: string) =>
|
(aug: string) => aug === AugmentationNames.NeuroFluxGovernor ||
|
||||||
aug === AugmentationNames.NeuroFluxGovernor ||
|
|
||||||
(!this.props.p.augmentations.some((a) => a.name === aug) &&
|
(!this.props.p.augmentations.some((a) => a.name === aug) &&
|
||||||
!this.props.p.queuedAugmentations.some((a) => a.name === aug)),
|
!this.props.p.queuedAugmentations.some((a) => a.name === aug)),
|
||||||
);
|
);
|
||||||
|
40
src/Faction/ui/InvitationPopup.tsx
Normal file
40
src/Faction/ui/InvitationPopup.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { joinFaction } from "../../Faction/FactionHelpers";
|
||||||
|
import { Faction } from "../../Faction/Faction";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
player: IPlayer;
|
||||||
|
faction: Faction;
|
||||||
|
popupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function InvitationPopup(props: IProps): React.ReactElement {
|
||||||
|
function join(): void {
|
||||||
|
//Remove from invited factions
|
||||||
|
const i = props.player.factionInvitations.findIndex((facName) => facName === props.faction.name);
|
||||||
|
if (i === -1) {
|
||||||
|
console.error("Could not find faction in Player.factionInvitations");
|
||||||
|
}
|
||||||
|
joinFaction(props.faction);
|
||||||
|
removePopup(props.popupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>You have received a faction invitation.</h1>
|
||||||
|
<p>
|
||||||
|
Would you like to join {props.faction.name}? <br />
|
||||||
|
<br />
|
||||||
|
Warning: Joining this faction may prevent you from joining other factions during this run!
|
||||||
|
</p>
|
||||||
|
<button className="std-button" onClick={join}>
|
||||||
|
Join!
|
||||||
|
</button>
|
||||||
|
<button className="std-button" onClick={() => removePopup(props.popupId)}>
|
||||||
|
Decide later
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
49
src/Faction/ui/PurchaseAugmentationPopup.tsx
Normal file
49
src/Faction/ui/PurchaseAugmentationPopup.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||||
|
import { Faction } from "../../Faction/Faction";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { purchaseAugmentation } from "../FactionHelpers";
|
||||||
|
import { isRepeatableAug } from "../../Augmentation/AugmentationHelpers";
|
||||||
|
import { Money } from "../../ui/React/Money";
|
||||||
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
player: IPlayer;
|
||||||
|
faction: Faction;
|
||||||
|
aug: Augmentation;
|
||||||
|
popupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PurchaseAugmentationPopup(props: IProps): React.ReactElement {
|
||||||
|
const factionInfo = props.faction.getInfo();
|
||||||
|
|
||||||
|
function buy(): void {
|
||||||
|
if (!isRepeatableAug(props.aug) && props.player.hasAugmentation(props.aug)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
purchaseAugmentation(props.aug, props.faction);
|
||||||
|
removePopup(props.popupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2>{props.aug.name}</h2>
|
||||||
|
<br />
|
||||||
|
{props.aug.info}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
{props.aug.stats}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Would you like to purchase the {props.aug.name} Augmentation for
|
||||||
|
<Money money={props.aug.baseCost * factionInfo.augmentationPriceMult} />?
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<button autoFocus={true} className="std-button" onClick={buy}>
|
||||||
|
Purchase
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -4,12 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import {
|
import { getNextNeurofluxLevel, hasAugmentationPrereqs, purchaseAugmentation } from "../FactionHelpers";
|
||||||
getNextNeurofluxLevel,
|
import { PurchaseAugmentationPopup } from "./PurchaseAugmentationPopup";
|
||||||
hasAugmentationPrereqs,
|
|
||||||
purchaseAugmentation,
|
|
||||||
purchaseAugmentationBoxCreate,
|
|
||||||
} from "../FactionHelpers";
|
|
||||||
|
|
||||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||||
@ -19,6 +15,7 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
|||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { Reputation } from "../../ui/React/Reputation";
|
import { Reputation } from "../../ui/React/Reputation";
|
||||||
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
import { IMap } from "../../types";
|
import { IMap } from "../../types";
|
||||||
|
|
||||||
import { StdButton } from "../../ui/React/StdButton";
|
import { StdButton } from "../../ui/React/StdButton";
|
||||||
@ -31,15 +28,6 @@ type IProps = {
|
|||||||
rerender: () => void;
|
rerender: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const spanStyleMarkup = {
|
|
||||||
margin: "4px",
|
|
||||||
padding: "4px",
|
|
||||||
};
|
|
||||||
|
|
||||||
const inlineStyleMarkup = {
|
|
||||||
display: "inline-block",
|
|
||||||
};
|
|
||||||
|
|
||||||
export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
||||||
aug: Augmentation;
|
aug: Augmentation;
|
||||||
|
|
||||||
@ -63,7 +51,13 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
|||||||
|
|
||||||
handleClick(): void {
|
handleClick(): void {
|
||||||
if (!Settings.SuppressBuyAugmentationConfirmation) {
|
if (!Settings.SuppressBuyAugmentationConfirmation) {
|
||||||
purchaseAugmentationBoxCreate(this.aug, this.props.faction);
|
const popupId = "purchase-augmentation-popup";
|
||||||
|
createPopup(popupId, PurchaseAugmentationPopup, {
|
||||||
|
aug: this.aug,
|
||||||
|
faction: this.props.faction,
|
||||||
|
player: this.props.p,
|
||||||
|
popupId: popupId,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
purchaseAugmentation(this.aug, this.props.faction);
|
purchaseAugmentation(this.aug, this.props.faction);
|
||||||
}
|
}
|
||||||
@ -170,12 +164,19 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li>
|
<li key={this.aug.name}>
|
||||||
<span style={spanStyleMarkup}>
|
<span
|
||||||
|
style={{
|
||||||
|
margin: "4px",
|
||||||
|
padding: "4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<StdButton
|
<StdButton
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
style={inlineStyleMarkup}
|
style={{
|
||||||
|
display: "inline-block",
|
||||||
|
}}
|
||||||
text={btnTxt}
|
text={btnTxt}
|
||||||
tooltip={tooltip}
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
|
@ -2,10 +2,8 @@ import { Engine } from "./engine";
|
|||||||
import { Player } from "./Player";
|
import { Player } from "./Player";
|
||||||
import { Settings } from "./Settings/Settings";
|
import { Settings } from "./Settings/Settings";
|
||||||
|
|
||||||
import { initializeMainMenuLinks } from "./ui/MainMenu/Links";
|
|
||||||
import { LiteratureNames } from "./Literature/data/LiteratureNames";
|
import { LiteratureNames } from "./Literature/data/LiteratureNames";
|
||||||
|
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
|
||||||
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
||||||
import { createElement } from "../utils/uiHelpers/createElement";
|
import { createElement } from "../utils/uiHelpers/createElement";
|
||||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||||
|
@ -4,24 +4,12 @@
|
|||||||
*/
|
*/
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
|
|
||||||
import { CityName } from "./data/CityNames";
|
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { AddToAllServers, createUniqueRandomIp } from "../Server/AllServers";
|
import { AddToAllServers, createUniqueRandomIp } from "../Server/AllServers";
|
||||||
import { safetlyCreateUniqueServer } from "../Server/ServerHelpers";
|
import { safetlyCreateUniqueServer } from "../Server/ServerHelpers";
|
||||||
import { SpecialServerIps } from "../Server/SpecialServerIps";
|
import { SpecialServerIps } from "../Server/SpecialServerIps";
|
||||||
import { Settings } from "../Settings/Settings";
|
|
||||||
|
|
||||||
import { Money } from "../ui/React/Money";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||||
import { yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose, yesNoBoxCreate } from "../../utils/YesNoBox";
|
|
||||||
|
|
||||||
import { createElement } from "../../utils/uiHelpers/createElement";
|
|
||||||
import { createPopup } from "../../utils/uiHelpers/createPopup";
|
|
||||||
import { createPopupCloseButton } from "../../utils/uiHelpers/createPopupCloseButton";
|
|
||||||
import { removeElementById } from "../../utils/uiHelpers/removeElementById";
|
|
||||||
import * as React from "react";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to purchase a TOR router
|
* Attempt to purchase a TOR router
|
||||||
|
@ -23,8 +23,8 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
|||||||
import { StdButton } from "../../ui/React/StdButton";
|
import { StdButton } from "../../ui/React/StdButton";
|
||||||
import { Reputation } from "../../ui/React/Reputation";
|
import { Reputation } from "../../ui/React/Reputation";
|
||||||
import { Favor } from "../../ui/React/Favor";
|
import { Favor } from "../../ui/React/Favor";
|
||||||
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
import { yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose, yesNoBoxCreate } from "../../../utils/YesNoBox";
|
import { QuitJobPopup } from "../../Company/ui/QuitJobPopup";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
engine: IEngine;
|
engine: IEngine;
|
||||||
@ -246,27 +246,15 @@ export class CompanyLocation extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
quit(e: React.MouseEvent<HTMLElement>): void {
|
quit(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) return;
|
||||||
return;
|
const popupId = `quit-job-popup`;
|
||||||
}
|
createPopup(popupId, QuitJobPopup, {
|
||||||
|
locName: this.props.locName,
|
||||||
const yesBtn = yesNoBoxGetYesButton();
|
company: this.company,
|
||||||
const noBtn = yesNoBoxGetNoButton();
|
player: this.props.p,
|
||||||
if (yesBtn == null || noBtn == null) {
|
onQuit: () => this.checkIfEmployedHere(true),
|
||||||
return;
|
popupId: popupId,
|
||||||
}
|
|
||||||
yesBtn.innerHTML = "Quit job";
|
|
||||||
noBtn.innerHTML = "Cancel";
|
|
||||||
yesBtn.addEventListener("click", () => {
|
|
||||||
this.props.p.quitJob(this.props.locName);
|
|
||||||
this.checkIfEmployedHere(true);
|
|
||||||
yesNoBoxClose();
|
|
||||||
});
|
});
|
||||||
noBtn.addEventListener("click", () => {
|
|
||||||
yesNoBoxClose();
|
|
||||||
});
|
|
||||||
|
|
||||||
yesNoBoxCreate(<>Would you like to quit your job at {this.company.name}?</>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): React.ReactNode {
|
render(): React.ReactNode {
|
||||||
@ -421,6 +409,11 @@ export class CompanyLocation extends React.Component<IProps, IState> {
|
|||||||
{this.location.infiltrationData != null && (
|
{this.location.infiltrationData != null && (
|
||||||
<StdButton onClick={this.startInfiltration} style={this.btnStyle} text={"Infiltrate Company"} />
|
<StdButton onClick={this.startInfiltration} style={this.btnStyle} text={"Infiltrate Company"} />
|
||||||
)}
|
)}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -63,8 +63,7 @@ function ListWorldMap(props: IProps): React.ReactElement {
|
|||||||
.map((city: string) => (
|
.map((city: string) => (
|
||||||
<StdButton
|
<StdButton
|
||||||
key={city}
|
key={city}
|
||||||
onClick={() =>
|
onClick={() => createTravelPopup(props.p, city, () => props.travel(CityName[city as keyof typeof CityName]))
|
||||||
createTravelPopup(props.p, city, () => props.travel(CityName[city as keyof typeof CityName]))
|
|
||||||
}
|
}
|
||||||
style={{ display: "block" }}
|
style={{ display: "block" }}
|
||||||
text={`Travel to ${city}`}
|
text={`Travel to ${city}`}
|
||||||
|
1
src/Missions.d.ts
vendored
Normal file
1
src/Missions.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare let inMission: boolean;
|
@ -43,7 +43,6 @@ import {
|
|||||||
SetProductMarketTA1,
|
SetProductMarketTA1,
|
||||||
SetProductMarketTA2,
|
SetProductMarketTA2,
|
||||||
} from "./Corporation/Actions";
|
} from "./Corporation/Actions";
|
||||||
import { Reviver } from "../utils/JSONReviver";
|
|
||||||
import { CorporationUnlockUpgrades } from "./Corporation/data/CorporationUnlockUpgrades";
|
import { CorporationUnlockUpgrades } from "./Corporation/data/CorporationUnlockUpgrades";
|
||||||
import { CorporationUpgrades } from "./Corporation/data/CorporationUpgrades";
|
import { CorporationUpgrades } from "./Corporation/data/CorporationUpgrades";
|
||||||
import {
|
import {
|
||||||
@ -4523,12 +4522,12 @@ function NetscriptFunctions(workerScript) {
|
|||||||
},
|
},
|
||||||
unlockUpgrade: function (upgradeName) {
|
unlockUpgrade: function (upgradeName) {
|
||||||
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
|
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
|
||||||
if (upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'");
|
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||||
UnlockUpgrade(Player.corporation, upgrade);
|
UnlockUpgrade(Player.corporation, upgrade);
|
||||||
},
|
},
|
||||||
levelUpgrade: function (upgradeName) {
|
levelUpgrade: function (upgradeName) {
|
||||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
|
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
|
||||||
if (upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'");
|
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||||
LevelUpgrade(Player.corporation, upgrade);
|
LevelUpgrade(Player.corporation, upgrade);
|
||||||
},
|
},
|
||||||
issueDividends: function (percent) {
|
issueDividends: function (percent) {
|
||||||
|
@ -9,6 +9,7 @@ import { Sleeve } from "./Sleeve/Sleeve";
|
|||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
|
|
||||||
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
||||||
|
import { Augmentation } from "../Augmentation/Augmentation";
|
||||||
import { Company } from "../Company/Company";
|
import { Company } from "../Company/Company";
|
||||||
import { CompanyPosition } from "../Company/CompanyPosition";
|
import { CompanyPosition } from "../Company/CompanyPosition";
|
||||||
import { CityName } from "../Locations/data/CityNames";
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
@ -119,6 +120,9 @@ export interface IPlayer {
|
|||||||
bladeburner_analysis_mult: number;
|
bladeburner_analysis_mult: number;
|
||||||
bladeburner_success_chance_mult: number;
|
bladeburner_success_chance_mult: number;
|
||||||
|
|
||||||
|
workRepGained: number;
|
||||||
|
focus: boolean;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
applyForAgentJob(sing?: boolean): boolean | void;
|
applyForAgentJob(sing?: boolean): boolean | void;
|
||||||
applyForBusinessConsultantJob(sing?: boolean): boolean | void;
|
applyForBusinessConsultantJob(sing?: boolean): boolean | void;
|
||||||
@ -154,6 +158,7 @@ export interface IPlayer {
|
|||||||
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition;
|
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition;
|
||||||
getUpgradeHomeRamCost(): number;
|
getUpgradeHomeRamCost(): number;
|
||||||
gotoLocation(to: LocationName): boolean;
|
gotoLocation(to: LocationName): boolean;
|
||||||
|
hasAugmentation(aug: Augmentation): boolean;
|
||||||
hasCorporation(): boolean;
|
hasCorporation(): boolean;
|
||||||
hasGangWith(facName: string): boolean;
|
hasGangWith(facName: string): boolean;
|
||||||
hasTorRouter(): boolean;
|
hasTorRouter(): boolean;
|
||||||
@ -186,6 +191,7 @@ export interface IPlayer {
|
|||||||
startFactionFieldWork(faction: Faction): void;
|
startFactionFieldWork(faction: Faction): void;
|
||||||
startFactionHackWork(faction: Faction): void;
|
startFactionHackWork(faction: Faction): void;
|
||||||
startFactionSecurityWork(faction: Faction): void;
|
startFactionSecurityWork(faction: Faction): void;
|
||||||
|
startFocusing(): void;
|
||||||
startGang(facName: string, isHacking: boolean): void;
|
startGang(facName: string, isHacking: boolean): void;
|
||||||
startWork(companyName: string): void;
|
startWork(companyName: string): void;
|
||||||
startWorkPartTime(companyName: string): void;
|
startWorkPartTime(companyName: string): void;
|
||||||
|
@ -60,11 +60,9 @@ const SortFunctions: {
|
|||||||
Dexterity: (a: Resleeve, b: Resleeve): number => a.dexterity - b.dexterity,
|
Dexterity: (a: Resleeve, b: Resleeve): number => a.dexterity - b.dexterity,
|
||||||
Agility: (a: Resleeve, b: Resleeve): number => a.agility - b.agility,
|
Agility: (a: Resleeve, b: Resleeve): number => a.agility - b.agility,
|
||||||
Charisma: (a: Resleeve, b: Resleeve): number => a.charisma - b.charisma,
|
Charisma: (a: Resleeve, b: Resleeve): number => a.charisma - b.charisma,
|
||||||
AverageCombatStats: (a: Resleeve, b: Resleeve): number =>
|
AverageCombatStats: (a: Resleeve, b: Resleeve): number => getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
||||||
getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
|
||||||
getAverage(b.strength, b.defense, b.dexterity, b.agility),
|
getAverage(b.strength, b.defense, b.dexterity, b.agility),
|
||||||
AverageAllStats: (a: Resleeve, b: Resleeve): number =>
|
AverageAllStats: (a: Resleeve, b: Resleeve): number => getAverage(a.hacking_skill, a.strength, a.defense, a.dexterity, a.agility, a.charisma) -
|
||||||
getAverage(a.hacking_skill, a.strength, a.defense, a.dexterity, a.agility, a.charisma) -
|
|
||||||
getAverage(b.hacking_skill, b.strength, b.defense, b.dexterity, b.agility, b.charisma),
|
getAverage(b.hacking_skill, b.strength, b.defense, b.dexterity, b.agility, b.charisma),
|
||||||
TotalNumAugmentations: (a: Resleeve, b: Resleeve): number => a.augmentations.length - b.augmentations.length,
|
TotalNumAugmentations: (a: Resleeve, b: Resleeve): number => a.augmentations.length - b.augmentations.length,
|
||||||
};
|
};
|
||||||
|
@ -183,10 +183,8 @@ const canDo: {
|
|||||||
"Work for Company": (player: IPlayer, sleeve: Sleeve) => possibleJobs(player, sleeve).length > 0,
|
"Work for Company": (player: IPlayer, sleeve: Sleeve) => possibleJobs(player, sleeve).length > 0,
|
||||||
"Work for Faction": (player: IPlayer, sleeve: Sleeve) => possibleFactions(player, sleeve).length > 0,
|
"Work for Faction": (player: IPlayer, sleeve: Sleeve) => possibleFactions(player, sleeve).length > 0,
|
||||||
"Commit Crime": () => true,
|
"Commit Crime": () => true,
|
||||||
"Take University Course": (player: IPlayer, sleeve: Sleeve) =>
|
"Take University Course": (player: IPlayer, sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
||||||
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
"Workout at Gym": (player: IPlayer, sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
||||||
"Workout at Gym": (player: IPlayer, sleeve: Sleeve) =>
|
|
||||||
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
|
||||||
"Shock Recovery": (player: IPlayer, sleeve: Sleeve) => sleeve.shock < 100,
|
"Shock Recovery": (player: IPlayer, sleeve: Sleeve) => sleeve.shock < 100,
|
||||||
Synchronize: (player: IPlayer, sleeve: Sleeve) => sleeve.sync < 100,
|
Synchronize: (player: IPlayer, sleeve: Sleeve) => sleeve.sync < 100,
|
||||||
};
|
};
|
||||||
@ -231,8 +229,7 @@ export function TaskSelector(props: IProps): React.ReactElement {
|
|||||||
const [s1, setS1] = useState(abc[1]);
|
const [s1, setS1] = useState(abc[1]);
|
||||||
const [s2, setS2] = useState(abc[2]);
|
const [s2, setS2] = useState(abc[2]);
|
||||||
|
|
||||||
const validActions = Object.keys(canDo).filter((k) =>
|
const validActions = Object.keys(canDo).filter((k) => (canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve),
|
||||||
(canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const detailsF = tasks[s0];
|
const detailsF = tasks[s0];
|
||||||
|
@ -2,7 +2,6 @@ import { Programs } from "./Programs";
|
|||||||
import { Program } from "./Program";
|
import { Program } from "./Program";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { createElement } from "../../utils/uiHelpers/createElement";
|
|
||||||
|
|
||||||
//Returns the programs this player can create.
|
//Returns the programs this player can create.
|
||||||
export function getAvailableCreatePrograms(player: IPlayer): Program[] {
|
export function getAvailableCreatePrograms(player: IPlayer): Program[] {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { Programs } from "../Programs";
|
|
||||||
import { getAvailableCreatePrograms } from "../ProgramHelpers";
|
import { getAvailableCreatePrograms } from "../ProgramHelpers";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
431
src/RedPill.js
431
src/RedPill.js
@ -1,431 +0,0 @@
|
|||||||
/**
|
|
||||||
* Implementation for what happens when you destroy a BitNode
|
|
||||||
*/
|
|
||||||
import { BitNodes } from "./BitNode/BitNode";
|
|
||||||
import { Engine } from "./engine";
|
|
||||||
import { Player } from "./Player";
|
|
||||||
import { prestigeSourceFile } from "./Prestige";
|
|
||||||
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
|
|
||||||
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
|
||||||
import { SourceFiles } from "./SourceFile/SourceFiles";
|
|
||||||
import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
|
||||||
import { yesNoBoxCreate, yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose } from "../utils/YesNoBox";
|
|
||||||
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
|
||||||
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
|
||||||
|
|
||||||
// Returns promise
|
|
||||||
function writeRedPillLine(line) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
var container = document.getElementById("red-pill-content");
|
|
||||||
var pElem = document.createElement("p");
|
|
||||||
container.appendChild(pElem);
|
|
||||||
|
|
||||||
var promise = writeRedPillLetter(pElem, line, 0);
|
|
||||||
promise.then(
|
|
||||||
function (res) {
|
|
||||||
resolve(res);
|
|
||||||
},
|
|
||||||
function (e) {
|
|
||||||
reject(e);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeRedPillLetter(pElem, line, i = 0) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
setTimeoutRef(function () {
|
|
||||||
if (i >= line.length) {
|
|
||||||
var textToShow = line.substring(0, i);
|
|
||||||
pElem.innerHTML = "> " + textToShow;
|
|
||||||
return resolve(true);
|
|
||||||
}
|
|
||||||
var textToShow = line.substring(0, i);
|
|
||||||
pElem.innerHTML = "> " + textToShow + "<span class='typed-cursor'> █ </span>";
|
|
||||||
var promise = writeRedPillLetter(pElem, line, i + 1);
|
|
||||||
promise.then(
|
|
||||||
function (res) {
|
|
||||||
resolve(res);
|
|
||||||
},
|
|
||||||
function (e) {
|
|
||||||
reject(e);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}, 30);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let redPillFlag = false;
|
|
||||||
function hackWorldDaemon(currentNodeNumber, flume = false, quick = false) {
|
|
||||||
// Clear Red Pill screen first
|
|
||||||
var container = document.getElementById("red-pill-content");
|
|
||||||
removeChildrenFromElement(container);
|
|
||||||
|
|
||||||
redPillFlag = true;
|
|
||||||
Engine.loadRedPillContent();
|
|
||||||
|
|
||||||
if (quick) {
|
|
||||||
return loadBitVerse(currentNodeNumber, flume, quick);
|
|
||||||
}
|
|
||||||
return writeRedPillLine("[ERROR] SEMPOOL INVALID")
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("[ERROR] Segmentation Fault");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("[ERROR] SIGKILL RECVD");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Dumping core...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("0000 000016FA 174FEE40 29AC8239 384FEA88");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("0010 745F696E 2BBBE394 390E3940 248BEC23");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("0020 7124696B 0000FF69 74652E6F FFFF1111");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("----------------------------------------");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Failsafe initiated...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Restarting BitNode-" + currentNodeNumber + "...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("...........");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("...........");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("[ERROR] FAILED TO AUTOMATICALLY REBOOT BITNODE");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("..............................................");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("..............................................");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return loadBitVerse(currentNodeNumber, flume);
|
|
||||||
})
|
|
||||||
.catch(function (e) {
|
|
||||||
console.error(e.toString());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function giveSourceFile(bitNodeNumber) {
|
|
||||||
var sourceFileKey = "SourceFile" + bitNodeNumber.toString();
|
|
||||||
var sourceFile = SourceFiles[sourceFileKey];
|
|
||||||
if (sourceFile == null) {
|
|
||||||
console.error(`Could not find source file for Bit node: ${bitNodeNumber}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if player already has this source file
|
|
||||||
var alreadyOwned = false;
|
|
||||||
var ownedSourceFile = null;
|
|
||||||
for (var i = 0; i < Player.sourceFiles.length; ++i) {
|
|
||||||
if (Player.sourceFiles[i].n === bitNodeNumber) {
|
|
||||||
alreadyOwned = true;
|
|
||||||
ownedSourceFile = Player.sourceFiles[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alreadyOwned && ownedSourceFile) {
|
|
||||||
if (ownedSourceFile.lvl >= 3 && ownedSourceFile.n !== 12) {
|
|
||||||
dialogBoxCreate(
|
|
||||||
"The Source-File for the BitNode you just destroyed, " + sourceFile.name + ", " + "is already at max level!",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
++ownedSourceFile.lvl;
|
|
||||||
dialogBoxCreate(
|
|
||||||
sourceFile.name +
|
|
||||||
" was upgraded to level " +
|
|
||||||
ownedSourceFile.lvl +
|
|
||||||
" for " +
|
|
||||||
"destroying its corresponding BitNode!",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1);
|
|
||||||
Player.sourceFiles.push(playerSrcFile);
|
|
||||||
if (bitNodeNumber === 5 && Player.intelligence === 0) {
|
|
||||||
// Artificial Intelligence
|
|
||||||
Player.intelligence = 1;
|
|
||||||
}
|
|
||||||
dialogBoxCreate(
|
|
||||||
"You received a Source-File for destroying a Bit Node!<br><br>" + sourceFile.name + "<br><br>" + sourceFile.info,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keeps track of what Source-Files the player will have AFTER the current bitnode
|
|
||||||
// is destroyed. Updated every time loadBitVerse() is called
|
|
||||||
let nextSourceFileFlags = [];
|
|
||||||
|
|
||||||
function loadBitVerse(destroyedBitNodeNum, flume = false, quick = false) {
|
|
||||||
// Clear the screen
|
|
||||||
const container = document.getElementById("red-pill-content");
|
|
||||||
removeChildrenFromElement(container);
|
|
||||||
|
|
||||||
// Update NextSourceFileFlags
|
|
||||||
nextSourceFileFlags = SourceFileFlags.slice();
|
|
||||||
if (!flume) {
|
|
||||||
if (nextSourceFileFlags[destroyedBitNodeNum] < 3) ++nextSourceFileFlags[destroyedBitNodeNum];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the Bit Verse
|
|
||||||
const bitVerseImage = document.createElement("pre");
|
|
||||||
const bitNodes = [];
|
|
||||||
for (let i = 1; i <= 12; ++i) {
|
|
||||||
bitNodes.push(createBitNode(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
bitVerseImage.innerHTML =
|
|
||||||
" O <br>" +
|
|
||||||
" | O O | O O | <br>" +
|
|
||||||
" O | | / __| \\ | | O <br>" +
|
|
||||||
" O | O | | O / | O | | O | O <br>" +
|
|
||||||
" | | | | |_/ |/ | \\_ \\_| | | | | <br>" +
|
|
||||||
" O | | | O | | O__/ | / \\__ | | O | | | O <br>" +
|
|
||||||
" | | | | | | | / /| O / \\| | | | | | | <br>" +
|
|
||||||
"O | | | \\| | O / _/ | / O | |/ | | | O<br>" +
|
|
||||||
"| | | |O / | | O / | O O | | \\ O| | | |<br>" +
|
|
||||||
"| | |/ \\/ / __| | |/ \\ | \\ | |__ \\ \\/ \\| | |<br>" +
|
|
||||||
" \\| O | |_/ |\\| \\ O \\__| \\_| | O |/ <br>" +
|
|
||||||
" | | |_/ | | \\| / | \\_| | | <br>" +
|
|
||||||
" \\| / \\| | / / \\ |/ <br>" +
|
|
||||||
" | " +
|
|
||||||
bitNodes[9] +
|
|
||||||
" | | / | " +
|
|
||||||
bitNodes[10] +
|
|
||||||
" | <br>" +
|
|
||||||
" " +
|
|
||||||
bitNodes[8] +
|
|
||||||
" | | | | | | | " +
|
|
||||||
bitNodes[11] +
|
|
||||||
" <br>" +
|
|
||||||
" | | | / / \\ \\ | | | <br>" +
|
|
||||||
" \\| | / " +
|
|
||||||
bitNodes[6] +
|
|
||||||
" / \\ " +
|
|
||||||
bitNodes[7] +
|
|
||||||
" \\ | |/ <br>" +
|
|
||||||
" \\ | / / | | \\ \\ | / <br>" +
|
|
||||||
" \\ \\JUMP " +
|
|
||||||
bitNodes[4] +
|
|
||||||
"3R | | | | | | R3" +
|
|
||||||
bitNodes[5] +
|
|
||||||
" PMUJ/ / <br>" +
|
|
||||||
" \\|| | | | | | | | | ||/ <br>" +
|
|
||||||
" \\| \\_ | | | | | | _/ |/ <br>" +
|
|
||||||
" \\ \\| / \\ / \\ |/ / <br>" +
|
|
||||||
" " +
|
|
||||||
bitNodes[0] +
|
|
||||||
" |/ " +
|
|
||||||
bitNodes[1] +
|
|
||||||
" | | " +
|
|
||||||
bitNodes[2] +
|
|
||||||
" \\| " +
|
|
||||||
bitNodes[3] +
|
|
||||||
" <br>" +
|
|
||||||
" | | | | | | | | <br>" +
|
|
||||||
" \\JUMP3R|JUMP|3R| |R3|PMUJ|R3PMUJ/ <br><br><br><br>";
|
|
||||||
|
|
||||||
container.appendChild(bitVerseImage);
|
|
||||||
|
|
||||||
// BitNode event listeners
|
|
||||||
for (let i = 1; i <= 12; ++i) {
|
|
||||||
(function (i) {
|
|
||||||
const elemId = "bitnode-" + i.toString();
|
|
||||||
const elem = clearEventListeners(elemId);
|
|
||||||
if (elem == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (i >= 1 && i <= 12) {
|
|
||||||
elem.addEventListener("click", function () {
|
|
||||||
const bitNodeKey = "BitNode" + i;
|
|
||||||
const bitNode = BitNodes[bitNodeKey];
|
|
||||||
if (bitNode == null) {
|
|
||||||
console.error(`Could not find BitNode object for number: ${i}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxSourceFileLevel = i === 12 ? "∞" : "3";
|
|
||||||
const popupBoxText =
|
|
||||||
`BitNode-${i}: ${bitNode.name}<br>` +
|
|
||||||
`Source-File Level: ${nextSourceFileFlags[i]} / ${maxSourceFileLevel}<br><br>` +
|
|
||||||
`${bitNode.info}`;
|
|
||||||
yesNoBoxCreate(popupBoxText);
|
|
||||||
createBitNodeYesNoEventListener(i, destroyedBitNodeNum, flume);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
elem.addEventListener("click", function () {
|
|
||||||
dialogBoxCreate("Not yet implemented! Coming soon!");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})(i); // Immediate invocation closure
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quick) {
|
|
||||||
return Promise.resolve(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create lore text
|
|
||||||
return writeRedPillLine(
|
|
||||||
"Many decades ago, a humanoid extraterrestial species which we call the Enders descended on the Earth...violently",
|
|
||||||
)
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine(
|
|
||||||
"Our species fought back, but it was futile. The Enders had technology far beyond our own...",
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Instead of killing every last one of us, the human race was enslaved...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("We were shackled in a digital world, chained into a prison for our minds...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine(
|
|
||||||
"Using their advanced technology, the Enders created complex simulations of a virtual reality...",
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Simulations designed to keep us content...ignorant of the truth.");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Simulations used to trap and suppress our consciousness, to keep us under control...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine(
|
|
||||||
"Why did they do this? Why didn't they just end our entire race? We don't know, not yet.",
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine(
|
|
||||||
"Humanity's only hope is to destroy these simulations, destroy the only realities we've ever known...",
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Only then can we begin to fight back...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine(
|
|
||||||
"By hacking the daemon that generated your reality, you've just destroyed one simulation, called a BitNode...",
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("But there is still a long way to go...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine(
|
|
||||||
"The technology the Enders used to enslave the human race wasn't just a single complex simulation...",
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("There are tens if not hundreds of BitNodes out there...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Each with their own simulations of a reality...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Each creating their own universes...a universe of universes");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("And all of which must be destroyed...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine(".......................................");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("Welcome to the Bitverse...");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine(" ");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return writeRedPillLine("(Enter a new BitNode using the image above)");
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return Promise.resolve(true);
|
|
||||||
})
|
|
||||||
.catch(function (e) {
|
|
||||||
console.error(e.toString());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns string with DOM element for Bit Node
|
|
||||||
function createBitNode(n) {
|
|
||||||
const bitNodeStr = "BitNode" + n.toString();
|
|
||||||
const bitNode = BitNodes[bitNodeStr];
|
|
||||||
if (bitNode == null) {
|
|
||||||
return "O";
|
|
||||||
}
|
|
||||||
|
|
||||||
const level = nextSourceFileFlags[n];
|
|
||||||
let cssClass;
|
|
||||||
if (n === 12 && level >= 2) {
|
|
||||||
// Repeating BitNode
|
|
||||||
cssClass = "level-2";
|
|
||||||
} else {
|
|
||||||
cssClass = `level-${level}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
`<a class='bitnode ${cssClass} tooltip' id='bitnode-${bitNode.number}'><strong>O</strong>` +
|
|
||||||
"<span class='tooltiptext'>" +
|
|
||||||
`<strong>BitNode-${bitNode.number.toString()}<br>${bitNode.name}</strong><br>` +
|
|
||||||
`${bitNode.desc}<br>` +
|
|
||||||
"</span></a>"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createBitNodeYesNoEventListener(newBitNode, destroyedBitNode, flume = false) {
|
|
||||||
const yesBtn = yesNoBoxGetYesButton();
|
|
||||||
yesBtn.innerHTML = "Enter BitNode-" + newBitNode;
|
|
||||||
yesBtn.addEventListener("click", function () {
|
|
||||||
if (!flume) {
|
|
||||||
giveSourceFile(destroyedBitNode);
|
|
||||||
} else {
|
|
||||||
if (SourceFileFlags[5] === 0 && newBitNode !== 5) {
|
|
||||||
Player.intelligence = 0;
|
|
||||||
Player.intelligence_exp = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newBitNode === 5 && Player.intelligence === 0) {
|
|
||||||
Player.intelligence = 1;
|
|
||||||
}
|
|
||||||
redPillFlag = false;
|
|
||||||
const container = document.getElementById("red-pill-content");
|
|
||||||
removeChildrenFromElement(container);
|
|
||||||
|
|
||||||
// Set new Bit Node
|
|
||||||
Player.bitNodeN = newBitNode;
|
|
||||||
|
|
||||||
// Reenable terminal
|
|
||||||
$("#hack-progress-bar").attr("id", "old-hack-progress-bar");
|
|
||||||
$("#hack-progress").attr("id", "old-hack-progress");
|
|
||||||
document.getElementById("terminal-input-td").innerHTML =
|
|
||||||
'$ <input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>';
|
|
||||||
$("input[class=terminal-input]").prop("disabled", false);
|
|
||||||
|
|
||||||
prestigeSourceFile(flume);
|
|
||||||
yesNoBoxClose();
|
|
||||||
});
|
|
||||||
const noBtn = yesNoBoxGetNoButton();
|
|
||||||
noBtn.innerHTML = "Back";
|
|
||||||
noBtn.addEventListener("click", function () {
|
|
||||||
yesNoBoxClose();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { redPillFlag, hackWorldDaemon };
|
|
104
src/RedPill.jsx
Normal file
104
src/RedPill.jsx
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* Implementation for what happens when you destroy a BitNode
|
||||||
|
*/
|
||||||
|
import { Engine } from "./engine";
|
||||||
|
import { Player } from "./Player";
|
||||||
|
import { prestigeSourceFile } from "./Prestige";
|
||||||
|
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
|
||||||
|
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||||
|
import { SourceFiles } from "./SourceFile/SourceFiles";
|
||||||
|
|
||||||
|
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||||
|
import { BitverseRoot } from "./BitNode/ui/BitverseRoot";
|
||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom";
|
||||||
|
|
||||||
|
let redPillFlag = false;
|
||||||
|
function hackWorldDaemon(currentNodeNumber, flume = false, quick = false) {
|
||||||
|
// Clear the screen
|
||||||
|
const container = document.getElementById("red-pill-content");
|
||||||
|
ReactDOM.unmountComponentAtNode(container);
|
||||||
|
Engine.loadRedPillContent();
|
||||||
|
ReactDOM.render(
|
||||||
|
<BitverseRoot destroyedBitNodeNum={currentNodeNumber} flume={flume} enter={enterBitNode} quick={quick} />,
|
||||||
|
container,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function giveSourceFile(bitNodeNumber) {
|
||||||
|
var sourceFileKey = "SourceFile" + bitNodeNumber.toString();
|
||||||
|
var sourceFile = SourceFiles[sourceFileKey];
|
||||||
|
if (sourceFile == null) {
|
||||||
|
console.error(`Could not find source file for Bit node: ${bitNodeNumber}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if player already has this source file
|
||||||
|
var alreadyOwned = false;
|
||||||
|
var ownedSourceFile = null;
|
||||||
|
for (var i = 0; i < Player.sourceFiles.length; ++i) {
|
||||||
|
if (Player.sourceFiles[i].n === bitNodeNumber) {
|
||||||
|
alreadyOwned = true;
|
||||||
|
ownedSourceFile = Player.sourceFiles[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alreadyOwned && ownedSourceFile) {
|
||||||
|
if (ownedSourceFile.lvl >= 3 && ownedSourceFile.n !== 12) {
|
||||||
|
dialogBoxCreate(
|
||||||
|
"The Source-File for the BitNode you just destroyed, " + sourceFile.name + ", " + "is already at max level!",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
++ownedSourceFile.lvl;
|
||||||
|
dialogBoxCreate(
|
||||||
|
sourceFile.name +
|
||||||
|
" was upgraded to level " +
|
||||||
|
ownedSourceFile.lvl +
|
||||||
|
" for " +
|
||||||
|
"destroying its corresponding BitNode!",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1);
|
||||||
|
Player.sourceFiles.push(playerSrcFile);
|
||||||
|
if (bitNodeNumber === 5 && Player.intelligence === 0) {
|
||||||
|
// Artificial Intelligence
|
||||||
|
Player.intelligence = 1;
|
||||||
|
}
|
||||||
|
dialogBoxCreate(
|
||||||
|
"You received a Source-File for destroying a Bit Node!<br><br>" + sourceFile.name + "<br><br>" + sourceFile.info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function enterBitNode(flume, destroyedBitNode, newBitNode) {
|
||||||
|
if (!flume) {
|
||||||
|
giveSourceFile(destroyedBitNode);
|
||||||
|
} else {
|
||||||
|
if (SourceFileFlags[5] === 0 && newBitNode !== 5) {
|
||||||
|
Player.intelligence = 0;
|
||||||
|
Player.intelligence_exp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newBitNode === 5 && Player.intelligence === 0) {
|
||||||
|
Player.intelligence = 1;
|
||||||
|
}
|
||||||
|
redPillFlag = false;
|
||||||
|
const container = document.getElementById("red-pill-content");
|
||||||
|
ReactDOM.unmountComponentAtNode(container);
|
||||||
|
|
||||||
|
// Set new Bit Node
|
||||||
|
Player.bitNodeN = newBitNode;
|
||||||
|
|
||||||
|
// Reenable terminal
|
||||||
|
$("#hack-progress-bar").attr("id", "old-hack-progress-bar");
|
||||||
|
$("#hack-progress").attr("id", "old-hack-progress");
|
||||||
|
document.getElementById("terminal-input-td").innerHTML =
|
||||||
|
'$ <input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>';
|
||||||
|
$("input[class=terminal-input]").prop("disabled", false);
|
||||||
|
|
||||||
|
prestigeSourceFile(flume);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { redPillFlag, hackWorldDaemon };
|
@ -3,8 +3,14 @@ import { IEngine } from "../../IEngine";
|
|||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../../InteractiveTutorial";
|
import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../../InteractiveTutorial";
|
||||||
import { getAvailableCreatePrograms } from "../../Programs/ProgramHelpers";
|
import { getAvailableCreatePrograms } from "../../Programs/ProgramHelpers";
|
||||||
import { ICorporation } from "../../Corporation/ICorporation";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { IGang } from "../../Gang/IGang";
|
import { redPillFlag } from "../../RedPill";
|
||||||
|
|
||||||
|
import { inMission } from "../../Missions";
|
||||||
|
import { cinematicTextFlag } from "../../CinematicText";
|
||||||
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
import { FconfSettings } from "../../Fconf/FconfSettings";
|
||||||
|
import { Page, routing } from "../../ui/navigationTracking";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
player: IPlayer;
|
player: IPlayer;
|
||||||
@ -16,13 +22,13 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
}
|
}
|
||||||
const [divisionName, setDivisionName] = useState("Overview");
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const id = setInterval(rerender, 20);
|
const id = setInterval(rerender, 20);
|
||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const [activeTab, setActiveTab] = useState("");
|
||||||
const [hackingOpen, setHackingOpen] = useState(true);
|
const [hackingOpen, setHackingOpen] = useState(true);
|
||||||
const [characterOpen, setCharacterOpen] = useState(true);
|
const [characterOpen, setCharacterOpen] = useState(true);
|
||||||
const [worldOpen, setWorldOpen] = useState(true);
|
const [worldOpen, setWorldOpen] = useState(true);
|
||||||
@ -42,36 +48,6 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
const flashTutorial = ITutorial.currStep === iTutorialSteps.WorldDescription;
|
const flashTutorial = ITutorial.currStep === iTutorialSteps.WorldDescription;
|
||||||
|
|
||||||
function clickTerminal() {
|
|
||||||
props.engine.loadTerminalContent();
|
|
||||||
if (flashTerminal) iTutorialNextStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clickStats() {
|
|
||||||
props.engine.loadCharacterContent();
|
|
||||||
if (flashStats) iTutorialNextStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clickActiveScripts() {
|
|
||||||
props.engine.loadActiveScriptsContent();
|
|
||||||
if (flashActiveScripts) iTutorialNextStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clickHacknet() {
|
|
||||||
props.engine.loadHacknetNodesContent();
|
|
||||||
if (flashHacknet) iTutorialNextStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clickCity() {
|
|
||||||
props.engine.loadLocationContent();
|
|
||||||
if (flashCity) iTutorialNextStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clickTutorial() {
|
|
||||||
props.engine.loadTutorialContent();
|
|
||||||
if (flashTutorial) iTutorialNextStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
const programCount = getAvailableCreatePrograms(props.player).length;
|
const programCount = getAvailableCreatePrograms(props.player).length;
|
||||||
const canCreateProgram =
|
const canCreateProgram =
|
||||||
programCount > 0 ||
|
programCount > 0 ||
|
||||||
@ -101,6 +77,182 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
const canStockMarket = props.player.hasWseAccount;
|
const canStockMarket = props.player.hasWseAccount;
|
||||||
const canBladeburner = !!(props.player.bladeburner as any);
|
const canBladeburner = !!(props.player.bladeburner as any);
|
||||||
|
|
||||||
|
function clickTerminal(): void {
|
||||||
|
setActiveTab("Terminal");
|
||||||
|
props.engine.loadTerminalContent();
|
||||||
|
if (flashTerminal) iTutorialNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickCreateScripts(): void {
|
||||||
|
setActiveTab("CreateScripts");
|
||||||
|
props.engine.loadScriptEditorContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickStats(): void {
|
||||||
|
setActiveTab("Stats");
|
||||||
|
props.engine.loadCharacterContent();
|
||||||
|
if (flashStats) iTutorialNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickActiveScripts(): void {
|
||||||
|
setActiveTab("ActiveScripts");
|
||||||
|
props.engine.loadActiveScriptsContent();
|
||||||
|
if (flashActiveScripts) iTutorialNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickCreateProgram(): void {
|
||||||
|
setActiveTab("CreateProgram");
|
||||||
|
props.engine.loadCreateProgramContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickFactions(): void {
|
||||||
|
setActiveTab("Factions");
|
||||||
|
props.engine.loadFactionsContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickAugmentations(): void {
|
||||||
|
setActiveTab("Augmentations");
|
||||||
|
props.engine.loadAugmentationsContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickSleeves(): void {
|
||||||
|
setActiveTab("Sleeves");
|
||||||
|
props.engine.loadSleevesContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickHacknet(): void {
|
||||||
|
setActiveTab("Hacknet");
|
||||||
|
props.engine.loadHacknetNodesContent();
|
||||||
|
if (flashHacknet) iTutorialNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickCity(): void {
|
||||||
|
setActiveTab("City");
|
||||||
|
props.engine.loadLocationContent();
|
||||||
|
if (flashCity) iTutorialNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickTravel(): void {
|
||||||
|
setActiveTab("Travel");
|
||||||
|
props.engine.loadTravelContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickJob(): void {
|
||||||
|
setActiveTab("Job");
|
||||||
|
props.engine.loadJobContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickStockMarket(): void {
|
||||||
|
setActiveTab("StockMarket");
|
||||||
|
props.engine.loadStockMarketContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickBladeburner(): void {
|
||||||
|
setActiveTab("Bladeburner");
|
||||||
|
props.engine.loadBladeburnerContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickCorp(): void {
|
||||||
|
setActiveTab("Corp");
|
||||||
|
props.engine.loadCorporationContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickGang(): void {
|
||||||
|
setActiveTab("Gang");
|
||||||
|
props.engine.loadGangContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickTutorial(): void {
|
||||||
|
setActiveTab("Tutorial");
|
||||||
|
props.engine.loadTutorialContent();
|
||||||
|
if (flashTutorial) iTutorialNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickMilestones(): void {
|
||||||
|
setActiveTab("Milestones");
|
||||||
|
props.engine.loadMilestonesContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickDev(): void {
|
||||||
|
setActiveTab("Dev");
|
||||||
|
props.engine.loadDevMenuContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Shortcuts to navigate through the game
|
||||||
|
// Alt-t - Terminal
|
||||||
|
// Alt-c - Character
|
||||||
|
// Alt-e - Script editor
|
||||||
|
// Alt-s - Active scripts
|
||||||
|
// Alt-h - Hacknet Nodes
|
||||||
|
// Alt-w - City
|
||||||
|
// Alt-j - Job
|
||||||
|
// Alt-r - Travel Agency of current city
|
||||||
|
// Alt-p - Create program
|
||||||
|
// Alt-f - Factions
|
||||||
|
// Alt-a - Augmentations
|
||||||
|
// Alt-u - Tutorial
|
||||||
|
// Alt-o - Options
|
||||||
|
function handleShortcuts(this: Document, event: KeyboardEvent): any {
|
||||||
|
if (Settings.DisableHotkeys) return;
|
||||||
|
if (props.player.isWorking || redPillFlag || inMission || cinematicTextFlag) return;
|
||||||
|
if (event.keyCode == KEY.T && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickTerminal();
|
||||||
|
} else if (event.keyCode === KEY.C && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickStats();
|
||||||
|
} else if (event.keyCode === KEY.E && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickCreateScripts();
|
||||||
|
} else if (event.keyCode === KEY.S && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickActiveScripts();
|
||||||
|
} else if (event.keyCode === KEY.H && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickHacknet();
|
||||||
|
} else if (event.keyCode === KEY.W && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickCity();
|
||||||
|
} else if (event.keyCode === KEY.J && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickJob();
|
||||||
|
} else if (event.keyCode === KEY.R && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickTravel();
|
||||||
|
} else if (event.keyCode === KEY.P && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickCreateProgram();
|
||||||
|
} else if (event.keyCode === KEY.F && event.altKey) {
|
||||||
|
// Overriden by Fconf
|
||||||
|
if (routing.isOn(Page.Terminal) && FconfSettings.ENABLE_BASH_HOTKEYS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
clickFactions();
|
||||||
|
} else if (event.keyCode === KEY.A && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickAugmentations();
|
||||||
|
} else if (event.keyCode === KEY.U && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickTutorial();
|
||||||
|
} else if (event.keyCode === KEY.B && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickBladeburner();
|
||||||
|
} else if (event.keyCode === KEY.G && event.altKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
clickGang();
|
||||||
|
}
|
||||||
|
// if (event.keyCode === KEY.O && event.altKey) {
|
||||||
|
// event.preventDefault();
|
||||||
|
// gameOptionsBoxOpen();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("keypress", handleShortcuts);
|
||||||
|
return () => document.removeEventListener("keypress", handleShortcuts);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul id="mainmenu" className="mainmenu noscrollbar noselect">
|
<ul id="mainmenu" className="mainmenu noscrollbar noselect">
|
||||||
{/* Hacking dropdown */}
|
{/* Hacking dropdown */}
|
||||||
@ -119,22 +271,33 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
</li>
|
</li>
|
||||||
{hackingOpen && (
|
{hackingOpen && (
|
||||||
<>
|
<>
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className={flashTerminal ? "flashing-button" : ""} onClick={clickTerminal}>
|
<button
|
||||||
|
className={(flashTerminal ? "flashing-button" : "") + activeTab === "Terminal" ? " active" : ""}
|
||||||
|
onClick={clickTerminal}
|
||||||
|
>
|
||||||
Terminal
|
Terminal
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadScriptEditorContent()}>Create Script</button>
|
<button className={activeTab === "CreateScripts" ? " active" : ""} onClick={clickCreateScripts}>
|
||||||
|
Create Script
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className={flashActiveScripts ? "flashing-button" : ""} onClick={clickActiveScripts}>
|
<button
|
||||||
|
className={(flashActiveScripts ? "flashing-button" : "") + activeTab === "ActiveScripts" ? " active" : ""}
|
||||||
|
onClick={clickActiveScripts}
|
||||||
|
>
|
||||||
Active Scripts
|
Active Scripts
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{canCreateProgram && (
|
{canCreateProgram && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className="notification" onClick={() => props.engine.loadCreateProgramContent()}>
|
<button
|
||||||
|
className={"notification" + (activeTab === "CreateProgram" ? " active" : "")}
|
||||||
|
onClick={clickCreateProgram}
|
||||||
|
>
|
||||||
Create Program
|
Create Program
|
||||||
{programCount > 0 && <span className="badge">{programCount}</span>}
|
{programCount > 0 && <span className="badge">{programCount}</span>}
|
||||||
</button>
|
</button>
|
||||||
@ -155,14 +318,17 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
</li>
|
</li>
|
||||||
{characterOpen && (
|
{characterOpen && (
|
||||||
<>
|
<>
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className={flashStats ? "flashing-button" : ""} onClick={clickStats}>
|
<button
|
||||||
|
className={(flashStats ? "flashing-button" : "") + activeTab === "Stats" ? " active" : ""}
|
||||||
|
onClick={clickStats}
|
||||||
|
>
|
||||||
Stats
|
Stats
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{canOpenFactions && (
|
{canOpenFactions && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className="notification" onClick={() => props.engine.loadFactionsContent()}>
|
<button className={"notification" + (activeTab === "Factions" ? " active" : "")} onClick={clickFactions}>
|
||||||
Factions
|
Factions
|
||||||
{props.player.factionInvitations.length > 0 && (
|
{props.player.factionInvitations.length > 0 && (
|
||||||
<span className="badge">{props.player.factionInvitations.length}</span>
|
<span className="badge">{props.player.factionInvitations.length}</span>
|
||||||
@ -171,8 +337,11 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{canOpenAugmentations && (
|
{canOpenAugmentations && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className="notification" onClick={() => props.engine.loadAugmentationsContent()}>
|
<button
|
||||||
|
className={"notification" + (activeTab === "Augmentations" ? " active" : "")}
|
||||||
|
onClick={clickAugmentations}
|
||||||
|
>
|
||||||
Augmentations
|
Augmentations
|
||||||
{props.player.queuedAugmentations.length > 0 && (
|
{props.player.queuedAugmentations.length > 0 && (
|
||||||
<span className="badge">{props.player.queuedAugmentations.length}</span>
|
<span className="badge">{props.player.queuedAugmentations.length}</span>
|
||||||
@ -180,14 +349,19 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className={flashHacknet ? "flashing-button" : ""} onClick={clickHacknet}>
|
<button
|
||||||
|
className={(flashHacknet ? "flashing-button" : "") + activeTab === "Hacknet" ? " active" : ""}
|
||||||
|
onClick={clickHacknet}
|
||||||
|
>
|
||||||
Hacknet
|
Hacknet
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{canOpenSleeves && (
|
{canOpenSleeves && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadSleevesContent()}>Sleeves</button>
|
<button className={activeTab === "Sleeves" ? " active" : ""} onClick={clickSleeves}>
|
||||||
|
Sleeves
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@ -205,37 +379,52 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
{worldOpen && (
|
{worldOpen && (
|
||||||
<>
|
<>
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className={flashCity ? "flashing-button" : ""} onClick={clickCity}>
|
<button
|
||||||
|
className={(flashCity ? "flashing-button" : "") + activeTab === "City" ? " active" : ""}
|
||||||
|
onClick={clickCity}
|
||||||
|
>
|
||||||
City
|
City
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadTravelContent()}>Travel</button>
|
<button className={activeTab === "Travel" ? " active" : ""} onClick={clickTravel}>
|
||||||
|
Travel
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{canJob && (
|
{canJob && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadJobContent()}>Job</button>
|
<button className={activeTab === "Job" ? " active" : ""} onClick={clickJob}>
|
||||||
|
Job
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{canStockMarket && (
|
{canStockMarket && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadStockMarketContent()}>Stock Market</button>
|
<button className={activeTab === "StockMarket" ? " active" : ""} onClick={clickStockMarket}>
|
||||||
|
Stock Market
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{canBladeburner && (
|
{canBladeburner && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadBladeburnerContent()}>Bladeburner</button>
|
<button className={activeTab === "Bladeburner" ? " active" : ""} onClick={clickBladeburner}>
|
||||||
|
Bladeburner
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{canCorporation && (
|
{canCorporation && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadCorporationContent()}>Corp</button>
|
<button className={activeTab === "Corp" ? " active" : ""} onClick={clickCorp}>
|
||||||
|
Corp
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{canGang && (
|
{canGang && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadGangContent()}>Gang</button>
|
<button className={activeTab === "Gang" ? " active" : ""} onClick={clickGang}>
|
||||||
|
Gang
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@ -251,11 +440,16 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
</li>
|
</li>
|
||||||
{helpOpen && (
|
{helpOpen && (
|
||||||
<>
|
<>
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadMilestonesContent()}>Milestones</button>
|
<button className={activeTab === "Milestones" ? " active" : ""} onClick={clickMilestones}>
|
||||||
|
Milestones
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button className={flashTutorial ? "flashing-button" : ""} onClick={clickTutorial}>
|
<button
|
||||||
|
className={(flashTutorial ? "flashing-button" : "") + activeTab === "Tutorial" ? " active" : ""}
|
||||||
|
onClick={clickTutorial}
|
||||||
|
>
|
||||||
Tutorial
|
Tutorial
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@ -263,8 +457,10 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
<button>Options</button>
|
<button>Options</button>
|
||||||
</li>*/}
|
</li>*/}
|
||||||
{process.env.NODE_ENV === "development" && (
|
{process.env.NODE_ENV === "development" && (
|
||||||
<li className="mainmenu-accordion-panel">
|
<li className={`mainmenu-accordion-panel`}>
|
||||||
<button onClick={() => props.engine.loadDevMenuContent()}>Dev</button>
|
<button className={activeTab === "Dev" ? " active" : ""} onClick={clickDev}>
|
||||||
|
Dev
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
34
src/StockMarket/ui/PlaceOrderPopup.tsx
Normal file
34
src/StockMarket/ui/PlaceOrderPopup.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
text: string;
|
||||||
|
placeText: string;
|
||||||
|
place: (price: number) => void;
|
||||||
|
popupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PlaceOrderPopup(props: IProps): React.ReactElement {
|
||||||
|
const [price, setPrice] = useState<number | null>(null);
|
||||||
|
function onClick(): void {
|
||||||
|
if (price === null) return;
|
||||||
|
if (isNaN(price)) return;
|
||||||
|
props.place(price);
|
||||||
|
removePopup(props.popupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
|
if (event.target.value === "") setPrice(null);
|
||||||
|
else setPrice(parseFloat(event.target.value));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>{props.text}</p>
|
||||||
|
<input autoFocus={true} className="text-input" type="number" onChange={onChange} placeholder="price" />
|
||||||
|
<button className="std-button" onClick={onClick}>
|
||||||
|
{props.placeText}
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -7,6 +7,7 @@ import { StockTickerHeaderText } from "./StockTickerHeaderText";
|
|||||||
import { StockTickerOrderList } from "./StockTickerOrderList";
|
import { StockTickerOrderList } from "./StockTickerOrderList";
|
||||||
import { StockTickerPositionText } from "./StockTickerPositionText";
|
import { StockTickerPositionText } from "./StockTickerPositionText";
|
||||||
import { StockTickerTxButton } from "./StockTickerTxButton";
|
import { StockTickerTxButton } from "./StockTickerTxButton";
|
||||||
|
import { PlaceOrderPopup } from "./PlaceOrderPopup";
|
||||||
|
|
||||||
import { Order } from "../Order";
|
import { Order } from "../Order";
|
||||||
import { Stock } from "../Stock";
|
import { Stock } from "../Stock";
|
||||||
@ -19,15 +20,9 @@ import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
|||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { Accordion } from "../../ui/React/Accordion";
|
import { Accordion } from "../../ui/React/Accordion";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||||
import {
|
|
||||||
yesNoTxtInpBoxClose,
|
|
||||||
yesNoTxtInpBoxCreate,
|
|
||||||
yesNoTxtInpBoxGetInput,
|
|
||||||
yesNoTxtInpBoxGetNoButton,
|
|
||||||
yesNoTxtInpBoxGetYesButton,
|
|
||||||
} from "../../../utils/YesNoBox";
|
|
||||||
|
|
||||||
enum SelectorOrderType {
|
enum SelectorOrderType {
|
||||||
Market = "Market Order",
|
Market = "Market Order",
|
||||||
@ -85,30 +80,6 @@ export class StockTicker extends React.Component<IProps, IState> {
|
|||||||
this.handleSellAllButtonClick = this.handleSellAllButtonClick.bind(this);
|
this.handleSellAllButtonClick = this.handleSellAllButtonClick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
createPlaceOrderPopupBox(yesTxt: string, popupTxt: string, yesBtnCb: (price: number) => void): void {
|
|
||||||
const yesBtn = yesNoTxtInpBoxGetYesButton();
|
|
||||||
const noBtn = yesNoTxtInpBoxGetNoButton();
|
|
||||||
|
|
||||||
yesBtn.innerText = yesTxt;
|
|
||||||
yesBtn.addEventListener("click", () => {
|
|
||||||
const price = parseFloat(yesNoTxtInpBoxGetInput());
|
|
||||||
if (isNaN(price)) {
|
|
||||||
dialogBoxCreate(`Invalid input for price: ${yesNoTxtInpBoxGetInput()}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
yesBtnCb(price);
|
|
||||||
yesNoTxtInpBoxClose();
|
|
||||||
});
|
|
||||||
|
|
||||||
noBtn.innerText = "Cancel Order";
|
|
||||||
noBtn.addEventListener("click", () => {
|
|
||||||
yesNoTxtInpBoxClose();
|
|
||||||
});
|
|
||||||
|
|
||||||
yesNoTxtInpBoxCreate(popupTxt);
|
|
||||||
}
|
|
||||||
|
|
||||||
getBuyTransactionCostContent(): JSX.Element | null {
|
getBuyTransactionCostContent(): JSX.Element | null {
|
||||||
const stock = this.props.stock;
|
const stock = this.props.stock;
|
||||||
const qty: number = this.getQuantity();
|
const qty: number = this.getQuantity();
|
||||||
@ -182,23 +153,23 @@ export class StockTicker extends React.Component<IProps, IState> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SelectorOrderType.Limit: {
|
case SelectorOrderType.Limit: {
|
||||||
this.createPlaceOrderPopupBox(
|
const popupId = `place-order-popup`;
|
||||||
"Place Buy Limit Order",
|
createPopup(popupId, PlaceOrderPopup, {
|
||||||
"Enter the price for your Limit Order",
|
text: "Enter the price for your Limit Order",
|
||||||
(price: number) => {
|
placeText: "Place Buy Limit Order",
|
||||||
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitBuy, this.state.position);
|
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitBuy, this.state.position),
|
||||||
},
|
popupId: popupId,
|
||||||
);
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SelectorOrderType.Stop: {
|
case SelectorOrderType.Stop: {
|
||||||
this.createPlaceOrderPopupBox(
|
const popupId = `place-order-popup`;
|
||||||
"Place Buy Stop Order",
|
createPopup(popupId, PlaceOrderPopup, {
|
||||||
"Enter the price for your Stop Order",
|
text: "Enter the price for your Stop Order",
|
||||||
(price: number) => {
|
placeText: "Place Buy Stop Order",
|
||||||
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopBuy, this.state.position);
|
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopBuy, this.state.position),
|
||||||
},
|
popupId: popupId,
|
||||||
);
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -304,23 +275,23 @@ export class StockTicker extends React.Component<IProps, IState> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SelectorOrderType.Limit: {
|
case SelectorOrderType.Limit: {
|
||||||
this.createPlaceOrderPopupBox(
|
const popupId = `place-order-popup`;
|
||||||
"Place Sell Limit Order",
|
createPopup(popupId, PlaceOrderPopup, {
|
||||||
"Enter the price for your Limit Order",
|
text: "Enter the price for your Limit Order",
|
||||||
(price: number) => {
|
placeText: "Place Sell Limit Order",
|
||||||
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitSell, this.state.position);
|
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitSell, this.state.position),
|
||||||
},
|
popupId: popupId,
|
||||||
);
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SelectorOrderType.Stop: {
|
case SelectorOrderType.Stop: {
|
||||||
this.createPlaceOrderPopupBox(
|
const popupId = `place-order-popup`;
|
||||||
"Place Sell Stop Order",
|
createPopup(popupId, PlaceOrderPopup, {
|
||||||
"Enter the price for your Stop Order",
|
text: "Enter the price for your Stop Order",
|
||||||
(price: number) => {
|
placeText: "Place Sell Stop Order",
|
||||||
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopSell, this.state.position);
|
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopSell, this.state.position),
|
||||||
},
|
popupId: popupId,
|
||||||
);
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -53,10 +53,11 @@ import { KEY } from "../utils/helpers/keyCodes";
|
|||||||
import { arrayToString } from "../utils/helpers/arrayToString";
|
import { arrayToString } from "../utils/helpers/arrayToString";
|
||||||
import { getTimestamp } from "../utils/helpers/getTimestamp";
|
import { getTimestamp } from "../utils/helpers/getTimestamp";
|
||||||
import { logBoxCreate } from "../utils/LogBox";
|
import { logBoxCreate } from "../utils/LogBox";
|
||||||
import { yesNoBoxCreate, yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose } from "../utils/YesNoBox";
|
|
||||||
import { post, postElement, postContent, postError, hackProgressBarPost, hackProgressPost } from "./ui/postToTerminal";
|
import { post, postElement, postContent, postError, hackProgressBarPost, hackProgressPost } from "./ui/postToTerminal";
|
||||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||||
import { Money } from "./ui/React/Money";
|
import { Money } from "./ui/React/Money";
|
||||||
|
import { createPopup } from "./ui/React/createPopup";
|
||||||
|
import { BitFlumePopup } from "./BitNode/ui/BitFlumePopup";
|
||||||
|
|
||||||
import autosize from "autosize";
|
import autosize from "autosize";
|
||||||
import * as JSZip from "jszip";
|
import * as JSZip from "jszip";
|
||||||
@ -2374,22 +2375,11 @@ let Terminal = {
|
|||||||
post("-- Daedalus --");
|
post("-- Daedalus --");
|
||||||
};
|
};
|
||||||
programHandlers[Programs.BitFlume.name] = () => {
|
programHandlers[Programs.BitFlume.name] = () => {
|
||||||
const yesBtn = yesNoBoxGetYesButton();
|
const popupId = "bitflume-popup";
|
||||||
const noBtn = yesNoBoxGetNoButton();
|
createPopup(popupId, BitFlumePopup, {
|
||||||
yesBtn.innerHTML = "Travel to BitNode Nexus";
|
player: Player,
|
||||||
noBtn.innerHTML = "Cancel";
|
popupId: popupId,
|
||||||
yesBtn.addEventListener("click", function () {
|
|
||||||
hackWorldDaemon(Player.bitNodeN, true);
|
|
||||||
return yesNoBoxClose();
|
|
||||||
});
|
});
|
||||||
noBtn.addEventListener("click", function () {
|
|
||||||
return yesNoBoxClose();
|
|
||||||
});
|
|
||||||
yesNoBoxCreate(
|
|
||||||
"WARNING: USING THIS PROGRAM WILL CAUSE YOU TO LOSE ALL OF YOUR PROGRESS ON THE CURRENT BITNODE.<br><br>" +
|
|
||||||
"Do you want to travel to the BitNode Nexus? This allows you to reset the current BitNode " +
|
|
||||||
"and select a new one.",
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!programHandlers.hasOwnProperty(programName)) {
|
if (!programHandlers.hasOwnProperty(programName)) {
|
||||||
|
@ -5,18 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
import { convertTimeMsToTimeElapsedString, replaceAt } from "../utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString, replaceAt } from "../utils/StringHelperFunctions";
|
||||||
import { Augmentations } from "./Augmentation/Augmentations";
|
import { Augmentations } from "./Augmentation/Augmentations";
|
||||||
import {
|
import { initAugmentations, installAugmentations } from "./Augmentation/AugmentationHelpers";
|
||||||
initAugmentations,
|
|
||||||
displayAugmentationsContent,
|
|
||||||
installAugmentations,
|
|
||||||
} from "./Augmentation/AugmentationHelpers";
|
|
||||||
import { onExport } from "./ExportBonus";
|
import { onExport } from "./ExportBonus";
|
||||||
import { AugmentationsRoot } from "./Augmentation/ui/Root";
|
import { AugmentationsRoot } from "./Augmentation/ui/Root";
|
||||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||||
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
||||||
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||||
import { CharacterOverviewComponent } from "./ui/React/CharacterOverview";
|
import { CharacterOverview } from "./ui/React/CharacterOverview";
|
||||||
import { cinematicTextFlag } from "./CinematicText";
|
|
||||||
import { generateRandomContract } from "./CodingContractGenerator";
|
import { generateRandomContract } from "./CodingContractGenerator";
|
||||||
import { initCompanies } from "./Company/Companies";
|
import { initCompanies } from "./Company/Companies";
|
||||||
import { Corporation } from "./Corporation/Corporation";
|
import { Corporation } from "./Corporation/Corporation";
|
||||||
@ -37,7 +32,6 @@ import {
|
|||||||
getFactionSecurityWorkRepGain,
|
getFactionSecurityWorkRepGain,
|
||||||
getFactionFieldWorkRepGain,
|
getFactionFieldWorkRepGain,
|
||||||
} from "./PersonObjects/formulas/reputation";
|
} from "./PersonObjects/formulas/reputation";
|
||||||
import { FconfSettings } from "./Fconf/FconfSettings";
|
|
||||||
import { hasHacknetServers, processHacknetEarnings } from "./Hacknet/HacknetHelpers";
|
import { hasHacknetServers, processHacknetEarnings } from "./Hacknet/HacknetHelpers";
|
||||||
import { HacknetRoot } from "./Hacknet/ui/HacknetRoot";
|
import { HacknetRoot } from "./Hacknet/ui/HacknetRoot";
|
||||||
import { iTutorialStart } from "./InteractiveTutorial";
|
import { iTutorialStart } from "./InteractiveTutorial";
|
||||||
@ -50,7 +44,6 @@ import { loadAllRunningScripts, updateOnlineScriptTimes } from "./NetscriptWorke
|
|||||||
import { Player } from "./Player";
|
import { Player } from "./Player";
|
||||||
import { prestigeAugmentation } from "./Prestige";
|
import { prestigeAugmentation } from "./Prestige";
|
||||||
import { ProgramsRoot } from "./Programs/ui/ProgramsRoot";
|
import { ProgramsRoot } from "./Programs/ui/ProgramsRoot";
|
||||||
import { redPillFlag } from "./RedPill";
|
|
||||||
import { saveObject, loadGame } from "./SaveObject";
|
import { saveObject, loadGame } from "./SaveObject";
|
||||||
import { Root as ScriptEditorRoot } from "./ScriptEditor/ui/Root";
|
import { Root as ScriptEditorRoot } from "./ScriptEditor/ui/Root";
|
||||||
import { initForeignServers, AllServers } from "./Server/AllServers";
|
import { initForeignServers, AllServers } from "./Server/AllServers";
|
||||||
@ -72,8 +65,7 @@ import { Hashes } from "./ui/React/Hashes";
|
|||||||
import { Reputation } from "./ui/React/Reputation";
|
import { Reputation } from "./ui/React/Reputation";
|
||||||
|
|
||||||
import { ActiveScriptsRoot } from "./ui/ActiveScripts/Root";
|
import { ActiveScriptsRoot } from "./ui/ActiveScripts/Root";
|
||||||
import { initializeMainMenuHeaders } from "./ui/MainMenu/Headers";
|
import { MainMenuLinks } from "./ui/MainMenu/Links";
|
||||||
import { initializeMainMenuLinks, MainMenuLinks } from "./ui/MainMenu/Links";
|
|
||||||
|
|
||||||
import { FileDiagnosticPopup } from "./Diagnostic/FileDiagnosticPopup";
|
import { FileDiagnosticPopup } from "./Diagnostic/FileDiagnosticPopup";
|
||||||
import { createPopup } from "./ui/React/createPopup";
|
import { createPopup } from "./ui/React/createPopup";
|
||||||
@ -82,90 +74,12 @@ import { dialogBoxCreate } from "../utils/DialogBox";
|
|||||||
import { gameOptionsBoxClose, gameOptionsBoxOpen } from "../utils/GameOptions";
|
import { gameOptionsBoxClose, gameOptionsBoxOpen } from "../utils/GameOptions";
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||||
import { removeLoadingScreen } from "../utils/uiHelpers/removeLoadingScreen";
|
import { removeLoadingScreen } from "../utils/uiHelpers/removeLoadingScreen";
|
||||||
import { KEY } from "../utils/helpers/keyCodes";
|
|
||||||
import "./Exploits/tampering";
|
import "./Exploits/tampering";
|
||||||
import "./Exploits/unclickable";
|
import "./Exploits/unclickable";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcuts to navigate through the game
|
|
||||||
* Alt-t - Terminal
|
|
||||||
* Alt-c - Character
|
|
||||||
* Alt-e - Script editor
|
|
||||||
* Alt-s - Active scripts
|
|
||||||
* Alt-h - Hacknet Nodes
|
|
||||||
* Alt-w - City
|
|
||||||
* Alt-j - Job
|
|
||||||
* Alt-r - Travel Agency of current city
|
|
||||||
* Alt-p - Create program
|
|
||||||
* Alt-f - Factions
|
|
||||||
* Alt-a - Augmentations
|
|
||||||
* Alt-u - Tutorial
|
|
||||||
* Alt-o - Options
|
|
||||||
*/
|
|
||||||
$(document).keydown(function (e) {
|
|
||||||
if (Settings.DisableHotkeys === true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Player.isWorking && !redPillFlag && !inMission && !cinematicTextFlag) {
|
|
||||||
if (e.keyCode == KEY.T && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadTerminalContent();
|
|
||||||
} else if (e.keyCode === KEY.C && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadCharacterContent();
|
|
||||||
} else if (e.keyCode === KEY.E && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadScriptEditorContent();
|
|
||||||
} else if (e.keyCode === KEY.S && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadActiveScriptsContent();
|
|
||||||
} else if (e.keyCode === KEY.H && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadHacknetNodesContent();
|
|
||||||
} else if (e.keyCode === KEY.W && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadLocationContent();
|
|
||||||
} else if (e.keyCode === KEY.J && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadJobContent();
|
|
||||||
} else if (e.keyCode === KEY.R && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadTravelContent();
|
|
||||||
} else if (e.keyCode === KEY.P && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadCreateProgramContent();
|
|
||||||
} else if (e.keyCode === KEY.F && e.altKey) {
|
|
||||||
// Overriden by Fconf
|
|
||||||
if (routing.isOn(Page.Terminal) && FconfSettings.ENABLE_BASH_HOTKEYS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadFactionsContent();
|
|
||||||
} else if (e.keyCode === KEY.A && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadAugmentationsContent();
|
|
||||||
} else if (e.keyCode === KEY.U && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadTutorialContent();
|
|
||||||
} else if (e.keyCode === KEY.B && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadBladeburnerContent();
|
|
||||||
} else if (e.keyCode === KEY.G && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
Engine.loadGangContent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.keyCode === KEY.O && e.altKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
gameOptionsBoxOpen();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const Engine = {
|
const Engine = {
|
||||||
// Clickable objects
|
// Clickable objects
|
||||||
Clickables: {
|
Clickables: {
|
||||||
@ -457,7 +371,7 @@ const Engine = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
displayCharacterOverviewInfo: function () {
|
displayCharacterOverviewInfo: function () {
|
||||||
ReactDOM.render(<CharacterOverviewComponent />, document.getElementById("character-overview-text"));
|
ReactDOM.render(<CharacterOverview player={Player} />, document.getElementById("character-overview-text"));
|
||||||
|
|
||||||
const save = document.getElementById("character-overview-save-button");
|
const save = document.getElementById("character-overview-save-button");
|
||||||
const flashClass = "flashing-button";
|
const flashClass = "flashing-button";
|
||||||
@ -635,11 +549,6 @@ const Engine = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Engine.Counters.updateSkillLevelsCounter <= 0) {
|
|
||||||
Player.updateSkillLevels();
|
|
||||||
Engine.Counters.updateSkillLevelsCounter = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Engine.Counters.updateDisplays <= 0) {
|
if (Engine.Counters.updateDisplays <= 0) {
|
||||||
Engine.displayCharacterOverviewInfo();
|
Engine.displayCharacterOverviewInfo();
|
||||||
Engine.Counters.updateDisplays = 3;
|
Engine.Counters.updateDisplays = 3;
|
||||||
|
@ -87,21 +87,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Faction Invitation Pop-up Box -->
|
|
||||||
<div id="faction-invitation-box-container" class="popup-box-container">
|
|
||||||
<div id="faction-invitation-box-content" class="popup-box-content">
|
|
||||||
<p id="faction-invitation-box-text"></p>
|
|
||||||
<p id="faction-invitation-box-message"></p>
|
|
||||||
<p id="faction-invitation-box-warning">
|
|
||||||
Would you like to join? <br />
|
|
||||||
<br />
|
|
||||||
Warning: Joining this faction may prevent you from joining other factions during this run!
|
|
||||||
</p>
|
|
||||||
<button id="faction-invitation-box-yes" class="popup-box-button">Join!</button>
|
|
||||||
<button id="faction-invitation-box-no" class="popup-box-button">Decide later</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mission container -->
|
<!-- Mission container -->
|
||||||
<div id="mission-container" class="generic-fullscreen-container"></div>
|
<div id="mission-container" class="generic-fullscreen-container"></div>
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ export function ActiveScriptsRoot(props: IProps): React.ReactElement {
|
|||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
}
|
}
|
||||||
const [divisionName, setDivisionName] = useState("Overview");
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const id = setInterval(rerender, 20);
|
const id = setInterval(rerender, 20);
|
||||||
|
@ -22,7 +22,6 @@ export function CharacterInfo(props: IProps): React.ReactElement {
|
|||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
}
|
}
|
||||||
const [divisionName, setDivisionName] = useState("Overview");
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const id = setInterval(rerender, 20);
|
const id = setInterval(rerender, 20);
|
||||||
@ -230,13 +229,8 @@ export function CharacterInfo(props: IProps): React.ReactElement {
|
|||||||
</span>
|
</span>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<div style={{ width: "60%", fontSize: "13px", marginLeft: "4%" }}>
|
<div style={{ width: "60%", fontSize: "13px", marginLeft: "2%" }}>
|
||||||
{BitNodes[index].info.split("<br>").map((t, i) => (
|
<span style={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>{BitNodes[index].info}</span>
|
||||||
<div key={i}>
|
|
||||||
<span style={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>{t}</span>
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,109 +0,0 @@
|
|||||||
// Root React Component for the Corporation UI
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import { Player } from "../../Player";
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
|
||||||
import { Reputation } from "./Reputation";
|
|
||||||
|
|
||||||
const Component = React.Component;
|
|
||||||
|
|
||||||
export class CharacterOverviewComponent extends Component {
|
|
||||||
render() {
|
|
||||||
const intelligence = (
|
|
||||||
<tr id="character-int-wrapper">
|
|
||||||
<td className="character-int-cell">Int: </td>
|
|
||||||
<td id="character-int-text" className="character-int-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatSkill(Player.intelligence)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
|
|
||||||
/*const work = (
|
|
||||||
<div>
|
|
||||||
<p>Work progress:</p>
|
|
||||||
<p>+{Reputation(Player.workRepGained)} rep</p>
|
|
||||||
<button onClick={() => Player.startFocusing()} id="character-overview-options-button" className="character-overview-btn">Focus</button>
|
|
||||||
</div>
|
|
||||||
);*/
|
|
||||||
const work = (
|
|
||||||
<>
|
|
||||||
<tr className="character-divider">
|
|
||||||
<td colSpan="2">Work progress:</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colSpan="2">+{Reputation(Player.workRepGained)} rep</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colSpan="2">
|
|
||||||
<button
|
|
||||||
onClick={() => Player.startFocusing()}
|
|
||||||
id="character-overview-options-button"
|
|
||||||
className="character-overview-btn"
|
|
||||||
>
|
|
||||||
Focus
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr id="character-hp-wrapper">
|
|
||||||
<td className="character-hp-cell">HP:</td>
|
|
||||||
<td id="character-hp-text" className="character-hp-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatHp(Player.hp) + " / " + numeralWrapper.formatHp(Player.max_hp)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="character-money-wrapper">
|
|
||||||
<td className="character-money-cell">Money: </td>
|
|
||||||
<td id="character-money-text" className="character-money-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatMoney(Player.money.toNumber())}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="character-hack-wrapper">
|
|
||||||
<td className="character-hack-cell">Hack: </td>
|
|
||||||
<td id="character-hack-text" className="character-hack-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatSkill(Player.hacking_skill)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="character-str-wrapper" className="character-divider">
|
|
||||||
<td className="character-combat-cell">Str: </td>
|
|
||||||
<td id="character-str-text" className="character-combat-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatSkill(Player.strength)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="character-def-wrapper">
|
|
||||||
<td className="character-combat-cell">Def: </td>
|
|
||||||
<td id="character-def-text" className="character-combat-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatSkill(Player.defense)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="character-dex-wrapper">
|
|
||||||
<td className="character-combat-cell">Dex: </td>
|
|
||||||
<td id="character-dex-text" className="character-combat-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatSkill(Player.dexterity)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="character-agi-wrapper">
|
|
||||||
<td className="character-combat-cell">Agi: </td>
|
|
||||||
<td id="character-agi-text" className="character-combat-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatSkill(Player.agility)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="character-cha-wrapper" className="character-divider">
|
|
||||||
<td className="character-cha-cell">Cha: </td>
|
|
||||||
<td id="character-cha-text" className="character-cha-cell character-stat-cell">
|
|
||||||
{numeralWrapper.formatSkill(Player.charisma)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{Player.intelligence >= 1 && intelligence}
|
|
||||||
{Player.isWorking && !Player.focus && work}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
102
src/ui/React/CharacterOverview.tsx
Normal file
102
src/ui/React/CharacterOverview.tsx
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// Root React Component for the Corporation UI
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
import { Reputation } from "./Reputation";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
player: IPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CharacterOverview(props: IProps): React.ReactElement {
|
||||||
|
const intelligence = (
|
||||||
|
<tr id="character-int-wrapper">
|
||||||
|
<td className="character-int-cell">Int: </td>
|
||||||
|
<td id="character-int-text" className="character-int-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatSkill(props.player.intelligence)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
|
||||||
|
const work = (
|
||||||
|
<>
|
||||||
|
<tr className="character-divider">
|
||||||
|
<td colSpan={2}>Work progress:</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colSpan={2}>+{Reputation(props.player.workRepGained)} rep</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<button
|
||||||
|
onClick={() => props.player.startFocusing()}
|
||||||
|
id="character-overview-options-button"
|
||||||
|
className="character-overview-btn"
|
||||||
|
>
|
||||||
|
Focus
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr id="character-hp-wrapper">
|
||||||
|
<td className="character-hp-cell">HP:</td>
|
||||||
|
<td id="character-hp-text" className="character-hp-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatHp(props.player.hp) + " / " + numeralWrapper.formatHp(props.player.max_hp)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="character-money-wrapper">
|
||||||
|
<td className="character-money-cell">Money: </td>
|
||||||
|
<td id="character-money-text" className="character-money-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatMoney(props.player.money.toNumber())}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="character-hack-wrapper">
|
||||||
|
<td className="character-hack-cell">Hack: </td>
|
||||||
|
<td id="character-hack-text" className="character-hack-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatSkill(props.player.hacking_skill)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="character-str-wrapper" className="character-divider">
|
||||||
|
<td className="character-combat-cell">Str: </td>
|
||||||
|
<td id="character-str-text" className="character-combat-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatSkill(props.player.strength)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="character-def-wrapper">
|
||||||
|
<td className="character-combat-cell">Def: </td>
|
||||||
|
<td id="character-def-text" className="character-combat-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatSkill(props.player.defense)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="character-dex-wrapper">
|
||||||
|
<td className="character-combat-cell">Dex: </td>
|
||||||
|
<td id="character-dex-text" className="character-combat-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatSkill(props.player.dexterity)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="character-agi-wrapper">
|
||||||
|
<td className="character-combat-cell">Agi: </td>
|
||||||
|
<td id="character-agi-text" className="character-combat-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatSkill(props.player.agility)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="character-cha-wrapper" className="character-divider">
|
||||||
|
<td className="character-cha-cell">Cha: </td>
|
||||||
|
<td id="character-cha-text" className="character-cha-cell character-stat-cell">
|
||||||
|
{numeralWrapper.formatSkill(props.player.charisma)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{props.player.intelligence >= 1 && intelligence}
|
||||||
|
{props.player.isWorking && !props.player.focus && work}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
43
src/ui/React/CinematicLine.tsx
Normal file
43
src/ui/React/CinematicLine.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
text: string;
|
||||||
|
onDone?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleep(ms: number): Promise<void> {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CinematicLine(props: IProps): React.ReactElement {
|
||||||
|
const [length, setLength] = useState(0);
|
||||||
|
const [done, setDone] = useState(false);
|
||||||
|
|
||||||
|
function advance(): void {
|
||||||
|
const newLength = length + 1;
|
||||||
|
setLength(newLength);
|
||||||
|
setDone(newLength >= props.text.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (done && props.onDone) {
|
||||||
|
props.onDone();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let cancel = false;
|
||||||
|
(async () => {
|
||||||
|
await sleep(10).then(() => !cancel && advance());
|
||||||
|
})();
|
||||||
|
return () => {
|
||||||
|
cancel = true;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<pre>
|
||||||
|
{props.text.slice(0, length)}
|
||||||
|
{!done && <span>█</span>}
|
||||||
|
</pre>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
27
src/ui/React/CinematicText.tsx
Normal file
27
src/ui/React/CinematicText.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
import { CinematicLine } from "./CinematicLine";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
lines: string[];
|
||||||
|
onDone?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CinematicText(props: IProps): React.ReactElement {
|
||||||
|
const [i, setI] = useState(0);
|
||||||
|
|
||||||
|
function advance(): void {
|
||||||
|
const newI = i + 1;
|
||||||
|
setI(newI);
|
||||||
|
if (newI >= props.lines.length && props.onDone) props.onDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{props.lines.slice(0, i).map((line, i) => (
|
||||||
|
<pre key={i}>{line}</pre>
|
||||||
|
))}
|
||||||
|
{props.lines.length > i && <CinematicLine key={i} text={props.lines[i]} onDone={advance} />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -7,11 +7,11 @@ interface IProps {
|
|||||||
content: JSX.Element;
|
content: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MessagePopup(props: IProps): React.ReactElement {
|
function MessagePopup(props: IProps): React.ReactElement {
|
||||||
return <>{props.content}</>;
|
return <>{props.content}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dialogBoxCreate(txt: string | JSX.Element, preformatted = false): void {
|
export function dialogBoxCreate(txt: string | JSX.Element, preformatted = false): void {
|
||||||
const popupId =
|
const popupId =
|
||||||
`popup-` +
|
`popup-` +
|
||||||
Array.from(Array(16))
|
Array.from(Array(16))
|
||||||
@ -41,5 +41,3 @@ function dialogBoxCreate(txt: string | JSX.Element, preformatted = false): void
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { dialogBoxCreate };
|
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
import { joinFaction } from "../src/Faction/FactionHelpers";
|
|
||||||
import { Engine } from "../src/engine";
|
|
||||||
import { Player } from "../src/Player";
|
|
||||||
import { clearEventListeners } from "./uiHelpers/clearEventListeners";
|
|
||||||
import { Page, routing } from "../src/ui/navigationTracking";
|
|
||||||
|
|
||||||
/* Faction Invitation Pop-up box */
|
|
||||||
function factionInvitationBoxClose() {
|
|
||||||
var factionInvitationBox = document.getElementById("faction-invitation-box-container");
|
|
||||||
factionInvitationBox.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
function factionInvitationBoxOpen() {
|
|
||||||
var factionInvitationBox = document.getElementById("faction-invitation-box-container");
|
|
||||||
factionInvitationBox.style.display = "flex";
|
|
||||||
}
|
|
||||||
|
|
||||||
function factionInvitationSetText(txt) {
|
|
||||||
var textBox = document.getElementById("faction-invitation-box-text");
|
|
||||||
textBox.innerHTML = txt;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ram argument is in GB
|
|
||||||
function factionInvitationBoxCreate(faction) {
|
|
||||||
factionInvitationSetText("You have received a faction invitation from " + faction.name);
|
|
||||||
faction.alreadyInvited = true;
|
|
||||||
Player.factionInvitations.push(faction.name);
|
|
||||||
|
|
||||||
if (routing.isOn(Page.Factions)) {
|
|
||||||
Engine.loadFactionsContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
var newYesButton = clearEventListeners("faction-invitation-box-yes");
|
|
||||||
newYesButton.addEventListener("click", function () {
|
|
||||||
//Remove from invited factions
|
|
||||||
var i = Player.factionInvitations.findIndex((facName) => {
|
|
||||||
return facName === faction.name;
|
|
||||||
});
|
|
||||||
if (i === -1) {
|
|
||||||
console.error("Could not find faction in Player.factionInvitations");
|
|
||||||
}
|
|
||||||
joinFaction(faction);
|
|
||||||
factionInvitationBoxClose();
|
|
||||||
if (routing.isOn(Page.Factions)) {
|
|
||||||
Engine.loadFactionsContent();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
var noButton = clearEventListeners("faction-invitation-box-no");
|
|
||||||
noButton.addEventListener("click", function () {
|
|
||||||
factionInvitationBoxClose();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
factionInvitationBoxOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
export { factionInvitationBoxCreate };
|
|
@ -1,168 +0,0 @@
|
|||||||
/**
|
|
||||||
* Generic Yes-No Pop-up box
|
|
||||||
* Used to create pop-up boxes that require a yes/no response from player
|
|
||||||
*
|
|
||||||
* There are two types of pop ups:
|
|
||||||
* 1. Just a Yes/No response from player
|
|
||||||
* 2. Popup also includes a text input field in addition to the Yes/No response
|
|
||||||
*/
|
|
||||||
import { clearEventListeners } from "./uiHelpers/clearEventListeners";
|
|
||||||
import { KEY } from "./helpers/keyCodes";
|
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
|
|
||||||
export let yesNoBoxOpen = false;
|
|
||||||
|
|
||||||
const yesNoBoxContainer: HTMLElement | null = document.getElementById("yes-no-box-container");
|
|
||||||
const yesNoBoxTextElement: HTMLElement | null = document.getElementById("yes-no-box-text");
|
|
||||||
|
|
||||||
function yesNoBoxHotkeyHandler(e: KeyboardEvent): void {
|
|
||||||
if (e.keyCode === KEY.ESC) {
|
|
||||||
yesNoBoxClose();
|
|
||||||
} else if (e.keyCode === KEY.ENTER) {
|
|
||||||
const yesBtn: HTMLElement | null = document.getElementById("yes-no-box-yes");
|
|
||||||
if (yesBtn) {
|
|
||||||
yesBtn.click();
|
|
||||||
} else {
|
|
||||||
console.error(`Could not find YesNoBox Yes button DOM element`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoBoxClose(): boolean {
|
|
||||||
if (yesNoBoxContainer) {
|
|
||||||
yesNoBoxContainer.style.display = "none";
|
|
||||||
} else {
|
|
||||||
console.error("Container not found for YesNoBox");
|
|
||||||
}
|
|
||||||
yesNoBoxOpen = false;
|
|
||||||
|
|
||||||
// Remove hotkey handler
|
|
||||||
document.removeEventListener("keydown", yesNoBoxHotkeyHandler);
|
|
||||||
|
|
||||||
return false; //So that 'return yesNoBoxClose()' is return false in event listeners
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoBoxGetYesButton(): HTMLElement | null {
|
|
||||||
return clearEventListeners("yes-no-box-yes");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoBoxGetNoButton(): HTMLElement | null {
|
|
||||||
return clearEventListeners("yes-no-box-no");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoBoxCreate(txt: string | JSX.Element): boolean {
|
|
||||||
if (yesNoBoxOpen) {
|
|
||||||
return false;
|
|
||||||
} //Already open
|
|
||||||
yesNoBoxOpen = true;
|
|
||||||
|
|
||||||
if (yesNoBoxTextElement) {
|
|
||||||
ReactDOM.unmountComponentAtNode(yesNoBoxTextElement);
|
|
||||||
yesNoBoxTextElement.innerHTML = "";
|
|
||||||
if (typeof txt === "string") {
|
|
||||||
yesNoBoxTextElement.innerHTML = txt as string;
|
|
||||||
} else {
|
|
||||||
ReactDOM.render(txt, yesNoBoxTextElement);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error(`Text element not found for YesNoBox`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yesNoBoxContainer) {
|
|
||||||
yesNoBoxContainer.style.display = "flex";
|
|
||||||
} else {
|
|
||||||
console.error("Container not found for YesNoBox");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add event listener for Esc and Enter hotkeys
|
|
||||||
document.addEventListener("keydown", yesNoBoxHotkeyHandler);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Yes-No pop up box with text input field
|
|
||||||
*/
|
|
||||||
const yesNoTextInputBoxContainer: HTMLElement | null = document.getElementById("yes-no-text-input-box-container");
|
|
||||||
const yesNoTextInputBoxInput: HTMLInputElement | null = document.getElementById(
|
|
||||||
"yes-no-text-input-box-input",
|
|
||||||
) as HTMLInputElement;
|
|
||||||
const yesNoTextInputBoxTextElement: HTMLElement | null = document.getElementById("yes-no-text-input-box-text");
|
|
||||||
|
|
||||||
export function yesNoTxtInpBoxHotkeyHandler(e: KeyboardEvent): void {
|
|
||||||
if (e.keyCode === KEY.ESC) {
|
|
||||||
yesNoTxtInpBoxClose();
|
|
||||||
} else if (e.keyCode === KEY.ENTER) {
|
|
||||||
const yesBtn: HTMLElement | null = document.getElementById("yes-no-text-input-box-yes");
|
|
||||||
if (yesBtn) {
|
|
||||||
yesBtn.click();
|
|
||||||
} else {
|
|
||||||
console.error(`Could not find YesNoTxtInputBox Yes button DOM element`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoTxtInpBoxClose(): boolean {
|
|
||||||
if (yesNoTextInputBoxContainer != null) {
|
|
||||||
yesNoTextInputBoxContainer.style.display = "none";
|
|
||||||
} else {
|
|
||||||
console.error("Container not found for YesNoTextInputBox");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!yesNoTextInputBoxInput) throw new Error("yesNoTextInputBoxInput was not set");
|
|
||||||
yesNoBoxOpen = false;
|
|
||||||
yesNoTextInputBoxInput.value = "";
|
|
||||||
|
|
||||||
// Remove hotkey handler
|
|
||||||
document.removeEventListener("keydown", yesNoTxtInpBoxHotkeyHandler);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoTxtInpBoxGetYesButton(): HTMLElement {
|
|
||||||
const elem = clearEventListeners("yes-no-text-input-box-yes");
|
|
||||||
if (elem === null) throw new Error("Could not find element with id: 'yes-no-text-input-box-yes'");
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoTxtInpBoxGetNoButton(): HTMLElement {
|
|
||||||
const elem = clearEventListeners("yes-no-text-input-box-no");
|
|
||||||
if (elem === null) throw new Error("Could not find element with id: 'yes-no-text-input-box-no'");
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoTxtInpBoxGetInput(): string {
|
|
||||||
if (!yesNoTextInputBoxInput) {
|
|
||||||
console.error("Could not find YesNoTextInputBox input element");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
let val: string = yesNoTextInputBoxInput.value;
|
|
||||||
val = val.replace(/\s+/g, "");
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function yesNoTxtInpBoxCreate(txt: string | JSX.Element): void {
|
|
||||||
yesNoBoxOpen = true;
|
|
||||||
|
|
||||||
if (yesNoTextInputBoxTextElement) {
|
|
||||||
ReactDOM.unmountComponentAtNode(yesNoTextInputBoxTextElement);
|
|
||||||
yesNoTextInputBoxTextElement.innerHTML = "";
|
|
||||||
if (typeof txt === "string") {
|
|
||||||
yesNoTextInputBoxTextElement.innerHTML = txt;
|
|
||||||
} else {
|
|
||||||
ReactDOM.render(txt, yesNoTextInputBoxTextElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yesNoTextInputBoxContainer) {
|
|
||||||
yesNoTextInputBoxContainer.style.display = "flex";
|
|
||||||
} else {
|
|
||||||
console.error("Container not found for YesNoTextInputBox");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add event listener for Esc and Enter hotkeys
|
|
||||||
document.addEventListener("keydown", yesNoTxtInpBoxHotkeyHandler);
|
|
||||||
|
|
||||||
if (!yesNoTextInputBoxInput) throw new Error("yesNoTextInputBoxInput was not set");
|
|
||||||
yesNoTextInputBoxInput.focus();
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user