This commit is contained in:
Olivier Gagnon 2021-10-07 01:36:59 -04:00
parent da746a63c3
commit 8e58482db0
21 changed files with 19132 additions and 569 deletions

11550
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -1,18 +1,18 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8" />
<title>Bitburner</title> <title>Bitburner</title>
<link rel="apple-touch-icon" sizes="180x180" href="dist/apple-touch-icon.png"/> <link rel="apple-touch-icon" sizes="180x180" href="dist/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png"/> <link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png"/> <link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png" />
<link rel="manifest" href="dist/site.webmanifest"/> <link rel="manifest" href="dist/site.webmanifest" />
<link rel="mask-icon" href="dist/safari-pinned-tab.svg" color="#000000"/> <link rel="mask-icon" href="dist/safari-pinned-tab.svg" color="#000000" />
<meta name="apple-mobile-web-app-title" content="Bitburner"/> <meta name="apple-mobile-web-app-title" content="Bitburner" />
<meta name="application-name" content="Bitburner"/> <meta name="application-name" content="Bitburner" />
<meta name="msapplication-TileColor" content="#000000"/> <meta name="msapplication-TileColor" content="#000000" />
<meta name="msapplication-config" content="dist/browserconfig.xml"/> <meta name="msapplication-config" content="dist/browserconfig.xml" />
<meta name="theme-color" content="#ffffff"/> <meta name="theme-color" content="#ffffff" />
<!-- Google Analytics --> <!-- Google Analytics -->
<script> <script>
@ -51,7 +51,7 @@
</style> </style>
<link rel="shortcut icon" href="favicon.ico"></head> <link rel="shortcut icon" href="favicon.ico"></head>
<body> <body>
<div id="root"/> <div id="root" />
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="main.bundle.js"></script></body> <script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="main.bundle.js"></script></body>
<!-- http://plaza.dsolver.ca/m/hydroflame4418 --> <!-- http://plaza.dsolver.ca/m/hydroflame4418 -->
</html> </html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -2377,8 +2377,7 @@ function initAugmentations(): void {
'Allison "Mother" Stanek imparts you with her gift. An ' + 'Allison "Mother" Stanek imparts you with her gift. An ' +
"experimental Augmentation implanted at the base of the neck. " + "experimental Augmentation implanted at the base of the neck. " +
"It allows you to overclock your entire system by carefully " + "It allows you to overclock your entire system by carefully " +
"changing the configuration.<br><br>" + "changing the configuration.",
"Its unstable nature decreases all your stats by 10%",
isSpecial: true, isSpecial: true,
hacking_chance_mult: 0.9, hacking_chance_mult: 0.9,
hacking_speed_mult: 0.9, hacking_speed_mult: 0.9,
@ -2406,7 +2405,7 @@ function initAugmentations(): void {
hacknet_node_core_cost_mult: 1.1, hacknet_node_core_cost_mult: 1.1,
hacknet_node_level_cost_mult: 1.1, hacknet_node_level_cost_mult: 1.1,
work_money_mult: 0.9, work_money_mult: 0.9,
stats: null, stats: <>Its unstable nature decreases all your stats by 10%</>,
}); });
StaneksGift1.addToFactions([ChurchOfTheMachineGodFactionName]); StaneksGift1.addToFactions([ChurchOfTheMachineGodFactionName]);
resetAugmentation(StaneksGift1); resetAugmentation(StaneksGift1);

