Merge pull request #3303 from danielyxie/dev

Re-add some gang augs at random.
This commit is contained in:
hydroflame 2022-03-30 21:00:55 -04:00 committed by GitHub
commit 176ddd4f0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 236 additions and 208 deletions

30
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -706,7 +706,7 @@ export const generalAugmentations = [
"so that the brain doesn't have to.",
hacking_speed_mult: 1.01,
hacking_mult: 1.05,
factions: [FactionNames.CyberSec],
factions: [FactionNames.CyberSec, FactionNames.NiteSec],
}),
new Augmentation({
name: AugmentationNames.CranialSignalProcessorsG2,

@ -91,14 +91,12 @@ function updateNeuroFluxGovernorCosts(neuroFluxGovernorAugmentation: Augmentatio
}
export function updateAugmentationCosts(): void {
console.log(Player.queuedAugmentations);
for (const name of Object.keys(Augmentations)) {
if (Augmentations.hasOwnProperty(name)) {
const augmentationToUpdate = Augmentations[name];
if (augmentationToUpdate.name === AugmentationNames.NeuroFluxGovernor) {
updateNeuroFluxGovernorCosts(augmentationToUpdate);
} else {
console.log(augmentationToUpdate.baseCost);
augmentationToUpdate.baseCost = augmentationToUpdate.startingCost * getGenericAugmentationPriceMultiplier();
}
}

@ -82,7 +82,9 @@ BitNodes["BitNode2"] = new BitNode(
<br />
The amount of money gained from crimes and Infiltration is tripled
<br />
Certain Factions ({FactionNames.SlumSnakes}, {FactionNames.Tetrads}, {FactionNames.TheSyndicate}, {FactionNames.TheDarkArmy}, {FactionNames.SpeakersForTheDead}, {FactionNames.NiteSec}, {FactionNames.TheBlackHand}) give the player the ability to form and manage their own gangs. These gangs will earn the player money and
Certain Factions ({FactionNames.SlumSnakes}, {FactionNames.Tetrads}, {FactionNames.TheSyndicate},{" "}
{FactionNames.TheDarkArmy}, {FactionNames.SpeakersForTheDead}, {FactionNames.NiteSec}, {FactionNames.TheBlackHand}
) 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
@ -225,15 +227,15 @@ BitNodes["BitNode6"] = new BitNode(
"Like Tears in Rain",
(
<>
In the middle of the 21st century, {FactionNames.OmniTekIncorporated} 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.
In the middle of the 21st century, {FactionNames.OmniTekIncorporated} 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 {FactionNames.Bladeburners} Division at the NSA, which provides a new mechanic for
progression. Furthermore:
In this BitNode you will be able to access the {FactionNames.Bladeburners} Division at the NSA, which provides a
new mechanic for progression. Furthermore:
<br />
<br />
Hacking and Hacknet Nodes will be less profitable
@ -250,9 +252,9 @@ BitNodes["BitNode6"] = new BitNode(
<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 {FactionNames.Bladeburners} Division in other
BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your combat
stats by:
level up to a maximum of 3. This Source-File allows you to access the NSA's {FactionNames.Bladeburners} 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%
@ -270,14 +272,15 @@ BitNodes["BitNode7"] = new BitNode(
"More human than humans",
(
<>
In the middle of the 21st century, you were doing cutting-edge work at {FactionNames.OmniTekIncorporated} 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
In the middle of the 21st century, you were doing cutting-edge work at {FactionNames.OmniTekIncorporated} 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 {FactionNames.Bladeburners} API, which allows you to access {FactionNames.Bladeburners}
In this BitNode you will be able to access the {FactionNames.Bladeburners} API, which allows you to access{" "}
{FactionNames.Bladeburners}
functionality through Netscript. Furthermore: <br />
<br />
The rank you gain from {FactionNames.Bladeburners} contracts/operations is reduced by 40%
@ -300,8 +303,9 @@ BitNodes["BitNode7"] = new BitNode(
<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 {FactionNames.Bladeburners} Netscript API in other BitNodes.
In addition, this Source-File will increase all of your {FactionNames.Bladeburners} multipliers by:
level up to a maximum of 3. This Source-File allows you to access the {FactionNames.Bladeburners} Netscript API in
other BitNodes. In addition, this Source-File will increase all of your {FactionNames.Bladeburners} multipliers
by:
<br />
<br />
Level 1: 8%
@ -364,10 +368,10 @@ BitNodes["BitNode9"] = new BitNode(
"Hacknet Unleashed",
(
<>
When {FactionNames.FulcrumSecretTechnologies} 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. {FactionNames.FulcrumSecretTechnologies} quickly abandoned the project and dissociated
themselves from it.
When {FactionNames.FulcrumSecretTechnologies} 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. {FactionNames.FulcrumSecretTechnologies}{" "}
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,
@ -538,8 +542,8 @@ BitNodes["BitNode13"] = new BitNode(
"1 step back, 2 steps forward",
(
<>
With the invention of Augmentations in the 2040s a religious group known as the {FactionNames.ChurchOfTheMachineGod} has
rallied far more support than anyone would have hoped.
With the invention of Augmentations in the 2040s a religious group known as the{" "}
{FactionNames.ChurchOfTheMachineGod} has rallied far more support than anyone would have hoped.
<br />
<br />
Their leader, Allison "Mother" Stanek is said to have created her own Augmentation whose power goes beyond any
@ -555,7 +559,8 @@ BitNodes["BitNode13"] = new BitNode(
<br />
<br />
Destroying this BitNode will give you Source-File 13, or if you already have this Source-File it will upgrade its
level up to a maximum of 3. This Source-File lets the {FactionNames.ChurchOfTheMachineGod} appear in other BitNodes.
level up to a maximum of 3. This Source-File lets the {FactionNames.ChurchOfTheMachineGod} appear in other
BitNodes.
<br />
<br />
Each level of this Source-File increases the size of Stanek's Gift.
@ -624,6 +629,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.PurchasedServerSoftcap = 1.3;
BitNodeMultipliers.GangSoftcap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.5;
break;
case 4: // The Singularity
BitNodeMultipliers.ServerMaxMoney = 0.15;
@ -642,6 +648,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.StaneksGiftExtraSize = 0;
BitNodeMultipliers.PurchasedServerSoftcap = 1.2;
BitNodeMultipliers.WorldDaemonDifficulty = 3;
BitNodeMultipliers.GangUniqueAugs = 0.5;
break;
case 5: // Artificial intelligence
BitNodeMultipliers.ServerMaxMoney = 2;
@ -659,6 +666,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.StaneksGiftExtraSize = 0;
BitNodeMultipliers.PurchasedServerSoftcap = 1.2;
BitNodeMultipliers.WorldDaemonDifficulty = 1.5;
BitNodeMultipliers.GangUniqueAugs = 0.5;
break;
case 6: // Bladeburner
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
@ -679,6 +687,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.7;
BitNodeMultipliers.CorporationSoftCap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.2;
break;
case 7: // Bladeburner 2079
BitNodeMultipliers.BladeburnerRank = 0.6;
@ -704,6 +713,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.7;
BitNodeMultipliers.CorporationSoftCap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.2;
break;
case 8: // Ghost of Wall Street
BitNodeMultipliers.ScriptHackMoney = 0.3;
@ -720,6 +730,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.PurchasedServerSoftcap = 4;
BitNodeMultipliers.GangSoftcap = 0;
BitNodeMultipliers.CorporationSoftCap = 0;
BitNodeMultipliers.GangUniqueAugs = 0;
break;
case 9: // Hacktocracy
BitNodeMultipliers.HackingLevelMultiplier = 0.5;
@ -746,6 +757,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.8;
BitNodeMultipliers.CorporationSoftCap = 0.7;
BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.25;
break;
case 10: // Digital Carbon
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
@ -775,6 +787,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.9;
BitNodeMultipliers.CorporationSoftCap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.25;
break;
case 11: //The Big Crash
BitNodeMultipliers.HackingLevelMultiplier = 0.6;
@ -796,6 +809,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.PurchasedServerSoftcap = 2;
BitNodeMultipliers.CorporationSoftCap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 1.5;
BitNodeMultipliers.GangUniqueAugs = 0.75;
break;
case 12: {
//The Recursion
@ -870,6 +884,8 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.8;
BitNodeMultipliers.CorporationSoftCap = 0.8;
BitNodeMultipliers.WorldDaemonDifficulty = inc;
BitNodeMultipliers.GangUniqueAugs = dec;
break;
}
case 13: {
@ -912,6 +928,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.3;
BitNodeMultipliers.CorporationSoftCap = 0.3;
BitNodeMultipliers.WorldDaemonDifficulty = 3;
BitNodeMultipliers.GangUniqueAugs = 0.1;
break;
}
default:

@ -114,6 +114,11 @@ interface IBitNodeMultipliers {
*/
GangSoftcap: number;
/**
* Percentage of unique augs that the gang has.
*/
GangUniqueAugs: number;
/**
* Influences the experienced gained when hacking a server.
*/
@ -300,6 +305,7 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
BladeburnerSkillCost: 1,
GangSoftcap: 1,
GangUniqueAugs: 1,
DaedalusAugsRequirement: 1,

@ -61,3 +61,35 @@ export class WHRNG implements RNG {
return (this.s1 / 30269.0 + this.s2 / 30307.0 + this.s3 / 30323.0) % 1.0;
}
}
export function SFC32RNG(seed: string): () => number {
let h = 1779033703 ^ seed.length;
for (let i = 0; i < seed.length; i++) {
h = Math.imul(h ^ seed.charCodeAt(i), 3432918353);
h = (h << 13) | (h >>> 19);
}
const genSeed = (): number => {
h = Math.imul(h ^ (h >>> 16), 2246822507);
h = Math.imul(h ^ (h >>> 13), 3266489909);
return (h ^= h >>> 16) >>> 0;
};
let a = genSeed();
let b = genSeed();
let c = genSeed();
let d = genSeed();
return (): number => {
a >>>= 0;
b >>>= 0;
c >>>= 0;
d >>>= 0;
let t = (a + b) | 0;
a = b ^ (b >>> 9);
b = (c + (c << 3)) | 0;
c = (c << 21) | (c >>> 11);
d = (d + 1) | 0;
t = (t + d) | 0;
c = (c + t) | 0;
return (t >>> 0) / 4294967296;
};
}

@ -8,6 +8,7 @@ import { CONSTANTS } from "../Constants";
import { Faction } from "./Faction";
import { Factions } from "./Factions";
import { Player } from "../Player";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Settings } from "../Settings/Settings";
import {
getHackingWorkRepGain,
@ -19,6 +20,7 @@ import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
import { dialogBoxCreate } from "../ui/React/DialogBox";
import { InvitationEvent } from "./ui/InvitationModal";
import { FactionNames } from "./data/FactionNames";
import { SFC32RNG } from "../Casino/RNG";
export function inviteToFaction(faction: Faction): void {
Player.receiveInvite(faction.name);
@ -32,9 +34,8 @@ export function joinFaction(faction: Faction): void {
if (faction.isMember) return;
faction.isMember = true;
Player.factions.push(faction.name);
const allFactions = Object.values(FactionNames).map(faction => faction as string)
Player.factions.sort((a, b) =>
allFactions.indexOf(a) - allFactions.indexOf(b));
const allFactions = Object.values(FactionNames).map((faction) => faction as string);
Player.factions.sort((a, b) => allFactions.indexOf(a) - allFactions.indexOf(b));
const factionInfo = faction.getInfo();
//Determine what factions you are banned from now that you have joined this faction
@ -134,18 +135,18 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
} else if (!Settings.SuppressBuyAugmentationConfirmation) {
dialogBoxCreate(
"You purchased " +
aug.name +
". Its enhancements will not take " +
"effect until they are installed. To install your augmentations, go to the " +
"'Augmentations' tab on the left-hand navigation menu. Purchasing additional " +
"augmentations will now be more expensive.",
aug.name +
". Its enhancements will not take " +
"effect until they are installed. To install your augmentations, go to the " +
"'Augmentations' tab on the left-hand navigation menu. Purchasing additional " +
"augmentations will now be more expensive.",
);
}
} else {
dialogBoxCreate(
"Hmm, something went wrong when trying to purchase an Augmentation. " +
"Please report this to the game developer with an explanation of how to " +
"reproduce this.",
"Please report this to the game developer with an explanation of how to " +
"reproduce this.",
);
}
return "";
@ -193,3 +194,43 @@ export function processPassiveFactionRepGain(numCycles: number): void {
faction.playerReputation += rate * numCycles * Player.faction_rep_mult * BitNodeMultipliers.FactionPassiveRepGain;
}
}
export const getFactionAugmentationsFiltered = (player: IPlayer, faction: Faction): string[] => {
// If player has a gang with this faction, return (almost) all augmentations
if (player.hasGangWith(faction.name)) {
let augs = Object.values(Augmentations);
// Remove special augs
augs = augs.filter((a) => !a.isSpecial);
const blacklist: string[] = [AugmentationNames.NeuroFluxGovernor];
if (player.bitNodeN !== 2) {
// TRP is not available outside of BN2 for Gangs
blacklist.push(AugmentationNames.TheRedPill);
}
const rng = SFC32RNG(`BN${player.bitNodeN}.${player.sourceFileLvl(player.bitNodeN)}`);
// Remove faction-unique augs that don't belong to this faction
const uniqueFilter = (a: Augmentation): boolean => {
// Keep all the non-unique one
if (a.factions.length > 1) {
return true;
}
// Keep all the ones that this faction has anyway.
if (faction.augmentations.includes(a.name)) {
return true;
}
return rng() >= 1 - BitNodeMultipliers.GangUniqueAugs;
};
augs = augs.filter(uniqueFilter);
// Remove blacklisted augs
augs = augs.filter((a) => !blacklist.includes(a.name));
return augs.map((a) => a.name);
}
return faction.augmentations.slice();
};

@ -10,7 +10,7 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Faction } from "../Faction";
import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { Settings } from "../../Settings/Settings";
import { hasAugmentationPrereqs } from "../FactionHelpers";
import { hasAugmentationPrereqs, getFactionAugmentationsFiltered } from "../FactionHelpers";
import { use } from "../../ui/Context";
import { Reputation } from "../../ui/React/Reputation";
@ -42,28 +42,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
}
function getAugs(): string[] {
if (isPlayersGang) {
// TODO: this code is duplicated in getAugmentationsFromFaction DRY
let augs = Object.values(Augmentations);
// Remove special augs.
augs = augs.filter((a) => !a.isSpecial);
if (player.bitNodeN !== 2) {
// Remove faction-unique augs outside BN2. (But keep the one for this faction.)
augs = augs.filter((a) => a.factions.length > 1 || props.faction.augmentations.includes(a.name));
// Remove blacklisted augs.
const blacklist = [AugmentationNames.NeuroFluxGovernor, AugmentationNames.TheRedPill].map(
(augmentation) => augmentation as string,
);
augs = augs.filter((a) => !blacklist.includes(a.name));
}
return augs.map((a) => a.name);
} else {
return props.faction.augmentations.slice();
}
return getFactionAugmentationsFiltered(player, props.faction);
}
function getAugsSorted(): string[] {

@ -9,7 +9,7 @@ import { Table, TableCell } from "../../ui/React/Table";
import { IRouter } from "../../ui/Router";
import { Faction } from "../Faction";
import { joinFaction } from "../FactionHelpers";
import { joinFaction, getFactionAugmentationsFiltered } from "../FactionHelpers";
import { Factions } from "../Factions";
import { FactionNames } from "../data/FactionNames";
@ -52,26 +52,7 @@ export function FactionsRoot(props: IProps): React.ReactElement {
}
const getAugsLeft = (faction: Faction, player: IPlayer): number => {
const isPlayersGang = player.inGang() && player.getGangName() === faction.name;
let augs: string[] = [];
if (isPlayersGang) {
for (const augName of Object.keys(Augmentations)) {
const aug = Augmentations[augName];
if (
augName === AugmentationNames.NeuroFluxGovernor ||
(augName === AugmentationNames.TheRedPill && player.bitNodeN !== 2) ||
// Special augs (i.e. Bladeburner augs)
aug.isSpecial ||
// Exclusive augs (i.e. QLink)
(aug.factions.length <= 1 && !faction.augmentations.includes(augName) && player.bitNodeN !== 2)
)
continue;
augs.push(augName);
}
} else {
augs = faction.augmentations.slice();
}
const augs = getFactionAugmentationsFiltered(player, faction);
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation)).length;
};

@ -63,7 +63,7 @@ export function WireCuttingGame(props: IMinigameProps): React.ReactElement {
const [questions] = useState(generateQuestion(wires, difficulty));
function checkWire(wireNum: number): boolean {
return questions.some((q) => q.shouldCut(wires[wireNum - 1], wireNum - 1));
return !questions.some((q) => q.shouldCut(wires[wireNum - 1], wireNum - 1));
}
function press(this: Document, event: KeyboardEvent): void {

@ -1,7 +1,7 @@
import { INetscriptHelper } from "./INetscriptHelper";
import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer";
import { purchaseAugmentation, joinFaction } from "../Faction/FactionHelpers";
import { purchaseAugmentation, joinFaction, getFactionAugmentationsFiltered } from "../Faction/FactionHelpers";
import { startWorkerScript } from "../NetscriptWorker";
import { Augmentation } from "../Augmentation/Augmentation";
import { Augmentations } from "../Augmentation/Augmentations";
@ -118,28 +118,7 @@ export function NetscriptSingularity(
helper.checkSingularityAccess("getAugmentationsFromFaction");
const faction = getFaction("getAugmentationsFromFaction", facName);
// If player has a gang with this faction, return all augmentations.
if (player.hasGangWith(facName)) {
let augs = Object.values(Augmentations);
// Remove special augs.
augs = augs.filter((a) => !a.isSpecial);
if (player.bitNodeN !== 2) {
// Remove faction-unique augs outside BN2. (But keep the one for this faction.)
augs = augs.filter((a) => a.factions.length > 1 || Factions[facName].augmentations.includes(a.name));
// Remove blacklisted augs.
const blacklist = [AugmentationNames.NeuroFluxGovernor, AugmentationNames.TheRedPill].map(
(augmentation) => augmentation as string,
);
augs = augs.filter((a) => !blacklist.includes(a.name));
}
return augs.map((a) => a.name);
}
return faction.augmentations.slice();
return getFactionAugmentationsFiltered(player, faction);
},
getAugmentationCost: function (_augName: unknown): [number, number] {
const augName = helper.string("getAugmentationCost", "augName", _augName);
@ -184,24 +163,7 @@ export function NetscriptSingularity(
const fac = getFaction("purchaseAugmentation", facName);
const aug = getAugmentation("purchaseAugmentation", augName);
let augs = [];
if (player.hasGangWith(facName)) {
for (const augName of Object.keys(Augmentations)) {
const aug = Augmentations[augName];
if (
augName === AugmentationNames.NeuroFluxGovernor ||
(augName === AugmentationNames.TheRedPill && player.bitNodeN !== 2) ||
// Special augs (i.e. Bladeburner augs)
aug.isSpecial ||
// Exclusive augs (i.e. QLink)
(aug.factions.length <= 1 && !fac.augmentations.includes(augName) && player.bitNodeN !== 2)
)
continue;
augs.push(augName);
}
} else {
augs = fac.augmentations;
}
const augs = getFactionAugmentationsFiltered(player, fac);
if (!augs.includes(augName)) {
workerScript.log(

@ -64,74 +64,78 @@ export const GraftingRoot = (): React.ReactElement => {
<Box sx={{ my: 3 }}>
<Typography variant="h5">Graft Augmentations</Typography>
<Paper sx={{ my: 1, width: "fit-content", display: "grid", gridTemplateColumns: "1fr 3fr" }}>
<List sx={{ maxHeight: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
{getAvailableAugs(player).map((k, i) => (
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
<Typography>{k}</Typography>
</ListItemButton>
))}
</List>
<Box sx={{ m: 1 }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
<Construction sx={{ mr: 1 }} /> {selectedAug}
</Typography>
<Button
onClick={() => setGraftOpen(true)}
sx={{ width: "100%" }}
disabled={player.money < GraftableAugmentations[selectedAug].cost}
>
Graft Augmentation (
<Typography>
<Money money={GraftableAugmentations[selectedAug].cost} player={player} />
{getAvailableAugs(player).length > 0 ? (
<Paper sx={{ my: 1, width: "fit-content", display: "grid", gridTemplateColumns: "1fr 3fr" }}>
<List sx={{ maxHeight: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
{getAvailableAugs(player).map((k, i) => (
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
<Typography>{k}</Typography>
</ListItemButton>
))}
</List>
<Box sx={{ m: 1 }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
<Construction sx={{ mr: 1 }} /> {selectedAug}
</Typography>
)
</Button>
<ConfirmationModal
open={graftOpen}
onClose={() => setGraftOpen(false)}
onConfirm={() => {
const graftableAug = GraftableAugmentations[selectedAug];
player.loseMoney(graftableAug.cost, "augmentations");
player.startGraftAugmentationWork(selectedAug, graftableAug.time);
player.startFocusing();
router.toWork();
}}
confirmationText={
<>
Cancelling grafting will <b>not</b> save grafting progress, and the money you spend will <b>not</b> be
returned.
<br />
<br />
Additionally, grafting an Augmentation will increase the potency of the Entropy virus.
</>
}
/>
<Typography color={Settings.theme.info}>
<b>Time to Graft:</b>{" "}
{convertTimeMsToTimeElapsedString(
GraftableAugmentations[selectedAug].time / (1 + (player.getIntelligenceBonus(3) - 1) / 3),
)}
{/* Use formula so the displayed creation time is accurate to player bonus */}
</Typography>
<Typography sx={{ maxHeight: 305, overflowY: "scroll" }}>
{(() => {
const aug = Augmentations[selectedAug];
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
const tooltip = (
<Button
onClick={() => setGraftOpen(true)}
sx={{ width: "100%" }}
disabled={player.money < GraftableAugmentations[selectedAug].cost}
>
Graft Augmentation (
<Typography>
<Money money={GraftableAugmentations[selectedAug].cost} player={player} />
</Typography>
)
</Button>
<ConfirmationModal
open={graftOpen}
onClose={() => setGraftOpen(false)}
onConfirm={() => {
const graftableAug = GraftableAugmentations[selectedAug];
player.loseMoney(graftableAug.cost, "augmentations");
player.startGraftAugmentationWork(selectedAug, graftableAug.time);
player.startFocusing();
router.toWork();
}}
confirmationText={
<>
{info}
Cancelling grafting will <b>not</b> save grafting progress, and the money you spend will <b>not</b>{" "}
be returned.
<br />
<br />
{aug.stats}
Additionally, grafting an Augmentation will increase the potency of the Entropy virus.
</>
);
return tooltip;
})()}
</Typography>
</Box>
</Paper>
}
/>
<Typography color={Settings.theme.info}>
<b>Time to Graft:</b>{" "}
{convertTimeMsToTimeElapsedString(
GraftableAugmentations[selectedAug].time / (1 + (player.getIntelligenceBonus(3) - 1) / 3),
)}
{/* Use formula so the displayed creation time is accurate to player bonus */}
</Typography>
<Typography sx={{ maxHeight: 305, overflowY: "scroll" }}>
{(() => {
const aug = Augmentations[selectedAug];
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
const tooltip = (
<>
{info}
<br />
<br />
{aug.stats}
</>
);
return tooltip;
})()}
</Typography>
</Box>
</Paper>
) : (
<Typography>All Augmentations owned</Typography>
)}
</Box>
<Box sx={{ my: 3 }}>

@ -217,11 +217,19 @@ export function WorkInProgressRoot(): React.ReactElement {
if (player.workType == CONSTANTS.WorkTypeCompany) {
const comp = Companies[player.companyName];
let companyRep = 0;
if (comp == null || !(comp instanceof Company)) {
throw new Error(`Could not find Company: ${player.companyName}`);
return (
<>
<Typography variant="h4" color="primary">
You cannot work for {player.companyName || "(Company not found)"} at this time, please try again if you
think this should have worked
</Typography>
<Button onClick={() => router.toTerminal()}>Back to Terminal</Button>
</>
);
}
companyRep = comp.playerReputation;
const companyRep = comp.playerReputation;
function cancel(): void {
player.finishWork(true);