mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-22 22:22:26 +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 { AugmentationNames } from "./data/AugmentationNames";
|
||||
|
||||
import { AugmentationsRoot } from "./ui/Root";
|
||||
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { Factions, factionExists } from "../Faction/Factions";
|
||||
import { Player } from "../Player";
|
||||
import { prestigeAugmentation } from "../Prestige";
|
||||
import { saveObject } from "../SaveObject";
|
||||
import { Page, routing } from "../ui/navigationTracking";
|
||||
import { onExport } from "../ExportBonus";
|
||||
import { Programs } from "../Programs/Programs";
|
||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
||||
|
||||
@ -22,7 +17,6 @@ import { clearObject } from "../../utils/helpers/clearObject";
|
||||
import { WHRNG } from "../Casino/RNG";
|
||||
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
function AddToAugmentations(aug) {
|
||||
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 { IIndustry } from "./IIndustry";
|
||||
import { IndustryStartingCosts } from "./IndustryData";
|
||||
import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
|
||||
import { Industry } from "./Industry";
|
||||
import { CorporationConstants } from "./data/Constants";
|
||||
import { OfficeSpace } from "./OfficeSpace";
|
||||
@ -13,7 +13,6 @@ import { Cities } from "../Locations/Cities";
|
||||
import { EmployeePositions } from "./EmployeePositions";
|
||||
import { Employee } from "./Employee";
|
||||
import { IndustryUpgrades } from "./IndustryUpgrades";
|
||||
import { IndustryResearchTrees } from "./IndustryData";
|
||||
import { ResearchMap } from "./ResearchMap";
|
||||
|
||||
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 possibleIndustries = allIndustries
|
||||
.filter(
|
||||
(industryType: string) =>
|
||||
props.corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
|
||||
(industryType: string) => props.corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
|
||||
)
|
||||
.sort();
|
||||
if (possibleIndustries.length === 0) return <></>;
|
||||
|
@ -18,7 +18,6 @@ import { ProductMarketTaPopup } from "./ProductMarketTaPopup";
|
||||
import { SmartSupplyPopup } from "./SmartSupplyPopup";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
|
||||
import { isString } from "../../../utils/helpers/isString";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
import { Product } from "../Product";
|
||||
import { LimitProductProduction } from "../Actions";
|
||||
|
@ -2,7 +2,6 @@ import React, { useState } from "react";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
import { Industries } from "../IndustryData";
|
||||
import { Product } from "../Product";
|
||||
import { ICorporation } from "../ICorporation";
|
||||
import { IIndustry } from "../IIndustry";
|
||||
import { MakeProduct } from "../Actions";
|
||||
|
@ -3,7 +3,6 @@ import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
import { IndustryResearchTrees } from "../IndustryData";
|
||||
import { CorporationConstants } from "../data/Constants";
|
||||
import { ResearchMap } from "../ResearchMap";
|
||||
import { Treant } from "treant-js";
|
||||
import { IIndustry } from "../IIndustry";
|
||||
import { Research } from "../Actions";
|
||||
@ -50,9 +49,6 @@ export function ResearchPopup(props: IProps): React.ReactElement {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the Research object
|
||||
const research = ResearchMap[allResearch[i]];
|
||||
|
||||
// Get the DOM Element to add a click listener to it
|
||||
const sanitizedName = allResearch[i].replace(/\s/g, "");
|
||||
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 { Programs } from "./Programs/Programs";
|
||||
import { Factions } from "./Faction/Factions";
|
||||
import { Player } from "./Player";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
|
||||
import { AllServers } from "./Server/AllServers";
|
||||
@ -18,14 +17,9 @@ import { IEngine } from "./IEngine";
|
||||
import { saveObject } from "./SaveObject";
|
||||
|
||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
import { Money } from "./ui/React/Money";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
const Component = React.Component;
|
||||
|
||||
// Update as additional BitNodes get implemented
|
||||
const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
||||
@ -41,7 +35,7 @@ interface IValueAdjusterProps {
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
function ValueAdjusterComponent(props: IValueAdjusterProps) {
|
||||
function ValueAdjusterComponent(props: IValueAdjusterProps): React.ReactElement {
|
||||
const [value, setValue] = useState(0);
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
@ -120,28 +114,28 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
|
||||
function addMoney(n: number) {
|
||||
return function () {
|
||||
Player.gainMoney(n);
|
||||
props.player.gainMoney(n);
|
||||
};
|
||||
}
|
||||
|
||||
function upgradeRam() {
|
||||
Player.getHomeComputer().maxRam *= 2;
|
||||
function upgradeRam(): void {
|
||||
props.player.getHomeComputer().maxRam *= 2;
|
||||
}
|
||||
|
||||
function quickB1tFlum3() {
|
||||
hackWorldDaemon(Player.bitNodeN, true, true);
|
||||
function quickB1tFlum3(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN, true, true);
|
||||
}
|
||||
|
||||
function b1tflum3() {
|
||||
hackWorldDaemon(Player.bitNodeN, true);
|
||||
function b1tflum3(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN, true);
|
||||
}
|
||||
|
||||
function quickHackW0r1dD43m0n() {
|
||||
hackWorldDaemon(Player.bitNodeN, false, true);
|
||||
function quickHackW0r1dD43m0n(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN, false, true);
|
||||
}
|
||||
|
||||
function hackW0r1dD43m0n() {
|
||||
hackWorldDaemon(Player.bitNodeN);
|
||||
function hackW0r1dD43m0n(): void {
|
||||
hackWorldDaemon(props.player.bitNodeN);
|
||||
}
|
||||
|
||||
function modifyExp(stat: string, modifier: number) {
|
||||
@ -149,127 +143,127 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
switch (stat) {
|
||||
case "hacking":
|
||||
if (exp) {
|
||||
Player.gainHackingExp(exp * modifier);
|
||||
props.player.gainHackingExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "strength":
|
||||
if (exp) {
|
||||
Player.gainStrengthExp(exp * modifier);
|
||||
props.player.gainStrengthExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "defense":
|
||||
if (exp) {
|
||||
Player.gainDefenseExp(exp * modifier);
|
||||
props.player.gainDefenseExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "dexterity":
|
||||
if (exp) {
|
||||
Player.gainDexterityExp(exp * modifier);
|
||||
props.player.gainDexterityExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "agility":
|
||||
if (exp) {
|
||||
Player.gainAgilityExp(exp * modifier);
|
||||
props.player.gainAgilityExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "charisma":
|
||||
if (exp) {
|
||||
Player.gainCharismaExp(exp * modifier);
|
||||
props.player.gainCharismaExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "intelligence":
|
||||
if (exp) {
|
||||
Player.gainIntelligenceExp(exp * modifier);
|
||||
props.player.gainIntelligenceExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Player.updateSkillLevels();
|
||||
props.player.updateSkillLevels();
|
||||
};
|
||||
}
|
||||
|
||||
function modifyKarma(modifier: number) {
|
||||
return function (amt: number) {
|
||||
Player.karma += amt * modifier;
|
||||
props.player.karma += amt * modifier;
|
||||
};
|
||||
}
|
||||
|
||||
function tonsOfExp() {
|
||||
Player.gainHackingExp(tonsPP);
|
||||
Player.gainStrengthExp(tonsPP);
|
||||
Player.gainDefenseExp(tonsPP);
|
||||
Player.gainDexterityExp(tonsPP);
|
||||
Player.gainAgilityExp(tonsPP);
|
||||
Player.gainCharismaExp(tonsPP);
|
||||
Player.gainIntelligenceExp(tonsPP);
|
||||
Player.updateSkillLevels();
|
||||
function tonsOfExp(): void {
|
||||
props.player.gainHackingExp(tonsPP);
|
||||
props.player.gainStrengthExp(tonsPP);
|
||||
props.player.gainDefenseExp(tonsPP);
|
||||
props.player.gainDexterityExp(tonsPP);
|
||||
props.player.gainAgilityExp(tonsPP);
|
||||
props.player.gainCharismaExp(tonsPP);
|
||||
props.player.gainIntelligenceExp(tonsPP);
|
||||
props.player.updateSkillLevels();
|
||||
}
|
||||
|
||||
function resetAllExp() {
|
||||
Player.hacking_exp = 0;
|
||||
Player.strength_exp = 0;
|
||||
Player.defense_exp = 0;
|
||||
Player.dexterity_exp = 0;
|
||||
Player.agility_exp = 0;
|
||||
Player.charisma_exp = 0;
|
||||
Player.intelligence_exp = 0;
|
||||
Player.updateSkillLevels();
|
||||
function resetAllExp(): void {
|
||||
props.player.hacking_exp = 0;
|
||||
props.player.strength_exp = 0;
|
||||
props.player.defense_exp = 0;
|
||||
props.player.dexterity_exp = 0;
|
||||
props.player.agility_exp = 0;
|
||||
props.player.charisma_exp = 0;
|
||||
props.player.intelligence_exp = 0;
|
||||
props.player.updateSkillLevels();
|
||||
}
|
||||
|
||||
function resetExperience(stat: string): () => void {
|
||||
return function () {
|
||||
switch (stat) {
|
||||
case "hacking":
|
||||
Player.hacking_exp = 0;
|
||||
props.player.hacking_exp = 0;
|
||||
break;
|
||||
case "strength":
|
||||
Player.strength_exp = 0;
|
||||
props.player.strength_exp = 0;
|
||||
break;
|
||||
case "defense":
|
||||
Player.defense_exp = 0;
|
||||
props.player.defense_exp = 0;
|
||||
break;
|
||||
case "dexterity":
|
||||
Player.dexterity_exp = 0;
|
||||
props.player.dexterity_exp = 0;
|
||||
break;
|
||||
case "agility":
|
||||
Player.agility_exp = 0;
|
||||
props.player.agility_exp = 0;
|
||||
break;
|
||||
case "charisma":
|
||||
Player.charisma_exp = 0;
|
||||
props.player.charisma_exp = 0;
|
||||
break;
|
||||
case "intelligence":
|
||||
Player.intelligence_exp = 0;
|
||||
props.player.intelligence_exp = 0;
|
||||
break;
|
||||
}
|
||||
Player.updateSkillLevels();
|
||||
props.player.updateSkillLevels();
|
||||
};
|
||||
}
|
||||
|
||||
function resetKarma() {
|
||||
function resetKarma(): () => void {
|
||||
return function () {
|
||||
Player.karma = 0;
|
||||
props.player.karma = 0;
|
||||
};
|
||||
}
|
||||
|
||||
function enableIntelligence() {
|
||||
if (Player.intelligence === 0) {
|
||||
Player.intelligence = 1;
|
||||
Player.updateSkillLevels();
|
||||
function enableIntelligence(): void {
|
||||
if (props.player.intelligence === 0) {
|
||||
props.player.intelligence = 1;
|
||||
props.player.updateSkillLevels();
|
||||
}
|
||||
}
|
||||
|
||||
function disableIntelligence() {
|
||||
Player.intelligence_exp = 0;
|
||||
Player.intelligence = 0;
|
||||
Player.updateSkillLevels();
|
||||
function disableIntelligence(): void {
|
||||
props.player.intelligence_exp = 0;
|
||||
props.player.intelligence = 0;
|
||||
props.player.updateSkillLevels();
|
||||
}
|
||||
|
||||
function receiveInvite() {
|
||||
Player.receiveInvite(faction);
|
||||
function receiveInvite(): void {
|
||||
props.player.receiveInvite(faction);
|
||||
}
|
||||
|
||||
function receiveAllInvites() {
|
||||
function receiveAllInvites(): void {
|
||||
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];
|
||||
if (fac != null) {
|
||||
fac.playerReputation = 0;
|
||||
@ -298,63 +292,63 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
};
|
||||
}
|
||||
|
||||
function resetFactionFavor() {
|
||||
function resetFactionFavor(): void {
|
||||
const fac = Factions[faction];
|
||||
if (fac != null) {
|
||||
fac.favor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function tonsOfRep() {
|
||||
function tonsOfRep(): void {
|
||||
for (const i in Factions) {
|
||||
Factions[i].playerReputation = tonsPP;
|
||||
}
|
||||
}
|
||||
|
||||
function resetAllRep() {
|
||||
function resetAllRep(): void {
|
||||
for (const i in Factions) {
|
||||
Factions[i].playerReputation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function tonsOfFactionFavor() {
|
||||
function tonsOfFactionFavor(): void {
|
||||
for (const i in Factions) {
|
||||
Factions[i].favor = tonsPP;
|
||||
}
|
||||
}
|
||||
|
||||
function resetAllFactionFavor() {
|
||||
function resetAllFactionFavor(): void {
|
||||
for (const i in Factions) {
|
||||
Factions[i].favor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function queueAug() {
|
||||
Player.queueAugmentation(augmentation);
|
||||
function queueAug(): void {
|
||||
props.player.queueAugmentation(augmentation);
|
||||
}
|
||||
|
||||
function queueAllAugs() {
|
||||
function queueAllAugs(): void {
|
||||
for (const i in AugmentationNames) {
|
||||
const augName = AugmentationNames[i];
|
||||
Player.queueAugmentation(augName);
|
||||
props.player.queueAugmentation(augName);
|
||||
}
|
||||
}
|
||||
|
||||
function setSF(sfN: number, sfLvl: number) {
|
||||
return function () {
|
||||
if (sfLvl === 0) {
|
||||
Player.sourceFiles = Player.sourceFiles.filter((sf) => sf.n !== sfN);
|
||||
props.player.sourceFiles = props.player.sourceFiles.filter((sf) => sf.n !== sfN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Player.sourceFiles.some((sf) => sf.n === sfN)) {
|
||||
Player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl));
|
||||
if (!props.player.sourceFiles.some((sf) => sf.n === sfN)) {
|
||||
props.player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl));
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < Player.sourceFiles.length; i++) {
|
||||
if (Player.sourceFiles[i].n === sfN) {
|
||||
Player.sourceFiles[i].lvl = sfLvl;
|
||||
for (let i = 0; i < props.player.sourceFiles.length; i++) {
|
||||
if (props.player.sourceFiles[i].n === sfN) {
|
||||
props.player.sourceFiles[i].lvl = sfLvl;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -368,25 +362,25 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
};
|
||||
}
|
||||
|
||||
function clearExploits() {
|
||||
Player.exploits = [];
|
||||
function clearExploits(): void {
|
||||
props.player.exploits = [];
|
||||
}
|
||||
|
||||
function addProgram() {
|
||||
if (!Player.hasProgram(program)) {
|
||||
Player.getHomeComputer().programs.push(program);
|
||||
function addProgram(): void {
|
||||
if (!props.player.hasProgram(program)) {
|
||||
props.player.getHomeComputer().programs.push(program);
|
||||
}
|
||||
}
|
||||
|
||||
function addAllPrograms() {
|
||||
function addAllPrograms(): void {
|
||||
for (const i in Programs) {
|
||||
if (!Player.hasProgram(Programs[i].name)) {
|
||||
Player.getHomeComputer().programs.push(Programs[i].name);
|
||||
if (!props.player.hasProgram(Programs[i].name)) {
|
||||
props.player.getHomeComputer().programs.push(Programs[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function rootServer() {
|
||||
function rootServer(): void {
|
||||
const s = GetServerByHostname(server);
|
||||
if (s === null) return;
|
||||
if (s instanceof HacknetServer) return;
|
||||
@ -399,7 +393,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
s.openPortCount = 5;
|
||||
}
|
||||
|
||||
function rootAllServers() {
|
||||
function rootAllServers(): void {
|
||||
for (const i in AllServers) {
|
||||
const s = AllServers[i];
|
||||
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);
|
||||
if (s === null) return;
|
||||
if (s instanceof HacknetServer) return;
|
||||
s.hackDifficulty = s.minDifficulty;
|
||||
}
|
||||
|
||||
function minAllSecurity() {
|
||||
function minAllSecurity(): void {
|
||||
for (const i in AllServers) {
|
||||
const server = AllServers[i];
|
||||
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);
|
||||
if (s === null) return;
|
||||
if (s instanceof HacknetServer) return;
|
||||
s.moneyAvailable = s.moneyMax;
|
||||
}
|
||||
|
||||
function maxAllMoney() {
|
||||
function maxAllMoney(): void {
|
||||
for (const i in AllServers) {
|
||||
const server = AllServers[i];
|
||||
if (server instanceof HacknetServer) continue;
|
||||
@ -495,98 +489,98 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
|
||||
function modifyBladeburnerRank(modify: number): (x: number) => void {
|
||||
return function (rank: number): void {
|
||||
if (Player.bladeburner) {
|
||||
Player.bladeburner.changeRank(Player, rank * modify);
|
||||
if (props.player.bladeburner) {
|
||||
props.player.bladeburner.changeRank(props.player, rank * modify);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetBladeburnerRank(): void {
|
||||
Player.bladeburner.rank = 0;
|
||||
Player.bladeburner.maxRank = 0;
|
||||
props.player.bladeburner.rank = 0;
|
||||
props.player.bladeburner.maxRank = 0;
|
||||
}
|
||||
|
||||
function addTonsBladeburnerRank(): void {
|
||||
if (Player.bladeburner) {
|
||||
Player.bladeburner.changeRank(Player, tonsP);
|
||||
if (props.player.bladeburner) {
|
||||
props.player.bladeburner.changeRank(props.player, tonsP);
|
||||
}
|
||||
}
|
||||
|
||||
function modifyBladeburnerCycles(modify: number): (x: number) => void {
|
||||
return function (cycles: number): void {
|
||||
if (Player.bladeburner) {
|
||||
Player.bladeburner.storedCycles += cycles * modify;
|
||||
if (props.player.bladeburner) {
|
||||
props.player.bladeburner.storedCycles += cycles * modify;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetBladeburnerCycles(): void {
|
||||
if (Player.bladeburner) {
|
||||
Player.bladeburner.storedCycles = 0;
|
||||
if (props.player.bladeburner) {
|
||||
props.player.bladeburner.storedCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function addTonsBladeburnerCycles(): void {
|
||||
if (Player.bladeburner) {
|
||||
Player.bladeburner.storedCycles += tonsP;
|
||||
if (props.player.bladeburner) {
|
||||
props.player.bladeburner.storedCycles += tonsP;
|
||||
}
|
||||
}
|
||||
|
||||
function addTonsGangCycles(): void {
|
||||
if (Player.gang) {
|
||||
Player.gang.storedCycles = tonsP;
|
||||
if (props.player.gang) {
|
||||
props.player.gang.storedCycles = tonsP;
|
||||
}
|
||||
}
|
||||
|
||||
function modifyGangCycles(modify: number): (x: number) => void {
|
||||
return function (cycles: number): void {
|
||||
if (Player.gang) {
|
||||
Player.gang.storedCycles += cycles * modify;
|
||||
if (props.player.gang) {
|
||||
props.player.gang.storedCycles += cycles * modify;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetGangCycles(): void {
|
||||
if (Player.gang) {
|
||||
Player.gang.storedCycles = 0;
|
||||
if (props.player.gang) {
|
||||
props.player.gang.storedCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function addTonsCorporationFunds(): void {
|
||||
if (Player.corporation) {
|
||||
Player.corporation.funds = Player.corporation.funds.plus(1e99);
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.funds = props.player.corporation.funds.plus(1e99);
|
||||
}
|
||||
}
|
||||
|
||||
function resetCorporationFunds(): void {
|
||||
if (Player.corporation) {
|
||||
Player.corporation.funds = Player.corporation.funds.minus(Player.corporation.funds);
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.funds = props.player.corporation.funds.minus(props.player.corporation.funds);
|
||||
}
|
||||
}
|
||||
|
||||
function addTonsCorporationCycles() {
|
||||
if (Player.corporation) {
|
||||
Player.corporation.storedCycles = tonsP;
|
||||
function addTonsCorporationCycles(): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.storedCycles = tonsP;
|
||||
}
|
||||
}
|
||||
|
||||
function modifyCorporationCycles(modify: number): (x: number) => void {
|
||||
return function (cycles: number): void {
|
||||
if (Player.corporation) {
|
||||
Player.corporation.storedCycles += cycles * modify;
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.storedCycles += cycles * modify;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetCorporationCycles() {
|
||||
if (Player.corporation) {
|
||||
Player.corporation.storedCycles = 0;
|
||||
function resetCorporationCycles(): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.storedCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function finishCorporationProducts() {
|
||||
if (!Player.corporation) return;
|
||||
Player.corporation.divisions.forEach((div) => {
|
||||
function finishCorporationProducts(): void {
|
||||
if (!props.player.corporation) return;
|
||||
props.player.corporation.divisions.forEach((div) => {
|
||||
Object.keys(div.products).forEach((prod) => {
|
||||
const product = div.products[prod];
|
||||
if (product === undefined) throw new Error("Impossible product undefined");
|
||||
@ -595,29 +589,29 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
});
|
||||
}
|
||||
|
||||
function addCorporationResearch() {
|
||||
if (!Player.corporation) return;
|
||||
Player.corporation.divisions.forEach((div) => {
|
||||
function addCorporationResearch(): void {
|
||||
if (!props.player.corporation) return;
|
||||
props.player.corporation.divisions.forEach((div) => {
|
||||
div.sciResearch.qty += 1e10;
|
||||
});
|
||||
}
|
||||
|
||||
function specificContract() {
|
||||
function specificContract(): void {
|
||||
generateContract({
|
||||
problemType: codingcontract,
|
||||
server: "home",
|
||||
});
|
||||
}
|
||||
|
||||
function processStocks(sub: (arg0: Stock) => void) {
|
||||
function processStocks(sub: (arg0: Stock) => void): void {
|
||||
const inputSymbols = stockSymbol.replace(/\s/g, "");
|
||||
|
||||
let match = function (symbol: string) {
|
||||
let match: (symbol: string) => boolean = (): boolean => {
|
||||
return true;
|
||||
};
|
||||
|
||||
if (inputSymbols !== "" && inputSymbols !== "all") {
|
||||
match = function (symbol: string) {
|
||||
match = function (symbol: string): boolean {
|
||||
return inputSymbols.split(",").includes(symbol);
|
||||
};
|
||||
}
|
||||
@ -632,7 +626,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
}
|
||||
}
|
||||
|
||||
function doSetStockPrice() {
|
||||
function doSetStockPrice(): void {
|
||||
if (!isNaN(stockPrice)) {
|
||||
processStocks((stock: Stock) => {
|
||||
stock.price = stockPrice;
|
||||
@ -640,8 +634,8 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
}
|
||||
}
|
||||
|
||||
function viewStockCaps() {
|
||||
let stocks: JSX.Element[] = [];
|
||||
function viewStockCaps(): void {
|
||||
const stocks: JSX.Element[] = [];
|
||||
processStocks((stock: Stock) => {
|
||||
stocks.push(
|
||||
<tr key={stock.symbol}>
|
||||
@ -665,40 +659,40 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
function sleeveMaxAllShock() {
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].shock = 0;
|
||||
function sleeveMaxAllShock(): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].shock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function sleeveClearAllShock() {
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].shock = 100;
|
||||
function sleeveClearAllShock(): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].shock = 100;
|
||||
}
|
||||
}
|
||||
|
||||
function sleeveSyncMaxAll() {
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].sync = 100;
|
||||
function sleeveSyncMaxAll(): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].sync = 100;
|
||||
}
|
||||
}
|
||||
|
||||
function sleeveSyncClearAll() {
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].sync = 0;
|
||||
function sleeveSyncClearAll(): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].sync = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function timeskip(time: number) {
|
||||
return () => {
|
||||
Player.lastUpdate -= time;
|
||||
props.player.lastUpdate -= time;
|
||||
props.engine._lastUpdate -= time;
|
||||
saveObject.saveGame(props.engine.indexedDb);
|
||||
setTimeout(() => location.reload(), 1000);
|
||||
};
|
||||
}
|
||||
|
||||
let factions = [];
|
||||
const factions = [];
|
||||
for (const i in Factions) {
|
||||
factions.push(
|
||||
<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) {
|
||||
augs.push(
|
||||
<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) {
|
||||
programs.push(
|
||||
<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) {
|
||||
const hn = AllServers[i].hostname;
|
||||
servers.push(
|
||||
@ -735,7 +729,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
let companies = [];
|
||||
const companies = [];
|
||||
for (const c in Companies) {
|
||||
const name = Companies[c].name;
|
||||
companies.push(
|
||||
@ -1310,7 +1304,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{Player.bladeburner instanceof Bladeburner && (
|
||||
{props.player.bladeburner instanceof Bladeburner && (
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<div className="row">
|
||||
@ -1360,7 +1354,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{Player.inGang() && (
|
||||
{props.player.inGang() && (
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<div className="row">
|
||||
@ -1392,7 +1386,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{Player.hasCorporation() && (
|
||||
{props.player.hasCorporation() && (
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<div className="row">
|
||||
@ -1485,7 +1479,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{Player.hasWseAccount && (
|
||||
{props.player.hasWseAccount && (
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<div className="row">
|
||||
@ -1540,7 +1534,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{Player.sleeves.length > 0 && (
|
||||
{props.player.sleeves.length > 0 && (
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<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 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 displayFactionContent(factionName: string, initiallyOnAugmentationsPage: boolean = false);
|
||||
export declare function joinFaction(faction: Faction): void;
|
||||
|
@ -4,7 +4,6 @@ import ReactDOM from "react-dom";
|
||||
import { FactionRoot } from "./ui/Root";
|
||||
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
import { isRepeatableAug } from "../Augmentation/AugmentationHelpers";
|
||||
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
@ -22,21 +21,20 @@ import {
|
||||
} from "../PersonObjects/formulas/reputation";
|
||||
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
|
||||
|
||||
import { Page, routing } from "../ui/navigationTracking";
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import { factionInvitationBoxCreate } from "../../utils/FactionInvitationBox";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import { yesNoBoxCreate, yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose } from "../../utils/YesNoBox";
|
||||
import { createPopup } from "../ui/React/createPopup";
|
||||
import { InvitationPopup } from "./ui/InvitationPopup";
|
||||
|
||||
export function inviteToFaction(faction) {
|
||||
if (Settings.SuppressFactionInvites) {
|
||||
faction.alreadyInvited = true;
|
||||
Player.factionInvitations.push(faction.name);
|
||||
if (routing.isOn(Page.Factions)) {
|
||||
Engine.loadFactionsContent();
|
||||
}
|
||||
} else {
|
||||
factionInvitationBoxCreate(faction);
|
||||
Player.factionInvitations.push(faction.name);
|
||||
faction.alreadyInvited = true;
|
||||
if (!Settings.SuppressFactionInvites) {
|
||||
const popupId = "faction-invitation";
|
||||
createPopup(popupId, InvitationPopup, {
|
||||
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
|
||||
//specified Augmentation
|
||||
export function hasAugmentationPrereqs(aug) {
|
||||
|
@ -123,8 +123,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
render(): React.ReactNode {
|
||||
const augs = this.getAugsSorted();
|
||||
const purchasable = augs.filter(
|
||||
(aug: string) =>
|
||||
aug === AugmentationNames.NeuroFluxGovernor ||
|
||||
(aug: string) => aug === AugmentationNames.NeuroFluxGovernor ||
|
||||
(!this.props.p.augmentations.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 {
|
||||
getNextNeurofluxLevel,
|
||||
hasAugmentationPrereqs,
|
||||
purchaseAugmentation,
|
||||
purchaseAugmentationBoxCreate,
|
||||
} from "../FactionHelpers";
|
||||
import { getNextNeurofluxLevel, hasAugmentationPrereqs, purchaseAugmentation } from "../FactionHelpers";
|
||||
import { PurchaseAugmentationPopup } from "./PurchaseAugmentationPopup";
|
||||
|
||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
@ -19,6 +15,7 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { IMap } from "../../types";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
@ -31,15 +28,6 @@ type IProps = {
|
||||
rerender: () => void;
|
||||
};
|
||||
|
||||
const spanStyleMarkup = {
|
||||
margin: "4px",
|
||||
padding: "4px",
|
||||
};
|
||||
|
||||
const inlineStyleMarkup = {
|
||||
display: "inline-block",
|
||||
};
|
||||
|
||||
export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
||||
aug: Augmentation;
|
||||
|
||||
@ -63,7 +51,13 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
||||
|
||||
handleClick(): void {
|
||||
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 {
|
||||
purchaseAugmentation(this.aug, this.props.faction);
|
||||
}
|
||||
@ -170,12 +164,19 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
||||
);
|
||||
|
||||
return (
|
||||
<li>
|
||||
<span style={spanStyleMarkup}>
|
||||
<li key={this.aug.name}>
|
||||
<span
|
||||
style={{
|
||||
margin: "4px",
|
||||
padding: "4px",
|
||||
}}
|
||||
>
|
||||
<StdButton
|
||||
disabled={disabled}
|
||||
onClick={this.handleClick}
|
||||
style={inlineStyleMarkup}
|
||||
style={{
|
||||
display: "inline-block",
|
||||
}}
|
||||
text={btnTxt}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
|
@ -2,10 +2,8 @@ import { Engine } from "./engine";
|
||||
import { Player } from "./Player";
|
||||
import { Settings } from "./Settings/Settings";
|
||||
|
||||
import { initializeMainMenuLinks } from "./ui/MainMenu/Links";
|
||||
import { LiteratureNames } from "./Literature/data/LiteratureNames";
|
||||
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
|
@ -4,24 +4,12 @@
|
||||
*/
|
||||
import { CONSTANTS } from "../Constants";
|
||||
|
||||
import { CityName } from "./data/CityNames";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { AddToAllServers, createUniqueRandomIp } from "../Server/AllServers";
|
||||
import { safetlyCreateUniqueServer } from "../Server/ServerHelpers";
|
||||
import { SpecialServerIps } from "../Server/SpecialServerIps";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
|
||||
import { Money } from "../ui/React/Money";
|
||||
|
||||
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
|
||||
|
@ -23,8 +23,8 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
|
||||
import { yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose, yesNoBoxCreate } from "../../../utils/YesNoBox";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { QuitJobPopup } from "../../Company/ui/QuitJobPopup";
|
||||
|
||||
type IProps = {
|
||||
engine: IEngine;
|
||||
@ -246,27 +246,15 @@ export class CompanyLocation extends React.Component<IProps, IState> {
|
||||
}
|
||||
|
||||
quit(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const yesBtn = yesNoBoxGetYesButton();
|
||||
const noBtn = yesNoBoxGetNoButton();
|
||||
if (yesBtn == null || noBtn == null) {
|
||||
return;
|
||||
}
|
||||
yesBtn.innerHTML = "Quit job";
|
||||
noBtn.innerHTML = "Cancel";
|
||||
yesBtn.addEventListener("click", () => {
|
||||
this.props.p.quitJob(this.props.locName);
|
||||
this.checkIfEmployedHere(true);
|
||||
yesNoBoxClose();
|
||||
if (!e.isTrusted) return;
|
||||
const popupId = `quit-job-popup`;
|
||||
createPopup(popupId, QuitJobPopup, {
|
||||
locName: this.props.locName,
|
||||
company: this.company,
|
||||
player: this.props.p,
|
||||
onQuit: () => this.checkIfEmployedHere(true),
|
||||
popupId: popupId,
|
||||
});
|
||||
noBtn.addEventListener("click", () => {
|
||||
yesNoBoxClose();
|
||||
});
|
||||
|
||||
yesNoBoxCreate(<>Would you like to quit your job at {this.company.name}?</>);
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
@ -421,6 +409,11 @@ export class CompanyLocation extends React.Component<IProps, IState> {
|
||||
{this.location.infiltrationData != null && (
|
||||
<StdButton onClick={this.startInfiltration} style={this.btnStyle} text={"Infiltrate Company"} />
|
||||
)}
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -63,8 +63,7 @@ function ListWorldMap(props: IProps): React.ReactElement {
|
||||
.map((city: string) => (
|
||||
<StdButton
|
||||
key={city}
|
||||
onClick={() =>
|
||||
createTravelPopup(props.p, city, () => props.travel(CityName[city as keyof typeof CityName]))
|
||||
onClick={() => createTravelPopup(props.p, city, () => props.travel(CityName[city as keyof typeof CityName]))
|
||||
}
|
||||
style={{ display: "block" }}
|
||||
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,
|
||||
SetProductMarketTA2,
|
||||
} from "./Corporation/Actions";
|
||||
import { Reviver } from "../utils/JSONReviver";
|
||||
import { CorporationUnlockUpgrades } from "./Corporation/data/CorporationUnlockUpgrades";
|
||||
import { CorporationUpgrades } from "./Corporation/data/CorporationUpgrades";
|
||||
import {
|
||||
@ -4523,12 +4522,12 @@ function NetscriptFunctions(workerScript) {
|
||||
},
|
||||
unlockUpgrade: function (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);
|
||||
},
|
||||
levelUpgrade: function (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);
|
||||
},
|
||||
issueDividends: function (percent) {
|
||||
|
@ -9,6 +9,7 @@ import { Sleeve } from "./Sleeve/Sleeve";
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
||||
import { Augmentation } from "../Augmentation/Augmentation";
|
||||
import { Company } from "../Company/Company";
|
||||
import { CompanyPosition } from "../Company/CompanyPosition";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
@ -119,6 +120,9 @@ export interface IPlayer {
|
||||
bladeburner_analysis_mult: number;
|
||||
bladeburner_success_chance_mult: number;
|
||||
|
||||
workRepGained: number;
|
||||
focus: boolean;
|
||||
|
||||
// Methods
|
||||
applyForAgentJob(sing?: boolean): boolean | void;
|
||||
applyForBusinessConsultantJob(sing?: boolean): boolean | void;
|
||||
@ -154,6 +158,7 @@ export interface IPlayer {
|
||||
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition;
|
||||
getUpgradeHomeRamCost(): number;
|
||||
gotoLocation(to: LocationName): boolean;
|
||||
hasAugmentation(aug: Augmentation): boolean;
|
||||
hasCorporation(): boolean;
|
||||
hasGangWith(facName: string): boolean;
|
||||
hasTorRouter(): boolean;
|
||||
@ -186,6 +191,7 @@ export interface IPlayer {
|
||||
startFactionFieldWork(faction: Faction): void;
|
||||
startFactionHackWork(faction: Faction): void;
|
||||
startFactionSecurityWork(faction: Faction): void;
|
||||
startFocusing(): void;
|
||||
startGang(facName: string, isHacking: boolean): void;
|
||||
startWork(companyName: string): void;
|
||||
startWorkPartTime(companyName: string): void;
|
||||
|
@ -60,11 +60,9 @@ const SortFunctions: {
|
||||
Dexterity: (a: Resleeve, b: Resleeve): number => a.dexterity - b.dexterity,
|
||||
Agility: (a: Resleeve, b: Resleeve): number => a.agility - b.agility,
|
||||
Charisma: (a: Resleeve, b: Resleeve): number => a.charisma - b.charisma,
|
||||
AverageCombatStats: (a: Resleeve, b: Resleeve): number =>
|
||||
getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
||||
AverageCombatStats: (a: Resleeve, b: Resleeve): number => getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
||||
getAverage(b.strength, b.defense, b.dexterity, b.agility),
|
||||
AverageAllStats: (a: Resleeve, b: Resleeve): number =>
|
||||
getAverage(a.hacking_skill, a.strength, a.defense, a.dexterity, a.agility, a.charisma) -
|
||||
AverageAllStats: (a: Resleeve, b: Resleeve): number => 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),
|
||||
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 Faction": (player: IPlayer, sleeve: Sleeve) => possibleFactions(player, sleeve).length > 0,
|
||||
"Commit Crime": () => true,
|
||||
"Take University Course": (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),
|
||||
"Take University Course": (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,
|
||||
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 [s2, setS2] = useState(abc[2]);
|
||||
|
||||
const validActions = Object.keys(canDo).filter((k) =>
|
||||
(canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve),
|
||||
const validActions = Object.keys(canDo).filter((k) => (canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve),
|
||||
);
|
||||
|
||||
const detailsF = tasks[s0];
|
||||
|
@ -2,7 +2,6 @@ import { Programs } from "./Programs";
|
||||
import { Program } from "./Program";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { createElement } from "../../utils/uiHelpers/createElement";
|
||||
|
||||
//Returns the programs this player can create.
|
||||
export function getAvailableCreatePrograms(player: IPlayer): Program[] {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Programs } from "../Programs";
|
||||
import { getAvailableCreatePrograms } from "../ProgramHelpers";
|
||||
|
||||
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 { iTutorialSteps, iTutorialNextStep, ITutorial } from "../../InteractiveTutorial";
|
||||
import { getAvailableCreatePrograms } from "../../Programs/ProgramHelpers";
|
||||
import { ICorporation } from "../../Corporation/ICorporation";
|
||||
import { IGang } from "../../Gang/IGang";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
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 {
|
||||
player: IPlayer;
|
||||
@ -16,13 +22,13 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
const [divisionName, setDivisionName] = useState("Overview");
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 20);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
const [activeTab, setActiveTab] = useState("");
|
||||
const [hackingOpen, setHackingOpen] = useState(true);
|
||||
const [characterOpen, setCharacterOpen] = useState(true);
|
||||
const [worldOpen, setWorldOpen] = useState(true);
|
||||
@ -42,36 +48,6 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
|
||||
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 canCreateProgram =
|
||||
programCount > 0 ||
|
||||
@ -101,6 +77,182 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
const canStockMarket = props.player.hasWseAccount;
|
||||
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 (
|
||||
<ul id="mainmenu" className="mainmenu noscrollbar noselect">
|
||||
{/* Hacking dropdown */}
|
||||
@ -119,22 +271,33 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
</li>
|
||||
{hackingOpen && (
|
||||
<>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashTerminal ? "flashing-button" : ""} onClick={clickTerminal}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button
|
||||
className={(flashTerminal ? "flashing-button" : "") + activeTab === "Terminal" ? " active" : ""}
|
||||
onClick={clickTerminal}
|
||||
>
|
||||
Terminal
|
||||
</button>
|
||||
</li>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadScriptEditorContent()}>Create Script</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "CreateScripts" ? " active" : ""} onClick={clickCreateScripts}>
|
||||
Create Script
|
||||
</button>
|
||||
</li>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashActiveScripts ? "flashing-button" : ""} onClick={clickActiveScripts}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button
|
||||
className={(flashActiveScripts ? "flashing-button" : "") + activeTab === "ActiveScripts" ? " active" : ""}
|
||||
onClick={clickActiveScripts}
|
||||
>
|
||||
Active Scripts
|
||||
</button>
|
||||
</li>
|
||||
{canCreateProgram && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className="notification" onClick={() => props.engine.loadCreateProgramContent()}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button
|
||||
className={"notification" + (activeTab === "CreateProgram" ? " active" : "")}
|
||||
onClick={clickCreateProgram}
|
||||
>
|
||||
Create Program
|
||||
{programCount > 0 && <span className="badge">{programCount}</span>}
|
||||
</button>
|
||||
@ -155,14 +318,17 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
</li>
|
||||
{characterOpen && (
|
||||
<>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashStats ? "flashing-button" : ""} onClick={clickStats}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button
|
||||
className={(flashStats ? "flashing-button" : "") + activeTab === "Stats" ? " active" : ""}
|
||||
onClick={clickStats}
|
||||
>
|
||||
Stats
|
||||
</button>
|
||||
</li>
|
||||
{canOpenFactions && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className="notification" onClick={() => props.engine.loadFactionsContent()}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={"notification" + (activeTab === "Factions" ? " active" : "")} onClick={clickFactions}>
|
||||
Factions
|
||||
{props.player.factionInvitations.length > 0 && (
|
||||
<span className="badge">{props.player.factionInvitations.length}</span>
|
||||
@ -171,8 +337,11 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
</li>
|
||||
)}
|
||||
{canOpenAugmentations && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className="notification" onClick={() => props.engine.loadAugmentationsContent()}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button
|
||||
className={"notification" + (activeTab === "Augmentations" ? " active" : "")}
|
||||
onClick={clickAugmentations}
|
||||
>
|
||||
Augmentations
|
||||
{props.player.queuedAugmentations.length > 0 && (
|
||||
<span className="badge">{props.player.queuedAugmentations.length}</span>
|
||||
@ -180,14 +349,19 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashHacknet ? "flashing-button" : ""} onClick={clickHacknet}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button
|
||||
className={(flashHacknet ? "flashing-button" : "") + activeTab === "Hacknet" ? " active" : ""}
|
||||
onClick={clickHacknet}
|
||||
>
|
||||
Hacknet
|
||||
</button>
|
||||
</li>
|
||||
{canOpenSleeves && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadSleevesContent()}>Sleeves</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "Sleeves" ? " active" : ""} onClick={clickSleeves}>
|
||||
Sleeves
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
</>
|
||||
@ -205,37 +379,52 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
|
||||
{worldOpen && (
|
||||
<>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashCity ? "flashing-button" : ""} onClick={clickCity}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button
|
||||
className={(flashCity ? "flashing-button" : "") + activeTab === "City" ? " active" : ""}
|
||||
onClick={clickCity}
|
||||
>
|
||||
City
|
||||
</button>
|
||||
</li>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadTravelContent()}>Travel</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "Travel" ? " active" : ""} onClick={clickTravel}>
|
||||
Travel
|
||||
</button>
|
||||
</li>
|
||||
{canJob && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadJobContent()}>Job</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "Job" ? " active" : ""} onClick={clickJob}>
|
||||
Job
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
{canStockMarket && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadStockMarketContent()}>Stock Market</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "StockMarket" ? " active" : ""} onClick={clickStockMarket}>
|
||||
Stock Market
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
{canBladeburner && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadBladeburnerContent()}>Bladeburner</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "Bladeburner" ? " active" : ""} onClick={clickBladeburner}>
|
||||
Bladeburner
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
{canCorporation && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadCorporationContent()}>Corp</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "Corp" ? " active" : ""} onClick={clickCorp}>
|
||||
Corp
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
{canGang && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadGangContent()}>Gang</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "Gang" ? " active" : ""} onClick={clickGang}>
|
||||
Gang
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
</>
|
||||
@ -251,11 +440,16 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
</li>
|
||||
{helpOpen && (
|
||||
<>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadMilestonesContent()}>Milestones</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "Milestones" ? " active" : ""} onClick={clickMilestones}>
|
||||
Milestones
|
||||
</button>
|
||||
</li>
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button className={flashTutorial ? "flashing-button" : ""} onClick={clickTutorial}>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button
|
||||
className={(flashTutorial ? "flashing-button" : "") + activeTab === "Tutorial" ? " active" : ""}
|
||||
onClick={clickTutorial}
|
||||
>
|
||||
Tutorial
|
||||
</button>
|
||||
</li>
|
||||
@ -263,8 +457,10 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
<button>Options</button>
|
||||
</li>*/}
|
||||
{process.env.NODE_ENV === "development" && (
|
||||
<li className="mainmenu-accordion-panel">
|
||||
<button onClick={() => props.engine.loadDevMenuContent()}>Dev</button>
|
||||
<li className={`mainmenu-accordion-panel`}>
|
||||
<button className={activeTab === "Dev" ? " active" : ""} onClick={clickDev}>
|
||||
Dev
|
||||
</button>
|
||||
</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 { StockTickerPositionText } from "./StockTickerPositionText";
|
||||
import { StockTickerTxButton } from "./StockTickerTxButton";
|
||||
import { PlaceOrderPopup } from "./PlaceOrderPopup";
|
||||
|
||||
import { Order } from "../Order";
|
||||
import { Stock } from "../Stock";
|
||||
@ -19,15 +20,9 @@ import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Accordion } from "../../ui/React/Accordion";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import {
|
||||
yesNoTxtInpBoxClose,
|
||||
yesNoTxtInpBoxCreate,
|
||||
yesNoTxtInpBoxGetInput,
|
||||
yesNoTxtInpBoxGetNoButton,
|
||||
yesNoTxtInpBoxGetYesButton,
|
||||
} from "../../../utils/YesNoBox";
|
||||
|
||||
enum SelectorOrderType {
|
||||
Market = "Market Order",
|
||||
@ -85,30 +80,6 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
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 {
|
||||
const stock = this.props.stock;
|
||||
const qty: number = this.getQuantity();
|
||||
@ -182,23 +153,23 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
break;
|
||||
}
|
||||
case SelectorOrderType.Limit: {
|
||||
this.createPlaceOrderPopupBox(
|
||||
"Place Buy Limit Order",
|
||||
"Enter the price for your Limit Order",
|
||||
(price: number) => {
|
||||
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitBuy, this.state.position);
|
||||
},
|
||||
);
|
||||
const popupId = `place-order-popup`;
|
||||
createPopup(popupId, PlaceOrderPopup, {
|
||||
text: "Enter the price for your Limit Order",
|
||||
placeText: "Place Buy Limit Order",
|
||||
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitBuy, this.state.position),
|
||||
popupId: popupId,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case SelectorOrderType.Stop: {
|
||||
this.createPlaceOrderPopupBox(
|
||||
"Place Buy Stop Order",
|
||||
"Enter the price for your Stop Order",
|
||||
(price: number) => {
|
||||
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopBuy, this.state.position);
|
||||
},
|
||||
);
|
||||
const popupId = `place-order-popup`;
|
||||
createPopup(popupId, PlaceOrderPopup, {
|
||||
text: "Enter the price for your Stop Order",
|
||||
placeText: "Place Buy Stop Order",
|
||||
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopBuy, this.state.position),
|
||||
popupId: popupId,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -304,23 +275,23 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
break;
|
||||
}
|
||||
case SelectorOrderType.Limit: {
|
||||
this.createPlaceOrderPopupBox(
|
||||
"Place Sell Limit Order",
|
||||
"Enter the price for your Limit Order",
|
||||
(price: number) => {
|
||||
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitSell, this.state.position);
|
||||
},
|
||||
);
|
||||
const popupId = `place-order-popup`;
|
||||
createPopup(popupId, PlaceOrderPopup, {
|
||||
text: "Enter the price for your Limit Order",
|
||||
placeText: "Place Sell Limit Order",
|
||||
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.LimitSell, this.state.position),
|
||||
popupId: popupId,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case SelectorOrderType.Stop: {
|
||||
this.createPlaceOrderPopupBox(
|
||||
"Place Sell Stop Order",
|
||||
"Enter the price for your Stop Order",
|
||||
(price: number) => {
|
||||
this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopSell, this.state.position);
|
||||
},
|
||||
);
|
||||
const popupId = `place-order-popup`;
|
||||
createPopup(popupId, PlaceOrderPopup, {
|
||||
text: "Enter the price for your Stop Order",
|
||||
placeText: "Place Sell Stop Order",
|
||||
place: (price: number) => this.props.placeOrder(this.props.stock, shares, price, OrderTypes.StopSell, this.state.position),
|
||||
popupId: popupId,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -53,10 +53,11 @@ import { KEY } from "../utils/helpers/keyCodes";
|
||||
import { arrayToString } from "../utils/helpers/arrayToString";
|
||||
import { getTimestamp } from "../utils/helpers/getTimestamp";
|
||||
import { logBoxCreate } from "../utils/LogBox";
|
||||
import { yesNoBoxCreate, yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose } from "../utils/YesNoBox";
|
||||
import { post, postElement, postContent, postError, hackProgressBarPost, hackProgressPost } from "./ui/postToTerminal";
|
||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
import { Money } from "./ui/React/Money";
|
||||
import { createPopup } from "./ui/React/createPopup";
|
||||
import { BitFlumePopup } from "./BitNode/ui/BitFlumePopup";
|
||||
|
||||
import autosize from "autosize";
|
||||
import * as JSZip from "jszip";
|
||||
@ -2374,22 +2375,11 @@ let Terminal = {
|
||||
post("-- Daedalus --");
|
||||
};
|
||||
programHandlers[Programs.BitFlume.name] = () => {
|
||||
const yesBtn = yesNoBoxGetYesButton();
|
||||
const noBtn = yesNoBoxGetNoButton();
|
||||
yesBtn.innerHTML = "Travel to BitNode Nexus";
|
||||
noBtn.innerHTML = "Cancel";
|
||||
yesBtn.addEventListener("click", function () {
|
||||
hackWorldDaemon(Player.bitNodeN, true);
|
||||
return yesNoBoxClose();
|
||||
const popupId = "bitflume-popup";
|
||||
createPopup(popupId, BitFlumePopup, {
|
||||
player: Player,
|
||||
popupId: popupId,
|
||||
});
|
||||
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)) {
|
||||
|
@ -5,18 +5,13 @@
|
||||
*/
|
||||
import { convertTimeMsToTimeElapsedString, replaceAt } from "../utils/StringHelperFunctions";
|
||||
import { Augmentations } from "./Augmentation/Augmentations";
|
||||
import {
|
||||
initAugmentations,
|
||||
displayAugmentationsContent,
|
||||
installAugmentations,
|
||||
} from "./Augmentation/AugmentationHelpers";
|
||||
import { initAugmentations, installAugmentations } from "./Augmentation/AugmentationHelpers";
|
||||
import { onExport } from "./ExportBonus";
|
||||
import { AugmentationsRoot } from "./Augmentation/ui/Root";
|
||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
||||
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||
import { CharacterOverviewComponent } from "./ui/React/CharacterOverview";
|
||||
import { cinematicTextFlag } from "./CinematicText";
|
||||
import { CharacterOverview } from "./ui/React/CharacterOverview";
|
||||
import { generateRandomContract } from "./CodingContractGenerator";
|
||||
import { initCompanies } from "./Company/Companies";
|
||||
import { Corporation } from "./Corporation/Corporation";
|
||||
@ -37,7 +32,6 @@ import {
|
||||
getFactionSecurityWorkRepGain,
|
||||
getFactionFieldWorkRepGain,
|
||||
} from "./PersonObjects/formulas/reputation";
|
||||
import { FconfSettings } from "./Fconf/FconfSettings";
|
||||
import { hasHacknetServers, processHacknetEarnings } from "./Hacknet/HacknetHelpers";
|
||||
import { HacknetRoot } from "./Hacknet/ui/HacknetRoot";
|
||||
import { iTutorialStart } from "./InteractiveTutorial";
|
||||
@ -50,7 +44,6 @@ import { loadAllRunningScripts, updateOnlineScriptTimes } from "./NetscriptWorke
|
||||
import { Player } from "./Player";
|
||||
import { prestigeAugmentation } from "./Prestige";
|
||||
import { ProgramsRoot } from "./Programs/ui/ProgramsRoot";
|
||||
import { redPillFlag } from "./RedPill";
|
||||
import { saveObject, loadGame } from "./SaveObject";
|
||||
import { Root as ScriptEditorRoot } from "./ScriptEditor/ui/Root";
|
||||
import { initForeignServers, AllServers } from "./Server/AllServers";
|
||||
@ -72,8 +65,7 @@ import { Hashes } from "./ui/React/Hashes";
|
||||
import { Reputation } from "./ui/React/Reputation";
|
||||
|
||||
import { ActiveScriptsRoot } from "./ui/ActiveScripts/Root";
|
||||
import { initializeMainMenuHeaders } from "./ui/MainMenu/Headers";
|
||||
import { initializeMainMenuLinks, MainMenuLinks } from "./ui/MainMenu/Links";
|
||||
import { MainMenuLinks } from "./ui/MainMenu/Links";
|
||||
|
||||
import { FileDiagnosticPopup } from "./Diagnostic/FileDiagnosticPopup";
|
||||
import { createPopup } from "./ui/React/createPopup";
|
||||
@ -82,90 +74,12 @@ import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
import { gameOptionsBoxClose, gameOptionsBoxOpen } from "../utils/GameOptions";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { removeLoadingScreen } from "../utils/uiHelpers/removeLoadingScreen";
|
||||
import { KEY } from "../utils/helpers/keyCodes";
|
||||
import "./Exploits/tampering";
|
||||
import "./Exploits/unclickable";
|
||||
|
||||
import React from "react";
|
||||
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 = {
|
||||
// Clickable objects
|
||||
Clickables: {
|
||||
@ -457,7 +371,7 @@ const Engine = {
|
||||
},
|
||||
|
||||
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 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) {
|
||||
Engine.displayCharacterOverviewInfo();
|
||||
Engine.Counters.updateDisplays = 3;
|
||||
|
@ -87,21 +87,6 @@
|
||||
</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 -->
|
||||
<div id="mission-container" class="generic-fullscreen-container"></div>
|
||||
|
||||
|
@ -20,7 +20,6 @@ export function ActiveScriptsRoot(props: IProps): React.ReactElement {
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
const [divisionName, setDivisionName] = useState("Overview");
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 20);
|
||||
|
@ -22,7 +22,6 @@ export function CharacterInfo(props: IProps): React.ReactElement {
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
const [divisionName, setDivisionName] = useState("Overview");
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 20);
|
||||
@ -230,13 +229,8 @@ export function CharacterInfo(props: IProps): React.ReactElement {
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<div style={{ width: "60%", fontSize: "13px", marginLeft: "4%" }}>
|
||||
{BitNodes[index].info.split("<br>").map((t, i) => (
|
||||
<div key={i}>
|
||||
<span style={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>{t}</span>
|
||||
<br />
|
||||
</div>
|
||||
))}
|
||||
<div style={{ width: "60%", fontSize: "13px", marginLeft: "2%" }}>
|
||||
<span style={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>{BitNodes[index].info}</span>
|
||||
</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;
|
||||
}
|
||||
|
||||
export function MessagePopup(props: IProps): React.ReactElement {
|
||||
function MessagePopup(props: IProps): React.ReactElement {
|
||||
return <>{props.content}</>;
|
||||
}
|
||||
|
||||
function dialogBoxCreate(txt: string | JSX.Element, preformatted = false): void {
|
||||
export function dialogBoxCreate(txt: string | JSX.Element, preformatted = false): void {
|
||||
const popupId =
|
||||
`popup-` +
|
||||
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