@ -542,7 +542,7 @@ BitNodes["BitNode13"] = new BitNode(
<br /> <br />
<br /> <br />
Their leader, Allison "Mother" Stanek is said to have created her own Augmentation whose power goes beyond any Their leader, Allison "Mother" Stanek is said to have created her own Augmentation whose power goes beyond any
other.' + Find her in Chongquin and gain her trust. other. Find her in Chongquing and gain her trust.
<br /> <br />
<br /> <br />
In this BitNode: In this BitNode:
@ -557,17 +557,7 @@ BitNodes["BitNode13"] = new BitNode(
level up to a maximum of 3. This Source-File lets the Church of the Machine God appear in other BitNodes. level up to a maximum of 3. This Source-File lets the Church of the Machine God appear in other BitNodes.
<br /> <br />
<br /> <br />
This Source-File also increases Stanek's Gift multipliers by: Each level of this Source-File increases the size of Stanek's Gift.
<br />
<br />
Level 1: 8%
<br />
Level 2: 12%
<br />
Level 3: 14%
<br />
<br />
Each level of this Source-File also increases the size of the gift.
</> </>
), ),
); );

@ -94,7 +94,7 @@ export function FragmentById(id: number): Fragment | null {
[_, _, X], [_, _, X],
], ],
FragmentType.Hacking, // type FragmentType.Hacking, // type
10, 1,
1, // limit 1, // limit
), ),
); );
@ -108,7 +108,189 @@ export function FragmentById(id: number): Fragment | null {
[_, X, _], [_, X, _],
], ],
FragmentType.Hacking, // type FragmentType.Hacking, // type
10, 1,
1, // limit
),
);
Fragments.push(
new Fragment(
5, // id
[
// shape
[X, X],
],
FragmentType.HackingSpeed, // type
1.3,
1, // limit
),
);
Fragments.push(
new Fragment(
6, // id
[
[X, _],
[X, X],
], // shape
FragmentType.HackingMoney, // type
2, // power
1, // limit
),
);
Fragments.push(
new Fragment(
7, // id
[
[X, X],
[X, X],
], // shape
FragmentType.HackingGrow, // type
0.5, // power
1, // limit
),
);
Fragments.push(
new Fragment(
8, // id
[
[X, X, X],
[_, X, _],
[X, X, X],
], // shape
FragmentType.Hacking, // type
1, // power
1, // limit
),
);
Fragments.push(
new Fragment(
10, // id
[
[X, X],
[_, X],
], // shape
FragmentType.Strength, // type
2, // power
1, // limit
),
);
Fragments.push(
new Fragment(
12, // id
[
[_, X],
[X, X],
], // shape
FragmentType.Defense, // type
2, // power
1, // limit
),
);
Fragments.push(
new Fragment(
14, // id
[
[X, X],
[X, _],
], // shape
FragmentType.Dexterity, // type
2, // power
1, // limit
),
);
Fragments.push(
new Fragment(
16, // id
[
[X, _],
[X, X],
], // shape
FragmentType.Agility, // type
2, // power
1, // limit
),
);
Fragments.push(
new Fragment(
18, // id
[
[X, X],
[X, _],
], // shape
FragmentType.Charisma, // type
3, // power
1, // limit
),
);
Fragments.push(
new Fragment(
20, // id
[
[X, _, _],
[X, X, _],
[X, X, X],
], // shape
FragmentType.HacknetMoney, // type
1, // power
1, // limit
),
);
Fragments.push(
new Fragment(
21, // id
[
[X, X],
[_, X],
[_, X],
], // shape
FragmentType.HacknetCost, // type
-1, // power
1, // limit
),
);
Fragments.push(
new Fragment(
25, // id
[
[X, X, X],
[_, X, _],
], // shape
FragmentType.Rep, // type
0.5, // power
1, // limit
),
);
Fragments.push(
new Fragment(
27, // id
[
[X, _],
[_, X],
], // shape
FragmentType.WorkMoney, // type
10, // power
1, // limit
),
);
Fragments.push(
new Fragment(
28, // id
[[X, X]], // shape
FragmentType.Crime, // type
2, // power
1, // limit
),
);
Fragments.push(
new Fragment(
30, // id
[
[X, X, X],
[X, X, X],
[X, X, X],
], // shape
FragmentType.Bladeburner, // type
1.3, // power
1, // limit 1, // limit
), ),
); );
@ -122,190 +304,23 @@ export function FragmentById(id: number): Fragment | null {
[X, X, X], [X, X, X],
], ],
FragmentType.Booster, // type FragmentType.Booster, // type
500, 1.1, // power
3, // limit 3, // limit
), ),
); );
Fragments.push( Fragments.push(
new Fragment( new Fragment(
5, // id 31, // id
[ [
// shape // shape
[X, X], [X],
[X],
[X],
[X],
], ],
FragmentType.HackingSpeed, // type FragmentType.Booster, // type
50, 1.1, // power
1, // limit 3, // limit
),
);
Fragments.push(
new Fragment(
6, // id
[
[X, _],
[X, X],
], // shape
FragmentType.HackingMoney, // type
10, // power
1, // limit
),
);
Fragments.push(
new Fragment(
7, // id
[
[X, X],
[X, X],
], // shape
FragmentType.HackingGrow, // type
30, // power
1, // limit
),
);
Fragments.push(
new Fragment(
8, // id
[
[X, X, X],
[_, X, _],
[X, X, X],
], // shape
FragmentType.Hacking, // type
50, // power
1, // limit
),
);
Fragments.push(
new Fragment(
10, // id
[
[X, X],
[_, X],
], // shape
FragmentType.Strength, // type
50, // power
1, // limit
),
);
Fragments.push(
new Fragment(
12, // id
[
[_, X],
[X, X],
], // shape
FragmentType.Defense, // type
50, // power
1, // limit
),
);
Fragments.push(
new Fragment(
14, // id
[
[X, X],
[X, _],
], // shape
FragmentType.Dexterity, // type
50, // power
1, // limit
),
);
Fragments.push(
new Fragment(
16, // id
[
[X, _],
[X, X],
], // shape
FragmentType.Agility, // type
50, // power
1, // limit
),
);
Fragments.push(
new Fragment(
18, // id
[
[X, X],
[X, _],
], // shape
FragmentType.Charisma, // type
50, // power
1, // limit
),
);
Fragments.push(
new Fragment(
20, // id
[
[X, _, _],
[X, X, _],
[X, X, X],
], // shape
FragmentType.HacknetMoney, // type
30, // power
1, // limit
),
);
Fragments.push(
new Fragment(
21, // id
[
[X, X],
[_, X],
[_, X],
], // shape
FragmentType.HacknetCost, // type
-10, // power
1, // limit
),
);
Fragments.push(
new Fragment(
25, // id
[
[X, X, X],
[_, X, _],
], // shape
FragmentType.Rep, // type
100, // power
1, // limit
),
);
Fragments.push(
new Fragment(
27, // id
[
[X, _],
[_, X],
], // shape
FragmentType.WorkMoney, // type
20, // power
1, // limit
),
);
Fragments.push(
new Fragment(
28, // id
[[X, X]], // shape
FragmentType.Crime, // type
20, // power
1, // limit
),
);
Fragments.push(
new Fragment(
30, // id
[
[X, X, X],
[X, X, X],
[X, X, X],
], // shape
FragmentType.Bladeburner, // type
50, // power
1, // limit
), ),
); );
})(); })();

