mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-05-04 06:37:49 +02:00
Merge branch 'dev' into bugfix/3348
# Conflicts: # src/Faction/FactionInfo.tsx # src/NetscriptFunctions/Singularity.ts
This commit is contained in:
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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,
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]",
|
||||
" ",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.",
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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],
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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} />,
|
||||
)}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
@@ -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)}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -5,5 +5,5 @@ export const StanekConstants: {
|
||||
} = {
|
||||
RAMBonus: 0.1,
|
||||
BaseSize: 9,
|
||||
MaxSize: 25
|
||||
MaxSize: 25,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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(
|
||||
(
|
||||
|
||||
@@ -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,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";
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
import { FactionNames } from '../Faction/data/FactionNames';
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { Reviver } from "../utils/JSONReviver";
|
||||
|
||||
interface GangTerritory {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FactionNames } from '../../Faction/data/FactionNames';
|
||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
export const PowerMultiplier: {
|
||||
[key: string]: number | undefined;
|
||||
} = {
|
||||
|
||||
@@ -51,7 +51,7 @@ export function AscensionModal(props: IProps): React.ReactElement {
|
||||
<br />
|
||||
Charisma: x{numeralWrapper.format(res.cha, "0.000")}
|
||||
<br />
|
||||
</>
|
||||
</>,
|
||||
);
|
||||
props.onClose();
|
||||
}
|
||||
|
||||
@@ -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} />
|
||||
))}
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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} />
|
||||
))}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)} />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -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,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";
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
</>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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$)",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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}'`);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
import { FactionNames } from '../../Faction/data/FactionNames';
|
||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
import { Sleeve } from "./Sleeve";
|
||||
|
||||
import { IPlayer } from "../IPlayer";
|
||||
|
||||
@@ -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>}>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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} />
|
||||
))}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 script’s logs.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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" }}>
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user