Merge branch 'dev' into bugfix/3348

# Conflicts:
#	src/Faction/FactionInfo.tsx
#	src/NetscriptFunctions/Singularity.ts
This commit is contained in:
phyzical
2022-04-07 16:17:28 +08:00
188 changed files with 4016 additions and 3210 deletions
+37 -22
View File
@@ -3,7 +3,7 @@ import React from "react";
import { Box, Typography } from "@mui/material";
import { Achievement } from "./Achievements";
import { Settings } from "../Settings/Settings"
import { Settings } from "../Settings/Settings";
import { AchievementIcon } from "./AchievementIcon";
interface IProps {
@@ -13,43 +13,58 @@ interface IProps {
cssFiltersLocked: string;
}
export function AchievementEntry({ achievement, unlockedOn, cssFiltersUnlocked, cssFiltersLocked }: IProps): JSX.Element {
export function AchievementEntry({
achievement,
unlockedOn,
cssFiltersUnlocked,
cssFiltersLocked,
}: IProps): JSX.Element {
if (!achievement) return <></>;
const isUnlocked = !!unlockedOn;
const mainColor = isUnlocked ? Settings.theme.primary : Settings.theme.secondarylight;
let achievedOn = '';
let achievedOn = "";
if (unlockedOn) {
achievedOn = new Date(unlockedOn).toLocaleString();
}
return (
<Box sx={{
border: `1px solid ${Settings.theme.well}`, mb: 2
}}>
<Box sx={{
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
}}>
<Box
sx={{
border: `1px solid ${Settings.theme.well}`,
mb: 2,
}}
>
<Box
sx={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
}}
>
<AchievementIcon
achievement={achievement} unlocked={isUnlocked} size="72px"
colorFilters={isUnlocked ? cssFiltersUnlocked: cssFiltersLocked} />
<Box sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
px: 1
}}>
<Typography variant="h6" sx={{ color: mainColor}}>
achievement={achievement}
unlocked={isUnlocked}
size="72px"
colorFilters={isUnlocked ? cssFiltersUnlocked : cssFiltersLocked}
/>
<Box
sx={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
px: 1,
}}
>
<Typography variant="h6" sx={{ color: mainColor }}>
{achievement.Name}
</Typography>
<Typography variant="body2" sx={{ maxWidth: '500px', color: mainColor}}>
<Typography variant="body2" sx={{ maxWidth: "500px", color: mainColor }}>
{achievement.Description}
</Typography>
{isUnlocked && (
<Typography variant="caption" sx={{ fontSize: '12px', color: Settings.theme.primarydark }}>
<Typography variant="caption" sx={{ fontSize: "12px", color: Settings.theme.primarydark }}>
Acquired on {achievedOn}
</Typography>
)}
+9 -6
View File
@@ -3,7 +3,7 @@ import React, { useState } from "react";
import { Box } from "@mui/material";
import { Achievement } from "./Achievements";
import { Settings } from "../Settings/Settings"
import { Settings } from "../Settings/Settings";
interface IProps {
achievement: Achievement;
@@ -16,20 +16,23 @@ export function AchievementIcon({ achievement, unlocked, colorFilters, size }: I
const [imgLoaded, setImgLoaded] = useState(false);
const mainColor = unlocked ? Settings.theme.primarydark : Settings.theme.secondarydark;
if (!achievement.Icon) return (<></>);
if (!achievement.Icon) return <></>;
return (
<Box
sx={{
border: `1px solid ${mainColor}`,
width: size, height: size,
width: size,
height: size,
m: 1,
visibility: imgLoaded ? 'visible' : 'hidden'
visibility: imgLoaded ? "visible" : "hidden",
}}
>
<img src={`dist/icons/achievements/${encodeURI(achievement.Icon)}.svg`}
<img
src={`dist/icons/achievements/${encodeURI(achievement.Icon)}.svg`}
style={{ filter: colorFilters, width: size, height: size }}
onLoad={() => setImgLoaded(true)}
alt={achievement.Name} />
alt={achievement.Name}
/>
</Box>
);
}
+36 -25
View File
@@ -3,8 +3,8 @@ import React from "react";
import { Accordion, AccordionSummary, AccordionDetails, Box, Typography } from "@mui/material";
import { AchievementEntry } from "./AchievementEntry";
import { Achievement, PlayerAchievement} from "./Achievements";
import { Settings } from "../Settings/Settings"
import { Achievement, PlayerAchievement } from "./Achievements";
import { Settings } from "../Settings/Settings";
import { getFiltersFromHex } from "../ThirdParty/colorUtils";
import { CorruptableText } from "../ui/React/CorruptableText";
@@ -18,32 +18,39 @@ export function AchievementList({ achievements, playerAchievements }: IProps): J
const cssPrimary = getFiltersFromHex(Settings.theme.primary);
const cssSecondary = getFiltersFromHex(Settings.theme.secondary);
const data = achievements.map(achievement => ({
achievement,
unlockedOn: playerAchievements.find(playerAchievement => playerAchievement.ID === achievement.ID)?.unlockedOn,
})).sort((a, b) => (b.unlockedOn ?? 0) - (a.unlockedOn ?? 0));
const data = achievements
.map((achievement) => ({
achievement,
unlockedOn: playerAchievements.find((playerAchievement) => playerAchievement.ID === achievement.ID)?.unlockedOn,
}))
.sort((a, b) => (b.unlockedOn ?? 0) - (a.unlockedOn ?? 0));
const unlocked = data.filter(entry => entry.unlockedOn);
const unlocked = data.filter((entry) => entry.unlockedOn);
// Hidden achievements
const secret = data.filter(entry => !entry.unlockedOn && entry.achievement.Secret)
const secret = data.filter((entry) => !entry.unlockedOn && entry.achievement.Secret);
// Locked behind locked content (bitnode x)
const unavailable = data.filter(entry => !entry.unlockedOn && !entry.achievement.Secret && entry.achievement.Visible && !entry.achievement.Visible());
const unavailable = data.filter(
(entry) =>
!entry.unlockedOn && !entry.achievement.Secret && entry.achievement.Visible && !entry.achievement.Visible(),
);
// Remaining achievements
const locked = data
.filter(entry => !unlocked.map(u => u.achievement.ID).includes(entry.achievement.ID))
.filter(entry => !secret.map(u => u.achievement.ID).includes(entry.achievement.ID))
.filter(entry => !unavailable.map(u => u.achievement.ID).includes(entry.achievement.ID));
.filter((entry) => !unlocked.map((u) => u.achievement.ID).includes(entry.achievement.ID))
.filter((entry) => !secret.map((u) => u.achievement.ID).includes(entry.achievement.ID))
.filter((entry) => !unavailable.map((u) => u.achievement.ID).includes(entry.achievement.ID));
return (
<Box sx={{ pr: 18, my: 2 }}>
<Box sx={{
display: 'flex',
flexDirection: 'column',
flexWrap: 'wrap',
}}>
<Box
sx={{
display: "flex",
flexDirection: "column",
flexWrap: "wrap",
}}
>
{unlocked.length > 0 && (
<Accordion defaultExpanded disableGutters square>
<AccordionSummary>
@@ -52,12 +59,14 @@ export function AchievementList({ achievements, playerAchievements }: IProps): J
</Typography>
</AccordionSummary>
<AccordionDetails sx={{ pt: 2 }}>
{unlocked.map(item => (
<AchievementEntry key={`unlocked_${item.achievement.ID}`}
{unlocked.map((item) => (
<AchievementEntry
key={`unlocked_${item.achievement.ID}`}
achievement={item.achievement}
unlockedOn={item.unlockedOn}
cssFiltersUnlocked={cssPrimary}
cssFiltersLocked={cssSecondary} />
cssFiltersLocked={cssSecondary}
/>
))}
</AccordionDetails>
</Accordion>
@@ -71,11 +80,13 @@ export function AchievementList({ achievements, playerAchievements }: IProps): J
</Typography>
</AccordionSummary>
<AccordionDetails sx={{ pt: 2 }}>
{locked.map(item => (
<AchievementEntry key={`locked_${item.achievement.ID}`}
{locked.map((item) => (
<AchievementEntry
key={`locked_${item.achievement.ID}`}
achievement={item.achievement}
cssFiltersUnlocked={cssPrimary}
cssFiltersLocked={cssSecondary} />
cssFiltersLocked={cssSecondary}
/>
))}
</AccordionDetails>
</Accordion>
@@ -89,7 +100,7 @@ export function AchievementList({ achievements, playerAchievements }: IProps): J
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography sx={{ mt: 1 }}>
<Typography sx={{ mt: 1 }}>
{unavailable.length} additional achievements hidden behind content you don't have access to.
</Typography>
</AccordionDetails>
@@ -105,7 +116,7 @@ export function AchievementList({ achievements, playerAchievements }: IProps): J
</AccordionSummary>
<AccordionDetails>
<Typography color="secondary" sx={{ mt: 1 }}>
{secret.map(item => (
{secret.map((item) => (
<span key={`secret_${item.achievement.ID}`}>
<CorruptableText content={item.achievement.ID}></CorruptableText>
<br />
+7 -7
View File
@@ -1,9 +1,9 @@
# Adding Achievements
* Add a .svg in `./assets/Steam/achievements/real`
* Create the achievement in Steam Dev Portal
* Run `sh ./assets/Steam/achievements/pack-for-web.sh`
* Run `node ./tools/fetch-steam-achievements-data DEVKEYHERE`
* Get your key here: https://steamcommunity.com/dev/apikey
* Add an entry in `./src/Achievements/Achievements.ts` -> achievements
* Commit `./dist/icons/achievements` & `./src/Achievements/AchievementData.json`
- Add a .svg in `./assets/Steam/achievements/real`
- Create the achievement in Steam Dev Portal
- Run `sh ./assets/Steam/achievements/pack-for-web.sh`
- Run `node ./tools/fetch-steam-achievements-data DEVKEYHERE`
- Get your key here: https://steamcommunity.com/dev/apikey
- Add an entry in `./src/Achievements/Achievements.ts` -> achievements
- Commit `./dist/icons/achievements` & `./src/Achievements/AchievementData.json`
+3 -3
View File
@@ -94,7 +94,7 @@ function getRandomBonus(): any {
return bonuses[Math.floor(bonuses.length * randomNumber.random())];
}
export const generalAugmentations = [
export const initGeneralAugmentations = (): Augmentation[] => [
new Augmentation({
name: AugmentationNames.HemoRecirculator,
moneyCost: 4.5e7,
@@ -1486,7 +1486,7 @@ export const generalAugmentations = [
}),
];
export const bladeburnerAugmentations = [
export const initBladeburnerAugmentations = (): Augmentation[] => [
new Augmentation({
name: AugmentationNames.EsperEyewear,
repCost: 1.25e3,
@@ -1751,7 +1751,7 @@ export const bladeburnerAugmentations = [
}),
];
export const churchOfTheMachineGodAugmentations = [
export const initChurchOfTheMachineGodAugmentations = (): Augmentation[] => [
new Augmentation({
name: AugmentationNames.StaneksGift1,
repCost: 0,
+6 -6
View File
@@ -15,9 +15,9 @@ import { clearObject } from "../utils/helpers/clearObject";
import { FactionNames } from "../Faction/data/FactionNames";
import {
bladeburnerAugmentations,
churchOfTheMachineGodAugmentations,
generalAugmentations,
initBladeburnerAugmentations,
initChurchOfTheMachineGodAugmentations,
initGeneralAugmentations,
initNeuroFluxGovernor,
initUnstableCircadianModulator,
} from "./AugmentationCreator";
@@ -50,9 +50,9 @@ function createAugmentations(): void {
[
initNeuroFluxGovernor(),
initUnstableCircadianModulator(),
...generalAugmentations,
...(factionExists(FactionNames.Bladeburners) ? bladeburnerAugmentations : []),
...(factionExists(FactionNames.ChurchOfTheMachineGod) ? churchOfTheMachineGodAugmentations : []),
...initGeneralAugmentations(),
...(factionExists(FactionNames.Bladeburners) ? initBladeburnerAugmentations() : []),
...(factionExists(FactionNames.ChurchOfTheMachineGod) ? initChurchOfTheMachineGodAugmentations() : []),
].map(resetAugmentation);
}
+1 -3
View File
@@ -134,9 +134,7 @@ export class Action implements IAction {
for (const decay of Object.keys(this.decays)) {
if (this.decays.hasOwnProperty(decay)) {
if (this.decays[decay] > 1) {
throw new Error(
`Invalid decays when constructing Action ${this.name}. Decay value cannot be greater than 1`,
);
throw new Error(`Invalid decays when constructing Action ${this.name}. Decay value cannot be greater than 1`);
}
}
}
+3 -3
View File
@@ -3,16 +3,16 @@ import { IMap } from "../types";
export const GeneralActions: IMap<Action> = {};
const actionNames : Array<string> = [
const actionNames: Array<string> = [
"Training",
"Field Analysis",
"Recruitment",
"Diplomacy",
"Hyperbolic Regeneration Chamber",
"Incite Violence"
"Incite Violence",
];
for (const actionName of actionNames){
for (const actionName of actionNames) {
GeneralActions[actionName] = new Action({
name: actionName,
});
+1 -2
View File
@@ -7,8 +7,7 @@ export const Skills: IMap<Skill> = {};
(function () {
Skills[SkillNames.BladesIntuition] = new Skill({
name: SkillNames.BladesIntuition,
desc:
"Each level of this skill increases your success chance for all Contracts, Operations, and BlackOps by 3%",
desc: "Each level of this skill increases your success chance for all Contracts, Operations, and BlackOps by 3%",
baseCost: 3,
costInc: 2.1,
successChanceAll: 3,
+64 -59
View File
@@ -17,8 +17,8 @@ export const BlackOperations: {
Zenyatta, along with the rest of the PMC, is a Synthoid.
<br />
<br />
The goal of {BlackOperationNames.OperationTyphoon} is to find and eliminate Zenyatta and RedWater by any means necessary. After the
task is completed, the actions must be covered up from the general public.
The goal of {BlackOperationNames.OperationTyphoon} is to find and eliminate Zenyatta and RedWater by any means
necessary. After the task is completed, the actions must be covered up from the general public.
</>
),
},
@@ -30,10 +30,10 @@ export const BlackOperations: {
supporter of Synthoid rights. He must be removed.
<br />
<br />
The goal of {BlackOperationNames.OperationZero} is to covertly infiltrate AeroCorp and uncover any incriminating evidence or
information against Watataki that will cause him to be removed from his position at AeroCorp. Incriminating
evidence can be fabricated as a last resort. Be warned that AeroCorp has some of the most advanced security
measures in the world.
The goal of {BlackOperationNames.OperationZero} is to covertly infiltrate AeroCorp and uncover any incriminating
evidence or information against Watataki that will cause him to be removed from his position at AeroCorp.
Incriminating evidence can be fabricated as a last resort. Be warned that AeroCorp has some of the most advanced
security measures in the world.
</>
),
},
@@ -47,8 +47,8 @@ export const BlackOperations: {
<br />
<br />
Samizdat has done a good job of keeping hidden and anonymous. However, we've just received intelligence that
their base of operations is in {CityName.Ishima}'s underground sewer systems. Your task is to investigate the sewer
systems, and eliminate Samizdat. They must never publish anything again.
their base of operations is in {CityName.Ishima}'s underground sewer systems. Your task is to investigate the
sewer systems, and eliminate Samizdat. They must never publish anything again.
</>
),
},
@@ -61,9 +61,9 @@ export const BlackOperations: {
dangerous.
<br />
<br />
Your goal is to enter and destroy the Bioengineering department's facility in {CityName.Aevum}. The task is not just to
retire the Synthoids there, but also to destroy any information or research at the facility that is relevant to
the Synthoids and their goals.
Your goal is to enter and destroy the Bioengineering department's facility in {CityName.Aevum}. The task is not
just to retire the Synthoids there, but also to destroy any information or research at the facility that is
relevant to the Synthoids and their goals.
</>
),
},
@@ -96,10 +96,10 @@ export const BlackOperations: {
desc: (
<>
The CIA has just encountered a new security threat. A new criminal group, lead by a shadowy operative who calls
himself Juggernaut, has been smuggling drugs and weapons (including suspected bioweapons) into {CityName.Sector12}. We
also have reason to believe they tried to break into one of Universal Energy's facilities in order to cause a
city-wide blackout. The CIA suspects that Juggernaut is a heavily-augmented Synthoid, and have thus enlisted our
help.
himself Juggernaut, has been smuggling drugs and weapons (including suspected bioweapons) into{" "}
{CityName.Sector12}. We also have reason to believe they tried to break into one of Universal Energy's
facilities in order to cause a city-wide blackout. The CIA suspects that Juggernaut is a heavily-augmented
Synthoid, and have thus enlisted our help.
<br />
<br />
Your mission is to eradicate Juggernaut and his followers.
@@ -109,13 +109,13 @@ export const BlackOperations: {
[BlackOperationNames.OperationRedDragon]: {
desc: (
<>
The {FactionNames.Tetrads} criminal organization is suspected of reverse-engineering the MK-VI Synthoid design. We believe they
altered and possibly improved the design and began manufacturing their own Synthoid models in order to bolster
their criminal activities.
The {FactionNames.Tetrads} criminal organization is suspected of reverse-engineering the MK-VI Synthoid design.
We believe they altered and possibly improved the design and began manufacturing their own Synthoid models in
order to bolster their criminal activities.
<br />
<br />
Your task is to infiltrate and destroy the {FactionNames.Tetrads}' base of operations in Los Angeles. Intelligence tells us
that their base houses one of their Synthoid manufacturing units.
Your task is to infiltrate and destroy the {FactionNames.Tetrads}' base of operations in Los Angeles.
Intelligence tells us that their base houses one of their Synthoid manufacturing units.
</>
),
},
@@ -138,23 +138,24 @@ export const BlackOperations: {
[BlackOperationNames.OperationDeckard]: {
desc: (
<>
Despite your success in eliminating VitaLife's new android-replicating technology in {BlackOperationNames.OperationK}, we've
discovered that a small group of MK-VI Synthoids were able to make off with the schematics and design of the
technology before the Operation. It is almost a certainty that these Synthoids are some of the rogue MK-VI ones
from the Synthoid Uprising.
Despite your success in eliminating VitaLife's new android-replicating technology in{" "}
{BlackOperationNames.OperationK}, we've discovered that a small group of MK-VI Synthoids were able to make off
with the schematics and design of the technology before the Operation. It is almost a certainty that these
Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising.
<br />
<br />
The goal of {BlackOperationNames.OperationDeckard} is to hunt down these Synthoids and retire them. I don't need to tell you how
critical this mission is.
The goal of {BlackOperationNames.OperationDeckard} is to hunt down these Synthoids and retire them. I don't need
to tell you how critical this mission is.
</>
),
},
[BlackOperationNames.OperationTyrell]: {
desc: (
<>
A week ago {FactionNames.BladeIndustries} reported a small break-in at one of their {CityName.Aevum} Augmentation storage facilities. We
figured out that {FactionNames.TheDarkArmy} was behind the heist, and didn't think any more of it. However, we've just
discovered that several known MK-VI Synthoids were part of that break-in group.
A week ago {FactionNames.BladeIndustries} reported a small break-in at one of their {CityName.Aevum}{" "}
Augmentation storage facilities. We figured out that {FactionNames.TheDarkArmy} was behind the heist, and didn't
think any more of it. However, we've just discovered that several known MK-VI Synthoids were part of that
break-in group.
<br />
<br />
We cannot have Synthoids upgrading their already-enhanced abilities with Augmentations. Your task is to hunt
@@ -165,15 +166,17 @@ export const BlackOperations: {
[BlackOperationNames.OperationWallace]: {
desc: (
<>
Based on information gathered from {BlackOperationNames.OperationTyrell}, we've discovered that {FactionNames.TheDarkArmy} was well aware that
there were Synthoids amongst their ranks. Even worse, we believe that {FactionNames.TheDarkArmy} is working together with
other criminal organizations such as {FactionNames.TheSyndicate} and that they are planning some sort of large-scale takeover
of multiple major cities, most notably {CityName.Aevum}. We suspect that Synthoids have infiltrated the ranks of these
criminal factions and are trying to stage another Synthoid uprising.
Based on information gathered from {BlackOperationNames.OperationTyrell}, we've discovered that{" "}
{FactionNames.TheDarkArmy} was well aware that there were Synthoids amongst their ranks. Even worse, we believe
that {FactionNames.TheDarkArmy} is working together with other criminal organizations such as{" "}
{FactionNames.TheSyndicate} and that they are planning some sort of large-scale takeover of multiple major
cities, most notably {CityName.Aevum}. We suspect that Synthoids have infiltrated the ranks of these criminal
factions and are trying to stage another Synthoid uprising.
<br />
<br />
The best way to deal with this is to prevent it before it even happens. The goal of {BlackOperationNames.OperationWallace} is to
destroy {FactionNames.TheDarkArmy} and Syndicate factions in {CityName.Aevum} immediately. Leave no survivors.
The best way to deal with this is to prevent it before it even happens. The goal of{" "}
{BlackOperationNames.OperationWallace} is to destroy {FactionNames.TheDarkArmy} and Syndicate factions in{" "}
{CityName.Aevum} immediately. Leave no survivors.
</>
),
},
@@ -193,18 +196,18 @@ export const BlackOperations: {
[BlackOperationNames.OperationHyron]: {
desc: (
<>
Our intelligence tells us that {FactionNames.FulcrumSecretTechnologies} is developing a quantum supercomputer using human brains as
core processors. This supercomputer is rumored to be able to store vast amounts of data and perform computations
unmatched by any other supercomputer on the planet. But more importantly, the use of organic human brains means
that the supercomputer may be able to reason abstractly and become self-aware.
Our intelligence tells us that {FactionNames.FulcrumSecretTechnologies} is developing a quantum supercomputer
using human brains as core processors. This supercomputer is rumored to be able to store vast amounts of data
and perform computations unmatched by any other supercomputer on the planet. But more importantly, the use of
organic human brains means that the supercomputer may be able to reason abstractly and become self-aware.
<br />
<br />
I do not need to remind you why sentient-level AIs pose a serious threat to all of mankind.
<br />
<br />
The research for this project is being conducted at one of {FactionNames.FulcrumSecretTechnologies} secret facilities in {CityName.Aevum},
codenamed 'Alpha Ranch'. Infiltrate the compound, delete and destroy the work, and then find and kill the
project lead.
The research for this project is being conducted at one of {FactionNames.FulcrumSecretTechnologies} secret
facilities in {CityName.Aevum}, codenamed 'Alpha Ranch'. Infiltrate the compound, delete and destroy the work,
and then find and kill the project lead.
</>
),
},
@@ -213,8 +216,8 @@ export const BlackOperations: {
<>
DreamSense Technologies is an advertising company that uses special technology to transmit their ads into the
people's dreams and subconcious. They do this using broadcast transmitter towers. Based on information from our
agents and informants in {CityName.Chongqing}, we have reason to believe that one of the broadcast towers there has been
compromised by Synthoids and is being used to spread pro-Synthoid propaganda.
agents and informants in {CityName.Chongqing}, we have reason to believe that one of the broadcast towers there
has been compromised by Synthoids and is being used to spread pro-Synthoid propaganda.
<br />
<br />
The mission is to destroy this broadcast tower. Speed and stealth are of the utmost importance for this.
@@ -224,36 +227,38 @@ export const BlackOperations: {
[BlackOperationNames.OperationIonStorm]: {
desc: (
<>
Our analysts have uncovered a gathering of MK-VI Synthoids that have taken up residence in the {CityName.Sector12} Slums.
We don't know if they are rogue Synthoids from the Uprising, but we do know that they have been stockpiling
weapons, money, and other resources. This makes them dangerous.
Our analysts have uncovered a gathering of MK-VI Synthoids that have taken up residence in the{" "}
{CityName.Sector12} Slums. We don't know if they are rogue Synthoids from the Uprising, but we do know that they
have been stockpiling weapons, money, and other resources. This makes them dangerous.
<br />
<br />
This is a full-scale assault operation to find and retire all of these Synthoids in the {CityName.Sector12} Slums.
This is a full-scale assault operation to find and retire all of these Synthoids in the {CityName.Sector12}{" "}
Slums.
</>
),
},
[BlackOperationNames.OperationAnnihilus]: {
desc: (
<>
Our superiors have ordered us to eradicate everything and everyone in an underground facility located in {CityName.Aevum}.
They tell us that the facility houses many dangerous Synthoids and belongs to a terrorist organization called
'{FactionNames.TheCovenant}'. We have no prior intelligence about this organization, so you are going in blind.
Our superiors have ordered us to eradicate everything and everyone in an underground facility located in{" "}
{CityName.Aevum}. They tell us that the facility houses many dangerous Synthoids and belongs to a terrorist
organization called '{FactionNames.TheCovenant}'. We have no prior intelligence about this organization, so you
are going in blind.
</>
),
},
[BlackOperationNames.OperationUltron]: {
desc: (
<>
{FactionNames.OmniTekIncorporated}, the original designer and manufacturer of Synthoids, has notified us of a malfunction in
their AI design. This malfunction, when triggered, causes MK-VI Synthoids to become radicalized and seek out the
destruction of humanity. They say that this bug affects all MK-VI Synthoids, not just the rogue ones from the
Uprising.
{FactionNames.OmniTekIncorporated}, the original designer and manufacturer of Synthoids, has notified us of a
malfunction in their AI design. This malfunction, when triggered, causes MK-VI Synthoids to become radicalized
and seek out the destruction of humanity. They say that this bug affects all MK-VI Synthoids, not just the rogue
ones from the Uprising.
<br />
<br />
{FactionNames.OmniTekIncorporated} has also told us they they believe someone has triggered this malfunction in a large group of MK-VI
Synthoids, and that these newly-radicalized Synthoids are now amassing in {CityName.Volhaven} to form a terrorist group
called Ultron.
{FactionNames.OmniTekIncorporated} has also told us they they believe someone has triggered this malfunction in
a large group of MK-VI Synthoids, and that these newly-radicalized Synthoids are now amassing in{" "}
{CityName.Volhaven} to form a terrorist group called Ultron.
<br />
<br />
Intelligence suggests Ultron is heavily armed and that their members are augmented. We believe Ultron is making
+9 -2
View File
@@ -1,4 +1,4 @@
import { CityName } from './../../Locations/data/CityNames';
import { CityName } from "./../../Locations/data/CityNames";
export const BladeburnerConstants: {
CityNames: string[];
CyclesPerSecond: number;
@@ -28,7 +28,14 @@ export const BladeburnerConstants: {
HrcHpGain: number;
HrcStaminaGain: number;
} = {
CityNames: [CityName.Aevum, CityName.Chongqing, CityName.Sector12, CityName.NewTokyo, CityName.Ishima, CityName.Volhaven],
CityNames: [
CityName.Aevum,
CityName.Chongqing,
CityName.Sector12,
CityName.NewTokyo,
CityName.Ishima,
CityName.Volhaven,
],
CyclesPerSecond: 5, // Game cycle is 200 ms
StaminaGainPerSecond: 0.0085,
+14 -14
View File
@@ -26,8 +26,8 @@ export const ConsoleHelpText: {
"Usage: automate [var] [val] [hi/low]",
" ",
"A simple way to automate your Bladeburner actions. This console command can be used " +
"to automatically start an action when your stamina rises above a certain threshold, and " +
"automatically switch to another action when your stamina drops below another threshold.",
"to automatically start an action when your stamina rises above a certain threshold, and " +
"automatically switch to another action when your stamina drops below another threshold.",
" ",
" automate status - Check the current status of your automation and get a brief description of what it'll do",
" automate en - Enable the automation feature",
@@ -41,9 +41,9 @@ export const ConsoleHelpText: {
" automate general 'Field Analysis' low",
" ",
"Using the four console commands above will set the automation to perform Tracking contracts " +
"if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " +
"50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " +
"exactly match whatever the name is in the UI.",
"if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " +
"50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " +
"exactly match whatever the name is in the UI.",
" ",
],
clear: ["Usage: clear", " ", "Clears the console", " "],
@@ -52,8 +52,8 @@ export const ConsoleHelpText: {
"Usage: help [command]",
" ",
"Running 'help' with no arguments displays the general help text, which lists all console commands " +
"and a brief description of what they do. A command can be specified to get more specific help text " +
"about that particular command. For example:",
"and a brief description of what they do. A command can be specified to get more specific help text " +
"about that particular command. For example:",
" ",
" help automate",
" ",
@@ -64,8 +64,8 @@ export const ConsoleHelpText: {
"Usage: log [en/dis] [type]",
" ",
"Enable or disable logging. By default, the results of completing actions such as contracts/operations are logged " +
"in the console. There are also random events that are logged in the console as well. The five categories of " +
"things that get logged are:",
"in the console. There are also random events that are logged in the console as well. The five categories of " +
"things that get logged are:",
" ",
"[general, contracts, ops, blackops, events]",
" ",
@@ -91,8 +91,8 @@ export const ConsoleHelpText: {
" skill list",
" ",
"To display information about a specific skill, specify the name of the skill afterwards. " +
"Note that the name of the skill is case-sensitive. Enter it exactly as seen in the UI. If " +
"the name of the skill has whitespace, enclose the name of the skill in double quotation marks:",
"Note that the name of the skill is case-sensitive. Enter it exactly as seen in the UI. If " +
"the name of the skill has whitespace, enclose the name of the skill in double quotation marks:",
" ",
" skill list Reaper",
" skill list 'Digital Observer'",
@@ -106,9 +106,9 @@ export const ConsoleHelpText: {
"Usage: start [type] [name]",
" ",
"Start an action. An action is specified by its type and its name. The " +
"name is case-sensitive. It must appear exactly as it does in the UI. If " +
"the name of the action has whitespace, enclose it in double quotation marks. " +
"Valid action types include:",
"name is case-sensitive. It must appear exactly as it does in the UI. If " +
"the name of the action has whitespace, enclose it in double quotation marks. " +
"Valid action types include:",
" ",
"[general, contract, op, blackop]",
" ",
+4 -1
View File
@@ -18,7 +18,10 @@ export function BlackOpPage(props: IProps): React.ReactElement {
successively by completing the one before it.
<br />
<br />
<b>Your ultimate goal to climb through the ranks of {FactionNames.Bladeburners} is to complete all of the Black Ops.</b>
<b>
Your ultimate goal to climb through the ranks of {FactionNames.Bladeburners} is to complete all of the Black
Ops.
</b>
<br />
<br />
Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank
+1 -1
View File
@@ -35,7 +35,7 @@ export function BladeburnerCinematic(): React.ReactElement {
router.toTerminal();
dialogBoxCreate(
`Visit the National Security Agency (NSA) to apply for their ${FactionNames.Bladeburners} ` +
"division! You will need 100 of each combat stat before doing this.",
"division! You will need 100 of each combat stat before doing this.",
);
}}
/>
+9 -7
View File
@@ -44,13 +44,15 @@ export function Stats(props: IProps): React.ReactElement {
}
return (
<Paper sx={{ p: 1, overflowY: 'auto', overflowX: 'hidden', wordBreak: 'break-all' }}>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1, maxHeight: '60vh' }}>
<Box sx={{ alignSelf: 'flex-start', width: '100%' }}>
<Button onClick={() => setTravelOpen(true)} sx={{ width: '50%' }}>Travel</Button>
<Paper sx={{ p: 1, overflowY: "auto", overflowX: "hidden", wordBreak: "break-all" }}>
<Box sx={{ display: "flex", flexDirection: "column", gap: 1, maxHeight: "60vh" }}>
<Box sx={{ alignSelf: "flex-start", width: "100%" }}>
<Button onClick={() => setTravelOpen(true)} sx={{ width: "50%" }}>
Travel
</Button>
<Tooltip title={!inFaction ? <Typography>Rank 25 required.</Typography> : ""}>
<span>
<Button disabled={!inFaction} onClick={openFaction} sx={{ width: '50%' }}>
<Button disabled={!inFaction} onClick={openFaction} sx={{ width: "50%" }}>
Faction
</Button>
</span>
@@ -110,8 +112,8 @@ export function Stats(props: IProps): React.ReactElement {
<Tooltip
title={
<Typography>
This is your Bladeburner division's estimate of how many Synthoids exist in your current city. An accurate
population count increases success rate estimates.
This is your Bladeburner division's estimate of how many Synthoids exist in your current city. An
accurate population count increases success rate estimates.
</Typography>
}
>
+3 -3
View File
@@ -159,7 +159,7 @@ export function SlotMachine(props: IProps): React.ReactElement {
const copy = index.slice();
for (let i = 0; i < copy.length; i++) {
if (copy[i] === locks[i] && !stoppedOne) continue;
copy[i] = (copy[i] - 1 >= 0) ? copy[i] - 1 : symbols.length - 1;
copy[i] = copy[i] - 1 >= 0 ? copy[i] - 1 : symbols.length - 1;
stoppedOne = true;
}
@@ -170,7 +170,7 @@ export function SlotMachine(props: IProps): React.ReactElement {
}
}
function getTable(index:number[], symbols:string[]): string[][] {
function getTable(index: number[], symbols: string[]): string[][] {
return [
[
symbols[(index[0] + symbols.length - 1) % symbols.length],
@@ -209,7 +209,7 @@ export function SlotMachine(props: IProps): React.ReactElement {
]);
}
function checkWinnings(t:string[][]): void {
function checkWinnings(t: string[][]): void {
const getPaylineData = function (payline: number[][]): string[] {
const data = [];
for (const point of payline) {
-1
View File
@@ -17,7 +17,6 @@ import { Employee } from "./Employee";
import { IndustryUpgrades } from "./IndustryUpgrades";
import { ResearchMap } from "./ResearchMap";
import { isRelevantMaterial } from "./ui/Helpers";
import { CityName } from "src/Locations/data/CityNames";
export function NewIndustry(corporation: ICorporation, industry: string, name: string): void {
if (corporation.divisions.find(({ type }) => industry == type))
+6 -5
View File
@@ -435,10 +435,10 @@ export class Industry implements IIndustry {
const popularityGain = corporation.getDreamSenseGain(),
awarenessGain = popularityGain * 4;
if (popularityGain > 0) {
const awareness = this.awareness + (awarenessGain * marketCycles);
const awareness = this.awareness + awarenessGain * marketCycles;
this.awareness = Math.min(awareness, Number.MAX_VALUE);
const popularity = this.popularity + (popularityGain * marketCycles);
const popularity = this.popularity + popularityGain * marketCycles;
this.popularity = Math.min(popularity, Number.MAX_VALUE);
}
@@ -1188,7 +1188,8 @@ export class Industry implements IIndustry {
}
}
product.maxsll = 0.5 *
product.maxsll =
0.5 *
Math.pow(product.rat, 0.65) *
marketFactor *
corporation.getSalesMultiplier() *
@@ -1281,10 +1282,10 @@ export class Industry implements IIndustry {
case 1: {
//AdVert.Inc,
const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier();
const awareness = (this.awareness + (3 * advMult)) * (1.01 * advMult);
const awareness = (this.awareness + 3 * advMult) * (1.01 * advMult);
this.awareness = Math.min(awareness, Number.MAX_VALUE);
const popularity = (this.popularity + (1 * advMult)) * ((1 + getRandomInt(1, 3) / 100) * advMult);
const popularity = (this.popularity + 1 * advMult) * ((1 + getRandomInt(1, 3) / 100) * advMult);
this.popularity = Math.min(popularity, Number.MAX_VALUE);
break;
}
+1 -1
View File
@@ -177,7 +177,7 @@ export class OfficeSpace {
let jobCount = this.employees.reduce((acc, employee) => (employee.pos === job ? acc + 1 : acc), 0);
for (const employee of this.employees) {
if (jobCount == amount) return true
if (jobCount == amount) return true;
if (employee.pos === EmployeePositions.Unassigned && jobCount <= amount) {
employee.pos = job;
jobCount++;
+11 -14
View File
@@ -1,4 +1,4 @@
import { CityName } from './../../Locations/data/CityNames';
import { CityName } from "./../../Locations/data/CityNames";
const CyclesPerMarketCycle = 50;
const AllCorporationStates = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];
export const CorporationConstants: {
@@ -38,7 +38,14 @@ export const CorporationConstants: {
CyclesPerIndustryStateCycle: CyclesPerMarketCycle / AllCorporationStates.length,
SecsPerMarketCycle: CyclesPerMarketCycle / 5,
Cities: [CityName.Aevum, CityName.Chongqing, CityName.Sector12, CityName.NewTokyo, CityName.Ishima, CityName.Volhaven],
Cities: [
CityName.Aevum,
CityName.Chongqing,
CityName.Sector12,
CityName.NewTokyo,
CityName.Ishima,
CityName.Volhaven,
],
WarehouseInitialCost: 5e9, //Initial purchase cost of warehouse
WarehouseInitialSize: 100,
@@ -74,16 +81,6 @@ export const CorporationConstants: {
"AI Cores",
"Real Estate",
],
FundingRoundShares: [
0.1,
0.35,
0.25,
0.2
],
FundingRoundMultiplier: [
4,
3,
3,
2.5
],
FundingRoundShares: [0.1, 0.35, 0.25, 0.2],
FundingRoundMultiplier: [4, 3, 3, 2.5],
};
+4 -5
View File
@@ -6,8 +6,8 @@ import { useCorporation } from "./Context";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import { BuyBackShares } from '../Actions';
import { dialogBoxCreate } from '../../ui/React/DialogBox';
import { BuyBackShares } from "../Actions";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { KEY } from "../../utils/helpers/keyCodes";
interface IProps {
@@ -40,9 +40,8 @@ export function BuybackSharesModal(props: IProps): React.ReactElement {
function buy(): void {
if (disabled) return;
try {
BuyBackShares(corp, player, shares)
}
catch (err) {
BuyBackShares(corp, player, shares);
} catch (err) {
dialogBoxCreate(err + "");
}
props.onClose();
+1 -1
View File
@@ -30,7 +30,7 @@ export function CityTabs(props: IProps): React.ReactElement {
}
return (
<>
<Tabs variant="fullWidth" value={city} onChange={handleChange} sx={{ maxWidth: '65%' }}>
<Tabs variant="fullWidth" value={city} onChange={handleChange} sx={{ maxWidth: "65%" }}>
{Object.values(division.offices).map(
(office: OfficeSpace | 0) => office !== 0 && <Tab key={office.loc} label={office.loc} value={office.loc} />,
)}
+1 -1
View File
@@ -38,7 +38,7 @@ export function CorporationRoot(): React.ReactElement {
return (
<Context.Corporation.Provider value={corporation}>
<Tabs variant="scrollable" value={divisionName} onChange={handleChange} sx={{ maxWidth: '65%' }} scrollButtons>
<Tabs variant="scrollable" value={divisionName} onChange={handleChange} sx={{ maxWidth: "65%" }} scrollButtons>
<Tab label={corporation.name} value={"Overview"} />
{corporation.divisions.map((div) => (
<Tab key={div.name} label={div.name} value={div.name} />
@@ -56,9 +56,11 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
return (
<Modal open={props.open} onClose={props.onClose}>
<Typography>
Would you like to start a corporation? This will require $150b for registration and initial funding. {player.bitNodeN === 3 && (`This $150b
Would you like to start a corporation? This will require $150b for registration and initial funding.{" "}
{player.bitNodeN === 3 &&
`This $150b
can either be self-funded, or you can obtain the seed money from the government in exchange for 500 million
shares`)}
shares`}
<br />
<br />
If you would like to start one, please enter a name for your corporation below:
+4 -2
View File
@@ -23,7 +23,9 @@ interface IProps {
// Create a popup that lets the player manage exports
export function ExportModal(props: IProps): React.ReactElement {
const corp = useCorporation();
const possibleDivisions = corp.divisions.filter((division: IIndustry) => isRelevantMaterial(props.mat.name, division));
const possibleDivisions = corp.divisions.filter((division: IIndustry) =>
isRelevantMaterial(props.mat.name, division),
);
if (possibleDivisions.length === 0) throw new Error("Export popup created with no divisions.");
const defaultDivision = possibleDivisions[0];
if (Object.keys(defaultDivision.warehouses).length === 0)
@@ -93,7 +95,7 @@ export function ExportModal(props: IProps): React.ReactElement {
<MenuItem key={division.name} value={division.name}>
{division.name}
</MenuItem>
))}
))}
</Select>
<Select onChange={onCityChange} value={city}>
{possibleCities.map((cityName: string) => {
+5 -1
View File
@@ -17,7 +17,11 @@ interface IProps {
export function FindInvestorsModal(props: IProps): React.ReactElement {
const corporation = useCorporation();
const val = corporation.determineValuation();
if (corporation.fundingRound >= CorporationConstants.FundingRoundShares.length || corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length) return <></>;
if (
corporation.fundingRound >= CorporationConstants.FundingRoundShares.length ||
corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length
)
return <></>;
const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound];
const roundMultiplier = CorporationConstants.FundingRoundMultiplier[corporation.fundingRound];
const funding = val * percShares * roundMultiplier;
@@ -18,7 +18,5 @@ export function IndustryProductEquation(props: IProps): React.ReactElement {
prod.push("Products");
}
return (
<MathJaxWrapper>{"\\(" + reqs.join("+") + `\\Rightarrow ` + prod.join("+") + "\\)"}</MathJaxWrapper>
);
return <MathJaxWrapper>{"\\(" + reqs.join("+") + `\\Rightarrow ` + prod.join("+") + "\\)"}</MathJaxWrapper>;
}
+33 -7
View File
@@ -42,9 +42,9 @@ interface IProps {
const useStyles = makeStyles(() =>
createStyles({
retainHeight: {
minHeight: '3em',
minHeight: "3em",
},
})
}),
);
function WarehouseRoot(props: IProps): React.ReactElement {
@@ -127,27 +127,53 @@ function WarehouseRoot(props: IProps): React.ReactElement {
const mat = props.warehouse.materials[matName];
if (!MaterialSizes.hasOwnProperty(matName)) continue;
if (mat.qty === 0) continue;
breakdownItems.push(<>{matName}: {numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0")}</>);
breakdownItems.push(
<>
{matName}: {numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0")}
</>,
);
}
for (const prodName of Object.keys(division.products)) {
const prod = division.products[prodName];
if (prod === undefined) continue;
breakdownItems.push(<>{prodName}: {numeralWrapper.format(prod.data[props.warehouse.loc][0] * prod.siz, "0,0.0")}</>);
breakdownItems.push(
<>
{prodName}: {numeralWrapper.format(prod.data[props.warehouse.loc][0] * prod.siz, "0,0.0")}
</>,
);
}
let breakdown;
if (breakdownItems && breakdownItems.length > 0) {
breakdown = breakdownItems.reduce(
(previous: JSX.Element, current: JSX.Element): JSX.Element => previous && <>{previous}<br />{current}</> || <>{current}</>);
(previous: JSX.Element, current: JSX.Element): JSX.Element =>
(previous && (
<>
{previous}
<br />
{current}
</>
)) || <>{current}</>,
);
} else {
breakdown = <>No items in storage.</>
breakdown = <>No items in storage.</>;
}
return (
<Paper>
<Box display="flex" alignItems="center">
<Tooltip title={props.warehouse.sizeUsed !== 0 ? <Typography><>{breakdown}</></Typography> : ""}>
<Tooltip
title={
props.warehouse.sizeUsed !== 0 ? (
<Typography>
<>{breakdown}</>
</Typography>
) : (
""
)
}
>
<Typography color={props.warehouse.sizeUsed >= props.warehouse.size ? "error" : "primary"}>
Storage: {numeralWrapper.formatBigNumber(props.warehouse.sizeUsed)} /{" "}
{numeralWrapper.formatBigNumber(props.warehouse.size)}
+9 -9
View File
@@ -112,7 +112,7 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
return (
<Paper>
<Box sx={{ display: 'grid', gridTemplateColumns: '2fr 1fr', m: '5px' }}>
<Box sx={{ display: "grid", gridTemplateColumns: "2fr 1fr", m: "5px" }}>
<Box>
<Tooltip
title={
@@ -149,17 +149,17 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
</Tooltip>
</Box>
<Box sx={{ "& button": { width: '100%' } }}>
<Box sx={{ "& button": { width: "100%" } }}>
<Tooltip
title={tutorial ? <Typography>Purchase your required materials to get production started!</Typography> : ""}
>
<Button
color={tutorial ? "error" : "primary"}
onClick={() => setPurchaseMaterialOpen(true)}
disabled={props.warehouse.smartSupplyEnabled && Object.keys(division.reqMats).includes(props.mat.name)}
>
{purchaseButtonText}
</Button>
<Button
color={tutorial ? "error" : "primary"}
onClick={() => setPurchaseMaterialOpen(true)}
disabled={props.warehouse.smartSupplyEnabled && Object.keys(division.reqMats).includes(props.mat.name)}
>
{purchaseButtonText}
</Button>
</Tooltip>
<PurchaseMaterialModal
mat={mat}
+3 -3
View File
@@ -89,7 +89,7 @@ export function Overview({ rerender }: IProps): React.ReactElement {
<StatsTable rows={multRows} />
<br />
<BonusTime />
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', width: 'fit-content' }}>
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", width: "fit-content" }}>
<Tooltip
title={
<Typography>
@@ -200,8 +200,8 @@ function PublicButtons({ rerender }: IPublicButtonsProps): React.ReactElement {
const sellSharesTooltip = sellSharesOnCd
? "Cannot sell shares for " + corp.convertCooldownToString(corp.shareSaleCooldown)
: "Sell your shares in the company. The money earned from selling your " +
"shares goes into your personal account, not the Corporation's. " +
"This is one of the only ways to profit from your business venture.";
"shares goes into your personal account, not the Corporation's. " +
"This is one of the only ways to profit from your business venture.";
const issueNewSharesOnCd = corp.issueNewSharesCooldown > 0;
const issueNewSharesTooltip = issueNewSharesOnCd
+33 -20
View File
@@ -16,7 +16,7 @@ import Box from "@mui/material/Box";
import Collapse from "@mui/material/Collapse";
import ExpandMore from "@mui/icons-material/ExpandMore";
import ExpandLess from "@mui/icons-material/ExpandLess";
import CheckIcon from '@mui/icons-material/Check';
import CheckIcon from "@mui/icons-material/Check";
interface INodeProps {
n: Node | null;
@@ -43,8 +43,8 @@ function Upgrade({ n, division }: INodeProps): React.ReactElement {
dialogBoxCreate(
`Researched ${n.text}. It may take a market cycle ` +
`(~${CorporationConstants.SecsPerMarketCycle} seconds) before the effects of ` +
`the Research apply.`,
`(~${CorporationConstants.SecsPerMarketCycle} seconds) before the effects of ` +
`the Research apply.`,
);
}
@@ -66,19 +66,23 @@ function Upgrade({ n, division }: INodeProps): React.ReactElement {
>
{ele}
</Tooltip>
)
}
);
};
const but = (
<Box>
{wrapInTooltip(
<span>
<Button color={color} disabled={disabled && !n.researched} onClick={research}
style={{ width: '100%', textAlign: 'left', justifyContent: 'unset' }}
<Button
color={color}
disabled={disabled && !n.researched}
onClick={research}
style={{ width: "100%", textAlign: "left", justifyContent: "unset" }}
>
{n.researched && (<CheckIcon sx={{ mr: 1 }} />)}{n.text}
{n.researched && <CheckIcon sx={{ mr: 1 }} />}
{n.text}
</Button>
</span>
</span>,
)}
</Box>
);
@@ -87,20 +91,29 @@ function Upgrade({ n, division }: INodeProps): React.ReactElement {
return (
<Box>
<Box display="flex" sx={{ border: '1px solid ' + Settings.theme.well }}>
<Box display="flex" sx={{ border: "1px solid " + Settings.theme.well }}>
{wrapInTooltip(
<span style={{ width: '100%' }}>
<Button color={color} disabled={disabled && !n.researched} onClick={research} sx={{
width: '100%',
textAlign: 'left',
justifyContent: 'unset',
borderColor: Settings.theme.button
}}>
{n.researched && (<CheckIcon sx={{ mr: 1 }} />)}{n.text}
<span style={{ width: "100%" }}>
<Button
color={color}
disabled={disabled && !n.researched}
onClick={research}
sx={{
width: "100%",
textAlign: "left",
justifyContent: "unset",
borderColor: Settings.theme.button,
}}
>
{n.researched && <CheckIcon sx={{ mr: 1 }} />}
{n.text}
</Button>
</span>
</span>,
)}
<Button onClick={() => setOpen((old) => !old)} sx={{ borderColor: Settings.theme.button, minWidth: 'fit-content' }}>
<Button
onClick={() => setOpen((old) => !old)}
sx={{ borderColor: Settings.theme.button, minWidth: "fit-content" }}
>
{open ? <ExpandLess color="primary" /> : <ExpandMore color="primary" />}
</Button>
</Box>
+1 -2
View File
@@ -51,7 +51,7 @@ export function SellSharesModal(props: IProps): React.ReactElement {
function sell(): void {
if (disabled) return;
try {
const profit = SellShares(corp, player, shares)
const profit = SellShares(corp, player, shares);
props.onClose();
dialogBoxCreate(
<>
@@ -65,7 +65,6 @@ export function SellSharesModal(props: IProps): React.ReactElement {
} catch (err) {
dialogBoxCreate(err + "");
}
}
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
+11 -11
View File
@@ -35,17 +35,17 @@ export function ThrowPartyModal(props: IProps): React.ReactElement {
if (cost === null || isNaN(cost) || cost < 0) {
dialogBoxCreate("Invalid value entered");
} else if (!canParty) {
dialogBoxCreate("You don't have enough company funds to throw a party!");
} else {
const mult = ThrowParty(corp, props.office, cost);
dialogBoxCreate(
"You threw a party for the office! The morale and happiness " +
"of each employee increased by " +
numeralWrapper.formatPercentage(mult - 1),
);
props.rerender();
props.onClose();
}
dialogBoxCreate("You don't have enough company funds to throw a party!");
} else {
const mult = ThrowParty(corp, props.office, cost);
dialogBoxCreate(
"You threw a party for the office! The morale and happiness " +
"of each employee increased by " +
numeralWrapper.formatPercentage(mult - 1),
);
props.rerender();
props.onClose();
}
}
function EffectText(): React.ReactElement {
+1 -1
View File
@@ -5,5 +5,5 @@ export const StanekConstants: {
} = {
RAMBonus: 0.1,
BaseSize: 9,
MaxSize: 25
MaxSize: 25,
};
+3 -1
View File
@@ -107,7 +107,9 @@ export function buyAllDarkwebItems(): void {
}
if (cost > Player.money) {
Terminal.error("Not enough money to purchase remaining programs, " + numeralWrapper.formatMoney(cost) + " required");
Terminal.error(
"Not enough money to purchase remaining programs, " + numeralWrapper.formatMoney(cost) + " required",
);
return;
}
+44 -35
View File
@@ -8,8 +8,8 @@ import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import ButtonGroup from "@mui/material/ButtonGroup";
import { Tooltip } from "@mui/material";
import LockIcon from '@mui/icons-material/Lock';
import LockOpenIcon from '@mui/icons-material/LockOpen';
import LockIcon from "@mui/icons-material/Lock";
import LockOpenIcon from "@mui/icons-material/LockOpen";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { achievements } from "../../Achievements/Achievements";
@@ -21,26 +21,26 @@ interface IProps {
}
export function Achievements(props: IProps): React.ReactElement {
const [playerAchievement, setPlayerAchievements] = useState(props.player.achievements.map(m => m.ID));
const [playerAchievement, setPlayerAchievements] = useState(props.player.achievements.map((m) => m.ID));
function grantAchievement(id: string): void {
props.player.giveAchievement(id);
setPlayerAchievements(props.player.achievements.map(m => m.ID));
setPlayerAchievements(props.player.achievements.map((m) => m.ID));
}
function grantAllAchievements(): void {
Object.values(achievements).forEach(a => props.player.giveAchievement(a.ID));
setPlayerAchievements(props.player.achievements.map(m => m.ID));
Object.values(achievements).forEach((a) => props.player.giveAchievement(a.ID));
setPlayerAchievements(props.player.achievements.map((m) => m.ID));
}
function removeAchievement(id: string): void {
props.player.achievements = props.player.achievements.filter(a => a.ID !== id);
setPlayerAchievements(props.player.achievements.map(m => m.ID));
props.player.achievements = props.player.achievements.filter((a) => a.ID !== id);
setPlayerAchievements(props.player.achievements.map((m) => m.ID));
}
function clearAchievements(): void {
props.player.achievements = [];
setPlayerAchievements(props.player.achievements.map(m => m.ID));
setPlayerAchievements(props.player.achievements.map((m) => m.ID));
}
function disableEngine(): void {
@@ -48,7 +48,7 @@ export function Achievements(props: IProps): React.ReactElement {
}
function enableEngine(): void {
props.engine.Counters.achievementsCounter = 0
props.engine.Counters.achievementsCounter = 0;
}
return (
@@ -60,8 +60,7 @@ export function Achievements(props: IProps): React.ReactElement {
<table>
<tbody>
<tr>
<td>
</td>
<td></td>
<td>
<Typography>Achievements:</Typography>
</td>
@@ -76,30 +75,40 @@ export function Achievements(props: IProps): React.ReactElement {
</tr>
{Object.values(achievements).map((i) => {
const achieved = playerAchievement.includes(i.ID);
return <tr key={"ach-" + i.ID}>
<td>
{achieved ? (
<Tooltip title="Achieved">
<LockOpenIcon color="primary" />
return (
<tr key={"ach-" + i.ID}>
<td>
{achieved ? (
<Tooltip title="Achieved">
<LockOpenIcon color="primary" />
</Tooltip>
) : (
<Tooltip title="Locked">
<LockIcon color="secondary" />
</Tooltip>
)}
</td>
<td>
<Tooltip
title={
<>
{i.ID}
<br />
{i.Description}
</>
}
>
<Typography color={achieved ? "primary" : "secondary"}>{i.Name}:</Typography>
</Tooltip>
) : (
<Tooltip title="Locked">
<LockIcon color="secondary" />
</Tooltip>
)}
</td>
<td>
<Tooltip title={<>{i.ID}<br />{i.Description}</>}>
<Typography color={achieved ? 'primary': 'secondary'}>{i.Name}:</Typography>
</Tooltip>
</td>
<td>
<ButtonGroup>
<Button onClick={() => grantAchievement(i.ID)}>Grant</Button>
<Button onClick={() => removeAchievement(i.ID)}>Clear</Button>
</ButtonGroup>
</td>
</tr>
</td>
<td>
<ButtonGroup>
<Button onClick={() => grantAchievement(i.ID)}>Grant</Button>
<Button onClick={() => removeAchievement(i.ID)}>Clear</Button>
</ButtonGroup>
</td>
</tr>
);
})}
</tbody>
</table>
+1 -1
View File
@@ -37,7 +37,7 @@ export function Factions(props: IProps): React.ReactElement {
}
function receiveAllInvites(): void {
Object.values(FactionNames).forEach(faction => props.player.receiveInvite(faction))
Object.values(FactionNames).forEach((faction) => props.player.receiveInvite(faction));
}
function modifyFactionRep(modifier: number): (x: number) => void {
+1 -1
View File
@@ -46,7 +46,7 @@ export function General(props: IProps): React.ReactElement {
}
useEffect(() => {
if (error) throw new ReferenceError('Manually thrown error');
if (error) throw new ReferenceError("Manually thrown error");
}, [error]);
return (
+48 -12
View File
@@ -85,8 +85,6 @@ export class FactionInfo {
}
}
/**
* A map of all factions and associated info to them.
*/
@@ -143,8 +141,9 @@ export const FactionInfos: IMap<FactionInfo> = {
[FactionNames.ECorp]: new FactionInfo(
(
<>
{FactionNames.ECorp}'s mission is simple: to connect the world of today with the technology of tomorrow. With our wide range of
Internet-related software and commercial hardware, {FactionNames.ECorp} makes the world's information universally accessible.
{FactionNames.ECorp}'s mission is simple: to connect the world of today with the technology of tomorrow. With
our wide range of Internet-related software and commercial hardware, {FactionNames.ECorp} makes the world's
information universally accessible.
</>
),
[],
@@ -159,12 +158,13 @@ export const FactionInfos: IMap<FactionInfo> = {
[FactionNames.MegaCorp]: new FactionInfo(
(
<>
{FactionNames.MegaCorp} does what no other dares to do. We imagine. We create. We invent. We create what others have never even
dreamed of. Our work fills the world's needs for food, water, power, and transportation on an unprecedented
scale, in ways that no other company can.
{FactionNames.MegaCorp} does what no other dares to do. We imagine. We create. We invent. We create what others
have never even dreamed of. Our work fills the world's needs for food, water, power, and transportation on an
unprecedented scale, in ways that no other company can.
<br />
<br />
In our labs and factories and on the ground with customers, {FactionNames.MegaCorp} is ushering in a new era for the world.
In our labs and factories and on the ground with customers, {FactionNames.MegaCorp} is ushering in a new era for
the world.
</>
),
[],
@@ -194,7 +194,16 @@ export const FactionInfos: IMap<FactionInfo> = {
true,
),
[FactionNames.BladeIndustries]: new FactionInfo(<>Augmentation is Salvation.</>, [], true, true, true, true, false, true),
[FactionNames.BladeIndustries]: new FactionInfo(
<>Augmentation is Salvation.</>,
[],
true,
true,
true,
true,
false,
true,
),
[FactionNames.NWO]: new FactionInfo(
(
@@ -486,12 +495,39 @@ export const FactionInfos: IMap<FactionInfo> = {
false,
),
[FactionNames.SlumSnakes]: new FactionInfo(<>{FactionNames.SlumSnakes} rule!</>, [], false, false, true, true, false, false),
[FactionNames.SlumSnakes]: new FactionInfo(
<>{FactionNames.SlumSnakes} rule!</>,
[],
false,
false,
true,
true,
false,
false,
),
// Earlygame factions - factions the player will prestige with early on that don't belong in other categories.
[FactionNames.Netburners]: new FactionInfo(<>{"~~//*>H4CK||3T 8URN3R5**>?>\\~~"}</>, [], true, true, false, false, false, false),
[FactionNames.Netburners]: new FactionInfo(
<>{"~~//*>H4CK||3T 8URN3R5**>?>\\~~"}</>,
[],
true,
true,
false,
false,
false,
false,
),
[FactionNames.TianDiHui]: new FactionInfo(<>Obey Heaven and work righteously.</>, [], true, true, false, true, false, false),
[FactionNames.TianDiHui]: new FactionInfo(
<>Obey Heaven and work righteously.</>,
[],
true,
true,
false,
true,
false,
false,
),
[FactionNames.CyberSec]: new FactionInfo(
(
-2
View File
@@ -32,8 +32,6 @@ type IProps = {
export function AugmentationsPage(props: IProps): React.ReactElement {
const player = use.Player();
// Flag for whether the player has a gang with this faction
const isPlayersGang = player.inGang() && player.getGangName() === props.faction.name;
const setRerender = useState(false)[1];
-2
View File
@@ -2,8 +2,6 @@ import React, { useEffect, useState } from "react";
import { Box, Button, Container, Paper, TableBody, TableRow, Typography } from "@mui/material";
import { Augmentations } from "../../Augmentation/Augmentations";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Table, TableCell } from "../../ui/React/Table";
import { IRouter } from "../../ui/Router";
+1 -4
View File
@@ -59,9 +59,7 @@ export function Info(props: IProps): React.ReactElement {
</Typography>
<MathJaxWrapper>{"\\(\\huge{r = \\text{total faction reputation}}\\)"}</MathJaxWrapper>
<MathJaxWrapper>
{
"\\(\\huge{favor=1+\\left\\lfloor\\log_{1.02}\\left(\\frac{r+25000}{25500}\\right)\\right\\rfloor}\\)"
}
{"\\(\\huge{favor=1+\\left\\lfloor\\log_{1.02}\\left(\\frac{r+25000}{25500}\\right)\\right\\rfloor}\\)"}
</MathJaxWrapper>
</>
}
@@ -86,7 +84,6 @@ export function Info(props: IProps): React.ReactElement {
<MathJaxWrapper>{"\\(\\huge{r = reputation}\\)"}</MathJaxWrapper>
<MathJaxWrapper>{"\\(\\huge{\\Delta r = \\Delta r \\times \\frac{100+favor}{100}}\\)"}</MathJaxWrapper>
</>
}
>
+1 -1
View File
@@ -1,4 +1,4 @@
import { FactionNames } from '../Faction/data/FactionNames';
import { FactionNames } from "../Faction/data/FactionNames";
import { Reviver } from "../utils/JSONReviver";
interface GangTerritory {
+1 -1
View File
@@ -1,4 +1,4 @@
import { FactionNames } from '../../Faction/data/FactionNames';
import { FactionNames } from "../../Faction/data/FactionNames";
export const PowerMultiplier: {
[key: string]: number | undefined;
} = {
+1 -1
View File
@@ -51,7 +51,7 @@ export function AscensionModal(props: IProps): React.ReactElement {
<br />
Charisma: x{numeralWrapper.format(res.cha, "0.000")}
<br />
</>
</>,
);
props.onClose();
}
+65 -54
View File
@@ -76,8 +76,8 @@ function UpgradeButton(props: IUpgradeButtonProps): React.ReactElement {
return (
<Tooltip title={<Typography dangerouslySetInnerHTML={{ __html: props.upg.desc }} />}>
<span>
<Button onClick={onClick} sx={{ display: 'flex', flexDirection: 'column', width: '100%', height: '100%' }}>
<Typography sx={{ display: 'block' }}>{props.upg.name}</Typography>
<Button onClick={onClick} sx={{ display: "flex", flexDirection: "column", width: "100%", height: "100%" }}>
<Typography sx={{ display: "block" }}>{props.upg.name}</Typography>
<Money money={gang.getUpgradeCost(props.upg)} />
</Button>
</span>
@@ -113,8 +113,8 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
const onChange = (event: SelectChangeEvent<string>): void => {
setCurrentCategory(event.target.value);
rerender()
}
rerender();
};
const weaponUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Weapon);
const armorUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Armor);
@@ -123,11 +123,11 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
const augUpgrades = filterUpgrades(props.member.augmentations, UpgradeType.Augmentation);
const categories: { [key: string]: (GangMemberUpgrade[] | UpgradeType)[] } = {
'Weapons': [weaponUpgrades, UpgradeType.Weapon],
'Armor': [armorUpgrades, UpgradeType.Armor],
'Vehicles': [vehicleUpgrades, UpgradeType.Vehicle],
'Rootkits': [rootkitUpgrades, UpgradeType.Rootkit],
'Augmentations': [augUpgrades, UpgradeType.Augmentation]
Weapons: [weaponUpgrades, UpgradeType.Weapon],
Armor: [armorUpgrades, UpgradeType.Armor],
Vehicles: [vehicleUpgrades, UpgradeType.Vehicle],
Rootkits: [rootkitUpgrades, UpgradeType.Rootkit],
Augmentations: [augUpgrades, UpgradeType.Augmentation],
};
const asc = {
@@ -140,7 +140,7 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
};
return (
<Paper>
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr', m: 1, gap: 1 }}>
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", m: 1, gap: 1 }}>
<span>
<Typography variant="h5" color="primary">
{props.member.name} ({props.member.task})
@@ -149,47 +149,70 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
title={
<Typography>
Hk: x{numeralWrapper.formatMultiplier(props.member.hack_mult * asc.hack)}(x
{numeralWrapper.formatMultiplier(props.member.hack_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.hack)}{" "}
Asc)
{numeralWrapper.formatMultiplier(props.member.hack_mult)} Eq, x
{numeralWrapper.formatMultiplier(asc.hack)} Asc)
<br />
St: x{numeralWrapper.formatMultiplier(props.member.str_mult * asc.str)}
(x{numeralWrapper.formatMultiplier(props.member.str_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.str)}{" "}
Asc)
(x{numeralWrapper.formatMultiplier(props.member.str_mult)} Eq, x
{numeralWrapper.formatMultiplier(asc.str)} Asc)
<br />
Df: x{numeralWrapper.formatMultiplier(props.member.def_mult * asc.def)}
(x{numeralWrapper.formatMultiplier(props.member.def_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.def)}{" "}
Asc)
(x{numeralWrapper.formatMultiplier(props.member.def_mult)} Eq, x
{numeralWrapper.formatMultiplier(asc.def)} Asc)
<br />
Dx: x{numeralWrapper.formatMultiplier(props.member.dex_mult * asc.dex)}
(x{numeralWrapper.formatMultiplier(props.member.dex_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.dex)}{" "}
Asc)
(x{numeralWrapper.formatMultiplier(props.member.dex_mult)} Eq, x
{numeralWrapper.formatMultiplier(asc.dex)} Asc)
<br />
Ag: x{numeralWrapper.formatMultiplier(props.member.agi_mult * asc.agi)}
(x{numeralWrapper.formatMultiplier(props.member.agi_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.agi)}{" "}
Asc)
(x{numeralWrapper.formatMultiplier(props.member.agi_mult)} Eq, x
{numeralWrapper.formatMultiplier(asc.agi)} Asc)
<br />
Ch: x{numeralWrapper.formatMultiplier(props.member.cha_mult * asc.cha)}
(x{numeralWrapper.formatMultiplier(props.member.cha_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.cha)}{" "}
Asc)
(x{numeralWrapper.formatMultiplier(props.member.cha_mult)} Eq, x
{numeralWrapper.formatMultiplier(asc.cha)} Asc)
</Typography>
}
>
<Table>
<TableBody>
<StatsRow name="Hacking" color={Settings.theme.hack} data={{ level: props.member.hack, exp: props.member.hack_exp }} />
<StatsRow name="Strength" color={Settings.theme.combat} data={{ level: props.member.str, exp: props.member.str_exp }} />
<StatsRow name="Defense" color={Settings.theme.combat} data={{ level: props.member.def, exp: props.member.def_exp }} />
<StatsRow name="Dexterity" color={Settings.theme.combat} data={{ level: props.member.dex, exp: props.member.dex_exp }} />
<StatsRow name="Agility" color={Settings.theme.combat} data={{ level: props.member.agi, exp: props.member.agi_exp }} />
<StatsRow name="Charisma" color={Settings.theme.cha} data={{ level: props.member.cha, exp: props.member.cha_exp }} />
<StatsRow
name="Hacking"
color={Settings.theme.hack}
data={{ level: props.member.hack, exp: props.member.hack_exp }}
/>
<StatsRow
name="Strength"
color={Settings.theme.combat}
data={{ level: props.member.str, exp: props.member.str_exp }}
/>
<StatsRow
name="Defense"
color={Settings.theme.combat}
data={{ level: props.member.def, exp: props.member.def_exp }}
/>
<StatsRow
name="Dexterity"
color={Settings.theme.combat}
data={{ level: props.member.dex, exp: props.member.dex_exp }}
/>
<StatsRow
name="Agility"
color={Settings.theme.combat}
data={{ level: props.member.agi, exp: props.member.agi_exp }}
/>
<StatsRow
name="Charisma"
color={Settings.theme.cha}
data={{ level: props.member.cha, exp: props.member.cha_exp }}
/>
</TableBody>
</Table>
</Tooltip>
</span>
<span>
<Select onChange={onChange} value={currentCategory} sx={{ width: '100%', mb: 1 }}>
<Select onChange={onChange} value={currentCategory} sx={{ width: "100%", mb: 1 }}>
{Object.keys(categories).map((k, i) => (
<MenuItem key={i + 1} value={k}>
<Typography variant="h6">{k}</Typography>
@@ -197,32 +220,22 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
))}
</Select>
<Box sx={{ width: '100%' }}>
<Box sx={{ width: "100%" }}>
{(categories[currentCategory][0] as GangMemberUpgrade[]).length === 0 && (
<Typography>
All upgrades owned!
</Typography>
<Typography>All upgrades owned!</Typography>
)}
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr' }}>
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr" }}>
{(categories[currentCategory][0] as GangMemberUpgrade[]).map((upg) => (
<UpgradeButton
key={upg.name}
rerender={rerender}
member={props.member}
upg={upg}
/>
<UpgradeButton key={upg.name} rerender={rerender} member={props.member} upg={upg} />
))}
</Box>
<NextReveal
type={categories[currentCategory][1] as UpgradeType}
upgrades={props.member.upgrades}
/>
<NextReveal type={categories[currentCategory][1] as UpgradeType} upgrades={props.member.upgrades} />
</Box>
</span>
</Box>
<Typography sx={{ mx: 1 }}>Purchased Upgrades: </Typography>
<Box display="grid" sx={{ gridTemplateColumns: 'repeat(4, 1fr)', m: 1 }}>
<Box display="grid" sx={{ gridTemplateColumns: "repeat(4, 1fr)", m: 1 }}>
{props.member.upgrades.map((upg: string) => (
<PurchasedUpgrade key={upg} upgName={upg} />
))}
@@ -230,7 +243,7 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
<PurchasedUpgrade key={upg} upgName={upg} />
))}
</Box>
</Paper >
</Paper>
);
}
@@ -238,13 +251,11 @@ export function EquipmentsSubpage(): React.ReactElement {
const gang = useGang();
const [filter, setFilter] = useState("");
const handleFilterChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
setFilter(event.target.value.toLowerCase());
}
};
const members = gang.members
.filter((member) => member && member.name.toLowerCase().includes(filter));
const members = gang.members.filter((member) => member && member.name.toLowerCase().includes(filter));
return (
<>
@@ -265,13 +276,13 @@ export function EquipmentsSubpage(): React.ReactElement {
autoFocus
InputProps={{
startAdornment: <SearchIcon />,
spellCheck: false
spellCheck: false,
}}
placeholder="Filter by member name"
sx={{ m: 1, width: '15%' }}
sx={{ m: 1, width: "15%" }}
/>
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr', width: '100%' }}>
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%" }}>
{members.map((member: GangMember) => (
<GangMemberUpgradePanel key={member.name} member={member} />
))}
+1 -1
View File
@@ -16,7 +16,7 @@ interface IProps {
export function GangMemberCard(props: IProps): React.ReactElement {
return (
<Box component={Paper} sx={{ width: 'auto' }}>
<Box component={Paper} sx={{ width: "auto" }}>
<Box sx={{ m: 1 }}>
<ListItemText primary={<b>{props.member.name}</b>} />
<GangMemberCardContent member={props.member} />
+6 -4
View File
@@ -26,15 +26,17 @@ export function GangMemberCardContent(props: IProps): React.ReactElement {
return (
<>
{props.member.canAscend() && (
<Box sx={{ display: 'flex', justifyContent: 'space-between', my: 1 }}>
<Button onClick={() => setAscendOpen(true)} style={{ flexGrow: 1, borderRightWidth: 0 }}>Ascend</Button>
<Box sx={{ display: "flex", justifyContent: "space-between", my: 1 }}>
<Button onClick={() => setAscendOpen(true)} style={{ flexGrow: 1, borderRightWidth: 0 }}>
Ascend
</Button>
<AscensionModal
open={ascendOpen}
onClose={() => setAscendOpen(false)}
member={props.member}
onAscend={() => setRerender((old) => !old)}
/>
<Button onClick={() => setHelpOpen(true)} style={{ width: 'fit-content', borderLeftWidth: 0 }}>
<Button onClick={() => setHelpOpen(true)} style={{ width: "fit-content", borderLeftWidth: 0 }}>
<HelpIcon />
</Button>
<StaticModal open={helpOpen} onClose={() => setHelpOpen(false)}>
@@ -53,7 +55,7 @@ export function GangMemberCardContent(props: IProps): React.ReactElement {
</StaticModal>
</Box>
)}
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr', width: '100%', gap: 1 }}>
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%", gap: 1 }}>
<GangMemberStats member={props.member} />
<TaskSelector onTaskChange={() => setRerender((old) => !old)} member={props.member} />
</Box>
+6 -11
View File
@@ -20,7 +20,7 @@ export function GangMemberList(): React.ReactElement {
const handleFilterChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
setFilter(event.target.value.toLowerCase());
}
};
const members = gang.members
.filter((member) => member && member.name.toLowerCase().includes(filter))
@@ -38,23 +38,18 @@ export function GangMemberList(): React.ReactElement {
autoFocus
InputProps={{
startAdornment: <SearchIcon />,
spellCheck: false
spellCheck: false,
}}
placeholder="Filter by member name"
sx={{ m: 1, width: '15%' }}
sx={{ m: 1, width: "15%" }}
/>
<OptionSwitch
checked={ascendOnly}
onChange={(newValue) => (setAscendOnly(newValue))}
onChange={(newValue) => setAscendOnly(newValue)}
text="Show only ascendable"
tooltip={
<>
Filter the members list by whether or not the member
can be ascended.
</>
}
tooltip={<>Filter the members list by whether or not the member can be ascended.</>}
/>
<Box display="grid" sx={{ gridTemplateColumns: 'repeat(2, 1fr)' }}>
<Box display="grid" sx={{ gridTemplateColumns: "repeat(2, 1fr)" }}>
{members.map((member: GangMember) => (
<GangMemberCard key={member.name} member={member} />
))}
+1 -1
View File
@@ -32,7 +32,7 @@ export function GangRoot(): React.ReactElement {
return (
<Context.Gang.Provider value={gang}>
<Tabs variant="fullWidth" value={value} onChange={handleChange} sx={{ minWidth: 'fit-content', maxWidth: '45%' }}>
<Tabs variant="fullWidth" value={value} onChange={handleChange} sx={{ minWidth: "fit-content", maxWidth: "45%" }}>
<Tab label="Management" />
<Tab label="Equipment" />
<Tab label="Territory" />
+4 -4
View File
@@ -25,10 +25,10 @@ export function RecruitButton(props: IProps): React.ReactElement {
const respect = gang.getRespectNeededToRecruitMember();
return (
<Box display="flex" alignItems="center" sx={{ mx: 1 }}>
<Button disabled>
Recruit Gang Member
</Button>
<Typography sx={{ ml: 1 }}>{numeralWrapper.formatRespect(respect)} respect needed to recruit next member</Typography>
<Button disabled>Recruit Gang Member</Button>
<Typography sx={{ ml: 1 }}>
{numeralWrapper.formatRespect(respect)} respect needed to recruit next member
</Typography>
</Box>
);
}
+4 -6
View File
@@ -21,11 +21,9 @@ export function TaskSelector(props: IProps): React.ReactElement {
const gang = useGang();
const [currentTask, setCurrentTask] = useState(props.member.task);
const contextMember = gang.members.find(member => member.name == props.member.name)
if (contextMember &&
contextMember.task != currentTask
) {
setCurrentTask(contextMember.task)
const contextMember = gang.members.find((member) => member.name == props.member.name);
if (contextMember && contextMember.task != currentTask) {
setCurrentTask(contextMember.task);
}
function onChange(event: SelectChangeEvent<string>): void {
@@ -39,7 +37,7 @@ export function TaskSelector(props: IProps): React.ReactElement {
return (
<Box>
<Select onChange={onChange} value={currentTask} sx={{ width: '100%' }}>
<Select onChange={onChange} value={currentTask} sx={{ width: "100%" }}>
<MenuItem key={0} value={"Unassigned"}>
Unassigned
</MenuItem>
+9 -15
View File
@@ -13,9 +13,7 @@ export const TerritoryInfoModal = ({ open, onClose }: IProps): React.ReactElemen
return (
<Modal open={open} onClose={onClose}>
<>
<Typography variant='h4'>
Clashing
</Typography>
<Typography variant="h4">Clashing</Typography>
<Typography>
Every ~20 seconds, your gang has a chance to 'clash' with other gangs. Your chance to win a clash depends on
your gang's power, which is listed in the display below. Your gang's power slowly accumulates over time. The
@@ -29,26 +27,22 @@ export const TerritoryInfoModal = ({ open, onClose }: IProps): React.ReactElemen
gang.
</Typography>
<br />
<Typography variant='h4'>
Territory
</Typography>
<Typography variant="h4">Territory</Typography>
<Typography>
The amount of territory you have affects all aspects of your Gang members' production, including money, respect,
and wanted level. It is very beneficial to have high territory control.
The amount of territory you have affects all aspects of your Gang members' production, including money,
respect, and wanted level. It is very beneficial to have high territory control.
<br />
<br />
To increase your chances of winning territory, assign gang members to "Territory Warfare". This will build your
gang power. Then, enable "Engage in Territory Warfare" to start fighting over territory.
To increase your chances of winning territory, assign gang members to "Territory Warfare". This will build
your gang power. Then, enable "Engage in Territory Warfare" to start fighting over territory.
</Typography>
<br />
<Typography variant='h4'>
Territory Clash Chance
</Typography>
<Typography variant="h4">Territory Clash Chance</Typography>
<Typography>
This percentage represents the chance you have of 'clashing' with another gang. If you do not wish to
gain/lose territory, then keep this percentage at 0% by not engaging in territory warfare.
</Typography>
</>
</Modal >
</Modal>
);
}
};
+43 -36
View File
@@ -3,16 +3,7 @@
*/
import React, { useState } from "react";
import {
Container,
Button,
Paper,
Box,
Tooltip,
Switch,
FormControlLabel,
Typography
} from "@mui/material";
import { Container, Button, Paper, Box, Tooltip, Switch, FormControlLabel, Typography } from "@mui/material";
import { Help } from "@mui/icons-material";
import { numeralWrapper } from "../../ui/numeralFormat";
@@ -41,35 +32,51 @@ export function TerritorySubpage(): React.ReactElement {
</Button>
<Box component={Paper} sx={{ p: 1, mb: 1 }}>
<Typography variant="h6" sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
{gang.facName} (Your gang)
</Typography>
<FormControlLabel
control={<Switch
checked={gang.territoryWarfareEngaged}
onChange={(event) => (gang.territoryWarfareEngaged = event.target.checked)}
/>}
label={<Tooltip
title={<Typography>
Engaging in Territory Warfare sets your clash chance to 100%. Disengaging will cause your clash chance
to gradually decrease until it reaches 0%.
</Typography>}>
<Typography>Engage in Territory Warfare</Typography>
</Tooltip>} />
control={
<Switch
checked={gang.territoryWarfareEngaged}
onChange={(event) => (gang.territoryWarfareEngaged = event.target.checked)}
/>
}
label={
<Tooltip
title={
<Typography>
Engaging in Territory Warfare sets your clash chance to 100%. Disengaging will cause your clash chance
to gradually decrease until it reaches 0%.
</Typography>
}
>
<Typography>Engage in Territory Warfare</Typography>
</Tooltip>
}
/>
<br />
<FormControlLabel
control={<Switch
checked={gang.notifyMemberDeath}
onChange={(event) => (gang.notifyMemberDeath = event.target.checked)}
/>}
label={<Tooltip
title={<Typography>
If this is enabled, then you will receive a pop-up notifying you whenever one of your Gang Members dies
in a territory clash.
</Typography>}>
<Typography>Notify about Gang Member Deaths</Typography>
</Tooltip>} />
control={
<Switch
checked={gang.notifyMemberDeath}
onChange={(event) => (gang.notifyMemberDeath = event.target.checked)}
/>
}
label={
<Tooltip
title={
<Typography>
If this is enabled, then you will receive a pop-up notifying you whenever one of your Gang Members
dies in a territory clash.
</Typography>
}
>
<Typography>Notify about Gang Member Deaths</Typography>
</Tooltip>
}
/>
<Typography>
<b>Territory Clash Chance:</b> {numeralWrapper.formatPercentage(gang.territoryClashChance, 3)} <br />
@@ -77,13 +84,13 @@ export function TerritorySubpage(): React.ReactElement {
<b>Territory:</b> {formatTerritory(AllGangs[gang.facName].territory)}% <br />
</Typography>
</Box>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}>
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)" }}>
{gangNames.map((name) => (
<OtherGangTerritory key={name} name={name} />
))}
</Box>
<TerritoryInfoModal open={infoOpen} onClose={() => setInfoOpen(false)} />
</Container >
</Container>
);
}
function formatTerritory(n: number): string {
@@ -109,7 +116,7 @@ function OtherGangTerritory(props: ITerritoryProps): React.ReactElement {
const clashVictoryChance = playerPower / (power + playerPower);
return (
<Box component={Paper} sx={{ p: 1 }}>
<Typography variant="h6" sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
{props.name}
</Typography>
<Typography>
+2 -1
View File
@@ -49,7 +49,8 @@ export function calculatePercentMoneyHacked(server: Server, player: IPlayer): nu
const difficultyMult = (100 - server.hackDifficulty) / 100;
const skillMult = (player.hacking - (server.requiredHackingSkill - 1)) / player.hacking;
const percentMoneyHacked = (difficultyMult * skillMult * player.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
const percentMoneyHacked =
(difficultyMult * skillMult * player.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
if (percentMoneyHacked < 0) {
return 0;
}
+2 -3
View File
@@ -21,14 +21,13 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver"
import { ObjectValidator, minMax } from "../utils/Validator";
export class HacknetNode implements IHacknetNode {
static validationData: ObjectValidator<HacknetNode> = {
cores: minMax(1, 1, HacknetNodeConstants.MaxCores),
level: minMax(1, 1, HacknetNodeConstants.MaxLevel),
ram: minMax(1, 1, HacknetNodeConstants.MaxRam),
onlineTimeSeconds: minMax(0, 0, Infinity),
totalMoneyGenerated: minMax(0, 0, Infinity)
}
totalMoneyGenerated: minMax(0, 0, Infinity),
};
// Node's number of cores
cores = 1;
+1 -1
View File
@@ -137,7 +137,7 @@ export function HacknetRoot(props: IProps): React.ReactElement {
{hasHacknetServers(props.player) && <Button onClick={() => setOpen(true)}>Spend Hashes on Upgrades</Button>}
<Box sx={{ display: 'grid', width: 'fit-content', gridTemplateColumns: 'repeat(3, 1fr)' }}>{nodes}</Box>
<Box sx={{ display: "grid", width: "fit-content", gridTemplateColumns: "repeat(3, 1fr)" }}>{nodes}</Box>
<HashUpgradeModal open={open} onClose={() => setOpen(false)} />
</>
);
+1 -1
View File
@@ -43,7 +43,7 @@ export function HacknetUpgradeElem(props: IProps): React.ReactElement {
if (!res) {
dialogBoxCreate(
"Failed to purchase upgrade. This may be because you do not have enough hashes, " +
"or because you do not have access to the feature upgrade affects.",
"or because you do not have access to the feature upgrade affects.",
);
}
props.rerender();
+1 -1
View File
@@ -1,4 +1,4 @@
import { CityName } from './../Locations/data/CityNames';
import { CityName } from "./../Locations/data/CityNames";
import { Literature } from "./Literature";
import { LiteratureNames } from "./data/LiteratureNames";
import { IMap } from "../types";
+1 -1
View File
@@ -34,7 +34,7 @@ export function CasinoLocation(props: IProps): React.ReactElement {
return (
<>
{game === GameType.None && (
<Box sx={{ display: 'grid', width: 'fit-content' }}>
<Box sx={{ display: "grid", width: "fit-content" }}>
<Button onClick={() => updateGame(GameType.Coin)}>Play coin flip</Button>
<Button onClick={() => updateGame(GameType.Slots)}>Play slots</Button>
<Button onClick={() => updateGame(GameType.Roulette)}>Play roulette</Button>
+3 -5
View File
@@ -228,9 +228,9 @@ export function CompanyLocation(props: IProps): React.ReactElement {
<br />
</>
)}
<Box sx={{ display: 'grid', width: 'fit-content' }}>
<Box sx={{ display: "grid", width: "fit-content" }}>
{isEmployedHere && (
<Box sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
<Button onClick={work}>Work</Button>
<Button onClick={() => setQuitOpen(true)}>Quit</Button>
<QuitJobModal
@@ -241,9 +241,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
onClose={() => setQuitOpen(false)}
/>
</Box>
)
}
)}
{company.hasAgentPositions() && (
<ApplyToJobButton
company={company}
+1 -5
View File
@@ -31,11 +31,7 @@ export function CoresButton(props: IProps): React.ReactElement {
}
return (
<Tooltip
title={
<MathJaxWrapper>{`\\(\\large{cost = 10^9 \\cdot 7.5 ^{\\text{cores}}}\\)`}</MathJaxWrapper>
}
>
<Tooltip title={<MathJaxWrapper>{`\\(\\large{cost = 10^9 \\cdot 7.5 ^{\\text{cores}}}\\)`}</MathJaxWrapper>}>
<span>
<br />
<Typography>
+7 -2
View File
@@ -96,8 +96,13 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
<Typography variant="h4" sx={{ mt: 1 }}>
{backdoorInstalled && !Settings.DisableTextEffects ? (
<Tooltip title={`Backdoor installed on ${loc.name}.`}>
<span><CorruptableText content={loc.name} /></span>
</Tooltip>) : loc.name}
<span>
<CorruptableText content={loc.name} />
</span>
</Tooltip>
) : (
loc.name
)}
</Typography>
{locContent}
</>
+1 -1
View File
@@ -59,7 +59,7 @@ export function GymLocation(props: IProps): React.ReactElement {
const cost = CONSTANTS.ClassGymBaseCost * calculateCost();
return (
<Box sx={{ display: 'grid', width: 'fit-content' }}>
<Box sx={{ display: "grid", width: "fit-content" }}>
<Button onClick={trainStrength}>
Train Strength (<Money money={cost} player={props.p} /> / sec)
</Button>
+1 -3
View File
@@ -32,9 +32,7 @@ export function RamButton(props: IProps): React.ReactElement {
return (
<Tooltip
title={
<MathJaxWrapper>{`\\(\\large{cost = 3.2 \\cdot 10^3 \\cdot 1.58^{log_2{(ram)}}}\\)`}</MathJaxWrapper>
}
title={<MathJaxWrapper>{`\\(\\large{cost = 3.2 \\cdot 10^3 \\cdot 1.58^{log_2{(ram)}}}\\)`}</MathJaxWrapper>}
>
<span>
<br />
+1 -1
View File
@@ -114,7 +114,7 @@ export function SlumsLocation(): React.ReactElement {
const heistChance = Crimes.Heist.successRate(player);
return (
<Box sx={{ display: 'grid', width: 'fit-content' }}>
<Box sx={{ display: "grid", width: "fit-content" }}>
<Tooltip title={<>Attempt to shoplift from a low-end retailer</>}>
<Button onClick={shoplift}>
Shoplift ({numeralWrapper.formatPercentage(shopliftChance)} chance of success)
+5 -1
View File
@@ -155,7 +155,11 @@ export function SpecialLocation(props: IProps): React.ReactElement {
if (!player.canAccessGrafting()) {
return <></>;
}
return <Button onClick={handleGrafting} sx={{ my: 5 }}>Enter the secret lab</Button>;
return (
<Button onClick={handleGrafting} sx={{ my: 5 }}>
Enter the secret lab
</Button>
);
}
function handleCotMG(): void {
+1 -3
View File
@@ -70,9 +70,7 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
return (
<>
<br />
<Box sx={{ display: 'grid', width: 'fit-content' }}>
{purchaseServerButtons}
</Box>
<Box sx={{ display: "grid", width: "fit-content" }}>{purchaseServerButtons}</Box>
<br />
<Typography>
<i>"You can order bigger servers via scripts. We don't take custom orders in person."</i>
+1 -1
View File
@@ -75,7 +75,7 @@ export function UniversityLocation(props: IProps): React.ReactElement {
const earnCharismaExpTooltip = `Gain charisma experience!`;
return (
<Box sx={{ display: 'grid', width: 'fit-content' }}>
<Box sx={{ display: "grid", width: "fit-content" }}>
<Tooltip title={earnHackingExpTooltip}>
<Button onClick={study}>Study Computer Science (free)</Button>
</Tooltip>
+2 -2
View File
@@ -1,4 +1,4 @@
import React from 'react';
import React from "react";
import { MathJax, MathJaxContext } from "better-react-mathjax";
interface IProps {
@@ -10,5 +10,5 @@ export function MathJaxWrapper({ children }: IProps): React.ReactElement {
<MathJaxContext version={3} src={"dist/ext/MathJax-3.2.0/es5/tex-chtml.js"}>
<MathJax>{children}</MathJax>
</MathJaxContext>
)
);
}
+34 -34
View File
@@ -129,48 +129,48 @@ function initMessages(): void {
new Message(
MessageFilenames.Jumper0,
"I know you can sense it. I know you're searching for it. " +
"It's why you spend night after " +
"night at your computer. <br><br>It's real, I've seen it. And I can " +
"help you find it. But not right now. You're not ready yet.<br><br>" +
"Use this program to track your progress<br><br>" +
"The fl1ght.exe program was added to your home computer<br><br>" +
"-jump3R",
"It's why you spend night after " +
"night at your computer. <br><br>It's real, I've seen it. And I can " +
"help you find it. But not right now. You're not ready yet.<br><br>" +
"Use this program to track your progress<br><br>" +
"The fl1ght.exe program was added to your home computer<br><br>" +
"-jump3R",
),
);
AddToAllMessages(
new Message(
MessageFilenames.Jumper1,
`Soon you will be contacted by a hacking group known as ${FactionNames.NiteSec}. ` +
"They can help you with your search. <br><br>" +
"You should join them, garner their favor, and " +
"exploit them for their Augmentations. But do not trust them. " +
"They are not what they seem. No one is.<br><br>" +
"-jump3R",
"They can help you with your search. <br><br>" +
"You should join them, garner their favor, and " +
"exploit them for their Augmentations. But do not trust them. " +
"They are not what they seem. No one is.<br><br>" +
"-jump3R",
),
);
AddToAllMessages(
new Message(
MessageFilenames.Jumper2,
"Do not try to save the world. There is no world to save. If " +
"you want to find the truth, worry only about yourself. Ethics and " +
`morals will get you killed. <br><br>Watch out for a hacking group known as ${FactionNames.NiteSec}.` +
"<br><br>-jump3R",
"you want to find the truth, worry only about yourself. Ethics and " +
`morals will get you killed. <br><br>Watch out for a hacking group known as ${FactionNames.NiteSec}.` +
"<br><br>-jump3R",
),
);
AddToAllMessages(
new Message(
MessageFilenames.Jumper3,
"You must learn to walk before you can run. And you must " +
`run before you can fly. Look for ${FactionNames.TheBlackHand}. <br><br>` +
"I.I.I.I <br><br>-jump3R",
`run before you can fly. Look for ${FactionNames.TheBlackHand}. <br><br>` +
"I.I.I.I <br><br>-jump3R",
),
);
AddToAllMessages(
new Message(
MessageFilenames.Jumper4,
"To find what you are searching for, you must understand the bits. " +
"The bits are all around us. The runners will help you.<br><br>" +
"-jump3R",
"The bits are all around us. The runners will help you.<br><br>" +
"-jump3R",
),
);
@@ -179,31 +179,31 @@ function initMessages(): void {
new Message(
MessageFilenames.CyberSecTest,
"We've been watching you. Your skills are very impressive. But you're wasting " +
"your talents. If you join us, you can put your skills to good use and change " +
"the world for the better. If you join us, we can unlock your full potential. <br><br>" +
"But first, you must pass our test. Find and install the backdoor on our server. <br><br>" +
`-${FactionNames.CyberSec}`,
"your talents. If you join us, you can put your skills to good use and change " +
"the world for the better. If you join us, we can unlock your full potential. <br><br>" +
"But first, you must pass our test. Find and install the backdoor on our server. <br><br>" +
`-${FactionNames.CyberSec}`,
),
);
AddToAllMessages(
new Message(
MessageFilenames.NiteSecTest,
"People say that the corrupted governments and corporations rule the world. " +
"Yes, maybe they do. But do you know who everyone really fears? People " +
"like us. Because they can't hide from us. Because they can't fight shadows " +
"and ideas with bullets. <br><br>" +
"Join us, and people will fear you, too. <br><br>" +
"Find and install the backdoor on our server. Then, we will contact you again." +
`<br><br>-${FactionNames.NiteSec}`,
"Yes, maybe they do. But do you know who everyone really fears? People " +
"like us. Because they can't hide from us. Because they can't fight shadows " +
"and ideas with bullets. <br><br>" +
"Join us, and people will fear you, too. <br><br>" +
"Find and install the backdoor on our server. Then, we will contact you again." +
`<br><br>-${FactionNames.NiteSec}`,
),
);
AddToAllMessages(
new Message(
MessageFilenames.BitRunnersTest,
"We know what you are doing. We know what drives you. We know " +
"what you are looking for. <br><br> " +
"We can help you find the answers.<br><br>" +
"run4theh111z",
"what you are looking for. <br><br> " +
"We can help you find the answers.<br><br>" +
"run4theh111z",
),
);
@@ -211,9 +211,9 @@ function initMessages(): void {
new Message(
MessageFilenames.RedPill,
"@)(#V%*N)@(#*)*C)@#%*)*V)@#(*%V@)(#VN%*)@#(*%<br>" +
")@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)<br>" +
"@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB<br>" +
"DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)",
")@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)<br>" +
"@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB<br>" +
"DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)",
),
);
}
+1 -1
View File
@@ -226,7 +226,7 @@ export const RamCosts: IMap<any> = {
universityCourse: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
gymWorkout: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
travelToCity: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
goToLocation: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
goToLocation: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
purchaseTor: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
purchaseProgram: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
getCurrentServer: SF4Cost(RamCostConstants.ScriptSingularityFn1RamCost),
+76 -77
View File
@@ -119,7 +119,6 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
console.warn(`WorkerScript detected NaN for threadcount for ${workerScript.name} on ${workerScript.hostname}`);
threads = 1;
}
workerScript.dynamicRamUsage += ramCost;
if (workerScript.dynamicRamUsage > 1.01 * workerScript.ramUsage) {
throw makeRuntimeRejectMsg(
@@ -521,8 +520,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
sprintf: sprintf,
vsprintf: vsprintf,
scan: function (_hostname: unknown = workerScript.hostname): string[] {
const hostname = helper.string("scan", "hostname", _hostname);
updateDynamicRam("scan", getRamCost(Player, "scan"));
const hostname = helper.string("scan", "hostname", _hostname);
const server = safeGetServer(hostname, "scan");
const out = [];
for (let i = 0; i < server.serversOnNetwork.length; i++) {
@@ -536,14 +535,14 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return out;
},
hack: function (_hostname: unknown, { threads: requestedThreads, stock }: BasicHGWOptions = {}): Promise<number> {
const hostname = helper.string("hack", "hostname", _hostname);
updateDynamicRam("hack", getRamCost(Player, "hack"));
const hostname = helper.string("hack", "hostname", _hostname);
return hack(hostname, false, { threads: requestedThreads, stock: stock });
},
hackAnalyzeThreads: function (_hostname: unknown, _hackAmount: unknown): number {
updateDynamicRam("hackAnalyzeThreads", getRamCost(Player, "hackAnalyzeThreads"));
const hostname = helper.string("hackAnalyzeThreads", "hostname", _hostname);
const hackAmount = helper.number("hackAnalyzeThreads", "hackAmount", _hackAmount);
updateDynamicRam("hackAnalyzeThreads", getRamCost(Player, "hackAnalyzeThreads"));
// Check argument validity
const server = safeGetServer(hostname, "hackAnalyzeThreads");
@@ -573,8 +572,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return hackAmount / Math.floor(server.moneyAvailable * percentHacked);
},
hackAnalyze: function (_hostname: unknown): number {
const hostname = helper.string("hackAnalyze", "hostname", _hostname);
updateDynamicRam("hackAnalyze", getRamCost(Player, "hackAnalyze"));
const hostname = helper.string("hackAnalyze", "hostname", _hostname);
const server = safeGetServer(hostname, "hackAnalyze");
if (!(server instanceof Server)) {
@@ -585,13 +584,13 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return calculatePercentMoneyHacked(server, Player);
},
hackAnalyzeSecurity: function (_threads: unknown): number {
const threads = helper.number("hackAnalyzeSecurity", "threads", _threads);
updateDynamicRam("hackAnalyzeSecurity", getRamCost(Player, "hackAnalyzeSecurity"));
const threads = helper.number("hackAnalyzeSecurity", "threads", _threads);
return CONSTANTS.ServerFortifyAmount * threads;
},
hackAnalyzeChance: function (_hostname: unknown): number {
const hostname = helper.string("hackAnalyzeChance", "hostname", _hostname);
updateDynamicRam("hackAnalyzeChance", getRamCost(Player, "hackAnalyzeChance"));
const hostname = helper.string("hackAnalyzeChance", "hostname", _hostname);
const server = safeGetServer(hostname, "hackAnalyzeChance");
if (!(server instanceof Server)) {
@@ -601,32 +600,32 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return calculateHackingChance(server, Player);
},
sleep: async function (_time: unknown = 0): Promise<void> {
const time = helper.number("sleep", "time", _time);
sleep: async function (_time: unknown = 0): Promise<true> {
updateDynamicRam("sleep", getRamCost(Player, "sleep"));
const time = helper.number("sleep", "time", _time);
if (time === undefined) {
throw makeRuntimeErrorMsg("sleep", "Takes 1 argument.");
}
workerScript.log("sleep", () => `Sleeping for ${time} milliseconds`);
return netscriptDelay(time, workerScript).then(function () {
return Promise.resolve();
return Promise.resolve(true);
});
},
asleep: function (_time: unknown = 0): Promise<void> {
const time = helper.number("asleep", "time", _time);
asleep: function (_time: unknown = 0): Promise<true> {
updateDynamicRam("asleep", getRamCost(Player, "asleep"));
const time = helper.number("asleep", "time", _time);
if (time === undefined) {
throw makeRuntimeErrorMsg("asleep", "Takes 1 argument.");
}
workerScript.log("asleep", () => `Sleeping for ${time} milliseconds`);
return new Promise((resolve) => setTimeout(resolve, time));
return new Promise((resolve) => setTimeout(() => resolve(true), time));
},
grow: async function (
_hostname: unknown,
{ threads: requestedThreads, stock }: BasicHGWOptions = {},
): Promise<number> {
const hostname = helper.string("grow", "hostname", _hostname);
updateDynamicRam("grow", getRamCost(Player, "grow"));
const hostname = helper.string("grow", "hostname", _hostname);
const threads = resolveNetscriptRequestedThreads(
workerScript,
"grow",
@@ -685,10 +684,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
});
},
growthAnalyze: function (_hostname: unknown, _growth: unknown, _cores: unknown = 1): number {
updateDynamicRam("growthAnalyze", getRamCost(Player, "growthAnalyze"));
const hostname = helper.string("growthAnalyze", "hostname", _hostname);
const growth = helper.number("growthAnalyze", "growth", _growth);
const cores = helper.number("growthAnalyze", "cores", _cores);
updateDynamicRam("growthAnalyze", getRamCost(Player, "growthAnalyze"));
// Check argument validity
const server = safeGetServer(hostname, "growthAnalyze");
@@ -703,13 +702,13 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return numCycleForGrowth(server, Number(growth), Player, cores);
},
growthAnalyzeSecurity: function (_threads: unknown): number {
const threads = helper.number("growthAnalyzeSecurity", "threads", _threads);
updateDynamicRam("growthAnalyzeSecurity", getRamCost(Player, "growthAnalyzeSecurity"));
const threads = helper.number("growthAnalyzeSecurity", "threads", _threads);
return 2 * CONSTANTS.ServerFortifyAmount * threads;
},
weaken: async function (_hostname: unknown, { threads: requestedThreads }: BasicHGWOptions = {}): Promise<number> {
const hostname = helper.string("weaken", "hostname", _hostname);
updateDynamicRam("weaken", getRamCost(Player, "weaken"));
const hostname = helper.string("weaken", "hostname", _hostname);
const threads = resolveNetscriptRequestedThreads(
workerScript,
"weaken",
@@ -762,9 +761,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
});
},
weakenAnalyze: function (_threads: unknown, _cores: unknown = 1): number {
updateDynamicRam("weakenAnalyze", getRamCost(Player, "weakenAnalyze"));
const threads = helper.number("weakenAnalyze", "threads", _threads);
const cores = helper.number("weakenAnalyze", "cores", _cores);
updateDynamicRam("weakenAnalyze", getRamCost(Player, "weakenAnalyze"));
const coreBonus = 1 + (cores - 1) / 16;
return CONSTANTS.ServerWeakenAmount * threads * coreBonus * BitNodeMultipliers.ServerWeakenRate;
},
@@ -789,8 +788,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.print(argsToString(args));
},
printf: function (_format: unknown, ...args: any[]): void {
const format = helper.string("printf", "format", _format);
updateDynamicRam("printf", getRamCost(Player, "printf"));
const format = helper.string("printf", "format", _format);
if (typeof format !== "string") {
throw makeRuntimeErrorMsg("printf", "First argument must be string for the format.");
}
@@ -821,8 +820,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
Terminal.print(`${workerScript.scriptRef.filename}: ${str}`);
},
tprintf: function (_format: unknown, ...args: any[]): void {
const format = helper.string("printf", "format", _format);
updateDynamicRam("tprintf", getRamCost(Player, "tprintf"));
const format = helper.string("printf", "format", _format);
if (typeof format !== "string") {
throw makeRuntimeErrorMsg("tprintf", "First argument must be string for the format.");
}
@@ -851,8 +850,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.scriptRef.clearLog();
},
disableLog: function (_fn: unknown): void {
const fn = helper.string("disableLog", "fn", _fn);
updateDynamicRam("disableLog", getRamCost(Player, "disableLog"));
const fn = helper.string("disableLog", "fn", _fn);
if (fn === "ALL") {
for (const fn of Object.keys(possibleLogs)) {
workerScript.disableLogs[fn] = true;
@@ -866,8 +865,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}
},
enableLog: function (_fn: unknown): void {
const fn = helper.string("enableLog", "fn", _fn);
updateDynamicRam("enableLog", getRamCost(Player, "enableLog"));
const fn = helper.string("enableLog", "fn", _fn);
if (fn === "ALL") {
for (const fn of Object.keys(possibleLogs)) {
delete workerScript.disableLogs[fn];
@@ -880,8 +879,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("enableLog", () => `Enabled logging for ${fn}`);
},
isLogEnabled: function (_fn: unknown): boolean {
const fn = helper.string("isLogEnabled", "fn", _fn);
updateDynamicRam("isLogEnabled", getRamCost(Player, "isLogEnabled"));
const fn = helper.string("isLogEnabled", "fn", _fn);
if (possibleLogs[fn] === undefined) {
throw makeRuntimeErrorMsg("isLogEnabled", `Invalid argument: ${fn}.`);
}
@@ -915,8 +914,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
LogBoxEvents.emit(runningScriptObj);
},
nuke: function (_hostname: unknown): boolean {
const hostname = helper.string("tail", "hostname", _hostname);
updateDynamicRam("nuke", getRamCost(Player, "nuke"));
const hostname = helper.string("tail", "hostname", _hostname);
if (hostname === undefined) {
throw makeRuntimeErrorMsg("nuke", "Takes 1 argument.");
}
@@ -940,8 +939,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return true;
},
brutessh: function (_hostname: unknown): boolean {
const hostname = helper.string("brutessh", "hostname", _hostname);
updateDynamicRam("brutessh", getRamCost(Player, "brutessh"));
const hostname = helper.string("brutessh", "hostname", _hostname);
if (hostname === undefined) {
throw makeRuntimeErrorMsg("brutessh", "Takes 1 argument.");
}
@@ -963,8 +962,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return true;
},
ftpcrack: function (_hostname: unknown): boolean {
const hostname = helper.string("ftpcrack", "hostname", _hostname);
updateDynamicRam("ftpcrack", getRamCost(Player, "ftpcrack"));
const hostname = helper.string("ftpcrack", "hostname", _hostname);
if (hostname === undefined) {
throw makeRuntimeErrorMsg("ftpcrack", "Takes 1 argument.");
}
@@ -986,8 +985,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return true;
},
relaysmtp: function (_hostname: unknown): boolean {
const hostname = helper.string("relaysmtp", "hostname", _hostname);
updateDynamicRam("relaysmtp", getRamCost(Player, "relaysmtp"));
const hostname = helper.string("relaysmtp", "hostname", _hostname);
if (hostname === undefined) {
throw makeRuntimeErrorMsg("relaysmtp", "Takes 1 argument.");
}
@@ -1009,8 +1008,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return true;
},
httpworm: function (_hostname: unknown): boolean {
const hostname = helper.string("httpworm", "hostname", _hostname);
updateDynamicRam("httpworm", getRamCost(Player, "httpworm"));
const hostname = helper.string("httpworm", "hostname", _hostname);
if (hostname === undefined) {
throw makeRuntimeErrorMsg("httpworm", "Takes 1 argument");
}
@@ -1032,8 +1031,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return true;
},
sqlinject: function (_hostname: unknown): boolean {
const hostname = helper.string("sqlinject", "hostname", _hostname);
updateDynamicRam("sqlinject", getRamCost(Player, "sqlinject"));
const hostname = helper.string("sqlinject", "hostname", _hostname);
if (hostname === undefined) {
throw makeRuntimeErrorMsg("sqlinject", "Takes 1 argument.");
}
@@ -1055,9 +1054,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return true;
},
run: function (_scriptname: unknown, _threads: unknown = 1, ...args: any[]): number {
updateDynamicRam("run", getRamCost(Player, "run"));
const scriptname = helper.string("run", "scriptname", _scriptname);
const threads = helper.number("run", "threads", _threads);
updateDynamicRam("run", getRamCost(Player, "run"));
if (scriptname === undefined) {
throw makeRuntimeErrorMsg("run", "Usage: run(scriptname, [numThreads], [arg1], [arg2]...)");
}
@@ -1072,10 +1071,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return runScriptFromScript(Player, "run", scriptServer, scriptname, args, workerScript, threads);
},
exec: function (_scriptname: unknown, _hostname: unknown, _threads: unknown = 1, ...args: any[]): number {
updateDynamicRam("exec", getRamCost(Player, "exec"));
const scriptname = helper.string("exec", "scriptname", _scriptname);
const hostname = helper.string("exec", "hostname", _hostname);
const threads = helper.number("exec", "threads", _threads);
updateDynamicRam("exec", getRamCost(Player, "exec"));
if (scriptname === undefined || hostname === undefined) {
throw makeRuntimeErrorMsg("exec", "Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)");
}
@@ -1086,9 +1085,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return runScriptFromScript(Player, "exec", server, scriptname, args, workerScript, threads);
},
spawn: function (_scriptname: unknown, _threads: unknown = 1, ...args: any[]): void {
updateDynamicRam("spawn", getRamCost(Player, "spawn"));
const scriptname = helper.string("spawn", "scriptname", _scriptname);
const threads = helper.number("spawn", "threads", _threads);
updateDynamicRam("spawn", getRamCost(Player, "spawn"));
if (!scriptname || !threads) {
throw makeRuntimeErrorMsg("spawn", "Usage: spawn(scriptname, threads)");
}
@@ -1160,8 +1159,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}
},
killall: function (_hostname: unknown = workerScript.hostname): boolean {
const hostname = helper.string("killall", "hostname", _hostname);
updateDynamicRam("killall", getRamCost(Player, "killall"));
const hostname = helper.string("killall", "hostname", _hostname);
if (hostname === undefined) {
throw makeRuntimeErrorMsg("killall", "Takes 1 argument");
}
@@ -1188,8 +1187,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}
},
scp: async function (scriptname: any, _hostname1: unknown, hostname2?: any): Promise<boolean> {
const hostname1 = helper.string("scp", "hostname1", _hostname1);
updateDynamicRam("scp", getRamCost(Player, "scp"));
const hostname1 = helper.string("scp", "hostname1", _hostname1);
if (arguments.length !== 2 && arguments.length !== 3) {
throw makeRuntimeErrorMsg("scp", "Takes 2 or 3 arguments");
}
@@ -1346,9 +1345,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
});
},
ls: function (_hostname: unknown, _grep: unknown = ""): string[] {
updateDynamicRam("ls", getRamCost(Player, "ls"));
const hostname = helper.string("ls", "hostname", _hostname);
const grep = helper.string("ls", "grep", _grep);
updateDynamicRam("ls", getRamCost(Player, "ls"));
if (hostname === undefined) {
throw makeRuntimeErrorMsg("ls", "Usage: ls(hostname/ip, [grep filter])");
}
@@ -1415,8 +1414,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return allFiles;
},
ps: function (_hostname: unknown = workerScript.hostname): ProcessInfo[] {
const hostname = helper.string("ps", "hostname", _hostname);
updateDynamicRam("ps", getRamCost(Player, "ps"));
const hostname = helper.string("ps", "hostname", _hostname);
const server = safeGetServer(hostname, "ps");
const processes = [];
for (const script of server.runningScripts) {
@@ -1430,8 +1429,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return processes;
},
hasRootAccess: function (_hostname: unknown): boolean {
const hostname = helper.string("hasRootAccess", "hostname", _hostname);
updateDynamicRam("hasRootAccess", getRamCost(Player, "hasRootAccess"));
const hostname = helper.string("hasRootAccess", "hostname", _hostname);
if (hostname === undefined) {
throw makeRuntimeErrorMsg("hasRootAccess", "Takes 1 argument");
}
@@ -1480,8 +1479,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return copy;
},
getServer: function (_hostname: unknown = workerScript.hostname): IServerDef {
const hostname = helper.string("getServer", "hostname", _hostname);
updateDynamicRam("getServer", getRamCost(Player, "getServer"));
const hostname = helper.string("getServer", "hostname", _hostname);
const server = safeGetServer(hostname, "getServer");
const copy = Object.assign({}, server) as any;
// These fields should be hidden.
@@ -1504,8 +1503,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return copy;
},
getServerMoneyAvailable: function (_hostname: unknown): number {
const hostname = helper.string("getServerMoneyAvailable", "hostname", _hostname);
updateDynamicRam("getServerMoneyAvailable", getRamCost(Player, "getServerMoneyAvailable"));
const hostname = helper.string("getServerMoneyAvailable", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerMoneyAvailable");
if (!(server instanceof Server)) {
workerScript.log("getServerMoneyAvailable", () => "Cannot be executed on this server.");
@@ -1529,8 +1528,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return server.moneyAvailable;
},
getServerSecurityLevel: function (_hostname: unknown): number {
const hostname = helper.string("getServerSecurityLevel", "hostname", _hostname);
updateDynamicRam("getServerSecurityLevel", getRamCost(Player, "getServerSecurityLevel"));
const hostname = helper.string("getServerSecurityLevel", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerSecurityLevel");
if (!(server instanceof Server)) {
workerScript.log("getServerSecurityLevel", () => "Cannot be executed on this server.");
@@ -1546,8 +1545,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return server.hackDifficulty;
},
getServerBaseSecurityLevel: function (_hostname: unknown): number {
const hostname = helper.string("getServerBaseSecurityLevel", "hostname", _hostname);
updateDynamicRam("getServerBaseSecurityLevel", getRamCost(Player, "getServerBaseSecurityLevel"));
const hostname = helper.string("getServerBaseSecurityLevel", "hostname", _hostname);
workerScript.log(
"getServerBaseSecurityLevel",
() => `getServerBaseSecurityLevel is deprecated because it's not useful.`,
@@ -1567,8 +1566,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return server.baseDifficulty;
},
getServerMinSecurityLevel: function (_hostname: unknown): number {
const hostname = helper.string("getServerMinSecurityLevel", "hostname", _hostname);
updateDynamicRam("getServerMinSecurityLevel", getRamCost(Player, "getServerMinSecurityLevel"));
const hostname = helper.string("getServerMinSecurityLevel", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerMinSecurityLevel");
if (!(server instanceof Server)) {
workerScript.log("getServerMinSecurityLevel", () => "Cannot be executed on this server.");
@@ -1584,8 +1583,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return server.minDifficulty;
},
getServerRequiredHackingLevel: function (_hostname: unknown): number {
const hostname = helper.string("getServerRequiredHackingLevel", "hostname", _hostname);
updateDynamicRam("getServerRequiredHackingLevel", getRamCost(Player, "getServerRequiredHackingLevel"));
const hostname = helper.string("getServerRequiredHackingLevel", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerRequiredHackingLevel");
if (!(server instanceof Server)) {
workerScript.log("getServerRequiredHackingLevel", () => "Cannot be executed on this server.");
@@ -1601,8 +1600,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return server.requiredHackingSkill;
},
getServerMaxMoney: function (_hostname: unknown): number {
const hostname = helper.string("getServerMaxMoney", "hostname", _hostname);
updateDynamicRam("getServerMaxMoney", getRamCost(Player, "getServerMaxMoney"));
const hostname = helper.string("getServerMaxMoney", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerMaxMoney");
if (!(server instanceof Server)) {
workerScript.log("getServerMaxMoney", () => "Cannot be executed on this server.");
@@ -1618,8 +1617,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return server.moneyMax;
},
getServerGrowth: function (_hostname: unknown): number {
const hostname = helper.string("getServerGrowth", "hostname", _hostname);
updateDynamicRam("getServerGrowth", getRamCost(Player, "getServerGrowth"));
const hostname = helper.string("getServerGrowth", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerGrowth");
if (!(server instanceof Server)) {
workerScript.log("getServerGrowth", () => "Cannot be executed on this server.");
@@ -1632,8 +1631,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return server.serverGrowth;
},
getServerNumPortsRequired: function (_hostname: unknown): number {
const hostname = helper.string("getServerNumPortsRequired", "hostname", _hostname);
updateDynamicRam("getServerNumPortsRequired", getRamCost(Player, "getServerNumPortsRequired"));
const hostname = helper.string("getServerNumPortsRequired", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerNumPortsRequired");
if (!(server instanceof Server)) {
workerScript.log("getServerNumPortsRequired", () => "Cannot be executed on this server.");
@@ -1649,8 +1648,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return server.numOpenPortsRequired;
},
getServerRam: function (_hostname: unknown): [number, number] {
const hostname = helper.string("getServerRam", "hostname", _hostname);
updateDynamicRam("getServerRam", getRamCost(Player, "getServerRam"));
const hostname = helper.string("getServerRam", "hostname", _hostname);
workerScript.log(
"getServerRam",
() => `getServerRam is deprecated in favor of getServerMaxRam / getServerUsedRam`,
@@ -1663,28 +1662,28 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return [server.maxRam, server.ramUsed];
},
getServerMaxRam: function (_hostname: unknown): number {
const hostname = helper.string("getServerMaxRam", "hostname", _hostname);
updateDynamicRam("getServerMaxRam", getRamCost(Player, "getServerMaxRam"));
const hostname = helper.string("getServerMaxRam", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerMaxRam");
workerScript.log("getServerMaxRam", () => `returned ${numeralWrapper.formatRAM(server.maxRam)}`);
return server.maxRam;
},
getServerUsedRam: function (_hostname: unknown): number {
const hostname = helper.string("getServerUsedRam", "hostname", _hostname);
updateDynamicRam("getServerUsedRam", getRamCost(Player, "getServerUsedRam"));
const hostname = helper.string("getServerUsedRam", "hostname", _hostname);
const server = safeGetServer(hostname, "getServerUsedRam");
workerScript.log("getServerUsedRam", () => `returned ${numeralWrapper.formatRAM(server.ramUsed)}`);
return server.ramUsed;
},
serverExists: function (_hostname: unknown): boolean {
const hostname = helper.string("serverExists", "hostname", _hostname);
updateDynamicRam("serverExists", getRamCost(Player, "serverExists"));
const hostname = helper.string("serverExists", "hostname", _hostname);
return GetServer(hostname) !== null;
},
fileExists: function (_filename: unknown, _hostname: unknown = workerScript.hostname): boolean {
updateDynamicRam("fileExists", getRamCost(Player, "fileExists"));
const filename = helper.string("fileExists", "filename", _filename);
const hostname = helper.string("fileExists", "hostname", _hostname);
updateDynamicRam("fileExists", getRamCost(Player, "fileExists"));
if (filename === undefined) {
throw makeRuntimeErrorMsg("fileExists", "Usage: fileExists(scriptname, [server])");
}
@@ -1729,8 +1728,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return getPurchaseServerMaxRam();
},
getPurchasedServerCost: function (_ram: unknown): number {
const ram = helper.number("getPurchasedServerCost", "ram", _ram);
updateDynamicRam("getPurchasedServerCost", getRamCost(Player, "getPurchasedServerCost"));
const ram = helper.number("getPurchasedServerCost", "ram", _ram);
const cost = getPurchaseServerCost(ram);
if (cost === Infinity) {
@@ -1741,10 +1740,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return cost;
},
purchaseServer: function (_name: unknown, _ram: unknown): string {
updateDynamicRam("purchaseServer", getRamCost(Player, "purchaseServer"));
const name = helper.string("purchaseServer", "name", _name);
const ram = helper.number("purchaseServer", "ram", _ram);
if (arguments.length !== 2) throw makeRuntimeErrorMsg("purchaseServer", "Takes 2 arguments");
updateDynamicRam("purchaseServer", getRamCost(Player, "purchaseServer"));
let hostnameStr = String(name);
hostnameStr = hostnameStr.replace(/\s+/g, "");
if (hostnameStr == "") {
@@ -1805,8 +1804,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return newServ.hostname;
},
deleteServer: function (_name: unknown): boolean {
const name = helper.string("purchaseServer", "name", _name);
updateDynamicRam("deleteServer", getRamCost(Player, "deleteServer"));
const name = helper.string("purchaseServer", "name", _name);
let hostnameStr = String(name);
hostnameStr = hostnameStr.replace(/\s\s+/g, "");
const server = GetServer(hostnameStr);
@@ -1890,8 +1889,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return res;
},
writePort: function (_port: unknown, data: any = ""): Promise<any> {
const port = helper.number("writePort", "port", _port);
updateDynamicRam("writePort", getRamCost(Player, "writePort"));
const port = helper.number("writePort", "port", _port);
if (typeof data !== "string" && typeof data !== "number") {
throw makeRuntimeErrorMsg(
"writePort",
@@ -1902,9 +1901,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return Promise.resolve(iport.write(data));
},
write: function (_port: unknown, data: any = "", _mode: unknown = "a"): Promise<void> {
updateDynamicRam("write", getRamCost(Player, "write"));
const port = helper.string("write", "port", _port);
const mode = helper.string("write", "mode", _mode);
updateDynamicRam("write", getRamCost(Player, "write"));
if (isString(port)) {
// Write to script or text file
let fn = port;
@@ -1957,8 +1956,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}
},
tryWritePort: function (_port: unknown, data: any = ""): Promise<any> {
let port = helper.number("tryWritePort", "port", _port);
updateDynamicRam("tryWritePort", getRamCost(Player, "tryWritePort"));
let port = helper.number("tryWritePort", "port", _port);
if (typeof data !== "string" && typeof data !== "number") {
throw makeRuntimeErrorMsg(
"tryWritePort",
@@ -1983,16 +1982,16 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}
},
readPort: function (_port: unknown): any {
const port = helper.number("readPort", "port", _port);
updateDynamicRam("readPort", getRamCost(Player, "readPort"));
const port = helper.number("readPort", "port", _port);
// Read from port
const iport = helper.getValidPort("readPort", port);
const x = iport.read();
return x;
},
read: function (_port: unknown): string {
const port = helper.string("read", "port", _port);
updateDynamicRam("read", getRamCost(Player, "read"));
const port = helper.string("read", "port", _port);
if (isString(port)) {
// Read from script or text file
const fn = port;
@@ -2021,15 +2020,15 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}
},
peek: function (_port: unknown): any {
const port = helper.number("peek", "port", _port);
updateDynamicRam("peek", getRamCost(Player, "peek"));
const port = helper.number("peek", "port", _port);
const iport = helper.getValidPort("peek", port);
const x = iport.peek();
return x;
},
clear: function (_file: unknown): void {
const file = helper.string("peek", "file", _file);
updateDynamicRam("clear", getRamCost(Player, "clear"));
const file = helper.string("peek", "file", _file);
if (isString(file)) {
// Clear text file
const fn = file;
@@ -2046,21 +2045,21 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}
},
clearPort: function (_port: unknown): void {
const port = helper.number("clearPort", "port", _port);
updateDynamicRam("clearPort", getRamCost(Player, "clearPort"));
const port = helper.number("clearPort", "port", _port);
// Clear port
const iport = helper.getValidPort("clearPort", port);
iport.clear();
},
getPortHandle: function (_port: unknown): IPort {
const port = helper.number("getPortHandle", "port", _port);
updateDynamicRam("getPortHandle", getRamCost(Player, "getPortHandle"));
const port = helper.number("getPortHandle", "port", _port);
const iport = helper.getValidPort("getPortHandle", port);
return iport;
},
rm: function (_fn: unknown, hostname: any): boolean {
const fn = helper.string("rm", "fn", _fn);
updateDynamicRam("rm", getRamCost(Player, "rm"));
const fn = helper.string("rm", "fn", _fn);
if (hostname == null || hostname === "") {
hostname = workerScript.hostname;
@@ -2075,9 +2074,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return status.res;
},
scriptRunning: function (_scriptname: unknown, _hostname: unknown): boolean {
updateDynamicRam("scriptRunning", getRamCost(Player, "scriptRunning"));
const scriptname = helper.string("scriptRunning", "scriptname", _scriptname);
const hostname = helper.string("scriptRunning", "hostname", _hostname);
updateDynamicRam("scriptRunning", getRamCost(Player, "scriptRunning"));
const server = safeGetServer(hostname, "scriptRunning");
for (let i = 0; i < server.runningScripts.length; ++i) {
if (server.runningScripts[i].filename == scriptname) {
@@ -2087,9 +2086,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return false;
},
scriptKill: function (_scriptname: unknown, _hostname: unknown): boolean {
updateDynamicRam("scriptKill", getRamCost(Player, "scriptKill"));
const scriptname = helper.string("scriptKill", "scriptname", _scriptname);
const hostname = helper.string("scriptKill", "hostname", _hostname);
updateDynamicRam("scriptKill", getRamCost(Player, "scriptKill"));
const server = safeGetServer(hostname, "scriptKill");
let suc = false;
for (let i = 0; i < server.runningScripts.length; i++) {
@@ -2106,9 +2105,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return workerScript.name;
},
getScriptRam: function (_scriptname: unknown, _hostname: unknown = workerScript.hostname): number {
updateDynamicRam("getScriptRam", getRamCost(Player, "getScriptRam"));
const scriptname = helper.string("getScriptRam", "scriptname", _scriptname);
const hostname = helper.string("getScriptRam", "hostname", _hostname);
updateDynamicRam("getScriptRam", getRamCost(Player, "getScriptRam"));
const server = safeGetServer(hostname, "getScriptRam");
for (let i = 0; i < server.scripts.length; ++i) {
if (server.scripts[i].filename == scriptname) {
@@ -2146,8 +2145,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
};
},
getHackTime: function (_hostname: unknown = workerScript.hostname): number {
const hostname = helper.string("getHackTime", "hostname", _hostname);
updateDynamicRam("getHackTime", getRamCost(Player, "getHackTime"));
const hostname = helper.string("getHackTime", "hostname", _hostname);
const server = safeGetServer(hostname, "getHackTime");
if (!(server instanceof Server)) {
workerScript.log("getHackTime", () => "invalid for this kind of server");
@@ -2160,8 +2159,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return calculateHackingTime(server, Player) * 1000;
},
getGrowTime: function (_hostname: unknown = workerScript.hostname): number {
const hostname = helper.string("getGrowTime", "hostname", _hostname);
updateDynamicRam("getGrowTime", getRamCost(Player, "getGrowTime"));
const hostname = helper.string("getGrowTime", "hostname", _hostname);
const server = safeGetServer(hostname, "getGrowTime");
if (!(server instanceof Server)) {
workerScript.log("getGrowTime", () => "invalid for this kind of server");
@@ -2174,8 +2173,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return calculateGrowTime(server, Player) * 1000;
},
getWeakenTime: function (_hostname: unknown = workerScript.hostname): number {
const hostname = helper.string("getWeakenTime", "hostname", _hostname);
updateDynamicRam("getWeakenTime", getRamCost(Player, "getWeakenTime"));
const hostname = helper.string("getWeakenTime", "hostname", _hostname);
const server = safeGetServer(hostname, "getWeakenTime");
if (!(server instanceof Server)) {
workerScript.log("getWeakenTime", () => "invalid for this kind of server");
@@ -2239,9 +2238,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}
},
nFormat: function (_n: unknown, _format: unknown): string {
updateDynamicRam("nFormat", getRamCost(Player, "nFormat"));
const n = helper.number("nFormat", "n", _n);
const format = helper.string("nFormat", "format", _format);
updateDynamicRam("nFormat", getRamCost(Player, "nFormat"));
if (isNaN(n)) {
return "";
}
@@ -2249,9 +2248,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return numeralWrapper.format(n, format);
},
tFormat: function (_milliseconds: unknown, _milliPrecision: unknown = false): string {
updateDynamicRam("tFormat", getRamCost(Player, "tFormat"));
const milliseconds = helper.number("tFormat", "milliseconds", _milliseconds);
const milliPrecision = helper.boolean(_milliPrecision);
updateDynamicRam("tFormat", getRamCost(Player, "tFormat"));
return convertTimeMsToTimeElapsedString(milliseconds, milliPrecision);
},
getTimeSinceLastAug: function (): number {
@@ -2259,21 +2258,21 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return Player.playtimeSinceLastAug;
},
alert: function (_message: unknown): void {
const message = helper.string("alert", "message", _message);
updateDynamicRam("alert", getRamCost(Player, "alert"));
const message = helper.string("alert", "message", _message);
dialogBoxCreate(message);
},
toast: function (_message: unknown, _variant: unknown = "success", duration: any = 2000): void {
updateDynamicRam("toast", getRamCost(Player, "toast"));
const message = helper.string("toast", "message", _message);
const variant = helper.string("toast", "variant", _variant);
updateDynamicRam("toast", getRamCost(Player, "toast"));
if (!["success", "info", "warning", "error"].includes(variant))
throw new Error(`variant must be one of "success", "info", "warning", or "error"`);
SnackbarEvents.emit(message, variant as any, duration);
},
prompt: function (_txt: unknown, options?: { type?: string; options?: string[] }): Promise<boolean | string> {
const txt = helper.string("toast", "txt", _txt);
updateDynamicRam("prompt", getRamCost(Player, "prompt"));
const txt = helper.string("toast", "txt", _txt);
return new Promise(function (resolve) {
PromptEvent.emit({
@@ -2288,10 +2287,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
_target: unknown,
_hostname: unknown = workerScript.hostname,
): Promise<boolean> {
updateDynamicRam("wget", getRamCost(Player, "wget"));
const url = helper.string("wget", "url", _url);
const target = helper.string("wget", "target", _target);
const hostname = helper.string("wget", "hostname", _hostname);
updateDynamicRam("wget", getRamCost(Player, "wget"));
if (!isScriptFilename(target) && !target.endsWith(".txt")) {
workerScript.log("wget", () => `Invalid target file: '${target}'. Must be a script or text file.`);
return Promise.resolve(false);
@@ -2450,10 +2449,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}; // Wrap the user function to prevent WorkerScript leaking as 'this'
},
mv: function (_host: unknown, _source: unknown, _destination: unknown): void {
updateDynamicRam("mv", getRamCost(Player, "mv"));
const host = helper.string("mv", "host", _host);
const source = helper.string("mv", "source", _source);
const destination = helper.string("mv", "destination", _destination);
updateDynamicRam("mv", getRamCost(Player, "mv"));
if (!isValidFilePath(source)) throw makeRuntimeErrorMsg("mv", `Invalid filename: '${source}'`);
if (!isValidFilePath(destination)) throw makeRuntimeErrorMsg("mv", `Invalid filename: '${destination}'`);
+37 -40
View File
@@ -56,53 +56,56 @@ export function NetscriptBladeburner(
return actionObj;
};
const updateRam = (funcName: string): void =>
helper.updateDynamicRam(funcName, getRamCost(player, "bladeburner", funcName));
return {
getContractNames: function (): string[] {
helper.updateDynamicRam("getContractNames", getRamCost(player, "bladeburner", "getContractNames"));
updateRam("getContractNames");
checkBladeburnerAccess("getContractNames");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getContractNamesNetscriptFn();
},
getOperationNames: function (): string[] {
helper.updateDynamicRam("getOperationNames", getRamCost(player, "bladeburner", "getOperationNames"));
updateRam("getOperationNames");
checkBladeburnerAccess("getOperationNames");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getOperationNamesNetscriptFn();
},
getBlackOpNames: function (): string[] {
helper.updateDynamicRam("getBlackOpNames", getRamCost(player, "bladeburner", "getBlackOpNames"));
updateRam("getBlackOpNames");
checkBladeburnerAccess("getBlackOpNames");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getBlackOpNamesNetscriptFn();
},
getBlackOpRank: function (_blackOpName: unknown): number {
updateRam("getBlackOpRank");
const blackOpName = helper.string("getBlackOpRank", "blackOpName", _blackOpName);
helper.updateDynamicRam("getBlackOpRank", getRamCost(player, "bladeburner", "getBlackOpRank"));
checkBladeburnerAccess("getBlackOpRank");
const action: any = getBladeburnerActionObject("getBlackOpRank", "blackops", blackOpName);
return action.reqdRank;
},
getGeneralActionNames: function (): string[] {
helper.updateDynamicRam("getGeneralActionNames", getRamCost(player, "bladeburner", "getGeneralActionNames"));
updateRam("getGeneralActionNames");
checkBladeburnerAccess("getGeneralActionNames");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getGeneralActionNamesNetscriptFn();
},
getSkillNames: function (): string[] {
helper.updateDynamicRam("getSkillNames", getRamCost(player, "bladeburner", "getSkillNames"));
updateRam("getSkillNames");
checkBladeburnerAccess("getSkillNames");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getSkillNamesNetscriptFn();
},
startAction: function (_type: unknown, _name: unknown): boolean {
updateRam("startAction");
const type = helper.string("startAction", "type", _type);
const name = helper.string("startAction", "name", _name);
helper.updateDynamicRam("startAction", getRamCost(player, "bladeburner", "startAction"));
checkBladeburnerAccess("startAction");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -113,23 +116,23 @@ export function NetscriptBladeburner(
}
},
stopBladeburnerAction: function (): void {
helper.updateDynamicRam("stopBladeburnerAction", getRamCost(player, "bladeburner", "stopBladeburnerAction"));
updateRam("stopBladeburnerAction");
checkBladeburnerAccess("stopBladeburnerAction");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.resetAction();
},
getCurrentAction: function (): BladeburnerCurAction {
helper.updateDynamicRam("getCurrentAction", getRamCost(player, "bladeburner", "getCurrentAction"));
updateRam("getCurrentAction");
checkBladeburnerAccess("getCurrentAction");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
},
getActionTime: function (_type: unknown, _name: unknown): number {
updateRam("getActionTime");
const type = helper.string("getActionTime", "type", _type);
const name = helper.string("getActionTime", "name", _name);
helper.updateDynamicRam("getActionTime", getRamCost(player, "bladeburner", "getActionTime"));
checkBladeburnerAccess("getActionTime");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -140,12 +143,9 @@ export function NetscriptBladeburner(
}
},
getActionEstimatedSuccessChance: function (_type: unknown, _name: unknown): [number, number] {
updateRam("getActionEstimatedSuccessChance");
const type = helper.string("getActionEstimatedSuccessChance", "type", _type);
const name = helper.string("getActionEstimatedSuccessChance", "name", _name);
helper.updateDynamicRam(
"getActionEstimatedSuccessChance",
getRamCost(player, "bladeburner", "getActionEstimatedSuccessChance"),
);
checkBladeburnerAccess("getActionEstimatedSuccessChance");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -156,10 +156,10 @@ export function NetscriptBladeburner(
}
},
getActionRepGain: function (_type: unknown, _name: unknown, _level: unknown): number {
updateRam("getActionRepGain");
const type = helper.string("getActionRepGain", "type", _type);
const name = helper.string("getActionRepGain", "name", _name);
const level = helper.number("getActionRepGain", "level", _level);
helper.updateDynamicRam("getActionRepGain", getRamCost(player, "bladeburner", "getActionRepGain"));
checkBladeburnerAccess("getActionRepGain");
const action = getBladeburnerActionObject("getActionRepGain", type, name);
let rewardMultiplier;
@@ -172,9 +172,9 @@ export function NetscriptBladeburner(
return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank;
},
getActionCountRemaining: function (_type: unknown, _name: unknown): number {
updateRam("getActionCountRemaining");
const type = helper.string("getActionCountRemaining", "type", _type);
const name = helper.string("getActionCountRemaining", "name", _name);
helper.updateDynamicRam("getActionCountRemaining", getRamCost(player, "bladeburner", "getActionCountRemaining"));
checkBladeburnerAccess("getActionCountRemaining");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -185,43 +185,43 @@ export function NetscriptBladeburner(
}
},
getActionMaxLevel: function (_type: unknown, _name: unknown): number {
updateRam("getActionMaxLevel");
const type = helper.string("getActionMaxLevel", "type", _type);
const name = helper.string("getActionMaxLevel", "name", _name);
helper.updateDynamicRam("getActionMaxLevel", getRamCost(player, "bladeburner", "getActionMaxLevel"));
checkBladeburnerAccess("getActionMaxLevel");
const action = getBladeburnerActionObject("getActionMaxLevel", type, name);
return action.maxLevel;
},
getActionCurrentLevel: function (_type: unknown, _name: unknown): number {
updateRam("getActionCurrentLevel");
const type = helper.string("getActionCurrentLevel", "type", _type);
const name = helper.string("getActionCurrentLevel", "name", _name);
helper.updateDynamicRam("getActionCurrentLevel", getRamCost(player, "bladeburner", "getActionCurrentLevel"));
checkBladeburnerAccess("getActionCurrentLevel");
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
return action.level;
},
getActionAutolevel: function (_type: unknown, _name: unknown): boolean {
updateRam("getActionAutolevel");
const type = helper.string("getActionAutolevel", "type", _type);
const name = helper.string("getActionAutolevel", "name", _name);
helper.updateDynamicRam("getActionAutolevel", getRamCost(player, "bladeburner", "getActionAutolevel"));
checkBladeburnerAccess("getActionAutolevel");
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
return action.autoLevel;
},
setActionAutolevel: function (_type: unknown, _name: unknown, _autoLevel: unknown = true): void {
updateRam("setActionAutolevel");
const type = helper.string("setActionAutolevel", "type", _type);
const name = helper.string("setActionAutolevel", "name", _name);
const autoLevel = helper.boolean(_autoLevel);
helper.updateDynamicRam("setActionAutolevel", getRamCost(player, "bladeburner", "setActionAutolevel"));
checkBladeburnerAccess("setActionAutolevel");
const action = getBladeburnerActionObject("setActionAutolevel", type, name);
action.autoLevel = autoLevel;
},
setActionLevel: function (_type: unknown, _name: unknown, _level: unknown = 1): void {
updateRam("setActionLevel");
const type = helper.string("setActionLevel", "type", _type);
const name = helper.string("setActionLevel", "name", _name);
const level = helper.number("setActionLevel", "level", _level);
helper.updateDynamicRam("setActionLevel", getRamCost(player, "bladeburner", "setActionLevel"));
checkBladeburnerAccess("setActionLevel");
const action = getBladeburnerActionObject("setActionLevel", type, name);
if (level < 1 || level > action.maxLevel) {
@@ -233,22 +233,22 @@ export function NetscriptBladeburner(
action.level = level;
},
getRank: function (): number {
helper.updateDynamicRam("getRank", getRamCost(player, "bladeburner", "getRank"));
updateRam("getRank");
checkBladeburnerAccess("getRank");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.rank;
},
getSkillPoints: function (): number {
helper.updateDynamicRam("getSkillPoints", getRamCost(player, "bladeburner", "getSkillPoints"));
updateRam("getSkillPoints");
checkBladeburnerAccess("getSkillPoints");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.skillPoints;
},
getSkillLevel: function (_skillName: unknown): number {
updateRam("getSkillLevel");
const skillName = helper.string("getSkillLevel", "skillName", _skillName);
helper.updateDynamicRam("getSkillLevel", getRamCost(player, "bladeburner", "getSkillLevel"));
checkBladeburnerAccess("getSkillLevel");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -259,8 +259,8 @@ export function NetscriptBladeburner(
}
},
getSkillUpgradeCost: function (_skillName: unknown): number {
updateRam("getSkillUpgradeCost");
const skillName = helper.string("getSkillUpgradeCost", "skillName", _skillName);
helper.updateDynamicRam("getSkillUpgradeCost", getRamCost(player, "bladeburner", "getSkillUpgradeCost"));
checkBladeburnerAccess("getSkillUpgradeCost");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -271,8 +271,8 @@ export function NetscriptBladeburner(
}
},
upgradeSkill: function (_skillName: unknown): boolean {
updateRam("upgradeSkill");
const skillName = helper.string("upgradeSkill", "skillName", _skillName);
helper.updateDynamicRam("upgradeSkill", getRamCost(player, "bladeburner", "upgradeSkill"));
checkBladeburnerAccess("upgradeSkill");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -283,9 +283,9 @@ export function NetscriptBladeburner(
}
},
getTeamSize: function (_type: unknown, _name: unknown): number {
updateRam("getTeamSize");
const type = helper.string("getTeamSize", "type", _type);
const name = helper.string("getTeamSize", "name", _name);
helper.updateDynamicRam("getTeamSize", getRamCost(player, "bladeburner", "getTeamSize"));
checkBladeburnerAccess("getTeamSize");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -296,10 +296,10 @@ export function NetscriptBladeburner(
}
},
setTeamSize: function (_type: unknown, _name: unknown, _size: unknown): number {
updateRam("setTeamSize");
const type = helper.string("setTeamSize", "type", _type);
const name = helper.string("setTeamSize", "name", _name);
const size = helper.number("setTeamSize", "size", _size);
helper.updateDynamicRam("setTeamSize", getRamCost(player, "bladeburner", "setTeamSize"));
checkBladeburnerAccess("setTeamSize");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
@@ -310,11 +310,8 @@ export function NetscriptBladeburner(
}
},
getCityEstimatedPopulation: function (_cityName: unknown): number {
updateRam("getCityEstimatedPopulation");
const cityName = helper.string("getCityEstimatedPopulation", "cityName", _cityName);
helper.updateDynamicRam(
"getCityEstimatedPopulation",
getRamCost(player, "bladeburner", "getCityEstimatedPopulation"),
);
checkBladeburnerAccess("getCityEstimatedPopulation");
checkBladeburnerCity("getCityEstimatedPopulation", cityName);
const bladeburner = player.bladeburner;
@@ -322,8 +319,8 @@ export function NetscriptBladeburner(
return bladeburner.cities[cityName].popEst;
},
getCityCommunities: function (_cityName: unknown): number {
updateRam("getCityCommunities");
const cityName = helper.string("getCityCommunities", "cityName", _cityName);
helper.updateDynamicRam("getCityCommunities", getRamCost(player, "bladeburner", "getCityCommunities"));
checkBladeburnerAccess("getCityCommunities");
checkBladeburnerCity("getCityCommunities", cityName);
const bladeburner = player.bladeburner;
@@ -331,8 +328,8 @@ export function NetscriptBladeburner(
return bladeburner.cities[cityName].comms;
},
getCityChaos: function (_cityName: unknown): number {
updateRam("getCityChaos");
const cityName = helper.string("getCityChaos", "cityName", _cityName);
helper.updateDynamicRam("getCityChaos", getRamCost(player, "bladeburner", "getCityChaos"));
checkBladeburnerAccess("getCityChaos");
checkBladeburnerCity("getCityChaos", cityName);
const bladeburner = player.bladeburner;
@@ -340,15 +337,15 @@ export function NetscriptBladeburner(
return bladeburner.cities[cityName].chaos;
},
getCity: function (): string {
helper.updateDynamicRam("getCity", getRamCost(player, "bladeburner", "getCity"));
updateRam("getCity");
checkBladeburnerAccess("getCityChaos");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.city;
},
switchCity: function (_cityName: unknown): boolean {
updateRam("switchCity");
const cityName = helper.string("switchCity", "cityName", _cityName);
helper.updateDynamicRam("switchCity", getRamCost(player, "bladeburner", "switchCity"));
checkBladeburnerAccess("switchCity");
checkBladeburnerCity("switchCity", cityName);
const bladeburner = player.bladeburner;
@@ -357,21 +354,21 @@ export function NetscriptBladeburner(
return true;
},
getStamina: function (): [number, number] {
helper.updateDynamicRam("getStamina", getRamCost(player, "bladeburner", "getStamina"));
updateRam("getStamina");
checkBladeburnerAccess("getStamina");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return [bladeburner.stamina, bladeburner.maxStamina];
},
joinBladeburnerFaction: function (): boolean {
helper.updateDynamicRam("joinBladeburnerFaction", getRamCost(player, "bladeburner", "joinBladeburnerFaction"));
updateRam("joinBladeburnerFaction");
checkBladeburnerAccess("joinBladeburnerFaction", true);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.joinBladeburnerFactionNetscriptFn(workerScript);
},
joinBladeburnerDivision: function (): boolean {
helper.updateDynamicRam("joinBladeburnerDivision", getRamCost(player, "bladeburner", "joinBladeburnerDivision"));
updateRam("joinBladeburnerDivision");
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
if (player.bitNodeN === 8) {
return false;
@@ -399,7 +396,7 @@ export function NetscriptBladeburner(
return false;
},
getBonusTime: function (): number {
helper.updateDynamicRam("getBonusTime", getRamCost(player, "bladeburner", "getBonusTime"));
updateRam("getBonusTime");
checkBladeburnerAccess("getBonusTime");
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
+8 -5
View File
@@ -24,6 +24,9 @@ export function NetscriptCodingContract(
return contract;
};
const updateRam = (funcName: string): void =>
helper.updateDynamicRam(funcName, getRamCost(player, "codingcontract", funcName));
return {
attempt: function (
answer: any,
@@ -31,9 +34,9 @@ export function NetscriptCodingContract(
_hostname: unknown = workerScript.hostname,
{ returnReward }: CodingAttemptOptions = { returnReward: false },
): boolean | string {
updateRam("attempt");
const filename = helper.string("attempt", "filename", _filename);
const hostname = helper.string("attempt", "hostname", _hostname);
helper.updateDynamicRam("attempt", getRamCost(player, "codingcontract", "attempt"));
const contract = getCodingContract("attempt", hostname, filename);
// Convert answer to string. If the answer is a 2D array, then we have to
@@ -83,16 +86,16 @@ export function NetscriptCodingContract(
}
},
getContractType: function (_filename: unknown, _hostname: unknown = workerScript.hostname): string {
updateRam("getContractType");
const filename = helper.string("getContractType", "filename", _filename);
const hostname = helper.string("getContractType", "hostname", _hostname);
helper.updateDynamicRam("getContractType", getRamCost(player, "codingcontract", "getContractType"));
const contract = getCodingContract("getContractType", hostname, filename);
return contract.getType();
},
getData: function (_filename: unknown, _hostname: unknown = workerScript.hostname): any {
updateRam("getData");
const filename = helper.string("getContractType", "filename", _filename);
const hostname = helper.string("getContractType", "hostname", _hostname);
helper.updateDynamicRam("getData", getRamCost(player, "codingcontract", "getData"));
const contract = getCodingContract("getData", hostname, filename);
const data = contract.getData();
if (data.constructor === Array) {
@@ -112,16 +115,16 @@ export function NetscriptCodingContract(
}
},
getDescription: function (_filename: unknown, _hostname: unknown = workerScript.hostname): string {
updateRam("getDescription");
const filename = helper.string("getDescription", "filename", _filename);
const hostname = helper.string("getDescription", "hostname", _hostname);
helper.updateDynamicRam("getDescription", getRamCost(player, "codingcontract", "getDescription"));
const contract = getCodingContract("getDescription", hostname, filename);
return contract.getDescription();
},
getNumTriesRemaining: function (_filename: unknown, _hostname: unknown = workerScript.hostname): number {
updateRam("getNumTriesRemaining");
const filename = helper.string("getNumTriesRemaining", "filename", _filename);
const hostname = helper.string("getNumTriesRemaining", "hostname", _hostname);
helper.updateDynamicRam("getNumTriesRemaining", getRamCost(player, "codingcontract", "getNumTriesRemaining"));
const contract = getCodingContract("getNumTriesRemaining", hostname, filename);
return contract.getMaxNumTries() - contract.tries;
},
+23 -21
View File
@@ -47,10 +47,12 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return task;
};
const updateRam = (funcName: string): void => helper.updateDynamicRam(funcName, getRamCost(player, "gang", funcName));
return {
createGang: function (_faction: unknown): boolean {
updateRam("createGang");
const faction = helper.string("createGang", "faction", _faction);
helper.updateDynamicRam("createGang", getRamCost(player, "gang", "createGang"));
// this list is copied from Faction/ui/Root.tsx
if (!player.canAccessGang() || !GangConstants.Names.includes(faction)) return false;
@@ -62,18 +64,18 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return true;
},
inGang: function (): boolean {
helper.updateDynamicRam("inGang", getRamCost(player, "gang", "inGang"));
updateRam("inGang");
return player.inGang();
},
getMemberNames: function (): string[] {
helper.updateDynamicRam("getMemberNames", getRamCost(player, "gang", "getMemberNames"));
updateRam("getMemberNames");
checkGangApiAccess("getMemberNames");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
return gang.members.map((member) => member.name);
},
getGangInformation: function (): GangGenInfo {
helper.updateDynamicRam("getGangInformation", getRamCost(player, "gang", "getGangInformation"));
updateRam("getGangInformation");
checkGangApiAccess("getGangInformation");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -93,7 +95,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
};
},
getOtherGangInformation: function (): GangOtherInfo {
helper.updateDynamicRam("getOtherGangInformation", getRamCost(player, "gang", "getOtherGangInformation"));
updateRam("getOtherGangInformation");
checkGangApiAccess("getOtherGangInformation");
const cpy: any = {};
for (const gang of Object.keys(AllGangs)) {
@@ -103,8 +105,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return cpy;
},
getMemberInformation: function (_memberName: unknown): GangMemberInfo {
updateRam("getMemberInformation");
const memberName = helper.string("getMemberInformation", "memberName", _memberName);
helper.updateDynamicRam("getMemberInformation", getRamCost(player, "gang", "getMemberInformation"));
checkGangApiAccess("getMemberInformation");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -157,15 +159,15 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
};
},
canRecruitMember: function (): boolean {
helper.updateDynamicRam("canRecruitMember", getRamCost(player, "gang", "canRecruitMember"));
updateRam("canRecruitMember");
checkGangApiAccess("canRecruitMember");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
return gang.canRecruitMember();
},
recruitMember: function (_memberName: unknown): boolean {
updateRam("recruitMember");
const memberName = helper.string("recruitMember", "memberName", _memberName);
helper.updateDynamicRam("recruitMember", getRamCost(player, "gang", "recruitMember"));
checkGangApiAccess("recruitMember");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -179,7 +181,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return recruited;
},
getTaskNames: function (): string[] {
helper.updateDynamicRam("getTaskNames", getRamCost(player, "gang", "getTaskNames"));
updateRam("getTaskNames");
checkGangApiAccess("getTaskNames");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -188,9 +190,9 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return tasks;
},
setMemberTask: function (_memberName: unknown, _taskName: unknown): boolean {
updateRam("setMemberTask");
const memberName = helper.string("setMemberTask", "memberName", _memberName);
const taskName = helper.string("setMemberTask", "taskName", _taskName);
helper.updateDynamicRam("setMemberTask", getRamCost(player, "gang", "setMemberTask"));
checkGangApiAccess("setMemberTask");
const member = getGangMember("setMemberTask", memberName);
const gang = player.gang;
@@ -219,8 +221,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return success;
},
getTaskStats: function (_taskName: unknown): GangTaskStats {
updateRam("getTaskStats");
const taskName = helper.string("getTaskStats", "taskName", _taskName);
helper.updateDynamicRam("getTaskStats", getRamCost(player, "gang", "getTaskStats"));
checkGangApiAccess("getTaskStats");
const task = getGangTask("getTaskStats", taskName);
const copy = Object.assign({}, task);
@@ -228,13 +230,13 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return copy;
},
getEquipmentNames: function (): string[] {
helper.updateDynamicRam("getEquipmentNames", getRamCost(player, "gang", "getEquipmentNames"));
updateRam("getEquipmentNames");
checkGangApiAccess("getEquipmentNames");
return Object.keys(GangMemberUpgrades);
},
getEquipmentCost: function (_equipName: any): number {
updateRam("getEquipmentCost");
const equipName = helper.string("getEquipmentCost", "equipName", _equipName);
helper.updateDynamicRam("getEquipmentCost", getRamCost(player, "gang", "getEquipmentCost"));
checkGangApiAccess("getEquipmentCost");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -243,16 +245,16 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return gang.getUpgradeCost(upg);
},
getEquipmentType: function (_equipName: unknown): string {
updateRam("getEquipmentType");
const equipName = helper.string("getEquipmentType", "equipName", _equipName);
helper.updateDynamicRam("getEquipmentType", getRamCost(player, "gang", "getEquipmentType"));
checkGangApiAccess("getEquipmentType");
const upg = GangMemberUpgrades[equipName];
if (upg == null) return "";
return upg.getType();
},
getEquipmentStats: function (_equipName: unknown): EquipmentStats {
updateRam("getEquipmentStats");
const equipName = helper.string("getEquipmentStats", "equipName", _equipName);
helper.updateDynamicRam("getEquipmentStats", getRamCost(player, "gang", "getEquipmentStats"));
checkGangApiAccess("getEquipmentStats");
const equipment = GangMemberUpgrades[equipName];
if (!equipment) {
@@ -262,9 +264,9 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return Object.assign({}, typecheck) as any;
},
purchaseEquipment: function (_memberName: unknown, _equipName: unknown): boolean {
updateRam("purchaseEquipment");
const memberName = helper.string("purchaseEquipment", "memberName", _memberName);
const equipName = helper.string("purchaseEquipment", "equipName", _equipName);
helper.updateDynamicRam("purchaseEquipment", getRamCost(player, "gang", "purchaseEquipment"));
checkGangApiAccess("purchaseEquipment");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -284,8 +286,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return res;
},
ascendMember: function (_memberName: unknown): GangMemberAscension | undefined {
updateRam("ascendMember");
const memberName = helper.string("ascendMember", "memberName", _memberName);
helper.updateDynamicRam("ascendMember", getRamCost(player, "gang", "ascendMember"));
checkGangApiAccess("ascendMember");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -294,8 +296,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return gang.ascendMember(member, workerScript);
},
getAscensionResult: function (_memberName: unknown): GangMemberAscension | undefined {
updateRam("getAscensionResult");
const memberName = helper.string("getAscensionResult", "memberName", _memberName);
helper.updateDynamicRam("getAscensionResult", getRamCost(player, "gang", "getAscensionResult"));
checkGangApiAccess("getAscensionResult");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -307,8 +309,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
};
},
setTerritoryWarfare: function (_engage: unknown): void {
updateRam("setTerritoryWarfare");
const engage = helper.boolean(_engage);
helper.updateDynamicRam("setTerritoryWarfare", getRamCost(player, "gang", "setTerritoryWarfare"));
checkGangApiAccess("setTerritoryWarfare");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -321,8 +323,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
}
},
getChanceToWinClash: function (_otherGang: unknown): number {
updateRam("getChanceToWinClash");
const otherGang = helper.string("getChanceToWinClash", "otherGang", _otherGang);
helper.updateDynamicRam("getChanceToWinClash", getRamCost(player, "gang", "getChanceToWinClash"));
checkGangApiAccess("getChanceToWinClash");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
@@ -336,7 +338,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return playerPower / (otherPower + playerPower);
},
getBonusTime: function (): number {
helper.updateDynamicRam("getBonusTime", getRamCost(player, "gang", "getBonusTime"));
updateRam("getBonusTime");
checkGangApiAccess("getBonusTime");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
+6 -3
View File
@@ -20,10 +20,13 @@ export function NetscriptGrafting(player: IPlayer, workerScript: WorkerScript, h
}
};
const updateRam = (funcName: string): void =>
helper.updateDynamicRam(funcName, getRamCost(player, "grafting", funcName));
return {
getAugmentationGraftPrice: (_augName: unknown): number => {
updateRam("getAugmentationGraftPrice");
const augName = helper.string("getAugmentationGraftPrice", "augName", _augName);
helper.updateDynamicRam("getAugmentationGraftPrice", getRamCost(player, "grafting", "getAugmentationGraftPrice"));
checkGraftingAPIAccess("getAugmentationGraftPrice");
if (!Augmentations.hasOwnProperty(augName)) {
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftPrice", `Invalid aug: ${augName}`);
@@ -33,8 +36,8 @@ export function NetscriptGrafting(player: IPlayer, workerScript: WorkerScript, h
},
getAugmentationGraftTime: (_augName: string): number => {
updateRam("getAugmentationGraftTime");
const augName = helper.string("getAugmentationGraftTime", "augName", _augName);
helper.updateDynamicRam("getAugmentationGraftTime", getRamCost(player, "grafting", "getAugmentationGraftTime"));
checkGraftingAPIAccess("getAugmentationGraftTime");
if (!Augmentations.hasOwnProperty(augName)) {
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftTime", `Invalid aug: ${augName}`);
@@ -44,9 +47,9 @@ export function NetscriptGrafting(player: IPlayer, workerScript: WorkerScript, h
},
graftAugmentation: (_augName: string, _focus: unknown = true): boolean => {
updateRam("graftAugmentation");
const augName = helper.string("graftAugmentation", "augName", _augName);
const focus = helper.boolean(_focus);
helper.updateDynamicRam("graftAugmentation", getRamCost(player, "grafting", "graftAugmentation"));
checkGraftingAPIAccess("graftAugmentation");
if (player.city !== CityName.NewTokyo) {
throw helper.makeRuntimeErrorMsg(
+51 -48
View File
@@ -96,10 +96,12 @@ export function NetscriptSingularity(
}
}
};
const updateRam = (funcName: string): void => helper.updateDynamicRam(funcName, getRamCost(player, funcName));
return {
getOwnedAugmentations: function (_purchased: unknown = false): string[] {
updateRam("getOwnedAugmentations");
const purchased = helper.boolean(_purchased);
helper.updateDynamicRam("getOwnedAugmentations", getRamCost(player, "getOwnedAugmentations"));
helper.checkSingularityAccess("getOwnedAugmentations");
const res = [];
for (let i = 0; i < player.augmentations.length; ++i) {
@@ -113,52 +115,52 @@ export function NetscriptSingularity(
return res;
},
getAugmentationsFromFaction: function (_facName: unknown): string[] {
updateRam("getAugmentationsFromFaction");
const facName = helper.string("getAugmentationsFromFaction", "facName", _facName);
helper.updateDynamicRam("getAugmentationsFromFaction", getRamCost(player, "getAugmentationsFromFaction"));
helper.checkSingularityAccess("getAugmentationsFromFaction");
const faction = getFaction("getAugmentationsFromFaction", facName);
return getFactionAugmentationsFiltered(player, faction);
},
getAugmentationCost: function (_augName: unknown): [number, number] {
updateRam("getAugmentationCost");
const augName = helper.string("getAugmentationCost", "augName", _augName);
helper.updateDynamicRam("getAugmentationCost", getRamCost(player, "getAugmentationCost"));
helper.checkSingularityAccess("getAugmentationCost");
const aug = getAugmentation("getAugmentationCost", augName);
return [aug.baseRepRequirement, aug.baseCost];
},
getAugmentationPrereq: function (_augName: unknown): string[] {
updateRam("getAugmentationPrereq");
const augName = helper.string("getAugmentationPrereq", "augName", _augName);
helper.updateDynamicRam("getAugmentationPrereq", getRamCost(player, "getAugmentationPrereq"));
helper.checkSingularityAccess("getAugmentationPrereq");
const aug = getAugmentation("getAugmentationPrereq", augName);
return aug.prereqs.slice();
},
getAugmentationPrice: function (_augName: unknown): number {
updateRam("getAugmentationPrice");
const augName = helper.string("getAugmentationPrice", "augName", _augName);
helper.updateDynamicRam("getAugmentationPrice", getRamCost(player, "getAugmentationPrice"));
helper.checkSingularityAccess("getAugmentationPrice");
const aug = getAugmentation("getAugmentationPrice", augName);
return aug.baseCost;
},
getAugmentationRepReq: function (_augName: unknown): number {
updateRam("getAugmentationRepReq");
const augName = helper.string("getAugmentationRepReq", "augName", _augName);
helper.updateDynamicRam("getAugmentationRepReq", getRamCost(player, "getAugmentationRepReq"));
helper.checkSingularityAccess("getAugmentationRepReq");
const aug = getAugmentation("getAugmentationRepReq", augName);
return aug.baseRepRequirement;
},
getAugmentationStats: function (_augName: unknown): AugmentationStats {
updateRam("getAugmentationStats");
const augName = helper.string("getAugmentationStats", "augName", _augName);
helper.updateDynamicRam("getAugmentationStats", getRamCost(player, "getAugmentationStats"));
helper.checkSingularityAccess("getAugmentationStats");
const aug = getAugmentation("getAugmentationStats", augName);
return Object.assign({}, aug.mults);
},
purchaseAugmentation: function (_facName: unknown, _augName: unknown): boolean {
updateRam("purchaseAugmentation");
const facName = helper.string("purchaseAugmentation", "facName", _facName);
const augName = helper.string("purchaseAugmentation", "augName", _augName);
helper.updateDynamicRam("purchaseAugmentation", getRamCost(player, "purchaseAugmentation"));
helper.checkSingularityAccess("purchaseAugmentation");
const fac = getFaction("purchaseAugmentation", facName);
const aug = getAugmentation("purchaseAugmentation", augName);
@@ -204,8 +206,8 @@ export function NetscriptSingularity(
}
},
softReset: function (_cbScript: unknown): void {
updateRam("softReset");
const cbScript = helper.string("softReset", "cbScript", _cbScript);
helper.updateDynamicRam("softReset", getRamCost(player, "softReset"));
helper.checkSingularityAccess("softReset");
workerScript.log("softReset", () => "Soft resetting. This will cause this script to be killed");
@@ -219,8 +221,8 @@ export function NetscriptSingularity(
killWorkerScript(workerScript);
},
installAugmentations: function (_cbScript: unknown = ""): boolean {
updateRam("installAugmentations");
const cbScript = helper.string("installAugmentations", "cbScript", _cbScript);
helper.updateDynamicRam("installAugmentations", getRamCost(player, "installAugmentations"));
helper.checkSingularityAccess("installAugmentations");
if (player.queuedAugmentations.length === 0) {
@@ -243,8 +245,8 @@ export function NetscriptSingularity(
},
goToLocation: function (_locationName: unknown): boolean {
updateRam("goToLocation");
const locationName = helper.string("goToLocation", "locationName", _locationName);
helper.updateDynamicRam("goToLocation", getRamCost(player, "goToLocation"));
helper.checkSingularityAccess("goToLocation");
const location = Object.values(Locations).find((l) => l.name === locationName);
if (!location) {
@@ -260,10 +262,10 @@ export function NetscriptSingularity(
return true;
},
universityCourse: function (_universityName: unknown, _className: unknown, _focus: unknown = true): boolean {
updateRam("universityCourse");
const universityName = helper.string("universityCourse", "universityName", _universityName);
const className = helper.string("universityCourse", "className", _className);
const focus = helper.boolean(_focus);
helper.updateDynamicRam("universityCourse", getRamCost(player, "universityCourse"));
helper.checkSingularityAccess("universityCourse");
const wasFocusing = player.focus;
if (player.isWorking) {
@@ -351,10 +353,10 @@ export function NetscriptSingularity(
},
gymWorkout: function (_gymName: unknown, _stat: unknown, _focus: unknown = true): boolean {
updateRam("gymWorkout");
const gymName = helper.string("gymWorkout", "gymName", _gymName);
const stat = helper.string("gymWorkout", "stat", _stat);
const focus = helper.boolean(_focus);
helper.updateDynamicRam("gymWorkout", getRamCost(player, "gymWorkout"));
helper.checkSingularityAccess("gymWorkout");
const wasFocusing = player.focus;
if (player.isWorking) {
@@ -466,8 +468,8 @@ export function NetscriptSingularity(
},
travelToCity: function (_cityName: unknown): boolean {
updateRam("travelToCity");
const cityName = helper.city("travelToCity", "cityName", _cityName);
helper.updateDynamicRam("travelToCity", getRamCost(player, "travelToCity"));
helper.checkSingularityAccess("travelToCity");
switch (cityName) {
@@ -492,7 +494,7 @@ export function NetscriptSingularity(
},
purchaseTor: function (): boolean {
helper.updateDynamicRam("purchaseTor", getRamCost(player, "purchaseTor"));
updateRam("purchaseTor");
helper.checkSingularityAccess("purchaseTor");
if (player.hasTorRouter()) {
@@ -524,8 +526,8 @@ export function NetscriptSingularity(
return true;
},
purchaseProgram: function (_programName: unknown): boolean {
updateRam("purchaseProgram");
const programName = helper.string("purchaseProgram", "programName", _programName).toLowerCase();
helper.updateDynamicRam("purchaseProgram", getRamCost(player, "purchaseProgram"));
helper.checkSingularityAccess("purchaseProgram");
if (!player.hasTorRouter()) {
@@ -562,13 +564,13 @@ export function NetscriptSingularity(
return true;
},
getCurrentServer: function (): string {
helper.updateDynamicRam("getCurrentServer", getRamCost(player, "getCurrentServer"));
updateRam("getCurrentServer");
helper.checkSingularityAccess("getCurrentServer");
return player.getCurrentServer().hostname;
},
connect: function (_hostname: unknown): boolean {
updateRam("connect");
const hostname = helper.string("purchaseProgram", "hostname", _hostname);
helper.updateDynamicRam("connect", getRamCost(player, "connect"));
helper.checkSingularityAccess("connect");
if (!hostname) {
throw helper.makeRuntimeErrorMsg("connect", `Invalid hostname: '${hostname}'`);
@@ -603,13 +605,13 @@ export function NetscriptSingularity(
return false;
},
manualHack: function (): Promise<number> {
helper.updateDynamicRam("manualHack", getRamCost(player, "manualHack"));
updateRam("manualHack");
helper.checkSingularityAccess("manualHack");
const server = player.getCurrentServer();
return helper.hack(server.hostname, true);
},
installBackdoor: function (): Promise<void> {
helper.updateDynamicRam("installBackdoor", getRamCost(player, "installBackdoor"));
updateRam("installBackdoor");
helper.checkSingularityAccess("installBackdoor");
const baseserver = player.getCurrentServer();
if (!(baseserver instanceof Server)) {
@@ -642,13 +644,13 @@ export function NetscriptSingularity(
});
},
isFocused: function (): boolean {
helper.updateDynamicRam("isFocused", getRamCost(player, "isFocused"));
updateRam("isFocused");
helper.checkSingularityAccess("isFocused");
return player.focus;
},
setFocus: function (_focus: unknown): boolean {
updateRam("setFocus");
const focus = helper.boolean(_focus);
helper.updateDynamicRam("setFocus", getRamCost(player, "setFocus"));
helper.checkSingularityAccess("setFocus");
if (!player.isWorking) {
throw helper.makeRuntimeErrorMsg("setFocus", "Not currently working");
@@ -676,7 +678,7 @@ export function NetscriptSingularity(
return false;
},
getStats: function (): PlayerSkills {
helper.updateDynamicRam("getStats", getRamCost(player, "getStats"));
updateRam("getStats");
helper.checkSingularityAccess("getStats");
workerScript.log("getStats", () => `getStats is deprecated, please use getplayer`);
@@ -691,7 +693,7 @@ export function NetscriptSingularity(
};
},
getCharacterInformation: function (): CharacterInfo {
helper.updateDynamicRam("getCharacterInformation", getRamCost(player, "getCharacterInformation"));
updateRam("getCharacterInformation");
helper.checkSingularityAccess("getCharacterInformation");
workerScript.log("getCharacterInformation", () => `getCharacterInformation is deprecated, please use getplayer`);
@@ -741,7 +743,7 @@ export function NetscriptSingularity(
};
},
hospitalize: function (): void {
helper.updateDynamicRam("hospitalize", getRamCost(player, "hospitalize"));
updateRam("hospitalize");
helper.checkSingularityAccess("hospitalize");
if (player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse) {
workerScript.log("hospitalize", () => "Cannot go to the hospital because the player is busy.");
@@ -750,12 +752,12 @@ export function NetscriptSingularity(
player.hospitalize();
},
isBusy: function (): boolean {
helper.updateDynamicRam("isBusy", getRamCost(player, "isBusy"));
updateRam("isBusy");
helper.checkSingularityAccess("isBusy");
return player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse;
},
stopAction: function (): boolean {
helper.updateDynamicRam("stopAction", getRamCost(player, "stopAction"));
updateRam("stopAction");
helper.checkSingularityAccess("stopAction");
if (player.isWorking) {
if (player.focus) {
@@ -769,7 +771,7 @@ export function NetscriptSingularity(
return false;
},
upgradeHomeCores: function (): boolean {
helper.updateDynamicRam("upgradeHomeCores", getRamCost(player, "upgradeHomeCores"));
updateRam("upgradeHomeCores");
helper.checkSingularityAccess("upgradeHomeCores");
// Check if we're at max cores
@@ -799,13 +801,13 @@ export function NetscriptSingularity(
return true;
},
getUpgradeHomeCoresCost: function (): number {
helper.updateDynamicRam("getUpgradeHomeCoresCost", getRamCost(player, "getUpgradeHomeCoresCost"));
updateRam("getUpgradeHomeCoresCost");
helper.checkSingularityAccess("getUpgradeHomeCoresCost");
return player.getUpgradeHomeCoresCost();
},
upgradeHomeRam: function (): boolean {
helper.updateDynamicRam("upgradeHomeRam", getRamCost(player, "upgradeHomeRam"));
updateRam("upgradeHomeRam");
helper.checkSingularityAccess("upgradeHomeRam");
// Check if we're at max RAM
@@ -838,15 +840,15 @@ export function NetscriptSingularity(
return true;
},
getUpgradeHomeRamCost: function (): number {
helper.updateDynamicRam("getUpgradeHomeRamCost", getRamCost(player, "getUpgradeHomeRamCost"));
updateRam("getUpgradeHomeRamCost");
helper.checkSingularityAccess("getUpgradeHomeRamCost");
return player.getUpgradeHomeRamCost();
},
workForCompany: function (_companyName: unknown, _focus: unknown = true): boolean {
updateRam("workForCompany");
let companyName = helper.string("workForCompany", "companyName", _companyName);
const focus = helper.boolean(_focus);
helper.updateDynamicRam("workForCompany", getRamCost(player, "workForCompany"));
helper.checkSingularityAccess("workForCompany");
// Sanitize input
@@ -900,9 +902,9 @@ export function NetscriptSingularity(
return true;
},
applyToCompany: function (_companyName: unknown, _field: unknown): boolean {
updateRam("applyToCompany");
const companyName = helper.string("applyToCompany", "companyName", _companyName);
const field = helper.string("applyToCompany", "field", _field);
helper.updateDynamicRam("applyToCompany", getRamCost(player, "applyToCompany"));
helper.checkSingularityAccess("applyToCompany");
getCompany("applyToCompany", companyName);
@@ -972,22 +974,22 @@ export function NetscriptSingularity(
return res;
},
getCompanyRep: function (_companyName: unknown): number {
updateRam("getCompanyRep");
const companyName = helper.string("getCompanyRep", "companyName", _companyName);
helper.updateDynamicRam("getCompanyRep", getRamCost(player, "getCompanyRep"));
helper.checkSingularityAccess("getCompanyRep");
const company = getCompany("getCompanyRep", companyName);
return company.playerReputation;
},
getCompanyFavor: function (_companyName: unknown): number {
updateRam("getCompanyFavor");
const companyName = helper.string("getCompanyFavor", "companyName", _companyName);
helper.updateDynamicRam("getCompanyFavor", getRamCost(player, "getCompanyFavor"));
helper.checkSingularityAccess("getCompanyFavor");
const company = getCompany("getCompanyFavor", companyName);
return company.favor;
},
getCompanyFavorGain: function (_companyName: unknown): number {
updateRam("getCompanyFavorGain");
const companyName = helper.string("getCompanyFavorGain", "companyName", _companyName);
helper.updateDynamicRam("getCompanyFavorGain", getRamCost(player, "getCompanyFavorGain"));
helper.checkSingularityAccess("getCompanyFavorGain");
const company = getCompany("getCompanyFavorGain", companyName);
return company.getFavorGain();
@@ -999,8 +1001,8 @@ export function NetscriptSingularity(
return player.factionInvitations.slice();
},
joinFaction: function (_facName: unknown): boolean {
updateRam("joinFaction");
const facName = helper.string("joinFaction", "facName", _facName);
helper.updateDynamicRam("joinFaction", getRamCost(player, "joinFaction"));
helper.checkSingularityAccess("joinFaction");
getFaction("joinFaction", facName);
@@ -1023,10 +1025,10 @@ export function NetscriptSingularity(
return true;
},
workForFaction: function (_facName: unknown, _type: unknown, _focus: unknown = true): boolean {
updateRam("workForFaction");
const facName = helper.string("workForFaction", "facName", _facName);
const type = helper.string("workForFaction", "type", _type);
const focus = helper.boolean(_focus);
helper.updateDynamicRam("workForFaction", getRamCost(player, "workForFaction"));
helper.checkSingularityAccess("workForFaction");
getFaction("workForFaction", facName);
@@ -1104,34 +1106,35 @@ export function NetscriptSingularity(
return true;
default:
workerScript.log("workForFaction", () => `Invalid work type: '${type}`);
return false;
}
return true;
},
getFactionRep: function (_facName: unknown): number {
updateRam("getFactionRep");
const facName = helper.string("getFactionRep", "facName", _facName);
helper.updateDynamicRam("getFactionRep", getRamCost(player, "getFactionRep"));
helper.checkSingularityAccess("getFactionRep");
const faction = getFaction("getFactionRep", facName);
return faction.playerReputation;
},
getFactionFavor: function (_facName: unknown): number {
updateRam("getFactionFavor");
const facName = helper.string("getFactionRep", "facName", _facName);
helper.updateDynamicRam("getFactionFavor", getRamCost(player, "getFactionFavor"));
helper.checkSingularityAccess("getFactionFavor");
const faction = getFaction("getFactionFavor", facName);
return faction.favor;
},
getFactionFavorGain: function (_facName: unknown): number {
updateRam("getFactionFavorGain");
const facName = helper.string("getFactionFavorGain", "facName", _facName);
helper.updateDynamicRam("getFactionFavorGain", getRamCost(player, "getFactionFavorGain"));
helper.checkSingularityAccess("getFactionFavorGain");
const faction = getFaction("getFactionFavorGain", facName);
return faction.getFavorGain();
},
donateToFaction: function (_facName: unknown, _amt: unknown): boolean {
updateRam("donateToFaction");
const facName = helper.string("donateToFaction", "facName", _facName);
const amt = helper.number("donateToFaction", "amt", _amt);
helper.updateDynamicRam("donateToFaction", getRamCost(player, "donateToFaction"));
helper.checkSingularityAccess("donateToFaction");
const faction = getFaction("donateToFaction", facName);
if (!player.factions.includes(faction.name)) {
@@ -1178,9 +1181,9 @@ export function NetscriptSingularity(
return true;
},
createProgram: function (_programName: unknown, _focus: unknown = true): boolean {
updateRam("createProgram");
const programName = helper.string("createProgram", "programName", _programName).toLowerCase();
const focus = helper.boolean(_focus);
helper.updateDynamicRam("createProgram", getRamCost(player, "createProgram"));
helper.checkSingularityAccess("createProgram");
const wasFocusing = player.focus;
@@ -1227,8 +1230,8 @@ export function NetscriptSingularity(
return true;
},
commitCrime: function (_crimeRoughName: unknown): number {
updateRam("commitCrime");
const crimeRoughName = helper.string("commitCrime", "crimeRoughName", _crimeRoughName);
helper.updateDynamicRam("commitCrime", getRamCost(player, "commitCrime"));
helper.checkSingularityAccess("commitCrime");
if (player.isWorking) {
@@ -1248,8 +1251,8 @@ export function NetscriptSingularity(
return crime.commit(Router, player, 1, workerScript);
},
getCrimeChance: function (_crimeRoughName: unknown): number {
updateRam("getCrimeChance");
const crimeRoughName = helper.string("getCrimeChance", "crimeRoughName", _crimeRoughName);
helper.updateDynamicRam("getCrimeChance", getRamCost(player, "getCrimeChance"));
helper.checkSingularityAccess("getCrimeChance");
const crime = findCrime(crimeRoughName.toLowerCase());
@@ -1260,8 +1263,8 @@ export function NetscriptSingularity(
return crime.successRate(player);
},
getCrimeStats: function (_crimeRoughName: unknown): CrimeStats {
updateRam("getCrimeStats");
const crimeRoughName = helper.string("getCrimeStats", "crimeRoughName", _crimeRoughName);
helper.updateDynamicRam("getCrimeStats", getRamCost(player, "getCrimeStats"));
helper.checkSingularityAccess("getCrimeStats");
const crime = findCrime(crimeRoughName.toLowerCase());
@@ -1272,7 +1275,7 @@ export function NetscriptSingularity(
return Object.assign({}, crime);
},
getDarkwebPrograms: function (): string[] {
helper.updateDynamicRam("getDarkwebPrograms", getRamCost(player, "getDarkwebPrograms"));
updateRam("getDarkwebPrograms");
helper.checkSingularityAccess("getDarkwebPrograms");
// If we don't have Tor, log it and return [] (empty list)
@@ -1283,8 +1286,8 @@ export function NetscriptSingularity(
return Object.values(DarkWebItems).map((p) => p.program);
},
getDarkwebProgramCost: function (_programName: unknown): number {
updateRam("getDarkwebProgramCost");
const programName = helper.string("getDarkwebProgramCost", "programName", _programName).toLowerCase();
helper.updateDynamicRam("getDarkwebProgramCost", getRamCost(player, "getDarkwebProgramCost"));
helper.checkSingularityAccess("getDarkwebProgramCost");
// If we don't have Tor, log it and return -1
+30 -16
View File
@@ -50,30 +50,33 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
};
};
const updateRam = (funcName: string): void =>
helper.updateDynamicRam(funcName, getRamCost(player, "sleeve", funcName));
return {
getNumSleeves: function (): number {
helper.updateDynamicRam("getNumSleeves", getRamCost(player, "sleeve", "getNumSleeves"));
updateRam("getNumSleeves");
checkSleeveAPIAccess("getNumSleeves");
return player.sleeves.length;
},
setToShockRecovery: function (_sleeveNumber: unknown): boolean {
updateRam("setToShockRecovery");
const sleeveNumber = helper.number("setToShockRecovery", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("setToShockRecovery", getRamCost(player, "sleeve", "setToShockRecovery"));
checkSleeveAPIAccess("setToShockRecovery");
checkSleeveNumber("setToShockRecovery", sleeveNumber);
return player.sleeves[sleeveNumber].shockRecovery(player);
},
setToSynchronize: function (_sleeveNumber: unknown): boolean {
updateRam("setToSynchronize");
const sleeveNumber = helper.number("setToSynchronize", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("setToSynchronize", getRamCost(player, "sleeve", "setToSynchronize"));
checkSleeveAPIAccess("setToSynchronize");
checkSleeveNumber("setToSynchronize", sleeveNumber);
return player.sleeves[sleeveNumber].synchronize(player);
},
setToCommitCrime: function (_sleeveNumber: unknown, _crimeRoughName: unknown): boolean {
updateRam("setToCommitCrime");
const sleeveNumber = helper.number("setToCommitCrime", "sleeveNumber", _sleeveNumber);
const crimeRoughName = helper.string("setToCommitCrime", "crimeName", _crimeRoughName);
helper.updateDynamicRam("setToCommitCrime", getRamCost(player, "sleeve", "setToCommitCrime"));
checkSleeveAPIAccess("setToCommitCrime");
checkSleeveNumber("setToCommitCrime", sleeveNumber);
const crime = findCrime(crimeRoughName);
@@ -83,26 +86,26 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
return player.sleeves[sleeveNumber].commitCrime(player, crime.name);
},
setToUniversityCourse: function (_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean {
updateRam("setToUniversityCourse");
const sleeveNumber = helper.number("setToUniversityCourse", "sleeveNumber", _sleeveNumber);
const universityName = helper.string("setToUniversityCourse", "universityName", _universityName);
const className = helper.string("setToUniversityCourse", "className", _className);
helper.updateDynamicRam("setToUniversityCourse", getRamCost(player, "sleeve", "setToUniversityCourse"));
checkSleeveAPIAccess("setToUniversityCourse");
checkSleeveNumber("setToUniversityCourse", sleeveNumber);
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
},
travel: function (_sleeveNumber: unknown, _cityName: unknown): boolean {
updateRam("travel");
const sleeveNumber = helper.number("travel", "sleeveNumber", _sleeveNumber);
const cityName = helper.string("setToUniversityCourse", "cityName", _cityName);
helper.updateDynamicRam("travel", getRamCost(player, "sleeve", "travel"));
checkSleeveAPIAccess("travel");
checkSleeveNumber("travel", sleeveNumber);
return player.sleeves[sleeveNumber].travel(player, cityName as CityName);
},
setToCompanyWork: function (_sleeveNumber: unknown, acompanyName: unknown): boolean {
updateRam("setToCompanyWork");
const sleeveNumber = helper.number("setToCompanyWork", "sleeveNumber", _sleeveNumber);
const companyName = helper.string("setToUniversityCourse", "companyName", acompanyName);
helper.updateDynamicRam("setToCompanyWork", getRamCost(player, "sleeve", "setToCompanyWork"));
checkSleeveAPIAccess("setToCompanyWork");
checkSleeveNumber("setToCompanyWork", sleeveNumber);
@@ -122,11 +125,15 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
return player.sleeves[sleeveNumber].workForCompany(player, companyName);
},
setToFactionWork: function (_sleeveNumber: unknown, _factionName: unknown, _workType: unknown): boolean {
setToFactionWork: function (
_sleeveNumber: unknown,
_factionName: unknown,
_workType: unknown,
): boolean | undefined {
updateRam("setToFactionWork");
const sleeveNumber = helper.number("setToFactionWork", "sleeveNumber", _sleeveNumber);
const factionName = helper.string("setToUniversityCourse", "factionName", _factionName);
const workType = helper.string("setToUniversityCourse", "workType", _workType);
helper.updateDynamicRam("setToFactionWork", getRamCost(player, "sleeve", "setToFactionWork"));
checkSleeveAPIAccess("setToFactionWork");
checkSleeveNumber("setToFactionWork", sleeveNumber);
@@ -144,28 +151,35 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
}
}
if (player.gang && player.gang.facName == factionName) {
throw helper.makeRuntimeErrorMsg(
"sleeve.setToFactionWork",
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
);
}
return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType);
},
setToGymWorkout: function (_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean {
updateRam("setToGymWorkout");
const sleeveNumber = helper.number("setToGymWorkout", "sleeveNumber", _sleeveNumber);
const gymName = helper.string("setToUniversityCourse", "gymName", _gymName);
const stat = helper.string("setToUniversityCourse", "stat", _stat);
helper.updateDynamicRam("setToGymWorkout", getRamCost(player, "sleeve", "setToGymWorkout"));
checkSleeveAPIAccess("setToGymWorkout");
checkSleeveNumber("setToGymWorkout", sleeveNumber);
return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat);
},
getSleeveStats: function (_sleeveNumber: unknown): SleeveSkills {
updateRam("getSleeveStats");
const sleeveNumber = helper.number("getSleeveStats", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("getSleeveStats", getRamCost(player, "sleeve", "getSleeveStats"));
checkSleeveAPIAccess("getSleeveStats");
checkSleeveNumber("getSleeveStats", sleeveNumber);
return getSleeveStats(sleeveNumber);
},
getTask: function (_sleeveNumber: unknown): SleeveTask {
updateRam("getTask");
const sleeveNumber = helper.number("getTask", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("getTask", getRamCost(player, "sleeve", "getTask"));
checkSleeveAPIAccess("getTask");
checkSleeveNumber("getTask", sleeveNumber);
@@ -179,8 +193,8 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
};
},
getInformation: function (_sleeveNumber: unknown): SleeveInformation {
updateRam("getInformation");
const sleeveNumber = helper.number("getInformation", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("getInformation", getRamCost(player, "sleeve", "getInformation"));
checkSleeveAPIAccess("getInformation");
checkSleeveNumber("getInformation", sleeveNumber);
@@ -245,8 +259,8 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
};
},
getSleeveAugmentations: function (_sleeveNumber: unknown): string[] {
updateRam("getSleeveAugmentations");
const sleeveNumber = helper.number("getSleeveAugmentations", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("getSleeveAugmentations", getRamCost(player, "sleeve", "getSleeveAugmentations"));
checkSleeveAPIAccess("getSleeveAugmentations");
checkSleeveNumber("getSleeveAugmentations", sleeveNumber);
@@ -257,8 +271,8 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
return augs;
},
getSleevePurchasableAugs: function (_sleeveNumber: unknown): AugmentPair[] {
updateRam("getSleevePurchasableAugs");
const sleeveNumber = helper.number("getSleevePurchasableAugs", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("getSleevePurchasableAugs", getRamCost(player, "sleeve", "getSleevePurchasableAugs"));
checkSleeveAPIAccess("getSleevePurchasableAugs");
checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber);
@@ -275,9 +289,9 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
return augs;
},
purchaseSleeveAug: function (_sleeveNumber: unknown, _augName: unknown): boolean {
updateRam("purchaseSleeveAug");
const sleeveNumber = helper.number("purchaseSleeveAug", "sleeveNumber", _sleeveNumber);
const augName = helper.string("purchaseSleeveAug", "augName", _augName);
helper.updateDynamicRam("purchaseSleeveAug", getRamCost(player, "sleeve", "purchaseSleeveAug"));
checkSleeveAPIAccess("purchaseSleeveAug");
checkSleeveNumber("purchaseSleeveAug", sleeveNumber);
+13 -11
View File
@@ -21,22 +21,24 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
}
}
const updateRam = (funcName: string): void =>
helper.updateDynamicRam(funcName, getRamCost(player, "stanek", funcName));
return {
giftWidth: function (): number {
helper.updateDynamicRam("giftWidth", getRamCost(player, "stanek", "giftWidth"));
updateRam("giftWidth");
checkStanekAPIAccess("giftWidth");
return staneksGift.width();
},
giftHeight: function (): number {
helper.updateDynamicRam("giftHeight", getRamCost(player, "stanek", "giftHeight"));
updateRam("giftHeight");
checkStanekAPIAccess("giftHeight");
return staneksGift.height();
},
chargeFragment: function (_rootX: unknown, _rootY: unknown): Promise<void> {
updateRam("chargeFragment");
const rootX = helper.number("stanek.chargeFragment", "rootX", _rootX);
const rootY = helper.number("stanek.chargeFragment", "rootY", _rootY);
helper.updateDynamicRam("chargeFragment", getRamCost(player, "stanek", "chargeFragment"));
checkStanekAPIAccess("chargeFragment");
const fragment = staneksGift.findFragment(rootX, rootY);
if (!fragment)
@@ -49,13 +51,13 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
});
},
fragmentDefinitions: function (): IFragment[] {
helper.updateDynamicRam("fragmentDefinitions", getRamCost(player, "stanek", "fragmentDefinitions"));
updateRam("fragmentDefinitions");
checkStanekAPIAccess("fragmentDefinitions");
workerScript.log("stanek.fragmentDefinitions", () => `Returned ${Fragments.length} fragments`);
return Fragments.map((f) => f.copy());
},
activeFragments: function (): IActiveFragment[] {
helper.updateDynamicRam("activeFragments", getRamCost(player, "stanek", "activeFragments"));
updateRam("activeFragments");
checkStanekAPIAccess("activeFragments");
workerScript.log("stanek.activeFragments", () => `Returned ${staneksGift.fragments.length} fragments`);
return staneksGift.fragments.map((af) => {
@@ -63,17 +65,17 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
});
},
clearGift: function (): void {
helper.updateDynamicRam("clearGift", getRamCost(player, "stanek", "clearGift"));
updateRam("clearGift");
checkStanekAPIAccess("clearGift");
workerScript.log("stanek.clearGift", () => `Cleared Stanek's Gift.`);
staneksGift.clear();
},
canPlaceFragment: function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean {
updateRam("canPlaceFragment");
const rootX = helper.number("stanek.canPlaceFragment", "rootX", _rootX);
const rootY = helper.number("stanek.canPlaceFragment", "rootY", _rootY);
const rotation = helper.number("stanek.canPlaceFragment", "rotation", _rotation);
const fragmentId = helper.number("stanek.canPlaceFragment", "fragmentId", _fragmentId);
helper.updateDynamicRam("canPlaceFragment", getRamCost(player, "stanek", "canPlaceFragment"));
checkStanekAPIAccess("canPlaceFragment");
const fragment = FragmentById(fragmentId);
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.canPlaceFragment", `Invalid fragment id: ${fragmentId}`);
@@ -81,29 +83,29 @@ export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, hel
return can;
},
placeFragment: function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean {
updateRam("placeFragment");
const rootX = helper.number("stanek.placeFragment", "rootX", _rootX);
const rootY = helper.number("stanek.placeFragment", "rootY", _rootY);
const rotation = helper.number("stanek.placeFragment", "rotation", _rotation);
const fragmentId = helper.number("stanek.placeFragment", "fragmentId", _fragmentId);
helper.updateDynamicRam("placeFragment", getRamCost(player, "stanek", "placeFragment"));
checkStanekAPIAccess("placeFragment");
const fragment = FragmentById(fragmentId);
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.placeFragment", `Invalid fragment id: ${fragmentId}`);
return staneksGift.place(rootX, rootY, rotation, fragment);
},
getFragment: function (_rootX: unknown, _rootY: unknown): IActiveFragment | undefined {
updateRam("getFragment");
const rootX = helper.number("stanek.getFragment", "rootX", _rootX);
const rootY = helper.number("stanek.getFragment", "rootY", _rootY);
helper.updateDynamicRam("getFragment", getRamCost(player, "stanek", "getFragment"));
checkStanekAPIAccess("getFragment");
const fragment = staneksGift.findFragment(rootX, rootY);
if (fragment !== undefined) return fragment.copy();
return undefined;
},
removeFragment: function (_rootX: unknown, _rootY: unknown): boolean {
updateRam("removeFragment");
const rootX = helper.number("stanek.removeFragment", "rootX", _rootX);
const rootY = helper.number("stanek.removeFragment", "rootY", _rootY);
helper.updateDynamicRam("removeFragment", getRamCost(player, "stanek", "removeFragment"));
checkStanekAPIAccess("removeFragment");
return staneksGift.delete(rootX, rootY);
},
+25 -21
View File
@@ -38,14 +38,18 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return stock;
};
const updateRam = (funcName: string): void =>
helper.updateDynamicRam(funcName, getRamCost(player, "stock", funcName));
return {
getSymbols: function (): string[] {
helper.updateDynamicRam("getSymbols", getRamCost(player, "stock", "getSymbols"));
updateRam("getSymbols");
checkTixApiAccess("getSymbols");
return Object.values(StockSymbols);
},
getPrice: function (_symbol: unknown): number {
helper.updateDynamicRam("getPrice", getRamCost(player, "stock", "getPrice"));
updateRam("getPrice");
const symbol = helper.string("getPrice", "symbol", _symbol);
checkTixApiAccess("getPrice");
const stock = getStockFromSymbol(symbol, "getPrice");
@@ -53,7 +57,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return stock.price;
},
getAskPrice: function (_symbol: unknown): number {
helper.updateDynamicRam("getAskPrice", getRamCost(player, "stock", "getAskPrice"));
updateRam("getAskPrice");
const symbol = helper.string("getAskPrice", "symbol", _symbol);
checkTixApiAccess("getAskPrice");
const stock = getStockFromSymbol(symbol, "getAskPrice");
@@ -61,7 +65,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return stock.getAskPrice();
},
getBidPrice: function (_symbol: unknown): number {
helper.updateDynamicRam("getBidPrice", getRamCost(player, "stock", "getBidPrice"));
updateRam("getBidPrice");
const symbol = helper.string("getBidPrice", "symbol", _symbol);
checkTixApiAccess("getBidPrice");
const stock = getStockFromSymbol(symbol, "getBidPrice");
@@ -69,7 +73,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return stock.getBidPrice();
},
getPosition: function (_symbol: unknown): [number, number, number, number] {
helper.updateDynamicRam("getPosition", getRamCost(player, "stock", "getPosition"));
updateRam("getPosition");
const symbol = helper.string("getPosition", "symbol", _symbol);
checkTixApiAccess("getPosition");
const stock = SymbolToStockMap[symbol];
@@ -79,7 +83,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
},
getMaxShares: function (_symbol: unknown): number {
helper.updateDynamicRam("getMaxShares", getRamCost(player, "stock", "getMaxShares"));
updateRam("getMaxShares");
const symbol = helper.string("getMaxShares", "symbol", _symbol);
checkTixApiAccess("getMaxShares");
const stock = getStockFromSymbol(symbol, "getMaxShares");
@@ -87,7 +91,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return stock.maxShares;
},
getPurchaseCost: function (_symbol: unknown, _shares: unknown, _posType: unknown): number {
helper.updateDynamicRam("getPurchaseCost", getRamCost(player, "stock", "getPurchaseCost"));
updateRam("getPurchaseCost");
const symbol = helper.string("getPurchaseCost", "symbol", _symbol);
let shares = helper.number("getPurchaseCost", "shares", _shares);
const posType = helper.string("getPurchaseCost", "posType", _posType);
@@ -113,7 +117,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return res;
},
getSaleGain: function (_symbol: unknown, _shares: unknown, _posType: unknown): number {
helper.updateDynamicRam("getSaleGain", getRamCost(player, "stock", "getSaleGain"));
updateRam("getSaleGain");
const symbol = helper.string("getSaleGain", "symbol", _symbol);
let shares = helper.number("getSaleGain", "shares", _shares);
const posType = helper.string("getSaleGain", "posType", _posType);
@@ -139,7 +143,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return res;
},
buy: function (_symbol: unknown, _shares: unknown): number {
helper.updateDynamicRam("buy", getRamCost(player, "stock", "buy"));
updateRam("buy");
const symbol = helper.string("buy", "symbol", _symbol);
const shares = helper.number("buy", "shares", _shares);
checkTixApiAccess("buy");
@@ -148,7 +152,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return res ? stock.getAskPrice() : 0;
},
sell: function (_symbol: unknown, _shares: unknown): number {
helper.updateDynamicRam("sell", getRamCost(player, "stock", "sell"));
updateRam("sell");
const symbol = helper.string("sell", "symbol", _symbol);
const shares = helper.number("sell", "shares", _shares);
checkTixApiAccess("sell");
@@ -158,7 +162,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return res ? stock.getBidPrice() : 0;
},
short: function (_symbol: unknown, _shares: unknown): number {
helper.updateDynamicRam("short", getRamCost(player, "stock", "short"));
updateRam("short");
const symbol = helper.string("short", "symbol", _symbol);
const shares = helper.number("short", "shares", _shares);
checkTixApiAccess("short");
@@ -176,7 +180,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return res ? stock.getBidPrice() : 0;
},
sellShort: function (_symbol: unknown, _shares: unknown): number {
helper.updateDynamicRam("sellShort", getRamCost(player, "stock", "sellShort"));
updateRam("sellShort");
const symbol = helper.string("sellShort", "symbol", _symbol);
const shares = helper.number("sellShort", "shares", _shares);
checkTixApiAccess("sellShort");
@@ -194,7 +198,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return res ? stock.getAskPrice() : 0;
},
placeOrder: function (_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean {
helper.updateDynamicRam("placeOrder", getRamCost(player, "stock", "placeOrder"));
updateRam("placeOrder");
const symbol = helper.string("placeOrder", "symbol", _symbol);
const shares = helper.number("placeOrder", "shares", _shares);
const price = helper.number("placeOrder", "price", _price);
@@ -244,7 +248,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
_type: unknown,
_pos: unknown,
): boolean {
helper.updateDynamicRam("cancelOrder", getRamCost(player, "stock", "cancelOrder"));
updateRam("cancelOrder");
const symbol = helper.string("cancelOrder", "symbol", _symbol);
const shares = helper.number("cancelOrder", "shares", _shares);
const price = helper.number("cancelOrder", "price", _price);
@@ -299,7 +303,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return cancelOrder(params, workerScript);
},
getOrders: function (): any {
helper.updateDynamicRam("getOrders", getRamCost(player, "stock", "getOrders"));
updateRam("getOrders");
checkTixApiAccess("getOrders");
if (player.bitNodeN !== 8) {
if (player.sourceFileLvl(8) <= 2) {
@@ -331,7 +335,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return orders;
},
getVolatility: function (_symbol: unknown): number {
helper.updateDynamicRam("getVolatility", getRamCost(player, "stock", "getVolatility"));
updateRam("getVolatility");
const symbol = helper.string("getVolatility", "symbol", _symbol);
if (!player.has4SDataTixApi) {
throw helper.makeRuntimeErrorMsg("getVolatility", "You don't have 4S Market Data TIX API Access!");
@@ -341,7 +345,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return stock.mv / 100; // Convert from percentage to decimal
},
getForecast: function (_symbol: unknown): number {
helper.updateDynamicRam("getForecast", getRamCost(player, "stock", "getForecast"));
updateRam("getForecast");
const symbol = helper.string("getForecast", "symbol", _symbol);
if (!player.has4SDataTixApi) {
throw helper.makeRuntimeErrorMsg("getForecast", "You don't have 4S Market Data TIX API Access!");
@@ -353,7 +357,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return forecast / 100; // Convert from percentage to decimal
},
purchase4SMarketData: function (): boolean {
helper.updateDynamicRam("purchase4SMarketData", getRamCost(player, "stock", "purchase4SMarketData"));
updateRam("purchase4SMarketData");
checkTixApiAccess("purchase4SMarketData");
if (player.has4SData) {
@@ -372,7 +376,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return true;
},
purchase4SMarketDataTixApi: function (): boolean {
helper.updateDynamicRam("purchase4SMarketDataTixApi", getRamCost(player, "stock", "purchase4SMarketDataTixApi"));
updateRam("purchase4SMarketDataTixApi");
checkTixApiAccess("purchase4SMarketDataTixApi");
if (player.has4SDataTixApi) {
@@ -394,7 +398,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return true;
},
purchaseWseAccount: function (): boolean {
helper.updateDynamicRam("PurchaseWseAccount", getRamCost(player, "stock", "purchaseWseAccount"));
updateRam("PurchaseWseAccount");
if (player.hasWseAccount) {
workerScript.log("stock.purchaseWseAccount", () => "Already purchased WSE Account");
@@ -412,7 +416,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return true;
},
purchaseTixApi: function (): boolean {
helper.updateDynamicRam("purchaseTixApi", getRamCost(player, "stock", "purchaseTixApi"));
updateRam("purchaseTixApi");
if (player.hasTixApiAccess) {
workerScript.log("stock.purchaseTixApi", () => "Already purchased TIX API");
+27 -19
View File
@@ -2,7 +2,12 @@ import { INetscriptHelper } from "./INetscriptHelper";
import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer";
import { getRamCost } from "../Netscript/RamCostGenerator";
import { GameInfo, IStyleSettings, UserInterface as IUserInterface, UserInterfaceTheme } from "../ScriptEditor/NetscriptDefinitions";
import {
GameInfo,
IStyleSettings,
UserInterface as IUserInterface,
UserInterfaceTheme,
} from "../ScriptEditor/NetscriptDefinitions";
import { Settings } from "../Settings/Settings";
import { ThemeEvents } from "../Themes/ui/Theme";
import { defaultTheme } from "../Themes/Themes";
@@ -15,27 +20,28 @@ export function NetscriptUserInterface(
workerScript: WorkerScript,
helper: INetscriptHelper,
): IUserInterface {
const updateRam = (funcName: string): void => helper.updateDynamicRam(funcName, getRamCost(player, "ui", funcName));
return {
getTheme: function (): UserInterfaceTheme {
helper.updateDynamicRam("getTheme", getRamCost(player, "ui", "getTheme"));
updateRam("getTheme");
return { ...Settings.theme };
},
getStyles: function (): IStyleSettings {
helper.updateDynamicRam("getStyles", getRamCost(player, "ui", "getStyles"));
updateRam("getStyles");
return { ...Settings.styles };
},
setTheme: function (newTheme: UserInterfaceTheme): void {
helper.updateDynamicRam("setTheme", getRamCost(player, "ui", "setTheme"));
updateRam("setTheme");
const hex = /^(#)((?:[A-Fa-f0-9]{2}){3,4}|(?:[A-Fa-f0-9]{3}))$/;
const currentTheme = {...Settings.theme}
const currentTheme = { ...Settings.theme };
const errors: string[] = [];
for (const key of Object.keys(newTheme)) {
if (!currentTheme[key]) {
// Invalid key
errors.push(`Invalid key "${key}"`);
} else if (!hex.test(newTheme[key] ?? '')) {
} else if (!hex.test(newTheme[key] ?? "")) {
errors.push(`Invalid color "${key}": ${newTheme[key]}`);
} else {
currentTheme[key] = newTheme[key];
@@ -47,17 +53,17 @@ export function NetscriptUserInterface(
ThemeEvents.emit();
workerScript.log("ui.setTheme", () => `Successfully set theme`);
} else {
workerScript.log("ui.setTheme", () => `Failed to set theme. Errors: ${errors.join(', ')}`);
workerScript.log("ui.setTheme", () => `Failed to set theme. Errors: ${errors.join(", ")}`);
}
},
setStyles: function (newStyles: IStyleSettings): void {
helper.updateDynamicRam("setStyles", getRamCost(player, "ui", "setStyles"));
updateRam("setStyles");
const currentStyles = {...Settings.styles}
const currentStyles = { ...Settings.styles };
const errors: string[] = [];
for (const key of Object.keys(newStyles)) {
if (!((currentStyles as any)[key])) {
if (!(currentStyles as any)[key]) {
// Invalid key
errors.push(`Invalid key "${key}"`);
} else {
@@ -70,35 +76,37 @@ export function NetscriptUserInterface(
ThemeEvents.emit();
workerScript.log("ui.setStyles", () => `Successfully set styles`);
} else {
workerScript.log("ui.setStyles", () => `Failed to set styles. Errors: ${errors.join(', ')}`);
workerScript.log("ui.setStyles", () => `Failed to set styles. Errors: ${errors.join(", ")}`);
}
},
resetTheme: function (): void {
helper.updateDynamicRam("resetTheme", getRamCost(player, "ui", "resetTheme"));
updateRam("resetTheme");
Settings.theme = { ...defaultTheme };
ThemeEvents.emit();
workerScript.log("ui.resetTheme", () => `Reinitialized theme to default`);
},
resetStyles: function (): void {
helper.updateDynamicRam("resetStyles", getRamCost(player, "ui", "resetStyles"));
updateRam("resetStyles");
Settings.styles = { ...defaultStyles };
ThemeEvents.emit();
workerScript.log("ui.resetStyles", () => `Reinitialized styles to default`);
},
getGameInfo: function (): GameInfo {
helper.updateDynamicRam("getGameInfo", getRamCost(player, "ui", "getGameInfo"));
updateRam("getGameInfo");
const version = CONSTANTS.VersionString;
const commit = hash();
const platform = (navigator.userAgent.toLowerCase().indexOf(" electron/") > -1) ? 'Steam' : 'Browser';
const platform = navigator.userAgent.toLowerCase().indexOf(" electron/") > -1 ? "Steam" : "Browser";
const gameInfo = {
version, commit, platform,
}
version,
commit,
platform,
};
return gameInfo;
}
}
},
};
}
+3 -1
View File
@@ -178,7 +178,9 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
const entry = ns[name];
if (typeof entry === "function") {
//Async functions need to be wrapped. See JS-Interpreter documentation
if (["hack", "grow", "weaken", "sleep", "prompt", "manualHack", "scp", "write", "share", "wget"].includes(name)) {
if (
["hack", "grow", "weaken", "sleep", "prompt", "manualHack", "scp", "write", "share", "wget"].includes(name)
) {
const tempWrapper = function (...args: any[]): void {
const fnArgs = [];
+1 -1
View File
@@ -859,7 +859,7 @@ export class Sleeve extends Person {
* Returns boolean indicating success
*/
workForFaction(p: IPlayer, factionName: string, workType: string): boolean {
const faction = Factions[factionName]
const faction = Factions[factionName];
if (factionName === "" || !faction || !(faction instanceof Faction) || !p.factions.includes(factionName)) {
return false;
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { FactionNames } from '../../Faction/data/FactionNames';
import { FactionNames } from "../../Faction/data/FactionNames";
import { Sleeve } from "./Sleeve";
import { IPlayer } from "../IPlayer";
+4 -3
View File
@@ -91,7 +91,8 @@ export function FAQModal({ open, onClose }: IProps): React.ReactElement {
<Typography variant="h4">Why can't I buy the X Augmentation for my sleeve?</Typography>
<br />
<Typography>
Certain Augmentations, like {FactionNames.Bladeburners}-specific ones and NeuroFlux Governor, are not available for sleeves.
Certain Augmentations, like {FactionNames.Bladeburners}-specific ones and NeuroFlux Governor, are not
available for sleeves.
</Typography>
<br />
<br />
@@ -110,8 +111,8 @@ export function FAQModal({ open, onClose }: IProps): React.ReactElement {
<br />
<br />
<Typography>
Memory can only be increased by purchasing upgrades from {FactionNames.TheCovenant}. It is a persistent stat, meaning it
never gets resets back to 1. The maximum possible value for a sleeve's memory is 100.
Memory can only be increased by purchasing upgrades from {FactionNames.TheCovenant}. It is a persistent stat,
meaning it never gets resets back to 1. The maximum possible value for a sleeve's memory is 100.
</Typography>
</>
</Modal>
@@ -91,11 +91,18 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement {
{ownedAugNames.length > 0 && (
<>
<Typography sx={{ mx: 1 }}>Owned Augmentations:</Typography>
<Box display="grid" sx={{ gridTemplateColumns: 'repeat(5, 1fr)', m: 1 }}>
<Box display="grid" sx={{ gridTemplateColumns: "repeat(5, 1fr)", m: 1 }}>
{ownedAugNames.map((augName) => {
const aug = Augmentations[augName];
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info
const tooltip = (<>{info}<br /><br />{aug.stats}</>);
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
const tooltip = (
<>
{info}
<br />
<br />
{aug.stats}
</>
);
return (
<Tooltip key={augName} title={<Typography>{tooltip}</Typography>}>
+13 -15
View File
@@ -1,12 +1,6 @@
import React, { useState } from "react";
import {
Box,
Paper,
Typography,
Button,
Tooltip
} from "@mui/material";
import { Box, Paper, Typography, Button, Tooltip } from "@mui/material";
import { CONSTANTS } from "../../../Constants";
import { Crimes } from "../../../Crime/Crimes";
@@ -137,12 +131,12 @@ export function SleeveElem(props: IProps): React.ReactElement {
}
return (
<Box component={Paper} sx={{ width: 'auto' }}>
<Box component={Paper} sx={{ width: "auto" }}>
<Box sx={{ m: 1 }}>
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr', width: '100%', gap: 1 }}>
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%", gap: 1 }}>
<Box>
<StatsElement sleeve={props.sleeve} />
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr', width: '100%' }}>
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%" }}>
<Button onClick={() => setStatsOpen(true)}>More Stats</Button>
<Button onClick={() => setEarningsOpen(true)}>More Earnings Info</Button>
<Tooltip title={player.money < CONSTANTS.TravelCost ? <Typography>Insufficient funds</Typography> : ""}>
@@ -150,20 +144,22 @@ export function SleeveElem(props: IProps): React.ReactElement {
<Button
onClick={() => setTravelOpen(true)}
disabled={player.money < CONSTANTS.TravelCost}
sx={{ width: '100%', height: '100%' }}
sx={{ width: "100%", height: "100%" }}
>
Travel
</Button>
</span>
</Tooltip>
<Tooltip
title={props.sleeve.shock < 100 ? <Typography>Unlocked when sleeve has fully recovered</Typography> : ""}
title={
props.sleeve.shock < 100 ? <Typography>Unlocked when sleeve has fully recovered</Typography> : ""
}
>
<span>
<Button
onClick={() => setAugmentationsOpen(true)}
disabled={props.sleeve.shock < 100}
sx={{ width: '100%', height: '100%' }}
sx={{ width: "100%", height: "100%" }}
>
Manage Augmentations
</Button>
@@ -175,7 +171,9 @@ export function SleeveElem(props: IProps): React.ReactElement {
<EarningsElement sleeve={props.sleeve} />
<Box>
<TaskSelector player={player} sleeve={props.sleeve} setABC={setABC} />
<Button onClick={setTask} sx={{ width: '100%' }}>Set Task</Button>
<Button onClick={setTask} sx={{ width: "100%" }}>
Set Task
</Button>
<Typography>{desc}</Typography>
<Typography>
{props.sleeve.currentTask === SleeveTaskType.Crime &&
@@ -201,6 +199,6 @@ export function SleeveElem(props: IProps): React.ReactElement {
/>
</Box>
</Box>
</Box >
</Box>
);
}
+6 -9
View File
@@ -1,11 +1,6 @@
import React, { useState, useEffect } from "react";
import {
Box,
Typography,
Button,
Container
} from "@mui/material";
import { Box, Typography, Button, Container } from "@mui/material";
import { use } from "../../../ui/Context";
@@ -38,14 +33,16 @@ export function SleeveRoot(): React.ReactElement {
<br />
<br />
</Typography>
</Container>
<Button onClick={() => setFAQOpen(true)}>FAQ</Button>
<Button href="https://bitburner.readthedocs.io/en/latest/advancedgameplay/sleeves.html#duplicate-sleeves" target="_blank">
<Button
href="https://bitburner.readthedocs.io/en/latest/advancedgameplay/sleeves.html#duplicate-sleeves"
target="_blank"
>
Wiki Documentation
</Button>
<Box display="grid" sx={{ gridTemplateColumns: 'repeat(2, 1fr)', mt: 1 }}>
<Box display="grid" sx={{ gridTemplateColumns: "repeat(2, 1fr)", mt: 1 }}>
{player.sleeves.map((sleeve, i) => (
<SleeveElem key={i} rerender={rerender} sleeve={sleeve} />
))}
+63 -26
View File
@@ -1,12 +1,6 @@
import React from "react";
import {
Typography,
Table,
TableBody,
TableCell,
TableRow,
} from "@mui/material";
import { Typography, Table, TableBody, TableCell, TableRow } from "@mui/material";
import { numeralWrapper } from "../../../ui/numeralFormat";
import { Settings } from "../../../Settings/Settings";
@@ -28,29 +22,69 @@ export function StatsElement(props: IProps): React.ReactElement {
const classes = useStyles();
return (
<Table sx={{ display: 'table', mb: 1, width: '100%' }}>
<Table sx={{ display: "table", mb: 1, width: "100%" }}>
<TableBody>
<StatsRow name="City" color={Settings.theme.primary} data={{ content: props.sleeve.city }} />
<StatsRow name="HP" color={Settings.theme.hp}
data={{ content: `${numeralWrapper.formatHp(props.sleeve.hp)} / ${numeralWrapper.formatHp(props.sleeve.max_hp)}` }}
<StatsRow
name="HP"
color={Settings.theme.hp}
data={{
content: `${numeralWrapper.formatHp(props.sleeve.hp)} / ${numeralWrapper.formatHp(props.sleeve.max_hp)}`,
}}
/>
<StatsRow
name="Hacking"
color={Settings.theme.hack}
data={{ level: props.sleeve.hacking, exp: props.sleeve.hacking_exp }}
/>
<StatsRow
name="Strength"
color={Settings.theme.combat}
data={{ level: props.sleeve.strength, exp: props.sleeve.strength_exp }}
/>
<StatsRow
name="Defense"
color={Settings.theme.combat}
data={{ level: props.sleeve.defense, exp: props.sleeve.defense_exp }}
/>
<StatsRow
name="Dexterity"
color={Settings.theme.combat}
data={{ level: props.sleeve.dexterity, exp: props.sleeve.dexterity_exp }}
/>
<StatsRow
name="Agility"
color={Settings.theme.combat}
data={{ level: props.sleeve.agility, exp: props.sleeve.agility_exp }}
/>
<StatsRow
name="Charisma"
color={Settings.theme.cha}
data={{ level: props.sleeve.charisma, exp: props.sleeve.charisma_exp }}
/>
<StatsRow name="Hacking" color={Settings.theme.hack} data={{ level: props.sleeve.hacking, exp: props.sleeve.hacking_exp }} />
<StatsRow name="Strength" color={Settings.theme.combat} data={{ level: props.sleeve.strength, exp: props.sleeve.strength_exp }} />
<StatsRow name="Defense" color={Settings.theme.combat} data={{ level: props.sleeve.defense, exp: props.sleeve.defense_exp }} />
<StatsRow name="Dexterity" color={Settings.theme.combat} data={{ level: props.sleeve.dexterity, exp: props.sleeve.dexterity_exp }} />
<StatsRow name="Agility" color={Settings.theme.combat} data={{ level: props.sleeve.agility, exp: props.sleeve.agility_exp }} />
<StatsRow name="Charisma" color={Settings.theme.cha} data={{ level: props.sleeve.charisma, exp: props.sleeve.charisma_exp }} />
<TableRow>
<TableCell classes={{ root: classes.cellNone }}>
<br />
</TableCell>
</TableRow>
<StatsRow name="Shock" color={Settings.theme.primary} data={{ content: numeralWrapper.formatSleeveShock(100 - props.sleeve.shock) }} />
<StatsRow name="Sync" color={Settings.theme.primary} data={{ content: numeralWrapper.formatSleeveSynchro(props.sleeve.sync) }} />
<StatsRow name="Memory" color={Settings.theme.primary} data={{ content: numeralWrapper.formatSleeveMemory(props.sleeve.memory) }} />
<StatsRow
name="Shock"
color={Settings.theme.primary}
data={{ content: numeralWrapper.formatSleeveShock(100 - props.sleeve.shock) }}
/>
<StatsRow
name="Sync"
color={Settings.theme.primary}
data={{ content: numeralWrapper.formatSleeveSynchro(props.sleeve.sync) }}
/>
<StatsRow
name="Memory"
color={Settings.theme.primary}
data={{ content: numeralWrapper.formatSleeveMemory(props.sleeve.memory) }}
/>
</TableBody>
</Table>
)
);
}
export function EarningsElement(props: IProps): React.ReactElement {
@@ -60,7 +94,12 @@ export function EarningsElement(props: IProps): React.ReactElement {
let data: any[][] = [];
if (props.sleeve.currentTask === SleeveTaskType.Crime) {
data = [
[`Money`, <><Money money={parseFloat(props.sleeve.currentTaskLocation)} /> (on success)</>],
[
`Money`,
<>
<Money money={parseFloat(props.sleeve.currentTaskLocation)} /> (on success)
</>,
],
[`Hacking Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.hack)} (2x on success)`],
[`Strength Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.str)} (2x on success)`],
[`Defense Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.def)} (2x on success)`],
@@ -85,13 +124,11 @@ export function EarningsElement(props: IProps): React.ReactElement {
}
return (
<Table sx={{ display: 'table', mb: 1, width: '100%', lineHeight: 0 }}>
<Table sx={{ display: "table", mb: 1, width: "100%", lineHeight: 0 }}>
<TableBody>
<TableRow>
<TableCell classes={{ root: classes.cellNone }}>
<Typography variant='h6'>
Earnings
</Typography>
<Typography variant="h6">Earnings</Typography>
</TableCell>
</TableRow>
{data.map(([a, b]) => (
@@ -106,5 +143,5 @@ export function EarningsElement(props: IProps): React.ReactElement {
))}
</TableBody>
</Table>
)
);
}
+5 -5
View File
@@ -76,9 +76,9 @@ function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] {
}
}
return factions.filter(faction => {
return factions.filter((faction) => {
const facInfo = Factions[faction].getInfo();
return facInfo.offerHackingWork || facInfo.offerFieldWork || facInfo.offerSecurityWork
return facInfo.offerHackingWork || facInfo.offerFieldWork || facInfo.offerSecurityWork;
});
}
@@ -279,7 +279,7 @@ export function TaskSelector(props: IProps): React.ReactElement {
return (
<>
<Select onChange={onS0Change} value={s0} sx={{ width: '100%' }}>
<Select onChange={onS0Change} value={s0} sx={{ width: "100%" }}>
{validActions.map((task) => (
<MenuItem key={task} value={task}>
{task}
@@ -288,7 +288,7 @@ export function TaskSelector(props: IProps): React.ReactElement {
</Select>
{!(details.first.length === 1 && details.first[0] === "------") && (
<>
<Select onChange={onS1Change} value={s1} sx={{ width: '100%' }}>
<Select onChange={onS1Change} value={s1} sx={{ width: "100%" }}>
{details.first.map((detail) => (
<MenuItem key={detail} value={detail}>
{detail}
@@ -299,7 +299,7 @@ export function TaskSelector(props: IProps): React.ReactElement {
)}
{!(details2.length === 1 && details2[0] === "------") && (
<>
<Select onChange={onS2Change} value={s2} sx={{ width: '100%' }}>
<Select onChange={onS2Change} value={s2} sx={{ width: "100%" }}>
{details2.map((detail) => (
<MenuItem key={detail} value={detail}>
{detail}
+11 -9
View File
@@ -24,20 +24,22 @@ export function getHackingWorkRepGain(p: IPlayer, f: Faction): number {
export function getFactionSecurityWorkRepGain(p: IPlayer, f: Faction): number {
const t =
(0.9 *
(p.strength + p.defense + p.dexterity + p.agility +
(p.hacking + p.intelligence) * CalculateShareMult()
)
) / CONSTANTS.MaxSkillLevel / 4.5;
(0.9 * (p.strength + p.defense + p.dexterity + p.agility + (p.hacking + p.intelligence) * CalculateShareMult())) /
CONSTANTS.MaxSkillLevel /
4.5;
return t * p.faction_rep_mult * mult(f) * p.getIntelligenceBonus(1);
}
export function getFactionFieldWorkRepGain(p: IPlayer, f: Faction): number {
const t =
(0.9 *
(p.strength + p.defense + p.dexterity + p.agility + p.charisma +
(p.hacking + p.intelligence) * CalculateShareMult()
)
) / CONSTANTS.MaxSkillLevel / 5.5;
(p.strength +
p.defense +
p.dexterity +
p.agility +
p.charisma +
(p.hacking + p.intelligence) * CalculateShareMult())) /
CONSTANTS.MaxSkillLevel /
5.5;
return t * p.faction_rep_mult * mult(f) * p.getIntelligenceBonus(1);
}
+12 -8
View File
@@ -13,14 +13,14 @@ export function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
let baseExperience = calculateExp(currentSkill, mult);
if (baseExperience < 0) baseExperience = 0;
let nextExperience = calculateExp(nextSkill, mult)
let nextExperience = calculateExp(nextSkill, mult);
if (nextExperience < 0) nextExperience = 0;
const normalize = (value: number): number => ((value - baseExperience) * 100) / (nextExperience - baseExperience);
let progress = (nextExperience - baseExperience !== 0) ? normalize(exp) : 99.99;
let progress = nextExperience - baseExperience !== 0 ? normalize(exp) : 99.99;
// Clamp progress: When sleeves are working out, the player gets way too much progress
if (progress < 0) progress = 0
if (progress < 0) progress = 0;
if (progress > 100) progress = 100;
// Clamp floating point imprecisions
@@ -37,8 +37,8 @@ export function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
nextExperience,
currentExperience,
remainingExperience,
progress
}
progress,
};
}
export interface ISkillProgress {
@@ -54,9 +54,13 @@ export interface ISkillProgress {
export function getEmptySkillProgress(): ISkillProgress {
return {
currentSkill: 0, nextSkill: 0,
baseExperience: 0, experience: 0, nextExperience: 0,
currentExperience: 0, remainingExperience: 0,
currentSkill: 0,
nextSkill: 0,
baseExperience: 0,
experience: 0,
nextExperience: 0,
currentExperience: 0,
remainingExperience: 0,
progress: 0,
};
}
+36 -36
View File
@@ -1,13 +1,7 @@
import React, { useState, useEffect } from "react";
import { find } from "lodash";
import {
Box,
Typography,
Button,
Container,
Paper
} from "@mui/material";
import { Box, Typography, Button, Container, Paper } from "@mui/material";
import { Check, Lock, Create } from "@mui/icons-material";
import { use } from "../../ui/Context";
@@ -26,7 +20,7 @@ export function ProgramsRoot(): React.ReactElement {
}
const programs = [...Object.values(Programs)]
.filter(prog => {
.filter((prog) => {
const create = prog.create;
if (create === null) return false;
if (prog.name === "b1t_flum3.exe") {
@@ -38,7 +32,7 @@ export function ProgramsRoot(): React.ReactElement {
if (player.hasProgram(a.name)) return 1;
if (player.hasProgram(b.name)) return -1;
return (a.create?.level ?? 0) - (b.create?.level ?? 0);
})
});
useEffect(() => {
programs.forEach((p) => {
@@ -54,11 +48,11 @@ export function ProgramsRoot(): React.ReactElement {
const getHackingLevelRemaining = (lvl: number): number => {
return Math.ceil(Math.max(lvl - (player.hacking + player.intelligence / 2), 0));
}
};
const getProgCompletion = (name: string): number => {
const programFile = find(player.getHomeComputer().programs, p => {
return (p.startsWith(name) && p.endsWith("%-INC"));
const programFile = find(player.getHomeComputer().programs, (p) => {
return p.startsWith(name) && p.endsWith("%-INC");
});
if (!programFile) return -1;
@@ -69,7 +63,7 @@ export function ProgramsRoot(): React.ReactElement {
return -1;
}
return percComplete;
}
};
return (
<Container disableGutters maxWidth="lg" sx={{ mx: 0, mb: 10 }}>
@@ -80,41 +74,47 @@ export function ProgramsRoot(): React.ReactElement {
time. Your progress will be saved and you can continue later.
</Typography>
<Box sx={{ display: 'grid', gridTemplateColumns: "repeat(3, 1fr)", my: 1 }}>
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", my: 1 }}>
{programs.map((program) => {
const create = program.create;
if (create === null) return <></>;
const curCompletion = getProgCompletion(program.name);
return (
<Box component={Paper} sx={{ p: 1, opacity: player.hasProgram(program.name) ? 0.75 : 1 }} key={program.name}>
<Typography variant="h6" sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
{player.hasProgram(program.name) && <Check sx={{ mr: 1 }} /> ||
(create.req(player) && <Create sx={{ mr: 1 }} /> || <Lock sx={{ mr: 1 }} />)}
<Box
component={Paper}
sx={{ p: 1, opacity: player.hasProgram(program.name) ? 0.75 : 1 }}
key={program.name}
>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
{(player.hasProgram(program.name) && <Check sx={{ mr: 1 }} />) ||
(create.req(player) && <Create sx={{ mr: 1 }} />) || <Lock sx={{ mr: 1 }} />}
{program.name}
</Typography>
{(!player.hasProgram(program.name) && create.req(player)) && <Button
sx={{ my: 1, width: '100%' }}
onClick={(event) => {
if (!event.isTrusted) return;
player.startCreateProgramWork(program.name, create.time, create.level);
player.startFocusing();
router.toWork();
}}
>
Create program
</Button>}
{(player.hasProgram(program.name) || getHackingLevelRemaining(create.level) === 0) ||
{!player.hasProgram(program.name) && create.req(player) && (
<Button
sx={{ my: 1, width: "100%" }}
onClick={(event) => {
if (!event.isTrusted) return;
player.startCreateProgramWork(program.name, create.time, create.level);
player.startFocusing();
router.toWork();
}}
>
Create program
</Button>
)}
{player.hasProgram(program.name) || getHackingLevelRemaining(create.level) === 0 || (
<Typography color={Settings.theme.hack}>
<b>Unlocks in:</b> {getHackingLevelRemaining(create.level)} hacking levels
</Typography>}
{(curCompletion !== -1) &&
</Typography>
)}
{curCompletion !== -1 && (
<Typography color={Settings.theme.infolight}>
<b>Current completion:</b> {curCompletion}%
</Typography>}
<Typography>
{create.tooltip}
</Typography>
</Typography>
)}
<Typography>{create.tooltip}</Typography>
</Box>
);
})}
+3 -3
View File
@@ -76,9 +76,9 @@ export function enterBitNode(router: IRouter, flume: boolean, destroyedBitNode:
if (!flume) {
giveSourceFile(destroyedBitNode);
} else if (SourceFileFlags[5] === 0 && newBitNode !== 5) {
Player.intelligence = 0;
Player.intelligence_exp = 0;
}
Player.intelligence = 0;
Player.intelligence_exp = 0;
}
if (newBitNode === 5 && Player.intelligence === 0) {
Player.intelligence = 1;
}
+11 -9
View File
@@ -17,7 +17,7 @@ import { areImportsEquals } from "../Terminal/DirectoryHelpers";
import { IPlayer } from "../PersonObjects/IPlayer";
export interface RamUsageEntry {
type: 'ns' | 'dom' | 'fn' | 'misc';
type: "ns" | "dom" | "fn" | "misc";
name: string;
cost: number;
}
@@ -139,7 +139,9 @@ async function parseOnlyRamCalculate(
// Finally, walk the reference map and generate a ram cost. The initial set of keys to scan
// are those that start with __SPECIAL_INITIAL_MODULE__.
let ram = RamCostConstants.ScriptBaseRamCost;
const detailedCosts: RamUsageEntry[] = [{ type: 'misc', name: 'baseCost', cost: RamCostConstants.ScriptBaseRamCost}];
const detailedCosts: RamUsageEntry[] = [
{ type: "misc", name: "baseCost", cost: RamCostConstants.ScriptBaseRamCost },
];
const unresolvedRefs = Object.keys(dependencyMap).filter((s) => s.startsWith(initialModule));
const resolvedRefs = new Set();
while (unresolvedRefs.length > 0) {
@@ -149,19 +151,19 @@ async function parseOnlyRamCalculate(
// Check if this is one of the special keys, and add the appropriate ram cost if so.
if (ref === "hacknet" && !resolvedRefs.has("hacknet")) {
ram += RamCostConstants.ScriptHacknetNodesRamCost;
detailedCosts.push({ type: 'ns', name: 'hacknet', cost: RamCostConstants.ScriptHacknetNodesRamCost});
detailedCosts.push({ type: "ns", name: "hacknet", cost: RamCostConstants.ScriptHacknetNodesRamCost });
}
if (ref === "document" && !resolvedRefs.has("document")) {
ram += RamCostConstants.ScriptDomRamCost;
detailedCosts.push({ type: 'dom', name: 'document', cost: RamCostConstants.ScriptDomRamCost});
detailedCosts.push({ type: "dom", name: "document", cost: RamCostConstants.ScriptDomRamCost });
}
if (ref === "window" && !resolvedRefs.has("window")) {
ram += RamCostConstants.ScriptDomRamCost;
detailedCosts.push({ type: 'dom', name: 'window', cost: RamCostConstants.ScriptDomRamCost});
detailedCosts.push({ type: "dom", name: "window", cost: RamCostConstants.ScriptDomRamCost });
}
if (ref === "corporation" && !resolvedRefs.has("corporation")) {
ram += RamCostConstants.ScriptCorporationRamCost;
detailedCosts.push({ type: 'ns', name: 'corporation', cost: RamCostConstants.ScriptCorporationRamCost});
detailedCosts.push({ type: "ns", name: "corporation", cost: RamCostConstants.ScriptCorporationRamCost });
}
resolvedRefs.add(ref);
@@ -203,7 +205,7 @@ async function parseOnlyRamCalculate(
// This accounts for namespaces (Bladeburner, CodingCpntract, etc.)
let func;
let refDetail = 'n/a';
let refDetail = "n/a";
if (ref in workerScript.env.vars.bladeburner) {
func = workerScript.env.vars.bladeburner[ref];
refDetail = `bladeburner.${ref}`;
@@ -234,12 +236,12 @@ async function parseOnlyRamCalculate(
}
const fnRam = applyFuncRam(func);
ram += fnRam;
detailedCosts.push({ type: 'fn', name: refDetail, cost: fnRam});
detailedCosts.push({ type: "fn", name: refDetail, cost: fnRam });
} catch (error) {
continue;
}
}
return { cost: ram, entries: detailedCosts.filter(e => e.cost > 0) };
return { cost: ram, entries: detailedCosts.filter((e) => e.cost > 0) };
} catch (error) {
// console.info("parse or eval error: ", error);
// This is not unexpected. The user may be editing a script, and it may be in
+4 -4
View File
@@ -3637,9 +3637,9 @@ export interface Sleeve {
* @param sleeveNumber - Index of the sleeve to work for the faction.
* @param factionName - Name of the faction to work for.
* @param factionWorkType - Name of the action to perform for this faction.
* @returns True if the sleeve started working on this faction, false otherwise.
* @returns True if the sleeve started working on this faction, false otherwise, can also throw on errors
*/
setToFactionWork(sleeveNumber: number, factionName: string, factionWorkType: string): boolean;
setToFactionWork(sleeveNumber: number, factionName: string, factionWorkType: string): boolean | undefined;
/**
* Set a sleeve to work for a company.
@@ -4642,7 +4642,7 @@ export interface NS extends Singularity {
* ```
* @returns
*/
sleep(millis: number): Promise<void>;
sleep(millis: number): Promise<true>;
/**
* Suspends the script for n milliseconds. Doesn't block with concurrent calls.
@@ -4652,7 +4652,7 @@ export interface NS extends Singularity {
* @param millis - Number of milliseconds to sleep.
* @returns
*/
asleep(millis: number): Promise<void>;
asleep(millis: number): Promise<true>;
/**
* Prints one or move values or variables to the scripts logs.
+1 -1
View File
@@ -1,4 +1,4 @@
export type WordWrapOptions = 'on' | 'off' | 'bounded' | 'wordWrapColumn';
export type WordWrapOptions = "on" | "off" | "bounded" | "wordWrapColumn";
export interface Options {
theme: string;
insertSpaces: boolean;
+30 -25
View File
@@ -235,7 +235,7 @@ export function Root(props: IProps): React.ReactElement {
MonacoVim.VimMode.Vim.mapCommand("gT", "action", "prevTabs", {}, { context: "normal" });
editor.focus();
});
} catch { }
} catch {}
} else if (!options.vim) {
// Whem vim mode is disabled
vimEditor?.dispose();
@@ -481,7 +481,7 @@ export function Root(props: IProps): React.ReactElement {
}
try {
infLoop(newCode);
} catch (err) { }
} catch (err) {}
}
function saveScript(scriptToSave: OpenScript): void {
@@ -794,11 +794,11 @@ export function Root(props: IProps): React.ReactElement {
setFilter(event.target.value);
}
function handleExpandSearch(): void {
setFilter("")
setSearchExpanded(!searchExpanded)
setFilter("");
setSearchExpanded(!searchExpanded);
}
const filteredOpenScripts = Object.values(openScripts).filter(
(script) => (script.hostname.includes(filter) || script.fileName.includes(filter))
(script) => script.hostname.includes(filter) || script.fileName.includes(filter),
);
// Toolbars are roughly 112px:
@@ -835,7 +835,7 @@ export function Root(props: IProps): React.ReactElement {
}}
>
<Tooltip title={"Search Open Scripts"}>
{searchExpanded ?
{searchExpanded ? (
<TextField
value={filter}
onChange={handleFilterChange}
@@ -843,9 +843,14 @@ export function Root(props: IProps): React.ReactElement {
InputProps={{
startAdornment: <SearchIcon />,
spellCheck: false,
endAdornment: <CloseIcon onClick={handleExpandSearch} />
endAdornment: <CloseIcon onClick={handleExpandSearch} />,
}}
/> : <Button onClick={handleExpandSearch} ><SearchIcon /></Button>}
/>
) : (
<Button onClick={handleExpandSearch}>
<SearchIcon />
</Button>
)}
</Tooltip>
{filteredOpenScripts.map(({ fileName, hostname }, index) => {
const iconButtonStyle = {
@@ -855,15 +860,15 @@ export function Root(props: IProps): React.ReactElement {
maxHeight: "38.5px",
...(currentScript?.fileName === filteredOpenScripts[index].fileName
? {
background: Settings.theme.button,
borderColor: Settings.theme.button,
color: Settings.theme.primary,
}
background: Settings.theme.button,
borderColor: Settings.theme.button,
color: Settings.theme.primary,
}
: {
background: Settings.theme.backgroundsecondary,
borderColor: Settings.theme.backgroundsecondary,
color: Settings.theme.secondary,
}),
background: Settings.theme.backgroundsecondary,
borderColor: Settings.theme.backgroundsecondary,
color: Settings.theme.secondary,
}),
};
const scriptTabText = `${hostname}:~/${fileName} ${dirty(index)}`;
@@ -896,19 +901,19 @@ export function Root(props: IProps): React.ReactElement {
}}
style={{
maxWidth: `${tabTextWidth}px`,
minHeight: '38.5px',
minHeight: "38.5px",
overflow: "hidden",
...(currentScript?.fileName === filteredOpenScripts[index].fileName
? {
background: Settings.theme.button,
borderColor: Settings.theme.button,
color: Settings.theme.primary,
}
background: Settings.theme.button,
borderColor: Settings.theme.button,
color: Settings.theme.primary,
}
: {
background: Settings.theme.backgroundsecondary,
borderColor: Settings.theme.backgroundsecondary,
color: Settings.theme.secondary,
}),
background: Settings.theme.backgroundsecondary,
borderColor: Settings.theme.backgroundsecondary,
color: Settings.theme.secondary,
}),
}}
>
<span style={{ overflow: "hidden", direction: "rtl", textOverflow: "ellipsis" }}>
+4 -5
View File
@@ -260,7 +260,6 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
token: "ns",
foreground: "FFB86C",
fontStyle: "italic",
},
{
token: "netscriptfunction",
@@ -273,7 +272,7 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
{
token: "type.identifier.js",
foreground: "7EE9FD",
fontStyle: "italic"
fontStyle: "italic",
},
{
token: "delimiter.square.js",
@@ -281,7 +280,7 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
},
{
token: "delimiter.parenthesis.js",
foreground: "FFD709"
foreground: "FFD709",
},
{
token: "delimiter.bracket.js",
@@ -293,7 +292,7 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
fontStyle: "italic",
},
],
"colors": {
colors: {
"editor.foreground": "#F8F8F2",
"editor.background": "#282A36",
"editorLineNumber.foreground": "#6272A4",
@@ -402,6 +401,6 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
"scrollbarSlider.background": "#4E566680",
"scrollbarSlider.activeBackground": "#747D9180",
"scrollbarSlider.hoverBackground": "#5A637580",
}
},
});
}

Some files were not shown because too many files have changed in this diff Show More