@ -24,3 +24,73 @@ export enum FragmentType {
// utility fragments. // utility fragments.
Booster, Booster,
} }
export function Effect(tpe: FragmentType): string {
switch (tpe) {
case FragmentType.HackingChance: {
return "+x% hack() success chance";
break;
}
case FragmentType.HackingSpeed: {
return "+x% faster hack(), grow(), and weaken()";
break;
}
case FragmentType.HackingMoney: {
return "+x% hack() power";
break;
}
case FragmentType.HackingGrow: {
return "+x% grow() power";
break;
}
case FragmentType.Hacking: {
return "+x% hacking skill";
break;
}
case FragmentType.Strength: {
return "+x% strength skill";
break;
}
case FragmentType.Defense: {
return "+x% defense skill";
break;
}
case FragmentType.Dexterity: {
return "+x% dexterity skill";
break;
}
case FragmentType.Agility: {
return "+x% agility skill";
break;
}
case FragmentType.Charisma: {
return "+x% charisma skill";
break;
}
case FragmentType.HacknetMoney: {
return "+x% hacknet production";
break;
}
case FragmentType.HacknetCost: {
return "-x% all hacknet cost";
break;
}
case FragmentType.Rep: {
return "+x% reputation from factions and companies";
break;
}
case FragmentType.WorkMoney: {
return "+x% work money";
break;
}
case FragmentType.Crime: {
return "+x% crime money";
break;
}
case FragmentType.Bladeburner: {
return "+x% all bladeburner stats";
break;
}
}
throw new Error("Calling effect for fragment type that doesn't have an effect " + tpe);
}

