mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-27 10:03:48 +01:00
Fix bug where ISocket get refreshed more than once, add BN19
This commit is contained in:
parent
548f08ce62
commit
3d87baeb15
@ -2,6 +2,7 @@ import React from "react";
|
||||
import { Player } from "@player";
|
||||
import { CityName, FactionName } from "@enums";
|
||||
import { BitNodeMultipliers, replaceCurrentNodeMults } from "./BitNodeMultipliers";
|
||||
import { CorruptableText } from "../ui/React/CorruptableText";
|
||||
|
||||
class BitNode {
|
||||
// A short description, or tagline, about the BitNode
|
||||
@ -480,6 +481,19 @@ export function initBitNodes() {
|
||||
</>
|
||||
),
|
||||
);
|
||||
|
||||
BitNodes.BitNode19 = new BitNode(
|
||||
19,
|
||||
2,
|
||||
"MyrianOS",
|
||||
"l̷i̵g̵h̴t̵ ̴a̷t̸ ̶t̵h̵e̸ ̶e̷n̵d̶ ̶o̸f̶ ̸t̴h̸e̴ ̸t̷u̶n̸n̸e̷l̵.̷",
|
||||
(
|
||||
<CorruptableText
|
||||
content={`yNjHLAgecI ASW1fQdKx5 n9DQ3rmHp3 mnv0XEdwH2 sBkAlBOPhx NohIDL9eRy TbIl8U3WKz 1wjnJ9iuwS VML36vYLNH K06StviNvI cRboTarefZ 7BSNntPpJj DfayVbfxU6 46xvOPQd2Y Ogyj2gnyLr FIND THE GLITCH IN ISHIMA S6E0Vpmxk6 GTF9dWvE6n EEGg7xvtYR Um8YIC0Qww PG4vauBKBk JWG8V1j5Z5 bfYYTTFnBY 7uoicoqIaV IeUu0F42aA EhTF7Fkxyt OBYgGSu0es bJQpenVoO6 L9cL39tRhh xfLroUMvY8 xmMckUHLSQ`}
|
||||
spoiler={false}
|
||||
/>
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
export const defaultMultipliers = new BitNodeMultipliers();
|
||||
@ -987,6 +1001,64 @@ export function getBitNodeMultipliers(n: number, lvl: number): BitNodeMultiplier
|
||||
WorldDaemonDifficulty: 5,
|
||||
});
|
||||
}
|
||||
case 19: {
|
||||
return new BitNodeMultipliers({
|
||||
MyrianPower: 10,
|
||||
|
||||
AgilityLevelMultiplier: 0.01,
|
||||
AugmentationMoneyCost: 100,
|
||||
AugmentationRepCost: 100,
|
||||
BladeburnerRank: 0.01,
|
||||
BladeburnerSkillCost: 100,
|
||||
CharismaLevelMultiplier: 0.01,
|
||||
ClassGymExpGain: 0.01,
|
||||
CodingContractMoney: 0.01,
|
||||
CompanyWorkExpGain: 0.01,
|
||||
CompanyWorkMoney: 0.01,
|
||||
CompanyWorkRepGain: 0.01,
|
||||
CorporationValuation: 0.01,
|
||||
CrimeExpGain: 0.01,
|
||||
CrimeMoney: 0.01,
|
||||
CrimeSuccessRate: 0.01,
|
||||
DaedalusAugsRequirement: 100,
|
||||
DefenseLevelMultiplier: 0.01,
|
||||
DexterityLevelMultiplier: 0.01,
|
||||
FactionPassiveRepGain: 0.01,
|
||||
FactionWorkExpGain: 0.01,
|
||||
FactionWorkRepGain: 0.01,
|
||||
FourSigmaMarketDataApiCost: 100,
|
||||
FourSigmaMarketDataCost: 100,
|
||||
GangSoftcap: 0.01,
|
||||
GangUniqueAugs: 0.01,
|
||||
GoPower: 0.01,
|
||||
HackExpGain: 0.01,
|
||||
HackingLevelMultiplier: 0.01,
|
||||
HackingSpeedMultiplier: 0.01,
|
||||
HacknetNodeMoney: 0.01,
|
||||
HomeComputerRamCost: 100,
|
||||
InfiltrationMoney: 0.01,
|
||||
InfiltrationRep: 0.01,
|
||||
ManualHackMoney: 0.01,
|
||||
PurchasedServerCost: 100,
|
||||
PurchasedServerSoftcap: 100,
|
||||
PurchasedServerLimit: 0.01,
|
||||
PurchasedServerMaxRam: 0.01,
|
||||
RepToDonateToFaction: 10000,
|
||||
ScriptHackMoney: 0.01,
|
||||
ScriptHackMoneyGain: 0.01,
|
||||
ServerGrowthRate: 0.01,
|
||||
ServerMaxMoney: 0.01,
|
||||
ServerStartingMoney: 0.01,
|
||||
ServerStartingSecurity: 100,
|
||||
ServerWeakenRate: 0.01,
|
||||
StrengthLevelMultiplier: 0.01,
|
||||
StaneksGiftPowerMultiplier: 0.01,
|
||||
StaneksGiftExtraSize: -100,
|
||||
WorldDaemonDifficulty: 100,
|
||||
CorporationSoftcap: 0.01,
|
||||
CorporationDivisions: 0.01,
|
||||
});
|
||||
}
|
||||
default: {
|
||||
throw new Error("Invalid BitNodeN");
|
||||
}
|
||||
|
@ -114,6 +114,9 @@ export class BitNodeMultipliers {
|
||||
*/
|
||||
ManualHackMoney = 1;
|
||||
|
||||
/** Influence how strongly Myrian improves bitnode multipliers */
|
||||
MyrianPower = 1;
|
||||
|
||||
/** Influence how much it costs to purchase a server */
|
||||
PurchasedServerCost = 1;
|
||||
|
||||
|
@ -239,7 +239,7 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O </Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | O O | O O | </Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O | | / __| \ | | O </Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O | O | | O / | O | | O | O </Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O | O | | <BitNodePortal n={19} level={n(19)} flume={props.flume} destroyedBitNode={destroyed} /> / | O | | O | O </Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | | |_/ |/ | \_ \_| | | | | </Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O | | | <BitNodePortal n={14} level={n(14)} flume={props.flume} destroyedBitNode={destroyed} /> | | O__/ | / \__ | | O | | | O </Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | | | | | / /| O / \| | | | | | | </Typography>
|
||||
|
@ -300,11 +300,36 @@ export function SpecialLocation(props: SpecialLocationProps): React.ReactElement
|
||||
}
|
||||
|
||||
function renderGlitch(): React.ReactElement {
|
||||
const onClick = () => {
|
||||
dialogBoxCreate(
|
||||
"Hexabytes of information are streamed to your mind. Completely drained one thing remained clear as crystal. You now understand how to connect directly to the machine running the bitnodes. Myrian.",
|
||||
);
|
||||
Router.toPage(Page.MyrianOS);
|
||||
Player.myrianConnection = true;
|
||||
};
|
||||
if (!Player.canAccessMyrian())
|
||||
return (
|
||||
<>
|
||||
<Typography>
|
||||
<CorruptableText
|
||||
content={"An eerie aura surrounds this area. You feel you should leave."}
|
||||
spoiler={false}
|
||||
/>
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography>
|
||||
<CorruptableText content={"An eerie aura surrounds this area. You feel you should leave."} spoiler={false} />
|
||||
You find yourself standing in a small, unremarkable alley. Despite the lack of air you do not feel the need to
|
||||
breathe. There is no light, yet you can see every details of every objects in the alley. A rat walking in the
|
||||
alley completely stop in it's track as if frozen in time. You know what this means. This location has fallen
|
||||
through the crack of the Enders.
|
||||
<br />
|
||||
In the middle of the alley is a personal link port. You can connect your personal link to the anomaly.
|
||||
</Typography>
|
||||
<Button onClick={onClick}>Connect your personal link to the anomaly</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
import React from "react";
|
||||
import { Container, Typography } from "@mui/material";
|
||||
import { Container, IconButton, Typography } from "@mui/material";
|
||||
|
||||
import { styled } from "@mui/system";
|
||||
import { myrian, myrianSize } from "../Helper";
|
||||
import { useRerender } from "../../ui/React/hooks";
|
||||
import { DeviceIcon, cellSize } from "./DeviceIcon";
|
||||
import { Info } from "@mui/icons-material";
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
import { MD } from "../../ui/MD/MD";
|
||||
import { tutorial } from "./tutorial";
|
||||
|
||||
const CellD = styled("div")({
|
||||
width: cellSize + "px",
|
||||
@ -80,9 +84,18 @@ interface IProps {}
|
||||
|
||||
export const MyrianRoot = (__props: IProps): React.ReactElement => {
|
||||
useRerender(50);
|
||||
|
||||
const onHelp = () => {
|
||||
dialogBoxCreate(<MD md={tutorial} />);
|
||||
};
|
||||
return (
|
||||
<Container maxWidth="lg" disableGutters sx={{ mx: 0 }}>
|
||||
<Typography variant="h4">Myrian OS</Typography>
|
||||
<Typography variant="h4">
|
||||
Myrian OS
|
||||
<IconButton onClick={onHelp}>
|
||||
<Info />
|
||||
</IconButton>
|
||||
</Typography>
|
||||
<Typography>
|
||||
{myrian.vulns} vulns : {myrian.totalVulns} total vulns
|
||||
</Typography>
|
||||
|
109
src/Myrian/ui/tutorial.ts
Normal file
109
src/Myrian/ui/tutorial.ts
Normal file
@ -0,0 +1,109 @@
|
||||
export const tutorial = `# Myrian
|
||||
|
||||
Myrian is the name of the OS that the BitNodes run on.
|
||||
|
||||
By gaining access to the OS directly you can start to break it apart by generating vulnerabilities (vulns).
|
||||
You do so by interracting with the various devices in the OS, represented by a grid.
|
||||
|
||||
## Devices
|
||||
|
||||
A device is a component that takes space on the Myrian, no 2 devices can be on the same tile.
|
||||
Devices can only interract when directly adjacent to each other. When one or more device is
|
||||
performing an action it will become busy and no other actions can be taken until the current one finishes.
|
||||
|
||||
Contrary to every other mechanic in the game. Async functions using myrian functions CAN run simultenaously.
|
||||
|
||||
|
||||
### Bus
|
||||
|
||||
The most important device is the Bus. Here's a few of the things it can do:
|
||||
|
||||
- move, only 1 tile at a time and that tile must be empty. No diagonal.
|
||||
- transfer content, most entity can store items called components, bus are the only device that can transfer components to and from other devices
|
||||
- use other devices, e.g. Use a Reducer device to create new components.
|
||||
|
||||
### ISocket
|
||||
|
||||
These devices produce basic components that can be used for other devices, [r0, g0, b0].
|
||||
They must be picked up by busses and will eventually produce another one after a certain cooldown has passed.
|
||||
|
||||
### OSocket
|
||||
|
||||
These devices request components and produce vulns in return, a bus simply needs to transfer a component into a OSocket content in order to fulfill the request
|
||||
|
||||
### Reducer
|
||||
|
||||
These devices can be used by a bus, when being used they will first check their content, if the content matches one of the recipe they will take some time to consume their content in order to produce a new, upgraded, more valuable component, e.g. r0 + r0 => r1
|
||||
|
||||
### Cache
|
||||
|
||||
These devices act as storage for components.
|
||||
|
||||
### Lock
|
||||
|
||||
These devices cannot be installed. They appear after various conditions are fulfilled in order to block certain tiles.
|
||||
|
||||
### Battery
|
||||
|
||||
These devices are only relevant when the Magnetism glitch is active. It recharges the energy of a bus.
|
||||
|
||||
## Installing
|
||||
|
||||
Bus can install new devices, when they do so a lock will appear over the tile that will eventually become the device. The cost of any device depends on the number of that type of device currently in the OS.
|
||||
|
||||
### Uninstalling
|
||||
|
||||
A bus can remove a device, there is no refund.
|
||||
|
||||
## Tiers
|
||||
|
||||
Upgrading a reducers tier allows it to reduce components of a higher tier and ONLY that higher tier.
|
||||
A tier 2 reducer can only tier 2 components like r1 + r1 => r2 and loses access to r0 + r0 => r1
|
||||
|
||||
Upgrading a batterys tier increases the amount of energy it produces.
|
||||
|
||||
## Glitches
|
||||
|
||||
glitches are optional difficulty modifiers that make the myrian more difficult BUT increase the amount of vulns gained.
|
||||
All glitches start at level 0 and must be activated when you chose. They also have a max level that differs from glitch to glitch.
|
||||
|
||||
### Magnetism
|
||||
|
||||
By default bus lose 0 energy when moving. But when this glitch is active they start losing energy, at 0 energy bus move much more slowly. Batteries must be installed and used to charge busses.
|
||||
|
||||
### Friction
|
||||
|
||||
When Friction is active busses move more slowly.
|
||||
|
||||
### Rust
|
||||
|
||||
When rust is active, hidden tiles are set on the Myrian. When a bus steps on one of these hidden tiles one of their upgrade lowers. Higher Rust level means lowers by a larger amount and more rust tiles are set.
|
||||
|
||||
### Isolation
|
||||
|
||||
When Isolation is active busses transfer and charge more slowly.
|
||||
|
||||
### Segmentation
|
||||
|
||||
When Segmentation is active random Locks will spawn on the Myrian. You have to remove these locks or the bord will be overrun with Locks and you won't be able to move.
|
||||
|
||||
### Virtualization
|
||||
|
||||
When Virtualization is active busses install and uninstall devices more slowly.
|
||||
|
||||
### Jamming
|
||||
|
||||
When Jamming is active busses use reducers more slowly.
|
||||
|
||||
### Roaming
|
||||
|
||||
When Roaming is active, isockets and osockets start to move around the map
|
||||
|
||||
### Encryption
|
||||
|
||||
Encryption is the only glitch that's always active. The level of Encryption determines the complexity of the requests made by osockets.
|
||||
|
||||
## Destabilization
|
||||
|
||||
As the number of total vulns increase the bitnode becomes unstable and it's multiplier become more favorable.
|
||||
`;
|
@ -193,6 +193,7 @@ export function NetscriptMyrian(): InternalAPI<IMyrian> {
|
||||
return helpers
|
||||
.netscriptDelay(ctx, transferSpeed(bus.transferLvl) * isolationMult(myrian.glitches[Glitch.Isolation]), true)
|
||||
.then(() => {
|
||||
const previousSize = container.content.length;
|
||||
toDevice.content = toDevice.content.filter((item) => !output.includes(item));
|
||||
toDevice.content.push(...input);
|
||||
|
||||
@ -201,6 +202,7 @@ export function NetscriptMyrian(): InternalAPI<IMyrian> {
|
||||
|
||||
switch (container.type) {
|
||||
case DeviceType.ISocket: {
|
||||
if (previousSize <= container.content.length) break;
|
||||
const cooldown = isocketSpeed(container.emissionLvl);
|
||||
container.cooldownUntil = Date.now() + cooldown;
|
||||
setTimeout(() => {
|
||||
@ -210,16 +212,15 @@ export function NetscriptMyrian(): InternalAPI<IMyrian> {
|
||||
}
|
||||
|
||||
case DeviceType.OSocket: {
|
||||
if (inventoryMatches(container.currentRequest, container.content)) {
|
||||
const gain =
|
||||
container.content.map((i) => vulnsMap[i]).reduce((a, b) => a + b, 0) * getTotalGlitchMult();
|
||||
myrian.vulns += gain;
|
||||
myrian.totalVulns += gain;
|
||||
container.content = [];
|
||||
const request = getNextISocketRequest(myrian.glitches[Glitch.Encryption]);
|
||||
container.currentRequest = request;
|
||||
container.maxContent = request.length;
|
||||
}
|
||||
if (!inventoryMatches(container.currentRequest, container.content)) break;
|
||||
const gain =
|
||||
container.content.map((i) => vulnsMap[i]).reduce((a, b) => a + b, 0) * getTotalGlitchMult();
|
||||
myrian.vulns += gain;
|
||||
myrian.totalVulns += gain;
|
||||
container.content = [];
|
||||
const request = getNextISocketRequest(myrian.glitches[Glitch.Encryption]);
|
||||
container.currentRequest = request;
|
||||
container.maxContent = request.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ export class PlayerObject extends Person implements IPlayer {
|
||||
lastUpdate = 0;
|
||||
lastSave = 0;
|
||||
totalPlaytime = 0;
|
||||
myrianConnection = false;
|
||||
|
||||
currentWork: Work | null = null;
|
||||
focus = false;
|
||||
@ -129,6 +130,7 @@ export class PlayerObject extends Person implements IPlayer {
|
||||
checkForFactionInvitations = generalMethods.checkForFactionInvitations;
|
||||
setBitNodeNumber = generalMethods.setBitNodeNumber;
|
||||
canAccessCotMG = generalMethods.canAccessCotMG;
|
||||
canAccessMyrian = generalMethods.canAccessMyrian;
|
||||
sourceFileLvl = generalMethods.sourceFileLvl;
|
||||
applyEntropy = augmentationMethods.applyEntropy;
|
||||
focusPenalty = generalMethods.focusPenalty;
|
||||
|
@ -577,6 +577,10 @@ export function canAccessCotMG(this: PlayerObject): boolean {
|
||||
return this.bitNodeN === 13 || this.sourceFileLvl(13) > 0;
|
||||
}
|
||||
|
||||
export function canAccessMyrian(this: PlayerObject): boolean {
|
||||
return this.bitNodeN === 19 || this.sourceFileLvl(19) > 0;
|
||||
}
|
||||
|
||||
export function sourceFileLvl(this: PlayerObject, n: number): number {
|
||||
return this.sourceFiles.get(n) ?? 0;
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ export function prestigeSourceFile(isFlume: boolean): void {
|
||||
updateHashManagerCapacity();
|
||||
}
|
||||
|
||||
if (Player.bitNodeN === 13) {
|
||||
if (Player.bitNodeN === 13 || Player.bitNodeN === 19) {
|
||||
Player.money = CONSTANTS.TravelCost;
|
||||
}
|
||||
staneksGift.prestigeSourceFile();
|
||||
|
@ -35,6 +35,7 @@ import CheckIcon from "@mui/icons-material/Check"; // Milestones
|
||||
import HelpIcon from "@mui/icons-material/Help"; // Tutorial
|
||||
import SettingsIcon from "@mui/icons-material/Settings"; // options
|
||||
import DeveloperBoardIcon from "@mui/icons-material/DeveloperBoard"; // Dev
|
||||
import SettingsInputComponentIcon from "@mui/icons-material/SettingsInputComponent"; // Myrian
|
||||
import EmojiEventsIcon from "@mui/icons-material/EmojiEvents"; // Achievements
|
||||
import AccountBoxIcon from "@mui/icons-material/AccountBox";
|
||||
import PublicIcon from "@mui/icons-material/Public";
|
||||
@ -354,7 +355,7 @@ export function SidebarRoot(props: { page: Page }): React.ReactElement {
|
||||
canCorporation && { key_: Page.Corporation, icon: BusinessIcon },
|
||||
canGang && { key_: Page.Gang, icon: SportsMmaIcon },
|
||||
canIPvGO && { key_: Page.Go, icon: BorderInnerSharp },
|
||||
{ key_: Page.MyrianOS, icon: DeveloperBoardIcon },
|
||||
(true || Player.myrianConnection) && { key_: Page.MyrianOS, icon: SettingsInputComponentIcon },
|
||||
]}
|
||||
/>
|
||||
<Divider />
|
||||
|
@ -256,4 +256,20 @@ export function initSourceFiles() {
|
||||
</>
|
||||
),
|
||||
);
|
||||
|
||||
SourceFiles.SourceFile19 = new SourceFile(
|
||||
19,
|
||||
(
|
||||
<>
|
||||
This Source-File grants the following benefits:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: Reduce the effect of the Rust Glitch
|
||||
<br />
|
||||
Level 2: Reduce the effect of the Magnetism Glitch
|
||||
<br />
|
||||
Level 3: Reduce the effect of the Friction, Isolation, Virtualization, and Jamming Glitch
|
||||
</>
|
||||
),
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user