@ -1,4 +1,3 @@
import { StaneksGift } from "./StaneksGift";
import { ActiveFragment } from "./ActiveFragment"; import { ActiveFragment } from "./ActiveFragment";
import { Fragment } from "./Fragment"; import { Fragment } from "./Fragment";
import { IPlayer } from "../PersonObjects/IPlayer"; import { IPlayer } from "../PersonObjects/IPlayer";
@ -9,10 +8,11 @@ export interface IStaneksGift {
height(): number; height(): number;
charge(worldX: number, worldY: number, ram: number): number; charge(worldX: number, worldY: number, ram: number): number;
process(p: IPlayer, n: number): void; process(p: IPlayer, n: number): void;
effect(fragment: ActiveFragment): number;
canPlace(x: number, y: number, fragment: Fragment): boolean; canPlace(x: number, y: number, fragment: Fragment): boolean;
place(x: number, y: number, fragment: Fragment): boolean; place(x: number, y: number, fragment: Fragment): boolean;
fragmentAt(worldX: number, worldY: number): ActiveFragment | null; fragmentAt(worldX: number, worldY: number): ActiveFragment | null;
deleteAt(worldX: number, worldY: number): boolean; deleteAt(worldX: number, worldY: number): boolean;
clear(): void; clear(): void;
count(fragment: Fragment): number; count(fragment: Fragment): number;
}; }

@ -1,4 +1,4 @@
import { Fragment, FragmentById } from "./Fragment"; import { Fragment } from "./Fragment";
import { ActiveFragment } from "./ActiveFragment"; import { ActiveFragment } from "./ActiveFragment";
import { FragmentType } from "./FragmentType"; import { FragmentType } from "./FragmentType";
import { IStaneksGift } from "./IStaneksGift"; import { IStaneksGift } from "./IStaneksGift";
@ -22,42 +22,34 @@ export class StaneksGift implements IStaneksGift {
const af = this.fragmentAt(worldX, worldY); const af = this.fragmentAt(worldX, worldY);
if (af === null) return 0; if (af === null) return 0;
// Find all the neighbooring cells const charge = CalculateCharge(ram);
const cells = af.neighboors(); af.charge += charge;
Factions["Church of the Machine God"].playerReputation += Math.log(ram) / Math.log(2);
return ram;
}
process(p: IPlayer, numCycles: number): void {
this.updateMults(p);
}
effect(fragment: ActiveFragment): number {
// Find all the neighbooring cells
const cells = fragment.neighboors();
// find the neighbooring active fragments. // find the neighbooring active fragments.
const maybeFragments = cells.map((n) => this.fragmentAt(n[0], n[1])); const maybeFragments = cells.map((n) => this.fragmentAt(n[0], n[1]));
// Filter out nulls with typescript "Type guard". Whatever // Filter out nulls with typescript "Type guard". Whatever
let neighboors = maybeFragments.filter((v: ActiveFragment | null): v is ActiveFragment => !!v); let neighboors = maybeFragments.filter((v: ActiveFragment | null): v is ActiveFragment => !!v);
// filter unique fragments neighboors = neighboors.filter((fragment) => fragment.fragment().type === FragmentType.Booster);
neighboors = neighboors.filter((value, index) => neighboors.indexOf(value) === index);
// count number of neighbooring boosts and cooling.
let boost = 1; let boost = 1;
for (const neighboor of neighboors) { for (const neighboor of neighboors) {
const f = neighboor.fragment(); boost *= neighboor.fragment().power;
if (f.type === FragmentType.Booster) boost *= 1 + f.power / 1000;
} }
const extraCharge = CalculateCharge(ram, boost); return CalculateEffect(fragment.charge, fragment.fragment().power, boost);
af.charge += extraCharge;
Factions["Church of the Machine God"].playerReputation += extraCharge;
return ram;
}
process(p: IPlayer, numCycles: number): void {
for (const activeFragment of this.fragments) {
const fragment = activeFragment.fragment();
// Boosters and cooling don't deal with heat.
if (fragment.type === FragmentType.Booster) continue;
}
this.updateMults(p);
} }
canPlace(x: number, y: number, fragment: Fragment): boolean { canPlace(x: number, y: number, fragment: Fragment): boolean {
@ -116,7 +108,8 @@ export class StaneksGift implements IStaneksGift {
for (const aFrag of this.fragments) { for (const aFrag of this.fragments) {
const fragment = aFrag.fragment(); const fragment = aFrag.fragment();
const power = CalculateEffect(aFrag.charge, fragment.power);
const power = this.effect(aFrag);
switch (fragment.type) { switch (fragment.type) {
case FragmentType.HackingChance: case FragmentType.HackingChance:
p.hacking_chance_mult *= power; p.hacking_chance_mult *= power;

@ -0,0 +1,5 @@
export const StanekConstants: {
RAMBonus: number;
} = {
RAMBonus: 0.1,
};

@ -1,4 +1,5 @@
export function CalculateCharge(ram: number, boost: number): number { import { StanekConstants } from "../data/Constants";
const extraCharge = ram * Math.pow(boost, 2);
return extraCharge; export function CalculateCharge(ram: number): number {
return ram * Math.pow(1 + Math.log2(ram) * StanekConstants.RAMBonus, 0.7);
} }

@ -1,3 +1,3 @@
export function CalculateEffect(charge: number, power: number): number { export function CalculateEffect(charge: number, power: number, boost: number): number {
return Math.pow((power/1000)+1, Math.log(charge+1)/Math.log(8)) return 1 + (Math.log(charge + 1) / (Math.log(3) * 100)) * power * boost;
} }

2
src/CotMG/notes Normal file

@ -0,0 +1,2 @@
incentive for more threads
boosters just multiply output, eg 20% * 1.5 = 30%

@ -1,13 +1,14 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { ActiveFragment } from "../ActiveFragment"; import { ActiveFragment } from "../ActiveFragment";
import { FragmentType } from "../FragmentType"; import { IStaneksGift } from "../IStaneksGift";
import { FragmentType, Effect } from "../FragmentType";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { CalculateEffect } from "../formulas/effect";
import Paper from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
type IProps = { type IProps = {
gift: IStaneksGift;
fragment: ActiveFragment | null; fragment: ActiveFragment | null;
x: number; x: number;
y: number; y: number;
@ -28,7 +29,7 @@ export function FragmentInspector(props: IProps): React.ReactElement {
<Typography> <Typography>
ID: N/A ID: N/A
<br /> <br />
Type: N/A Effect: N/A
<br /> <br />
Magnitude: N/A Magnitude: N/A
<br /> <br />
@ -48,24 +49,26 @@ export function FragmentInspector(props: IProps): React.ReactElement {
const f = props.fragment.fragment(); const f = props.fragment.fragment();
let charge = numeralWrapper.formatStaneksGiftCharge(props.fragment.charge); let charge = numeralWrapper.formatStaneksGiftCharge(props.fragment.charge);
let effect = "N/A";
// Boosters and cooling don't deal with heat. // Boosters and cooling don't deal with heat.
if (f.type === FragmentType.Booster) { if ([FragmentType.Booster, FragmentType.None, FragmentType.Delete].includes(f.type)) {
charge = "N/A"; charge = "N/A";
effect = `${f.power}x adjacent fragment power`;
} else {
effect = Effect(f.type).replace("+x%", numeralWrapper.formatPercentage(props.gift.effect(props.fragment) - 1));
} }
const effect = numeralWrapper.format(CalculateEffect(props.fragment.charge, f.power) - 1, "+0.00%");
return ( return (
<Paper> <Paper>
<Typography> <Typography>
ID: {props.fragment.id} ID: {props.fragment.id}
<br /> <br />
Type: {FragmentType[f.type]} Effect: {effect}
<br /> <br />
Power: {numeralWrapper.formatStaneksGiftPower(f.power)} Power: {numeralWrapper.formatStaneksGiftPower(f.power)}
<br /> <br />
Charge: {charge} Charge: {charge}
<br /> <br />
Effect: {effect}
<br /> <br />
root [X, Y] {props.fragment.x}, {props.fragment.y} root [X, Y] {props.fragment.x}, {props.fragment.y}
<br /> <br />

@ -1,6 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Fragments, Fragment, NoneFragment, DeleteFragment } from "../Fragment"; import { Fragments, Fragment, NoneFragment, DeleteFragment } from "../Fragment";
import { FragmentType } from "../FragmentType"; import { FragmentType, Effect } from "../FragmentType";
import { IStaneksGift } from "../IStaneksGift"; import { IStaneksGift } from "../IStaneksGift";
import { FragmentPreview } from "./FragmentPreview"; import { FragmentPreview } from "./FragmentPreview";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
@ -8,6 +8,7 @@ import { numeralWrapper } from "../../ui/numeralFormat";
import Select, { SelectChangeEvent } from "@mui/material/Select"; import Select, { SelectChangeEvent } from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem"; import MenuItem from "@mui/material/MenuItem";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
type IOptionProps = { type IOptionProps = {
gift: IStaneksGift; gift: IStaneksGift;
@ -23,21 +24,26 @@ function FragmentOption(props: IOptionProps): React.ReactElement {
<></> <></>
); );
return ( return (
<> <Box display="flex">
<Box sx={{ mx: 2 }}>
<FragmentPreview
width={props.fragment.width()}
height={props.fragment.height()}
colorAt={(x, y) => {
return !props.fragment.fullAt(x, y) ? "" : props.fragment.type === FragmentType.Booster ? "blue" : "green";
}}
/>
</Box>
<Typography> <Typography>
{FragmentType[props.fragment.type]} {props.fragment.type === FragmentType.Booster
? `${props.fragment.power}x adjacent fragment power`
: Effect(props.fragment.type)}
<br /> <br />
power: {numeralWrapper.formatStaneksGiftPower(props.fragment.power)} power: {numeralWrapper.formatStaneksGiftPower(props.fragment.power)}
<br /> <br />
{remaining} {remaining}
</Typography> </Typography>
<br /> </Box>
<FragmentPreview
width={props.fragment.width()}
height={props.fragment.height()}
colorAt={(x, y) => (props.fragment.fullAt(x, y) ? "green" : "")}
/>
</>
); );
} }
@ -51,8 +57,13 @@ export function FragmentSelector(props: IProps): React.ReactElement {
function onChange(event: SelectChangeEvent<string | number>): void { function onChange(event: SelectChangeEvent<string | number>): void {
const v = event.target.value; const v = event.target.value;
setValue(v); setValue(v);
if (v === "None") props.selectFragment(NoneFragment); if (v === "None") {
else if (v === "Delete") props.selectFragment(DeleteFragment); props.selectFragment(NoneFragment);
return;
} else if (v === "Delete") {
props.selectFragment(DeleteFragment);
return;
}
const fragment = Fragments.find((f) => f.id === v); const fragment = Fragments.find((f) => f.id === v);
if (fragment === undefined) throw new Error("Fragment selector selected an undefined fragment with id " + v); if (fragment === undefined) throw new Error("Fragment selector selected an undefined fragment with id " + v);
if (typeof v === "number") props.selectFragment(fragment); if (typeof v === "number") props.selectFragment(fragment);

@ -136,7 +136,7 @@ export function Grid(props: GridProps): React.ReactElement {
</Table> </Table>
<FragmentSelector gift={props.gift} selectFragment={updateSelectedFragment} /> <FragmentSelector gift={props.gift} selectFragment={updateSelectedFragment} />
<Button onClick={clear}>Clear</Button> <Button onClick={clear}>Clear</Button>
<FragmentInspector x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} /> <FragmentInspector gift={props.gift} x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} />
</> </>
); );
} }

@ -250,6 +250,10 @@ function prestigeSourceFile(flume: boolean): void {
dialogBoxCreate("Visit VitaLife in New Tokyo if you'd like to purchase a new sleeve!"); dialogBoxCreate("Visit VitaLife in New Tokyo if you'd like to purchase a new sleeve!");
} }
if (Player.bitNodeN === 13) {
dialogBoxCreate("Trouble is brewing in Chongqing");
}
// Reset Stock market, gang, and corporation // Reset Stock market, gang, and corporation
if (Player.hasWseAccount) { if (Player.hasWseAccount) {
initStockMarket(); initStockMarket();

@ -161,7 +161,7 @@ export function SidebarRoot(props: IProps): React.ReactElement {
const canJob = props.player.companyName !== ""; const canJob = props.player.companyName !== "";
const canStockMarket = props.player.hasWseAccount; const canStockMarket = props.player.hasWseAccount;
const canBladeburner = !!(props.player.bladeburner as any); const canBladeburner = !!(props.player.bladeburner as any);
const canStaneksGift = props.player.hasAugmentation(AugmentationNames.StaneksGift1); const canStaneksGift = props.player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1);
function clickTerminal(): void { function clickTerminal(): void {
props.router.toTerminal(); props.router.toTerminal();
@ -442,7 +442,9 @@ export function SidebarRoot(props: IProps): React.ReactElement {
<DeveloperBoardIcon color={props.page !== Page.StaneksGift ? "secondary" : "primary"} /> <DeveloperBoardIcon color={props.page !== Page.StaneksGift ? "secondary" : "primary"} />
</ListItemIcon> </ListItemIcon>
<ListItemText> <ListItemText>
<Typography color={props.page !== Page.StaneksGift ? "secondary" : "primary"}>StaneksGift</Typography> <Typography color={props.page !== Page.StaneksGift ? "secondary" : "primary"}>
Stanek's Gift
</Typography>
</ListItemText> </ListItemText>
</ListItem> </ListItem>
)} )}

@ -204,3 +204,7 @@ SourceFiles["SourceFile12"] = new SourceFile(
12, 12,
<>This Source-File lets the player start with Neuroflux Governor equal to the level of this Source-File.</>, <>This Source-File lets the player start with Neuroflux Governor equal to the level of this Source-File.</>,
); );
SourceFiles["SourceFile13"] = new SourceFile(
12,
<>Each level of this Source-File increases the size of Stanek's Gift.</>,
);

@ -174,7 +174,7 @@ class NumeralFormatter {
} }
formatStaneksGiftPower(n: number): string { formatStaneksGiftPower(n: number): string {
return this.format(n, "0"); return this.format(n, "0.00");
} }
parseMoney(s: string): number { parseMoney(s: string): number {